Patch 8.2.3389
Problem:    Cannot stop insert mode completion without side effects.
Solution:   Add CTRL-X CTRL-Z. (closes #8821)
Files:      runtime/doc/index.txt, runtime/doc/insert.txt, src/insexpand.c,
            src/testdir/test_ins_complete.vim


*** ../vim-8.2.3388/runtime/doc/index.txt       2021-06-10 19:39:07.273697695 
+0200
--- runtime/doc/index.txt       2021-08-31 19:05:25.366528171 +0200
***************
*** 168,173 ****
--- 168,174 ----
  |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
  
*** ../vim-8.2.3388/runtime/doc/insert.txt      2021-01-31 17:02:06.254490174 
+0100
--- runtime/doc/insert.txt      2021-08-31 19:06:08.002398301 +0200
***************
*** 640,645 ****
--- 640,647 ----
  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,1047 ****
--- 1044,1055 ----
                        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'.
*** ../vim-8.2.3388/src/insexpand.c     2021-08-05 16:23:05.482890089 +0200
--- src/insexpand.c     2021-08-31 19:10:57.721764812 +0200
***************
*** 37,42 ****
--- 37,43 ----
  # 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,65 ****
--- 61,67 ----
      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,86 ****
        "omni",
        "spell",
        NULL,               // CTRL_X_LOCAL_MSG only used in "ctrl_x_msgs"
!       "eval"
  };
  #endif
  
--- 82,89 ----
        "omni",
        "spell",
        NULL,               // CTRL_X_LOCAL_MSG only used in "ctrl_x_msgs"
!       "eval",
!       "cmdline",
  };
  #endif
  
***************
*** 222,230 ****
      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
--- 225,231 ----
      void
  ins_ctrl_x(void)
  {
!     if (!ctrl_x_mode_cmdline())
      {
        // if the next ^X<> won't ADD nothing, then reset
        // compl_cont_status
***************
*** 238,243 ****
--- 239,248 ----
        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,261 ****
                                   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_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; }
--- 260,268 ----
                                   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
!               || 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,278 ****
  }
  
  /*
!  * Whether CTRL-X was typed without a following character.
   */
      int
  ctrl_x_mode_not_defined_yet(void)
--- 279,286 ----
  }
  
  /*
!  * 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,344 ****
        case 0:             // Not in any CTRL-X mode
            return (c == Ctrl_N || c == Ctrl_P || c == Ctrl_X);
        case CTRL_X_NOT_DEFINED_YET:
            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');
        case CTRL_X_SCROLL:
            return (c == Ctrl_Y || c == Ctrl_E);
        case CTRL_X_WHOLE_LINE:
--- 341,354 ----
        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_Z);
        case CTRL_X_SCROLL:
            return (c == Ctrl_Y || c == Ctrl_E);
        case CTRL_X_WHOLE_LINE:
***************
*** 396,401 ****
--- 406,412 ----
            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,1865 ****
--- 1871,1899 ----
      }
  #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,1938 ****
--- 1967,1978 ----
            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,2934 ****
--- 2969,2975 ----
            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)
*** ../vim-8.2.3388/src/testdir/test_ins_complete.vim   2021-07-25 
20:27:03.223912393 +0200
--- src/testdir/test_ins_complete.vim   2021-08-31 18:58:12.079869338 +0200
***************
*** 730,735 ****
--- 730,795 ----
    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
  
*** ../vim-8.2.3388/src/version.c       2021-08-30 21:26:12.860831195 +0200
--- src/version.c       2021-08-31 18:59:39.959593224 +0200
***************
*** 757,758 ****
--- 757,760 ----
  {   /* Add new patch number below this line */
+ /**/
+     3389,
  /**/

-- 
BEDEVERE: Wait.  Wait ... tell me, what also floats on water?
ALL:      Bread?  No, no, no.  Apples .... gravy ... very small rocks ...
ARTHUR:   A duck.
                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/202108311713.17VHDPeZ3930617%40masaka.moolenaar.net.

Raspunde prin e-mail lui