Merge pull request #132 from MightyCreak/remove-lasting-lint-errors

Remove lasting lint errors
This commit is contained in:
Creak 2021-11-24 20:44:18 -05:00 committed by GitHub
commit 4ed02b2281
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 364 additions and 217 deletions

View File

@ -2,6 +2,3 @@
builtins = _ builtins = _
max-line-length = 100 max-line-length = 100
show-source = true show-source = true
# Temporary
exclude = src/diffuse/main.py

View File

@ -18,34 +18,38 @@ jobs:
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: actions/setup-python@v2 - uses: actions/setup-python@v2
- run: sudo apt install libgirepository1.0-dev
- run: pip install -r requirements.txt
- name: Flake8
run: flake8 src/ po/
- name: MyPy
run: mypy src/ po/
meson-build-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- name: Install dependencies - name: Install dependencies
run: sudo apt-get -y install appstream appstream-util desktop-file-utils gettext run: |
sudo apt-get -y install libgirepository1.0-dev appstream appstream-util desktop-file-utils gettext
pip install -r requirements.dev.txt
- name: Meson build - name: Meson build
uses: BSFishy/meson-build@v1.0.3 uses: BSFishy/meson-build@v1.0.3
with: with:
action: build action: build
setup-options: --prefix=/tmp/diffuse
- name: Meson test - name: Meson test
uses: BSFishy/meson-build@v1.0.3 uses: BSFishy/meson-build@v1.0.3
with: with:
action: test action: test
- name: Meson install
uses: BSFishy/meson-build@v1.0.3
with:
action: install
- name: Flake8
run: |
flake8 /tmp/diffuse/
flake8 po/
- name: MyPy
run: |
mypy /tmp/diffuse/
mypy po/
flatpak-build-test: flatpak-build-test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: container:

View File

@ -16,6 +16,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
io.github.mightycreak.Diffuse.appdata.xml.in io.github.mightycreak.Diffuse.appdata.xml.in
- Leaner README.md - Leaner README.md
- Moved the documentation to docs/ - Moved the documentation to docs/
- In the CI, call the linters on the installed directory
### Fixed
- Removed the lasting lint errors (i.e. in main.py)
## 0.7.3 - 2021-11-22 ## 0.7.3 - 2021-11-22
@ -23,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added linters (flake8 and mypy) and fixed some errors - Added linters (flake8 and mypy) and fixed some errors
- Added lint jobs for both in the CI - Added lint jobs for both in the CI
- Added a flatpak job in the CI - Added a flatpak job in the CI
- Created a requirements.dev.txt just for the developers
### Changed ### Changed
- main.py slimmed down by about 5000 lines - main.py slimmed down by about 5000 lines

View File

