pyDiffTools 0.1.32__tar.gz → 0.1.33__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.32/pyDiffTools.egg-info → pydifftools-0.1.33}/PKG-INFO +1 -1
- {pydifftools-0.1.32 → pydifftools-0.1.33/pyDiffTools.egg-info}/PKG-INFO +1 -1
- pydifftools-0.1.33/pydifftools/doc_contents.py +206 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/outline.py +2 -2
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pyproject.toml +1 -1
- pydifftools-0.1.32/pydifftools/doc_contents.py +0 -162
- {pydifftools-0.1.32 → pydifftools-0.1.33}/LICENSE.md +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/MANIFEST.in +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/README.rst +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/_quarto.yml +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/__version__.txt +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/1a724af72b16f5a9e607e12b1c721645/base.ipynb +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/1b28fc9daac9081847e5161b2c546f8a/base.ipynb +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/231f64eee282fa225d1104935cf80a24/base.ipynb +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/26e56f6b0ff54851a45145157f2f0dc4/base.ipynb +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/311fabd7029ffd050d056e2f316eb50f/base.ipynb +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/57da2021e5b156ac3adf01398201c723/base.ipynb +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/62b24ea7da75011d92b0f8924faa208d/base.ipynb +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/7f1b20d69d889514ab5d1cc92e3cb14f/base.ipynb +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/86f74c8c54a87ff892d9b15dd714e8f0/base.ipynb +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/88893b4234eac2945d9d6cb2e277f186/base.ipynb +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/9a40046ada6f582ee34af00fbdbfb417/base.ipynb +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/a1bf4d270d0641ff41faf1d7cce3439a/base.ipynb +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/a3789f7d9585a781f2a1c60ce95ff10d/base.ipynb +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/be46ecba858d39ad5f0c46902ddf1c02/base.ipynb +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/d0cbc57a12f2ccce710a5afd04cc05e7/base.ipynb +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/d3e12d320b14228f701231ae32ddd7dd/base.ipynb +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/eb434f61555438d020a6970a5dbf9ee8/base.ipynb +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/f6b0e73aa7fa029134665d4dde57e096/base.ipynb +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/f719a6e4ff09873cb0ffb06ec9d232f9/base.ipynb +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/feeee244a7ce3d60e1a227eb604df823/base.ipynb +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/global.db +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/example.qmd +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/example.tex +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/index.qmd +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/subproject1/.jupyter_cache/__version__.txt +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/subproject1/.jupyter_cache/executed/ca90e4df5f4f0583df6554156a68dc7f/base.ipynb +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/subproject1/.jupyter_cache/global.db +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/subproject1/end_vs_he_sketch.jpg +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/subproject1/independent.qmd +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/subproject1/index.qmd +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/subproject1/tasks.qmd +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/subproject1/test_include.qmd +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/subproject1/tryforerror.qmd +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/test_include.qmd +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pyDiffTools.egg-info/SOURCES.txt +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pyDiffTools.egg-info/dependency_links.txt +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pyDiffTools.egg-info/entry_points.txt +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pyDiffTools.egg-info/requires.txt +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pyDiffTools.egg-info/top_level.txt +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/__init__.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/browser_lifecycle.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/check_numbers.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/command_line.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/command_registry.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/comment_functions.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/comment_tags.lua +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/comment_tags_margin.lua +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/comment_tags_no_comments.lua +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/comment_toggle.js +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/comments.css +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/continuous.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/copy_files.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/diff-doc.js +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/flowchart/__init__.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/flowchart/comparison.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/flowchart/dot_to_yaml.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/flowchart/graph.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/flowchart/svg-pan-zoom.min.js +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/flowchart/watch_graph.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/flowchart/wgrph_view.js +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/forward_search.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/git_gd.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/git_gd_history.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/git_gd_image.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/git_gd_qt.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/html_comments.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/html_uncomments.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/log_example.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/match_spaces.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/notebook/__init__.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/notebook/display.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/notebook/fast_build.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/notebook/tex_to_qmd.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/onewordify.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/onewordify_undo.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/rearrange_tex.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/searchacro.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/separate_comments.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/split_conflict.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/unseparate_comments.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/update_check.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/wrap_sentences.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/xml2xlsx.vbs +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/setup.cfg +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/tests/test_browser_lifecycle.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/tests/test_check_single_use.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/tests/test_command_line_help.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/tests/test_continuous_shutdown.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/tests/test_forward_search.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/tests/test_git_gd_history.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/tests/test_git_gd_image.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/tests/test_git_gd_qt.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/tests/test_rrng.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/tests/test_tex_to_qmd.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/tests/test_update_check.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/tests/test_wrap_check.py +0 -0
- {pydifftools-0.1.32 → pydifftools-0.1.33}/tests/test_wrapping.py +0 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
from collections import OrderedDict
|
|
2
|
+
import re
|
|
3
|
+
from fuzzywuzzy import fuzz
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class doc_contents_class(object):
|
|
7
|
+
def __init__(self, format_type="latex"):
|
|
8
|
+
self.contents = OrderedDict()
|
|
9
|
+
self.contents["header"] = ""
|
|
10
|
+
self.types = {}
|
|
11
|
+
self.types["header"] = "header"
|
|
12
|
+
self._aliases = {}
|
|
13
|
+
self._processed_titles = []
|
|
14
|
+
self.set_format(format_type)
|
|
15
|
+
|
|
16
|
+
def set_format(self, format_type):
|
|
17
|
+
if format_type == "markdown":
|
|
18
|
+
# markdown levels go deeper, so include subparagraph mapping
|
|
19
|
+
self.level_numbers = {
|
|
20
|
+
"section": 1,
|
|
21
|
+
"subsection": 2,
|
|
22
|
+
"subsubsection": 3,
|
|
23
|
+
"paragraph": 4,
|
|
24
|
+
"subparagraph": 5,
|
|
25
|
+
}
|
|
26
|
+
else:
|
|
27
|
+
# default to latex behavior
|
|
28
|
+
self.level_numbers = {
|
|
29
|
+
"section": 1,
|
|
30
|
+
"subsection": 2,
|
|
31
|
+
"subsubsection": 3,
|
|
32
|
+
"paragraph": 4,
|
|
33
|
+
"subparagraph": 5,
|
|
34
|
+
}
|
|
35
|
+
# map indentation back to section type for outline parsing
|
|
36
|
+
self.inv_prefix = {
|
|
37
|
+
(level - 1) * "\t": section
|
|
38
|
+
for section, level in self.level_numbers.items()
|
|
39
|
+
}
|
|
40
|
+
self.format_type = format_type
|
|
41
|
+
|
|
42
|
+
def start_sec(self, thistype, thistitle):
|
|
43
|
+
assert thistitle not in self.contents.keys(), (
|
|
44
|
+
"more than one section with the name:\n" + thistitle
|
|
45
|
+
)
|
|
46
|
+
self.contents[thistitle] = ""
|
|
47
|
+
self.types[thistitle] = thistype
|
|
48
|
+
print("added", thistitle)
|
|
49
|
+
|
|
50
|
+
def __setstate__(self, d):
|
|
51
|
+
"set the info from a pickle"
|
|
52
|
+
self.contents = d["contents"]
|
|
53
|
+
self.types = d["types"]
|
|
54
|
+
self._aliases = {} # doesn't exist, but still needed
|
|
55
|
+
self._processed_titles = []
|
|
56
|
+
if "format_type" in d:
|
|
57
|
+
self.set_format(d["format_type"])
|
|
58
|
+
else:
|
|
59
|
+
self.set_format("latex")
|
|
60
|
+
return
|
|
61
|
+
|
|
62
|
+
def __getstate__(self):
|
|
63
|
+
"return info for a pickle"
|
|
64
|
+
return {
|
|
65
|
+
"contents": self.contents,
|
|
66
|
+
"types": self.types,
|
|
67
|
+
"format_type": self.format_type,
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
def __iadd__(self, value):
|
|
71
|
+
self.contents[next(reversed(self.contents))] += value
|
|
72
|
+
return self
|
|
73
|
+
|
|
74
|
+
def __str__(self):
|
|
75
|
+
if len(self._processed_titles) > 0:
|
|
76
|
+
raise ValueError(
|
|
77
|
+
"the following section titles are missing from the"
|
|
78
|
+
" outline:\n\t"
|
|
79
|
+
+ "\n\t".join(self._processed_titles)
|
|
80
|
+
+ "\nEvery existing section must appear in the outline, so"
|
|
81
|
+
" that entire sections of text are never dropped by"
|
|
82
|
+
" accident. If you really want to get rid of a section,"
|
|
83
|
+
" add a new heading (e.g. 'for deletion') to the outline"
|
|
84
|
+
" and move the unwanted sections underneath it; then delete"
|
|
85
|
+
" that part of the file by hand."
|
|
86
|
+
)
|
|
87
|
+
retval = ""
|
|
88
|
+
for j in self.contents.keys():
|
|
89
|
+
if self.types[j] != "header":
|
|
90
|
+
new_name = j
|
|
91
|
+
if j in self._aliases.keys():
|
|
92
|
+
new_name = self._aliases[j]
|
|
93
|
+
if self.format_type == "markdown":
|
|
94
|
+
retval += "#" * self.level_numbers[self.types[j]]
|
|
95
|
+
retval += f" {new_name}\n"
|
|
96
|
+
else:
|
|
97
|
+
retval += f"\\{self.types[j]}{{{new_name}}}"
|
|
98
|
+
retval += f"{self.contents[j]}"
|
|
99
|
+
return retval
|
|
100
|
+
|
|
101
|
+
@property
|
|
102
|
+
def outline(self):
|
|
103
|
+
retval = []
|
|
104
|
+
for j in self.contents.keys():
|
|
105
|
+
if self.types[j] != "header":
|
|
106
|
+
indent = (self.level_numbers[self.types[j]] - 1) * "\t"
|
|
107
|
+
thistitle = (indent + "\t").join(j.split("\n"))
|
|
108
|
+
retval.append(indent + "*\t" + thistitle)
|
|
109
|
+
return "\n".join(retval)
|
|
110
|
+
|
|
111
|
+
def outline_in_order(self, outline_lines):
|
|
112
|
+
self._processed_titles = [
|
|
113
|
+
j for j in self.contents.keys() if self.types[j] != "header"
|
|
114
|
+
]
|
|
115
|
+
# {{{ parse (level, title) from each outline line
|
|
116
|
+
parsed = []
|
|
117
|
+
for thisline in outline_lines:
|
|
118
|
+
if not thisline.strip():
|
|
119
|
+
continue
|
|
120
|
+
ilevel = 0
|
|
121
|
+
spacelevel = 0
|
|
122
|
+
hitmarker = False
|
|
123
|
+
for j, thischar in enumerate(thisline):
|
|
124
|
+
if not hitmarker:
|
|
125
|
+
if thischar == " ":
|
|
126
|
+
spacelevel += 1
|
|
127
|
+
if spacelevel == 4 or thischar == "\t":
|
|
128
|
+
ilevel += 1
|
|
129
|
+
spacelevel = 0
|
|
130
|
+
elif thischar == "*":
|
|
131
|
+
hitmarker = True
|
|
132
|
+
else:
|
|
133
|
+
assert thischar in [" ", "\t"]
|
|
134
|
+
title = thisline[j + 1 :]
|
|
135
|
+
break
|
|
136
|
+
if not hitmarker:
|
|
137
|
+
raise ValueError("somehow, there wasn't a * marker!")
|
|
138
|
+
parsed.append((ilevel, title))
|
|
139
|
+
# }}}
|
|
140
|
+
# {{{ resolve titles that aren't existing sections -- only sections
|
|
141
|
+
# that appear nowhere in the outline can have been renamed
|
|
142
|
+
outline_titles = {title for _, title in parsed}
|
|
143
|
+
orphans = [
|
|
144
|
+
j
|
|
145
|
+
for j in self.contents.keys()
|
|
146
|
+
if self.types[j] != "header" and j not in outline_titles
|
|
147
|
+
]
|
|
148
|
+
renamed = {}
|
|
149
|
+
for _, title in parsed:
|
|
150
|
+
if title in self.contents.keys() or title in renamed:
|
|
151
|
+
continue
|
|
152
|
+
if re.search(r"\bNEW\b", title):
|
|
153
|
+
print(f"adding\n\t{title}\nas a new section (labeled NEW)")
|
|
154
|
+
elif len(orphans) == 0:
|
|
155
|
+
print(
|
|
156
|
+
f"adding\n\t{title}\nas a new section (no unplaced"
|
|
157
|
+
" sections are left that it could be a rename of)"
|
|
158
|
+
)
|
|
159
|
+
else:
|
|
160
|
+
ranked = sorted(
|
|
161
|
+
orphans,
|
|
162
|
+
key=lambda j: fuzz.token_sort_ratio(title, j),
|
|
163
|
+
reverse=True,
|
|
164
|
+
)[:5]
|
|
165
|
+
choices = "".join(
|
|
166
|
+
f"\n {n + 1}) [{fuzz.token_sort_ratio(title, j)}] {j}"
|
|
167
|
+
for n, j in enumerate(ranked)
|
|
168
|
+
)
|
|
169
|
+
prompt = (
|
|
170
|
+
f"didn't find\n\t{title}\namong the existing sections."
|
|
171
|
+
" Is it a renamed version of one of these sections that"
|
|
172
|
+
f" don't appear in the outline?{choices}\nenter a number"
|
|
173
|
+
" to rename, n to add it as a new, empty section, or q"
|
|
174
|
+
" to quit without writing anything: "
|
|
175
|
+
)
|
|
176
|
+
while True:
|
|
177
|
+
answer = input(prompt).strip()
|
|
178
|
+
if answer in ("n", "q"):
|
|
179
|
+
break
|
|
180
|
+
if answer.isdigit() and 1 <= int(answer) <= len(ranked):
|
|
181
|
+
break
|
|
182
|
+
print(f"didn't understand {answer!r}")
|
|
183
|
+
if answer == "q":
|
|
184
|
+
raise ValueError("aborted -- nothing was written")
|
|
185
|
+
if answer != "n":
|
|
186
|
+
original = ranked[int(answer) - 1]
|
|
187
|
+
self._aliases[original] = title # will be replaced later
|
|
188
|
+
renamed[title] = original
|
|
189
|
+
orphans.remove(original)
|
|
190
|
+
continue
|
|
191
|
+
# a new section, so it isn't on the list of titles to place
|
|
192
|
+
self.contents[title] = ""
|
|
193
|
+
self._processed_titles.append(title)
|
|
194
|
+
# }}}
|
|
195
|
+
# {{{ reorder sections to match the outline
|
|
196
|
+
for ilevel, title in parsed:
|
|
197
|
+
title = renamed.get(title, title)
|
|
198
|
+
if title not in self._processed_titles:
|
|
199
|
+
raise ValueError(
|
|
200
|
+
f"the section\n\t{title}\nappears more than once in the"
|
|
201
|
+
" outline"
|
|
202
|
+
)
|
|
203
|
+
self.contents.move_to_end(title)
|
|
204
|
+
self._processed_titles.remove(title)
|
|
205
|
+
self.types[title] = self.inv_prefix[ilevel * "\t"]
|
|
206
|
+
# }}}
|
|
@@ -171,8 +171,8 @@ def xore(filename):
|
|
|
171
171
|
all_contents = pickle.load(fp)
|
|
172
172
|
all_contents.set_format(format_type)
|
|
173
173
|
with open(markdownfile, "r", encoding="utf-8") as fp:
|
|
174
|
-
for
|
|
175
|
-
|
|
174
|
+
outline_lines = [j.rstrip() for j in fp]
|
|
175
|
+
all_contents.outline_in_order(outline_lines)
|
|
176
176
|
# build the text before opening the target, so that an error (e.g. a
|
|
177
177
|
# section missing from the outline) doesn't leave an empty file
|
|
178
178
|
reordered = str(all_contents)
|
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
from collections import OrderedDict
|
|
2
|
-
from fuzzywuzzy import process
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
class doc_contents_class(object):
|
|
6
|
-
def __init__(self, format_type="latex"):
|
|
7
|
-
self.contents = OrderedDict()
|
|
8
|
-
self.contents["header"] = ""
|
|
9
|
-
self.types = {}
|
|
10
|
-
self.types["header"] = "header"
|
|
11
|
-
self._reordering_started = False
|
|
12
|
-
self._aliases = {}
|
|
13
|
-
self._processed_titles = []
|
|
14
|
-
self.set_format(format_type)
|
|
15
|
-
|
|
16
|
-
def set_format(self, format_type):
|
|
17
|
-
if format_type == "markdown":
|
|
18
|
-
# markdown levels go deeper, so include subparagraph mapping
|
|
19
|
-
self.level_numbers = {
|
|
20
|
-
"section": 1,
|
|
21
|
-
"subsection": 2,
|
|
22
|
-
"subsubsection": 3,
|
|
23
|
-
"paragraph": 4,
|
|
24
|
-
"subparagraph": 5,
|
|
25
|
-
}
|
|
26
|
-
else:
|
|
27
|
-
# default to latex behavior
|
|
28
|
-
self.level_numbers = {
|
|
29
|
-
"section": 1,
|
|
30
|
-
"subsection": 2,
|
|
31
|
-
"subsubsection": 3,
|
|
32
|
-
"paragraph": 4,
|
|
33
|
-
"subparagraph": 5,
|
|
34
|
-
}
|
|
35
|
-
# map indentation back to section type for outline parsing
|
|
36
|
-
self.inv_prefix = {
|
|
37
|
-
(level - 1) * "\t": section
|
|
38
|
-
for section, level in self.level_numbers.items()
|
|
39
|
-
}
|
|
40
|
-
self.format_type = format_type
|
|
41
|
-
|
|
42
|
-
def start_sec(self, thistype, thistitle):
|
|
43
|
-
assert thistitle not in self.contents.keys(), (
|
|
44
|
-
"more than one section with the name:\n" + thistitle
|
|
45
|
-
)
|
|
46
|
-
self.contents[thistitle] = ""
|
|
47
|
-
self.types[thistitle] = thistype
|
|
48
|
-
print("added", thistitle)
|
|
49
|
-
|
|
50
|
-
def __setstate__(self, d):
|
|
51
|
-
"set the info from a pickle"
|
|
52
|
-
self.contents = d["contents"]
|
|
53
|
-
self.types = d["types"]
|
|
54
|
-
self._aliases = {} # doesn't exist, but still needed
|
|
55
|
-
self._reordering_started = False
|
|
56
|
-
self._processed_titles = []
|
|
57
|
-
if "format_type" in d:
|
|
58
|
-
self.set_format(d["format_type"])
|
|
59
|
-
else:
|
|
60
|
-
self.set_format("latex")
|
|
61
|
-
return
|
|
62
|
-
|
|
63
|
-
def __getstate__(self):
|
|
64
|
-
"return info for a pickle"
|
|
65
|
-
return {
|
|
66
|
-
"contents": self.contents,
|
|
67
|
-
"types": self.types,
|
|
68
|
-
"format_type": self.format_type,
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
def __iadd__(self, value):
|
|
72
|
-
self.contents[next(reversed(self.contents))] += value
|
|
73
|
-
return self
|
|
74
|
-
|
|
75
|
-
def __str__(self):
|
|
76
|
-
if len(self._processed_titles) > 0:
|
|
77
|
-
raise ValueError(
|
|
78
|
-
"the following section titles are missing from the"
|
|
79
|
-
" outline:\n\t"
|
|
80
|
-
+ "\n\t".join(self._processed_titles)
|
|
81
|
-
+ "\nEvery existing section must appear in the outline, so"
|
|
82
|
-
" that entire sections of text are never dropped by"
|
|
83
|
-
" accident. If you really want to get rid of a section,"
|
|
84
|
-
" add a new heading (e.g. 'for deletion') to the outline"
|
|
85
|
-
" and move the unwanted sections underneath it; then delete"
|
|
86
|
-
" that part of the file by hand."
|
|
87
|
-
)
|
|
88
|
-
retval = ""
|
|
89
|
-
for j in self.contents.keys():
|
|
90
|
-
if self.types[j] != "header":
|
|
91
|
-
new_name = j
|
|
92
|
-
if j in self._aliases.keys():
|
|
93
|
-
new_name = self._aliases[j]
|
|
94
|
-
if self.format_type == "markdown":
|
|
95
|
-
retval += "#" * self.level_numbers[self.types[j]]
|
|
96
|
-
retval += f" {new_name}\n"
|
|
97
|
-
else:
|
|
98
|
-
retval += f"\\{self.types[j]}{{{new_name}}}"
|
|
99
|
-
retval += f"{self.contents[j]}"
|
|
100
|
-
return retval
|
|
101
|
-
|
|
102
|
-
@property
|
|
103
|
-
def outline(self):
|
|
104
|
-
retval = []
|
|
105
|
-
for j in self.contents.keys():
|
|
106
|
-
if self.types[j] != "header":
|
|
107
|
-
indent = (self.level_numbers[self.types[j]] - 1) * "\t"
|
|
108
|
-
thistitle = (indent + "\t").join(j.split("\n"))
|
|
109
|
-
retval.append(indent + "*\t" + thistitle)
|
|
110
|
-
self._reordering_started = False
|
|
111
|
-
return "\n".join(retval)
|
|
112
|
-
|
|
113
|
-
def outline_in_order(self, thisline):
|
|
114
|
-
if not self._reordering_started:
|
|
115
|
-
self._processed_titles = [
|
|
116
|
-
j for j in self.contents.keys() if self.types[j] != "header"
|
|
117
|
-
]
|
|
118
|
-
self._reordering_started = True
|
|
119
|
-
ilevel = 0
|
|
120
|
-
spacelevel = 0
|
|
121
|
-
hitmarker = False
|
|
122
|
-
for j, thischar in enumerate(thisline):
|
|
123
|
-
if not hitmarker:
|
|
124
|
-
if thischar == " ":
|
|
125
|
-
spacelevel += 1
|
|
126
|
-
if spacelevel == 4 or thischar == "\t":
|
|
127
|
-
ilevel += 1
|
|
128
|
-
spacelevel = 0
|
|
129
|
-
elif thischar == "*":
|
|
130
|
-
hitmarker = True
|
|
131
|
-
else:
|
|
132
|
-
assert thischar in [" ", "\t"]
|
|
133
|
-
title = thisline[j + 1 :]
|
|
134
|
-
break
|
|
135
|
-
if not hitmarker:
|
|
136
|
-
raise ValueError("somehow, there wasn't a * marker!")
|
|
137
|
-
if title not in self.contents.keys():
|
|
138
|
-
best_match, match_quality = process.extractOne(
|
|
139
|
-
title, self.contents.keys()
|
|
140
|
-
)
|
|
141
|
-
yesorno = input(
|
|
142
|
-
f"didn't find\n\t{title}\namong the existing sections."
|
|
143
|
-
f" Is it a renamed version of\n\t{best_match}\n?"
|
|
144
|
-
" say y to rename, or n to add it as a new, empty section: "
|
|
145
|
-
)
|
|
146
|
-
if yesorno == "y":
|
|
147
|
-
self._aliases[best_match] = title # will be replaced later
|
|
148
|
-
title = best_match
|
|
149
|
-
elif yesorno == "n":
|
|
150
|
-
# a new section, so it isn't on the list of titles to place
|
|
151
|
-
self.contents[title] = ""
|
|
152
|
-
self._processed_titles.append(title)
|
|
153
|
-
else:
|
|
154
|
-
raise ValueError("expected y or n")
|
|
155
|
-
if title not in self._processed_titles:
|
|
156
|
-
raise ValueError(
|
|
157
|
-
f"the section\n\t{title}\nappears more than once in the"
|
|
158
|
-
" outline"
|
|
159
|
-
)
|
|
160
|
-
self.contents.move_to_end(title)
|
|
161
|
-
self._processed_titles.remove(title)
|
|
162
|
-
self.types[title] = self.inv_prefix[ilevel * "\t"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/__version__.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/global.db
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/subproject1/end_vs_he_sketch.jpg
RENAMED
|
File without changes
|
{pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/subproject1/independent.qmd
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/subproject1/test_include.qmd
RENAMED
|
File without changes
|
{pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/subproject1/tryforerror.qmd
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|