Skip to content
Phil Hagelberg edited this page Feb 2, 2024 · 1 revision

The command-line REPL that comes with the fennel script works out of the box, but the built-in line-reader is very limited in user experience. Adding GNU Readline support enables user-friendly features, such as:

  • tab-completion on the REPL that can complete on all locals, macros, and special forms
  • a rolling history buffer, which can be navigated, searched (ctrl+r), and optionally persisted to disk so you can search input from previous REPL sessions
  • Emacs (default) or vi key binding emulation via readline's custom support for better line navigation
  • optional use of additional readline features in ~/.inputrc, such as blinking on matched parentheses or color output (described below)

Requirements for readline support

  • GNU Readline (installation steps vary for different operating systems, but you may already have it!)
  • readline.lua Lua bindings to libreadline

The best way to get readline.lua is to install it with your system's package manager, but if you can't do that you can use LuaRocks, which will fetch the package and automatically compile the native bindings for you.

Note: The Fennel REPL will automatically load and use the readline bindings when it can resolve the readline module, so that's all you need to get started.

Installing readline.lua with LuaRocks

To install readline.lua with LuaRocks:

  1. Ensure libreadline is installed.
  2. Run one of the following commands:
    • luarocks install --local readline (recommended)
    • luarocks install --lua-version=5.1 readline (for a non-default Lua version)
    • luarocks install readline (requires root or admin)

Note: If you've installed with the --local flag, you may need to ensure your package.path and package.cpath contain its location.

Configuring readline.lua

You can configure readline.lua using one of the following options:

  • the readline.lua API in ~/.fennelrc
  • the readline ~/.inputrc file

If you have readline installed but do not wish to use it (for example, running Fennel inside an Emacs shell or recording a session to a file) you can export TERM=dumb as an environment variable.

Enabling persistent history using fennelrc

To configure the REPL to save the rolling history to file at the end of every session, add the following to your ~/.fennelrc with your desired filename:

See the readline.lua documentation for information on its API, most notably other parameters that can be set via rl.set_options.

;; persist repl history
(case package.loaded.readline
  rl   (rl.set_options {:histfile  "~/.fennel_history" ; default:"" (don't save)
                        :keeplines 1000}))             ; default:1000

Configuring readline in ~/.inputrc

See the documentation on the readline init file for the full set of options and a sample inputrc.

The following example adds these behaviors:

  • Blink on a matching parenthesis when entering ). Useful in a Lisp REPL, where the parens are plentiful!
  • Enable bracketed paste mode for more reliable pasting from clipboard
  • When tab-completing on a term with more than one possible match, display all candidates immediately instead of ringing the bell + requiring a second <tab>

Create a ~/.inputrc file with the following contents:

set enable-bracketed-paste on
set blink-matching-paren on
set show-all-if-ambiguous on

You can make use of a conditional directive your inputrc if you would like certain settings to only apply to Fennel.

Clone this wiki locally