samtregar has asked for the wisdom of the Perl Monks concerning the following question:

Hello monks. Does anyone know of a good Perl LOC counter? A trip to the Oracle at Super Search and the archives of Google failed to produce a usable program. I'd like something that can skip comments, whitespace and POD. If I can't find anything I'll write one myself but this is one wheel I'm not dying to reinvent.

Thanks!
-sam

Replies are listed 'Best First'.
Re: Perl LOC counter?
by diotalevi (Canon) on May 14, 2003 at 22:31 UTC

    How about perl -MO=Deparse foo.pl | wc -l?

      Nice. One caveat: this will include __DATA__ and __END__ and the lines following if you don't want to consider those LOC.
Re: Perl LOC counter?
by hv (Prior) on May 15, 2003 at 02:12 UTC

    Here's something I knocked up for my current work project:

    #!/usr/bin/perl -w use strict; use File::Find; my($d, $c, $h, $q, $s, $x) = (0, 0, 0, 0, 0, 0); for my $dir (qw/ cgi lib util /) { find(sub { return if /^\.#/ || /,v$/ || /\.(swp|gif|jpg|png|ps|tr|o|a)$/ +|| /~$/ || /^core$/; $File::Find::prune = 1, return if $File::Find::dir =~ /\bCVS\b +/; return unless -f && -T; local *F; my $file = $_; open F, $file or warn "$File::Find::dir/$file: $!\n"; my $cut = 0; my $here = undef; my $where; while (<F>) { if ($cut) { ++$$where; $cut = 0 if $cut > 0 && /^=cut/; } elsif ($here) { ++$$where; $here = undef if /$here/; } elsif (/^=/) { ++$d; $cut = 1; $where = \$d; } elsif (!/\S/) { ++$s; } elsif (/^\s*#/) { ++$c; } elsif (/<<(?:'(\w+)'|(\w+))/) { my $style = $1 || $2; $where = ($style eq 'SQL') ? \$q : \$h; $here = qr/^$style$/; ++$x; } elsif (/^__(DATA|END)__$/) { $cut = -1; $where = \$h; } else { ++$x; } } }, $dir); } print "doc $d, comment $c, SQL $q, text $h, space $s, code $x\n";

    You'd probably want to tailor the pruning logic and the list of directories to check (or perhaps refactor it to handle just one file at a time) and lose the special-case 'SQL' check, but I think the rest is quite generally applicable.

    Hugo
Re: Perl LOC counter?
by abell (Chaplain) on May 15, 2003 at 09:09 UTC
    Sloccount works for many languages including perl.



    The stupider the astronaut, the easier it is to win the trip to Vega - A. Tucket
      Thanks, that looks like the answer. However, I had to fix a bug in sloccount 2.22 before it would actually skip POD. I'll send it to the maintainer, but here it is in case anyone needs it too:

      --- ../sloccount-2.22/perl_count 2002-01-02 12:21:08.000000000 +-0500 +++ perl_count 2003-05-15 13:33:45.000000000 -0400 @@ -58,7 +58,8 @@ open (FILE, $file); while (<FILE>) { s/#.*//; # Delete leading comments. - if (m/^\s*$heredocument/) {$heredocument = ""; # finished here do +c. + if ($heredocument and m/^\s*$heredocument/) { + $heredocument = ""; # finished here doc. } elsif (m/<<\s*["']?([A-Za-z0-9_-]+)["']?[;,]\s*$/) { # Beginning of a here document. $heredocument = $1;

      -sam

Re: Perl LOC counter?
by jplindstrom (Monsignor) on May 15, 2003 at 13:45 UTC
    I wrote a script like that. It's available here:

    http://www.bahnhof.se/~johanl/perl/perl_summary/perl_summary.pl.txt

    This is a typical output when $ARGV1 doesn't contain an output file:

    *** MODULES ***
    Total used: 45
    
    -- SKIP MODULE LIST --
    
    
    No files: 33
    
    *** LINES ***
    Source (total): 12094
        Code + POD: 9101 (75%)
              Code: 6090 (50%)
               POD: 3011 (24%) (33% of code + POD lines)
     Comments left: 183 ( 1%) of source
      Comments EOL: 408 ( 6%) of code
        Whitespace: 6004 (49%)
         Size (Kb): 216
    

    If you provide an output file, you can run it daily and open the file in Execel and create a progress diagram over time.

    All available disclaimers apply, it's second time it left my computer today :) If you find it usefull, fine. If not, fine. I'm sure ther are stuff to improve.

    /J

      Very interesting. I ran this on some test code and the results are very different from SLOCCount (see above). They're around twice as high for the count of lines of code. My guess is that it has something to do with how you're counting POD lines. SLOCCount just stops counting lines of code when it sees /^=\w/ and starts again when it sees /^=cut/. Your method seems more sophisticated, but I wonder if it's correct. I plan to investigate more closely to figure out which one is right.

      -sam

        Well, looking at my code I see that

        $noLineCode += scalar(grep { $_ =~ /\w/ } @aLine);

        will include POD as well, so... it actually measures "code" as opposed to "whitespace", not "code" as opposed to "non-code". Eh, so to speak :)

        It depends on what you want to measure and what you think the metric says about the source.

        /J