The Dark Balloon

A weblog by Hao Lian.
A journey into the soft of night.
A terrible secret guarded by golems.

§
The carefully woven ack duality amid the surreptitious cloak of night.

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.

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?

@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 cmd.exe 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 follows: cmd.exe ignores the Perl bits thanks to goto endofperl and @rem. Perl ignores the command prompt bits with an assignment to the fake array @rem.

Two more juicy and more obvious bits: The assignment to @rem doesn’t 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.

[(2008 June 21) .]

You’ll find that Perl command line tools generally get wrapped up in that .BAT cleverness on Windows - it’s not specific to ack.

You’re right though, ack is indeed “the infinitely superior grep alternative”

D’oh. I got all caught up in my excitement, I just assumed it was ack-specific. Thanks for the context.

Dude, that just doesnt make any sense whatsoever.

JT http://www.anondo.alturl.com

—JImmyDoLIt on 2008.06.22 (07:28)

Abandon your ideas.

Use Markdown+, but not HTML. In code blocks, beware angle brackets.