mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
autocmd: introduce "once" feature
Adds a new feature to :autocmd which sets the handler to be executed at most one times. Before: augroup FooGroup autocmd! autocmd FileType foo call Foo() | autocmd! FooGroup * <buffer> augroup END After: autocmd FileType foo once call Foo()
This commit is contained in:
parent
092e7e6c60
commit
c12cf5bde7
@ -40,15 +40,18 @@ effects. Be careful not to destroy your text.
|
|||||||
2. Defining autocommands *autocmd-define*
|
2. Defining autocommands *autocmd-define*
|
||||||
|
|
||||||
*:au* *:autocmd*
|
*:au* *:autocmd*
|
||||||
:au[tocmd] [group] {event} {pat} [nested] {cmd}
|
:au[tocmd] [group] {event} {pat} [once] [nested] {cmd}
|
||||||
Add {cmd} to the list of commands that Vim will
|
Add {cmd} to the list of commands that Vim will
|
||||||
execute automatically on {event} for a file matching
|
execute automatically on {event} for a file matching
|
||||||
{pat} |autocmd-patterns|.
|
{pat} |autocmd-patterns|.
|
||||||
Note: A quote character is seen as argument to the
|
Note: A quote character is seen as argument to the
|
||||||
:autocmd and won't start a comment.
|
:autocmd and won't start a comment.
|
||||||
Vim always adds the {cmd} after existing autocommands,
|
Nvim always adds {cmd} after existing autocommands so
|
||||||
so that the autocommands execute in the order in which
|
they execute in the order in which they were defined.
|
||||||
they were given. See |autocmd-nested| for [nested].
|
See |autocmd-nested| for [nested].
|
||||||
|
*autocmd-once*
|
||||||
|
If [once] is supplied the command is executed once,
|
||||||
|
then removed ("one shot").
|
||||||
|
|
||||||
The special pattern <buffer> or <buffer=N> defines a buffer-local autocommand.
|
The special pattern <buffer> or <buffer=N> defines a buffer-local autocommand.
|
||||||
See |autocmd-buflocal|.
|
See |autocmd-buflocal|.
|
||||||
@ -116,10 +119,11 @@ prompt. When one command outputs two messages this can happen anyway.
|
|||||||
==============================================================================
|
==============================================================================
|
||||||
3. Removing autocommands *autocmd-remove*
|
3. Removing autocommands *autocmd-remove*
|
||||||
|
|
||||||
:au[tocmd]! [group] {event} {pat} [nested] {cmd}
|
:au[tocmd]! [group] {event} {pat} [once] [nested] {cmd}
|
||||||
Remove all autocommands associated with {event} and
|
Remove all autocommands associated with {event} and
|
||||||
{pat}, and add the command {cmd}. See
|
{pat}, and add the command {cmd}.
|
||||||
|autocmd-nested| for [nested].
|
See |autocmd-once| for [once].
|
||||||
|
See |autocmd-nested| for [nested].
|
||||||
|
|
||||||
:au[tocmd]! [group] {event} {pat}
|
:au[tocmd]! [group] {event} {pat}
|
||||||
Remove all autocommands associated with {event} and
|
Remove all autocommands associated with {event} and
|
||||||
@ -1323,8 +1327,7 @@ option will not cause any commands to be executed.
|
|||||||
another extension. Example: >
|
another extension. Example: >
|
||||||
:au BufEnter *.cpp so ~/.config/nvim/init_cpp.vim
|
:au BufEnter *.cpp so ~/.config/nvim/init_cpp.vim
|
||||||
:au BufEnter *.cpp doau BufEnter x.c
|
:au BufEnter *.cpp doau BufEnter x.c
|
||||||
< Be careful to avoid endless loops. See
|
< Be careful to avoid endless loops. |autocmd-nested|
|
||||||
|autocmd-nested|.
|
|
||||||
|
|
||||||
When the [group] argument is not given, Vim executes
|
When the [group] argument is not given, Vim executes
|
||||||
the autocommands for all groups. When the [group]
|
the autocommands for all groups. When the [group]
|
||||||
|
@ -133,6 +133,7 @@ Command-line highlighting:
|
|||||||
removed in the future).
|
removed in the future).
|
||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
|
|:autocmd| accepts the `once` flag
|
||||||
|:checkhealth|
|
|:checkhealth|
|
||||||
|:cquit| can use [count] to set the exit code
|
|:cquit| can use [count] to set the exit code
|
||||||
|:drop| is always available
|
|:drop| is always available
|
||||||
|
@ -20160,7 +20160,7 @@ void ex_function(exarg_T *eap)
|
|||||||
skip_until = vim_strsave((char_u *)".");
|
skip_until = vim_strsave((char_u *)".");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for ":python <<EOF", ":lua <<EOF", etc.
|
// heredoc: Check for ":python <<EOF", ":lua <<EOF", etc.
|
||||||
arg = skipwhite(skiptowhite(p));
|
arg = skipwhite(skiptowhite(p));
|
||||||
if (arg[0] == '<' && arg[1] =='<'
|
if (arg[0] == '<' && arg[1] =='<'
|
||||||
&& ((p[0] == 'p' && p[1] == 'y'
|
&& ((p[0] == 'p' && p[1] == 'y'
|
||||||
|
@ -99,8 +99,9 @@
|
|||||||
// defined and will have to be executed.
|
// defined and will have to be executed.
|
||||||
//
|
//
|
||||||
typedef struct AutoCmd {
|
typedef struct AutoCmd {
|
||||||
char_u *cmd; // The command to be executed (NULL
|
char_u *cmd; // Command to be executed (NULL when
|
||||||
// when command has been removed)
|
// command has been removed)
|
||||||
|
bool once; // "One shot": removed after execution
|
||||||
char nested; // If autocommands nest here
|
char nested; // If autocommands nest here
|
||||||
char last; // last command in list
|
char last; // last command in list
|
||||||
scid_T scriptID; // script ID where defined
|
scid_T scriptID; // script ID where defined
|
||||||
@ -121,20 +122,20 @@ typedef struct AutoPat {
|
|||||||
char last; // last pattern for apply_autocmds()
|
char last; // last pattern for apply_autocmds()
|
||||||
} AutoPat;
|
} AutoPat;
|
||||||
|
|
||||||
/*
|
///
|
||||||
* struct used to keep status while executing autocommands for an event.
|
/// Struct used to keep status while executing autocommands for an event.
|
||||||
*/
|
///
|
||||||
typedef struct AutoPatCmd {
|
typedef struct AutoPatCmd {
|
||||||
AutoPat *curpat; /* next AutoPat to examine */
|
AutoPat *curpat; // next AutoPat to examine
|
||||||
AutoCmd *nextcmd; /* next AutoCmd to execute */
|
AutoCmd *nextcmd; // next AutoCmd to execute
|
||||||
int group; /* group being used */
|
int group; // group being used
|
||||||
char_u *fname; /* fname to match with */
|
char_u *fname; // fname to match with
|
||||||
char_u *sfname; /* sfname to match with */
|
char_u *sfname; // sfname to match with
|
||||||
char_u *tail; /* tail of fname */
|
char_u *tail; // tail of fname
|
||||||
event_T event; /* current event */
|
event_T event; // current event
|
||||||
int arg_bufnr; /* initially equal to <abuf>, set to zero when
|
int arg_bufnr; // initially equal to <abuf>, set to zero when
|
||||||
buf is deleted */
|
// buf is deleted
|
||||||
struct AutoPatCmd *next; /* chain of active apc-s for auto-invalidation*/
|
struct AutoPatCmd *next; // chain of active apc-s for auto-invalidation
|
||||||
} AutoPatCmd;
|
} AutoPatCmd;
|
||||||
|
|
||||||
#define AUGROUP_DEFAULT -1 /* default autocmd group */
|
#define AUGROUP_DEFAULT -1 /* default autocmd group */
|
||||||
@ -5563,29 +5564,31 @@ static void show_autocmd(AutoPat *ap, event_T event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Mark an autocommand handler for deletion.
|
||||||
* Mark an autocommand pattern for deletion.
|
|
||||||
*/
|
|
||||||
static void au_remove_pat(AutoPat *ap)
|
static void au_remove_pat(AutoPat *ap)
|
||||||
{
|
{
|
||||||
xfree(ap->pat);
|
xfree(ap->pat);
|
||||||
ap->pat = NULL;
|
ap->pat = NULL;
|
||||||
ap->buflocal_nr = -1;
|
ap->buflocal_nr = -1;
|
||||||
au_need_clean = TRUE;
|
au_need_clean = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Mark all commands for a pattern for deletion.
|
||||||
* Mark all commands for a pattern for deletion.
|
|
||||||
*/
|
|
||||||
static void au_remove_cmds(AutoPat *ap)
|
static void au_remove_cmds(AutoPat *ap)
|
||||||
{
|
{
|
||||||
AutoCmd *ac;
|
for (AutoCmd *ac = ap->cmds; ac != NULL; ac = ac->next) {
|
||||||
|
|
||||||
for (ac = ap->cmds; ac != NULL; ac = ac->next) {
|
|
||||||
xfree(ac->cmd);
|
xfree(ac->cmd);
|
||||||
ac->cmd = NULL;
|
ac->cmd = NULL;
|
||||||
}
|
}
|
||||||
au_need_clean = TRUE;
|
au_need_clean = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete one command from an autocmd pattern.
|
||||||
|
static void au_del_cmd(AutoCmd *ac)
|
||||||
|
{
|
||||||
|
xfree(ac->cmd);
|
||||||
|
ac->cmd = NULL;
|
||||||
|
au_need_clean = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -5674,18 +5677,18 @@ void aubuflocal_remove(buf_T *buf)
|
|||||||
au_cleanup();
|
au_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Add an autocmd group name.
|
||||||
* Add an autocmd group name.
|
// Return its ID. Returns AUGROUP_ERROR (< 0) for error.
|
||||||
* Return it's ID. Returns AUGROUP_ERROR (< 0) for error.
|
|
||||||
*/
|
|
||||||
static int au_new_group(char_u *name)
|
static int au_new_group(char_u *name)
|
||||||
{
|
{
|
||||||
int i = au_find_group(name);
|
int i = au_find_group(name);
|
||||||
if (i == AUGROUP_ERROR) { /* the group doesn't exist yet, add it */
|
if (i == AUGROUP_ERROR) { // the group doesn't exist yet, add it.
|
||||||
/* First try using a free entry. */
|
// First try using a free entry.
|
||||||
for (i = 0; i < augroups.ga_len; ++i)
|
for (i = 0; i < augroups.ga_len; i++) {
|
||||||
if (AUGROUP_NAME(i) == NULL)
|
if (AUGROUP_NAME(i) == NULL) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (i == augroups.ga_len) {
|
if (i == augroups.ga_len) {
|
||||||
ga_grow(&augroups, 1);
|
ga_grow(&augroups, 1);
|
||||||
}
|
}
|
||||||
@ -5701,9 +5704,7 @@ static int au_new_group(char_u *name)
|
|||||||
|
|
||||||
static void au_del_group(char_u *name)
|
static void au_del_group(char_u *name)
|
||||||
{
|
{
|
||||||
int i;
|
int i = au_find_group(name);
|
||||||
|
|
||||||
i = au_find_group(name);
|
|
||||||
if (i == AUGROUP_ERROR) { // the group doesn't exist
|
if (i == AUGROUP_ERROR) { // the group doesn't exist
|
||||||
EMSG2(_("E367: No such group: \"%s\""), name);
|
EMSG2(_("E367: No such group: \"%s\""), name);
|
||||||
} else if (i == current_augroup) {
|
} else if (i == current_augroup) {
|
||||||
@ -5760,23 +5761,22 @@ bool au_has_group(const char_u *name)
|
|||||||
return au_find_group(name) != AUGROUP_ERROR;
|
return au_find_group(name) != AUGROUP_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/// ":augroup {name}".
|
||||||
* ":augroup {name}".
|
|
||||||
*/
|
|
||||||
void do_augroup(char_u *arg, int del_group)
|
void do_augroup(char_u *arg, int del_group)
|
||||||
{
|
{
|
||||||
if (del_group) {
|
if (del_group) {
|
||||||
if (*arg == NUL)
|
if (*arg == NUL) {
|
||||||
EMSG(_(e_argreq));
|
EMSG(_(e_argreq));
|
||||||
else
|
} else {
|
||||||
au_del_group(arg);
|
au_del_group(arg);
|
||||||
} else if (STRICMP(arg, "end") == 0) /* ":aug end": back to group 0 */
|
}
|
||||||
|
} else if (STRICMP(arg, "end") == 0) { // ":aug end": back to group 0
|
||||||
current_augroup = AUGROUP_DEFAULT;
|
current_augroup = AUGROUP_DEFAULT;
|
||||||
else if (*arg) { /* ":aug xxx": switch to group xxx */
|
} else if (*arg) { // ":aug xxx": switch to group xxx
|
||||||
int i = au_new_group(arg);
|
int i = au_new_group(arg);
|
||||||
if (i != AUGROUP_ERROR)
|
if (i != AUGROUP_ERROR)
|
||||||
current_augroup = i;
|
current_augroup = i;
|
||||||
} else { /* ":aug": list the group names */
|
} else { // ":aug": list the group names
|
||||||
msg_start();
|
msg_start();
|
||||||
for (int i = 0; i < augroups.ga_len; ++i) {
|
for (int i = 0; i < augroups.ga_len; ++i) {
|
||||||
if (AUGROUP_NAME(i) != NULL) {
|
if (AUGROUP_NAME(i) != NULL) {
|
||||||
@ -5957,38 +5957,38 @@ void au_event_restore(char_u *old_ei)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Implements :autocmd.
|
||||||
* do_autocmd() -- implements the :autocmd command. Can be used in the
|
// Defines an autocmd (does not execute; cf. apply_autocmds_group).
|
||||||
* following ways:
|
//
|
||||||
*
|
// Can be used in the following ways:
|
||||||
* :autocmd <event> <pat> <cmd> Add <cmd> to the list of commands that
|
//
|
||||||
* will be automatically executed for <event>
|
// :autocmd <event> <pat> <cmd> Add <cmd> to the list of commands that
|
||||||
* when editing a file matching <pat>, in
|
// will be automatically executed for <event>
|
||||||
* the current group.
|
// when editing a file matching <pat>, in
|
||||||
* :autocmd <event> <pat> Show the autocommands associated with
|
// the current group.
|
||||||
* <event> and <pat>.
|
// :autocmd <event> <pat> Show the autocommands associated with
|
||||||
* :autocmd <event> Show the autocommands associated with
|
// <event> and <pat>.
|
||||||
* <event>.
|
// :autocmd <event> Show the autocommands associated with
|
||||||
* :autocmd Show all autocommands.
|
// <event>.
|
||||||
* :autocmd! <event> <pat> <cmd> Remove all autocommands associated with
|
// :autocmd Show all autocommands.
|
||||||
* <event> and <pat>, and add the command
|
// :autocmd! <event> <pat> <cmd> Remove all autocommands associated with
|
||||||
* <cmd>, for the current group.
|
// <event> and <pat>, and add the command
|
||||||
* :autocmd! <event> <pat> Remove all autocommands associated with
|
// <cmd>, for the current group.
|
||||||
* <event> and <pat> for the current group.
|
// :autocmd! <event> <pat> Remove all autocommands associated with
|
||||||
* :autocmd! <event> Remove all autocommands associated with
|
// <event> and <pat> for the current group.
|
||||||
* <event> for the current group.
|
// :autocmd! <event> Remove all autocommands associated with
|
||||||
* :autocmd! Remove ALL autocommands for the current
|
// <event> for the current group.
|
||||||
* group.
|
// :autocmd! Remove ALL autocommands for the current
|
||||||
*
|
// group.
|
||||||
* Multiple events and patterns may be given separated by commas. Here are
|
//
|
||||||
* some examples:
|
// Multiple events and patterns may be given separated by commas. Here are
|
||||||
* :autocmd bufread,bufenter *.c,*.h set tw=0 smartindent noic
|
// some examples:
|
||||||
* :autocmd bufleave * set tw=79 nosmartindent ic infercase
|
// :autocmd bufread,bufenter *.c,*.h set tw=0 smartindent noic
|
||||||
*
|
// :autocmd bufleave * set tw=79 nosmartindent ic infercase
|
||||||
* :autocmd * *.c show all autocommands for *.c files.
|
//
|
||||||
*
|
// :autocmd * *.c show all autocommands for *.c files.
|
||||||
* Mostly a {group} argument can optionally appear before <event>.
|
//
|
||||||
*/
|
// Mostly a {group} argument can optionally appear before <event>.
|
||||||
void do_autocmd(char_u *arg_in, int forceit)
|
void do_autocmd(char_u *arg_in, int forceit)
|
||||||
{
|
{
|
||||||
char_u *arg = arg_in;
|
char_u *arg = arg_in;
|
||||||
@ -5997,6 +5997,7 @@ void do_autocmd(char_u *arg_in, int forceit)
|
|||||||
char_u *cmd;
|
char_u *cmd;
|
||||||
int need_free = false;
|
int need_free = false;
|
||||||
int nested = false;
|
int nested = false;
|
||||||
|
bool once = false;
|
||||||
int group;
|
int group;
|
||||||
|
|
||||||
if (*arg == '|') {
|
if (*arg == '|') {
|
||||||
@ -6046,6 +6047,14 @@ void do_autocmd(char_u *arg_in, int forceit)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for "once" flag.
|
||||||
|
cmd = skipwhite(cmd);
|
||||||
|
if (*cmd != NUL && STRNCMP(cmd, "once", 4) == 0
|
||||||
|
&& ascii_iswhite(cmd[4])) {
|
||||||
|
once = true;
|
||||||
|
cmd = skipwhite(cmd + 4);
|
||||||
|
}
|
||||||
|
|
||||||
// Check for "nested" flag.
|
// Check for "nested" flag.
|
||||||
cmd = skipwhite(cmd);
|
cmd = skipwhite(cmd);
|
||||||
if (*cmd != NUL && STRNCMP(cmd, "nested", 6) == 0
|
if (*cmd != NUL && STRNCMP(cmd, "nested", 6) == 0
|
||||||
@ -6081,7 +6090,8 @@ void do_autocmd(char_u *arg_in, int forceit)
|
|||||||
if (*arg == '*' || *arg == NUL || *arg == '|') {
|
if (*arg == '*' || *arg == NUL || *arg == '|') {
|
||||||
for (event_T event = (event_T)0; (int)event < (int)NUM_EVENTS;
|
for (event_T event = (event_T)0; (int)event < (int)NUM_EVENTS;
|
||||||
event = (event_T)((int)event + 1)) {
|
event = (event_T)((int)event + 1)) {
|
||||||
if (do_autocmd_event(event, pat, nested, cmd, forceit, group) == FAIL) {
|
if (do_autocmd_event(event, pat, once, nested, cmd, forceit, group)
|
||||||
|
== FAIL) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6089,7 +6099,8 @@ void do_autocmd(char_u *arg_in, int forceit)
|
|||||||
while (*arg && *arg != '|' && !ascii_iswhite(*arg)) {
|
while (*arg && *arg != '|' && !ascii_iswhite(*arg)) {
|
||||||
event_T event = event_name2nr(arg, &arg);
|
event_T event = event_name2nr(arg, &arg);
|
||||||
assert(event < NUM_EVENTS);
|
assert(event < NUM_EVENTS);
|
||||||
if (do_autocmd_event(event, pat, nested, cmd, forceit, group) == FAIL) {
|
if (do_autocmd_event(event, pat, once, nested, cmd, forceit, group)
|
||||||
|
== FAIL) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6127,14 +6138,15 @@ static int au_get_grouparg(char_u **argp)
|
|||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// do_autocmd() for one event.
|
||||||
* do_autocmd() for one event.
|
// Defines an autocmd (does not execute; cf. apply_autocmds_group).
|
||||||
* If *pat == NUL do for all patterns.
|
//
|
||||||
* If *cmd == NUL show entries.
|
// If *pat == NUL: do for all patterns.
|
||||||
* If forceit == TRUE delete entries.
|
// If *cmd == NUL: show entries.
|
||||||
* If group is not AUGROUP_ALL, only use this group.
|
// If forceit == TRUE: delete entries.
|
||||||
*/
|
// If group is not AUGROUP_ALL: only use this group.
|
||||||
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, bool once, int nested,
|
||||||
|
char_u *cmd, int forceit, int group)
|
||||||
{
|
{
|
||||||
AutoPat *ap;
|
AutoPat *ap;
|
||||||
AutoPat **prev_ap;
|
AutoPat **prev_ap;
|
||||||
@ -6333,6 +6345,7 @@ static int do_autocmd_event(event_T event, char_u *pat, int nested, char_u *cmd,
|
|||||||
ac->scriptID = current_SID;
|
ac->scriptID = current_SID;
|
||||||
ac->next = NULL;
|
ac->next = NULL;
|
||||||
*prev_ac = ac;
|
*prev_ac = ac;
|
||||||
|
ac->once = once;
|
||||||
ac->nested = nested;
|
ac->nested = nested;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6996,7 +7009,7 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io,
|
|||||||
patcmd.event = event;
|
patcmd.event = event;
|
||||||
patcmd.arg_bufnr = autocmd_bufnr;
|
patcmd.arg_bufnr = autocmd_bufnr;
|
||||||
patcmd.next = NULL;
|
patcmd.next = NULL;
|
||||||
auto_next_pat(&patcmd, FALSE);
|
auto_next_pat(&patcmd, false);
|
||||||
|
|
||||||
/* found one, start executing the autocommands */
|
/* found one, start executing the autocommands */
|
||||||
if (patcmd.curpat != NULL) {
|
if (patcmd.curpat != NULL) {
|
||||||
@ -7020,8 +7033,11 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io,
|
|||||||
}
|
}
|
||||||
ap->last = true;
|
ap->last = true;
|
||||||
check_lnums(true); // make sure cursor and topline are valid
|
check_lnums(true); // make sure cursor and topline are valid
|
||||||
|
|
||||||
|
// Execute the autocmd. The `getnextac` callback handles iteration.
|
||||||
do_cmdline(NULL, getnextac, (void *)&patcmd,
|
do_cmdline(NULL, getnextac, (void *)&patcmd,
|
||||||
DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
|
DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
|
||||||
|
|
||||||
if (eap != NULL) {
|
if (eap != NULL) {
|
||||||
(void)set_cmdarg(NULL, save_cmdarg);
|
(void)set_cmdarg(NULL, save_cmdarg);
|
||||||
set_vim_var_nr(VV_CMDBANG, save_cmdbang);
|
set_vim_var_nr(VV_CMDBANG, save_cmdbang);
|
||||||
@ -7233,12 +7249,18 @@ char_u *getnextac(int c, void *cookie, int indent)
|
|||||||
verbose_leave_scroll();
|
verbose_leave_scroll();
|
||||||
}
|
}
|
||||||
retval = vim_strsave(ac->cmd);
|
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;
|
autocmd_nested = ac->nested;
|
||||||
current_SID = ac->scriptID;
|
current_SID = ac->scriptID;
|
||||||
if (ac->last)
|
if (ac->last) {
|
||||||
acp->nextcmd = NULL;
|
acp->nextcmd = NULL;
|
||||||
else
|
} else {
|
||||||
acp->nextcmd = ac->next;
|
acp->nextcmd = ac->next;
|
||||||
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
local helpers = require('test.functional.helpers')(after_each)
|
local helpers = require('test.functional.helpers')(after_each)
|
||||||
|
|
||||||
|
local dedent = helpers.dedent
|
||||||
local eq = helpers.eq
|
local eq = helpers.eq
|
||||||
local eval = helpers.eval
|
local eval = helpers.eval
|
||||||
|
local feed = helpers.feed
|
||||||
local clear = helpers.clear
|
local clear = helpers.clear
|
||||||
local meths = helpers.meths
|
local meths = helpers.meths
|
||||||
|
local funcs = helpers.funcs
|
||||||
local expect = helpers.expect
|
local expect = helpers.expect
|
||||||
local command = helpers.command
|
local command = helpers.command
|
||||||
local exc_exec = helpers.exc_exec
|
local exc_exec = helpers.exc_exec
|
||||||
local curbufmeths = helpers.curbufmeths
|
local curbufmeths = helpers.curbufmeths
|
||||||
|
|
||||||
describe('autocmds:', function()
|
describe('autocmd', function()
|
||||||
before_each(clear)
|
before_each(clear)
|
||||||
|
|
||||||
it(':tabnew triggers events in the correct order', function()
|
it(':tabnew triggers events in the correct order', function()
|
||||||
@ -55,4 +58,72 @@ describe('autocmds:', function()
|
|||||||
end of test file xx]])
|
end of test file xx]])
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('once', function() -- :help autocmd-once
|
||||||
|
--
|
||||||
|
-- ":autocmd ... once" executes its handler once, then removes the handler.
|
||||||
|
--
|
||||||
|
local expected = {
|
||||||
|
'Many1',
|
||||||
|
'Once1',
|
||||||
|
'Once2',
|
||||||
|
'Many2',
|
||||||
|
'Once3',
|
||||||
|
'Many1',
|
||||||
|
'Many2',
|
||||||
|
'Many1',
|
||||||
|
'Many2',
|
||||||
|
}
|
||||||
|
command('let g:foo = []')
|
||||||
|
command('autocmd TabNew * :call add(g:foo, "Many1")')
|
||||||
|
command('autocmd TabNew * once :call add(g:foo, "Once1")')
|
||||||
|
command('autocmd TabNew * once :call add(g:foo, "Once2")')
|
||||||
|
command('autocmd TabNew * :call add(g:foo, "Many2")')
|
||||||
|
command('autocmd TabNew * once :call add(g:foo, "Once3")')
|
||||||
|
eq(dedent([[
|
||||||
|
|
||||||
|
--- Autocommands ---
|
||||||
|
TabNew
|
||||||
|
* :call add(g:foo, "Many1")
|
||||||
|
:call add(g:foo, "Once1")
|
||||||
|
:call add(g:foo, "Once2")
|
||||||
|
:call add(g:foo, "Many2")
|
||||||
|
:call add(g:foo, "Once3")]]),
|
||||||
|
funcs.execute('autocmd Tabnew'))
|
||||||
|
command('tabnew')
|
||||||
|
command('tabnew')
|
||||||
|
command('tabnew')
|
||||||
|
eq(expected, eval('g:foo'))
|
||||||
|
eq(dedent([[
|
||||||
|
|
||||||
|
--- Autocommands ---
|
||||||
|
TabNew
|
||||||
|
* :call add(g:foo, "Many1")
|
||||||
|
:call add(g:foo, "Many2")]]),
|
||||||
|
funcs.execute('autocmd Tabnew'))
|
||||||
|
|
||||||
|
--
|
||||||
|
-- ":autocmd ... once" handlers can be deleted.
|
||||||
|
--
|
||||||
|
expected = {}
|
||||||
|
command('let g:foo = []')
|
||||||
|
command('autocmd TabNew * once :call add(g:foo, "Once1")')
|
||||||
|
command('autocmd! TabNew')
|
||||||
|
command('tabnew')
|
||||||
|
eq(expected, eval('g:foo'))
|
||||||
|
|
||||||
|
--
|
||||||
|
-- ":autocmd ... <buffer> once nested"
|
||||||
|
--
|
||||||
|
expected = {
|
||||||
|
'OptionSet-Once',
|
||||||
|
'CursorMoved-Once',
|
||||||
|
}
|
||||||
|
command('let g:foo = []')
|
||||||
|
command('autocmd OptionSet binary once nested :call add(g:foo, "OptionSet-Once")')
|
||||||
|
command('autocmd CursorMoved <buffer> once nested setlocal binary|:call add(g:foo, "CursorMoved-Once")')
|
||||||
|
command("put ='foo bar baz'")
|
||||||
|
feed('0llhlh')
|
||||||
|
eq(expected, eval('g:foo'))
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
Loading…
Reference in New Issue
Block a user