summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--alot/commands/__init__.py27
-rw-r--r--alot/commands/globals.py28
-rw-r--r--alot/defaults/alot.rc.spec13
-rw-r--r--alot/defaults/default.bindings13
-rw-r--r--alot/ui.py266
-rw-r--r--alot/widgets/globals.py8
-rw-r--r--alot/widgets/utils.py20
-rw-r--r--docs/source/api/interface.rst17
-rw-r--r--docs/source/conf.py1
9 files changed, 187 insertions, 206 deletions
diff --git a/alot/commands/__init__.py b/alot/commands/__init__.py
index d3a052d0..2fd61b84 100644
--- a/alot/commands/__init__.py
+++ b/alot/commands/__init__.py
@@ -14,17 +14,9 @@ from alot.helper import split_commandstring
class Command(object):
"""base class for commands"""
- def __init__(self, prehook=None, posthook=None):
- """
- :param prehook: name of the hook to call directly before
- applying this command
- :type prehook: str
- :param posthook: name of the hook to call directly after
- applying this command
- :type posthook: str
- """
- self.prehook = prehook
- self.posthook = posthook
+ def __init__(self):
+ self.prehook = None
+ self.posthook = None
self.undoable = False
self.help = self.__doc__
@@ -191,17 +183,20 @@ def commandfactory(cmdline, mode='global'):
parms = vars(parser.parse_args(args))
parms.update(forcedparms)
- logging.debug('PARMS: %s' % parms)
+
+ logging.debug('cmd parms %s' % parms)
+
+ # create Command
+ cmd = cmdclass(**parms)
# set pre and post command hooks
get_hook = settings.get_hook
- parms['prehook'] = get_hook('pre_%s_%s' % (mode, cmdname)) or \
+ cmd.prehook = get_hook('pre_%s_%s' % (mode, cmdname)) or \
get_hook('pre_global_%s' % cmdname)
- parms['posthook'] = get_hook('post_%s_%s' % (mode, cmdname)) or \
+ cmd.posthook = get_hook('post_%s_%s' % (mode, cmdname)) or \
get_hook('post_global_%s' % cmdname)
- logging.debug('cmd parms %s' % parms)
- return cmdclass(**parms)
+ return cmd
pyfiles = glob.glob1(os.path.dirname(__file__), '*.py')
diff --git a/alot/commands/globals.py b/alot/commands/globals.py
index 02579519..db1c764a 100644
--- a/alot/commands/globals.py
+++ b/alot/commands/globals.py
@@ -56,6 +56,9 @@ class SearchCommand(Command):
"""
:param query: notmuch querystring
:type query: str
+ :param sort: how to order results. Must be one of
+ 'oldest_first', 'newest_first', 'message_id' or 'unsorted'.
+ :type sort: str
"""
self.query = ' '.join(query)
self.order = sort
@@ -508,18 +511,17 @@ class HelpCommand(Command):
linewidgets.append(line)
body = urwid.ListBox(linewidgets)
- ckey = 'cancel'
- titletext = 'Bindings Help (%s cancels)' % ckey
+ titletext = 'Bindings Help (escape cancels)'
box = DialogBox(body, titletext,
bodyattr=text_att,
titleattr=title_att)
# put promptwidget as overlay on main widget
- overlay = urwid.Overlay(box, ui.mainframe_themed, 'center',
+ overlay = urwid.Overlay(box, ui.root_widget, 'center',
('relative', 70), 'middle',
('relative', 70))
- ui.show_as_root_until_keypress(overlay, 'cancel')
+ ui.show_as_root_until_keypress(overlay, 'esc')
else:
logging.debug('HELP %s' % self.commandname)
parser = commands.lookup_parser(self.commandname, ui.mode)
@@ -732,21 +734,3 @@ class ComposeCommand(Command):
cmd = commands.envelope.EditCommand(envelope=self.envelope,
spawn=self.force_spawn, refocus=False)
ui.apply_command(cmd)
-
-
-@registerCommand(MODE, 'move', help='move focus', arguments=[
- (['key'], {'nargs':'+', 'help':'direction'})])
-@registerCommand(MODE, 'cancel', help='send cancel event',
- forced={'key': 'cancel'})
-@registerCommand(MODE, 'select', help='send select event',
- forced={'key': 'select'})
-class SendKeypressCommand(Command):
- """send a keypress to the main widget to be processed by urwid"""
- def __init__(self, key, **kwargs):
- Command.__init__(self, **kwargs)
- if isinstance(key, list):
- key = ' '.join(key)
- self.key = key
-
- def apply(self, ui):
- ui.keypress(self.key)
diff --git a/alot/defaults/alot.rc.spec b/alot/defaults/alot.rc.spec
index 174413fd..63689e9f 100644
--- a/alot/defaults/alot.rc.spec
+++ b/alot/defaults/alot.rc.spec
@@ -4,6 +4,9 @@ ask_subject = boolean(default=True) # ask for subject when compose
# directory prefix for downloading attachments
attachment_prefix = string(default='~')
+# timeout in (floating point) seconds until partial input is cleared
+input_timeout = float(default=1.0)
+
# confirm exit
bug_on_exit = boolean(default=False)
@@ -88,7 +91,7 @@ show_statusbar = boolean(default=True)
# * `{buffer_no}`: index of this buffer in the global buffer list
# * `{total_messages}`: total numer of messages indexed by notmuch
# * `{pending_writes}`: number of pending write operations to the index
-bufferlist_statusbar = mixed_list(string, string, default=list('[{buffer_no}: bufferlist]','total messages: {total_messages}'))
+bufferlist_statusbar = mixed_list(string, string, default=list('[{buffer_no}: bufferlist]','{input_queue} total messages: {total_messages}'))
# Format of the status-bar in search mode.
# This is a pair of strings to be left and right aligned in the status-bar.
@@ -98,7 +101,7 @@ bufferlist_statusbar = mixed_list(string, string, default=list('[{buffer_no}: bu
# * `{querystring}`: search string
# * `{result_count}`: number of matching messages
# * `{result_count_positive}`: 's' if result count is greater than 0.
-search_statusbar = mixed_list(string, string, default=list('[{buffer_no}: search] for "{querystring}"','{result_count} of {total_messages} messages'))
+search_statusbar = mixed_list(string, string, default=list('[{buffer_no}: search] for "{querystring}"','{input_queue} {result_count} of {total_messages} messages'))
# Format of the status-bar in thread mode.
# This is a pair of strings to be left and right aligned in the status-bar.
@@ -109,13 +112,13 @@ search_statusbar = mixed_list(string, string, default=list('[{buffer_no}: search
# * `{subject}`: subject line of the thread
# * `{authors}`: abbreviated authors string for this thread
# * `{message_count}`: number of contained messages
-thread_statusbar = mixed_list(string, string, default=list('[{buffer_no}: thread] {subject}','total messages: {total_messages}'))
+thread_statusbar = mixed_list(string, string, default=list('[{buffer_no}: thread] {subject}','{input_queue} total messages: {total_messages}'))
# Format of the status-bar in taglist mode.
# This is a pair of strings to be left and right aligned in the status-bar.
# These strings may contain variables listed at :ref:`bufferlist_statusbar <bufferlist-statusbar>`
# that will be substituted accordingly.
-taglist_statusbar = mixed_list(string, string, default=list('[{buffer_no}: taglist]','total messages: {total_messages}'))
+taglist_statusbar = mixed_list(string, string, default=list('[{buffer_no}: taglist]','{input_queue} total messages: {total_messages}'))
# Format of the status-bar in envelope mode.
# This is a pair of strings to be left and right aligned in the status-bar.
@@ -123,7 +126,7 @@ taglist_statusbar = mixed_list(string, string, default=list('[{buffer_no}: tagli
# these strings may contain variables:
#
# * `{to}`: To-header of the envelope
-envelope_statusbar = mixed_list(string, string, default=list('[{buffer_no}: envelope]','total messages: {total_messages}'))
+envelope_statusbar = mixed_list(string, string, default=list('[{buffer_no}: envelope]','{input_queue} total messages: {total_messages}'))
# timestamp format in `strftime format syntax <http://docs.python.org/library/datetime.html#strftime-strptime-behavior>`_
timestamp_format = string(default=None)
diff --git a/alot/defaults/default.bindings b/alot/defaults/default.bindings
index 204f3cb6..71a53d14 100644
--- a/alot/defaults/default.bindings
+++ b/alot/defaults/default.bindings
@@ -1,8 +1,10 @@
+up = move up
+down = move down
+page up = move page up
+page down = move page down
j = move down
k = move up
' ' = move page down
-esc = cancel
-enter = select
@ = refresh
? = help bindings
I = search tag:inbox AND NOT tag:killed
@@ -21,9 +23,10 @@ q = exit
[bufferlist]
x = close
- select = openfocussed
+ enter = openfocussed
[search]
+ enter = select
a = toggletags inbox
& = toggletags killed
! = toggletags flagged
@@ -41,12 +44,14 @@ q = exit
b = 'refine Bcc'
c = 'refine Cc'
S = togglesign
- select = edit
+ enter = edit
H = toggleheaders
[taglist]
+ enter = select
[thread]
+ enter = select
C = fold --all
E = unfold --all
c = fold
diff --git a/alot/ui.py b/alot/ui.py
index 54b43c76..e84db7a5 100644
--- a/alot/ui.py
+++ b/alot/ui.py
@@ -7,62 +7,13 @@ from twisted.internet import reactor, defer
from settings import settings
from buffers import BufferlistBuffer
-import commands
from commands import commandfactory
from alot.commands import CommandParseError
from alot.helper import string_decode
-from alot.widgets.utils import CatchKeyWidgetWrap
from alot.widgets.globals import CompleteEdit
from alot.widgets.globals import ChoiceWidget
-class InputWrap(urwid.WidgetWrap):
- """
- This is the topmost widget used in the widget tree.
- Its purpose is to capture and interpret keypresses
- by instantiating and applying the relevant :class:`Command` objects
- or relaying them to the wrapped `rootwidget`.
- """
- def __init__(self, ui, rootwidget):
- urwid.WidgetWrap.__init__(self, rootwidget)
- self.ui = ui
- self.rootwidget = rootwidget
- self.select_cancel_only = False
-
- def set_root(self, w):
- self._w = w
-
- def get_root(self):
- return self._w
-
- def allowed_command(self, cmd):
- """sanity check if the given command should be applied.
- This is used in :meth:`keypress`"""
- if not self.select_cancel_only:
- return True
- elif isinstance(cmd, commands.globals.SendKeypressCommand):
- if cmd.key in ['select', 'cancel']:
- return True
- else:
- return False
-
- def keypress(self, size, key):
- """overwrites `urwid.WidgetWrap.keypress`"""
- mode = self.ui.mode
- if self.select_cancel_only:
- mode = 'global'
- cmdline = settings.get_keybinding(mode, key)
- if cmdline:
- try:
- cmd = commandfactory(cmdline, mode)
- if self.allowed_command(cmd):
- self.ui.apply_command(cmd)
- return None
- except CommandParseError, e:
- self.ui.notify(e.message, priority='error')
- return self._w.keypress(size, key)
-
-
class UI(object):
"""
This class integrates all components of alot and offers
@@ -75,7 +26,13 @@ class UI(object):
current_buffer = None
"""points to currently active :class:`~alot.buffers.Buffer`"""
dbman = None
- """Database manager (:class:`~alot.db.DBManager`)"""
+ """Database Manager (:class:`~alot.db.manager.DBManager`)"""
+ mode = None
+ """interface mode identifier - type of current buffer"""
+ commandprompthistory = []
+ """history of the command line prompt"""
+ input_queue = []
+ """stores partial keyboard input"""
def __init__(self, dbman, initialcmd):
"""
@@ -85,50 +42,124 @@ class UI(object):
:param colourmode: determines which theme to chose
:type colourmode: int in [1,16,256]
"""
+ # store database manager
self.dbman = dbman
-
- colourmode = int(settings.get('colourmode'))
- logging.info('setup gui in %d colours' % colourmode)
+ # define empty notification pile
+ self._notificationbar = None
+ # should we show a status bar?
+ self._show_statusbar = settings.get('show_statusbar')
+ # pass keypresses to the root widget and never interpret bindings
+ self._passall = False
+ # indicates "input lock": only focus move commands are interpreted
+ self._locked = False
+ self._unlock_callback = None # will be called after input lock ended
+ self._unlock_key = None # key that ends input lock
+
+ # alarm handle for callback that clears input queue (to cancel alarm)
+ self._alarm = None
+
+ # create root widget
global_att = settings.get_theming_attribute('global', 'body')
- self.mainframe = urwid.Frame(urwid.SolidFill())
- self.mainframe_themed = urwid.AttrMap(self.mainframe, global_att)
- self.inputwrap = InputWrap(self, self.mainframe_themed)
- self.mainloop = urwid.MainLoop(self.inputwrap,
+ mainframe = urwid.Frame(urwid.SolidFill())
+ self.root_widget = urwid.AttrMap(mainframe, global_att)
+
+ # set up main loop
+ self.mainloop = urwid.MainLoop(self.root_widget,
handle_mouse=False,
event_loop=urwid.TwistedEventLoop(),
- unhandled_input=self.unhandeled_input)
- self.mainloop.screen.set_terminal_properties(colors=colourmode)
+ unhandled_input=self._unhandeled_input,
+ input_filter=self._input_filter)
- self.show_statusbar = settings.get('show_statusbar')
- self.notificationbar = None
- self.mode = 'global'
- self.commandprompthistory = []
+ # set up colours
+ colourmode = int(settings.get('colourmode'))
+ logging.info('setup gui in %d colours' % colourmode)
+ self.mainloop.screen.set_terminal_properties(colors=colourmode)
logging.debug('fire first command')
self.apply_command(initialcmd)
+
+ # start urwids mainloop
self.mainloop.run()
- def unhandeled_input(self, key):
- """called if a keypress is not handled."""
+ def _input_filter(self, keys, raw):
+ """
+ handles keypresses.
+ This function gets triggered directly by class:`urwid.MainLoop`
+ upon user input and is supposed to pass on its `keys` parameter
+ to let the root widget handle keys. We intercept the input here
+ to trigger custom commands as defined in our keybindings.
+ """
+ logging.debug("Got key (%s, %s)" % (keys, raw))
+ # work around: escape triggers this twice, with keys = raw = []
+ # the first time..
+ if not keys:
+ return
+ # let widgets handle input if key is virtual window resize keypress
+ # or we are in "passall" mode
+ elif 'window resize' in keys or self._passall:
+ return keys
+ # end "lockdown" mode if the right key was pressed
+ elif self._locked and keys[0] == self._unlock_key:
+ self._locked = False
+ self.mainloop.widget = self.root_widget
+ if callable(self._unlock_callback):
+ self._unlock_callback()
+ # otherwise interpret keybinding
+ else:
+ # define callback that resets input queue
+ def clear(*args):
+ if self._alarm is not None:
+ self.mainloop.remove_alarm(self._alarm)
+ self.input_queue = []
+ self.update()
+
+ key = keys[0]
+ self.input_queue.append(key)
+ keyseq = ' '.join(self.input_queue)
+ cmdline = settings.get_keybinding(self.mode, keyseq)
+ if cmdline:
+ logging.debug("cmdline: '%s'" % cmdline)
+ # move keys are always passed
+ if cmdline.startswith('move '):
+ movecmd = cmdline[5:].rstrip()
+ logging.debug("GOT MOVE: '%s'" % movecmd)
+ if movecmd in ['up', 'down', 'page up', 'page down']:
+ clear()
+ return [movecmd]
+ elif not self._locked:
+ try:
+ clear()
+ cmd = commandfactory(cmdline, self.mode)
+ self.apply_command(cmd)
+ except CommandParseError, e:
+ self.notify(e.message, priority='error')
+
+ timeout = float(settings.get('input_timeout'))
+ if self._alarm is not None:
+ self.mainloop.remove_alarm(self._alarm)
+ self._alarm = self.mainloop.set_alarm_in(timeout, clear)
+ # update statusbar
+ self.update()
+
+ def _unhandeled_input(self, key):
+ """
+ Called by :class:`urwid.MainLoop` if a keypress was passed to the root widget by
+ `self._input_filter` but is not handled in any widget.
+ We keep it for debuging purposes.
+ """
logging.debug('unhandled input: %s' % key)
- def keypress(self, key):
- """relay all keypresses to our `InputWrap`"""
- self.inputwrap.keypress((150, 20), key)
-
- def show_as_root_until_keypress(self, w, key, relay_rest=True,
- afterwards=None):
- def oe():
- self.inputwrap.set_root(self.mainframe_themed)
- self.inputwrap.select_cancel_only = False
- if callable(afterwards):
- logging.debug('called')
- afterwards()
- logging.debug('relay: %s' % relay_rest)
- helpwrap = CatchKeyWidgetWrap(w, key, on_catch=oe,
- relay_rest=relay_rest)
- self.inputwrap.set_root(helpwrap)
- self.inputwrap.select_cancel_only = not relay_rest
+ def show_as_root_until_keypress(self, w, key, afterwards=None):
+ """
+ Replaces root widget by given :class:`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.
+ """
+ self.mainloop.widget = w
+ self._unlock_key = key
+ self._unlock_callback = afterwards
+ self._locked = True
def prompt(self, prefix, text=u'', completer=None, tab=0, history=[]):
"""prompt for text input
@@ -144,16 +175,16 @@ class UI(object):
:type tab: int
:param history: history to be used for up/down keys
:type history: list of str
- :returns: a :class:`twisted.defer.Deferred`
+ :rtype: :class:`twisted.defer.Deferred`
"""
d = defer.Deferred() # create return deferred
- oldroot = self.inputwrap.get_root()
+ oldroot = self.mainloop.widget
def select_or_cancel(text):
# restore main screen and invoke callback
# (delayed return) with given text
- self.inputwrap.set_root(oldroot)
- self.inputwrap.select_cancel_only = False
+ self.mainloop.widget = oldroot
+ self._passall = False
d.callback(text)
prefix = prefix + settings.get('prompt_suffix')
@@ -181,14 +212,14 @@ class UI(object):
('fixed right', 0),
('fixed bottom', 1),
None)
- self.inputwrap.set_root(overlay)
- self.inputwrap.select_cancel_only = True
+ self.mainloop.widget = overlay
+ self._passall = True
return d # return deferred
def exit(self):
"""
shuts down user interface without cleaning up.
- Use a :class:`commands.globals.ExitCommand` for a clean shutdown.
+ Use a :class:`alot.commands.globals.ExitCommand` for a clean shutdown.
"""
exit_msg = None
try:
@@ -239,7 +270,6 @@ class UI(object):
else:
if self.current_buffer != buf:
self.current_buffer = buf
- self.inputwrap.set_root(self.mainframe_themed)
self.mode = buf.modename
if isinstance(self.current_buffer, BufferlistBuffer):
self.current_buffer.rebuild()
@@ -260,26 +290,26 @@ class UI(object):
def get_buffers_of_type(self, t):
"""
returns currently open buffers for a given subclass of
- :class:`alot.buffer.Buffer`
+ :class:`~alot.buffers.Buffer`
"""
return filter(lambda x: isinstance(x, t), self.buffers)
def clear_notify(self, messages):
"""
- clears notification popups. Call this to ged rid of messages that don't
+ Clears notification popups. Call this to ged rid of messages that don't
time out.
:param messages: The popups to remove. This should be exactly
what :meth:`notify` returned when creating the popup
"""
- newpile = self.notificationbar.widget_list
+ newpile = self._notificationbar.widget_list
for l in messages:
if l in newpile:
newpile.remove(l)
if newpile:
- self.notificationbar = urwid.Pile(newpile)
+ self._notificationbar = urwid.Pile(newpile)
else:
- self.notificationbar = None
+ self._notificationbar = None
self.update()
def choice(self, message, choices={'y': 'yes', 'n': 'no'},
@@ -300,18 +330,18 @@ class UI(object):
:param msg_position: determines if `message` is above or left of the
prompt. Must be `above` or `left`.
:type msg_position: str
- :returns: a :class:`twisted.defer.Deferred`
+ :rtype: :class:`twisted.defer.Deferred`
"""
assert select in choices.values() + [None]
assert cancel in choices.values() + [None]
assert msg_position in ['left', 'above']
d = defer.Deferred() # create return deferred
- oldroot = self.inputwrap.get_root()
+ oldroot = self.mainloop.widget
def select_or_cancel(text):
- self.inputwrap.set_root(oldroot)
- self.inputwrap.select_cancel_only = False
+ self.mainloop.widget = oldroot
+ self._passall = False
d.callback(text)
#set up widgets
@@ -337,8 +367,8 @@ class UI(object):
('fixed right', 0),
('fixed bottom', 1),
None)
- self.inputwrap.set_root(overlay)
- self.inputwrap.select_cancel_only = True
+ self.mainloop.widget = overlay
+ self._passall = True
return d # return deferred
def notify(self, message, priority='normal', timeout=0, block=False):
@@ -367,11 +397,11 @@ class UI(object):
return urwid.AttrMap(cols, att)
msgs = [build_line(message, priority)]
- if not self.notificationbar:
- self.notificationbar = urwid.Pile(msgs)
+ if not self._notificationbar:
+ self._notificationbar = urwid.Pile(msgs)
else:
- newpile = self.notificationbar.widget_list + msgs
- self.notificationbar = urwid.Pile(newpile)
+ newpile = self._notificationbar.widget_list + msgs
+ self._notificationbar = urwid.Pile(newpile)
self.update()
def clear(*args):
@@ -379,14 +409,13 @@ class UI(object):
if block:
# put "cancel to continue" widget as overlay on main widget
- txt = build_line('(cancel continues)', priority)
- overlay = urwid.Overlay(txt, self.mainframe_themed,
+ txt = build_line('(escape continues)', priority)
+ overlay = urwid.Overlay(txt, self.root_widget,
('fixed left', 0),
('fixed right', 0),
('fixed bottom', 0),
None)
- self.show_as_root_until_keypress(overlay, 'cancel',
- relay_rest=False,
+ self.show_as_root_until_keypress(overlay, 'esc',
afterwards=clear)
else:
if timeout >= 0:
@@ -397,26 +426,24 @@ class UI(object):
def update(self):
"""redraw interface"""
- #who needs a header?
- #head = urwid.Text('notmuch gui')
- #h=urwid.AttrMap(head, 'header')
- #self.mainframe.set_header(h)
+ # get the main urwid.Frame widget
+ mainframe = self.root_widget.original_widget
# body
if self.current_buffer:
- self.mainframe.set_body(self.current_buffer)
+ mainframe.set_body(self.current_buffer)
# footer
lines = []
- if self.notificationbar: # .get_text()[0] != ' ':
- lines.append(self.notificationbar)
- if self.show_statusbar:
+ if self._notificationbar: # .get_text()[0] != ' ':
+ lines.append(self._notificationbar)
+ if self._show_statusbar:
lines.append(self.build_statusbar())
if lines:
- self.mainframe.set_footer(urwid.Pile(lines))
+ mainframe.set_footer(urwid.Pile(lines))
else:
- self.mainframe.set_footer(None)
+ mainframe.set_footer(None)
# force a screen redraw
if self.mainloop.screen.started:
self.mainloop.draw_screen()
@@ -434,6 +461,7 @@ class UI(object):
info['buffer_type'] = btype
info['total_messages'] = self.dbman.count_messages('*')
info['pending_writes'] = len(self.dbman.writequeue)
+ info['input_queue'] = ' '.join(self.input_queue)
lefttxt = righttxt = u''
if cb is not None:
diff --git a/alot/widgets/globals.py b/alot/widgets/globals.py
index 210d4b54..940db187 100644
--- a/alot/widgets/globals.py
+++ b/alot/widgets/globals.py
@@ -57,9 +57,9 @@ class ChoiceWidget(urwid.Text):
return True
def keypress(self, size, key):
- if key == 'select' and self.select is not None:
+ if key == 'enter' and self.select is not None:
self.callback(self.select)
- elif key == 'cancel' and self.cancel is not None:
+ elif key == 'esc' and self.cancel is not None:
self.callback(self.cancel)
elif key in self.choices:
self.callback(self.choices[key])
@@ -114,9 +114,9 @@ class CompleteEdit(urwid.Edit):
else:
self.historypos = (self.historypos - 1) % len(self.history)
self.set_edit_text(self.history[self.historypos])
- elif key == 'select':
+ elif key == 'enter':
self.on_exit(self.edit_text)
- elif key == 'cancel':
+ elif key == 'esc':
self.on_exit(None)
elif key == 'ctrl a':
self.set_edit_pos(0)
diff --git a/alot/widgets/utils.py b/alot/widgets/utils.py
index b50b2db9..ce64a6eb 100644
--- a/alot/widgets/utils.py
+++ b/alot/widgets/utils.py
@@ -6,7 +6,6 @@
Utility Widgets not specific to alot
"""
import urwid
-import logging
class AttrFlipWidget(urwid.AttrMap):
@@ -43,22 +42,3 @@ class DialogBox(urwid.WidgetWrap):
def keypress(self, size, key):
return self.body.keypress(size, key)
-
-
-class CatchKeyWidgetWrap(urwid.WidgetWrap):
- def __init__(self, widget, key, on_catch, relay_rest=True):
- urwid.WidgetWrap.__init__(self, widget)
- self.key = key
- self.relay = relay_rest
- self.on_catch = on_catch
-
- def selectable(self):
- return True
-
- def keypress(self, size, key):
- logging.debug('CATCH KEY: %s' % key)
- logging.debug('relay: %s' % self.relay)
- if key == self.key:
- self.on_catch()
- elif self._w.selectable() and self.relay:
- return self._w.keypress(size, key)
diff --git a/docs/source/api/interface.rst b/docs/source/api/interface.rst
index d2294e26..7d66cf1f 100644
--- a/docs/source/api/interface.rst
+++ b/docs/source/api/interface.rst
@@ -38,22 +38,7 @@ input and acts on it:
.. module:: alot.ui
.. autoclass:: UI
-
- .. autoattribute:: buffers
- .. autoattribute:: current_buffer
- .. autoattribute:: dbman
-
- .. automethod:: apply_command
- .. automethod:: prompt
- .. automethod:: choice
- .. automethod:: notify
- .. automethod:: clear_notify
- .. automethod:: buffer_open
- .. automethod:: buffer_focus
- .. automethod:: buffer_close
- .. automethod:: get_buffers_of_type
- .. automethod:: exit
-
+ :members:
Buffers
----------
diff --git a/docs/source/conf.py b/docs/source/conf.py
index 039ef980..030c19c3 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -242,6 +242,7 @@ latex_documents = [
# If false, no module index is generated.
#latex_domain_indices = True
+autodoc_member_order = 'groupwise'
# -- Options for manual page output --------------------------------------------