Perl::Tags - Generate (possibly exuberant) Ctags style tags for Perl sourcecode
use Perl::Tags; my $naive_tagger = Perl::Tags::Naive->new( max_level=>2 ); $naive_tagger->process( files => ['Foo.pm', 'bar.pl'], refresh=>1 );
Recursively follows use and require statements, up to a maximum of max_level.
use
require
max_level
The implemented tagger, Perl::Tags::Naive is a more-or-less straight ripoff, slightly updated, of the original pltags code, and is rather naive. It should be possible to subclass using something like PPI or Text::Balanced, though be aware that this is alpha software and the internals are subject to change (so get in touch to let me know what you want to do and I'll try to help).
Perl::Tags::Naive
PPI
Text::Balanced
* Recursive, incremental tagging. * parses `use_ok`/`require_ok` line from Test::More
Perl::Tags is designed to be used with vim. My ~/.vim/ftplugin/perl.vim contains the following:
Perl::Tags
~/.vim/ftplugin/perl.vim
setlocal iskeyword+=: " make tags with :: in them useful if ! exists("s:defined_functions") function s:init_tags() perl <<EOF use Perl::Tags; $naive_tagger = Perl::Tags::Naive->new( max_level=>2 ); # only go one level down by default EOF endfunction " let vim do the tempfile cleanup and protection let s:tagsfile = tempname() function s:do_tags(filename) perl <<EOF my $filename = VIM::Eval('a:filename'); $naive_tagger->process(files => $filename, refresh=>1 ); my $tagsfile=VIM::Eval('s:tagsfile'); VIM::SetOption("tags+=$tagsfile"); # of course, it may not even output, for example, if there's nothing new to process $naive_tagger->output( outfile => $tagsfile ); EOF endfunction call s:init_tags() " only the first time let s:defined_functions = 1 endif call s:do_tags(expand('%')) augroup perltags au! autocmd BufRead,BufWritePost *.pm,*.pl call s:do_tags(expand('%')) augroup END
Note the following:
You will need to have a vim with perl compiled in it. Debuntu packages this as vim-perl. Alternatively you can compile from source (you'll need Perl + the development headers libperl-dev).
vim-perl
libperl-dev
The EOF in the examples has to be at the beginning of the line (the verbatim text above has leading whitespace)
EOF
new
Perl::Tags is an abstract baseclass. Perl::Tags::Naive is provided and can be instantiated with new.
$naive_tagger = Perl::Tags::Naive->new( max_level=>2 );
Accepts the following parameters
max_level: levels of "use" statements to descend into, default 2 do_variables: tag variables? default 1 (true) exts: use the Exuberant extensions
to_string
A Perl::Tags object will stringify to a textual representation of a ctags file.
print $tagger;
clean_file
Delete all tags, but without touching the "order" seen, that way, if the tags are recreated, they will remain near the top of the "interestingness" tree
output
Save the file to disk if it has changed. (The private {is_dirty} attribute is used, as the tags object may be made up incrementally and recursively within your IDE.
{is_dirty}
process
Scan one or more Perl file for tags
$tagger->process( files => [ 'Module.pm', 'script.pl' ] ); $tagger->process( files => 'script.pl', refresh => 1, );
queue
popqueue
Internal methods managing the processing
process_item
process_file
Do the heavy lifting for process above.
register
The parsing is done by a number of lightweight objects (parsers) which look for subroutine references, variables, module inclusion etc. When they are successful, they call the register method in the main tags object.
get_parsers
Return the parses for this object. Abstract, see Perl::Tags::Naive below.
A naive implementation. That is to say, it's based on the classic pltags.pl script distributed with Perl, which is by and large a better bet than the results produced by ctags. But a "better" approach may be to integrate this with PPI.
pltags.pl
ctags
See TodoTagger in the t/ directory of the distribution for a fully working example (tested in <t/02_subclass.t>). You may want to reuse parsers in the ::Naive package, or use all of the existing parsers and add your own.
t/
package My::Tagger; use Perl::Tags; our @ISA = qw( Perl::Tags::Naive ); sub get_parsers { my $self = shift; return ( $self->can('todo_line'), # a new parser $self->SUPER::get_parsers(), # all ::Naive's parsers # or maybe... $self->can('variable'), # one of ::Naive's parsers ); } sub todo_line { # your new parser code here! } sub package_line { # override one of ::Naive's parsers }
Because ::Naive uses can('parser') instead of \&parser, you can just override a particular parser by redefining in the subclass.
can('parser')
\&parser
The following parsers are defined by this module.
trim
A filter rather than a parser, removes whitespace and comments.
variable
Tags definitions of my, our, and local variables.
my
our
local
Returns a Perl::Tags::Tag::Var if found
package_line
Parse a package declaration, returning a Perl::Tags::Tag::Package if found.
sub_line
Parse the declaration of a subroutine, returning a Perl::Tags::Tag::Sub if found.
use_constant
Parse a use constant directive
use_line
Parse a use, require, and also a use_ok line (from Test::More). Uses a dummy tag (Perl::Tags::Tag::Recurse to do so).
label_line
Parse label declaration
Perl::Tags::Tag
A superclass for tags
Returns a new tag object
type
modify_options
Abstract methods
A tag stringifies to an appropriate line in a ctags file.
on_register
Allows tag to meddle with process when registered with the main tagger object. Return false if want to prevent registration (true normally).`
Perl::Tags::Tag::Package
Sets static=0
Sets the package name
Perl::Tags::Tag::Var
Make a tag for this variable unless we're told not to. We assume that a variable is always static, unless it appears in a package before any sub. (Not necessarily true, but it's ok for most purposes and Vim works fine even if it is incorrect) - pltags.pl comments
Perl::Tags::Tag::Sub
Make a tag for this sub unless we're told not to. We assume that a sub is static, unless it appears in a package. (Not necessarily true, but it's ok for most purposes and Vim works fine even if it is incorrect) - pltags comments
Perl::Tags::Tag::Constant
Perl::Tags::Tag::Label
Perl::Tags::Tag::Recurse
Recurse adding this new module to the queue.
(Apologies if I've missed anyone out -- I'm working on notes from... oops... a couple of years ago. Huge thanks!)
::PPI subclass
patch to use File::Temp
patch to parse constant and label declarations
::Naive::Spiffy and ::Naive::Lib subclasses
prodding me to make repo public
::PPI fixes, pestering me to release again
osfameron (2006-2008) - osfameron@gmail.com
For support, try emailing me or grabbing me on irc #london.pm on irc.perl.org Offers to co-maintain this module are very welcome!
This was originally ripped off pltags.pl, as distributed with vim and available from http://www.mscha.com/mscha.html?pltags#tools Version 2.3, 28 February 2002 Written by Michael Schaap <pltags@mscha.com>.
This is licensed under the same terms as Perl itself. (Or as Vim if you prefer).
To install Perl::Tags, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Perl::Tags
CPAN shell
perl -MCPAN -e shell install Perl::Tags
For more information on module installation, please visit the detailed CPAN module installation guide.