~technomancy/fennel-mode

Emacs support for the Fennel programming language
Treat multisym separators as punctuation.
handle values from the ,return op
add support for the ,return command

refs

main
browse  log 

clone

read-only
https://git.sr.ht/~technomancy/fennel-mode
read/write
git@git.sr.ht:~technomancy/fennel-mode

You can also use your local clone with git send-email.

#Fennel Mode

Font-lock, indentation, navigation, documentation, and REPL support for the Fennel programming language.

Supports M-x imenu for quick navigation to local definitions.

#Installation

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))

Note that fennel-mode doesn't inherit from lisp-mode since 0.4.0, and instead switched to prog-mode. This means that there is no longer any way to declare shared functionality (such as paredit) that you want to be applied to every lisp you use; you have to add hooks specifically to fennel-mode-hook.

#Interactivity

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.

  • C-c C-z - Start or switch to REPL buffer
  • C-c C-e - Evaluate current top-level form (also C-M-x)
  • C-x C-e - Evaluate last expression before the point
  • C-c C-r - Evaluate the region
  • C-c C-S-p - Evaluate the paragraph
  • C-c C-k - Reload the module for the current file (requires fennel.seacher)
  • C-c C-d - Ask for a value and show its docstring in the REPL
  • C-c C-l - Display compilation output for the current file
  • C-c C-t - Reformat current buffer with fnlfmt (separate install)
  • C-c C-p - Print macro expansion of expression at point in the REPL
  • M-. - Jump to the definition of a globally-visible function
  • M-' - Jump to the definition of a function in a module
  • M-, - Jump back to where you were before jumping to definition
  • M-TAB - Completion at point (Fennel 0.9.3+)

These 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 finding the definition of a function with M-. only works when the function is in scope for the REPL, which means it's usually best to load a module and set it as a global if you want to use it this way.

#Antifennel

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.

#Protocol-based REPL

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:

  • IO and evaluation results are separated.
  • Stack traces in Errors can be used to jump to the error location.
  • Evaluation results are shown in the echo area - no need to keep the REPL window open.
  • Running multiple REPLs is easier, and different buffers can be linked to different REPLs.
  • Synchronous and Asynchronous API.
  • Support for Eldoc and Xref.

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 session
  • C-c C-b - Evaluate the whole buffer
  • C-c C-a - Ask for a function and show its argument list in the REPL

Starting 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.

#Org Babel support

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.

#Contributing

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.

#Testing

This package has tests stored in the tests directory. When developing new functionality consider writing a test for it. You can use cask to run these tests like so:

$ cask install # needs to be done only once
$ cask exec ert-runner

It should automatically find all test files and execute all of the tests. Alternatively, tests can be ran via the ert-run-tests-batch-and-exit combined with find:

$ find test -type f -exec emacs -batch -L . -l path/to/lua-mode.el -l {} -f ert-run-tests-batch-and-exit \;

Copyright © 2018-2023 Phil Hagelberg and contributors

Licensed under the same license as Emacs (GPL v3 or later); see LICENSE