diff options
-rw-r--r-- | runtime/lua/vim/fs.lua | 2 | ||||
-rw-r--r-- | src/nvim/buffer_updates.c | 16 | ||||
-rw-r--r-- | src/nvim/eval/funcs.c | 7 | ||||
-rw-r--r-- | src/nvim/ex_getln.c | 2 | ||||
-rw-r--r-- | src/nvim/lua/executor.c | 1 | ||||
-rw-r--r-- | src/nvim/msgpack_rpc/channel.c | 3 | ||||
-rw-r--r-- | src/nvim/option.c | 2 | ||||
-rw-r--r-- | src/nvim/tui/input.c | 24 | ||||
-rw-r--r-- | src/nvim/tui/tui.c | 7 | ||||
-rw-r--r-- | src/nvim/ui.c | 8 | ||||
-rw-r--r-- | src/nvim/ui_client.c | 33 | ||||
-rw-r--r-- | src/nvim/window.c | 6 | ||||
-rw-r--r-- | src/nvim/window.h | 2 | ||||
-rw-r--r-- | test/functional/lua/fs_spec.lua | 5 | ||||
-rw-r--r-- | test/functional/ui/cmdline_spec.lua | 36 |
15 files changed, 98 insertions, 56 deletions
diff --git a/runtime/lua/vim/fs.lua b/runtime/lua/vim/fs.lua index 89a1d0d345..65e6ca677c 100644 --- a/runtime/lua/vim/fs.lua +++ b/runtime/lua/vim/fs.lua @@ -74,7 +74,7 @@ end ---@private local function join_paths(...) - return table.concat({ ... }, '/') + return (table.concat({ ... }, '/'):gsub('//+', '/')) end --- Return an iterator over the files and directories located in {path} diff --git a/src/nvim/buffer_updates.c b/src/nvim/buffer_updates.c index c66571560a..075ac2adbf 100644 --- a/src/nvim/buffer_updates.c +++ b/src/nvim/buffer_updates.c @@ -88,6 +88,7 @@ bool buf_updates_register(buf_T *buf, uint64_t channel_id, BufUpdateCallbacks cb args.items[5] = BOOLEAN_OBJ(false); rpc_send_event(channel_id, "nvim_buf_lines_event", args); + api_free_array(args); // TODO(bfredl): no } else { buf_updates_changedtick_single(buf, channel_id); } @@ -103,10 +104,8 @@ bool buf_updates_active(buf_T *buf) void buf_updates_send_end(buf_T *buf, uint64_t channelid) { - Array args = ARRAY_DICT_INIT; - args.size = 1; - args.items = xcalloc(args.size, sizeof(Object)); - args.items[0] = BUFFER_OBJ(buf->handle); + MAXSIZE_TEMP_ARRAY(args, 1); + ADD_C(args, BUFFER_OBJ(buf->handle)); rpc_send_event(channelid, "nvim_buf_detach_event", args); } @@ -262,6 +261,7 @@ void buf_updates_send_changes(buf_T *buf, linenr_T firstline, int64_t num_added, // the end. badchannelid = channelid; } + api_free_array(args); // TODO(bfredl): no } // We can only ever remove one dead channel at a time. This is OK because the @@ -408,15 +408,13 @@ void buf_updates_changedtick(buf_T *buf) void buf_updates_changedtick_single(buf_T *buf, uint64_t channel_id) { - Array args = ARRAY_DICT_INIT; - args.size = 2; - args.items = xcalloc(args.size, sizeof(Object)); + MAXSIZE_TEMP_ARRAY(args, 2); // the first argument is always the buffer handle - args.items[0] = BUFFER_OBJ(buf->handle); + ADD_C(args, BUFFER_OBJ(buf->handle)); // next argument is b:changedtick - args.items[1] = INTEGER_OBJ(buf_get_changedtick(buf)); + ADD_C(args, INTEGER_OBJ(buf_get_changedtick(buf))); // don't try and clean up dead channels here rpc_send_event(channel_id, "nvim_buf_changedtick_event", args); diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 77e8e23ab6..d377508e27 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -6322,12 +6322,15 @@ static void f_rpcnotify(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) ADD(args, vim_to_object(tv)); } - if (!rpc_send_event((uint64_t)argvars[0].vval.v_number, - tv_get_string(&argvars[1]), args)) { + bool ok = rpc_send_event((uint64_t)argvars[0].vval.v_number, + tv_get_string(&argvars[1]), args); + + if (!ok) { semsg(_(e_invarg2), "Channel doesn't exist"); return; } + api_free_array(args); rettv->vval.v_number = 1; } diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index be6253d1c9..5c0dfaacbb 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -3843,7 +3843,7 @@ void compute_cmdrow(void) cmdline_row = wp->w_winrow + wp->w_height + wp->w_hsep_height + wp->w_status_height + global_stl_height(); } - if (cmdline_row == Rows) { + if (cmdline_row == Rows && p_ch > 0) { cmdline_row--; } lines_left = cmdline_row; diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 590d6fa920..d4e7f3fb2c 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -1190,6 +1190,7 @@ static int nlua_rpc(lua_State *lstate, bool request) api_set_error(&err, kErrorTypeValidation, "Invalid channel: %" PRIu64, chan_id); } + api_free_array(args); // TODO(bfredl): no } check_err: diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 4d011dc079..5b8e330e15 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -136,6 +136,7 @@ Object rpc_send_call(uint64_t id, const char *method_name, Array args, ArenaMem uint32_t request_id = rpc->next_request_id++; // Send the msgpack-rpc request send_request(channel, request_id, method_name, args); + api_free_array(args); // Push the frame ChannelCallFrame frame = { request_id, false, false, NIL, NULL }; @@ -491,7 +492,6 @@ static void broadcast_event(const char *name, Array args) }); if (!kv_size(subscribed)) { - api_free_array(args); goto end; } @@ -593,7 +593,6 @@ static WBuffer *serialize_request(uint64_t channel_id, uint32_t request_id, cons refcount, xfree); msgpack_sbuffer_clear(sbuffer); - api_free_array(args); return rv; } diff --git a/src/nvim/option.c b/src/nvim/option.c index 03d8faa90a..2d59eec91f 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -2256,6 +2256,8 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf, int minval = 0; if (value < minval) { errmsg = e_positive; + } else { + p_ch_was_zero = value == 0; } } else if (pp == &p_tm) { if (value < 0) { diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c index c6066597f0..b837a380d5 100644 --- a/src/nvim/tui/input.c +++ b/src/nvim/tui/input.c @@ -220,11 +220,12 @@ static void tinput_wait_enqueue(void **argv) const size_t len = rbuffer_size(input->key_buffer); String keys = { .data = xmallocz(len), .size = len }; rbuffer_read(input->key_buffer, keys.data, len); - Array args = ARRAY_DICT_INIT; - ADD(args, STRING_OBJ(keys)); // 'data' - ADD(args, BOOLEAN_OBJ(true)); // 'crlf' - ADD(args, INTEGER_OBJ(input->paste)); // 'phase' + MAXSIZE_TEMP_ARRAY(args, 3); + ADD_C(args, STRING_OBJ(keys)); // 'data' + ADD_C(args, BOOLEAN_OBJ(true)); // 'crlf' + ADD_C(args, INTEGER_OBJ(input->paste)); // 'phase' rpc_send_event(ui_client_channel_id, "nvim_paste", args); + api_free_string(keys); if (input->paste == 1) { // Paste phase: "continue" input->paste = 2; @@ -233,8 +234,8 @@ static void tinput_wait_enqueue(void **argv) } else { // enqueue input for the main thread or Nvim server RBUFFER_UNTIL_EMPTY(input->key_buffer, buf, len) { const String keys = { .data = buf, .size = len }; - Array args = ARRAY_DICT_INIT; - ADD(args, STRING_OBJ(copy_string(keys, NULL))); + MAXSIZE_TEMP_ARRAY(args, 1); + ADD_C(args, STRING_OBJ(keys)); // NOTE: This is non-blocking and won't check partially processed input, // but should be fine as all big sends are handled with nvim_paste, not nvim_input rpc_send_event(ui_client_channel_id, "nvim_input", args); @@ -529,8 +530,8 @@ static bool handle_focus_event(TermInput *input) // Advance past the sequence rbuffer_consumed(input->read_stream.buffer, 3); - Array args = ARRAY_DICT_INIT; - ADD(args, BOOLEAN_OBJ(focus_gained)); + MAXSIZE_TEMP_ARRAY(args, 1); + ADD_C(args, BOOLEAN_OBJ(focus_gained)); rpc_send_event(ui_client_channel_id, "nvim_ui_set_focus", args); return true; } @@ -581,10 +582,9 @@ static HandleState handle_bracketed_paste(TermInput *input) static void set_bg(char *bgvalue) { if (ui_client_attached) { - Array args = ARRAY_DICT_INIT; - ADD(args, STRING_OBJ(cstr_to_string("term_background"))); - ADD(args, STRING_OBJ(cstr_as_string(xstrdup(bgvalue)))); - + MAXSIZE_TEMP_ARRAY(args, 2); + ADD_C(args, STRING_OBJ(cstr_as_string("term_background"))); + ADD_C(args, STRING_OBJ(cstr_as_string(bgvalue))); rpc_send_event(ui_client_channel_id, "nvim_ui_set_option", args); } } diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index 0d01cd44cd..3205547324 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -1401,6 +1401,7 @@ static void show_verbose_terminfo(TUIData *data) PUT(opts, "verbose", BOOLEAN_OBJ(true)); ADD(args, DICTIONARY_OBJ(opts)); rpc_send_event(ui_client_channel_id, "nvim_echo", args); + api_free_array(args); } #ifdef UNIX @@ -1493,9 +1494,9 @@ static void tui_option_set(UI *ui, String name, Object value) invalidate(ui, 0, data->grid.height, 0, data->grid.width); if (ui_client_channel_id) { - Array args = ARRAY_DICT_INIT; - ADD(args, STRING_OBJ(cstr_as_string(xstrdup("rgb")))); - ADD(args, BOOLEAN_OBJ(value.data.boolean)); + MAXSIZE_TEMP_ARRAY(args, 2); + ADD_C(args, STRING_OBJ(cstr_as_string("rgb"))); + ADD_C(args, BOOLEAN_OBJ(value.data.boolean)); rpc_send_event(ui_client_channel_id, "nvim_ui_set_option", args); } } else if (strequal(name.data, "ttimeout")) { diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 4c640693cc..0cb48a9cf4 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -227,9 +227,9 @@ void ui_refresh(void) if (ui_client_attached) { // TODO(bfredl): ui_refresh() should only be used on the server // we are in the client process. forward the resize - Array args = ARRAY_DICT_INIT; - ADD(args, INTEGER_OBJ((int)width)); - ADD(args, INTEGER_OBJ((int)height)); + MAXSIZE_TEMP_ARRAY(args, 2); + ADD_C(args, INTEGER_OBJ((int)width)); + ADD_C(args, INTEGER_OBJ((int)height)); rpc_send_event(ui_client_channel_id, "nvim_ui_try_resize", args); } else { /// TODO(bfredl): Messy! The screen does not yet exist, but we need to @@ -241,7 +241,7 @@ void ui_refresh(void) } if (ext_widgets[kUIMessages]) { - p_ch = 0; + set_option_value("cmdheight", 0L, NULL, 0); command_height(); } ui_mode_info_set(); diff --git a/src/nvim/ui_client.c b/src/nvim/ui_client.c index 6fc3a05e96..365a76de3f 100644 --- a/src/nvim/ui_client.c +++ b/src/nvim/ui_client.c @@ -56,33 +56,30 @@ void ui_client_run(bool remote_ui) loop_poll_events(&main_loop, 1); - Array args = ARRAY_DICT_INIT; - Dictionary opts = ARRAY_DICT_INIT; - - PUT(opts, "rgb", BOOLEAN_OBJ(true)); - PUT(opts, "ext_linegrid", BOOLEAN_OBJ(true)); - PUT(opts, "ext_termcolors", BOOLEAN_OBJ(true)); - + MAXSIZE_TEMP_ARRAY(args, 3); + ADD_C(args, INTEGER_OBJ(Columns)); + ADD_C(args, INTEGER_OBJ(Rows)); + + MAXSIZE_TEMP_DICT(opts, 9); + PUT_C(opts, "rgb", BOOLEAN_OBJ(true)); + PUT_C(opts, "ext_linegrid", BOOLEAN_OBJ(true)); + PUT_C(opts, "ext_termcolors", BOOLEAN_OBJ(true)); if (ui_client_termname) { - PUT(opts, "term_name", STRING_OBJ(cstr_as_string(ui_client_termname))); + PUT_C(opts, "term_name", STRING_OBJ(cstr_as_string(ui_client_termname))); } if (ui_client_bg_respose != kNone) { bool is_dark = (ui_client_bg_respose == kTrue); - PUT(opts, "term_background", STRING_OBJ(cstr_as_string(is_dark ? "dark" : "light"))); + PUT_C(opts, "term_background", STRING_OBJ(cstr_as_string(is_dark ? "dark" : "light"))); } - PUT(opts, "term_colors", INTEGER_OBJ(t_colors)); + PUT_C(opts, "term_colors", INTEGER_OBJ(t_colors)); if (!remote_ui) { - PUT(opts, "stdin_tty", BOOLEAN_OBJ(stdin_isatty)); - PUT(opts, "stdout_tty", BOOLEAN_OBJ(stdout_isatty)); + PUT_C(opts, "stdin_tty", BOOLEAN_OBJ(stdin_isatty)); + PUT_C(opts, "stdout_tty", BOOLEAN_OBJ(stdout_isatty)); if (ui_client_forward_stdin) { - PUT(opts, "stdin_fd", INTEGER_OBJ(UI_CLIENT_STDIN_FD)); + PUT_C(opts, "stdin_fd", INTEGER_OBJ(UI_CLIENT_STDIN_FD)); } } - - ADD(args, INTEGER_OBJ(Columns)); - ADD(args, INTEGER_OBJ(Rows)); - ADD(args, DICTIONARY_OBJ(opts)); - + ADD_C(args, DICTIONARY_OBJ(opts)); rpc_send_event(ui_client_channel_id, "nvim_ui_attach", args); ui_client_attached = true; diff --git a/src/nvim/window.c b/src/nvim/window.c index 4c03893173..57d40ceb42 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -5765,8 +5765,8 @@ static void frame_setheight(frame_T *curfrp, int height) if (height > ROWS_AVAIL) { // If height is greater than the available space, try to create space for // the frame by reducing 'cmdheight' if possible, while making sure - // `cmdheight` doesn't go below 1. - height = (int)MIN((p_ch > 0 ? ROWS_AVAIL + (p_ch - 1) : ROWS_AVAIL), height); + // `cmdheight` doesn't go below 1 if it wasn't set to 0 explicitly. + height = (int)MIN(ROWS_AVAIL + p_ch - !p_ch_was_zero, height); } if (height > 0) { frame_new_height(curfrp, height, false, false); @@ -6097,8 +6097,6 @@ void win_setminwidth(void) /// Status line of dragwin is dragged "offset" lines down (negative is up). void win_drag_status_line(win_T *dragwin, int offset) { - static bool p_ch_was_zero = false; - // If the user explicitly set 'cmdheight' to zero, then allow for dragging // the status line making it zero again. if (p_ch == 0) { diff --git a/src/nvim/window.h b/src/nvim/window.h index 9fd4d67b3f..f348f102c9 100644 --- a/src/nvim/window.h +++ b/src/nvim/window.h @@ -35,6 +35,8 @@ #define MIN_COLUMNS 12 // minimal columns for screen #define MIN_LINES 2 // minimal lines for screen +// Set to true if 'cmdheight' was explicitly set to 0. +EXTERN bool p_ch_was_zero INIT(= false); #ifdef INCLUDE_GENERATED_DECLARATIONS # include "window.h.generated.h" #endif diff --git a/test/functional/lua/fs_spec.lua b/test/functional/lua/fs_spec.lua index 20a1660b0e..642d36f63a 100644 --- a/test/functional/lua/fs_spec.lua +++ b/test/functional/lua/fs_spec.lua @@ -230,6 +230,11 @@ describe('vim.fs', function() local dir, nvim = ... return vim.fs.find(nvim, { path = dir, type = 'file' }) ]], test_build_dir, nvim_prog_basename)) + eq({nvim_dir}, exec_lua([[ + local dir = ... + local parent, name = dir:match('^(.*/)([^/]+)$') + return vim.fs.find(name, { path = parent, upward = true, type = 'directory' }) + ]], nvim_dir)) end) it('accepts predicate as names', function() diff --git a/test/functional/ui/cmdline_spec.lua b/test/functional/ui/cmdline_spec.lua index 1bdd55d66b..8e689fb378 100644 --- a/test/functional/ui/cmdline_spec.lua +++ b/test/functional/ui/cmdline_spec.lua @@ -1364,4 +1364,40 @@ describe('cmdheight=0', function() ]]) assert_alive() end) + + it('can only be resized to 0 if set explicitly', function() + command('set laststatus=2') + command('resize +1') + screen:expect([[ + ^ | + {1:~ }| + {1:~ }| + {2:[No Name] }| + | + ]]) + command('set cmdheight=0') + command('resize -1') + command('resize +1') + screen:expect([[ + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {2:[No Name] }| + ]]) + end) + + it("clears cmdline area when resized with external messages", function() + clear() + screen = new_screen({rgb=true, ext_messages=true}) + command('set laststatus=2 cmdheight=0') + command('resize -1') + screen:expect([[ + ^ | + {1:~ }| + {1:~ }| + {3:[No Name] }| + | + ]]) + end) end) |