From 7ae88c71428cf4fd7d2987fe701547ac00208864 Mon Sep 17 00:00:00 2001 From: Perryvw Date: Sat, 23 Feb 2019 15:55:04 +0100 Subject: [PATCH] Made boolean CLI option values optional, if no value is supplied they default to true --- src/CommandLineParser.ts | 29 ++++++++++++++++++++------ test/unit/commandLineParser.spec.ts | 32 +++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 6 deletions(-) diff --git a/src/CommandLineParser.ts b/src/CommandLineParser.ts index 4d631a501..4881adc4d 100644 --- a/src/CommandLineParser.ts +++ b/src/CommandLineParser.ts @@ -10,6 +10,10 @@ type ParseResult = { isValid: true; result: T } | { isValid: false, errorMessage: string}; +type ArgumentParseResult = + { isValid: true; result: T; increment?: number } + | { isValid: false, errorMessage: string }; + interface ParsedCommandLine extends ts.ParsedCommandLine { options: CompilerOptions; } @@ -190,10 +194,11 @@ function parseTSTLOptions(commandLine: ts.ParsedCommandLine, args: string[]): CL const argumentName = args[i].substr(2); const option = optionDeclarations[argumentName]; if (option) { - const argumentResult = getArgumentValue(argumentName, args[i + 1]); - i++; // Skip the value from being considered as argument name + const argumentResult = getArgumentValue(argumentName, i, args); if (argumentResult.isValid === true) { result[argumentName] = argumentResult.result; + // Skip value from being considered as option + i += argumentResult.increment !== undefined ? argumentResult.increment : 1; } else { return { isValid: false, errorMessage: argumentResult.errorMessage }; } @@ -209,10 +214,11 @@ function parseTSTLOptions(commandLine: ts.ParsedCommandLine, args: string[]): CL } if (argumentName) { - const argumentResult = getArgumentValue(argumentName, args[i + 1]); - i++; // Skip the value from being considered as argument name + const argumentResult = getArgumentValue(argumentName, i, args); if (argumentResult.isValid === true) { result[argumentName] = argumentResult.result; + // Skip value from being considered as option + i += argumentResult.increment !== undefined ? argumentResult.increment : 1; } else { return { isValid: false, errorMessage: argumentResult.errorMessage }; } @@ -232,13 +238,24 @@ function parseTSTLOptions(commandLine: ts.ParsedCommandLine, args: string[]): CL return { isValid: true, result: commandLine }; } -function getArgumentValue(argumentName: string, argument: string): ParseResult +function getArgumentValue( + argumentName: string, + argumentIndex: number, + args: string[] +): ArgumentParseResult { + const option = optionDeclarations[argumentName]; + const argument = args[argumentIndex + 1]; + + if (option.type === "boolean" && (argument === undefined || argument.startsWith("-"))) { + // Set boolean arguments without supplied value to true + return { isValid: true, result: true, increment: 0 }; + } + if (argument === undefined) { return { isValid: false, errorMessage: `Missing value for parameter ${argumentName}`}; } - const option = optionDeclarations[argumentName]; const value = readValue(argument, option.type, argumentName); if (option.choices) { diff --git a/test/unit/commandLineParser.spec.ts b/test/unit/commandLineParser.spec.ts index 3b9bceacd..ab20b33d2 100644 --- a/test/unit/commandLineParser.spec.ts +++ b/test/unit/commandLineParser.spec.ts @@ -66,6 +66,8 @@ export class CommandLineParserTests @TestCase([""], false) @TestCase(["--noHeader", "true"], true) @TestCase(["--noHeader", "false"], false) + @TestCase(["--noHeader"], true) + @TestCase(["--noHeader", "--noHoisting"], true) @Test("CLI parser noHeader") public cliParserNoHeader(args: string[], expected: boolean): void { const result = parseCommandLine(args); @@ -76,6 +78,21 @@ export class CommandLineParserTests } } + @TestCase([""], false) + @TestCase(["--noHoisting", "true"], true) + @TestCase(["--noHoisting", "false"], false) + @TestCase(["--noHoisting"], true) + @TestCase(["--noHoisting", "--noHeader"], true) + @Test("CLI parser noHoisting") + public cliParserNoHoisting(args: string[], expected: boolean): void { + const result = parseCommandLine(args); + if (result.isValid === true) { + Expect(result.result.options.noHoisting).toBe(expected); + } else { + Expect(result.isValid).toBeTruthy(); + } + } + @TestCase([""], false) @TestCase(["--project", "tsconfig.json"], true) @TestCase(["-p", "tsconfig.json"], true) @@ -89,6 +106,21 @@ export class CommandLineParserTests } } + @Test("CLI Parser Multiple Options") + public cliParserMultipleOptions(): void { + const commandLine = "--project tsconfig.json --noHeader --noHoisting -lt 5.3"; + const result = parseCommandLine(commandLine.split(" ")); + + if (result.isValid === true) { + Expect(result.result.options.project).toBeDefined(); + Expect(result.result.options.noHeader).toBe(true); + Expect(result.result.options.noHoisting).toBe(true); + Expect(result.result.options.luaTarget).toBe(LuaTarget.Lua53); + } else { + Expect(result.isValid).toBeTruthy(); + } + } + @TestCase([""], false) @TestCase(["--help"], true) @TestCase(["-h"], true)