PerlySense for Vim

Ovid on 2008-02-04T15:33:25

If you haven't seen Devel::PerlySense, I highly recommend that you check it out. It's a relatively new project by Johan Lindström to bring Intellisense functionality to Perl.

In your .vimrc, make sure you have the following line:

filetype plugin on

In your .vim/ftplugin/ directory, create a file named perl_perlysense.vim and add the following:

if exists( "b:perlysense" )
    finish
endif
let b:perlysense = 1

map  pp :call PerlySense_POD()
map  pg :call PerlySense_smart_go_to()

function! PerlySense_POD()
    call GetPos()
    let command="perly_sense smart_doc --file=" . b:file." --row=".b:row." --col=".b:col
    echo system(command)
endfunction

function! PerlySense_smart_go_to()
    call GetPos()
    let command="perly_sense smart_go_to --file=" . b:file." --row=".b:row." --col=".b:col
    let result = split( system(command), "\t" )
    let file = result[0]
    execute "e " . file
endfunction

function! GetPos()
    let b:file = bufname("%")
    let b:row = line(".")
    let b:col = col(".")
endfunction

Position your cursor on next and type \pp (replace the backslash with your leader character (see :help mapleader in vim) if you have a different leader character) and you should see this:

found   method  name    next    docType hint
METHODS
  Instance Methods
   "next"
      my $parser = TAP::Parser->new( { source => $file } );
      while ( my $result = $parser->next ) {
          print $result->as_string, "\n";
      }

    This method returns the results of the parsing, one result at a time.
    Note that it is destructive. You can't rewind and examine previous
    results.

    If callbacks are used, they will be issued before this call returns.

    Each result returned is a subclass of TAP::Parser::Result. See that
    module and related classes for more information on how to use them.

Pretty nifty, eh? Note that this is a snippet of perldoc from a completely different file. Perlysense just knew where to look for it.

Also with the above code, if you position your cursor on a package name and type \pg, vim will automatically edit the correct file. It works, but I get strange error message about "Cannot redefine function PerlySense_smart_go_to, it is already in use". You can eliminate by removing the "!" after function. Makes it a bit tougher for developing this plugin, but it should work for you :)

PerlySense has the limitation that Perl is a dynamic language, of course, but so far it looks pretty sweet. It also does not yet have the much of an idea of a current project and the interface is still evolving, but so far this looks like a fantastic tool to help us get IDE style integration with our editor of choice.

It's worth noting that there's a heck of a lot more in PerlySense than just documentation. I'll try and post more if I get time. Suggestions for improving my vim code welcome. Some refactoring will be obvious as this grows, but some will simply be my not understanding vim programming terribly well.


PerlySense vs Omnicompletion

markjugg on 2008-02-04T16:43:14

This sounds a lot like Omnicompletion, which was included in Vim 7:

http://www.perlmonks.org/?node_id=621766

Does PerlySense complement or compete with that approach?

(Of course, if you are stuck on machines that have older vims that aren't easily upgradeable, then PerlySense would be the way to go.)

Re:PerlySense vs Omnicompletion

Ovid on 2008-02-04T17:08:34

I'm really not sure. Johan's going to be away for a bit, so I can't ask him.

On a related note, I've discovered that using tab completion was very painful as it would often do a full scan over everything in @INC. I added this to my .vimrc and now it just scans what's in buffers (thanks to smylers for help on this):

set complete=.,w,b,u,t " omits ',i'. This avoids full file scans.

function! CleverTab()
   if strpart( getline('.'), 0, col('.')-1 ) =~ '^\s*$'
      return "\<Tab>"
   else
      return "\<C-N>"
endfunction
inoremap <Tab> <C-R>=CleverTab()<CR>

I'm sure that this could be updated for the omnicompletion.

Er, maybe not. I just tried that script and can't figure out how to make it work :(

Re:PerlySense vs Omnicompletion

jplindstrom on 2008-02-09T17:44:52

Currently PerlySense complements Onicompletion, because it doesn't do completion at all yet. Starting the project I thought that would be the killer useful feature, but it turned out to not be very high up on the list at all.

Right now, PerlySense does have a good idea of what the current class looks like (i.e. $self), but not so good idea of the environment, because there is still no @INC-wide or project-wide repository of "things".

Whenever completions is implemented, Omnicompletion could potentially start using the PerlySense backend as a provider of completions to display.

Names and keys

jplindstrom on 2008-02-09T17:52:45

It's probably a good idea to try to adhere to the conventions of PerlySense a bit better, i.e. not call it "POD", but rather "Docs".

Because it isn't just POD. Docs could be POD, but also other things that shed light on how to use a method, like the method signature deduced from the source, or an example $self->method_call($param1, $param2) taken from the source. Or something else.

So the key stroke should also not be "p" for POD, but rather "g" or "G". I'll write up the conventions for key strokes/bindings, but they should be fairly obvious from reading the manual as it is.