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

Cursor position after reload of a file during FileChangedShell

Expand Messages
  • Hari Krishna Dara
    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
    Message 1 of 4 , Jul 1, 2004
    • 0 Attachment
      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?

      --
      Thanks a lot,
      Hari



      __________________________________
      Do you Yahoo!?
      New and Improved Yahoo! Mail - Send 10MB messages!
      http://promotions.yahoo.com/new_mail
    • 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 2 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
      • 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 3 of 4 , Jul 2, 2004
        • 0 Attachment
          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 4 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.