4.3. 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 asyncio - which allows asynchronous calls without the use of callbacks. Alot makes use of the python 3.5 async/await syntax

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

4.3.1. UI - the main component

class alot.ui.UI(dbman, initialcmdline)

This class integrates all components of alot and offers methods for user interaction like prompt(), notify() etc. It handles the urwid widget tree and mainloop (we use asyncio) and is responsible for opening, closing and focussing buffers.

Parameters
  • dbmanDBManager

  • initialcmdline (str) – commandline applied after setting up interface

  • colourmode (int in [1,16,256]) – determines which theme to chose

async apply_command(cmd)

applies a command

This calls the pre and post hooks attached to the command, as well as cmd.apply().

Parameters

cmd (Command) – an applicable command

async apply_commandline(cmdline)

interprets a command line string

i.e., splits it into separate command strings, instanciates Commands accordingly and applies then in sequence.

Parameters

cmdline (str) – command line to interpret

buffer_close(buf, redraw=True)

closes given Buffer.

This it removes it from the bufferlist and calls its cleanup() method.

buffer_focus(buf, redraw=True)

focus given Buffer.

buffer_open(buf)

register and focus new Buffer.

build_statusbar()

construct and return statusbar widget

choice(message, choices=None, select=None, cancel=None, msg_position='above', choices_to_return=None)

prompt user to make a choice.

Parameters
  • message (unicode) – string to display before list of choices

  • choices (dict: keymap->choice key is str and value is any obj)) – dict of possible choices

  • choices_to_return – dict of possible choices to return for the choices of the choices of paramter

  • select (str) – choice to return if enter/return is hit. Ignored if set to None.

  • cancel (str) – choice to return if escape is hit. Ignored if set to None.

  • msg_position (str) – determines if message is above or left of the prompt. Must be above or left.

Return type

asyncio.Future

cleanup()

Do the final clean up before shutting down.

clear_notify(messages)

Clears notification popups. Call this to ged rid of messages that don’t time out.

Parameters

messages – The popups to remove. This should be exactly what notify() returned when creating the popup

static exit()

shuts down user interface without cleaning up. Use a alot.commands.globals.ExitCommand for a clean shutdown.

get_buffers_of_type(t)

returns currently open buffers for a given subclass of Buffer.

Parameters

t (alot.buffers.Buffer) – Buffer class

Return type

list

get_deep_focus(startfrom=None)

return the bottom most focussed widget of the widget tree

handle_signal(signum, frame)

handles UNIX signals

This function currently just handles SIGUSR1. It could be extended to handle more

Parameters
notify(message, priority='normal', timeout=0, block=False)

opens notification popup.

Parameters
  • message (str) – message to print

  • priority (str) – priority string, used to format the popup: currently, ‘normal’ and ‘error’ are defined. If you use ‘X’ here, the attribute ‘global_notify_X’ is used to format the popup.

  • timeout (int) – seconds until message disappears. Defaults to the value of ‘notify_timeout’ in the general config section. A negative value means never time out.

  • block (bool) – this notification blocks until a keypress is made

Returns

an urwid widget (this notification) that can be handed to clear_notify() for removal

paused()

context manager that pauses the UI to allow running external commands.

If an exception occurs, the UI will be started before the exception is re-raised.

prompt(prefix, text='', completer=None, tab=0, history=None)

prompt for text input. This returns a asyncio.Future, which will have a string value

Parameters
  • prefix (str) – text to print before the input field

  • text (str) – initial content of the input field

  • completer (alot.completion.Completer()) – completion object to use

  • tab (int) – number of tabs to press initially (to select completion results)

  • history (list of str) – history to be used for up/down keys

Return type

asyncio.Future

show_as_root_until_keypress(w, key, afterwards=None)

Replaces root widget by given urwid.Widget and makes the UI ignore all further commands apart from cursor movement. If later on key is pressed, the old root widget is reset, callable afterwards is called and normal behaviour is resumed.

update(redraw=True)

redraw interface

buffers = None

list of active buffers

commandprompthistory = None

history of the command line prompt

current_buffer = None

points to currently active Buffer

db_was_locked = None

flag used to prevent multiple ‘index locked’ notifications

dbman = None

Database Manager (DBManager)

input_queue = None

stores partial keyboard input

last_commandline = None

saves the last executed commandline

mode = None

interface mode identifier - type of current buffer

recipienthistory = None

history of the recipients prompt

senderhistory = None

history of the sender prompt

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

class alot.buffers.Buffer(ui, widget)

Abstract base class for buffers.

cleanup()

called before buffer is closed

get_info()

return dict of meta infos about this buffer. This can be requested to be displayed in the statusbar.

rebuild()

tells the buffer to (re)construct its visible content.

Available modes are:

Mode

Buffer Subclass

search

SearchBuffer

thread

ThreadBuffer

bufferlist

BufferlistBuffer

taglist

TagListBuffer

namedqueries

NamedQueriesBuffer

envelope

EnvelopeBuffer

class alot.buffers.BufferlistBuffer(ui, filtfun=<function BufferlistBuffer.<lambda>>)

lists all active buffers

focus_first()

Focus the first line in the buffer list.

get_selected_buffer()

returns currently selected Buffer element from list

index_of(b)

