mirror of
https://github.com/neovim/neovim.git
synced 2025-09-18 01:08:20 +00:00
api/buffer: add "on_bytes" callback to nvim_buf_attach
This implements byte-resolution updates of buffer changes. Note: there is no promise that the buffer state is valid inside the callback!
This commit is contained in:
@@ -479,18 +479,18 @@ void extmark_apply_undo(ExtmarkUndoObject undo_info, bool undo)
|
||||
// Undo
|
||||
ExtmarkSplice splice = undo_info.data.splice;
|
||||
if (undo) {
|
||||
extmark_splice(curbuf,
|
||||
splice.start_row, splice.start_col,
|
||||
splice.new_row, splice.new_col,
|
||||
splice.old_row, splice.old_col,
|
||||
kExtmarkNoUndo);
|
||||
extmark_splice_impl(curbuf,
|
||||
splice.start_row, splice.start_col, splice.start_byte,
|
||||
splice.new_row, splice.new_col, splice.new_byte,
|
||||
splice.old_row, splice.old_col, splice.old_byte,
|
||||
kExtmarkNoUndo);
|
||||
|
||||
} else {
|
||||
extmark_splice(curbuf,
|
||||
splice.start_row, splice.start_col,
|
||||
splice.old_row, splice.old_col,
|
||||
splice.new_row, splice.new_col,
|
||||
kExtmarkNoUndo);
|
||||
extmark_splice_impl(curbuf,
|
||||
splice.start_row, splice.start_col, splice.start_byte,
|
||||
splice.old_row, splice.old_col, splice.old_byte,
|
||||
splice.new_row, splice.new_col, splice.new_byte,
|
||||
kExtmarkNoUndo);
|
||||
}
|
||||
// kExtmarkSavePos
|
||||
} else if (undo_info.type == kExtmarkSavePos) {
|
||||
@@ -509,15 +509,15 @@ void extmark_apply_undo(ExtmarkUndoObject undo_info, bool undo)
|
||||
ExtmarkMove move = undo_info.data.move;
|
||||
if (undo) {
|
||||
extmark_move_region(curbuf,
|
||||
move.new_row, move.new_col,
|
||||
move.extent_row, move.extent_col,
|
||||
move.start_row, move.start_col,
|
||||
move.new_row, move.new_col, move.new_byte,
|
||||
move.extent_row, move.extent_col, move.extent_byte,
|
||||
move.start_row, move.start_col, move.start_byte,
|
||||
kExtmarkNoUndo);
|
||||
} else {
|
||||
extmark_move_region(curbuf,
|
||||
move.start_row, move.start_col,
|
||||
move.extent_row, move.extent_col,
|
||||
move.new_row, move.new_col,
|
||||
move.start_row, move.start_col, move.start_byte,
|
||||
move.extent_row, move.extent_col, move.extent_byte,
|
||||
move.new_row, move.new_col, move.new_byte,
|
||||
kExtmarkNoUndo);
|
||||
}
|
||||
}
|
||||
@@ -532,36 +532,57 @@ void extmark_adjust(buf_T *buf,
|
||||
long amount_after,
|
||||
ExtmarkOp undo)
|
||||
{
|
||||
if (!curbuf_splice_pending) {
|
||||
int old_extent, new_extent;
|
||||
if (amount == MAXLNUM) {
|
||||
old_extent = (int)(line2 - line1+1);
|
||||
new_extent = (int)(amount_after + old_extent);
|
||||
} else {
|
||||
// A region is either deleted (amount == MAXLNUM) or
|
||||
// added (line2 == MAXLNUM). The only other case is :move
|
||||
// which is handled by a separate entry point extmark_move_region.
|
||||
assert(line2 == MAXLNUM);
|
||||
old_extent = 0;
|
||||
new_extent = (int)amount;
|
||||
}
|
||||
extmark_splice(buf,
|
||||
(int)line1-1, 0,
|
||||
old_extent, 0,
|
||||
new_extent, 0, undo);
|
||||
if (curbuf_splice_pending) {
|
||||
return;
|
||||
}
|
||||
bcount_t start_byte = ml_find_line_or_offset(buf, line1, NULL, true);
|
||||
bcount_t old_byte = 0, new_byte = 0;
|
||||
int old_row, new_row;
|
||||
if (amount == MAXLNUM) {
|
||||
old_row = (int)(line2 - line1+1);
|
||||
// TODO: ej kasta?
|
||||
old_byte = (bcount_t)buf->deleted_bytes2;
|
||||
|
||||
new_row = (int)(amount_after + old_row);
|
||||
} else {
|
||||
// A region is either deleted (amount == MAXLNUM) or
|
||||
// added (line2 == MAXLNUM). The only other case is :move
|
||||
// which is handled by a separate entry point extmark_move_region.
|
||||
assert(line2 == MAXLNUM);
|
||||
old_row = 0;
|
||||
new_row = (int)amount;
|
||||
}
|
||||
if (new_row > 0) {
|
||||
new_byte = ml_find_line_or_offset(buf, line1+new_row, NULL, true)-start_byte;
|
||||
}
|
||||
extmark_splice_impl(buf,
|
||||
(int)line1-1, 0, start_byte,
|
||||
old_row, 0, old_byte,
|
||||
new_row, 0, new_byte, undo);
|
||||
}
|
||||
|
||||
|
||||
void extmark_splice(buf_T *buf,
|
||||
int start_row, colnr_T start_col,
|
||||
int old_row, colnr_T old_col,
|
||||
int new_row, colnr_T new_col,
|
||||
ExtmarkOp undo)
|
||||
int start_row, colnr_T start_col,
|
||||
int old_row, colnr_T old_col, bcount_t old_byte,
|
||||
int new_row, colnr_T new_col, bcount_t new_byte,
|
||||
ExtmarkOp undo)
|
||||
{
|
||||
buf_updates_send_splice(buf, start_row, start_col,
|
||||
old_row, old_col,
|
||||
new_row, new_col);
|
||||
long offset = ml_find_line_or_offset(buf, start_row+1, NULL, true);
|
||||
extmark_splice_impl(buf, start_row, start_col, offset+start_col,
|
||||
old_row, old_col, old_byte, new_row, new_col, new_byte,
|
||||
undo);
|
||||
}
|
||||
|
||||
void extmark_splice_impl(buf_T *buf,
|
||||
int start_row, colnr_T start_col, bcount_t start_byte,
|
||||
int old_row, colnr_T old_col, bcount_t old_byte,
|
||||
int new_row, colnr_T new_col, bcount_t new_byte,
|
||||
ExtmarkOp undo)
|
||||
{
|
||||
curbuf->deleted_bytes2 = 0;
|
||||
buf_updates_send_splice(buf, start_row, start_col, start_byte,
|
||||
old_row, old_col, old_byte,
|
||||
new_row, new_col, new_byte);
|
||||
|
||||
if (undo == kExtmarkUndo && (old_row > 0 || old_col > 0)) {
|
||||
// Copy marks that would be effected by delete
|
||||
@@ -599,15 +620,19 @@ void extmark_splice(buf_T *buf,
|
||||
if (old_col == 0 && start_col >= splice->start_col
|
||||
&& start_col <= splice->start_col+splice->new_col) {
|
||||
splice->new_col += new_col;
|
||||
splice->new_byte += new_byte;
|
||||
merged = true;
|
||||
} else if (new_col == 0
|
||||
&& start_col == splice->start_col+splice->new_col) {
|
||||
splice->old_col += old_col;
|
||||
splice->old_byte += old_byte;
|
||||
merged = true;
|
||||
} else if (new_col == 0
|
||||
&& start_col + old_col == splice->start_col) {
|
||||
splice->start_col = start_col;
|
||||
splice->start_byte = start_byte;
|
||||
splice->old_col += old_col;
|
||||
splice->old_byte += old_byte;
|
||||
merged = true;
|
||||
}
|
||||
}
|
||||
@@ -618,10 +643,13 @@ void extmark_splice(buf_T *buf,
|
||||
ExtmarkSplice splice;
|
||||
splice.start_row = start_row;
|
||||
splice.start_col = start_col;
|
||||
splice.start_byte = start_byte;
|
||||
splice.old_row = old_row;
|
||||
splice.old_col = old_col;
|
||||
splice.old_byte = old_byte;
|
||||
splice.new_row = new_row;
|
||||
splice.new_col = new_col;
|
||||
splice.new_byte = new_byte;
|
||||
|
||||
kv_push(uhp->uh_extmark,
|
||||
((ExtmarkUndoObject){ .type = kExtmarkSplice,
|
||||
@@ -635,29 +663,31 @@ void extmark_splice_cols(buf_T *buf,
|
||||
colnr_T old_col, colnr_T new_col,
|
||||
ExtmarkOp undo)
|
||||
{
|
||||
extmark_splice(buf, start_row, start_col, 0, old_col, 0, new_col, undo);
|
||||
extmark_splice(buf, start_row, start_col,
|
||||
0, old_col, old_col,
|
||||
0, new_col, new_col, undo);
|
||||
}
|
||||
|
||||
void extmark_move_region(buf_T *buf,
|
||||
int start_row, colnr_T start_col,
|
||||
int extent_row, colnr_T extent_col,
|
||||
int new_row, colnr_T new_col,
|
||||
int start_row, colnr_T start_col, bcount_t start_byte,
|
||||
int extent_row, colnr_T extent_col, bcount_t extent_byte,
|
||||
int new_row, colnr_T new_col, bcount_t new_byte,
|
||||
ExtmarkOp undo)
|
||||
{
|
||||
// TODO(bfredl): this is not synced to the buffer state inside the callback.
|
||||
// But unless we make the undo implementation smarter, this is not ensured
|
||||
// anyway.
|
||||
buf_updates_send_splice(buf, start_row, start_col,
|
||||
extent_row, extent_col,
|
||||
0, 0);
|
||||
buf_updates_send_splice(buf, start_row, start_col, start_byte,
|
||||
extent_row, extent_col, extent_byte,
|
||||
0, 0, 0);
|
||||
|
||||
marktree_move_region(buf->b_marktree, start_row, start_col,
|
||||
extent_row, extent_col,
|
||||
new_row, new_col);
|
||||
|
||||
buf_updates_send_splice(buf, new_row, new_col,
|
||||
0, 0,
|
||||
extent_row, extent_col);
|
||||
buf_updates_send_splice(buf, new_row, new_col, new_byte,
|
||||
0, 0, 0,
|
||||
extent_row, extent_col, extent_byte);
|
||||
|
||||
|
||||
if (undo == kExtmarkUndo) {
|
||||
@@ -669,10 +699,13 @@ void extmark_move_region(buf_T *buf,
|
||||
ExtmarkMove move;
|
||||
move.start_row = start_row;
|
||||
move.start_col = start_col;
|
||||
move.start_byte = start_byte;
|
||||
move.extent_row = extent_row;
|
||||
move.extent_col = extent_col;
|
||||
move.extent_byte = extent_byte;
|
||||
move.new_row = new_row;
|
||||
move.new_col = new_col;
|
||||
move.new_byte = new_byte;
|
||||
|
||||
kv_push(uhp->uh_extmark,
|
||||
((ExtmarkUndoObject){ .type = kExtmarkMove,
|
||||
|
Reference in New Issue
Block a user