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.
Files changed (108) hide show
  1. {pydifftools-0.1.32/pyDiffTools.egg-info → pydifftools-0.1.33}/PKG-INFO +1 -1
  2. {pydifftools-0.1.32 → pydifftools-0.1.33/pyDiffTools.egg-info}/PKG-INFO +1 -1
  3. pydifftools-0.1.33/pydifftools/doc_contents.py +206 -0
  4. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/outline.py +2 -2
  5. {pydifftools-0.1.32 → pydifftools-0.1.33}/pyproject.toml +1 -1
  6. pydifftools-0.1.32/pydifftools/doc_contents.py +0 -162
  7. {pydifftools-0.1.32 → pydifftools-0.1.33}/LICENSE.md +0 -0
  8. {pydifftools-0.1.32 → pydifftools-0.1.33}/MANIFEST.in +0 -0
  9. {pydifftools-0.1.32 → pydifftools-0.1.33}/README.rst +0 -0
  10. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/_quarto.yml +0 -0
  11. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/__version__.txt +0 -0
  12. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/1a724af72b16f5a9e607e12b1c721645/base.ipynb +0 -0
  13. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/1b28fc9daac9081847e5161b2c546f8a/base.ipynb +0 -0
  14. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/231f64eee282fa225d1104935cf80a24/base.ipynb +0 -0
  15. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/26e56f6b0ff54851a45145157f2f0dc4/base.ipynb +0 -0
  16. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/311fabd7029ffd050d056e2f316eb50f/base.ipynb +0 -0
  17. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/57da2021e5b156ac3adf01398201c723/base.ipynb +0 -0
  18. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/62b24ea7da75011d92b0f8924faa208d/base.ipynb +0 -0
  19. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/7f1b20d69d889514ab5d1cc92e3cb14f/base.ipynb +0 -0
  20. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/86f74c8c54a87ff892d9b15dd714e8f0/base.ipynb +0 -0
  21. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/88893b4234eac2945d9d6cb2e277f186/base.ipynb +0 -0
  22. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/9a40046ada6f582ee34af00fbdbfb417/base.ipynb +0 -0
  23. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/a1bf4d270d0641ff41faf1d7cce3439a/base.ipynb +0 -0
  24. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/a3789f7d9585a781f2a1c60ce95ff10d/base.ipynb +0 -0
  25. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/be46ecba858d39ad5f0c46902ddf1c02/base.ipynb +0 -0
  26. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/d0cbc57a12f2ccce710a5afd04cc05e7/base.ipynb +0 -0
  27. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/d3e12d320b14228f701231ae32ddd7dd/base.ipynb +0 -0
  28. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/eb434f61555438d020a6970a5dbf9ee8/base.ipynb +0 -0
  29. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/f6b0e73aa7fa029134665d4dde57e096/base.ipynb +0 -0
  30. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/f719a6e4ff09873cb0ffb06ec9d232f9/base.ipynb +0 -0
  31. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/executed/feeee244a7ce3d60e1a227eb604df823/base.ipynb +0 -0
  32. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/.jupyter_cache/global.db +0 -0
  33. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/example.qmd +0 -0
  34. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/example.tex +0 -0
  35. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/index.qmd +0 -0
  36. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/subproject1/.jupyter_cache/__version__.txt +0 -0
  37. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/subproject1/.jupyter_cache/executed/ca90e4df5f4f0583df6554156a68dc7f/base.ipynb +0 -0
  38. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/subproject1/.jupyter_cache/global.db +0 -0
  39. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/subproject1/end_vs_he_sketch.jpg +0 -0
  40. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/subproject1/independent.qmd +0 -0
  41. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/subproject1/index.qmd +0 -0
  42. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/subproject1/tasks.qmd +0 -0
  43. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/subproject1/test_include.qmd +0 -0
  44. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/subproject1/tryforerror.qmd +0 -0
  45. {pydifftools-0.1.32 → pydifftools-0.1.33}/example_notebook/project1/test_include.qmd +0 -0
  46. {pydifftools-0.1.32 → pydifftools-0.1.33}/pyDiffTools.egg-info/SOURCES.txt +0 -0
  47. {pydifftools-0.1.32 → pydifftools-0.1.33}/pyDiffTools.egg-info/dependency_links.txt +0 -0
  48. {pydifftools-0.1.32 → pydifftools-0.1.33}/pyDiffTools.egg-info/entry_points.txt +0 -0
  49. {pydifftools-0.1.32 → pydifftools-0.1.33}/pyDiffTools.egg-info/requires.txt +0 -0
  50. {pydifftools-0.1.32 → pydifftools-0.1.33}/pyDiffTools.egg-info/top_level.txt +0 -0
  51. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/__init__.py +0 -0
  52. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/browser_lifecycle.py +0 -0
  53. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/check_numbers.py +0 -0
  54. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/command_line.py +0 -0
  55. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/command_registry.py +0 -0
  56. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/comment_functions.py +0 -0
  57. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/comment_tags.lua +0 -0
  58. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/comment_tags_margin.lua +0 -0
  59. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/comment_tags_no_comments.lua +0 -0
  60. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/comment_toggle.js +0 -0
  61. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/comments.css +0 -0
  62. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/continuous.py +0 -0
  63. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/copy_files.py +0 -0
  64. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/diff-doc.js +0 -0
  65. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/flowchart/__init__.py +0 -0
  66. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/flowchart/comparison.py +0 -0
  67. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/flowchart/dot_to_yaml.py +0 -0
  68. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/flowchart/graph.py +0 -0
  69. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/flowchart/svg-pan-zoom.min.js +0 -0
  70. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/flowchart/watch_graph.py +0 -0
  71. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/flowchart/wgrph_view.js +0 -0
  72. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/forward_search.py +0 -0
  73. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/git_gd.py +0 -0
  74. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/git_gd_history.py +0 -0
  75. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/git_gd_image.py +0 -0
  76. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/git_gd_qt.py +0 -0
  77. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/html_comments.py +0 -0
  78. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/html_uncomments.py +0 -0
  79. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/log_example.py +0 -0
  80. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/match_spaces.py +0 -0
  81. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/notebook/__init__.py +0 -0
  82. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/notebook/display.py +0 -0
  83. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/notebook/fast_build.py +0 -0
  84. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/notebook/tex_to_qmd.py +0 -0
  85. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/onewordify.py +0 -0
  86. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/onewordify_undo.py +0 -0
  87. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/rearrange_tex.py +0 -0
  88. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/searchacro.py +0 -0
  89. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/separate_comments.py +0 -0
  90. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/split_conflict.py +0 -0
  91. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/unseparate_comments.py +0 -0
  92. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/update_check.py +0 -0
  93. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/wrap_sentences.py +0 -0
  94. {pydifftools-0.1.32 → pydifftools-0.1.33}/pydifftools/xml2xlsx.vbs +0 -0
  95. {pydifftools-0.1.32 → pydifftools-0.1.33}/setup.cfg +0 -0
  96. {pydifftools-0.1.32 → pydifftools-0.1.33}/tests/test_browser_lifecycle.py +0 -0
  97. {pydifftools-0.1.32 → pydifftools-0.1.33}/tests/test_check_single_use.py +0 -0
  98. {pydifftools-0.1.32 → pydifftools-0.1.33}/tests/test_command_line_help.py +0 -0
  99. {pydifftools-0.1.32 → pydifftools-0.1.33}/tests/test_continuous_shutdown.py +0 -0
  100. {pydifftools-0.1.32 → pydifftools-0.1.33}/tests/test_forward_search.py +0 -0
  101. {pydifftools-0.1.32 → pydifftools-0.1.33}/tests/test_git_gd_history.py +0 -0
  102. {pydifftools-0.1.32 → pydifftools-0.1.33}/tests/test_git_gd_image.py +0 -0
  103. {pydifftools-0.1.32 → pydifftools-0.1.33}/tests/test_git_gd_qt.py +0 -0
  104. {pydifftools-0.1.32 → pydifftools-0.1.33}/tests/test_rrng.py +0 -0
  105. {pydifftools-0.1.32 → pydifftools-0.1.33}/tests/test_tex_to_qmd.py +0 -0
  106. {pydifftools-0.1.32 → pydifftools-0.1.33}/tests/test_update_check.py +0 -0
  107. {pydifftools-0.1.32 → pydifftools-0.1.33}/tests/test_wrap_check.py +0 -0
  108. {pydifftools-0.1.32 → pydifftools-0.1.33}/tests/test_wrapping.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyDiffTools
3
- Version: 0.1.32
3
+ Version: 0.1.33
4
4
  Summary: Diff tools
5
5
  Author: J M Franck
6
6
  License: Copyright (c) 2015, jmfranck
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyDiffTools
3
- Version: 0.1.32
3
+ Version: 0.1.33
4
4
  Summary: Diff tools
5
5
  Author: J M Franck
6
6
  License: Copyright (c) 2015, jmfranck
@@ -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 thisline in fp:
175
- all_contents.outline_in_order(thisline.rstrip())
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)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pyDiffTools"
7
- version = "0.1.32"
7
+ version = "0.1.33"
8
8
  authors = [{ name = "J M Franck" }]
9
9
  description = "Diff tools"
10
10
  readme = "README.rst"
@@ -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