Skip to content

Commit

Permalink
Add HELP message to command groups
Browse files Browse the repository at this point in the history
  • Loading branch information
dyedgreen committed Dec 27, 2021
1 parent 27939ae commit 180d20b
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/command_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Deno.test("basic command errors", () => {
});
});

Deno.test("help messages shows closest flag", () => {
Deno.test("command help messages shows closest flag", () => {
const cmd = new Command("A test command.")
.required(string, "test", { flags: ["test"] });

Expand Down
5 changes: 4 additions & 1 deletion src/distance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ function union<T>(a: Set<T>, b: Set<T>): number {
return union;
}

export function closest(string: string, options: Set<string>): string | null {
export function closest(
string: string,
options: Iterable<string>,
): string | null {
const stringSet = new Set(string);
let bestItem = null;
let bestScore = 0;
Expand Down
18 changes: 15 additions & 3 deletions src/group.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Command } from "./command.ts";
import { ArgumentError, HelpError } from "./error.ts";
import { leftPad } from "./fmt.ts";
import { closest } from "./distance.ts";

/**
* A group of `Command`s.
Expand Down Expand Up @@ -36,6 +37,19 @@ export class CommandGroup<T = Record<never, never>> {
}`;
}

private _fmtUnknownCommand(arg: string): string {
const unknownCommand = `Unknown command '${arg.replaceAll("'", "\\'")}'`;
const closestCommand = closest(
arg,
Object.getOwnPropertyNames(this._commands),
);
if (closestCommand) {
return `${unknownCommand}\n\nHELP:\n\tDid you mean ${closestCommand}?`;
} else {
return unknownCommand;
}
}

/**
* Add a sub command, which can either be a `Command`,
* or another `CommandGroup`.
Expand Down Expand Up @@ -86,9 +100,7 @@ export class CommandGroup<T = Record<never, never>> {
if (isHelp) {
throw new HelpError(this.help(args.slice(0, skip)));
} else {
throw new ArgumentError(
`Unknown command ${args[skip].replaceAll("'", "\\'")}`,
);
throw new ArgumentError(this._fmtUnknownCommand(args[skip]));
}
}
}
Expand Down
16 changes: 16 additions & 0 deletions src/group_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,22 @@ Deno.test("command group errors work", () => {
assertThrows(() => group.parse(["first"]));
});

Deno.test("command group help messages shows closest subcommand", () => {
const group = new CommandGroup("A test command.")
.subcommand("test", cmd);

let message = "";
try {
group.parse(["tst"]);
} catch (error) {
message = error.message;
}
assertEquals(
message,
"Unknown command 'tst'\n\nHELP:\n\tDid you mean test?",
);
});

Deno.test("command group help output", () => {
const innerGroup = new CommandGroup("Inner group.")
.subcommand("first", cmd)
Expand Down

0 comments on commit 180d20b

Please sign in to comment.