Monday, August 31, 2009

au_exists bug, was Re: Test Existence of Autocommand?

On Tue, Aug 25, 2009 at 11:38 AM, Ben Fritz<fritzophrenic@gmail.com> wrote:
>> On Fri, Aug 14, 2009 at 6:38 PM, Edward Beach<beach9...@hotmail.com> wrote:
>> > I'm trying to write a script that will toggle an autocommand on/off
>> > and I'm looking for a function to return it's existence.  I've found
>> > the built-in exists function and from the help it gives me this:
>> >                        #group#event    autocommand defined for this group and event.
>> > So from my command line I enter in the following
>> >        :aug TestGroup | aug END | echo exists("#TestGroup#BufWritePost")
>> > and it comes back 1 -- but shouldn't it be 0 since I haven't created a
>> > BufWritePost event and since
>> >        :au TestGroup
>> > returns nothing?
>>
>> It looks like the #group#event code doesn't check for an autocommand
>> for that event being defined *within* the group, just whether both the
>> group and the autocommand exist.  The #group#event#pattern does check
>> for an autocommand defined within the specified group, though, so that
>> may be helpful to you.

> Since this is a patch for some VERY unexpected behavior, I'm cc'ing
> vim_dev where such things are normally discussed.
>
> My opinion is that this is a bug, if it can be reliably reproduced. I
> can't imagine any situation where the described behavior would be
> helpful.

Here's a probably better patch, and a test case to show the behavior I
expect from exists() with respect to autocommands:

diff --git a/src/fileio.c b/src/fileio.c
index a9552b5..5da1a96 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -9498,15 +9498,10 @@ au_exists(arg)
ap = first_autopat[(int)event];
if (ap == NULL)
goto theend;
- if (pattern == NULL)
- {
- retval = TRUE;
- goto theend;
- }

/* if pattern is "<buffer>", special handling is needed which
uses curbuf */
/* for pattern "<buffer=N>, fnamecmp() will work fine */
- if (STRICMP(pattern, "<buffer>") == 0)
+ if (pattern != NULL && STRICMP(pattern, "<buffer>") == 0)
buflocal_buf = curbuf;

/* Check if there is an autocommand with the given pattern. */
@@ -9515,9 +9510,10 @@ au_exists(arg)
/* For buffer-local autocommands, fnamecmp() works fine. */
if (ap->pat != NULL && ap->cmds != NULL
&& (group == AUGROUP_ALL || ap->group == group)
- && (buflocal_buf == NULL
- ? fnamecmp(ap->pat, pattern) == 0
- : ap->buflocal_nr == buflocal_buf->b_fnum))
+ && (pattern == NULL
+ || (buflocal_buf == NULL
+ ? fnamecmp(ap->pat, pattern) == 0
+ : ap->buflocal_nr == buflocal_buf->b_fnum)))
{
retval = TRUE;
break;

unpatched testcase results:

$ /usr/bin/vim -u ~/testcase.vim
BufEnter is a valid event (should be true) : 1
BufEnter defined generally (should be false) : 0
BufEnter defined generally (should be true) : 1
BufEnter defined in 'auexists' group (should be false) : 1
BufEnter defined in 'auexists' group (should be true) : 1
BufEnter defined for *.test (should be false) : 0
BufEnter defined for *.test (should be true) : 1
BufEnter defined for local buffer (should be false) : 0
BufEnter defined for local buffer (should be true) : 1


patched testcase results:

$ vim -u ~/testcase.vim
BufEnter is a valid event (should be true) : 1
BufEnter defined generally (should be false) : 0
BufEnter defined generally (should be true) : 1
BufEnter defined in 'auexists' group (should be false) : 0
BufEnter defined in 'auexists' group (should be true) : 1
BufEnter defined for *.test (should be false) : 0
BufEnter defined for *.test (should be true) : 1
BufEnter defined for local buffer (should be false) : 0
BufEnter defined for local buffer (should be true) : 1

testcase.vim:

augroup auexists
augroup END
echomsg "BufEnter is a valid event (should be true) : " exists("##BufEnter")
echomsg "BufEnter defined generally (should be false) : " exists("#BufEnter")
au BufEnter * let g:entered=1
echomsg "BufEnter defined generally (should be true) : " exists("#BufEnter")
echomsg "BufEnter defined in 'auexists' group (should be false) : "
exists("#auexists#BufEnter")
augroup auexists
au BufEnter * let g:entered=1
augroup END
echomsg "BufEnter defined in 'auexists' group (should be true) : "
exists("#auexists#BufEnter")
echomsg "BufEnter defined for *.test (should be false) : "
exists("#BufEnter#*.test")
au BufEnter *.test let g:entered=1
echomsg "BufEnter defined for *.test (should be true) : "
exists("#BufEnter#*.test")
silent edit testfile.test
echomsg "BufEnter defined for local buffer (should be false) : "
exists("#BufEnter#<buffer>")
au BufEnter <buffer> let g:entered=1
echomsg "BufEnter defined for local buffer (should be true) : "
exists("#BufEnter#<buffer>")


Thank you,

bob

--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_use" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---

No comments: