summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Totzke <patricktotzke@gmail.com>2012-11-07 09:26:52 +0000
committerPatrick Totzke <patricktotzke@gmail.com>2012-11-07 09:26:52 +0000
commitdd784938d4fbc14372e0f73abfe4b622c81dd9a1 (patch)
tree664f80f94f548d35341d93cd5a7cffa4bf339804
parent793e090bf29017abb041f696c8b1601261c425df (diff)
parentf2d65413f5e9fdb56831c633aff70b1ea552b46a (diff)
Merge remote-tracking branch 'origin/0.3.3-feature-tagsearch-517'
Conflicts: alot/commands/thread.py
-rw-r--r--alot/commands/globals.py12
-rw-r--r--alot/commands/search.py68
-rw-r--r--alot/db/manager.py2
-rw-r--r--alot/widgets/search.py8
-rw-r--r--docs/source/configuration/alotrc_table2
-rw-r--r--docs/source/usage/modes/search.rst53
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