regexperlexuberant-ctags

Using regexp with etags to parse customized definitions


I have a perl file where some functions are defined using special syntax (Mojolicious):

$app->helper('helper1' => sub {
            print "Hello 1";
        });

$app->helper("helper2" => sub {
            print "Hello 2";
        });

$app->helper(helper3 => sub {
            print "Hello 3";
        });

helper1();
helper2();
helper3();

I managed to create the Perl regexp to capture these definitions:

#!/usr/bin/perl

use strict;
use warnings;
use File::Slurp 'read_file';

my $code = read_file('helpers.pl');

my @matches = $code =~ /\$app\->helper\(['"]?(.*?)['"]? => sub/g;
foreach(@matches)
{
    print "$_\n";
}

Output:

helper1
helper2
helper3

But my attempt to use it in etags failed;

etags -l perl --regex="/\$app\->helper\\\(['\"]\(.*?\)['\"] => sub/" ./helpers.pl

Gives an empty TAGS file. What's wrong?


Solution

  • Universal Ctags just introduced pcre2 as an optional regular expression engine. If you build a ctags executable from the latest code in the git repository (git clone https://github.com/universal-ctags/ctags.git) with pcre2, you can use non-greedy match. That means the command line Andreas Louv showed may work well.

    $ cat /tmp/foo.pl                                                                                                                                                                             
    $app->helper('helper1' => sub {                                                                                                                                                               
                print "Hello 1";                                                                                                                                                                  
            });                                                                                                                                                                                   
                                                                                                                                                                                                  
    $app->helper("helper2" => sub {                                                                                                                                                               
                print "Hello 2";                                                                                                                                                                  
            });                                                                                                                                                                                   
                                                                                                                                                                                                  
    $app->helper(helper3 => sub {                                                                                                                                                                 
                print "Hello 3";                                                                                                                                                                  
            });                                                                                                                                                                                   
                                                                                                                                                                                                  
    helper1();                                                                                                                                                                                    
    helper2();                                                                                                                                                                                    
    helper3();                                                                                                                                                                                    
                                                                                                                                                                                                  
    $ ./ctags -o - --regex-perl='/\$app->helper\(['\''"]?(.*?)['\''"]? => sub/\1/s/{pcre2}' /tmp/foo.pl                                                                                           
    helper1 /tmp/foo.pl     /^$app->helper('helper1' => sub {$/;"   s                                                                                                                             
    helper2 /tmp/foo.pl     /^$app->helper("helper2" => sub {$/;"   s                                                                                                                             
    helper3 /tmp/foo.pl     /^$app->helper(helper3 => sub {$/;"     s                                                                                                                             
    $ ./ctags -e --regex-perl='/\$app->helper\(['\''"]?(.*?)['\''"]? => sub/\1/s/{pcre2}' /tmp/foo.pl                                                                                             
    $ cat TAGS                                                                                                                                                                                    
    ^L                                                                                                                                                                                            
    /tmp/foo.pl,133                                                                                                                                                                               
    $app->helper('helper1' => sub {^?helper1^A1,0                                                                                                                                                 
    $app->helper("helper2" => sub {^?helper2^A5,74                                                                                                                                                
    $app->helper(helper3 => sub {^?helper3^A9,148                                                                                                                                                 
    $                                                                                             
    

    You can verify you whether pcre2 is linked to your ctags or not.

    $ ./ctags --list-features | grep pcre2
    pcre2             has pcre2 regex engine
    $