Note from the editorial board: This was originally published on The Dark Balloon. Yes I am an idiot for not realizing it was pl2bat.
How does Ack on Windows work? After all, Windows’ command prompt
doesn’t support shebangs or any other terminal features invented in
the last century. Once you type
ack, it actually matches to the
ack.bat file in your PATH. And when you open that, you get a huge
surprise because somebody has smuggled an entire Perl program into
a batch script. Furthermore, Emacs is in Perl mode for no apparent
reason. What the hell is going on?
Update: Thanks, AndyArmstrong! This magic is specific not to ack but to pl2bat, and unfortunately I can’t track down the person who wrote that sexy voodoo, so I am removing the attribution below. There are similar tools for Python (by Christian Schaller) and Ruby.
@rem = '--*-Perl-*-- @echo off perl -x -S %0 %* goto endofperl @rem '; #!/usr/local/bin/perl #line 15 use warnings; use strict; our $VERSION = '1.84'; use App::Ack (); [rest of the code] :endofperl
These are the edited first lines to
ack.bat, the executable for
Windows. It’s part of the infinitely superior grep alternative,
Ack. (To install, type
cpan App::Ack into your terminal unless
you’re using ActiveState Perl. In that case, you should switch to
Strawberry Perl to preserve sanity.)
Why is this terribly clever? The
@rem = '--*--Perl-*-- should tip
you off. It’s a MS-DOS comment (that is,
cmd.exe totally ignores
that line), but it’s also a Perl array assignment. In fact, the
single quotation mark starts a string that doesn’t end until the
semicolon at which point the
ack script takes over.
Now the big picture emerges: When you run
ack, you run
ack.bat. That, in turn, it runs
perl.exe ack.bat %*, where
is a list of arguments you passed to
ack.bat. And, boom, the rest
cmd.exe ignores the Perl bits thanks to
@rem. Perl ignores the command prompt bits with an assignment to
the fake array
Two more juicy and more obvious bits: The assignment to
throw a warning because it happens before
use strict. And the
--*-Perl-*-- tells Emacs, vim, and your favorite text editor to switch to Perl mode.