diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2019-03-15 12:38:53 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-15 12:38:53 +0100 |
commit | 1baf4edbd97539a7d331e350d23de35eeabf68b6 (patch) | |
tree | 42ab813ad2cb35113519a371a976adfacd82518a | |
parent | 680252aa15159f0e969f6d169d01a8fbad097fa4 (diff) | |
parent | b1f25ea18797101f423cab23ac52c4e17377c5d4 (diff) | |
download | rneovim-1baf4edbd97539a7d331e350d23de35eeabf68b6.tar.gz rneovim-1baf4edbd97539a7d331e350d23de35eeabf68b6.tar.bz2 rneovim-1baf4edbd97539a7d331e350d23de35eeabf68b6.zip |
Merge #9728 from justinmk/autocmd-once
-rw-r--r-- | runtime/doc/autocmd.txt | 16 | ||||
-rw-r--r-- | runtime/doc/nvim_terminal_emulator.txt | 2 | ||||
-rw-r--r-- | runtime/doc/usr_40.txt | 8 | ||||
-rw-r--r-- | runtime/doc/vim_diff.txt | 2 | ||||
-rw-r--r-- | runtime/doc/windows.txt | 8 | ||||
-rw-r--r-- | src/nvim/fileio.c | 52 | ||||
-rw-r--r-- | src/nvim/tui/input.c | 4 | ||||
-rw-r--r-- | test/functional/autocmd/autocmd_spec.lua | 38 |
8 files changed, 79 insertions, 51 deletions
diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt index b0b36271e9..4372342c02 100644 --- a/runtime/doc/autocmd.txt +++ b/runtime/doc/autocmd.txt @@ -40,7 +40,7 @@ effects. Be careful not to destroy your text. 2. Defining autocommands *autocmd-define* *:au* *:autocmd* -:au[tocmd] [group] {event} {pat} [-once] [-nested] {cmd} +:au[tocmd] [group] {event} {pat} [++once] [++nested] {cmd} Add {cmd} to the list of commands that Vim will execute automatically on {event} for a file matching {pat} |autocmd-patterns|. @@ -48,9 +48,9 @@ effects. Be careful not to destroy your text. :autocmd and won't start a comment. Nvim always adds {cmd} after existing autocommands so they execute in the order in which they were defined. - See |autocmd-nested| for [-nested]. + See |autocmd-nested| for [++nested]. *autocmd-once* - If [-once] is supplied the command is executed 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. @@ -119,11 +119,11 @@ prompt. When one command outputs two messages this can happen anyway. ============================================================================== 3. Removing autocommands *autocmd-remove* -:au[tocmd]! [group] {event} {pat} [-once] [-nested] {cmd} +:au[tocmd]! [group] {event} {pat} [++once] [++nested] {cmd} Remove all autocommands associated with {event} and {pat}, and add the command {cmd}. - See |autocmd-once| for [-once]. - See |autocmd-nested| for [-nested]. + See |autocmd-once| for [++once]. + See |autocmd-nested| for [++nested]. :au[tocmd]! [group] {event} {pat} Remove all autocommands associated with {event} and @@ -1446,9 +1446,9 @@ instead of ":q!". *autocmd-nested* *E218* By default, autocommands do not nest. If you use ":e" or ":w" in an autocommand, Vim does not execute the BufRead and BufWrite autocommands for -those commands. If you do want this, use the "-nested" flag for those +those commands. If you do want this, use the "++nested" flag for those commands in which you want nesting. For example: > - :autocmd FileChangedShell *.c -nested e! + :autocmd FileChangedShell *.c ++nested e! The nesting is limited to 10 levels to get out of recursive loops. It's possible to use the ":au" command in an autocommand. This can be a diff --git a/runtime/doc/nvim_terminal_emulator.txt b/runtime/doc/nvim_terminal_emulator.txt index 2eaaf82934..af94c60629 100644 --- a/runtime/doc/nvim_terminal_emulator.txt +++ b/runtime/doc/nvim_terminal_emulator.txt @@ -35,7 +35,7 @@ There are 3 ways to create a terminal buffer: < Note: The "term://" pattern is handled by a BufReadCmd handler, so the |autocmd-nested| modifier is required to use it in an autocmd. > - autocmd VimEnter * -nested split term://sh + autocmd VimEnter * ++nested split term://sh < This is only mentioned for reference; use |:terminal| instead. When the terminal starts, the buffer contents are updated and the buffer is diff --git a/runtime/doc/usr_40.txt b/runtime/doc/usr_40.txt index abb4a1dbfa..9a1fe50f31 100644 --- a/runtime/doc/usr_40.txt +++ b/runtime/doc/usr_40.txt @@ -453,14 +453,14 @@ matching BufWritePre autocommands and executes them, and then it performs the ":write". The general form of the :autocmd command is as follows: > - :autocmd [group] {events} {file_pattern} [-nested] {command} + :autocmd [group] {events} {file_pattern} [++nested] {command} The [group] name is optional. It is used in managing and calling the commands (more on this later). The {events} parameter is a list of events (comma separated) that trigger the command. {file_pattern} is a filename, usually with wildcards. For example, using "*.txt" makes the autocommand be used for all files whose name end in ".txt". -The optional [-nested] flag allows for nesting of autocommands (see below), +The optional [++nested] flag allows for nesting of autocommands (see below), and finally, {command} is the command to be executed. @@ -576,9 +576,9 @@ NESTING Generally, commands executed as the result of an autocommand event will not trigger any new events. If you read a file in response to a FileChangedShell event, it will not trigger the autocommands that would set the syntax, for -example. To make the events triggered, add the "-nested" flag: > +example. To make the events triggered, add the "++nested" flag: > - :autocmd FileChangedShell * -nested edit + :autocmd FileChangedShell * ++nested edit EXECUTING AUTOCOMMANDS diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index 3b5a5cded2..55c3be9a57 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -133,7 +133,7 @@ Command-line highlighting: removed in the future). Commands: - |:autocmd| accepts the `once` flag + |:autocmd| accepts the `++once` flag |:checkhealth| |:cquit| can use [count] to set the exit code |:drop| is always available diff --git a/runtime/doc/windows.txt b/runtime/doc/windows.txt index 65ce72d62c..63ffd91bfc 100644 --- a/runtime/doc/windows.txt +++ b/runtime/doc/windows.txt @@ -880,15 +880,15 @@ CTRL-W g } *CTRL-W_g}* cursor. This is less clever than using |:ptag|, but you don't need a tags file and it will also find matches in system include files. Example: > - :au! CursorHold *.[ch] -nested exe "silent! psearch " . expand("<cword>") + :au! CursorHold *.[ch] ++nested exe "silent! psearch " . expand("<cword>") < Warning: This can be slow. Example *CursorHold-example* > - :au! CursorHold *.[ch] -nested exe "silent! ptag " . expand("<cword>") + :au! CursorHold *.[ch] ++nested exe "silent! ptag " . expand("<cword>") This will cause a ":ptag" to be executed for the keyword under the cursor, -when the cursor hasn't moved for the time set with 'updatetime'. "-nested" +when the cursor hasn't moved for the time set with 'updatetime'. "++nested" makes other autocommands be executed, so that syntax highlighting works in the preview window. The "silent!" avoids an error message when the tag could not be found. Also see |CursorHold|. To disable this again: > @@ -898,7 +898,7 @@ be found. Also see |CursorHold|. To disable this again: > A nice addition is to highlight the found tag, avoid the ":ptag" when there is no word under the cursor, and a few other things: > - :au! CursorHold *.[ch] -nested call PreviewWord() + :au! CursorHold *.[ch] ++nested call PreviewWord() :func PreviewWord() : if &previewwindow " don't do this in the preview window : return diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 51180c4939..7be4107c94 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -5591,39 +5591,48 @@ static void au_del_cmd(AutoCmd *ac) au_need_clean = true; } -/* - * Cleanup autocommands and patterns that have been deleted. - * This is only done when not executing autocommands. - */ +/// Cleanup autocommands and patterns that have been deleted. +/// This is only done when not executing autocommands. static void au_cleanup(void) { AutoPat *ap, **prev_ap; AutoCmd *ac, **prev_ac; event_T event; - if (autocmd_busy || !au_need_clean) + if (autocmd_busy || !au_need_clean) { return; + } - /* loop over all events */ + // Loop over all events. for (event = (event_T)0; (int)event < (int)NUM_EVENTS; event = (event_T)((int)event + 1)) { - /* loop over all autocommand patterns */ + // Loop over all autocommand patterns. prev_ap = &(first_autopat[(int)event]); for (ap = *prev_ap; ap != NULL; ap = *prev_ap) { - /* loop over all commands for this pattern */ + // Loop over all commands for this pattern. prev_ac = &(ap->cmds); + bool has_cmd = false; + for (ac = *prev_ac; ac != NULL; ac = *prev_ac) { - /* remove the command if the pattern is to be deleted or when - * the command has been marked for deletion */ + // Remove the command if the pattern is to be deleted or when + // the command has been marked for deletion. if (ap->pat == NULL || ac->cmd == NULL) { *prev_ac = ac->next; xfree(ac->cmd); xfree(ac); - } else + } else { + has_cmd = true; prev_ac = &(ac->next); + } } - /* remove the pattern if it has been marked for deletion */ + 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. if (ap->pat == NULL) { if (ap->next == NULL) { if (prev_ap == &(first_autopat[(int)event])) { @@ -5637,12 +5646,13 @@ static void au_cleanup(void) *prev_ap = ap->next; vim_regfree(ap->reg_prog); xfree(ap); - } else + } else { prev_ap = &(ap->next); + } } } - au_need_clean = FALSE; + au_need_clean = false; } /* @@ -6050,18 +6060,18 @@ void do_autocmd(char_u *arg_in, int forceit) cmd = skipwhite(cmd); for (size_t i = 0; i < 2; i++) { if (*cmd != NUL) { - // Check for "-once" flag. - if (!once && STRNCMP(cmd, "-once", 5) == 0 && ascii_iswhite(cmd[5])) { + // Check for "++once" flag. + if (!once && STRNCMP(cmd, "++once", 6) == 0 && ascii_iswhite(cmd[6])) { once = true; - cmd = skipwhite(cmd + 5); + cmd = skipwhite(cmd + 6); } - // Check for "-nested" flag. + // Check for "++nested" flag. if (!nested - && ((STRNCMP(cmd, "-nested", 7) == 0 && ascii_iswhite(cmd[7])) - // Deprecated form (without "-"). + && ((STRNCMP(cmd, "++nested", 8) == 0 && ascii_iswhite(cmd[8])) + // Deprecated form (without "++"). || (STRNCMP(cmd, "nested", 6) == 0 && ascii_iswhite(cmd[6])))) { nested = true; - cmd = skipwhite(cmd + ('-' == cmd[0] ? 7 : 6)); + cmd = skipwhite(cmd + ('+' == cmd[0] ? 8 : 6)); } } } diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c index 703feac305..0bdda17299 100644 --- a/src/nvim/tui/input.c +++ b/src/nvim/tui/input.c @@ -363,8 +363,8 @@ static void set_bg_deferred(void **argv) if (starting) { // Wait until after startup, so OptionSet is triggered. do_cmdline_cmd((bgvalue[0] == 'l') - ? "autocmd VimEnter * once nested set background=light" - : "autocmd VimEnter * once nested set background=dark"); + ? "autocmd VimEnter * ++once ++nested set bg=light" + : "autocmd VimEnter * ++once ++nested set bg=dark"); } else { set_option_value("bg", 0L, bgvalue, 0); reset_option_was_set("bg"); diff --git a/test/functional/autocmd/autocmd_spec.lua b/test/functional/autocmd/autocmd_spec.lua index 4efabd37fb..814624d8e2 100644 --- a/test/functional/autocmd/autocmd_spec.lua +++ b/test/functional/autocmd/autocmd_spec.lua @@ -59,9 +59,9 @@ describe('autocmd', function() end) end) - it('-once', function() -- :help autocmd-once + it('++once', function() -- :help autocmd-once -- - -- ":autocmd ... -once" executes its handler once, then removes the handler. + -- ":autocmd ... ++once" executes its handler once, then removes the handler. -- local expected = { 'Many1', @@ -76,10 +76,10 @@ describe('autocmd', function() } 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 * ++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")') + command('autocmd TabNew * ++once :call add(g:foo, "Once3")') eq(dedent([[ --- Autocommands --- @@ -103,27 +103,45 @@ describe('autocmd', function() funcs.execute('autocmd Tabnew')) -- - -- ":autocmd ... -once" handlers can be deleted. + -- ":autocmd ... ++once" handlers can be deleted. -- expected = {} command('let g:foo = []') - command('autocmd TabNew * -once :call add(g:foo, "Once1")') + command('autocmd TabNew * ++once :call add(g:foo, "Once1")') command('autocmd! TabNew') command('tabnew') eq(expected, eval('g:foo')) -- - -- ":autocmd ... <buffer> -once -nested" + -- ":autocmd ... <buffer> ++once ++nested" -- expected = { 'OptionSet-Once', 'CursorMoved-Once', } command('let g:foo = []') - command('autocmd OptionSet binary -nested -once :call add(g:foo, "OptionSet-Once")') - command('autocmd CursorMoved <buffer> -once -nested setlocal binary|:call add(g:foo, "CursorMoved-Once")') + command('autocmd OptionSet binary ++nested ++once :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')) + + -- + -- :autocmd should not show empty section after ++once handlers expire. + -- + expected = { + 'Once1', + 'Once2', + } + command('let g:foo = []') + command('autocmd! TabNew') -- Clear all TabNew handlers. + command('autocmd TabNew * ++once :call add(g:foo, "Once1")') + command('autocmd TabNew * ++once :call add(g:foo, "Once2")') + command('tabnew') + eq(expected, eval('g:foo')) + eq(dedent([[ + + --- Autocommands ---]]), + funcs.execute('autocmd Tabnew')) end) end) |