Back references in Vim scripts

Ovid on 2005-09-13T02:47:26

Is there any way, in a vim script, to get "dollar digit" variables such as those used in Perl to extract matched text? I have the following:

function GotoCFile()
    if search('^\s*#\s*cfile:\s*\(\w\+\)')

        " $1 is not the variable in vim
        exe "echo 'Found ".$1."'"
    else
        exe "echo 'Could not find name of corresponding file'"
    end
endfunction

I'm trying to find a Perl comment like this:

# cfile: somefile

And assign "somefile" to a variable. I've searched all over the Vim documentation for this and it seems to involve finding the starting and ending positions of the match and doing a bit of math and a extracting a substring. Tell me it's not this hard!


I'm guessing matchstr is what you're after

wickline on 2005-09-13T03:28:53

function! GotoCFile()
    :write!
    :redraw!
 
    let cfile_prefix     = '#\s*cfile:\s*'
    let cfile_expression = cfile_prefix . '\w\+'
    if match(getline('.'), cfile_expression) > -1
        let good_line = matchstr(getline('.'), cfile_expression)
        " probably need some more interesting way to make a relative path
        " also need to get rid of any stuff that might trail the filename
        execute ":edit ./" . substitute(good_line, cfile_prefix, "", "g")
    else
        echom "no cfile recognized with my wimpy regex"
    endif
endfunction

Re:I'm guessing matchstr is what you're after

Smylers on 2005-09-13T06:25:31

Unfortunately matchstr() operates on a string, not the current buffer, so you've first of all had to read the current line into a string.

This has the distinct disadvantage that it only works if you already happen to be on the line that you're looking for.

Smylers

Re:I'm guessing matchstr is what you're after

wickline on 2005-09-14T05:28:08

> only works if you already happen to be on the line

I'm relying on some inside information to guess that he's expecting to be on the line when he uses this command. I could be wrong.

We used to work at the same shop where we had a bunch of shortcuts that worked in that sort of fashion (go to test, implementation, module, base class, mason component).

Re:I'm guessing matchstr is what you're after

Ovid on 2005-09-13T16:52:42

Out of curiosity, how did you learn Vim scripting? Is there a decent tutorial out there or did you go through the docs?

Re:I'm guessing matchstr is what you're after

wickline on 2005-09-14T05:38:24

> how did you learn Vim scripting?

I'm not sure I'd say that I've learned it. When I started at Rentrak, they already had ,gi ,gt ,t and ,T. I just copy/paste/tweaked from there for the most part. Before I started at Rentrak, I'd primarily been a BBEdit user, with ten-year-rusty vi experience. Rentrak was the first place I used Vim.

> Is there a decent tutorial out there or did you go through the docs

There may well be a decent tutorial. If so, I never found it. Instead I spent way to much time banging my head against the :help docs. I agree that Vim's macro language bites donkey dorks.

Bruce has been extending the emacs support at work to the point that it does everything the vim macros do and tons more For example, you can type a random function like create_test_whatever in the middle of some bit of code and hit a keystroke to have emacs find the appropriate place from which to import that sucker, add the appropriate use line at the appropriate place in the code, format it and sort it to look pretty with the other use lines, and return you to editing where you typed that function. Very slick.

Elisp looks like a comparative dream to work with. At this point, the only thing holding me back is the lack of quick keyboard editing/navigation. The functionality for extensions is better than vim, but the plain vanilla functionality still strikes me as less efficient than vim.

Anyhow, I sypathize with your struggle to not strangle vim :)

-matt

Grab It To a Register

Smylers on 2005-09-13T06:32:05

If you change the pattern just to position the cursor at the point you're interested in then you can yank the next word into a register with a separate command:

function! GotoCFile()
  if search('\v%(^\s*#\s*cfile:\s*)@<=\w')
    normal "zye
    echo 'Found ' . @z
  else
    echo 'Could not find name of corresponding file'
  end
endfunction

If however, as suggested by the name of your function, your actual desire is not to put the filename into a variable but to go to that file then it's easier to do that directly:

function! GotoCFile()
  if search('\v%(^\s*#\s*cfile:\s*)@<=\w')
    find <cfile>
  else
    echo 'Could not find name of corresponding file'
  end
endfunction

Use edit instead of find if you don't want to search the path.

Smylers

Re:Grab It To a Register

Ovid on 2005-09-13T16:48:34

Thanks! That's useful information. I have to admit, I'm thinking about Emacs just because I find the Vim docs so intensely painful. I'm not Stephen Hawking, but I'm not particularly stupid, either. I don't know why I have such trouble with the Vim docs, but I do. This really should have not been so hard to figure out :/