Show Perl subname in vim statusline
I asked on the vim mailing list how to see the name of Perl's current sub/method in the status line and Alan Young, the author of PPIx::IndexLines has a great suggestion which unfortunately relied on PPI. I'm working with very large modules and PPI ground to a halt for me. As a result, I took his suggestion and worked out the following.
First, make sure that your .vimrc has set laststatus=2 in it. That will ensure that you always get a status line, even if you only have one window (i.e., don't have split windows). Then drop the following into your .vim/ftplugin/perl.vim:
if ! exists("g:did_perl_statusline")
setlocal statusline+=%(\ %{StatusLineIndexLine()}%)
setlocal statusline+=%=
setlocal statusline+=%f\
setlocal statusline+=%P
let g:did_perl_statusline = 1
endif
if has( 'perl' )
perl << EOP
use strict;
sub current_sub {
my $curwin = $main::curwin;
my $curbuf = $main::curbuf;
my @document = map { $curbuf->Get($_) } 0 .. $curbuf->Count;
my ( $line_number, $column ) = $curwin->Cursor;
my $sub_name = '(not in sub)';
for my $i ( reverse ( 1 .. $line_number -1 ) ) {
my $line = $document[$i];
if ( $line =~ /^\s*sub\s+(\w+)\b/ ) {
$sub_name = $1;
last;
}
}
VIM::DoCommand "let subName='$line_number: $sub_name'";
}
EOP
function! StatusLineIndexLine()
perl current_sub()
return subName
endfunction
endif
All this does is naïvely read backwards from the current line to get "sub $name" and report $name. It will fail on many common cases. However, it's fast. Very fast. Unlike the PPI solution, I can use this and manually correct any files which don't fit this convention.
It's a quick and nasty hack, but already I'm finding it very useful. Suggestions welcome :)
Note that this requires Perl support. Just ":echo has('perl')" and if it displays '1', you're good to go. Then type "help perl-using" to see what's going on.
Update: I've updated that statusline. There's a space after the '\' and it now shows the column, filename and percent. See ":help statusline" or this blog post for more ideas.
Update2: Changed "set" to "setlocal" so we don't screw with non-Perl buffers.
Update3: If I do an ":e $anotherfile", I lose the new status line. Eliminating the exists("g:did_perl_statusline") seems to fix this.