aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorluukvbaal <luukvbaal@gmail.com>2025-01-02 14:51:03 +0100
committerGitHub <noreply@github.com>2025-01-02 05:51:03 -0800
commit48e2a73610ca5639408f79b3d8eebd3e5f57a327 (patch)
treee84d5ab3decc765d7532c172d961fcd554d5b23a /src
parent9d9ee3476e6478850ce8822c85154f0c98570371 (diff)
downloadrneovim-48e2a73610ca5639408f79b3d8eebd3e5f57a327.tar.gz
rneovim-48e2a73610ca5639408f79b3d8eebd3e5f57a327.tar.bz2
rneovim-48e2a73610ca5639408f79b3d8eebd3e5f57a327.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/nvim/bufwrite.c2
-rw-r--r--src/nvim/debugger.c3
-rw-r--r--src/nvim/eval/funcs.c6
-rw-r--r--src/nvim/ex_cmds.c43
-rw-r--r--src/nvim/ex_docmd.c2
-rw-r--r--src/nvim/ex_getln.c49
-rw-r--r--src/nvim/ex_getln_defs.h2
-rw-r--r--src/nvim/input.c146
-rw-r--r--src/nvim/memline.c3
-rw-r--r--src/nvim/message.c56
-rw-r--r--src/nvim/spellsuggest.c12
-rw-r--r--src/nvim/tag.c2
-rw-r--r--src/nvim/ui.c6
13 files changed, 130 insertions, 202 deletions
diff --git a/src/nvim/bufwrite.c b/src/nvim/bufwrite.c
index ced806e524..1afa10df63 100644
--- a/src/nvim/bufwrite.c
+++ b/src/nvim/bufwrite.c
@@ -350,7 +350,7 @@ static int check_mtime(buf_T *buf, FileInfo *file_info)
msg_silent = 0; // Must give this prompt.
// Don't use emsg() here, don't want to flush the buffers.
msg(_("WARNING: The file has been changed since reading it!!!"), HLF_E);
- if (ask_yesno(_("Do you really want to write to it"), true) == 'n') {
+ if (ask_yesno(_("Do you really want to write to it")) == 'n') {
return FAIL;
}
msg_scroll = false; // Always overwrite the file message now.
diff --git a/src/nvim/debugger.c b/src/nvim/debugger.c
index b71ff23f57..f3e4ef0698 100644
--- a/src/nvim/debugger.c
+++ b/src/nvim/debugger.c
@@ -153,8 +153,7 @@ void do_debug(char *cmd)
debug_break_level = -1;
xfree(cmdline);
- cmdline = getcmdline_prompt('>', NULL, 0, EXPAND_NOTHING, NULL,
- CALLBACK_NONE);
+ cmdline = getcmdline_prompt('>', NULL, 0, EXPAND_NOTHING, NULL, CALLBACK_NONE, false, NULL);
debug_break_level = n;
if (typeahead_saved) {
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index fbaa6e679f..ed3efca0d7 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -3557,10 +3557,10 @@ static void f_inputlist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
});
// Ask for choice.
- bool mouse_used;
- int selected = prompt_for_number(&mouse_used);
+ bool mouse_used = false;
+ int selected = prompt_for_input(NULL, 0, false, &mouse_used);
if (mouse_used) {
- selected -= lines_left;
+ selected = tv_list_len(argvars[0].vval.v_list) - (cmdline_row - mouse_row);
}
rettv->vval.v_number = selected;
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index a1a6f13023..0510619825 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -3707,12 +3707,9 @@ static int do_sub(exarg_T *eap, const proftime_T timeout, const int cmdpreview_n
// Loop until 'y', 'n', 'q', CTRL-E or CTRL-Y typed.
while (subflags.do_ask) {
if (exmode_active) {
- char *prompt;
- char *resp;
- colnr_T sc, ec;
-
print_line_no_prefix(lnum, subflags.do_number, subflags.do_list);
+ colnr_T sc, ec;
getvcol(curwin, &curwin->w_cursor, &sc, NULL, NULL);
curwin->w_cursor.col = MAX(regmatch.endpos[0].col - 1, 0);
@@ -3724,10 +3721,11 @@ static int do_sub(exarg_T *eap, const proftime_T timeout, const int cmdpreview_n
ec += numw;
}
- prompt = xmallocz((size_t)ec + 1);
+ char *prompt = xmallocz((size_t)ec + 1);
memset(prompt, ' ', (size_t)sc);
memset(prompt + sc, '^', (size_t)(ec - sc) + 1);
- resp = getcmdline_prompt(-1, prompt, 0, EXPAND_NOTHING, NULL, CALLBACK_NONE);
+ char *resp = getcmdline_prompt(-1, prompt, 0, EXPAND_NOTHING, NULL,
+ CALLBACK_NONE, false, NULL);
msg_putchar('\n');
xfree(prompt);
if (resp != NULL) {
@@ -3794,35 +3792,14 @@ static int do_sub(exarg_T *eap, const proftime_T timeout, const int cmdpreview_n
redraw_later(curwin, UPD_SOME_VALID);
curwin->w_p_fen = save_p_fen;
- if (msg_row == Rows - 1) {
- msg_didout = false; // avoid a scroll-up
- }
- msg_starthere();
- i = msg_scroll;
- msg_scroll = 0; // truncate msg when
- // needed
- msg_no_more = true;
- msg_ext_set_kind("confirm_sub");
- // Same highlight as wait_return().
- smsg(HLF_R, _("replace with %s (y/n/a/q/l/^E/^Y)?"), sub);
- msg_no_more = false;
- msg_scroll = i;
- if (!ui_has(kUIMessages)) {
- ui_cursor_goto(msg_row, msg_col);
- }
- RedrawingDisabled = temp;
- no_mapping++; // don't map this key
- allow_keys++; // allow special keys
- typed = plain_vgetc();
- no_mapping--;
- allow_keys--;
+ snprintf(IObuff, IOSIZE, _("replace with %s (y/n/a/q/l/^E/^Y)?"), sub);
+ char *prompt = xstrdup(IObuff);
+ typed = prompt_for_input(prompt, HLF_R, true, NULL);
+ xfree(prompt);
- // clear the question
- msg_didout = false; // don't scroll up
- msg_col = 0;
- gotocmdline(true);
p_lz = save_p_lz;
+ RedrawingDisabled = temp;
// restore the line
if (orig_line != NULL) {
@@ -4808,7 +4785,7 @@ void ex_oldfiles(exarg_T *eap)
// File selection prompt on ":browse oldfiles"
if (cmdmod.cmod_flags & CMOD_BROWSE) {
quit_more = false;
- nr = prompt_for_number(false);
+ nr = prompt_for_input(NULL, 0, false, NULL);
msg_starthere();
if (nr > 0 && nr <= tv_list_len(l)) {
const char *const p = tv_list_find_str(l, nr - 1);
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 551e8fcb1d..6f9f0f07c9 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -2201,7 +2201,7 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
errormsg = _("E493: Backwards range given");
goto doend;
}
- if (ask_yesno(_("Backwards range given, OK to swap"), false) != 'y') {
+ if (ask_yesno(_("Backwards range given, OK to swap")) != 'y') {
goto doend;
}
}
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 <ESC> 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);
diff --git a/src/nvim/ex_getln_defs.h b/src/nvim/ex_getln_defs.h
index 584c360450..e05d8f27db 100644
--- a/src/nvim/ex_getln_defs.h
+++ b/src/nvim/ex_getln_defs.h
@@ -65,4 +65,6 @@ struct cmdline_info {
char special_char; ///< last putcmdline char (used for redraws)
bool special_shift; ///< shift of last putcmdline char
CmdRedraw redraw_state; ///< needed redraw for external cmdline
+ bool one_key; ///< return after one key press for button prompt
+ bool *mouse_used; ///< mouse clicked in prompt
};
diff --git a/src/nvim/input.c b/src/nvim/input.c
index 5a3a791de4..ca2a13e016 100644
--- a/src/nvim/input.c
+++ b/src/nvim/input.c
@@ -6,6 +6,7 @@
#include <string.h>
#include "nvim/ascii_defs.h"
+#include "nvim/ex_getln.h"
#include "nvim/getchar.h"
#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
@@ -32,44 +33,36 @@
/// No other characters are accepted, the message is repeated until a valid
/// reply is entered or <C-c> is hit.
///
-/// @param[in] str Prompt: question to ask user. Is always followed by
-/// " (y/n)?".
-/// @param[in] direct Determines what function to use to get user input. If
-/// true then input_get() will be used, otherwise vgetc().
-/// I.e. when direct is true then characters are obtained
-/// directly from the user without buffers involved.
+/// @param[in] str Prompt: question to ask user. Is always followed by " (y/n)?".
///
/// @return 'y' or 'n'. Last is also what will be returned in case of interrupt.
-int ask_yesno(const char *const str, const bool direct)
+int ask_yesno(const char *const str)
{
const int save_State = State;
no_wait_return++;
State = MODE_CONFIRM; // Mouse behaves like with :confirm.
setmouse(); // Disable mouse in xterm.
- no_mapping++;
- allow_keys++; // no mapping here, but recognize keys
+ snprintf(IObuff, IOSIZE, _("%s (y/n)?"), str);
+ char *prompt = xstrdup(IObuff);
int r = ' ';
while (r != 'y' && r != 'n') {
// same highlighting as for wait_return()
- smsg(HLF_R, "%s (y/n)?", str);
- if (direct) {
- r = get_keystroke(NULL);
- } else {
- r = plain_vgetc();
- }
+ r = prompt_for_input(prompt, HLF_R, true, NULL);
if (r == Ctrl_C || r == ESC) {
r = 'n';
+ if (!ui_has(kUIMessages)) {
+ msg_putchar(r);
+ }
}
- msg_putchar(r); // Show what you typed.
- ui_flush();
}
+
+ need_wait_return = msg_scrolled;
no_wait_return--;
State = save_State;
setmouse();
- no_mapping--;
- allow_keys--;
+ xfree(prompt);
return r;
}
@@ -155,105 +148,42 @@ int get_keystroke(MultiQueue *events)
return n;
}
-/// Get a number from the user.
-/// When "mouse_used" is not NULL allow using the mouse.
+/// Ask the user for input through a cmdline prompt.
///
-/// @param colon allow colon to abort
-int get_number(int colon, bool *mouse_used)
+/// @param one_key Return from cmdline after one key press.
+/// @param mouse_used When not NULL, allow using the mouse to press a number.
+int prompt_for_input(char *prompt, int hl_id, bool one_key, bool *mouse_used)
{
- int n = 0;
- int typed = 0;
+ int ret = one_key ? ESC : 0;
+ char *kmsg = keep_msg ? xstrdup(keep_msg) : NULL;
- if (mouse_used != NULL) {
- *mouse_used = false;
+ if (prompt == NULL) {
+ if (mouse_used != NULL) {
+ prompt = _("Type number and <Enter> or click with the mouse (q or empty cancels):");
+ } else {
+ prompt = _("Type number and <Enter> (q or empty cancels):");
+ }
}
- // When not printing messages, the user won't know what to type, return a
- // zero (as if CR was hit).
- if (msg_silent != 0) {
- return 0;
- }
+ cmdline_row = msg_row;
+ ui_flush();
- no_mapping++;
- allow_keys++; // no mapping here, but recognize keys
- while (true) {
- ui_cursor_goto(msg_row, msg_col);
- int c = safe_vgetc();
- if (ascii_isdigit(c)) {
- if (vim_append_digit_int(&n, c - '0') == FAIL) {
- return 0;
- }
- msg_putchar(c);
- typed++;
- } else if (c == K_DEL || c == K_KDEL || c == K_BS || c == Ctrl_H) {
- if (typed > 0) {
- msg_puts("\b \b");
- typed--;
- }
- n /= 10;
- } else if (mouse_used != NULL && c == K_LEFTMOUSE) {
- *mouse_used = true;
- n = mouse_row + 1;
- break;
- } else if (n == 0 && c == ':' && colon) {
- stuffcharReadbuff(':');
- if (!exmode_active) {
- cmdline_row = msg_row;
- }
- skip_redraw = true; // skip redraw once
- do_redraw = false;
- break;
- } else if (c == Ctrl_C || c == ESC || c == 'q') {
- n = 0;
- break;
- } else if (c == CAR || c == NL) {
- break;
- }
- }
- no_mapping--;
+ no_mapping++; // don't map prompt input
+ allow_keys++; // allow special keys
+ char *resp = getcmdline_prompt(-1, prompt, hl_id, EXPAND_NOTHING, NULL,
+ CALLBACK_NONE, one_key, mouse_used);
allow_keys--;
- return n;
-}
+ no_mapping--;
-/// Ask the user to enter a number.
-///
-/// When "mouse_used" is not NULL allow using the mouse and in that case return
-/// the line number.
-int prompt_for_number(bool *mouse_used)
-{
- msg_ext_set_kind("number_prompt");
- // When using ":silent" assume that <CR> was entered.
- if (mouse_used != NULL) {
- msg_puts(_("Type number and <Enter> or click with the mouse "
- "(q or empty cancels): "));
- } else {
- msg_puts(_("Type number and <Enter> (q or empty cancels): "));
+ if (resp) {
+ ret = one_key ? (int)(*resp) : atoi(resp);
+ xfree(resp);
}
- // Set the state such that text can be selected/copied/pasted and we still
- // get mouse events.
- int save_cmdline_row = cmdline_row;
- cmdline_row = 0;
- int save_State = State;
- State = MODE_ASKMORE; // prevents a screen update when using a timer
- // May show different mouse shape.
- setmouse();
-
- int i = get_number(true, mouse_used);
- if (KeyTyped) {
- // don't call wait_return() now
- if (msg_row > 0) {
- cmdline_row = msg_row - 1;
- }
- need_wait_return = false;
- msg_didany = false;
- msg_didout = false;
- } else {
- cmdline_row = save_cmdline_row;
+ if (kmsg != NULL) {
+ set_keep_msg(kmsg, keep_msg_hl_id);
+ xfree(kmsg);
}
- State = save_State;
- // May need to restore mouse shape.
- setmouse();
- return i;
+ return ret;
}
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index a2b8aa34ef..ce04362a3e 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -804,8 +804,7 @@ void ml_recover(bool checkext)
// list the names of the swapfiles
recover_names(fname, true, NULL, 0, NULL);
msg_putchar('\n');
- msg_puts(_("Enter number of swap file to use (0 to quit): "));
- i = get_number(false, NULL);
+ i = prompt_for_input(_("Enter number of swap file to use (0 to quit): "), 0, false, NULL);
if (i < 1 || i > len) {
goto theend;
}
diff --git a/src/nvim/message.c b/src/nvim/message.c
index f86f0feca5..69e8f66bbe 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -92,7 +92,7 @@ static int confirm_msg_used = false; // displaying confirm_msg
# include "message.c.generated.h"
#endif
static char *confirm_msg = NULL; // ":confirm" message
-static char *confirm_msg_tail; // tail of confirm_msg
+static char *confirm_buttons; // ":confirm" buttons sent to cmdline as prompt
MessageHistoryEntry *first_msg_hist = NULL;
MessageHistoryEntry *last_msg_hist = NULL;
@@ -2286,7 +2286,7 @@ static void msg_puts_display(const char *str, int maxlen, int hl_id, int recurse
if (p_more && lines_left == 0 && State != MODE_HITRETURN
&& !msg_no_more && !exmode_active) {
if (do_more_prompt(NUL)) {
- s = confirm_msg_tail;
+ s = confirm_buttons;
}
if (quit_more) {
return;
@@ -2778,7 +2778,7 @@ static void msg_puts_printf(const char *str, const ptrdiff_t maxlen)
/// When at hit-enter prompt "typed_char" is the already typed character,
/// otherwise it's NUL.
///
-/// @return true when jumping ahead to "confirm_msg_tail".
+/// @return true when jumping ahead to "confirm_buttons".
static bool do_more_prompt(int typed_char)
{
static bool entered = false;
@@ -3502,10 +3502,10 @@ int do_dialog(int type, const char *title, const char *message, const char *butt
}
// Get a typed character directly from the user.
- int c = get_keystroke(NULL);
+ int c = prompt_for_input(confirm_buttons, HLF_M, true, NULL);
switch (c) {
case CAR: // User accepts default option
- case NL:
+ case NUL:
retval = dfltbutton;
break;
case Ctrl_C: // User aborts/cancels
@@ -3514,6 +3514,7 @@ int do_dialog(int type, const char *title, const char *message, const char *butt
break;
default: // Could be a hotkey?
if (c < 0) { // special keys are ignored here
+ msg_didout = msg_didany = false;
continue;
}
if (c == ':' && ex_cmd) {
@@ -3536,6 +3537,7 @@ int do_dialog(int type, const char *title, const char *message, const char *butt
break;
}
// No hotkey match, so keep waiting
+ msg_didout = msg_didany = false;
continue;
}
break;
@@ -3589,19 +3591,20 @@ static char *console_dialog_alloc(const char *message, const char *buttons, bool
has_hotkey[0] = false;
// Compute the size of memory to allocate.
- int len = 0;
+ int msg_len = 0;
+ int button_len = 0;
int idx = 0;
const char *r = buttons;
while (*r) {
if (*r == DLG_BUTTON_SEP) {
- len += 3; // '\n' -> ', '; 'x' -> '(x)'
+ button_len += 3; // '\n' -> ', '; 'x' -> '(x)'
lenhotkey += HOTK_LEN; // each button needs a hotkey
if (idx < HAS_HOTKEY_LEN - 1) {
has_hotkey[++idx] = false;
}
} else if (*r == DLG_HOTKEY_CHAR) {
r++;
- len++; // '&a' -> '[a]'
+ button_len++; // '&a' -> '[a]'
if (idx < HAS_HOTKEY_LEN - 1) {
has_hotkey[idx] = true;
}
@@ -3611,21 +3614,22 @@ static char *console_dialog_alloc(const char *message, const char *buttons, bool
MB_PTR_ADV(r);
}
- len += (int)(strlen(message)
- + 2 // for the NL's
- + strlen(buttons)
- + 3); // for the ": " and NUL
- lenhotkey++; // for the NUL
+ msg_len += (int)strlen(message) + 3; // for the NL's and NUL
+ button_len += (int)strlen(buttons) + 3; // for the ": " and NUL
+ lenhotkey++; // for the NUL
// If no hotkey is specified, first char is used.
if (!has_hotkey[0]) {
- len += 2; // "x" -> "[x]"
+ button_len += 2; // "x" -> "[x]"
}
// Now allocate space for the strings
xfree(confirm_msg);
- confirm_msg = xmalloc((size_t)len);
- *confirm_msg = NUL;
+ confirm_msg = xmalloc((size_t)msg_len);
+ snprintf(confirm_msg, (size_t)msg_len, "\n%s\n", message);
+
+ xfree(confirm_buttons);
+ confirm_buttons = xmalloc((size_t)button_len);
return xmalloc((size_t)lenhotkey);
}
@@ -3643,42 +3647,34 @@ static char *msg_show_console_dialog(const char *message, const char *buttons, i
bool has_hotkey[HAS_HOTKEY_LEN] = { false };
char *hotk = console_dialog_alloc(message, buttons, has_hotkey);
- copy_hotkeys_and_msg(message, buttons, dfltbutton, has_hotkey, hotk);
+ copy_confirm_hotkeys(buttons, dfltbutton, has_hotkey, hotk);
display_confirm_msg();
return hotk;
}
-/// Copies hotkeys & dialog message into the memory allocated for it
+/// Copies hotkeys into the memory allocated for it
///
-/// @param message Message which will be part of the confirm_msg
/// @param buttons String containing button names
/// @param default_button_idx Number of default button
/// @param has_hotkey An element in this array is true if corresponding button
/// has a hotkey
/// @param[out] hotkeys_ptr Pointer to the memory location where hotkeys will be copied
-static void copy_hotkeys_and_msg(const char *message, const char *buttons, int default_button_idx,
+static void copy_confirm_hotkeys(const char *buttons, int default_button_idx,
const bool has_hotkey[], char *hotkeys_ptr)
{
- *confirm_msg = '\n';
- STRCPY(confirm_msg + 1, message);
-
- char *msgp = confirm_msg + 1 + strlen(message);
-
// Define first default hotkey. Keep the hotkey string NUL
// terminated to avoid reading past the end.
hotkeys_ptr[copy_char(buttons, hotkeys_ptr, true)] = NUL;
- // Remember where the choices start, displaying starts here when
- // "hotkeys_ptr" typed at the more prompt.
- confirm_msg_tail = msgp;
- *msgp++ = '\n';
-
bool first_hotkey = false; // Is the first char of button a hotkey
if (!has_hotkey[0]) {
first_hotkey = true; // If no hotkey is specified, first char is used
}
+ // Remember where the choices start, sent as prompt to cmdline.
+ char *msgp = confirm_buttons;
+
int idx = 0;
const char *r = buttons;
while (*r) {
diff --git a/src/nvim/spellsuggest.c b/src/nvim/spellsuggest.c
index 3a985ab004..21bfa367bf 100644
--- a/src/nvim/spellsuggest.c
+++ b/src/nvim/spellsuggest.c
@@ -444,7 +444,7 @@ void spell_suggest(int count)
char wcopy[MAXWLEN + 2];
suginfo_T sug;
suggest_T *stp;
- bool mouse_used;
+ bool mouse_used = false;
int selected = count;
int badlen = 0;
int msg_scroll_save = msg_scroll;
@@ -594,15 +594,11 @@ void spell_suggest(int count)
cmdmsg_rl = false;
msg_col = 0;
// Ask for choice.
- selected = prompt_for_number(&mouse_used);
-
- if (ui_has(kUIMessages)) {
- ui_call_msg_clear();
- }
-
+ selected = prompt_for_input(NULL, 0, false, &mouse_used);
if (mouse_used) {
- selected -= lines_left;
+ selected = sug.su_ga.ga_len + 1 - (cmdline_row - mouse_row);
}
+
lines_left = Rows; // avoid more prompt
// don't delay for 'smd' in normal_cmd()
msg_scroll = msg_scroll_save;
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index cdce97fc01..c676b00986 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -668,7 +668,7 @@ void do_tag(char *tag, int type, int count, int forceit, bool verbose)
if (ask_for_selection) {
// Ask to select a tag from the list.
- int i = prompt_for_number(NULL);
+ int i = prompt_for_input(NULL, 0, false, NULL);
if (i <= 0 || i > num_matches || got_int) {
// no valid choice: don't change anything
if (use_tagstack) {
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index 4f443028b3..d242baf83b 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -717,10 +717,10 @@ void ui_call_event(char *name, bool fast, Array args)
bool handled = false;
UIEventCallback *event_cb;
- // Prompt messages should be shown immediately so must be safe
+ // Return prompt is still a non-fast event, other prompt messages are
+ // followed by a "cmdline_show" event.
if (strcmp(name, "msg_show") == 0) {
- char *kind = args.items[0].data.string.data;
- fast = !kind || ((strncmp(kind, "confirm", 7) != 0 && strstr(kind, "_prompt") == NULL));
+ fast = !strequal(args.items[0].data.string.data, "return_prompt");
}
map_foreach(&ui_event_cbs, ui_event_ns_id, event_cb, {