[neomutt-devel] Neomutt: now featuring Lua scripting!

Guyzmo z+mutt+neomutt at m0g.net
Fri Apr 28 00:49:40 CEST 2017


My dear neomutters,

Following a few past mails on the topic, now neomutt is embedding a Lua
runtime that makes it possible to access all of neomutt's 'public' API
as a Lua API.

Because the Muttrc language is just a simple descriptive language (it
being a list of command statements), it is not aimed at being a Turing
complete language — pardon my French. But thanks to Lua, you can get it
all with a fully feature language that's built-in, and does not add
weight to the Neomutt binary.

Because up until now I've been the only user of Lua in Neomutt, please,
please, try it out, implement some fresh ideas, have fun with it!
But don't hesitate to torture it, find edge cases, make it scream,
crash, burn 🔥! And don't forget to report if you do!

When the Lua abilities (and its API) will be considered stable enough by
the community, it will be enabled by default at compilation, and
properly documented in the manual.

# Presentation of the Lua API

There are three main novelties with this feature:

1. there is two new Neomuttrc commands:

    :lua                       to execute a single line of lua
    :lua-source                to execute a lua source file

the Lua interpreter is running for the whole duration of the Neomutt
session. So a variable declared in Neomuttrc will be available in a
sourced Lua file, and during runtime with :lua.

2. a command line argument --batch (-B) that starts mutt, executes any
Neomuttrc file commands and exists without launching the GUI or
expecting any mail composition.

That can be useful if you want to run a Lua script exploiting the Neomutt
API, but without launching the ncurses user interface.

3. the interpreter exposes in Lua's global scope a mutt namespace
containing a very basic API.

⚠️ Because Lua support is still very immature, you need to explicitely
enable it at compile time, by adding the `--enable-lua` option to the
configure script.

# Description of the API

## settings

    mutt.get(option)           returns an option into a object
    mutt.set(option, value)    sets options to value

settings are typed accordingly to Neomutt's expectations with matching
Lua types. If you feed it an incompatible type, expect an exception!

## commands

    mutt.enter(cmd)            runs a string containing a command exactly
                               as you'd write it on the `:` enter-command
                               command line.
    mutt.call(cmd, arg1, …)    runs a command, the command name is the
                               first argument, its arguments all the
                               following ones.
    mutt.command.<cmd>(args)   runs a command as a standard Lua function.

Some commands can return values, and those will be assignable.
Upon error, they will throw exceptions.

# Example 

which can be used as a muttrc:

```muttrc
# settings

lua mutt.set("visual", "less")
lua mutt.set("connect_timeout",42)
lua mutt.set("arrow_cursor", true)
lua mutt.set("abort_noattach", mutt.QUAD_ASKNO)

# commands, the three following ones are strictly equivalent

lua mutt.command.color("quoted", "brightblue", "default")
lua mutt.call("color", "quoted", "brightblue", "default")
lua mutt.enter("color quoted brightblue default")

# of course the first one is more elegant
```

# Road ahead

I'm making a call for everybody interested to try it out, integrate it
in their configurations, and implement neat ideas! With that simple API,
and the full force of Lua libraries, it's possible to create a lot of
great plugins!

For the next step, I'd like to follow up with:

* binding all the commands that are contextualized to the buffers (index,
  pager…)
* exposing internals, using functions and objects:
    * manipulate the index,
    * manipulate the pager,
    * maniputale a message details,
    * manipulate a message's attachments
    * and so and sofort

eventually, I think that some mutt patches that became part of Neomutt
could be extracted as Lua plugins, or some unpopular feature requests
could be made using it.


# Resources

* a test suite has been implemented as an example and is available in
  the sources (you'll need to install `busted` with luarocks to test it):
    * https://github.com/neomutt/neomutt/blob/master/contrib/lua/test_lua-api_spec.lua
    * https://github.com/neomutt/neomutt/blob/master/contrib/lua/test_lua-api_runner.muttrc
* here's the ticket that has been used to track development of that
  feature:
    * https://github.com/neomutt/neomutt/issues/153
* here's a script I used to check typing of the get/set options during
  development (a poor man's unit test):
    * https://gist.github.com/guyzmo/9ed8ec8cd54486cf6e97d4c8f2526a2e

# Finally

don't hesitate to follow up on this mail, ping me on IRC (zmo on
#neomutt), open an issue in the bugtracker for ideas, feature requests,
or when you'll find a bug.

Thank you for reading this mail 🙌
And have fun with it!

Cheers,

-- 
zmo


More information about the neomutt-devel mailing list