summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2021-02-04 17:09:19 +0100
committerAnton Khirnov <anton@khirnov.net>2021-02-04 17:09:19 +0100
commita64a9b3219d0fd9241c6fcb6960f013588950571 (patch)
treef4f81fb8b88a11ec5448a0a8bfc4623b3fb4af35
parentf0d91a67e9fcdccaddfaad3204426a7caa17bf5d (diff)
commands/thread: add --thread option to tagging commands
Makes the command affect the whole thread, rather than just those messages matching the query.
-rw-r--r--alot/commands/search.py119
1 files changed, 65 insertions, 54 deletions
diff --git a/alot/commands/search.py b/alot/commands/search.py
index 82a3cf39..9e4a3688 100644
--- a/alot/commands/search.py
+++ b/alot/commands/search.py
@@ -88,38 +88,42 @@ class RefinePromptCommand(Command):
RetagPromptCommand = registerCommand(MODE, 'retagprompt')(RetagPromptCommand)
+_tag_help_common = 'By default, this command applies only to the currently ' \
+ 'focused thread, and furthermore only to those messages in the thread ' \
+ 'that match the search query. This behaviour may be changed by the --all ' \
+ 'and --thread options.'
+
+_tag_opt_all = (['--all'],
+ {'action' : 'store_true',
+ 'dest' : 'all_threads',
+ 'default' : False,
+ 'help' : 'apply to all threads rather than only the focused one'})
+_tag_opt_thread = (['--thread'],
+ {'action' : 'store_true',
+ 'dest' : 'thread',
+ 'default' : False,
+ 'help' : 'apply to all messages in the thread rather than only those'
+ 'matching the query'})
+_tag_opt_tags = (['tags'], {'help': 'comma separated list of tags'})
@registerCommand(
MODE, 'tag', forced={'action': 'add'},
- arguments=[
- (['--all'], {'action': 'store_true', 'dest': 'allmessages',
- 'default': False,
- 'help': 'tag all messages that match the current search query'}),
- (['tags'], {'help': 'comma separated list of tags'})],
- help='add tags to all messages in the selected thread',
+ arguments = [ _tag_opt_all, _tag_opt_thread, _tag_opt_tags ],
+ help = 'Add tags to messages. ' + _tag_help_common,
)
@registerCommand(
MODE, 'retag', forced={'action': 'set'},
- arguments=[
- (['--all'], {'action': 'store_true', 'dest': 'allmessages',
- 'default': False,
- 'help': 'retag all messages that match the current query'}),
- (['tags'], {'help': 'comma separated list of tags'})],
- help='set tags to all messages in the selected thread',
+ arguments = [ _tag_opt_all, _tag_opt_thread, _tag_opt_tags ],
+ help = 'Set tags to messages. ' + _tag_help_common,
)
@registerCommand(
MODE, 'untag', forced={'action': 'remove'},
- arguments=[
- (['--all'], {'action': 'store_true', 'dest': 'allmessages',
- 'default': False,
- 'help': 'untag all messages that match the current query'}),
- (['tags'], {'help': 'comma separated list of tags'})],
- help='remove tags from all messages in the selected thread',
+ arguments = [ _tag_opt_all, _tag_opt_thread, _tag_opt_tags ],
+ help = 'Remove tags from messages. ' + _tag_help_common,
)
@registerCommand(
MODE, 'toggletags', forced={'action': 'toggle'},
- arguments=[
- (['tags'], {'help': 'comma separated list of tags'})],
+ arguments = [ _tag_opt_tags ],
help='flip presence of tags on the selected thread: a tag is considered present '
'and will be removed if at least one message in this thread is '
'tagged with it')
@@ -128,7 +132,13 @@ class TagCommand(Command):
"""manipulate message tags"""
repeatable = True
- def __init__(self, tags='', action='add', allmessages=False, **kwargs):
+ _tags = None
+ _action = None
+ _all_threads = None
+ _thread = None
+
+ def __init__(self, tags = '', action = 'add', all_threads = False,
+ thread = False, **kwargs):
"""
:param tags: comma separated list of tagstrings to set
:type tags: str
@@ -136,12 +146,12 @@ class TagCommand(Command):
and removes all other if 'set' or toggle individually if
'toggle'
:type action: str
- :param allmessages: tag all messages in search result
- :type allmessages: bool
"""
- self.tagsstring = tags
- self.action = action
- self.allm = allmessages
+ self._tags = frozenset(filter(None, tags.split(',')))
+ self._action = action
+ self._all_threads = all_threads
+ self._thread = thread
+
super().__init__(**kwargs)
async def apply(self, ui):
@@ -152,38 +162,31 @@ class TagCommand(Command):
if threadline_widget is None:
return
- testquery = searchbuffer.querystring
- thread = threadline_widget.get_thread()
- if not self.allm:
- testquery = "(%s) AND thread:%s" % (testquery, thread.id)
- logging.debug('all? %s', self.allm)
- logging.debug('q: %s', testquery)
-
- def refresh():
- # update total result count
- if not self.allm:
- threadline_widget.rebuild()
- searchbuffer.result_count = searchbuffer.dbman.count_messages(
- searchbuffer.querystring)
- else:
- searchbuffer.rebuild()
-
- ui.update()
+ if self._all_threads:
+ if self._thread:
+ ui.notify('--all with --thread is not supported yet',
+ priority = 'error')
+ return
+ testquery = searchbuffer.querystring
+ else:
+ thread = threadline_widget.get_thread()
+ testquery = 'thread:' + thread.id
- tags = frozenset(filter(None, self.tagsstring.split(',')))
+ if not self._thread:
+ testquery += ' and (%s)' % searchbuffer.querystring
try:
- if self.action == 'add':
- await ui.dbman.tags_add(testquery, tags)
- if self.action == 'set':
- await ui.dbman.tags_set(testquery, tags)
- elif self.action == 'remove':
- await ui.dbman.tags_remove(testquery, tags)
- elif self.action == 'toggle':
- if not self.allm:
+ if self._action == 'add':
+ await ui.dbman.tags_add(testquery, self._tags)
+ if self._action == 'set':
+ await ui.dbman.tags_set(testquery, self._tags)
+ elif self._action == 'remove':
+ await ui.dbman.tags_remove(testquery, self._tags)
+ elif self._action == 'toggle':
+ if not self._all_threads:
to_remove = set()
to_add = set()
- for t in tags:
+ for t in self._tags:
if t in thread.get_tags():
to_remove.add(t)
else:
@@ -194,7 +197,15 @@ class TagCommand(Command):
ui.notify('index in read-only mode', priority='error')
return
- refresh()
+ # update total result count
+ if not self._all_threads:
+ threadline_widget.rebuild()
+ searchbuffer.result_count = searchbuffer.dbman.count_messages(
+ searchbuffer.querystring)
+ else:
+ searchbuffer.rebuild()
+
+ ui.update()
@registerCommand(
MODE, 'move', help='move focus in search buffer',