You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
109 lines
2.6 KiB
109 lines
2.6 KiB
import assert from "assert"; |
|
|
|
const argv = [...process.argv]; |
|
function next() { |
|
return argv.shift(); |
|
} |
|
|
|
function peek() { |
|
return argv[0]; |
|
} |
|
|
|
const positional: Array<string | boolean> = []; |
|
const named: { [key: string]: string | boolean } = {}; |
|
|
|
while (argv.length) { |
|
const arg = next(); |
|
if (arg === undefined) break; |
|
|
|
if (arg.startsWith("--")) { |
|
const match = arg.match(/^--([^=]*)(=?)(.*)$/); |
|
assert(match); |
|
const name = match[1]; |
|
if (!name.length) continue; |
|
let value: string | boolean = true; |
|
if (match[2] === "=") { |
|
if (match[3].length) { |
|
value = match[3]; |
|
} |
|
} else { |
|
const nextArg = peek(); |
|
if (nextArg && !nextArg.startsWith("-")) { |
|
next(); |
|
value = nextArg; |
|
} |
|
} |
|
named[name] = value; |
|
} else if (arg.startsWith("-")) { |
|
const match = arg.match(/^-(.*?)(=?)([^=a-zA-Z]*)$/); |
|
assert(match); |
|
const names = match[1].split(""); |
|
if (!names.length) continue; |
|
while (names.length > 1) { |
|
const name = names.shift(); |
|
if (name && name.length) { |
|
named[name] = true; |
|
} |
|
} |
|
let lastName = names.shift(); |
|
if (!lastName) continue; |
|
let lastValue: string | boolean = true; |
|
if (match[2] === "=") { |
|
if (match[3].length) { |
|
lastValue = match[3]; |
|
} |
|
} else { |
|
const nextArg = peek(); |
|
if (nextArg && !nextArg.startsWith("-")) { |
|
next(); |
|
lastValue = nextArg; |
|
} |
|
} |
|
named[lastName] = lastValue; |
|
} else { |
|
positional.push(arg); |
|
} |
|
} |
|
|
|
function getArg(...nameOrPositions: Array<string | number>) { |
|
let value: string | boolean | undefined; |
|
for (const nameOrPosition of nameOrPositions) { |
|
if (typeof nameOrPosition === "string") { |
|
const name = nameOrPosition; |
|
if (name in named) { |
|
value = named[name]; |
|
break; |
|
} |
|
} else if (Number.isInteger(nameOrPosition)) { |
|
const position = nameOrPosition; |
|
if (position < positional.length) { |
|
return positional[position]; |
|
} |
|
} |
|
} |
|
return value; |
|
} |
|
|
|
export const ArgParse = { |
|
argv: { |
|
_: positional, |
|
...named, |
|
}, |
|
getStringArg(...nameOrPositions: Array<string | number>): string | undefined { |
|
const value = getArg(...nameOrPositions); |
|
if (typeof value === "string") { |
|
return value; |
|
} |
|
}, |
|
getBooleanArg(...nameOrPositions: Array<string | number>): boolean { |
|
return Boolean(getArg(...nameOrPositions)); |
|
}, |
|
getIntegerArg( |
|
...nameOrPositions: Array<string | number> |
|
): number | undefined { |
|
const value = Number(getArg(...nameOrPositions)); |
|
if (Number.isInteger(value)) { |
|
return value; |
|
} |
|
}, |
|
};
|
|
|