/geiser

GNU Emacs and Scheme talk to each other

Primary LanguageEmacs LispBSD 3-Clause "New" or "Revised" LicenseBSD-3-Clause

Overview

Geiser is a generic Emacs/Scheme interaction mode, featuring an enhanced REPL and a set of minor modes improving Emacs’ basic scheme major mode. The main functionalities provided are:

  • Evaluation of forms in the namespace of the current module.
  • Macro expansion.
  • File/module loading.
  • Namespace-aware identifier completion (including local bindings, names visible in the current module, and module names).
  • Autodoc: the echo area shows information about the signature of the procedure/macro around point automatically.
  • Jump to definition of identifier at point.
  • Access to documentation (including docstrings when the implementation provides it).
  • Listings of identifiers exported by a given module.
  • Listings of callers/callees of procedures.
  • Rudimentary support for debugging (list of evaluation/compilation error in an Emacs’ compilation-mode buffer).
  • Support for inline images in schemes, such as Racket, that treat them as first order values.

If you’re not in a hurry, Geiser’s website contains a much nicer manual.

Supported schemes

Geiser needs Emacs 27.1 or better, and installing also at least one of the supported scheme implementations.

The following schemes are supported via an independent package, installable from either NonGNU ELPA or MELPA:

Installation

Using ELPA

Geiser is available in the ELPA repositories NonGNU ELPA (pre-configured by default as a source starting in Emacs 28) and MELPA. So the easiest way is to use the ELPA package, and just type

M-x package-install RET geiser-<implementation>

inside emacs, or the corresponding use-package stanza, for, say

(use-package geiser-mit :ensure t)

All the concrete implementation packages depend on the base geiser package, so it’ll be installed for you.

From a repository checkout

If you are not using MELPA, just put this repository’s elisp directory and the target’s scheme directory in your load path and require the latter:

(add-to-list 'load-path "<geiser checkout dir>/elisp")
(add-to-list 'load-path "<geiser-mit checkout dir>")
(require 'geiser-mit)

Some scheme implementations need additional installation steps to fully support all geiser operations, so please do check their corresponding web pages.

Basic configuration

When opening a scheme file, Geiser will try to guess its Scheme, defaulting to the first in the list geiser-active-implementations. If you’ve installed more than one geiser package, you can also use C-c C-s to select the implementation by hand (on a per file basis).

Check the geiser customization group for some other options with:

M-x customize-group RET geiser RET

In particular, customize geiser-<impl>-binary, which should point to an executable in your path.

To start a REPL, run M-x geiser.

Completion at point

Geiser offers identifier and module name completion, bound to M-TAB and M-` respectively. Only names visible in the current module are offered.

While that is cool and all, things are even better: if you have Company or Corfu installed, Geiser’s completion will integrate with it. Just enable global-company-mode/corfu-global-mode and, from then on, any new scheme buffer or REPL will use it. Alternatively you can activate company-mode or corfu-mode individually only in some buffers.

Macro expansion with macrostep-geiser

Geiser offers basic macro expansion in a dedicated buffer. If you prefer in-buffer, step by step expansion, please take a look at Nikita Bloshchanevich’s macrostep-geiser.

Quick key reference

(See also the user’s manual cheat sheet’)

In Scheme buffers:

C-c C-sSpecify Scheme implementation for buffer
C-c C-zSwitch to REPL
C-c C-aSwitch to REPL and current module
M-.Go to definition of identifier at point
M-,Go back to where M-. was last invoked
C-c C-e mAsk for a module and open its file
C-c C-e C-lAdd a given directory to Scheme’s load path
C-c C-e [Toggle between () and [] for current form
c-c C-e \Insert λ
C-c C-iInterrupt on-going evaluation
C-M-xEval definition around point
C-c C-cEval definition around point
C-c M-eEval definition around point and switch to REPL
C-x C-eEval sexp before point
C-c C-rEval region
C-c M-rEval region and switch to REPL
C-c C-bEval buffer
C-c M-bEval buffer and switch to REPL
C-c C-m xMacro-expand definition around point
C-c C-m eMacro-expand sexp before point
C-c C-m rMacro-expand region
C-c C-kCompile and load current buffer
C-c C-lLoad scheme file
C-u C-c C-kCompile and load current buffer, restarting REPL
C-c C-d dSee documentation for identifier at point
C-c C-d sSee short documentation for identifier at point
C-c C-d iLook up manual for identifier at point
C-c C-d mSee a list of a module’s exported identifiers
C-c C-d aToggle autodoc mode
C-c <Show callers of procedure at point
C-c >Show callees of procedure at point
M-TABComplete identifier at point
M-`, C-.Complete module name at point
TABComplete identifier at point or indent
(If geiser-mode-smart-tab-p is t)

In the REPL

C-c C-zStart Scheme REPL, or jump to previous buffer
C-c M-oClear scheme output
C-c C-qKill Scheme process
C-c C-lLoad scheme file
C-c C-kNuke REPL: use it if the REPL becomes unresponsive
M-.Edit identifier at point
TAB, M-TABComplete identifier at point
M-`, C-.Complete module name at point
M-p, M-nPrompt history, matching current prefix
C-c \Insert λ
C-c [Toggle between () and [] for current form
C-c C-mSet current module
C-c C-iImport module into current namespace
C-c C-rAdd a given directory to scheme’s load path
C-c C-d C-dSee documentation for symbol at point
C-c C-d C-mSee documentation for module
C-c C-d C-aToggle autodoc mode

In the documentation browser:

fNext page
bPrevious page
TAB, nNext link
S-TAB, pPrevious link
NNext section
PPrevious section
kKill current page and go to previous or next
g, rRefresh page
cClear browsing history
., M-.Edit identifier at point
zSwitch to REPL
qBury buffer

In backtrace (evaluation/compile result) buffers:

  • M-g n, M-g p, C-x ` for error location navigation.
  • n, p for moving among errors in the buffer.
  • , to pop-up the debugger actions menu.
  • q to bury buffer.

How to support a new scheme implementation

Geiser works by running an instance of a REPL, or remotely connecting to one, and evaluating the scheme code it sees there. Then, every time it needs to perform some operation (like, say, printing autodoc, jumping to a source location or expanding a macro), it asks the running scheme instance for that information.

So supporting a new scheme usually means writing a small scheme library that provides that information on demand, and then some standard elisp functions that invoke the procedures in that library.

To see what elisp functions one needs to implement, just execute the command `M-x geiser-implementation-help` inside emacs with a recent version of geiser installed. And then take a look at, say, geiser-guile.el for examples of how those functions are implemented for concrete schemes.

Not all schemes can provide introspective information to implement all the functionality that geiser tries to offer. That is okay: you can leave as many functions unimplemented as you see fit (there is even an explicit list of unsupported features), and geiser will still know how to use the ones that are implemented.