Merge pull request #23943 from zeertzjq/autocmd-fname

fix(events): don't expand non-file as file name
This commit is contained in:
zeertzjq 2023-06-07 10:17:19 +08:00 committed by GitHub
commit fcaf0d5f38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 33 additions and 22 deletions

View File

@ -1603,6 +1603,7 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force
// Save the autocmd_* variables and info about the current buffer. // Save the autocmd_* variables and info about the current buffer.
char *save_autocmd_fname = autocmd_fname; char *save_autocmd_fname = autocmd_fname;
bool save_autocmd_fname_full = autocmd_fname_full;
int save_autocmd_bufnr = autocmd_bufnr; int save_autocmd_bufnr = autocmd_bufnr;
char *save_autocmd_match = autocmd_match; char *save_autocmd_match = autocmd_match;
int save_autocmd_busy = autocmd_busy; int save_autocmd_busy = autocmd_busy;
@ -1631,6 +1632,7 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force
// Allocate MAXPATHL for when eval_vars() resolves the fullpath. // Allocate MAXPATHL for when eval_vars() resolves the fullpath.
autocmd_fname = xstrnsave(autocmd_fname, MAXPATHL); autocmd_fname = xstrnsave(autocmd_fname, MAXPATHL);
} }
autocmd_fname_full = false; // call FullName_save() later
// Set the buffer number to be used for <abuf>. // Set the buffer number to be used for <abuf>.
autocmd_bufnr = buf == NULL ? 0 : buf->b_fnum; autocmd_bufnr = buf == NULL ? 0 : buf->b_fnum;
@ -1674,6 +1676,7 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force
|| event == EVENT_USER || event == EVENT_WINCLOSED || event == EVENT_USER || event == EVENT_WINCLOSED
|| event == EVENT_WINRESIZED || event == EVENT_WINSCROLLED) { || event == EVENT_WINRESIZED || event == EVENT_WINSCROLLED) {
fname = xstrdup(fname); fname = xstrdup(fname);
autocmd_fname_full = true; // don't expand it later
} else { } else {
fname = FullName_save(fname, false); fname = FullName_save(fname, false);
} }
@ -1806,6 +1809,7 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force
estack_pop(); estack_pop();
xfree(autocmd_fname); xfree(autocmd_fname);
autocmd_fname = save_autocmd_fname; autocmd_fname = save_autocmd_fname;
autocmd_fname_full = save_autocmd_fname_full;
autocmd_bufnr = save_autocmd_bufnr; autocmd_bufnr = save_autocmd_bufnr;
autocmd_match = save_autocmd_match; autocmd_match = save_autocmd_match;
current_sctx = save_current_sctx; current_sctx = save_current_sctx;

View File

@ -8609,6 +8609,7 @@ typval_T eval_call_provider(char *provider, char *method, list_T *arguments, boo
.es_entry = ((estack_T *)exestack.ga_data)[exestack.ga_len - 1], .es_entry = ((estack_T *)exestack.ga_data)[exestack.ga_len - 1],
.autocmd_fname = autocmd_fname, .autocmd_fname = autocmd_fname,
.autocmd_match = autocmd_match, .autocmd_match = autocmd_match,
.autocmd_fname_full = autocmd_fname_full,
.autocmd_bufnr = autocmd_bufnr, .autocmd_bufnr = autocmd_bufnr,
.funccalp = (void *)get_current_funccal() .funccalp = (void *)get_current_funccal()
}; };

View File

