mirror of
https://github.com/neovim/neovim.git
synced 2024-12-31 17:13:26 -07:00
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:
parent
52d4978b03
commit
0701e1bfa4
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user