Skip to content

Commit

Permalink
Add help messages when passing unknown flags
Browse files Browse the repository at this point in the history
  • Loading branch information
dyedgreen committed Dec 27, 2021
1 parent 48731fd commit 921a15a
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 1 deletion.
9 changes: 8 additions & 1 deletion src/command.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { ArgumentType } from "./types.ts";
import { ArgumentError, HelpError } from "./error.ts";
import { leftPad } from "./fmt.ts";
import { closest } from "./distance.ts";

export interface ArgumentOptions {
/**
Expand Down Expand Up @@ -139,7 +140,13 @@ export class Command<T = Record<never, never>> {
}

private _fmtUnknownFlag(arg: string): string {
return `Unknown flag '${arg.replaceAll("'", "\\'")}'`;
const unknownFlag = `Unknown flag '${arg.replaceAll("'", "\\'")}'`;
const closestFlag = closest(arg, this._allFlags);
if (closestFlag) {
return `${unknownFlag}\n\nHELP:\n\tDid you mean ${closestFlag}?`;
} else {
return unknownFlag;
}
}

private _normalizeFlags(flags: string[]): string[] {
Expand Down
26 changes: 26 additions & 0 deletions src/distance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
function intersection<T>(a: Set<T>, b: Set<T>): number {
let intersection = 0;
for (const item of a) if (b.has(item)) intersection += 1;
return intersection;
}

function union<T>(a: Set<T>, b: Set<T>): number {
let union = a.size;
for (const item of b) if (!a.has(item)) union += 1;
return union;
}

export function closest(string: string, options: Set<string>): string | null {
const stringSet = new Set(string);
let bestItem = null;
let bestScore = 0;
for (const item of options) {
const itemSet = new Set(item);
const score = intersection(stringSet, itemSet) / union(stringSet, itemSet);
if (bestScore <= score) {
bestScore = score;
bestItem = item;
}
}
return bestItem;
}

0 comments on commit 921a15a

Please sign in to comment.