In: Articles
14 Oct 2012Textmate is a marvelous text editor for programming and other text based tasks on OSX. It even has a great extension for assisting when programming Perl. One of the really helpful features is a syntax validation happening when a file is saved.
Take for example this incomplete Perl source file below

If you specify the contents as perl (see the bottom of the window) or let Textmate resolve this Textmate will evaluate the contents when I save and get an error due to the very obvious syntax error in line 3.

Correcting the contents of the file, will give me status indicating an evaluation success.

This is really nifty most of the time, but I ran into a problem.
I am using App::perlbrew (perlbrew) to handle my local Perl installations. Perlbrew is a magnificent tool and it lets me install several different Perl interpreters in parallel. So I can evaluate my code using different versions of Perl.
The check executed by Textmate is handled by a script named: perlcheckmate.pl (available on Github) and it relies solely on the system perl installed in /usr/bin.
So when I work on a project requiring a newer (or older) version and I then use Perlbrew to satisfy this, I have to install external dependencies with two Perls – not exactly optimal also because I am not interested in maintaining and feeding all sort of crazy modules to my system Perl, just because I am working on some project.
Luckily adjusting perlcheckmate.pl to recognize and use perlbrew is quite easy.
perlbrew sets some environment variables when active:
When perlbrew is active these variables will have content, if not or not installed, existing behavior should be preserved – and not everyone uses perlbrew.
So if PERLBREW_PERL is defined we have a Perl interpreter controlled by perlbrew and we can adjust accordingly. See lines 34 to 42. So We define our Perl interpreter to point to this instead of the Perl interpreter located in /usr/bin.
- #!/usr/bin/perl
- use strict;
- # cwd should be $™_DIRECTORY
- # filename to check is $ARGV[0]
- my $file = $ARGV[0];
- my %file_source;
- sub read_source {
- my $file_source;
- my $path = $file;
- if (!-f $path || !File::Spec->file_name_is_absolute($path)) {
- $path = File::Spec->rel2abs($path, $ENV{™_DIRECTORY});
- if (!-e $path) {
- my $base = File::Basename::basename($path);
- foreach (@INC) {
- my $file = File::Spec->catfile($_, $base);
- $path = $file, last if -e $file;
- }
- }
- }
- $file_source{$file} = { source => \@file_source, path => $path };
- }
- my $perl;
- if ($PERLBREW_PERL) {
- $perl = “$PERLBREW_ROOT/perls/$PERLBREW_PERL/bin/perl”;
- } else {
- $perl = ‘perl’;
- }
- my @lines = `”$perl” -Tcw “$file” 2>&1`;
- }
- $lines =~ s/&/&/g;
- $lines =~ s/</</g;
- $lines =~ s/>/>/g;
- # link line numbers to source
- $lines =~ s%^((?:.+)[ ]+at[ ]+(.+)[ ]+line[ ]+)(\d+)[.,]%
- my $pre = $1;
- my $file = $2;
- my $lnum = $3;
- my $col;
- if ($pre =~ m/“([^”]+)”/) {
- read_source($file)
- my $source_line = $file_source{$file}{source}[$lnum-1];
- $file = $file_source{$file}{path};
- $col = $col != -1 ? $col + 1 : 0;
- } else {
- read_source($file)
- $file = $file_source{$file}{path};
- }
- }
- $url .= “&column=$col” if $col;
- %gmex;
- my $output = ‘<pre style=“word-wrap: break-word;”>’;
- $output .= $lines;
- $output .= ‘</pre>’;
To make a point on my opinion on the use of system perl. You can have a look at the perlcheckmate.pl script above. This script is an external application, bundled with Textmate and therefor it relies on the presence of perl in /usr/bin in order to work, so this line is perfectly okay and it should work even though the operating system is updated.
If you read the script carefully you can see that the script uses two external components:
These are Perl core modules and they should not give any problems. But if you by some weird coincidence and accidentally change or break these as part of development, you are breaking your toolchain at the same time. Your system perl should be considered a key component in your operating system on most modern operating systems.
This blog acts as a channel for communicating logicLAB’s open source activities. Announcements on open source initiatives, involvements and releases of open source distributions of software products, projects and applications.
3 Responses to Textmate and Perlbrew
Joel Berger
October 14th, 2012 at 15:47
I know on Linux, its easier to just invoke a script using ‘#!/usr/bin/env perl’. A quick google search shows that env exists on mac too. Might you just want to change the #! line to this in perlcheckmate.pl?
Alex
October 17th, 2012 at 01:23
If you use…
#!/usr/bin/env perl
As your shebang line it should pick up whatever perl you currently have set as your currently active perlbrew perl, or the system wide perl if perlbrew is in “off” mode.
Then in your code if you really need access to your perl binary’s path you can use $^X.
alex@karin:~$ perlbrew list
* perl-5.16.1
alex@karin:~$ /usr/bin/env perl -E ‘say $^V; say $^X;’
v5.16.1
/home/alex/perl5/perlbrew/perls/perl-5.16.1/bin/perl
alex@karin:~$ /usr/bin/perl -E ‘say $^V; say $^X;’
v5.14.2
/usr/bin/perl
jonasbn
January 12th, 2013 at 13:49
Thanks for the feedback. I am very happy to see the use of env working on OSX. It works like a charm…