summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatrick <p.totzke@ed.ac.uk>2011-05-18 15:36:50 +0100
committerpatrick <p.totzke@ed.ac.uk>2011-05-18 15:36:50 +0100
commit122819a4b3a03206b76d34411855d3210a379d42 (patch)
treea8ce50c7739d9e484de7a38ce85ed1572dfab02d
parent97e147ccf964e992a3074964f2d344f0e8ac798a (diff)
added readme,todo and small fixes
-rw-r--r--README85
-rw-r--r--TODO32
-rw-r--r--ng/buffer.py3
-rw-r--r--ng/db.py4
-rw-r--r--ng/ui.py1
5 files changed, 122 insertions, 3 deletions
diff --git a/README b/README
index e69de29b..a4dd6b8b 100644
--- a/README
+++ b/README
@@ -0,0 +1,85 @@
+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 explayin 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 airchitecture.
+
+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 moethods 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 baseclass for different types of buffers, or displaymodi if you like. So far there's only a SearchBuffer (might be a bad name)
+that displays the result of a search for mailthreads, 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 keypresses. 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. searchresults, display single thread, envelope, logmode) and knows how to summaryse itselt.
+ this is currently done as self.info(), and shoulld probably be self.__str__().
+ - knows how to handle local (mode-specific) keybindings (self.bindings see below)
+
+ng.commands.Command
+Again, a baseclass 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 countain a help-info about what it does (to aumagically 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, definately 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 iteratotors. 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 currrent buffer and in case it doesnt handle it,
+it will be handeled 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 instanciate
+a command with of tyoe commandtypestring with parameters parameterhash. See self.bindings in ng.buffer.BufferListBuffer
+for an example.
diff --git a/TODO b/TODO
new file mode 100644
index 00000000..fa40b4c1
--- /dev/null
+++ b/TODO
@@ -0,0 +1,32 @@
+There is a lot to be done, most of it is not going to be hard:
+
+* pydoc!
+
+* Fixing the walkers (there is a problem with the last entry)
+
+* build a prompt for ng.ui.
+ ui.prompt(promptprefix='>>')
+ keep in mind tabcompletion?
+ it would be cool if we had a cmdline like vim or mutt when pressing ":".
+ ng.command.Commands already have typenames, calling them from a prompt could
+ use the command.factory to build one and pass it to ui.apply_command.
+
+* "update" functionality for the notmuch index. tag/untag given thread/messages etc
+ If that's there, one can make commands for these actions, make them known to command.factory
+ and bind them to the SearchBuffer..
+
+* A buffer for single-thread view
+ displays mails in thread, folding of mails/textpassages
+
+* an Envelope buffer that contains widgets for recipients,subject, gpg settings.
+
+* A "SendManager" that can send and archive (in a maildir send folder),
+ loads the mail into the notmuch index and maybe refreshes open buffers accordingly
+
+* a config mechanism needs to be discussed/implemented. i don't think a single settings.py like in django
+ is a good approach.
+
+* remove direct calls to logging (use ui.logging instead)
+
+* packaging? last time i checked "PIPifying" a project wasn't hard, a bit of fumbling with a setup.py?
+
diff --git a/ng/buffer.py b/ng/buffer.py
index e87aed66..48306d98 100644
--- a/ng/buffer.py
+++ b/ng/buffer.py
@@ -96,8 +96,7 @@ class SearchBuffer(Buffer):
logging.info("querystring: %s"%self.querystring)
self.result_count = self.dbman.count_messages(self.querystring)
logging.info("count: %d"%self.result_count)
- q = self.dbman.query(self.querystring)
- threads = q.search_threads()
+ threads = self.dbman.search_threads(self.querystring)
self.threadlist = urwid.ListBox(IteratorWalker(threads,widgets.ThreadlineWidget))
self.original_widget = self.threadlist
diff --git a/ng/db.py b/ng/db.py
index 76bb760d..d0e3613b 100644
--- a/ng/db.py
+++ b/ng/db.py
@@ -8,6 +8,10 @@ class DBManager():
q = self.query(querystring)
return q.count_messages()
+ def search_threads(self,querystring):
+ q = self.query(querystring)
+ return q.search_threads()
+
def query(self,querystring):
mode = Database.MODE.READ_ONLY
db = Database(path=self.path,mode=mode)
diff --git a/ng/ui.py b/ng/ui.py
index 781d4e3b..fb18686b 100644
--- a/ng/ui.py
+++ b/ng/ui.py
@@ -101,4 +101,3 @@ class UI:
except:
self.logger.error('posthook failed')
raise
-