src/misc/bunyan.js
function parseArgv(argv) {
    var parsed = {
        args: [],
        help: false,
        color: null,
        paginate: null,
        outputMode: OM_LONG,
        jsonIndent: 2,
        level: null,
        strict: false,
        pids: null,
        pidsType: null,
        timeFormat: TIME_UTC  // one of the TIME_ constants
    };

    // Turn '-iH' into '-i -H', except for argument-accepting options.
    var args = argv.slice(2);  // drop ['node', 'scriptname']
    var newArgs = [];
    var optTakesArg = {'d': true, 'o': true, 'c': true, 'l': true, 'p': true};
    for (var i = 0; i < args.length; i++) {
        if (args[i].charAt(0) === '-' && args[i].charAt(1) !== '-' &&
            args[i].length > 2)
        {
            var splitOpts = args[i].slice(1).split('');
            for (var j = 0; j < splitOpts.length; j++) {
                newArgs.push('-' + splitOpts[j]);
                if (optTakesArg[splitOpts[j]]) {
                    var optArg = splitOpts.slice(j+1).join('');
                    if (optArg.length) {
                        newArgs.push(optArg);
                    }
                    break;
                }
            }
        } else {
            newArgs.push(args[i]);
        }
    }
    args = newArgs;

    // Expose level definitions to condition vm context
    var condDefines = [];
    Object.keys(upperNameFromLevel).forEach(function (lvl) {
        condDefines.push(
            format('Object.prototype.%s = %s;', upperNameFromLevel[lvl], lvl));
    });
    condDefines = condDefines.join('\n') + '\n';

    var endOfOptions = false;
    while (args.length > 0) {
        var arg = args.shift();
        switch (arg) {
            case '--':
                endOfOptions = true;
                break;
            case '-h': // display help and exit
            case '--help':
                parsed.help = true;
                break;
            case '--version':
                parsed.version = true;
                break;
            case '--strict':
                parsed.strict = true;
                break;
            case '--color':
                parsed.color = true;
                break;
            case '--no-color':
                parsed.color = false;
                break;
            case '--pager':
                parsed.paginate = true;
                break;
            case '--no-pager':
                parsed.paginate = false;
                break;
            case '-o':
            case '--output':
                var name = args.shift();
                var idx = name.lastIndexOf('-');
                if (idx !== -1) {
                    var indentation = Number(name.slice(idx+1));
                    if (! isNaN(indentation)) {
                        parsed.jsonIndent = indentation;
                        name = name.slice(0, idx);
                    }
                }
                parsed.outputMode = OM_FROM_NAME[name];
                if (parsed.outputMode === undefined) {
                    throw new Error('unknown output mode: "'+name+'"');
                }
                break;
            case '-j': // output with JSON.stringify
                parsed.outputMode = OM_JSON;
                break;
            case '-0':
                parsed.outputMode = OM_BUNYAN;
                break;
            case '-L':
                parsed.timeFormat = TIME_LOCAL;
                if (!moment) {
                    throw new Error(
                        'could not find moment package required for "-L"');
                }
                break;
            case '--time':
                var timeArg = args.shift();
                switch (timeArg) {
                case 'utc':
                    parsed.timeFormat = TIME_UTC;
                    break
                case 'local':
                    parsed.timeFormat = TIME_LOCAL;
                    if (!moment) {
                        throw new Error('could not find moment package '
                            + 'required for "--time=local"');
                    }
                    break
                case undefined:
                    throw new Error('missing argument to "--time"');
                default:
                    throw new Error(format('invalid time format: "%s"',
                        timeArg));
                }
                break;
            case '-p':
                if (!parsed.pids) {
                    parsed.pids = [];
                }
                var pidArg = args.shift();
                var pid = +(pidArg);
                if (!isNaN(pid) || pidArg === '*') {
                    if (parsed.pidsType && parsed.pidsType !== 'num') {
                        throw new Error(format('cannot mix PID name and '
                            + 'number arguments: "%s"', pidArg));
                    }
                    parsed.pidsType = 'num';
                    if (!parsed.pids) {
                        parsed.pids = [];
                    }
                    parsed.pids.push(isNaN(pid) ? pidArg : pid);
                } else {
                    if (parsed.pidsType && parsed.pidsType !== 'name') {
                        throw new Error(format('cannot mix PID name and '
                            + 'number arguments: "%s"', pidArg));
                    }
                    parsed.pidsType = 'name';
                    parsed.pids = pidArg;
                }
                break;
            case '-l':
            case '--level':
                var levelArg = args.shift();
                var level = +(levelArg);
                if (isNaN(level)) {
                    level = +levelFromName[levelArg.toLowerCase()];
                }
                if (isNaN(level)) {
                    throw new Error('unknown level value: "'+levelArg+'"');
                }
                parsed.level = level;
                break;
            case '-c':
            case '--condition':
                gUsingConditionOpts = true;
                var condition = args.shift();
                if (Boolean(process.env.BUNYAN_EXEC &&
                    process.env.BUNYAN_EXEC === 'vm'))
                {
                    parsed.condVm = parsed.condVm || [];
                    var scriptName = 'bunyan-condition-'+parsed.condVm.length;
                    var code = condDefines + condition;
                    var script;
                    try {
                        script = vm.createScript(code, scriptName);
                    } catch (complErr) {
                        throw new Error(format('illegal CONDITION code: %s\n'
                            + '  CONDITION script:\n'
                            + '%s\n'
                            + '  Error:\n'
                            + '%s',
                            complErr, indent(code), indent(complErr.stack)));
                    }

                    // Ensure this is a reasonably safe CONDITION.
                    try {
                        script.runInNewContext(minValidRecord);
                    } catch (condErr) {
                        throw new Error(format(
                            /* JSSTYLED */
                            'CONDITION code cannot safely filter a minimal Bunyan log record\n'
                            + '  CONDITION script:\n'
                            + '%s\n'
                            + '  Minimal Bunyan log record:\n'
                            + '%s\n'
                            + '  Filter error:\n'
                            + '%s',
                            indent(code),
                            indent(JSON.stringify(minValidRecord, null, 2)),
                            indent(condErr.stack)
                            ));
                    }
                    parsed.condVm.push(script);
                } else  {
                    parsed.condFuncs = parsed.condFuncs || [];
                    parsed.condFuncs.push(funcWithReturnFromSnippet(condition));
                }
                break;
            default: // arguments
                if (!endOfOptions && arg.length > 0 && arg[0] === '-') {
                    throw new Error('unknown option "'+arg+'"');
                }
                parsed.args.push(arg);
                break;
        }
    }
    //TODO: '--' handling and error on a first arg that looks like an option.

    return parsed;
}
function parseArgv(argv) {
    var parsed = {
        args: [],
        help: false,
        color: null,
        paginate: null,
        outputMode: OM_LONG,
        jsonIndent: 2,
        level: null,
        strict: false,
        pids: null,
        pidsType: null,
        timeFormat: TIME_UTC  // one of the TIME_ constants
    };

    // Turn '-iH' into '-i -H', except for argument-accepting options.
    var args = argv.slice(2);  // drop ['node', 'scriptname']
    var newArgs = [];
    var optTakesArg = {'d': true, 'o': true, 'c': true, 'l': true, 'p': true};
    for (var i = 0; i < args.length; i++) {
        if (args[i].charAt(0) === '-' && args[i].charAt(1) !== '-' &&
            args[i].length > 2)
        {
            var splitOpts = args[i].slice(1).split('');
            for (var j = 0; j < splitOpts.length; j++) {
                newArgs.push('-' + splitOpts[j]);
                if (optTakesArg[splitOpts[j]]) {
                    var optArg = splitOpts.slice(j+1).join('');
                    if (optArg.length) {
                        newArgs.push(optArg);
                    }
                    break;
                }
            }
        } else {
            newArgs.push(args[i]);
        }
    }
    args = newArgs;

    // Expose level definitions to condition vm context
    var condDefines = [];
    Object.keys(upperNameFromLevel).forEach(function (lvl) {
        condDefines.push(
            format('Object.prototype.%s = %s;', upperNameFromLevel[lvl], lvl));
    });
    condDefines = condDefines.join('\n') + '\n';

    var endOfOptions = false;
    while (args.length > 0) {
        var arg = args.shift();
        switch (arg) {
            case '--':
                endOfOptions = true;
                break;
            case '-h': // display help and exit
            case '--help':
                parsed.help = true;
                break;
            case '--version':
                parsed.version = true;
                break;
            case '--strict':
                parsed.strict = true;
                break;
            case '--color':
                parsed.color = true;
                break;
            case '--no-color':
                parsed.color = false;
                break;
            case '--pager':
                parsed.paginate = true;
                break;
            case '--no-pager':
                parsed.paginate = false;
                break;
            case '-o':
            case '--output':
                var name = args.shift();
                var idx = name.lastIndexOf('-');
                if (idx !== -1) {
                    var indentation = Number(name.slice(idx+1));
                    if (! isNaN(indentation)) {
                        parsed.jsonIndent = indentation;
                        name = name.slice(0, idx);
                    }
                }
                parsed.outputMode = OM_FROM_NAME[name];
                if (parsed.outputMode === undefined) {
                    throw new Error('unknown output mode: "'+name+'"');
                }
                break;
            case '-j': // output with JSON.stringify
                parsed.outputMode = OM_JSON;
                break;
            case '-0':
                parsed.outputMode = OM_BUNYAN;
                break;
            case '-L':
                parsed.timeFormat = TIME_LOCAL;
                if (!moment) {
                    throw new Error(
                        'could not find moment package required for "-L"');
                }
                break;
            case '--time':
                var timeArg = args.shift();
                switch (timeArg) {
                case 'utc':
                    parsed.timeFormat = TIME_UTC;
                    break
                case 'local':
                    parsed.timeFormat = TIME_LOCAL;
                    if (!moment) {
                        throw new Error('could not find moment package '
                            + 'required for "--time=local"');
                    }
                    break
                case undefined:
                    throw new Error('missing argument to "--time"');
                default:
                    throw new Error(format('invalid time format: "%s"',
                        timeArg));
                }
                break;
            case '-p':
                if (!parsed.pids) {
                    parsed.pids = [];
                }
                var pidArg = args.shift();
                var pid = +(pidArg);
                if (!isNaN(pid) || pidArg === '*') {
                    if (parsed.pidsType && parsed.pidsType !== 'num') {
                        throw new Error(format('cannot mix PID name and '
                            + 'number arguments: "%s"', pidArg));
                    }
                    parsed.pidsType = 'num';
                    if (!parsed.pids) {
                        parsed.pids = [];
                    }
                    parsed.pids.push(isNaN(pid) ? pidArg : pid);
                } else {
                    if (parsed.pidsType && parsed.pidsType !== 'name') {
                        throw new Error(format('cannot mix PID name and '
                            + 'number arguments: "%s"', pidArg));
                    }
                    parsed.pidsType = 'name';
                    parsed.pids = pidArg;
                }
                break;
            case '-l':
            case '--level':
                var levelArg = args.shift();
                var level = +(levelArg);
                if (isNaN(level)) {
                    level = +levelFromName[levelArg.toLowerCase()];
                }
                if (isNaN(level)) {
                    throw new Error('unknown level value: "'+levelArg+'"');
                }
                parsed.level = level;
                break;
            case '-c':
            case '--condition':
                gUsingConditionOpts = true;
                var condition = args.shift();
                if (Boolean(process.env.BUNYAN_EXEC &&
                    process.env.BUNYAN_EXEC === 'vm'))
                {
                    parsed.condVm = parsed.condVm || [];
                    var scriptName = 'bunyan-condition-'+parsed.condVm.length;
                    var code = condDefines + condition;
                    var script;
                    try {
                        script = vm.createScript(code, scriptName);
                    } catch (complErr) {
                        throw new Error(format('illegal CONDITION code: %s\n'
                            + '  CONDITION script:\n'
                            + '%s\n'
                            + '  Error:\n'
                            + '%s',
                            complErr, indent(code), indent(complErr.stack)));
                    }

                    // Ensure this is a reasonably safe CONDITION.
                    try {
                        script.runInNewContext(minValidRecord);
                    } catch (condErr) {
                        throw new Error(format(
                            /* JSSTYLED */
                            'CONDITION code cannot safely filter a minimal Bunyan log record\n'
                            + '  CONDITION script:\n'
                            + '%s\n'
                            + '  Minimal Bunyan log record:\n'
                            + '%s\n'
                            + '  Filter error:\n'
                            + '%s',
                            indent(code),
                            indent(JSON.stringify(minValidRecord, null, 2)),
                            indent(condErr.stack)
                            ));
                    }
                    parsed.condVm.push(script);
                } else  {
                    parsed.condFuncs = parsed.condFuncs || [];
                    parsed.condFuncs.push(funcWithReturnFromSnippet(condition));
                }
                break;
            default: // arguments
                if (!endOfOptions && arg.length > 0 && arg[0] === '-') {
                    throw new Error('unknown option "'+arg+'"');
                }
                parsed.args.push(arg);
                break;
        }
    }
    //TODO: '--' handling and error on a first arg that looks like an option.

    return parsed;
}
function parseArgv ( argv ) { var parsed = { args : [ ] , help : false , color : null , paginate : null , outputMode : OM_LONG , jsonIndent : 2 , level : null , strict : false , pids : null , pidsType : null , timeFormat : TIME_UTC // one of the TIME_ constants } ; // Turn '-iH' into '-i -H', except for argument-accepting options. var args = argv . slice ( 2 ) ; // drop ['node', 'scriptname'] var newArgs = [ ] ; var optTakesArg = { 'd' : true , 'o' : true , 'c' : true , 'l' : true , 'p' : true } ; for ( var i = 0 ; i < args . length ; i ++ ) { if ( args [ i ] . charAt ( 0 ) === '-' && args [ i ] . charAt ( 1 ) !== '-' && args [ i ] . length > 2 ) { var splitOpts = args [ i ] . slice ( 1 ) . split ( '' ) ; for ( var j = 0 ; j < splitOpts . length ; j ++ ) { newArgs . push ( '-' + splitOpts [ j ] ) ; if ( optTakesArg [ splitOpts [ j ] ] ) { var optArg = splitOpts . slice ( j + 1 ) . join ( '' ) ; if ( optArg . length ) { newArgs . push ( optArg ) ; } break ; } } } else { newArgs . push ( args [ i ] ) ; } } args = newArgs ; // Expose level definitions to condition vm context var condDefines = [ ] ; Object . keys ( upperNameFromLevel ) . forEach ( function ( lvl ) { condDefines . push ( format ( 'Object.prototype.%s = %s;' , upperNameFromLevel [ lvl ] , lvl ) ) ; } ) ; condDefines = condDefines . join ( '\n' ) + '\n' ; var endOfOptions = false ; while ( args . length > 0 ) { var arg = args . shift ( ) ; switch ( arg ) { case '--' : endOfOptions = true ; break ; case '-h' : // display help and exit case '--help' : parsed . help = true ; break ; case '--version' : parsed . version = true ; break ; case '--strict' : parsed . strict = true ; break ; case '--color' : parsed . color = true ; break ; case '--no-color' : parsed . color = false ; break ; case '--pager' : parsed . paginate = true ; break ; case '--no-pager' : parsed . paginate = false ; break ; case '-o' : case '--output' : var name = args . shift ( ) ; var idx = name . lastIndexOf ( '-' ) ; if ( idx !== - 1 ) { var indentation = Number ( name . slice ( idx + 1 ) ) ; if ( ! isNaN ( indentation ) ) { parsed . jsonIndent = indentation ; name = name . slice ( 0 , idx ) ; } } parsed . outputMode = OM_FROM_NAME [ name ] ; if ( parsed . outputMode === undefined ) { throw new Error ( 'unknown output mode: "' + name + '"' ) ; } break ; case '-j' : // output with JSON.stringify parsed . outputMode = OM_JSON ; break ; case '-0' : parsed . outputMode = OM_BUNYAN ; break ; case '-L' : parsed . timeFormat = TIME_LOCAL ; if ( ! moment ) { throw new Error ( 'could not find moment package required for "-L"' ) ; } break ; case '--time' : var timeArg = args . shift ( ) ; switch ( timeArg ) { case 'utc' : parsed . timeFormat = TIME_UTC ; break case 'local' : parsed . timeFormat = TIME_LOCAL ; if ( ! moment ) { throw new Error ( 'could not find moment package ' + 'required for "--time=local"' ) ; } break case undefined : throw new Error ( 'missing argument to "--time"' ) ; default : throw new Error ( format ( 'invalid time format: "%s"' , timeArg ) ) ; } break ; case '-p' : if ( ! parsed . pids ) { parsed . pids = [ ] ; } var pidArg = args . shift ( ) ; var pid = + ( pidArg ) ; if ( ! isNaN ( pid ) || pidArg === '*' ) { if ( parsed . pidsType && parsed . pidsType !== 'num' ) { throw new Error ( format ( 'cannot mix PID name and ' + 'number arguments: "%s"' , pidArg ) ) ; } parsed . pidsType = 'num' ; if ( ! parsed . pids ) { parsed . pids = [ ] ; } parsed . pids . push ( isNaN ( pid ) ? pidArg : pid ) ; } else { if ( parsed . pidsType && parsed . pidsType !== 'name' ) { throw new Error ( format ( 'cannot mix PID name and ' + 'number arguments: "%s"' , pidArg ) ) ; } parsed . pidsType = 'name' ; parsed . pids = pidArg ; } break ; case '-l' : case '--level' : var levelArg = args . shift ( ) ; var level = + ( levelArg ) ; if ( isNaN ( level ) ) { level = + levelFromName [ levelArg . toLowerCase ( ) ] ; } if ( isNaN ( level ) ) { throw new Error ( 'unknown level value: "' + levelArg + '"' ) ; } parsed . level = level ; break ; case '-c' : case '--condition' : gUsingConditionOpts = true ; var condition = args . shift ( ) ; if ( Boolean ( process . env . BUNYAN_EXEC && process . env . BUNYAN_EXEC === 'vm' ) ) { parsed . condVm = parsed . condVm || [ ] ; var scriptName = 'bunyan-condition-' + parsed . condVm . length ; var code = condDefines + condition ; var script ; try { script = vm . createScript ( code , scriptName ) ; } catch ( complErr ) { throw new Error ( format ( 'illegal CONDITION code: %s\n' + '  CONDITION script:\n' + '%s\n' + '  Error:\n' + '%s' , complErr , indent ( code ) , indent ( complErr . stack ) ) ) ; } // Ensure this is a reasonably safe CONDITION. try { script . runInNewContext ( minValidRecord ) ; } catch ( condErr ) { throw new Error ( format ( /* JSSTYLED */ 'CONDITION code cannot safely filter a minimal Bunyan log record\n' + '  CONDITION script:\n' + '%s\n' + '  Minimal Bunyan log record:\n' + '%s\n' + '  Filter error:\n' + '%s' , indent ( code ) , indent ( JSON . stringify ( minValidRecord , null , 2 ) ) , indent ( condErr . stack ) ) ) ; } parsed . condVm . push ( script ) ; } else { parsed . condFuncs = parsed . condFuncs || [ ] ; parsed . condFuncs . push ( funcWithReturnFromSnippet ( condition ) ) ; } break ; default : // arguments if ( ! endOfOptions && arg . length > 0 && arg [ 0 ] === '-' ) { throw new Error ( 'unknown option "' + arg + '"' ) ; } parsed . args . push ( arg ) ; break ; } } //TODO: '--' handling and error on a first arg that looks like an option. return parsed ; }
Parse the command-line options and arguments into an object.

{
'args': [...]       // arguments
'help': true,       // true if '-h' option given
// etc.
}

@return {Object} The parsed options. `.args` is the argument list.
@throws {Error} If there is an error parsing argv.
Parse the command - line options and arguments into an object .