Skip to content

Replaced minimist with mri for lighter CLI args parsing #110

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

outslept
Copy link

Note

Keeping this as a draft in case of possible discussions

To ensure compatibility, I created a small script comparing both libraries across various CLI argument scenarios
See below for the test cases used and the output.


Test script used:

compare.js
const minimist = require('minimist');
const mri = require('mri');

const options = {
  string: ['dir', 'input', 'port', 'stringArg', 'foo-bar'],
  boolean: ['version', 'help', 'domdiff', 'boolArg', 'boolArg2', 'flag'],
  alias: {
    input: ['dir', 'i'],
    dir: ['input', 'd'],
    version: 'v',
    help: 'h',
    'foo-bar': ['foobar', 'fb']
  },
  default: {
    dir: 'defaultDir',
    port: '3000',
    domdiff: false,
    version: false,
    help: false,
    boolArg: false,
    boolArg2: true,
    stringArg: 'defaultString',
    flag: true,
    'foo-bar': 'baz'
  }
};

const tests = [
  // Basic string/boolean/number flags
  ['--dir=src', '--input=test', '--port', '8080', '--version', '--help', '--domdiff'],
  // Boolean/string values and overrides
  ['--boolArg', '--boolArg2=false', '--stringArg=hello'],
  // Aliases and short flags
  ['-d', 'aliased', '-i', 'double', '-v', '-h'],
  // Repeated (array) values
  ['--dir=src', '--dir=dist', '--input=foo'],
  // Positional and mixed args
  ['file1', 'file2', '--dir=src', '--port=5000'],
  // Boolean flags with/without value
  ['--boolArg', '--boolArg2', '--flag=false'],
  ['--boolArg=false', '--boolArg2=true', '--flag'],
  // Numeric values
  ['--port=8080', '--port', '9090'],
  // Unknown flags
  ['--unknown', '--dir=src'],
  // Combined short flags
  ['-abc'],
  // Dashed flags
  ['--foo-bar=123', '--foobar=456', '--fb=789'],
  // Defaults (no args)
  [],
  // "--" parsing stop scenario
  ['--dir=src', '--', '--notAFlag', 'positional'],
  // String/boolean mix and edge-cases
  ['--version', '--version=false', '--help=hello'],
];

console.log('=== minimist ===');
for (const args of tests) {
  try {
    const result = minimist(args, {
      ...options,
      unknown: (arg) => {
        console.log(`[minimist unknown] ${arg}`);
        return false;
      }
    });
    console.log(`args: ${JSON.stringify(args)} =>`);
    console.dir(result, { depth: null });
    console.log();
  } catch (e) {
    console.error('minimist error:', e.message);
  }
}

console.log('=== mri ===');
for (const args of tests) {
  try {
    const result = mri(args, {
      ...options,
      unknown: (arg) => {
        console.log(`[mri unknown] ${arg}`);
        throw new Error(`[mri unknown] ${arg}`);
      }
    });
    console.log(`args: ${JSON.stringify(args)} =>`);
    console.dir(result, { depth: null });
    console.log();
  } catch (e) {
    console.error('mri error:', e.message);
  }
}

Test output:

Console output
~ node .\compare.js

=== minimist ===
args: ["--dir=src","--input=test","--port","8080","--version","--help","--domdiff"] =>
{
  _: [],
  version: true,
  v: true,
  help: true,
  h: true,
  domdiff: true,
  boolArg: false,
  boolArg2: true,
  flag: true,
  dir: [ 'src', 'test' ],
  input: [ 'src', 'test' ],
  d: [ 'src', 'test' ],
  port: '8080',
  stringArg: 'defaultString',
  'foo-bar': 'baz',
  foobar: 'baz',
  fb: 'baz'
}

