summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author迷渡 <justjavac@gmail.com>2019-09-09 05:18:39 +0800
committerRyan Dahl <ry@tinyclouds.org>2019-09-08 17:18:39 -0400
commitf37df2d0d6d500f6321e23787ad0dfa267c72366 (patch)
tree14e6021ddf78ca341df188ca082c3498d023e28c
parent25def60c213a2ebaa943779c18bcab1e8f30cd93 (diff)
flags: Parse builtin properties (denoland/deno_std#579)
Original: https://github.com/denoland/deno_std/commit/03304cd2d3c1d1567f72f05708cf516795cc67af
-rw-r--r--flags/mod.ts59
-rwxr-xr-xflags/parse_test.ts7
2 files changed, 40 insertions, 26 deletions
diff --git a/flags/mod.ts b/flags/mod.ts
index 61cd06f91..1333b96d5 100644
--- a/flags/mod.ts
+++ b/flags/mod.ts
@@ -30,6 +30,12 @@ interface NestedMapping {
[key: string]: NestedMapping | unknown;
}
+function get<T>(obj: { [s: string]: T }, key: string): T | undefined {
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
+ return obj[key];
+ }
+}
+
function isNumber(x: unknown): boolean {
if (typeof x === "number") return true;
if (/^0x[0-9a-f]+$/i.test(String(x))) return true;
@@ -39,7 +45,7 @@ function isNumber(x: unknown): boolean {
function hasKey(obj: NestedMapping, keys: string[]): boolean {
let o = obj;
keys.slice(0, -1).forEach(function(key: string): void {
- o = (o[key] || {}) as NestedMapping;
+ o = (get(o, key) || {}) as NestedMapping;
});
const key = keys[keys.length - 1];
@@ -84,7 +90,7 @@ export function parse(
const aliases: { [key: string]: string[] } = {};
if (options.alias !== undefined) {
for (const key in options.alias) {
- const val = options.alias[key];
+ const val = get(options.alias, key)!;
if (typeof val === "string") {
aliases[key] = [val];
@@ -92,7 +98,7 @@ export function parse(
aliases[key] = val;
}
- for (const alias of aliases[key]) {
+ for (const alias of get(aliases, key)!) {
aliases[alias] = [key].concat(
aliases[key].filter((y: string): boolean => alias !== y)
);
@@ -106,8 +112,9 @@ export function parse(
stringArgs.filter(Boolean).forEach(function(key): void {
flags.strings[key] = true;
- if (aliases[key]) {
- aliases[key].forEach(
+ const alias = get(aliases, key);
+ if (alias) {
+ alias.forEach(
(alias: string): void => {
flags.strings[alias] = true;
}
@@ -123,32 +130,32 @@ export function parse(
function argDefined(key: string, arg: string): boolean {
return (
(flags.allBools && /^--[^=]+$/.test(arg)) ||
- flags.bools[key] ||
- !!flags.strings[key] ||
- !!aliases[key]
+ get(flags.bools, key) ||
+ !!get(flags.strings, key) ||
+ !!get(aliases, key)
);
}
function setKey(obj: NestedMapping, keys: string[], value: unknown): void {
let o = obj;
keys.slice(0, -1).forEach(function(key): void {
- if (o[key] === undefined) {
+ if (get(o, key) === undefined) {
o[key] = {};
}
- o = o[key] as NestedMapping;
+ o = get(o, key) as NestedMapping;
});
const key = keys[keys.length - 1];
if (
- o[key] === undefined ||
- flags.bools[key] ||
- typeof o[key] === "boolean"
+ get(o, key) === undefined ||
+ get(flags.bools, key) ||
+ typeof get(o, key) === "boolean"
) {
o[key] = value;
- } else if (Array.isArray(o[key])) {
+ } else if (Array.isArray(get(o, key))) {
(o[key] as unknown[]).push(value);
} else {
- o[key] = [o[key], value];
+ o[key] = [get(o, key), value];
}
}
@@ -161,17 +168,17 @@ export function parse(
if (flags.unknownFn(arg) === false) return;
}
- const value = !flags.strings[key] && isNumber(val) ? Number(val) : val;
+ const value = !get(flags.strings, key) && isNumber(val) ? Number(val) : val;
setKey(argv, key.split("."), value);
- (aliases[key] || []).forEach(function(x): void {
+ (get(aliases, key) || []).forEach(function(x): void {
setKey(argv, x.split("."), value);
});
}
function aliasIsBoolean(key: string): boolean {
- return aliases[key].some(function(x): boolean {
- return flags.bools[x];
+ return get(aliases, key)!.some(function(x): boolean {
+ return get(flags.bools, x)!;
});
}
@@ -213,9 +220,9 @@ export function parse(
if (
next !== undefined &&
!/^-/.test(next) &&
- !flags.bools[key] &&
+ !get(flags.bools, key) &&
!flags.allBools &&
- (aliases[key] ? !aliasIsBoolean(key) : true)
+ (get(aliases, key) ? !aliasIsBoolean(key) : true)
) {
setArg(key, next, arg);
i++;
@@ -223,7 +230,7 @@ export function parse(
setArg(key, next === "true", arg);
i++;
} else {
- setArg(key, flags.strings[key] ? "" : true, arg);
+ setArg(key, get(flags.strings, key) ? "" : true, arg);
}
} else if (/^-[^-]+/.test(arg)) {
const letters = arg.slice(1, -1).split("");
@@ -257,7 +264,7 @@ export function parse(
broken = true;
break;
} else {
- setArg(letters[j], flags.strings[letters[j]] ? "" : true, arg);
+ setArg(letters[j], get(flags.strings, letters[j]) ? "" : true, arg);
}
}
@@ -266,8 +273,8 @@ export function parse(
if (
args[i + 1] &&
!/^(-|--)[^-]/.test(args[i + 1]) &&
- !flags.bools[key] &&
- (aliases[key] ? !aliasIsBoolean(key) : true)
+ !get(flags.bools, key) &&
+ (get(aliases, key) ? !aliasIsBoolean(key) : true)
) {
setArg(key, args[i + 1], arg);
i++;
@@ -275,7 +282,7 @@ export function parse(
setArg(key, args[i + 1] === "true", arg);
i++;
} else {
- setArg(key, flags.strings[key] ? "" : true, arg);
+ setArg(key, get(flags.strings, key) ? "" : true, arg);
}
}
} else {
diff --git a/flags/parse_test.ts b/flags/parse_test.ts
index 2e154f78c..9918ce8bb 100755
--- a/flags/parse_test.ts
+++ b/flags/parse_test.ts
@@ -192,3 +192,10 @@ test(function nestedDottedObjects(): void {
});
assertEquals(argv.beep, { boop: true });
});
+
+test(function flagBuiltinProperty(): void {
+ const argv = parse(["--toString", "--valueOf", "foo"]);
+ assertEquals(argv, { toString: true, valueOf: "foo", _: [] });
+ assertEquals(typeof argv.toString, "boolean");
+ assertEquals(typeof argv.valueOf, "string");
+});