The problem is that the default setting for Perl reports not only all the subroutine declarations, but also declarations of lexical variables (my). I don't need to know where a lexical variable was declared: normally, it's in the same block where the cursor is, maybe one level higher. What I'd like to have, though, are the attributes' accesors that Moo(se) provides; they're declared with has which etags can't handle.
I haven't found a way how to persuade etags to handle multiline declarations, neither have I found any other solution. So, I created a simple script that creates the TAGS file that's more useful for me than the default. It still doesn't handle all the possibilities (different names for setters/getters, builders, delegation, etc.) - you can check the END section for all the constructs it can parse.
The current version of the code is here, but you can find it at GitHub where it might change as I (or you!) add new features.
#!/usr/bin/perl use warnings; use strict; use feature qw{ say }; use List::MoreUtils qw{ any }; use Path::Tiny qw{ path }; sub wanted { my ($path, $state) = @_; return if $path->is_dir || $path !~ /\.p[lm]$/; my $code = $path->slurp; my %found; for my $regex ( qr/^(\s* (sub | method) \s+ (\w+)) /xm, qr/^(\s* (alias) \s+ (\w+)) /xm, qr/^(\s* (has) \s+ (?:["']\+?)? (\w+)) /xm, qr/^(\s* (has) \s+ \[ \s* qw \s* . \s* ([^)\]\/>]+) +) /xm, ) { while ($code =~ /$regex/g) { my ($full, $keyword, $funcs) = ($1, $2, $3); for my $func (split ' ', $funcs) { my $pos = pos($code) - length $full; my $nl_count = substr($code, 0, $pos) =~ tr/\n//; my ($single_line) = $full =~ /(.*\Q$func\E.*)/g; $found{$keyword}{$func} = [$nl_count + 1, $pos, $singl +e_line]; } } } return unless keys %found; say "\cl"; my $string = join "\n", map { my $keyword = $_; map "$found{$keyword}{$_}[2]\x7f\x01" . "$found{$keyword}{$_}[0],$found{$keyword}{$ +_}[1]", keys %{ $found{$keyword} } } keys %found; say $path, ',', 1 + length $string; say $string; } sub main { path('.')->visit(\&wanted, { recurse => 1 }); } main(); =head1 NAME perl-etags.pl =head1 SYNOPSIS cd /project/root && perl-etags.pl > TAGS =head1 DESCRIPTION Creates TAGS file similar to what the command C<etags> produces, but tries to handle C<Moose> keywords as well (C<has>, C<alias>). =head1 AUTHOR (c) 2016 E. Choroba =cut __END__ # Tested on the following: # ------------------------ #!/usr/bin/perl use warnings; use strict; package Etags::Test; use Moose; use MooseX::Aliases; has bare => (is => 'rw'); has 'quoted' => (is => 'rw'); has "double_quoted" => (is => 'rw'); has [qw[ list1 list2 ]] => (is => 'ro'); has [qw[ multi line ]] => (is => 'ro'); sub method {} sub method2 {} alias m2 => 'method2'; use MooseX::Declare; class Etags::Test2 { method method3 (Num $count) {} }
($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Etags for Emacs and Moose
by zakame (Pilgrim) on Sep 14, 2016 at 10:59 UTC | |
|
Re: Etags for Emacs and Moose
by LanX (Saint) on Aug 30, 2016 at 10:23 UTC |