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
    • 0 Attachment
      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 2 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:

        [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.