Skip to content

After you've started it seems like a bad idea?

To recap: given the absence of other credible alternatives I had two options:

  • Re-hack mutt to give me a sidebar that will show only folders containing new messages.
  • Look at writing a "simple mail client". Haha. Ha. Hah.

I think there is room for a new console client, because mutt is showing its age and does feel like it should have a real extension language - be it guile, lisp, javascript(!), Lua, or something else.

So I distilled what I thought I wanted into three sections:

  • mode-ful. There would be a "folder-browsing mode", a "message-browsing mode" and a "read-a-single-message" mode.
  • There would be scripting. Real scripting. I chose Lua.
  • You give it ~/Maildir as the configuration. Nothing else. If the damn computer cannot find your mailboxes something is wrong.

So how did I do? I wrote a ncurses-based client which has Lua backed into it. You can fully explore the sidebar-mode - which lets you select multiple folders.

From there you can view the messages in a list.

What you can't do is anything "real":

  • Update a messages flags. new -> read, etc.
  • GPG-validation.
  • MIME-handling.
  • Attachment viewing.

For a two-day hack it is remarkably robust, and allowing scripting shows awesomeness. Consider this:

-- show all folders in the Maildir-list.
function all()
   -- ensure that the sidebar displays all folders
   sidebar_mode = "all";
   -- we're going to be in "maildir browsing mode"
   cmail_mode = "sidebar";

-- Test code, show that the pattern-searching works.
-- To use this press ":" to enter the prompt, then enter "livejournal".
-- OR press "l" when in the sidebar-mode.
function livejournal()
   sidebar_pattern = "/.livejournal.2";
   sidebar_mode = "pattern";

-- There is a different table for each mode.
keymap = {}
keymap['sidebar'] = {}
keymap['index']   = {}
keymap['message'] = {}

-- In the sidebar-mode "b" toggles the sidebar <-> index.
-- ":" invokes the evaluator.
-- "q" quits the browser and goes to the index-mode.
-- "Q" quits the program entirely.
keymap['sidebar'][':'] = "prompt-eval"
keymap['sidebar']['b'] = "toggle"
keymap['sidebar']['q'] = "toggle"
keymap['sidebar']['Q'] = "exit"

-- show all/unread/livejournal folders
keymap['sidebar']['a'] = "all"
keymap['sidebar']['u'] = "unread"
keymap['sidebar']['l'] = "livejournal"

Neat, huh? See the cmail.lua file on github for more details.

My decision hasn't really progressed any further, though I can see that if this client were complete I'd love to use it. Its just that the remaining parts are the fiddly ones.

I guess I'll re-hack mutt, and keep this on the back-burner.

The code is ropey in places, but should you wish to view:

And damn C is kicking my ass.

Comments On This Entry

  1. [gravitar] Anonymous

    Why are you writing this in C?

    Also, Lua is barely passable as a language, and more importantly the C interface used to embed it and expose API to it ranks among the worst for extension languages. You might seriously consider choosing another extension language. Perhaps Scheme or Python.

  2. [author] Steve Kemp

    I (mostly) like C, and picked it because I wanted to write it using S-Lang or curses.

    Though I expect if I were to do further work I'd probably jump-ship to C++ to get access to STL. (Having vectors, etc, would be a lot simpler than rolling my own horrid linked-lists).

    As for Lua I'm just going to say I disagree with you 100%. Lua is a fine extension language, certainly for this use-case where I'm calling into my application-code most of the time it works just fine. Lua is also significantly easier to embed, and lighter than Python would be.

    I would be tempted by a lisp for the future. But to get started it was almost trivial in Lua.

  3. [gravitar] Anonymous

    Almost every language has a binding to curses. Slang seems somewhat less common, though most decent languages have an FFI.

    I guess I just hate to see new code written in C when it doesn't absolutely need to be, especially for something like a mail client that deals with a lot of untrusted data in fun and exciting formats.

  4. [gravitar] Asbjørn Sloth Tønnesen

    Try to take a look at Lua Event Machine, that could simplify a lot of "fiddily ones", however it doesn't have a lem-ncurses extension yet, but a regular lua-ncurses could be used. A lem-gnutls is on the way, and will probably be pushed soon after Esmil is back from vacation next week.