Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions changes/unreleased/grouped-help.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- **`sysml -help` and the manual page list the options by task.** The 84 flags come under headings — General, Evaluating, Checking a model, Running behaviors, Analysis engines, Checking every schedule, Converting and migrating, Compiling natively, Rendering views, Rendering documents, Styling HTML documents, Syncing against a repository, Diagnostics and profiling, Deprecated — instead of in one alphabetical list. Each is spelled once with its shorthand folded in (`-e, -eval <expr>`, `-o, -output <file>`) and its argument named (`<format>`, `<duration>`, `<policy>`) rather than typed (`string`, `value`); a description is a wrapped line or two, with the detail it carried moved into the section on that mode (`Checking a model`, `Running actions and state machines`, `Checking every schedule`, ...), and the three `-pdf-*` spellings sit under *Deprecated* pointing at their `-doc-*` names. The examples come first. A flag added without a heading fails a test.
- **A mistyped flag prints the error, the synopsis and `Run 'sysml -help' for the options.`** — three lines, rather than the whole help after the error.
- **`%help` groups every REPL command under a heading and wraps its description.** The commands that had none come under *Session*, *Settings*, *Analysis engines* and *Checking every schedule*; a description wraps into the column after its command, and a signature too wide for that column takes a line of its own. `%exit` is noted beside `%quit` rather than listed as a command.
15 changes: 8 additions & 7 deletions cmd/sysml/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,10 +274,10 @@ func flagGiven(name string) bool {
return given
}

// printUsage writes the help to w: the caller chooses the stream, since help
// asked for is a result and help shown over a misuse belongs with the error.
func printUsage(w io.Writer) {
doc().WriteText(w, flag.CommandLine)
// printUsage writes the help for the flags of fs to w: help asked for is a
// result, so it goes on stdout.
func printUsage(w io.Writer, fs *flag.FlagSet) {
doc().WriteText(w, fs)
}

// printMan writes the command's manual page, rendered from the same description
Expand All @@ -289,8 +289,9 @@ func printMan(w io.Writer) {
// runCLI carries out what the command line asked for and returns the exit
// status, so a profile started for the run is written before the process exits.
func runCLI() int {
// Usage shown over a misuse goes on the stream the error naming it goes on.
flag.Usage = func() { printUsage(flag.CommandLine.Output()) }
// A misuse is answered on the error's stream with the synopsis and where the
// help is, not the help itself, which would bury the error.
flag.Usage = func() { doc().WriteHint(flag.CommandLine.Output()) }

// The tool manifest is read before the flags, since -engine is checked against its engines.
if err := resolveEngines(); err != nil {
Expand All @@ -306,7 +307,7 @@ func runCLI() int {
// Help that was asked for is the result of the run: it belongs on stdout, where
// it can be piped, and the run did what was asked.
if showHelp {
printUsage(os.Stdout)
printUsage(os.Stdout, flag.CommandLine)
return exitHolds
}

Expand Down
6 changes: 3 additions & 3 deletions cmd/sysml/streams_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,14 +156,14 @@ func TestStreamsAndStatus(t *testing.T) {
model: checkModel,
args: []string{"-h"},
status: exitHolds,
stdout: []string{"Usage: sysml [options] [file...]", "-convert string"},
stdout: []string{"Usage: sysml [options] [file...]", "-convert <format>"},
emptyErrs: true,
}, {
name: "a flag that is not defined is reported with the usage on stderr",
name: "a flag that is not defined is reported with a pointer to the help on stderr",
model: checkModel,
args: []string{"--nosuchflag"},
status: exitUnevaluable,
stderr: []string{"flag provided but not defined: -nosuchflag", "Usage: sysml [options] [file...]"},
stderr: []string{"flag provided but not defined: -nosuchflag", "Usage: sysml [options] [file...]", "Run 'sysml -help' for the options."},
emptyOut: true,
}}

Expand Down
398 changes: 323 additions & 75 deletions cmd/sysml/usage.go

Large diffs are not rendered by default.

10 changes: 9 additions & 1 deletion cmd/sysml/usage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
// reports, wrapped rather than reworded.
func TestPrintUsageStatesTheExperimentalNotice(t *testing.T) {
var help bytes.Buffer
printUsage(&help)
printUsage(&help, docFlags())

unwrapped := strings.Join(strings.Fields(help.String()), " ")
if !strings.Contains(unwrapped, convert.ExperimentalNotice) {
Expand All @@ -24,3 +24,11 @@ func TestPrintUsageStatesTheExperimentalNotice(t *testing.T) {
}
}
}

// Every flag is listed under exactly one heading, so a flag added without a
// place in the help is caught here rather than by a reader who cannot find it.
func TestEveryFlagIsInOneOptionGroup(t *testing.T) {
if err := doc().CheckOptions(docFlags()); err != nil {
t.Error(err)
}
}
6 changes: 3 additions & 3 deletions docs/reference/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -235,9 +235,9 @@ reported, so a script that reads it takes the output from the first `{`.
| `--html-mermaid <cdn\|url>` | | Have the HTML page load Mermaid to draw its diagrams: `cdn` loads a pinned release from jsDelivr, a URL loads the script it names (default: diagrams stay Mermaid source) |
| `--html-math <cdn\|url>` | | Have the HTML page load MathJax to typeset its formulas: `cdn` loads a pinned release from jsDelivr, a URL loads the script it names (default: formulas stay LaTeX source) |
| `--pdf-engine <engine>` | | Converter `--doc-form pdf` drives: `weasyprint` (default), `pandoc` or `prince` |
| `--pdf-title-page` | | Alias of `--doc-title-page` |
| `--pdf-toc` | | Alias of `--doc-toc` |
| `--pdf-number-sections` | | Alias of `--doc-number-sections` |
| `--pdf-title-page` | | Former name of `--doc-title-page` |
| `--pdf-toc` | | Former name of `--doc-toc` |
| `--pdf-number-sections` | | Former name of `--doc-number-sections` |
| `--output <file>` | `-o` | Write the conversion, the rendering or the rendered document to a file instead of stdout |
| `--version` | `-v` | Show version information |
| `--help` | `-h` | Show usage information |
Expand Down
Loading
Loading