Patch 8.2.3665
Problem: Cannot use a lambda for 'tagfunc'.
Solution: Use 'tagfunc' like 'opfunc'. (Yegappan Lakshmanan, closes #9204)
Files: runtime/doc/options.txt, src/buffer.c, src/option.c,
src/optionstr.c, src/proto/tag.pro, src/structs.h, src/tag.c,
src/testdir/test_tagfunc.vim
*** ../vim-8.2.3664/runtime/doc/options.txt 2021-11-18 22:08:52.007682711
+0000
--- runtime/doc/options.txt 2021-11-24 16:27:46.892748472 +0000
***************
*** 370,378 ****
or a function reference or a lambda function. Examples:
>
set opfunc=MyOpFunc
! set opfunc=function("MyOpFunc")
! set opfunc=funcref("MyOpFunc")
! set opfunc={t\ ->\ MyOpFunc(t)}
<
Setting the filetype
--- 377,385 ----
or a function reference or a lambda function. Examples:
>
set opfunc=MyOpFunc
! set opfunc=function('MyOpFunc')
! set opfunc=funcref('MyOpFunc')
! let &opfunc = "{t -> MyOpFunc(t)}"
<
Setting the filetype
***************
*** 7770,7776 ****
This option specifies a function to be used to perform tag searches.
The function gets the tag pattern and should return a List of matching
tags. See |tag-function| for an explanation of how to write the
! function and an example.
*'taglength'* *'tl'*
'taglength' 'tl' number (default 0)
--- 7792,7800 ----
This option specifies a function to be used to perform tag searches.
The function gets the tag pattern and should return a List of matching
tags. See |tag-function| for an explanation of how to write the
! function and an example. The value can be the name of a function, a
! |lambda| or a |Funcref|. See |option-value-function| for more
! information.
*'taglength'* *'tl'*
'taglength' 'tl' number (default 0)
*** ../vim-8.2.3664/src/buffer.c 2021-11-19 17:01:05.555037778 +0000
--- src/buffer.c 2021-11-24 16:26:17.400826784 +0000
***************
*** 2344,2349 ****
--- 2344,2350 ----
clear_string_option(&buf->b_p_tc);
#ifdef FEAT_EVAL
clear_string_option(&buf->b_p_tfu);
+ free_callback(&buf->b_tfu_cb);
#endif
clear_string_option(&buf->b_p_dict);
clear_string_option(&buf->b_p_tsr);
*** ../vim-8.2.3664/src/option.c 2021-11-20 13:45:37.806729612 +0000
--- src/option.c 2021-11-24 16:26:17.400826784 +0000
***************
*** 810,815 ****
--- 810,816 ----
clear_string_option((char_u **)options[i].var);
}
free_operatorfunc_option();
+ free_tagfunc_option();
}
#endif
***************
*** 5956,5961 ****
--- 5957,5963 ----
#ifdef FEAT_EVAL
buf->b_p_tfu = vim_strsave(p_tfu);
COPY_OPT_SCTX(buf, BV_TFU);
+ buf_set_tfu_callback(buf);
#endif
buf->b_p_sts = p_sts;
COPY_OPT_SCTX(buf, BV_STS);
*** ../vim-8.2.3664/src/optionstr.c 2021-11-20 13:45:37.806729612 +0000
--- src/optionstr.c 2021-11-24 16:26:17.400826784 +0000
***************
*** 2333,2338 ****
--- 2333,2347 ----
}
#endif
+ #ifdef FEAT_EVAL
+ // 'tagfunc'
+ else if (gvarp == &p_tfu)
+ {
+ if (set_tagfunc_option() == FAIL)
+ errmsg = e_invarg;
+ }
+ #endif
+
// Options that are a list of flags.
else
{
*** ../vim-8.2.3664/src/proto/tag.pro 2019-12-12 11:55:34.000000000 +0000
--- src/proto/tag.pro 2021-11-24 16:30:12.228602387 +0000
***************
*** 1,4 ****
--- 1,7 ----
/* tag.c */
+ int set_tagfunc_option(void);
+ void free_tagfunc_option(void);
+ void buf_set_tfu_callback(buf_T *buf);
int do_tag(char_u *tag, int type, int count, int forceit, int verbose);
void tag_freematch(void);
void do_tags(exarg_T *eap);
*** ../vim-8.2.3664/src/structs.h 2021-11-24 16:19:41.389010087 +0000
--- src/structs.h 2021-11-24 16:26:17.400826784 +0000
***************
*** 2878,2884 ****
char_u *b_p_ofu; // 'omnifunc'
#endif
#ifdef FEAT_EVAL
! char_u *b_p_tfu; // 'tagfunc'
#endif
int b_p_eol; // 'endofline'
int b_p_fixeol; // 'fixendofline'
--- 2878,2885 ----
char_u *b_p_ofu; // 'omnifunc'
#endif
#ifdef FEAT_EVAL
! char_u *b_p_tfu; // 'tagfunc' option value
! callback_T b_tfu_cb; // 'tagfunc' callback
#endif
int b_p_eol; // 'endofline'
int b_p_fixeol; // 'fixendofline'
*** ../vim-8.2.3664/src/tag.c 2021-10-02 11:23:01.566500862 +0100
--- src/tag.c 2021-11-24 16:26:17.404826781 +0000
***************
*** 103,114 ****
--- 103,163 ----
#ifdef FEAT_EVAL
static int tfu_in_use = FALSE; // disallow recursive call of
tagfunc
+ static callback_T tfu_cb; // 'tagfunc' callback function
#endif
// Used instead of NUL to separate tag fields in the growarrays.
#define TAG_SEP 0x02
/*
+ * Reads the 'tagfunc' option value and convert that to a callback value.
+ * Invoked when the 'tagfunc' option is set. The option value can be a name of
+ * a function (string), or function(<name>) or funcref(<name>) or a lambda.
+ */
+ int
+ set_tagfunc_option()
+ {
+ #ifdef FEAT_EVAL
+ free_callback(&tfu_cb);
+ free_callback(&curbuf->b_tfu_cb);
+
+ if (*curbuf->b_p_tfu == NUL)
+ return OK;
+
+ if (option_set_callback_func(curbuf->b_p_tfu, &tfu_cb) == FAIL)
+ return FAIL;
+
+ copy_callback(&curbuf->b_tfu_cb, &tfu_cb);
+ #endif
+
+ return OK;
+ }
+
+ # if defined(EXITFREE) || defined(PROTO)
+ void
+ free_tagfunc_option(void)
+ {
+ # ifdef FEAT_EVAL
+ free_callback(&tfu_cb);
+ # endif
+ }
+ # endif
+
+ /*
+ * Copy the global 'tagfunc' callback function to the buffer-local 'tagfunc'
+ * callback for 'buf'.
+ */
+ void
+ buf_set_tfu_callback(buf_T *buf UNUSED)
+ {
+ #ifdef FEAT_EVAL
+ free_callback(&buf->b_tfu_cb);
+ if (tfu_cb.cb_name != NULL && *tfu_cb.cb_name != NUL)
+ copy_callback(&buf->b_tfu_cb, &tfu_cb);
+ #endif
+ }
+
+ /*
* Jump to tag; handling of tag commands and tag stack
*
* *tag != NUL: ":tag {tag}", jump to new tag, add to tag stack
***************
*** 1341,1347 ****
flags & TAG_REGEXP ? "r": "");
save_pos = curwin->w_cursor;
! result = call_vim_function(curbuf->b_p_tfu, 3, args, &rettv);
curwin->w_cursor = save_pos; // restore the cursor position
--d->dv_refcount;
--- 1390,1396 ----
flags & TAG_REGEXP ? "r": "");
save_pos = curwin->w_cursor;
! result = call_callback(&curbuf->b_tfu_cb, 0, &rettv, 3, args);
curwin->w_cursor = save_pos; // restore the cursor position
--d->dv_refcount;
*** ../vim-8.2.3664/src/testdir/test_tagfunc.vim 2021-03-21
13:49:53.453675479 +0000
--- src/testdir/test_tagfunc.vim 2021-11-24 16:26:17.404826781 +0000
***************
*** 117,120 ****
--- 117,170 ----
delfunc Mytagfunc2
endfunc
+ " Test for different ways of setting the 'tagfunc' option
+ func Test_tagfunc_callback()
+ " Test for using a function()
+ func MytagFunc1(pat, flags, info)
+ let g:MytagFunc1_args = [a:pat, a:flags, a:info]
+ return v:null
+ endfunc
+ let g:MytagFunc1_args = []
+ set tagfunc=function('MytagFunc1')
+ call assert_fails('tag abc', 'E433:')
+ call assert_equal(['abc', '', {}], g:MytagFunc1_args)
+
+ " Test for using a funcref()
+ new
+ func MytagFunc2(pat, flags, info)
+ let g:MytagFunc2_args = [a:pat, a:flags, a:info]
+ return v:null
+ endfunc
+ let g:MytagFunc2_args = []
+ set tagfunc=funcref('MytagFunc2')
+ call assert_fails('tag def', 'E433:')
+ call assert_equal(['def', '', {}], g:MytagFunc2_args)
+
+ " Test for using a lambda function
+ new
+ func MytagFunc3(pat, flags, info)
+ let g:MytagFunc3_args = [a:pat, a:flags, a:info]
+ return v:null
+ endfunc
+ let g:MytagFunc3_args = []
+ let &tagfunc= '{a, b, c -> MytagFunc3(a, b, c)}'
+ call assert_fails('tag ghi', 'E433:')
+ call assert_equal(['ghi', '', {}], g:MytagFunc3_args)
+
+ " Test for clearing the 'tagfunc' option
+ set tagfunc=''
+ set tagfunc&
+
+ call assert_fails("set tagfunc=function('abc')", "E700:")
+ call assert_fails("set tagfunc=funcref('abc')", "E700:")
+ let &tagfunc = "{a -> 'abc'}"
+ call assert_fails("echo taglist('a')", "E987:")
+
+ " cleanup
+ delfunc MytagFunc1
+ delfunc MytagFunc2
+ delfunc MytagFunc3
+ %bw!
+ endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
*** ../vim-8.2.3664/src/version.c 2021-11-24 16:19:41.393010087 +0000
--- src/version.c 2021-11-24 16:29:04.868672714 +0000
***************
*** 759,760 ****
--- 759,762 ----
{ /* Add new patch number below this line */
+ /**/
+ 3665,
/**/
--
A programmer's wife asks him: "Please run to the store and pick up a loaf of
bread. If they have eggs, get a dozen". The programmer comes home with 12
loafs of bread.
/// 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/20211124163325.6365A1C0745%40moolenaar.net.