diff --git a/method.py b/method.py index 917dcc4..c10ca46 100644 --- a/method.py +++ b/method.py @@ -650,45 +650,93 @@ class WrapLine(Method): for t in tokens: l += len(t) return l - def _find_line_bounds(self, tokens): + def _find_line_bounds(self, tokens, x, y): if len(tokens[0]) > self.limit: i = 1 else: i = 0 - while i < len(tokens) and self._token_len(tokens[:i+1]) <= self.limit: + l = self._token_len(tokens[:i+1]) + while i < len(tokens) and l <= self.limit: i += 1 + l = self._token_len(tokens[:i+1]) while i > 1 and tokens and tokens[i-1].isspace(): - del tokens[i-1] + token = tokens.pop(i-1) + l -= len(token) + if x > l: + x -= len(token) i -= 1 - return i - def _clear_preceeding_spaces(self, tokens): + return i, x, y + def _clear_preceeding_spaces(self, tokens, x, y): while tokens and tokens[0].isspace(): + if x > 0: + x = max(0, x - len(tokens[0])) del tokens[0] - def _execute(self, w, **vargs): - cursor = w.logical_cursor() - x, y = cursor.xy() + return x, y - tokens = re.findall('[^ ]+| +', w.buffer.lines[y]) + def _wrap_line(self, line, x, y): + tokens = re.findall('[^ ]+| +', line) if self._token_len(tokens) <= self.limit: - return + return None, None, None lines = [] while tokens and self._token_len(tokens) > self.limit: - i = self._find_line_bounds(tokens) + i, x, y = self._find_line_bounds(tokens, x, y) s = ''.join(tokens[:i]) lines.append(s) if x > len(s): y += 1 x -= len(s) del tokens[:i] - self._clear_preceeding_spaces(tokens) + x, y = self._clear_preceeding_spaces(tokens, x, y) if tokens: lines.append(''.join(tokens)) + return lines, x, y + def _execute(self, w, **vargs): + cursor = w.logical_cursor() + x, y = cursor.xy() + lines, x, y = self._wrap_line(w.buffer.lines[y], x, y) + if lines is None: + return w.buffer.delete_line(cursor.y) w.buffer.insert_lines(Point(0, cursor.y), lines) w.goto(Point(x, y)) -class WrapParagraph(Method): +class WrapParagraph(WrapLine): + limit = 80 + empty_re = regex.whitespace + prefix_re = regex.leading_whitespace + def _execute(self, w, **vargs): + c = w.logical_cursor() + y2 = y1 = c.y + x2 = x1 = 0 + line = w.buffer.lines[y1] + if self.empty_re.match(line): + return + + m = self.prefix_re.match(line) + prefix = m.group(0) + lines = [line.strip()] + y2 += 1 + + while y2 < len(w.buffer.lines): + line = w.buffer.lines[y2] + if self.empty_re.match(line): + break + lines.append(line.strip()) + y2 += 1 + y2 -= 1 + + x, y = c.xy() + lines, x, y = self._wrap_line(w.buffer.lines[y], x, y) + if lines is None: + return + + w.set_error(repr(lines)) + + w.buffer.delete(Point(x1, y1), Point(x2, y2)) + w.buffer.insert_lines(Point(0, c.y), lines) + w.goto(Point(x, y)) +class WrapParagraph2(Method): limit = 80 wrapper = WrapLine spacer = InsertSpace diff --git a/regex.py b/regex.py index 37bcd70..2cc3e3e 100644 --- a/regex.py +++ b/regex.py @@ -16,6 +16,7 @@ leading_whitespace = re.compile('^ *') trailing_whitespace = re.compile(' *$') whitespace = re.compile('^[ \n]*$') space = re.compile('^ *$') +leading_whitespace2 = re.compile('^( *?)(.*?)\n?$') # word regexes word = re.compile('^[A-Za-z0-9_]+$')