2

I think I observe a weird behaviour in Vim autocommands, in which opening a new buffer changes the result of past commands (!). Here is a simple example (VIM 7.3 2010 Aug 15). I just created a file test containing only the line 'disk version', then save this file to disk. Keeping this file test open in Vim, I change the text to "SWAP VERSION", without saving: now the file test has an associated swap file.

Null case:

Instead of a .vimrc, I write a init.vim file containing a single autocommand, typing out the content of a file at time of BufRead invocation:

au BufRead * %p

When I then load vim -u init.vim test and hit the r key to accept swap recovery, the autocommand prints out 'SWAP VERSION' as expected.

Strange case:

I change the autocommand in init.vim in the following way:

au BufRead * %p | new

The same procedure (vim -u init.vim test, r) now prints out 'disk version'. In other words, the new command has modified the content of the buffer at the time when the previous command was executed. Replacing the new command by an inoffensive echo returns to the "null" case.

Does any Vim wizard know what, exactly, is happening here?

(Edit) Context:

I am trying to build a (very simplified) version of recover.vim.

  • Why not use the existing plugin recover.vim? Because I'm trying to do something that is both (probably) simpler and different from what it does. Plus, this plugin uses lots of shell escapes, which is bad in my context. I would happily sacrifice functionality to get rid of these escapes.
  • I should at least look at how recover.vim does: Probably. But since it is rather complex to follow, I thought that working up from the documentation would be easier... (I will, however, have a go at older github revisions of recover.vim).
  • I'm using an old Vim version: I have no choice here (not admin and not even compile rights in this environment).
Circonflexe
  • 351
  • 1
  • 9
  • 1
    What are you trying to accomplish? Printing out the contents of a buffer is weird enough on `BufRead`, but deciding to switch the current buffer during `BufRead` is just asking for trouble. – Peter Rincker Dec 12 '14 at 18:49
  • 1
    The `%p` is only here as a debug command - this is a MWE. This is a bug (?) I found while trying to build an ad-hoc `SwapExists` command. The actual command would do many other things unimportant here, such as a `diff` between the two versions, etc. I am aware of `recover.vim`, but would prefer reinventing the wheel, for various reasons (one of them being that this script will not work in the system where I want it). To be more to the point, if using `new` inside a `BufRead` causes strange behaviour, then the doc should simply forbid it. – Circonflexe Dec 15 '14 at 09:52
  • 1) The docs states `BufRead` is called after a file is successfully recovered, so you are too late. However you might have found a bug using `:new` with `BufRead`. 2) Your script should probably be using the `SwapExists` event 3) You may want to try `noautocmd new` and/or switching back to the previous buffer via `windcmd p`. 4) You may want to `:set verbose=9` to help test autocmds. 5) I would suggest you take a closer look at recover.vim and see how it works 6) Why will recover.vim not work for your system? 7) Please test this on the latest vim version – Peter Rincker Dec 15 '14 at 15:10
  • 1
    0) Thanks for your answer. 1) my idea is: since `SwapExists` is restricted (no buffer switching allowed), it sets a flag that is then caught when the `BufRead` autocommand is executed - so it is not too late, but exactly the time I want this executed. 3) I did not know about `noautocmd`: thanks for this! (However, in my particular example, it does not seem to work). 5) will do, but I thought going up from doc was easier than down from `recover.vim`. 6,7) My work environment is non-standard, I am not an admin, and cannot install any binary - already happy to have a semi-recent, functional Vim. – Circonflexe Dec 15 '14 at 15:59
  • There is a [comment in recover.vim](https://github.com/chrisbra/Recover.vim/blob/master/autoload/recover.vim#L37) that might clue us in to you issue. Your plan sounds fair enough however you may want to trigger your new split on `BufReadPost` or some other event after `BufRead`. I believe recover.vim works in a similar way as you laid out. You may consider opening an [issue](https://github.com/chrisbra/Recover.vim/issues) as I believe this could be a fairly large undertaking on your part. – Peter Rincker Dec 15 '14 at 16:17
  • 1
    I got a workaround for this. It seems that when recovering a file, the `BufRead` autocommand is actually executed three times - but the `new` command disrupts this flow and prevents recovery from the swap file. Incrementing a counter in the autocommand and waiting for the third call to open a new buffer seems to work as intended. (Another option could be to use a manual `:recover` command). tl;dr: third time's the charm! – Circonflexe Dec 16 '14 at 07:41

0 Answers0