diff options
| author | Thiago de Arruda <tpadilha84@gmail.com> | 2015-10-23 08:22:16 -0300 |
|---|---|---|
| committer | Thiago de Arruda <tpadilha84@gmail.com> | 2015-10-26 10:52:02 -0300 |
| commit | 0701e1bfa4ba5b54748d9f99b39ca007177a898b (patch) | |
| tree | 486966a484ead3a70b095a3f15410a04c4beaa43 /src | |
| parent | 52d4978b034670935054ca320ca34ff9e4596fe0 (diff) | |
| download | rneovim-0701e1bfa4ba5b54748d9f99b39ca007177a898b.tar.gz rneovim-0701e1bfa4ba5b54748d9f99b39ca007177a898b.tar.bz2 rneovim-0701e1bfa4ba5b54748d9f99b39ca007177a898b.zip | |
ex_getln: refactor command line mode to use the `state_enter` loop
Split `getcmdline()` into command_line_{enter,check,execute}`
Diffstat (limited to 'src')
| -rw-r--r-- | src/nvim/ex_getln.c | 2260 |
1 files changed, 1135 insertions, 1125 deletions
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 38670052bb..19b21875ad 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -160,32 +160,7 @@ static int hislen = 0; /* actual length of history tables */ static int cmd_hkmap = 0; /* Hebrew mapping during command line */ static int cmd_fkmap = 0; /* Farsi mapping during command line */ - -/* - * getcmdline() - accept a command line starting with firstc. - * - * firstc == ':' get ":" command line. - * firstc == '/' or '?' get search pattern - * firstc == '=' get expression - * firstc == '@' get text for input() function - * firstc == '>' get text for debug mode - * firstc == NUL get text for :insert command - * firstc == -1 like NUL, and break on CTRL-C - * - * The line is collected in ccline.cmdbuff, which is reallocated to fit the - * command line. - * - * Careful: getcmdline() can be called recursively! - * - * Return pointer to allocated string if there is a commandline, NULL - * otherwise. - */ -char_u * -getcmdline ( - int firstc, - long count, // only used for incremental search - int indent // indent for inside conditionals -) +static uint8_t *command_line_enter(int firstc, long count, int indent) { CommandLineState state, *s = &state; memset(s, 0, sizeof(CommandLineState)); @@ -298,650 +273,650 @@ getcmdline ( did_emsg = false; got_int = false; + s->state.check = command_line_check; + s->state.execute = command_line_execute; + state_enter(&s->state); - // Collect the command string, handling editing keys. - for (;;) { - redir_off = true; // Don't redirect the typed command. - // Repeated, because a ":redir" inside - // completion may switch it on. - quit_more = false; // reset after CTRL-D which had a more-prompt + cmdmsg_rl = false; - cursorcmd(); // set the cursor on the right spot + cmd_fkmap = 0; - // Get a character. Ignore K_IGNORE, it should not do anything, such - // as stop completion. - input_enable_events(); - do { - s->c = safe_vgetc(); - } while (s->c == K_IGNORE || s->c == K_PASTE); - input_disable_events(); + ExpandCleanup(&s->xpc); + ccline.xpc = NULL; - if (s->c == K_EVENT) { - queue_process_events(loop.events); - continue; - } + if (s->did_incsearch) { + curwin->w_cursor = s->old_cursor; + curwin->w_curswant = s->old_curswant; + curwin->w_leftcol = s->old_leftcol; + curwin->w_topline = s->old_topline; + curwin->w_topfill = s->old_topfill; + curwin->w_botline = s->old_botline; + highlight_match = false; + validate_cursor(); // needed for TAB + redraw_later(SOME_VALID); + } - if (KeyTyped) { - s->some_key_typed = true; - if (cmd_hkmap) { - s->c = hkmap(s->c); + if (ccline.cmdbuff != NULL) { + // Put line in history buffer (":" and "=" only when it was typed). + if (ccline.cmdlen && s->firstc != NUL + && (s->some_key_typed || s->histype == HIST_SEARCH)) { + add_to_history(s->histype, ccline.cmdbuff, true, + s->histype == HIST_SEARCH ? s->firstc : NUL); + if (s->firstc == ':') { + xfree(new_last_cmdline); + new_last_cmdline = vim_strsave(ccline.cmdbuff); } + } - if (cmd_fkmap) { - s->c = cmdl_fkmap(s->c); + if (s->gotesc) { // abandon command line + xfree(ccline.cmdbuff); + ccline.cmdbuff = NULL; + if (msg_scrolled == 0) { + compute_cmdrow(); } + MSG(""); + redraw_cmdline = true; + } + } - if (cmdmsg_rl && !KeyStuffed) { - // Invert horizontal movements and operations. Only when - // typed by the user directly, not when the result of a - // mapping. - switch (s->c) { - case K_RIGHT: s->c = K_LEFT; break; - case K_S_RIGHT: s->c = K_S_LEFT; break; - case K_C_RIGHT: s->c = K_C_LEFT; break; - case K_LEFT: s->c = K_RIGHT; break; - case K_S_LEFT: s->c = K_S_RIGHT; break; - case K_C_LEFT: s->c = K_C_RIGHT; break; - } - } + // If the screen was shifted up, redraw the whole screen (later). + // If the line is too long, clear it, so ruler and shown command do + // not get printed in the middle of it. + msg_check(); + msg_scroll = s->save_msg_scroll; + redir_off = false; + + // When the command line was typed, no need for a wait-return prompt. + if (s->some_key_typed) { + need_wait_return = false; + } + + State = s->save_State; + setmouse(); + ui_cursor_shape(); // may show different cursor shape + + { + char_u *p = ccline.cmdbuff; + + // Make ccline empty, getcmdline() may try to use it. + ccline.cmdbuff = NULL; + return p; + } +} + +static int command_line_check(VimState *state) +{ + redir_off = true; // Don't redirect the typed command. + // Repeated, because a ":redir" inside + // completion may switch it on. + quit_more = false; // reset after CTRL-D which had a more-prompt + + cursorcmd(); // set the cursor on the right spot + return 1; +} + +static int command_line_execute(VimState *state, int key) +{ + if (key == K_IGNORE || key == K_PASTE) { + return -1; // get another key + } + + CommandLineState *s = (CommandLineState *)state; + s->c = key; + + if (s->c == K_EVENT) { + queue_process_events(loop.events); + return 1; + } + + if (KeyTyped) { + s->some_key_typed = true; + if (cmd_hkmap) { + s->c = hkmap(s->c); } - // Ignore got_int when CTRL-C was typed here. - // Don't ignore it in :global, we really need to break then, e.g., for - // ":g/pat/normal /pat" (without the <CR>). - // Don't ignore it for the input() function. - if ((s->c == Ctrl_C) - && s->firstc != '@' - && !s->break_ctrl_c - && !global_busy) { - got_int = false; + if (cmd_fkmap) { + s->c = cmdl_fkmap(s->c); } - // free old command line when finished moving around in the history - // list - if (s->lookfor != NULL - && s->c != K_S_DOWN && s->c != K_S_UP - && s->c != K_DOWN && s->c != K_UP - && s->c != K_PAGEDOWN && s->c != K_PAGEUP - && s->c != K_KPAGEDOWN && s->c != K_KPAGEUP - && s->c != K_LEFT && s->c != K_RIGHT - && (s->xpc.xp_numfiles > 0 || (s->c != Ctrl_P && s->c != Ctrl_N))) { - xfree(s->lookfor); - s->lookfor = NULL; + if (cmdmsg_rl && !KeyStuffed) { + // Invert horizontal movements and operations. Only when + // typed by the user directly, not when the result of a + // mapping. + switch (s->c) { + case K_RIGHT: s->c = K_LEFT; break; + case K_S_RIGHT: s->c = K_S_LEFT; break; + case K_C_RIGHT: s->c = K_C_LEFT; break; + case K_LEFT: s->c = K_RIGHT; break; + case K_S_LEFT: s->c = K_S_RIGHT; break; + case K_C_LEFT: s->c = K_C_RIGHT; break; + } } + } - // When there are matching completions to select <S-Tab> works like - // CTRL-P (unless 'wc' is <S-Tab>). - if (s->c != p_wc && s->c == K_S_TAB && s->xpc.xp_numfiles > 0) { + // Ignore got_int when CTRL-C was typed here. + // Don't ignore it in :global, we really need to break then, e.g., for + // ":g/pat/normal /pat" (without the <CR>). + // Don't ignore it for the input() function. + if ((s->c == Ctrl_C) + && s->firstc != '@' + && !s->break_ctrl_c + && !global_busy) { + got_int = false; + } + + // free old command line when finished moving around in the history + // list + if (s->lookfor != NULL + && s->c != K_S_DOWN && s->c != K_S_UP + && s->c != K_DOWN && s->c != K_UP + && s->c != K_PAGEDOWN && s->c != K_PAGEUP + && s->c != K_KPAGEDOWN && s->c != K_KPAGEUP + && s->c != K_LEFT && s->c != K_RIGHT + && (s->xpc.xp_numfiles > 0 || (s->c != Ctrl_P && s->c != Ctrl_N))) { + xfree(s->lookfor); + s->lookfor = NULL; + } + + // When there are matching completions to select <S-Tab> works like + // CTRL-P (unless 'wc' is <S-Tab>). + if (s->c != p_wc && s->c == K_S_TAB && s->xpc.xp_numfiles > 0) { + s->c = Ctrl_P; + } + + // Special translations for 'wildmenu' + if (s->did_wild_list && p_wmnu) { + if (s->c == K_LEFT) { s->c = Ctrl_P; + } else if (s->c == K_RIGHT) { + s->c = Ctrl_N; } + } - // Special translations for 'wildmenu' - if (s->did_wild_list && p_wmnu) { - if (s->c == K_LEFT) { - s->c = Ctrl_P; - } else if (s->c == K_RIGHT) { - s->c = Ctrl_N; - } - } + // Hitting CR after "emenu Name.": complete submenu + if (s->xpc.xp_context == EXPAND_MENUNAMES && p_wmnu + && ccline.cmdpos > 1 + && ccline.cmdbuff[ccline.cmdpos - 1] == '.' + && ccline.cmdbuff[ccline.cmdpos - 2] != '\\' + && (s->c == '\n' || s->c == '\r' || s->c == K_KENTER)) { + s->c = K_DOWN; + } - // Hitting CR after "emenu Name.": complete submenu - if (s->xpc.xp_context == EXPAND_MENUNAMES && p_wmnu - && ccline.cmdpos > 1 - && ccline.cmdbuff[ccline.cmdpos - 1] == '.' - && ccline.cmdbuff[ccline.cmdpos - 2] != '\\' - && (s->c == '\n' || s->c == '\r' || s->c == K_KENTER)) { - s->c = K_DOWN; + // free expanded names when finished walking through matches + if (s->xpc.xp_numfiles != -1 + && !(s->c == p_wc && KeyTyped) && s->c != p_wcm + && s->c != Ctrl_N && s->c != Ctrl_P && s->c != Ctrl_A + && s->c != Ctrl_L) { + (void)ExpandOne(&s->xpc, NULL, NULL, 0, WILD_FREE); + s->did_wild_list = false; + if (!p_wmnu || (s->c != K_UP && s->c != K_DOWN)) { + s->xpc.xp_context = EXPAND_NOTHING; } + s->wim_index = 0; + if (p_wmnu && wild_menu_showing != 0) { + int skt = KeyTyped; + int old_RedrawingDisabled = RedrawingDisabled; - // free expanded names when finished walking through matches - if (s->xpc.xp_numfiles != -1 - && !(s->c == p_wc && KeyTyped) && s->c != p_wcm - && s->c != Ctrl_N && s->c != Ctrl_P && s->c != Ctrl_A - && s->c != Ctrl_L) { - (void)ExpandOne(&s->xpc, NULL, NULL, 0, WILD_FREE); - s->did_wild_list = false; - if (!p_wmnu || (s->c != K_UP && s->c != K_DOWN)) { - s->xpc.xp_context = EXPAND_NOTHING; + if (ccline.input_fn) { + RedrawingDisabled = 0; } - s->wim_index = 0; - if (p_wmnu && wild_menu_showing != 0) { - int skt = KeyTyped; - int old_RedrawingDisabled = RedrawingDisabled; - if (ccline.input_fn) { - RedrawingDisabled = 0; - } - - if (wild_menu_showing == WM_SCROLLED) { - // Entered command line, move it up - cmdline_row--; - redrawcmd(); - } else if (save_p_ls != -1) { - // restore 'laststatus' and 'winminheight' - 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; - } else { - win_redraw_last_status(topframe); - redraw_statuslines(); - } - KeyTyped = skt; - wild_menu_showing = 0; - if (ccline.input_fn) { - RedrawingDisabled = old_RedrawingDisabled; - } + if (wild_menu_showing == WM_SCROLLED) { + // Entered command line, move it up + cmdline_row--; + redrawcmd(); + } else if (save_p_ls != -1) { + // restore 'laststatus' and 'winminheight' + 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; + } else { + win_redraw_last_status(topframe); + redraw_statuslines(); + } + KeyTyped = skt; + wild_menu_showing = 0; + if (ccline.input_fn) { + RedrawingDisabled = old_RedrawingDisabled; } } + } - // Special translations for 'wildmenu' - if (s->xpc.xp_context == EXPAND_MENUNAMES && p_wmnu) { - // Hitting <Down> after "emenu Name.": complete submenu - if (s->c == K_DOWN && ccline.cmdpos > 0 - && ccline.cmdbuff[ccline.cmdpos - 1] == '.') { - s->c = p_wc; - } else if (s->c == K_UP) { - // Hitting <Up>: Remove one submenu name in front of the - // cursor - int found = false; + // Special translations for 'wildmenu' + if (s->xpc.xp_context == EXPAND_MENUNAMES && p_wmnu) { + // Hitting <Down> after "emenu Name.": complete submenu + if (s->c == K_DOWN && ccline.cmdpos > 0 + && ccline.cmdbuff[ccline.cmdpos - 1] == '.') { + s->c = p_wc; + } else if (s->c == K_UP) { + // Hitting <Up>: Remove one submenu name in front of the + // cursor + int found = false; + + s->j = (int)(s->xpc.xp_pattern - ccline.cmdbuff); + s->i = 0; + while (--s->j > 0) { + // check for start of menu name + if (ccline.cmdbuff[s->j] == ' ' + && ccline.cmdbuff[s->j - 1] != '\\') { + s->i = s->j + 1; + break; + } - s->j = (int)(s->xpc.xp_pattern - ccline.cmdbuff); - s->i = 0; - while (--s->j > 0) { - // check for start of menu name - if (ccline.cmdbuff[s->j] == ' ' - && ccline.cmdbuff[s->j - 1] != '\\') { + // check for start of submenu name + if (ccline.cmdbuff[s->j] == '.' + && ccline.cmdbuff[s->j - 1] != '\\') { + if (found) { s->i = s->j + 1; break; - } - - // check for start of submenu name - if (ccline.cmdbuff[s->j] == '.' - && ccline.cmdbuff[s->j - 1] != '\\') { - if (found) { - s->i = s->j + 1; - break; - } else { - found = true; - } + } else { + found = true; } } - if (s->i > 0) { - cmdline_del(s->i); - } - s->c = p_wc; - s->xpc.xp_context = EXPAND_NOTHING; } + if (s->i > 0) { + cmdline_del(s->i); + } + s->c = p_wc; + s->xpc.xp_context = EXPAND_NOTHING; } - if ((s->xpc.xp_context == EXPAND_FILES - || s->xpc.xp_context == EXPAND_DIRECTORIES - || s->xpc.xp_context == EXPAND_SHELLCMD) && p_wmnu) { - char_u upseg[5]; - - upseg[0] = PATHSEP; - upseg[1] = '.'; - upseg[2] = '.'; - upseg[3] = PATHSEP; - upseg[4] = NUL; - - if (s->c == K_DOWN - && ccline.cmdpos > 0 - && ccline.cmdbuff[ccline.cmdpos - 1] == PATHSEP - && (ccline.cmdpos < 3 - || ccline.cmdbuff[ccline.cmdpos - 2] != '.' - || ccline.cmdbuff[ccline.cmdpos - 3] != '.')) { - // go down a directory - s->c = p_wc; - } else if (STRNCMP(s->xpc.xp_pattern, upseg + 1, 3) == 0 - && s->c == K_DOWN) { - // If in a direct ancestor, strip off one ../ to go down - int found = false; - - s->j = ccline.cmdpos; - s->i = (int)(s->xpc.xp_pattern - ccline.cmdbuff); - while (--s->j > s->i) { - if (has_mbyte) { - s->j -= (*mb_head_off)(ccline.cmdbuff, ccline.cmdbuff + s->j); - } - if (vim_ispathsep(ccline.cmdbuff[s->j])) { - found = true; - break; - } + } + if ((s->xpc.xp_context == EXPAND_FILES + || s->xpc.xp_context == EXPAND_DIRECTORIES + || s->xpc.xp_context == EXPAND_SHELLCMD) && p_wmnu) { + char_u upseg[5]; + + upseg[0] = PATHSEP; + upseg[1] = '.'; + upseg[2] = '.'; + upseg[3] = PATHSEP; + upseg[4] = NUL; + + if (s->c == K_DOWN + && ccline.cmdpos > 0 + && ccline.cmdbuff[ccline.cmdpos - 1] == PATHSEP + && (ccline.cmdpos < 3 + || ccline.cmdbuff[ccline.cmdpos - 2] != '.' + || ccline.cmdbuff[ccline.cmdpos - 3] != '.')) { + // go down a directory + s->c = p_wc; + } else if (STRNCMP(s->xpc.xp_pattern, upseg + 1, 3) == 0 + && s->c == K_DOWN) { + // If in a direct ancestor, strip off one ../ to go down + int found = false; + + s->j = ccline.cmdpos; + s->i = (int)(s->xpc.xp_pattern - ccline.cmdbuff); + while (--s->j > s->i) { + if (has_mbyte) { + s->j -= (*mb_head_off)(ccline.cmdbuff, ccline.cmdbuff + s->j); } - if (found - && ccline.cmdbuff[s->j - 1] == '.' - && ccline.cmdbuff[s->j - 2] == '.' - && (vim_ispathsep(ccline.cmdbuff[s->j - 3]) || s->j == s->i + 2)) { - cmdline_del(s->j - 2); - s->c = p_wc; + if (vim_ispathsep(ccline.cmdbuff[s->j])) { + found = true; + break; } - } else if (s->c == K_UP) { - // go up a directory - int found = false; + } + if (found + && ccline.cmdbuff[s->j - 1] == '.' + && ccline.cmdbuff[s->j - 2] == '.' + && (vim_ispathsep(ccline.cmdbuff[s->j - 3]) || s->j == s->i + 2)) { + cmdline_del(s->j - 2); + s->c = p_wc; + } + } else if (s->c == K_UP) { + // go up a directory + int found = false; - s->j = ccline.cmdpos - 1; - s->i = (int)(s->xpc.xp_pattern - ccline.cmdbuff); - while (--s->j > s->i) { - if (has_mbyte) { - s->j -= (*mb_head_off)(ccline.cmdbuff, ccline.cmdbuff + s->j); - } - if (vim_ispathsep(ccline.cmdbuff[s->j]) + s->j = ccline.cmdpos - 1; + s->i = (int)(s->xpc.xp_pattern - ccline.cmdbuff); + while (--s->j > s->i) { + if (has_mbyte) { + s->j -= (*mb_head_off)(ccline.cmdbuff, ccline.cmdbuff + s->j); + } + if (vim_ispathsep(ccline.cmdbuff[s->j]) #ifdef BACKSLASH_IN_FILENAME - && vim_strchr(" *?[{`$%#", ccline.cmdbuff[j + 1]) - == NULL + && vim_strchr(" *?[{`$%#", ccline.cmdbuff[j + 1]) + == NULL #endif - ) { - if (found) { - s->i = s->j + 1; - break; - } else { - found = true; - } + ) { + if (found) { + s->i = s->j + 1; + break; + } else { + found = true; } } + } - if (!found) { - s->j = s->i; - } else if (STRNCMP(ccline.cmdbuff + s->j, upseg, 4) == 0) { - s->j += 4; - } else if (STRNCMP(ccline.cmdbuff + s->j, upseg + 1, 3) == 0 - && s->j == s->i) { - s->j += 3; - } else { - s->j = 0; - } - - if (s->j > 0) { - // TODO(tarruda): this is only for DOS/UNIX systems - need to put in - // machine-specific stuff here and in upseg init - cmdline_del(s->j); - put_on_cmdline(upseg + 1, 3, false); - } else if (ccline.cmdpos > s->i) { - cmdline_del(s->i); - } + if (!found) { + s->j = s->i; + } else if (STRNCMP(ccline.cmdbuff + s->j, upseg, 4) == 0) { + s->j += 4; + } else if (STRNCMP(ccline.cmdbuff + s->j, upseg + 1, 3) == 0 + && s->j == s->i) { + s->j += 3; + } else { + s->j = 0; + } - // Now complete in the new directory. Set KeyTyped in case the - // Up key came from a mapping. - s->c = p_wc; - KeyTyped = true; + if (s->j > 0) { + // TODO(tarruda): this is only for DOS/UNIX systems - need to put in + // machine-specific stuff here and in upseg init + cmdline_del(s->j); + put_on_cmdline(upseg + 1, 3, false); + } else if (ccline.cmdpos > s->i) { + cmdline_del(s->i); } + + // Now complete in the new directory. Set KeyTyped in case the + // Up key came from a mapping. + s->c = p_wc; + KeyTyped = true; } + } - // CTRL-\ CTRL-N goes to Normal mode, CTRL-\ CTRL-G goes to Insert - // mode when 'insertmode' is set, CTRL-\ e prompts for an expression. - if (s->c == Ctrl_BSL) { - ++no_mapping; - ++allow_keys; - s->c = plain_vgetc(); - --no_mapping; - --allow_keys; - // CTRL-\ e doesn't work when obtaining an expression, unless it - // is in a mapping. - if (s->c != Ctrl_N && s->c != Ctrl_G && (s->c != 'e' - || (ccline.cmdfirstc == '=' && - KeyTyped))) { - vungetc(s->c); - s->c = Ctrl_BSL; - } else if (s->c == 'e') { - char_u *p = NULL; - int len; - - // Replace the command line with the result of an expression. - // Need to save and restore the current command line, to be - // able to enter a new one... - if (ccline.cmdpos == ccline.cmdlen) { - new_cmdpos = 99999; // keep it at the end - } else { - new_cmdpos = ccline.cmdpos; - } + // CTRL-\ CTRL-N goes to Normal mode, CTRL-\ CTRL-G goes to Insert + // mode when 'insertmode' is set, CTRL-\ e prompts for an expression. + if (s->c == Ctrl_BSL) { + ++no_mapping; + ++allow_keys; + s->c = plain_vgetc(); + --no_mapping; + --allow_keys; + // CTRL-\ e doesn't work when obtaining an expression, unless it + // is in a mapping. + if (s->c != Ctrl_N && s->c != Ctrl_G && (s->c != 'e' + || (ccline.cmdfirstc == '=' && + KeyTyped))) { + vungetc(s->c); + s->c = Ctrl_BSL; + } else if (s->c == 'e') { + char_u *p = NULL; + int len; + + // Replace the command line with the result of an expression. + // Need to save and restore the current command line, to be + // able to enter a new one... + if (ccline.cmdpos == ccline.cmdlen) { + new_cmdpos = 99999; // keep it at the end + } else { + 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); - s->c = get_expr_register(); + ++textlock; + p = get_expr_line(); + --textlock; 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; - p = get_expr_line(); - --textlock; - restore_cmdline(&s->save_ccline); - - if (p != NULL) { - len = (int)STRLEN(p); - realloc_cmdbuff(len + 1); - ccline.cmdlen = len; - STRCPY(ccline.cmdbuff, p); - xfree(p); - - // Restore the cursor or use the position set with - // set_cmdline_pos(). - if (new_cmdpos > ccline.cmdlen) { - ccline.cmdpos = ccline.cmdlen; - } else { - ccline.cmdpos = new_cmdpos; - } - KeyTyped = false; // Don't do p_wc completion. - redrawcmd(); - goto cmdline_changed; + if (p != NULL) { + len = (int)STRLEN(p); + realloc_cmdbuff(len + 1); + ccline.cmdlen = len; + STRCPY(ccline.cmdbuff, p); + xfree(p); + + // Restore the cursor or use the position set with + // set_cmdline_pos(). + if (new_cmdpos > ccline.cmdlen) { + ccline.cmdpos = ccline.cmdlen; + } else { + ccline.cmdpos = new_cmdpos; } + + KeyTyped = false; // Don't do p_wc completion. + redrawcmd(); + goto cmdline_changed; } - beep_flush(); - got_int = false; // don't abandon the command line - did_emsg = false; - emsg_on_display = false; - redrawcmd(); - goto cmdline_not_changed; - } else { - if (s->c == Ctrl_G && p_im && restart_edit == 0) { - restart_edit = 'a'; - } - s->gotesc = true; // will free ccline.cmdbuff after putting it - // in history - goto returncmd; // back to Normal mode } + beep_flush(); + got_int = false; // don't abandon the command line + did_emsg = false; + emsg_on_display = false; + redrawcmd(); + goto cmdline_not_changed; + } else { + if (s->c == Ctrl_G && p_im && restart_edit == 0) { + restart_edit = 'a'; + } + s->gotesc = true; // will free ccline.cmdbuff after putting it + // in history + return 0; // back to Normal mode } + } - if (s->c == cedit_key || s->c == K_CMDWIN) { - if (ex_normal_busy == 0 && got_int == false) { - // Open a window to edit the command line (and history). - s->c = ex_window(); - s->some_key_typed = true; - } - } else { - s->c = do_digraph(s->c); + if (s->c == cedit_key || s->c == K_CMDWIN) { + if (ex_normal_busy == 0 && got_int == false) { + // Open a window to edit the command line (and history). + s->c = ex_window(); + s->some_key_typed = true; } + } else { + s->c = do_digraph(s->c); + } - if (s->c == '\n' - || s->c == '\r' - || s->c == K_KENTER - || (s->c == ESC - && (!KeyTyped || vim_strchr(p_cpo, CPO_ESC) != NULL))) { - // In Ex mode a backslash escapes a newline. - if (exmode_active - && s->c != ESC - && ccline.cmdpos == ccline.cmdlen - && ccline.cmdpos > 0 - && ccline.cmdbuff[ccline.cmdpos - 1] == '\\') { - if (s->c == K_KENTER) { - s->c = '\n'; - } - } else { - s->gotesc = false; // Might have typed ESC previously, don't - // truncate the cmdline now. - if (ccheck_abbr(s->c + ABBR_OFF)) { - goto cmdline_changed; - } + if (s->c == '\n' + || s->c == '\r' + || s->c == K_KENTER + || (s->c == ESC + && (!KeyTyped || vim_strchr(p_cpo, CPO_ESC) != NULL))) { + // In Ex mode a backslash escapes a newline. + if (exmode_active + && s->c != ESC + && ccline.cmdpos == ccline.cmdlen + && ccline.cmdpos > 0 + && ccline.cmdbuff[ccline.cmdpos - 1] == '\\') { + if (s->c == K_KENTER) { + s->c = '\n'; + } + } else { + s->gotesc = false; // Might have typed ESC previously, don't + // truncate the cmdline now. + if (ccheck_abbr(s->c + ABBR_OFF)) { + goto cmdline_changed; + } - if (!cmd_silent) { - ui_cursor_goto(msg_row, 0); - ui_flush(); - } - break; + if (!cmd_silent) { + ui_cursor_goto(msg_row, 0); + ui_flush(); } + return 0; } + } - // Completion for 'wildchar' or 'wildcharm' key. - // - hitting <ESC> twice means: abandon command line. - // - wildcard expansion is only done when the 'wildchar' key is really - // typed, not when it comes from a macro - if ((s->c == p_wc && !s->gotesc && KeyTyped) || s->c == p_wcm) { - 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)) { - (void)showmatches(&s->xpc, false); - redrawcmd(); - s->did_wild_list = true; - } - - if (wim_flags[s->wim_index] & WIM_LONGEST) { - s->res = nextwild(&s->xpc, WILD_LONGEST, WILD_NO_BEEP, - s->firstc != '@'); - } else if (wim_flags[s->wim_index] & WIM_FULL) { - s->res = nextwild(&s->xpc, WILD_NEXT, WILD_NO_BEEP, - s->firstc != '@'); - } else { - s->res = OK; // don't insert 'wildchar' now - } - } else { // typed p_wc first time - s->wim_index = 0; - s->j = ccline.cmdpos; - - // if 'wildmode' first contains "longest", get longest - // common part - if (wim_flags[0] & WIM_LONGEST) { - s->res = nextwild(&s->xpc, WILD_LONGEST, WILD_NO_BEEP, - s->firstc != '@'); - } else { - s->res = nextwild(&s->xpc, WILD_EXPAND_KEEP, WILD_NO_BEEP, - s->firstc != '@'); - } - - // if interrupted while completing, behave like it failed - if (got_int) { - (void)vpeekc(); // remove <C-C> from input stream - got_int = false; // don't abandon the command line - (void)ExpandOne(&s->xpc, NULL, NULL, 0, WILD_FREE); - s->xpc.xp_context = EXPAND_NOTHING; - goto cmdline_changed; - } - - // when more than one match, and 'wildmode' first contains - // "list", or no change and 'wildmode' contains "longest,list", - // list all matches - if (s->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 == s->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)) { - int p_wmnu_save = p_wmnu; - p_wmnu = 0; - // remove match - nextwild(&s->xpc, WILD_PREV, 0, s->firstc != '@'); - p_wmnu = p_wmnu_save; - } - - (void)showmatches(&s->xpc, p_wmnu - && ((wim_flags[s->wim_index] & WIM_LIST) == 0)); - redrawcmd(); - s->did_wild_list = true; - - if (wim_flags[s->wim_index] & WIM_LONGEST) { - nextwild(&s->xpc, WILD_LONGEST, WILD_NO_BEEP, - s->firstc != '@'); - } else if (wim_flags[s->wim_index] & WIM_FULL) { - nextwild(&s->xpc, WILD_NEXT, WILD_NO_BEEP, - s->firstc != '@'); - } - } else { - vim_beep(BO_WILD); - } - } else if (s->xpc.xp_numfiles == -1) { - s->xpc.xp_context = EXPAND_NOTHING; - } + // Completion for 'wildchar' or 'wildcharm' key. + // - hitting <ESC> twice means: abandon command line. + // - wildcard expansion is only done when the 'wildchar' key is really + // typed, not when it comes from a macro + if ((s->c == p_wc && !s->gotesc && KeyTyped) || s->c == p_wcm) { + 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)) { + (void)showmatches(&s->xpc, false); + redrawcmd(); + s->did_wild_list = true; } - if (s->wim_index < 3) { - ++s->wim_index; + if (wim_flags[s->wim_index] & WIM_LONGEST) { + s->res = nextwild(&s->xpc, WILD_LONGEST, WILD_NO_BEEP, + s->firstc != '@'); + } else if (wim_flags[s->wim_index] & WIM_FULL) { + s->res = nextwild(&s->xpc, WILD_NEXT, WILD_NO_BEEP, + s->firstc != '@'); + } else { + s->res = OK; // don't insert 'wildchar' now } + } else { // typed p_wc first time + s->wim_index = 0; + s->j = ccline.cmdpos; - if (s->c == ESC) { - s->gotesc = true; + // if 'wildmode' first contains "longest", get longest + // common part + if (wim_flags[0] & WIM_LONGEST) { + s->res = nextwild(&s->xpc, WILD_LONGEST, WILD_NO_BEEP, + s->firstc != '@'); + } else { + s->res = nextwild(&s->xpc, WILD_EXPAND_KEEP, WILD_NO_BEEP, + s->firstc != '@'); } - if (s->res == OK) { + // if interrupted while completing, behave like it failed + if (got_int) { + (void)vpeekc(); // remove <C-C> from input stream + got_int = false; // don't abandon the command line + (void)ExpandOne(&s->xpc, NULL, NULL, 0, WILD_FREE); + s->xpc.xp_context = EXPAND_NOTHING; goto cmdline_changed; } - } - s->gotesc = false; + // when more than one match, and 'wildmode' first contains + // "list", or no change and 'wildmode' contains "longest,list", + // list all matches + if (s->res == OK && s->xpc.xp_numfiles > 1) { + // a "longest" that didn't do anything is skipped (but not + // "list:longest") + if |