mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 04:17:01 +00:00 
			
		
		
		
	vim-patch:9.1.0821: 'findexpr' completion doesn't set v:fname to cmdline argument
Problem:  'findexpr' completion doesn't set v:fname to cmdline argument.
Solution: Set v:fname to the cmdline argument as-is (zeertzjq).
closes: vim/vim#15934
20e045f781
			
			
This commit is contained in:
		| @@ -2611,6 +2611,10 @@ A jump table for the options with a short description can be found at |Q_op|. | ||||
| 	The expression is evaluated only once per |:find| command invocation. | ||||
| 	The expression can process all the directories specified in 'path'. | ||||
|  | ||||
| 	The expression may be evaluated for command-line completion as well, | ||||
| 	in which case the |v:cmdcomplete| variable will be set to |v:true|, | ||||
| 	otherwise it will be set to |v:false|. | ||||
|  | ||||
| 	If a match is found, the expression should return a |List| containing | ||||
| 	one or more file names.  If a match is not found, the expression | ||||
| 	should return an empty List. | ||||
| @@ -2630,7 +2634,8 @@ A jump table for the options with a short description can be found at |Q_op|. | ||||
| 	>vim | ||||
| 	    " Use glob() | ||||
| 	    func FindExprGlob() | ||||
| 		return glob(v:fname, v:false, v:true) | ||||
| 		let pat = v:cmdcomplete ? $'{v:fname}*' : v:fname | ||||
| 		return glob(pat, v:false, v:true) | ||||
| 	    endfunc | ||||
| 	    set findexpr=FindExprGlob() | ||||
|  | ||||
|   | ||||
| @@ -48,6 +48,11 @@ v:cmdbang | ||||
| 		can only be used in autocommands.  For user commands |<bang>| | ||||
| 		can be used. | ||||
|  | ||||
| 				*v:cmdcomplete* *cmdcomplete-variable* | ||||
| v:cmdcomplete | ||||
| 		When evaluating 'findexpr': if 'findexpr' is used for cmdline | ||||
| 		completion the value is |v:true|, otherwise it is |v:false|. | ||||
|  | ||||
| 					*v:collate* *collate-variable* | ||||
| v:collate | ||||
| 		The current locale setting for collation order of the runtime | ||||
|   | ||||
							
								
								
									
										7
									
								
								runtime/lua/vim/_meta/options.lua
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										7
									
								
								runtime/lua/vim/_meta/options.lua
									
									
									
										generated
									
									
									
								
							| @@ -2304,6 +2304,10 @@ vim.go.fcs = vim.go.fillchars | ||||
