aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/edit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/edit.c')
-rw-r--r--src/nvim/edit.c58
1 files changed, 47 insertions, 11 deletions
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 8216987635..f39a6a281b 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -84,6 +84,7 @@
#define CTRL_X_SPELL 14
#define CTRL_X_LOCAL_MSG 15 ///< only used in "ctrl_x_msgs"
#define CTRL_X_EVAL 16 ///< for builtin function complete()
+#define CTRL_X_CMDLINE_CTRL_X 17 ///< CTRL-X typed in CTRL_X_CMDLINE
#define CTRL_X_MSG(i) ctrl_x_msgs[(i) & ~CTRL_X_WANT_IDENT]
#define CTRL_X_MODE_LINE_OR_EVAL(m) \
@@ -109,6 +110,7 @@ static char *ctrl_x_msgs[] =
N_(" Spelling suggestion (s^N^P)"),
N_(" Keyword Local completion (^N^P)"),
NULL, // CTRL_X_EVAL doesn't use msg.
+ N_(" Command-line completion (^V^N^P)"),
};
static char *ctrl_x_mode_names[] = {
@@ -128,7 +130,8 @@ static char *ctrl_x_mode_names[] = {
"omni",
"spell",
NULL, // CTRL_X_LOCAL_MSG only used in "ctrl_x_msgs"
- "eval"
+ "eval",
+ "cmdline",
};
static char e_hitend[] = N_("Hit end of paragraph");
@@ -762,7 +765,8 @@ static int insert_execute(VimState *state, int key)
s->c = do_digraph(s->c);
- if ((s->c == Ctrl_V || s->c == Ctrl_Q) && ctrl_x_mode == CTRL_X_CMDLINE) {
+ if ((s->c == Ctrl_V || s->c == Ctrl_Q)
+ && (ctrl_x_mode == CTRL_X_CMDLINE || ctrl_x_mode == CTRL_X_CMDLINE_CTRL_X)) {
insert_do_complete(s);
return 1;
}
@@ -2028,11 +2032,8 @@ static bool del_char_after_col(int limit_col)
*/
static void ins_ctrl_x(void)
{
- /* CTRL-X after CTRL-X CTRL-V doesn't do anything, so that CTRL-X
- * CTRL-V works like CTRL-N */
- if (ctrl_x_mode != CTRL_X_CMDLINE) {
- /* if the next ^X<> won't ADD nothing, then reset
- * compl_cont_status */
+ if (ctrl_x_mode != CTRL_X_CMDLINE && ctrl_x_mode != CTRL_X_CMDLINE_CTRL_X) {
+ // if the next ^X<> won't ADD nothing, then reset compl_cont_status
if (compl_cont_status & CONT_N_ADDS) {
compl_cont_status |= CONT_INTRPT;
} else {
@@ -2043,6 +2044,10 @@ static void ins_ctrl_x(void)
edit_submode = (char_u *)_(CTRL_X_MSG(ctrl_x_mode));
edit_submode_pre = NULL;
showmode();
+ } else {
+ // CTRL-X in CTRL-X CTRL-V mode behaves differently to make CTRL-X
+ // CTRL-V look like CTRL-N
+ ctrl_x_mode = CTRL_X_CMDLINE_CTRL_X;
}
}
@@ -2052,7 +2057,8 @@ bool ctrl_x_mode_not_default(void)
return ctrl_x_mode != CTRL_X_NORMAL;
}
-// Whether CTRL-X was typed without a following character.
+// Whether CTRL-X was typed without a following character,
+// not including when in CTRL-X CTRL-V mode.
bool ctrl_x_mode_not_defined_yet(void)
{
return ctrl_x_mode == CTRL_X_NOT_DEFINED_YET;
@@ -2104,12 +2110,14 @@ bool vim_is_ctrl_x_key(int c)
case 0: // Not in any CTRL-X mode
return c == Ctrl_N || c == Ctrl_P || c == Ctrl_X;
case CTRL_X_NOT_DEFINED_YET:
+ case CTRL_X_CMDLINE_CTRL_X:
return c == Ctrl_X || c == Ctrl_Y || c == Ctrl_E
|| c == Ctrl_L || c == Ctrl_F || c == Ctrl_RSB
|| c == Ctrl_I || c == Ctrl_D || c == Ctrl_P
|| c == Ctrl_N || c == Ctrl_T || c == Ctrl_V
|| c == Ctrl_Q || c == Ctrl_U || c == Ctrl_O
- || c == Ctrl_S || c == Ctrl_K || c == 's';
+ || c == Ctrl_S || c == Ctrl_K || c == 's'
+ || c == Ctrl_Z;
case CTRL_X_SCROLL:
return c == Ctrl_Y || c == Ctrl_E;
case CTRL_X_WHOLE_LINE:
@@ -2163,6 +2171,7 @@ static bool ins_compl_accept_char(int c)
return vim_isfilec(c) && !vim_ispathsep(c);
case CTRL_X_CMDLINE:
+ case CTRL_X_CMDLINE_CTRL_X:
case CTRL_X_OMNI:
// Command line and Omni completion can work with just about any
// printable character, but do stop at white space.
@@ -3567,6 +3576,26 @@ static bool ins_compl_prep(int c)
return retval;
}
+ if (ctrl_x_mode == CTRL_X_CMDLINE_CTRL_X && c != Ctrl_X) {
+ if (c == Ctrl_V || c == Ctrl_Q || c == Ctrl_Z || ins_compl_pum_key(c)
+ || !vim_is_ctrl_x_key(c)) {
+ // Not starting another completion mode.
+ ctrl_x_mode = CTRL_X_CMDLINE;
+
+ // CTRL-X CTRL-Z should stop completion without inserting anything
+ if (c == Ctrl_Z) {
+ retval = true;
+ }
+ } else {
+ ctrl_x_mode = CTRL_X_CMDLINE;
+
+ // Other CTRL-X keys first stop completion, then start another
+ // completion mode.
+ ins_compl_prep(' ');
+ ctrl_x_mode = CTRL_X_NOT_DEFINED_YET;
+ }
+ }
+
// Set "compl_get_longest" when finding the first matches.
if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET
|| (ctrl_x_mode == CTRL_X_NORMAL && !compl_started)) {
@@ -3633,6 +3662,12 @@ static bool ins_compl_prep(int c)
case Ctrl_Q:
ctrl_x_mode = CTRL_X_CMDLINE;
break;
+ case Ctrl_Z:
+ ctrl_x_mode = CTRL_X_NORMAL;
+ edit_submode = NULL;
+ showmode();
+ retval = true;
+ break;
case Ctrl_P:
case Ctrl_N:
/* ^X^P means LOCAL expansion if nothing interrupted (eg we
@@ -4292,10 +4327,11 @@ static int ins_compl_get_exp(pos_T *ini)
break;
case CTRL_X_CMDLINE:
+ case CTRL_X_CMDLINE_CTRL_X:
if (expand_cmdline(&compl_xp, compl_pattern,
(int)STRLEN(compl_pattern),
&num_matches, &matches) == EXPAND_OK) {
- ins_compl_add_matches(num_matches, matches, FALSE);
+ ins_compl_add_matches(num_matches, matches, false);
}
break;
@@ -5135,7 +5171,7 @@ static int ins_complete(int c, bool enable_pum)
compl_col += startcol;
compl_length = (int)curs_col - startcol;
compl_pattern = addstar(line + compl_col, compl_length, EXPAND_FILES);
- } else if (ctrl_x_mode == CTRL_X_CMDLINE) {
+ } else if (ctrl_x_mode == CTRL_X_CMDLINE || ctrl_x_mode == CTRL_X_CMDLINE_CTRL_X) {
compl_pattern = vim_strnsave(line, curs_col);
set_cmd_context(&compl_xp, compl_pattern,
(int)STRLEN(compl_pattern), curs_col, false);