From 21b8cfb470df79eac831c6e80f8b633c64ff788f Mon Sep 17 00:00:00 2001 From: Barrett Ruth Date: Sun, 1 Feb 2026 17:38:32 -0500 Subject: [PATCH 1/5] feat: add the entire plugin --- README.md | 16 +++-- doc/fugitive-ts.nvim.txt | 69 +++++++++++++++++++++ lua/fugitive-ts/health.lua | 41 +++++++++++++ lua/fugitive-ts/highlight.lua | 52 ++++++++++++++++ lua/fugitive-ts/init.lua | 109 ++++++++++++++++++++++++++++++++++ lua/fugitive-ts/parser.lua | 89 +++++++++++++++++++++++++++ plugin/fugitive-ts.lua | 11 ++++ 7 files changed, 382 insertions(+), 5 deletions(-) create mode 100644 doc/fugitive-ts.nvim.txt create mode 100644 lua/fugitive-ts/health.lua create mode 100644 lua/fugitive-ts/highlight.lua create mode 100644 lua/fugitive-ts/init.lua create mode 100644 lua/fugitive-ts/parser.lua create mode 100644 plugin/fugitive-ts.lua diff --git a/README.md b/README.md index 871ab74..adad924 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,9 @@ Treesitter syntax highlighting for vim-fugitive diff views. ## Problem -vim-fugitive uses regex-based `syntax/diff.vim` for highlighting expanded diffs in the status buffer. This means code inside diffs has no language-aware highlighting: +vim-fugitive uses regex-based `syntax/diff.vim` for highlighting expanded diffs +in the status buffer. This means code inside diffs has no language-aware +highlighting: ``` Unstaged (1) @@ -17,7 +19,9 @@ M lua/mymodule.lua ## Solution -Hook into fugitive's buffer, detect diff hunks, extract the language from filenames, and apply treesitter highlights as extmarks on top of fugitive's existing highlighting. +Hook into fugitive's buffer, detect diff hunks, extract the language from +filenames, and apply treesitter highlights as extmarks on top of fugitive's +existing highlighting. ``` Unstaged (1) @@ -66,6 +70,7 @@ Staged (N) ``` Pattern to detect: + - Filename: `^[MADRC?] .+%.(%w+)$` → captures extension - Hunk header: `^@@ .+ @@` - Code lines: after hunk header, lines starting with ` `, `+`, or `-` @@ -154,7 +159,8 @@ end ### 6. Re-highlight on Buffer Change -Fugitive modifies the buffer when user expands/collapses diffs. Need to re-parse: +Fugitive modifies the buffer when user expands/collapses diffs. Need to +re-parse: ```lua vim.api.nvim_create_autocmd({"TextChanged", "TextChangedI"}, { @@ -226,5 +232,5 @@ require("fugitive-ts").setup({ - [Neovim Treesitter API](https://neovim.io/doc/user/treesitter.html) - [vim-fugitive User events](https://github.com/tpope/vim-fugitive/blob/master/doc/fugitive.txt) -- [nvim_buf_set_extmark](https://neovim.io/doc/user/api.html#nvim_buf_set_extmark()) -- [vim.treesitter.get_string_parser](https://neovim.io/doc/user/treesitter.html#vim.treesitter.get_string_parser()) +- [nvim_buf_set_extmark]() +- [vim.treesitter.get_string_parser]() diff --git a/doc/fugitive-ts.nvim.txt b/doc/fugitive-ts.nvim.txt new file mode 100644 index 0000000..8fb052d --- /dev/null +++ b/doc/fugitive-ts.nvim.txt @@ -0,0 +1,69 @@ +*fugitive-ts.nvim.txt* Treesitter highlighting for vim-fugitive diffs + +Author: Barrett Ruth +License: MIT + +============================================================================== +INTRODUCTION *fugitive-ts.nvim* + +fugitive-ts.nvim adds treesitter-based syntax highlighting to vim-fugitive +diff views. It overlays language-aware highlights on top of fugitive's +default regex-based diff highlighting. + +============================================================================== +REQUIREMENTS *fugitive-ts-requirements* + +- Neovim 0.9.0+ +- vim-fugitive +- Treesitter parsers for languages you want highlighted + +============================================================================== +SETUP *fugitive-ts-setup* + +>lua + require('fugitive-ts').setup({ + -- Enable/disable highlighting (default: true) + enabled = true, + + -- Custom filename -> language mappings (optional) + languages = {}, + + -- Debounce delay in ms (default: 50) + debounce_ms = 50, + }) +< + +============================================================================== +COMMANDS *fugitive-ts-commands* + +This plugin works automatically when you open a fugitive buffer. No commands +are required. + +============================================================================== +API *fugitive-ts-api* + + *fugitive-ts.setup()* +setup({opts}) + Configure the plugin. See |fugitive-ts-setup| for options. + + *fugitive-ts.attach()* +attach({bufnr}) + Manually attach highlighting to a buffer. Called automatically for + fugitive buffers. + + *fugitive-ts.refresh()* +refresh({bufnr}) + Manually refresh highlighting for a buffer. + +============================================================================== +ROADMAP *fugitive-ts-roadmap* + +Planned features and improvements: + +- Vim syntax fallback: For languages without treesitter parsers, fall back + to vim's built-in syntax highlighting via scratch buffers. This would + provide highlighting coverage for more languages at the cost of + implementation complexity. + +============================================================================== + vim:tw=78:ts=8:ft=help:norl: diff --git a/lua/fugitive-ts/health.lua b/lua/fugitive-ts/health.lua new file mode 100644 index 0000000..bdeebdd --- /dev/null +++ b/lua/fugitive-ts/health.lua @@ -0,0 +1,41 @@ +local M = {} + +function M.check() + vim.health.start('fugitive-ts.nvim') + + if vim.fn.has('nvim-0.9.0') == 1 then + vim.health.ok('Neovim 0.9.0+ detected') + else + vim.health.error('fugitive-ts.nvim requires Neovim 0.9.0+') + end + + local fugitive_loaded = vim.fn.exists(':Git') == 2 + if fugitive_loaded then + vim.health.ok('vim-fugitive detected') + else + vim.health.warn('vim-fugitive not detected (required for this plugin to be useful)') + end + + local common_langs = { 'lua', 'python', 'javascript', 'typescript', 'rust', 'go', 'c', 'cpp' } + local available = {} + local missing = {} + + for _, lang in ipairs(common_langs) do + local ok = pcall(vim.treesitter.language.inspect, lang) + if ok then + table.insert(available, lang) + else + table.insert(missing, lang) + end + end + + if #available > 0 then + vim.health.ok('Treesitter parsers available: ' .. table.concat(available, ', ')) + end + + if #missing > 0 then + vim.health.info('Treesitter parsers not installed: ' .. table.concat(missing, ', ')) + end +end + +return M diff --git a/lua/fugitive-ts/highlight.lua b/lua/fugitive-ts/highlight.lua new file mode 100644 index 0000000..650436d --- /dev/null +++ b/lua/fugitive-ts/highlight.lua @@ -0,0 +1,52 @@ +local M = {} + +function M.highlight_hunk(bufnr, ns, hunk) + local lang = hunk.lang + if not lang then + return + end + + local code_lines = {} + for _, line in ipairs(hunk.lines) do + table.insert(code_lines, line:sub(2)) + end + + local code = table.concat(code_lines, '\n') + if code == '' then + return + end + + local ok, parser_obj = pcall(vim.treesitter.get_string_parser, code, lang) + if not ok or not parser_obj then + return + end + + local trees = parser_obj:parse() + if not trees or #trees == 0 then + return + end + + local query = vim.treesitter.query.get(lang, 'highlights') + if not query then + return + end + + for id, node, _ in query:iter_captures(trees[1]:root(), code) do + local capture_name = '@' .. query.captures[id] + local sr, sc, er, ec = node:range() + + local buf_sr = hunk.start_line + sr + local buf_er = hunk.start_line + er + local buf_sc = sc + 1 + local buf_ec = ec + 1 + + pcall(vim.api.nvim_buf_set_extmark, bufnr, ns, buf_sr, buf_sc, { + end_row = buf_er, + end_col = buf_ec, + hl_group = capture_name, + priority = 200, + }) + end +end + +return M diff --git a/lua/fugitive-ts/init.lua b/lua/fugitive-ts/init.lua new file mode 100644 index 0000000..9bc5d7a --- /dev/null +++ b/lua/fugitive-ts/init.lua @@ -0,0 +1,109 @@ +---@class fugitive-ts.Config +---@field enabled boolean +---@field languages table +---@field debounce_ms integer + +---@class fugitive-ts +---@field attach fun(bufnr?: integer) +---@field refresh fun(bufnr?: integer) +---@field setup fun(opts?: fugitive-ts.Config) +local M = {} + +local highlight = require('fugitive-ts.highlight') +local parser = require('fugitive-ts.parser') + +local ns = vim.api.nvim_create_namespace('fugitive_ts') + +---@type fugitive-ts.Config +local default_config = { + enabled = true, + languages = {}, + debounce_ms = 50, +} + +---@type fugitive-ts.Config +local config = vim.deepcopy(default_config) + +---@type table +local attached_buffers = {} + +---@param bufnr integer +local function highlight_buffer(bufnr) + if not config.enabled then + return + end + + if not vim.api.nvim_buf_is_valid(bufnr) then + return + end + + vim.api.nvim_buf_clear_namespace(bufnr, ns, 0, -1) + + local hunks = parser.parse_buffer(bufnr, config.languages) + for _, hunk in ipairs(hunks) do + highlight.highlight_hunk(bufnr, ns, hunk) + end +end + +---@param bufnr integer +---@return fun() +local function create_debounced_highlight(bufnr) + ---@type uv_timer_t? + local timer = nil + return function() + if timer then + timer:stop() + timer:close() + end + timer = vim.uv.new_timer() + timer:start( + config.debounce_ms, + 0, + vim.schedule_wrap(function() + timer:close() + timer = nil + highlight_buffer(bufnr) + end) + ) + end +end + +---@param bufnr? integer +function M.attach(bufnr) + bufnr = bufnr or vim.api.nvim_get_current_buf() + + if attached_buffers[bufnr] then + return + end + attached_buffers[bufnr] = true + + local debounced = create_debounced_highlight(bufnr) + + highlight_buffer(bufnr) + + vim.api.nvim_create_autocmd({ 'TextChanged', 'TextChangedI' }, { + buffer = bufnr, + callback = debounced, + }) + + vim.api.nvim_create_autocmd('BufWipeout', { + buffer = bufnr, + callback = function() + attached_buffers[bufnr] = nil + end, + }) +end + +---@param bufnr? integer +function M.refresh(bufnr) + bufnr = bufnr or vim.api.nvim_get_current_buf() + highlight_buffer(bufnr) +end + +---@param opts? fugitive-ts.Config +function M.setup(opts) + opts = opts or {} + config = vim.tbl_deep_extend('force', default_config, opts) +end + +return M diff --git a/lua/fugitive-ts/parser.lua b/lua/fugitive-ts/parser.lua new file mode 100644 index 0000000..7ca5cb5 --- /dev/null +++ b/lua/fugitive-ts/parser.lua @@ -0,0 +1,89 @@ +---@class fugitive-ts.Hunk +---@field filename string +---@field lang string +---@field start_line integer +---@field lines string[] + +local M = {} + +---@param filename string +---@param custom_langs? table +---@return string? +local function get_lang_from_filename(filename, custom_langs) + if custom_langs and custom_langs[filename] then + return custom_langs[filename] + end + + local ft = vim.filetype.match({ filename = filename }) + if not ft then + return nil + end + + local lang = vim.treesitter.language.get_lang(ft) + if lang then + local ok = pcall(vim.treesitter.language.inspect, lang) + if ok then + return lang + end + end + + return nil +end + +---@param bufnr integer +---@param custom_langs? table +---@return fugitive-ts.Hunk[] +function M.parse_buffer(bufnr, custom_langs) + local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false) + ---@type fugitive-ts.Hunk[] + local hunks = {} + + ---@type string? + local current_filename = nil + ---@type string? + local current_lang = nil + ---@type integer? + local hunk_start = nil + ---@type string[] + local hunk_lines = {} + + local function flush_hunk() + if hunk_start and #hunk_lines > 0 and current_lang then + table.insert(hunks, { + filename = current_filename, + lang = current_lang, + start_line = hunk_start, + lines = hunk_lines, + }) + end + hunk_start = nil + hunk_lines = {} + end + + for i, line in ipairs(lines) do + local filename = line:match('^[MADRC%?!]%s+(.+)$') + if filename then + flush_hunk() + current_filename = filename + current_lang = get_lang_from_filename(filename, custom_langs) + elseif line:match('^@@.-@@') then + flush_hunk() + hunk_start = i + elseif hunk_start then + local prefix = line:sub(1, 1) + if prefix == ' ' or prefix == '+' or prefix == '-' then + table.insert(hunk_lines, line) + elseif line == '' or line:match('^[MADRC%?!]%s+') or line:match('^%a') then + flush_hunk() + current_filename = nil + current_lang = nil + end + end + end + + flush_hunk() + + return hunks +end + +return M diff --git a/plugin/fugitive-ts.lua b/plugin/fugitive-ts.lua new file mode 100644 index 0000000..cfe7a03 --- /dev/null +++ b/plugin/fugitive-ts.lua @@ -0,0 +1,11 @@ +if vim.g.loaded_fugitive_ts then + return +end +vim.g.loaded_fugitive_ts = 1 + +vim.api.nvim_create_autocmd('FileType', { + pattern = 'fugitive', + callback = function(args) + require('fugitive-ts').attach(args.buf) + end, +}) From 29f9a5f7e4bfc6fd1b9b3ba475c042400c82ec85 Mon Sep 17 00:00:00 2001 From: Barrett Ruth Date: Sun, 1 Feb 2026 17:38:58 -0500 Subject: [PATCH 2/5] feat: luacats annotations --- lua/fugitive-ts/health.lua | 3 +++ lua/fugitive-ts/highlight.lua | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/lua/fugitive-ts/health.lua b/lua/fugitive-ts/health.lua index bdeebdd..48f946b 100644 --- a/lua/fugitive-ts/health.lua +++ b/lua/fugitive-ts/health.lua @@ -16,8 +16,11 @@ function M.check() vim.health.warn('vim-fugitive not detected (required for this plugin to be useful)') end + ---@type string[] local common_langs = { 'lua', 'python', 'javascript', 'typescript', 'rust', 'go', 'c', 'cpp' } + ---@type string[] local available = {} + ---@type string[] local missing = {} for _, lang in ipairs(common_langs) do diff --git a/lua/fugitive-ts/highlight.lua b/lua/fugitive-ts/highlight.lua index 650436d..3c29658 100644 --- a/lua/fugitive-ts/highlight.lua +++ b/lua/fugitive-ts/highlight.lua @@ -1,11 +1,15 @@ local M = {} +---@param bufnr integer +---@param ns integer +---@param hunk fugitive-ts.Hunk function M.highlight_hunk(bufnr, ns, hunk) local lang = hunk.lang if not lang then return end + ---@type string[] local code_lines = {} for _, line in ipairs(hunk.lines) do table.insert(code_lines, line:sub(2)) From ae727159b9104557af72c79a7cf78e215cef154a Mon Sep 17 00:00:00 2001 From: Barrett Ruth Date: Sun, 1 Feb 2026 17:44:28 -0500 Subject: [PATCH 3/5] feat: debug option --- doc/fugitive-ts.nvim.txt | 4 ++++ lua/fugitive-ts/highlight.lua | 25 ++++++++++++++++++++++++- lua/fugitive-ts/init.lua | 19 +++++++++++++++++-- lua/fugitive-ts/parser.lua | 26 +++++++++++++++++++++++--- 4 files changed, 68 insertions(+), 6 deletions(-) diff --git a/doc/fugitive-ts.nvim.txt b/doc/fugitive-ts.nvim.txt index 8fb052d..a825909 100644 --- a/doc/fugitive-ts.nvim.txt +++ b/doc/fugitive-ts.nvim.txt @@ -25,6 +25,10 @@ SETUP *fugitive-ts-setup* -- Enable/disable highlighting (default: true) enabled = true, + -- Enable debug logging (default: false) + -- Outputs to :messages with [fugitive-ts] prefix + debug = false, + -- Custom filename -> language mappings (optional) languages = {}, diff --git a/lua/fugitive-ts/highlight.lua b/lua/fugitive-ts/highlight.lua index 3c29658..c77a3fa 100644 --- a/lua/fugitive-ts/highlight.lua +++ b/lua/fugitive-ts/highlight.lua @@ -1,9 +1,17 @@ local M = {} +---@param msg string +---@param ... any +local function dbg(msg, ...) + local formatted = string.format(msg, ...) + vim.notify('[fugitive-ts] ' .. formatted, vim.log.levels.DEBUG) +end + ---@param bufnr integer ---@param ns integer ---@param hunk fugitive-ts.Hunk -function M.highlight_hunk(bufnr, ns, hunk) +---@param debug? boolean +function M.highlight_hunk(bufnr, ns, hunk, debug) local lang = hunk.lang if not lang then return @@ -22,19 +30,29 @@ function M.highlight_hunk(bufnr, ns, hunk) local ok, parser_obj = pcall(vim.treesitter.get_string_parser, code, lang) if not ok or not parser_obj then + if debug then + dbg('failed to create parser for lang: %s', lang) + end return end local trees = parser_obj:parse() if not trees or #trees == 0 then + if debug then + dbg('parse returned no trees for lang: %s', lang) + end return end local query = vim.treesitter.query.get(lang, 'highlights') if not query then + if debug then + dbg('no highlights query for lang: %s', lang) + end return end + local extmark_count = 0 for id, node, _ in query:iter_captures(trees[1]:root(), code) do local capture_name = '@' .. query.captures[id] local sr, sc, er, ec = node:range() @@ -50,6 +68,11 @@ function M.highlight_hunk(bufnr, ns, hunk) hl_group = capture_name, priority = 200, }) + extmark_count = extmark_count + 1 + end + + if debug then + dbg('hunk %s:%d applied %d extmarks', hunk.filename, hunk.start_line, extmark_count) end end diff --git a/lua/fugitive-ts/init.lua b/lua/fugitive-ts/init.lua index 9bc5d7a..8bd4977 100644 --- a/lua/fugitive-ts/init.lua +++ b/lua/fugitive-ts/init.lua @@ -1,5 +1,6 @@ ---@class fugitive-ts.Config ---@field enabled boolean +---@field debug boolean ---@field languages table ---@field debounce_ms integer @@ -17,6 +18,7 @@ local ns = vim.api.nvim_create_namespace('fugitive_ts') ---@type fugitive-ts.Config local default_config = { enabled = true, + debug = false, languages = {}, debounce_ms = 50, } @@ -27,6 +29,16 @@ local config = vim.deepcopy(default_config) ---@type table local attached_buffers = {} +---@param msg string +---@param ... any +local function dbg(msg, ...) + if not config.debug then + return + end + local formatted = string.format(msg, ...) + vim.notify('[fugitive-ts] ' .. formatted, vim.log.levels.DEBUG) +end + ---@param bufnr integer local function highlight_buffer(bufnr) if not config.enabled then @@ -39,9 +51,10 @@ local function highlight_buffer(bufnr) vim.api.nvim_buf_clear_namespace(bufnr, ns, 0, -1) - local hunks = parser.parse_buffer(bufnr, config.languages) + local hunks = parser.parse_buffer(bufnr, config.languages, config.debug) + dbg('found %d hunks in buffer %d', #hunks, bufnr) for _, hunk in ipairs(hunks) do - highlight.highlight_hunk(bufnr, ns, hunk) + highlight.highlight_hunk(bufnr, ns, hunk, config.debug) end end @@ -77,6 +90,8 @@ function M.attach(bufnr) end attached_buffers[bufnr] = true + dbg('attaching to buffer %d', bufnr) + local debounced = create_debounced_highlight(bufnr) highlight_buffer(bufnr) diff --git a/lua/fugitive-ts/parser.lua b/lua/fugitive-ts/parser.lua index 7ca5cb5..fec0dda 100644 --- a/lua/fugitive-ts/parser.lua +++ b/lua/fugitive-ts/parser.lua @@ -6,16 +6,27 @@ local M = {} +---@param msg string +---@param ... any +local function dbg(msg, ...) + local formatted = string.format(msg, ...) + vim.notify('[fugitive-ts] ' .. formatted, vim.log.levels.DEBUG) +end + ---@param filename string ---@param custom_langs? table +---@param debug? boolean ---@return string? -local function get_lang_from_filename(filename, custom_langs) +local function get_lang_from_filename(filename, custom_langs, debug) if custom_langs and custom_langs[filename] then return custom_langs[filename] end local ft = vim.filetype.match({ filename = filename }) if not ft then + if debug then + dbg('no filetype for: %s', filename) + end return nil end @@ -25,6 +36,11 @@ local function get_lang_from_filename(filename, custom_langs) if ok then return lang end + if debug then + dbg('no parser for lang: %s (ft: %s)', lang, ft) + end + elseif debug then + dbg('no ts lang for filetype: %s', ft) end return nil @@ -32,8 +48,9 @@ end ---@param bufnr integer ---@param custom_langs? table +---@param debug? boolean ---@return fugitive-ts.Hunk[] -function M.parse_buffer(bufnr, custom_langs) +function M.parse_buffer(bufnr, custom_langs, debug) local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false) ---@type fugitive-ts.Hunk[] local hunks = {} @@ -65,7 +82,10 @@ function M.parse_buffer(bufnr, custom_langs) if filename then flush_hunk() current_filename = filename - current_lang = get_lang_from_filename(filename, custom_langs) + current_lang = get_lang_from_filename(filename, custom_langs, debug) + if debug and current_lang then + dbg('file: %s -> lang: %s', filename, current_lang) + end elseif line:match('^@@.-@@') then flush_hunk() hunk_start = i From 0e86f45c39e88bbabdc9da80cd9ee50a1e2c63ec Mon Sep 17 00:00:00 2001 From: Barrett Ruth Date: Sun, 1 Feb 2026 18:52:00 -0500 Subject: [PATCH 4/5] feat: add some config options --- doc/fugitive-ts.nvim.txt | 4 ++++ lua/fugitive-ts/highlight.lua | 28 +++++++++++++++++++++++++++- lua/fugitive-ts/init.lua | 12 +++++++++++- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/doc/fugitive-ts.nvim.txt b/doc/fugitive-ts.nvim.txt index a825909..f91fb09 100644 --- a/doc/fugitive-ts.nvim.txt +++ b/doc/fugitive-ts.nvim.txt @@ -34,6 +34,10 @@ SETUP *fugitive-ts-setup* -- Debounce delay in ms (default: 50) debounce_ms = 50, + + -- Max lines per hunk before skipping treesitter (default: 500) + -- Prevents lag on large diffs + max_lines_per_hunk = 500, }) < diff --git a/lua/fugitive-ts/highlight.lua b/lua/fugitive-ts/highlight.lua index c77a3fa..ea292d0 100644 --- a/lua/fugitive-ts/highlight.lua +++ b/lua/fugitive-ts/highlight.lua @@ -10,13 +10,27 @@ end ---@param bufnr integer ---@param ns integer ---@param hunk fugitive-ts.Hunk +---@param max_lines integer ---@param debug? boolean -function M.highlight_hunk(bufnr, ns, hunk, debug) +function M.highlight_hunk(bufnr, ns, hunk, max_lines, debug) local lang = hunk.lang if not lang then return end + if #hunk.lines > max_lines then + if debug then + dbg( + 'skipping hunk %s:%d (%d lines > %d max)', + hunk.filename, + hunk.start_line, + #hunk.lines, + max_lines + ) + end + return + end + ---@type string[] local code_lines = {} for _, line in ipairs(hunk.lines) do @@ -52,6 +66,18 @@ function M.highlight_hunk(bufnr, ns, hunk, debug) return end + for i, line in ipairs(hunk.lines) do + local buf_line = hunk.start_line + i - 1 + local line_len = #line + if line_len > 1 then + pcall(vim.api.nvim_buf_set_extmark, bufnr, ns, buf_line, 1, { + end_col = line_len, + hl_group = 'Normal', + priority = 199, + }) + end + end + local extmark_count = 0 for id, node, _ in query:iter_captures(trees[1]:root(), code) do local capture_name = '@' .. query.captures[id] diff --git a/lua/fugitive-ts/init.lua b/lua/fugitive-ts/init.lua index 8bd4977..e6de719 100644 --- a/lua/fugitive-ts/init.lua +++ b/lua/fugitive-ts/init.lua @@ -3,6 +3,7 @@ ---@field debug boolean ---@field languages table ---@field debounce_ms integer +---@field max_lines_per_hunk integer ---@class fugitive-ts ---@field attach fun(bufnr?: integer) @@ -21,6 +22,7 @@ local default_config = { debug = false, languages = {}, debounce_ms = 50, + max_lines_per_hunk = 500, } ---@type fugitive-ts.Config @@ -54,7 +56,7 @@ local function highlight_buffer(bufnr) local hunks = parser.parse_buffer(bufnr, config.languages, config.debug) dbg('found %d hunks in buffer %d', #hunks, bufnr) for _, hunk in ipairs(hunks) do - highlight.highlight_hunk(bufnr, ns, hunk, config.debug) + highlight.highlight_hunk(bufnr, ns, hunk, config.max_lines_per_hunk, config.debug) end end @@ -101,6 +103,14 @@ function M.attach(bufnr) callback = debounced, }) + vim.api.nvim_create_autocmd('Syntax', { + buffer = bufnr, + callback = function() + dbg('syntax event, re-highlighting buffer %d', bufnr) + highlight_buffer(bufnr) + end, + }) + vim.api.nvim_create_autocmd('BufWipeout', { buffer = bufnr, callback = function() From 8d8a09635c25ac84bc5696cc74e832d15b77d630 Mon Sep 17 00:00:00 2001 From: Barrett Ruth Date: Sun, 1 Feb 2026 19:03:52 -0500 Subject: [PATCH 5/5] fix: correct ci --- .github/workflows/luarocks.yaml | 2 +- .pre-commit-config.yaml | 2 +- lua/fugitive-ts/init.lua | 5 ++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/luarocks.yaml b/.github/workflows/luarocks.yaml index 9f934a5..9b6664e 100644 --- a/.github/workflows/luarocks.yaml +++ b/.github/workflows/luarocks.yaml @@ -3,7 +3,7 @@ name: luarocks on: push: tags: - - "v*" + - 'v*' jobs: quality: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b9f6659..2edf043 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,4 +14,4 @@ repos: hooks: - id: prettier name: prettier - files: \.(md|,toml,yaml,sh)$ + files: \.(md|toml|yaml|sh)$ diff --git a/lua/fugitive-ts/init.lua b/lua/fugitive-ts/init.lua index e6de719..4247062 100644 --- a/lua/fugitive-ts/init.lua +++ b/lua/fugitive-ts/init.lua @@ -63,12 +63,11 @@ end ---@param bufnr integer ---@return fun() local function create_debounced_highlight(bufnr) - ---@type uv_timer_t? local timer = nil return function() if timer then - timer:stop() - timer:close() + timer:stop() ---@diagnostic disable-line: undefined-field + timer:close() ---@diagnostic disable-line: undefined-field end timer = vim.uv.new_timer() timer:start(