Fennel on Neovim: Getting Started (with nfnl) [editor/fennel-getting-started]

Why Fennel? Because Lua is too verbose to my taste. And among the alternatives, Fennel

  • ships with many syntax sugars and concise syntax forms.
    • Tables get much shorter!
  • is a Lisp.
    • S-expressions.
    • Expression-based syntax.
    • Macros.
  • has a near one-to-one mapping to Lua.

For instance:

{
  config = function()
    if vim.o.columns < 60 then
      return "short"
    else
      return "full"
    end
  end
}

in Lua is

{:config #(if (< vim.o.columns 60)
              "short"
              "full")}

in Fennel. Now you can see the benefits, as I have many similar cases in my actual config.

I use a little plugin called nfnl1, which automatically compiles Fennel code to Lua on save.

After installing the plugin, a Neovim config in Fennel is as simple as:

# in the config directory
# you can also use an empty file, which saves you from future permission prompts
echo {} > .nfnl.fnl
nvim init.fnl

Upon saving, nfnl will generate init.lua from init.fnl (it won’t override pre-existing files though). If you are migrating from a Lua-based config, you may find it easier to write an init_.fnl and check the compiled Lua before swapping it in place. It’s rather trivial to write Fennel code equivalent to Lua, so it won’t take long after you get used to the language. And the generated file is decently readable, so check it out when in doubt.

Since this plugin compiles Fennel to Lua ahead of time, it’s not needed to load a config developed with it. Actually there’s no need to load it at all in filetypes other than Fennel. In my config with lazy.nvim I wrote:

[{1 "Olical/nfnl" :ft "fennel"}]

And it works as intended. Neovim gets its Lua, I get my Fennel and they lived happily thereafter.

1

There are other solutions like aniseed and hotpot.nvim. I chose nfnl because it’s minimal and robust.