6

I am currently coding fortran, and I have huge "subprograms" (called "subroutine" in fortran). So I would like the name of the current subroutine (the subprogram my cursor is currently in) to be displayed in my statusline.

This is what a subroutine looks like in fortran (this should make my trick clearer):

subroutine my_subprogram(args)
   stuff going on 
end

I found the following trick, currently in my .vimrc file.

function! SubName()
   let current_line = line(".")  " I store the current line number 
   ?subroutine                   " searches the previous occurence of "subroutine"
   let title_line = line(".")    " stores the line where the subroutine title is
   execute ":".title_line        " go to the line where the title is
   normal! eeb                   " put the cursor on the 2nd word :  "my_subprogram"
   let sub_name = expand("<cword>") " extract the subroutine name in a variable
   execute ":".current_line      " come back to the initial position
   return sub_name
endfunction

Then I put the function in my statusline and it works almost fine : the name is displayed but... I cant do / searches anymore ! It highlights found text but I can't scroll to the next occurences of the pattern I'm looking for.

I guess this might be because the function is permanently called and thus Vim permanently performs researches because of the ?subroutine line.

(This is my first time trying to vimscript, so there are probably some ugly things there that you may want to correct -- please do not hesitate !)

  • Rather than a function, you can use key mappings simply. – SibiCoder Apr 20 '16 at 16:39
  • I did at first, that's how my .vimrc is set at the moment : I press my shortcut each time I want to know in which subroutine I am. But I wanted it to be automatic and permanent (hence the displaying in the statusline). Or maybe I am misunderstanding you ? – Feffe Apr 20 '16 at 17:51
  • 1
    Not what you wer looking for, but as an idea: you could go for github.com/majutsushi/tagbar. It'll show you where you're in the file. – Rolf Apr 22 '16 at 11:00
6

You could try the following code:

function! SubName() abort
    let prev_sub_line_num = search('subroutine ', 'bcnW')
    return matchstr(getline(prev_sub_line_num), 'subroutine \zs\w\+')
endfunction

set stl+=%{SubName()}

    let prev_sub_line_num = search('subroutine ', 'bcnW')

Call the search() function to look for the pattern subroutine.
In the 2nd argument, 4 flags are passed to search():

  • b look backward instead of forward
  • c accept a match at current cursor position
  • n don't move the cursor
  • W don't wrap around the end of the file

So, search() returns the number of the line where the previous subroutine text is found.
This number is stored in the variable prev_sub_line_num.

return matchstr(getline(prev_sub_line_num), 'subroutine \zs\w\+')

Then, matchstr() is called, which looks for the pattern subroutine \zs\w\+ inside the contents of the line prev_sub_line_num, and returns the matching text.

2 arguments are passed to matchstr():

  • getline(prev_sub_line_num) which gets the contents of the previous line where subroutine was found
  • the pattern subroutine \zs\w\+ which matches the word (\w\+) just after the text subroutine. In a regex, \zs allows you to set the start of a match. Here, it allows you to get rid of subroutine, even though it's inside the pattern.

Note that the contents of the statusline including the expression SubName() will be evaluated on every screen update, which could slow Vim down.

  • 1
    nice, do you know if those flags exists for the //? also ? – nobe4 Apr 20 '16 at 17:29
  • 2
    @Nobe4 I don't know for the c and n flags, but you can get something similar to W by typing :set nowrapscan. You can also apply some offsets after a / / ? search. For example, /foobar/e should position the cursor on the end of the next foobar (r), and ?foobar?s+3 should position the cursor on the third character after the start of the previous foobar (b). Other than that, I don't know if you can tweak the behavior of a search. – user9433424 Apr 20 '16 at 17:45
  • Wow. This shows how much I have to learn about vim. Thank you very much, I will test it asap. – Feffe Apr 20 '16 at 17:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.