]> granicus.if.org Git - vim/commitdiff
patch 8.2.3389: cannot stop insert mode completion without side effects v8.2.3389
authorzeertzjq <zeertzjq@outlook.com>
Tue, 31 Aug 2021 17:12:51 +0000 (19:12 +0200)
committerBram Moolenaar <Bram@vim.org>
Tue, 31 Aug 2021 17:12:51 +0000 (19:12 +0200)
Problem:    Cannot stop insert mode completion without side effects.
Solution:   Add CTRL-X CTRL-Z. (closes #8821)

runtime/doc/index.txt
runtime/doc/insert.txt
src/insexpand.c
src/testdir/test_ins_complete.vim
src/version.c

index 683afe45de8c6ec37e3e88cc85e41998aef21dae..8c114a2411f791cddb45b15675aa393bee85c806 100644 (file)
@@ -168,6 +168,7 @@ commands in CTRL-X submode                          *i_CTRL-X_index*
 |i_CTRL-X_CTRL-Y|      CTRL-X CTRL-Y   scroll down
 |i_CTRL-X_CTRL-U|      CTRL-X CTRL-U   complete with 'completefunc'
 |i_CTRL-X_CTRL-V|      CTRL-X CTRL-V   complete like in : command line
+|i_CTRL-X_CTRL-Z|      CTRL-X CTRL-Z   stop completion, keeping the text as-is
 |i_CTRL-X_CTRL-]|      CTRL-X CTRL-]   complete tags
 |i_CTRL-X_s|           CTRL-X s        spelling suggestions
 
index 1caf08437fa1ce44f2025a2a7059db0ff85103f2..18b40f76fa0fd37d7ce03229cadb19f70c797c1b 100644 (file)
@@ -640,6 +640,8 @@ Completion can be done for:
 12. Spelling suggestions                               |i_CTRL-X_s|
 13. keywords in 'complete'                             |i_CTRL-N| |i_CTRL-P|
 
+Additionally, |i_CTRL-X_CTRL-Z| stops completion without changing the text.
+
 All these, except CTRL-N and CTRL-P, are done in CTRL-X mode.  This is a
 sub-mode of Insert and Replace modes.  You enter CTRL-X mode by typing CTRL-X
 and one of the CTRL-X commands.  You exit CTRL-X mode by typing a key that is
@@ -1042,6 +1044,12 @@ CTRL-P                   Find previous match for words that start with the
                        other contexts unless a double CTRL-X is used.
 
 
+Stop completion                                                *compl-stop*
+
+                                                       *i_CTRL-X_CTRL-Z*
+CTRL-X CTRL-Z          Stop completion without changing the text.
+
+
 FUNCTIONS FOR FINDING COMPLETIONS                      *complete-functions*
 
 This applies to 'completefunc' and 'omnifunc'.
index 4f8a6265175f192b4d95464cf9459416f8a21dd5..0e363f737544b1da22a2164851ca5b6c1145f4c5 100644 (file)
@@ -37,6 +37,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]
 
@@ -60,6 +61,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)"),
 };
 
 #if defined(FEAT_COMPL_FUNC) || defined(FEAT_EVAL)
@@ -80,7 +82,8 @@ static char *ctrl_x_mode_names[] = {
        "omni",
        "spell",
        NULL,               // CTRL_X_LOCAL_MSG only used in "ctrl_x_msgs"
-       "eval"
+       "eval",
+       "cmdline",
 };
 #endif
 
@@ -222,9 +225,7 @@ static int  spell_bad_len = 0;      // length of located bad word
     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 (!ctrl_x_mode_cmdline())
     {
        // if the next ^X<> won't ADD nothing, then reset
        // compl_cont_status
@@ -238,6 +239,10 @@ ins_ctrl_x(void)
        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;
 }
 
 /*
@@ -255,7 +260,9 @@ int ctrl_x_mode_path_defines(void) {
                                   return ctrl_x_mode == CTRL_X_PATH_DEFINES; }
 int ctrl_x_mode_dictionary(void) { return ctrl_x_mode == CTRL_X_DICTIONARY; }
 int ctrl_x_mode_thesaurus(void) { return ctrl_x_mode == CTRL_X_THESAURUS; }
-int ctrl_x_mode_cmdline(void) { return ctrl_x_mode == CTRL_X_CMDLINE; }
+int ctrl_x_mode_cmdline(void) {
+       return ctrl_x_mode == CTRL_X_CMDLINE
+               || ctrl_x_mode == CTRL_X_CMDLINE_CTRL_X; }
 int ctrl_x_mode_function(void) { return ctrl_x_mode == CTRL_X_FUNCTION; }
 int ctrl_x_mode_omni(void) { return ctrl_x_mode == CTRL_X_OMNI; }
 int ctrl_x_mode_spell(void) { return ctrl_x_mode == CTRL_X_SPELL; }
@@ -272,7 +279,8 @@ ctrl_x_mode_not_default(void)
 }
 
 /*
- * 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.
  */
     int
 ctrl_x_mode_not_defined_yet(void)
