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_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 */
static uint8_t *command_line_enter(int firstc, long count, int indent)
/*
* 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
)
{ {
CommandLineState state, *s = &state; CommandLineState state, *s = &state;
memset(s, 0, sizeof(CommandLineState)); memset(s, 0, sizeof(CommandLineState));
@ -298,27 +273,100 @@ getcmdline (
did_emsg = false; did_emsg = false;
got_int = 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. cmdmsg_rl = false;
for (;;) {
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. redir_off = true; // Don't redirect the typed command.
// Repeated, because a ":redir" inside // Repeated, because a ":redir" inside
// completion may switch it on. // completion may switch it on.
quit_more = false; // reset after CTRL-D which had a more-prompt quit_more = false; // reset after CTRL-D which had a more-prompt
cursorcmd(); // set the cursor on the right spot cursorcmd(); // set the cursor on the right spot
return 1;
}
// Get a character. Ignore K_IGNORE, it should not do anything, such static int command_line_execute(VimState *state, int key)
// as stop completion. {
input_enable_events(); if (key == K_IGNORE || key == K_PASTE) {
do { return -1; // get another key
s->c = safe_vgetc(); }
} while (s->c == K_IGNORE || s->c == K_PASTE);
input_disable_events(); CommandLineState *s = (CommandLineState *)state;
s->c = key;
if (s->c == K_EVENT) { if (s->c == K_EVENT) {
queue_process_events(loop.events); queue_process_events(loop.events);
continue; return 1;
} }
if (KeyTyped) { if (KeyTyped) {
@ -645,7 +693,7 @@ getcmdline (
} }
s->gotesc = true; // will free ccline.cmdbuff after putting it s->gotesc = true; // will free ccline.cmdbuff after putting it
// in history // 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_cursor_goto(msg_row, 0);
ui_flush(); ui_flush();
} }
break; return 0;
} }
} }
@ -894,7 +942,7 @@ getcmdline (
msg_putchar(' '); // delete ':' msg_putchar(' '); // delete ':'
} }
redraw_cmdline = true; redraw_cmdline = true;
goto returncmd; // back to cmd mode return 0; // back to cmd mode
} }
goto cmdline_changed; goto cmdline_changed;
@ -962,7 +1010,7 @@ getcmdline (
s->gotesc = true; // will free ccline.cmdbuff after s->gotesc = true; // will free ccline.cmdbuff after
// putting it in history // putting it in history
goto returncmd; // back to cmd mode return 0; // back to cmd mode
case Ctrl_R: // insert register case Ctrl_R: // insert register
putcmdline('"', true); putcmdline('"', true);
@ -999,7 +1047,7 @@ getcmdline (
if (aborting()) { if (aborting()) {
s->gotesc = true; // will free ccline.cmdbuff after s->gotesc = true; // will free ccline.cmdbuff after
// putting it in history // putting it in history
goto returncmd; // back to cmd mode return 0; // back to cmd mode
} }
KeyTyped = false; // Don't do p_wc completion. KeyTyped = false; // Don't do p_wc completion.
if (new_cmdpos >= 0) { if (new_cmdpos >= 0) {
@ -1020,7 +1068,7 @@ getcmdline (
} }
redrawcmd(); redrawcmd();
continue; // don't do incremental search now return 1; // don't do incremental search now
case K_RIGHT: case K_RIGHT:
case K_S_RIGHT: case K_S_RIGHT:
@ -1439,7 +1487,7 @@ getcmdline (
// (Sorry for the goto's, I know it is ugly). // (Sorry for the goto's, I know it is ugly).
cmdline_not_changed: cmdline_not_changed:
if (!s->incsearch_postponed) { if (!s->incsearch_postponed) {
continue; return 1;
} }
cmdline_changed: cmdline_changed:
@ -1451,7 +1499,7 @@ cmdline_changed:
// if there is a character waiting, search and redraw later // if there is a character waiting, search and redraw later
if (char_avail()) { if (char_avail()) {
s->incsearch_postponed = true; s->incsearch_postponed = true;
continue; return 1;
} }
s->incsearch_postponed = false; s->incsearch_postponed = false;
curwin->w_cursor = s->old_cursor; // start at old position curwin->w_cursor = s->old_cursor; // start at old position
@ -1543,75 +1591,37 @@ cmdline_changed:
redrawcmd(); redrawcmd();
} }
} }
return 1;
} }
returncmd: /*
* getcmdline() - accept a command line starting with firstc.
cmdmsg_rl = false; *
* firstc == ':' get ":" command line.
cmd_fkmap = 0; * firstc == '/' or '?' get search pattern
* firstc == '=' get expression
ExpandCleanup(&s->xpc); * firstc == '@' get text for input() function
ccline.xpc = NULL; * firstc == '>' get text for debug mode
* firstc == NUL get text for :insert command
if (s->did_incsearch) { * firstc == -1 like NUL, and break on CTRL-C
curwin->w_cursor = s->old_cursor; *
curwin->w_curswant = s->old_curswant; * The line is collected in ccline.cmdbuff, which is reallocated to fit the
curwin->w_leftcol = s->old_leftcol; * command line.
curwin->w_topline = s->old_topline; *
curwin->w_topfill = s->old_topfill; * Careful: getcmdline() can be called recursively!
curwin->w_botline = s->old_botline; *
highlight_match = false; * Return pointer to allocated string if there is a commandline, NULL
validate_cursor(); // needed for TAB * otherwise.
redraw_later(SOME_VALID); */
} char_u *
getcmdline (
if (ccline.cmdbuff != NULL) { int firstc,
// Put line in history buffer (":" and "=" only when it was typed). long count, // only used for incremental search
if (ccline.cmdlen && s->firstc != NUL int indent // indent for inside conditionals
&& (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; return command_line_enter(firstc, count, indent);
// Make ccline empty, getcmdline() may try to use it.
ccline.cmdbuff = NULL;
return p;
}
} }
/* /*