diff --git a/lib/environment.js b/lib/environment.js index 800e940f..58eec896 100644 --- a/lib/environment.js +++ b/lib/environment.js @@ -14,6 +14,23 @@ const Store = require('./store'); const resolver = require('./resolver'); const TerminalAdapter = require('./adapter'); +/** + * Two-step argument splitting function that first splits arguments in quotes, + * and then splits up the remaining arguments if they are not part of a quote. + */ +function splitArgsFromString(argsString) { + let result = []; + const quoteSeparatedArgs = argsString.split(/(\x22[^\x22]*\x22)/).filter(x => x); + quoteSeparatedArgs.forEach(arg => { + if (arg.match('\x22')) { + result.push(arg.replace(/\x22/g, '')); + } else { + result = result.concat(arg.trim().split(' ')); + } + }); + return result; +} + /** * `Environment` object is responsible of handling the lifecyle and bootstrap * of generators in a specific environment (your app). @@ -107,7 +124,7 @@ class Environment extends EventEmitter { super(); args = args || []; - this.arguments = Array.isArray(args) ? args : args.split(' '); + this.arguments = Array.isArray(args) ? args : splitArgsFromString(args); this.options = opts || {}; this.adapter = adapter || new TerminalAdapter(); this.cwd = this.options.cwd || process.cwd(); @@ -376,7 +393,7 @@ class Environment extends EventEmitter { options = options || {}; let args = options.arguments || options.args || _.clone(this.arguments); - args = Array.isArray(args) ? args : args.split(' '); + args = Array.isArray(args) ? args : splitArgsFromString(args); const opts = options.options || _.clone(this.options); @@ -410,7 +427,7 @@ class Environment extends EventEmitter { args = this.arguments; } - args = Array.isArray(args) ? args : args.split(' '); + args = Array.isArray(args) ? args : splitArgsFromString(args); options = options || this.options; const name = args.shift(); diff --git a/test/environment.js b/test/environment.js index 12bc88a3..96e4944b 100644 --- a/test/environment.js +++ b/test/environment.js @@ -55,6 +55,11 @@ describe('Environment', () => { it('instantiates a mem-fs instance', function () { assert.ok(this.env.sharedFs); }); + + it('takes multi-word arguments', () => { + const args = 'foo bar "foo bar" baz "bar foo"'; + assert.deepEqual(new Environment(args).arguments, ['foo', 'bar', 'foo bar', 'baz', 'bar foo']); + }); }); describe('#help()', () => {