Font lock the interpreter line
font-lock eros messages
add eros integration to fennel-proto-repl
Font-lock, indentation, navigation, documentation, and REPL support for the Fennel programming language in Emacs.
Supports M-x imenu for quick navigation to local definitions.
Add this to your config:
(autoload 'fennel-mode "/path/to/fennel-mode/fennel-mode" nil t)
(add-to-list 'auto-mode-alist '("\\.fnl\\'" . fennel-mode))
Separately you'll also probably want to use fennel-ls, which works
great with eglot. In Emacs 30+, it will work automatically once
fennel-ls is installed; in earlier versions you need to add this to
your config:
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs '(fennel-mode . ("fennel-ls"))))
Run M-x fennel-repl RET to open a REPL buffer. Once a REPL is open,
you can send code from a fennel-mode buffer to be evaluated.
fennel-modeM-. - Jump to the definition of a globally-visible function (xref)M-, - Jump back to where you were before jumping to definitionM-' - Jump to the definition of a function in a moduleC-c C-k - Reload the module for the current file (requires fennel.seacher)C-c C-l - Display compilation output for the current fileC-c C-z - Start or switch to REPL bufferC-c C-t - Reformat current buffer with fnlfmt (separate install)C-c C-d - Ask for a value and show its docstring in the REPL (also C-c C-f)C-c C-v - Show docstring of variable at pointC-c C-p - Print macro expansion of expression at point in the REPLC-x C-e - Evaluate last expression before the pointC-c C-e - Evaluate current top-level form (also C-M-x)C-c C-n - Evaluate current top-level form, then move to the nextC-c C-r - Evaluate the regionC-c C-z - Start or switch to REPL bufferfennel-repl-modeTAB - Completion at pointC-c M-o - Clear the REPL outputC-c C-d - Ask for a value and show its docstring in the REPL (also C-c C-f)C-c C-v - Show docstring of variable at pointM-. - Jump to the definition of a globally-visible functionC-c C-z - Toggle back to previous fennel-mode bufferC-c C-q - Quit the REPLThese functions assume a fennel executable is present on your
path. You can override the location by setting inferior-lisp-program
or invoking C-u M-x fennel-repl. For instance, if you have a stdio
REPL in a LÖVE game, you can set this to love ..
Note that many evaluation or jump features require having the
functions in the repl scope, not just in scope for the file. The repl
cannot "enter" a file as this concept does not exist at runtime in Lua.
Running C-c C-k will load the buffer into a module but will not dump
its contents into the repl; you would need C-c C-r for that.
This repo also contains antifennel.el which allows you to compile
Lua code to Fennel straight from a lua-mode buffer. It requires
installing antifennel first. Install it with:
(autoload 'antifennel-mode "/path/to/fennel-mode/antifennel.el" nil t)
(add-hook 'lua-mode-hook 'antifennel-mode)
Now when antifennel-mode is active in a Lua buffer, you can press
C-c C-f to open a new buffer containing the Fennel equivalent of the
Lua code.
A separate REPL integration is provided via the fennel-proto-repl
module. This module provides a client that can connect to a regular
Fennel REPL, upgrade it with the protocol code, and provides a
more robust interactive experience. Advantages over the default
fennel-repl are:
project.el or projectile.Installation is similar to the other modules:
(autoload 'fennel-proto-repl "/path/to/fennel-mode/fennel-proto-repl.el" nil t)
(add-hook 'fennel-mode-hook 'fennel-proto-repl-minor-mode)
The fennel-proto-repl-minor-mode re-binds all of the default REPL
interaction keys available in fennel-mode to use fennel-proto-repl
instead of a regular fennel-repl. In addition to the usual
fennel-mode mappings listed above, additional commands are
available:
C-c C-S-l - link the current buffer to a specific REPL sessionC-c C-b - Evaluate the whole bufferC-c C-a - Ask for a function and show its argument list in the REPLStarting the REPL or switching to the existing one is done via the
same C-c C-z shortcut, and the new REPL session can be started at
any moment with the fennel-proto-repl command. The buffer is
automatically linked to the newly created REPL.
Note that fennel-proto-repl requires a Fennel version recent enough
to include the ___repl___ variable. If the Fennel doesn't have the
___repl___ variable the Proto REPL won't be started.
Installation is similar to the other modules:
(autoload 'ob-fennel "/path/to/fennel-mode/ob-fennel.el" nil t)
Then, the support for Fennel in Org buffers can be activated by adding the following code to the Emacs init file:
(with-eval-after-load 'org
(require 'ob-fennel))
After that, the #+begin_src fennel code blocks can be executed in
Org buffers. The integration requires the fennel-proto-repl module
to be available and operational.
The ob-fennel module supports evaluating code from the regular "src
blocks", and "inline src blocks" (src_fennel[]{...}), with the
ability to access variables and tables defined elsewhere in the file.
Multiple sessions can be used, and a different command to start the
REPL process can be passed via the :fennel-cmd header argument.
The Flymake backend depends on the fennel-ls for linting, if you would rather avoid using eglot.
Installation is similar to the other modules:
(autoload 'fennel-ls-flymake "/path/to/fennel-mode/fennel-ls-flymake.el" nil t)
Enabling the Flymake integration for Fennel buffers can be done via a hook:
(add-hook 'fennel-mode-hook 'fennel-ls-flymake)
Send patches to the Fennel mailing list. If you prefer not to use email you can send a pull request on the Codeberg mirror. Please byte-compile to check for warnings.
This package has tests stored in the test/ directory. When
developing new functionality consider writing a test for it.
You can run the tests with make. By default this runs the tests for
fennel-mode alone; for fennel-proto-repl and ob-fennel you can
override the TESTS argument or run tests interactively via
ert-run-tests-interactively after loading the respecting test file.
Use make EMACS=emacs29 to test against a different Emacs version.
During development it may be more convenient to use M-x ert-run-tests-interactively but try to make sure the tests pass with
a fresh Emacs using make before committing.
Copyright © 2018-2025 Phil Hagelberg and contributors
Licensed under the same license as Emacs (GPL v3 or later); see LICENSE