diff options
author | Patrick Totzke <patricktotzke@gmail.com> | 2012-11-07 09:26:52 +0000 |
---|---|---|
committer | Patrick Totzke <patricktotzke@gmail.com> | 2012-11-07 09:26:52 +0000 |
commit | dd784938d4fbc14372e0f73abfe4b622c81dd9a1 (patch) | |
tree | 664f80f94f548d35341d93cd5a7cffa4bf339804 | |
parent | 793e090bf29017abb041f696c8b1601261c425df (diff) | |
parent | f2d65413f5e9fdb56831c633aff70b1ea552b46a (diff) |
Merge remote-tracking branch 'origin/0.3.3-feature-tagsearch-517'
Conflicts:
alot/commands/thread.py
-rw-r--r-- | alot/commands/globals.py | 12 | ||||
-rw-r--r-- | alot/commands/search.py | 68 | ||||
-rw-r--r-- | alot/db/manager.py | 2 | ||||
-rw-r--r-- | alot/widgets/search.py | 8 | ||||
-rw-r--r-- | docs/source/configuration/alotrc_table | 2 | ||||
-rw-r--r-- | docs/source/usage/modes/search.rst | 53 |
6 files changed, 116 insertions, 29 deletions
diff --git a/alot/commands/globals.py b/alot/commands/globals.py index 900aea4e..6509e554 100644 --- a/alot/commands/globals.py +++ b/alot/commands/globals.py @@ -456,9 +456,20 @@ class TagListCommand(Command): @registerCommand(MODE, 'flush') class FlushCommand(Command): """flush write operations or retry until committed""" + def __init__(self, callback=None, **kwargs): + """ + :param callback: function to call after successful writeout + :type callback: callable + """ + Command.__init__(self, **kwargs) + self.callback = callback + def apply(self, ui): try: ui.dbman.flush() + if callable(self.callback): + self.callback() + logging.debug('flush complete') except DatabaseLockedError: timeout = settings.get('flush_retry_timeout') @@ -468,7 +479,6 @@ class FlushCommand(Command): ui.notify('index locked, will try again in %d secs' % timeout) ui.update() return - logging.debug('flush complete') #TODO: choices diff --git a/alot/commands/search.py b/alot/commands/search.py index 51a3fdd6..db718807 100644 --- a/alot/commands/search.py +++ b/alot/commands/search.py @@ -11,6 +11,7 @@ from alot.db.errors import DatabaseROError from alot import commands from alot import buffers + MODE = 'search' @@ -103,24 +104,34 @@ class RetagPromptCommand(Command): @registerCommand(MODE, 'tag', forced={'action': 'add'}, arguments=[ (['--no-flush'], {'action': 'store_false', 'dest': 'flush', + 'default': 'True', 'help': 'postpone a writeout to the index'}), + (['--all'], {'action': 'store_true', 'dest': 'allmessages', 'default': + False, 'help':'retag all messages in search result'}), (['tags'], {'help':'comma separated list of tags'})], help='add tags to all messages in the thread', ) @registerCommand(MODE, 'retag', forced={'action': 'set'}, arguments=[ (['--no-flush'], {'action': 'store_false', 'dest': 'flush', + 'default': 'True', 'help': 'postpone a writeout to the index'}), + (['--all'], {'action': 'store_true', 'dest': 'allmessages', 'default': + False, 'help':'retag all messages in search result'}), (['tags'], {'help':'comma separated list of tags'})], help='set tags of all messages in the thread', ) @registerCommand(MODE, 'untag', forced={'action': 'remove'}, arguments=[ (['--no-flush'], {'action': 'store_false', 'dest': 'flush', + 'default': 'True', 'help': 'postpone a writeout to the index'}), + (['--all'], {'action': 'store_true', 'dest': 'allmessages', 'default': + False, 'help':'retag all messages in search result'}), (['tags'], {'help':'comma separated list of tags'})], help='remove tags from all messages in the thread', ) @registerCommand(MODE, 'toggletags', forced={'action': 'toggle'}, arguments=[ (['--no-flush'], {'action': 'store_false', 'dest': 'flush', + 'default': 'True', 'help': 'postpone a writeout to the index'}), (['tags'], {'help':'comma separated list of tags'})], help="""flip presence of tags on this thread. @@ -130,7 +141,7 @@ class RetagPromptCommand(Command): """) class TagCommand(Command): """manipulate message tags""" - def __init__(self, tags=u'', action='add', all=False, flush=True, + def __init__(self, tags=u'', action='add', allmessages=False, flush=True, **kwargs): """ :param tags: comma separated list of tagstrings to set @@ -139,14 +150,14 @@ class TagCommand(Command): and removes all other if 'set' or toggle individually if 'toggle' :type action: str - :param all: tag all messages in thread + :param all: tag all messages in search result :type all: bool :param flush: imediately write out to the index :type flush: bool """ self.tagsstring = tags - self.all = all self.action = action + self.allm = allmessages self.flush = flush Command.__init__(self, **kwargs) @@ -157,9 +168,15 @@ class TagCommand(Command): # (displays an empty search result) if threadline_widget is None: return + + testquery = searchbuffer.querystring thread = threadline_widget.get_thread() - testquery = "(%s) AND thread:%s" % (searchbuffer.querystring, - thread.get_thread_id()) + if not self.allm: + testquery = "(%s) AND thread:%s" % (testquery, + thread.get_thread_id()) + logging.debug('all? %s' % self.allm) + logging.debug('q: %s' % testquery) + hitcount_before = ui.dbman.count_messages(testquery) def remove_thread(): @@ -172,37 +189,42 @@ class TagCommand(Command): # remove thread from resultset if it doesn't match the search query # any more and refresh selected threadline otherwise hitcount_after = ui.dbman.count_messages(testquery) - if hitcount_after == 0: - remove_thread() - else: - threadline_widget.rebuild() # update total result count + if not self.allm: + if hitcount_after == 0: + remove_thread() + else: + threadline_widget.rebuild() + else: + searchbuffer.rebuild() + searchbuffer.result_count += (hitcount_after - hitcount_before) ui.update() tags = filter(lambda x: x, self.tagsstring.split(',')) + try: if self.action == 'add': - thread.add_tags(tags, afterwards=refresh) + ui.dbman.tag(testquery, tags, remove_rest=False) if self.action == 'set': - thread.add_tags(tags, afterwards=refresh, - remove_rest=True) + ui.dbman.tag(testquery, tags, remove_rest=True) elif self.action == 'remove': - thread.remove_tags(tags, afterwards=refresh) + ui.dbman.untag(testquery, tags) elif self.action == 'toggle': - to_remove = [] - to_add = [] - for t in tags: - if t in thread.get_tags(): - to_remove.append(t) - else: - to_add.append(t) - thread.remove_tags(to_remove) - thread.add_tags(to_add, afterwards=refresh) + if not self.allm: + to_remove = [] + to_add = [] + for t in tags: + if t in thread.get_tags(): + to_remove.append(t) + else: + to_add.append(t) + thread.remove_tags(to_remove) + thread.add_tags(to_add, afterwards=refresh) except DatabaseROError: ui.notify('index in read-only mode', priority='error') return # flush index if self.flush: - ui.apply_command(commands.globals.FlushCommand()) + ui.apply_command(commands.globals.FlushCommand(callback=refresh)) diff --git a/alot/db/manager.py b/alot/db/manager.py index c52da7b2..3c938f9b 100644 --- a/alot/db/manager.py +++ b/alot/db/manager.py @@ -153,7 +153,7 @@ class DBManager(object): if callable(afterwards): logging.debug(str(afterwards)) afterwards() - logging.debug('called callback') + logging.debug('called callback') # re-insert item to the queue upon Xapian/NotmuchErrors except (XapianError, NotmuchError) as e: diff --git a/alot/widgets/search.py b/alot/widgets/search.py index 7a301d81..13789454 100644 --- a/alot/widgets/search.py +++ b/alot/widgets/search.py @@ -20,7 +20,8 @@ class ThreadlineWidget(urwid.AttrMap): """ def __init__(self, tid, dbman): self.dbman = dbman - self.thread = dbman.get_thread(tid) + self.tid = tid + self.thread = None # will be set by refresh() self.tag_widgets = [] self.display_content = settings.get('display_content_in_threadline') self.structure = None @@ -105,9 +106,7 @@ class ThreadlineWidget(urwid.AttrMap): msgs.sort(key=lambda msg: msg.get_date(), reverse=True) lastcontent = ' '.join([m.get_text_content() for m in msgs]) contentstring = pad(lastcontent.replace('\n', ' ').strip()) - content_w = AttrFlipWidget(urwid.Text( - contentstring, - wrap='clip'), + content_w = AttrFlipWidget(urwid.Text(contentstring, wrap='clip'), struct['content']) width = len(contentstring) part = content_w @@ -135,6 +134,7 @@ class ThreadlineWidget(urwid.AttrMap): return width, part def rebuild(self): + self.thread = self.dbman.get_thread(self.tid) self.widgets = [] columns = [] self.structure = settings.get_threadline_theming(self.thread) diff --git a/docs/source/configuration/alotrc_table b/docs/source/configuration/alotrc_table index e2a20e50..ec0e8abb 100644 --- a/docs/source/configuration/alotrc_table +++ b/docs/source/configuration/alotrc_table @@ -111,6 +111,8 @@ :default: From, To, Cc, Bcc, Subject + The pseudo-header "Tags" displays message tags. + .. _edit-headers-blacklist: .. describe:: edit_headers_blacklist diff --git a/docs/source/usage/modes/search.rst b/docs/source/usage/modes/search.rst index 5347e44d..990d8f7a 100644 --- a/docs/source/usage/modes/search.rst +++ b/docs/source/usage/modes/search.rst @@ -27,6 +27,18 @@ The following commands are available in search mode optional arguments :---no-flush: postpone a writeout to the index (Defaults to: 'True'). +.. _cmd.search.untagsearch: + +.. describe:: untagsearch + + remove tags from all messages in threads in the search results + + argument + comma separated list of tags + + optional arguments + :---no-flush: postpone a writeout to the index (Defaults to: 'True'). + .. _cmd.search.retag: .. describe:: retag @@ -39,6 +51,18 @@ The following commands are available in search mode optional arguments :---no-flush: postpone a writeout to the index (Defaults to: 'True'). +.. _cmd.search.retagsearch: + +.. describe:: retagsearch + + set tags of all messages in all threads in the search results + + argument + comma separated list of tags + + optional arguments + :---no-flush: postpone a writeout to the index (Defaults to: 'True'). + .. _cmd.search.refineprompt: .. describe:: refineprompt @@ -58,6 +82,18 @@ The following commands are available in search mode optional arguments :---no-flush: postpone a writeout to the index (Defaults to: 'True'). +.. _cmd.search.tagsearch: + +.. describe:: tagsearch + + add tags to all messages in all threads in the search results + + argument + comma separated list of tags + + optional arguments + :---no-flush: postpone a writeout to the index (Defaults to: 'True'). + .. _cmd.search.refine: .. describe:: refine @@ -93,6 +129,23 @@ The following commands are available in search mode optional arguments :---no-flush: postpone a writeout to the index (Defaults to: 'True'). +.. _cmd.search.toggletagssearch: + +.. describe:: toggletagssearch + + flip presence of tags on threads in the search results. + A tag is considered present if at least one message contained in this + thread is tagged with it. In that case this command will remove the tag + from every message in the thread. + + + argument + comma separated list of tags + + optional arguments + :---no-flush: postpone a writeout to the index (Defaults to: 'True'). + + .. _cmd.search.select: .. describe:: select |