From 11bfcd4befc88c6f7626b09f78f55624fcc78430 Mon Sep 17 00:00:00 2001 From: hacksalot Date: Mon, 11 Jan 2016 18:07:56 -0500 Subject: [PATCH] Support raw JSON in the --options parameter. --- src/cli/main.js | 111 ++++++++++++++++++++++++++++++++------------- src/verbs/build.js | 13 +++--- 2 files changed, 87 insertions(+), 37 deletions(-) diff --git a/src/cli/main.js b/src/cli/main.js index 9259cc5..64c825f 100644 --- a/src/cli/main.js +++ b/src/cli/main.js @@ -24,6 +24,8 @@ Definition of the `main` function. , StringUtils = require('../utils/string.js') , _ = require('underscore') , OUTPUT = require('./out') + , SAFELOAD = require('../utils/safe-json-loader') + , PAD = require('string-padding') , Command = require('commander').Command; @@ -33,20 +35,23 @@ Definition of the `main` function. @license MIT. See LICENSE.md for details. @module main.js */ - var main = module.exports = function( args ) { + var main = module.exports = function( rawArgs ) { - args = initialize( args ); + var initInfo = initialize( rawArgs ); + var args = initInfo.args; // Create the top-level (application) command... var program = new Command('hackmyresume') .version(PKG.version) .description(chalk.yellow.bold('*** HackMyResume ***')) - .option('-o --opts ', 'Path to a .hackmyrc options file') + //.option('-o --optionsSafe ', 'Path to a .hackmyrc options file', /^\"(.*)\"$/i ) .option('-s --silent', 'Run in silent mode') .option('--no-color', 'Disable colors') .option('--color', 'Enable colors') .option('-d --debug', 'Enable diagnostics', false) - .option('-v --version', 'Show the version'); + .option('-v --version', 'Show the version') + .allowUnknownOption(); + program.jsonArgs = initInfo.options; //.usage('COMMAND [TO ]'); // Create the NEW command @@ -121,20 +126,12 @@ Definition of the `main` function. logMsg( title ); - // Support case-insensitive sub-commands (build, generate, validate, etc.).. - var oVerb, verb = '', args = ar.slice(), cleanArgs = args.slice(2); - if( cleanArgs.length ) { - var verbIdx = _.findIndex( cleanArgs, function(v){ return v[0] !== '-'; }); - if( verbIdx !== -1 ) { - oVerb = cleanArgs[ verbIdx ]; - verb = args[ verbIdx + 2 ] = oVerb.trim().toLowerCase(); - } - } + var o = initOptions( ar ); // Handle invalid verbs here (a bit easier here than in commander.js)... - if( verb && !HMR.verbs[ verb ] && !HMR.alias[ verb ] ) { + if( o.verb && !HMR.verbs[ o.verb ] && !HMR.alias[ o.verb ] ) { throw { fluenterror: HACKMYSTATUS.invalidCommand, shouldExit: true, - attempted: oVerb }; + attempted: o.orgVerb }; } // Override the .missingArgument behavior @@ -150,17 +147,56 @@ Definition of the `main` function. return chalk.green.bold(manPage); }; - return args; + return { + args: o.args, + options: o.json + }; } + function initOptions( ar ) { + var oVerb, verb = '', args = ar.slice(), cleanArgs = args.slice(2), oJSON; + if( cleanArgs.length ) { + + // Support case-insensitive sub-commands (build, generate, validate, etc.).. + var vidx = _.findIndex( cleanArgs, function(v){ return v[0] !== '-'; }); + if( vidx !== -1 ) { + oVerb = cleanArgs[ vidx ]; + verb = args[ vidx + 2 ] = oVerb.trim().toLowerCase(); + } + + // Remove --options --opts -o and process separately + var optsIdx = _.findIndex( cleanArgs, function(v){ + return v === '-o' || v === '--options' || v === '--opts'; + }); + if(optsIdx !== -1) { + optStr = cleanArgs[ optsIdx + 1]; + args.splice( optsIdx + 2, 2 ); + if( optStr && (optStr = optStr.trim()) ) { + //var myJSON = JSON.parse(optStr); + if( optStr[0] === '{') + oJSON = eval('(' + optStr + ')'); // jshint ignore:line + else + oJSON = SAFELOAD.loadSafeJson( optStr ); + } + } + } + + return { + orgVerb: oVerb, + verb: verb, + json: oJSON, + args: args + }; + } + /** Invoke a HackMyResume verb. */ function execute( src, dst, opts, log ) { - loadOptions.call( this, opts ); + loadOptions.call( this, opts, this.parent.jsonArgs ); require( '../core/error-handler' ).init( _opts.debug ); var out = new OUTPUT( _opts ); var v = new HMR.verbs[ this.name() ](); @@ -173,21 +209,35 @@ Definition of the `main` function. /** Initialize HackMyResume options. + TODO: Options loading is a little hacky, for two reasons: + - Commander.js idiosyncracies + - Need to accept JSON inputs from the command line. */ - function loadOptions( o ) { - o.opts = this.parent.opts; + function loadOptions( o, cmdO ) { + + // o and this.opts() seem to be the same (command-specific options) + // Load the specified options file (if any) and apply options - if( o.opts && String.is( o.opts )) { - var json = safeLoadJSON( PATH.relative( process.cwd(), o.opts ) ); - json && ( o = EXTEND( true, o, json ) ); - if( !json ) { - throw safeLoadJSON.error; - } - } + if( cmdO ) + o = EXTEND(true, o, cmdO); + // Merge in command-line options o = EXTEND( true, o, this.opts() ); - o.silent = this.parent.silent; - o.debug = this.parent.debug; + + // Kludge parent-level options until piping issue is resolved + if( this.parent.silent !== undefined && this.parent.silent !== null) + o.silent = this.parent.silent; + if( this.parent.debug !== undefined && this.parent.debug !== null) + o.debug = this.parent.debug; + + if( o.debug ) { + logMsg(chalk.cyan('Merged options: ')); + _.each(o, function(val, key) { + logMsg(chalk.cyan('%s: %s'), PAD(key,10), val); + }); + } + + // Cache _opts = o; } @@ -228,9 +278,8 @@ Definition of the `main` function. /** Simple logging placeholder. */ - function logMsg( msg ) { - msg = msg || ''; - _opts.silent || console.log( msg ); + function logMsg() { + _opts.silent || console.log.apply( console.log, arguments ); } diff --git a/src/verbs/build.js b/src/verbs/build.js index c44995b..6b7fe75 100644 --- a/src/verbs/build.js +++ b/src/verbs/build.js @@ -88,7 +88,8 @@ Implementation of the 'build' verb for HackMyResume. rez = _.reduceRight( sheets, function( a, b, idx ) { return extend( true, b, a ); }); - (sheets.length > 1) && this.stat( HME.afterMerge, { r: rez } ); + // TODO: Fix this condition + (sheets.length) && this.stat( HME.afterMerge, { r: rez } ); // Expand output resumes... var targets = expand( dst, theme ); @@ -155,11 +156,11 @@ Implementation of the 'build' verb for HackMyResume. // If targInfo.fmt.files exists, this format is backed by a document. // Fluent/FRESH themes are handled here. if( targInfo.fmt.files && targInfo.fmt.files.length ) { - theFormat = _fmts.filter( - function(fmt) { return fmt.name === targInfo.fmt.outFormat; })[0]; - MKDIRP.sync( PATH.dirname( f ) ); // Ensure dest folder exists; - _opts.targets = finished; - return theFormat.gen.generate( rez, f, _opts ); + theFormat = _fmts.filter( + function(fmt) { return fmt.name === targInfo.fmt.outFormat; })[0]; + MKDIRP.sync( PATH.dirname( f ) ); // Ensure dest folder exists; + _opts.targets = finished; + return theFormat.gen.generate( rez, f, _opts ); } //Otherwise this is an ad-hoc format (JSON, YML, or PNG) that every theme