returns the index of Buffer b in the global list of active buffers.

rebuild()

tells the buffer to (re)construct its visible content.

class alot.buffers.EnvelopeBuffer(ui, envelope)

message composition mode

cleanup()

called before buffer is closed

get_info()

return dict of meta infos about this buffer. This can be requested to be displayed in the statusbar.

rebuild()

tells the buffer to (re)construct its visible content.

set_displaypart(part)

Update the view to display body part (plaintext, html, src).

..note:: This assumes that selv.envelope.body_html exists in case the requested part is ‘html’ or ‘src’!

toggle_all_headers()

Toggle visibility of all envelope headers.

class alot.buffers.NamedQueriesBuffer(ui, filtfun)

lists named queries present in the notmuch database

focus_first()

Focus the first line in the query list.

get_info()

return dict of meta infos about this buffer. This can be requested to be displayed in the statusbar.

get_selected_query()

returns selected query

rebuild()

tells the buffer to (re)construct its visible content.

class alot.buffers.SearchBuffer(ui, initialquery='', sort_order=None)

shows a result list of threads for a query

get_info()

return dict of meta infos about this buffer. This can be requested to be displayed in the statusbar.

get_selected_thread()

returns currently selected Thread

get_selected_threadline()

returns curently focussed alot.widgets.ThreadlineWidget from the result list.

rebuild(reverse=False)

tells the buffer to (re)construct its visible content.

class alot.buffers.ThreadBuffer(ui, thread)

displays a thread as a tree of messages.

Parameters
  • ui (UI) – main UI

  • thread (Thread) – thread to display

collapse(msgpos)

collapse message at given position

collapse_all()

collapse all messages in thread

expand(msgpos)

expand message at given position

expand_all()

expand all messages in thread

focus_first()

set focus to first message of thread

focus_first_reply()

move focus to first reply to currently focussed message

focus_last_reply()

move focus to last reply to currently focussed message

focus_next()

focus next message in depth first order

focus_next_matching(querystring)

focus next matching message in depth first order

focus_next_sibling()

focus next sibling of currently focussed message in thread tree

focus_next_unfolded()

focus next unfolded message in depth first order

focus_parent()

move focus to parent of currently focussed message

focus_prev()

focus previous message in depth first order

focus_prev_matching(querystring)

focus previous matching message in depth first order

focus_prev_sibling()

focus previous sibling of currently focussed message in thread tree

focus_prev_unfolded()

focus previous unfolded message in depth first order

focus_property(prop, direction)

does a walk in the given direction and focuses the first message tree that matches the given property

focus_selected_message()

focus the summary line of currently focussed message

get_focus()

Get the focus from the underlying body widget.

get_info()

return dict of meta infos about this buffer. This can be requested to be displayed in the statusbar.

get_messagetree_positions()

Return a Generator to walk through all positions of MessageTree in the ThreadTree of this buffer.

get_selected_message()

Return focussed Message.

get_selected_message_position()

Return position of focussed message in the thread tree.

get_selected_messagetree()

Return currently focussed MessageTree.

get_selected_mid()

Return Message ID of focussed message.

get_selected_thread()

Return the displayed Thread.

messagetree_at_position(pos)

get MessageTree for given position

messagetrees()

returns a Generator of all MessageTree in the ThreadTree of this buffer.

rebuild()

tells the buffer to (re)construct its visible content.

refresh()

Refresh and flush caches of Thread tree.

set_focus(pos)

Set the focus in the underlying body widget.

unfold_matching(querystring, focus_first=True)

expand all messages that match a given querystring.

Parameters
  • querystring (str) – query to match

  • focus_first (bool) – set the focus to the first matching message

class alot.buffers.TagListBuffer(ui, alltags=None, filtfun=<function TagListBuffer.<lambda>>)

lists all tagstrings present in the notmuch database

focus_first()

Focus the first line in the tag list.

get_selected_tag()

returns selected tagstring

rebuild()

tells the buffer to (re)construct its visible content.

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

4.3.3.1. utils

Utility Widgets not specific to alot

4.3.3.2. globals

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

4.3.3.3. bufferlist

Widgets specific to Bufferlist mode

4.3.3.4. search

Widgets specific to search mode

alot.widgets.search.build_tags_part(tags, attr_normal, attr_focus)

create an urwid.Columns widget (wrapped in approproate Attributes) to display a list of tag strings, as part of a threadline.

Parameters
  • tags (list of str) – list of tag strings to include

  • attr_normal – urwid attribute to use if unfocussed

  • attr_focus – urwid attribute to use if focussed

Returns

overall width in characters and a Columns widget.

Return type

tuple[int, urwid.Columns]

alot.widgets.search.build_text_part(name, thread, struct)

create an urwid.Text widget (wrapped in approproate Attributes) to display a plain text parts in a threadline. create an urwid.Columns widget (wrapped in approproate Attributes) to display a list of tag strings, as part of a threadline.

Parameters
Returns

overall width (in characters) and a widget.

Return type

tuple[int, AttrFliwWidget]

alot.widgets.search.prepare_string(partname, thread, maxw)

extract a content string for part ‘partname’ from ‘thread’ of maximal length ‘maxw’.

4.3.3.5. thread

Widgets specific to thread mode

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