The home of Mikael Jansson, hacker, hobby chef & adrenaline junkie based in Sweden. More…

Mikael Jansson.be » Hacking
limp.png

1   Limp: When You Need More Than Just A Lisp

Contact:
Limp User for help/comments (subscribe to limp-user)
Web:
Download Limp (Vim.org)
IRC:
#limp on irc.freenode.net (I'm logged in as tic)
Date:

$Date: 2008-06-12 00:28:50 -0700 (Thu, 12 Jun 2008) $

Author:

Mikael Jansson


Limp's goal is to provide a compelling alternative to SLIME for Vim.

Features include:

works-on-my-machine.png
  • booting/attaching/detaching a Lisp (SBCL) from Vim or a command-line script, optionally specifying a core;
  • send code to the attached Lisp (and limited introspection, see Help Describe);
  • automatically close brackets;
  • highlight current form under the cursor;
  • lookup documentation from the HyperSpec;
  • complete (some) names.

1.2   Installation

1.2.1   Upgrading from 0.3.2 and earlier

Limp is now a filetype plugin. If you're using 0.3.2 or earlier, you need to remove your old installation of Limp, i.e.:

$ rm -rf ~/.vim/plugin/limp.vim
$ rm -rf ~/.vim/limp

then proceed with the installation as described below.

1.2.2   Dependencies

Limp relies on a few application and packages.

  • Vim7.x with +eval
  • SBCL
  • rlwrap for SBCL command-line editing
  • UNIX SCREEN for SBCL communication
  • The Common Lisp Hyperspec for the For the Lisp thesaurus
  • Perl for generating the Lisp thesaurus

These are easily installable on Debian-based systems such as Ubuntu:

$ sudo aptitude install vim-full sbcl hyperspec rlwrap screen perl

1.2.3   Automatic Installation

Unpack the archive, change to the newly created directory and run the installation script:

$ sudo ./install.sh

This will install Limp in /usr/local/limp/0.3.4, symlink it to latest in the same directory, and finally make a symlink in your Vim configuration directory's ftplugin/lisp (creating it if it doesn't already exist) pointing to latest Limp.

1.2.4   Manual Installation

Unless installed in /usr/local/limp/0.3.4, Limp needs to have the variable $LIMPRUNTIME pointing to the base directory, so add this to your ~/.bash_profile (or equivalent settings file for your shell):

export LIMPRUNTIME=/path/to/limp/0.3.4

Place 0.3.4 in the directory pointed out by $LIMPRUNTIME and setup the following symlinks:

$ ln -sf $LIMPRUNTIME/vim $HOME/.vim/ftplugin/lisp/limp
$ ln -sf limp/limp.vim $HOME/.vim/ftplugin/lisp/limp.vim

Finally, generate the Lisp thesaurus:

$ cd $LIMPRUNTIME/bin
$ ./make-thesaurus.sh

1.2.5   Optional

I've included a nifty color scheme, for 256-color-capable terminals: 0.3.4/vim/desert256.vim. Copy it to your $HOME/.vim/colors directory.

If you're planning on using the command line tool lisp.sh to list/boot/connect to Lisp listeners outside of Vim, make a symlink like this:

$ ln -sf /usr/local/limp/0.3.4/bin/lisp.sh /usr/local/bin

1.3   Quickstart

This should get you going with Limp!

screenshots/disconnected.png

Vim started with a simple hello-world program.

screenshots/connecting.png

Press <F12> and Enter to start a new Lisp.

screenshots/listener.png

Press <F12> again to go to the listener.

screenshots/sending-code.png

Press <F12> to return to Vim.

Move the cursor somewhere inside the form and press \et (Evaluate Top form). The function definition will be sent to the running Lisp.
screenshots/listener-with-defun.png

Looking at the listener, you see that the code you just sent has been compiled.

screenshots/highlighting-current-form.png

Let's add more code inside the function definition. With the cursor in the middle of the newly added form, you can now press \ec (Evaluate Current form) to send only what's currently highlighted.

screenshots/evaluating-current-form.png

And here you can see the results.

screenshots/evaluate-prompt.png

We can also evaluate arbitrary expressions, such as looking at a symbol, using \ex (Evaluate eXpression) and typing something at the prompt, followed by enter to send it.

screenshots/expression-sent.png

Yes, it is indeed a symbol.

screenshots/defun-with-documentation.png

Let's remove that extra line of code in the function, and add a docstring describing the function. Send the definition to Lisp with \et.

screenshots/describe-symbol.png

With the cursor on the word say-hello, we now press \hd (Help Describe) to get detailed information from Lisp about the symbol.

screenshots/describe-results.png

This is what our Lisp believes SAY-HELLO to be.

