4.4. User Interface

Alot sets up a widget tree and a mainloop in the constructor of alot.ui.UI. The visible area is a urwid.Frame, where the footer is used as a status line and the body part displays the currently active alot.buffers.Buffer.

To be able to bind keystrokes and translate them to Commands, keypresses are not propagated down the widget tree as is customary in urwid. Instead, the root widget given to urwids mainloop is a custom wrapper (alot.ui.Inputwrap) that interprets key presses. A dedicated SendKeypressCommand can be used to trigger key presses to the wrapped root widget and thereby accessing standard urwid behaviour.

In order to keep the interface non-blocking and react to events like terminal size changes, alot makes use of twisted’s deferred - a framework that makes it easy to deal with callbacks. Many commands in alot make use of inline callbacks, which allow you to treat deferred-returning functions almost like syncronous functions. Consider the following example of a function that prompts for some input and acts on it:

from twisted.internet import defer

def greet(ui):  # ui is instance of alot.ui.UI
    name = yield ui.prompt('pls enter your name')
    ui.notify('your name is: ' + name)

4.4.1. UI - the main component

4.4.2. Buffers

A buffer defines a view to your data. It knows how to render itself, to interpret keypresses and is visible in the “body” part of the widget frame. Different modes are defined by subclasses of the following base class.

Available modes are:

Mode Buffer Subclass
search SearchBuffer
thread ThreadBuffer
bufferlist BufferlistBuffer
taglist TagListBuffer
envelope EnvelopeBuffer

4.4.3. Widgets

What follows is a list of the non-standard urwid widgets used in alot. Some of them respect user settings, themes in particular. utils

Utility Widgets not specific to alot

class alot.widgets.utils.AttrFlipWidget(w, maps, init_map='normal')

An AttrMap that can remember attributes to set globals

This contains alot-specific urwid.Widget used in more than one mode.

class alot.widgets.globals.AttachmentWidget(attachment, selectable=True)

one-line summary of an Attachment.

class alot.widgets.globals.CompleteEdit(completer, on_exit, on_error=None, edit_text=u'', history=None, **kwargs)

This is a vamped-up urwid.Edit widget that allows for tab-completion using Completer objects

These widgets are meant to be used as user input prompts and hence react to ‘return’ key presses by calling a ‘on_exit’ callback that processes the current text value.

The interpretation of some keypresses is hard-wired:
enter:calls ‘on_exit’ callback with current value
esc/ctrl g:calls ‘on_exit’ with value None, which can be interpreted as cancelation
tab:calls the completer and tabs forward in the result list
shift tab:tabs backward in the result list
up/down:move in the local input history
ctrl f/b:moves curser one character to the right/left
meta f/b shift right/left:
 moves the cursor one word to the right/left
ctrl a/e:moves curser to the beginning/end of the input
ctrl d:deletes the character under the cursor
meta d:deletes everything from the cursor to the end of the next word
meta delete/backspace ctrl w:
 deletes everything from the cursor to the beginning of the current word
ctrl k:deletes everything from the cursor to the end of the input
ctrl u:deletes everything from the cursor to the beginning of the input
  • completer (alot.completion.Completer) – completer to use
  • on_exit (callable) – “enter”-callback that interprets the input (str)
  • on_error (callback) – callback that handles alot.errors.CompletionErrors
  • edit_text (str) – initial text
  • history (list or str) – initial command history
class alot.widgets.globals.HeadersList(headerslist, key_attr, value_attr, gaps_attr=None)

renders a pile of header values as key/value list

  • headerslist (list of (str, str)) – list of key/value pairs to display
  • key_attr (urwid.AttrSpec) – theming attribute to use for keys
  • value_attr (urwid.AttrSpec) – theming attribute to use for values
  • gaps_attr (urwid.AttrSpec) – theming attribute to wrap lines in
class alot.widgets.globals.TagWidget(tag, fallback_normal=None, fallback_focus=None)

text widget that renders a tagstring.

It looks up the string it displays in the tags section of the config as well as custom theme settings for its tag. bufferlist

Widgets specific to Bufferlist mode

class alot.widgets.bufferlist.BufferlineWidget(buffer)

selectable text widget that represents a Buffer in the BufferlistBuffer. search

Widgets specific to search mode

class alot.widgets.search.ThreadlineWidget(tid, dbman)

selectable line widget that represents a Thread in the SearchBuffer. thread

4.4.4. Completion

alot.ui.UI.prompt() allows tab completion using a Completer object handed as ‘completer’ parameter. alot.completion defines several subclasses for different occasions like completing email addresses from an AddressBook, notmuch tagstrings. Some of these actually build on top of each other; the QueryCompleter for example uses a TagsCompleter internally to allow tagstring completion after “is:” or “tag:” keywords when typing a notmuch querystring.

All these classes overide the method complete(), which for a given string and cursor position in that string returns a list of tuples (completed_string, new_cursor_position) that are taken to be the completed values. Note that completed_string does not need to have the original string as prefix. complete() may rise alot.errors.CompletionError exceptions.