Chris Koknat
Chris Koknat

Reputation: 3451

.vimrc to automatically compile perl code, based on actual perl version

My .vimrc is configured to automatically compile my Perl script upon save. However, it is hard-coded to perl 5.14.
Some of the scripts I maintain are 5.8.8, and others are 5.16
I would like vim to compile my code based on the version in the hashbang #! line
Is this possible?

Here is my current .vimrc:

" check perl code with :make
"     by default it will call "perl -c" to verify the code and, if there are any errors, the cursor will be positioned in the offending line.
" errorformat uses scanf to extract info from errors/warnings generated by make.
"     %f = filename  %l = line number  %m = error message
" autowrite tells vim to save the file whenever the buffer is changed (for example during a save)
" BufWritePost executes the command after writing the buffer to file
" [F4] for quick :make
autocmd FileType perl set makeprg=/home/utils/perl-5.14/5.14.1-nothreads-64/bin/perl\ -c\ %\ $*
autocmd FileType perl set errorformat=%f:%l:%m
autocmd FileType perl set autowrite
autocmd BufWritePost *.pl,*.pm,*.t :make 

Upvotes: 3

Views: 483

Answers (3)

Chris Koknat
Chris Koknat

Reputation: 3451

I found another way to solve this problem.
Instead of setting makeprg to the perl executable, I tell vim to execute another script.
That script determines the appropriate version of perl, then runs that version with -c
This solution could be extended for other scripting languages

In the .vimrc, change:
autocmd FileType perl set makeprg=/home/utils/perl-5.14/5.14.1-nothreads-64/bin/perl\ -c\ %\ $*
to:
autocmd FileType perl set makeprg=/home/username/check_script_syntax.pl\ %\ $*

#!/home/utils/perl-5.14/5.14.1-nothreads-64/bin/perl
use 5.014;    # enables 'say' and 'strict'
use warnings FATAL => 'all';
use IO::All;
my $script = shift;
my $executable;
for my $line ( io($script)->slurp ) {
    ##!/home/utils/perl-5.14/5.14.1-nothreads-64/bin/perl
    ##!/home/utils/perl-5.8.8/bin/perl
    if ( $line =~ /^#!(\/\S+)/ ) {
        $executable = $1;
    } elsif ( $script =~ /\.(pm)$/ ) {
        if ( $script =~ /(releasePatterns.pm|p4Add.pm|dftform.pm)$/ ) {
            $executable = '/home/utils/perl-5.8.8/bin/perl';
        } else {
            $executable = '/home/utils/perl-5.14/5.14.1-nothreads-64/bin/perl';
        }
    } else {
        die "ERROR:  Could not find #! line in your script $script";
    }
    last;
}
if ( $script =~ /\.(pl|pm|t)$/ ) {
    $executable .= " -c";
} else {
    die "ERROR:  Did not understand how to compile your script $script";
}
my $cmd = "$executable $script";
say "Running $cmd";
say `$cmd`;

Upvotes: 0

ernix
ernix

Reputation: 3643

Use plenv to change perl versions for your projects: plenv local 5.8.8

https://github.com/tokuhirom/plenv

You don't have to specify the path for shebang and makeprg.

Upvotes: 0

Ingo Karkat
Ingo Karkat

Reputation: 172600

You have to dynamically change the Perl path in 'makeprg' based on the shebang line. For example:

:let perlExecutable = matchstr(getline(1), '^#!\zs\S\+')
:let perlExecutable = (empty(perlExecutable) ? '/home/utils/perl-5.14/5.14.1-nothreads-64/bin/perl' : perlExecutable) " Default in case of no match
:let &makeprg = perlExecutable . ' -c % $*'

You can invoke that (maybe encapsulated in a function) on the FileType event, but then it won't properly detect new files that don't have the shebang yet. Or prepend the call to your autocmd BufWritePost *.pl,*.pm,*.t :make; that will re-detect after each save.


PS: Instead of all those :autocmd FileType in your ~/.vimrc, I would rather place those in ~/.vim/after/ftplugin/perl.vim (if you have :filetype plugin on). Also, you should use :setlocal instead of (global) :set.

Upvotes: 2

Related Questions