aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/api/buffer.c
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2025-02-05 23:09:29 +0000
committerJosh Rahm <joshuarahm@gmail.com>2025-02-05 23:09:29 +0000
commitd5f194ce780c95821a855aca3c19426576d28ae0 (patch)
treed45f461b19f9118ad2bb1f440a7a08973ad18832 /src/nvim/api/buffer.c
parentc5d770d311841ea5230426cc4c868e8db27300a8 (diff)
parent44740e561fc93afe3ebecfd3618bda2d2abeafb0 (diff)
downloadrneovim-rahm.tar.gz
rneovim-rahm.tar.bz2
rneovim-rahm.zip
Merge remote-tracking branch 'upstream/master' into mix_20240309HEADrahm
Diffstat (limited to 'src/nvim/api/buffer.c')
-rw-r--r--src/nvim/api/buffer.c351
1 files changed, 175 insertions, 176 deletions
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index 9480292d9a..aa349790b3 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -23,7 +23,6 @@
#include "nvim/buffer_updates.h"
#include "nvim/change.h"
#include "nvim/cursor.h"
-#include "nvim/drawscreen.h"
#include "nvim/ex_cmds.h"
#include "nvim/extmark.h"
#include "nvim/extmark_defs.h"
@@ -360,93 +359,91 @@ void nvim_buf_set_lines(uint64_t channel_id, Buffer buffer, Integer start, Integ
memchrsub(lines[i], NUL, NL, l.size);
}
- try_start();
-
- if (!MODIFIABLE(buf)) {
- api_set_error(err, kErrorTypeException, "Buffer is not 'modifiable'");
- goto end;
- }
-
- if (u_save_buf(buf, (linenr_T)(start - 1), (linenr_T)end) == FAIL) {
- api_set_error(err, kErrorTypeException, "Failed to save undo information");
- goto end;
- }
-
- bcount_t deleted_bytes = get_region_bytecount(buf, (linenr_T)start, (linenr_T)end, 0, 0);
-
- // 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
- // repeatedly deleting line "start".
- size_t to_delete = (new_len < old_len) ? old_len - new_len : 0;
- for (size_t i = 0; i < to_delete; i++) {
- if (ml_delete_buf(buf, (linenr_T)start, false) == FAIL) {
- api_set_error(err, kErrorTypeException, "Failed to delete line");
+ TRY_WRAP(err, {
+ if (!MODIFIABLE(buf)) {
+ api_set_error(err, kErrorTypeException, "Buffer is not 'modifiable'");
goto end;
}
- }
- if (to_delete > 0) {
- extra -= (ptrdiff_t)to_delete;
- }
+ if (u_save_buf(buf, (linenr_T)(start - 1), (linenr_T)end) == FAIL) {
+ api_set_error(err, kErrorTypeException, "Failed to save undo information");
+ goto end;
+ }
- // For as long as possible, replace the existing old_len with the
- // new old_len. This is a more efficient operation, as it requires
- // less memory allocation and freeing.
- 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++) {
- int64_t lnum = start + (int64_t)i;
+ bcount_t deleted_bytes = get_region_bytecount(buf, (linenr_T)start, (linenr_T)end, 0, 0);
- VALIDATE(lnum < MAXLNUM, "%s", "Index out of bounds", {
- goto end;
- });
+ // 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
+ // repeatedly deleting line "start".
+ size_t to_delete = (new_len < old_len) ? old_len - new_len : 0;
+ for (size_t i = 0; i < to_delete; i++) {
+ if (ml_delete_buf(buf, (linenr_T)start, false) == FAIL) {
+ api_set_error(err, kErrorTypeException, "Failed to delete line");
+ goto end;
+ }
+ }
- if (ml_replace_buf(buf, (linenr_T)lnum, lines[i], false, true) == FAIL) {
- api_set_error(err, kErrorTypeException, "Failed to replace line");
- goto end;
+ if (to_delete > 0) {
+ extra -= (ptrdiff_t)to_delete;
}
- inserted_bytes += (bcount_t)strlen(lines[i]) + 1;
- }
+ // For as long as possible, replace the existing old_len with the
+ // new old_len. This is a more efficient operation, as it requires
+ // less memory allocation and freeing.
+ 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++) {
+ int64_t lnum = start + (int64_t)i;
+
+ VALIDATE(lnum < MAXLNUM, "%s", "Index out of bounds", {
+ goto end;
+ });
+
+ if (ml_replace_buf(buf, (linenr_T)lnum, lines[i], false, true) == FAIL) {
+ api_set_error(err, kErrorTypeException, "Failed to replace line");
+ goto end;
+ }
- // Now we may need to insert the remaining new old_len
- for (size_t i = to_replace; i < new_len; i++) {
- int64_t lnum = start + (int64_t)i - 1;
+ inserted_bytes += (bcount_t)strlen(lines[i]) + 1;
+ }
- VALIDATE(lnum < MAXLNUM, "%s", "Index out of bounds", {
- goto end;
- });
+ // Now we may need to insert the remaining new old_len
+ for (size_t i = to_replace; i < new_len; i++) {
+ int64_t lnum = start + (int64_t)i - 1;
- if (ml_append_buf(buf, (linenr_T)lnum, lines[i], 0, false) == FAIL) {
- api_set_error(err, kErrorTypeException, "Failed to insert line");
- goto end;
- }
+ VALIDATE(lnum < MAXLNUM, "%s", "Index out of bounds", {
+ goto end;
+ });
- inserted_bytes += (bcount_t)strlen(lines[i]) + 1;
+ if (ml_append_buf(buf, (linenr_T)lnum, lines[i], 0, false) == FAIL) {
+ api_set_error(err, kErrorTypeException, "Failed to insert line");
+ goto end;
+ }
- extra++;
- }
+ inserted_bytes += (bcount_t)strlen(lines[i]) + 1;
- // Adjust marks. Invalidate any which lie in the
- // changed range, and move any in the remainder of the buffer.
- linenr_T adjust = end > start ? MAXLNUM : 0;
- mark_adjust_buf(buf, (linenr_T)start, (linenr_T)(end - 1), adjust, (linenr_T)extra,
- true, true, kExtmarkNOOP);
+ extra++;
+ }
- extmark_splice(buf, (int)start - 1, 0, (int)(end - start), 0,
- deleted_bytes, (int)new_len, 0, inserted_bytes,
- kExtmarkUndo);
+ // Adjust marks. Invalidate any which lie in the
+ // changed range, and move any in the remainder of the buffer.
+ linenr_T adjust = end > start ? MAXLNUM : 0;
+ mark_adjust_buf(buf, (linenr_T)start, (linenr_T)(end - 1), adjust, (linenr_T)extra,
+ true, true, kExtmarkNOOP);
- changed_lines(buf, (linenr_T)start, 0, (linenr_T)end, (linenr_T)extra, true);
+ extmark_splice(buf, (int)start - 1, 0, (int)(end - start), 0,
+ deleted_bytes, (int)new_len, 0, inserted_bytes,
+ kExtmarkUndo);
- FOR_ALL_TAB_WINDOWS(tp, win) {
- if (win->w_buffer == buf) {
- fix_cursor(win, (linenr_T)start, (linenr_T)end, (linenr_T)extra);
- }
- }
+ changed_lines(buf, (linenr_T)start, 0, (linenr_T)end, (linenr_T)extra, true);
-end:
- try_end(err);
+ FOR_ALL_TAB_WINDOWS(tp, win) {
+ if (win->w_buffer == buf) {
+ fix_cursor(win, (linenr_T)start, (linenr_T)end, (linenr_T)extra);
+ }
+ }
+ end:;
+ });
}
/// Sets (replaces) a range in the buffer
@@ -593,101 +590,99 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In
new_byte += (bcount_t)(last_item.size) + 1;
}
- try_start();
-
- if (!MODIFIABLE(buf)) {
- api_set_error(err, kErrorTypeException, "Buffer is not 'modifiable'");
- goto end;
- }
-
- // Small note about undo states: unlike set_lines, we want to save the
- // undo state of one past the end_row, since end_row is inclusive.
- if (u_save_buf(buf, (linenr_T)start_row - 1, (linenr_T)end_row + 1) == FAIL) {
- api_set_error(err, kErrorTypeException, "Failed to save undo information");
- goto end;
- }
-
- ptrdiff_t extra = 0; // lines added to text, can be negative
- size_t old_len = (size_t)(end_row - start_row + 1);
-
- // 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
- // repeatedly deleting line "start".
- size_t to_delete = (new_len < old_len) ? old_len - new_len : 0;
- for (size_t i = 0; i < to_delete; i++) {
- if (ml_delete_buf(buf, (linenr_T)start_row, false) == FAIL) {
- api_set_error(err, kErrorTypeException, "Failed to delete line");
+ TRY_WRAP(err, {
+ if (!MODIFIABLE(buf)) {
+ api_set_error(err, kErrorTypeException, "Buffer is not 'modifiable'");
goto end;
}
- }
- if (to_delete > 0) {
- extra -= (ptrdiff_t)to_delete;
- }
-
- // For as long as possible, replace the existing old_len with the
- // new old_len. This is a more efficient operation, as it requires
- // less memory allocation and freeing.
- size_t to_replace = old_len < new_len ? old_len : new_len;
- for (size_t i = 0; i < to_replace; i++) {
- int64_t lnum = start_row + (int64_t)i;
-
- VALIDATE((lnum < MAXLNUM), "%s", "Index out of bounds", {
+ // Small note about undo states: unlike set_lines, we want to save the
+ // undo state of one past the end_row, since end_row is inclusive.
+ if (u_save_buf(buf, (linenr_T)start_row - 1, (linenr_T)end_row + 1) == FAIL) {
+ api_set_error(err, kErrorTypeException, "Failed to save undo information");
goto end;
- });
+ }
- if (ml_replace_buf(buf, (linenr_T)lnum, lines[i], false, true) == FAIL) {
- api_set_error(err, kErrorTypeException, "Failed to replace line");
- goto end;
+ ptrdiff_t extra = 0; // lines added to text, can be negative
+ size_t old_len = (size_t)(end_row - start_row + 1);
+
+ // 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
+ // repeatedly deleting line "start".
+ size_t to_delete = (new_len < old_len) ? old_len - new_len : 0;
+ for (size_t i = 0; i < to_delete; i++) {
+ if (ml_delete_buf(buf, (linenr_T)start_row, false) == FAIL) {
+ api_set_error(err, kErrorTypeException, "Failed to delete line");
+ goto end;
+ }
}
- }
- // Now we may need to insert the remaining new old_len
- for (size_t i = to_replace; i < new_len; i++) {
- int64_t lnum = start_row + (int64_t)i - 1;
+ if (to_delete > 0) {
+ extra -= (ptrdiff_t)to_delete;
+ }
- VALIDATE((lnum < MAXLNUM), "%s", "Index out of bounds", {
- goto end;
- });
+ // For as long as possible, replace the existing old_len with the
+ // new old_len. This is a more efficient operation, as it requires
+ // less memory allocation and freeing.
+ size_t to_replace = old_len < new_len ? old_len : new_len;
+ for (size_t i = 0; i < to_replace; i++) {
+ int64_t lnum = start_row + (int64_t)i;
- if (ml_append_buf(buf, (linenr_T)lnum, lines[i], 0, false) == FAIL) {
- api_set_error(err, kErrorTypeException, "Failed to insert line");
- goto end;
+ VALIDATE((lnum < MAXLNUM), "%s", "Index out of bounds", {
+ goto end;
+ });
+
+ if (ml_replace_buf(buf, (linenr_T)lnum, lines[i], false, true) == FAIL) {
+ api_set_error(err, kErrorTypeException, "Failed to replace line");
+ goto end;
+ }
}
- extra++;
- }
+ // Now we may need to insert the remaining new old_len
+ for (size_t i = to_replace; i < new_len; i++) {
+ int64_t lnum = start_row + (int64_t)i - 1;
- colnr_T col_extent = (colnr_T)(end_col
- - ((end_row == start_row) ? start_col : 0));
-
- // Adjust marks. Invalidate any which lie in the
- // changed range, and move any in the remainder of the buffer.
- // Do not adjust any cursors. need to use column-aware logic (below)
- linenr_T adjust = end_row >= start_row ? MAXLNUM : 0;
- mark_adjust_buf(buf, (linenr_T)start_row, (linenr_T)end_row, adjust, (linenr_T)extra,
- true, true, kExtmarkNOOP);
-
- extmark_splice(buf, (int)start_row - 1, (colnr_T)start_col,
- (int)(end_row - start_row), col_extent, old_byte,
- (int)new_len - 1, (colnr_T)last_item.size, new_byte,
- kExtmarkUndo);
-
- changed_lines(buf, (linenr_T)start_row, 0, (linenr_T)end_row + 1, (linenr_T)extra, true);
-
- FOR_ALL_TAB_WINDOWS(tp, win) {
- if (win->w_buffer == buf) {
- if (win->w_cursor.lnum >= start_row && win->w_cursor.lnum <= end_row) {
- fix_cursor_cols(win, (linenr_T)start_row, (colnr_T)start_col, (linenr_T)end_row,
- (colnr_T)end_col, (linenr_T)new_len, (colnr_T)last_item.size);
- } else {
- fix_cursor(win, (linenr_T)start_row, (linenr_T)end_row, (linenr_T)extra);
+ VALIDATE((lnum < MAXLNUM), "%s", "Index out of bounds", {
+ goto end;
+ });
+
+ if (ml_append_buf(buf, (linenr_T)lnum, lines[i], 0, false) == FAIL) {
+ api_set_error(err, kErrorTypeException, "Failed to insert line");
+ goto end;
}
+
+ extra++;
}
- }
-end:
- try_end(err);
+ colnr_T col_extent = (colnr_T)(end_col
+ - ((end_row == start_row) ? start_col : 0));
+
+ // Adjust marks. Invalidate any which lie in the
+ // changed range, and move any in the remainder of the buffer.
+ // Do not adjust any cursors. need to use column-aware logic (below)
+ linenr_T adjust = end_row >= start_row ? MAXLNUM : 0;
+ mark_adjust_buf(buf, (linenr_T)start_row, (linenr_T)end_row, adjust, (linenr_T)extra,
+ true, true, kExtmarkNOOP);
+
+ extmark_splice(buf, (int)start_row - 1, (colnr_T)start_col,
+ (int)(end_row - start_row), col_extent, old_byte,
+ (int)new_len - 1, (colnr_T)last_item.size, new_byte,
+ kExtmarkUndo);
+
+ changed_lines(buf, (linenr_T)start_row, 0, (linenr_T)end_row + 1, (linenr_T)extra, true);
+
+ FOR_ALL_TAB_WINDOWS(tp, win) {
+ if (win->w_buffer == buf) {
+ if (win->w_cursor.lnum >= start_row && win->w_cursor.lnum <= end_row) {
+ fix_cursor_cols(win, (linenr_T)start_row, (colnr_T)start_col, (linenr_T)end_row,
+ (colnr_T)end_col, (linenr_T)new_len, (colnr_T)last_item.size);
+ } else {
+ fix_cursor(win, (linenr_T)start_row, (linenr_T)end_row, (linenr_T)extra);
+ }
+ }
+ }
+ end:;
+ });
}
/// Gets a range from the buffer.
@@ -965,26 +960,27 @@ void nvim_buf_set_name(Buffer buffer, String name, Error *err)
return;
}
- try_start();
-
- const bool is_curbuf = buf == curbuf;
- const int save_acd = p_acd;
- if (!is_curbuf) {
- // Temporarily disable 'autochdir' when setting file name for another buffer.
- p_acd = false;
- }
+ int ren_ret = OK;
+ TRY_WRAP(err, {
+ const bool is_curbuf = buf == curbuf;
+ const int save_acd = p_acd;
+ if (!is_curbuf) {
+ // Temporarily disable 'autochdir' when setting file name for another buffer.
+ p_acd = false;
+ }
- // Using aucmd_*: autocommands will be executed by rename_buffer
- aco_save_T aco;
- aucmd_prepbuf(&aco, buf);
- int ren_ret = rename_buffer(name.data);
- aucmd_restbuf(&aco);
+ // Using aucmd_*: autocommands will be executed by rename_buffer
+ aco_save_T aco;
+ aucmd_prepbuf(&aco, buf);
+ ren_ret = rename_buffer(name.data);
+ aucmd_restbuf(&aco);
- if (!is_curbuf) {
- p_acd = save_acd;
- }
+ if (!is_curbuf) {
+ p_acd = save_acd;
+ }
+ });
- if (try_end(err)) {
+ if (ERROR_SET(err)) {
return;
}
@@ -1184,12 +1180,12 @@ ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Arena *arena,
/// This temporarily switches current buffer to "buffer".
/// If the current window already shows "buffer", the window is not switched.
/// If a window inside the current tabpage (including a float) already shows the
-/// buffer, then one of these windows will be set as current window temporarily.
+/// buffer, then one of those windows will be set as current window temporarily.
/// Otherwise a temporary scratch window (called the "autocmd window" for
/// historical reasons) will be used.
///
/// This is useful e.g. to call Vimscript functions that only work with the
-/// current buffer/window currently, like |termopen()|.
+/// current buffer/window currently, like `jobstart(…, {'term': v:true})`.
///
/// @param buffer Buffer handle, or 0 for current buffer
/// @param fun Function to call inside the buffer (currently Lua callable
@@ -1204,15 +1200,18 @@ Object nvim_buf_call(Buffer buffer, LuaRef fun, Error *err)
if (!buf) {
return NIL;
}
- try_start();
- aco_save_T aco;
- aucmd_prepbuf(&aco, buf);
- Array args = ARRAY_DICT_INIT;
- Object res = nlua_call_ref(fun, NULL, args, kRetLuaref, NULL, err);
+ Object res = OBJECT_INIT;
+ TRY_WRAP(err, {
+ aco_save_T aco;
+ aucmd_prepbuf(&aco, buf);
+
+ Array args = ARRAY_DICT_INIT;
+ res = nlua_call_ref(fun, NULL, args, kRetLuaref, NULL, err);
+
+ aucmd_restbuf(&aco);
+ });
- aucmd_restbuf(&aco);
- try_end(err);
return res;
}