summaryrefslogtreecommitdiff
path: root/alot/widgets
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2020-05-24 11:05:39 +0200
committerAnton Khirnov <anton@khirnov.net>2020-05-24 11:05:39 +0200
commit2b1f282a30a0a3f5888a88457ab0b1c7e8e5b1a7 (patch)
treea82e8e8a12d72e2d97657514173ffe17502c0dcb /alot/widgets
parent8c33418c97a5bf37819c2344f9750e19b1bf192f (diff)
widgets/thread: add heuristics for broken quote levels
Diffstat (limited to 'alot/widgets')
-rw-r--r--alot/widgets/thread.py48
1 files changed, 40 insertions, 8 deletions
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