1.3.1   Shell

screenshots/listing-lisps.png

If we exit Vim, our Lisp is still active. You can attach from it directly from the command line, or from another Vim session.

1.3.2   Freezing and Thawing

You can save your Lisp's state and later restore it. Very handy.

screenshots/save-lisp-and-die.png

Here, I've booted up a fresh Lisp and evaluated the function definition. Then, <Shift-F12> asks for the path of a file to save the core in. The Lisp core is now frozen in time.

screenshots/custom-core.png

I quit Vim and opened up a completely empty file, empty.lisp, to really point out that I will not evaluate any code from the Lisp file. Press <F12>, Enter, name it "test", Enter and Limp then asks for a core to boot. Here, input the core we just saved.

screenshots/evaluate-saved-code.png

With the core booted, we should have the function say-hello available.

screenshots/listener-from-core.png

Yup. Nice!

1.4   Usage

1.4.1   Documentation Lookup

Example 1:

(defun fib (n)
;   ^ cursor here
  (cond ((or (= n 0)
             (= n 1)) 1)
        (t (+ (fib (- n 1))
           (fib (- n 2))))))

With the cursor at the indicated spot, "K" (see below) will invoke your browser with file://localhost/path/to/hyperspec/Body/m_defun.htm#defun. This may require some configuration of a Perl script, limp-hyperspec.pl. See below.

Example 2:

with-
; ^ cursor here

With the cursor at the indicated spot, "hp" (see below) will invoke your browser with the address of a freshly built index of links to:

with-accessors
with-compilation-unit
with-condition-restarts
with-hash-table-iterator
with-input-from-string
with-open-file
with-open-stream
with-output-to-string
with-package-iterator
with-simple-restart
with-slots
with-standard-io-syntax

1.4.1.1   Configuration

Limp uses a Perl script, limp/bin/limp-hyperspec.pl, for invoking a browser with the documentation. I use Opera (www.opera.com), so Limp comes comes pre-configured to use it. I've done some testing with Lynx and Netscape, so uncomment those lines to try those browsers. I haven't gotten Konqueror to work to my satisfaction; if you do, please drop me an e-mail.

There are a few configuration parameters you can set in the file to modify the default browser and such.

$BASE
Where you keep your copy of the HyperSpec. Defaults to /usr/share/doc/hyperspec.
$browser_name
The name of your browser, assumed findable via your $PATH. Defaults to "opera".
$external
Will your browser open a new window (e.g. set to 0 to use lynx). Defaults to 1.
@browser_args

Array of string arguments to your browser. Opera's "new-page" argument to openURL gives each set of HyperSpec search results a new page. Other browsers may have analogous flags, and similar behavior.

limp-hyperspec.pl replaces %s in @browser_args with the URL to be opened. See the Opera configuration for an example.

$READLINE_ON_BROWSER_START
Whether to make you press enter when it starts a browser for the first time. Defaults to 0 (i.e. no).

The script requires you to have a local copy of the HyperSpec. It searches $BASE/Front/X_Perm_*.htm to find the symbols you want it to look for. You can find a tarball of the CLHS at http://www.xanalys.com. If you use Debian or a derivative, such as Ubuntu, apt-get install hyperspec will put the HyperSpec in /usr/share/doc/hyperspec. limp-hyperspec.pl looks for it there, by default.

1.4.2   Completion

1.4.2.1   Name Completion

Limp can complete the names of symbols. They tend to be rather long, so it's a useful thing.

screenshots/name-completion.png

First, type this in Vim...

screenshots/name-completion-popup.png

Then, hitting ^N (Ctrl-N) will expand least- into least-negative-long-float first, then (with another ^N) least-positive-long-float, then least-negative-short-float, and so on.

1.4.2.2   Name Expansion

There's a convention to talk about dashed names by abbreviating them into the first letter of each word, e.g.:

screenshots/name-expansion.png

First, type this in Vim...

screenshots/name-expansion-popup.png

Then, hitting ^N^N (Ctrl-N twice) will expand the p-n to package-name. ^N again will replace package-name with pathname-name, and ^N yet again will replace that with pprint-newline. See Vim help for complete, compl-generic, and i_CTRL-X_CTRL-T. Also, see below for notes on this facility.

1.4.2.3   Notes

  • Due to the way the Vim thesaurus works, you have to press ^N (Ctrl-N) twice to get the first replacement for abbreviations like w-a => with-accessors, but only once after that. For Vim to know to expand w-a into with-accessors, I have to include w-a in the thesaurus file, so w-a expands first into just w-a, then with-accessors. See the lisp-thesaurus file and "help i_CTRL-X_CTRL-T".
  • For the multi-word symbols beginning with * and & (e.g. &allow-other-keys), you can expand on an abbreviation with or without the leading special character (e.g. a-o-k and &a-o-k both expand into &allow-other-keys (if you've set iskeyword correctly -- see above)).
  • lisp-thesaurus sorts keywords by length, and then alphabetically. This mostly matters when expanding ambiguous abbreviations for multi-word symbols. E.g., c-i expands into char-int, then count-if (which both have eight characters), then clear-input (which comes before count-if alphabetically, but has eleven characters).
  • I generated lisp-thesaurus from the HyperSpec with make-lisp-thes.pl. Figuring it out is left as an exercise to the reader.

Finally, you should install SuperTab and and use that instead of the default keys used for completion!

1.4.3   Commands

Limp defines a buffer-level command, :Eval.

:Eval <sexp> will evaluate an s-exp, e.g.:

:Eval (format t "Hello, world!~%")

Limp mode is automatically set when evaluating the following:

:set filetype=lisp

Useful for editing files not automatically detected as Lisp files (such as .asd-files, $HOME/.sbclrc, etc.)

1.4.3.1   GVim notes

The default behaviour when running gvim is to open an xterm. There are two flags you can adjust:

b:listener_always_open_window
Open a separate xterm even if running console vim
b:listener_keep_open
Open the xterm in the background. Will not prevent you from pressing F12 multiple times (and thus open many xterms).

1.4.4   Keyboard Reference

The default settings in Limp. All bindings can be easily changed in /path/to/limp/0.3.4/vim/keys.vim.

<F12>
Connect to a running Lisp or start a new Lisp, optionally specifying a core file to boot from. When connected, the key will toggle displaying the Lisp or Vim.
<Control-F12>
Disconnect from the current Lisp, which will be active in the background. You can re-attach to it using <F12>.
<Shift-F12>
Quit Lisp, optionally saving the core in a file (prompted for).

The rest of the bindings assumes <LocalLeader> == "\", which is the default. Some people prefer let maplocalleader = ",".

1.4.4.1   Listener

This is a regular screen session. Escape is <Ctrl-z>, and <F12> is mapped to detach (<Ctrl-z> d).

1.4.4.2   Lisp Interaction

For sending code to a Lisp.

  • \ec: (Evaluate Current): Evaluate the current form
  • \et: (Evaluate current Top level form): Evaluate the currrent form to the top level
  • \ex: (Evaluate eXpression): Prompt for arbitrary expression to evaluate
  • \eb/ec/et: (Evaluate currently selected Block): Evaluate the currently visual block
  • \lf: (Load File): Load the current file in Lisp
  • \la: (Load Any file): Load any version (.lisp, .fasl, ...) of this file
  • \cf: (Compile File): Compile the current file
  • \cl: (Compile and Load): Compile current file and load
  • \ar: (Abort Reset): Send ABORT to Lisp
  • \ai :(Abort Interrupt): Send C-c to Lisp

1.4.4.3   S-Exp Manipulation

Source transformation.

  • \mt: (Mark Top): Mark the current form to the top level
  • \fc: (Format Current): Reindent/format current form
  • \ft: (Format current Top level form): Reindent/format current form to the top level
  • \sw: (S-exp Wrap): Wrap the current form inside another list
  • \sp: (S-exp Peel): Peel off a list around the current s-exp
  • \sc :(S-exp Comment top): Comment top form
  • \sC :(S-exp comment Current): Comment current form
  • (, ): Go to previous/next s-exp
  • {, }: Transpose current s-exp backward/forward (Experimental! Works only for easy cases.)

1.4.4.4   Limp

Vim interaction.

  • \gt: (Goto Test): Goto the test buffer
  • \gs: (Goto Scratch): Goto the scratch buffer (where the latest evaluated form is)
  • \gl: (Goto Last): Goto the last buffer
  • \tc: (Test Current): Send current form to test buffer
  • \tt: (Test Top): Send top-level form to test buffer

1.4.4.5   Documentation

Looks things up in the HyperSpec, by opening a browser pointing to a local copy of the HyperSpec.

  • \hd: (Help Describe): Describe the current symbol in the Lisp listener
  • \he: (Help Exact): Lookup exact symbol
  • \hp: (Help Prefix): Lookup symbol as prefix
  • \hs: (Help Prefix): Lookup symbol as suffix
  • \hg: (Help Grep): Lookup symbol by greping through all symbols
  • \hi: (Help Index): Go the the index page of the first letter of the current word. E.g., if you have the cursor on "member" and type hi, takes you to the Permuted Symbol Index (M) page.
  • \hI: (Help Index page): Takes you to the Alphabetical Symbol Index & Permuted Symbol Index page.

Moreover, K works as expected, doing an exact matching.

1.4.4.6   Brackets

When typing an opening bracket, paren or double-quote, it automatically adds the closing bracket. You can now either type the closing symbol yourself or skip it altogether. Backspacing over it removes the pair.

1.4.4.7   OS X Notes

Depending on your keyboard preferences, you might have to press Cmd-(Shift-)F12. Also, Ctrl-F12 seems to be chomped by the system, so you'll have to change vim/limp.vim to use something else than <C-F12> for disconnect. (Or, you can simply quit Vim; that'll have the same effect.)

Also, if Vim doesn't say you're connected after booting Lisp, you might have to set the proper location to SBCL/SBCL_HOME in bin/lisp.sh.

1.4.4.8   Useful Vim Commands

Vim comes with support for a few useful things out-of-the-box. You should try these out:

[<CTRL-I>
Jump to the definition of the word under the cursor
[I
Display all lines containing the word under the cursor.

Exuberant Ctags works perfectly well for Lisp source code, so you can use the tag system to navigate in your Lisp source code. For non-US keyboards, the default keybinding can be impossible to type in. Here's a better mapping, <Ctrl-Space> (... which generates C-@):

map <C-@> <C-]>

1.5   Changelog

1.5.1   Version 0.3.3

  • 2008-05-23 by Mikael Jansson <mail@mikael.jansson.be>
    • CompileFile/CompileAndLoadFile now saves the file before telling Lisp to load it (#4).
  • 2008-05-20 by Mikael Jansson <mail@mikael.jansson.be>
    • New command, :Eval, same functionality as \ex.
    • Easier keyboard configuration (keys.vim)
  • 2008-05-19 by Mikael Jansson <mail@mikael.jansson.be>
    • It is now a Lisp filetype plugin, so Limp will start automatically for Lisp files. (set filetype=lisp)
  • 2008-05-15 by Mikael Jansson <mail@mikael.jansson.be>
    • Configurable location of SBCL in lisp.sh
    • Updated documentation about Cmd for Fn-keys in OS X

1.5.2   Version 0.3.2

  • 2008-04-28 by Mikael Jansson <mail@mikael.jansson.be>
    • ADDED: TODO file in the distro.
    • FIXED: Last occurance of "Lim" found in the HyperSpec helper. Now documentation should work properly.
    • TWEAK: Only change colorscheme and nocompatible when not previously set.
  • 2008-04-27 by Mikael Jansson <mail@mikael.jansson.be>
    • FIXED: Connect-or-boot, without a name given to boot.

1.5.3   Version 0.3.1

  • 2008-04-27 by Mikael Jansson <mail@mikael.jansson.be>
    • FIXED: Stray LIMRUNTIME. Could make Limp connect to the wrong Lisp if both LIMRUNTIME and LIMPRUNTIME was set and pointing at different locations.

1.5.4   Version 0.3

  • 2008-04-26 by Mikael Jansson <mail@mikael.jansson.be>
    • ADDED: Optionally specify core at startup and shutdown.
    • ADDED Added "quit Lisp" mapping on Shift-F12 and removed the \aq mapping.
    • FIXED: (Hopefully) fixed lisp.sh to work on OS X and other non-GNU systems. Thanks to Nico Weber for patches!
    • TWEAK: Renamed Lim to Limp.

1.5.5   Version 0.2.2

  • 2008-04-26 by Mikael Jansson <mail@mikael.jansson.be>
    • FIXED: Typo in HyperSpec lookup code
    • TWEAK: Updated documentation

1.5.6   Version 0.2.1

  • 2008-04-26 by Mikael Jansson <mail@mikael.jansson.be>
    • FIXED: Fixed copy-paste typo for 'Goto Last'
    • TWEAK: Better connection status information

1.5.7   Version 0.2

  • 2008-04-25 by Mikael Jansson <mail@mikael.jansson.be>
    • ADDED: Replaced the Perl funnel betwen Vim and Lisp with screen.

1.5.8   Version 0.1

1.6   Known Issues

  • When the Lisp disappears, no warning is given when trying to send code to it (you will get an error message, though). When that happens, disconnect (<Control-F12>) and reconnect.

1.7   Authors

Mikael Jansson
Main developer, more info at http://mikael.jansson.be

1.7.1   Includes Work By

Larry Clapp
Without his hard work on VIlisp, this would never have happened.
Karl Guertin
For AutoClose. Small patch applied to enable/disable instead of toggling.
Charles E. Campbell, Jr.
For HiMtchBrkt. Modified to highlight the contents inside the brackets, removed Vim (<7.x) backward compatibility.
'