mirror of
https://github.com/neovim/neovim.git
synced 2024-12-19 02:34:59 -07:00
Compare commits
2 Commits
f6239b5278
...
06ada3c16a
Author | SHA1 | Date | |
---|---|---|---|
|
06ada3c16a | ||
|
378edbbd34 |
@ -1086,9 +1086,8 @@ vim.ui_attach({ns}, {options}, {callback}) *vim.ui_attach()*
|
||||
|ui-popupmenu| and the sections below for event format for respective
|
||||
events.
|
||||
|
||||
Callbacks for `msg_show` events are executed in |api-fast| context unless
|
||||
Nvim will wait for input, in which case messages should be shown
|
||||
immediately.
|
||||
Callbacks for `msg_show` events are executed in |api-fast| context;
|
||||
showing the message should be scheduled.
|
||||
|
||||
Excessive errors inside the callback will result in forced detachment.
|
||||
|
||||
|
@ -791,7 +791,6 @@ must handle.
|
||||
"" (empty) Unknown (consider a |feature-request|)
|
||||
"bufwrite" |:write| message
|
||||
"confirm" |confirm()| or |:confirm| dialog
|
||||
"confirm_sub" |:substitute| confirm dialog |:s_c|
|
||||
"emsg" Error (|errors|, internal error, |:throw|, …)
|
||||
"echo" |:echo| message
|
||||
"echomsg" |:echomsg| message
|
||||
@ -800,7 +799,6 @@ must handle.
|
||||
"lua_error" Error in |:lua| code
|
||||
"lua_print" |print()| from |:lua| code
|
||||
"rpc_error" Error response from |rpcrequest()|
|
||||
"number_prompt" Number input prompt (|inputlist()|, |z=|, …)
|
||||
"return_prompt" |press-enter| prompt after a multiple messages
|
||||
"quickfix" Quickfix navigation message
|
||||
"search_cmd" Entered search command
|
||||
|
@ -233,9 +233,8 @@ function vim.wait(time, callback, interval, fast_only) end
|
||||
--- {callback} receives event name plus additional parameters. See |ui-popupmenu|
|
||||
--- and the sections below for event format for respective events.
|
||||
---
|
||||
--- Callbacks for `msg_show` events are executed in |api-fast| context unless
|
||||
--- Nvim will wait for input, in which case messages should be shown
|
||||
--- immediately.
|
||||
--- Callbacks for `msg_show` events are executed in |api-fast| context; showing
|
||||
--- the message should be scheduled.
|
||||
---
|
||||
--- Excessive errors inside the callback will result in forced detachment.
|
||||
---
|
||||
|
@ -351,7 +351,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.
|
||||
|
@ -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) {
|
||||
|
@ -3554,10 +3554,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;
|
||||
|
@ -3708,12 +3708,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);
|
||||
|
||||
@ -3725,10 +3722,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) {
|
||||
@ -3803,27 +3801,20 @@ static int do_sub(exarg_T *eap, const proftime_T timeout, const int cmdpreview_n
|
||||
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) {
|
||||
@ -4809,7 +4800,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);
|
||||
|
@ -2202,7 +2202,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;
|
||||
}
|
||||
}
|
||||
|
@ -123,7 +123,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
|
||||
@ -131,17 +131,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
|
||||
@ -1851,6 +1851,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:
|
||||
@ -2001,6 +2007,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);
|
||||
@ -2158,6 +2170,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
|
||||
@ -2178,6 +2198,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);
|
||||
@ -2186,7 +2207,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)
|
||||
@ -2724,8 +2745,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.
|
||||
@ -2764,11 +2788,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;
|
||||
@ -2789,11 +2815,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);
|
||||
@ -4790,7 +4819,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);
|
||||
|
||||
|
@ -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
|
||||
};
|
||||
|
148
src/nvim/input.c
148
src/nvim/input.c
@ -7,6 +7,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"
|
||||
@ -34,44 +35,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;
|
||||
}
|
||||
@ -157,105 +150,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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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;
|
||||
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):");
|
||||
}
|
||||
}
|
||||
no_mapping--;
|
||||
|
||||
cmdline_row = msg_row;
|
||||
ui_flush();
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -805,8 +805,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;
|
||||
}
|
||||
|
@ -90,7 +90,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;
|
||||
@ -2296,7 +2296,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;
|
||||
@ -2788,7 +2788,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;
|
||||
@ -3511,10 +3511,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
|
||||
@ -3523,6 +3523,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) {
|
||||
@ -3545,6 +3546,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;
|
||||
@ -3598,19 +3600,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;
|
||||
}
|
||||
@ -3620,21 +3623,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);
|
||||
}
|
||||
@ -3652,42 +3656,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) {
|
||||
|
@ -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;
|
||||
|
@ -669,7 +669,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) {
|
||||
|
@ -718,10 +718,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, {
|
||||
|
@ -219,6 +219,7 @@ describe('swapfile detection', function()
|
||||
.. [[%.swp"]],
|
||||
}
|
||||
feed('e') -- Chose "Edit" at the swap dialog.
|
||||
screen2:expect({ any = pesc('E5555: API call: Vim(edit):E325: ATTENTION') })
|
||||
feed('<c-c>')
|
||||
screen2:expect(expected_no_dialog)
|
||||
|
||||
@ -531,10 +532,6 @@ describe('quitting swapfile dialog on startup stops TUI properly', function()
|
||||
)
|
||||
end)
|
||||
api.nvim_chan_send(chan, 'q')
|
||||
retry(nil, nil, function()
|
||||
eq('Press ENTER or type command to continue', eval("getline('$')->trim(' ', 2)"))
|
||||
end)
|
||||
api.nvim_chan_send(chan, '\r')
|
||||
retry(nil, nil, function()
|
||||
eq(
|
||||
{ '', '[Process exited 1]', '' },
|
||||
|
@ -268,43 +268,6 @@ describe('vim.ui_attach', function()
|
||||
},
|
||||
},
|
||||
})
|
||||
-- No fast context for prompt message kinds
|
||||
feed(':%s/Function/Replacement/c<cr>')
|
||||
screen:expect({
|
||||
grid = [[
|
||||
^E122: {10:Function} Foo already exists, add !|
|
||||
to replace it |
|
||||
replace with Replacement (y/n/a/q/l/^E/^|
|
||||
Y)? |
|
||||
{1:~ }|
|
||||
]],
|
||||
messages = {
|
||||
{
|
||||
content = { { 'replace with Replacement (y/n/a/q/l/^E/^Y)?', 6, 18 } },
|
||||
kind = 'confirm_sub',
|
||||
},
|
||||
},
|
||||
})
|
||||
feed('<esc>:call inputlist(["Select:", "One", "Two"])<cr>')
|
||||
screen:expect({
|
||||
grid = [[
|
||||
E122: {10:Function} Foo already exists, add !|
|
||||
to replace it |
|
||||
Type number and <Enter> or click with th|
|
||||
e mouse (q or empty cancels): |
|
||||
{1:^~ }|
|
||||
]],
|
||||
messages = {
|
||||
{
|
||||
content = { { 'Select:\nOne\nTwo\n' } },
|
||||
kind = 'list_cmd',
|
||||
},
|
||||
{
|
||||
content = { { 'Type number and <Enter> or click with the mouse (q or empty cancels): ' } },
|
||||
kind = 'number_prompt',
|
||||
},
|
||||
},
|
||||
})
|
||||
end)
|
||||
end)
|
||||
|
||||
|
@ -1456,13 +1456,12 @@ describe('cmdheight=0', function()
|
||||
}
|
||||
|
||||
feed(':%s/foo/bar/gc<CR>')
|
||||
screen:expect {
|
||||
grid = [[
|
||||
{2:foo} |
|
||||
{1:~ }|*3
|
||||
{6:replace wi...q/l/^E/^Y)?}^ |
|
||||
]],
|
||||
}
|
||||
screen:expect([[
|
||||
{3: }|
|
||||
|*2
|
||||
{6:replace with bar (y/n/a/q}|
|
||||
{6:/l/^E/^Y)?}^ |
|
||||
]])
|
||||
|
||||
feed('y')
|
||||
screen:expect {
|
||||
|
@ -368,7 +368,7 @@ describe('input non-printable chars', function()
|
||||
"Xtest-overwrite" |
|
||||
{9:WARNING: The file has been changed since reading it!!!} |
|
||||
{6:Do you really want to write to it (y/n)?}u |
|
||||
{6:Do you really want to write to it (y/n)?} |
|
||||
{6:Do you really want to write to it (y/n)?}{18:^E} |
|
||||
{6:Do you really want to write to it (y/n)?}^ |
|
||||
]])
|
||||
|
||||
@ -379,7 +379,7 @@ describe('input non-printable chars', function()
|
||||
"Xtest-overwrite" |
|
||||
{9:WARNING: The file has been changed since reading it!!!} |
|
||||
{6:Do you really want to write to it (y/n)?}u |
|
||||
{6:Do you really want to write to it (y/n)?} |
|
||||
{6:Do you really want to write to it (y/n)?}{18:^E} |
|
||||
{6:Do you really want to write to it (y/n)?}n |
|
||||
{6:Press ENTER or type command to continue}^ |
|
||||
]])
|
||||
|
@ -42,18 +42,25 @@ describe('ui/ext_messages', function()
|
||||
it('msg_clear follows msg_show kind of confirm', function()
|
||||
feed('iline 1<esc>')
|
||||
feed(':call confirm("test")<cr>')
|
||||
screen:expect {
|
||||
screen:expect({
|
||||
grid = [[
|
||||
line ^1 |
|
||||
{1:~ }|*4
|
||||
]],
|
||||
line ^1 |
|
||||
{1:~ }|*4
|
||||
]],
|
||||
cmdline = {
|
||||
{
|
||||
content = { { '' } },
|
||||
pos = 0,
|
||||
prompt = '[O]k: ',
|
||||
},
|
||||
},
|
||||
messages = {
|
||||
{
|
||||
content = { { '\ntest\n[O]k: ', 6, 10 } },
|
||||
content = { { '\ntest\n', 6, 10 } },
|
||||
kind = 'confirm',
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
feed('<cr>')
|
||||
screen:expect {
|
||||
@ -67,22 +74,29 @@ describe('ui/ext_messages', function()
|
||||
it('msg_show kinds', function()
|
||||
feed('iline 1\nline 2<esc>')
|
||||
|
||||
-- kind=confirm
|
||||
-- confirm is now cmdline prompt
|
||||
feed(':echo confirm("test")<cr>')
|
||||
screen:expect {
|
||||
screen:expect({
|
||||
grid = [[
|
||||
line 1 |
|
||||
line ^2 |
|
||||
{1:~ }|*3
|
||||
]],
|
||||
line 1 |
|
||||
line ^2 |
|
||||
{1:~ }|*3
|
||||
]],
|
||||
cmdline = {
|
||||
{
|
||||
content = { { '' } },
|
||||
pos = 0,
|
||||
prompt = '[O]k: ',
|
||||
},
|
||||
},
|
||||
messages = {
|
||||
{
|
||||
content = { { '\ntest\n[O]k: ', 6, 10 } },
|
||||
content = { { '\ntest\n', 6, 10 } },
|
||||
kind = 'confirm',
|
||||
},
|
||||
},
|
||||
}
|
||||
feed('<cr><cr>')
|
||||
})
|
||||
feed('<cr>')
|
||||
screen:expect {
|
||||
grid = [[
|
||||
line 1 |
|
||||
@ -91,7 +105,7 @@ describe('ui/ext_messages', function()
|
||||
]],
|
||||
messages = {
|
||||
{
|
||||
content = { { '\ntest\n[O]k: ', 6, 10 } },
|
||||
content = { { '\ntest\n', 6, 10 } },
|
||||
kind = 'confirm',
|
||||
},
|
||||
{
|
||||
@ -104,23 +118,24 @@ describe('ui/ext_messages', function()
|
||||
},
|
||||
},
|
||||
}
|
||||
feed('<cr><cr>')
|
||||
feed('<cr>')
|
||||
|
||||
-- kind=confirm_sub
|
||||
-- :substitute confirm is now cmdline prompt
|
||||
feed(':%s/i/X/gc<cr>')
|
||||
screen:expect {
|
||||
screen:expect({
|
||||
grid = [[
|
||||
l{2:i}ne 1 |
|
||||
l{10:i}ne ^2 |
|
||||
{1:~ }|*3
|
||||
]],
|
||||
messages = {
|
||||
l{2:^i}ne 1 |
|
||||
l{10:i}ne 2 |
|
||||
{1:~ }|*3
|
||||
]],
|
||||
cmdline = {
|
||||
{
|
||||
content = { { 'replace with X (y/n/a/q/l/^E/^Y)?', 6, 18 } },
|
||||
kind = 'confirm_sub',
|
||||
content = { { '' } },
|
||||
pos = 0,
|
||||
prompt = 'replace with X (y/n/a/q/l/^E/^Y)?',
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
feed('nq')
|
||||
|
||||
-- kind=wmsg (editing readonly file)
|
||||
@ -1031,42 +1046,42 @@ stack traceback:
|
||||
feed('z=')
|
||||
screen:expect({
|
||||
grid = [[
|
||||
{100:helllo} |
|
||||
{1:~ }|*3
|
||||
{1:^~ }|
|
||||
{100:^helllo} |
|
||||
{1:~ }|*4
|
||||
]],
|
||||
cmdline = {
|
||||
{
|
||||
content = { { '' } },
|
||||
pos = 0,
|
||||
prompt = 'Type number and <Enter> or click with the mouse (q or empty cancels):',
|
||||
},
|
||||
},
|
||||
messages = {
|
||||
{
|
||||
content = { { 'Change "helllo" to:\n 1 "Hello"\n 2 "Hallo"\n 3 "Hullo"\n' } },
|
||||
kind = 'list_cmd',
|
||||
},
|
||||
{
|
||||
content = { { 'Type number and <Enter> or click with the mouse (q or empty cancels): ' } },
|
||||
kind = 'number_prompt',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
feed('1')
|
||||
screen:expect({
|
||||
grid = [[
|
||||
{100:helllo} |
|
||||
{1:~ }|*3
|
||||
{1:^~ }|
|
||||
{100:^helllo} |
|
||||
{1:~ }|*4
|
||||
]],
|
||||
cmdline = {
|
||||
{
|
||||
content = { { '1' } },
|
||||
pos = 1,
|
||||
prompt = 'Type number and <Enter> or click with the mouse (q or empty cancels):',
|
||||
},
|
||||
},
|
||||
messages = {
|
||||
{
|
||||
content = { { 'Change "helllo" to:\n 1 "Hello"\n 2 "Hallo"\n 3 "Hullo"\n' } },
|
||||
kind = 'list_cmd',
|
||||
},
|
||||
{
|
||||
content = { { 'Type number and <Enter> or click with the mouse (q or empty cancels): ' } },
|
||||
kind = 'number_prompt',
|
||||
},
|
||||
{
|
||||
content = { { '1' } },
|
||||
kind = '',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -116,7 +116,7 @@ describe('NULL', function()
|
||||
null_expr_test(
|
||||
'is accepted as an empty list by inputlist()',
|
||||
'[feedkeys("\\n"), inputlist(L)]',
|
||||
'Type number and <Enter> or click with the mouse (q or empty cancels): ',
|
||||
'',
|
||||
{ 0, 0 }
|
||||
)
|
||||
null_expr_test(
|
||||
|
@ -471,7 +471,9 @@ func Test_spellsuggest_option_number()
|
||||
\ .. "Change \"baord\" to:\n"
|
||||
\ .. " 1 \"board\"\n"
|
||||
\ .. " 2 \"bard\"\n"
|
||||
\ .. "Type number and <Enter> or click with the mouse (q or empty cancels): ", a)
|
||||
"\ Nvim: Prompt message is sent to cmdline prompt.
|
||||
"\ .. "Type number and <Enter> or click with the mouse (q or empty cancels): ", a)
|
||||
\ , a)
|
||||
|
||||
set spell spellsuggest=0
|
||||
call assert_equal("\nSorry, no suggestions", execute('norm $z='))
|
||||
@ -509,7 +511,9 @@ func Test_spellsuggest_option_expr()
|
||||
\ .. " 1 \"BARD\"\n"
|
||||
\ .. " 2 \"BOARD\"\n"
|
||||
\ .. " 3 \"BROAD\"\n"
|
||||
\ .. "Type number and <Enter> or click with the mouse (q or empty cancels): ", a)
|
||||
"\ Nvim: Prompt message is sent to cmdline prompt.
|
||||
"\ .. "Type number and <Enter> or click with the mouse (q or empty cancels): ", a)
|
||||
\ , a)
|
||||
|
||||
" With verbose, z= should show the score i.e. word length with
|
||||
" our SpellSuggest() function.
|
||||
@ -521,7 +525,9 @@ func Test_spellsuggest_option_expr()
|
||||
\ .. " 1 \"BARD\" (4 - 0)\n"
|
||||
\ .. " 2 \"BOARD\" (5 - 0)\n"
|
||||
\ .. " 3 \"BROAD\" (5 - 0)\n"
|
||||
\ .. "Type number and <Enter> or click with the mouse (q or empty cancels): ", a)
|
||||
"\ Nvim: Prompt message is sent to cmdline prompt.
|
||||
"\ .. "Type number and <Enter> or click with the mouse (q or empty cancels): ", a)
|
||||
\ , a)
|
||||
|
||||
set spell& spellsuggest& verbose&
|
||||
bwipe!
|
||||
|
@ -1231,8 +1231,10 @@ func Test_tselect_listing()
|
||||
2 FS v first Xfoo
|
||||
typeref:typename:char
|
||||
2
|
||||
Type number and <Enter> (q or empty cancels):
|
||||
[DATA]
|
||||
" Type number and <Enter> (q or empty cancels):
|
||||
" Nvim: Prompt message is sent to cmdline prompt.
|
||||
|
||||
call assert_equal(expected, l)
|
||||
|
||||
call delete('Xtags')
|
||||
|
Loading…
Reference in New Issue
Block a user