aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/ex_getln.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/ex_getln.c')
-rw-r--r--src/nvim/ex_getln.c97
1 files changed, 52 insertions, 45 deletions
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index b4509f9e92..5c02c4c4d6 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -177,10 +177,6 @@ typedef struct command_line_state {
int break_ctrl_c;
expand_T xpc;
long *b_im_ptr;
- // Everything that may work recursively should save and restore the
- // current command line in save_ccline. That includes update_screen(), a
- // custom status line may invoke ":normal".
- struct cmdline_info save_ccline;
} CommandLineState;
typedef struct cmdline_info CmdlineInfo;
@@ -225,11 +221,19 @@ static bool need_cursor_update = false;
# include "ex_getln.c.generated.h"
#endif
-static int cmd_hkmap = 0; /* Hebrew mapping during command line */
+static int cmd_hkmap = 0; // Hebrew mapping during command line
+static int cmd_fkmap = 0; // Farsi mapping during command line
-static int cmd_fkmap = 0; /* Farsi mapping during command line */
+/// Internal entry point for cmdline mode.
+///
+/// caller must use save_cmdline and restore_cmdline. Best is to use
+/// getcmdline or getcmdline_prompt, instead of calling this directly.
static uint8_t *command_line_enter(int firstc, long count, int indent)
{
+ // can be invoked recursively, identify each level
+ static int cmdline_level = 0;
+ cmdline_level++;
+
CommandLineState state, *s = &state;
memset(s, 0, sizeof(CommandLineState));
s->firstc = firstc;
@@ -257,7 +261,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent)
}
ccline.prompt_id = last_prompt_id++;
- ccline.level++;
+ ccline.level = cmdline_level;
ccline.overstrike = false; // always start in insert mode
clearpos(&s->match_end);
s->save_cursor = curwin->w_cursor; // may be restored later
@@ -489,19 +493,14 @@ static uint8_t *command_line_enter(int firstc, long count, int indent)
sb_text_end_cmdline();
- {
- char_u *p = ccline.cmdbuff;
-
- // Make ccline empty, getcmdline() may try to use it.
- ccline.cmdbuff = NULL;
+ char_u *p = ccline.cmdbuff;
- if (ui_is_external(kUICmdline)) {
- ccline.redraw_state = kCmdRedrawNone;
- ui_call_cmdline_hide(ccline.level);
- }
- ccline.level--;
- return p;
+ if (ui_is_external(kUICmdline)) {
+ ui_call_cmdline_hide(ccline.level);
}
+
+ cmdline_level--;
+ return p;
}
static int command_line_check(VimState *state)
@@ -641,9 +640,7 @@ static int command_line_execute(VimState *state, int key)
p_ls = save_p_ls;
p_wmh = save_p_wmh;
last_status(false);
- save_cmdline(&s->save_ccline);
update_screen(VALID); // redraw the screen NOW
- restore_cmdline(&s->save_ccline);
redrawcmd();
save_p_ls = -1;
wild_menu_showing = 0;
@@ -814,18 +811,17 @@ static int command_line_execute(VimState *state, int key)
new_cmdpos = ccline.cmdpos;
}
- save_cmdline(&s->save_ccline);
s->c = get_expr_register();
- restore_cmdline(&s->save_ccline);
if (s->c == '=') {
// Need to save and restore ccline. And set "textlock"
// to avoid nasty things like going to another buffer when
// evaluating an expression.
- save_cmdline(&s->save_ccline);
- ++textlock;
+ CmdlineInfo save_ccline;
+ save_cmdline(&save_ccline);
+ textlock++;
p = get_expr_line();
- --textlock;
- restore_cmdline(&s->save_ccline);
+ textlock--;
+ restore_cmdline(&save_ccline);
if (p != NULL) {
len = (int)STRLEN(p);
@@ -1358,9 +1354,10 @@ static int command_line_handle_key(CommandLineState *s)
beep_flush();
s->c = ESC;
} else {
- save_cmdline(&s->save_ccline);
+ CmdlineInfo save_ccline;
+ save_cmdline(&save_ccline);
s->c = get_expr_register();
- restore_cmdline(&s->save_ccline);
+ restore_cmdline(&save_ccline);
}
}
@@ -1892,9 +1889,7 @@ static int command_line_changed(CommandLineState *s)
curwin->w_redr_status = true;
}
- save_cmdline(&s->save_ccline);
update_screen(SOME_VALID);
- restore_cmdline(&s->save_ccline);
restore_last_search_pattern();
// Leave it at the end to make CTRL-R CTRL-W work.
@@ -1989,7 +1984,14 @@ getcmdline (
int indent // indent for inside conditionals
)
{
- return command_line_enter(firstc, count, indent);
+ // Be prepared for situations where cmdline can be invoked recursively.
+ // That includes cmd mappings, event handlers, as well as update_screen()
+ // (custom status line eval), which all may invoke ":normal :".
+ CmdlineInfo save_ccline;
+ save_cmdline(&save_ccline);
+ char_u *retval = command_line_enter(firstc, count, indent);
+ restore_cmdline(&save_ccline);
+ return retval;
}
/// Get a command line with a prompt
@@ -2013,7 +2015,7 @@ char *getcmdline_prompt(const char firstc, const char *const prompt,
{
const int msg_col_save = msg_col;
- struct cmdline_info save_ccline;
+ CmdlineInfo save_ccline;
save_cmdline(&save_ccline);
ccline.prompt_id = last_prompt_id++;
@@ -2027,7 +2029,7 @@ char *getcmdline_prompt(const char firstc, const char *const prompt,
int msg_silent_saved = msg_silent;
msg_silent = 0;
- char *const ret = (char *)getcmdline(firstc, 1L, 0);
+ char *const ret = (char *)command_line_enter(firstc, 1L, 0);
restore_cmdline(&save_ccline);
msg_silent = msg_silent_saved;
@@ -2169,6 +2171,7 @@ getexline (
/* When executing a register, remove ':' that's in front of each line. */
if (exec_from_reg && vpeekc() == ':')
(void)vgetc();
+
return getcmdline(c, 1L, indent);
}
@@ -2976,7 +2979,7 @@ void ui_ext_cmdline_block_append(int indent, const char *line)
memcpy(buf + indent, line, strlen(line)); // -V575
Array item = ARRAY_DICT_INIT;
- ADD(item, DICTIONARY_OBJ((Dictionary)ARRAY_DICT_INIT));
+ ADD(item, INTEGER_OBJ(0));
ADD(item, STRING_OBJ(cstr_as_string(buf)));
Array content = ARRAY_DICT_INIT;
ADD(content, ARRAY_OBJ(item));
@@ -3008,16 +3011,16 @@ void cmdline_screen_cleared(void)
}
int prev_level = ccline.level-1;
- CmdlineInfo *prev_ccline = ccline.prev_ccline;
- while (prev_level > 0 && prev_ccline) {
- if (prev_ccline->level == prev_level) {
+ CmdlineInfo *line = ccline.prev_ccline;
+ while (prev_level > 0 && line) {
+ if (line->level == prev_level) {
// don't redraw a cmdline already shown in the cmdline window
if (prev_level != cmdwin_level) {
- prev_ccline->redraw_state = kCmdRedrawAll;
+ line->redraw_state = kCmdRedrawAll;
}
prev_level--;
}
- prev_ccline = prev_ccline->prev_ccline;
+ line = line->prev_ccline;
}
need_cursor_update = true;
@@ -3230,6 +3233,7 @@ static void save_cmdline(struct cmdline_info *ccp)
ccline.cmdprompt = NULL;
ccline.xpc = NULL;
ccline.special_char = NUL;
+ ccline.level = 0;
}
/*
@@ -3272,17 +3276,18 @@ void restore_cmdline_alloc(char_u *p)
/// @returns FAIL for failure, OK otherwise
static bool cmdline_paste(int regname, bool literally, bool remcr)
{
- long i;
char_u *arg;
char_u *p;
- int allocated;
+ bool allocated;
struct cmdline_info save_ccline;
/* check for valid regname; also accept special characters for CTRL-R in
* the command line */
if (regname != Ctrl_F && regname != Ctrl_P && regname != Ctrl_W
- && regname != Ctrl_A && !valid_yank_reg(regname, false))
+ && regname != Ctrl_A && regname != Ctrl_L
+ && !valid_yank_reg(regname, false)) {
return FAIL;
+ }
/* A register containing CTRL-R can cause an endless loop. Allow using
* CTRL-C to break the loop. */
@@ -3294,9 +3299,9 @@ static bool cmdline_paste(int regname, bool literally, bool remcr)
/* Need to save and restore ccline. And set "textlock" to avoid nasty
* things like going to another buffer when evaluating an expression. */
save_cmdline(&save_ccline);
- ++textlock;
- i = get_spec_reg(regname, &arg, &allocated, TRUE);
- --textlock;
+ textlock++;
+ const bool i = get_spec_reg(regname, &arg, &allocated, true);
+ textlock--;
restore_cmdline(&save_ccline);
if (i) {
@@ -4742,6 +4747,7 @@ ExpandFromContext (
} tab[] = {
{ EXPAND_COMMANDS, get_command_name, false, true },
{ EXPAND_BEHAVE, get_behave_arg, true, true },
+ { EXPAND_MAPCLEAR, get_mapclear_arg, true, true },
{ EXPAND_MESSAGES, get_messages_arg, true, true },
{ EXPAND_HISTORY, get_history_arg, true, true },
{ EXPAND_USER_COMMANDS, get_user_commands, false, true },
@@ -4769,6 +4775,7 @@ ExpandFromContext (
#endif
{ EXPAND_ENV_VARS, get_env_name, true, true },
{ EXPAND_USER, get_users, true, false },
+ { EXPAND_ARGLIST, get_arglist_name, true, false },
};
int i;