Repository: yargs/yargs (js)

Issue:
Wrong $0 in bundled electron app
We have an election app that is bundled to an .exe file.

A command line like
`bundled.exe -f filename`
will result in:
`
{ _: ['filename'],
  '$0': 'bundled.exe  -f' }
`

The following workaround:
`
const argv = yargs.parse(process.argv.slice(1));
`
will result in 
`
{ _: [],
 f: 'filename',
  '$0': 'bundled.exe  -f' }
`

Please notice that the $0 ist still wrong because it contains the "-f".

If this an expected behavior? Is there a way to work around it?


Pull request description:
fix: $0 contains first arg on bundled electron app; fixes #685
Default behavior of yargs is to take the first two args of process.argv
to put into $0 as this is usually the program to execute a script
e.g. 'node app.js' but for bundled electron apps this results in $0
being populated with not only the executing program but also the first
parameter. This fix modifies the check for node/iojs (and adds electron)
so in case of those 3, the executing program is skipped in $0 as it was
before, but in case where a bundled app is executed, the first parameter
is skipped.

This is only a cosmetic change for proper help printouts which use $0
A manual `yargs.parse(process.argv.slice(1))` is still necessary for
electron not to skip the first parameter, during parsing

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7dbcc92..8fe7d6e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,18 @@
 
 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="12.0.2"></a>
