Skip to content

Instantly share code, notes, and snippets.

@BananaAcid
Last active Aug 12, 2021
Embed
What would you like to do?
node js simple param parsing

commandline parsing in nodejs

Parse commandline arguments (common formats) on osx/linux/windows:

    --param1             =>  argv.param1 = true
    --param2 "ab c"      =>  argv.param2 = 'ab c'
    --param3 abc         =>  argv.param3 = 'abc'
    -p4                  =>  argv.p4 = true
    -p4 val              =>  argv.p4 = 'val'
    -p4 "val 2"          =>  argv.p4 = 'val 2'
    /p5                  =>  argv.p5 = true
    /p5 val              =>  argv.p5 = 'val'
    /p5 "val 2"          =>  argv.p5 = 'val 2'
    --param6="abc = def" =>  argv.param6 = 'abc = def'
    /p7="abc = def"      =>  argv.p7 = 'abc = def'


    params-extended-dashed.mjs:
      `--` support
      parse() is exported.

  • params-module.js

    • just uses a simple function to parse the arguments (common formats) on osx/linux/windows
  • params-simple.mjs

    • does the same as params-module.js just being a rewrite as ES6 module
  • params-extended.mjs

    • is as params-simple.mjs but supports --param="some thing" and returns the unused param values in faulty
  • params-extended-dashed.mjs

    • is as params-extended.mjs but supports -- for a second part and exports parse(args) to parse these additional arguments after the dashes

specific ones

  • params-debug.js

    • only param is -l * and --log * (* == app:* and can be anything to use debug with), uses the debug module and fixes the logging level afterwards (anywhere in the code.)
  • params-debug.log-only.js

    • only param is -l and --log (simple example, debug will be set like DEBUG=*)

note

only params-extended-dashed.mjs supports the -- divider

usage

to test, you can use from the command line

  • npm install gist:76f700a3b221f23f054016bb54279620 && node node_modules/cli-params-simple/params-module.js --param1 --param2 "ab c" -p3 (download and run)

  • currently not testable:

    • npx gist:76f700a3b221f23f054016bb54279620 --param1 --param2 "ab c" -p3

Result

[ param1: true, param2: 'ab c', p3: true ]

in code

using require: (any NodeJS version)

var args = require('cli-params-simple/params-module.js');

using import: (NodeJS 12+)

import args1 from 'cli-params-simple/params-simple.mjs';
import args2, {faulty} from 'cli-params-simple/params-extended.mjs';
import args3, {faulty as faulty2, dashed, parse} from './params-extended-dashed.mjs';

see test.mjs

{
"name": "cli-params-simple",
"version": "1.0.2",
"main": "params-extended.mjs",
"bin": {
"cli-params-simple": "params-module.js",
"cli-params-debug": "params-debug.js",
"cli.params-debug-log": "params-debug.log-only.js"
},
"scripts": {
"test": "node test.mjs --param1 --param2 \"ab c\" -p3 --param4=\"asdad =addd\" /p5 as asdadd"
},
"dependencies": {
"debug": "latest"
},
"repository": "gist:BananaAcid/76f700a3b221f23f054016bb54279620"
}
#!/usr/bin/env node
// example
// manually handling the --logging param to have debug be set up before anything else
let debug = require('debug');
let debug_prefix = 'app:'; // <- setting it to app:* or alike ...
let argv_logging = 'undefined';
process.argv.forEach((val, index) => {
let params = val.split('=');
if ('--log' == params[0].toLocaleLowerCase() || '-l' == params[0].toLocaleLowerCase()) {
let param = params.length == 2 ? params.pop() : (params.length == 1 && process.argv[index +1] && process.argv[index +1][0] != '-' ? process.argv[index +1] : '*');
argv_logging = param;
debug.enable(debug_prefix + param); // <- setting it to app:* or alike ... overwriting environment variable DEBUG=* or alike
}
});
console.log('START');
let d = debug('app:init');
let di = debug('app:info');
let de = debug('app:error');
let dos = debug('app:option');
d('start');
dos('logging: ', argv_logging);
d('doing something');
di('triffic and so on');
de('404 because of somehting');
d('ending');
console.log('END');
#!/usr/bin/env node
//example
let debug = require('debug');
// param test:
if (~process.argv.indexOf('--log') || ~process.argv.indexOf('-l')) debug.enable('*'); else console.log('no --log param used.');
debug('app')('get any debug, log is used');
// .. do something.
debug('app')('logging something');
/**
@author Nabil Redmann <repo+gist@bananaacid.de>
@license MIT
@version 1.3
@usage
simple param parsing
--param1 => argv.param1 = true
--param2 "ab c" => argv.param2 = 'ab c'
--param3 abc => argv.param3 = 'abc'
-p4 => argv.p4 = true
-p4 val => argv.p4 = 'val'
-p4 "val 2" => argv.p4 = 'val 2'
/p5 => argv.p5 = true
/p5 val => argv.p5 = 'val'
/p5 "val 2" => argv.p5 = 'val 2'
--param6="abc = def" => argv.param6 = 'abc = def'
/p7="abc = def" => argv.p7 = 'abc = def'
@note
additional arguments after `--` will be stored as an array and not be touched,
parsing of these can be done by using the exported `parse(args)` function
@example
index.mjs
import args, { rest, dashed, parse } from './params-extended-dashed.mjs';
console.log(process.argv, args);
console.log('rest ones:', rest);
console.log('after --:', dashed);
$ node index.mjs --param1 a1 --param2="asdad =addd" /p as asdadd -- --safsdfasdf 123 fffff
**/
let parseFn = (accumulator, currentValue, currentIndex, source) => {
if (currentValue && !!~['-', '/'].indexOf(currentValue[0])) {
let cv = currentValue.replace(/^(-|\/)+/, '');
let val = true;
if (!!~cv.indexOf('=')) {
let [cvNew, ...rest] = cv.split('=');
cv = cvNew;
val = rest.join('=');
} else if (source[currentIndex + 1] && (!~['-', '/'].indexOf(source[currentIndex + 1][0]))) {
val = source[currentIndex + 1];
source[currentIndex + 1] = undefined;
}
accumulator.params[cv] = val;
} else if (currentValue) {
// left over value
//console.error('value can not be associated:', currentValue);
accumulator.rest.push(currentValue);
}
return accumulator;
};
let argsBase = process.argv.slice(2);
const idx = argsBase.indexOf('--');
let argsDashed = [];
if (!!~idx) {
argsDashed = argsBase.splice(idx);
argsDashed.shift();
}
const args = argsBase.reduce(parseFn, { 'params': {}, 'rest': [] });
//const argsd = argsDashed.reduce(parseFn, { 'params': {}, 'rest': [] }); // parse the args after `--`
export default args.params;
export const rest = args.rest;
export const dashed = argsDashed; // argsd
export const parse = argsBase => argsBase.reduce(parseFn, { 'params': {}, 'rest': [] });
/**
@author Nabil Redmann <repo+gist@bananaacid.de>
@license MIT
@version 1.1
simple param parsing
--param1 => argv.param1 = true
--param2 "ab c" => argv.param2 = 'ab c'
--param3 abc => argv.param3 = 'abc'
-p4 => argv.p4 = true
-p4 val => argv.p4 = 'val'
-p4 "val 2" => argv.p4 = 'val 2'
/p5 => argv.p5 = true
/p5 val => argv.p5 = 'val'
/p5 "val 2" => argv.p5 = 'val 2'
--param6="abc = def" => argv.param6 = 'abc = def'
/p7="abc = def" => argv.p7 = 'abc = def'
test:
index.mjs
import args,{rest} from './params-extended.mjs';
console.log(process.argv, args);
$ node index.mjs --param1 a1 --param2="asdad =addd" /p as asdadd
*/
let args_err = [];
const args = process.argv.slice(2).reduce((accumulator,currentValue,currentIndex,source) => {
if (currentValue && !!~[ '-', '/'].indexOf(currentValue[0])) {
let cv = currentValue.replace(/^(-|\/)+/, '');
let val = true;
if (!!~cv.indexOf('=')) {
let [cvNew, ...rest] = cv.split('=');
cv = cvNew;
val = rest.join('=');
}
else if ( source[currentIndex+1] && (!~[ '-', '/'].indexOf(source[currentIndex+1][0]) ) ) {
val = source[currentIndex+1];
source[currentIndex+1] = undefined;
}
accumulator[cv] = val;
}
else if (currentValue) {
// left over value
//console.error('value can not be associated:', currentValue);
args_err.push(currentValue);
}
return accumulator;
}, {});
export default args;
export const rest = args_err;
#!/usr/bin/env node
/**
@author Nabil Redmann <repo+gist@bananaacid.de>
@license MIT
@version 1.0
simple param parsing
--param1 => argv.param1 = true
--param2 "ab c" => argv.param2 = 'ab c'
--param3 abc => argv.param3 = 'abc'
-p4 => argv.p4 = true
-p4 val => argv.p4 = 'val'
-p4 "val 2" => argv.p4 = 'val 2'
/p5 => argv.p5 = true
/p5 val => argv.p5 = 'val'
/p5 "val 2" => argv.p5 = 'val 2'
*/
/*
* test:
* $ node cli-params.js --param "abc def" -p2
*/
let args = (function(argv) {
//var argv = process.argv.slice(2); -> node script.js --param1 ...
var args = [];
var i = 0;
while (i !== null) {
if (argv[i]) {
if (argv[i][0] == '-' || argv[i][0] == '/') {
var p = argv[i].replace(/^(-|\/)+/, ''); // get param name
var v = true;
if (argv[i+1] && (argv[i+1][0] !== '-' && argv[i+1][0] !== '/')) {
v = argv[i+1];
i++;
}
args[p] = v;
}
i++;
}
else
i = null;
}
return args;
})(process.argv.slice(2));
if (!!~process.argv[1].indexOf('params-module.js')) console.log('Arguments: ', args);
module.exports = args;
/**
@author Nabil Redmann <repo+gist@bananaacid.de>
@license MIT
@version 1.0
simple param parsing
--param1 => argv.param1 = true
--param2 "ab c" => argv.param2 = 'ab c'
--param3 abc => argv.param3 = 'abc'
-p4 => argv.p4 = true
-p4 val => argv.p4 = 'val'
-p4 "val 2" => argv.p4 = 'val 2'
/p5 => argv.p5 = true
/p5 val => argv.p5 = 'val'
/p5 "val 2" => argv.p5 = 'val 2'
test:
index.mjs
import args from './params-simple.mjs';
console.log(process.argv, args);
$ node index.mjs --param1 a1 --param2="asdad =addd" /p as asdadd
*/
const args = process.argv.slice(2).reduce((accumulator,currentValue,currentIndex,source) => {
if (currentValue && !!~[ '-', '/'].indexOf(currentValue[0])) {
let cv = currentValue.replace(/^(-|\/)+/, '');
let val = true;
if ( source[currentIndex+1] && (!~[ '-', '/'].indexOf(source[currentIndex+1][0]) ) ) {
val = source[currentIndex+1];
source[currentIndex+1] = undefined;
}
accumulator[cv] = val;
}
return accumulator;
}, {});
export default args;
import args0 from './params-module.js';
import args1 from './params-simple.mjs';
import args2, {rest as rest1} from './params-extended.mjs';
import args3, {rest as rest2, dashed, parse} from './params-extended-dashed.mjs';
console.log(process.argv, args0, args1, args2, args3);
console.log('--');
console.log('rest ones:', rest1);
console.log('--');
console.log('dashed ones:', dashed);
console.log('rest2 ones:', rest2);
const {params, rest} = parse('--help -? --param=var whatever');
console.log('parse fn:', params, rest);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment