pyDiffTools 0.1.8__py3-none-any.whl

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.
@@ -0,0 +1,65 @@
1
+ import argparse
2
+ import inspect
3
+
4
+
5
+ class CommandRegistrationError(Exception):
6
+ """Exception raised when attempting to register a duplicate subcommand."""
7
+
8
+ # Registry that stores all subcommands made available to the CLI dispatcher.
9
+ _COMMAND_SPECS = {}
10
+
11
+
12
+ def register_command(help_text, description=None, help=None):
13
+ """Register a command handler for the CLI dispatcher."""
14
+
15
+ def decorator(func):
16
+ name = func.__name__.replace("_", "-")
17
+ if name in _COMMAND_SPECS:
18
+ raise CommandRegistrationError(
19
+ f"Command '{name}' already registered"
20
+ )
21
+ _COMMAND_SPECS[name] = {
22
+ "handler": func,
23
+ "help": help_text.strip(),
24
+ "description": (
25
+ description if description is not None else help_text
26
+ ).strip(),
27
+ "arguments": [],
28
+ }
29
+ signature = inspect.signature(func)
30
+ argument_help = help if help is not None else {}
31
+ for parameter in signature.parameters.values():
32
+ if parameter.kind in [
33
+ inspect.Parameter.VAR_POSITIONAL,
34
+ inspect.Parameter.VAR_KEYWORD,
35
+ ]:
36
+ continue
37
+ flags = []
38
+ kwargs = {}
39
+ if parameter.default is inspect._empty:
40
+ flags.append(parameter.name)
41
+ if parameter.name == "arguments":
42
+ # Most commands accept a raw list of trailing arguments.
43
+ kwargs["nargs"] = argparse.REMAINDER
44
+ kwargs["help"] = argparse.SUPPRESS
45
+ else:
46
+ # Single-letter keywords use a short flag; everything else uses
47
+ # the long two-dash style expected by the CLI.
48
+ dash_prefix = "-" if len(parameter.name) == 1 else "--"
49
+ flags.append(dash_prefix + parameter.name.replace("_", "-"))
50
+ kwargs["default"] = parameter.default
51
+ if isinstance(parameter.default, bool):
52
+ # Boolean flags toggle on or off without needing a value.
53
+ kwargs["action"] = (
54
+ "store_false" if parameter.default else "store_true"
55
+ )
56
+ elif parameter.default is not None:
57
+ kwargs["type"] = type(parameter.default)
58
+ if parameter.name in argument_help:
59
+ kwargs["help"] = argument_help[parameter.name].strip()
60
+ _COMMAND_SPECS[name]["arguments"].append(
61
+ {"flags": flags, "kwargs": kwargs}
62
+ )
63
+ return func
64
+
65
+ return decorator
@@ -0,0 +1,39 @@
1
+ def comment_definition(commandname, name, comment_text):
2
+ return r"\newcommand{\%s}{%s}" % (commandname, comment_text) + "\n"
3
+
4
+
5
+ def generate_alphabetnumber(x):
6
+ if x < 26:
7
+ return chr(ord("a") + x)
8
+ else:
9
+ higher_places = x // 26
10
+ return generate_alphabetnumber(
11
+ higher_places - 1
12
+ ) + generate_alphabetnumber(x - higher_places * 26)
13
+
14
+
15
+ def matchingbrackets(content, startpoint, bracket_type):
16
+ if bracket_type == "(":
17
+ opening = "("
18
+ closing = ")"
19
+ elif bracket_type == "[":
20
+ opening = "["
21
+ closing = "]"
22
+ elif bracket_type == "{":
23
+ opening = "{"
24
+ closing = "}"
25
+ else:
26
+ raise ValueError("I didn't understand the type of bracket!")
27
+ first = (
28
+ False # of course, don't want to break until we've found at least one
29
+ )
30
+ level = 0
31
+ for j in range(startpoint, len(content)):
32
+ if content[j] == opening:
33
+ if level == 0:
34
+ first = j
35
+ level += 1
36
+ if content[j] == closing:
37
+ level -= 1
38
+ if level == 0 and first:
39
+ return first, j
@@ -0,0 +1,194 @@
1
+ """Continuous Pandoc build utility that requires geckodriver."""
2
+
3
+ import time
4
+ import subprocess
5
+ import sys
6
+ import os
7
+ import re
8
+ import shutil
9
+ from watchdog.events import FileSystemEventHandler
10
+ from watchdog.observers import Observer
11
+ from .command_registry import register_command
12
+
13
+
14
+ def run_pandoc(filename, html_file):
15
+ # Pandoc and pandoc-crossref must be installed for HTML rendering.
16
+ if shutil.which("pandoc") is None:
17
+ raise RuntimeError(
18
+ "Pandoc must be installed to render HTML output. Install pandoc"
19
+ " so the 'pandoc' executable is available on your PATH."
20
+ )
21
+ if shutil.which("pandoc-crossref") is None:
22
+ raise RuntimeError(
23
+ "Pandoc-crossref must be installed to render HTML output. Install"
24
+ " pandoc-crossref so the 'pandoc-crossref' executable is available"
25
+ " on your PATH."
26
+ )
27
+ if os.path.exists("MathJax-3.1.2"):
28
+ has_local_jax = True
29
+ else:
30
+ has_local_jax = False
31
+ print("you don't have a local copy of mathjax. You could get it with")
32
+ print(
33
+ "wget https://github.com/mathjax/MathJax/archive/"
34
+ + "refs/tags/3.1.2.zip"
35
+ )
36
+ print("and then unzip")
37
+ current_dir = os.getcwd()
38
+ localfiles = {}
39
+ for k in ["csl", "bib"]:
40
+ localfiles[k] = [
41
+ f for f in os.listdir(current_dir) if f.endswith("." + k)
42
+ ]
43
+ if len(localfiles[k]) == 1:
44
+ localfiles[k] = localfiles[k][0]
45
+ else:
46
+ raise ValueError(
47
+ f"You have more than one (or no) {k} file in this directory!"
48
+ " Get rid of all but one! of "
49
+ + "and".join(localfiles[k])
50
+ )
51
+ command = [
52
+ "pandoc",
53
+ "--bibliography",
54
+ localfiles["bib"],
55
+ f"--csl={localfiles['csl']}",
56
+ "--filter",
57
+ "pandoc-crossref",
58
+ "--citeproc",
59
+ "--mathjax",
60
+ "--number-sections",
61
+ "--toc",
62
+ "-s",
63
+ "-o",
64
+ html_file,
65
+ filename,
66
+ ]
67
+ # command = ['pandoc', '-s', '--mathjax', '-o', html_file, filename]
68
+ print("running:", " ".join(command))
69
+ subprocess.run(
70
+ command,
71
+ )
72
+ print("running:\n", command)
73
+ if has_local_jax:
74
+ # {{{ for slow internet connection, remove remote files
75
+ with open(html_file, encoding="utf-8") as fp:
76
+ text = fp.read()
77
+ patterns = [
78
+ r"<script.{0,20}?cdn\.jsdeli.{0,20}?mathjax.{0,60}?script>",
79
+ r"<script.{0,20}?https...polyfill.{0,60}?script>",
80
+ ]
81
+ for j in patterns:
82
+ text = re.sub(j, "", text, flags=re.DOTALL)
83
+ with open(html_file, "w", encoding="utf-8") as fp:
84
+ fp.write(text)
85
+ # }}}
86
+ with open(html_file, encoding="utf-8") as fp:
87
+ text = fp.read()
88
+ style_block = (
89
+ '\n<style id="pydifftools-hide-low-headers">\n'
90
+ "h5, h6 { display: none; }\n"
91
+ "</style>\n"
92
+ )
93
+ if style_block not in text:
94
+ # hide organizational headers while keeping higher levels visible
95
+ if "</head>" in text:
96
+ text = text.replace("</head>", style_block + "</head>", 1)
97
+ else:
98
+ text = style_block + text
99
+ with open(html_file, "w", encoding="utf-8") as fp:
100
+ fp.write(text)
101
+ return
102
+
103
+
104
+ class Handler(FileSystemEventHandler):
105
+ def __init__(self, filename, observer):
106
+ self.observer = observer
107
+ self.filename = filename
108
+ self.html_file = filename.rsplit(".", 1)[0] + ".html"
109
+ self.init_firefox()
110
+
111
+ def init_firefox(self):
112
+ # apparently, selenium breaks stdin/out for tests, so it must be
113
+ # imported here
114
+ from selenium import webdriver
115
+
116
+ self.firefox = webdriver.Chrome()
117
+ run_pandoc(self.filename, self.html_file)
118
+ if not os.path.exists(self.html_file):
119
+ print("html doesn't exist")
120
+ self.append_autorefresh()
121
+ self.firefox.get("file://" + os.path.abspath(self.html_file))
122
+
123
+ def on_modified(self, event):
124
+ from selenium.common.exceptions import WebDriverException
125
+
126
+ if os.path.normpath(
127
+ os.path.abspath(event.src_path)
128
+ ) == os.path.normpath(os.path.abspath(self.filename)):
129
+ run_pandoc(self.filename, self.html_file)
130
+ self.append_autorefresh()
131
+ try:
132
+ self.firefox.refresh()
133
+ except WebDriverException:
134
+ print(
135
+ "I'm quitting!! You probably suspended the computer, which"
136
+ " seems to freak selenium out. Just restart"
137
+ )
138
+ self.firefox.quit()
139
+ self.init_firefox()
140
+
141
+ def append_autorefresh(self):
142
+ with open(self.html_file, "r", encoding="utf-8") as fp:
143
+ all_data = fp.read()
144
+ all_data = all_data.replace(
145
+ "</head>",
146
+ """
147
+ <script id="MathJax-script" async src="MathJax-3.1.2/es5/tex-mml-chtml.js"\
148
+ ></script>
149
+ <script>
150
+ // When the page is about to be unloaded, save the current scroll\
151
+ position
152
+ window.addEventListener('beforeunload', function() {
153
+ sessionStorage.setItem('scrollPosition', window.scrollY);
154
+ });
155
+
156
+ // When the page has loaded, scroll to the previous scroll position
157
+ window.addEventListener('load', function() {
158
+ var scrollPosition = sessionStorage.getItem('scrollPosition');
159
+ if (scrollPosition) {
160
+ window.scrollTo(0, scrollPosition);
161
+ sessionStorage.removeItem('scrollPosition');
162
+ }
163
+ });
164
+ </script>
165
+ </head>
166
+ """,
167
+ )
168
+ with open(self.html_file, "w", encoding="utf-8") as fp:
169
+ fp.write(all_data)
170
+
171
+
172
+ @register_command(
173
+ "continuous pandoc build. Like latexmk, but for markdown!",
174
+ help={"filename": "Markdown or TeX file to watch for changes"},
175
+ )
176
+ def cpb(filename):
177
+ observer = Observer()
178
+ event_handler = Handler(filename, observer)
179
+ observer.schedule(event_handler, path=".", recursive=False)
180
+ observer.start()
181
+
182
+ try:
183
+ while True:
184
+ time.sleep(1)
185
+ except KeyboardInterrupt:
186
+ observer.stop()
187
+
188
+ observer.join()
189
+
190
+
191
+ if __name__ == "__main__":
192
+ filename = sys.argv[1]
193
+ cpb(filename)
194
+ # Open the HTML file in the default web browser
@@ -0,0 +1,75 @@
1
+ # from https://tex.stackexchange.com/questions/24542/create-list-of-all-external-files-used-by-master-latex-document
2
+ """Copy figures used by document."""
3
+ import os
4
+ import shutil
5
+ from pathlib import Path, PurePosixPath
6
+ import subprocess
7
+ import sys
8
+
9
+
10
+ def copy_image_files(ROOT_TEX, project_name, TARGET_DIR, include_suppinfo):
11
+ all_files = []
12
+ with open(ROOT_TEX + ".tex", "r") as fp:
13
+ alltext = fp.read()
14
+ if r"\RequirePackage{snapshot}" not in alltext:
15
+ raise RuntimeError(
16
+ "You haven't called \\RequirePackage{snapshot} in the root tex file. I can't do my thing without that!"
17
+ )
18
+ with open(ROOT_TEX + ".dep", "r") as f:
19
+ for line in f:
20
+ if "*{file}" in line:
21
+ value = line.split("{")[2].split("}")
22
+ source = value[0]
23
+ _, e = os.path.splitext(source)
24
+ if len(e) == 0 and os.path.exists(source + ".tex"):
25
+ all_files.append(source + ".tex")
26
+ print("found", source + ".tex")
27
+ elif os.path.exists(source):
28
+ all_files.append(source)
29
+ elif "*{package}" in line:
30
+ value = line.split("{")[2].split("}")
31
+ source = value[0]
32
+ _, e = os.path.splitext(source)
33
+ if len(e) == 0 and os.path.exists(source + ".sty"):
34
+ all_files.append(source + ".sty")
35
+ print("found", source + ".sty")
36
+ elif os.path.exists(source):
37
+ all_files.append(source)
38
+ else:
39
+ continue
40
+ os.makedirs(TARGET_DIR, exist_ok=True)
41
+ if include_suppinfo:
42
+ all_files.append("suppinfo.pdf")
43
+ all_files.append("suppinfo.aux")
44
+ for source in all_files:
45
+ d, f = os.path.split(source)
46
+ b, _ = os.path.splitext(source)
47
+ if b == ROOT_TEX:
48
+ f = f.replace(ROOT_TEX, "ms")
49
+ newpath = TARGET_DIR / d / f
50
+ print("copying", source, PurePosixPath(newpath))
51
+ if len(d) > 0:
52
+ print("going to make", newpath.parents[0])
53
+ os.makedirs(newpath.parents[0], exist_ok=True)
54
+ shutil.copy(source, PurePosixPath(newpath))
55
+ shutil.copy(ROOT_TEX + ".tex", os.path.join(TARGET_DIR, "ms.tex"))
56
+
57
+
58
+ if __name__ == "__main__":
59
+ copy_image_files()
60
+ os.chdir(Path.cwd().parent)
61
+ output_filename = f"{project_name}_forarxiv.tgz"
62
+ # create tar process
63
+ tar = subprocess.Popen(
64
+ ["tar", "cf", "-", TARGET_DIR.name], stdout=subprocess.PIPE
65
+ )
66
+ # create gzip process, using tar's stdout as its stdin
67
+ gzip = subprocess.Popen(
68
+ ["gzip", "-9"], stdin=tar.stdout, stdout=subprocess.PIPE
69
+ )
70
+ # close tar's stdout so it doesn't hang around waiting for input
71
+ tar.stdout.close()
72
+ # write gzip's stdout to a file
73
+ with open(output_filename, "wb") as fp:
74
+ shutil.copyfileobj(gzip.stdout, fp)
75
+ gzip.stdout.close()
@@ -0,0 +1,193 @@
1
+ //
2
+ // TortoiseSVN Diff script for Word Doc files
3
+ //
4
+ // Copyright (C) 2004-2008 the TortoiseSVN team
5
+ // This file is distributed under the same license as TortoiseSVN
6
+ //
7
+ // Last commit by:
8
+ // $Author$
9
+ // $Date$
10
+ // $Rev$
11
+ //
12
+ // Authors:
13
+ // Jared Silva, 2008
14
+ // Davide Orlandi and Hans-Emil Skogh, 2005
15
+ //
16
+
17
+ var objArgs,num,sBaseDoc,sNewDoc,sTempDoc,objScript,word,destination;
18
+ // Microsoft Office versions for Microsoft Windows OS
19
+ var vOffice2000 = 9;
20
+ var vOffice2002 = 10;
21
+ var vOffice2003 = 11;
22
+ var vOffice2007 = 12;
23
+ // WdCompareTarget
24
+ var wdCompareTargetSelected = 0;
25
+ var wdCompareTargetCurrent = 1;
26
+ var wdCompareTargetNew = 2;
27
+ // WdViewType
28
+ var wdMasterView = 5;
29
+ var wdNormalView = 1;
30
+ var wdOutlineView = 2;
31
+ // WdSaveOptions
32
+ var wdDoNotSaveChanges = 0;
33
+ var wdPromptToSaveChanges = -2;
34
+ var wdSaveChanges = -1;
35
+
36
+ objArgs = WScript.Arguments;
37
+ num = objArgs.length;
38
+ if (num < 2)
39
+ {
40
+ WScript.Echo("Usage: [CScript | WScript] diff-doc.js base.doc new.doc");
41
+ WScript.Quit(1);
42
+ }
43
+
44
+ sBaseDoc = objArgs(0);
45
+ sNewDoc = objArgs(1);
46
+
47
+ objScript = new ActiveXObject("Scripting.FileSystemObject");
48
+ if ( ! objScript.FileExists(sBaseDoc))
49
+ {
50
+ WScript.Echo("File " + sBaseDoc + " does not exist. Cannot compare the documents.");
51
+ WScript.Quit(1);
52
+ }
53
+ if ( ! objScript.FileExists(sNewDoc))
54
+ {
55
+ WScript.Echo("File " + sNewDoc + " does not exist. Cannot compare the documents.");
56
+ WScript.Quit(1);
57
+ }
58
+
59
+ try
60
+ {
61
+ word = WScript.CreateObject("Word.Application");
62
+ }
63
+ catch(e)
64
+ {
65
+ // before giving up, try with OpenOffice
66
+ try
67
+ {
68
+ var OO;
69
+ OO = WScript.CreateObject("com.sun.star.ServiceManager");
70
+ }
71
+ catch(e)
72
+ {
73
+ WScript.Echo("You must have Microsoft Word or OpenOffice installed to perform this operation.");
74
+ WScript.Quit(1);
75
+ }
76
+ // yes, OO is installed - do the diff with that one instead
77
+ var objFile = objScript.GetFile(sNewDoc);
78
+ if ((objFile.Attributes & 1)==1)
79
+ {
80
+ // reset the readonly attribute
81
+ objFile.Attributes = objFile.Attributes & (~1);
82
+ }
83
+ //Create the DesktopSet
84
+ var objDesktop = OO.createInstance("com.sun.star.frame.Desktop");
85
+ var objUriTranslator = OO.createInstance("com.sun.star.uri.ExternalUriReferenceTranslator");
86
+ //Adjust the paths for OO
87
+ sBaseDoc = sBaseDoc.replace(/\\/g, "/");
88
+ sBaseDoc = sBaseDoc.replace(/:/g, "|");
89
+ sBaseDoc = sBaseDoc.replace(/ /g, "%20");
90
+ sBaseDoc="file:///" + sBaseDoc;
91
+ sBaseDoc=objUriTranslator.translateToInternal(sBaseDoc);
92
+ sNewDoc = sNewDoc.replace(/\\/g, "/");
93
+ sNewDoc = sNewDoc.replace(/:/g, "|");
94
+ sNewDoc = sNewDoc.replace(/ /g, "%20");
95
+ sNewDoc="file:///" + sNewDoc;
96
+ sNewDoc=objUriTranslator.translateToInternal(sNewDoc);
97
+
98
+ //Open the %base document
99
+ var oPropertyValue = new Array();
100
+ oPropertyValue[0] = OO.Bridge_GetStruct("com.sun.star.beans.PropertyValue");
101
+ oPropertyValue[0].Name = "ShowTrackedChanges";
102
+ oPropertyValue[0].Value = true;
103
+ var objDocument=objDesktop.loadComponentFromURL(sNewDoc,"_blank", 0, oPropertyValue);
104
+
105
+ //Set the frame
106
+ var Frame = objDesktop.getCurrentFrame();
107
+
108
+ var dispatcher=OO.CreateInstance("com.sun.star.frame.DispatchHelper");
109
+
110
+ //Execute the comparison
111
+ dispatcher.executeDispatch(Frame, ".uno:ShowTrackedChanges", "", 0, oPropertyValue);
112
+ oPropertyValue[0].Name = "URL";
113
+ oPropertyValue[0].Value = sBaseDoc;
114
+ dispatcher.executeDispatch(Frame, ".uno:CompareDocuments", "", 0, oPropertyValue);
115
+ WScript.Quit(0);
116
+ }
117
+
118
+ if (parseInt(word.Version) >= vOffice2007)
119
+ {
120
+ sTempDoc = sNewDoc;
121
+ sNewDoc = sBaseDoc;
122
+ sBaseDoc = sTempDoc;
123
+ }
124
+
125
+ objScript = null;
126
+
127
+ word.visible = true;
128
+
129
+ // Open the new document
130
+ try
131
+ {
132
+ destination = word.Documents.Open(sNewDoc, true, true);
133
+ }
134
+ catch(e)
135
+ {
136
+ WScript.Echo("Error opening " + sNewDoc);
137
+ // Quit
138
+ WScript.Quit(1);
139
+ }
140
+
141
+ // If the Type property returns either wdOutlineView or wdMasterView and the Count property returns zero, the current document is an outline.
142
+ if (((destination.ActiveWindow.View.Type == wdOutlineView) || (destination.ActiveWindow.View.Type == wdMasterView)) && (destination.Subdocuments.Count == 0))
143
+ {
144
+ // Change the Type property of the current document to normal
145
+ destination.ActiveWindow.View.Type = wdNormalView;
146
+ }
147
+
148
+ // Compare to the base document
149
+ if (parseInt(word.Version) <= vOffice2000)
150
+ {
151
+ // Compare for Office 2000 and earlier
152
+ try
153
+ {
154
+ destination.Compare(sBaseDoc);
155
+ }
156
+ catch(e)
157
+ {
158
+ WScript.Echo("Error comparing " + sBaseDoc + " and " + sNewDoc);
159
+ // Quit
160
+ WScript.Quit(1);
161
+ }
162
+ }
163
+ else
164
+ {
165
+ // Compare for Office XP (2002) and later
166
+ try
167
+ {
168
+ destination.Compare(sBaseDoc, "Comparison", wdCompareTargetNew, true, true);
169
+ }
170
+ catch(e)
171
+ {
172
+ WScript.Echo("Error comparing " + sBaseDoc + " and " + sNewDoc);
173
+ // Close the first document and quit
174
+ destination.Close(wdDoNotSaveChanges);
175
+ WScript.Quit(1);
176
+ }
177
+ }
178
+
179
+ // Show the comparison result
180
+ if (parseInt(word.Version) < vOffice2007)
181
+ {
182
+ word.ActiveDocument.Windows(1).Visible = 1;
183
+ }
184
+
185
+ // Mark the comparison document as saved to prevent the annoying
186
+ // "Save as" dialog from appearing.
187
+ word.ActiveDocument.Saved = 1;
188
+
189
+ // Close the first document
190
+ if (parseInt(word.Version) >= vOffice2002)
191
+ {
192
+ destination.Close(wdDoNotSaveChanges);
193
+ }