pyDiffTools 0.1.59__tar.gz → 0.1.60__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.59/pyDiffTools.egg-info → pydifftools-0.1.60}/PKG-INFO +26 -5
- {pydifftools-0.1.59 → pydifftools-0.1.60}/README.rst +25 -4
- {pydifftools-0.1.59 → pydifftools-0.1.60/pyDiffTools.egg-info}/PKG-INFO +26 -5
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pyDiffTools.egg-info/SOURCES.txt +3 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/command_line.py +49 -3
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/continuous.py +27 -5
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/forward_search.py +76 -1
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/git_gd.py +22 -3
- pydifftools-0.1.60/pydifftools/git_gd_terminal.py +182 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/line_alignment.py +28 -1
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/match_spaces.py +10 -2
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/wrap_sentences.py +6 -4
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/wrapping_options.py +7 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pyproject.toml +1 -1
- {pydifftools-0.1.59 → pydifftools-0.1.60}/tests/test_browser_lifecycle.py +5 -2
- {pydifftools-0.1.59 → pydifftools-0.1.60}/tests/test_command_line_help.py +6 -2
- {pydifftools-0.1.59 → pydifftools-0.1.60}/tests/test_continuous_shutdown.py +10 -7
- {pydifftools-0.1.59 → pydifftools-0.1.60}/tests/test_forward_search.py +40 -0
- pydifftools-0.1.60/tests/test_git_gd_terminal.py +98 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/tests/test_source_jump.py +2 -2
- {pydifftools-0.1.59 → pydifftools-0.1.60}/tests/test_wrap_check.py +17 -12
- {pydifftools-0.1.59 → pydifftools-0.1.60}/tests/test_wrapping.py +2 -7
- pydifftools-0.1.60/tests/test_wrapping_width_limits.py +91 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/LICENSE.md +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/MANIFEST.in +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/_quarto.yml +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/.jupyter_cache/__version__.txt +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/.jupyter_cache/executed/1a724af72b16f5a9e607e12b1c721645/base.ipynb +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/.jupyter_cache/executed/1b28fc9daac9081847e5161b2c546f8a/base.ipynb +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/.jupyter_cache/executed/231f64eee282fa225d1104935cf80a24/base.ipynb +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/.jupyter_cache/executed/26e56f6b0ff54851a45145157f2f0dc4/base.ipynb +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/.jupyter_cache/executed/311fabd7029ffd050d056e2f316eb50f/base.ipynb +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/.jupyter_cache/executed/57da2021e5b156ac3adf01398201c723/base.ipynb +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/.jupyter_cache/executed/62b24ea7da75011d92b0f8924faa208d/base.ipynb +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/.jupyter_cache/executed/7f1b20d69d889514ab5d1cc92e3cb14f/base.ipynb +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/.jupyter_cache/executed/86f74c8c54a87ff892d9b15dd714e8f0/base.ipynb +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/.jupyter_cache/executed/88893b4234eac2945d9d6cb2e277f186/base.ipynb +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/.jupyter_cache/executed/9a40046ada6f582ee34af00fbdbfb417/base.ipynb +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/.jupyter_cache/executed/a1bf4d270d0641ff41faf1d7cce3439a/base.ipynb +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/.jupyter_cache/executed/a3789f7d9585a781f2a1c60ce95ff10d/base.ipynb +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/.jupyter_cache/executed/be46ecba858d39ad5f0c46902ddf1c02/base.ipynb +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/.jupyter_cache/executed/d0cbc57a12f2ccce710a5afd04cc05e7/base.ipynb +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/.jupyter_cache/executed/d3e12d320b14228f701231ae32ddd7dd/base.ipynb +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/.jupyter_cache/executed/eb434f61555438d020a6970a5dbf9ee8/base.ipynb +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/.jupyter_cache/executed/f6b0e73aa7fa029134665d4dde57e096/base.ipynb +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/.jupyter_cache/executed/f719a6e4ff09873cb0ffb06ec9d232f9/base.ipynb +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/.jupyter_cache/executed/feeee244a7ce3d60e1a227eb604df823/base.ipynb +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/.jupyter_cache/global.db +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/example.qmd +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/example.tex +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/index.qmd +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/subproject1/.jupyter_cache/__version__.txt +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/subproject1/.jupyter_cache/executed/ca90e4df5f4f0583df6554156a68dc7f/base.ipynb +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/subproject1/.jupyter_cache/global.db +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/subproject1/end_vs_he_sketch.jpg +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/subproject1/independent.qmd +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/subproject1/index.qmd +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/subproject1/tasks.qmd +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/subproject1/test_include.qmd +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/subproject1/tryforerror.qmd +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/example_notebook/project1/test_include.qmd +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pyDiffTools.egg-info/dependency_links.txt +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pyDiffTools.egg-info/entry_points.txt +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pyDiffTools.egg-info/requires.txt +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pyDiffTools.egg-info/top_level.txt +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/__init__.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/bibliography.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/browser_lifecycle.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/check_numbers.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/citation_dialog.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/command_registry.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/comment_filter_history.json +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/comment_functions.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/comment_migration.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/comment_tags.lua +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/comment_tags_margin.lua +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/comment_tags_no_comments.lua +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/comment_toggle.js +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/comments.css +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/comments_author_colors.css +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/completions/git-mergein +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/copy_files.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/diff-doc.js +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/doc_contents.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/flowchart/__init__.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/flowchart/comparison.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/flowchart/dot_to_yaml.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/flowchart/graph.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/flowchart/source_jump.js +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/flowchart/svg-pan-zoom.min.js +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/flowchart/watch_graph.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/flowchart/wgrph_view.js +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/git_aliases.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/git_gd_history.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/git_gd_image.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/git_gd_qt.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/git_reattach.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/html_comments.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/html_uncomments.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/log_example.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/notebook/__init__.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/notebook/display.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/notebook/fast_build.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/notebook/tex_to_qmd.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/onewordify.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/onewordify_undo.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/outline.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/pdf_diff.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/rearrange_tex.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/searchacro.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/separate_comments.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/source_jump.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/split_conflict.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/unseparate_comments.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/update_check.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/xml2xlsx.vbs +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/pydifftools/zotero.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/setup.cfg +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/tests/test_bibliography.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/tests/test_check_single_use.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/tests/test_comment_filters.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/tests/test_comment_migration.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/tests/test_git_gd_history.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/tests/test_git_gd_image.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/tests/test_git_gd_qt.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/tests/test_git_mergein.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/tests/test_git_pdf_diff.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/tests/test_git_reattach.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/tests/test_line_alignment.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/tests/test_pdf_diff.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/tests/test_qt_lifecycle.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/tests/test_rrng.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/tests/test_tex_to_qmd.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/tests/test_update_check.py +0 -0
- {pydifftools-0.1.59 → pydifftools-0.1.60}/tests/test_zotero.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyDiffTools
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.60
|
|
4
4
|
Summary: Diff tools
|
|
5
5
|
Author: J M Franck
|
|
6
6
|
License: Copyright (c) 2015, jmfranck
|
|
@@ -274,6 +274,12 @@ included are (listed in order of fun/utility):
|
|
|
274
274
|
retaining the exact command of an existing global ``gd`` alias. If none
|
|
275
275
|
is configured, it installs ``!f() { pydifft gd "$@"; }; f``.
|
|
276
276
|
Configure ``difftool.mygvim.cmd`` for the GUI diff tool.
|
|
277
|
+
Use ``pydifft gd --terminal [git diff args...]`` for a colored terminal
|
|
278
|
+
picker that opens diffs in foreground Vim without GUI configuration.
|
|
279
|
+
Navigate with arrows or ``j``/``k``, press Enter to open a diff, Space to
|
|
280
|
+
toggle its reviewed marker, and ``q`` to quit. Closing Vim returns to the
|
|
281
|
+
picker. Images and other binary files are skipped. Set ``NO_COLOR`` to
|
|
282
|
+
disable colors.
|
|
277
283
|
- ``pydifft --add_to_git gd pd tree mergein reattach`` installs any selected subset
|
|
278
284
|
of these global Git aliases in one invocation. Installation appears
|
|
279
285
|
alongside the subcommands in root help; the former per-command
|
|
@@ -328,10 +334,14 @@ included are (listed in order of fun/utility):
|
|
|
328
334
|
their words using Git's minimal diff, and restores reference whitespace.
|
|
329
335
|
It then considers extra breaks that preserve an unchanged reference line
|
|
330
336
|
without stranding an edited fragment of three words or fewer, and checks
|
|
331
|
-
wrapping rules.
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
337
|
+
wrapping rules. ``--desired-width`` (default 45) limits the width of
|
|
338
|
+
lines created by removing existing breaks to match Git. Breaks are
|
|
339
|
+
retained when joining would exceed that desired width.
|
|
340
|
+
|
|
341
|
+
* ``--wrapnumber`` independently sets the maximum width (79 for ``cpb``
|
|
342
|
+
and ``wmatch``), including for stable prose from the Git baseline.
|
|
343
|
+
For example, ``cpb --desired-width 50 --wrapnumber 85 manuscript.md``
|
|
344
|
+
changes both limits.
|
|
335
345
|
Wmatch also uses nearby reference widths for large edits, retaining
|
|
336
346
|
unchanged reference lines and protected Markdown blocks.
|
|
337
347
|
|
|
@@ -408,3 +418,14 @@ Future versions will include:
|
|
|
408
418
|
- Scripts for converting word html comments to latex commands.
|
|
409
419
|
|
|
410
420
|
- converting to/form one word per line files (for doing things like wdiff, but with more control)
|
|
421
|
+
|
|
422
|
+
Concurrent cpb previews
|
|
423
|
+
-----------------------
|
|
424
|
+
|
|
425
|
+
``cpb`` starts at loopback port 51235 and reports occupied ports to stdout
|
|
426
|
+
before trying the next port. The first process keeps a directory-to-port
|
|
427
|
+
registry; subsequent previews register their source file's directory there.
|
|
428
|
+
Run ``pydifft mfs`` from that directory to search the matching preview.
|
|
429
|
+
Directory paths are resolved so symlink aliases identify the same project.
|
|
430
|
+
Keep the first process open while using the other previews: its registry
|
|
431
|
+
lives in memory and ends when that process exits.
|
|
@@ -219,6 +219,12 @@ included are (listed in order of fun/utility):
|
|
|
219
219
|
retaining the exact command of an existing global ``gd`` alias. If none
|
|
220
220
|
is configured, it installs ``!f() { pydifft gd "$@"; }; f``.
|
|
221
221
|
Configure ``difftool.mygvim.cmd`` for the GUI diff tool.
|
|
222
|
+
Use ``pydifft gd --terminal [git diff args...]`` for a colored terminal
|
|
223
|
+
picker that opens diffs in foreground Vim without GUI configuration.
|
|
224
|
+
Navigate with arrows or ``j``/``k``, press Enter to open a diff, Space to
|
|
225
|
+
toggle its reviewed marker, and ``q`` to quit. Closing Vim returns to the
|
|
226
|
+
picker. Images and other binary files are skipped. Set ``NO_COLOR`` to
|
|
227
|
+
disable colors.
|
|
222
228
|
- ``pydifft --add_to_git gd pd tree mergein reattach`` installs any selected subset
|
|
223
229
|
of these global Git aliases in one invocation. Installation appears
|
|
224
230
|
alongside the subcommands in root help; the former per-command
|
|
@@ -273,10 +279,14 @@ included are (listed in order of fun/utility):
|
|
|
273
279
|
their words using Git's minimal diff, and restores reference whitespace.
|
|
274
280
|
It then considers extra breaks that preserve an unchanged reference line
|
|
275
281
|
without stranding an edited fragment of three words or fewer, and checks
|
|
276
|
-
wrapping rules.
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
282
|
+
wrapping rules. ``--desired-width`` (default 45) limits the width of
|
|
283
|
+
lines created by removing existing breaks to match Git. Breaks are
|
|
284
|
+
retained when joining would exceed that desired width.
|
|
285
|
+
|
|
286
|
+
* ``--wrapnumber`` independently sets the maximum width (79 for ``cpb``
|
|
287
|
+
and ``wmatch``), including for stable prose from the Git baseline.
|
|
288
|
+
For example, ``cpb --desired-width 50 --wrapnumber 85 manuscript.md``
|
|
289
|
+
changes both limits.
|
|
280
290
|
Wmatch also uses nearby reference widths for large edits, retaining
|
|
281
291
|
unchanged reference lines and protected Markdown blocks.
|
|
282
292
|
|
|
@@ -353,3 +363,14 @@ Future versions will include:
|
|
|
353
363
|
- Scripts for converting word html comments to latex commands.
|
|
354
364
|
|
|
355
365
|
- converting to/form one word per line files (for doing things like wdiff, but with more control)
|
|
366
|
+
|
|
367
|
+
Concurrent cpb previews
|
|
368
|
+
-----------------------
|
|
369
|
+
|
|
370
|
+
``cpb`` starts at loopback port 51235 and reports occupied ports to stdout
|
|
371
|
+
before trying the next port. The first process keeps a directory-to-port
|
|
372
|
+
registry; subsequent previews register their source file's directory there.
|
|
373
|
+
Run ``pydifft mfs`` from that directory to search the matching preview.
|
|
374
|
+
Directory paths are resolved so symlink aliases identify the same project.
|
|
375
|
+
Keep the first process open while using the other previews: its registry
|
|
376
|
+
lives in memory and ends when that process exits.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyDiffTools
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.60
|
|
4
4
|
Summary: Diff tools
|
|
5
5
|
Author: J M Franck
|
|
6
6
|
License: Copyright (c) 2015, jmfranck
|
|
@@ -274,6 +274,12 @@ included are (listed in order of fun/utility):
|
|
|
274
274
|
retaining the exact command of an existing global ``gd`` alias. If none
|
|
275
275
|
is configured, it installs ``!f() { pydifft gd "$@"; }; f``.
|
|
276
276
|
Configure ``difftool.mygvim.cmd`` for the GUI diff tool.
|
|
277
|
+
Use ``pydifft gd --terminal [git diff args...]`` for a colored terminal
|
|
278
|
+
picker that opens diffs in foreground Vim without GUI configuration.
|
|
279
|
+
Navigate with arrows or ``j``/``k``, press Enter to open a diff, Space to
|
|
280
|
+
toggle its reviewed marker, and ``q`` to quit. Closing Vim returns to the
|
|
281
|
+
picker. Images and other binary files are skipped. Set ``NO_COLOR`` to
|
|
282
|
+
disable colors.
|
|
277
283
|
- ``pydifft --add_to_git gd pd tree mergein reattach`` installs any selected subset
|
|
278
284
|
of these global Git aliases in one invocation. Installation appears
|
|
279
285
|
alongside the subcommands in root help; the former per-command
|
|
@@ -328,10 +334,14 @@ included are (listed in order of fun/utility):
|
|
|
328
334
|
their words using Git's minimal diff, and restores reference whitespace.
|
|
329
335
|
It then considers extra breaks that preserve an unchanged reference line
|
|
330
336
|
without stranding an edited fragment of three words or fewer, and checks
|
|
331
|
-
wrapping rules.
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
337
|
+
wrapping rules. ``--desired-width`` (default 45) limits the width of
|
|
338
|
+
lines created by removing existing breaks to match Git. Breaks are
|
|
339
|
+
retained when joining would exceed that desired width.
|
|
340
|
+
|
|
341
|
+
* ``--wrapnumber`` independently sets the maximum width (79 for ``cpb``
|
|
342
|
+
and ``wmatch``), including for stable prose from the Git baseline.
|
|
343
|
+
For example, ``cpb --desired-width 50 --wrapnumber 85 manuscript.md``
|
|
344
|
+
changes both limits.
|
|
335
345
|
Wmatch also uses nearby reference widths for large edits, retaining
|
|
336
346
|
unchanged reference lines and protected Markdown blocks.
|
|
337
347
|
|
|
@@ -408,3 +418,14 @@ Future versions will include:
|
|
|
408
418
|
- Scripts for converting word html comments to latex commands.
|
|
409
419
|
|
|
410
420
|
- converting to/form one word per line files (for doing things like wdiff, but with more control)
|
|
421
|
+
|
|
422
|
+
Concurrent cpb previews
|
|
423
|
+
-----------------------
|
|
424
|
+
|
|
425
|
+
``cpb`` starts at loopback port 51235 and reports occupied ports to stdout
|
|
426
|
+
before trying the next port. The first process keeps a directory-to-port
|
|
427
|
+
registry; subsequent previews register their source file's directory there.
|
|
428
|
+
Run ``pydifft mfs`` from that directory to search the matching preview.
|
|
429
|
+
Directory paths are resolved so symlink aliases identify the same project.
|
|
430
|
+
Keep the first process open while using the other previews: its registry
|
|
431
|
+
lives in memory and ends when that process exits.
|
|
@@ -70,6 +70,7 @@ pydifftools/git_gd.py
|
|
|
70
70
|
pydifftools/git_gd_history.py
|
|
71
71
|
pydifftools/git_gd_image.py
|
|
72
72
|
pydifftools/git_gd_qt.py
|
|
73
|
+
pydifftools/git_gd_terminal.py
|
|
73
74
|
pydifftools/git_reattach.py
|
|
74
75
|
pydifftools/html_comments.py
|
|
75
76
|
pydifftools/html_uncomments.py
|
|
@@ -115,6 +116,7 @@ tests/test_forward_search.py
|
|
|
115
116
|
tests/test_git_gd_history.py
|
|
116
117
|
tests/test_git_gd_image.py
|
|
117
118
|
tests/test_git_gd_qt.py
|
|
119
|
+
tests/test_git_gd_terminal.py
|
|
118
120
|
tests/test_git_mergein.py
|
|
119
121
|
tests/test_git_pdf_diff.py
|
|
120
122
|
tests/test_git_reattach.py
|
|
@@ -127,4 +129,5 @@ tests/test_tex_to_qmd.py
|
|
|
127
129
|
tests/test_update_check.py
|
|
128
130
|
tests/test_wrap_check.py
|
|
129
131
|
tests/test_wrapping.py
|
|
132
|
+
tests/test_wrapping_width_limits.py
|
|
130
133
|
tests/test_zotero.py
|
|
@@ -25,6 +25,7 @@ from .forward_search import (
|
|
|
25
25
|
ForwardSearchProtocolError,
|
|
26
26
|
ForwardSearchUnavailable,
|
|
27
27
|
send_forward_search,
|
|
28
|
+
directory_port,
|
|
28
29
|
)
|
|
29
30
|
from .wrap_sentences import wr as wrap_sentences_wr # registers wrap command
|
|
30
31
|
from .wrap_sentences import ( # registers wrchk command
|
|
@@ -55,7 +56,8 @@ from .notebook.fast_build import (
|
|
|
55
56
|
|
|
56
57
|
from .command_registry import _COMMAND_SPECS, register_command
|
|
57
58
|
from .wrapping_options import (
|
|
58
|
-
DEFAULT_WIDTH,
|
|
59
|
+
DEFAULT_WIDTH, DEFAULT_DESIRED_WIDTH,
|
|
60
|
+
DEFAULT_TRAILING_DEPENDENT_PHRASE, WRAPPING_ARGUMENTS,
|
|
59
61
|
)
|
|
60
62
|
|
|
61
63
|
_ARGCOMPLETE_SPEC = importlib.util.find_spec("argcomplete")
|
|
@@ -388,8 +390,11 @@ def gvr(arguments):
|
|
|
388
390
|
def wmatch(
|
|
389
391
|
arguments, wrapnumber=DEFAULT_WIDTH,
|
|
390
392
|
trailing_dependent_phrase=DEFAULT_TRAILING_DEPENDENT_PHRASE,
|
|
393
|
+
desired_width=DEFAULT_DESIRED_WIDTH,
|
|
391
394
|
):
|
|
392
|
-
match_spaces.run(
|
|
395
|
+
match_spaces.run(
|
|
396
|
+
arguments, wrapnumber, trailing_dependent_phrase, desired_width,
|
|
397
|
+
)
|
|
393
398
|
|
|
394
399
|
|
|
395
400
|
@register_command("split conflict")
|
|
@@ -580,7 +585,38 @@ def mfs(text):
|
|
|
580
585
|
def try_existing_listener():
|
|
581
586
|
protocol_errors = []
|
|
582
587
|
delivered = False
|
|
583
|
-
|
|
588
|
+
addresses = socket_addresses
|
|
589
|
+
try:
|
|
590
|
+
route = directory_port(socket_addresses[0], os.getcwd())
|
|
591
|
+
except ForwardSearchUnavailable:
|
|
592
|
+
route = None
|
|
593
|
+
except ForwardSearchProtocolError as exc:
|
|
594
|
+
raise RuntimeError(
|
|
595
|
+
"Refusing to open another browser window: " + str(exc)
|
|
596
|
+
) from exc
|
|
597
|
+
if route and route["registry"]:
|
|
598
|
+
if route["port"] is not None:
|
|
599
|
+
try:
|
|
600
|
+
send_forward_search(
|
|
601
|
+
(FORWARD_SEARCH_HOST, route["port"]), search_text
|
|
602
|
+
)
|
|
603
|
+
return True
|
|
604
|
+
except ForwardSearchUnavailable:
|
|
605
|
+
directory_port(socket_addresses[0], os.getcwd(), port=None)
|
|
606
|
+
addresses = socket_addresses[1:]
|
|
607
|
+
for address in addresses:
|
|
608
|
+
if route and route["registry"] and address != socket_addresses[0]:
|
|
609
|
+
try:
|
|
610
|
+
candidate = directory_port(address, os.getcwd())
|
|
611
|
+
except ForwardSearchUnavailable:
|
|
612
|
+
continue
|
|
613
|
+
except ForwardSearchProtocolError as exc:
|
|
614
|
+
protocol_errors.append(str(exc))
|
|
615
|
+
continue
|
|
616
|
+
if candidate["registry"]:
|
|
617
|
+
if candidate["port"] is None:
|
|
618
|
+
continue
|
|
619
|
+
address = (FORWARD_SEARCH_HOST, candidate["port"])
|
|
584
620
|
try:
|
|
585
621
|
send_forward_search(address, search_text)
|
|
586
622
|
except ForwardSearchUnavailable:
|
|
@@ -995,6 +1031,14 @@ def main(argv=None):
|
|
|
995
1031
|
if subcommand in parser._pydifft_subparsers:
|
|
996
1032
|
parser._pydifft_subparsers[subcommand].print_help()
|
|
997
1033
|
return
|
|
1034
|
+
# gd forwards Git's options verbatim, including leading --cached/-M.
|
|
1035
|
+
# argparse's REMAINDER only accepts those after a positional argument.
|
|
1036
|
+
if argv[0] == "gd":
|
|
1037
|
+
option_end = argv.index("--") if "--" in argv else len(argv)
|
|
1038
|
+
if any(arg in ("-h", "--help") for arg in argv[1:option_end]):
|
|
1039
|
+
parser._pydifft_subparsers["gd"].print_help()
|
|
1040
|
+
return
|
|
1041
|
+
return gd(argv[1:])
|
|
998
1042
|
namespace = parser.parse_args(argv)
|
|
999
1043
|
if namespace.add_to_git is not None:
|
|
1000
1044
|
if not namespace.add_to_git:
|
|
@@ -1020,6 +1064,8 @@ def main(argv=None):
|
|
|
1020
1064
|
parser._pydifft_subparsers[namespace.command].error(
|
|
1021
1065
|
"--wrapnumber must be at least 1"
|
|
1022
1066
|
)
|
|
1067
|
+
if getattr(namespace, "desired_width", 45) < 1:
|
|
1068
|
+
parser.error("--desired-width must be at least 1")
|
|
1023
1069
|
if getattr(namespace, "trailing_dependent_phrase",
|
|
1024
1070
|
getattr(namespace, "punctuation_slop", 0)) < 0:
|
|
1025
1071
|
parser._pydifft_subparsers[namespace.command].error(
|
|
@@ -21,7 +21,8 @@ from watchdog.observers import Observer
|
|
|
21
21
|
from watchdog.observers.polling import PollingObserver
|
|
22
22
|
from .command_registry import register_command
|
|
23
23
|
from .wrapping_options import (
|
|
24
|
-
DEFAULT_WIDTH,
|
|
24
|
+
DEFAULT_WIDTH, DEFAULT_DESIRED_WIDTH,
|
|
25
|
+
DEFAULT_TRAILING_DEPENDENT_PHRASE, WRAPPING_ARGUMENTS,
|
|
25
26
|
)
|
|
26
27
|
from .zotero import recover_bibliography, zotero_notice
|
|
27
28
|
from .comment_migration import prepare_comment_source
|
|
@@ -35,7 +36,10 @@ from .browser_lifecycle import (
|
|
|
35
36
|
from .forward_search import (
|
|
36
37
|
CPB_FORWARD_SEARCH_PORT,
|
|
37
38
|
FORWARD_SEARCH_HOST,
|
|
38
|
-
|
|
39
|
+
bind_cpb_server,
|
|
40
|
+
directory_port,
|
|
41
|
+
ForwardSearchUnavailable,
|
|
42
|
+
ForwardSearchProtocolError,
|
|
39
43
|
drain_forward_search_queue,
|
|
40
44
|
serve_forward_search,
|
|
41
45
|
)
|
|
@@ -513,6 +517,7 @@ def run_pandoc(
|
|
|
513
517
|
wrapnumber=DEFAULT_WIDTH,
|
|
514
518
|
trailing_dependent_phrase=DEFAULT_TRAILING_DEPENDENT_PHRASE,
|
|
515
519
|
diff=None,
|
|
520
|
+
desired_width=DEFAULT_DESIRED_WIDTH,
|
|
516
521
|
):
|
|
517
522
|
# {{{ automatically fix Markdown source and request edits for
|
|
518
523
|
# unfinished spans
|
|
@@ -523,6 +528,7 @@ def run_pandoc(
|
|
|
523
528
|
report = autofix_markdown_file(
|
|
524
529
|
filename, wrapnumber=wrapnumber, git_index=True, git_ref=diff,
|
|
525
530
|
punctuation_slop=trailing_dependent_phrase,
|
|
531
|
+
desired_width=desired_width,
|
|
526
532
|
)
|
|
527
533
|
automatic_fixes_were_made |= bool(report["fixes"])
|
|
528
534
|
if report["fixes"] or report["warnings"]:
|
|
@@ -1215,6 +1221,7 @@ def cpb(
|
|
|
1215
1221
|
wrapnumber=DEFAULT_WIDTH,
|
|
1216
1222
|
trailing_dependent_phrase=DEFAULT_TRAILING_DEPENDENT_PHRASE,
|
|
1217
1223
|
diff=None,
|
|
1224
|
+
desired_width=DEFAULT_DESIRED_WIDTH,
|
|
1218
1225
|
):
|
|
1219
1226
|
source_path = os.path.normpath(os.path.abspath(filename))
|
|
1220
1227
|
source_dir = os.path.dirname(source_path)
|
|
@@ -1222,12 +1229,12 @@ def cpb(
|
|
|
1222
1229
|
comment_filter_session = {}
|
|
1223
1230
|
search_queue = queue.Queue()
|
|
1224
1231
|
stop_event = threading.Event()
|
|
1225
|
-
forward_search_server =
|
|
1226
|
-
(FORWARD_SEARCH_HOST, FORWARD_SEARCH_PORT)
|
|
1232
|
+
forward_search_server = bind_cpb_server(
|
|
1233
|
+
(FORWARD_SEARCH_HOST, FORWARD_SEARCH_PORT)
|
|
1227
1234
|
)
|
|
1228
1235
|
socket_thread = threading.Thread(
|
|
1229
1236
|
target=serve_forward_search,
|
|
1230
|
-
args=(forward_search_server, stop_event, search_queue),
|
|
1237
|
+
args=(forward_search_server, stop_event, search_queue, source_dir),
|
|
1231
1238
|
daemon=True,
|
|
1232
1239
|
)
|
|
1233
1240
|
chrome = None
|
|
@@ -1247,6 +1254,14 @@ def cpb(
|
|
|
1247
1254
|
# port authoritative even while a slow initial build is in progress.
|
|
1248
1255
|
socket_thread.start()
|
|
1249
1256
|
socket_thread_started = True
|
|
1257
|
+
registry_address = (FORWARD_SEARCH_HOST, FORWARD_SEARCH_PORT)
|
|
1258
|
+
session_port = forward_search_server.getsockname()[1]
|
|
1259
|
+
if session_port != FORWARD_SEARCH_PORT:
|
|
1260
|
+
try:
|
|
1261
|
+
directory_port(registry_address, source_dir, port=session_port)
|
|
1262
|
+
except (ForwardSearchUnavailable, ForwardSearchProtocolError):
|
|
1263
|
+
print("cpb: standard port has no directory registry; "
|
|
1264
|
+
"mfs discovery is unavailable.")
|
|
1250
1265
|
|
|
1251
1266
|
# Build before opening the browser so a failed build cannot leave an
|
|
1252
1267
|
# orphaned browser session. Remember the source version from before
|
|
@@ -1271,6 +1286,7 @@ def cpb(
|
|
|
1271
1286
|
wrapnumber=wrapnumber,
|
|
1272
1287
|
trailing_dependent_phrase=trailing_dependent_phrase,
|
|
1273
1288
|
diff=diff,
|
|
1289
|
+
desired_width=desired_width,
|
|
1274
1290
|
)
|
|
1275
1291
|
source_jump_server = SourceJumpServer(source_path)
|
|
1276
1292
|
source_jump_server.start()
|
|
@@ -1418,6 +1434,7 @@ def cpb(
|
|
|
1418
1434
|
trailing_dependent_phrase
|
|
1419
1435
|
),
|
|
1420
1436
|
diff=diff,
|
|
1437
|
+
desired_width=desired_width,
|
|
1421
1438
|
)
|
|
1422
1439
|
append_autorefresh(
|
|
1423
1440
|
html_file, source_jump_server.url
|
|
@@ -1463,6 +1480,11 @@ def cpb(
|
|
|
1463
1480
|
except KeyboardInterrupt:
|
|
1464
1481
|
pass
|
|
1465
1482
|
finally:
|
|
1483
|
+
if socket_thread_started and session_port != FORWARD_SEARCH_PORT:
|
|
1484
|
+
try:
|
|
1485
|
+
directory_port(registry_address, source_dir, port=None)
|
|
1486
|
+
except (ForwardSearchUnavailable, ForwardSearchProtocolError):
|
|
1487
|
+
pass
|
|
1466
1488
|
stop_event.set()
|
|
1467
1489
|
forward_search_server.close()
|
|
1468
1490
|
if source_jump_server is not None:
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
"""Acknowledged loopback transport for browser forward-search requests."""
|
|
2
2
|
|
|
3
|
+
import errno
|
|
4
|
+
import json
|
|
5
|
+
import os
|
|
3
6
|
import queue
|
|
4
7
|
import socket
|
|
5
8
|
|
|
@@ -41,9 +44,13 @@ def bind_forward_search_server(address, service_name):
|
|
|
41
44
|
return server
|
|
42
45
|
|
|
43
46
|
|
|
44
|
-
def serve_forward_search(server, stop_event, search_queue):
|
|
47
|
+
def serve_forward_search(server, stop_event, search_queue, directory=None):
|
|
45
48
|
"""Accept clients, queue valid UTF-8 payloads, and acknowledge receipt."""
|
|
46
49
|
|
|
50
|
+
registrations = {}
|
|
51
|
+
if directory is not None:
|
|
52
|
+
registrations[os.path.realpath(directory)] = server.getsockname()[1]
|
|
53
|
+
|
|
47
54
|
while not stop_event.is_set():
|
|
48
55
|
try:
|
|
49
56
|
connection, _ = server.accept()
|
|
@@ -71,6 +78,24 @@ def serve_forward_search(server, stop_event, search_queue):
|
|
|
71
78
|
search_text = payload.decode("utf-8")
|
|
72
79
|
except UnicodeDecodeError:
|
|
73
80
|
continue
|
|
81
|
+
if search_text.startswith("pydifft-directory\n"):
|
|
82
|
+
try:
|
|
83
|
+
request = json.loads(search_text.split("\n", 1)[1])
|
|
84
|
+
directory_key = os.path.realpath(request["directory"])
|
|
85
|
+
if "port" in request:
|
|
86
|
+
port = request["port"]
|
|
87
|
+
if port is None:
|
|
88
|
+
registrations.pop(directory_key, None)
|
|
89
|
+
elif isinstance(port, int) and 0 < port < 65536:
|
|
90
|
+
registrations[directory_key] = port
|
|
91
|
+
response = json.dumps({
|
|
92
|
+
"port": registrations.get(directory_key),
|
|
93
|
+
"registry": directory is not None,
|
|
94
|
+
}).encode()
|
|
95
|
+
connection.sendall(response)
|
|
96
|
+
except (ValueError, KeyError, TypeError, OSError):
|
|
97
|
+
pass
|
|
98
|
+
continue
|
|
74
99
|
search_queue.put(search_text)
|
|
75
100
|
try:
|
|
76
101
|
connection.sendall(FORWARD_SEARCH_ACK)
|
|
@@ -127,3 +152,53 @@ def drain_forward_search_queue(search_queue):
|
|
|
127
152
|
searches.append(search_queue.get_nowait())
|
|
128
153
|
except queue.Empty:
|
|
129
154
|
return searches
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
# also used by: continuous.py and command_line.py
|
|
158
|
+
def directory_port(address, directory, **registration):
|
|
159
|
+
"""Query or update the first cpb process's directory registry."""
|
|
160
|
+
request = {"directory": os.path.realpath(directory), **registration}
|
|
161
|
+
try:
|
|
162
|
+
with socket.create_connection(address, timeout=1) as client:
|
|
163
|
+
client.settimeout(1)
|
|
164
|
+
client.sendall(("pydifft-directory\n" + json.dumps(request)).encode())
|
|
165
|
+
client.shutdown(socket.SHUT_WR)
|
|
166
|
+
response = bytearray()
|
|
167
|
+
while True:
|
|
168
|
+
chunk = client.recv(4096)
|
|
169
|
+
if not chunk:
|
|
170
|
+
break
|
|
171
|
+
response.extend(chunk)
|
|
172
|
+
if len(response) > 4096:
|
|
173
|
+
raise ValueError("oversized registry response")
|
|
174
|
+
except OSError as exc:
|
|
175
|
+
raise ForwardSearchUnavailable(address) from exc
|
|
176
|
+
try:
|
|
177
|
+
result = json.loads(response)
|
|
178
|
+
if not isinstance(result, dict) or not isinstance(
|
|
179
|
+
result.get("registry"), bool
|
|
180
|
+
):
|
|
181
|
+
raise ValueError("invalid registry response")
|
|
182
|
+
port = result.get("port")
|
|
183
|
+
if port is not None and (type(port) is not int or not 0 < port < 65536):
|
|
184
|
+
raise ValueError("invalid port")
|
|
185
|
+
return result
|
|
186
|
+
except (ValueError, TypeError) as exc:
|
|
187
|
+
raise ForwardSearchProtocolError(
|
|
188
|
+
f"Invalid directory registry response from {address}"
|
|
189
|
+
) from exc
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
# also used by: continuous.py and tests/test_forward_search.py
|
|
193
|
+
def bind_cpb_server(address):
|
|
194
|
+
"""Take the first available port, reporting every occupied port."""
|
|
195
|
+
for port in range(address[1], 65536):
|
|
196
|
+
try:
|
|
197
|
+
return bind_forward_search_server((address[0], port), "cpb")
|
|
198
|
+
except RuntimeError as exc:
|
|
199
|
+
if not isinstance(exc.__cause__, OSError) or (
|
|
200
|
+
exc.__cause__.errno != errno.EADDRINUSE
|
|
201
|
+
):
|
|
202
|
+
raise
|
|
203
|
+
print(f"cpb: port {port} is taken; trying port {port + 1}.")
|
|
204
|
+
raise RuntimeError("No free cpb forward-search port remains")
|
|
@@ -273,6 +273,7 @@ def build_image_difftool_command(
|
|
|
273
273
|
)
|
|
274
274
|
|
|
275
275
|
|
|
276
|
+
# also used by: tests/cli/test_commands.py.
|
|
276
277
|
def build_image_score_command(
|
|
277
278
|
diff_args: Sequence[str], entry: DiffEntry
|
|
278
279
|
) -> list[str]:
|
|
@@ -363,6 +364,7 @@ def repo_name() -> str:
|
|
|
363
364
|
return Path(top).name
|
|
364
365
|
|
|
365
366
|
|
|
367
|
+
# also used by: git_gd_history.py and tests/cli/test_commands.py.
|
|
366
368
|
def build_entries(argv: Sequence[str]):
|
|
367
369
|
# {{{ separate Git options/revisions from file filters
|
|
368
370
|
if "--" in argv:
|
|
@@ -407,9 +409,18 @@ def diff_entry_sort_key(entry: DiffEntry):
|
|
|
407
409
|
return (group, 2, entry.path)
|
|
408
410
|
|
|
409
411
|
|
|
412
|
+
# also used by: tests/test_git_gd_terminal.py.
|
|
410
413
|
def main(argv: Sequence[str]) -> int:
|
|
414
|
+
# Only consume our flag before Git's pathspec separator.
|
|
415
|
+
args = list(argv)
|
|
416
|
+
option_end = args.index("--") if "--" in args else len(args)
|
|
417
|
+
terminal = "--terminal" in args[:option_end]
|
|
418
|
+
if terminal:
|
|
419
|
+
args = [arg for arg in args[:option_end] if arg != "--terminal"] + (
|
|
420
|
+
args[option_end:]
|
|
421
|
+
)
|
|
411
422
|
try:
|
|
412
|
-
diff_args, entries = build_entries(
|
|
423
|
+
diff_args, entries = build_entries(args)
|
|
413
424
|
name = repo_name()
|
|
414
425
|
except subprocess.CalledProcessError as exc:
|
|
415
426
|
if isinstance(exc.stderr, bytes):
|
|
@@ -417,6 +428,10 @@ def main(argv: Sequence[str]) -> int:
|
|
|
417
428
|
elif exc.stderr:
|
|
418
429
|
sys.stderr.write(exc.stderr)
|
|
419
430
|
return exc.returncode
|
|
431
|
+
if terminal:
|
|
432
|
+
from .git_gd_terminal import launch_review
|
|
433
|
+
|
|
434
|
+
return launch_review(name, diff_args, entries)
|
|
420
435
|
try:
|
|
421
436
|
from .git_gd_qt import launch_review
|
|
422
437
|
except ModuleNotFoundError as exc:
|
|
@@ -429,10 +444,13 @@ def main(argv: Sequence[str]) -> int:
|
|
|
429
444
|
return launch_review(name, diff_args, entries, command_args=argv)
|
|
430
445
|
|
|
431
446
|
|
|
447
|
+
# also used by: command_line.py's registered command dispatcher.
|
|
432
448
|
@register_command(
|
|
433
449
|
"review changed files in a Qt table before launching git difftool",
|
|
434
450
|
"review changed files in a Qt table before launching git difftool\n\n"
|
|
435
451
|
"With no arguments, review unstaged changes, like git diff.\n"
|
|
452
|
+
"Add --terminal for a colored terminal picker and Vim diffs;\n"
|
|
453
|
+
"images and binary files are skipped in terminal mode.\n"
|
|
436
454
|
"Use pydifft tree to browse Git history.\n\n"
|
|
437
455
|
"Install the matching git alias automatically with:\n"
|
|
438
456
|
" pydifft --add_to_git gd\n\n"
|
|
@@ -440,11 +458,12 @@ def main(argv: Sequence[str]) -> int:
|
|
|
440
458
|
" git config --global alias.gd '!f() { pydifft gd \"$@\"; }; f'\n\n"
|
|
441
459
|
"This command shells out to git difftool --tool=mygvim, so keep\n"
|
|
442
460
|
"difftool.mygvim.cmd configured in your git config.",
|
|
461
|
+
help={"terminal": "Use a terminal picker and Vim; skip images/binaries."},
|
|
443
462
|
)
|
|
444
|
-
def gd(arguments):
|
|
463
|
+
def gd(arguments, terminal=False):
|
|
445
464
|
"""Mirror ``git_gd_qt.py``."""
|
|
446
465
|
|
|
447
|
-
return_code = main(arguments)
|
|
466
|
+
return_code = main(["--terminal", *arguments] if terminal else arguments)
|
|
448
467
|
if return_code != 0:
|
|
449
468
|
raise SystemExit(return_code)
|
|
450
469
|
|