Reputation: 3451
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
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
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
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