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
dbman –
DBManager
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.
-
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
signum – The signal number (see man 7 signal)
frame – The execution frame (https://docs.python.org/2/reference/datamodel.html#frame-objects)
-
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 usetab (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
-
db_was_locked
= None¶ flag used to prevent multiple ‘index locked’ notifications
-
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 |
|
thread |
|
bufferlist |
|
taglist |
|
namedqueries |
|
envelope |
-
class
alot.buffers.
BufferlistBuffer
(ui, filtfun=<function BufferlistBuffer.<lambda>>)¶ lists all active buffers
-
focus_first
()¶ Focus the first line in the buffer list.
-
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_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.
-
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 theThreadTree
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.
-
messagetree_at_position
(pos)¶ get
MessageTree
for given position
-
messagetrees
()¶ returns a Generator of all
MessageTree
in theThreadTree
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
-
class
alot.widgets.utils.
AttrFlipWidget
(w, maps, init_map='normal')¶ An AttrMap that can remember attributes to set
-
class
alot.widgets.utils.
DialogBox
(body, title, bodyattr=None, titleattr=None)¶
4.3.3.2. 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.
ChoiceWidget
(choices, callback, cancel=None, select=None, separator=' ', choices_to_return=None)¶
-
class
alot.widgets.globals.
CompleteEdit
(completer, on_exit, on_error=None, edit_text='', history=None, **kwargs)¶ This is a vamped-up
urwid.Edit
widget that allows for tab-completion usingCompleter
objectsThese 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 cancellation
- 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
- Parameters
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
- Parameters
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.
- Attributes that should be considered publicly readable:
- attr tag
the notmuch tag
- type tag
str
4.3.3.3. bufferlist¶
Widgets specific to Bufferlist mode
-
class
alot.widgets.bufferlist.
BufferlineWidget
(buffer)¶ selectable text widget that represents a
Buffer
in theBufferlistBuffer
.
4.3.3.4. search¶
Widgets specific to search mode
-
class
alot.widgets.search.
ThreadlineWidget
(tid, dbman)¶ selectable line widget that represents a
Thread
in theSearchBuffer
.
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
name (str) – id of part to build
thread (
alot.db.thread.Thread
) – the thread to get local info forstruct (dict) – theming attributes for this part, as provided by
alot.settings.theme.Theme.get_threadline_theming
- 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
-
class
alot.widgets.thread.
DictList
(content, key_attr, value_attr, gaps_attr=None)¶ SimpleTree
that displays key-value pairs.The structure will obey the Tree API but will not actually be a tree but a flat list: It contains one top-level node (displaying the k/v pair in Columns) per pair. That is, the root will be the first pair, its sibblings will be the other pairs and first|last_child will always be None.
- Parameters
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.thread.
MessageSummaryWidget
(message, even=True)¶ one line summary of a
Message
.- Parameters
message (alot.db.Message) – a message
even (bool) – even entry in a pile of messages? Used for theming.
-
class
alot.widgets.thread.
MessageTree
(message, odd=True)¶ Tree
that displays contents of a singlealot.db.Message
.Its root node is a
MessageSummaryWidget
, and its child nodes reflect the messages content (parts for headers/attachments etc).Collapsing this message corresponds to showing the summary only.
- Parameters
message (alot.db.Message) – Message to display
odd (bool) – theme summary widget as if this is an odd line (in the message-pile)
-
collapse_if_matches
(querystring)¶ collapse (and show summary only) if the
alot.db.Message
matches given querystring
-
expand
(pos)¶ overload CollapsibleTree.expand method to ensure all parts are present. Initially, only the summary widget is created to avoid reading the messafe file and thus speed up the creation of this object. Once we expand = unfold the message, we need to make sure that body/attachments exist.
-
set_mimepart
(mimepart)¶ Set message widget mime part and invalidate body tree.
-
class
alot.widgets.thread.
TextlinesList
(content, attr=None, attr_focus=None)¶ SimpleTree
that contains a list of all-level-0 Text widgets for each line in content.
-
class
alot.widgets.thread.
ThreadTree
(thread)¶ Tree
that parses a givenalot.db.Thread
into a tree ofMessageTrees
that display this threads individual messages. As MessageTreess are not urwid widgets themself this is to be used in combination withNestedTree
only.
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.