fix: 3-level hierarchy in help paste output
Some checks failed
CI / gitleaks (push) Failing after 4s
CI / lint (push) Failing after 23s
CI / test (3.11) (push) Has been skipped
CI / test (3.12) (push) Has been skipped
CI / test (3.13) (push) Has been skipped
CI / build (push) Has been skipped

Plugin name at column 0, command at indent 4, docstring at indent 8.
Single-command paste keeps command at 0, docstring at 4.
Only paste when actual docstring content exists.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
user
2026-02-23 23:21:10 +01:00
parent ecfa7cea39
commit 20c1d738be
2 changed files with 67 additions and 36 deletions

View File

@@ -8,18 +8,20 @@ from derp import __version__
from derp.plugin import command
def _build_cmd_detail(handler, prefix: str) -> str:
"""Extract and format a command's docstring into a detail block.
def _build_cmd_detail(handler, prefix: str, indent: int = 0) -> str:
"""Format command header + docstring at the given indent level.
Command name anchors the left edge; docstring body is indented 4 spaces.
Command name sits at *indent*, docstring body at *indent + 4*.
Returns just the header line when no docstring exists.
"""
doc = textwrap.dedent(handler.callback.__doc__ or "").strip()
if not doc:
return ""
header = f"{prefix}{handler.name}"
pad = " " * indent
header = f"{pad}{prefix}{handler.name}"
if handler.help:
header += f" -- {handler.help}"
indented = textwrap.indent(doc, " ")
doc = textwrap.dedent(handler.callback.__doc__ or "").strip()
if not doc:
return header
indented = textwrap.indent(doc, " " * (indent + 4))
return f"{header}\n{indented}"
@@ -57,8 +59,8 @@ async def cmd_help(bot, message):
if handler and bot._plugin_allowed(handler.plugin, channel):
help_text = handler.help or "No help available."
reply = f"{bot.prefix}{name} -- {help_text}"
detail = _build_cmd_detail(handler, bot.prefix)
if detail:
if (handler.callback.__doc__ or "").strip():
detail = _build_cmd_detail(handler, bot.prefix)
url = await _paste(bot, detail)
if url:
reply += f" | {url}"
@@ -77,15 +79,20 @@ async def cmd_help(bot, message):
if cmds:
lines.append(f"Commands: {', '.join(bot.prefix + c for c in cmds)}")
reply = " | ".join(lines)
# Build detail block for all plugin commands
blocks = []
# Build detail: plugin header + indented commands
section_lines = [f"[{name}]"]
if desc:
section_lines.append(f" {desc}")
section_lines.append("")
has_detail = False
for cmd_name in cmds:
h = bot.registry.commands[cmd_name]
blk = _build_cmd_detail(h, bot.prefix)
if blk:
blocks.append(blk)
if blocks:
url = await _paste(bot, "\n\n".join(blocks))
section_lines.append(_build_cmd_detail(h, bot.prefix, indent=4))
section_lines.append("")
if (h.callback.__doc__ or "").strip():
has_detail = True
if has_detail:
url = await _paste(bot, "\n".join(section_lines).rstrip())
if url:
reply += f" | {url}"
await bot.reply(message, reply)
@@ -106,27 +113,21 @@ async def cmd_help(bot, message):
for cmd_name in names:
h = bot.registry.commands[cmd_name]
plugins.setdefault(h.plugin, []).append(cmd_name)
blocks = []
sections = []
for plugin_name in sorted(plugins):
mod = bot.registry._modules.get(plugin_name)
desc = (getattr(mod, "__doc__", "") or "").split("\n")[0].strip() if mod else ""
header = f"[{plugin_name}]"
section_lines = [f"[{plugin_name}]"]
if desc:
header += f"\n {desc}"
cmd_lines = []
section_lines.append(f" {desc}")
section_lines.append("")
for cmd_name in plugins[plugin_name]:
h = bot.registry.commands[cmd_name]
detail = _build_cmd_detail(h, bot.prefix)
if detail:
cmd_lines.append(detail)
else:
line = f"{bot.prefix}{cmd_name}"
if h.help:
line += f" -- {h.help}"
cmd_lines.append(line)
blocks.append(header + "\n\n" + "\n\n".join(cmd_lines))
if blocks:
url = await _paste(bot, "\n\n".join(blocks))
section_lines.append(_build_cmd_detail(h, bot.prefix, indent=4))
section_lines.append("")
sections.append("\n".join(section_lines).rstrip())
if sections:
url = await _paste(bot, "\n\n".join(sections))
if url:
reply += f" | {url}"
await bot.reply(message, reply)