Last Action Hero

This sort of thing happens to me all the time:

$ emacs
The file does not exist.
$ touch
$ emacs

Or maybe I’m just lsing a bunch of directories and find one I need to get into:

$ ls /long/path/to/where/ever
$ cd /long/path/to/where/ever

Or I want to remind myself of what a shell function does before running it, so I run cat. But I see something’s off, so I need to make a quick update:

$ cat ~/.config/fish/functions/
$ emacs ~/.config/fish/functions/

There are three ways to create that second command:

  1. Type the whole thing out.
  2. Hit the up arrow, alt-arrow back through the path, delete the cat, type in emacs.
  3. The same as #2 but you hit ctrl-a instead of alt-arrowing.

And here’s a fourth method:

$ lah emacs

lah stands for Last Action Hero. It finds the last non-lah command in your history, replaces the executable’s name with the new name you provide, and executes that new command.


$ emacs
The file does not exist.
$ lah touch

will run touch, and then

$ lah emacs

will run emacs

If you enter more than one parameter, it will append the rest to the end of the new command. So, following the above,

$ lah emacs notes

will run emacs notes

If you want to give a gander, it’s on Github.


Lisp is wonderful. I’ve been reading Structure and Interpretation of Computer Programs and The Little Schemer and pretty much any article related to Lisp that appears on Hacker News but I haven’t yet had a reason to write anything in a Lisp beyond the exercises in the books.

So lah is my first. It works and I’m happy with it but it’s not a very good solution to the problem. Here’s a fish function to accomplish basically the same thing:

function lah
  set old_cmd $history[1]
  set old_exec (echo $old_cmd | cut -f 1 -d ' ')
  set new_cmd (echo $old_cmd | sed "s/$old_exec/$argv[1]/")
  eval $new_cmd

But why write six lines of fish when you could write 66 lines of Lisp?