args: ["--boolArg","--boolArg2=false","--stringArg=hello"] =>
{
  _: [],
  version: false,
  v: false,
  help: false,
  h: false,
  domdiff: false,
  boolArg: true,
  boolArg2: false,
  flag: true,
  stringArg: 'hello',
  dir: 'defaultDir',
  input: 'defaultDir',
  d: 'defaultDir',
  port: '3000',
  'foo-bar': 'baz',
  foobar: 'baz',
  fb: 'baz'
}

args: ["-d","aliased","-i","double","-v","-h"] =>
{
  _: [],
  version: true,
  v: true,
  help: true,
  h: true,
  domdiff: false,
  boolArg: false,
  boolArg2: true,
  flag: true,
  d: 'aliased',
  dir: [ 'aliased', 'double' ],
  input: [ 'aliased', 'double' ],
  i: 'double',
  port: '3000',
  stringArg: 'defaultString',
  'foo-bar': 'baz',
  foobar: 'baz',
  fb: 'baz'
}

args: ["--dir=src","--dir=dist","--input=foo"] =>
{
  _: [],
  version: false,
  v: false,
  help: false,
  h: false,
  domdiff: false,
  boolArg: false,
  boolArg2: true,
  flag: true,
  dir: [ 'src', 'dist', 'foo' ],
  input: [ 'src', 'dist', 'foo' ],
  d: [ 'src', 'dist', 'foo' ],
  port: '3000',
  stringArg: 'defaultString',
  'foo-bar': 'baz',
  foobar: 'baz',
  fb: 'baz'
}

[minimist unknown] file1
[minimist unknown] file2
args: ["file1","file2","--dir=src","--port=5000"] =>
{
  _: [],
  version: false,
  v: false,
  help: false,
  h: false,
  domdiff: false,
  boolArg: false,
  boolArg2: true,
  flag: true,
  dir: 'src',
  input: 'src',
  d: 'src',
  port: '5000',
  stringArg: 'defaultString',
  'foo-bar': 'baz',
  foobar: 'baz',
  fb: 'baz'
}

args: ["--boolArg","--boolArg2","--flag=false"] =>
{
  _: [],
  version: false,
  v: false,
  help: false,
  h: false,
  domdiff: false,
  boolArg: true,
  boolArg2: true,
  flag: false,
  dir: 'defaultDir',
  input: 'defaultDir',
  d: 'defaultDir',
  port: '3000',
  stringArg: 'defaultString',
  'foo-bar': 'baz',
  foobar: 'baz',
  fb: 'baz'
}

args: ["--boolArg=false","--boolArg2=true","--flag"] =>
{
  _: [],
  version: false,
  v: false,
  help: false,
  h: false,
  domdiff: false,
  boolArg: false,
  boolArg2: true,
  flag: true,
  dir: 'defaultDir',
  input: 'defaultDir',
  d: 'defaultDir',
  port: '3000',
  stringArg: 'defaultString',
  'foo-bar': 'baz',
  foobar: 'baz',
  fb: 'baz'
}

args: ["--port=8080","--port","9090"] =>
{
  _: [],
  version: false,
  v: false,
  help: false,
  h: false,
  domdiff: false,
  boolArg: false,
  boolArg2: true,
  flag: true,
  port: [ '8080', '9090' ],
  dir: 'defaultDir',
  input: 'defaultDir',
  d: 'defaultDir',
  stringArg: 'defaultString',
  'foo-bar': 'baz',
  foobar: 'baz',
  fb: 'baz'
}

[minimist unknown] --unknown
args: ["--unknown","--dir=src"] =>
{
  _: [],
  version: false,
  v: false,
  help: false,
  h: false,
  domdiff: false,
  boolArg: false,
  boolArg2: true,
  flag: true,
  dir: 'src',
  input: 'src',
  d: 'src',
  port: '3000',
  stringArg: 'defaultString',
  'foo-bar': 'baz',
  foobar: 'baz',
  fb: 'baz'
}

