tagrefsorter 0.1.1__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.
@@ -0,0 +1,27 @@
1
+ Metadata-Version: 2.4
2
+ Name: tagrefsorter
3
+ Version: 0.1.1
4
+ Summary: CLI tool to normalize LaTeX \tag numbering in Jupyter Notebook files
5
+ Author-email: SuzuSys <sigmatics@outlook.jp>
6
+ License: MIT
7
+ Requires-Python: >=3.9
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: nbformat>=5.0
10
+
11
+ # tagrefsorter
12
+
13
+ A CLI tool to normalize LaTeX `\tag{}` numbering in Jupyter Notebook (`.ipynb`) files.
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ pip install tagrefsorter
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ ```bash
24
+ tagrefsorter path/to/notebook.ipynb
25
+ ```
26
+
27
+ The notebook is overwritten in place.
@@ -0,0 +1,17 @@
1
+ # tagrefsorter
2
+
3
+ A CLI tool to normalize LaTeX `\tag{}` numbering in Jupyter Notebook (`.ipynb`) files.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install tagrefsorter
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```bash
14
+ tagrefsorter path/to/notebook.ipynb
15
+ ```
16
+
17
+ The notebook is overwritten in place.
@@ -0,0 +1,28 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "tagrefsorter"
7
+ version = "0.1.1"
8
+ description = "CLI tool to normalize LaTeX \\tag numbering in Jupyter Notebook files"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = { text = "MIT" }
12
+
13
+ authors = [
14
+ { name = "SuzuSys", email = "sigmatics@outlook.jp" }
15
+ ]
16
+
17
+ dependencies = [
18
+ "nbformat>=5.0"
19
+ ]
20
+
21
+ [project.scripts]
22
+ tagrefsorter = "tagrefsorter.cli:main"
23
+
24
+ [tool.setuptools]
25
+ package-dir = { "" = "src" }
26
+
27
+ [tool.setuptools.packages.find]
28
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1 @@
1
+ __version__ = "0.1.0"
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env python3
2
+ import argparse
3
+ import pathlib
4
+ import sys
5
+ import nbformat
6
+ import re
7
+ from typing import Callable
8
+ from dataclasses import dataclass, field
9
+
10
+
11
+ def parse_args():
12
+ parser = argparse.ArgumentParser(
13
+ description="Jupyter Notebook (.ipynb) を読み込み、LaTeX の tag を整理します"
14
+ )
15
+ parser.add_argument(
16
+ "notebook",
17
+ type=pathlib.Path,
18
+ help="変更する .ipynb ファイルのパス",
19
+ )
20
+ return parser.parse_args()
21
+
22
+
23
+ _LATEX_BLOCK = re.compile(r"\$\$(.*?)\$\$", flags=re.DOTALL)
24
+ _LATEX_ALIGN = re.compile(r"\\begin\{align\}(.*?)\\end\{align\}", flags=re.DOTALL)
25
+ _LATEX_TAG = re.compile(r"\\tag\{(.*?)\}")
26
+
27
+
28
+ @dataclass
29
+ class EditState:
30
+ update_map: dict[str, str] = field(default_factory=dict)
31
+ next_tag: int = 1
32
+
33
+
34
+ def update_nb(nb: nbformat.NotebookNode) -> nbformat.NotebookNode:
35
+ state = EditState()
36
+
37
+ def sub_editor(subtex: str, align: bool) -> str:
38
+ match = _LATEX_TAG.search(subtex)
39
+ if match:
40
+ old_tag = match.group(1)
41
+ new_tag = str(state.next_tag)
42
+ if old_tag != new_tag:
43
+ state.update_map[old_tag] = new_tag
44
+ if align:
45
+ subtex = _LATEX_TAG.sub(rf"\\\\tag{{{new_tag}}}", subtex)
46
+ else:
47
+ subtex = _LATEX_TAG.sub(rf"\\tag{{{new_tag}}}", subtex)
48
+ else:
49
+ new_tag = str(state.next_tag)
50
+ if align:
51
+ subtex += rf"\\tag{{{new_tag}}}"
52
+ else:
53
+ subtex += rf"\tag{{{new_tag}}}"
54
+ state.next_tag += 1
55
+ return subtex
56
+
57
+ def editor(latex: str) -> str:
58
+ match = _LATEX_ALIGN.search(latex)
59
+ if match:
60
+ align_body = match.group(1)
61
+ parts = re.split(r"(\\\\)", align_body)
62
+ print(parts)
63
+ new_parts = []
64
+ for part in parts:
65
+ if part == r"\\":
66
+ new_parts.append(r"\\\\")
67
+ else:
68
+ new_parts.append(sub_editor(part, align=True))
69
+ print(new_parts)
70
+ new_align_body = "".join(new_parts)
71
+ latex = _LATEX_ALIGN.sub(
72
+ rf"\\begin{{align}}{new_align_body}\\end{{align}}",
73
+ latex,
74
+ )
75
+ else:
76
+ latex = sub_editor(latex, align=False)
77
+ return latex
78
+
79
+ def edit_latex_blocks(text: str, editor: Callable[[str], str]) -> str:
80
+ def repl(m: re.Match) -> str:
81
+ inner = m.group(1)
82
+ new_inner = editor(inner)
83
+ return f"$${new_inner}$$\n"
84
+
85
+ return _LATEX_BLOCK.sub(repl, text)
86
+
87
+ for cell in nb.cells:
88
+ if cell.cell_type == "markdown":
89
+ cell.source = edit_latex_blocks(cell.source, editor)
90
+
91
+ for cell in nb.cells:
92
+ if cell.cell_type == "markdown":
93
+ for old_tag, new_tag in state.update_map.items():
94
+ cell.source = re.sub(
95
+ rf"\$\({re.escape(old_tag)}\)\$",
96
+ rf"$({new_tag})$",
97
+ cell.source,
98
+ )
99
+
100
+ return nb
101
+
102
+
103
+ def main():
104
+ args = parse_args()
105
+ nb_path: pathlib.Path = args.notebook
106
+
107
+ if not nb_path.exists():
108
+ print(f"Error: file not found: {nb_path}", file=sys.stderr)
109
+ sys.exit(1)
110
+
111
+ if nb_path.suffix != ".ipynb":
112
+ print("Error: input file must be .ipynb", file=sys.stderr)
113
+ sys.exit(1)
114
+
115
+ nb = nbformat.read(nb_path, as_version=4)
116
+ updated_nb = update_nb(nb)
117
+ nbformat.write(updated_nb, nb_path)
118
+
119
+ print(f"Overwritten: {nb_path}")
@@ -0,0 +1,27 @@
1
+ Metadata-Version: 2.4
2
+ Name: tagrefsorter
3
+ Version: 0.1.1
4
+ Summary: CLI tool to normalize LaTeX \tag numbering in Jupyter Notebook files
5
+ Author-email: SuzuSys <sigmatics@outlook.jp>
6
+ License: MIT
7
+ Requires-Python: >=3.9
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: nbformat>=5.0
10
+
11
+ # tagrefsorter
12
+
13
+ A CLI tool to normalize LaTeX `\tag{}` numbering in Jupyter Notebook (`.ipynb`) files.
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ pip install tagrefsorter
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ ```bash
24
+ tagrefsorter path/to/notebook.ipynb
25
+ ```
26
+
27
+ The notebook is overwritten in place.
@@ -0,0 +1,10 @@
1
+ README.md
2
+ pyproject.toml
3
+ src/tagrefsorter/__init__.py
4
+ src/tagrefsorter/cli.py
5
+ src/tagrefsorter.egg-info/PKG-INFO
6
+ src/tagrefsorter.egg-info/SOURCES.txt
7
+ src/tagrefsorter.egg-info/dependency_links.txt
8
+ src/tagrefsorter.egg-info/entry_points.txt
9
+ src/tagrefsorter.egg-info/requires.txt
10
+ src/tagrefsorter.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ tagrefsorter = tagrefsorter.cli:main
@@ -0,0 +1 @@
1
+ nbformat>=5.0
@@ -0,0 +1 @@
1
+ tagrefsorter