Loading ...
Sorry, an error occurred while loading the content.

How does Vim bundle the actions done by a BufWritePre autocmd?

Expand Messages
  • Elliot Shank
    I ve got a situation similar to the following: augroup A autocmd BufWritePre [stuff that changes the buffer before writing] augroup END augroup B
    Message 1 of 3 , Aug 31, 2006
    • 0 Attachment
      I've got a situation similar to the following:

      augroup A
      autocmd BufWritePre <buffer> [stuff that changes the buffer before writing]
      augroup END

      augroup B
      autocmd BufWritePre <buffer> [stuff that changes the buffer before writing]
      autocmd BufWritePost <buffer> undo
      augroup END


      Obviously, in group A I'm trying to make a change in the buffer as well as on disk. In group B, I'm trying to only make a change to disk.

      The command handlers are invoked in the order seen. First Pre A, then Pre B, then Post B.

      The problem is that the post command in group B is undoing the changes from group A, as well from itself. The problem is that it isn't easy to reverse the modifications in Pre B, other than by invoking :undo.


      Any ideas?
    • Yakov Lerner
      ... 1. What happens here is that edits from sequential noninteractive commands are considered as one undo block. You want to insert undo break at the
      Message 2 of 3 , Sep 1, 2006
      • 0 Attachment
        On 8/31/06, Elliot Shank <vim@...> wrote:
        > I've got a situation similar to the following:
        >
        > augroup A
        > autocmd BufWritePre <buffer> [stuff that changes the buffer before writing]
        > augroup END
        >
        > augroup B
        > autocmd BufWritePre <buffer> [stuff that changes the buffer before writing]
        > autocmd BufWritePost <buffer> undo
        > augroup END
        >
        >
        > Obviously, in group A I'm trying to make a change in the buffer as well as on disk. In group B, I'm trying to only make a change to disk.
        >
        > The command handlers are invoked in the order seen. First Pre A, then Pre B, then Post B.
        >
        > The problem is that the post command in group B is undoing
        > the changes from group A, as well from itself. The problem is
        > that it isn't easy to reverse the modifications in Pre B, other
        > than by invoking :undo.

        1. What happens here is that edits from sequential noninteractive
        commands are considered as one undo block. You want
        to insert "undo break" at the beginning of Pre B (or at the
        and of Pre B).
        There is a method of inserting "undo break" from a script.
        I forgot exactly how it is done, but maybe it is
        |i_CTRL-G_u| CTRL-G u start new undoable edit
        , thus something like :exe ":normal i\<c-G>u\<esc>"
        (untested), see
        :help i_CTRL-G_u

        2. However, if you do this, you'll break recommendation
        which is described in autocmds.txt line 1045:

        Note that the *WritePost commands should undo any changes to the buffer that
        were caused by the *WritePre commands; otherwise, writing the file will have
        the side effect of changing the buffer.

        Yakov
      • Elliot Shank
        ... [chop] ... Eeew. Go from command mode into normal mode, get into insert mode, do the CTRL-G u to get back into normal mode and then command mode, make
        Message 3 of 3 , Sep 1, 2006
        • 0 Attachment
          Yakov Lerner wrote:
          > On 8/31/06, Elliot Shank <vim@...> wrote:
          >> I've got a situation similar to the following:
          [chop]
          >> Obviously, in group A I'm trying to make a change in the buffer as
          >> well as on disk. In group B, I'm trying to only make a change to disk.
          >>
          >> The command handlers are invoked in the order seen. First Pre A, then
          >> Pre B, then Post B.
          >>
          >> The problem is that the post command in group B is undoing
          >> the changes from group A, as well from itself. The problem is
          >> that it isn't easy to reverse the modifications in Pre B, other
          >> than by invoking :undo.
          >
          > 1. What happens here is that edits from sequential noninteractive
          > commands are considered as one undo block. You want
          > to insert "undo break" at the beginning of Pre B (or at the
          > and of Pre B).
          > There is a method of inserting "undo break" from a script.
          > I forgot exactly how it is done, but maybe it is
          > |i_CTRL-G_u| CTRL-G u start new undoable edit
          > , thus something like :exe ":normal i\<c-G>u\<esc>"
          > (untested), see
          > :help i_CTRL-G_u

          Eeew. Go from command mode into normal mode, get into insert mode, do the CTRL-G u to get back into normal mode and then command mode, make changes, get back into normal mode in order to get back into insert mode, and back into normal mode, then command mode. I think that there would be a bit of pain in getting that correct.

          The other thing is that, while Pre A is currently happening before Pre B, I can't guarantee that that will be the case in the future.

          I think that I'm just going to have to do as good of a job of undoing Pre B as I can (which will work 99% of the time). The real solution, of course, would be to implement a *WriteCmd handler for augroup B, but that's a bit more than I want to take on right now.

          > 2. However, if you do this, you'll break recommendation
          > which is described in autocmds.txt line 1045:
          >
          > Note that the *WritePost commands should undo any changes to the
          > buffer that were caused by the *WritePre commands; otherwise, writing
          > the file will have the side effect of changing the buffer.

          Actually, I'm explicitly trying to break that, i.e. every time the user saves, some cleanup is done automatically, so the user doesn't have to do it themselves.
        Your message has been successfully submitted and would be delivered to recipients shortly.