]> granicus.if.org Git - vim/commitdiff
patch 8.2.3520: cannot define a function for thesaurus completion v8.2.3520
authorYegappan Lakshmanan <yegappan@yahoo.com>
Sat, 16 Oct 2021 14:41:29 +0000 (15:41 +0100)
committerBram Moolenaar <Bram@vim.org>
Sat, 16 Oct 2021 14:41:29 +0000 (15:41 +0100)
Problem:    Cannot define a function for thesaurus completion.
Solution:   Add 'thesaurusfunc'. (Yegappan Lakshmanan, closes #8987,
            closes 8950)

12 files changed:
runtime/doc/insert.txt
runtime/doc/options.txt
runtime/doc/quickref.txt
src/buffer.c
src/insexpand.c
src/option.c
src/option.h
src/optiondefs.h
src/optionstr.c
src/structs.h
src/testdir/test_edit.vim
src/version.c

index 31b820f7b1792660b220c5847303f4878823c621..8d47a7e962b4bae9bb7e973b1d6dc527d4e0a024 100644 (file)
@@ -842,6 +842,12 @@ CTRL-X CTRL-T              Works as CTRL-X CTRL-K, but in a special way.  It uses
                        Other uses include translation between two languages,
                        or grouping API functions by keyword.
 
+                       If the 'thesaurusfunc' option is set, then the user
+                       specified function is invoked to get the list of
+                       completion matches and the 'thesaurus' option is not
+                       used. See |complete-functions| for an explanation of
+                       how the function is invoked and what it should return.
+
        CTRL-T  or
        CTRL-N          Search forward for next matching keyword.  This
                        keyword replaces the previous matching keyword.
@@ -1052,7 +1058,7 @@ CTRL-X CTRL-Z             Stop completion without changing the text.
 
 FUNCTIONS FOR FINDING COMPLETIONS                      *complete-functions*
 
-This applies to 'completefunc' and 'omnifunc'.
+This applies to 'completefunc', 'thesaurusfunc' and 'omnifunc'.
 
 The function is called in two different ways:
 - First the function is called to find the start of the text to be completed.
index 41d710529e65d9292af476f4a420dee199434009..67504795b6abb9c73004d607a1a040a6a87f1494 100644 (file)
@@ -8028,6 +8028,18 @@ A jump table for the options with a short description can be found at |Q_op|.
        uses another default.
        Backticks cannot be used in this option for security reasons.
 
+                                               *'thesaurusfunc'* *tsrfu'*
+'thesaurusfunc' 'tsrfu'        string  (default: empty)
+                       local to buffer
+                       {not available when compiled without the |+eval|
+                       feature}
+       This option specifies a function to be used for thesaurus completion
+       with CTRL-X CTRL-T. |i_CTRL-X_CTRL-T|
+       See |complete-functions| for an explanation of how the function is
+       invoked and what it should return.
+       This option cannot be set from a |modeline| or in the |sandbox|, for
+       security reasons.
+
                             *'tildeop'* *'top'* *'notildeop'* *'notop'*
 'tildeop' 'top'                boolean (default off)
                        global
index fcdd5a7fe25fe54f8a2608401e74de4e06eef706..f7c5c1789e7132d49204f54b58bf1d860278c999 100644 (file)
@@ -948,6 +948,7 @@ Short explanation of each option:           *option-list*
 'textmode'       'tx'      obsolete, use 'fileformat'
 'textwidth'      'tw'      maximum width of text that is being inserted
 'thesaurus'      'tsr'     list of thesaurus files for keyword completion
+'thesaurusfunc'          'tsrfu'   function to be used for thesaurus completion
 'tildeop'        'top'     tilde command "~" behaves like an operator
 'timeout'        'to'      time out on mappings and key codes
 'timeoutlen'     'tm'      time out time in milliseconds
index 86dc88687a596334b02732d61c2de80276b9cf0a..ba20a611d1aba464b1b4f0f9195f4322f0126891 100644 (file)
@@ -2364,6 +2364,7 @@ free_buf_options(
 #ifdef FEAT_COMPL_FUNC
     clear_string_option(&buf->b_p_cfu);
     clear_string_option(&buf->b_p_ofu);
+    clear_string_option(&buf->b_p_thsfu);
 #endif
 #ifdef FEAT_QUICKFIX
     clear_string_option(&buf->b_p_gp);
index ee8263c8b8f29b7e9d5bc362cc0b6419432860ac..624146a3f1b22057ebc096ff504214ef175cfffb 100644 (file)
@@ -299,7 +299,11 @@ has_compl_option(int dict_opt)
                                                        && !curwin->w_p_spell
 #endif
                                                        )
-                : (*curbuf->b_p_tsr == NUL && *p_tsr == NUL))
+                : (*curbuf->b_p_tsr == NUL && *p_tsr == NUL
+#ifdef FEAT_COMPL_FUNC
+                    && *curbuf->b_p_thsfu == NUL
+#endif
+                  ))
     {
        ctrl_x_mode = CTRL_X_NORMAL;
        edit_submode = NULL;
@@ -2229,6 +2233,25 @@ ins_compl_next_buf(buf_T *buf, int flag)
 }
 
 #ifdef FEAT_COMPL_FUNC
+/*
+ * Get the user-defined completion function name for completion 'type'
+ */
+    static char_u *
+get_complete_funcname(int type)
+{
+    switch (type)
+    {
+       case CTRL_X_FUNCTION:
+           return curbuf->b_p_cfu;
+       case CTRL_X_OMNI:
+           return curbuf->b_p_ofu;
+       case CTRL_X_THESAURUS:
+           return curbuf->b_p_thsfu;
+       default:
+           return (char_u *)"";
+    }
+}
+
 /*
  * Execute user defined complete function 'completefunc' or 'omnifunc', and
  * get matches in "matches".
@@ -2246,7 +2269,7 @@ expand_by_function(
     typval_T   rettv;
     int                save_State = State;
 
-    funcname = (type == CTRL_X_FUNCTION) ? curbuf->b_p_cfu : curbuf->b_p_ofu;
+    funcname = get_complete_funcname(type);
     if (*funcname == NUL)
        return;
 
@@ -2720,6 +2743,21 @@ f_complete_info(typval_T *argvars, typval_T *rettv)
 }
 #endif
 
+/*
+ * Returns TRUE when using a user-defined function for thesaurus completion.
+ */
+    static int
+thesaurus_func_complete(int type UNUSED)
+{
+#ifdef FEAT_COMPL_FUNC
+    return (type == CTRL_X_THESAURUS
+               && curbuf->b_p_thsfu != NULL
+               && *curbuf->b_p_thsfu != NUL);
+#else
+    return FALSE;
+#endif
+}
+
 /*
  * Get the next expansion(s), using "compl_pattern".
  * The search starts at position "ini" in curbuf and in the direction
@@ -2906,7 +2944,12 @@ ins_compl_get_exp(pos_T *ini)
 
        case CTRL_X_DICTIONARY:
        case CTRL_X_THESAURUS:
-           ins_compl_dictionaries(
+#ifdef FEAT_COMPL_FUNC
+           if (thesaurus_func_complete(type))
+               expand_by_function(type, compl_pattern);
+           else
+#endif
+               ins_compl_dictionaries(
                    dict != NULL ? dict
                         : (type == CTRL_X_THESAURUS
                             ? (*curbuf->b_p_tsr == NUL
@@ -3760,7 +3803,9 @@ ins_complete(int c, int enable_pum)
        }
 
        // Work out completion pattern and original text -- webb
-       if (ctrl_x_mode == CTRL_X_NORMAL || (ctrl_x_mode & CTRL_X_WANT_IDENT))
+       if (ctrl_x_mode == CTRL_X_NORMAL
+               || (ctrl_x_mode & CTRL_X_WANT_IDENT
+                   && !thesaurus_func_complete(ctrl_x_mode)))
        {
            if ((compl_cont_status & CONT_SOL)
                    || ctrl_x_mode == CTRL_X_PATH_DEFINES)
@@ -3910,7 +3955,8 @@ ins_complete(int c, int enable_pum)
                compl_col = (int)(compl_xp.xp_pattern - compl_pattern);
            compl_length = curs_col - compl_col;
        }
-       else if (ctrl_x_mode == CTRL_X_FUNCTION || ctrl_x_mode == CTRL_X_OMNI)
+       else if (ctrl_x_mode == CTRL_X_FUNCTION || ctrl_x_mode == CTRL_X_OMNI
+               || thesaurus_func_complete(ctrl_x_mode))
        {
 #ifdef FEAT_COMPL_FUNC
            // Call user defined function 'completefunc' with "a:findstart"
@@ -3923,8 +3969,7 @@ ins_complete(int c, int enable_pum)
 
            // Call 'completefunc' or 'omnifunc' and get pattern length as a
            // string
-           funcname = ctrl_x_mode == CTRL_X_FUNCTION
-                                         ? curbuf->b_p_cfu : curbuf->b_p_ofu;
+           funcname = get_complete_funcname(ctrl_x_mode);
            if (*funcname == NUL)
            {
                semsg(_(e_notset), ctrl_x_mode == CTRL_X_FUNCTION
index fe5ff4367c3600fc046477944811a594797cf4d2..385126eb3d676e0f16ef790f828231e410a8bda2 100644 (file)
@@ -5433,6 +5433,7 @@ get_varp(struct vimoption *p)
 #ifdef FEAT_COMPL_FUNC
        case PV_CFU:    return (char_u *)&(curbuf->b_p_cfu);
        case PV_OFU:    return (char_u *)&(curbuf->b_p_ofu);
+       case PV_THSFU:  return (char_u *)&(curbuf->b_p_thsfu);
 #endif
 #ifdef FEAT_EVAL
        case PV_TFU:    return (char_u *)&(curbuf->b_p_tfu);
@@ -5935,6 +5936,8 @@ buf_copy_options(buf_T *buf, int flags)
            COPY_OPT_SCTX(buf, BV_CFU);
            buf->b_p_ofu = vim_strsave(p_ofu);
            COPY_OPT_SCTX(buf, BV_OFU);
+           buf->b_p_thsfu = vim_strsave(p_thsfu);
+           COPY_OPT_SCTX(buf, BV_THSFU);
 #endif
 #ifdef FEAT_EVAL
            buf->b_p_tfu = vim_strsave(p_tfu);
index 48a3ec34b282b1be81aea5470b41ec261189f253..75c83d56d96dfcf6f8e608c176e0d7ac25e7c6c1 100644 (file)
@@ -404,6 +404,7 @@ EXTERN char_u       *p_cinw;        // 'cinwords'
 #ifdef FEAT_COMPL_FUNC
 EXTERN char_u  *p_cfu;         // 'completefunc'
 EXTERN char_u  *p_ofu;         // 'omnifunc'
+EXTERN char_u  *p_thsfu;       // 'thesaurusfunc'
 #endif
 EXTERN int     p_ci;           // 'copyindent'
 #if defined(FEAT_GUI) && defined(MACOS_X)
@@ -1217,6 +1218,9 @@ enum
 #endif
     , BV_TAGS
     , BV_TC
+#ifdef FEAT_COMPL_FUNC
+    , BV_THSFU
+#endif
     , BV_TS
     , BV_TW
     , BV_TX
index ec89558f15696e0662a18e2b19848413113f0922..a7a3d0c9008291a64d26590fa2868d557d26f002 100644 (file)
 #ifdef FEAT_EVAL
 # define PV_TFU                OPT_BUF(BV_TFU)
 #endif
+#ifdef FEAT_COMPL_FUNC
+# define PV_THSFU              OPT_BUF(BV_THSFU)
+#endif
 #define PV_TAGS                OPT_BOTH(OPT_BUF(BV_TAGS))
 #define PV_TC          OPT_BOTH(OPT_BUF(BV_TC))
 #define PV_TS          OPT_BUF(BV_TS)
@@ -2616,6 +2619,15 @@ static struct vimoption options[] =
     {"thesaurus",   "tsr",  P_STRING|P_EXPAND|P_VI_DEF|P_ONECOMMA|P_NODUP|P_NDNAME,
                            (char_u *)&p_tsr, PV_TSR,
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
+    {"thesaurusfunc", "tsrfu",  P_STRING|P_ALLOCED|P_VI_DEF|P_SECURE,
+#ifdef FEAT_COMPL_FUNC
+                           (char_u *)&p_thsfu, PV_THSFU,
+                           {(char_u *)"", (char_u *)0L}
+#else
+                           (char_u *)NULL, PV_NONE,
+                           {(char_u *)0L, (char_u *)0L}
+#endif
+                           SCTX_INIT},
     {"tildeop",            "top",  P_BOOL|P_VI_DEF|P_VIM,
                            (char_u *)&p_to, PV_NONE,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
index ff1321881a06bec4cf2ebd4e4e35b5216a300cac..06a633b0fcce1560709f8f0282c7c87acc23de52 100644 (file)
@@ -271,6 +271,7 @@ check_buf_options(buf_T *buf)
 #ifdef FEAT_COMPL_FUNC
     check_string_option(&buf->b_p_cfu);
     check_string_option(&buf->b_p_ofu);
+    check_string_option(&buf->b_p_thsfu);
 #endif
 #ifdef FEAT_EVAL
     check_string_option(&buf->b_p_tfu);
index 83a13a76514410f9945fff5533a56c8e337391e8..021206e1ee6b836b132fe86099081e88074598f7 100644 (file)
@@ -2864,6 +2864,7 @@ struct file_buffer
 #ifdef FEAT_COMPL_FUNC
     char_u     *b_p_cfu;       // 'completefunc'
     char_u     *b_p_ofu;       // 'omnifunc'
+    char_u     *b_p_thsfu;     // 'thesaurusfunc'
 #endif
 #ifdef FEAT_EVAL
     char_u     *b_p_tfu;       // 'tagfunc'
index 6561edc5cd14bd259673ee1163b1b10518115955..2cce85ca395cfec0ddd13b8e52e6131cee58febb 100644 (file)
@@ -890,6 +890,48 @@ func Test_edit_CTRL_T()
   bw!
 endfunc
 
+" Test 'thesaurusfunc'
+func MyThesaurus(findstart, base)
+  let mythesaurus = [
+        \ #{word: "happy",
+        \   synonyms: "cheerful,blissful,flying high,looking good,peppy"},
+        \ #{word: "kind",
+        \   synonyms: "amiable,bleeding-heart,heart in right place"}]
+  if a:findstart
+    " locate the start of the word
+    let line = getline('.')
+    let start = col('.') - 1
+    while start > 0 && line[start - 1] =~ '\a'
+      let start -= 1
+    endwhile
+    return start
+  else
+    " find strings matching with "a:base"
+    let res = []
+    for w in mythesaurus
+      if w.word =~ '^' . a:base
+        call add(res, w.word)
+        call extend(res, split(w.synonyms, ","))
+      endif
+    endfor
+    return res
+  endif
+endfunc
+
+func Test_thesaurus_func()
+  new
+  set thesaurus=
+  set thesaurusfunc=MyThesaurus
+  call setline(1, "an ki")
+  call cursor(1, 1)
+  call feedkeys("A\<c-x>\<c-t>\<c-n>\<cr>\<esc>", 'tnix')
+  call assert_equal(['an amiable', ''], getline(1, '$'))
+  set thesaurusfunc=NonExistingFunc
+  call assert_fails("normal $a\<C-X>\<C-T>", 'E117:')
+  set thesaurusfunc&
+  %bw!
+endfunc
+
 func Test_edit_CTRL_U()
   " Test 'completefunc'
   new
index c5e9f258dfab6d4341a83860308b842bf9183830..00617b5c9ff9782febd8ceb8359af04b6cb55794 100644 (file)
@@ -757,6 +757,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    3520,
 /**/
     3519,
 /**/