pyDiffTools 0.1.52__tar.gz → 0.1.53__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pydifftools-0.1.52 → pydifftools-0.1.53}/MANIFEST.in +1 -0
- {pydifftools-0.1.52/pyDiffTools.egg-info → pydifftools-0.1.53}/PKG-INFO +58 -9
- {pydifftools-0.1.52 → pydifftools-0.1.53}/README.rst +57 -8
- {pydifftools-0.1.52 → pydifftools-0.1.53/pyDiffTools.egg-info}/PKG-INFO +58 -9
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pyDiffTools.egg-info/SOURCES.txt +2 -0
- pydifftools-0.1.53/pydifftools/browser_lifecycle.py +173 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/command_line.py +45 -5
- pydifftools-0.1.53/pydifftools/completions/git-mergein +41 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/continuous.py +106 -168
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/flowchart/watch_graph.py +8 -33
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/forward_search.py +5 -0
- pydifftools-0.1.53/pydifftools/git_aliases.py +139 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/git_gd.py +8 -51
- pydifftools-0.1.53/pydifftools/line_alignment.py +571 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/notebook/fast_build.py +503 -379
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/pdf_diff.py +2 -17
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/wrap_sentences.py +142 -38
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pyproject.toml +2 -1
- pydifftools-0.1.53/tests/test_browser_lifecycle.py +273 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/tests/test_command_line_help.py +29 -3
- {pydifftools-0.1.52 → pydifftools-0.1.53}/tests/test_continuous_shutdown.py +6 -2
- {pydifftools-0.1.52 → pydifftools-0.1.53}/tests/test_forward_search.py +131 -0
- pydifftools-0.1.53/tests/test_git_mergein.py +256 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/tests/test_git_pdf_diff.py +11 -12
- pydifftools-0.1.53/tests/test_line_alignment.py +385 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/tests/test_pdf_diff.py +2 -3
- {pydifftools-0.1.52 → pydifftools-0.1.53}/tests/test_wrap_check.py +373 -46
- pydifftools-0.1.52/pydifftools/browser_lifecycle.py +0 -141
- pydifftools-0.1.52/pydifftools/git_aliases.py +0 -30
- pydifftools-0.1.52/pydifftools/line_alignment.py +0 -391
- pydifftools-0.1.52/tests/test_browser_lifecycle.py +0 -171
- pydifftools-0.1.52/tests/test_line_alignment.py +0 -131
- {pydifftools-0.1.52 → pydifftools-0.1.53}/LICENSE.md +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/_quarto.yml +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/.jupyter_cache/__version__.txt +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/.jupyter_cache/executed/1a724af72b16f5a9e607e12b1c721645/base.ipynb +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/.jupyter_cache/executed/1b28fc9daac9081847e5161b2c546f8a/base.ipynb +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/.jupyter_cache/executed/231f64eee282fa225d1104935cf80a24/base.ipynb +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/.jupyter_cache/executed/26e56f6b0ff54851a45145157f2f0dc4/base.ipynb +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/.jupyter_cache/executed/311fabd7029ffd050d056e2f316eb50f/base.ipynb +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/.jupyter_cache/executed/57da2021e5b156ac3adf01398201c723/base.ipynb +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/.jupyter_cache/executed/62b24ea7da75011d92b0f8924faa208d/base.ipynb +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/.jupyter_cache/executed/7f1b20d69d889514ab5d1cc92e3cb14f/base.ipynb +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/.jupyter_cache/executed/86f74c8c54a87ff892d9b15dd714e8f0/base.ipynb +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/.jupyter_cache/executed/88893b4234eac2945d9d6cb2e277f186/base.ipynb +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/.jupyter_cache/executed/9a40046ada6f582ee34af00fbdbfb417/base.ipynb +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/.jupyter_cache/executed/a1bf4d270d0641ff41faf1d7cce3439a/base.ipynb +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/.jupyter_cache/executed/a3789f7d9585a781f2a1c60ce95ff10d/base.ipynb +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/.jupyter_cache/executed/be46ecba858d39ad5f0c46902ddf1c02/base.ipynb +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/.jupyter_cache/executed/d0cbc57a12f2ccce710a5afd04cc05e7/base.ipynb +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/.jupyter_cache/executed/d3e12d320b14228f701231ae32ddd7dd/base.ipynb +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/.jupyter_cache/executed/eb434f61555438d020a6970a5dbf9ee8/base.ipynb +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/.jupyter_cache/executed/f6b0e73aa7fa029134665d4dde57e096/base.ipynb +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/.jupyter_cache/executed/f719a6e4ff09873cb0ffb06ec9d232f9/base.ipynb +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/.jupyter_cache/executed/feeee244a7ce3d60e1a227eb604df823/base.ipynb +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/.jupyter_cache/global.db +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/example.qmd +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/example.tex +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/index.qmd +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/subproject1/.jupyter_cache/__version__.txt +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/subproject1/.jupyter_cache/executed/ca90e4df5f4f0583df6554156a68dc7f/base.ipynb +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/subproject1/.jupyter_cache/global.db +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/subproject1/end_vs_he_sketch.jpg +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/subproject1/independent.qmd +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/subproject1/index.qmd +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/subproject1/tasks.qmd +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/subproject1/test_include.qmd +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/subproject1/tryforerror.qmd +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/example_notebook/project1/test_include.qmd +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pyDiffTools.egg-info/dependency_links.txt +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pyDiffTools.egg-info/entry_points.txt +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pyDiffTools.egg-info/requires.txt +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pyDiffTools.egg-info/top_level.txt +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/__init__.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/bibliography.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/check_numbers.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/citation_dialog.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/command_registry.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/comment_filter_history.json +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/comment_functions.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/comment_migration.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/comment_tags.lua +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/comment_tags_margin.lua +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/comment_tags_no_comments.lua +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/comment_toggle.js +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/comments.css +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/comments_author_colors.css +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/copy_files.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/diff-doc.js +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/doc_contents.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/flowchart/__init__.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/flowchart/comparison.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/flowchart/dot_to_yaml.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/flowchart/graph.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/flowchart/source_jump.js +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/flowchart/svg-pan-zoom.min.js +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/flowchart/wgrph_view.js +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/git_gd_history.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/git_gd_image.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/git_gd_qt.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/html_comments.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/html_uncomments.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/log_example.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/match_spaces.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/notebook/__init__.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/notebook/display.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/notebook/tex_to_qmd.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/onewordify.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/onewordify_undo.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/outline.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/rearrange_tex.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/searchacro.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/separate_comments.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/source_jump.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/split_conflict.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/unseparate_comments.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/update_check.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/wrapping_options.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/xml2xlsx.vbs +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/pydifftools/zotero.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/setup.cfg +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/tests/test_bibliography.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/tests/test_check_single_use.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/tests/test_comment_filters.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/tests/test_comment_migration.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/tests/test_git_gd_history.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/tests/test_git_gd_image.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/tests/test_git_gd_qt.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/tests/test_rrng.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/tests/test_source_jump.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/tests/test_tex_to_qmd.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/tests/test_update_check.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/tests/test_wrapping.py +0 -0
- {pydifftools-0.1.52 → pydifftools-0.1.53}/tests/test_zotero.py +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# In addition to the package file, various *.sh files are included -- these will eventually be converted to python
|
|
2
2
|
include README.rst
|
|
3
3
|
include LICENSE.md
|
|
4
|
+
include pydifftools/completions/git-mergein
|
|
4
5
|
include pydifftools/diff-doc.js
|
|
5
6
|
include pydifftools/xml2xlsx.vbs
|
|
6
7
|
include pydifftools/comments.css
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyDiffTools
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.53
|
|
4
4
|
Summary: Diff tools
|
|
5
5
|
Author: J M Franck
|
|
6
6
|
License: Copyright (c) 2015, jmfranck
|
|
@@ -72,6 +72,30 @@ included are (listed in order of fun/utility):
|
|
|
72
72
|
`filename.md`, build the result,
|
|
73
73
|
and displays it in your browser.
|
|
74
74
|
|
|
75
|
+
Source diff linting minimizes line-break changes against the Git index
|
|
76
|
+
(staging area) by default, matching plain ``git diff``. Use
|
|
77
|
+
``pydifft cpb filename.md --diff-base @`` to compare against HEAD, or
|
|
78
|
+
``--diff-base jf_last`` to compare against a tag, branch, or commit hash.
|
|
79
|
+
The selected baseline is read again on each build. An unreadable explicit
|
|
80
|
+
baseline stops the build; an unavailable index baseline, such as for an
|
|
81
|
+
untracked file, falls back to ordinary source linting.
|
|
82
|
+
All diff-minimizing line-break fixes are applied automatically before
|
|
83
|
+
their notice appears. Each page shows as many changed hunks as fit in the
|
|
84
|
+
window, with a blank line separating hunks; larger changes are applied
|
|
85
|
+
just like single-break changes.
|
|
86
|
+
Diff alignment has separate eligibility rules from prose linting.
|
|
87
|
+
Equations and HTML comment contents participate in alignment, including
|
|
88
|
+
hunks that begin inside them. Display equations and hidden text remain
|
|
89
|
+
exempt from prose wrapping and sentence rules. Equation delimiters are
|
|
90
|
+
matched independently of their contents, and surviving matches on either
|
|
91
|
+
side of an edit restore whitespace while preserving changed values and
|
|
92
|
+
TeX commands. Literal delimiters in code are preserved.
|
|
93
|
+
Leading whitespace at matching line starts is restored in top-level
|
|
94
|
+
prose when both margins contain at most three spaces, and inside HTML
|
|
95
|
+
comments and equations. Container indentation (lists, definitions, and
|
|
96
|
+
quotations), tabs or four-space code indentation outside those spans,
|
|
97
|
+
and protected blocks retain their current margins.
|
|
98
|
+
|
|
75
99
|
Continuous pandoc build.
|
|
76
100
|
This works *very well* together
|
|
77
101
|
with the `g/` vim command
|
|
@@ -205,6 +229,12 @@ included are (listed in order of fun/utility):
|
|
|
205
229
|
``_build``/``_display`` directories; with ``--watch`` it starts the HTTP
|
|
206
230
|
server and automatically rebuilds the staged fragments whenever you edit
|
|
207
231
|
a ``.qmd`` file.
|
|
232
|
+
Browser previews in ``qmdb``, ``cpb``, and ``wgrph`` share the same
|
|
233
|
+
Selenium launcher: Chrome/Chromium is preferred, with Firefox as a
|
|
234
|
+
fallback. Installed ``chromedriver`` and ``geckodriver`` are used directly
|
|
235
|
+
without online driver discovery; if only ``geckodriver`` is installed,
|
|
236
|
+
Firefox opens directly. With neither driver installed, Selenium handles
|
|
237
|
+
discovery. Chrome startup failures are reported before trying Firefox.
|
|
208
238
|
- ``pydifft tree`` (or ``git tree`` with the alias installed) opens the last
|
|
209
239
|
40 commits across all branches, in Git date order. Use the down arrow
|
|
210
240
|
below the history to add the next 40 commits. Colors follow
|
|
@@ -215,7 +245,7 @@ included are (listed in order of fun/utility):
|
|
|
215
245
|
or set a commit as the comparison endpoint. The right-click menu can restore
|
|
216
246
|
the working-directory endpoint. Diff window titles show the equivalent
|
|
217
247
|
arguments, preferring tags, then branch names, then six-character hashes.
|
|
218
|
-
Run ``pydifft tree
|
|
248
|
+
Run ``pydifft --add_to_git tree`` to add the matching ``git tree`` alias.
|
|
219
249
|
- ``pydifft gd`` (or ``git gd`` with the alias installed) reviews unstaged
|
|
220
250
|
changes, like bare ``git diff``.
|
|
221
251
|
``pydifft gd [git diff args...]`` shows the same Qt review table as the old
|
|
@@ -229,12 +259,31 @@ included are (listed in order of fun/utility):
|
|
|
229
259
|
among the original, difference, and aligned new image. Images with an
|
|
230
260
|
alpha channel are displayed over a checkerboard; when transparency
|
|
231
261
|
changes, an additional red/blue alpha-difference view is included.
|
|
232
|
-
Run ``pydifft gd
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
262
|
+
Run ``pydifft --add_to_git gd`` to install the global ``git gd`` alias,
|
|
263
|
+
retaining the exact command of an existing global ``gd`` alias. If none
|
|
264
|
+
is configured, it installs ``!f() { pydifft gd "$@"; }; f``.
|
|
265
|
+
Configure ``difftool.mygvim.cmd`` for the GUI diff tool.
|
|
266
|
+
- ``pydifft --add_to_git gd pd tree mergein`` installs any selected subset
|
|
267
|
+
of these global Git aliases in one invocation. Installation appears
|
|
268
|
+
alongside the subcommands in root help; the former per-command
|
|
269
|
+
``--install`` and ``--add-to-git`` flags have been removed.
|
|
270
|
+
- ``pydifft mergein BRANCH [--remote REMOTE]`` updates an incoming local
|
|
271
|
+
branch without switching branches, then merges it into the current
|
|
272
|
+
branch. Install ``git mergein`` with ``pydifft --add_to_git mergein``.
|
|
273
|
+
``git mergein incoming/topic`` runs ``git fetch origin
|
|
274
|
+
incoming/topic:incoming/topic`` followed by ``git merge --no-ff
|
|
275
|
+
incoming/topic``. Use ``--remote upstream`` to select another remote;
|
|
276
|
+
``origin`` is the default. Fetch failures stop the sequence, local
|
|
277
|
+
branch updates are not forced, and merge conflicts remain available
|
|
278
|
+
for normal Git resolution.
|
|
279
|
+
|
|
280
|
+
Installing ``mergein`` also installs its Bash completion in the user
|
|
281
|
+
Bash completion directory (honoring ``BASH_COMPLETION_USER_DIR`` and
|
|
282
|
+
``XDG_DATA_HOME``). With standard Git Bash completion enabled,
|
|
283
|
+
``git mergein`` suggests cached branches of the selected remote, using
|
|
284
|
+
bare branch names such as ``incoming/topic``. Completion does not
|
|
285
|
+
contact the remote; fetch to refresh the suggestions. The ``pydifft``
|
|
286
|
+
form supports the same suggestions when argcomplete is enabled.
|
|
238
287
|
- `pydifft qmdinit [directory]` scaffolds a new Quarto-style project using
|
|
239
288
|
the bundled templates and example ``project1`` hierarchy, then downloads
|
|
240
289
|
MathJax into ``_template/mathjax`` so the builder can run immediately.
|
|
@@ -300,7 +349,7 @@ included are (listed in order of fun/utility):
|
|
|
300
349
|
The former ``git-latexdiffnocompile.sh`` is a compatibility wrapper for
|
|
301
350
|
``pydifft pd --no-compile``.
|
|
302
351
|
|
|
303
|
-
Run ``pydifft pd
|
|
352
|
+
Run ``pydifft --add_to_git pd`` to install the global ``git pd`` alias.
|
|
304
353
|
It accepts Git diff arguments: ``git pd 00ffaa -- filename.md`` compares
|
|
305
354
|
that revision with the working file; bare ``git pd`` compares unstaged
|
|
306
355
|
changes; ``git pd --cached`` compares staged changes; and
|
|
@@ -17,6 +17,30 @@ included are (listed in order of fun/utility):
|
|
|
17
17
|
`filename.md`, build the result,
|
|
18
18
|
and displays it in your browser.
|
|
19
19
|
|
|
20
|
+
Source diff linting minimizes line-break changes against the Git index
|
|
21
|
+
(staging area) by default, matching plain ``git diff``. Use
|
|
22
|
+
``pydifft cpb filename.md --diff-base @`` to compare against HEAD, or
|
|
23
|
+
``--diff-base jf_last`` to compare against a tag, branch, or commit hash.
|
|
24
|
+
The selected baseline is read again on each build. An unreadable explicit
|
|
25
|
+
baseline stops the build; an unavailable index baseline, such as for an
|
|
26
|
+
untracked file, falls back to ordinary source linting.
|
|
27
|
+
All diff-minimizing line-break fixes are applied automatically before
|
|
28
|
+
their notice appears. Each page shows as many changed hunks as fit in the
|
|
29
|
+
window, with a blank line separating hunks; larger changes are applied
|
|
30
|
+
just like single-break changes.
|
|
31
|
+
Diff alignment has separate eligibility rules from prose linting.
|
|
32
|
+
Equations and HTML comment contents participate in alignment, including
|
|
33
|
+
hunks that begin inside them. Display equations and hidden text remain
|
|
34
|
+
exempt from prose wrapping and sentence rules. Equation delimiters are
|
|
35
|
+
matched independently of their contents, and surviving matches on either
|
|
36
|
+
side of an edit restore whitespace while preserving changed values and
|
|
37
|
+
TeX commands. Literal delimiters in code are preserved.
|
|
38
|
+
Leading whitespace at matching line starts is restored in top-level
|
|
39
|
+
prose when both margins contain at most three spaces, and inside HTML
|
|
40
|
+
comments and equations. Container indentation (lists, definitions, and
|
|
41
|
+
quotations), tabs or four-space code indentation outside those spans,
|
|
42
|
+
and protected blocks retain their current margins.
|
|
43
|
+
|
|
20
44
|
Continuous pandoc build.
|
|
21
45
|
This works *very well* together
|
|
22
46
|
with the `g/` vim command
|
|
@@ -150,6 +174,12 @@ included are (listed in order of fun/utility):
|
|
|
150
174
|
``_build``/``_display`` directories; with ``--watch`` it starts the HTTP
|
|
151
175
|
server and automatically rebuilds the staged fragments whenever you edit
|
|
152
176
|
a ``.qmd`` file.
|
|
177
|
+
Browser previews in ``qmdb``, ``cpb``, and ``wgrph`` share the same
|
|
178
|
+
Selenium launcher: Chrome/Chromium is preferred, with Firefox as a
|
|
179
|
+
fallback. Installed ``chromedriver`` and ``geckodriver`` are used directly
|
|
180
|
+
without online driver discovery; if only ``geckodriver`` is installed,
|
|
181
|
+
Firefox opens directly. With neither driver installed, Selenium handles
|
|
182
|
+
discovery. Chrome startup failures are reported before trying Firefox.
|
|
153
183
|
- ``pydifft tree`` (or ``git tree`` with the alias installed) opens the last
|
|
154
184
|
40 commits across all branches, in Git date order. Use the down arrow
|
|
155
185
|
below the history to add the next 40 commits. Colors follow
|
|
@@ -160,7 +190,7 @@ included are (listed in order of fun/utility):
|
|
|
160
190
|
or set a commit as the comparison endpoint. The right-click menu can restore
|
|
161
191
|
the working-directory endpoint. Diff window titles show the equivalent
|
|
162
192
|
arguments, preferring tags, then branch names, then six-character hashes.
|
|
163
|
-
Run ``pydifft tree
|
|
193
|
+
Run ``pydifft --add_to_git tree`` to add the matching ``git tree`` alias.
|
|
164
194
|
- ``pydifft gd`` (or ``git gd`` with the alias installed) reviews unstaged
|
|
165
195
|
changes, like bare ``git diff``.
|
|
166
196
|
``pydifft gd [git diff args...]`` shows the same Qt review table as the old
|
|
@@ -174,12 +204,31 @@ included are (listed in order of fun/utility):
|
|
|
174
204
|
among the original, difference, and aligned new image. Images with an
|
|
175
205
|
alpha channel are displayed over a checkerboard; when transparency
|
|
176
206
|
changes, an additional red/blue alpha-difference view is included.
|
|
177
|
-
Run ``pydifft gd
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
207
|
+
Run ``pydifft --add_to_git gd`` to install the global ``git gd`` alias,
|
|
208
|
+
retaining the exact command of an existing global ``gd`` alias. If none
|
|
209
|
+
is configured, it installs ``!f() { pydifft gd "$@"; }; f``.
|
|
210
|
+
Configure ``difftool.mygvim.cmd`` for the GUI diff tool.
|
|
211
|
+
- ``pydifft --add_to_git gd pd tree mergein`` installs any selected subset
|
|
212
|
+
of these global Git aliases in one invocation. Installation appears
|
|
213
|
+
alongside the subcommands in root help; the former per-command
|
|
214
|
+
``--install`` and ``--add-to-git`` flags have been removed.
|
|
215
|
+
- ``pydifft mergein BRANCH [--remote REMOTE]`` updates an incoming local
|
|
216
|
+
branch without switching branches, then merges it into the current
|
|
217
|
+
branch. Install ``git mergein`` with ``pydifft --add_to_git mergein``.
|
|
218
|
+
``git mergein incoming/topic`` runs ``git fetch origin
|
|
219
|
+
incoming/topic:incoming/topic`` followed by ``git merge --no-ff
|
|
220
|
+
incoming/topic``. Use ``--remote upstream`` to select another remote;
|
|
221
|
+
``origin`` is the default. Fetch failures stop the sequence, local
|
|
222
|
+
branch updates are not forced, and merge conflicts remain available
|
|
223
|
+
for normal Git resolution.
|
|
224
|
+
|
|
225
|
+
Installing ``mergein`` also installs its Bash completion in the user
|
|
226
|
+
Bash completion directory (honoring ``BASH_COMPLETION_USER_DIR`` and
|
|
227
|
+
``XDG_DATA_HOME``). With standard Git Bash completion enabled,
|
|
228
|
+
``git mergein`` suggests cached branches of the selected remote, using
|
|
229
|
+
bare branch names such as ``incoming/topic``. Completion does not
|
|
230
|
+
contact the remote; fetch to refresh the suggestions. The ``pydifft``
|
|
231
|
+
form supports the same suggestions when argcomplete is enabled.
|
|
183
232
|
- `pydifft qmdinit [directory]` scaffolds a new Quarto-style project using
|
|
184
233
|
the bundled templates and example ``project1`` hierarchy, then downloads
|
|
185
234
|
MathJax into ``_template/mathjax`` so the builder can run immediately.
|
|
@@ -245,7 +294,7 @@ included are (listed in order of fun/utility):
|
|
|
245
294
|
The former ``git-latexdiffnocompile.sh`` is a compatibility wrapper for
|
|
246
295
|
``pydifft pd --no-compile``.
|
|
247
296
|
|
|
248
|
-
Run ``pydifft pd
|
|
297
|
+
Run ``pydifft --add_to_git pd`` to install the global ``git pd`` alias.
|
|
249
298
|
It accepts Git diff arguments: ``git pd 00ffaa -- filename.md`` compares
|
|
250
299
|
that revision with the working file; bare ``git pd`` compares unstaged
|
|
251
300
|
changes; ``git pd --cached`` compares staged changes; and
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyDiffTools
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.53
|
|
4
4
|
Summary: Diff tools
|
|
5
5
|
Author: J M Franck
|
|
6
6
|
License: Copyright (c) 2015, jmfranck
|
|
@@ -72,6 +72,30 @@ included are (listed in order of fun/utility):
|
|
|
72
72
|
`filename.md`, build the result,
|
|
73
73
|
and displays it in your browser.
|
|
74
74
|
|
|
75
|
+
Source diff linting minimizes line-break changes against the Git index
|
|
76
|
+
(staging area) by default, matching plain ``git diff``. Use
|
|
77
|
+
``pydifft cpb filename.md --diff-base @`` to compare against HEAD, or
|
|
78
|
+
``--diff-base jf_last`` to compare against a tag, branch, or commit hash.
|
|
79
|
+
The selected baseline is read again on each build. An unreadable explicit
|
|
80
|
+
baseline stops the build; an unavailable index baseline, such as for an
|
|
81
|
+
untracked file, falls back to ordinary source linting.
|
|
82
|
+
All diff-minimizing line-break fixes are applied automatically before
|
|
83
|
+
their notice appears. Each page shows as many changed hunks as fit in the
|
|
84
|
+
window, with a blank line separating hunks; larger changes are applied
|
|
85
|
+
just like single-break changes.
|
|
86
|
+
Diff alignment has separate eligibility rules from prose linting.
|
|
87
|
+
Equations and HTML comment contents participate in alignment, including
|
|
88
|
+
hunks that begin inside them. Display equations and hidden text remain
|
|
89
|
+
exempt from prose wrapping and sentence rules. Equation delimiters are
|
|
90
|
+
matched independently of their contents, and surviving matches on either
|
|
91
|
+
side of an edit restore whitespace while preserving changed values and
|
|
92
|
+
TeX commands. Literal delimiters in code are preserved.
|
|
93
|
+
Leading whitespace at matching line starts is restored in top-level
|
|
94
|
+
prose when both margins contain at most three spaces, and inside HTML
|
|
95
|
+
comments and equations. Container indentation (lists, definitions, and
|
|
96
|
+
quotations), tabs or four-space code indentation outside those spans,
|
|
97
|
+
and protected blocks retain their current margins.
|
|
98
|
+
|
|
75
99
|
Continuous pandoc build.
|
|
76
100
|
This works *very well* together
|
|
77
101
|
with the `g/` vim command
|
|
@@ -205,6 +229,12 @@ included are (listed in order of fun/utility):
|
|
|
205
229
|
``_build``/``_display`` directories; with ``--watch`` it starts the HTTP
|
|
206
230
|
server and automatically rebuilds the staged fragments whenever you edit
|
|
207
231
|
a ``.qmd`` file.
|
|
232
|
+
Browser previews in ``qmdb``, ``cpb``, and ``wgrph`` share the same
|
|
233
|
+
Selenium launcher: Chrome/Chromium is preferred, with Firefox as a
|
|
234
|
+
fallback. Installed ``chromedriver`` and ``geckodriver`` are used directly
|
|
235
|
+
without online driver discovery; if only ``geckodriver`` is installed,
|
|
236
|
+
Firefox opens directly. With neither driver installed, Selenium handles
|
|
237
|
+
discovery. Chrome startup failures are reported before trying Firefox.
|
|
208
238
|
- ``pydifft tree`` (or ``git tree`` with the alias installed) opens the last
|
|
209
239
|
40 commits across all branches, in Git date order. Use the down arrow
|
|
210
240
|
below the history to add the next 40 commits. Colors follow
|
|
@@ -215,7 +245,7 @@ included are (listed in order of fun/utility):
|
|
|
215
245
|
or set a commit as the comparison endpoint. The right-click menu can restore
|
|
216
246
|
the working-directory endpoint. Diff window titles show the equivalent
|
|
217
247
|
arguments, preferring tags, then branch names, then six-character hashes.
|
|
218
|
-
Run ``pydifft tree
|
|
248
|
+
Run ``pydifft --add_to_git tree`` to add the matching ``git tree`` alias.
|
|
219
249
|
- ``pydifft gd`` (or ``git gd`` with the alias installed) reviews unstaged
|
|
220
250
|
changes, like bare ``git diff``.
|
|
221
251
|
``pydifft gd [git diff args...]`` shows the same Qt review table as the old
|
|
@@ -229,12 +259,31 @@ included are (listed in order of fun/utility):
|
|
|
229
259
|
among the original, difference, and aligned new image. Images with an
|
|
230
260
|
alpha channel are displayed over a checkerboard; when transparency
|
|
231
261
|
changes, an additional red/blue alpha-difference view is included.
|
|
232
|
-
Run ``pydifft gd
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
262
|
+
Run ``pydifft --add_to_git gd`` to install the global ``git gd`` alias,
|
|
263
|
+
retaining the exact command of an existing global ``gd`` alias. If none
|
|
264
|
+
is configured, it installs ``!f() { pydifft gd "$@"; }; f``.
|
|
265
|
+
Configure ``difftool.mygvim.cmd`` for the GUI diff tool.
|
|
266
|
+
- ``pydifft --add_to_git gd pd tree mergein`` installs any selected subset
|
|
267
|
+
of these global Git aliases in one invocation. Installation appears
|
|
268
|
+
alongside the subcommands in root help; the former per-command
|
|
269
|
+
``--install`` and ``--add-to-git`` flags have been removed.
|
|
270
|
+
- ``pydifft mergein BRANCH [--remote REMOTE]`` updates an incoming local
|
|
271
|
+
branch without switching branches, then merges it into the current
|
|
272
|
+
branch. Install ``git mergein`` with ``pydifft --add_to_git mergein``.
|
|
273
|
+
``git mergein incoming/topic`` runs ``git fetch origin
|
|
274
|
+
incoming/topic:incoming/topic`` followed by ``git merge --no-ff
|
|
275
|
+
incoming/topic``. Use ``--remote upstream`` to select another remote;
|
|
276
|
+
``origin`` is the default. Fetch failures stop the sequence, local
|
|
277
|
+
branch updates are not forced, and merge conflicts remain available
|
|
278
|
+
for normal Git resolution.
|
|
279
|
+
|
|
280
|
+
Installing ``mergein`` also installs its Bash completion in the user
|
|
281
|
+
Bash completion directory (honoring ``BASH_COMPLETION_USER_DIR`` and
|
|
282
|
+
``XDG_DATA_HOME``). With standard Git Bash completion enabled,
|
|
283
|
+
``git mergein`` suggests cached branches of the selected remote, using
|
|
284
|
+
bare branch names such as ``incoming/topic``. Completion does not
|
|
285
|
+
contact the remote; fetch to refresh the suggestions. The ``pydifft``
|
|
286
|
+
form supports the same suggestions when argcomplete is enabled.
|
|
238
287
|
- `pydifft qmdinit [directory]` scaffolds a new Quarto-style project using
|
|
239
288
|
the bundled templates and example ``project1`` hierarchy, then downloads
|
|
240
289
|
MathJax into ``_template/mathjax`` so the builder can run immediately.
|
|
@@ -300,7 +349,7 @@ included are (listed in order of fun/utility):
|
|
|
300
349
|
The former ``git-latexdiffnocompile.sh`` is a compatibility wrapper for
|
|
301
350
|
``pydifft pd --no-compile``.
|
|
302
351
|
|
|
303
|
-
Run ``pydifft pd
|
|
352
|
+
Run ``pydifft --add_to_git pd`` to install the global ``git pd`` alias.
|
|
304
353
|
It accepts Git diff arguments: ``git pd 00ffaa -- filename.md`` compares
|
|
305
354
|
that revision with the working file; bare ``git pd`` compares unstaged
|
|
306
355
|
changes; ``git pd --cached`` compares staged changes; and
|
|
@@ -90,6 +90,7 @@ pydifftools/wrap_sentences.py
|
|
|
90
90
|
pydifftools/wrapping_options.py
|
|
91
91
|
pydifftools/xml2xlsx.vbs
|
|
92
92
|
pydifftools/zotero.py
|
|
93
|
+
pydifftools/completions/git-mergein
|
|
93
94
|
pydifftools/flowchart/__init__.py
|
|
94
95
|
pydifftools/flowchart/comparison.py
|
|
95
96
|
pydifftools/flowchart/dot_to_yaml.py
|
|
@@ -113,6 +114,7 @@ tests/test_forward_search.py
|
|
|
113
114
|
tests/test_git_gd_history.py
|
|
114
115
|
tests/test_git_gd_image.py
|
|
115
116
|
tests/test_git_gd_qt.py
|
|
117
|
+
tests/test_git_mergein.py
|
|
116
118
|
tests/test_git_pdf_diff.py
|
|
117
119
|
tests/test_line_alignment.py
|
|
118
120
|
tests/test_pdf_diff.py
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import re
|
|
3
|
+
import shutil
|
|
4
|
+
import subprocess
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
# callbacks that run before any dialog needs the user; cpb registers one
|
|
8
|
+
# that closes its live preview, so issues are dealt with before it reopens
|
|
9
|
+
dialog_callbacks = []
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# also used by: continuous.py, notebook/fast_build.py, flowchart/watch_graph.py
|
|
13
|
+
def start_browser():
|
|
14
|
+
"""Prefer Chrome/Chromium, using installed drivers before discovery.
|
|
15
|
+
|
|
16
|
+
If only GeckoDriver is installed, use Firefox directly. Otherwise try
|
|
17
|
+
Chrome first, including version-mismatch recovery, then Firefox.
|
|
18
|
+
"""
|
|
19
|
+
from selenium import webdriver
|
|
20
|
+
from selenium.common.exceptions import (
|
|
21
|
+
SessionNotCreatedException,
|
|
22
|
+
WebDriverException,
|
|
23
|
+
)
|
|
24
|
+
from selenium.webdriver.chrome.service import Service as ChromeService
|
|
25
|
+
from selenium.webdriver.firefox.service import Service as FirefoxService
|
|
26
|
+
|
|
27
|
+
chrome_driver = shutil.which("chromedriver")
|
|
28
|
+
firefox_driver = shutil.which("geckodriver")
|
|
29
|
+
chrome_error = None
|
|
30
|
+
if chrome_driver or not firefox_driver:
|
|
31
|
+
# {{{ Use installed ChromeDriver without an online Manager lookup
|
|
32
|
+
kwargs = {}
|
|
33
|
+
if chrome_driver:
|
|
34
|
+
options = webdriver.ChromeOptions()
|
|
35
|
+
# Debian's driver defaults to Chromium even if Chrome is installed;
|
|
36
|
+
# retain Selenium Manager's preference for Google Chrome.
|
|
37
|
+
browser_path = (
|
|
38
|
+
shutil.which("google-chrome")
|
|
39
|
+
or shutil.which("google-chrome-stable")
|
|
40
|
+
or shutil.which("chromium")
|
|
41
|
+
or shutil.which("chromium-browser")
|
|
42
|
+
)
|
|
43
|
+
if browser_path:
|
|
44
|
+
options.binary_location = browser_path
|
|
45
|
+
kwargs = {
|
|
46
|
+
"service": ChromeService(chrome_driver),
|
|
47
|
+
"options": options,
|
|
48
|
+
}
|
|
49
|
+
# }}}
|
|
50
|
+
try:
|
|
51
|
+
try:
|
|
52
|
+
return webdriver.Chrome(**kwargs)
|
|
53
|
+
except SessionNotCreatedException as exc:
|
|
54
|
+
# {{{ Retry ChromeDriver's explicit browser-version rejection
|
|
55
|
+
details = str(exc)
|
|
56
|
+
driver_match = re.search(
|
|
57
|
+
r"ChromeDriver only supports Chrome version (\d+)", details
|
|
58
|
+
)
|
|
59
|
+
browser_match = re.search(
|
|
60
|
+
r"Current browser version is (\d+)", details
|
|
61
|
+
)
|
|
62
|
+
if driver_match is None or browser_match is None:
|
|
63
|
+
raise
|
|
64
|
+
print(
|
|
65
|
+
"pydifft: warning: ChromeDriver "
|
|
66
|
+
f"{driver_match.group(1)} and Chrome "
|
|
67
|
+
f"{browser_match.group(1)} do not match; retrying "
|
|
68
|
+
"with the driver version check disabled.",
|
|
69
|
+
file=sys.stderr,
|
|
70
|
+
)
|
|
71
|
+
service = kwargs.get("service")
|
|
72
|
+
kwargs["service"] = ChromeService(
|
|
73
|
+
executable_path=service.path if service else None,
|
|
74
|
+
service_args=[
|
|
75
|
+
*(service.service_args if service else []),
|
|
76
|
+
"--disable-build-check",
|
|
77
|
+
],
|
|
78
|
+
)
|
|
79
|
+
return webdriver.Chrome(**kwargs)
|
|
80
|
+
# }}}
|
|
81
|
+
except WebDriverException as exc:
|
|
82
|
+
chrome_error = exc
|
|
83
|
+
print(
|
|
84
|
+
f"pydifft: warning: Chrome/Chromium could not start: {exc}\n"
|
|
85
|
+
"Trying Firefox instead.",
|
|
86
|
+
file=sys.stderr,
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
try:
|
|
90
|
+
if firefox_driver:
|
|
91
|
+
return webdriver.Firefox(service=FirefoxService(firefox_driver))
|
|
92
|
+
return webdriver.Firefox()
|
|
93
|
+
except WebDriverException as exc:
|
|
94
|
+
if chrome_error is not None:
|
|
95
|
+
raise exc from chrome_error
|
|
96
|
+
raise
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def prepare_for_dialog():
|
|
100
|
+
"""Let watch commands close their preview before a dialog appears."""
|
|
101
|
+
for callback in list(dialog_callbacks):
|
|
102
|
+
callback()
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
# also used by: continuous.py, notebook/fast_build.py, flowchart/watch_graph.py
|
|
106
|
+
def browser_window_is_alive(browser):
|
|
107
|
+
# Keep all browser liveness checks in one place so watch commands share
|
|
108
|
+
# the same shutdown behavior when a user closes the browser window.
|
|
109
|
+
# Do not probe with execute_script here: page navigations can briefly
|
|
110
|
+
# interrupt script execution even while the window is still open.
|
|
111
|
+
if browser is None:
|
|
112
|
+
return False
|
|
113
|
+
try:
|
|
114
|
+
handles = browser.window_handles
|
|
115
|
+
if not handles:
|
|
116
|
+
return False
|
|
117
|
+
return True
|
|
118
|
+
except Exception:
|
|
119
|
+
return False
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def close_browser_window(browser):
|
|
123
|
+
# Close a Selenium browser session and ignore errors from already-closed
|
|
124
|
+
# windows so cleanup paths stay simple.
|
|
125
|
+
if browser is None:
|
|
126
|
+
return
|
|
127
|
+
try:
|
|
128
|
+
browser.quit()
|
|
129
|
+
except Exception:
|
|
130
|
+
pass
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
# also used by: notebook/fast_build.py (qmdb's forward search), besides
|
|
134
|
+
# cpb in continuous.py; tests/test_continuous_shutdown.py monkeypatches it
|
|
135
|
+
def forward_search_in_browser(browser, search_text):
|
|
136
|
+
# Reuse the same browser-side find logic across cpb and qmdb.
|
|
137
|
+
if browser is None or not search_text:
|
|
138
|
+
return False
|
|
139
|
+
found = browser.execute_script(
|
|
140
|
+
"""
|
|
141
|
+
var searchText = arguments[0];
|
|
142
|
+
if (!window.find) {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
var didFind = window.find(searchText);
|
|
146
|
+
if (didFind && window.getSelection) {
|
|
147
|
+
var selection = window.getSelection();
|
|
148
|
+
if (selection.rangeCount > 0) {
|
|
149
|
+
var rect = selection.getRangeAt(0).getBoundingClientRect();
|
|
150
|
+
window.scrollBy(0, rect.top - window.innerHeight / 3);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return didFind;
|
|
154
|
+
""",
|
|
155
|
+
search_text,
|
|
156
|
+
)
|
|
157
|
+
if not found:
|
|
158
|
+
print("forward search did not find text:", search_text)
|
|
159
|
+
# Bring the browser window to the foreground in Linux window managers,
|
|
160
|
+
# but only when it found the text, since every qmdb session hears it.
|
|
161
|
+
if found and os.name == "posix" and shutil.which("wmctrl"):
|
|
162
|
+
window_title = browser.execute_script("return document.title;")
|
|
163
|
+
if window_title:
|
|
164
|
+
# Try common browser title forms used by desktop environments.
|
|
165
|
+
for title_candidate in [
|
|
166
|
+
window_title,
|
|
167
|
+
window_title + " - Google Chrome",
|
|
168
|
+
window_title + " - Chromium",
|
|
169
|
+
window_title + " - Chrome",
|
|
170
|
+
window_title + " - Mozilla Firefox",
|
|
171
|
+
]:
|
|
172
|
+
subprocess.run(["wmctrl", "-a", title_candidate], check=False)
|
|
173
|
+
return found
|
|
@@ -37,6 +37,9 @@ from .searchacro import replace_acros
|
|
|
37
37
|
from .rearrange_tex import run as rearrange_tex_run
|
|
38
38
|
from .git_gd import gd # registers git difftool review command
|
|
39
39
|
from .pdf_diff import pd, git_pd # registers PDF diff command
|
|
40
|
+
from .git_aliases import (
|
|
41
|
+
GIT_ALIASES, install_git_alias, mergein_completer,
|
|
42
|
+
)
|
|
40
43
|
from .flowchart.watch_graph import wgrph
|
|
41
44
|
from .flowchart.graph import load_graph_yaml
|
|
42
45
|
from .notebook.tex_to_qmd import tex2qmd
|
|
@@ -45,6 +48,7 @@ from .notebook.fast_build import (
|
|
|
45
48
|
qmdinit,
|
|
46
49
|
QMDB_FORWARD_SEARCH_HOST,
|
|
47
50
|
QMDB_FORWARD_SEARCH_PORT,
|
|
51
|
+
QMDB_PORT_ATTEMPTS,
|
|
48
52
|
)
|
|
49
53
|
|
|
50
54
|
from .command_registry import _COMMAND_SPECS, register_command
|
|
@@ -575,13 +579,17 @@ def mfs(text):
|
|
|
575
579
|
search_text = text.strip()
|
|
576
580
|
|
|
577
581
|
# Try existing cpb and qmdb listeners before launching a new cpb process.
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
582
|
+
# Several qmdb sessions can run at once on consecutive ports; each one
|
|
583
|
+
# receives the search and only a browser that finds the text comes
|
|
584
|
+
# forward.
|
|
585
|
+
socket_addresses = [(FORWARD_SEARCH_HOST, FORWARD_SEARCH_PORT)] + [
|
|
586
|
+
(QMDB_FORWARD_SEARCH_HOST, QMDB_FORWARD_SEARCH_PORT + offset)
|
|
587
|
+
for offset in range(QMDB_PORT_ATTEMPTS)
|
|
581
588
|
]
|
|
582
589
|
|
|
583
590
|
def try_existing_listener():
|
|
584
591
|
protocol_errors = []
|
|
592
|
+
delivered = False
|
|
585
593
|
for address in socket_addresses:
|
|
586
594
|
try:
|
|
587
595
|
send_forward_search(address, search_text)
|
|
@@ -590,6 +598,10 @@ def mfs(text):
|
|
|
590
598
|
except ForwardSearchProtocolError as exc:
|
|
591
599
|
protocol_errors.append(str(exc))
|
|
592
600
|
continue
|
|
601
|
+
if address == socket_addresses[0]:
|
|
602
|
+
return True
|
|
603
|
+
delivered = True
|
|
604
|
+
if delivered:
|
|
593
605
|
return True
|
|
594
606
|
if protocol_errors:
|
|
595
607
|
raise RuntimeError(
|
|
@@ -902,8 +914,14 @@ def build_parser():
|
|
|
902
914
|
)
|
|
903
915
|
parser.epilog = _subcommand_help_hint(parser.prog)
|
|
904
916
|
parser._pydifft_subparsers = {}
|
|
905
|
-
subparsers = parser.add_subparsers(dest="command")
|
|
906
|
-
|
|
917
|
+
subparsers = parser.add_subparsers(dest="command", title="commands")
|
|
918
|
+
# Consume installer names exclusively, including during completion.
|
|
919
|
+
# argparse does not validate REMAINDER choices; main checks them first.
|
|
920
|
+
subparsers.container.add_argument(
|
|
921
|
+
"--add_to_git", nargs=argparse.REMAINDER, choices=list(GIT_ALIASES),
|
|
922
|
+
help=("Install one or more global Git aliases: gd, pd, tree, mergein "
|
|
923
|
+
"(without a subcommand)."),
|
|
924
|
+
)
|
|
907
925
|
for name, spec in _COMMAND_SPECS.items():
|
|
908
926
|
subparser = subparsers.add_parser(
|
|
909
927
|
name,
|
|
@@ -926,6 +944,8 @@ def build_parser():
|
|
|
926
944
|
if name == "wgrph" and action.dest == "t":
|
|
927
945
|
# Offer case-insensitive completions for incomplete task names.
|
|
928
946
|
action.completer = wgrph_task_completer
|
|
947
|
+
if name == "mergein" and action.dest in ("branch", "remote"):
|
|
948
|
+
action.completer = mergein_completer
|
|
929
949
|
subparser.set_defaults(_handler=spec["handler"])
|
|
930
950
|
parser._pydifft_subparsers[name] = subparser
|
|
931
951
|
return parser
|
|
@@ -985,6 +1005,25 @@ def main(argv=None):
|
|
|
985
1005
|
parser._pydifft_subparsers[subcommand].print_help()
|
|
986
1006
|
return
|
|
987
1007
|
namespace = parser.parse_args(argv)
|
|
1008
|
+
if namespace.add_to_git is not None:
|
|
1009
|
+
if not namespace.add_to_git:
|
|
1010
|
+
parser.error("--add_to_git requires at least one command name")
|
|
1011
|
+
unknown_names = [
|
|
1012
|
+
name for name in namespace.add_to_git if name not in GIT_ALIASES
|
|
1013
|
+
]
|
|
1014
|
+
if unknown_names:
|
|
1015
|
+
parser.error(
|
|
1016
|
+
"unknown Git alias name(s): " + ", ".join(unknown_names)
|
|
1017
|
+
)
|
|
1018
|
+
if namespace.command is not None:
|
|
1019
|
+
parser.error("--add_to_git cannot be combined with a subcommand")
|
|
1020
|
+
for name in dict.fromkeys(namespace.add_to_git):
|
|
1021
|
+
install_git_alias(
|
|
1022
|
+
name, GIT_ALIASES[name], preserve_existing=(name == "gd"),
|
|
1023
|
+
)
|
|
1024
|
+
return
|
|
1025
|
+
if namespace.command is None:
|
|
1026
|
+
parser.error("a subcommand or --add_to_git is required")
|
|
988
1027
|
# Shared wrapping arguments are validated identically for each command.
|
|
989
1028
|
if hasattr(namespace, "wrapnumber") and namespace.wrapnumber < 1:
|
|
990
1029
|
parser._pydifft_subparsers[namespace.command].error(
|
|
@@ -1016,6 +1055,7 @@ def main(argv=None):
|
|
|
1016
1055
|
handler_kwargs = dict(vars(namespace))
|
|
1017
1056
|
handler_kwargs.pop("_handler", None)
|
|
1018
1057
|
handler_kwargs.pop("command", None)
|
|
1058
|
+
handler_kwargs.pop("add_to_git", None)
|
|
1019
1059
|
# {{{ explain Chrome and ChromeDriver version mismatches
|
|
1020
1060
|
from selenium.common.exceptions import SessionNotCreatedException
|
|
1021
1061
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Loaded by Git's Bash completion through _completion_loader git-mergein.
|
|
2
|
+
_git_mergein ()
|
|
3
|
+
{
|
|
4
|
+
local remote=origin branch_seen=0 expect_remote=0 end_options=0
|
|
5
|
+
local i word ref symref ref_prefix candidate
|
|
6
|
+
for ((i = __git_cmd_idx + 1; i < cword; i++)); do
|
|
7
|
+
word=${words[i]}
|
|
8
|
+
if ((expect_remote)); then
|
|
9
|
+
remote=$word
|
|
10
|
+
expect_remote=0
|
|
11
|
+
elif ((end_options)); then
|
|
12
|
+
branch_seen=1
|
|
13
|
+
else
|
|
14
|
+
case "$word" in
|
|
15
|
+
--remote) expect_remote=1 ;;
|
|
16
|
+
--remote=*) remote=${word#--remote=} ;;
|
|
17
|
+
--) end_options=1 ;;
|
|
18
|
+
-*) ;;
|
|
19
|
+
*) branch_seen=1 ;;
|
|
20
|
+
esac
|
|
21
|
+
fi
|
|
22
|
+
done
|
|
23
|
+
if ((expect_remote)); then
|
|
24
|
+
__gitcomp_nl "$(__git remote)"
|
|
25
|
+
elif ((!end_options)) && [[ $cur == --remote=* ]]; then
|
|
26
|
+
__gitcomp_nl "$(__git remote)" "--remote=" "${cur#--remote=}"
|
|
27
|
+
elif ((!end_options)) && [[ $cur == -* ]]; then
|
|
28
|
+
__gitcomp "--remote --help"
|
|
29
|
+
elif ((!branch_seen)); then
|
|
30
|
+
ref_prefix="refs/remotes/$remote/"
|
|
31
|
+
local candidates=
|
|
32
|
+
while read -r ref symref; do
|
|
33
|
+
[[ $ref == "$ref_prefix"* && -z $symref ]] || continue
|
|
34
|
+
candidate=${ref#"$ref_prefix"}
|
|
35
|
+
[[ $candidate == HEAD ]] && continue
|
|
36
|
+
candidates+="$candidate"$'\n'
|
|
37
|
+
done < <(__git for-each-ref --format='%(refname) %(symref)' \
|
|
38
|
+
-- "$ref_prefix" 2>/dev/null)
|
|
39
|
+
__gitcomp_nl "$candidates"
|
|
40
|
+
fi
|
|
41
|
+
}
|