Optimized CLI

This commit is contained in:
Kevin Veen-Birkenbach 2025-05-16 12:12:17 +02:00
parent 94a57312dd
commit 02137576bd
No known key found for this signature in database
GPG Key ID: 44D8F11FD62F878E
5 changed files with 36 additions and 13 deletions

45
main.py
View File

@ -4,6 +4,16 @@ import argparse
import os import os
import subprocess import subprocess
import sys import sys
import textwrap
def format_command_help(name, description, indent=2, col_width=36, width=80):
prefix = " " * indent + f"{name:<{col_width - indent}}"
wrapper = textwrap.TextWrapper(
width=width,
initial_indent=prefix,
subsequent_indent=" " * col_width
)
return wrapper.fill(description)
def list_cli_commands(cli_dir): def list_cli_commands(cli_dir):
return sorted( return sorted(
@ -11,17 +21,30 @@ def list_cli_commands(cli_dir):
if f.is_file() and f.name.endswith(".py") and not f.name.startswith("__") if f.is_file() and f.name.endswith(".py") and not f.name.startswith("__")
) )
def extract_docstring(cli_script_path): def extract_description_via_help(cli_script_path):
"""Run `script --help` and extract the first non-usage line after usage block."""
try: try:
with open(cli_script_path, "r", encoding="utf-8") as f: result = subprocess.run(
for line in f: [sys.executable, cli_script_path, "--help"],
if line.strip().startswith(('"""', "'''")): capture_output=True,
return line.strip().strip('"\'') text=True,
if line.strip().startswith("DESCRIPTION"): check=True
return line.split("=", 1)[1].strip().strip("\"'") )
lines = result.stdout.splitlines()
# Skip until first empty line after usage block
for i, line in enumerate(lines):
if line.strip().startswith("usage:"):
continue
if line.strip() == "":
# description usually comes after usage and empty line
for j in range(i+1, len(lines)):
desc = lines[j].strip()
if desc:
return desc
return "-"
except Exception: except Exception:
pass return "-"
return "-"
def main(): def main():
script_dir = os.path.dirname(os.path.realpath(__file__)) script_dir = os.path.dirname(os.path.realpath(__file__))
@ -44,8 +67,8 @@ def main():
print("Available commands:") print("Available commands:")
for cmd in available_cli_commands: for cmd in available_cli_commands:
path = os.path.join(cli_dir, f"{cmd}.py") path = os.path.join(cli_dir, f"{cmd}.py")
desc = extract_docstring(path) desc = extract_description_via_help(path)
print(f" {cmd:25} {desc}") print(format_command_help(cmd, desc))
print("\nUse 'cymais <command> --help' for details on each command.") print("\nUse 'cymais <command> --help' for details on each command.")
sys.exit(0) sys.exit(0)

View File

@ -29,7 +29,7 @@ class TestGenerateDefaultApplications(unittest.TestCase):
shutil.rmtree(self.temp_dir) shutil.rmtree(self.temp_dir)
def test_script_generates_expected_yaml(self): def test_script_generates_expected_yaml(self):
script_path = Path(__file__).resolve().parent.parent.parent / "cli" / "generate_defaults_applications.py" script_path = Path(__file__).resolve().parent.parent.parent / "cli" / "generate-applications-defaults.py"
result = subprocess.run( result = subprocess.run(
[ [

View File

@ -7,7 +7,7 @@ PROJECT_ROOT = Path(__file__).parent.parent.parent.resolve()
sys.path.insert(0, str(PROJECT_ROOT)) sys.path.insert(0, str(PROJECT_ROOT))
# 2) Import from the cli package # 2) Import from the cli package
import cli.generate_vaulted_credentials as gvc import cli.create_credentials as gvc
class DummyProc: class DummyProc:
def __init__(self, returncode, stdout, stderr=''): def __init__(self, returncode, stdout, stderr=''):