diff options
Diffstat (limited to 'src/nvim/ex_getln.c')
-rw-r--r-- | src/nvim/ex_getln.c | 97 |
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; |