| --- The expression is evaluated only once per `:find` command invocation. | ||||
| --- The expression can process all the directories specified in 'path'. | ||||
| --- | ||||
| --- The expression may be evaluated for command-line completion as well, | ||||
| --- in which case the `v:cmdcomplete` variable will be set to `v:true`, | ||||
| --- otherwise it will be set to `v:false`. | ||||
| --- | ||||
| --- If a match is found, the expression should return a `List` containing | ||||
| --- one or more file names.  If a match is not found, the expression | ||||
| --- should return an empty List. | ||||
| @@ -2324,7 +2328,8 @@ vim.go.fcs = vim.go.fillchars | ||||
| --- ```vim | ||||
| ---     " Use glob() | ||||
| ---     func FindExprGlob() | ||||
| --- 	return glob(v:fname, v:false, v:true) | ||||
| --- 	let pat = v:cmdcomplete ? $'{v:fname}*' : v:fname | ||||
| --- 	return glob(pat, v:false, v:true) | ||||
| ---     endfunc | ||||
| ---     set findexpr=FindExprGlob() | ||||
| --- | ||||
|   | ||||
							
								
								
									
										5
									
								
								runtime/lua/vim/_meta/vvars.lua
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										5
									
								
								runtime/lua/vim/_meta/vvars.lua
									
									
									
										generated
									
									
									
								
							| @@ -44,6 +44,11 @@ vim.v.cmdarg = ... | ||||
| --- @type integer | ||||
| vim.v.cmdbang = ... | ||||
|  | ||||
| --- When evaluating 'findexpr': if 'findexpr' is used for cmdline | ||||
| --- completion the value is `v:true`, otherwise it is `v:false`. | ||||
| --- @type boolean | ||||
| vim.v.cmdcomplete = ... | ||||
|  | ||||
| --- The current locale setting for collation order of the runtime | ||||
| --- environment.  This allows Vim scripts to be aware of the | ||||
| --- current locale encoding.  Technical: it's the value of | ||||
|   | ||||
| @@ -109,6 +109,7 @@ static bool cmdline_fuzzy_completion_supported(const expand_T *const xp) | ||||
|          && xp->xp_context != EXPAND_FILES | ||||
|          && xp->xp_context != EXPAND_FILES_IN_PATH | ||||
|          && xp->xp_context != EXPAND_FILETYPE | ||||
|          && xp->xp_context != EXPAND_FINDEXPR | ||||
|          && xp->xp_context != EXPAND_HELP | ||||
|          && xp->xp_context != EXPAND_KEYMAP | ||||
|          && xp->xp_context != EXPAND_LUA | ||||
| @@ -1228,7 +1229,8 @@ char *addstar(char *fname, size_t len, int context) | ||||
|  | ||||
|     // For help tags the translation is done in find_help_tags(). | ||||
|     // For a tag pattern starting with "/" no translation is needed. | ||||
|     if (context == EXPAND_HELP | ||||
|     if (context == EXPAND_FINDEXPR | ||||
|         || context == EXPAND_HELP | ||||
|         || context == EXPAND_COLORS | ||||
|         || context == EXPAND_COMPILER | ||||
|         || context == EXPAND_OWNSYNTAX | ||||
| @@ -1827,7 +1829,7 @@ static const char *set_context_by_cmdname(const char *cmd, cmdidx_T cmdidx, expa | ||||
|   case CMD_sfind: | ||||
|   case CMD_tabfind: | ||||
|     if (xp->xp_context == EXPAND_FILES) { | ||||
|       xp->xp_context = EXPAND_FILES_IN_PATH; | ||||
|       xp->xp_context = *get_findexpr() != NUL ? EXPAND_FINDEXPR : EXPAND_FILES_IN_PATH; | ||||
|     } | ||||
|     break; | ||||
|   case CMD_cd: | ||||
| @@ -2498,7 +2500,7 @@ static int expand_files_and_dirs(expand_T *xp, char *pat, char ***matches, int * | ||||
|   } | ||||
|  | ||||
|   int ret = FAIL; | ||||
|   if (xp->xp_context == EXPAND_FILES_IN_PATH && *get_findexpr() != NUL) { | ||||
|   if (xp->xp_context == EXPAND_FINDEXPR) { | ||||
|     ret = expand_findexpr(pat, matches, numMatches); | ||||
|   } else { | ||||
|     if (xp->xp_context == EXPAND_FILES) { | ||||
| @@ -2720,6 +2722,7 @@ static int ExpandFromContext(expand_T *xp, char *pat, char ***matches, int *numM | ||||
|   if (xp->xp_context == EXPAND_FILES | ||||
|       || xp->xp_context == EXPAND_DIRECTORIES | ||||
|       || xp->xp_context == EXPAND_FILES_IN_PATH | ||||
|       || xp->xp_context == EXPAND_FINDEXPR | ||||
|       || xp->xp_context == EXPAND_DIRS_IN_CDPATH) { | ||||
|     return expand_files_and_dirs(xp, pat, matches, numMatches, flags, options); | ||||
|   } | ||||
|   | ||||
| @@ -107,6 +107,7 @@ enum { | ||||
|   EXPAND_KEYMAP, | ||||
|   EXPAND_DIRS_IN_CDPATH, | ||||
|   EXPAND_SHELLCMDLINE, | ||||
|   EXPAND_FINDEXPR, | ||||
|   EXPAND_CHECKHEALTH, | ||||
|   EXPAND_LUA, | ||||
| }; | ||||
|   | ||||
| @@ -186,7 +186,7 @@ INIT(= N_("E5767: Cannot use :undo! to redo or move to a different undo branch") | ||||
|  | ||||
| EXTERN const char e_winfixbuf_cannot_go_to_buffer[] | ||||
| INIT(= N_("E1513: Cannot switch buffer. 'winfixbuf' is enabled")); | ||||
| EXTERN const char e_invalid_return_type_from_findexpr[] INIT( = N_("E1514: findexpr did not return a List type")); | ||||
| EXTERN const char e_invalid_return_type_from_findexpr[] INIT( = N_("E1514: 'findexpr' did not return a List type")); | ||||
|  | ||||
| EXTERN const char e_trustfile[] INIT(= N_("E5570: Cannot update trust file: %s")); | ||||
|  | ||||
|   | ||||
| @@ -270,6 +270,7 @@ static struct vimvar { | ||||
|   VV(VV_COLLATE,          "collate",          VAR_STRING, VV_RO), | ||||
|   VV(VV_EXITING,          "exiting",          VAR_NUMBER, VV_RO), | ||||
|   VV(VV_MAXCOL,           "maxcol",           VAR_NUMBER, VV_RO), | ||||
|   VV(VV_CMDCOMPLETE,      "cmdcomplete",      VAR_BOOL, VV_RO), | ||||
|   // Neovim | ||||
|   VV(VV_STDERR,           "stderr",           VAR_NUMBER, VV_RO), | ||||
|   VV(VV_MSGPACK_TYPES,    "msgpack_types",    VAR_DICT, VV_RO), | ||||
| @@ -460,6 +461,9 @@ void eval_init(void) | ||||
|   set_vim_var_nr(VV_SEARCHFORWARD, 1); | ||||
|   set_vim_var_nr(VV_HLSEARCH, 1); | ||||
|   set_vim_var_nr(VV_COUNT1, 1); | ||||
|   set_vim_var_special(VV_EXITING, kSpecialVarNull); | ||||
|   set_vim_var_bool(VV_CMDCOMPLETE, kBoolVarFalse); | ||||
|  | ||||
|   set_vim_var_nr(VV_TYPE_NUMBER, VAR_TYPE_NUMBER); | ||||
|   set_vim_var_nr(VV_TYPE_STRING, VAR_TYPE_STRING); | ||||
|   set_vim_var_nr(VV_TYPE_FUNC,   VAR_TYPE_FUNC); | ||||
| @@ -475,7 +479,6 @@ void eval_init(void) | ||||
|   set_vim_var_nr(VV_NUMBERMAX, VARNUMBER_MAX); | ||||
|   set_vim_var_nr(VV_NUMBERMIN, VARNUMBER_MIN); | ||||
|   set_vim_var_nr(VV_NUMBERSIZE, sizeof(varnumber_T) * 8); | ||||
|   set_vim_var_special(VV_EXITING, kSpecialVarNull); | ||||
|   set_vim_var_nr(VV_MAXCOL, MAXCOL); | ||||
|  | ||||
|   set_vim_var_nr(VV_ECHOSPACE,    sc_col - 1); | ||||
|   | ||||
| @@ -167,6 +167,7 @@ typedef enum { | ||||
|   VV_COLLATE, | ||||
|   VV_EXITING, | ||||
|   VV_MAXCOL, | ||||
|   VV_CMDCOMPLETE, | ||||
|   // Nvim | ||||
|   VV_STDERR, | ||||
|   VV_MSGPACK_TYPES, | ||||
|   | ||||
| @@ -5167,13 +5167,14 @@ static void ex_wrongmodifier(exarg_T *eap) | ||||
|  | ||||
| /// Evaluate the 'findexpr' expression and return the result.  When evaluating | ||||
| /// the expression, v:fname is set to the ":find" command argument. | ||||
| static list_T *eval_findexpr(const char *ptr) | ||||
| static list_T *eval_findexpr(const char *pat, bool cmdcomplete) | ||||
| { | ||||
|   const sctx_T saved_sctx = current_sctx; | ||||
|  | ||||
|   char *findexpr = get_findexpr(); | ||||
|  | ||||
|   set_vim_var_string(VV_FNAME, ptr, -1); | ||||
|   set_vim_var_string(VV_FNAME, pat, -1); | ||||
|   set_vim_var_bool(VV_CMDCOMPLETE, cmdcomplete ? kBoolVarTrue : kBoolVarFalse); | ||||
|   current_sctx = curbuf->b_p_script_ctx[BV_FEXPR].script_ctx; | ||||
|  | ||||
|   char *arg = skipwhite(findexpr); | ||||
| @@ -5198,6 +5199,7 @@ static list_T *eval_findexpr(const char *ptr) | ||||
|   clear_evalarg(&EVALARG_EVALUATE, NULL); | ||||
|  | ||||
|   set_vim_var_string(VV_FNAME, NULL, 0); | ||||
|   set_vim_var_bool(VV_CMDCOMPLETE, kBoolVarFalse); | ||||
|   current_sctx = saved_sctx; | ||||
|  | ||||
|   return retlist; | ||||
| @@ -5211,18 +5213,7 @@ int expand_findexpr(const char *pat, char ***files, int *numMatches) | ||||
|   *numMatches = 0; | ||||
|   *files = NULL; | ||||
|  | ||||
|   // File name expansion uses wildchars.  But the 'findexpr' expression | ||||
|   // expects a regular expression argument.  So convert wildchars in the | ||||
|   // argument to regular expression patterns. | ||||
|   char *regpat = file_pat_to_reg_pat(pat, NULL, NULL, false); | ||||
|   if (regpat == NULL) { | ||||
|     return FAIL; | ||||
|   } | ||||
|  | ||||
|   list_T *l = eval_findexpr(regpat); | ||||
|  | ||||
|   xfree(regpat); | ||||
|  | ||||
|   list_T *l = eval_findexpr(pat, true); | ||||
|   if (l == NULL) { | ||||
|     return FAIL; | ||||
|   } | ||||
| @@ -5258,7 +5249,7 @@ static char *findexpr_find_file(char *findarg, size_t findarg_len, int count) | ||||
|   const char cc = findarg[findarg_len]; | ||||
|   findarg[findarg_len] = NUL; | ||||
|  | ||||
|   list_T *fname_list = eval_findexpr(findarg); | ||||
|   list_T *fname_list = eval_findexpr(findarg, false); | ||||
|   int fname_count = tv_list_len(fname_list); | ||||
|  | ||||
|   if (fname_count == 0) { | ||||
|   | ||||
| @@ -2920,6 +2920,10 @@ return { | ||||
|         The expression is evaluated only once per |:find| command invocation. | ||||
|         The expression can process all the directories specified in 'path'. | ||||
|  | ||||
|         The expression may be evaluated for command-line completion as well, | ||||
|         in which case the |v:cmdcomplete| variable will be set to |v:true|, | ||||
|         otherwise it will be set to |v:false|. | ||||
|  | ||||
|         If a match is found, the expression should return a |List| containing | ||||
|         one or more file names.  If a match is not found, the expression | ||||
|         should return an empty List. | ||||
| @@ -2939,7 +2943,8 @@ return { | ||||
|         >vim | ||||
|             " Use glob() | ||||
|             func FindExprGlob() | ||||
|         	return glob(v:fname, v:false, v:true) | ||||
|         	let pat = v:cmdcomplete ? $'{v:fname}*' : v:fname | ||||
|         	return glob(pat, v:false, v:true) | ||||
|             endfunc | ||||
|             set findexpr=FindExprGlob() | ||||
|  | ||||
|   | ||||
| @@ -50,6 +50,13 @@ M.vars = { | ||||
|       can be used. | ||||
|     ]=], | ||||
|   }, | ||||
|   cmdcomplete = { | ||||
|     type = 'boolean', | ||||
|     desc = [=[ | ||||
|       When evaluating 'findexpr': if 'findexpr' is used for cmdline | ||||
|       completion the value is |v:true|, otherwise it is |v:false|. | ||||
|     ]=], | ||||
|   }, | ||||
|   collate = { | ||||
|     type = 'string', | ||||
|     desc = [=[ | ||||
|   | ||||
| @@ -379,7 +379,7 @@ func Test_findexpr() | ||||
|  | ||||
|   " Expression returning a string | ||||
|   set findexpr='abc' | ||||
|   call assert_fails('find Xfindexpr1.c', 'E1514: findexpr did not return a List type') | ||||
|   call assert_fails('find Xfindexpr1.c', "E1514: 'findexpr' did not return a List type") | ||||
|  | ||||
|   set findexpr& | ||||
|   delfunc! FindExpr1 | ||||
| @@ -459,29 +459,52 @@ endfunc | ||||
|  | ||||
| " Test for expanding the argument to the :find command using 'findexpr' | ||||
| func Test_findexpr_expand_arg() | ||||
|   func FindExpr1() | ||||
|     let fnames = ['Xfindexpr1.c', 'Xfindexpr2.c', 'Xfindexpr3.c'] | ||||
|     return fnames->copy()->filter('v:val =~? v:fname') | ||||
|   let s:fnames = ['Xfindexpr1.c', 'Xfindexpr2.c', 'Xfindexpr3.c'] | ||||
|  | ||||
|   " 'findexpr' that accepts a regular expression | ||||
|   func FindExprRegexp() | ||||
|     return s:fnames->copy()->filter('v:val =~? v:fname') | ||||
|   endfunc | ||||
|   set findexpr=FindExpr1() | ||||
|  | ||||
|   call feedkeys(":find \<Tab>\<C-B>\"\<CR>", "xt") | ||||
|   call assert_equal('"find Xfindexpr1.c', @:) | ||||
|   " 'findexpr' that accepts a glob | ||||
|   func FindExprGlob() | ||||
|     let pat = glob2regpat(v:cmdcomplete ? $'*{v:fname}*' : v:fname) | ||||
|     return s:fnames->copy()->filter('v:val =~? pat') | ||||
|   endfunc | ||||
|  | ||||
|   call feedkeys(":find Xfind\<Tab>\<Tab>\<C-B>\"\<CR>", "xt") | ||||
|   call assert_equal('"find Xfindexpr2.c', @:) | ||||
|   for regexp in [v:true, v:false] | ||||
|     let &findexpr = regexp ? 'FindExprRegexp()' : 'FindExprGlob()' | ||||
|  | ||||
|   call feedkeys(":find *3*\<Tab>\<C-B>\"\<CR>", "xt") | ||||
|   call assert_equal('"find Xfindexpr3.c', @:) | ||||
|     call feedkeys(":find \<Tab>\<C-B>\"\<CR>", "xt") | ||||
|     call assert_equal('"find Xfindexpr1.c', @:) | ||||
|  | ||||
|   call feedkeys(":find Xfind\<C-A>\<C-B>\"\<CR>", "xt") | ||||
|   call assert_equal('"find Xfindexpr1.c Xfindexpr2.c Xfindexpr3.c', @:) | ||||
|     call feedkeys(":find Xfind\<Tab>\<Tab>\<C-B>\"\<CR>", "xt") | ||||
|     call assert_equal('"find Xfindexpr2.c', @:) | ||||
|  | ||||
|   call feedkeys(":find abc\<Tab>\<C-B>\"\<CR>", "xt") | ||||
|   call assert_equal('"find abc', @:) | ||||
|     call assert_equal(s:fnames, getcompletion('find ', 'cmdline')) | ||||
|     call assert_equal(s:fnames, getcompletion('find Xfind', 'cmdline')) | ||||
|  | ||||
|     let pat = regexp ? 'X.*1\.c' : 'X*1.c' | ||||
|     call feedkeys($":find {pat}\<Tab>\<C-B>\"\<CR>", "xt") | ||||
|     call assert_equal('"find Xfindexpr1.c', @:) | ||||
|     call assert_equal(['Xfindexpr1.c'], getcompletion($'find {pat}', 'cmdline')) | ||||
|  | ||||
|     call feedkeys(":find 3\<Tab>\<C-B>\"\<CR>", "xt") | ||||
|     call assert_equal('"find Xfindexpr3.c', @:) | ||||
|     call assert_equal(['Xfindexpr3.c'], getcompletion($'find 3', 'cmdline')) | ||||
|  | ||||
|     call feedkeys(":find Xfind\<C-A>\<C-B>\"\<CR>", "xt") | ||||
|     call assert_equal('"find Xfindexpr1.c Xfindexpr2.c Xfindexpr3.c', @:) | ||||
|  | ||||
|     call feedkeys(":find abc\<Tab>\<C-B>\"\<CR>", "xt") | ||||
|     call assert_equal('"find abc', @:) | ||||
|     call assert_equal([], getcompletion('find abc', 'cmdline')) | ||||
|   endfor | ||||
|  | ||||
|   set findexpr& | ||||
|   delfunc! FindExpr1 | ||||
|   delfunc! FindExprRegexp | ||||
|   delfunc! FindExprGlob | ||||
|   unlet s:fnames | ||||
| endfunc | ||||
|  | ||||
| " vim: shiftwidth=2 sts=2 expandtab | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 zeertzjq
					zeertzjq