mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
refactor nvim_buf_set_lines to use extmark_splice
This commit is contained in:
parent
d2be261e8d
commit
a847abc21b
@ -27,6 +27,7 @@
|
|||||||
#include "nvim/map_defs.h"
|
#include "nvim/map_defs.h"
|
||||||
#include "nvim/map.h"
|
#include "nvim/map.h"
|
||||||
#include "nvim/mark.h"
|
#include "nvim/mark.h"
|
||||||
|
#include "nvim/ops.h"
|
||||||
#include "nvim/extmark.h"
|
#include "nvim/extmark.h"
|
||||||
#include "nvim/decoration.h"
|
#include "nvim/decoration.h"
|
||||||
#include "nvim/fileio.h"
|
#include "nvim/fileio.h"
|
||||||
@ -441,6 +442,8 @@ void nvim_buf_set_lines(uint64_t channel_id,
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bcount_t deleted_bytes = MAX(get_region_bytecount(start, end, 0, 0)-1, 0);
|
||||||
|
|
||||||
// If the size of the range is reducing (ie, new_len < old_len) we
|
// If the size of the range is reducing (ie, new_len < old_len) we
|
||||||
// need to delete some old_len. We do this at the start, by
|
// need to delete some old_len. We do this at the start, by
|
||||||
// repeatedly deleting line "start".
|
// repeatedly deleting line "start".
|
||||||
@ -460,6 +463,7 @@ void nvim_buf_set_lines(uint64_t channel_id,
|
|||||||
// new old_len. This is a more efficient operation, as it requires
|
// new old_len. This is a more efficient operation, as it requires
|
||||||
// less memory allocation and freeing.
|
// less memory allocation and freeing.
|
||||||
size_t to_replace = old_len < new_len ? old_len : new_len;
|
size_t to_replace = old_len < new_len ? old_len : new_len;
|
||||||
|
bcount_t inserted_bytes = 0;
|
||||||
for (size_t i = 0; i < to_replace; i++) {
|
for (size_t i = 0; i < to_replace; i++) {
|
||||||
int64_t lnum = start + (int64_t)i;
|
int64_t lnum = start + (int64_t)i;
|
||||||
|
|
||||||
@ -472,6 +476,8 @@ void nvim_buf_set_lines(uint64_t channel_id,
|
|||||||
api_set_error(err, kErrorTypeException, "Failed to replace line");
|
api_set_error(err, kErrorTypeException, "Failed to replace line");
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inserted_bytes += STRLEN(lines[i]) + 1;
|
||||||
// Mark lines that haven't been passed to the buffer as they need
|
// Mark lines that haven't been passed to the buffer as they need
|
||||||
// to be freed later
|
// to be freed later
|
||||||
lines[i] = NULL;
|
lines[i] = NULL;
|
||||||
@ -491,6 +497,8 @@ void nvim_buf_set_lines(uint64_t channel_id,
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inserted_bytes += STRLEN(lines[i]) + 1;
|
||||||
|
|
||||||
// Same as with replacing, but we also need to free lines
|
// Same as with replacing, but we also need to free lines
|
||||||
xfree(lines[i]);
|
xfree(lines[i]);
|
||||||
lines[i] = NULL;
|
lines[i] = NULL;
|
||||||
@ -505,7 +513,11 @@ void nvim_buf_set_lines(uint64_t channel_id,
|
|||||||
(linenr_T)(end - 1),
|
(linenr_T)(end - 1),
|
||||||
MAXLNUM,
|
MAXLNUM,
|
||||||
(long)extra,
|
(long)extra,
|
||||||
kExtmarkUndo);
|
kExtmarkNOOP);
|
||||||
|
|
||||||
|
extmark_splice(curbuf, (int)start-1, 0, (int)(end-start), 0,
|
||||||
|
deleted_bytes, (int)(end+extra-1), 0, inserted_bytes,
|
||||||
|
kExtmarkUndo);
|
||||||
|
|
||||||
changed_lines((linenr_T)start, 0, (linenr_T)end, (long)extra, true);
|
changed_lines((linenr_T)start, 0, (linenr_T)end, (long)extra, true);
|
||||||
fix_cursor((linenr_T)start, (linenr_T)end, (linenr_T)extra);
|
fix_cursor((linenr_T)start, (linenr_T)end, (linenr_T)extra);
|
||||||
|
@ -1676,17 +1676,14 @@ int op_delete(oparg_T *oap)
|
|||||||
|
|
||||||
curbuf_splice_pending++;
|
curbuf_splice_pending++;
|
||||||
pos_T startpos = curwin->w_cursor; // start position for delete
|
pos_T startpos = curwin->w_cursor; // start position for delete
|
||||||
bcount_t deleted_bytes = (bcount_t)STRLEN(
|
bcount_t deleted_bytes = get_region_bytecount(
|
||||||
ml_get(startpos.lnum)) + 1 - startpos.col;
|
startpos.lnum, oap->end.lnum, startpos.col,
|
||||||
|
oap->end.col) - !oap->inclusive;
|
||||||
truncate_line(true); // delete from cursor to end of line
|
truncate_line(true); // delete from cursor to end of line
|
||||||
|
|
||||||
curpos = curwin->w_cursor; // remember curwin->w_cursor
|
curpos = curwin->w_cursor; // remember curwin->w_cursor
|
||||||
curwin->w_cursor.lnum++;
|
curwin->w_cursor.lnum++;
|
||||||
|
|
||||||
for (linenr_T i = 1; i <= oap->line_count - 2; i++) {
|
|
||||||
deleted_bytes += (bcount_t)STRLEN(
|
|
||||||
ml_get(startpos.lnum + i)) + 1;
|
|
||||||
}
|
|
||||||
del_lines(oap->line_count - 2, false);
|
del_lines(oap->line_count - 2, false);
|
||||||
|
|
||||||
// delete from start of line until op_end
|
// delete from start of line until op_end
|
||||||
@ -1694,7 +1691,6 @@ int op_delete(oparg_T *oap)
|
|||||||
curwin->w_cursor.col = 0;
|
curwin->w_cursor.col = 0;
|
||||||
(void)del_bytes((colnr_T)n, !virtual_op,
|
(void)del_bytes((colnr_T)n, !virtual_op,
|
||||||
oap->op_type == OP_DELETE && !oap->is_VIsual);
|
oap->op_type == OP_DELETE && !oap->is_VIsual);
|
||||||
deleted_bytes += n;
|
|
||||||
curwin->w_cursor = curpos; // restore curwin->w_cursor
|
curwin->w_cursor = curpos; // restore curwin->w_cursor
|
||||||
(void)do_join(2, false, false, false, false);
|
(void)do_join(2, false, false, false, false);
|
||||||
curbuf_splice_pending--;
|
curbuf_splice_pending--;
|
||||||
@ -6303,3 +6299,20 @@ bool op_reg_set_previous(const char name)
|
|||||||
y_previous = &y_regs[i];
|
y_previous = &y_regs[i];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bcount_t get_region_bytecount(linenr_T start_lnum, linenr_T end_lnum,
|
||||||
|
colnr_T start_col, colnr_T end_col)
|
||||||
|
{
|
||||||
|
const char *first = (const char *)ml_get(start_lnum);
|
||||||
|
bcount_t deleted_bytes = (bcount_t)STRLEN(first) - start_col + 1;
|
||||||
|
|
||||||
|
if (start_lnum == end_lnum) {
|
||||||
|
return deleted_bytes - ((bcount_t)STRLEN(first) - end_col + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (linenr_T i = 1; i <= end_lnum-start_lnum-1; i++) {
|
||||||
|
deleted_bytes += (bcount_t)STRLEN(
|
||||||
|
ml_get(start_lnum + i)) + 1;
|
||||||
|
}
|
||||||
|
return deleted_bytes + end_col + 1;
|
||||||
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "nvim/macros.h"
|
#include "nvim/macros.h"
|
||||||
#include "nvim/ascii.h"
|
#include "nvim/ascii.h"
|
||||||
#include "nvim/types.h"
|
#include "nvim/types.h"
|
||||||
|
#include "nvim/extmark.h"
|
||||||
#include "nvim/eval/typval.h"
|
#include "nvim/eval/typval.h"
|
||||||
#include "nvim/os/time.h"
|
#include "nvim/os/time.h"
|
||||||
#include "nvim/normal.h" // for MotionType and oparg_T
|
#include "nvim/normal.h" // for MotionType and oparg_T
|
||||||
|
@ -958,6 +958,29 @@ describe('lua: nvim_buf_attach on_bytes', function()
|
|||||||
}
|
}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it("nvim_buf_set_lines", function()
|
||||||
|
local check_events = setup_eventcheck(verify, {"AAA", "BBB"})
|
||||||
|
|
||||||
|
-- delete
|
||||||
|
command("lua vim.api.nvim_buf_set_lines(0, 0, 1, true, {})")
|
||||||
|
|
||||||
|
check_events {
|
||||||
|
{ "test1", "bytes", 1, 3, 0, 0, 0, 1, 0, 4, 0, 0, 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
-- add
|
||||||
|
command("lua vim.api.nvim_buf_set_lines(0, 0, 0, true, {'asdf'})")
|
||||||
|
check_events {
|
||||||
|
{ "test1", "bytes", 1, 4, 0, 0, 0, 0, 0, 0, 1, 0, 5 };
|
||||||
|
}
|
||||||
|
|
||||||
|
-- replace
|
||||||
|
command("lua vim.api.nvim_buf_set_lines(0, 0, 1, true, {'asdf', 'fdsa'})")
|
||||||
|
check_events {
|
||||||
|
{ "test1", "bytes", 1, 5, 0, 0, 0, 1, 0, 5, 2, 0, 10 };
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
|
||||||
teardown(function()
|
teardown(function()
|
||||||
os.remove "Xtest-reload"
|
os.remove "Xtest-reload"
|
||||||
os.remove "Xtest-undofile"
|
os.remove "Xtest-undofile"
|
||||||
|
Loading…
Reference in New Issue
Block a user