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

Re: Cursor position after reload of a file during FileChangedShell

Expand Messages
  • 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 1 of 4 , Jul 2, 2004
    • 0 Attachment
      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:


      > > 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 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!

      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()

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

      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

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

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

      Thanks again,

      Do you Yahoo!?
      Yahoo! Mail - 50x more storage than other providers!
    Your message has been successfully submitted and would be delivered to recipients shortly.