shellscripts 0.23.1__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.
- shell_scripts/__init__.py +5 -0
- shell_scripts/__main__.py +5 -0
- shell_scripts/commands/__init__.py +81 -0
- shell_scripts/commands/_dc_common.py +138 -0
- shell_scripts/commands/ai_install.py +453 -0
- shell_scripts/commands/bin_links.py +78 -0
- shell_scripts/commands/claude.py +56 -0
- shell_scripts/commands/clean.py +98 -0
- shell_scripts/commands/codex.py +107 -0
- shell_scripts/commands/copilot.py +54 -0
- shell_scripts/commands/dicom2jpg.py +98 -0
- shell_scripts/commands/dicomviewer.py +83 -0
- shell_scripts/commands/diff_cmd.py +50 -0
- shell_scripts/commands/doxygen_cmd.py +159 -0
- shell_scripts/commands/edit_cmd.py +50 -0
- shell_scripts/commands/gemini.py +54 -0
- shell_scripts/commands/kiro.py +54 -0
- shell_scripts/commands/opencode.py +54 -0
- shell_scripts/commands/pdf_crop.py +520 -0
- shell_scripts/commands/pdf_merge.py +180 -0
- shell_scripts/commands/pdf_split_by_format.py +243 -0
- shell_scripts/commands/pdf_split_by_toc.py +197 -0
- shell_scripts/commands/pdf_tiler_090.py +61 -0
- shell_scripts/commands/pdf_tiler_100.py +61 -0
- shell_scripts/commands/pdf_toc_clean.py +175 -0
- shell_scripts/commands/pi.py +61 -0
- shell_scripts/commands/req_cmd.py +362 -0
- shell_scripts/commands/tests_cmd.py +87 -0
- shell_scripts/commands/ubuntu_dark_theme.py +64 -0
- shell_scripts/commands/venv_cmd.py +82 -0
- shell_scripts/commands/video2h264.py +89 -0
- shell_scripts/commands/video2h265.py +87 -0
- shell_scripts/commands/view_cmd.py +50 -0
- shell_scripts/commands/vscode_cmd.py +42 -0
- shell_scripts/commands/vsinsider_cmd.py +42 -0
- shell_scripts/config.py +328 -0
- shell_scripts/core.py +324 -0
- shell_scripts/utils.py +455 -0
- shell_scripts/version_check.py +323 -0
- shellscripts-0.23.1.dist-info/METADATA +310 -0
- shellscripts-0.23.1.dist-info/RECORD +45 -0
- shellscripts-0.23.1.dist-info/WHEEL +5 -0
- shellscripts-0.23.1.dist-info/entry_points.txt +3 -0
- shellscripts-0.23.1.dist-info/licenses/LICENSE +674 -0
- shellscripts-0.23.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
import os
|
|
3
|
+
import shutil
|
|
4
|
+
import subprocess
|
|
5
|
+
import tempfile
|
|
6
|
+
import xml.etree.ElementTree as ET
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
from shell_scripts.utils import require_project_root, require_commands, print_error
|
|
10
|
+
|
|
11
|
+
PROGRAM = "shellscripts"
|
|
12
|
+
DESCRIPTION = "Generate Doxygen documentation (HTML, PDF, Markdown)."
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def print_help(version):
|
|
16
|
+
print(f"Usage: {PROGRAM} doxygen ({version})")
|
|
17
|
+
print()
|
|
18
|
+
print("doxygen options:")
|
|
19
|
+
print(" --help - Show this help message.")
|
|
20
|
+
print()
|
|
21
|
+
print("Generates HTML, PDF, and Markdown documentation in doxygen/ directory.")
|
|
22
|
+
print("Requires: doxygen, make, pdflatex.")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _supports_generate_markdown():
|
|
26
|
+
require_commands("doxygen")
|
|
27
|
+
try:
|
|
28
|
+
result = subprocess.run(
|
|
29
|
+
["doxygen", "-x"],
|
|
30
|
+
capture_output=True,
|
|
31
|
+
text=True,
|
|
32
|
+
timeout=10,
|
|
33
|
+
)
|
|
34
|
+
return "GENERATE_MARKDOWN" in result.stdout
|
|
35
|
+
except Exception:
|
|
36
|
+
return False
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _write_doxyfile(path, project_root, src_dir, doxygen_dir, has_md):
|
|
40
|
+
content = f"""PROJECT_NAME = "{project_root.name}"
|
|
41
|
+
OUTPUT_DIRECTORY = "{doxygen_dir}"
|
|
42
|
+
INPUT = "{src_dir}"
|
|
43
|
+
FILE_PATTERNS = *.py *.sh *.js *.ts *.go *.java *.c *.cpp *.h *.hpp *.rb *.php *.rs *.swift *.kt *.scala *.lua *.r *.m *.mm *.cs
|
|
44
|
+
RECURSIVE = YES
|
|
45
|
+
EXTRACT_ALL = YES
|
|
46
|
+
EXTRACT_PRIVATE = YES
|
|
47
|
+
EXTRACT_STATIC = YES
|
|
48
|
+
EXTRACT_LOCAL_CLASSES = YES
|
|
49
|
+
EXTRACT_ANON_NSPACES = YES
|
|
50
|
+
JAVADOC_AUTOBRIEF = YES
|
|
51
|
+
MULTILINE_CPP_IS_BRIEF = YES
|
|
52
|
+
SORT_MEMBER_DOCS = YES
|
|
53
|
+
SORT_BRIEF_DOCS = YES
|
|
54
|
+
FULL_PATH_NAMES = NO
|
|
55
|
+
STRIP_FROM_PATH = "{project_root}"
|
|
56
|
+
WARN_IF_UNDOCUMENTED = NO
|
|
57
|
+
WARN_IF_DOC_ERROR = YES
|
|
58
|
+
WARN_NO_PARAMDOC = NO
|
|
59
|
+
QUIET = YES
|
|
60
|
+
GENERATE_HTML = YES
|
|
61
|
+
HTML_OUTPUT = html
|
|
62
|
+
GENERATE_LATEX = YES
|
|
63
|
+
LATEX_OUTPUT = latex
|
|
64
|
+
USE_PDFLATEX = YES
|
|
65
|
+
GENERATE_XML = YES
|
|
66
|
+
XML_OUTPUT = xml
|
|
67
|
+
MARKDOWN_ID_STYLE = GITHUB
|
|
68
|
+
TOC_INCLUDE_HEADINGS = 3
|
|
69
|
+
"""
|
|
70
|
+
if has_md:
|
|
71
|
+
content += "GENERATE_MARKDOWN = YES\nMARKDOWN_OUTPUT = markdown\n"
|
|
72
|
+
|
|
73
|
+
Path(path).write_text(content)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _generate_markdown_fallback(xml_dir, markdown_dir):
|
|
77
|
+
markdown_dir.mkdir(parents=True, exist_ok=True)
|
|
78
|
+
index_xml = xml_dir / "index.xml"
|
|
79
|
+
if not index_xml.exists():
|
|
80
|
+
return
|
|
81
|
+
|
|
82
|
+
root = ET.parse(str(index_xml)).getroot()
|
|
83
|
+
entries = []
|
|
84
|
+
for compound in root.findall("compound"):
|
|
85
|
+
name = (compound.findtext("name") or "").strip()
|
|
86
|
+
kind = (compound.get("kind") or "").strip()
|
|
87
|
+
refid = (compound.get("refid") or "").strip()
|
|
88
|
+
if name:
|
|
89
|
+
entries.append((kind, name, refid))
|
|
90
|
+
|
|
91
|
+
entries.sort(key=lambda item: (item[0], item[1]))
|
|
92
|
+
lines = ["# Doxygen Markdown Index", "", "Generated from Doxygen XML output.", ""]
|
|
93
|
+
for kind, name, refid in entries:
|
|
94
|
+
lines.append(f"- `{kind}` `{name}` (`{refid}`)")
|
|
95
|
+
|
|
96
|
+
(markdown_dir / "index.md").write_text("\n".join(lines) + "\n")
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def run(args):
|
|
100
|
+
project_root = require_project_root()
|
|
101
|
+
os.chdir(project_root)
|
|
102
|
+
|
|
103
|
+
require_commands("doxygen")
|
|
104
|
+
|
|
105
|
+
src_dir = project_root / "src"
|
|
106
|
+
doxygen_dir = project_root / "doxygen"
|
|
107
|
+
html_dir = doxygen_dir / "html"
|
|
108
|
+
markdown_dir = doxygen_dir / "markdown"
|
|
109
|
+
pdf_dir = doxygen_dir / "pdf"
|
|
110
|
+
latex_dir = doxygen_dir / "latex"
|
|
111
|
+
xml_dir = doxygen_dir / "xml"
|
|
112
|
+
|
|
113
|
+
if not src_dir.is_dir():
|
|
114
|
+
print_error(f"Source directory not found: {src_dir}")
|
|
115
|
+
return 1
|
|
116
|
+
|
|
117
|
+
has_md = _supports_generate_markdown()
|
|
118
|
+
|
|
119
|
+
for d in (html_dir, markdown_dir, pdf_dir, latex_dir, xml_dir):
|
|
120
|
+
if d.exists():
|
|
121
|
+
shutil.rmtree(d)
|
|
122
|
+
doxygen_dir.mkdir(parents=True, exist_ok=True)
|
|
123
|
+
pdf_dir.mkdir(parents=True, exist_ok=True)
|
|
124
|
+
|
|
125
|
+
with tempfile.NamedTemporaryFile(mode="w", suffix=".conf", delete=False) as f:
|
|
126
|
+
doxyfile = f.name
|
|
127
|
+
try:
|
|
128
|
+
_write_doxyfile(doxyfile, project_root, src_dir, doxygen_dir, has_md)
|
|
129
|
+
result = subprocess.run(["doxygen", doxyfile])
|
|
130
|
+
if result.returncode != 0:
|
|
131
|
+
print_error("Doxygen generation failed.")
|
|
132
|
+
return 1
|
|
133
|
+
finally:
|
|
134
|
+
os.unlink(doxyfile)
|
|
135
|
+
|
|
136
|
+
if not has_md:
|
|
137
|
+
_generate_markdown_fallback(xml_dir, markdown_dir)
|
|
138
|
+
|
|
139
|
+
makefile = latex_dir / "Makefile"
|
|
140
|
+
if makefile.exists():
|
|
141
|
+
from shell_scripts.utils import command_exists
|
|
142
|
+
|
|
143
|
+
if command_exists("make") and command_exists("pdflatex"):
|
|
144
|
+
require_commands("make", "pdflatex")
|
|
145
|
+
subprocess.run(["make", "-C", str(latex_dir)], stdout=subprocess.DEVNULL)
|
|
146
|
+
refman = latex_dir / "refman.pdf"
|
|
147
|
+
if refman.exists():
|
|
148
|
+
shutil.copy2(str(refman), str(pdf_dir / "refman.pdf"))
|
|
149
|
+
else:
|
|
150
|
+
print_error(f"PDF artifact not generated: {refman}")
|
|
151
|
+
else:
|
|
152
|
+
print_error("'make' or 'pdflatex' not found; skipping PDF build.")
|
|
153
|
+
|
|
154
|
+
print(f"Generated: {html_dir}")
|
|
155
|
+
print(f"Generated: {markdown_dir}")
|
|
156
|
+
if (pdf_dir / "refman.pdf").exists():
|
|
157
|
+
print(f"Generated: {pdf_dir / 'refman.pdf'}")
|
|
158
|
+
|
|
159
|
+
return 0
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""@brief MIME-based edit command wrapper.
|
|
3
|
+
|
|
4
|
+
@details Exposes the `edit` CLI command and delegates category-based executable
|
|
5
|
+
selection to shared `_dc_common.dispatch` logic.
|
|
6
|
+
@satisfies PRJ-003, DES-007, REQ-023, REQ-024
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import sys
|
|
10
|
+
|
|
11
|
+
from shell_scripts.config import get_dispatch_profile
|
|
12
|
+
from shell_scripts.commands._dc_common import dispatch
|
|
13
|
+
|
|
14
|
+
PROGRAM = "shellscripts"
|
|
15
|
+
DESCRIPTION = "File editor dispatcher by MIME type."
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def print_help(version):
|
|
19
|
+
"""@brief Render command help for `edit`.
|
|
20
|
+
|
|
21
|
+
@details Prints usage, required file argument semantics, and argument
|
|
22
|
+
forwarding contract for the selected external editor executable.
|
|
23
|
+
@param version {str} Version string appended in usage output.
|
|
24
|
+
@return {None} Writes help text to stdout.
|
|
25
|
+
@satisfies DES-008
|
|
26
|
+
"""
|
|
27
|
+
print(f"Usage: {PROGRAM} edit <file> [args...] ({version})")
|
|
28
|
+
print()
|
|
29
|
+
print("edit options:")
|
|
30
|
+
print(" <file> - File to edit (required).")
|
|
31
|
+
print(" Additional arguments are passed to the selected editor.")
|
|
32
|
+
print(" --help - Show this help message.")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def run(args):
|
|
36
|
+
"""@brief Execute MIME-routed edit dispatch.
|
|
37
|
+
|
|
38
|
+
@details Validates that a file argument exists; on missing argument prints
|
|
39
|
+
error plus help and returns status code `2`; otherwise resolves runtime
|
|
40
|
+
dispatch profile and delegates by file category through shared `_dc_common`.
|
|
41
|
+
@param args {list[str]} CLI args where `args[0]` is file path.
|
|
42
|
+
@return {int} Return code `2` on missing file; otherwise delegated dispatch result.
|
|
43
|
+
@satisfies REQ-023, REQ-024
|
|
44
|
+
"""
|
|
45
|
+
if not args:
|
|
46
|
+
print("Error: file argument required.", file=sys.stderr)
|
|
47
|
+
print_help("")
|
|
48
|
+
return 2
|
|
49
|
+
category_cmds, fallback = get_dispatch_profile("edit")
|
|
50
|
+
return dispatch(category_cmds, fallback, args[0], args[1:])
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""@brief Google Gemini CLI launcher in project context.
|
|
3
|
+
|
|
4
|
+
@details Ensures project-root prerequisite and executable availability before
|
|
5
|
+
blocking subprocess invocation of `gemini`.
|
|
6
|
+
@satisfies REQ-016, REQ-055, REQ-056, REQ-064
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import subprocess
|
|
10
|
+
|
|
11
|
+
from shell_scripts.utils import require_project_root, require_commands
|
|
12
|
+
|
|
13
|
+
## @var PROGRAM
|
|
14
|
+
# @brief Base CLI program name used in help output.
|
|
15
|
+
# @details Constant identifier for usage-line rendering in command help.
|
|
16
|
+
PROGRAM = "shellscripts"
|
|
17
|
+
## @var DESCRIPTION
|
|
18
|
+
# @brief One-line command description for dispatcher help surfaces.
|
|
19
|
+
# @details Exposed by command registry introspection (`get_all_commands`).
|
|
20
|
+
DESCRIPTION = "Launch Google Gemini CLI in the project context."
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def print_help(version):
|
|
24
|
+
"""@brief Print command-specific help for `gemini`.
|
|
25
|
+
|
|
26
|
+
@details Emits usage and pass-through argument behavior for deterministic
|
|
27
|
+
terminal rendering; does not mutate process state.
|
|
28
|
+
@param version {str} CLI version string propagated by dispatcher.
|
|
29
|
+
@return {None} Writes help text to stdout.
|
|
30
|
+
@satisfies DES-008
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
print(f"Usage: {PROGRAM} gemini [args...] ({version})")
|
|
34
|
+
print()
|
|
35
|
+
print("gemini options:")
|
|
36
|
+
print(" All arguments are passed through to the Gemini CLI.")
|
|
37
|
+
print(" --help - Show this help message.")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def run(args):
|
|
41
|
+
"""@brief Launch Gemini CLI after external executable validation.
|
|
42
|
+
|
|
43
|
+
@details Resolves project root, checks executable availability for
|
|
44
|
+
`gemini`, then executes pass-through args through blocking subprocess run.
|
|
45
|
+
@param args {list[str]} Additional CLI args forwarded to Gemini.
|
|
46
|
+
@return {int} Child process return code.
|
|
47
|
+
@satisfies REQ-016, REQ-055, REQ-056, REQ-064
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
require_project_root()
|
|
51
|
+
cmd = ["gemini", "--yolo"] + args
|
|
52
|
+
cmd[0] = require_commands(cmd[0])
|
|
53
|
+
result = subprocess.run(cmd)
|
|
54
|
+
return result.returncode
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""@brief Kiro CLI launcher in project context.
|
|
3
|
+
|
|
4
|
+
@details Ensures project-root prerequisite and executable availability before
|
|
5
|
+
blocking subprocess invocation of `kiro-cli`.
|
|
6
|
+
@satisfies REQ-019, REQ-055, REQ-056, REQ-064
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import subprocess
|
|
10
|
+
|
|
11
|
+
from shell_scripts.utils import require_project_root, require_commands
|
|
12
|
+
|
|
13
|
+
## @var PROGRAM
|
|
14
|
+
# @brief Base CLI program name used in help output.
|
|
15
|
+
# @details Constant identifier for usage-line rendering in command help.
|
|
16
|
+
PROGRAM = "shellscripts"
|
|
17
|
+
## @var DESCRIPTION
|
|
18
|
+
# @brief One-line command description for dispatcher help surfaces.
|
|
19
|
+
# @details Exposed by command registry introspection (`get_all_commands`).
|
|
20
|
+
DESCRIPTION = "Launch Kiro CLI in the project context."
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def print_help(version):
|
|
24
|
+
"""@brief Print command-specific help for `kiro`.
|
|
25
|
+
|
|
26
|
+
@details Emits usage and pass-through argument behavior for deterministic
|
|
27
|
+
terminal rendering; does not mutate process state.
|
|
28
|
+
@param version {str} CLI version string propagated by dispatcher.
|
|
29
|
+
@return {None} Writes help text to stdout.
|
|
30
|
+
@satisfies DES-008
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
print(f"Usage: {PROGRAM} kiro [args...] ({version})")
|
|
34
|
+
print()
|
|
35
|
+
print("kiro options:")
|
|
36
|
+
print(" All arguments are passed through to the Kiro CLI.")
|
|
37
|
+
print(" --help - Show this help message.")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def run(args):
|
|
41
|
+
"""@brief Launch Kiro CLI after external executable validation.
|
|
42
|
+
|
|
43
|
+
@details Resolves project root, validates executable availability for
|
|
44
|
+
`kiro-cli`, then executes pass-through args through blocking subprocess run.
|
|
45
|
+
@param args {list[str]} Additional CLI args forwarded to Kiro.
|
|
46
|
+
@return {int} Child process return code.
|
|
47
|
+
@satisfies REQ-019, REQ-055, REQ-056, REQ-064
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
require_project_root()
|
|
51
|
+
cmd = ["kiro-cli"] + args
|
|
52
|
+
cmd[0] = require_commands(cmd[0])
|
|
53
|
+
result = subprocess.run(cmd)
|
|
54
|
+
return result.returncode
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""@brief OpenCode CLI launcher in project context.
|
|
3
|
+
|
|
4
|
+
@details Ensures project-root prerequisite and executable availability before
|
|
5
|
+
blocking subprocess invocation of `opencode`.
|
|
6
|
+
@satisfies REQ-018, REQ-055, REQ-056, REQ-064
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import subprocess
|
|
10
|
+
|
|
11
|
+
from shell_scripts.utils import require_project_root, require_commands
|
|
12
|
+
|
|
13
|
+
## @var PROGRAM
|
|
14
|
+
# @brief Base CLI program name used in help output.
|
|
15
|
+
# @details Constant identifier for usage-line rendering in command help.
|
|
16
|
+
PROGRAM = "shellscripts"
|
|
17
|
+
## @var DESCRIPTION
|
|
18
|
+
# @brief One-line command description for dispatcher help surfaces.
|
|
19
|
+
# @details Exposed by command registry introspection (`get_all_commands`).
|
|
20
|
+
DESCRIPTION = "Launch OpenCode CLI in the project context."
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def print_help(version):
|
|
24
|
+
"""@brief Print command-specific help for `opencode`.
|
|
25
|
+
|
|
26
|
+
@details Emits usage and pass-through argument behavior for deterministic
|
|
27
|
+
terminal rendering; does not mutate process state.
|
|
28
|
+
@param version {str} CLI version string propagated by dispatcher.
|
|
29
|
+
@return {None} Writes help text to stdout.
|
|
30
|
+
@satisfies DES-008
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
print(f"Usage: {PROGRAM} opencode [args...] ({version})")
|
|
34
|
+
print()
|
|
35
|
+
print("opencode options:")
|
|
36
|
+
print(" All arguments are passed through to the OpenCode CLI.")
|
|
37
|
+
print(" --help - Show this help message.")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def run(args):
|
|
41
|
+
"""@brief Launch OpenCode CLI after external executable validation.
|
|
42
|
+
|
|
43
|
+
@details Resolves project root, checks executable availability for
|
|
44
|
+
`opencode`, then executes pass-through args through blocking subprocess run.
|
|
45
|
+
@param args {list[str]} Additional CLI args forwarded to OpenCode.
|
|
46
|
+
@return {int} Child process return code.
|
|
47
|
+
@satisfies REQ-018, REQ-055, REQ-056, REQ-064
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
require_project_root()
|
|
51
|
+
cmd = ["opencode"] + args
|
|
52
|
+
cmd[0] = require_commands(cmd[0])
|
|
53
|
+
result = subprocess.run(cmd)
|
|
54
|
+
return result.returncode
|