Skip to content

feat: show subcommands near the top of help output - #70

Merged
sergej-koscejev merged 5 commits into
mainfrom
issue-52-help-order
Oct 22, 2026
Merged

sergej-koscejev merged 5 commits into
mainfrom
issue-52-help-order

Conversation

@sergej-koscejev

@sergej-koscejev sergej-koscejev commented Oct 13, 2026 •

Copy link
Copy Markdown
Member

Closes #52

Summary

Command Help is laid out for mops <cmd> --help | head -N: subcommands and Explain Topics come first, the global options once at the end.

 Usage: mops find [-h] [COMMAND]
-            [--refs-as-urls] [--daemon-home=PATH] [--java-home=PATH] ...
 Search editable MPS project sources or loaded concept hierarchies.
-      --daemon-home=PATH    ...
-  -h, --help                ...
-      --mps-home=PATH       ...
 Commands:
-  subconcepts   Find extending concepts and interface implementors in all
-                  loaded language runtimes, including libraries. Excludes the ...
+  subconcepts   Find subconcepts of one MPS concept.
+  instances     Find instances of one MPS concept.
+  usages        Find references to one MPS node.
+  root-by-name  Find root nodes by name pattern.
+  node-by-id    Find every node with a given node ID.
+Options:
+  -h, --help                Show this help message and exit.
+Global options:
+      --daemon-home=PATH    ...
+      --mps-home=PATH       ...

Section order is picocli's default with three edits:

-headerHeading, header
 synopsisHeading, synopsis, descriptionHeading, description,
+commandListHeading, commandList
 parameterListHeading, ..., optionListHeading, optionList, ...
-commandListHeading, commandList
 exitCodeListHeading, exitCodeList,
+globalOptionListHeading, globalOptionList
 footerHeading, footer
cli/src/main/kotlin/com/specificlanguages/mops/cli/
├── help/HelpLayout.kt  # section order, Options / Global options split, synopsis without globals
├── Main.kt             # applies HelpLayout; appends topic lists to explain and examples
├── MopsCommand.kt      # bare `mops` prints the configured usage (was missing the command list)
└── */*Command.kt       # one-line `header` where description[0] did not fit

Evidence

  • Before: mops find --help | head -12 ends inside the first subcommand's description; mops examples --help shows no topics; bare mops prints usage without Commands:.

    After: mops find --help | head -12 lists all five subcommands on lines 4-8; mops examples --help and mops explain --help list their topics before the options; bare mops equals mops --help.

  • New tests in CommandHelpTest (commands before options for every group, one line per Commands: entry, Global options: last and listing --mps-home once, head -12, bare mops), ExamplesCommandTest and ExplainCommandTest (topics in --help). ./gradlew :cli:test passes.

Merge Danger

Door: two-way

Help text only; argument parsing is unchanged.

Blast Radius: help-text

Anything scraping help output (none in this repo's tests) sees new Options: / Global options: headings and shorter synopses.

Decisions

  • Test seams: rendered help text from newCommandLine().execute(..., "--help") (CommandHelpTest, ExamplesCommandTest, ExplainCommandTest); no tests against picocli internals.
  • The section order is derived from picocli's default keys (root.helpSectionKeys) by moving or inserting only the keys that change, instead of listing every key.
  • Global options are identified by ScopeType.INHERIT (not OptionSpec.inherited()), so the root command's own declarations land in Global options: too. They need their own section because picocli copies inherited options to subcommands but not @ArgGroups, so a named option group cannot carry them.
  • Global options are also dropped from every synopsis (via a Help subclass installed with setHelpFactory); the Global options: section documents them, and shorter synopses keep head output short.
  • Added Options: and Parameters: headings so the unlabeled blocks do not sit between labeled Commands: and Global options: sections.
  • header is set only where description[0] does not fit one line in the parent's list; picocli falls back to the description otherwise, and the one-line property is enforced by a test for the root and every group.
  • The header section is removed from each command's own help (picocli would print it above Usage:), so header serves only the parent's Commands: list; RecursiveHelpCommand moved its header text into the description.
  • Topic lists are appended to the description of explain and examples in Main.newCommandLine (ExplainTopics.topicList(), ExampleTopics.topicList(), which index() reuses), so they precede the option sections and survive --help | head; explain summaries now wrap at 80 columns in both mops explain and --help.
  • Fixed bare mops (no arguments), which built a fresh CommandLine and therefore printed usage without the command list; it now prints the configured usage via @Spec.
  • README, SKILL.md, and explain pages have no help-layout text to update.
  • Integration tests were not run: none exercises help output, which :cli:test covers.

@sergej-koscejev sergej-koscejev changed the title Show subcommands near the top of help output feat: show subcommands near the top of help output Oct 17, 2026
@sergej-koscejev
sergej-koscejev force-pushed the issue-52-help-order branch 2 times, most recently from 72cbb61 to b8818c3 Compare October 22, 2026 15:47
@sergej-koscejev
sergej-koscejev merged commit 2a6105d into main Oct 22, 2026
12 checks passed
@sergej-koscejev
sergej-koscejev deleted the issue-52-help-order branch October 22, 2026 19:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Show subcommands near the top of help output

1 participant