diff options
-rw-r--r-- | alot/db.py | 30 | ||||
-rw-r--r-- | alot/defaults/alot.rc | 17 | ||||
-rw-r--r-- | alot/message.py | 4 | ||||
-rw-r--r-- | alot/settings.py | 64 | ||||
-rw-r--r-- | alot/widgets.py | 22 |
5 files changed, 79 insertions, 58 deletions
@@ -362,22 +362,6 @@ class Thread(object): """returns id of this thread""" return self._id - def has_tags(self, *tags): - """ - Checks whether this thread is tagged with the given tags. - - :param tags: tags to check - :type tag: list[string] - :returns: True if this thread is tagged with all the given tags, False - otherwise. - :rtype: bool - """ - result = True - for tag in tags: - if not tag in self._tags: - result = False - return result - def get_tags(self): """ returns tagsstrings attached to this thread @@ -512,3 +496,17 @@ class Thread(object): def get_total_messages(self): """returns number of contained messages""" return self._total_messages + + def matches(self, query): + """ + Check if this thread matches the given notmuch query. + + :param query: The query to check against + :type query: string + :returns: True if this thread matches the given query, False otherwise + :rtype: bool + """ + thread_query = 'thread:{tid} AND {subquery}'.format(tid=self._id, + subquery=query) + num_matches = self._dbman.count_messages(thread_query) + return num_matches > 0 diff --git a/alot/defaults/alot.rc b/alot/defaults/alot.rc index 2f07ed9d..8e1e225f 100644 --- a/alot/defaults/alot.rc +++ b/alot/defaults/alot.rc @@ -35,17 +35,20 @@ terminal_cmd = x-terminal-emulator -e ###################### # HIGHLIGHT settings # ###################### -# Thread lines in the search buffer can be highlighted upon occurrence of a tag +# Thread lines in the search buffer can be highlighted if they match a query # by theming their components. -# comma separated list of tag combinations you want highlighting for. Note that -# the sequence of the list defines the search order. The first specified tag -# combination that is found defines the themeing. Tag combinations are joined by -# the '+' character. -thread_highlight_tags = unread+flagged,unread,flagged +# dictionary of highlighting rules. The keys are queries you want highlighting +# for; values are chosen designators that identify themeing options in the +# colour scheme: +# search_thread_<component>_[focus_]<id>_[fg|bg] +# Note that the sequence of the list defines the search order. The first +# specified query that matches selects the themeing. +thread_highlight_rules = { "tag:unread AND tag:flagged":"unread+flagged", + "tag:unread":"unread", "tag:flagged":"flagged" } # comma separated list of the components of a thread line you want highlighted -# if a configured tag is found. +# if a query matches. # Possible components are [date|mailcount|authors|subject]. thread_highlight_components = subject diff --git a/alot/message.py b/alot/message.py index 1be06bcb..36f2a5ff 100644 --- a/alot/message.py +++ b/alot/message.py @@ -134,8 +134,8 @@ class Message(object): """ if self._datetime == None: return None - formatstring = config.get('general', 'timestamp_format') - if formatstring: + if config.has_option('general', 'timestamp_format'): + formatstring = config.get('general', 'timestamp_format') res = self._datetime.strftime(formatstring) else: res = helper.pretty_datetime(self._datetime) diff --git a/alot/settings.py b/alot/settings.py index 72d5a7a1..a9cdb279 100644 --- a/alot/settings.py +++ b/alot/settings.py @@ -2,11 +2,13 @@ import imp import os import re import ast +import json import mailcap import codecs import logging -from ConfigParser import SafeConfigParser +from collections import OrderedDict +from ConfigParser import SafeConfigParser, ParsingError, NoOptionError class FallbackConfigParser(SafeConfigParser): @@ -25,15 +27,20 @@ class FallbackConfigParser(SafeConfigParser): :param fallback: the value to fall back if option undefined :type fallback: str """ - if SafeConfigParser.has_option(self, section, option): return SafeConfigParser.get(self, section, option, *args, **kwargs) - return fallback + elif fallback != None: + return fallback + else: + raise NoOptionError(option, section) def getstringlist(self, section, option, **kwargs): """directly parses a config value into a list of strings""" - value = self.get(section, option, **kwargs) - return [s.strip() for s in value.split(',') if s.strip()] + stringlist = list() + if self.has_option(section, option): + value = self.get(section, option, **kwargs) + stringlist = [s.strip() for s in value.split(',') if s.strip()] + return stringlist class AlotConfigParser(FallbackConfigParser): @@ -163,17 +170,26 @@ class AlotConfigParser(FallbackConfigParser): has_bg = self.has_option(theme, themeing + '_bg') return (has_fg or has_bg) - def get_highlight_tags(self): - if self.has_option('general', 'thread_highlight_tags'): - highlight_tags = list() - raw_lists = self.getstringlist('general', 'thread_highlight_tags') - for raw_list in raw_lists: - raw_combo = raw_list.split('+') - tag_combo = [tag.strip() for tag in raw_combo] - highlight_tags.append(tag_combo) - return highlight_tags - else: - raise NameError("No config option 'thread_highlight_tags'.") + def get_highlight_rules(self): + """ + Parse the highlighting rules from the config file. + + :returns: The highlighting rules + :rtype: :py:class:`collections.OrderedDict` + """ + rules = OrderedDict() + try: + config_string = self.get('general', 'thread_highlight_rules') + rules = json.loads(config_string, object_pairs_hook=OrderedDict) + except NoOptionError as err: + logging.exception(err) + except ValueError as err: + report = ParsingError("Could not parse config option" \ + " 'thread_highlight_rules' in section" \ + " 'general': {reason}".format(reason=err)) + logging.exception(report) + finally: + return rules def get_tagattr(self, tag, focus=False): """ @@ -188,19 +204,19 @@ class AlotConfigParser(FallbackConfigParser): mode = self.getint('general', 'colourmode') base = 'tag_%s' % tag if mode == 2: - if self.get('1c-theme', base): + if self.has_option('1c-theme', base): return base elif mode == 16: - has_fg = self.get('16c-theme', base + '_fg') - has_bg = self.get('16c-theme', base + '_bg') + has_fg = self.has_option('16c-theme', base + '_fg') + has_bg = self.has_option('16c-theme', base + '_bg') if has_fg or has_bg: if focus: return base + '_focus' else: return base else: # highcolour - has_fg = self.get('256c-theme', base + '_fg') - has_bg = self.get('256c-theme', base + '_bg') + has_fg = self.has_option('256c-theme', base + '_fg') + has_bg = self.has_option('256c-theme', base + '_bg') if has_fg or has_bg: if focus: return base + '_focus' @@ -239,8 +255,10 @@ class AlotConfigParser(FallbackConfigParser): :returns: a command line to be applied upon keypress :rtype: str """ - cmdline = self.get(mode + '-maps', key) - if not cmdline: + cmdline = None + if self.has_option(mode + '-maps', key): + cmdline = self.get(mode + '-maps', key) + elif self.has_option('global-maps', key): cmdline = self.get('global-maps', key) return cmdline diff --git a/alot/widgets.py b/alot/widgets.py index 9a024afa..17141917 100644 --- a/alot/widgets.py +++ b/alot/widgets.py @@ -79,7 +79,7 @@ class ThreadlineWidget(urwid.AttrMap): 'display_content_in_threadline') self.highlight_components = config.getstringlist('general', 'thread_highlight_components') - self.highlight_tags = config.get_highlight_tags() + self.highlight_rules = config.get_highlight_rules() self.rebuild() urwid.AttrMap.__init__(self, self.columns, 'search_thread', 'search_thread_focus') @@ -93,8 +93,8 @@ class ThreadlineWidget(urwid.AttrMap): if newest == None: datestring = u' ' * 10 else: - formatstring = config.get('general', 'timestamp_format') - if formatstring: + if config.has_option('general', 'timestamp_format'): + formatstring = config.get('general', 'timestamp_format') datestring = newest.strftime(formatstring) else: datestring = pretty_datetime(newest).rjust(10) @@ -192,9 +192,9 @@ class ThreadlineWidget(urwid.AttrMap): def _get_highlight_theme_suffix(self): suffix = None - for tags in self.highlight_tags: - if self.thread.has_tags(*tags): - suffix = '+'.join(tags) + for query in self.highlight_rules.keys(): + if self.thread.matches(query): + suffix = self.highlight_rules[query] break return suffix @@ -202,10 +202,12 @@ class ThreadlineWidget(urwid.AttrMap): theme = 'search_thread_{0}'.format(component) if focus: theme = theme + '_focus' - if self.highlight_theme_suffix and component in self.highlight_components: - tag_theme = theme + '_{tags}'.format(tags=self.highlight_theme_suffix) - if config.has_themeing(tag_theme): - theme = tag_theme + if (self.highlight_theme_suffix and + component in self.highlight_components): + highlight_theme = (theme + + '_{id}'.format(id=self.highlight_theme_suffix)) + if config.has_themeing(highlight_theme): + theme = highlight_theme return theme |