Skip to content

Commit

Permalink
Add support for quoted arguments
Browse files Browse the repository at this point in the history
  • Loading branch information
coreybutler committed Aug 5, 2021
1 parent 5c7c242 commit 2b1a045
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 12 deletions.
6 changes: 2 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@author.io/arg",
"version": "1.3.14",
"version": "1.3.15",
"description": "An argument parser for CLI applications.",
"main": "src/index.js",
"exports": {
Expand All @@ -12,11 +12,9 @@
"test": "npm run test:node && npm run test:deno && npm run test:browser && npm run report:syntax && npm run report:size",
"test:node": "dev test -rt node tests/*.js",
"test:node:sanity": "dev test -rt node tests/01-sanity.js",
"test:node:base": "dev test -rt node tests/02-base.js",
"test:node:relationships": "dev test -rt node tests/06-relationships.js",
"test:node:regression": "dev test -rt node tests/09-regression.js",
"test:browser": "dev test -rt browser tests/*.js",
"test:browser:sanity": "dev test -rt browser tests/01-sanity.js",
"test:browser:base": "dev test -rt browser tests/02-base.js",
"test:deno": "dev test -rt deno tests/*.js",
"test:deno:sanity": "dev test -rt deno tests/01-sanity.js",
"manually": "dev test -rt manual tests/*.js",
Expand Down
15 changes: 7 additions & 8 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Flag from './flag.js'

// const PARSER = /\s*(?:((?:(?:"(?:\\.|[^"])*")|(?:'[^']*')|(?:\\.)|\S)+)\s*)/gi
const PARSER = /((-+(?<flag>[^\s\"\']+))(\s+(?<value>([\"\']((\\\"|\\\')|[^\"\'])+[\"\']|[^-][^\s]+)))?|(?<arg>[^\s]+))/gi // eslint-disable-line no-useless-escape
const PARSER = /((-+(?<flag>[^\s\"\']+))(\s+((?<value>[\"\'](?<unquoted_value>((\\\"|\\\')|[^\"\'])+)[\"\']|[^-][^\s]+)))?|(([\"\'](?<quoted_arg>((\\\"|\\\')|[^\"\'])+)[\"\']))|(?<arg>[^\s]+))/gi // eslint-disable-line no-useless-escape
const BOOLS = new Set(['true', 'false'])

class Parser {
Expand Down Expand Up @@ -176,25 +176,24 @@ class Parser {

// Normalize each flag/value pairing
Array.from([...input.matchAll(PARSER)]).forEach(parsedArg => {
let { flag, value, arg } = parsedArg.groups
let { flag, value, unquoted_value, quoted_arg, arg } = parsedArg.groups

// If the arg attribute is present, add the
// value to the arguments placeholder instead
// of the flags
if (arg) {
args.push(arg)
} else if (quoted_arg) {
args.push(quoted_arg)
} else {
value = unquoted_value || value
// Flags without values are considered boolean "true"
value = value !== undefined ? value : true

// Remove surrounding quotes in string values
// and convert true/false strings to boolean values.
if (typeof value === 'string') {
value = value.replace(/^[\"\']|[\"\']$/gi, '').replace(/\\([\"\'])/gi, '$1') // eslint-disable-line no-useless-escape

if (BOOLS.has(value.toLowerCase())) {
value = value.toLowerCase() === 'true'
}
if (typeof value === 'string' && BOOLS.has(value.toLowerCase())) {
value = value.toLowerCase() === 'true'
}

flags.push({ flag, value })
Expand Down
3 changes: 3 additions & 0 deletions tests/01-sanity.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ test('Support custom validation methods', t => {
let Args = new Parser(input, cfg)

t.ok(Args.violations.length === 0, `Expected no violations, recognized ${Args.violations.length}.`)
if (Args.violations.length > 0) { console.log(Args.violations) }

cfg.bad = {
alias: 'b',
Expand All @@ -54,6 +55,7 @@ test('Support custom validation methods', t => {

Args = new Parser(input, cfg)
t.ok(Args.violations.length === 1, `Expected 1 violation, recognized ${Args.violations.length}.`)
if (Args.violations.length > 1) { console.log(Args.violations) }

Args = new Parser('test --pass abbbbc', {
pass: {
Expand All @@ -62,6 +64,7 @@ test('Support custom validation methods', t => {
})

t.ok(Args.violations.length === 0, `Expected no violations, recognized ${Args.violations.length}.`)
if (Args.violations.length > 0) { console.log(Args.violations) }

t.end()
})
15 changes: 15 additions & 0 deletions tests/09-regression.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,18 @@ test('Multi-value flags', t => {
t.expect(2, data.file.length, 'Extract multiple values')
t.end()
})

test('Multi-value quoted and unquoted arguments', t => {
const input = '[email protected] "John Doe" empty -name \'Jill Doe\''
const cfg = {
name: { alias: 'n' }
}
const { data } = new Parser(input, cfg)

t.expect('Jill Doe', data.name, 'recognized single quoted flag')
t.ok(data['[email protected]'], 'recognized unquoted string with special characters')
t.ok(data['John Doe'], 'recognized double quoted argument with space in the value')
t.ok(data.empty, 'recognized unquoted argument')

t.end()
})

0 comments on commit 2b1a045

Please sign in to comment.