+## [12.0.2](https://github.com/yargs/yargs/compare/v12.0.1...v12.0.2) (2018-09-04)
+
+
+### Bug Fixes
+
+* middleware should work regardless of when method is called  ([664b265](https://github.com/yargs/yargs/commit/664b265)), closes [#1178](https://github.com/yargs/yargs/issues/1178)
+* translation not working when using __ with a single parameter ([#1183](https://github.com/yargs/yargs/issues/1183)) ([f449aea](https://github.com/yargs/yargs/commit/f449aea))
+* upgrade os-locale to version that addresses license issue ([#1195](https://github.com/yargs/yargs/issues/1195)) ([efc0970](https://github.com/yargs/yargs/commit/efc0970))
+
+
+
 <a name="12.0.1"></a>
 ## [12.0.1](https://github.com/yargs/yargs/compare/v12.0.0...v12.0.1) (2018-06-29)
 
diff --git a/lib/middleware.js b/lib/middleware.js
index ca4280b..567ba57 100644
--- a/lib/middleware.js
+++ b/lib/middleware.js
@@ -2,7 +2,7 @@ module.exports = function (globalMiddleware, context) {
   return function (callback) {
     if (Array.isArray(callback)) {
       Array.prototype.push.apply(globalMiddleware, callback)
-    } else if (typeof callback === 'object') {
+    } else if (typeof callback === 'function') {
       globalMiddleware.push(callback)
     }
     return context
diff --git a/lib/usage.js b/lib/usage.js
index 6451c98..9be8a99 100644
--- a/lib/usage.js
+++ b/lib/usage.js
@@ -161,13 +161,7 @@ module.exports = function usage (yargs, y18n) {
     keys = keys.concat(Object.keys(demandedOptions))
     keys = keys.concat(Object.keys(demandedCommands))
     keys = keys.concat(Object.keys(options.default))
-    keys = keys.filter(key => {
-      if (options.hiddenOptions.indexOf(key) < 0) {
-        return true
-      } else if (yargs.parsed.argv[options.showHiddenOpt]) {
-        return true
-      }
-    })
+    keys = keys.filter(filterHiddenOptions)
     keys = Object.keys(keys.reduce((acc, key) => {
       if (key !== '_') acc[key] = true
       return acc
@@ -251,11 +245,9 @@ module.exports = function usage (yargs, y18n) {
     Object.keys(groups).forEach((groupName) => {
       if (!groups[groupName].length) return
 
-      ui.div(__(groupName))
-
       // if we've grouped the key 'f', but 'f' aliases 'foobar',
       // normalizedKeys should contain only 'foobar'.
-      const normalizedKeys = groups[groupName].map((key) => {
+      const normalizedKeys = groups[groupName].filter(filterHiddenOptions).map((key) => {
         if (~aliasKeys.indexOf(key)) return key
         for (let i = 0, aliasKey; (aliasKey = aliasKeys[i]) !== undefined; i++) {
           if (~(options.alias[aliasKey] || []).indexOf(key)) return aliasKey
@@ -263,6 +255,10 @@ module.exports = function usage (yargs, y18n) {
         return key
       })
 
+      if (normalizedKeys.length < 1) return
+
+      ui.div(__(groupName))
+
       // actually generate the switches string --foo, -f, --bar.
       const switches = normalizedKeys.reduce((acc, key) => {
         acc[key] = [ key ].concat(options.alias[key] || [])
@@ -420,6 +416,10 @@ module.exports = function usage (yargs, y18n) {
     return groupedKeys
   }
 
+  function filterHiddenOptions (key) {
+    return yargs.getOptions().hiddenOptions.indexOf(key) < 0 || yargs.parsed.argv[yargs.getOptions().showHiddenOpt]
+  }
+
   self.showHelp = (level) => {
     const logger = yargs._getLoggerInstance()
     if (!level) level = 'error'
diff --git a/locales/nb.json b/locales/nb.json
index fc607fb..55be1fb 100644
--- a/locales/nb.json
+++ b/locales/nb.json
@@ -27,7 +27,7 @@
   },
   "Invalid values:": "Ugyldige verdier:",
   "Argument: %s, Given: %s, Choices: %s": "Argument: %s, Gitt: %s, Valg: %s",
-  "Argument check failed: %s": "Argument sjekk mislyktes: %s",
+  "Argument check failed: %s": "Argumentsjekk mislyktes: %s",
   "Implications failed:": "Konsekvensene mislyktes:",
   "Not enough arguments following: %s": "Ikke nok følgende argumenter: %s",
   "Invalid JSON config file: %s": "Ugyldig JSON konfigurasjonsfil: %s",
diff --git a/locales/nn.json b/locales/nn.json
index 5e03c50..5a3c951 100644
--- a/locales/nn.json
+++ b/locales/nn.json
@@ -29,9 +29,9 @@
   },
   "Invalid values:": "Ugyldige verdiar:",
   "Argument: %s, Given: %s, Choices: %s": "Argument: %s, Gjeve: %s, Val: %s",
-  "Argument check failed: %s": "Argument sjekk mislukkast: %s",
+  "Argument check failed: %s": "Argumentsjekk mislukkast: %s",
   "Implications failed:": "Konsekvensane mislukkast:",
-  "Not enough arguments following: %s": "Ikkje nok fylgande argument: %s",
+  "Not enough arguments following: %s": "Ikkje nok fylgjande argument: %s",
   "Invalid JSON config file: %s": "Ugyldig JSON konfigurasjonsfil: %s",
   "Path to JSON config file": "Bane til JSON konfigurasjonsfil",
   "Show help": "Vis hjelp",
diff --git a/package.json b/package.json
index b515a40..5e6ba37 100644
--- a/package.json
+++ b/package.json
@@ -1,8 +1,14 @@
 {
   "name": "yargs",
-  "version": "12.0.1",
+  "version": "12.0.2",
   "description": "yargs the modern, pirate-themed, successor to optimist.",
   "main": "./index.js",
+  "contributors": [
+    {
+      "name": "Yargs Contributors",
+      "url": "https://github.com/yargs/yargs/graphs/contributors"
+    }
+  ],
   "files": [
     "index.js",
     "yargs.js",
@@ -13,7 +19,7 @@
   ],
   "dependencies": {
     "cliui": "^4.0.0",
-    "decamelize": "^2.0.0",
+    "decamelize": "^1.2.0",
     "find-up": "^3.0.0",
     "get-caller-file": "^1.0.1",
     "os-locale": "^3.0.0",
@@ -49,9 +55,9 @@
   },
   "repository": {
     "type": "git",
-    "url": "http://github.com/yargs/yargs.git"
+    "url": "https://github.com/yargs/yargs.git"
   },
-  "homepage": "http://yargs.js.org/",
+  "homepage": "https://yargs.js.org/",
   "standard": {
     "ignore": [
       "**/example/**"
diff --git a/yargs.js b/yargs.js
index 683d5c3..24c8e99 100644
--- a/yargs.js
+++ b/yargs.js
@@ -42,12 +42,16 @@ function Yargs (processArgs, cwd, parentRequire) {
     return self
   }
 
-  self.$0 = process.argv
-    .slice(0, 2)
+  // ignore the node bin, specify this in your
+  // bin file with #!/usr/bin/env node
+  if (/\b(node|iojs|electron)(\.exe)?$/.test(process.argv[0])) {
+    self.$0 = process.argv.slice(1, 2)
+  } else {
+    self.$0 = process.argv.slice(0, 1)
+  }
+
+  self.$0 = self.$0
     .map((x, i) => {
-      // ignore the node bin, specify this in your
-      // bin file with #!/usr/bin/env node
-      if (i === 0 && /\b(node|iojs)(\.exe)?$/.test(x)) return
       const b = rebase(cwd, x)
       return x.match(/^(\/|([a-zA-Z]:)?\\)/) && b.length < x.length ? b : x
     })


Test patch:
diff --git a/test/middleware.js b/test/middleware.js
index 0423768..295ec95 100644
--- a/test/middleware.js
+++ b/test/middleware.js
@@ -24,11 +24,30 @@ describe('middleware', () => {
   it('should add a single callback to global middleware', () => {
     const globalMiddleware = []
 
-    middlewareFactory(globalMiddleware)({})
+    middlewareFactory(globalMiddleware)(function () {})
 
     globalMiddleware.should.have.lengthOf(1)
   })
 
+  it('runs the middleware before reaching the handler', function (done) {
+    yargs(['mw'])
+      .middleware(function (argv) {
+        argv.mw = 'mw'
+      })
+      .command(
+        'mw',
+        'adds func to middleware',
+        function () {},
+        function (argv) {
+          // we should get the argv filled with data from the middleware
+          argv.mw.should.equal('mw')
+          return done()
+        }
+      )
+      .exitProcess(false) // defaults to true.
+      .parse()
+  })
+
   it('runs all middleware before reaching the handler', function (done) {
     yargs(['mw'])
       .middleware([
@@ -56,11 +75,9 @@ describe('middleware', () => {
 
   it('should be able to register middleware regardless of when middleware is called', function (done) {
     yargs(['mw'])
-      .middleware([
-        function (argv) {
-          argv.mw1 = 'mw1'
-        }
-      ])
+      .middleware(function (argv) {
+        argv.mw1 = 'mw1'
+      })
       .command(
         'mw',
         'adds func list to middleware',
@@ -69,12 +86,20 @@ describe('middleware', () => {
           // we should get the argv filled with data from the middleware
           argv.mw1.should.equal('mw1')
           argv.mw2.should.equal('mw2')
+          argv.mw3.should.equal('mw3')
+          argv.mw4.should.equal('mw4')
           return done()
         }
       )
+      .middleware(function (argv) {
+        argv.mw2 = 'mw2'
+      })
       .middleware([
         function (argv) {
-          argv.mw2 = 'mw2'
+          argv.mw3 = 'mw3'
+        },
+        function (argv) {
+          argv.mw4 = 'mw4'
         }
       ])
       .exitProcess(false) // defaults to true.
diff --git a/test/usage.js b/test/usage.js
index 6cfad3e..bcc216c 100644
--- a/test/usage.js
+++ b/test/usage.js
@@ -2853,6 +2853,61 @@ describe('usage tests', () => {
         '  --bar'
       ])
     })
+    it('--help should display all options except for hidden ones even in a group', () => {
+      const r = checkUsage(() => yargs('--help')
+        .options({
+          foo: {
+            describe: 'FOO',
+            hidden: true
+          },
+          bar: {},
+          baz: {
+            describe: 'BAZ',
+            group: 'Hidden:',
+            hidden: true
+          }
+        })
+        .parse()
+      )
+
+      r.logs[0].split('\n').should.deep.equal([
+        'Options:',
+        '  --help     Show help                                                 [boolean]',
+        '  --version  Show version number                                       [boolean]',
+        '  --bar'
+      ])
+    })
+    it('--help should display all groups except for ones with only hidden options', () => {
+      const r = checkUsage(() => yargs('--help')
+        .options({
+          foo: {
+            describe: 'FOO',
+            group: 'Hidden:',
+            hidden: true
+          },
+          bar: {},
+          baz: {
+            describe: 'BAZ',
+            group: 'Hidden:',
+            hidden: true
+          },
+          qux: {
+            group: 'Shown:'
+          }
+        })
+        .parse()
+      )
+
+      r.logs[0].split('\n').should.deep.equal([
+        'Shown:',
+        '  --qux',
+        '',
+        'Options:',
+        '  --help     Show help                                                 [boolean]',
+        '  --version  Show version number                                       [boolean]',
+        '  --bar'
+      ])
+    })
     it('--help should display all options (including hidden ones) with --show-hidden', () => {
       const r = checkUsage(() => yargs('--help --show-hidden --mama ama')
         .options({
@@ -2877,6 +2932,41 @@ describe('usage tests', () => {
         '  --baz      BAZ'
       ])
     })
+    it('--help should display all groups (including ones with only hidden options) with --show-hidden', () => {
+      const r = checkUsage(() => yargs('--help --show-hidden')
+        .options({
+          foo: {
+            describe: 'FOO',
+            group: 'Hidden:',
+            hidden: true
+          },
+          bar: {},
+          baz: {
+            describe: 'BAZ',
+            group: 'Hidden:',
+            hidden: true
+          },
+          qux: {
+            group: 'Shown:'
+          }
+        })
+        .argv
+      )
+
+      r.logs[0].split('\n').should.deep.equal([
+        'Hidden:',
+        '  --foo  FOO',
+        '  --baz  BAZ',
+        '',
+        'Shown:',
+        '  --qux',
+        '',
+        'Options:',
+        '  --help     Show help                                                 [boolean]',
+        '  --version  Show version number                                       [boolean]',
+        '  --bar'
+      ])
+    })
     it('--help should display --custom-show-hidden', () => {
       const r = checkUsage(() => yargs('--help')
         .options({