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

Re: Cursor position after reload of a file during FileChangedShell

Expand Messages
  • Benji Fisher
    ... I do not make use of the FileChangedRO autocommand myself, so let me first make sure that I have this straight. You are editing a RO file and (starting in
    Message 1 of 4 , Jul 2, 2004
      On Thu, Jul 01, 2004 at 05:49:33PM -0700, Hari Krishna Dara wrote:
      >
      > This is minor, but would like to get a workaround if possible, as I
      > regularly get into this problem.
      >
      > In my perforce plugin, like many SCM plugins might already be doing, I
      > capture the FileChangedRO events and provide the option to checkout the
      > file. In addition, I automatically reload the file to avoid showing up
      > as readonly. The mechanism works something like this:
      >
      > aug FCRO
      > au!
      > au FileChangedRO * nested :call CheckOutFile()
      > aug END
      >
      > function! CheckOutFile()
      > call system('chmod +w '.expand('%'))
      > doautocmd FileChangedShell
      > call SaveHardPosition('T') | e! | call RestoreHardPosition('T')
      > endfunction
      >
      > The SaveHardPosition() and RestoreHardPosition() functions are from my
      > genutils.vim which are simple cursor save and restore functions (marks
      > will not work across file reload). Here are the simplified versions of
      > these function definitions for your convenience:
      >
      >
      > function SaveHardPosition(scriptid)
      > let s:col_{a:scriptid} = virtcol(".")
      > let s:lin_{a:scriptid} = line(".")
      > "let s:winline_{a:scriptid} = winline()
      > endfunction
      >
      > function RestoreHardPosition(scriptid)
      > execute s:lin_{a:scriptid}
      > execute "normal!" s:col_{a:scriptid} . "|"
      > "call MoveCurLineToWinLine(s:winline_{a:scriptid})
      > endfunction
      >
      >
      > The problem now is that when SaveHardPosition() is called, I see that
      > the column position is one more than the col('$') because the cursor
      > must already have been placed for the "A" mode. But when
      > RestoreHardPosition() is called, the "|" command to position the cursor
      > at the end of the line doesn't position it AFTER the last character, so
      > at the end, the cursor is left between the last-but-one and the last
      > characters. To fix, I have to press <Esc> immediately, and press A
      > again, which is an inconvenience everytime I start editing like this.
      >
      > My understanding of the problem is that Vim behaves like it was an
      > insert command after the reload, though I used Append command. I don't
      > know if it is easy to fix, but can anyone think of a workaround for this
      > problem?

      I do not make use of the FileChangedRO autocommand myself, so let
      me first make sure that I have this straight. You are editing a RO file
      and (starting in Normal mode) type A to begin making the first change.
      This triggers the autocommand, which calls the CheckOutFile() function.

      It should not be hard for the CheckOutFile() function, or perhaps
      the SaveHardPosition() function, to figure out that the cursor is beyond
      the end of the line: just check whether col(".") == col("$") . If this
      is done in the CheckOutFile() function, save this information in a local
      variable; if it is done in the SaveHardPosition() function, use a
      script-local variable.

      Now, what to do with this information? The simplest, if it works,
      would be to use :startinsert! . If that does not work, append an extra
      character at the end of the line; at worst, you will need to type an
      extra <Del> when all is done, which is a little better than <Esc>A . At
      best, you can use

      :execute "normal! $v\<C-G>"

      to capture the extra character in Select mode.

      BTW, why not use cursor() in the RestoreHardPosition() function?

      HTH --Benji Fisher
    • Benji Fisher
      Apologies if this is a duplicate. ... I do not make use of the FileChangedRO autocommand myself, so let me first make sure that I have this straight. You are
      Message 2 of 4 , Jul 2, 2004
        Apologies if this is a duplicate.

        On Thu, Jul 01, 2004 at 05:49:33PM -0700, Hari Krishna Dara wrote:
        >
        > This is minor, but would like to get a workaround if possible, as I
        > regularly get into this problem.
        >
        > In my perforce plugin, like many SCM plugins might already be doing, I
        > capture the FileChangedRO events and provide the option to checkout the
        > file. In addition, I automatically reload the file to avoid showing up
        > as readonly. The mechanism works something like this:
        >
        > aug FCRO
        > au!
        > au FileChangedRO * nested :call CheckOutFile()
        > aug END
        >
        > function! CheckOutFile()
        > call system('chmod +w '.expand('%'))
        > doautocmd FileChangedShell
        > call SaveHardPosition('T') | e! | call RestoreHardPosition('T')
        > endfunction
        >
        > The SaveHardPosition() and RestoreHardPosition() functions are from my
        > genutils.vim which are simple cursor save and restore functions (marks
        > will not work across file reload). Here are the simplified versions of
        > these function definitions for your convenience:
        >
        >
        > function SaveHardPosition(scriptid)
        > let s:col_{a:scriptid} = virtcol(".")
        > let s:lin_{a:scriptid} = line(".")
        > "let s:winline_{a:scriptid} = winline()
        > endfunction
        >
        > function RestoreHardPosition(scriptid)
        > execute s:lin_{a:scriptid}
        > execute "normal!" s:col_{a:scriptid} . "|"
        > "call MoveCurLineToWinLine(s:winline_{a:scriptid})
        > endfunction
        >
        >
        > The problem now is that when SaveHardPosition() is called, I see that
        > the column position is one more than the col('$') because the cursor
        > must already have been placed for the "A" mode. But when
        > RestoreHardPosition() is called, the "|" command to position the cursor
        > at the end of the line doesn't position it AFTER the last character, so
        > at the end, the cursor is left between the last-but-one and the last
        > characters. To fix, I have to press <Esc> immediately, and press A
        > again, which is an inconvenience everytime I start editing like this.
        >
        > My understanding of the problem is that Vim behaves like it was an
        > insert command after the reload, though I used Append command. I don't
        > know if it is easy to fix, but can anyone think of a workaround for this
        > problem?

        I do not make use of the FileChangedRO autocommand myself, so let
        me first make sure that I have this straight. You are editing a RO file
        and (starting in Normal mode) type A to begin making the first change.
        This triggers the autocommand, which calls the CheckOutFile() function.

        It should not be hard for the CheckOutFile() function, or perhaps
        the SaveHardPosition() function, to figure out that the cursor is beyond
        the end of the line: just check whether col(".") == col("$") . If this
        is done in the CheckOutFile() function, save this information in a local
        variable; if it is done in the SaveHardPosition() function, use a
        script-local variable.

        Now, what to do with this information? The simplest, if it works,
        would be to use :startinsert! . If that does not work, append an extra
        character at the end of the line; at worst, you will need to type an
        extra <Del> when all is done, which is a little better than <Esc>A . At
        best, you can use

        :execute "normal! $v\<C-G>"

        to capture the extra character in Select mode.

        BTW, why not use cursor() in the RestoreHardPosition() function?

        HTH --Benji Fisher
      • Hari Krishna Dara
        ... [snip] ... Thanks a lot for the conditional :startinsert! idea. It worked like a charm, except that it was funny that I had to press twice. I think
        Message 3 of 4 , Jul 2, 2004
          On Fri, 2 Jul 2004 at 11:14am, Benji Fisher wrote:

          > On Thu, Jul 01, 2004 at 05:49:33PM -0700, Hari Krishna Dara wrote:
          > >
          > > This is minor, but would like to get a workaround if possible, as I
          > > regularly get into this problem.
          > >
          > > In my perforce plugin, like many SCM plugins might already be doing, I
          > > capture the FileChangedRO events and provide the option to checkout the
          > > file. In addition, I automatically reload the file to avoid showing up
          > > as readonly. The mechanism works something like this:

          [snip]

          > > The problem now is that when SaveHardPosition() is called, I see that
          > > the column position is one more than the col('$') because the cursor
          > > must already have been placed for the "A" mode. But when
          > > RestoreHardPosition() is called, the "|" command to position the cursor
          > > at the end of the line doesn't position it AFTER the last character, so
          > > at the end, the cursor is left between the last-but-one and the last
          > > characters. To fix, I have to press <Esc> immediately, and press A
          > > again, which is an inconvenience everytime I start editing like this.
          > >
          > > My understanding of the problem is that Vim behaves like it was an
          > > insert command after the reload, though I used Append command. I don't
          > > know if it is easy to fix, but can anyone think of a workaround for this
          > > problem?
          >
          > I do not make use of the FileChangedRO autocommand myself, so let
          > me first make sure that I have this straight. You are editing a RO file
          > and (starting in Normal mode) type A to begin making the first change.
          > This triggers the autocommand, which calls the CheckOutFile() function.
          >
          > It should not be hard for the CheckOutFile() function, or perhaps
          > the SaveHardPosition() function, to figure out that the cursor is beyond
          > the end of the line: just check whether col(".") == col("$") . If this
          > is done in the CheckOutFile() function, save this information in a local
          > variable; if it is done in the SaveHardPosition() function, use a
          > script-local variable.
          >
          > Now, what to do with this information? The simplest, if it works,
          > would be to use :startinsert! . If that does not work, append an extra
          > character at the end of the line; at worst, you will need to type an
          > extra <Del> when all is done, which is a little better than <Esc>A . At
          > best, you can use
          >
          > :execute "normal! $v\<C-G>"
          >
          > to capture the extra character in Select mode.
          >
          > BTW, why not use cursor() in the RestoreHardPosition() function?
          >
          > HTH --Benji Fisher
          >
          >

          Thanks a lot for the conditional :startinsert! idea. It worked like a
          charm, except that it was funny that I had to press <Esc> twice. I think
          it was because Vim noted that the insert mode was started twice
          (actually, makes me wonder when this can be useful). So as a workaround,
          I did a :stopinsert and it seems to work fine. So here is the final
          solution that worked:

          aug FCRO
          au!
          au FileChangedRO * nested :call CheckOutFile()
          aug END

          function! CheckOutFile()
          call system('chmod +w '.expand('%'))
          doautocmd FileChangedShell
          let curOnLastCol = (col('.') == col('$'))
          call SaveHardPosition('T') | e! | call RestoreHardPosition('T')
          if curOnLastCol
          stopinsert | startinsert!
          endif
          endfunction

          The SaveHardPosition() and RestoreHardPosition() functions are from my
          genutils.vim which are simple cursor save and restore functions (marks
          will not work across file reload). Here are the simplified versions of
          these function definitions for your convenience:


          function SaveHardPosition(scriptid)
          let s:col_{a:scriptid} = virtcol(".")
          let s:lin_{a:scriptid} = line(".")
          "let s:winline_{a:scriptid} = winline()
          endfunction

          function RestoreHardPosition(scriptid)
          execute s:lin_{a:scriptid}
          execute "normal!" s:col_{a:scriptid} . "|"
          "call MoveCurLineToWinLine(s:winline_{a:scriptid})
          endfunction


          To answer why I don't use cursor() function, in fact when this function
          was introduced, I did modify this function to take advantage of it,
          but later realized that it won't work with virtual columns. As you can
          see, I save the virtcol() instead of col(). Positioning cursor this way
          works more accurately than using col(), and in addition, using
          MoveCurLineToWinLine() makes the buffer look exactly same (I commented
          it above to reduce the interference). Here is the implementation for
          MoveCurLineToWinLine():

          function! MoveCurLineToWinLine(n)
          normal! zt
          if a:n == 1
          return
          endif
          let _wrap = &l:wrap
          setl nowrap
          let n = a:n
          if n >= winheight(0)
          let n = winheight(0)
          endif
          let n = n - 1
          execute "normal! " . n . "\<C-Y>"
          let &l:wrap = _wrap
          endfunction

          Just realized, I should use try block here, just in case it ever fails
          in the middle.

          --
          Thanks again,
          Hari



          __________________________________
          Do you Yahoo!?
          Yahoo! Mail - 50x more storage than other providers!
          http://promotions.yahoo.com/new_mail
        Your message has been successfully submitted and would be delivered to recipients shortly.