@ -6552,6 +6552,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
sctx_T save_current_sctx; sctx_T save_current_sctx;
char *save_autocmd_fname, *save_autocmd_match; char *save_autocmd_fname, *save_autocmd_match;
bool save_autocmd_fname_full;
int save_autocmd_bufnr; int save_autocmd_bufnr;
funccal_entry_T funccal_entry; funccal_entry_T funccal_entry;
@ -6561,6 +6562,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
save_current_sctx = current_sctx; save_current_sctx = current_sctx;
save_autocmd_fname = autocmd_fname; save_autocmd_fname = autocmd_fname;
save_autocmd_match = autocmd_match; save_autocmd_match = autocmd_match;
save_autocmd_fname_full = autocmd_fname_full;
save_autocmd_bufnr = autocmd_bufnr; save_autocmd_bufnr = autocmd_bufnr;
save_funccal(&funccal_entry); save_funccal(&funccal_entry);
@ -6569,6 +6571,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
((estack_T *)exestack.ga_data)[exestack.ga_len++] = provider_caller_scope.es_entry; ((estack_T *)exestack.ga_data)[exestack.ga_len++] = provider_caller_scope.es_entry;
autocmd_fname = provider_caller_scope.autocmd_fname; autocmd_fname = provider_caller_scope.autocmd_fname;
autocmd_match = provider_caller_scope.autocmd_match; autocmd_match = provider_caller_scope.autocmd_match;
autocmd_fname_full = provider_caller_scope.autocmd_fname_full;
autocmd_bufnr = provider_caller_scope.autocmd_bufnr; autocmd_bufnr = provider_caller_scope.autocmd_bufnr;
set_current_funccal((funccall_T *)(provider_caller_scope.funccalp)); set_current_funccal((funccall_T *)(provider_caller_scope.funccalp));
} }
@ -6586,6 +6589,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
exestack.ga_len--; exestack.ga_len--;
autocmd_fname = save_autocmd_fname; autocmd_fname = save_autocmd_fname;
autocmd_match = save_autocmd_match; autocmd_match = save_autocmd_match;
autocmd_fname_full = save_autocmd_fname_full;
autocmd_bufnr = save_autocmd_bufnr; autocmd_bufnr = save_autocmd_bufnr;
restore_funccal(); restore_funccal();
} }

View File

