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

Bram: Any explanation for that? - Re: How can I force no undo dunring a function call?

Expand Messages
  • Mario Schweigler
    The thing is that it works sometimes, but not always, depending on whether I have changed the text before calling the function. Just as you described it, it
    Message 1 of 2 , Jul 31, 2002
      The thing is that it works sometimes, but not always, depending on
      whether I have changed the text before calling the function. Just as you
      described it, it works fine, but if you change something in the text
      before calling the function, sometimes (depending on WHERE in the text I
      change something) it does not work. In this case, "u" would undo
      everything the function did PLUS the last change before the function.

      Now I tried something else, and it seems to work (although I have not
      the slightest idea why...):

      :let save_ul = &undolevels
      :setlocal undolevels=-1
      :silent! undo
      :silent! undo
      :silent! undo
      :silent! undo

      at the beginning of the function and

      :exe 'setlocal undolevels=' . save_ul

      at the end of the function.

      By doing the undo stuff after setting undolevels to -1, vim somehow
      (Bram, please explain why!) forgets what is in the undo buffer after the
      function is finished.

      The reason that it is *FOUR* undos is the following:

      When undolevels is -1, two undos have the same effect as undo+redo. I
      cannot use undo+redo, as it would screw up things when I have made a
      change and undid it before calling the function (because the undo in the
      function would have no effect, but the redo would redo the change I
      undid before calling the function).

      OK, thus far it is OK. But if cpoptions contains u, then for some reason
      (I don't know why - Bram, please explain!) after setting undolevels to
      -1, two undos only have the effect of one undo, and the second undo has
      no effect. So we need another two undos (which is 4 in total) to get the
      redo effect.

      When there were no changes before calling the function, all the 4 undos
      have no effect, which is OK (and because we use "silent!", we won't get
      a beep).

      So there are five possibilities:

      * No changes before calling the function, cpoptions doesn't matter:
      WHAT - WHAT IT DOES
      undo #1 - beep
      undo #2 - beep
      undo #3 - beep
      undo #4 - beep

      * We did a change before calling the function, cpoptions is without u:
      undo #1 - undo
      undo #2 - redo
      undo #3 - undo
      undo #4 - redo

      * We did a change before calling the function, cpoptions is with u:
      undo #1 - undo
      undo #2 - beep
      undo #3 - redo
      undo #4 - beep

      * We did a change and undid it before calling the function, cpoptions is
      without u:
      undo #1 - redo
      undo #2 - undo
      undo #3 - redo
      undo #4 - undo

      * We did a change and undid it before calling the function, cpoptions is
      with u:
      undo #1 - beep
      undo #2 - redo
      undo #3 - beep
      undo #4 - undo

      (NB: The beeps are not heard during the function call because of the
      "silent!", this is just the normal behaviour).

      In the end, after the 4 undos, we always have unchanged text, and after
      the end of the function call, the undo (and redo) buffer is empty.

      All this took me ages to find out, and it was pure trial and error. I
      have no idea why all this is so...

      Bram, could you please explain! The help says nothing about it...

      Mario

      Benji Fisher wrote:
      >
      > Mario Schweigler wrote:
      > >
      > > Hi,
      > >
      > > I want the following: When I call a function, I would like that
      > > afterwards the undo buffer is empty, i.e. I can't undo the stuff that
      > > the function has changed.
      > >
      > > But if I change something manually later, it must be undoable just like
      > > normal.
      > >
      > > I tried
      > >
      > > :let save_ul = &undolevels
      > > :setlocal undolevels=-1
      > >
      > > at the beginning of the function and
      > >
      > > :exe 'setlocal undolevels=' . save_ul
      > >
      > > at the end of the function. But it does not work! If I press u after
      > > calling the function it still undoes the function's changes.
      >
      > It works as expected for me. Maybe the problem is somewhere else. I tried
      >
      > fun! UndoTest()
      > setlocal ul=-1
      > put='testing undolevels'
      > setlocal ul=1000
      > endfun
      >
      > After :call UndoTest() I get an extra line, and "u" does not make it go away.
      > BTW, I used :setlocal because you did, but 'ul' is a global option, so this
      > should work just the same as :set .
      >
      > HTH --Benji Fisher
    • Bram Moolenaar
      ... It s not so mysterious: changing undolevels only has effect for the next thing being saved for undo. If you are performing a sequence of commands
      Message 2 of 2 , Aug 1, 2002
        Mario Schweigler wrote:

        > The thing is that it works sometimes, but not always, depending on
        > whether I have changed the text before calling the function. Just as you
        > described it, it works fine, but if you change something in the text
        > before calling the function, sometimes (depending on WHERE in the text I
        > change something) it does not work. In this case, "u" would undo
        > everything the function did PLUS the last change before the function.

        It's not so mysterious: changing 'undolevels' only has effect for the
        next thing being saved for undo. If you are performing a sequence of
        commands without typing, this is counted as one undo-able action. You
        can't really switch off undo halfway. However, if you attempt undoing
        halfway the action, this counts as restarting undo and then the value of
        'undolevels' is checked. But since you don't really want to undo
        anything you make it complicated to get back what you want.

        Best is if you can set 'undolevels' to -1 before making any change.
        Changing 'undolevels' halfway a change has unpredictable results.

        --
        From "know your smileys":
        :q vi user saying, "How do I get out of this damn emacs editor?"

        /// Bram Moolenaar -- Bram@... -- http://www.moolenaar.net \\\
        /// Creator of Vim -- http://vim.sf.net -- ftp://ftp.vim.org/pub/vim \\\
        \\\ Project leader for A-A-P -- http://www.a-a-p.org ///
        \\\ Lord Of The Rings helps Uganda - http://iccf-holland.org/lotr.html ///
      Your message has been successfully submitted and would be delivered to recipients shortly.