summaryrefslogtreecommitdiff
path: root/README
blob: 1ddef0f8e443d9f07a1fe8bccd4a1e8ddd1ae9f2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
This is a proposal for a terminal gui for notmuch mail, written in python.
Currently, it is more a sketch of a framework, so let me explain the key ideas here:

* OOP approach using python 
* aim at the look and feel of sup for now
* use libraries whenever possible. 
  urwid: http://excess.org/urwid/ 
  mailbox: http://docs.python.org/library/mailbox.html
  obviously the cnotmuch bindings: https://bitbucket.org/spaetz/cnotmuch/
  (urwid-satext: http://wiki.goffi.org/wiki/Urwid-satext

You need the cnotmuch python bindings and urwid to run it. I run it like this 
> python ng.py -l debug.log -d debug
and "tail -f debug.log" in another window. See settings.py for global bindings.

Here is an overview of the current architecture.

ng.ui.UI 
contains the main component: it
 - handles the urwid.MainLoop that manages the screen etc.
 - contains a logging.logger that can be used for log/debug messages like so: ui.logger.info('hello logworld')
 - sets up and updates the header/footer/body widgets
 - is able to open/close/focus buffers (there's a list ui.buffers of currently known buffers, and a ui.current_buffer, pointing to the focussed one)
 - handles global keybindings. See below for more on bindings.
 - can apply (and further down the road undo/redo) commands (see command.py)
 - should be able to open a prompt/dialogs? for user input. This is still missing

ng.db.DBManager 
is the door to the notmuch index. Currently, it has very limited functionality, but should be able to to this:
 - store the connection settings (index path and whether or not we use a read_only connection..)
 - two basic methods for reading from and writing to the index. Lets call it dbman.query(querystring) and dbman.update(updatestring).
   query will return a notmuch.Query object, i haven't bothered with update so far.
 - a method for all interesting operations on the index These will use self.query/update accordingly. See dbman.count_messages for a simple example

ng.buffer.Buffer
Is used as a base class for different types of buffers, or display-modi if you
like. So far there's only a SearchBuffer (might be a bad name) that displays
the result of a search for mail threads, and a BufferListBuffer, that displays
a list of buffers.  Technically, ng.buffer.Buffer inherits from urwid.AttrMap.
This is done so that it can be directly be set as the body-part of the main
gui, thereby intercepting (and filter/handle according to local bindings) the
key presses. A Buffer
 - is a widget, that can be drawn,focussed etc as all widgets.
 - has a pointer to the main ui, a typename, (e.g. search results, display
   single thread, envelope, logmode) and knows how to summarise itself.
 - knows how to handle local (mode-specific) keybindings (self.bindings see
   below)

ng.commands.Command
Again, a base class for different commands. A command is an object that
represents an atomic action. It will only be be applied once (and is then
stored in a undo-list somewhere). It
 - has a typename, that is used to identify a type of command for the command
   factory
 - can be applied using cmd.apply with a fixed interface: I  assume we want at
   least pointers to the main ui and the dbman objects here
 - should contain a help-info about what it does (to automagically create
   dynamic help-buffers later on)
 - should know if its undoable, and if so, implement undo() and redo()
 - points to pre and post hooks. This might get tricky with undoable cmds.. The
   idea is, that a cmd gets applied (see ng.ui.UI.apply_command), also its pre
   and posthooks are called if defined. These should have the same signature as
   cmd.apply(). See settings.hooks for an example.  There's a number of
   commands i already implemented. Each one should be created by the
   ng.command.factory (which also attaches the hooks)

ng.widgets
contains the urwid.Widgets i use do draw notmuch objects. There's a Threadline
widget for example, that knows how to present a notmuch.thread object as a
textline. Should be pretty self explanatory, definitely needs some love.  These
inherit from AttrMap, which is not very clean i guess, but they must be
"selectable" so that we can use them in a urwid.ListBox (which displays a list
and can focus elements). Since ThreadlineWidget is selectable it must include a
dummy keypress method.

ng.hooks
this should later on include methods that look for and call? hooks.  The idea
is that a user might define either python callables or paths to binaries, and
ng.hooks.get_hook(hookname) retrieves them so that they can be placed in
commands.  This might be a totally stupid idea

ng.walker
Contains urwid.ListWalker derived classes that implement a listwalker (the
content-part of a urwid.ListBox widget) that dynamically allocates its content.
The thing is that if one makes a query for all threads in the index and naively
creating a ng.widgets.ThreadlineWidget for each and placing them in a
urwid.Listbox (actually a urwid.SimplieListWalker, and /that/ in a listbox),
one this will potentially eat up your memory and take a long time. So
ng.walker.IteratorWalker will dynamically create its next element from the next
element of the iterator. For now, there's a NotmuchIteratorWalker class that
does the same for notmuch's one-time iterators. This is almost certainly a bad
idea methinks.

Bindings
Are currently a hash in objects of the classes ng.ui.UI and ng.buffer.Buffer.
Obviously, a key is first handed to the current buffer and in case it doesn't
handle it, it will be handled by the main UI.  Each buffer-subclass comes with
its own default local bindings which whi might want to overwrite at some point.
I guess we should have a "map" command that takes a buffertype, a key and
something to call.  For now, a key in the binding hash is a string that
represents a keypress (urwid style: 'shift j', 'k' etc are valid).  The value
is then a pair of (commandtypestring, parameterhash), that is used by the
command.factory to instantiate a command with of type commandtypestring with
parameters parameterhash. Values in the parameterhash will be called at cmd
creation by command.factory if callable. See self.bindings in
ng.buffer.BufferListBuffer for an example.