@ -2,4 +2,4 @@
# #
# Copyright (C) 2006-2009 Derrick Moser <derrick_moser@yahoo.com> # Copyright (C) 2006-2009 Derrick Moser <derrick_moser@yahoo.com>
import @pkgdatadir@/syntax/*.syntax import @PKGDATADIR@/syntax/*.syntax

View File

@ -33,7 +33,7 @@ endif
# Diffuse config file # Diffuse config file
conf = configuration_data() conf = configuration_data()
conf.set('pkgdatadir', pkgdatadir) conf.set('PKGDATADIR', pkgdatadir)
configure_file( configure_file(
input: 'diffuserc.in', input: 'diffuserc.in',

View File

@ -2,11 +2,17 @@
## Requirements ## Requirements
Diffuse is implemented in Python and should run on any platform with Python and To install the requirements just to execute the binary, run:
PyGObject.
* Python >= 3.4 ```sh
* PyGObject >= 3.18 pip install -r requirements.txt
```
For developer tools, run this one instead (it includes requirements.txt):
```sh
pip install -r requirements.dev.txt
```
## Setup on Linux ## Setup on Linux

4
requirements.dev.txt Normal file
View File

@ -0,0 +1,4 @@
-r requirements.txt
flake8 ~= 3.8
flake8-noqa ~= 1.2
mypy ~= 0.910

View File

@ -1,3 +1 @@
flake8 ~= 3.8
mypy ~= 0.910
PyGObject ~= 3.40 PyGObject ~= 3.40

View File

@ -20,11 +20,11 @@
APP_NAME = 'Diffuse' APP_NAME = 'Diffuse'
VERSION = '@VERSION@' VERSION = '@VERSION@'
COPYRIGHT = '''{copyright} © 2006-2019 Derrick Moser COPYRIGHT = '''{copyright} © 2006-2019 Derrick Moser
{copyright} © 2015-2021 Romain Failliot'''.format(copyright=_("Copyright")) {copyright} © 2015-2021 Romain Failliot'''.format(copyright=_("Copyright")) # type: ignore
WEBSITE = 'https://mightycreak.github.io/diffuse/' WEBSITE = 'https://mightycreak.github.io/diffuse/'
sysconfigdir = '@sysconfigdir@' SYSCONFIGDIR = '@SYSCONFIGDIR@'
use_flatpak = @use_flatpak@ LOG_PRINT_OUTPUT = @LOG_PRINT_OUTPUT@
log_print_output = @log_print_output@ LOG_PRINT_STACK = @LOG_PRINT_STACK@
log_print_stack = @log_print_stack@ USE_FLATPAK = @USE_FLATPAK@

View File

@ -19,7 +19,7 @@
import os import os
from diffuse import constants # type: ignore from diffuse import constants
from diffuse import utils from diffuse import utils
import gi # type: ignore import gi # type: ignore

View File

@ -22,11 +22,8 @@
import sys import sys
import gettext import gettext
PKGDATADIR = '@pkgdatadir@' sys.path.insert(1, '@PKGDATADIR@')
LOCALEDIR = '@localedir@' gettext.install('diffuse', '@LOCALEDIR@')
sys.path.insert(1, PKGDATADIR)
gettext.install('diffuse', LOCALEDIR)
if __name__ == '__main__': if __name__ == '__main__':
from diffuse import main from diffuse import main

View File

@ -27,7 +27,7 @@ import webbrowser
from urllib.parse import urlparse from urllib.parse import urlparse
from diffuse import constants # type: ignore from diffuse import constants
from diffuse import utils from diffuse import utils
from diffuse.dialogs import AboutDialog, FileChooserDialog, NumericDialog, SearchDialog from diffuse.dialogs import AboutDialog, FileChooserDialog, NumericDialog, SearchDialog
from diffuse.preferences import Preferences from diffuse.preferences import Preferences
@ -43,11 +43,12 @@ gi.require_version('Gdk', '3.0')
gi.require_version('GdkPixbuf', '2.0') gi.require_version('GdkPixbuf', '2.0')
gi.require_version('Pango', '1.0') gi.require_version('Pango', '1.0')
gi.require_version('PangoCairo', '1.0') gi.require_version('PangoCairo', '1.0')
from gi.repository import GObject, Gtk, Gdk, GdkPixbuf, Pango, PangoCairo # type: ignore # noqa: E402 from gi.repository import GObject, Gtk, Gdk, GdkPixbuf, Pango # type: ignore # noqa: E402
theVCSs = VcsRegistry() theVCSs = VcsRegistry()
# widget classed to create notebook tabs with labels and a close button # widget classed to create notebook tabs with labels and a close button
# use notebooktab.button.connect() to be notified when the button is pressed # use notebooktab.button.connect() to be notified when the button is pressed
# make this a Gtk.EventBox so signals can be connected for MMB and RMB button # make this a Gtk.EventBox so signals can be connected for MMB and RMB button
@ -86,6 +87,7 @@ class NotebookTab(Gtk.EventBox):
def set_text(self, s): def set_text(self, s):
self.label.set_text(s) self.label.set_text(s)
# contains information about a file # contains information about a file
class FileInfo: class FileInfo:
def __init__(self, name=None, encoding=None, vcs=None, revision=None, label=None): def __init__(self, name=None, encoding=None, vcs=None, revision=None, label=None):
@ -106,6 +108,7 @@ class FileInfo:
# to warn about changes to file on disk # to warn about changes to file on disk
self.last_stat = None self.last_stat = None
# the main application class containing a set of file viewers # the main application class containing a set of file viewers
# this class displays tab for switching between viewers and dispatches menu # this class displays tab for switching between viewers and dispatches menu
# commands to the current viewer # commands to the current viewer
@ -115,12 +118,12 @@ class Diffuse(Gtk.Window):
# pane header # pane header
class PaneHeader(Gtk.Box): class PaneHeader(Gtk.Box):
def __init__(self): def __init__(self):
Gtk.Box.__init__(self, orientation = Gtk.Orientation.HORIZONTAL, spacing = 0) Gtk.Box.__init__(self, orientation=Gtk.Orientation.HORIZONTAL, spacing=0)
_append_buttons(self, Gtk.IconSize.MENU, [ _append_buttons(self, Gtk.IconSize.MENU, [
[Gtk.STOCK_OPEN, self.button_cb, 'open', _('Open File...')], [Gtk.STOCK_OPEN, self.button_cb, 'open', _('Open File...')],
[Gtk.STOCK_REFRESH, self.button_cb, 'reload', _('Reload File')], [Gtk.STOCK_REFRESH, self.button_cb, 'reload', _('Reload File')],
[Gtk.STOCK_SAVE, self.button_cb, 'save', _('Save File')], [Gtk.STOCK_SAVE, self.button_cb, 'save', _('Save File')],
[Gtk.STOCK_SAVE_AS, self.button_cb, 'save_as', _('Save File As...') ]]) [Gtk.STOCK_SAVE_AS, self.button_cb, 'save_as', _('Save File As...')]])
self.label = label = Gtk.Label.new() self.label = label = Gtk.Label.new()
label.set_selectable(True) label.set_selectable(True)
@ -168,7 +171,7 @@ class Diffuse(Gtk.Window):
# pane footer # pane footer
class PaneFooter(Gtk.Box): class PaneFooter(Gtk.Box):
def __init__(self): def __init__(self):
Gtk.Box.__init__(self, orientation = Gtk.Orientation.HORIZONTAL, spacing = 0) Gtk.Box.__init__(self, orientation=Gtk.Orientation.HORIZONTAL, spacing=0)
self.cursor = label = Gtk.Label.new() self.cursor = label = Gtk.Label.new()
self.cursor.set_size_request(-1, -1) self.cursor.set_size_request(-1, -1)
self.pack_start(label, False, False, 0) self.pack_start(label, False, False, 0)
@ -194,12 +197,12 @@ class Diffuse(Gtk.Window):
# set the cursor label # set the cursor label
def updateCursor(self, viewer, f): def updateCursor(self, viewer, f):
if viewer.mode == CHAR_MODE and viewer.current_pane == f: if viewer.mode == CHAR_MODE and viewer.current_pane == f:
## TODO: Find a fix for the column bug (resizing issue when editing a line) # # TODO: Find a fix for the column bug (resizing issue when editing a line)
#j = viewer.current_char # j = viewer.current_char
#if j > 0: # if j > 0:
# text = viewer.getLineText(viewer.current_pane, viewer.current_line)[:j] # text = viewer.getLineText(viewer.current_pane, viewer.current_line)[:j]
# j = viewer.stringWidth(text) # j = viewer.stringWidth(text)
#s = _('Column %d') % (j, ) # s = _('Column %d') % (j, )
s = '' s = ''
else: else:
s = '' s = ''
@ -255,7 +258,11 @@ class Diffuse(Gtk.Window):
self.connect('format-changed', self.format_changed_cb) self.connect('format-changed', self.format_changed_cb)
for i, darea in enumerate(self.dareas): for i, darea in enumerate(self.dareas):
darea.drag_dest_set(Gtk.DestDefaults.ALL, [Gtk.TargetEntry.new('text/uri-list', 0, 0)], Gdk.DragAction.COPY) darea.drag_dest_set(
Gtk.DestDefaults.ALL,
[Gtk.TargetEntry.new('text/uri-list', 0, 0)],
Gdk.DragAction.COPY
)
darea.connect('drag-data-received', self.drag_data_received_cb, i) darea.connect('drag-data-received', self.drag_data_received_cb, i)
# initialise status # initialise status
self.updateStatus() self.updateStatus()
@ -265,7 +272,12 @@ class Diffuse(Gtk.Window):
def loadFromInfo(self, f, info): def loadFromInfo(self, f, info):
if self.headers[f].has_edits: if self.headers[f].has_edits:
# warn users of any unsaved changes they might lose # warn users of any unsaved changes they might lose
dialog = Gtk.MessageDialog(self.get_toplevel(), Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.WARNING, Gtk.ButtonsType.NONE, _('Save changes before loading the new file?')) dialog = Gtk.MessageDialog(
self.get_toplevel(),
Gtk.DialogFlags.DESTROY_WITH_PARENT,
Gtk.MessageType.WARNING,
Gtk.ButtonsType.NONE, _('Save changes before loading the new file?')
)
dialog.set_title(constants.APP_NAME) dialog.set_title(constants.APP_NAME)
dialog.add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL) dialog.add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL)
dialog.add_button(Gtk.STOCK_NO, Gtk.ResponseType.REJECT) dialog.add_button(Gtk.STOCK_NO, Gtk.ResponseType.REJECT)
@ -374,7 +386,9 @@ class Diffuse(Gtk.Window):
except (IOError, OSError, UnicodeDecodeError, LookupError): except (IOError, OSError, UnicodeDecodeError, LookupError):
# FIXME: this can occur before the toplevel window is drawn # FIXME: this can occur before the toplevel window is drawn
if rev is not None: if rev is not None:
msg = _('Error reading revision %(rev)s of %(file)s.') % { 'rev': rev, 'file': name } msg = _(
'Error reading revision %(rev)s of %(file)s.'
) % {'rev': rev, 'file': name}
else: else:
msg = _('Error reading %s.') % (name, ) msg = _('Error reading %s.') % (name, )
utils.logErrorAndDialog(msg, self.get_toplevel()) utils.logErrorAndDialog(msg, self.get_toplevel())
@ -397,7 +411,14 @@ class Diffuse(Gtk.Window):
if not reload: if not reload:
# we need to ask for a file name if we are not reloading the # we need to ask for a file name if we are not reloading the
# existing file # existing file
dialog = FileChooserDialog(_('Open File'), self.get_toplevel(), self.prefs, Gtk.FileChooserAction.OPEN, Gtk.STOCK_OPEN, True) dialog = FileChooserDialog(
_('Open File'),
self.get_toplevel(),
self.prefs,
Gtk.FileChooserAction.OPEN,
Gtk.STOCK_OPEN,
True
)
if info.name is not None: if info.name is not None:
dialog.set_filename(os.path.realpath(info.name)) dialog.set_filename(os.path.realpath(info.name))
dialog.set_encoding(info.encoding) dialog.set_encoding(info.encoding)
@ -447,8 +468,14 @@ class Diffuse(Gtk.Window):
s = info.label s = info.label
else: else:
s = info.name s = info.name
msg = _('The file %s changed on disk. Do you want to reload the file?') % (s, ) msg = _(
dialog = utils.MessageDialog(self.get_toplevel(), Gtk.MessageType.QUESTION, msg) 'The file %s changed on disk. Do you want to reload the file?'
) % (s, )
dialog = utils.MessageDialog(
self.get_toplevel(),
Gtk.MessageType.QUESTION,
msg
)
ok = (dialog.run() == Gtk.ResponseType.OK) ok = (dialog.run() == Gtk.ResponseType.OK)
dialog.destroy() dialog.destroy()
if ok: if ok:
@ -467,7 +494,13 @@ class Diffuse(Gtk.Window):
save_as = True save_as = True
if save_as: if save_as:
# prompt for a file name # prompt for a file name
dialog = FileChooserDialog(_('Save %(title)s Pane %(pane)d') % { 'title': self.title, 'pane': f + 1 }, self.get_toplevel(), self.prefs, Gtk.FileChooserAction.SAVE, Gtk.STOCK_SAVE) dialog = FileChooserDialog(
_('Save %(title)s Pane %(pane)d') % {'title': self.title, 'pane': f + 1},
self.get_toplevel(),
self.prefs,
Gtk.FileChooserAction.SAVE,
Gtk.STOCK_SAVE
)
if name is not None: if name is not None:
dialog.set_filename(os.path.abspath(name)) dialog.set_filename(os.path.abspath(name))
if encoding is None: if encoding is None:
@ -493,12 +526,17 @@ class Diffuse(Gtk.Window):
# warn if we are about to overwrite an existing file # warn if we are about to overwrite an existing file
if save_as: if save_as:
if os.path.exists(name): if os.path.exists(name):
msg = _('A file named %s already exists. Do you want to overwrite it?') % (name, ) msg = _(
'A file named %s already exists. Do you want to overwrite it?'
) % (name, )
# warn if we are about to overwrite a file that has changed # warn if we are about to overwrite a file that has changed
# since we last read it # since we last read it
elif info.stat is not None: elif info.stat is not None:
if info.stat[stat.ST_MTIME] < os.stat(name)[stat.ST_MTIME]: if info.stat[stat.ST_MTIME] < os.stat(name)[stat.ST_MTIME]:
msg = _('The file %s has been modified by another process since reading it. If you save, all the external changes could be lost. Save anyways?') % (name, ) msg = _(
'The file %s has been modified by another process since reading it. '
'If you save, all the external changes could be lost. Save anyways?'
) % (name, )
if msg is not None: if msg is not None:
dialog = utils.MessageDialog(self.get_toplevel(), Gtk.MessageType.QUESTION, msg) dialog = utils.MessageDialog(self.get_toplevel(), Gtk.MessageType.QUESTION, msg)
end = (dialog.run() != Gtk.ResponseType.OK) end = (dialog.run() != Gtk.ResponseType.OK)
@ -537,7 +575,10 @@ class Diffuse(Gtk.Window):
self.setSyntax(syntax) self.setSyntax(syntax)
return True return True
except (UnicodeEncodeError, LookupError): except (UnicodeEncodeError, LookupError):
utils.logErrorAndDialog(_('Error encoding to %s.') % (encoding, ), self.get_toplevel()) utils.logErrorAndDialog(
_('Error encoding to %s.') % (encoding, ),
self.get_toplevel()
)
except IOError: except IOError:
utils.logErrorAndDialog(_('Error writing %s.') % (name, ), self.get_toplevel()) utils.logErrorAndDialog(_('Error writing %s.') % (name, ), self.get_toplevel())
return False return False
@ -567,7 +608,14 @@ class Diffuse(Gtk.Window):
# callback for go to line menu item # callback for go to line menu item
def go_to_line_cb(self, widget, data): def go_to_line_cb(self, widget, data):
parent = self.get_toplevel() parent = self.get_toplevel()
dialog = NumericDialog(parent, _('Go To Line...'), _('Line Number: '), 1, 1, self.panes[self.current_pane].max_line_number + 1) dialog = NumericDialog(
parent,
_('Go To Line...'),
_('Line Number: '),
val=1,
lower=1,
step=self.panes[self.current_pane].max_line_number + 1
)
okay = (dialog.run() == Gtk.ResponseType.ACCEPT) okay = (dialog.run() == Gtk.ResponseType.ACCEPT)
i = dialog.button.get_value_as_int() i = dialog.button.get_value_as_int()
dialog.destroy() dialog.destroy()
@ -593,11 +641,17 @@ class Diffuse(Gtk.Window):
# update the viewer's current status message # update the viewer's current status message
def updateStatus(self): def updateStatus(self):
if self.mode == LINE_MODE: if self.mode == LINE_MODE:
s = _('Press the enter key or double click to edit. Press the space bar or use the RMB menu to manually align.') s = _(
'Press the enter key or double click to edit. Press the space bar or use the '
'RMB menu to manually align.'
)
elif self.mode == CHAR_MODE: elif self.mode == CHAR_MODE:
s = _('Press the escape key to finish editing.') s = _('Press the escape key to finish editing.')
elif self.mode == ALIGN_MODE: elif self.mode == ALIGN_MODE:
s = _('Select target line and press the space bar to align. Press the escape key to cancel.') s = _(
'Select target line and press the space bar to align. Press the escape key to '
'cancel.'
)
else: else:
s = None s = None
self.status = s self.status = s
@ -617,7 +671,7 @@ class Diffuse(Gtk.Window):
self.footers[f].setFormat(fmt) self.footers[f].setFormat(fmt)
def __init__(self, rc_dir): def __init__(self, rc_dir):
Gtk.Window.__init__(self, type = Gtk.WindowType.TOPLEVEL) Gtk.Window.__init__(self, type=Gtk.WindowType.TOPLEVEL)
self.prefs = Preferences(os.path.join(rc_dir, 'prefs')) self.prefs = Preferences(os.path.join(rc_dir, 'prefs'))
# number of created viewers (used to label some tabs) # number of created viewers (used to label some tabs)
@ -627,10 +681,20 @@ class Diffuse(Gtk.Window):
monitor_geometry = Gdk.Display.get_default().get_monitor(0).get_geometry() monitor_geometry = Gdk.Display.get_default().get_monitor(0).get_geometry()
# state information that should persist across sessions # state information that should persist across sessions
self.bool_state = { 'window_maximized': False, 'search_matchcase': False, 'search_backwards': False } self.bool_state = {
self.int_state = { 'window_width': 1024, 'window_height': 768 } 'window_maximized': False,
self.int_state['window_x'] = max(0, (monitor_geometry.width - self.int_state['window_width']) / 2) 'search_matchcase': False,
self.int_state['window_y'] = max(0, (monitor_geometry.height - self.int_state['window_height']) / 2) 'search_backwards': False
}
self.int_state = {'window_width': 1024, 'window_height': 768}
self.int_state['window_x'] = max(
0,
(monitor_geometry.width - self.int_state['window_width']) / 2
)
self.int_state['window_y'] = max(
0,
(monitor_geometry.height - self.int_state['window_height']) / 2
)
self.connect('configure-event', self.configure_cb) self.connect('configure-event', self.configure_cb)
self.connect('window-state-event', self.window_state_cb) self.connect('window-state-event', self.window_state_cb)
@ -708,10 +772,10 @@ class Diffuse(Gtk.Window):
factory.add_default() factory.add_default()
menuspecs = [] menuspecs = []
menuspecs.append([ _('_File'), [ menuspecs.append([_('_File'), [
[_('_Open File...'), self.open_file_cb, None, Gtk.STOCK_OPEN, 'open_file'], [_('_Open File...'), self.open_file_cb, None, Gtk.STOCK_OPEN, 'open_file'],
[_('Open File In New _Tab...'), self.open_file_in_new_tab_cb, None, None, 'open_file_in_new_tab'], [_('Open File In New _Tab...'), self.open_file_in_new_tab_cb, None, None, 'open_file_in_new_tab'], # noqa: E501
[_('Open _Modified Files...'), self.open_modified_files_cb, None, None, 'open_modified_files'], [_('Open _Modified Files...'), self.open_modified_files_cb, None, None, 'open_modified_files'], # noqa: E501
[_('Open Commi_t...'), self.open_commit_cb, None, None, 'open_commit'], [_('Open Commi_t...'), self.open_commit_cb, None, None, 'open_commit'],
[_('_Reload File'), self.reload_file_cb, None, Gtk.STOCK_REFRESH, 'reload_file'], [_('_Reload File'), self.reload_file_cb, None, Gtk.STOCK_REFRESH, 'reload_file'],
[], [],
@ -719,15 +783,16 @@ class Diffuse(Gtk.Window):
[_('Save File _As...'), self.save_file_as_cb, None, Gtk.STOCK_SAVE_AS, 'save_file_as'], [_('Save File _As...'), self.save_file_as_cb, None, Gtk.STOCK_SAVE_AS, 'save_file_as'],
[_('Save A_ll'), self.save_all_cb, None, None, 'save_all'], [_('Save A_ll'), self.save_all_cb, None, None, 'save_all'],
[], [],
[_('New _2-Way File Merge'), self.new_2_way_file_merge_cb, None, DIFFUSE_STOCK_NEW_2WAY_MERGE, 'new_2_way_file_merge'], [_('New _2-Way File Merge'), self.new_2_way_file_merge_cb, None, DIFFUSE_STOCK_NEW_2WAY_MERGE, 'new_2_way_file_merge'], # noqa: E501
[_('New _3-Way File Merge'), self.new_3_way_file_merge_cb, None, DIFFUSE_STOCK_NEW_3WAY_MERGE, 'new_3_way_file_merge'], [_('New _3-Way File Merge'), self.new_3_way_file_merge_cb, None, DIFFUSE_STOCK_NEW_3WAY_MERGE, 'new_3_way_file_merge'], # noqa: E501
[_('New _N-Way File Merge...'), self.new_n_way_file_merge_cb, None, None, 'new_n_way_file_merge'], [_('New _N-Way File Merge...'), self.new_n_way_file_merge_cb, None, None, 'new_n_way_file_merge'], # noqa: E501
[], [],
[_('_Close Tab'), self.close_tab_cb, None, Gtk.STOCK_CLOSE, 'close_tab'], [_('_Close Tab'), self.close_tab_cb, None, Gtk.STOCK_CLOSE, 'close_tab'],
[_('_Undo Close Tab'), self.undo_close_tab_cb, None, None, 'undo_close_tab'], [_('_Undo Close Tab'), self.undo_close_tab_cb, None, None, 'undo_close_tab'],
[_('_Quit'), self.quit_cb, None, Gtk.STOCK_QUIT, 'quit'] ] ]) [_('_Quit'), self.quit_cb, None, Gtk.STOCK_QUIT, 'quit']
]])
menuspecs.append([ _('_Edit'), [ menuspecs.append([_('_Edit'), [
[_('_Undo'), self.button_cb, 'undo', Gtk.STOCK_UNDO, 'undo'], [_('_Undo'), self.button_cb, 'undo', Gtk.STOCK_UNDO, 'undo'],
[_('_Redo'), self.button_cb, 'redo', Gtk.STOCK_REDO, 'redo'], [_('_Redo'), self.button_cb, 'redo', Gtk.STOCK_REDO, 'redo'],
[], [],
@ -737,33 +802,45 @@ class Diffuse(Gtk.Window):
[], [],
[_('Select _All'), self.button_cb, 'select_all', None, 'select_all'], [_('Select _All'), self.button_cb, 'select_all', None, 'select_all'],
[_('C_lear Edits'), self.button_cb, 'clear_edits', Gtk.STOCK_CLEAR, 'clear_edits'], [_('C_lear Edits'), self.button_cb, 'clear_edits', Gtk.STOCK_CLEAR, 'clear_edits'],
[_('_Dismiss All Edits'), self.button_cb, 'dismiss_all_edits', None, 'dismiss_all_edits'], [_('_Dismiss All Edits'), self.button_cb, 'dismiss_all_edits', None, 'dismiss_all_edits'], # noqa: E501
[], [],
[_('_Find...'), self.find_cb, None, Gtk.STOCK_FIND, 'find'], [_('_Find...'), self.find_cb, None, Gtk.STOCK_FIND, 'find'],
[_('Find _Next'), self.find_next_cb, None, None, 'find_next'], [_('Find _Next'), self.find_next_cb, None, None, 'find_next'],
[_('Find Pre_vious'), self.find_previous_cb, None, None, 'find_previous'], [_('Find Pre_vious'), self.find_previous_cb, None, None, 'find_previous'],
[_('_Go To Line...'), self.go_to_line_cb, None, Gtk.STOCK_JUMP_TO, 'go_to_line'], [_('_Go To Line...'), self.go_to_line_cb, None, Gtk.STOCK_JUMP_TO, 'go_to_line'],
[], [],
[_('Pr_eferences...'), self.preferences_cb, None, Gtk.STOCK_PREFERENCES, 'preferences'] ] ]) [_('Pr_eferences...'), self.preferences_cb, None, Gtk.STOCK_PREFERENCES, 'preferences']
]])
submenudef = [[_('None'), self.syntax_cb, None, None, 'no_syntax_highlighting', True, None, ('syntax', None) ]] submenudef = [
[_('None'), self.syntax_cb, None, None, 'no_syntax_highlighting', True, None, ('syntax', None)] # noqa: E501
]
names = theResources.getSyntaxNames() names = theResources.getSyntaxNames()
if len(names) > 0: if len(names) > 0:
submenudef.append([]) submenudef.append([])
names.sort(key=str.lower) names.sort(key=str.lower)
for name in names: for name in names:
submenudef.append([name, self.syntax_cb, name, None, 'syntax_highlighting_' + name, True, None, ('syntax', name) ]) submenudef.append([
name,
self.syntax_cb,
name,
None,
'syntax_highlighting_' + name,
True,
None,
('syntax', name)
])
menuspecs.append([ _('_View'), [ menuspecs.append([_('_View'), [
[_('_Syntax Highlighting'), None, None, None, None, True, submenudef], [_('_Syntax Highlighting'), None, None, None, None, True, submenudef],
[], [],
[_('Re_align All'), self.button_cb, 'realign_all', Gtk.STOCK_EXECUTE, 'realign_all'], [_('Re_align All'), self.button_cb, 'realign_all', Gtk.STOCK_EXECUTE, 'realign_all'],
[_('_Isolate'), self.button_cb, 'isolate', None, 'isolate'], [_('_Isolate'), self.button_cb, 'isolate', None, 'isolate'],
[], [],
[_('_First Difference'), self.button_cb, 'first_difference', Gtk.STOCK_GOTO_TOP, 'first_difference'], [_('_First Difference'), self.button_cb, 'first_difference', Gtk.STOCK_GOTO_TOP, 'first_difference'], # noqa: E501
[_('_Previous Difference'), self.button_cb, 'previous_difference', Gtk.STOCK_GO_UP, 'previous_difference'], [_('_Previous Difference'), self.button_cb, 'previous_difference', Gtk.STOCK_GO_UP, 'previous_difference'], # noqa: E501
[_('_Next Difference'), self.button_cb, 'next_difference', Gtk.STOCK_GO_DOWN, 'next_difference'], [_('_Next Difference'), self.button_cb, 'next_difference', Gtk.STOCK_GO_DOWN, 'next_difference'], # noqa: E501
[_('_Last Difference'), self.button_cb, 'last_difference', Gtk.STOCK_GOTO_BOTTOM, 'last_difference'], [_('_Last Difference'), self.button_cb, 'last_difference', Gtk.STOCK_GOTO_BOTTOM, 'last_difference'], # noqa: E501
[], [],
[_('Fir_st Tab'), self.first_tab_cb, None, None, 'first_tab'], [_('Fir_st Tab'), self.first_tab_cb, None, None, 'first_tab'],
[_('Pre_vious Tab'), self.previous_tab_cb, None, None, 'previous_tab'], [_('Pre_vious Tab'), self.previous_tab_cb, None, None, 'previous_tab'],
@ -771,39 +848,43 @@ class Diffuse(Gtk.Window):
[_('Las_t Tab'), self.last_tab_cb, None, None, 'last_tab'], [_('Las_t Tab'), self.last_tab_cb, None, None, 'last_tab'],
[], [],
[_('Shift Pane _Right'), self.button_cb, 'shift_pane_right', None, 'shift_pane_right'], [_('Shift Pane _Right'), self.button_cb, 'shift_pane_right', None, 'shift_pane_right'],
[_('Shift Pane _Left'), self.button_cb, 'shift_pane_left', None, 'shift_pane_left'] ] ]) [_('Shift Pane _Left'), self.button_cb, 'shift_pane_left', None, 'shift_pane_left']
]])
menuspecs.append([ _('F_ormat'), [ menuspecs.append([_('F_ormat'), [
[_('Convert To _Upper Case'), self.button_cb, 'convert_to_upper_case', None, 'convert_to_upper_case'], [_('Convert To _Upper Case'), self.button_cb, 'convert_to_upper_case', None, 'convert_to_upper_case'], # noqa: E501
[_('Convert To _Lower Case'), self.button_cb, 'convert_to_lower_case', None, 'convert_to_lower_case'], [_('Convert To _Lower Case'), self.button_cb, 'convert_to_lower_case', None, 'convert_to_lower_case'], # noqa: E501
[], [],
[_('Sort Lines In _Ascending Order'), self.button_cb, 'sort_lines_in_ascending_order', Gtk.STOCK_SORT_ASCENDING, 'sort_lines_in_ascending_order'], [_('Sort Lines In _Ascending Order'), self.button_cb, 'sort_lines_in_ascending_order', Gtk.STOCK_SORT_ASCENDING, 'sort_lines_in_ascending_order'], # noqa: E501
[_('Sort Lines In D_escending Order'), self.button_cb, 'sort_lines_in_descending_order', Gtk.STOCK_SORT_DESCENDING, 'sort_lines_in_descending_order'], [_('Sort Lines In D_escending Order'), self.button_cb, 'sort_lines_in_descending_order', Gtk.STOCK_SORT_DESCENDING, 'sort_lines_in_descending_order'], # noqa: E501
[], [],
[_('Remove Trailing _White Space'), self.button_cb, 'remove_trailing_white_space', None, 'remove_trailing_white_space'], [_('Remove Trailing _White Space'), self.button_cb, 'remove_trailing_white_space', None, 'remove_trailing_white_space'], # noqa: E501
[_('Convert Tabs To _Spaces'), self.button_cb, 'convert_tabs_to_spaces', None, 'convert_tabs_to_spaces'], [_('Convert Tabs To _Spaces'), self.button_cb, 'convert_tabs_to_spaces', None, 'convert_tabs_to_spaces'], # noqa: E501
[_('Convert Leading Spaces To _Tabs'), self.button_cb, 'convert_leading_spaces_to_tabs', None, 'convert_leading_spaces_to_tabs'], [_('Convert Leading Spaces To _Tabs'), self.button_cb, 'convert_leading_spaces_to_tabs', None, 'convert_leading_spaces_to_tabs'], # noqa: E501
[], [],
[_('_Increase Indenting'), self.button_cb, 'increase_indenting', Gtk.STOCK_INDENT, 'increase_indenting'], [_('_Increase Indenting'), self.button_cb, 'increase_indenting', Gtk.STOCK_INDENT, 'increase_indenting'], # noqa: E501
[_('De_crease Indenting'), self.button_cb, 'decrease_indenting', Gtk.STOCK_UNINDENT, 'decrease_indenting'], [_('De_crease Indenting'), self.button_cb, 'decrease_indenting', Gtk.STOCK_UNINDENT, 'decrease_indenting'], # noqa: E501
[], [],
[_('Convert To _DOS Format'), self.button_cb, 'convert_to_dos', None, 'convert_to_dos'], [_('Convert To _DOS Format'), self.button_cb, 'convert_to_dos', None, 'convert_to_dos'], # noqa: E501
[_('Convert To _Mac Format'), self.button_cb, 'convert_to_mac', None, 'convert_to_mac'], [_('Convert To _Mac Format'), self.button_cb, 'convert_to_mac', None, 'convert_to_mac'], # noqa: E501
[_('Convert To Uni_x Format'), self.button_cb, 'convert_to_unix', None, 'convert_to_unix'] ] ]) [_('Convert To Uni_x Format'), self.button_cb, 'convert_to_unix', None, 'convert_to_unix'] # noqa: E501
]])
menuspecs.append([ _('_Merge'), [ menuspecs.append([_('_Merge'), [
[_('Copy Selection _Right'), self.button_cb, 'copy_selection_right', Gtk.STOCK_GOTO_LAST, 'copy_selection_right'], [_('Copy Selection _Right'), self.button_cb, 'copy_selection_right', Gtk.STOCK_GOTO_LAST, 'copy_selection_right'], # noqa: E501
[_('Copy Selection _Left'), self.button_cb, 'copy_selection_left', Gtk.STOCK_GOTO_FIRST, 'copy_selection_left'], [_('Copy Selection _Left'), self.button_cb, 'copy_selection_left', Gtk.STOCK_GOTO_FIRST, 'copy_selection_left'], # noqa: E501
[], [],
[_('Copy Left _Into Selection'), self.button_cb, 'copy_left_into_selection', Gtk.STOCK_GO_FORWARD, 'copy_left_into_selection'], [_('Copy Left _Into Selection'), self.button_cb, 'copy_left_into_selection', Gtk.STOCK_GO_FORWARD, 'copy_left_into_selection'], # noqa: E501
[_('Copy Right I_nto Selection'), self.button_cb, 'copy_right_into_selection', Gtk.STOCK_GO_BACK, 'copy_right_into_selection'], [_('Copy Right I_nto Selection'), self.button_cb, 'copy_right_into_selection', Gtk.STOCK_GO_BACK, 'copy_right_into_selection'], # noqa: E501
[_('_Merge From Left Then Right'), self.button_cb, 'merge_from_left_then_right', DIFFUSE_STOCK_LEFT_RIGHT, 'merge_from_left_then_right'], [_('_Merge From Left Then Right'), self.button_cb, 'merge_from_left_then_right', DIFFUSE_STOCK_LEFT_RIGHT, 'merge_from_left_then_right'], # noqa: E501
[_('M_erge From Right Then Left'), self.button_cb, 'merge_from_right_then_left', DIFFUSE_STOCK_RIGHT_LEFT, 'merge_from_right_then_left'] ] ]) [_('M_erge From Right Then Left'), self.button_cb, 'merge_from_right_then_left', DIFFUSE_STOCK_RIGHT_LEFT, 'merge_from_right_then_left'] # noqa: E501
]])
menuspecs.append([ _('_Help'), [ menuspecs.append([_('_Help'), [
[_('_Help Contents...'), self.help_contents_cb, None, Gtk.STOCK_HELP, 'help_contents'], [_('_Help Contents...'), self.help_contents_cb, None, Gtk.STOCK_HELP, 'help_contents'],
[], [],
[_('_About %s...') % (constants.APP_NAME, ), self.about_cb, None, Gtk.STOCK_ABOUT, 'about'] ] ]) [_('_About %s...') % (constants.APP_NAME, ), self.about_cb, None, Gtk.STOCK_ABOUT, 'about'] # noqa: E501
]])
# used to disable menu events when switching tabs # used to disable menu events when switching tabs
self.menu_update_depth = 0 self.menu_update_depth = 0
@ -817,8 +898,8 @@ class Diffuse(Gtk.Window):
# create button bar # create button bar
hbox = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 0) hbox = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 0)
_append_buttons(hbox, Gtk.IconSize.LARGE_TOOLBAR, [ _append_buttons(hbox, Gtk.IconSize.LARGE_TOOLBAR, [
[DIFFUSE_STOCK_NEW_2WAY_MERGE, self.new_2_way_file_merge_cb, None, _('New 2-Way File Merge')], [DIFFUSE_STOCK_NEW_2WAY_MERGE, self.new_2_way_file_merge_cb, None, _('New 2-Way File Merge')], # noqa: E501
[DIFFUSE_STOCK_NEW_3WAY_MERGE, self.new_3_way_file_merge_cb, None, _('New 3-Way File Merge')], [DIFFUSE_STOCK_NEW_3WAY_MERGE, self.new_3_way_file_merge_cb, None, _('New 3-Way File Merge')], # noqa: E501
[], [],
[Gtk.STOCK_EXECUTE, self.button_cb, 'realign_all', _('Realign All')], [Gtk.STOCK_EXECUTE, self.button_cb, 'realign_all', _('Realign All')],
[Gtk.STOCK_GOTO_TOP, self.button_cb, 'first_difference', _('First Difference')], [Gtk.STOCK_GOTO_TOP, self.button_cb, 'first_difference', _('First Difference')],
@ -826,19 +907,20 @@ class Diffuse(Gtk.Window):
[Gtk.STOCK_GO_DOWN, self.button_cb, 'next_difference', _('Next Difference')], [Gtk.STOCK_GO_DOWN, self.button_cb, 'next_difference', _('Next Difference')],
[Gtk.STOCK_GOTO_BOTTOM, self.button_cb, 'last_difference', _('Last Difference')], [Gtk.STOCK_GOTO_BOTTOM, self.button_cb, 'last_difference', _('Last Difference')],
[], [],
[Gtk.STOCK_GOTO_LAST, self.button_cb, 'copy_selection_right', _('Copy Selection Right')], [Gtk.STOCK_GOTO_LAST, self.button_cb, 'copy_selection_right', _('Copy Selection Right')], # noqa: E501
[Gtk.STOCK_GOTO_FIRST, self.button_cb, 'copy_selection_left', _('Copy Selection Left')], [Gtk.STOCK_GOTO_FIRST, self.button_cb, 'copy_selection_left', _('Copy Selection Left')],
[Gtk.STOCK_GO_FORWARD, self.button_cb, 'copy_left_into_selection', _('Copy Left Into Selection')], [Gtk.STOCK_GO_FORWARD, self.button_cb, 'copy_left_into_selection', _('Copy Left Into Selection')], # noqa: E501
[Gtk.STOCK_GO_BACK, self.button_cb, 'copy_right_into_selection', _('Copy Right Into Selection')], [Gtk.STOCK_GO_BACK, self.button_cb, 'copy_right_into_selection', _('Copy Right Into Selection')], # noqa: E501
[DIFFUSE_STOCK_LEFT_RIGHT, self.button_cb, 'merge_from_left_then_right', _('Merge From Left Then Right')], [DIFFUSE_STOCK_LEFT_RIGHT, self.button_cb, 'merge_from_left_then_right', _('Merge From Left Then Right')], # noqa: E501
[DIFFUSE_STOCK_RIGHT_LEFT, self.button_cb, 'merge_from_right_then_left', _('Merge From Right Then Left')], [DIFFUSE_STOCK_RIGHT_LEFT, self.button_cb, 'merge_from_right_then_left', _('Merge From Right Then Left')], # noqa: E501
[], [],
[Gtk.STOCK_UNDO, self.button_cb, 'undo', _('Undo')], [Gtk.STOCK_UNDO, self.button_cb, 'undo', _('Undo')],
[Gtk.STOCK_REDO, self.button_cb, 'redo', _('Redo')], [Gtk.STOCK_REDO, self.button_cb, 'redo', _('Redo')],
[Gtk.STOCK_CUT, self.button_cb, 'cut', _('Cut')], [Gtk.STOCK_CUT, self.button_cb, 'cut', _('Cut')],
[Gtk.STOCK_COPY, self.button_cb, 'copy', _('Copy')], [Gtk.STOCK_COPY, self.button_cb, 'copy', _('Copy')],
[Gtk.STOCK_PASTE, self.button_cb, 'paste', _('Paste')], [Gtk.STOCK_PASTE, self.button_cb, 'paste', _('Paste')],
[Gtk.STOCK_CLEAR, self.button_cb, 'clear_edits', _('Clear Edits') ]]) [Gtk.STOCK_CLEAR, self.button_cb, 'clear_edits', _('Clear Edits')]
])
# avoid the button bar from dictating the minimum window size # avoid the button bar from dictating the minimum window size
hbox.set_size_request(0, hbox.get_size_request()[1]) hbox.set_size_request(0, hbox.get_size_request()[1])
vbox.pack_start(hbox, False, False, 0) vbox.pack_start(hbox, False, False, 0)
@ -872,13 +954,15 @@ class Diffuse(Gtk.Window):
# read the state directly instead of using window_maximized as the order # read the state directly instead of using window_maximized as the order
# of configure/window_state events is undefined # of configure/window_state events is undefined
if (widget.get_window().get_state() & Gdk.WindowState.MAXIMIZED) == 0: if (widget.get_window().get_state() & Gdk.WindowState.MAXIMIZED) == 0:
self.int_state['window_x'], self.int_state['window_y'] = widget.get_window().get_root_origin() self.int_state['window_x'], self.int_state['window_y'] = widget.get_window().get_root_origin() # noqa: E501
self.int_state['window_width'] = event.width self.int_state['window_width'] = event.width
self.int_state['window_height'] = event.height self.int_state['window_height'] = event.height
# record the window's maximised state # record the window's maximised state
def window_state_cb(self, window, event): def window_state_cb(self, window, event):
self.bool_state['window_maximized'] = ((event.new_window_state & Gdk.WindowState.MAXIMIZED) != 0) self.bool_state['window_maximized'] = (
(event.new_window_state & Gdk.WindowState.MAXIMIZED) != 0
)
# load state information that should persist across sessions # load state information that should persist across sessions
def loadState(self, statepath): def loadState(self, statepath):
@ -920,7 +1004,7 @@ class Diffuse(Gtk.Window):
ss.append(f'{k} {v}\n') ss.append(f'{k} {v}\n')
ss.sort() ss.sort()
f = open(statepath, 'w') f = open(statepath, 'w')
f.write(f"# This state file was generated by {constants.APP_NAME} {constants.VERSION}.\n\n") f.write(f"# This state file was generated by {constants.APP_NAME} {constants.VERSION}.\n\n") # noqa: E501
for s in ss: for s in ss:
f.write(s) f.write(s)
f.close() f.close()
@ -958,7 +1042,8 @@ class Diffuse(Gtk.Window):
destroy_with_parent=True, destroy_with_parent=True,
message_type=Gtk.MessageType.WARNING, message_type=Gtk.MessageType.WARNING,
buttons=Gtk.ButtonsType.NONE, buttons=Gtk.ButtonsType.NONE,
text=_('Some files have unsaved changes. Select the files to save before closing.')) text=_('Some files have unsaved changes. '
'Select the files to save before closing.'))
dialog.set_resizable(True) dialog.set_resizable(True)
dialog.set_title(constants.APP_NAME) dialog.set_title(constants.APP_NAME)
# add list of files with unsaved changes # add list of files with unsaved changes
@ -1023,7 +1108,11 @@ class Diffuse(Gtk.Window):
# convenience method to request confirmation when closing the last tab # convenience method to request confirmation when closing the last tab
def _confirm_tab_close(self): def _confirm_tab_close(self):
dialog = utils.MessageDialog(self.get_toplevel(), Gtk.MessageType.WARNING, _('Closing this tab will quit %s.') % (constants.APP_NAME, )) dialog = utils.MessageDialog(
self.get_toplevel(),
Gtk.MessageType.WARNING,
_('Closing this tab will quit %s.') % (constants.APP_NAME, )
)
end = (dialog.run() == Gtk.ResponseType.OK) end = (dialog.run() == Gtk.ResponseType.OK)
dialog.destroy() dialog.destroy()
return end return end
@ -1116,7 +1205,9 @@ class Diffuse(Gtk.Window):
self.notebook.set_tab_reorderable(viewer, True) self.notebook.set_tab_reorderable(viewer, True)
tab.show() tab.show()
viewer.show() viewer.show()
self.notebook.set_show_tabs(self.prefs.getBool('tabs_always_show') or self.notebook.get_n_pages() > 1) self.notebook.set_show_tabs(
self.prefs.getBool('tabs_always_show') or self.notebook.get_n_pages() > 1
)
viewer.connect('title-changed', self.title_changed_cb) viewer.connect('title-changed', self.title_changed_cb)
viewer.connect('status-changed', self.status_changed_cb) viewer.connect('status-changed', self.status_changed_cb)
viewer.connect('syntax-changed', self.syntax_changed_cb) viewer.connect('syntax-changed', self.syntax_changed_cb)
@ -1208,7 +1299,10 @@ class Diffuse(Gtk.Window):
viewer.load(i, FileInfo(name, encoding, vcs, rev)) viewer.load(i, FileInfo(name, encoding, vcs, rev))
viewer.setOptions(options) viewer.setOptions(options)
except (IOError, OSError): except (IOError, OSError):
utils.logErrorAndDialog(_('Error retrieving commits for %s.') % (dn, ), self.get_toplevel()) utils.logErrorAndDialog(
_('Error retrieving commits for %s.') % (dn, ),
self.get_toplevel()
)
# create a new viewer for each modified file found in 'items' # create a new viewer for each modified file found in 'items'
def createModifiedFileTabs(self, items, labels, options): def createModifiedFileTabs(self, items, labels, options):
@ -1237,7 +1331,10 @@ class Diffuse(Gtk.Window):
viewer.load(i, FileInfo(name, encoding, vcs, rev)) viewer.load(i, FileInfo(name, encoding, vcs, rev))
viewer.setOptions(options) viewer.setOptions(options)
except (IOError, OSError): except (IOError, OSError):
utils.logErrorAndDialog(_('Error retrieving modifications for %s.') % (dn, ), self.get_toplevel()) utils.logErrorAndDialog(
_('Error retrieving modifications for %s.') % (dn, ),
self.get_toplevel()
)
# close all tabs without differences # close all tabs without differences
def closeOnSame(self): def closeOnSame(self):
@ -1267,7 +1364,14 @@ class Diffuse(Gtk.Window):
# callback for the open file menu item # callback for the open file menu item
def open_file_in_new_tab_cb(self, widget, data): def open_file_in_new_tab_cb(self, widget, data):
dialog = FileChooserDialog(_('Open File In New Tab'), self.get_toplevel(), self.prefs, Gtk.FileChooserAction.OPEN, Gtk.STOCK_OPEN, True) dialog = FileChooserDialog(
_('Open File In New Tab'),
self.get_toplevel(),
self.prefs,
Gtk.FileChooserAction.OPEN,
Gtk.STOCK_OPEN,
True
)
dialog.set_default_response(Gtk.ResponseType.OK) dialog.set_default_response(Gtk.ResponseType.OK)
accept = (dialog.run() == Gtk.ResponseType.OK) accept = (dialog.run() == Gtk.ResponseType.OK)
name, encoding = dialog.get_filename(), dialog.get_encoding() name, encoding = dialog.get_filename(), dialog.get_encoding()
@ -1283,7 +1387,13 @@ class Diffuse(Gtk.Window):
# callback for the open modified files menu item # callback for the open modified files menu item
def open_modified_files_cb(self, widget, data): def open_modified_files_cb(self, widget, data):
parent = self.get_toplevel() parent = self.get_toplevel()
dialog = FileChooserDialog(_('Choose Folder With Modified Files'), parent, self.prefs, Gtk.FileChooserAction.SELECT_FOLDER, Gtk.STOCK_OPEN) dialog = FileChooserDialog(
_('Choose Folder With Modified Files'),
parent,
self.prefs,
Gtk.FileChooserAction.SELECT_FOLDER,
Gtk.STOCK_OPEN
)
dialog.set_default_response(Gtk.ResponseType.OK) dialog.set_default_response(Gtk.ResponseType.OK)
accept = (dialog.run() == Gtk.ResponseType.OK) accept = (dialog.run() == Gtk.ResponseType.OK)
name, encoding = dialog.get_filename(), dialog.get_encoding() name, encoding = dialog.get_filename(), dialog.get_encoding()
@ -1301,14 +1411,22 @@ class Diffuse(Gtk.Window):
# callback for the open commit menu item # callback for the open commit menu item
def open_commit_cb(self, widget, data): def open_commit_cb(self, widget, data):
parent = self.get_toplevel() parent = self.get_toplevel()
dialog = FileChooserDialog(_('Choose Folder With Commit'), parent, self.prefs, Gtk.FileChooserAction.SELECT_FOLDER, Gtk.STOCK_OPEN, True) dialog = FileChooserDialog(
_('Choose Folder With Commit'),
parent, self.prefs,
Gtk.FileChooserAction.SELECT_FOLDER,
Gtk.STOCK_OPEN,
True
)
dialog.set_default_response(Gtk.ResponseType.OK) dialog.set_default_response(Gtk.ResponseType.OK)
accept = (dialog.run() == Gtk.ResponseType.OK) accept = (dialog.run() == Gtk.ResponseType.OK)
name, rev, encoding = dialog.get_filename(), dialog.get_revision(), dialog.get_encoding() name = dialog.get_filename()
rev = dialog.get_revision()
encoding = dialog.get_encoding()
dialog.destroy() dialog.destroy()
if accept: if accept:
n = self.notebook.get_n_pages() n = self.notebook.get_n_pages()
self.createCommitFileTabs([(name, [(None, encoding)])], [], { 'commit': rev }) self.createCommitFileTabs([(name, [(None, encoding)])], [], {'commit': rev})
if self.notebook.get_n_pages() > n: if self.notebook.get_n_pages() > n:
# we added some new tabs, focus on the first one # we added some new tabs, focus on the first one
self.notebook.set_current_page(n) self.notebook.set_current_page(n)
@ -1348,7 +1466,14 @@ class Diffuse(Gtk.Window):
# callback for the new n-way file merge menu item # callback for the new n-way file merge menu item
def new_n_way_file_merge_cb(self, widget, data): def new_n_way_file_merge_cb(self, widget, data):
parent = self.get_toplevel() parent = self.get_toplevel()
dialog = NumericDialog(parent, _('New N-Way File Merge...'), _('Number of panes: '), 4, 2, 16) dialog = NumericDialog(
parent,
_('New N-Way File Merge...'),
_('Number of panes: '),
val=4,
lower=2,
upper=16
)
okay = (dialog.run() == Gtk.ResponseType.ACCEPT) okay = (dialog.run() == Gtk.ResponseType.ACCEPT)
npanes = dialog.button.get_value_as_int() npanes = dialog.button.get_value_as_int()
dialog.destroy() dialog.destroy()
@ -1409,7 +1534,12 @@ class Diffuse(Gtk.Window):
reverse ^= self.bool_state['search_backwards'] reverse ^= self.bool_state['search_backwards']
from_start, more = False, True from_start, more = False, True
while more: while more:
if viewer.find(self.search_pattern, self.bool_state['search_matchcase'], reverse, from_start): if viewer.find(
self.search_pattern,
self.bool_state['search_matchcase'],
reverse,
from_start
):
break break
if reverse: if reverse:
@ -1543,6 +1673,7 @@ class Diffuse(Gtk.Window):
dialog.run() dialog.run()
dialog.destroy() dialog.destroy()
# convenience method for creating a menu bar according to a template # convenience method for creating a menu bar according to a template
def _create_menu_bar(specs, radio, accel_group): def _create_menu_bar(specs, radio, accel_group):
menu_bar = Gtk.MenuBar.new() menu_bar = Gtk.MenuBar.new()
@ -1554,6 +1685,7 @@ def _create_menu_bar(specs, radio, accel_group):
menu_bar.append(menu) menu_bar.append(menu)
return menu_bar return menu_bar
# convenience method for packing buttons into a container according to a # convenience method for packing buttons into a container according to a
# template # template
def _append_buttons(box, size, specs): def _append_buttons(box, size, specs):
@ -1577,6 +1709,7 @@ def _append_buttons(box, size, specs):
box.pack_start(separator, False, False, 5) box.pack_start(separator, False, False, 5)
separator.show() separator.show()
# constructs a full URL for the named file # constructs a full URL for the named file
def _path2url(path, proto='file'): def _path2url(path, proto='file'):
r = [proto, ':///'] r = [proto, ':///']
@ -1596,6 +1729,7 @@ def _path2url(path, proto='file'):
r.append(c) r.append(c)
return ''.join(r) return ''.join(r)
# assign user specified labels to the corresponding files # assign user specified labels to the corresponding files
def _assign_file_labels(items, labels): def _assign_file_labels(items, labels):
new_items = [] new_items = []
@ -1608,13 +1742,15 @@ def _assign_file_labels(items, labels):
new_items.append((name, data, s)) new_items.append((name, data, s))
return new_items return new_items
GObject.signal_new('title-changed', Diffuse.FileDiffViewer, GObject.SignalFlags.RUN_LAST, GObject.TYPE_NONE, (str, ))
GObject.signal_new('status-changed', Diffuse.FileDiffViewer, GObject.SignalFlags.RUN_LAST, GObject.TYPE_NONE, (str, )) GObject.signal_new('title-changed', Diffuse.FileDiffViewer, GObject.SignalFlags.RUN_LAST, GObject.TYPE_NONE, (str, )) # noqa: E501
GObject.signal_new('title-changed', Diffuse.FileDiffViewer.PaneHeader, GObject.SignalFlags.RUN_LAST, GObject.TYPE_NONE, ()) GObject.signal_new('status-changed', Diffuse.FileDiffViewer, GObject.SignalFlags.RUN_LAST, GObject.TYPE_NONE, (str, )) # noqa: E501
GObject.signal_new('open', Diffuse.FileDiffViewer.PaneHeader, GObject.SignalFlags.RUN_LAST, GObject.TYPE_NONE, ()) GObject.signal_new('title-changed', Diffuse.FileDiffViewer.PaneHeader, GObject.SignalFlags.RUN_LAST, GObject.TYPE_NONE, ()) # noqa: E501
GObject.signal_new('reload', Diffuse.FileDiffViewer.PaneHeader, GObject.SignalFlags.RUN_LAST, GObject.TYPE_NONE, ()) GObject.signal_new('open', Diffuse.FileDiffViewer.PaneHeader, GObject.SignalFlags.RUN_LAST, GObject.TYPE_NONE, ()) # noqa: E501
GObject.signal_new('save', Diffuse.FileDiffViewer.PaneHeader, GObject.SignalFlags.RUN_LAST, GObject.TYPE_NONE, ()) GObject.signal_new('reload', Diffuse.FileDiffViewer.PaneHeader, GObject.SignalFlags.RUN_LAST, GObject.TYPE_NONE, ()) # noqa: E501
GObject.signal_new('save-as', Diffuse.FileDiffViewer.PaneHeader, GObject.SignalFlags.RUN_LAST, GObject.TYPE_NONE, ()) GObject.signal_new('save', Diffuse.FileDiffViewer.PaneHeader, GObject.SignalFlags.RUN_LAST, GObject.TYPE_NONE, ()) # noqa: E501
GObject.signal_new('save-as', Diffuse.FileDiffViewer.PaneHeader, GObject.SignalFlags.RUN_LAST, GObject.TYPE_NONE, ()) # noqa: E501
def main(): def main():
# app = Application() # app = Application()
@ -1629,7 +1765,7 @@ def main():
if argc == 2 and args[1] in ['-h', '-?', '--help']: if argc == 2 and args[1] in ['-h', '-?', '--help']:
print(_('''Usage: print(_('''Usage:
diffuse [ [OPTION...] [FILE...] ]... diffuse [OPTION...] [FILE...]
diffuse ( -h | -? | --help | -v | --version ) diffuse ( -h | -? | --help | -v | --version )
Diffuse is a graphical tool for merging and comparing text files. Diffuse is Diffuse is a graphical tool for merging and comparing text files. Diffuse is
@ -1697,7 +1833,7 @@ Display Options:
if utils.isWindows(): if utils.isWindows():
rc_file = os.path.join(utils.bin_dir, 'diffuserc') rc_file = os.path.join(utils.bin_dir, 'diffuserc')
else: else:
rc_file = os.path.join(utils.bin_dir, f'{constants.sysconfigdir}/diffuserc') rc_file = os.path.join(utils.bin_dir, f'{constants.SYSCONFIGDIR}/diffuserc')
for rc_file in rc_file, os.path.join(rc_dir, 'diffuserc'): for rc_file in rc_file, os.path.join(rc_dir, 'diffuserc'):
if os.path.isfile(rc_file): if os.path.isfile(rc_file):
rc_files.append(rc_file) rc_files.append(rc_file)
@ -1740,8 +1876,7 @@ Display Options:
# specified revision # specified revision
funcs[mode](specs, labels, options) funcs[mode](specs, labels, options)
i += 1 i += 1
rev = args[i] specs, labels, options = [], [], {'commit': args[i]}
specs, labels, options = [], [], { 'commit': args[i] }
mode = 'commit' mode = 'commit'
elif arg in ['-D', '--close-if-same']: elif arg in ['-D', '--close-if-same']:
close_on_same = True close_on_same = True
@ -1816,7 +1951,9 @@ Display Options:
if len(specs) > 0: if len(specs) > 0:
filename = os.path.join(filename, os.path.basename(specs[-1][0])) filename = os.path.join(filename, os.path.basename(specs[-1][0]))
else: else:
utils.logError(_('Error processing argument "%s". Directory not expected.') % (args[i], )) utils.logError(_(
'Error processing argument "%s". Directory not expected.') % (args[i], )
)
filename = None filename = None
if filename is not None: if filename is not None:
if len(revs) == 0: if len(revs) == 0:

View File

@ -1,13 +1,12 @@
pkgdatadir = join_paths(get_option('prefix'), get_option('datadir'), meson.project_name()) pkgdatadir = join_paths(get_option('prefix'), get_option('datadir'), meson.project_name())
moduledir = join_paths(pkgdatadir, 'diffuse') moduledir = join_paths(pkgdatadir, 'diffuse')
sysconfdir = join_paths(get_option('prefix'), get_option('sysconfdir'))
python = import('python') python = import('python')
conf = configuration_data() conf = configuration_data()
conf.set('PYTHON', python.find_installation('python3').path()) conf.set('PYTHON', python.find_installation('python3').path())
conf.set('pkgdatadir', pkgdatadir) conf.set('PKGDATADIR', pkgdatadir)
conf.set('localedir', join_paths(get_option('prefix'), get_option('localedir'))) conf.set('LOCALEDIR', join_paths(get_option('prefix'), get_option('localedir')))
configure_file( configure_file(
input: 'diffuse.in', input: 'diffuse.in',
@ -19,10 +18,10 @@ configure_file(
conf = configuration_data() conf = configuration_data()
conf.set('VERSION', meson.project_version()) conf.set('VERSION', meson.project_version())
conf.set('sysconfigdir', sysconfdir) conf.set('SYSCONFIGDIR', join_paths(get_option('prefix'), get_option('sysconfdir')))
conf.set('log_print_output', get_option('log_print_output')) conf.set('LOG_PRINT_OUTPUT', get_option('log_print_output'))
conf.set('log_print_stack', get_option('log_print_stack')) conf.set('LOG_PRINT_STACK', get_option('log_print_stack'))
conf.set('use_flatpak', get_option('use_flatpak')) conf.set('USE_FLATPAK', get_option('use_flatpak'))
configure_file( configure_file(
input: 'constants.py.in', input: 'constants.py.in',

View File

@ -23,7 +23,7 @@ import os
import shlex import shlex
import sys import sys
from diffuse import constants # type: ignore from diffuse import constants
from diffuse import utils from diffuse import utils
import gi # type: ignore import gi # type: ignore

View File

@ -23,7 +23,7 @@ import locale
import subprocess import subprocess
import traceback import traceback
from diffuse import constants # type: ignore from diffuse import constants
import gi # type: ignore import gi # type: ignore
gi.require_version('Gtk', '3.0') gi.require_version('Gtk', '3.0')
@ -77,9 +77,9 @@ def isWindows():
def _logPrintOutput(msg): def _logPrintOutput(msg):
if constants.log_print_output: if constants.LOG_PRINT_OUTPUT:
print(msg, file=sys.stderr) print(msg, file=sys.stderr)
if constants.log_print_stack: if constants.LOG_PRINT_STACK:
traceback.print_stack() traceback.print_stack()
@ -154,7 +154,7 @@ def _bash_escape(s):
def _use_flatpak(): def _use_flatpak():
return constants.use_flatpak return constants.USE_FLATPAK
# use popen to read the output of a command # use popen to read the output of a command