[minimist unknown] -abc
[minimist unknown] -abc
[minimist unknown] -abc
args: ["-abc"] =>
{
  _: [],
  version: false,
  v: false,
  help: false,
  h: false,
  domdiff: false,
  boolArg: false,
  boolArg2: true,
  flag: true,
  dir: 'defaultDir',
  input: 'defaultDir',
  d: 'defaultDir',
  port: '3000',
  stringArg: 'defaultString',
  'foo-bar': 'baz',
  foobar: 'baz',
  fb: 'baz'
}

args: ["--foo-bar=123","--foobar=456","--fb=789"] =>
{
  _: [],
  version: false,
  v: false,
  help: false,
  h: false,
  domdiff: false,
  boolArg: false,
  boolArg2: true,
  flag: true,
  'foo-bar': [ '123', '456', '789' ],
  foobar: [ '123', '456', '789' ],
  fb: [ '123', '456', '789' ],
  dir: 'defaultDir',
  input: 'defaultDir',
  d: 'defaultDir',
  port: '3000',
  stringArg: 'defaultString'
}

args: [] =>
{
  _: [],
  version: false,
  v: false,
  help: false,
  h: false,
  domdiff: false,
  boolArg: false,
  boolArg2: true,
  flag: true,
  dir: 'defaultDir',
  input: 'defaultDir',
  d: 'defaultDir',
  port: '3000',
  stringArg: 'defaultString',
  'foo-bar': 'baz',
  foobar: 'baz',
  fb: 'baz'
}

args: ["--dir=src","--","--notAFlag","positional"] =>
{
  _: [ '--notAFlag', 'positional' ],
  version: false,
  v: false,
  help: false,
  h: false,
  domdiff: false,
  boolArg: false,
  boolArg2: true,
  flag: true,
  dir: 'src',
  input: 'src',
  d: 'src',
  port: '3000',
  stringArg: 'defaultString',
  'foo-bar': 'baz',
  foobar: 'baz',
  fb: 'baz'
}

args: ["--version","--version=false","--help=hello"] =>
{
  _: [],
  version: false,
  v: false,
  help: true,
  h: true,
  domdiff: false,
  boolArg: false,
  boolArg2: true,
  flag: true,
  dir: 'defaultDir',
  input: 'defaultDir',
  d: 'defaultDir',
  port: '3000',
  stringArg: 'defaultString',
  'foo-bar': 'baz',
  foobar: 'baz',
  fb: 'baz'
}

=== mri ===
args: ["--dir=src","--input=test","--port","8080","--version","--help","--domdiff"] =>
{
  _: [],
  dir: 'src',
  input: 'src',
  port: '8080',
  version: true,
  help: true,
  domdiff: true,
  boolArg: false,
  boolArg2: true,
  stringArg: 'defaultString',
  flag: true,
  'foo-bar': 'baz',
  i: 'src',
  v: true,
  h: true,
  foobar: 'baz',
  fb: 'baz'
}

args: ["--boolArg","--boolArg2=false","--stringArg=hello"] =>
{
  _: [],
  boolArg: true,
  boolArg2: false,
  stringArg: 'hello',
  dir: 'defaultDir',
  port: '3000',
  domdiff: false,
  version: false,
  help: false,
  flag: true,
  'foo-bar': 'baz',
  input: 'defaultDir',
  i: 'defaultDir',
  v: false,
  h: false,
  foobar: 'baz',
  fb: 'baz'
}

[mri unknown] -d
mri error: [mri unknown] -d
args: ["--dir=src","--dir=dist","--input=foo"] =>
{
  _: [],
  dir: [ 'src', 'dist' ],
  input: [ 'src', 'dist' ],
  port: '3000',
  domdiff: false,
  version: false,
  help: false,
  boolArg: false,
  boolArg2: true,
  stringArg: 'defaultString',
  flag: true,
  'foo-bar': 'baz',
  i: [ 'src', 'dist' ],
  v: false,
  h: false,
  foobar: 'baz',
  fb: 'baz'
}

