Emacs REPL Management: Mastering termint for Interactive Coding
Tired of clunky REPL interactions in Emacs? Discover how termint.el
streamlines your Read-Eval-Print Loop workflow with flexible terminal emulators. Control multiple REPLs within Emacs using termint
with support for term
, vterm
, and eat
.
Why Use termint
for Emacs REPLs?
termint.el
provides a robust way to manage REPL sessions directly within Emacs, leveraging the power of terminal emulators. Unlike Emacs' built-in comint-mode
, termint
utilizes terminal emulators like term
, vterm
, or eat
, meaning bracketed paste mode and proper rendering are enabled, providing a cleaner, more efficient REPL experience.
Key Features of termint.el
- Flexible REPL Definition: Easily define interactions for various REPLs using the
termint-define
macro. - Multiple Terminal Backends: Supports
term
,vterm
, andeat
. Choose your preferred backend withtermint-backend
. - Customizable Interaction: Fine-tune behavior like bracketed paste, code delimiters, and preprocessing.
- Code Sourcing: Simplify code execution with temporary file writing and sourcing commands.
- Automatically Generated Commands:
- Start/switch REPL sessions.
- Send selected regions/strings to the REPL.
- Source selected regions in the REPL.
- Hide the REPL window.
- Evil Integration: Seamlessly incorporates Evil operators for efficient text manipulation.
- Dedicated Keymap: Easily access generated commands through a dedicated prefix keymap.
Installation and Setup
- Install
termint
from MELPA:
Or, using(package-install 'termint)
straight.el
:(straight-use-package 'termint)
- Choose Your Terminal Backend:
Ensure the corresponding package ((setq termint-backend 'eat) ; Or 'vterm', or 'term'
vterm
oreat
) is installed if you select it.term
is built-in. It's generally recommended to useeat
orvterm
for better performance.
Mastering the termint-define
Macro
The termint-define
macro is the heart of termint
. It enables the definition of a schema for interacting with a specific REPL.
(termint-define REPL-NAME REPL-CMD &rest ARGS)
For example:
(termint-define "myrepl" "myrepl-command" :bracketed-paste-p t :source-syntax "source %s")
This generates functions like termint-myrepl-start
, termint-myrepl-send-string
, plus region, paragraph, buffer, and defun operations for sending and sourcing code. Let's explore some functions it generates:
Key Functions at a Glance
termint-myrepl-start
: Starts or switches to the REPL session in a new terminal buffer.termint-myrepl-send-string
: Sends a string (prompted) to the REPL, useful for individual commands.termint-myrepl-send-region
: Sends the selected region of the buffer for execution.termint-myrepl-source-region
: Sources the selected region, treating it as a file. More on this below.termint-myrepl-hide-window
: Hides the REPL window.termint-myrepl-map
: A keymap containing default bindings for the generated functions. You can bind this map to a prefix key for convenient access.
Understanding Sourcing Versus Sending Code
termint
distinguishes between "sourcing" and "sending" code to the REPL.
- Sending: Code is passed directly to the REPL's standard input (like typing or pasting). Best for interactive commands and short snippets.
- Sourcing: Code is written to a temporary file, and a command is sent to the REPL to execute that file. Ideal for large code blocks, avoiding cluttering interaction history and mitigating potential issues with
stdin
processing, especially on Windows.
Important Security Note: Sourcing involves temporary file creation, so be aware of potential vulnerabilities if temporary file handling is compromised.
Bracketed-Paste Mode Explained
Bracketed-paste mode wraps pasted text in escape sequences, allowing terminal emulators to differentiate between typed input and pasted text. Enable it using :bracketed-paste-p t
in termint-define
. This prevents misinterpretation of newlines and special characters, but test for compatibility with your REPL.
Integrating with use-package
To configure termint
with lazy-loading and autoloading, use use-package
. Separate use-package
forms for each REPL schema are recommended.
(use-package termint
:demand t
:after python
:bind
(:map python-ts-mode-map
("C-c s" . termint-ipython-start))
:config
(termint-define "ipython" "ipython" :bracketed-paste-p t
:source-syntax termint-ipython-source-syntax-template)
(define-key python-ts-mode-map (kbd "C-c m") termint-ipython-map))
Key Points for use-package
integration:
- Use
:bind-keymap
to globally bind atermint-repl-map
to a prefix key. - Use
define-key
within the:config
block to bind atermint-repl-map
to a prefix key within a specific major mode.
Customizing Window Management
Control the display behavior of REPL buffers by defining window popup rules in display-buffer-alist
.
(add-to-list 'display-buffer-alist
'("\\*ipython\\*"
(display-buffer-in-side-window
display-buffer-reuse-window)
(window-width . 0.5)
(window-height . 0.5)
(side . bottom)
(slot . -1)))
termint
vs. Alternatives
- Emacs Built-in
comint
:termint
offers superior terminal emulation compared tocomint
, supporting advanced features. - Language/Backend-Specific Packages: While packages like
py-vterm-interaction
provide deeper integration,termint
offers a more general and flexible, backend-agnostic solution (works withterm
,vterm
,eat
) suitable for multiple languages.
Start leveraging termint
today to transform your Emacs REPL experience! Contributions, bug reports, and feature requests are welcome.