Coding style
This commit is contained in:
parent
80048c64f8
commit
3cb877406f
3 changed files with 61 additions and 56 deletions
|
|
@ -8,6 +8,7 @@ Edit two files side by side, showing differences.
|
||||||
|
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import contextlib
|
||||||
import difflib
|
import difflib
|
||||||
import functools
|
import functools
|
||||||
import os
|
import os
|
||||||
|
|
@ -50,7 +51,7 @@ _LINE_MAP = {"━": 0b0101, "┃": 0b1010, "┏": 0b0110, "┗": 0b1100, "┛":
|
||||||
_LINE_MAP_INVERTED = {v: k for k, v in _LINE_MAP.items()}
|
_LINE_MAP_INVERTED = {v: k for k, v in _LINE_MAP.items()}
|
||||||
|
|
||||||
|
|
||||||
@functools.lru_cache()
|
@functools.cache
|
||||||
def union_box_line(a_line, b_line):
|
def union_box_line(a_line, b_line):
|
||||||
return _LINE_MAP_INVERTED[_LINE_MAP[a_line] | _LINE_MAP[b_line]]
|
return _LINE_MAP_INVERTED[_LINE_MAP[a_line] | _LINE_MAP[b_line]]
|
||||||
|
|
||||||
|
|
@ -66,12 +67,13 @@ def highlight_str(line, bg_color, transparency):
|
||||||
|
|
||||||
|
|
||||||
@functools.lru_cache(maxsize=500)
|
@functools.lru_cache(maxsize=500)
|
||||||
def get_diff(a_text, b_text):
|
def line_diff(a_text, b_text):
|
||||||
return difflib.SequenceMatcher(a=a_text, b=b_text).get_opcodes()
|
return difflib.SequenceMatcher(a=a_text, b=b_text).get_opcodes()
|
||||||
|
|
||||||
|
|
||||||
def get_lines(text_editor, start, end):
|
def get_lines(text_editor, start, end):
|
||||||
return tuple(text_editor.text_widget[start:end]), tuple(text_editor.text_widget.appearance_interval((start, end)))
|
return (tuple(text_editor.text_widget[start:end]),
|
||||||
|
tuple(text_editor.text_widget.appearance_interval((start, end))))
|
||||||
|
|
||||||
|
|
||||||
def replace_part(a_str, start, end, part):
|
def replace_part(a_str, start, end, part):
|
||||||
|
|
@ -86,7 +88,7 @@ def highlight_modification(a_lines, b_lines, show_sub_highlights):
|
||||||
right_line = fill3.join("\n", tuple(colored_line[:len(line)]
|
right_line = fill3.join("\n", tuple(colored_line[:len(line)]
|
||||||
for line, colored_line in zip(*b_lines)))
|
for line, colored_line in zip(*b_lines)))
|
||||||
if show_sub_highlights:
|
if show_sub_highlights:
|
||||||
diff = get_diff(left_line.data, right_line.data)
|
diff = line_diff(left_line.data, right_line.data)
|
||||||
for opcode, left_start, left_end, right_start, right_end in diff:
|
for opcode, left_start, left_end, right_start, right_end in diff:
|
||||||
color = termstr.Color.white if opcode == "replace" else termstr.Color.green
|
color = termstr.Color.white if opcode == "replace" else termstr.Color.green
|
||||||
if opcode == "delete" or opcode == "replace":
|
if opcode == "delete" or opcode == "replace":
|
||||||
|
|
@ -148,50 +150,57 @@ class DiffEditor:
|
||||||
self.right_editor = editor.Editor()
|
self.right_editor = editor.Editor()
|
||||||
self.right_editor.load(right_path)
|
self.right_editor.load(right_path)
|
||||||
self.show_sub_highlights = True
|
self.show_sub_highlights = True
|
||||||
self.diff = None
|
left_decor = editor.Decor(self.left_editor.text_widget, self._left_highlight_lines)
|
||||||
|
self.left_editor.decor_widget.widget = left_decor
|
||||||
|
self.left_view = self.left_editor.view_widget
|
||||||
|
right_decor = editor.Decor(self.right_editor.text_widget, self._right_highlight_lines)
|
||||||
|
self.right_editor.decor_widget.widget = right_decor
|
||||||
|
self.right_view = self.right_editor.view_widget
|
||||||
|
self.right_editor.is_editing = False
|
||||||
|
self.editors = [self.left_editor, self.right_editor]
|
||||||
|
|
||||||
def highlight_lines(appearance, start, end, opcode, change_opcode):
|
@functools.cached_property
|
||||||
|
def diff(self):
|
||||||
|
return difflib.SequenceMatcher(a=self.left_editor.text_widget,
|
||||||
|
b=self.right_editor.text_widget).get_opcodes()
|
||||||
|
|
||||||
|
def diff_changed(self):
|
||||||
|
with contextlib.suppress(AttributeError):
|
||||||
|
del self.diff
|
||||||
|
|
||||||
|
def _highlight_lines(self, appearance, start, end, opcode, change_opcode):
|
||||||
if opcode == change_opcode:
|
if opcode == change_opcode:
|
||||||
for index in range(start, end):
|
for index in range(start, end):
|
||||||
appearance[index] = highlight_str(appearance[index], (0, 200, 0), 0.6)
|
appearance[index] = highlight_str(appearance[index], (0, 200, 0), 0.6)
|
||||||
|
|
||||||
def left_highlight_lines(appearance):
|
def _left_highlight_lines(self, appearance):
|
||||||
view_x, view_y = self.left_view.position
|
view_x, view_y = self.left_view.position
|
||||||
|
view_end_y = view_y + len(appearance)
|
||||||
for op, left_start, left_end, right_start, right_end in self.diff:
|
for op, left_start, left_end, right_start, right_end in self.diff:
|
||||||
if (op == "replace"
|
if op == "replace" and ranges_overlap((left_start, left_end), (view_y, view_end_y)):
|
||||||
and ranges_overlap((left_start, left_end), (view_y, view_y + len(appearance)))):
|
|
||||||
left_lines = get_lines(self.left_editor, left_start, left_end)
|
left_lines = get_lines(self.left_editor, left_start, left_end)
|
||||||
right_lines = get_lines(self.right_editor, right_start, right_end)
|
right_lines = get_lines(self.right_editor, right_start, right_end)
|
||||||
left_appearance, right_appearance = highlight_modification(
|
left_appearance, right_appearance = highlight_modification(
|
||||||
left_lines, right_lines, self.show_sub_highlights)
|
left_lines, right_lines, self.show_sub_highlights)
|
||||||
overlay_list(appearance, left_appearance, left_start - view_y)
|
overlay_list(appearance, left_appearance, left_start - view_y)
|
||||||
highlight_lines(appearance, max(left_start, view_y) - view_y,
|
self._highlight_lines(appearance, max(left_start, view_y) - view_y,
|
||||||
min(left_end, view_y + len(appearance)) - view_y, op, "delete")
|
min(left_end, view_end_y) - view_y, op, "delete")
|
||||||
return appearance
|
return appearance
|
||||||
|
|
||||||
def right_highlight_lines(appearance):
|
def _right_highlight_lines(self, appearance):
|
||||||
view_x, view_y = self.right_view.position
|
view_x, view_y = self.right_view.position
|
||||||
|
view_end_y = view_y + len(appearance)
|
||||||
for op, left_start, left_end, right_start, right_end in self.diff:
|
for op, left_start, left_end, right_start, right_end in self.diff:
|
||||||
if (op == "replace"
|
if op == "replace" and ranges_overlap((right_start, right_end), (view_y, view_end_y)):
|
||||||
and ranges_overlap((right_start, right_end), (view_y, view_y + len(appearance)))):
|
|
||||||
left_lines = get_lines(self.left_editor, left_start, left_end)
|
left_lines = get_lines(self.left_editor, left_start, left_end)
|
||||||
right_lines = get_lines(self.right_editor, right_start, right_end)
|
right_lines = get_lines(self.right_editor, right_start, right_end)
|
||||||
left_appearance, right_appearance = highlight_modification(
|
left_appearance, right_appearance = highlight_modification(
|
||||||
left_lines, right_lines, self.show_sub_highlights)
|
left_lines, right_lines, self.show_sub_highlights)
|
||||||
overlay_list(appearance, right_appearance, right_start - view_y)
|
overlay_list(appearance, right_appearance, right_start - view_y)
|
||||||
highlight_lines(appearance, max(right_start, view_y) - view_y,
|
self._highlight_lines(appearance, max(right_start, view_y) - view_y,
|
||||||
min(right_end, view_y + len(appearance)) - view_y, op, "insert")
|
min(right_end, view_end_y) - view_y, op, "insert")
|
||||||
return appearance
|
return appearance
|
||||||
|
|
||||||
left_decor = editor.Decor(self.left_editor.text_widget, left_highlight_lines)
|
|
||||||
self.left_editor.decor_widget.widget = left_decor
|
|
||||||
self.left_view = self.left_editor.view_widget
|
|
||||||
right_decor = editor.Decor(self.right_editor.text_widget, right_highlight_lines)
|
|
||||||
self.right_editor.decor_widget.widget = right_decor
|
|
||||||
self.right_view = self.right_editor.view_widget
|
|
||||||
self.right_editor.is_editing = False
|
|
||||||
self.editors = [self.left_editor, self.right_editor]
|
|
||||||
|
|
||||||
def _equivalent_line(self, y):
|
def _equivalent_line(self, y):
|
||||||
for opcode, left_start, left_end, right_start, right_end in self.diff:
|
for opcode, left_start, left_end, right_start, right_end in self.diff:
|
||||||
if self.editors[0] == self.right_editor:
|
if self.editors[0] == self.right_editor:
|
||||||
|
|
@ -229,12 +238,12 @@ class DiffEditor:
|
||||||
self.left_editor.text_widget[left_start:left_end] = \
|
self.left_editor.text_widget[left_start:left_end] = \
|
||||||
[self.right_editor.text_widget[line_num]
|
[self.right_editor.text_widget[line_num]
|
||||||
for line_num in range(right_start, right_end)]
|
for line_num in range(right_start, right_end)]
|
||||||
self.diff = None
|
self.diff_changed()
|
||||||
elif x == right_x and right_y == y:
|
elif x == right_x and right_y == y:
|
||||||
self.right_editor.text_widget[right_start:right_end] = \
|
self.right_editor.text_widget[right_start:right_end] = \
|
||||||
[self.left_editor.text_widget[line_num]
|
[self.left_editor.text_widget[line_num]
|
||||||
for line_num in range(left_start, left_end)]
|
for line_num in range(left_start, left_end)]
|
||||||
self.diff = None
|
self.diff_changed()
|
||||||
|
|
||||||
def on_mouse_press(self, x, y, left_x, right_x):
|
def on_mouse_press(self, x, y, left_x, right_x):
|
||||||
if x < left_x:
|
if x < left_x:
|
||||||
|
|
@ -261,10 +270,6 @@ class DiffEditor:
|
||||||
elif x > right_x:
|
elif x > right_x:
|
||||||
self.right_editor.on_mouse_drag(x - right_x - 1, y)
|
self.right_editor.on_mouse_drag(x - right_x - 1, y)
|
||||||
|
|
||||||
def update_diff(self):
|
|
||||||
self.diff = difflib.SequenceMatcher(a=self.left_editor.text_widget,
|
|
||||||
b=self.right_editor.text_widget).get_opcodes()
|
|
||||||
|
|
||||||
def toggle_highlights(self):
|
def toggle_highlights(self):
|
||||||
self.show_sub_highlights = not self.show_sub_highlights
|
self.show_sub_highlights = not self.show_sub_highlights
|
||||||
|
|
||||||
|
|
@ -307,7 +312,7 @@ class DiffEditor:
|
||||||
self.KEY_MAP[term_code](self)
|
self.KEY_MAP[term_code](self)
|
||||||
else:
|
else:
|
||||||
self.editors[0].on_keyboard_input(term_code)
|
self.editors[0].on_keyboard_input(term_code)
|
||||||
self.diff = None
|
self.diff_changed()
|
||||||
fill3.APPEARANCE_CHANGED_EVENT.set()
|
fill3.APPEARANCE_CHANGED_EVENT.set()
|
||||||
|
|
||||||
def on_mouse_input(self, term_code):
|
def on_mouse_input(self, term_code):
|
||||||
|
|
@ -351,8 +356,6 @@ class DiffEditor:
|
||||||
|
|
||||||
def appearance_for(self, dimensions):
|
def appearance_for(self, dimensions):
|
||||||
width, height = self.last_dimensions = dimensions
|
width, height = self.last_dimensions = dimensions
|
||||||
if self.diff is None:
|
|
||||||
self.update_diff()
|
|
||||||
self.follow_scroll()
|
self.follow_scroll()
|
||||||
divider_width = 3
|
divider_width = 3
|
||||||
left_width = (width - divider_width) // 2
|
left_width = (width - divider_width) // 2
|
||||||
|
|
|
||||||
|
|
@ -275,11 +275,13 @@ class Editor:
|
||||||
result[start_y] = highlight_part(result[start_y], screen_start_x, screen_end_x)
|
result[start_y] = highlight_part(result[start_y], screen_start_x, screen_end_x)
|
||||||
else:
|
else:
|
||||||
if 0 <= start_y < len(result):
|
if 0 <= start_y < len(result):
|
||||||
result[start_y] = highlight_part(result[start_y], screen_start_x, len(result[start_y]))
|
result[start_y] = highlight_part(result[start_y], screen_start_x,
|
||||||
|
len(result[start_y]))
|
||||||
view_x, view_y = self.view_widget.position
|
view_x, view_y = self.view_widget.position
|
||||||
for line_num in range(max(start_y+1, 0), min(end_y, self.last_height)):
|
for line_num in range(max(start_y+1, 0), min(end_y, self.last_height)):
|
||||||
if 0 <= line_num < len(result):
|
if 0 <= line_num < len(result):
|
||||||
result[line_num] = highlight_part(result[line_num], 0, len(result[line_num]))
|
result[line_num] = highlight_part(result[line_num], 0,
|
||||||
|
len(result[line_num]))
|
||||||
if 0 <= end_y < len(result):
|
if 0 <= end_y < len(result):
|
||||||
result[end_y] = highlight_part(result[end_y], 0, screen_end_x)
|
result[end_y] = highlight_part(result[end_y], 0, screen_end_x)
|
||||||
if self.cursor_x >= len(result[0]):
|
if self.cursor_x >= len(result[0]):
|
||||||
|
|
@ -288,9 +290,9 @@ class Editor:
|
||||||
screen_x = len(expand_str(self.text_widget[self.cursor_y][:self.cursor_x]))
|
screen_x = len(expand_str(self.text_widget[self.cursor_y][:self.cursor_x]))
|
||||||
screen_x_after = (screen_x + 1 if self._current_character() in ["\t", "\n"]
|
screen_x_after = (screen_x + 1 if self._current_character() in ["\t", "\n"]
|
||||||
else len(expand_str(self.text_widget[self.cursor_y][:self.cursor_x+1])))
|
else len(expand_str(self.text_widget[self.cursor_y][:self.cursor_x+1])))
|
||||||
result[self.cursor_y - view_y] = (cursor_line[:screen_x] +
|
result[self.cursor_y - view_y] = (
|
||||||
termstr.TermStr(cursor_line[screen_x:screen_x_after]).invert() +
|
cursor_line[:screen_x] + termstr.TermStr(cursor_line[screen_x:screen_x_after]).invert()
|
||||||
cursor_line[screen_x_after:])
|
+ cursor_line[screen_x_after:])
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def set_text(self, text):
|
def set_text(self, text):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue