From 8516c2dc1f301c439695629fff771227dbe00d30 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Sat, 23 Nov 2024 14:22:06 +0600 Subject: refactor(options): autogenerate valid values and flag enums for options (#31089) Problem: Option metadata like list of valid values for an option and option flags are not listed in the `options.lua` file and are instead manually defined in C, which means option metadata is split between several places. Solution: Put metadata such as list of valid values for an option and option flags in `options.lua`, and autogenerate the corresponding C variables and enums. Supersedes #28659 Co-authored-by: glepnir --- src/nvim/ex_getln.c | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index ace62ea729..2d9d4417dd 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1070,23 +1070,23 @@ static int command_line_wildchar_complete(CommandLineState *s) { int res; int options = WILD_NO_BEEP; - if (wim_flags[s->wim_index] & WIM_BUFLASTUSED) { + if (wim_flags[s->wim_index] & kOptWimFlagLastused) { options |= WILD_BUFLASTUSED; } if (s->xpc.xp_numfiles > 0) { // typed p_wc at least twice // if 'wildmode' contains "list" may still need to list if (s->xpc.xp_numfiles > 1 && !s->did_wild_list - && ((wim_flags[s->wim_index] & WIM_LIST) - || (p_wmnu && (wim_flags[s->wim_index] & WIM_FULL) != 0))) { - showmatches(&s->xpc, p_wmnu && ((wim_flags[s->wim_index] & WIM_LIST) == 0)); + && ((wim_flags[s->wim_index] & kOptWimFlagList) + || (p_wmnu && (wim_flags[s->wim_index] & kOptWimFlagFull) != 0))) { + showmatches(&s->xpc, p_wmnu && ((wim_flags[s->wim_index] & kOptWimFlagList) == 0)); redrawcmd(); s->did_wild_list = true; } - if (wim_flags[s->wim_index] & WIM_LONGEST) { + if (wim_flags[s->wim_index] & kOptWimFlagLongest) { res = nextwild(&s->xpc, WILD_LONGEST, options, s->firstc != '@'); - } else if (wim_flags[s->wim_index] & WIM_FULL) { + } else if (wim_flags[s->wim_index] & kOptWimFlagFull) { res = nextwild(&s->xpc, WILD_NEXT, options, s->firstc != '@'); } else { res = OK; // don't insert 'wildchar' now @@ -1097,7 +1097,7 @@ static int command_line_wildchar_complete(CommandLineState *s) // if 'wildmode' first contains "longest", get longest // common part - if (wim_flags[0] & WIM_LONGEST) { + if (wim_flags[0] & kOptWimFlagLongest) { res = nextwild(&s->xpc, WILD_LONGEST, options, s->firstc != '@'); } else { res = nextwild(&s->xpc, WILD_EXPAND_KEEP, options, s->firstc != '@'); @@ -1118,12 +1118,12 @@ static int command_line_wildchar_complete(CommandLineState *s) if (res == OK && s->xpc.xp_numfiles > 1) { // a "longest" that didn't do anything is skipped (but not // "list:longest") - if (wim_flags[0] == WIM_LONGEST && ccline.cmdpos == j) { + if (wim_flags[0] == kOptWimFlagLongest && ccline.cmdpos == j) { s->wim_index = 1; } - if ((wim_flags[s->wim_index] & WIM_LIST) - || (p_wmnu && (wim_flags[s->wim_index] & WIM_FULL) != 0)) { - if (!(wim_flags[0] & WIM_LONGEST)) { + if ((wim_flags[s->wim_index] & kOptWimFlagList) + || (p_wmnu && (wim_flags[s->wim_index] & kOptWimFlagFull) != 0)) { + if (!(wim_flags[0] & kOptWimFlagLongest)) { int p_wmnu_save = p_wmnu; p_wmnu = 0; // remove match @@ -1131,17 +1131,17 @@ static int command_line_wildchar_complete(CommandLineState *s) p_wmnu = p_wmnu_save; } - showmatches(&s->xpc, p_wmnu && ((wim_flags[s->wim_index] & WIM_LIST) == 0)); + showmatches(&s->xpc, p_wmnu && ((wim_flags[s->wim_index] & kOptWimFlagList) == 0)); redrawcmd(); s->did_wild_list = true; - if (wim_flags[s->wim_index] & WIM_LONGEST) { + if (wim_flags[s->wim_index] & kOptWimFlagLongest) { nextwild(&s->xpc, WILD_LONGEST, options, s->firstc != '@'); - } else if (wim_flags[s->wim_index] & WIM_FULL) { + } else if (wim_flags[s->wim_index] & kOptWimFlagFull) { nextwild(&s->xpc, WILD_NEXT, options, s->firstc != '@'); } } else { - vim_beep(BO_WILD); + vim_beep(kOptBoFlagWildmode); } } else if (s->xpc.xp_numfiles == -1) { s->xpc.xp_context = EXPAND_NOTHING; @@ -1380,9 +1380,9 @@ static int command_line_execute(VimState *state, int key) if (s->c == K_S_TAB && KeyTyped) { if (nextwild(&s->xpc, WILD_EXPAND_KEEP, 0, s->firstc != '@') == OK) { if (s->xpc.xp_numfiles > 1 - && ((!s->did_wild_list && (wim_flags[s->wim_index] & WIM_LIST)) || p_wmnu)) { + && ((!s->did_wild_list && (wim_flags[s->wim_index] & kOptWimFlagList)) || p_wmnu)) { // Trigger the popup menu when wildoptions=pum - showmatches(&s->xpc, p_wmnu && ((wim_flags[s->wim_index] & WIM_LIST) == 0)); + showmatches(&s->xpc, p_wmnu && ((wim_flags[s->wim_index] & kOptWimFlagList) == 0)); } nextwild(&s->xpc, WILD_PREV, 0, s->firstc != '@'); nextwild(&s->xpc, WILD_PREV, 0, s->firstc != '@'); @@ -1511,7 +1511,7 @@ static int may_do_command_line_next_incsearch(int firstc, int count, incsearch_s redrawcmdline(); curwin->w_cursor = s->match_end; } else { - vim_beep(BO_ERROR); + vim_beep(kOptBoFlagError); } restore_last_search_pattern(); return FAIL; @@ -2820,19 +2820,19 @@ int check_opt_wim(void) } for (char *p = p_wim; *p; p++) { - // Note: Keep this in sync with p_wim_values. + // Note: Keep this in sync with opt_wim_values. for (i = 0; ASCII_ISALPHA(p[i]); i++) {} if (p[i] != NUL && p[i] != ',' && p[i] != ':') { return FAIL; } if (i == 7 && strncmp(p, "longest", 7) == 0) { - new_wim_flags[idx] |= WIM_LONGEST; + new_wim_flags[idx] |= kOptWimFlagLongest; } else if (i == 4 && strncmp(p, "full", 4) == 0) { - new_wim_flags[idx] |= WIM_FULL; + new_wim_flags[idx] |= kOptWimFlagFull; } else if (i == 4 && strncmp(p, "list", 4) == 0) { - new_wim_flags[idx] |= WIM_LIST; + new_wim_flags[idx] |= kOptWimFlagList; } else if (i == 8 && strncmp(p, "lastused", 8) == 0) { - new_wim_flags[idx] |= WIM_BUFLASTUSED; + new_wim_flags[idx] |= kOptWimFlagLastused; } else { return FAIL; } -- cgit From d1fd674df3eb07049c780d6b7821e17d471fdc4c Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 10 Dec 2024 14:53:02 +0800 Subject: fix(ui): update title in more cases (#31508) --- src/nvim/ex_getln.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 2d9d4417dd..85fbdbd20a 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -847,6 +847,10 @@ static uint8_t *command_line_enter(int firstc, int count, int indent, bool clear found_one = true; } + if (redraw_custom_title_later()) { + found_one = true; + } + if (found_one) { redraw_statuslines(); } @@ -959,6 +963,7 @@ theend: msg_ext_clear_later(); } if (!cmd_silent) { + redraw_custom_title_later(); status_redraw_all(); // redraw to show mode change } -- cgit From 6bf2a6fc5bb395b67c88cb26d332f882a106c7ab Mon Sep 17 00:00:00 2001 From: luukvbaal Date: Tue, 17 Dec 2024 13:12:22 +0100 Subject: refactor(api): always use TRY_WRAP #31600 Problem: Two separate try/end wrappers, that only marginally differ by restoring a few variables. Wrappers that don't restore previous state are dangerous to use in "api-fast" functions. Solution: Remove wrappers that don't restore the previous state. Always use TRY_WRAP. --- src/nvim/ex_getln.c | 95 ++++++++++++++++++++++++++--------------------------- 1 file changed, 46 insertions(+), 49 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 85fbdbd20a..2c1653006c 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -787,9 +787,7 @@ static uint8_t *command_line_enter(int firstc, int count, int indent, bool clear setmouse(); setcursor(); - TryState tstate; Error err = ERROR_INIT; - bool tl_ret = true; char firstcbuf[2]; firstcbuf[0] = (char)(firstc > 0 ? firstc : '-'); firstcbuf[1] = 0; @@ -802,20 +800,19 @@ static uint8_t *command_line_enter(int firstc, int count, int indent, bool clear tv_dict_add_str(dict, S_LEN("cmdtype"), firstcbuf); tv_dict_add_nr(dict, S_LEN("cmdlevel"), ccline.level); tv_dict_set_keys_readonly(dict); - try_enter(&tstate); + TRY_WRAP(&err, { + apply_autocmds(EVENT_CMDLINEENTER, firstcbuf, firstcbuf, false, curbuf); + restore_v_event(dict, &save_v_event); + }); - apply_autocmds(EVENT_CMDLINEENTER, firstcbuf, firstcbuf, false, curbuf); - restore_v_event(dict, &save_v_event); - - tl_ret = try_leave(&tstate, &err); - if (!tl_ret && ERROR_SET(&err)) { + if (ERROR_SET(&err)) { msg_putchar('\n'); msg_scroll = true; msg_puts_hl(err.msg, HLF_E, true); api_clear_error(&err); redrawcmd(); } - tl_ret = true; + err = ERROR_INIT; } may_trigger_modechanged(); @@ -873,10 +870,10 @@ static uint8_t *command_line_enter(int firstc, int count, int indent, bool clear // not readonly: tv_dict_add_bool(dict, S_LEN("abort"), s->gotesc ? kBoolVarTrue : kBoolVarFalse); - try_enter(&tstate); - apply_autocmds(EVENT_CMDLINELEAVE, firstcbuf, firstcbuf, false, curbuf); - // error printed below, to avoid redraw issues - tl_ret = try_leave(&tstate, &err); + TRY_WRAP(&err, { + apply_autocmds(EVENT_CMDLINELEAVE, firstcbuf, firstcbuf, false, curbuf); + // error printed below, to avoid redraw issues + }); if (tv_dict_get_number(dict, "abort") != 0) { s->gotesc = true; } @@ -929,7 +926,7 @@ static uint8_t *command_line_enter(int firstc, int count, int indent, bool clear msg_scroll = s->save_msg_scroll; redir_off = false; - if (!tl_ret && ERROR_SET(&err)) { + if (ERROR_SET(&err)) { msg_putchar('\n'); emsg(err.msg); did_emsg = false; @@ -937,7 +934,7 @@ static uint8_t *command_line_enter(int firstc, int count, int indent, bool clear } // When the command line was typed, no need for a wait-return prompt. - if (s->some_key_typed && tl_ret) { + if (s->some_key_typed && !ERROR_SET(&err)) { need_wait_return = false; } @@ -2315,11 +2312,13 @@ static win_T *cmdpreview_open_win(buf_T *cmdpreview_buf) win_T *preview_win = curwin; Error err = ERROR_INIT; + int result = OK; // Switch to preview buffer - try_start(); - int result = do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, cmdpreview_buf->handle, 0); - if (try_end(&err) || result == FAIL) { + TRY_WRAP(&err, { + result = do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, cmdpreview_buf->handle, 0); + }); + if (ERROR_SET(&err) || result == FAIL) { api_clear_error(&err); return NULL; } @@ -2600,9 +2599,10 @@ static bool cmdpreview_may_show(CommandLineState *s) // open the preview window. The preview callback also handles doing the changes and highlights for // the preview. Error err = ERROR_INIT; - try_start(); - cmdpreview_type = execute_cmd(&ea, &cmdinfo, true); - if (try_end(&err)) { + TRY_WRAP(&err, { + cmdpreview_type = execute_cmd(&ea, &cmdinfo, true); + }); + if (ERROR_SET(&err)) { api_clear_error(&err); cmdpreview_type = 0; } @@ -2643,7 +2643,6 @@ end: static void do_autocmd_cmdlinechanged(int firstc) { if (has_event(EVENT_CMDLINECHANGED)) { - TryState tstate; Error err = ERROR_INIT; save_v_event_T save_v_event; dict_T *dict = get_v_event(&save_v_event); @@ -2656,13 +2655,11 @@ static void do_autocmd_cmdlinechanged(int firstc) tv_dict_add_str(dict, S_LEN("cmdtype"), firstcbuf); tv_dict_add_nr(dict, S_LEN("cmdlevel"), ccline.level); tv_dict_set_keys_readonly(dict); - try_enter(&tstate); - - apply_autocmds(EVENT_CMDLINECHANGED, firstcbuf, firstcbuf, false, curbuf); - restore_v_event(dict, &save_v_event); - - bool tl_ret = try_leave(&tstate, &err); - if (!tl_ret && ERROR_SET(&err)) { + TRY_WRAP(&err, { + apply_autocmds(EVENT_CMDLINECHANGED, firstcbuf, firstcbuf, false, curbuf); + restore_v_event(dict, &save_v_event); + }); + if (ERROR_SET(&err)) { msg_putchar('\n'); msg_scroll = true; msg_puts_hl(err.msg, HLF_E, true); @@ -3179,11 +3176,9 @@ static bool color_cmdline(CmdlineInfo *colored_ccline) static int prev_prompt_errors = 0; Callback color_cb = CALLBACK_NONE; bool can_free_cb = false; - TryState tstate; Error err = ERROR_INIT; const char *err_errmsg = e_intern2; bool dgc_ret = true; - bool tl_ret = true; if (colored_ccline->prompt_id != prev_prompt_id) { prev_prompt_errors = 0; @@ -3196,16 +3191,16 @@ static bool color_cmdline(CmdlineInfo *colored_ccline) assert(colored_ccline->input_fn); color_cb = colored_ccline->highlight_callback; } else if (colored_ccline->cmdfirstc == ':') { - try_enter(&tstate); - err_errmsg = N_("E5408: Unable to get g:Nvim_color_cmdline callback: %s"); - dgc_ret = tv_dict_get_callback(&globvardict, S_LEN("Nvim_color_cmdline"), - &color_cb); - tl_ret = try_leave(&tstate, &err); + TRY_WRAP(&err, { + err_errmsg = N_("E5408: Unable to get g:Nvim_color_cmdline callback: %s"); + dgc_ret = tv_dict_get_callback(&globvardict, S_LEN("Nvim_color_cmdline"), + &color_cb); + }); can_free_cb = true; } else if (colored_ccline->cmdfirstc == '=') { color_expr_cmdline(colored_ccline, ccline_colors); } - if (!tl_ret || !dgc_ret) { + if (ERROR_SET(&err) || !dgc_ret) { goto color_cmdline_error; } @@ -3226,20 +3221,22 @@ static bool color_cmdline(CmdlineInfo *colored_ccline) // correct, with msg_col it just misses leading `:`. Since `redraw!` in // callback lags this is least of the user problems. // - // Also using try_enter() because error messages may overwrite typed + // Also using TRY_WRAP because error messages may overwrite typed // command-line which is not expected. getln_interrupted_highlight = false; - try_enter(&tstate); - err_errmsg = N_("E5407: Callback has thrown an exception: %s"); - const int saved_msg_col = msg_col; - msg_silent++; - const bool cbcall_ret = callback_call(&color_cb, 1, &arg, &tv); - msg_silent--; - msg_col = saved_msg_col; - if (got_int) { - getln_interrupted_highlight = true; - } - if (!try_leave(&tstate, &err) || !cbcall_ret) { + bool cbcall_ret = true; + TRY_WRAP(&err, { + err_errmsg = N_("E5407: Callback has thrown an exception: %s"); + const int saved_msg_col = msg_col; + msg_silent++; + cbcall_ret = callback_call(&color_cb, 1, &arg, &tv); + msg_silent--; + msg_col = saved_msg_col; + if (got_int) { + getln_interrupted_highlight = true; + } + }); + if (ERROR_SET(&err) || !cbcall_ret) { goto color_cmdline_error; } if (tv.v_type != VAR_LIST) { -- cgit From 394f69a25dc32c5b101ba2d34ac6376b0c75b2a2 Mon Sep 17 00:00:00 2001 From: Luuk van Baal Date: Fri, 20 Dec 2024 21:11:38 +0100 Subject: feat(ui): additional arguments for cmdline_show/hide events Problem: Unable to tell what highlight the prompt part of a cmdline_show event should have, and whether cmdline_hide was emitted after aborting. Solution: Add additional arguments hl_id to cmdline_show, and abort to cmdline_hide. --- src/nvim/ex_getln.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 2c1653006c..b134a899c9 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -956,7 +956,7 @@ theend: char *p = ccline.cmdbuff; if (ui_has(kUICmdline)) { - ui_call_cmdline_hide(ccline.level); + ui_call_cmdline_hide(ccline.level, s->gotesc); msg_ext_clear_later(); } if (!cmd_silent) { @@ -3422,8 +3422,7 @@ static void ui_ext_cmdline_show(CmdlineInfo *line) ui_call_cmdline_show(content, line->cmdpos, cstr_as_string(charbuf), cstr_as_string((line->cmdprompt)), - line->cmdindent, - line->level); + line->cmdindent, line->level, line->hl_id); if (line->special_char) { charbuf[0] = line->special_char; ui_call_cmdline_special_char(cstr_as_string(charbuf), @@ -4477,7 +4476,7 @@ static int open_cmdwin(void) invalidate_botline(curwin); if (ui_has(kUICmdline)) { ccline.redraw_state = kCmdRedrawNone; - ui_call_cmdline_hide(ccline.level); + ui_call_cmdline_hide(ccline.level, false); } redraw_later(curwin, UPD_SOME_VALID); -- cgit From d1e00a5f6dce9cf1fa80f613d4d27019966e5a79 Mon Sep 17 00:00:00 2001 From: luukvbaal Date: Sun, 22 Dec 2024 15:42:48 +0100 Subject: fix(messages): typo and unwanted truncation in msg_outtrans_long #31669 - Typo/bug in msg_outtrans_long passing string length as "hist" argument. - Avoid truncating message in msg_outtrans_long with ext_messages (followup to 1097d239c307a10a87fa995c4cfbe5987939e177). - Remove `_hl` from `msg_keep`, `smsg_keep` as there is no non-`_hl` variant. - `msg_printf_hl` is removed (identical to `smsg` except it sets `msg_scroll = true`, seemingly as a caveat to force a more prompt in cmdline mode). Move this logic to the only the only place this was used in ex_getln.c. --- src/nvim/ex_getln.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 2c1653006c..09d4c88dcd 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -3142,8 +3142,9 @@ static bool color_cmdline(CmdlineInfo *colored_ccline) #define PRINT_ERRMSG(...) \ do { \ + msg_scroll = true; \ msg_putchar('\n'); \ - msg_printf_hl(HLF_E, __VA_ARGS__); \ + smsg(HLF_E, __VA_ARGS__); \ printed_errmsg = true; \ } while (0) bool ret = true; -- cgit From 2a7d0ed6145bf3f8b139c2694563f460f829813a Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 23 Dec 2024 05:43:52 -0800 Subject: refactor: iwyu #31637 Result of `make iwyu` (after some "fixups"). --- src/nvim/ex_getln.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index ff752fb489..7f2f739e00 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -14,7 +14,6 @@ #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" #include "nvim/api/vim.h" -#include "nvim/arabic.h" #include "nvim/ascii_defs.h" #include "nvim/autocmd.h" #include "nvim/autocmd_defs.h" @@ -43,7 +42,6 @@ #include "nvim/getchar.h" #include "nvim/gettext_defs.h" #include "nvim/globals.h" -#include "nvim/highlight.h" #include "nvim/highlight_defs.h" #include "nvim/highlight_group.h" #include "nvim/keycodes.h" @@ -64,7 +62,6 @@ #include "nvim/option.h" #include "nvim/option_defs.h" #include "nvim/option_vars.h" -#include "nvim/optionstr.h" #include "nvim/os/input.h" #include "nvim/os/os.h" #include "nvim/path.h" -- cgit From 48e2a73610ca5639408f79b3d8eebd3e5f57a327 Mon Sep 17 00:00:00 2001 From: luukvbaal Date: Thu, 2 Jan 2025 14:51:03 +0100 Subject: feat(ui)!: emit prompt "messages" as cmdline events #31525 Problem: Prompts are emitted as messages events, where cmdline events are more appropriate. The user input is also emitted as message events in fast context, so cannot be displayed with vim.ui_attach(). Solution: Prompt for user input through cmdline prompts. --- src/nvim/ex_getln.c | 49 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 10 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 7f2f739e00..09006484ca 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -120,7 +120,7 @@ typedef struct { int indent; int c; bool gotesc; // true when just typed - int do_abbr; // when true check for abbr. + bool do_abbr; // when true check for abbr. char *lookfor; // string to match int lookforlen; int hiscnt; // current history line in use @@ -128,17 +128,17 @@ typedef struct { // to jump to next match int histype; // history type to be used incsearch_state_T is_state; - int did_wild_list; // did wild_list() recently + bool did_wild_list; // did wild_list() recently int wim_index; // index in wim_flags[] int save_msg_scroll; int save_State; // remember State when called int prev_cmdpos; char *save_p_icm; - int some_key_typed; // one of the keys was typed + bool some_key_typed; // one of the keys was typed // mouse drag and release events are ignored, unless they are // preceded with a mouse down event - int ignore_drag_release; - int break_ctrl_c; + bool ignore_drag_release; + bool break_ctrl_c; expand_T xpc; OptInt *b_im_ptr; buf_T *b_im_ptr_buf; ///< buffer where b_im_ptr is valid @@ -1848,6 +1848,12 @@ static int command_line_browse_history(CommandLineState *s) static int command_line_handle_key(CommandLineState *s) { + // For one key prompt, avoid putting ESC and Ctrl_C onto cmdline. + // For all other keys, just put onto cmdline and exit. + if (ccline.one_key && s->c != ESC && s->c != Ctrl_C) { + goto end; + } + // Big switch for a typed command line character. switch (s->c) { case K_BS: @@ -1998,6 +2004,12 @@ static int command_line_handle_key(CommandLineState *s) } FALLTHROUGH; case K_LEFTMOUSE: + // Return on left click above number prompt + if (ccline.mouse_used && mouse_row < cmdline_row) { + *ccline.mouse_used = true; + return 0; + } + FALLTHROUGH; case K_RIGHTMOUSE: command_line_left_right_mouse(s); return command_line_not_changed(s); @@ -2155,6 +2167,14 @@ static int command_line_handle_key(CommandLineState *s) } return command_line_not_changed(s); + case 'q': + // Number prompts use the mouse and return on 'q' press + if (ccline.mouse_used) { + *ccline.cmdbuff = NUL; + return 0; + } + FALLTHROUGH; + default: // Normal character with no special meaning. Just set mod_mask // to 0x0 so that typing Shift-Space in the GUI doesn't enter @@ -2175,6 +2195,7 @@ static int command_line_handle_key(CommandLineState *s) return command_line_changed(s); } +end: // put the character in the command line if (IS_SPECIAL(s->c) || mod_mask != 0) { put_on_cmdline(get_special_key_name(s->c, mod_mask), -1, true); @@ -2183,7 +2204,7 @@ static int command_line_handle_key(CommandLineState *s) IObuff[j] = NUL; // exclude composing chars put_on_cmdline(IObuff, j, true); } - return command_line_changed(s); + return ccline.one_key ? 0 : command_line_changed(s); } static int command_line_not_changed(CommandLineState *s) @@ -2721,8 +2742,11 @@ static void abandon_cmdline(void) if (msg_scrolled == 0) { compute_cmdrow(); } - msg("", 0); - redraw_cmdline = true; + // Avoid overwriting key prompt + if (!ccline.one_key) { + msg("", 0); + redraw_cmdline = true; + } } /// getcmdline() - accept a command line starting with firstc. @@ -2761,11 +2785,13 @@ char *getcmdline(int firstc, int count, int indent, bool do_concat FUNC_ATTR_UNU /// @param[in] xp_context Type of expansion. /// @param[in] xp_arg User-defined expansion argument. /// @param[in] highlight_callback Callback used for highlighting user input. +/// @param[in] one_key Return after one key press for button prompt. +/// @param[in] mouse_used Set to true when returning after right mouse click. /// /// @return [allocated] Command line or NULL. char *getcmdline_prompt(const int firstc, const char *const prompt, const int hl_id, const int xp_context, const char *const xp_arg, - const Callback highlight_callback) + const Callback highlight_callback, bool one_key, bool *mouse_used) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC { const int msg_col_save = msg_col; @@ -2786,11 +2812,14 @@ char *getcmdline_prompt(const int firstc, const char *const prompt, const int hl ccline.xp_arg = (char *)xp_arg; ccline.input_fn = (firstc == '@'); ccline.highlight_callback = highlight_callback; + ccline.one_key = one_key; + ccline.mouse_used = mouse_used; int msg_silent_saved = msg_silent; msg_silent = 0; char *const ret = (char *)command_line_enter(firstc, 1, 0, false); + ccline.redraw_state = kCmdRedrawNone; if (did_save_ccline) { restore_cmdline(&save_ccline); @@ -4787,7 +4816,7 @@ void get_user_input(const typval_T *const argvars, typval_T *const rettv, const const int save_ex_normal_busy = ex_normal_busy; ex_normal_busy = 0; rettv->vval.v_string = getcmdline_prompt(secret ? NUL : '@', p, get_echo_hl_id(), - xp_type, xp_arg, input_callback); + xp_type, xp_arg, input_callback, false, NULL); ex_normal_busy = save_ex_normal_busy; callback_free(&input_callback); -- cgit From 847c28f6f6ccdfa6d7887605b84137e00e5f7968 Mon Sep 17 00:00:00 2001 From: luukvbaal Date: Sun, 5 Jan 2025 14:59:50 +0100 Subject: fix(cmdline): always show cmdline when it is a prompt #31866 Cmdline prompts should ignore `cmd_silent`. --- src/nvim/ex_getln.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 09006484ca..b26a2ef1bc 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2815,8 +2815,10 @@ char *getcmdline_prompt(const int firstc, const char *const prompt, const int hl ccline.one_key = one_key; ccline.mouse_used = mouse_used; + const bool cmd_silent_saved = cmd_silent; int msg_silent_saved = msg_silent; msg_silent = 0; + cmd_silent = false; // Want to see the prompt. char *const ret = (char *)command_line_enter(firstc, 1, 0, false); ccline.redraw_state = kCmdRedrawNone; @@ -2825,6 +2827,7 @@ char *getcmdline_prompt(const int firstc, const char *const prompt, const int hl restore_cmdline(&save_ccline); } msg_silent = msg_silent_saved; + cmd_silent = cmd_silent_saved; // Restore msg_col, the prompt from input() may have changed it. // But only if called recursively and the commandline is therefore being // restored to an old one; if not, the input() prompt stays on the screen, @@ -4792,9 +4795,6 @@ void get_user_input(const typval_T *const argvars, typval_T *const rettv, const } } - const bool cmd_silent_save = cmd_silent; - - cmd_silent = false; // Want to see the prompt. // Only the part of the message after the last NL is considered as // prompt for the command line, unlsess cmdline is externalized const char *p = prompt; @@ -4829,5 +4829,4 @@ void get_user_input(const typval_T *const argvars, typval_T *const rettv, const // Since the user typed this, no need to wait for return. need_wait_return = false; msg_didout = false; - cmd_silent = cmd_silent_save; } -- cgit From b6ab294838421afb6932c52dd6e6d35d571e621d Mon Sep 17 00:00:00 2001 From: dundargoc Date: Mon, 6 Jan 2025 20:29:55 +0100 Subject: fix: fix incorrect search code --- src/nvim/ex_getln.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index b26a2ef1bc..0b5d0864e5 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -400,7 +400,7 @@ static bool do_incsearch_highlighting(int firstc, int *search_delim, incsearch_s parse_cmd_address(&ea, &dummy, true); if (ea.addr_count > 0) { // Allow for reverse match. - search_first_line = MIN(ea.line1, ea.line1); + search_first_line = MIN(ea.line2, ea.line1); search_last_line = MAX(ea.line2, ea.line1); } else if (cmd[0] == 's' && cmd[1] != 'o') { // :s defaults to the current line -- cgit From bbf36ef8ef86534e317e4e0153730a40ae4c936e Mon Sep 17 00:00:00 2001 From: luukvbaal Date: Wed, 15 Jan 2025 15:55:21 +0100 Subject: fix(cmdline): prevent cmdline_show events after exiting cmdline #32033 Problem: If a (vim.ui_attach) cmdline_hide callback triggers a redraw, it may cause cmdline_show events for an already exited cmdline. Solution: Avoid emitting cmdline_show event when ccline.cmdbuff is already NULL. Unset ccline.cmdbuff before emitting cmdline_hide. --- src/nvim/ex_getln.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 0b5d0864e5..baff795e71 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -951,6 +951,8 @@ theend: kv_destroy(ccline.last_colors.colors); char *p = ccline.cmdbuff; + // Prevent show events triggered by a (vim.ui_attach) hide callback. + ccline.cmdbuff = NULL; if (ui_has(kUICmdline)) { ui_call_cmdline_hide(ccline.level, s->gotesc); @@ -965,8 +967,6 @@ theend: if (did_save_ccline) { restore_cmdline(&save_ccline); - } else { - ccline.cmdbuff = NULL; } return (uint8_t *)p; @@ -3415,6 +3415,10 @@ static void draw_cmdline(int start, int len) static void ui_ext_cmdline_show(CmdlineInfo *line) { + if (line->cmdbuff == NULL) { + return; + } + Arena arena = ARENA_EMPTY; Array content; if (cmdline_star) { -- cgit From 5dd60e01ace2621f2307eebeb92e9e7351210d3a Mon Sep 17 00:00:00 2001 From: Luuk van Baal Date: Thu, 16 Jan 2025 01:11:07 +0100 Subject: refactor(cmdline): more idiomatic way to avoid cmdline_show Problem: Fix applied in #32033 can be more idiomatic. Solution: Unset redraw_state instead of cmdbuff. --- src/nvim/ex_getln.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index baff795e71..423b50cd32 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -951,10 +951,9 @@ theend: kv_destroy(ccline.last_colors.colors); char *p = ccline.cmdbuff; - // Prevent show events triggered by a (vim.ui_attach) hide callback. - ccline.cmdbuff = NULL; if (ui_has(kUICmdline)) { + ccline.redraw_state = kCmdRedrawNone; ui_call_cmdline_hide(ccline.level, s->gotesc); msg_ext_clear_later(); } @@ -967,6 +966,8 @@ theend: if (did_save_ccline) { restore_cmdline(&save_ccline); + } else { + ccline.cmdbuff = NULL; } return (uint8_t *)p; @@ -3415,10 +3416,6 @@ static void draw_cmdline(int start, int len) static void ui_ext_cmdline_show(CmdlineInfo *line) { - if (line->cmdbuff == NULL) { - return; - } - Arena arena = ARENA_EMPTY; Array content; if (cmdline_star) { -- cgit From 5b1136a99c7fc6db4cfe6865b72c069a4697c1a5 Mon Sep 17 00:00:00 2001 From: Donatas Date: Mon, 20 Jan 2025 16:40:26 +0200 Subject: feat(inccommand): preview 'nomodifiable' buffers #32034 Problem: Incremental preview is not allowed on 'nomodifiable' buffers. Solution: - Allow preview on 'nomodifiable' buffers. - Restore the 'modifiable' option in case the preview function changes it. --- src/nvim/ex_getln.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 423b50cd32..1eecee2a38 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -163,6 +163,7 @@ typedef struct { typedef struct { buf_T *buf; OptInt save_b_p_ul; + int save_b_p_ma; int save_b_changed; pos_T save_b_op_start; pos_T save_b_op_end; @@ -2419,6 +2420,7 @@ static void cmdpreview_prepare(CpInfo *cpinfo) if (!set_has(ptr_t, &saved_bufs, buf)) { CpBufInfo cp_bufinfo; cp_bufinfo.buf = buf; + cp_bufinfo.save_b_p_ma = buf->b_p_ma; cp_bufinfo.save_b_p_ul = buf->b_p_ul; cp_bufinfo.save_b_changed = buf->b_changed; cp_bufinfo.save_b_op_start = buf->b_op_start; @@ -2509,6 +2511,7 @@ static void cmdpreview_restore_state(CpInfo *cpinfo) } buf->b_p_ul = cp_bufinfo.save_b_p_ul; // Restore 'undolevels' + buf->b_p_ma = cp_bufinfo.save_b_p_ma; // Restore 'modifiable' } for (size_t i = 0; i < cpinfo->win_info.size; i++) { @@ -2704,7 +2707,6 @@ static int command_line_changed(CommandLineState *s) && current_sctx.sc_sid == 0 // only if interactive && *p_icm != NUL // 'inccommand' is set && !exmode_active // not in ex mode - && curbuf->b_p_ma // buffer is modifiable && cmdline_star == 0 // not typing a password && !vpeekc_any() && cmdpreview_may_show(s)) { -- cgit From 216ec739721494fb31111f19b1dee356a0d88ba1 Mon Sep 17 00:00:00 2001 From: luukvbaal Date: Wed, 29 Jan 2025 12:07:27 +0100 Subject: fix(ui): avoid redundant ext_cmdline events (#32237) Problem: `cmdline_show` is emitted unnecessarily each event loop iteration, because `cmdline_was_last_drawn` is never set. Solution: Keep track of whether the cmdline was last drawn to avoid unnecessarily emitting cmdline_show. Set `redraw_state` to emit `cmdline_pos` when emitting `CursorMovedC`. Only emit `cmdline_pos` when cmdline was last drawn. --- src/nvim/ex_getln.c | 54 +++++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 26 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 1eecee2a38..b5fa05e5a4 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -679,6 +679,15 @@ static void init_ccline(int firstc, int indent) } } +static void ui_ext_cmdline_hide(bool abort) +{ + if (ui_has(kUICmdline)) { + cmdline_was_last_drawn = false; + ccline.redraw_state = kCmdRedrawNone; + ui_call_cmdline_hide(ccline.level, abort); + } +} + /// Internal entry point for cmdline mode. /// /// @param count only used for incremental search @@ -954,8 +963,7 @@ theend: char *p = ccline.cmdbuff; if (ui_has(kUICmdline)) { - ccline.redraw_state = kCmdRedrawNone; - ui_call_cmdline_hide(ccline.level, s->gotesc); + ui_ext_cmdline_hide(s->gotesc); msg_ext_clear_later(); } if (!cmd_silent) { @@ -2209,14 +2217,19 @@ end: return ccline.one_key ? 0 : command_line_changed(s); } -static int command_line_not_changed(CommandLineState *s) +/// Trigger CursorMovedC autocommands. +static void may_trigger_cursormovedc(CommandLineState *s) { - // Trigger CursorMovedC autocommands. if (ccline.cmdpos != s->prev_cmdpos) { trigger_cmd_autocmd(get_cmdline_type(), EVENT_CURSORMOVEDC); s->prev_cmdpos = ccline.cmdpos; + ccline.redraw_state = MAX(ccline.redraw_state, kCmdRedrawPos); } +} +static int command_line_not_changed(CommandLineState *s) +{ + may_trigger_cursormovedc(s); // Incremental searches for "/" and "?": // Enter command_line_not_changed() when a character has been read but the // command line did not change. Then we only search and redraw if something @@ -2696,11 +2709,7 @@ static int command_line_changed(CommandLineState *s) // Trigger CmdlineChanged autocommands. do_autocmd_cmdlinechanged(s->firstc > 0 ? s->firstc : '-'); - // Trigger CursorMovedC autocommands. - if (ccline.cmdpos != s->prev_cmdpos) { - trigger_cmd_autocmd(get_cmdline_type(), EVENT_CURSORMOVEDC); - s->prev_cmdpos = ccline.cmdpos; - } + may_trigger_cursormovedc(s); const bool prev_cmdpreview = cmdpreview; if (s->firstc == ':' @@ -2741,7 +2750,6 @@ static int command_line_changed(CommandLineState *s) static void abandon_cmdline(void) { dealloc_cmdbuff(); - ccline.redraw_state = kCmdRedrawNone; if (msg_scrolled == 0) { compute_cmdrow(); } @@ -3385,7 +3393,7 @@ color_cmdline_error: // when cmdline_star is true. static void draw_cmdline(int start, int len) { - if (!color_cmdline(&ccline)) { + if (ccline.cmdbuff == NULL || !color_cmdline(&ccline)) { return; } @@ -3491,8 +3499,7 @@ void ui_ext_cmdline_block_leave(void) ui_call_cmdline_block_hide(); } -/// Extra redrawing needed for redraw! and on ui_attach -/// assumes "redrawcmdline()" will already be invoked +/// Extra redrawing needed for redraw! and on ui_attach. void cmdline_screen_cleared(void) { if (!ui_has(kUICmdline)) { @@ -3515,6 +3522,7 @@ void cmdline_screen_cleared(void) } line = line->prev_ccline; } + redrawcmd(); } /// called by ui_flush, do what redraws necessary to keep cmdline updated. @@ -3527,12 +3535,14 @@ void cmdline_ui_flush(void) CmdlineInfo *line = &ccline; while (level > 0 && line) { if (line->level == level) { - if (line->redraw_state == kCmdRedrawAll) { + CmdRedraw redraw_state = line->redraw_state; + line->redraw_state = kCmdRedrawNone; + if (redraw_state == kCmdRedrawAll) { + cmdline_was_last_drawn = true; ui_ext_cmdline_show(line); - } else if (line->redraw_state == kCmdRedrawPos) { + } else if (redraw_state == kCmdRedrawPos && cmdline_was_last_drawn) { ui_call_cmdline_pos(line->cmdpos, line->level); } - line->redraw_state = kCmdRedrawNone; level--; } line = line->prev_ccline; @@ -3900,12 +3910,7 @@ void compute_cmdrow(void) void cursorcmd(void) { - if (cmd_silent) { - return; - } - - if (ui_has(kUICmdline)) { - ccline.redraw_state = MAX(ccline.redraw_state, kCmdRedrawPos); + if (cmd_silent || ui_has(kUICmdline)) { return; } @@ -4507,10 +4512,7 @@ static int open_cmdwin(void) curwin->w_cursor.col = ccline.cmdpos; changed_line_abv_curs(); invalidate_botline(curwin); - if (ui_has(kUICmdline)) { - ccline.redraw_state = kCmdRedrawNone; - ui_call_cmdline_hide(ccline.level, false); - } + ui_ext_cmdline_hide(false); redraw_later(curwin, UPD_SOME_VALID); // No Ex mode here! -- cgit From e71d2c817d1a2475551f58a98e411f6b39a5be3f Mon Sep 17 00:00:00 2001 From: dundargoc Date: Mon, 13 Jan 2025 15:48:02 +0100 Subject: docs: misc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Dustin S. Co-authored-by: Ferenc Fejes Co-authored-by: Maria José Solano Co-authored-by: Yochem van Rosmalen Co-authored-by: brianhuster Co-authored-by: zeertzjq --- src/nvim/ex_getln.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index b5fa05e5a4..fc20748309 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2593,7 +2593,7 @@ static bool cmdpreview_may_show(CommandLineState *s) // Place it there in case preview callback flushes it. #30696 cursorcmd(); // Flush now: external cmdline may itself wish to update the screen which is - // currently disallowed during cmdpreview(no longer needed in case that changes). + // currently disallowed during cmdpreview (no longer needed in case that changes). cmdline_ui_flush(); // Swap invalid command range if needed -- cgit