@@ -333,12 +341,14 @@ 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:
@@ -396,6 +406,7 @@ 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.
@@ -1860,6 +1871,29 @@ ins_compl_prep(int c)
     }
 #endif
 
+    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))
@@ -1933,6 +1967,12 @@ 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
@@ -2929,6 +2969,7 @@ 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)
index 1f2c7fe31b24848a8ec8f065f555b2c402aa8280..b0914d906792fed34bdea909bb05122ff6b37b6d 100644 (file)
@@ -730,6 +730,66 @@ func Test_complete_cmdline()
   call assert_equal('call getqflist(', getline(2))
   exe "normal oabcxyz(\<C-X>\<C-V>"
   call assert_equal('abcxyz(', getline(3))
+  com! -buffer TestCommand1 echo 'TestCommand1'
+  com! -buffer TestCommand2 echo 'TestCommand2'
+  write TestCommand1Test
+  write TestCommand2Test
+  " Test repeating <CTRL-X> <CTRL-V> and switching to another CTRL-X mode
+  exe "normal oT\<C-X>\<C-V>\<C-X>\<C-V>\<C-X>\<C-F>\<Esc>"
+  call assert_equal('TestCommand2Test', getline(4))
+  call delete('TestCommand1Test')
+  call delete('TestCommand2Test')
+  delcom TestCommand1
+  delcom TestCommand2
+  close!
+endfunc
+
+" Test for <CTRL-X> <CTRL-Z> stopping completion without changing the match
+func Test_complete_stop()
+  new
+  func Save_mode1()
+    let g:mode1 = mode(1)
+    return ''
+  endfunc
+  func Save_mode2()
+    let g:mode2 = mode(1)
+    return ''
+  endfunc
+  inoremap <F1> <C-R>=Save_mode1()<CR>
+  inoremap <F2> <C-R>=Save_mode2()<CR>
+  call setline(1, ['aaa bbb ccc '])
+  exe "normal A\<C-N>\<C-P>\<F1>\<C-X>\<C-Z>\<F2>\<Esc>"
+  call assert_equal('ic', g:mode1)
+  call assert_equal('i', g:mode2)
+  call assert_equal('aaa bbb ccc ', getline(1))
+  exe "normal A\<C-N>\<Down>\<F1>\<C-X>\<C-Z>\<F2>\<Esc>"
+  call assert_equal('ic', g:mode1)
+  call assert_equal('i', g:mode2)
+  call assert_equal('aaa bbb ccc aaa', getline(1))
+  set completeopt+=noselect
+  exe "normal A \<C-N>\<Down>\<Down>\<C-L>\<C-L>\<F1>\<C-X>\<C-Z>\<F2>\<Esc>"
+  call assert_equal('ic', g:mode1)
+  call assert_equal('i', g:mode2)
+  call assert_equal('aaa bbb ccc aaa bb', getline(1))
+  set completeopt&
+  exe "normal A d\<C-N>\<F1>\<C-X>\<C-Z>\<F2>\<Esc>"
+  call assert_equal('ic', g:mode1)
+  call assert_equal('i', g:mode2)
+  call assert_equal('aaa bbb ccc aaa bb d', getline(1))
+  com! -buffer TestCommand1 echo 'TestCommand1'
+  com! -buffer TestCommand2 echo 'TestCommand2'
+  exe "normal oT\<C-X>\<C-V>\<C-X>\<C-V>\<F1>\<C-X>\<C-Z>\<F2>\<Esc>"
+  call assert_equal('ic', g:mode1)
+  call assert_equal('i', g:mode2)
+  call assert_equal('TestCommand2', getline(2))
+  delcom TestCommand1
+  delcom TestCommand2
+  unlet g:mode1
+  unlet g:mode2
+  iunmap <F1>
+  iunmap <F2>
+  delfunc Save_mode1
+  delfunc Save_mode2
   close!
 endfunc
 
index 7aef272f62847a49ae1559e4bef6b9e76789acd1..fd854d526a2fb5fc623bca1dc3b415488d9c181e 100644 (file)
@@ -755,6 +755,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    3389,
 /**/
     3388,
 /**/