diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 74c4516ef1..9a36b368be 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -16,6 +16,7 @@ #include "nvim/autocmd_defs.h" #include "nvim/buffer.h" #include "nvim/buffer_defs.h" +#include "nvim/change.h" #include "nvim/charset.h" #include "nvim/cursor.h" #include "nvim/drawscreen.h" @@ -31,6 +32,7 @@ #include "nvim/ex_eval.h" #include "nvim/ex_eval_defs.h" #include "nvim/ex_getln.h" +#include "nvim/extmark.h" #include "nvim/fileio.h" #include "nvim/fold.h" #include "nvim/garray.h" @@ -50,6 +52,7 @@ #include "nvim/message.h" #include "nvim/move.h" #include "nvim/normal.h" +#include "nvim/ops.h" #include "nvim/option.h" #include "nvim/option_defs.h" #include "nvim/option_vars.h" @@ -4149,6 +4152,8 @@ static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last) } linenr_T old_line_count = buf->b_ml.ml_line_count; + colnr_T old_endcol = ml_get_buf_len(buf, old_line_count); + bcount_t old_bytecount = get_region_bytecount(buf, 1, old_line_count, 0, old_endcol); int qf_winid = 0; win_T *win; @@ -4182,7 +4187,25 @@ static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last) qf_update_win_titlevar(qi); qf_fill_buffer(qf_get_curlist(qi), buf, old_last, qf_winid); - buf_inc_changedtick(buf); + + linenr_T new_line_count = buf->b_ml.ml_line_count; + colnr_T new_endcol = ml_get_buf_len(buf, new_line_count); + bcount_t new_byte_count; + + linenr_T delta = new_line_count - old_line_count; + if (old_last == NULL) { + new_byte_count = get_region_bytecount(buf, 1, new_line_count, 0, new_endcol); + extmark_splice(buf, 0, 0, old_line_count - 1, 0, old_bytecount, new_line_count - 1, new_endcol, + new_byte_count, kExtmarkNoUndo); + changed_lines(buf, 1, 0, old_line_count > 0 ? old_line_count + 1 : 1, delta, true); + } else { + linenr_T start_lnum = old_line_count + 1; + new_byte_count = get_region_bytecount(buf, start_lnum, new_line_count, 0, new_endcol); + extmark_splice(buf, old_line_count - 1, old_endcol, 0, 0, 0, delta, new_endcol, new_byte_count, + kExtmarkNoUndo); + changed_lines(buf, start_lnum, 0, new_line_count + 1, delta + 1, true); + } + buf->b_changed = false; if (old_last == NULL) { qf_win_pos_update(qi, 0); diff --git a/test/functional/lua/buffer_updates_spec.lua b/test/functional/lua/buffer_updates_spec.lua index b9c1e9f897..93829bc5d4 100644 --- a/test/functional/lua/buffer_updates_spec.lua +++ b/test/functional/lua/buffer_updates_spec.lua @@ -420,6 +420,35 @@ describe('lua buffer event callbacks: on_lines', function() feed('i') eq({ '\ta' }, exec_lua('return _G.res[#_G.res]')) end) + + it('quickfix buffer send change', function() + command('copen') + exec_lua(function() + vim.api.nvim_buf_attach(vim.api.nvim_get_current_buf(), false, { + on_lines = function(...) + vim.g.qf_on_lines = { ... } + end, + on_bytes = function(...) + vim.g.qf_on_bytes = { ... } + end, + }) + end) + command('caddexpr "foo"') + eq({ 'bytes', 2, 2, 0, 0, 0, 0, 0, 0, 0, 6, 6 }, api.nvim_get_var('qf_on_bytes')) + eq({ 'lines', 2, 3, 0, 1, 1, 1 }, api.nvim_get_var('qf_on_lines')) + + command('caddexpr "bar"') + eq({ 'bytes', 2, 3, 0, 6, 6, 0, 0, 0, 1, 6, 6 }, api.nvim_get_var('qf_on_bytes')) + eq({ 'lines', 2, 4, 1, 2, 4, 0 }, api.nvim_get_var('qf_on_lines')) + + command('caddexpr ["line1", "line2", "line3"]') + eq({ 'bytes', 2, 4, 1, 6, 13, 0, 0, 0, 3, 8, 26 }, api.nvim_get_var('qf_on_bytes')) + eq({ 'lines', 2, 5, 2, 5, 9, 0 }, api.nvim_get_var('qf_on_lines')) + + command('cexpr "replace"') + eq({ 'bytes', 2, 5, 0, 0, 0, 4, 0, 40, 0, 10, 10 }, api.nvim_get_var('qf_on_bytes')) + eq({ 'lines', 2, 6, 0, 5, 1, 42 }, api.nvim_get_var('qf_on_lines')) + end) end) describe('lua: nvim_buf_attach on_bytes', function()