From 2b1f282a30a0a3f5888a88457ab0b1c7e8e5b1a7 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 24 May 2020 11:05:39 +0200 Subject: widgets/thread: add heuristics for broken quote levels --- alot/widgets/thread.py | 48 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 8 deletions(-) (limited to 'alot/widgets') diff --git a/alot/widgets/thread.py b/alot/widgets/thread.py index 78d974f2..2af22b07 100644 --- a/alot/widgets/thread.py +++ b/alot/widgets/thread.py @@ -192,10 +192,13 @@ class _TextPart(_MIMEPartWidget): fold_context = settings.get('thread_fold_context') blocks = self._split_quotes(text) - max_level = max((b[0] for b in blocks)) + max_level = max((b['level'] for b in blocks)) block_wgts = [] - for level, lines in blocks: + for b in blocks: + level = b['level'] + lines = b['data'] + if level == 0 or len(attrs_quote) < 1: attr = attr_text else: @@ -215,19 +218,48 @@ class _TextPart(_MIMEPartWidget): """ lines = text.splitlines() + # first pass: assign a level to each line based on the number of quote + # characters at the beginning blocks = [] for line in lines: level = 0 m = re.match(self._QUOTE_REGEX, line) if m is not None: - g = m.group(0) + quote_prefix = m.group(0) + remainder = line[len(quote_prefix):] for c in self._QUOTE_CHARS: - level += g.count(c) - - if len(blocks) > 0 and blocks[-1][0] == level: - blocks[-1][1].append(line) + level += quote_prefix.count(c) else: - blocks.append((level, [line])) + quote_prefix = '' + remainder = line + + if len(blocks) == 0 or blocks[-1]['level'] != level: + # start a new block + blocks.append({ 'level' : level, 'data' : [], 'data_empty' : True}) + + blocks[-1]['data'].append(line) + if len(remainder) > 0: + blocks[-1]['data_empty'] = False + + # second pass: every quoted block where the remainder (line minus the + # leading quote characters) is empty gets merged into an adjacent quoted + # block, higher level preferred + for idx, b in enumerate(blocks): + if b['level'] > 0 and b['data_empty']: + b_prev = blocks[idx - 1] if idx > 0 else None + b_next = blocks[idx + 1] if idx + 1 < len(blocks) else None + + merge_level = None + if (b_prev is not None and not b_prev['data_empty'] and + b_prev['level'] > 0): + merge_level = b_prev['level'] + + if (b_next is not None and not b_next['data_empty'] and + (merge_level is None or merge_level < b_next['level'])): + merge_level = b_next['level'] + + if merge_level is not None: + b['level'] = merge_level return blocks -- cgit v1.2.3