mirror of
https://github.com/vim/vim.git
synced 2025-10-28 09:27:14 -04:00
patch 8.1.1113: making an autocommand trigger once is not so easy
Problem: Making an autocommand trigger once is not so easy.
Solution: Add the ++once argument. Also add ++nested as an alias for
"nested". (Justin M. Keyes, closes #4100)
This commit is contained in:
@@ -52,6 +52,7 @@ typedef struct AutoCmd
|
||||
{
|
||||
char_u *cmd; // The command to be executed (NULL
|
||||
// when command has been removed).
|
||||
char once; // "One shot": removed after execution
|
||||
char nested; // If autocommands nest here.
|
||||
char last; // last command in list
|
||||
#ifdef FEAT_EVAL
|
||||
@@ -256,7 +257,7 @@ static int au_need_clean = FALSE; /* need to delete marked patterns */
|
||||
|
||||
static char_u *event_nr2name(event_T event);
|
||||
static int au_get_grouparg(char_u **argp);
|
||||
static int do_autocmd_event(event_T event, char_u *pat, int nested, char_u *cmd, int forceit, int group);
|
||||
static int do_autocmd_event(event_T event, char_u *pat, int once, int nested, char_u *cmd, int forceit, int group);
|
||||
static int apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, int force, int group, buf_T *buf, exarg_T *eap);
|
||||
static void auto_next_pat(AutoPatCmd *apc, int stop_at_last);
|
||||
static int au_find_group(char_u *name);
|
||||
@@ -361,6 +362,13 @@ au_remove_cmds(AutoPat *ap)
|
||||
au_need_clean = TRUE;
|
||||
}
|
||||
|
||||
// Delete one command from an autocmd pattern.
|
||||
static void au_del_cmd(AutoCmd *ac)
|
||||
{
|
||||
VIM_CLEAR(ac->cmd);
|
||||
au_need_clean = TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Cleanup autocommands and patterns that have been deleted.
|
||||
* This is only done when not executing autocommands.
|
||||
@@ -385,6 +393,8 @@ au_cleanup(void)
|
||||
{
|
||||
// loop over all commands for this pattern
|
||||
prev_ac = &(ap->cmds);
|
||||
int has_cmd = FALSE;
|
||||
|
||||
for (ac = *prev_ac; ac != NULL; ac = *prev_ac)
|
||||
{
|
||||
// remove the command if the pattern is to be deleted or when
|
||||
@@ -395,8 +405,16 @@ au_cleanup(void)
|
||||
vim_free(ac->cmd);
|
||||
vim_free(ac);
|
||||
}
|
||||
else
|
||||
else {
|
||||
has_cmd = TRUE;
|
||||
prev_ac = &(ac->next);
|
||||
}
|
||||
}
|
||||
|
||||
if (ap->pat != NULL && !has_cmd) {
|
||||
// Pattern was not marked for deletion, but all of its
|
||||
// commands were. So mark the pattern for deletion.
|
||||
au_remove_pat(ap);
|
||||
}
|
||||
|
||||
// remove the pattern if it has been marked for deletion
|
||||
@@ -815,7 +833,9 @@ do_autocmd(char_u *arg_in, int forceit)
|
||||
event_T event;
|
||||
int need_free = FALSE;
|
||||
int nested = FALSE;
|
||||
int once = FALSE;
|
||||
int group;
|
||||
int i;
|
||||
|
||||
if (*arg == '|')
|
||||
{
|
||||
@@ -874,15 +894,38 @@ do_autocmd(char_u *arg_in, int forceit)
|
||||
pat = envpat;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for "nested" flag.
|
||||
*/
|
||||
cmd = skipwhite(cmd);
|
||||
if (*cmd != NUL && STRNCMP(cmd, "nested", 6) == 0
|
||||
&& VIM_ISWHITE(cmd[6]))
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
nested = TRUE;
|
||||
cmd = skipwhite(cmd + 6);
|
||||
if (*cmd != NUL)
|
||||
{
|
||||
// Check for "++once" flag.
|
||||
if (STRNCMP(cmd, "++once", 6) == 0 && VIM_ISWHITE(cmd[6]))
|
||||
{
|
||||
if (once)
|
||||
semsg(_(e_duparg2), "++once");
|
||||
once = TRUE;
|
||||
cmd = skipwhite(cmd + 6);
|
||||
}
|
||||
|
||||
// Check for "++nested" flag.
|
||||
if ((STRNCMP(cmd, "++nested", 8) == 0 && VIM_ISWHITE(cmd[8])))
|
||||
{
|
||||
if (nested)
|
||||
semsg(_(e_duparg2), "++nested");
|
||||
nested = TRUE;
|
||||
cmd = skipwhite(cmd + 8);
|
||||
}
|
||||
|
||||
// Check for the old "nested" flag.
|
||||
if (STRNCMP(cmd, "nested", 6) == 0 && VIM_ISWHITE(cmd[6]))
|
||||
{
|
||||
if (nested)
|
||||
semsg(_(e_duparg2), "nested");
|
||||
nested = TRUE;
|
||||
cmd = skipwhite(cmd + 6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -915,14 +958,14 @@ do_autocmd(char_u *arg_in, int forceit)
|
||||
for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
|
||||
event = (event_T)((int)event + 1))
|
||||
if (do_autocmd_event(event, pat,
|
||||
nested, cmd, forceit, group) == FAIL)
|
||||
once, nested, cmd, forceit, group) == FAIL)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (*arg && *arg != '|' && !VIM_ISWHITE(*arg))
|
||||
if (do_autocmd_event(event_name2nr(arg, &arg), pat,
|
||||
nested, cmd, forceit, group) == FAIL)
|
||||
once, nested, cmd, forceit, group) == FAIL)
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -973,6 +1016,7 @@ au_get_grouparg(char_u **argp)
|
||||
do_autocmd_event(
|
||||
event_T event,
|
||||
char_u *pat,
|
||||
int once,
|
||||
int nested,
|
||||
char_u *cmd,
|
||||
int forceit,
|
||||
@@ -1212,6 +1256,7 @@ do_autocmd_event(
|
||||
}
|
||||
ac->next = NULL;
|
||||
*prev_ac = ac;
|
||||
ac->once = once;
|
||||
ac->nested = nested;
|
||||
}
|
||||
}
|
||||
@@ -2319,6 +2364,9 @@ getnextac(int c UNUSED, void *cookie, int indent UNUSED)
|
||||
verbose_leave_scroll();
|
||||
}
|
||||
retval = vim_strsave(ac->cmd);
|
||||
// Remove one-shot ("once") autocmd in anticipation of its execution.
|
||||
if (ac->once)
|
||||
au_del_cmd(ac);
|
||||
autocmd_nested = ac->nested;
|
||||
#ifdef FEAT_EVAL
|
||||
current_sctx = ac->script_ctx;
|
||||
|
||||
Reference in New Issue
Block a user