Repository: yargs/yargs
Pull request #950 (2017-09-06 13:07:51)

Run default cmd even if it is the only defined cmd
This ensures that the default command is executed even if the default command
is the only command that is defined.


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e0631dc..018b463 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,16 @@
 
 All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
 
+<a name="9.0.1"></a>
+## [9.0.1](https://github.com/yargs/yargs/compare/v9.0.0...v9.0.1) (2017-09-17)
+
+
+### Bug Fixes
+
+* implications fails only displayed once ([#954](https://github.com/yargs/yargs/issues/954)) ([ac8088b](https://github.com/yargs/yargs/commit/ac8088b))
+
+
+
 <a name="9.0.0"></a>
 # [9.0.0](https://github.com/yargs/yargs/compare/v8.0.2...v9.0.0) (2017-09-03)
 
diff --git a/lib/usage.js b/lib/usage.js
index 47cbf75..16c4b19 100644
--- a/lib/usage.js
+++ b/lib/usage.js
@@ -64,11 +64,21 @@ module.exports = function usage (yargs, y18n) {
   }
 
   // methods for ouputting/building help (usage) message.
-  let usage
+  let usages = []
+  let usageDisabled = false
   self.usage = (msg) => {
-    usage = msg
+    if (msg === null) {
+      usageDisabled = true
+      usages = []
+      return
+    }
+    usageDisabled = false
+    usages.push(msg)
+  }
+  self.getUsage = () => {
+    if (usageDisabled) return null
+    return usages.reduce((usageMsg, msg) => `${usageMsg}${msg}\n`, '') || undefined
   }
-  self.getUsage = () => usage
 
   let examples = []
   self.example = (cmd, description) => {
@@ -151,9 +161,9 @@ module.exports = function usage (yargs, y18n) {
     })
 
     // the usage string.
-    if (usage) {
-      const u = usage.replace(/\$0/g, yargs.$0)
-      ui.div(`${u}\n`)
+    if (usages.length && !usageDisabled) {
+      const u = self.getUsage().replace(/\$0/g, yargs.$0)
+      ui.div(`${u}`)
     }
 
     // your application's commands, i.e., non-option
@@ -435,7 +445,8 @@ module.exports = function usage (yargs, y18n) {
     // do not reset fails here
     failMessage = null
     failureOutput = false
-    usage = undefined
+    usages = []
+    usageDisabled = false
     epilog = undefined
     examples = []
     commands = []
@@ -448,7 +459,8 @@ module.exports = function usage (yargs, y18n) {
     frozen = {}
     frozen.failMessage = failMessage
     frozen.failureOutput = failureOutput
-    frozen.usage = usage
+    frozen.usages = usages
+    frozen.usageDisabled = usageDisabled
     frozen.epilog = epilog
     frozen.examples = examples
     frozen.commands = commands
@@ -457,7 +469,8 @@ module.exports = function usage (yargs, y18n) {
   self.unfreeze = function unfreeze () {
     failMessage = frozen.failMessage
     failureOutput = frozen.failureOutput
-    usage = frozen.usage
+    usages = frozen.usages
+    usageDisabled = frozen.usageDisabled
     epilog = frozen.epilog
     examples = frozen.examples
     commands = frozen.commands
diff --git a/lib/validation.js b/lib/validation.js
index 0b322a3..1eee2fb 100644
--- a/lib/validation.js
+++ b/lib/validation.js
@@ -249,6 +249,7 @@ module.exports = function validation (yargs, usage, y18n) {
       ;(implied[key] || []).forEach((value) => {
         let num
         let key = origKey
+        const origValue = value
 
         // convert string '1' to number 1
         num = Number(key)
@@ -278,7 +279,7 @@ module.exports = function validation (yargs, usage, y18n) {
           value = argv[value]
         }
         if (key && !value) {
-          implyFail.push(origKey)
+          implyFail.push(` ${origKey} -> ${origValue}`)
         }
       })
     })
@@ -286,12 +287,8 @@ module.exports = function validation (yargs, usage, y18n) {
     if (implyFail.length) {
       let msg = `${__('Implications failed:')}\n`
 
-      implyFail.forEach((key) => {
-        if (implied[key]) {
-          implied[key].forEach((value) => {
-            msg += (` ${key} -> ${value}`)
-          })
-        }
+      implyFail.forEach((value) => {
+        msg += (value)
       })
 
       usage.fail(msg)
diff --git a/package.json b/package.json
index 49097a0..9bcfc68 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "yargs",
-  "version": "9.0.0",
+  "version": "9.0.1",
   "description": "yargs the modern, pirate-themed, successor to optimist.",
   "main": "./index.js",
   "files": [
diff --git a/yargs.js b/yargs.js
index 8ea1c42..2d7b214 100644
--- a/yargs.js
+++ b/yargs.js
@@ -985,6 +985,9 @@ function Yargs (processArgs, cwd, parentRequire) {
           if (recommendCommands && firstUnknownCommand && !argv[helpOpt]) {
             validation.recommendCommands(firstUnknownCommand, handlerKeys)
           }
+        } else if (command.hasDefaultCommand() && !argv[helpOpt]) {
+          setPlaceholderKeys(argv)
+          return command.runCommand(null, self, parsed)
         }
 
         // generate a completion script for adding to ~/.bashrc.


Test patch:
diff --git a/test/command.js b/test/command.js
index cd3f840..6bc28ae 100644
--- a/test/command.js
+++ b/test/command.js
@@ -1198,6 +1198,26 @@ describe('Command', () => {
         .argv
     })
 
+    it('executes default command if undefined positional arguments and only command', (done) => {
+      yargs('baz --foo bar')
+        .command('*', 'default command', noop, (argv) => {
+          argv.foo.should.equal('bar')
+          argv._.should.contain('baz')
+          return done()
+        })
+        .argv
+    })
+
+    it('executes default command if defined positional arguments and only command', (done) => {
+      yargs('baz --foo bar')
+        .command('* <target>', 'default command', noop, (argv) => {
+          argv.foo.should.equal('bar')
+          argv.target.should.equal('baz')
+          return done()
+        })
+        .argv
+    })
+
     it('does not execute default command if another command is provided', (done) => {
       yargs('run bcoe --foo bar')
         .command('*', 'default command', noop, (argv) => {})
diff --git a/test/usage.js b/test/usage.js
index 8b5c3dc..5ed522f 100644
--- a/test/usage.js
+++ b/test/usage.js
@@ -1817,6 +1817,39 @@ describe('usage tests', () => {
         ''
       ])
     })
+
+    it('allows a builder to add more than one usage with mutiple usage calls', () => {
+      const r = checkUsage(() => yargs('upload --help')
+        .command('upload', 'upload something', yargs => yargs.usage('$0 upload [something]').usage('$0 upload [something else]'), (argv) => {})
+        .wrap(null)
+        .argv
+      )
+
+      r.logs[0].split('\n').should.deep.equal([
+        './usage upload [something]',
+        './usage upload [something else]',
+        '',
+        'Options:',
+        '  --help     Show help  [boolean]',
+        '  --version  Show version number  [boolean]',
+        ''
+      ])
+    })
+
+    it('allows a builder to disable usage with null after mutiple usage calls', () => {
+      const r = checkUsage(() => yargs('upload --help')
+        .command('upload', 'upload something', yargs => yargs.usage('$0 upload [something]').usage('$0 upload [something else]').usage(null), (argv) => {})
+        .wrap(null)
+        .argv
+      )
+
+      r.logs[0].split('\n').should.deep.equal([
+        'Options:',
+        '  --help     Show help  [boolean]',
+        '  --version  Show version number  [boolean]',
+        ''
+      ])
+    })
   })
 
   describe('epilogue', () => {
diff --git a/test/validation.js b/test/validation.js
index b65c19f..ff9a607 100644
--- a/test/validation.js
+++ b/test/validation.js
@@ -38,15 +38,17 @@ describe('validation tests', () => {
         .argv
     })
 
-    it('fails if either implied argument is not set', (done) => {
+    it('fails if either implied argument is not set and displays only failed', (done) => {
       yargs(['-f', '-b'])
           .implies('f', ['b', 'c'])
           .fail((msg1) => {
             yargs(['-f', '-c'])
                 .implies('f', ['b', 'c'])
                 .fail((msg2) => {
-                  msg1.should.match(/f -> b f -> c/)
-                  msg2.should.match(/f -> b f -> c/)
+                  msg1.should.match(/f -> c/)
+                  msg1.should.not.match(/f -> b/)
+                  msg2.should.match(/f -> b/)
+                  msg2.should.not.match(/f -> c/)
                   return done()
                 })
                 .argv