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

vimscript question

Expand Messages
  • vim@useunix.net
    The text between the ----- lines below contains a vim function and command that calls the function which counts the number of times a pattern is matched over a
    Message 1 of 6 , Feb 1, 2005
      The text between the ----- lines below contains a vim function and
      command that calls the function which counts the number of times a
      pattern is matched over a range of lines in a file.

      It seems to work but the last cursor() call before the echo statement
      has no effect even though I know that l:curr_line and l:curr_col are
      correct. It always ends up on the last line of the file. This doesn't
      seem to be something specific to my command, it happens for many vim
      commands. Basically I want to call this function, have it do its job and
      then have the cursor placed back at the position where I called the
      function. I tried to call and exec but I am not clear on the what the
      difference is.

      FYI: Yes, I know I can call the function directly but using a
      user-defined-command to do this seems cleaner to me, thus the command at
      the bottom.

      Any and all help is appreciated.
      ------------------------------------------------------------------------------
      " CM: CountMatches counts the number of times a pattern matches a
      " range of lines
      function! CM(pattern) range
      let l:match_count = 0
      let l:curr_col = col(".")
      let l:curr_line = line(".")

      " move cursor to 1st line of search range
      call cursor(a:firstline, 0)

      " loop over the lines of the search range looking for pattern
      while 1
      let l:lnum = search(a:pattern, "W")

      " break loop if we are outside of the search range or we didn't
      " find a match (l:lnum == 0)
      if l:lnum > a:lastline || l:lnum == 0
      break
      endif

      let l:match_count = l:match_count + 1
      endwhile

      " place cursor back at original position
      exec cursor(l:curr_line, l:curr_col)

      " tell the user how many match we found
      echo "Pattern matched " . l:match_count . " times."
      endfunction

      com! -range -nargs=1 CM <line1>,<line2>call CM("<args>")
      ------------------------------------------------------------------------------
    • Antoine J. Mechelynck
      vim@useunix.net wrote: [...] ... :call invokes a _function_ and discards its return value. :exec executes a _string_ (or a number of space-separated
      Message 2 of 6 , Feb 1, 2005
        vim@... wrote:
        [...]
        > I tried to call and exec but I am not clear on the what the
        > difference is.

        ":call" invokes a _function_ and discards its return value. ":exec"
        executes a _string_ (or a number of space-separated strings, as with
        ":echo") as an ex-command (i.e. as the kind of command that you can type
        on the command-line after hitting : to get into command-line mode). The
        string(s) can be the result of evaluation expression. Thus in your case
        you should use ":call cursor (l:curr_line, l:curr_col)".

        >
        > FYI: Yes, I know I can call the function directly but using a
        > user-defined-command to do this seems cleaner to me, thus the command at
        > the bottom.
        >
        > Any and all help is appreciated.
        > ------------------------------------------------------------------------------
        > " CM: CountMatches counts the number of times a pattern matches a
        > " range of lines
        > function! CM(pattern) range
        > let l:match_count = 0
        > let l:curr_col = col(".")
        > let l:curr_line = line(".")
        >
        > " move cursor to 1st line of search range
        > call cursor(a:firstline, 0)
        >
        > " loop over the lines of the search range looking for pattern
        > while 1
        > let l:lnum = search(a:pattern, "W")
        >
        > " break loop if we are outside of the search range or we didn't
        > " find a match (l:lnum == 0)
        > if l:lnum > a:lastline || l:lnum == 0
        > break
        > endif
        >
        > let l:match_count = l:match_count + 1
        > endwhile
        >
        > " place cursor back at original position
        > exec cursor(l:curr_line, l:curr_col)
        >
        > " tell the user how many match we found
        > echo "Pattern matched " . l:match_count . " times."
        > endfunction
        >
        > com! -range -nargs=1 CM <line1>,<line2>call CM("<args>")
        > ------------------------------------------------------------------------------
        >
        >
        >
      • Gary Johnson
        ... In addition to what Tony said, you ll find that moving the cursor back to its original location isn t sufficient to restore the screen to the state it was
        Message 3 of 6 , Feb 1, 2005
          On 2005-02-01, vim@... wrote:

          > ... Basically I want to call this function, have it do its job
          > and then have the cursor placed back at the position where I
          > called the function. ...

          In addition to what Tony said, you'll find that moving the cursor
          back to its original location isn't sufficient to restore the screen
          to the state it was in before calling your function. If you care
          about that, you might also want to include something like this in
          your functions.

          " Save original cursor and screen location.
          "
          let curr_line = line(".")
          let restore_cursor = "normal!" . curr_line . "G" . virtcol(".") . "|"
          normal! H
          let restore_screen = line(".") . "normal!zt"

          [function does its work]

          " Restore screen and cursor to original positions.
          "
          execute restore_screen
          execute restore_cursor

          There are lots of variations on this; that's just one way to do it.

          HTH,
          Gary

          --
          Gary Johnson | Agilent Technologies
          garyjohn@... | Wireless Division
          | Spokane, Washington, USA
        • vim@useunix.net
          Thanks Gary and Antoine for the replies. I have integrated Gary s screen and cursor save/restore code into my function. Now if I call the function using a
          Message 4 of 6 , Feb 1, 2005
            Thanks Gary and Antoine for the replies. I have integrated Gary's
            screen and cursor save/restore code into my function. Now if I call the
            function using a call like
            :10,20call CM("text")
            or as a command like this:
            :10,20CM text

            The cursor ends up on the line that begins the search range, in this
            case line 10. Could it be that vim is positioning the cursor prior to
            calling my function so my code thinks the start range is the current
            cursor position?

            Thanks again,
            Wayne

            On Tue, Feb 01, 2005 at 11:53:15AM -0800, Gary Johnson wrote:
            > On 2005-02-01, vim@... wrote:
            >
            > > ... Basically I want to call this function, have it do its job
            > > and then have the cursor placed back at the position where I
            > > called the function. ...
            >
            > In addition to what Tony said, you'll find that moving the cursor
            > back to its original location isn't sufficient to restore the screen
            > to the state it was in before calling your function. If you care
            > about that, you might also want to include something like this in
            > your functions.
            >
            > " Save original cursor and screen location.
            > "
            > let curr_line = line(".")
            > let restore_cursor = "normal!" . curr_line . "G" . virtcol(".") . "|"
            > normal! H
            > let restore_screen = line(".") . "normal!zt"
            >
            > [function does its work]
            >
            > " Restore screen and cursor to original positions.
            > "
            > execute restore_screen
            > execute restore_cursor
            >
            > There are lots of variations on this; that's just one way to do it.
            >
            > HTH,
            > Gary
            >
            > --
            > Gary Johnson | Agilent Technologies
            > garyjohn@... | Wireless Division
            > | Spokane, Washington, USA
          • Antoine J. Mechelynck
            ... yes, see :help :call : Without a range and for functions that accept a range, the function is called once. When a range is given the cursor is positioned
            Message 5 of 6 , Feb 1, 2005
              vim@... wrote:
              > Thanks Gary and Antoine for the replies. I have integrated Gary's
              > screen and cursor save/restore code into my function. Now if I call the
              > function using a call like
              > :10,20call CM("text")
              > or as a command like this:
              > :10,20CM text
              >
              > The cursor ends up on the line that begins the search range, in this
              > case line 10. Could it be that vim is positioning the cursor prior to
              > calling my function so my code thinks the start range is the current
              > cursor position?
              >
              > Thanks again,
              > Wayne
              >
              yes, see ":help :call":

              Without a range and for functions that accept a range, the
              function is called once. When a range is given the cursor is
              positioned at the start of the first line before executing the
              function.

              Best regards,
              Tony.
            • Gary Johnson
              ... That would be my guess. In fact, :help :call (just above :help function-range-example ) says: Without a range and for functions that accept a range,
              Message 6 of 6 , Feb 1, 2005
                On 2005-02-01, vim@... wrote:
                > Thanks Gary and Antoine for the replies. I have integrated Gary's
                > screen and cursor save/restore code into my function. Now if I call the
                > function using a call like
                > :10,20call CM("text")
                > or as a command like this:
                > :10,20CM text
                >
                > The cursor ends up on the line that begins the search range, in this
                > case line 10. Could it be that vim is positioning the cursor prior to
                > calling my function so my code thinks the start range is the current
                > cursor position?

                That would be my guess. In fact, ":help :call" (just above ":help
                function-range-example") says:

                Without a range and for functions that accept a range, the
                function is called once. When a range is given the cursor is
                positioned at the start of the first line before executing the
                function.

                You might try another approach. How about defining your CM command
                to take a range and then passing that range explicitly to your
                function. Then define the function _without_ the range argument,
                but something like this:

                function CM(pattern, firstline, lastline)

                Gary

                --
                Gary Johnson | Agilent Technologies
                garyjohn@... | Wireless Division
                | Spokane, Washington, USA
              Your message has been successfully submitted and would be delivered to recipients shortly.