@benev/argv
Advanced tools
Comparing version 0.0.0-dev.2 to 0.0.0-dev.3
{ | ||
"name": "@benev/argv", | ||
"version": "0.0.0-dev.2", | ||
"version": "0.0.0-dev.3", | ||
"description": "command line argument parser", | ||
@@ -13,5 +13,2 @@ "license": "MIT", | ||
], | ||
"bin": { | ||
"argv-echo": "x/echo.js" | ||
}, | ||
"scripts": { | ||
@@ -23,3 +20,3 @@ "build": "run-s clean compile", | ||
"watch": "tsc -w", | ||
"test": "exit 0" | ||
"test": "node x/internals/testing/suite.test.js" | ||
}, | ||
@@ -26,0 +23,0 @@ "devDependencies": { |
106
readme.md
@@ -7,4 +7,4 @@ | ||
🤖 for making node cli programs | ||
🕵️♂️ designed for proper typescript typings | ||
🏗️ experimental design, breaking changes likely | ||
💁 autogenerated `--help` page | ||
🕵️♂️ designed for good typescript typings | ||
🧼 zero dependencies | ||
@@ -15,5 +15,15 @@ 💖 made free and open source, just for you | ||
## argv instructions | ||
## example generated help page | ||
1. install via npm | ||
```sh | ||
$ icecream waffle-cone --flavor cookie-dough --scoops 5 | ||
``` | ||
![example help output](assets/help.png) | ||
<br/> | ||
## instructions | ||
1. install `@benev/argv` via npm | ||
```sh | ||
@@ -29,10 +39,9 @@ npm install @benev/argv | ||
export type Args = { | ||
environment: string | ||
suite: string | ||
vessel: string | ||
} | ||
export type Params = { | ||
"--label": string | ||
"--verbose": boolean | ||
"--port": number | ||
"--flavor": string | ||
"--scoops": number | ||
"--help": boolean | ||
} | ||
@@ -43,34 +52,16 @@ ``` | ||
const {args, params} = cli<Args, Params>()({ | ||
// your program's name | ||
bin: "myprogram", | ||
// process.argv is a nodejs builtin | ||
program: "icecream", | ||
argv: process.argv, | ||
columns: process.stdout.columns ?? 72, | ||
// terminal width, used for text-wrapping | ||
columns: process.stdout.columns, | ||
// link to your readme, for +help | ||
readme: "https://github.com/@benev/argv", | ||
// explainer for your menu, for +help | ||
help: "my first command line program!", | ||
// positional arguments your program will accept | ||
argorder: ["currency", "amount"], | ||
argorder: ["vessel"], | ||
// arguments your program will accept | ||
args: { | ||
currency: { | ||
vessel: { | ||
type: String, | ||
mode: "requirement", | ||
help: "currency, like 'usd' or 'cad'", | ||
help: 'can be "cone", "bowl", or "waffle-cone"', | ||
}, | ||
amount: { | ||
type: Number, | ||
mode: "default", | ||
default: 123, | ||
help: "amount of money", | ||
}, | ||
}, | ||
@@ -80,18 +71,18 @@ | ||
params: { | ||
"--label": { | ||
"--flavor": { | ||
type: String, | ||
mode: "option", | ||
help: "a cool title", | ||
mode: "default", | ||
default: "vanilla", | ||
help: "your favorite icecream flavor", | ||
}, | ||
"--verbose": { | ||
"--scoops": { | ||
type: Number, | ||
mode: "requirement", | ||
help: "number of icecream scoops", | ||
}, | ||
"--help": { | ||
type: Boolean, | ||
mode: "option", | ||
help: "display additional information", | ||
help: "trigger the help page", | ||
}, | ||
"--port": { | ||
type: Number, | ||
mode: "default", | ||
default: 8021, | ||
help: "tcp port server will listen on", | ||
}, | ||
}, | ||
@@ -103,18 +94,12 @@ }) | ||
// example command: | ||
// main.js usd +verbose --port 8021 | ||
// $ icecream waffle-cone --flavor cookie-dough --scoops 5 | ||
args.currency | ||
// "usd" | ||
args.vessel | ||
// "waffle-cone" | ||
args.amount | ||
// 123 | ||
params["--flavor"] | ||
// "cookie-dough" | ||
params["--label"] | ||
// undefined | ||
params["--verbose"] | ||
// true | ||
params["--port"] | ||
// 8021 | ||
params["--scoops"] | ||
// 5 | ||
``` | ||
@@ -141,1 +126,10 @@ | ||
- `"enabled"` | ||
- `--help` has magic handling: it's the only "void" parameter which doesn't expect to be followed by a value | ||
- eg, `icecream --help` is good | ||
- eg, `icecream --help true` is bad | ||
- understand that --help is the ONLY parameter treated this way | ||
- all other parameters require a value | ||
- parameter syntax is strict like this so that it's consistent and unambiguous | ||
- however people will panic if `--help` doesn't give the expected result, thus the magic handling here | ||
- use `+param` as a shorthand for enabling a boolean | ||
- `+help` also works |
26
s/cli.ts
@@ -10,5 +10,13 @@ | ||
import {applyDefaults} from "./internals/parsing/apply-defaults.js" | ||
import {ConsoleLogger, Logger} from "./internals/testing/utils/logger.js" | ||
import {validateRequirements} from "./internals/parsing/validate-requirements.js" | ||
export function cli<A extends Values, P extends Values>() { | ||
export function cli<A extends Values, P extends Values>({ | ||
logger = new ConsoleLogger(), | ||
exit = code => process.exit(code), | ||
}: { | ||
logger?: Logger | ||
exit?: (code: number) => void | ||
} = {}) { | ||
return function< | ||
@@ -22,7 +30,7 @@ FA extends Field.GroupFromValues<A>, | ||
if ("--help" in command.params && command.params["--help"]) { | ||
if ("--help" in command.params) { | ||
for (const report of helper(command)) | ||
console.log(report) | ||
logger.log(report) | ||
process.exit(0) | ||
return <any>exit(0) | ||
} | ||
@@ -40,14 +48,14 @@ | ||
const errortext = errorReport(err) | ||
const printError = () => console.error(...errortext) | ||
const printError = () => logger.error(errortext.join(" ")) | ||
printError() | ||
console.error("") | ||
logger.error("") | ||
for (const report of helper({spec})) | ||
console.error(report) | ||
logger.error(report) | ||
console.error("") | ||
logger.error("") | ||
printError() | ||
process.exit(1) | ||
return <any>exit(1) | ||
} | ||
} | ||
} |
export * from "./cli.js" | ||
export * from "./theme.js" | ||
@@ -4,0 +5,0 @@ export * from "./errors/argv-error.js" |
@@ -0,1 +1,2 @@ | ||
import {Theme} from "../theme.js" | ||
@@ -13,1 +14,19 @@ export const stdcolumns = 72 | ||
] | ||
export function makeTips(theme: Theme) { | ||
const synonyms = affirmatives | ||
.filter(s => s !== "true") | ||
.map(s => theme.value(s)) | ||
.join("/") | ||
const lines = [ | ||
`${theme.param("--param value")} is same as ${theme.param(`--param="value"`)}`, | ||
`${theme.param("+param")} is shorthand for ${theme.param("--param=true")}`, | ||
`${theme.value("true")} has synonyms ${synonyms}` | ||
] | ||
return lines | ||
.map(s => theme.tip("~ ") + s) | ||
.join("\n") | ||
} |
import {Spec} from "../types/spec.js" | ||
import {Field} from "../types/field.js" | ||
import {stdcolumns} from "./constants.js" | ||
import {makeTips, stdcolumns} from "./constants.js" | ||
import {Values} from "../types/values.js" | ||
import {palette} from "./helping/palette.js" | ||
import {stdtheme} from "../theme.js" | ||
import {textblock} from "./helping/textblock.js" | ||
@@ -21,2 +21,4 @@ import {fieldReport} from "./helping/field-report.js" | ||
const theme = spec.theme ?? stdtheme | ||
const tips = spec.tips ?? true | ||
@@ -26,10 +28,10 @@ const columns = (spec.columns ?? stdcolumns) - 4 | ||
yield palette.binary(spec.bin) + " " + ( | ||
yield theme.binary(spec.program) + " " + ( | ||
argorder | ||
.map(a => palette.arg(`<${a}>`)) | ||
.map(a => theme.arg(`<${a}>`)) | ||
.join(" ") | ||
) + palette.param(" {parameters}") | ||
) + theme.param(" {parameters}") | ||
if (spec.readme) | ||
yield palette.readme(" readme ") + palette.link(spec.readme) | ||
yield theme.readme(" readme ") + theme.link(spec.readme) | ||
@@ -47,5 +49,6 @@ if (spec.help) | ||
columns, | ||
theme, | ||
field: spec.args[name], | ||
value: retrieveValue(args, name), | ||
color: palette.arg, | ||
color: theme.arg, | ||
}) | ||
@@ -56,6 +59,7 @@ | ||
name, | ||
field, | ||
columns, | ||
field, | ||
theme, | ||
value: retrieveValue(params, name), | ||
color: palette.param, | ||
color: theme.param, | ||
}) | ||
@@ -65,14 +69,9 @@ | ||
yield "" | ||
yield palette.tip("tips") | ||
yield theme.tip("tips") | ||
yield textblock({ | ||
columns, | ||
indent: [2, " "], | ||
text: | ||
[ | ||
`"${palette.param("+param")}" is short for "${palette.param("--param=true")}"`, | ||
] | ||
.map(s => palette.tip("~ ") + s) | ||
.join("\n"), | ||
text: makeTips(theme), | ||
}) | ||
} | ||
} |
import {val} from "./val.js" | ||
import {palette} from "./palette.js" | ||
import {Theme} from "../../theme.js" | ||
import {Type} from "../../types/type.js" | ||
import {Field} from "../../types/field.js" | ||
export function defaultValue(field: Field.Default<Type>) { | ||
export function defaultValue(theme: Theme, field: Field.Default<Type>) { | ||
return "default" in field | ||
? " " + palette.value(val(field.default)) | ||
? " " + theme.value(val(field.default)) | ||
: "" | ||
} |
@@ -5,3 +5,3 @@ | ||
import {stype} from "./stype.js" | ||
import {palette} from "./palette.js" | ||
import {Theme} from "../../theme.js" | ||
import {textblock} from "./textblock.js" | ||
@@ -17,2 +17,3 @@ import {Type} from "../../types/type.js" | ||
value, | ||
theme, | ||
color, | ||
@@ -22,2 +23,3 @@ }: { | ||
columns: number | ||
theme: Theme | ||
field: Field.Any<Type> | ||
@@ -35,7 +37,7 @@ value: undefined | {v: any} | ||
text: `${color(name)}` | ||
+ ` ${mode(field.mode)}` | ||
+ ` ${stype(field.type)}` | ||
+ `${defaultValue(<any>field)}` | ||
+ ` ${mode(theme, field.mode)}` | ||
+ ` ${theme.type(stype(field.type))}` | ||
+ `${defaultValue(theme, <any>field)}` | ||
+ (value | ||
? " " + palette.detected("got ") + palette.value(val(value.v)) | ||
? " " + theme.detected("got ") + theme.value(val(value.v)) | ||
: "") | ||
@@ -42,0 +44,0 @@ , |
import {palette} from "./palette.js" | ||
import {Theme} from "../../theme.js" | ||
import {Field} from "../../types/field.js" | ||
export function mode(mode: Field.Mode) { | ||
export function mode(theme: Theme, mode: Field.Mode) { | ||
switch (mode) { | ||
case "requirement": | ||
return palette.required("required") | ||
return theme.required("required") | ||
case "option": | ||
return palette.mode("optional") | ||
return theme.mode("optional") | ||
case "default": | ||
return palette.mode("default") | ||
return theme.mode("default") | ||
} | ||
} |
import {palette} from "./palette.js" | ||
import {Type} from "../../types/type.js" | ||
@@ -9,10 +8,13 @@ | ||
case String: | ||
return palette.type("string") | ||
return "string" | ||
case Number: | ||
return palette.type("number") | ||
return "number" | ||
case Boolean: | ||
return palette.type("boolean") | ||
return "boolean" | ||
default: | ||
return "unknown" | ||
} | ||
} |
@@ -21,5 +21,6 @@ | ||
saveArg, | ||
saveParam, | ||
saveParamTrue, | ||
saveScheduledParam, | ||
saveEqualSignedParam, | ||
saveEnabledBooleanParam, | ||
saveShorthandBoolean, | ||
scheduledParamAssignment, | ||
@@ -31,3 +32,3 @@ scheduleNextItemAsParamValue, | ||
if (scheduledParamAssignment()) | ||
saveParam(item) | ||
saveScheduledParam(item) | ||
else { | ||
@@ -38,5 +39,8 @@ if (item.startsWith("--")) | ||
else | ||
scheduleNextItemAsParamValue(item) | ||
if (item === "--help") | ||
saveParamTrue(item) | ||
else | ||
scheduleNextItemAsParamValue(item) | ||
else if (item.startsWith("+")) | ||
saveEnabledBooleanParam(item) | ||
saveShorthandBoolean(item) | ||
else | ||
@@ -43,0 +47,0 @@ saveArg(item) |
@@ -42,3 +42,7 @@ | ||
saveParam: (item: string) => { | ||
saveParamTrue: (item: string) => { | ||
params[<keyof FP>item] = <any>true | ||
}, | ||
saveScheduledParam: (item: string) => { | ||
const name = scheduledParamAssignment! | ||
@@ -60,3 +64,3 @@ scheduledParamAssignment = undefined | ||
saveEnabledBooleanParam(item: string) { | ||
saveShorthandBoolean(item: string) { | ||
const name = "--" + item.slice(1) | ||
@@ -63,0 +67,0 @@ params[<keyof FP>name] = <any>true |
@@ -20,3 +20,3 @@ | ||
.map(([key, code]) => [ | ||
key, | ||
key, | ||
(s: string) => `${code}${s}${codes.reset}`, | ||
@@ -23,0 +23,0 @@ ]) |
import {Field} from "./field.js" | ||
import {Theme} from "../theme.js" | ||
@@ -8,11 +9,32 @@ export interface Spec< | ||
> { | ||
bin: string | ||
/** the name of your program's executable */ | ||
program: string | ||
/** command line arguments (in node, use process.argv) */ | ||
argv: string[] | ||
/** positional arguments your program will accept */ | ||
argorder: (keyof FA)[] | ||
/** arguments specification */ | ||
args: FA | ||
/** parameters specification */ | ||
params: FP | ||
/** url to your program's readme */ | ||
readme?: string | ||
/** description and usage instructions for your program */ | ||
help?: string | ||
/** current terminal width, used for text-wrapping */ | ||
columns?: number | ||
/** display "tips" section at end of +help page */ | ||
tips?: boolean | ||
/** color palette to use in the +help page */ | ||
theme?: Theme | ||
} |
@@ -5,2 +5,6 @@ import { Spec } from "./types/spec.js"; | ||
import { Command } from "./types/command.js"; | ||
export declare function cli<A extends Values, P extends Values>(): <FA extends Field.GroupFromValues<A>, FP extends Field.GroupFromValues<P>>(spec: Spec<FA, FP>) => Command<FA, FP>; | ||
import { Logger } from "./internals/testing/utils/logger.js"; | ||
export declare function cli<A extends Values, P extends Values>({ logger, exit, }?: { | ||
logger?: Logger; | ||
exit?: (code: number) => void; | ||
}): <FA extends Field.GroupFromValues<A>, FP extends Field.GroupFromValues<P>>(spec: Spec<FA, FP>) => Command<FA, FP>; |
19
x/cli.js
@@ -5,11 +5,12 @@ import { parse } from "./internals/parse.js"; | ||
import { applyDefaults } from "./internals/parsing/apply-defaults.js"; | ||
import { ConsoleLogger } from "./internals/testing/utils/logger.js"; | ||
import { validateRequirements } from "./internals/parsing/validate-requirements.js"; | ||
export function cli() { | ||
export function cli({ logger = new ConsoleLogger(), exit = code => process.exit(code), } = {}) { | ||
return function (spec) { | ||
try { | ||
const command = parse(spec); | ||
if ("--help" in command.params && command.params["--help"]) { | ||
if ("--help" in command.params) { | ||
for (const report of helper(command)) | ||
console.log(report); | ||
process.exit(0); | ||
logger.log(report); | ||
return exit(0); | ||
} | ||
@@ -24,10 +25,10 @@ validateRequirements(command.spec.args, command.args); | ||
const errortext = errorReport(err); | ||
const printError = () => console.error(...errortext); | ||
const printError = () => logger.error(errortext.join(" ")); | ||
printError(); | ||
console.error(""); | ||
logger.error(""); | ||
for (const report of helper({ spec })) | ||
console.error(report); | ||
console.error(""); | ||
logger.error(report); | ||
logger.error(""); | ||
printError(); | ||
process.exit(1); | ||
return exit(1); | ||
} | ||
@@ -34,0 +35,0 @@ }; |
export * from "./cli.js"; | ||
export * from "./theme.js"; | ||
export * from "./errors/argv-error.js"; | ||
@@ -3,0 +4,0 @@ export * from "./tools/colors.js"; |
export * from "./cli.js"; | ||
export * from "./theme.js"; | ||
export * from "./errors/argv-error.js"; | ||
@@ -3,0 +4,0 @@ export * from "./tools/colors.js"; |
@@ -0,3 +1,5 @@ | ||
import { Theme } from "../theme.js"; | ||
export declare const stdcolumns = 72; | ||
export declare const mincolumns = 10; | ||
export declare const affirmatives: string[]; | ||
export declare function makeTips(theme: Theme): string; |
@@ -11,2 +11,16 @@ export const stdcolumns = 72; | ||
]; | ||
export function makeTips(theme) { | ||
const synonyms = affirmatives | ||
.filter(s => s !== "true") | ||
.map(s => theme.value(s)) | ||
.join("/"); | ||
const lines = [ | ||
`${theme.param("--param value")} is same as ${theme.param(`--param="value"`)}`, | ||
`${theme.param("+param")} is shorthand for ${theme.param("--param=true")}`, | ||
`${theme.value("true")} has synonyms ${synonyms}` | ||
]; | ||
return lines | ||
.map(s => theme.tip("~ ") + s) | ||
.join("\n"); | ||
} | ||
//# sourceMappingURL=constants.js.map |
@@ -1,3 +0,3 @@ | ||
import { stdcolumns } from "./constants.js"; | ||
import { palette } from "./helping/palette.js"; | ||
import { makeTips, stdcolumns } from "./constants.js"; | ||
import { stdtheme } from "../theme.js"; | ||
import { textblock } from "./helping/textblock.js"; | ||
@@ -7,11 +7,12 @@ import { fieldReport } from "./helping/field-report.js"; | ||
export function* helper({ spec, args = {}, params = {}, }) { | ||
var _a, _b; | ||
const tips = (_a = spec.tips) !== null && _a !== void 0 ? _a : true; | ||
const columns = ((_b = spec.columns) !== null && _b !== void 0 ? _b : stdcolumns) - 4; | ||
var _a, _b, _c; | ||
const theme = (_a = spec.theme) !== null && _a !== void 0 ? _a : stdtheme; | ||
const tips = (_b = spec.tips) !== null && _b !== void 0 ? _b : true; | ||
const columns = ((_c = spec.columns) !== null && _c !== void 0 ? _c : stdcolumns) - 4; | ||
const argorder = spec.argorder; | ||
yield palette.binary(spec.bin) + " " + (argorder | ||
.map(a => palette.arg(`<${a}>`)) | ||
.join(" ")) + palette.param(" {parameters}"); | ||
yield theme.binary(spec.program) + " " + (argorder | ||
.map(a => theme.arg(`<${a}>`)) | ||
.join(" ")) + theme.param(" {parameters}"); | ||
if (spec.readme) | ||
yield palette.readme(" readme ") + palette.link(spec.readme); | ||
yield theme.readme(" readme ") + theme.link(spec.readme); | ||
if (spec.help) | ||
@@ -27,5 +28,6 @@ yield textblock({ | ||
columns, | ||
theme, | ||
field: spec.args[name], | ||
value: retrieveValue(args, name), | ||
color: palette.arg, | ||
color: theme.arg, | ||
}); | ||
@@ -35,18 +37,15 @@ for (const [name, field] of Object.entries(spec.params)) | ||
name, | ||
field, | ||
columns, | ||
field, | ||
theme, | ||
value: retrieveValue(params, name), | ||
color: palette.param, | ||
color: theme.param, | ||
}); | ||
if (tips) { | ||
yield ""; | ||
yield palette.tip("tips"); | ||
yield theme.tip("tips"); | ||
yield textblock({ | ||
columns, | ||
indent: [2, " "], | ||
text: [ | ||
`"${palette.param("+param")}" is short for "${palette.param("--param=true")}"`, | ||
] | ||
.map(s => palette.tip("~ ") + s) | ||
.join("\n"), | ||
text: makeTips(theme), | ||
}); | ||
@@ -53,0 +52,0 @@ } |
@@ -0,3 +1,4 @@ | ||
import { Theme } from "../../theme.js"; | ||
import { Type } from "../../types/type.js"; | ||
import { Field } from "../../types/field.js"; | ||
export declare function defaultValue(field: Field.Default<Type>): string; | ||
export declare function defaultValue(theme: Theme, field: Field.Default<Type>): string; |
import { val } from "./val.js"; | ||
import { palette } from "./palette.js"; | ||
export function defaultValue(field) { | ||
export function defaultValue(theme, field) { | ||
return "default" in field | ||
? " " + palette.value(val(field.default)) | ||
? " " + theme.value(val(field.default)) | ||
: ""; | ||
} | ||
//# sourceMappingURL=default-value.js.map |
@@ -0,6 +1,8 @@ | ||
import { Theme } from "../../theme.js"; | ||
import { Type } from "../../types/type.js"; | ||
import { Field } from "../../types/field.js"; | ||
export declare function fieldReport({ name, columns, field, value, color, }: { | ||
export declare function fieldReport({ name, columns, field, value, theme, color, }: { | ||
name: string; | ||
columns: number; | ||
theme: Theme; | ||
field: Field.Any<Type>; | ||
@@ -7,0 +9,0 @@ value: undefined | { |
import { val } from "./val.js"; | ||
import { mode } from "./mode.js"; | ||
import { stype } from "./stype.js"; | ||
import { palette } from "./palette.js"; | ||
import { textblock } from "./textblock.js"; | ||
import { defaultValue } from "./default-value.js"; | ||
export function fieldReport({ name, columns, field, value, color, }) { | ||
export function fieldReport({ name, columns, field, value, theme, color, }) { | ||
let report = ""; | ||
@@ -14,7 +13,7 @@ report += "\n"; | ||
text: `${color(name)}` | ||
+ ` ${mode(field.mode)}` | ||
+ ` ${stype(field.type)}` | ||
+ `${defaultValue(field)}` | ||
+ ` ${mode(theme, field.mode)}` | ||
+ ` ${theme.type(stype(field.type))}` | ||
+ `${defaultValue(theme, field)}` | ||
+ (value | ||
? " " + palette.detected("got ") + palette.value(val(value.v)) | ||
? " " + theme.detected("got ") + theme.value(val(value.v)) | ||
: ""), | ||
@@ -21,0 +20,0 @@ }); |
@@ -0,2 +1,3 @@ | ||
import { Theme } from "../../theme.js"; | ||
import { Field } from "../../types/field.js"; | ||
export declare function mode(mode: Field.Mode): string; | ||
export declare function mode(theme: Theme, mode: Field.Mode): string; |
@@ -1,12 +0,11 @@ | ||
import { palette } from "./palette.js"; | ||
export function mode(mode) { | ||
export function mode(theme, mode) { | ||
switch (mode) { | ||
case "requirement": | ||
return palette.required("required"); | ||
return theme.required("required"); | ||
case "option": | ||
return palette.mode("optional"); | ||
return theme.mode("optional"); | ||
case "default": | ||
return palette.mode("default"); | ||
return theme.mode("default"); | ||
} | ||
} | ||
//# sourceMappingURL=mode.js.map |
import { Type } from "../../types/type.js"; | ||
export declare function stype(type: Type): string | undefined; | ||
export declare function stype(type: Type): "string" | "number" | "boolean" | "unknown"; |
@@ -1,12 +0,13 @@ | ||
import { palette } from "./palette.js"; | ||
export function stype(type) { | ||
switch (type) { | ||
case String: | ||
return palette.type("string"); | ||
return "string"; | ||
case Number: | ||
return palette.type("number"); | ||
return "number"; | ||
case Boolean: | ||
return palette.type("boolean"); | ||
return "boolean"; | ||
default: | ||
return "unknown"; | ||
} | ||
} | ||
//# sourceMappingURL=stype.js.map |
@@ -7,6 +7,6 @@ import { parsingMachine } from "./parsing/machine.js"; | ||
const [executable, module, ...items] = spec.argv; | ||
const { args, params, saveArg, saveParam, saveEqualSignedParam, saveEnabledBooleanParam, scheduledParamAssignment, scheduleNextItemAsParamValue, } = parsingMachine(spec); | ||
const { args, params, saveArg, saveParamTrue, saveScheduledParam, saveEqualSignedParam, saveShorthandBoolean, scheduledParamAssignment, scheduleNextItemAsParamValue, } = parsingMachine(spec); | ||
for (const item of items) { | ||
if (scheduledParamAssignment()) | ||
saveParam(item); | ||
saveScheduledParam(item); | ||
else { | ||
@@ -16,6 +16,8 @@ if (item.startsWith("--")) | ||
saveEqualSignedParam(item); | ||
else if (item === "--help") | ||
saveParamTrue(item); | ||
else | ||
scheduleNextItemAsParamValue(item); | ||
else if (item.startsWith("+")) | ||
saveEnabledBooleanParam(item); | ||
saveShorthandBoolean(item); | ||
else | ||
@@ -22,0 +24,0 @@ saveArg(item); |
@@ -9,6 +9,7 @@ import { Spec } from "../../types/spec.js"; | ||
scheduleNextItemAsParamValue: (item: string) => void; | ||
saveParam: (item: string) => void; | ||
saveParamTrue: (item: string) => void; | ||
saveScheduledParam: (item: string) => void; | ||
saveArg: (item: string) => void; | ||
saveEqualSignedParam(item: string): void; | ||
saveEnabledBooleanParam(item: string): void; | ||
saveShorthandBoolean(item: string): void; | ||
}; |
@@ -26,3 +26,6 @@ import { parseValue } from "./parse-value.js"; | ||
}, | ||
saveParam: (item) => { | ||
saveParamTrue: (item) => { | ||
params[item] = true; | ||
}, | ||
saveScheduledParam: (item) => { | ||
const name = scheduledParamAssignment; | ||
@@ -41,3 +44,3 @@ scheduledParamAssignment = undefined; | ||
}, | ||
saveEnabledBooleanParam(item) { | ||
saveShorthandBoolean(item) { | ||
const name = "--" + item.slice(1); | ||
@@ -44,0 +47,0 @@ params[name] = true; |
import { Field } from "./field.js"; | ||
import { Theme } from "../theme.js"; | ||
export interface Spec<FA extends Field.Group = Field.Group, FP extends Field.Group = Field.Group> { | ||
bin: string; | ||
/** the name of your program's executable */ | ||
program: string; | ||
/** command line arguments (in node, use process.argv) */ | ||
argv: string[]; | ||
/** positional arguments your program will accept */ | ||
argorder: (keyof FA)[]; | ||
/** arguments specification */ | ||
args: FA; | ||
/** parameters specification */ | ||
params: FP; | ||
/** url to your program's readme */ | ||
readme?: string; | ||
/** description and usage instructions for your program */ | ||
help?: string; | ||
/** current terminal width, used for text-wrapping */ | ||
columns?: number; | ||
/** display "tips" section at end of +help page */ | ||
tips?: boolean; | ||
/** color palette to use in the +help page */ | ||
theme?: Theme; | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
104661
199
2137
0
129