JavaScript
Node.js
minimist

minimistはオプション値に数字を含むと挙動が変わるので注意

More than 1 year has passed since last update.

Node.jsのコマンドラインツールを今作っているんですが、
引数のオプション処理に、minimistというライブラリを使ってます。

例えばこんなプログラムを書くと、

args.js
const argv = require('minimist')(process.argv.slice(2), {
  alias: {
    u: 'username',
  }
})

console.log('username: ', argv.username)

以下の5通りの実行方法で、どれも同じ結果を出してくれます。
便利ですねー。

$ node args.js -uUser1
$ node args.js -u User1
$ node args.js -u=User1
$ node args.js --username User1
$ node args.js --username=User1
username:  User1

しかし、 1文字オプション かつ オプション後にスペースを空けない 場合、
渡す文字列によっては失敗する場合があるのです。

例えばこちら、意図しない挙動になります。

$ node args.js -uAdmin
username:  true

試しにargv配列全体も出力してみましょう。

args.js
const argv = require('minimist')(process.argv.slice(2), {
  alias: {
    u: 'username',
  }
})

console.log(argv)
console.log('username: ', argv.username)
$ node args.js -uAdmin
{ _: [],
  u: true,
  username: true,
  A: true,
  d: true,
  m: true,
  i: true,
  n: true }
username:  true

わかりますね?以下の2つは同じ意味になっちゃうのです。

$ node args.js -uAdmin
$ node args.js -u -A -d -m -i -n
username:  true

ではなぜ最初の例ではうまくいったかというと、
オプションに渡す文字列に数字が含まれていたからです。

$ node args.js -uUser1
{ _: [], u: 'User1', username: 'User1' }
username:  User1

「オプションが数字1文字」はあり得ないので、
2文字目以降に数字が含まれる場合に限り、オプション値と見なすようですね。

軽くハマったので、メモでした〜。