Add static typing for widgets
This commit is contained in:
parent
e660acdc48
commit
e975f66fde
|
@ -333,6 +333,7 @@ class LineEnding(IntFlag):
|
|||
|
||||
Values can be used as flags in bitwise operations.'''
|
||||
|
||||
NO_FORMAT = 0
|
||||
DOS_FORMAT = 1
|
||||
MAC_FORMAT = 2
|
||||
UNIX_FORMAT = 4
|
||||
|
|
|
@ -21,8 +21,9 @@ import difflib
|
|||
import os
|
||||
import unicodedata
|
||||
|
||||
from enum import IntFlag
|
||||
from gettext import gettext as _
|
||||
from typing import Any, Dict, List, Optional
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
|
||||
from diffuse import utils
|
||||
from diffuse.resources import theResources
|
||||
|
@ -38,7 +39,7 @@ from gi.repository import GObject, Gdk, Gtk, Pango, PangoCairo # type: ignore #
|
|||
|
||||
|
||||
# mapping to column width of a character (tab will never be in this map)
|
||||
_char_width_cache: Dict[str, str] = {}
|
||||
_char_width_cache: Dict[str, int] = {}
|
||||
|
||||
# the file diff viewer is always in one of these modes defining the cursor,
|
||||
# and hotkey behavior
|
||||
|
@ -151,7 +152,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
class Pane:
|
||||
def __init__(self) -> None:
|
||||
# list of lines displayed in this pane (including spacing lines)
|
||||
self.lines: List[FileDiffViewerBase.Line] = []
|
||||
self.lines: List[Optional[FileDiffViewerBase.Line]] = []
|
||||
# high water mark for line length in Pango units (used to determine
|
||||
# the required horizontal scroll range)
|
||||
self.line_lengths = 0
|
||||
|
@ -167,7 +168,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
# portion of the cache are cleared by setting entries to None
|
||||
self.diff_cache: List[List[Any]] = []
|
||||
# mask indicating the type of line endings present
|
||||
self.format = 0
|
||||
self.format: LineEnding = LineEnding.NO_FORMAT
|
||||
# number of lines with edits
|
||||
self.num_edits = 0
|
||||
|
||||
|
@ -407,7 +408,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
# returns the 'column width' for a string -- used to help position
|
||||
# characters when tabs and other special characters are present
|
||||
# This is an inline loop over self.characterWidth() for performance reasons.
|
||||
def stringWidth(self, s):
|
||||
def stringWidth(self, s: str) -> int:
|
||||
if not self.prefs.getBool('display_show_whitespace'):
|
||||
s = utils.strip_eol(s)
|
||||
col = 0
|
||||
|
@ -436,7 +437,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
return col
|
||||
|
||||
# returns the 'column width' for a single character created at column 'i'
|
||||
def characterWidth(self, i, c):
|
||||
def characterWidth(self, i: int, c: str) -> int:
|
||||
try:
|
||||
return _char_width_cache[c]
|
||||
except KeyError:
|
||||
|
@ -458,13 +459,13 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
|
||||
# translates a string into an array of the printable representation for
|
||||
# each character
|
||||
def expand(self, s):
|
||||
def expand(self, s: str) -> List[str]:
|
||||
visible = self.prefs.getBool('display_show_whitespace')
|
||||
if not visible:
|
||||
s = utils.strip_eol(s)
|
||||
tab_width = self.prefs.getInt('display_tab_width')
|
||||
col = 0
|
||||
result = []
|
||||
result: List[str] = []
|
||||
for c in s:
|
||||
v = ord(c)
|
||||
if v <= 32:
|
||||
|
@ -493,7 +494,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
return result
|
||||
|
||||
# changes the viewer's mode to LINE_MODE
|
||||
def setLineMode(self):
|
||||
def setLineMode(self) -> None:
|
||||
if self.mode != LINE_MODE:
|
||||
if self.mode == CHAR_MODE:
|
||||
self._im_focus_out()
|
||||
|
@ -512,7 +513,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
self.emit('mode_changed')
|
||||
|
||||
# changes the viewer's mode to CHAR_MODE
|
||||
def setCharMode(self):
|
||||
def setCharMode(self) -> None:
|
||||
if self.mode != CHAR_MODE:
|
||||
if self.mode == LINE_MODE:
|
||||
self.cursor_column = -1
|
||||
|
@ -546,7 +547,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
return self.syntax
|
||||
|
||||
# returns True if any pane contains edits
|
||||
def hasEdits(self):
|
||||
def hasEdits(self) -> bool:
|
||||
for pane in self.panes:
|
||||
if pane.num_edits > 0:
|
||||
return True
|
||||
|
@ -561,7 +562,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
# openUndoBlock() should be called when the action from a user, like a
|
||||
# mouse button press, menu item, etc. may cause change to the diff viewer's
|
||||
# state
|
||||
def openUndoBlock(self):
|
||||
def openUndoBlock(self) -> None:
|
||||
self.undoblock = []
|
||||
|
||||
# all changes to the diff viewer's state should create an Undo object and
|
||||
|
@ -574,14 +575,14 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
# all openUndoBlock() calls should also have a matching closeUndoBlock()
|
||||
# this method collects all Undos created since the openUndoBlock() call
|
||||
# and pushes them onto the undo stack as a single unit
|
||||
def closeUndoBlock(self):
|
||||
def closeUndoBlock(self) -> None:
|
||||
if len(self.undoblock) > 0:
|
||||
self.redos = []
|
||||
self.undos.append(self.undoblock)
|
||||
self.undoblock = None
|
||||
|
||||
# 'undo' action
|
||||
def undo(self):
|
||||
def undo(self) -> None:
|
||||
self.undoblock, old_block = None, self.undoblock
|
||||
if self.mode == CHAR_MODE:
|
||||
# avoid implicit preedit commit when an undo changes the mode
|
||||
|
@ -597,7 +598,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
self.undoblock = old_block
|
||||
|
||||
# 'redo' action
|
||||
def redo(self):
|
||||
def redo(self) -> None:
|
||||
self.undoblock, old_block = None, self.undoblock
|
||||
if self.mode in (LINE_MODE, CHAR_MODE):
|
||||
if self.mode == CHAR_MODE:
|
||||
|
@ -613,7 +614,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
self.undoblock = old_block
|
||||
|
||||
# returns the width of the viewport's line number column in Pango units
|
||||
def getLineNumberWidth(self):
|
||||
def getLineNumberWidth(self) -> int:
|
||||
# find the maximum number of digits for a line number from all panes
|
||||
n = 0
|
||||
if self.prefs.getBool('display_show_line_numbers'):
|
||||
|
@ -624,7 +625,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
return n
|
||||
|
||||
# returns the width of a string in Pango units
|
||||
def getTextWidth(self, text):
|
||||
def getTextWidth(self, text: str) -> int:
|
||||
if len(text) == 0:
|
||||
return 0
|
||||
layout = self.create_pango_layout(text)
|
||||
|
@ -635,7 +636,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
# set 'compute_width' to False if the high water mark for line length can
|
||||
# be used to determine the required width for the viewport, use True for
|
||||
# this value otherwise
|
||||
def updateSize(self, compute_width, f=None):
|
||||
def updateSize(self, compute_width: bool, f: Optional[int] = None) -> None:
|
||||
digit_width, stringWidth = self.digit_width, self.stringWidth
|
||||
string_width_cache = self.string_width_cache
|
||||
if compute_width:
|
||||
|
@ -685,14 +686,14 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
self.vadj.step_increment = self.font_height
|
||||
|
||||
# returns a line from the specified pane and offset
|
||||
def getLine(self, f, i):
|
||||
def getLine(self, f: int, i: int) -> Optional[Line]:
|
||||
lines = self.panes[f].lines
|
||||
if i < len(lines):
|
||||
return lines[i]
|
||||
return None
|
||||
|
||||
# returns the text for the specified line
|
||||
def getLineText(self, f, i):
|
||||
def getLineText(self, f: int, i: int) -> Optional[str]:
|
||||
line = self.getLine(f, i)
|
||||
if line is not None:
|
||||
return line.getText()
|
||||
|
@ -700,7 +701,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
|
||||
# Undo for changes to the cached line ending style
|
||||
class SetFormatUndo:
|
||||
def __init__(self, f, fmt, old_format):
|
||||
def __init__(self, f: int, fmt: LineEnding, old_format: LineEnding) -> None:
|
||||
self.data = (f, fmt, old_format)
|
||||
|
||||
def undo(self, viewer):
|
||||
|
@ -712,7 +713,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
viewer.setFormat(f, fmt)
|
||||
|
||||
# sets the cached line ending style
|
||||
def setFormat(self, f, fmt):
|
||||
def setFormat(self, f: int, fmt: LineEnding) -> None:
|
||||
pane = self.panes[f]
|
||||
if self.undoblock is not None:
|
||||
# create an Undo object for the action
|
||||
|
@ -722,7 +723,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
|
||||
# Undo for the creation of Line objects
|
||||
class InstanceLineUndo:
|
||||
def __init__(self, f, i, reverse):
|
||||
def __init__(self, f: int, i: int, reverse: bool) -> None:
|
||||
self.data = (f, i, reverse)
|
||||
|
||||
def undo(self, viewer):
|
||||
|
@ -735,7 +736,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
|
||||
# creates an instance of a Line object for the specified pane and offset
|
||||
# deletes an instance when 'reverse' is set to True
|
||||
def instanceLine(self, f, i, reverse=False):
|
||||
def instanceLine(self, f: int, i: int, reverse: bool = False) -> None:
|
||||
if self.undoblock is not None:
|
||||
# create an Undo object for the action
|
||||
self.addUndo(FileDiffViewerBase.InstanceLineUndo(f, i, reverse))
|
||||
|
@ -759,7 +760,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
f, i, _, _, is_modified, text = self.data
|
||||
viewer.updateLineText(f, i, is_modified, text)
|
||||
|
||||
def getMapFlags(self, f, i):
|
||||
def getMapFlags(self, f: int, i: int) -> int:
|
||||
flags = 0
|
||||
compare_text = self.getCompareString(f, i)
|
||||
if f > 0 and self.getCompareString(f - 1, i) != compare_text:
|
||||
|
@ -822,7 +823,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
|
||||
# Undo for inserting a spacing line in a single pane
|
||||
class InsertNullUndo:
|
||||
def __init__(self, f, i, reverse):
|
||||
def __init__(self, f: int, i: int, reverse: bool) -> None:
|
||||
self.data = (f, i, reverse)
|
||||
|
||||
def undo(self, viewer):
|
||||
|
@ -836,7 +837,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
# insert a spacing line at line 'i' in pane 'f'
|
||||
# this caller must ensure the blocks and number of lines in each pane
|
||||
# are valid again
|
||||
def insertNull(self, f, i, reverse):
|
||||
def insertNull(self, f: int, i: int, reverse: bool) -> None:
|
||||
if self.undoblock is not None:
|
||||
# create an Undo object for the action
|
||||
self.addUndo(FileDiffViewerBase.InsertNullUndo(f, i, reverse))
|
||||
|
@ -885,7 +886,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
|
||||
# Undo for alignment changes
|
||||
class AlignmentChangeUndo:
|
||||
def __init__(self, finished):
|
||||
def __init__(self, finished: bool) -> None:
|
||||
self.data = finished
|
||||
|
||||
def undo(self, viewer):
|
||||
|
@ -897,7 +898,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
viewer.alignmentChange(finished)
|
||||
|
||||
# update viewer in response to alignment changes
|
||||
def alignmentChange(self, finished):
|
||||
def alignmentChange(self, finished: bool) -> None:
|
||||
if self.undoblock is not None:
|
||||
# create an Undo object for the action
|
||||
self.addUndo(FileDiffViewerBase.AlignmentChangeUndo(finished))
|
||||
|
@ -947,7 +948,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
self.blocks = blocks
|
||||
|
||||
# insert 'n' blank lines in all panes
|
||||
def insertLines(self, i, n):
|
||||
def insertLines(self, i: int, n: int) -> None:
|
||||
# insert lines
|
||||
self.updateAlignment(i, 0, [n * [None] for pane in self.panes])
|
||||
pre, post = _cut_blocks(i, self.blocks)
|
||||
|
@ -966,7 +967,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
self.diffmap.queue_draw()
|
||||
|
||||
# remove a line
|
||||
def removeSpacerLines(self, i, n, skip=-1):
|
||||
def removeSpacerLines(self, i: int, n: int, skip: int = -1) -> int:
|
||||
npanes, removed = len(self.panes), []
|
||||
for j in range(i, i + n):
|
||||
for f in range(npanes):
|
||||
|
@ -1055,7 +1056,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
self.diffmap.queue_draw()
|
||||
|
||||
# create a hash for a line to use for line matching
|
||||
def _alignmentHash(self, line):
|
||||
def _alignmentHash(self, line: Line) -> Optional[str]:
|
||||
text = line.getText()
|
||||
if text is None:
|
||||
return None
|
||||
|
@ -1076,15 +1077,14 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
if pref('align_ignore_whitespace_changes'):
|
||||
# replace all blocks of white space with a single space
|
||||
pc = True
|
||||
r = []
|
||||
append = r.append
|
||||
r: List[str] = []
|
||||
for c in text:
|
||||
if c in utils.whitespace:
|
||||
if pc:
|
||||
append(' ')
|
||||
r.append(' ')
|
||||
pc = False
|
||||
else:
|
||||
append(c)
|
||||
r.append(c)
|
||||
pc = True
|
||||
text = ''.join(r)
|
||||
if pref('align_ignore_case'):
|
||||
|
@ -1110,9 +1110,8 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
s1, s2 = mlines
|
||||
n1, n2 = 0, 0
|
||||
# hash lines according to the alignment preferences
|
||||
a = self._alignmentHash
|
||||
t1 = [a(s) for s in s1]
|
||||
t2 = [a(s) for s in s2]
|
||||
t1 = [self._alignmentHash(s) for s in s1]
|
||||
t2 = [self._alignmentHash(s) for s in s2]
|
||||
# align s1 and s2 by inserting spacer lines
|
||||
# this will be used to determine which lines from the inner lists of
|
||||
# lines should be neighbours
|
||||
|
@ -1253,8 +1252,9 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
|
||||
# refresh the lines to contain new objects with updated line numbers and
|
||||
# no local edits
|
||||
def bakeEdits(self, f):
|
||||
pane, lines, line_num = self.panes[f], [], 0
|
||||
def bakeEdits(self, f: int) -> None:
|
||||
lines: List[Optional[FileDiffViewerBase.Line]] = []
|
||||
pane, line_num = self.panes[f], 0
|
||||
for i in range(len(pane.lines)):
|
||||
s = self.getLineText(f, i)
|
||||
if s is None:
|
||||
|
@ -1267,7 +1267,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
self.replaceLines(f, pane.lines, lines, pane.max_line_number, line_num)
|
||||
|
||||
# update the contents for a line, creating the line if necessary
|
||||
def updateText(self, f, i, text, is_modified=True):
|
||||
def updateText(self, f: int, i: int, text: Optional[str], is_modified: bool = True) -> None:
|
||||
if self.panes[f].lines[i] is None:
|
||||
self.instanceLine(f, i)
|
||||
self.updateLineText(f, i, is_modified, text)
|
||||
|
@ -1533,7 +1533,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
self.dareas[old_f].queue_draw()
|
||||
|
||||
# queue a range of lines for redrawing
|
||||
def _queue_draw_lines(self, f, line0, line1=None):
|
||||
def _queue_draw_lines(self, f: int, line0: int, line1: Optional[int] = None) -> None:
|
||||
if line1 is None:
|
||||
line1 = line0
|
||||
elif line0 > line1:
|
||||
|
@ -1543,7 +1543,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
darea.queue_draw_area(0, line0 * h - int(self.vadj.get_value()), w, (line1 - line0 + 1) * h)
|
||||
|
||||
# scroll vertically to ensure the current line is visible
|
||||
def _ensure_line_is_visible(self, i):
|
||||
def _ensure_line_is_visible(self, i: int) -> None:
|
||||
h = self.font_height
|
||||
lower = i * h
|
||||
upper = lower + h
|
||||
|
@ -1557,7 +1557,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
|
||||
# change the current selection in LINE_MODE
|
||||
# use extend=True to extend the selection
|
||||
def setCurrentLine(self, f, i, selection=None):
|
||||
def setCurrentLine(self, f: int, i: int, selection: Optional[int] = None) -> None:
|
||||
# remember old cursor position so we can just redraw what is necessary
|
||||
old_f = self.current_pane
|
||||
line0, line1 = self.current_line, self.selection_line
|
||||
|
@ -1569,10 +1569,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
# update cursor
|
||||
self.current_pane = f
|
||||
self.current_line = i
|
||||
if selection is None:
|
||||
self.selection_line = i
|
||||
else:
|
||||
self.selection_line = selection
|
||||
self.selection_line = selection if selection is not None else i
|
||||
|
||||
self.emit('cursor_changed')
|
||||
|
||||
|
@ -1585,7 +1582,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
self._ensure_line_is_visible(i)
|
||||
|
||||
# returns True if the line has preedit text
|
||||
def hasPreedit(self, f, i):
|
||||
def hasPreedit(self, f: int, i: int) -> bool:
|
||||
return (
|
||||
self.mode == CHAR_MODE and
|
||||
self.current_pane == f and
|
||||
|
@ -1626,15 +1623,17 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
self.im_context.set_cursor_location(rect)
|
||||
|
||||
# get the position of the cursor in Pango units
|
||||
def _get_cursor_x_offset(self):
|
||||
def _get_cursor_x_offset(self) -> int:
|
||||
j = self.current_char
|
||||
if j > 0:
|
||||
text = self.getLineText(self.current_pane, self.current_line)[:j]
|
||||
return self.getTextWidth(''.join(self.expand(text)))
|
||||
text = self.getLineText(self.current_pane, self.current_line)
|
||||
if text is not None:
|
||||
text = text[:j]
|
||||
return self.getTextWidth(''.join(self.expand(text)))
|
||||
return 0
|
||||
|
||||
# scroll to ensure the current cursor position is visible
|
||||
def _ensure_cursor_is_visible(self):
|
||||
def _ensure_cursor_is_visible(self) -> None:
|
||||
current_line = self.current_line
|
||||
|
||||
# find the cursor's horizontal range
|
||||
|
@ -1722,7 +1721,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
return ''.join([s for s in ss if s is not None])
|
||||
|
||||
# expands the selection to include everything
|
||||
def select_all(self):
|
||||
def select_all(self) -> None:
|
||||
if self.mode in (LINE_MODE, CHAR_MODE):
|
||||
f = self.current_pane
|
||||
self.selection_line = 0
|
||||
|
@ -1735,7 +1734,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
# returns the index of the last character in text that should be left of
|
||||
# 'x' _pixels from the edge of the darea widget
|
||||
# if partial=True, include characters only partially to the left of 'x'
|
||||
def _getPickedCharacter(self, text, x, partial):
|
||||
def _getPickedCharacter(self, text: Optional[str], x: int, partial: bool) -> int:
|
||||
if text is None:
|
||||
return 0
|
||||
n = len(text)
|
||||
|
@ -1945,7 +1944,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
|
||||
# returns a hash of a string that can be used to quickly compare strings
|
||||
# according to the display preferences
|
||||
def getCompareString(self, f, i):
|
||||
def getCompareString(self, f: int, i: int) -> Optional[str]:
|
||||
line = self.getLine(f, i)
|
||||
if line is None:
|
||||
return None
|
||||
|
@ -2553,7 +2552,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
self.setCurrentLine(self.current_pane, self.current_line - delta, selection)
|
||||
|
||||
# 'extend_page_up' keybinding action
|
||||
def _line_mode_extend_page_up(self):
|
||||
def _line_mode_extend_page_up(self) -> None:
|
||||
self._line_mode_page_up(self.selection_line)
|
||||
|
||||
# 'page_down' keybinding action
|
||||
|
@ -2562,20 +2561,20 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
self.setCurrentLine(self.current_pane, self.current_line + delta, selection)
|
||||
|
||||
# 'extend_page_down' keybinding action
|
||||
def _line_mode_extend_page_down(self):
|
||||
def _line_mode_extend_page_down(self) -> None:
|
||||
self._line_mode_page_down(self.selection_line)
|
||||
|
||||
# 'delete_text' keybinding action
|
||||
def _delete_text(self):
|
||||
def _delete_text(self) -> None:
|
||||
self.replaceText('')
|
||||
|
||||
# 'enter_line_mode' keybinding action
|
||||
def _align_mode_enter_line_mode(self):
|
||||
def _align_mode_enter_line_mode(self) -> None:
|
||||
self.selection_line = self.current_line
|
||||
self.setLineMode()
|
||||
|
||||
# 'align' keybinding action
|
||||
def _align_text(self):
|
||||
def _align_text(self) -> None:
|
||||
f1 = self.align_pane
|
||||
line1 = self.align_line
|
||||
line2 = self.current_line
|
||||
|
@ -2587,12 +2586,12 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
self.align(self.current_pane, line2, line1)
|
||||
|
||||
# give the input method focus
|
||||
def _im_focus_in(self):
|
||||
def _im_focus_in(self) -> None:
|
||||
if self.has_focus:
|
||||
self.im_context.focus_in()
|
||||
|
||||
# remove input method focus
|
||||
def _im_focus_out(self):
|
||||
def _im_focus_out(self) -> None:
|
||||
if self.has_focus:
|
||||
self.im_context.focus_out()
|
||||
|
||||
|
@ -2762,7 +2761,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
if text is not None and j < len(text):
|
||||
c = _get_character_class(text[j])
|
||||
if (
|
||||
c != WHITESPACE_CLASS and
|
||||
c != CharacterClass.WHITESPACE and
|
||||
(j < 1 or j - 1 >= len(text) or _get_character_class(text[j - 1]) != c)
|
||||
):
|
||||
break
|
||||
|
@ -2929,12 +2928,12 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
return retval
|
||||
|
||||
# 'copy' action
|
||||
def copy(self):
|
||||
def copy(self) -> None:
|
||||
if self.mode in (LINE_MODE, CHAR_MODE):
|
||||
self._set_clipboard_text(Gdk.SELECTION_CLIPBOARD, self.getSelectedText())
|
||||
|
||||
# 'cut' action
|
||||
def cut(self):
|
||||
def cut(self) -> None:
|
||||
if self.mode in (LINE_MODE, CHAR_MODE):
|
||||
self.copy()
|
||||
self.replaceText('')
|
||||
|
@ -2952,13 +2951,13 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
self.closeUndoBlock()
|
||||
|
||||
# 'paste' action
|
||||
def paste(self):
|
||||
def paste(self) -> None:
|
||||
Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD).request_text(
|
||||
self.receive_clipboard_text_cb,
|
||||
None)
|
||||
|
||||
# 'clear_edits' action
|
||||
def clear_edits(self):
|
||||
def clear_edits(self) -> None:
|
||||
self.setLineMode()
|
||||
self.recordEditMode()
|
||||
f = self.current_pane
|
||||
|
@ -2977,7 +2976,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
self.recordEditMode()
|
||||
|
||||
# 'dismiss_all_edits' action
|
||||
def dismiss_all_edits(self):
|
||||
def dismiss_all_edits(self) -> None:
|
||||
if self.mode in (LINE_MODE, CHAR_MODE):
|
||||
self.bakeEdits(self.current_pane)
|
||||
|
||||
|
@ -3038,7 +3037,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
return False
|
||||
|
||||
# move cursor to a given line
|
||||
def go_to_line(self, i):
|
||||
def go_to_line(self, i: int) -> None:
|
||||
f, idx = self.current_pane, 0
|
||||
if i > 0:
|
||||
# search for a line matching that number
|
||||
|
@ -3057,7 +3056,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
|
||||
# recompute viewport size and redraw as the display preferences may have
|
||||
# changed
|
||||
def prefsUpdated(self):
|
||||
def prefsUpdated(self) -> None:
|
||||
# clear cache as tab width may have changed
|
||||
self.string_width_cache = {}
|
||||
self.setFont(
|
||||
|
@ -3075,12 +3074,12 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
self.diffmap.queue_draw()
|
||||
|
||||
# 'realign_all' action
|
||||
def realign_all(self):
|
||||
def realign_all(self) -> None:
|
||||
self.setLineMode()
|
||||
f = self.current_pane
|
||||
self.recordEditMode()
|
||||
lines = []
|
||||
blocks = []
|
||||
lines: List[List[FileDiffViewerBase.Line]] = []
|
||||
blocks: List[int] = []
|
||||
for pane in self.panes:
|
||||
# create a new list of lines with no spacers
|
||||
newlines = [[line for line in pane.lines if line is not None]]
|
||||
|
@ -3114,7 +3113,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
self.closeUndoBlock()
|
||||
|
||||
# 'isolate' action
|
||||
def isolate(self):
|
||||
def isolate(self) -> None:
|
||||
self.setLineMode()
|
||||
self.recordEditMode()
|
||||
f = self.current_pane
|
||||
|
@ -3157,7 +3156,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
|
||||
# returns True if line 'i' in pane 'f' has an edit or is different from its
|
||||
# neighbour
|
||||
def hasEditsOrDifference(self, f, i):
|
||||
def hasEditsOrDifference(self, f: int, i: int) -> bool:
|
||||
line = self.getLine(f, i)
|
||||
if line is not None and line.is_modified:
|
||||
return True
|
||||
|
@ -3167,7 +3166,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
(f + 1 < len(self.panes) and text != self.getCompareString(f + 1, i)))
|
||||
|
||||
# returns True if there are any differences
|
||||
def hasDifferences(self):
|
||||
def hasDifferences(self) -> bool:
|
||||
n = len(self.panes)
|
||||
nlines = len(self.panes[0].lines)
|
||||
for i in range(nlines):
|
||||
|
@ -3178,13 +3177,13 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
return False
|
||||
|
||||
# scroll the viewport so _pixels at position 'y' are centred
|
||||
def centre_view_about_y(self, y):
|
||||
def centre_view_about_y(self, y: int) -> None:
|
||||
vadj = self.vadj
|
||||
y = min(max(0, y - vadj.get_page_size() / 2), vadj.get_upper() - vadj.get_page_size())
|
||||
vadj.set_value(y)
|
||||
|
||||
# move the cursor from line 'i' to the next difference in direction 'delta'
|
||||
def go_to_difference(self, i, delta):
|
||||
def go_to_difference(self, i: int, delta: int) -> None:
|
||||
f = self.current_pane
|
||||
nlines = len(self.panes[f].lines)
|
||||
# back up to beginning of difference
|
||||
|
@ -3210,31 +3209,31 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
self.setCurrentLine(f, start, i)
|
||||
|
||||
# 'first_difference' action
|
||||
def first_difference(self):
|
||||
def first_difference(self) -> None:
|
||||
self.setLineMode()
|
||||
self.go_to_difference(0, 1)
|
||||
|
||||
# 'previous_difference' action
|
||||
def previous_difference(self):
|
||||
def previous_difference(self) -> None:
|
||||
self.setLineMode()
|
||||
i = min(self.current_line, self.selection_line) - 1
|
||||
self.go_to_difference(i, -1)
|
||||
|
||||
# 'next_difference' action
|
||||
def next_difference(self):
|
||||
def next_difference(self) -> None:
|
||||
self.setLineMode()
|
||||
i = max(self.current_line, self.selection_line) + 1
|
||||
self.go_to_difference(i, 1)
|
||||
|
||||
# 'last_difference' action
|
||||
def last_difference(self):
|
||||
def last_difference(self) -> None:
|
||||
self.setLineMode()
|
||||
i = len(self.panes[self.current_pane].lines)
|
||||
self.go_to_difference(i, -1)
|
||||
|
||||
# Undo for changes to the pane ordering
|
||||
class SwapPanesUndo:
|
||||
def __init__(self, f_dst, f_src):
|
||||
def __init__(self, f_dst: int, f_src: int) -> None:
|
||||
self.data = (f_dst, f_src)
|
||||
|
||||
def undo(self, viewer):
|
||||
|
@ -3246,7 +3245,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
viewer.swapPanes(f_dst, f_src)
|
||||
|
||||
# swap the contents of two panes
|
||||
def swapPanes(self, f_dst, f_src):
|
||||
def swapPanes(self, f_dst: int, f_src: int) -> None:
|
||||
if self.undoblock is not None:
|
||||
self.addUndo(FileDiffViewerBase.SwapPanesUndo(f_dst, f_src))
|
||||
self.current_pane = f_dst
|
||||
|
@ -3267,7 +3266,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
self.emit('swapped_panes', f_dst, f_src)
|
||||
|
||||
# swap the contents of two panes
|
||||
def swap_panes(self, f_dst, f_src):
|
||||
def swap_panes(self, f_dst: int, f_src: int) -> None:
|
||||
if 0 <= f_dst < len(self.panes):
|
||||
if self.mode == ALIGN_MODE:
|
||||
self.setLineMode()
|
||||
|
@ -3282,17 +3281,17 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
self.closeUndoBlock()
|
||||
|
||||
# 'shift_pane_left' action
|
||||
def shift_pane_left(self):
|
||||
def shift_pane_left(self) -> None:
|
||||
f = self.current_pane
|
||||
self.swap_panes(f - 1, f)
|
||||
|
||||
# 'shift_pane_right' action
|
||||
def shift_pane_right(self):
|
||||
def shift_pane_right(self) -> None:
|
||||
f = self.current_pane
|
||||
self.swap_panes(f + 1, f)
|
||||
|
||||
# 'convert_to_upper_case' action
|
||||
def _convert_case(self, to_upper):
|
||||
def _convert_case(self, to_upper: bool) -> None:
|
||||
# find range of characters to operate upon
|
||||
if self.mode == CHAR_MODE:
|
||||
start, end = self.current_line, self.selection_line
|
||||
|
@ -3333,15 +3332,15 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
self.updateText(f, i, s)
|
||||
|
||||
# 'convert_to_upper_case' action
|
||||
def convert_to_upper_case(self):
|
||||
def convert_to_upper_case(self) -> None:
|
||||
self._convert_case(True)
|
||||
|
||||
# 'convert_to_lower_case' action
|
||||
def convert_to_lower_case(self):
|
||||
def convert_to_lower_case(self) -> None:
|
||||
self._convert_case(False)
|
||||
|
||||
# sort lines
|
||||
def _sort_lines(self, descending):
|
||||
def _sort_lines(self, descending: bool) -> None:
|
||||
if self.mode != CHAR_MODE:
|
||||
self.setLineMode()
|
||||
self.recordEditMode()
|
||||
|
@ -3353,7 +3352,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
# get set of lines
|
||||
ss = [self.getLineText(f, i) for i in range(start, end + 1)]
|
||||
# create sorted list, removing any nulls
|
||||
temp = [s for s in ss if s is not None]
|
||||
temp: List[Optional[str]] = [s for s in ss if s is not None]
|
||||
temp.sort()
|
||||
if descending:
|
||||
temp.reverse()
|
||||
|
@ -3369,15 +3368,15 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
self.recordEditMode()
|
||||
|
||||
# 'sort_lines_in_ascending_order' action
|
||||
def sort_lines_in_ascending_order(self):
|
||||
def sort_lines_in_ascending_order(self) -> None:
|
||||
self._sort_lines(False)
|
||||
|
||||
# 'sort_lines_in_descending_order' action
|
||||
def sort_lines_in_descending_order(self):
|
||||
def sort_lines_in_descending_order(self) -> None:
|
||||
self._sort_lines(True)
|
||||
|
||||
# 'remove_trailing_white_space' action
|
||||
def remove_trailing_white_space(self):
|
||||
def remove_trailing_white_space(self) -> None:
|
||||
if self.mode != CHAR_MODE:
|
||||
self.setLineMode()
|
||||
self.recordEditMode()
|
||||
|
@ -3403,7 +3402,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
self.recordEditMode()
|
||||
|
||||
# 'convert_tabs_to_spaces' action
|
||||
def convert_tabs_to_spaces(self):
|
||||
def convert_tabs_to_spaces(self) -> None:
|
||||
# find range of characters to operate upon
|
||||
if self.mode == CHAR_MODE:
|
||||
start, end = self.current_line, self.selection_line
|
||||
|
@ -3456,7 +3455,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
self.recordEditMode()
|
||||
|
||||
# 'convert_leading_spaces_to_tabs' action
|
||||
def convert_leading_spaces_to_tabs(self):
|
||||
def convert_leading_spaces_to_tabs(self) -> None:
|
||||
if self.mode != CHAR_MODE:
|
||||
self.setLineMode()
|
||||
self.recordEditMode()
|
||||
|
@ -3486,7 +3485,7 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
self.recordEditMode()
|
||||
|
||||
# adjust indenting of the selected lines by 'offset' soft tabs
|
||||
def _adjust_indenting(self, offset):
|
||||
def _adjust_indenting(self, offset: int) -> None:
|
||||
if self.mode != CHAR_MODE:
|
||||
self.setLineMode()
|
||||
# find range of lines to operate upon
|
||||
|
@ -3519,14 +3518,14 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
self.recordEditMode()
|
||||
|
||||
# 'increase_indenting' action
|
||||
def increase_indenting(self):
|
||||
def increase_indenting(self) -> None:
|
||||
self._adjust_indenting(1)
|
||||
|
||||
# 'decrease_indenting' action
|
||||
def decrease_indenting(self):
|
||||
def decrease_indenting(self) -> None:
|
||||
self._adjust_indenting(-1)
|
||||
|
||||
def convert_format(self, fmt):
|
||||
def convert_format(self, fmt: LineEnding) -> None:
|
||||
self.setLineMode()
|
||||
self.recordEditMode()
|
||||
f = self.current_pane
|
||||
|
@ -3539,19 +3538,19 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
self.setFormat(f, fmt)
|
||||
|
||||
# 'convert_to_dos' action
|
||||
def convert_to_dos(self):
|
||||
def convert_to_dos(self) -> None:
|
||||
self.convert_format(LineEnding.DOS_FORMAT)
|
||||
|
||||
# 'convert_to_mac' action
|
||||
def convert_to_mac(self):
|
||||
def convert_to_mac(self) -> None:
|
||||
self.convert_format(LineEnding.MAC_FORMAT)
|
||||
|
||||
# 'convert_to_unix' action
|
||||
def convert_to_unix(self):
|
||||
def convert_to_unix(self) -> None:
|
||||
self.convert_format(LineEnding.UNIX_FORMAT)
|
||||
|
||||
# copies the selected range of lines from pane 'f_src' to 'f_dst'
|
||||
def merge_lines(self, f_dst, f_src):
|
||||
def merge_lines(self, f_dst: int, f_src: int) -> None:
|
||||
self.recordEditMode()
|
||||
self.setLineMode()
|
||||
pane = self.panes[f_dst]
|
||||
|
@ -3581,25 +3580,25 @@ class FileDiffViewerBase(Gtk.Grid):
|
|||
self.closeUndoBlock()
|
||||
|
||||
# 'copy_selection_right' action
|
||||
def copy_selection_right(self):
|
||||
def copy_selection_right(self) -> None:
|
||||
f = self.current_pane + 1
|
||||
if 0 < f < len(self.panes):
|
||||
self.merge_lines(f, f - 1)
|
||||
|
||||
# 'copy_selection_left' action
|
||||
def copy_selection_left(self):
|
||||
def copy_selection_left(self) -> None:
|
||||
f = self.current_pane - 1
|
||||
if f >= 0 and f + 1 < len(self.panes):
|
||||
self.merge_lines(f, f + 1)
|
||||
|
||||
# 'copy_left_into_selection' action
|
||||
def copy_left_into_selection(self):
|
||||
def copy_left_into_selection(self) -> None:
|
||||
f = self.current_pane
|
||||
if 0 < f < len(self.panes):
|
||||
self.merge_lines(f, f - 1)
|
||||
|
||||
# 'copy_right_into_selection' action
|
||||
def copy_right_into_selection(self):
|
||||
def copy_right_into_selection(self) -> None:
|
||||
f = self.current_pane
|
||||
if f >= 0 and f + 1 < len(self.panes):
|
||||
self.merge_lines(f, f + 1)
|
||||
|
@ -3740,18 +3739,19 @@ def createMenu(specs, radio=None, accel_group=None):
|
|||
return menu
|
||||
|
||||
|
||||
ALPHANUMERIC_CLASS = 0
|
||||
WHITESPACE_CLASS = 1
|
||||
OTHER_CLASS = 2
|
||||
class CharacterClass(IntFlag):
|
||||
ALPHANUMERIC = 0
|
||||
WHITESPACE = 1
|
||||
OTHER = 2
|
||||
|
||||
|
||||
# maps similar types of characters to a group
|
||||
def _get_character_class(c):
|
||||
def _get_character_class(c: str) -> CharacterClass:
|
||||
if c.isalnum() or c == '_':
|
||||
return ALPHANUMERIC_CLASS
|
||||
return CharacterClass.ALPHANUMERIC
|
||||
if c.isspace():
|
||||
return WHITESPACE_CLASS
|
||||
return OTHER_CLASS
|
||||
return CharacterClass.WHITESPACE
|
||||
return CharacterClass.OTHER
|
||||
|
||||
|
||||
# patience diff with difflib-style fallback
|
||||
|
@ -3966,36 +3966,36 @@ def _lcs_approx(a, b):
|
|||
|
||||
|
||||
# True if the string ends with '\r\n'
|
||||
def _has_dos_line_ending(s):
|
||||
def _has_dos_line_ending(s: str) -> bool:
|
||||
return s.endswith('\r\n')
|
||||
|
||||
|
||||
# True if the string ends with '\r'
|
||||
def _has_mac_line_ending(s):
|
||||
def _has_mac_line_ending(s: str) -> bool:
|
||||
return s.endswith('\r')
|
||||
|
||||
|
||||
# True if the string ends with '\n' but not '\r\n'
|
||||
def _has_unix_line_ending(s):
|
||||
def _has_unix_line_ending(s: str) -> bool:
|
||||
return s.endswith('\n') and not s.endswith('\r\n')
|
||||
|
||||
|
||||
# returns the format mask for a list of strings
|
||||
def _get_format(ss):
|
||||
flags = 0
|
||||
for s in ss:
|
||||
if s is not None:
|
||||
if _has_dos_line_ending(s):
|
||||
def _get_format(lines: List[Optional[str]]) -> LineEnding:
|
||||
flags: LineEnding = LineEnding.NO_FORMAT
|
||||
for line in lines:
|
||||
if line is not None:
|
||||
if _has_dos_line_ending(line):
|
||||
flags |= LineEnding.DOS_FORMAT
|
||||
elif _has_mac_line_ending(s):
|
||||
elif _has_mac_line_ending(line):
|
||||
flags |= LineEnding.MAC_FORMAT
|
||||
elif _has_unix_line_ending(s):
|
||||
elif _has_unix_line_ending(line):
|
||||
flags |= LineEnding.UNIX_FORMAT
|
||||
return flags
|
||||
|
||||
|
||||
# convenience method to change the line ending of a string
|
||||
def _convert_to_format(s, fmt):
|
||||
def _convert_to_format(s: Optional[str], fmt: LineEnding) -> Optional[str]:
|
||||
if s is not None and fmt != 0:
|
||||
old_format = _get_format([s])
|
||||
if old_format != 0 and (old_format & fmt) == 0:
|
||||
|
@ -4025,14 +4025,14 @@ def _convert_to_format(s, fmt):
|
|||
# in this array so 'blocks' will be an empty array when there are no lines. A
|
||||
# 'cut' at location 'i' means a line 'i-1' and line 'i' belong to different
|
||||
# sections
|
||||
def _create_block(n):
|
||||
def _create_block(n: int) -> List[int]:
|
||||
if n > 0:
|
||||
return [n]
|
||||
return []
|
||||
|
||||
|
||||
# returns the two sets of blocks after cutting at 'i'
|
||||
def _cut_blocks(i, blocks):
|
||||
def _cut_blocks(i: int, blocks: List[int]) -> Tuple[List[int], List[int]]:
|
||||
pre, post, nlines = [], [], 0
|
||||
for b in blocks:
|
||||
if nlines >= i:
|
||||
|
@ -4048,7 +4048,7 @@ def _cut_blocks(i, blocks):
|
|||
|
||||
|
||||
# returns a set of blocks containing all of the cuts in the inputs
|
||||
def _merge_blocks(leftblocks, rightblocks):
|
||||
def _merge_blocks(leftblocks: List[int], rightblocks: List[int]) -> List[int]:
|
||||
leftblocks, rightblocks, b = leftblocks[:], rightblocks[:], []
|
||||
while len(leftblocks) > 0:
|
||||
nleft, nright = leftblocks[0], rightblocks[0]
|
||||
|
@ -4122,14 +4122,14 @@ def _remove_null_lines(blocks, lines_set):
|
|||
|
||||
|
||||
# returns true if the string only contains whitespace characters
|
||||
def _is_blank(s):
|
||||
def _is_blank(s: str) -> bool:
|
||||
for c in utils.whitespace:
|
||||
s = s.replace(c, '')
|
||||
return len(s) == 0
|
||||
|
||||
|
||||
# use Pango.SCALE instead of Pango.PIXELS to avoid overflow exception
|
||||
def _pixels(size):
|
||||
def _pixels(size: int) -> int:
|
||||
return int(size / Pango.SCALE + 0.5)
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue