summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYegappan Lakshmanan <yegappan@yahoo.com>2021-10-16 15:41:29 +0100
committerBram Moolenaar <Bram@vim.org>2021-10-16 15:41:29 +0100
commit160e994d768d03a3c826b58115cde94df8fce607 (patch)
tree38f6ec253633b656db1be92790c26fc71eb72eee
parent2286304cdbba53ceb52b3ba2ba4a521b0a2f8d0f (diff)
downloadvim-git-160e994d768d03a3c826b58115cde94df8fce607.tar.gz
patch 8.2.3520: cannot define a function for thesaurus completionv8.2.3520
Problem: Cannot define a function for thesaurus completion. Solution: Add 'thesaurusfunc'. (Yegappan Lakshmanan, closes #8987, closes 8950)
-rw-r--r--runtime/doc/insert.txt8
-rw-r--r--runtime/doc/options.txt12
-rw-r--r--runtime/doc/quickref.txt1
-rw-r--r--src/buffer.c1
-rw-r--r--src/insexpand.c59
-rw-r--r--src/option.c3
-rw-r--r--src/option.h4
-rw-r--r--src/optiondefs.h12
-rw-r--r--src/optionstr.c1
-rw-r--r--src/structs.h1
-rw-r--r--src/testdir/test_edit.vim42
-rw-r--r--src/version.c2
12 files changed, 138 insertions, 8 deletions
diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt
index 31b820f7b..8d47a7e96 100644
--- a/runtime/doc/insert.txt
+++ b/runtime/doc/insert.txt
@@ -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.
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 41d710529..67504795b 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -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
diff --git a/runtime/doc/quickref.txt b/runtime/doc/quickref.txt
index fcdd5a7fe..f7c5c1789 100644
--- a/runtime/doc/quickref.txt
+++ b/runtime/doc/quickref.txt
@@ -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
diff --git a/src/buffer.c b/src/buffer.c
index 86dc88687..ba20a611d 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -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);
diff --git a/src/insexpand.c b/src/insexpand.c
index ee8263c8b..624146a3f 100644
--- a/src/insexpand.c
+++ b/src/insexpand.c
@@ -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;
@@ -2230,6 +2234,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;
@@ -2721,6 +2744,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
* compl_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
diff --git a/src/option.c b/src/option.c
index fe5ff4367..385126eb3 100644
--- a/src/option.c
+++ b/src/option.c
@@ -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);
diff --git a/src/option.h b/src/option.h
index 48a3ec34b..75c83d56d 100644
--- a/src/option.h
+++ b/src/option.h
@@ -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
diff --git a/src/optiondefs.h b/src/optiondefs.h
index ec89558f1..a7a3d0c90 100644
--- a/src/optiondefs.h
+++ b/src/optiondefs.h
@@ -140,6 +140,9 @@
#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},
diff --git a/src/optionstr.c b/src/optionstr.c
index ff1321881..06a633b0f 100644
--- a/src/optionstr.c
+++ b/src/optionstr.c
@@ -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);
diff --git a/src/structs.h b/src/structs.h
index 83a13a765..021206e1e 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -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'
diff --git a/src/testdir/test_edit.vim b/src/testdir/test_edit.vim
index 6561edc5c..2cce85ca3 100644
--- a/src/testdir/test_edit.vim
+++ b/src/testdir/test_edit.vim
@@ -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
diff --git a/src/version.c b/src/version.c
index c5e9f258d..00617b5c9 100644
--- a/src/version.c
+++ b/src/version.c
@@ -758,6 +758,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 3520,
+/**/
3519,
/**/
3518,