@ -6899,12 +6899,10 @@ char *eval_vars(char *src, const char *srcstart, size_t *usedlen, linenr_T *lnum
break; break;
case SPEC_AFILE: // file name for autocommand case SPEC_AFILE: // file name for autocommand
if (autocmd_fname != NULL if (autocmd_fname != NULL && !autocmd_fname_full) {
&& !path_is_absolute(autocmd_fname)
// For CmdlineEnter and related events, <afile> is not a path! #9348
&& !strequal("/", autocmd_fname)) {
// Still need to turn the fname into a full path. It was // Still need to turn the fname into a full path. It was
// postponed to avoid a delay when <afile> is not used. // postponed to avoid a delay when <afile> is not used.
autocmd_fname_full = true;
result = FullName_save(autocmd_fname, false); result = FullName_save(autocmd_fname, false);
// Copy into `autocmd_fname`, don't reassign it. #8165 // Copy into `autocmd_fname`, don't reassign it. #8165
xstrlcpy(autocmd_fname, result, MAXPATHL); xstrlcpy(autocmd_fname, result, MAXPATHL);

View File

@ -336,6 +336,7 @@ EXTERN struct caller_scope {
sctx_T script_ctx; sctx_T script_ctx;
estack_T es_entry; estack_T es_entry;
char *autocmd_fname, *autocmd_match; char *autocmd_fname, *autocmd_match;
bool autocmd_fname_full;
int autocmd_bufnr; int autocmd_bufnr;
void *funccalp; void *funccalp;
} provider_caller_scope; } provider_caller_scope;
@ -759,6 +760,7 @@ EXTERN char *last_cmdline INIT(= NULL); // last command line (for ":)
EXTERN char *repeat_cmdline INIT(= NULL); // command line for "." EXTERN char *repeat_cmdline INIT(= NULL); // command line for "."
EXTERN char *new_last_cmdline INIT(= NULL); // new value for last_cmdline EXTERN char *new_last_cmdline INIT(= NULL); // new value for last_cmdline
EXTERN char *autocmd_fname INIT(= NULL); // fname for <afile> on cmdline EXTERN char *autocmd_fname INIT(= NULL); // fname for <afile> on cmdline
EXTERN bool autocmd_fname_full INIT(= false); // autocmd_fname is full path
EXTERN int autocmd_bufnr INIT(= 0); // fnum for <abuf> on cmdline EXTERN int autocmd_bufnr INIT(= 0); // fnum for <abuf> on cmdline
EXTERN char *autocmd_match INIT(= NULL); // name for <amatch> on cmdline EXTERN char *autocmd_match INIT(= NULL); // name for <amatch> on cmdline
EXTERN bool did_cursorhold INIT(= false); // set when CursorHold t'gerd EXTERN bool did_cursorhold INIT(= false); // set when CursorHold t'gerd

View File

@ -2087,17 +2087,17 @@ char *path_shorten_fname(char *full_path, char *dir_name)
assert(dir_name != NULL); assert(dir_name != NULL);
size_t len = strlen(dir_name); size_t len = strlen(dir_name);
// If dir_name is a path head, full_path can always be made relative.
if (len == (size_t)path_head_length() && is_path_head(dir_name)) {
return full_path + len;
}
// If full_path and dir_name do not match, it's impossible to make one // If full_path and dir_name do not match, it's impossible to make one
// relative to the other. // relative to the other.
if (path_fnamencmp(dir_name, full_path, len) != 0) { if (path_fnamencmp(dir_name, full_path, len) != 0) {
return NULL; return NULL;
} }
// If dir_name is a path head, full_path can always be made relative.
if (len == (size_t)path_head_length() && is_path_head(dir_name)) {
return full_path + len;
}
char *p = full_path + len; char *p = full_path + len;
// If *p is not pointing to a path separator, this means that full_path's // If *p is not pointing to a path separator, this means that full_path's

View File

@ -228,23 +228,28 @@ describe('autocmd api', function()
end) end)
it('receives an args table', function() it('receives an args table', function()
local res = exec_lua [[ local group_id = meths.create_augroup("TestGroup", {})
local group_id = vim.api.nvim_create_augroup("TestGroup", {}) -- Having an existing autocmd calling expand("<afile>") shouldn't change args #18964
local autocmd_id = vim.api.nvim_create_autocmd("User", { meths.create_autocmd('User', {
group = 'TestGroup',
pattern = 'Te*',
command = 'call expand("<afile>")',
})
local autocmd_id = exec_lua [[
return vim.api.nvim_create_autocmd("User", {
group = "TestGroup", group = "TestGroup",
pattern = "Te*", pattern = "Te*",
callback = function(args) callback = function(args)
vim.g.autocmd_args = args vim.g.autocmd_args = args
end, end,
}) })
return {group_id, autocmd_id}
]] ]]
meths.exec_autocmds("User", {pattern = "Test pattern"}) meths.exec_autocmds("User", {pattern = "Test pattern"})
eq({ eq({
id = res[2], id = autocmd_id,
group = res[1], group = group_id,
event = "User", event = "User",
match = "Test pattern", match = "Test pattern",
file = "Test pattern", file = "Test pattern",
@ -252,27 +257,24 @@ describe('autocmd api', function()
}, meths.get_var("autocmd_args")) }, meths.get_var("autocmd_args"))
-- Test without a group -- Test without a group
res = exec_lua [[ autocmd_id = exec_lua [[
local autocmd_id = vim.api.nvim_create_autocmd("User", { return vim.api.nvim_create_autocmd("User", {
pattern = "*", pattern = "*",
callback = function(args) callback = function(args)
vim.g.autocmd_args = args vim.g.autocmd_args = args
end, end,
}) })
return {autocmd_id}
]] ]]
meths.exec_autocmds("User", {pattern = "some_pat"}) meths.exec_autocmds("User", {pattern = "some_pat"})
eq({ eq({
id = res[1], id = autocmd_id,
group = nil, group = nil,
event = "User", event = "User",
match = "some_pat", match = "some_pat",
file = "some_pat", file = "some_pat",
buf = 1, buf = 1,
}, meths.get_var("autocmd_args")) }, meths.get_var("autocmd_args"))
end) end)
it('can receive arbitrary data', function() it('can receive arbitrary data', function()