ex_getln: refactor command line mode to use the state_enter loop

Split `getcmdline()` into command_line_{enter,check,execute}`
This commit is contained in:
Thiago de Arruda 2015-10-23 08:22:16 -03:00
parent 52d4978b03
commit 0701e1bfa4

View File

@ -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,27 +273,100 @@ 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 (;;) {
cmdmsg_rl = false;
cmd_fkmap = 0;
ExpandCleanup(&s->xpc);
ccline.xpc = NULL;
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 (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 (s->gotesc) { // abandon command line
xfree(ccline.cmdbuff);
ccline.cmdbuff = NULL;
if (msg_scrolled == 0) {
compute_cmdrow();
}
MSG("");
redraw_cmdline = true;
}
}
// 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;
}
// 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();
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);
continue;
return 1;
}
if (KeyTyped) {
@ -645,7 +693,7 @@ getcmdline (
}
s->gotesc = true; // will free ccline.cmdbuff after putting it
// in history
goto returncmd; // back to Normal mode
return 0; // back to Normal mode
}
}
@ -684,7 +732,7 @@ getcmdline (
ui_cursor_goto(msg_row, 0);
ui_flush();
}
break;
return 0;
}
}
@ -894,7 +942,7 @@ getcmdline (
msg_putchar(' '); // delete ':'
}
redraw_cmdline = true;
goto returncmd; // back to cmd mode
return 0; // back to cmd mode
}
goto cmdline_changed;
@ -962,7 +1010,7 @@ getcmdline (
s->gotesc = true; // will free ccline.cmdbuff after
// putting it in history
goto returncmd; // back to cmd mode
return 0; // back to cmd mode
case Ctrl_R: // insert register
putcmdline('"', true);
@ -999,7 +1047,7 @@ getcmdline (
if (aborting()) {
s->gotesc = true; // will free ccline.cmdbuff after
// putting it in history
goto returncmd; // back to cmd mode
return 0; // back to cmd mode
}
KeyTyped = false; // Don't do p_wc completion.
if (new_cmdpos >= 0) {
@ -1020,7 +1068,7 @@ getcmdline (
}
redrawcmd();
continue; // don't do incremental search now
return 1; // don't do incremental search now
case K_RIGHT:
case K_S_RIGHT:
@ -1439,7 +1487,7 @@ getcmdline (
// (Sorry for the goto's, I know it is ugly).
cmdline_not_changed:
if (!s->incsearch_postponed) {
continue;
return 1;
}
cmdline_changed:
@ -1451,7 +1499,7 @@ cmdline_changed:
// if there is a character waiting, search and redraw later
if (char_avail()) {
s->incsearch_postponed = true;
continue;
return 1;
}
s->incsearch_postponed = false;
curwin->w_cursor = s->old_cursor; // start at old position
@ -1543,75 +1591,37 @@ cmdline_changed:
redrawcmd();
}
}
}
returncmd:
return 1;
}
cmdmsg_rl = false;
cmd_fkmap = 0;
ExpandCleanup(&s->xpc);
ccline.xpc = NULL;
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 (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 (s->gotesc) { // abandon command line
xfree(ccline.cmdbuff);
ccline.cmdbuff = NULL;
if (msg_scrolled == 0) {
compute_cmdrow();
}
MSG("");
redraw_cmdline = true;
}
}
// 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;
}
/*
* 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
)
{
return command_line_enter(firstc, count, indent);
}
/*