3 # pltags - create a tags file for Perl code, for use by vi(m)
5 # Distributed with Vim <http://www.vim.org/>, latest version always available
6 # at <http://www.mscha.com/mscha.html?pltags#tools>
8 # Version 2.3, 28 February 2002
10 # Written by Michael Schaap <pltags@mscha.com>. Suggestions for improvement
13 # This script will not work with Perl 4 or below!
16 # 1.0 1997? Original version, quickly hacked together
17 # 2.0 1999? Completely rewritten, better structured and documented,
18 # support for variables, packages, Exuberant Ctags extensions
19 # 2.1 Jun 2000 Fixed critical bug (typo in comment) ;-)
20 # Support multiple level packages (e.g. Archive::Zip::Member)
21 # 2.2 Jul 2001 'Glob' wildcards - especially useful under Windows
22 # (thanks to Serge Sivkov and Jason King)
23 # Bug fix: reset package name for each file
24 # 2.21 Jul 2001 Oops... bug in variable detection (/local../ -> /^local.../)
25 # 2.3 Feb 2002 Support variables declared with "our"
26 # (thanks to Lutz Mende)
28 # Complain about undeclared variables
34 # Options with their defaults
35 my $do_subs = 1; # --subs, --nosubs include subs in tags file?
36 my $do_vars = 1; # --vars, --novars include variables in tags file?
37 my $do_pkgs = 1; # --pkgs, --nopkgs include packages in tags file?
38 my $do_exts = 1; # --extensions, --noextensions
39 # include Exuberant Ctags extensions
42 my $VERSION = "2.21"; # pltags version
43 my $status = 0; # GetOptions return value
44 my $file = ""; # File being processed
45 my @tags = (); # List of produced tags
46 my $is_pkg = 0; # Are we tagging a package?
47 my $has_subs = 0; # Has this file any subs yet?
48 my $package_name = ""; # Name of current package
49 my $var_continues = 0; # Variable declaration continues on last line
50 my $line = ""; # Current line in file
51 my $stmt = ""; # Current Perl statement
52 my @vars = (); # List of variables in declaration
53 my $var = ""; # Variable in declaration
54 my $tagline = ""; # Tag file line
56 # Create a tag file line and push it on the list of found tags
61 $is_static, # Is this a static tag?
62 $file, # File in which tag appears
63 $line) = @_; # Line in which tag appears
65 my $tagline = ""; # Created tag line
67 # Only process tag if not empty
70 # Get rid of \n, and escape / and \ in line
76 $tagline = "$tag\t$file\t/^$line\$/";
78 # If we're told to do so, add extensions
81 $tagline .= ";\"\t$type"
82 . ($is_static ?
"\tfile:" : "")
83 . ($package_name ?
"\tclass:$package_name" : "");
86 # Push it on the stack
87 push (@tags, $tagline);
91 # Parse package name from statement
94 my ($stmt) = @_; # Statement
96 # Look for the argument to "package". Return it if found, else return ""
97 if ($stmt =~ /^package\s+([\w:]+)/)
101 # Remove any parent package name(s)
111 # Parse sub name from statement
114 my ($stmt) = @_; # Statement
116 # Look for the argument to "sub". Return it if found, else return ""
117 if ($stmt =~ /^sub\s+([\w:]+)/)
121 # Remove any parent package name(s)
131 # Parse all variable names from statement
136 # Remove my or local from statement, if present
137 $stmt =~ s/^(my|our|local)\s+//;
139 # Remove any assignment piece
142 # Now find all variable names, i.e. "words" preceded by $, @ or %
143 @vars = ($stmt =~ /[\$\@\%]([\w:]+)\b/g);
145 # Remove any parent package name(s)
151 ############### Start ###############
153 print "\npltags $VERSION by Michael Schaap <mscha\@mscha.com>\n\n";
156 $status = GetOptions
("subs!" => \
$do_subs,
157 "vars!" => \
$do_vars,
158 "pkgs!" => \
$do_pkgs,
159 "extensions!" => \
$do_exts);
161 # Usage if error in options or no arguments given
162 unless ($status && @ARGV)
164 print "\n" unless ($status);
165 print " Usage: $0 [options] filename ...\n\n";
166 print " Where options can be:\n";
167 print " --subs (--nosubs) (don't) include sub declarations in tag file\n";
168 print " --vars (--novars) (don't) include variable declarations in tag file\n";
169 print " --pkgs (--nopkgs) (don't) include package declarations in tag file\n";
170 print " --extensions (--noextensions)\n";
171 print " (don't) include Exuberant Ctags / Vim style\n";
172 print " extensions in tag file\n\n";
173 print " Default options: ";
174 print ($do_subs ?
"--subs " : "--nosubs ");
175 print ($do_vars ?
"--vars " : "--novars ");
176 print ($do_pkgs ?
"--pkgs " : "--nopkgs ");
177 print ($do_exts ?
"--extensions\n\n" : "--noextensions\n\n");
178 print " Example: $0 *.pl *.pm ../shared/*.pm\n\n";
182 # Loop through files on command line - 'glob' any wildcards, since Windows
183 # doesn't do this for us
184 foreach $file (map { glob } @ARGV)
186 # Skip if this is not a file we can open. Also skip tags files and backup
188 next unless ((-f
$file) && (-r
$file) && ($file !~ /tags$/)
191 print "Tagging file $file...\n";
198 open (IN
, $file) or die "Can't open file '$file': $!";
203 # Statement is line with comments and whitespace trimmed
204 ($stmt = $line) =~ s/#.*//;
208 # Nothing left? Never mind.
211 # This is a variable declaration if one was started on the previous
212 # line, or if this line starts with my or local
213 if ($var_continues or ($stmt =~/^my\b/)
214 or ($stmt =~/^our\b/) or ($stmt =~/^local\b/))
216 # The declaration continues if the line does not end with ;
217 $var_continues = ($stmt !~ /;$/);
219 # Loop through all variable names in the declaration
220 foreach $var (VarNames
($stmt))
222 # Make a tag for this variable unless we're told not to. We
223 # assume that a variable is always static, unless it appears
224 # in a package before any sub. (Not necessarily true, but
225 # it's ok for most purposes and Vim works fine even if it is
229 MakeTag
($var, "v", (!$is_pkg or $has_subs), $file, $line);
234 # This is a package declaration if the line starts with package
235 elsif ($stmt =~/^package\b/)
237 # Get name of the package
238 $package_name = PackageName
($stmt);
242 # Remember that we're doing a package
245 # Make a tag for this package unless we're told not to. A
246 # package is never static.
249 MakeTag
($package_name, "p", 0, $file, $line);
254 # This is a sub declaration if the line starts with sub
255 elsif ($stmt =~/^sub\b/)
257 # Remember that this file has subs
260 # Make a tag for this sub unless we're told not to. We assume
261 # that a sub is static, unless it appears in a package. (Not
262 # necessarily true, but it's ok for most purposes and Vim works
263 # fine even if it is incorrect)
266 MakeTag
(SubName
($stmt), "s", (!$is_pkg), $file, $line);
273 # Do we have any tags? If so, write them to the tags file
276 # Add some tag file extensions if we're told to
279 push (@tags, "!_TAG_FILE_FORMAT\t2\t/extended format/");
280 push (@tags, "!_TAG_FILE_SORTED\t1\t/0=unsorted, 1=sorted/");
281 push (@tags, "!_TAG_PROGRAM_AUTHOR\tMichael Schaap\t/mscha\@mscha.com/");
282 push (@tags, "!_TAG_PROGRAM_NAME\tpltags\t//");
283 push (@tags, "!_TAG_PROGRAM_VERSION\t$VERSION\t/supports multiple tags and extended format/");
286 print "\nWriting tags file.\n";
288 open (OUT
, ">tags") or die "Can't open tags file: $!";
290 foreach $tagline (sort @tags)
292 print OUT
"$tagline\n";
299 print "\nNo tags found.\n";