mirror of
https://github.com/hanzoai/insights.git
synced 2026-10-30 16:15:31 +00:00
Four internal names, none of them on a wire: is_hog_identifier_kind pub(crate) in the InsightsQL parser runHogliListUnits/DevApply unexported, in the phrocs TUI "Hogli's db:restore-..." a CI comment ".TH HOGLI 1" the generated man page's title And the reason all four survived a rule that exists to refuse exactly this: `HOGLI_` only matches when an underscore follows. The man page says `HOGLI 1`, the TUI says `Hogli`, and `tools/insightscli/AGENTS.md` wrote the heading as `HOGLI\_\*` -- markdown-escaped, so the backslash sat between the letters and the underscore the rule was anchored on. Its own body already said `INSIGHTSCLI_` throughout; only the heading was stale. So the rule takes the escaped form, the bare word, and the capitalized one. Checked against `INSIGHTSCLI_DEBUG` and `hogline`, which must stay unmatched. Rust and Go renames are whole-word, with definitions and call sites counted and no leftovers; neither toolchain is installed here, so that count is the verification, not a compile. Co-authored-by: Hanzo Dev <[email protected]>
131 lines
3.9 KiB
Python
131 lines
3.9 KiB
Python
#!/usr/bin/env python3
|
|
"""Generate the insightscli(1) man page from live CLI help output."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
import sys
|
|
import argparse
|
|
from pathlib import Path
|
|
|
|
import click
|
|
from insightscli.cli import cli
|
|
|
|
ANSI_RE = re.compile(r"\x1B\[[0-9;]*[A-Za-z]")
|
|
TERMINAL_WIDTH = 120
|
|
|
|
|
|
def _parse_args() -> argparse.Namespace:
|
|
parser = argparse.ArgumentParser(description="Generate insightscli(1) from the current CLI.")
|
|
parser.add_argument(
|
|
"--output",
|
|
type=Path,
|
|
help="Write the generated man page to this path. If omitted, print to stdout.",
|
|
)
|
|
return parser.parse_args()
|
|
|
|
|
|
def _strip_ansi(text: str) -> str:
|
|
return ANSI_RE.sub("", text)
|
|
|
|
|
|
def _escape_roff(line: str) -> str:
|
|
escaped = line.replace("\\", r"\\")
|
|
if escaped.startswith(".") or escaped.startswith("'"):
|
|
escaped = rf"\&{escaped}"
|
|
return escaped
|
|
|
|
|
|
def _collect_help_text() -> str:
|
|
ctx = click.Context(cli, info_name="insightscli", terminal_width=TERMINAL_WIDTH, color=False)
|
|
return _strip_ansi(cli.get_help(ctx)).strip()
|
|
|
|
|
|
def _collect_command_help() -> list[tuple[str, str]]:
|
|
root_ctx = click.Context(cli, info_name="insightscli", terminal_width=TERMINAL_WIDTH, color=False)
|
|
command_help_sections: list[tuple[str, str]] = []
|
|
for command_name in cli.list_commands(root_ctx):
|
|
command = cli.get_command(root_ctx, command_name)
|
|
if command is None or command.hidden:
|
|
continue
|
|
|
|
sub_ctx = click.Context(
|
|
command,
|
|
info_name=f"insightscli {command_name}",
|
|
parent=root_ctx,
|
|
terminal_width=TERMINAL_WIDTH,
|
|
color=False,
|
|
)
|
|
command_help_sections.append((command_name, _strip_ansi(command.get_help(sub_ctx)).strip()))
|
|
|
|
return command_help_sections
|
|
|
|
|
|
def _render(help_text: str, command_help_sections: list[tuple[str, str]]) -> str:
|
|
escaped_help_lines = [_escape_roff(line) for line in help_text.splitlines()]
|
|
lines = [
|
|
'.TH INSIGHTSCLI 1 "Auto-generated" "Insights" "User Commands"',
|
|
".SH NAME",
|
|
"insightscli \\- Insights developer CLI",
|
|
".SH SYNOPSIS",
|
|
".B insightscli",
|
|
"[\\fIOPTIONS\\fR] \\fICOMMAND\\fR [\\fIARGS\\fR]...",
|
|
".SH DESCRIPTION",
|
|
"\\fBinsightscli\\fR is the unified command line interface for Insights development workflows.",
|
|
"This page is generated from the current CLI help output.",
|
|
".SH HELP OUTPUT",
|
|
".nf",
|
|
*escaped_help_lines,
|
|
".fi",
|
|
]
|
|
|
|
if command_help_sections:
|
|
lines.append(".SH COMMAND HELP OUTPUT")
|
|
for command_name, command_help in command_help_sections:
|
|
lines.extend(
|
|
[
|
|
".SS \\fB" + _escape_roff(command_name) + "\\fR",
|
|
".nf",
|
|
*[_escape_roff(line) for line in command_help.splitlines()],
|
|
".fi",
|
|
]
|
|
)
|
|
|
|
lines.extend(
|
|
[
|
|
".SH FILES",
|
|
".TP",
|
|
"\\fIinsightscli.yaml\\fR",
|
|
"Command definitions and metadata.",
|
|
".TP",
|
|
"\\fItools/insightscli/src/insightscli/cli.py\\fR",
|
|
"CLI group and command registration.",
|
|
".TP",
|
|
"\\fItools/insightscli-commands/insightscli_commands/\\fR",
|
|
"Insights-specific lazy Click command modules.",
|
|
"",
|
|
]
|
|
)
|
|
return "\n".join(lines)
|
|
|
|
|
|
def _write(output_path: Path, content: str) -> None:
|
|
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
output_path.write_text(content, encoding="utf-8")
|
|
|
|
|
|
def main() -> int:
|
|
args = _parse_args()
|
|
content = _render(_collect_help_text(), _collect_command_help())
|
|
|
|
if not args.output:
|
|
sys.stdout.write(content)
|
|
return 0
|
|
|
|
_write(args.output, content)
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|