args: ["file1","file2","--dir=src","--port=5000"] =>
{
  _: [ 'file1', 'file2' ],
  dir: 'src',
  port: '5000',
  domdiff: false,
  version: false,
  help: false,
  boolArg: false,
  boolArg2: true,
  stringArg: 'defaultString',
  flag: true,
  'foo-bar': 'baz',
  input: 'src',
  i: 'src',
  v: false,
  h: false,
  foobar: 'baz',
  fb: 'baz'
}

args: ["--boolArg","--boolArg2","--flag=false"] =>
{
  _: [],
  boolArg: true,
  boolArg2: true,
  flag: false,
  dir: 'defaultDir',
  port: '3000',
  domdiff: false,
  version: false,
  help: false,
  stringArg: 'defaultString',
  'foo-bar': 'baz',
  input: 'defaultDir',
  i: 'defaultDir',
  v: false,
  h: false,
  foobar: 'baz',
  fb: 'baz'
}

args: ["--boolArg=false","--boolArg2=true","--flag"] =>
{
  _: [],
  boolArg: false,
  boolArg2: true,
  flag: true,
  dir: 'defaultDir',
  port: '3000',
  domdiff: false,
  version: false,
  help: false,
  stringArg: 'defaultString',
  'foo-bar': 'baz',
  input: 'defaultDir',
  i: 'defaultDir',
  v: false,
  h: false,
  foobar: 'baz',
  fb: 'baz'
}

args: ["--port=8080","--port","9090"] =>
{
  _: [],
  port: [ '8080', '9090' ],
  dir: 'defaultDir',
  domdiff: false,
  version: false,
  help: false,
  boolArg: false,
  boolArg2: true,
  stringArg: 'defaultString',
  flag: true,
  'foo-bar': 'baz',
  input: 'defaultDir',
  i: 'defaultDir',
  v: false,
  h: false,
  foobar: 'baz',
  fb: 'baz'
}

[mri unknown] --unknown
mri error: [mri unknown] --unknown
[mri unknown] -a
mri error: [mri unknown] -a
args: ["--foo-bar=123","--foobar=456","--fb=789"] =>
{
  _: [],
  'foo-bar': '123',
  foobar: '123',
  fb: '123',
  dir: 'defaultDir',
  port: '3000',
  domdiff: false,
  version: false,
  help: false,
  boolArg: false,
  boolArg2: true,
  stringArg: 'defaultString',
  flag: true,
  input: 'defaultDir',
  i: 'defaultDir',
  v: false,
  h: false
}

args: [] =>
{
  _: [],
  dir: 'defaultDir',
  port: '3000',
  domdiff: false,
  version: false,
  help: false,
  boolArg: false,
  boolArg2: true,
  stringArg: 'defaultString',
  flag: true,
  'foo-bar': 'baz',
  input: 'defaultDir',
  i: 'defaultDir',
  v: false,
  h: false
}

args: ["--dir=src","--","--notAFlag","positional"] =>
{
  _: [ '--notAFlag', 'positional' ],
  dir: 'src',
  port: '3000',
  domdiff: false,
  version: false,
  help: false,
  boolArg: false,
  boolArg2: true,
  stringArg: 'defaultString',
  flag: true,
  'foo-bar': 'baz',
  input: 'src',
  i: 'src',
  v: false,
  h: false
}

args: ["--version","--version=false","--help=hello"] =>
{
  _: [ 'hello' ],
  version: [ true, false ],
  help: true,
  dir: 'defaultDir',
  port: '3000',
  domdiff: false,
  boolArg: false,
  boolArg2: true,
  stringArg: 'defaultString',
  flag: true,
  'foo-bar': 'baz',
  v: [ true, false ],
  h: true,
  input: 'defaultDir',
  i: 'defaultDir'
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants