mirror of
				https://github.com/JuanCanham/HackMyResume.git
				synced 2025-10-31 05:07:26 +00:00 
			
		
		
		
	Use Commander.js for invocations.
This commit is contained in:
		| @@ -46,6 +46,7 @@ | |||||||
|   "homepage": "https://github.com/hacksalot/HackMyResume", |   "homepage": "https://github.com/hacksalot/HackMyResume", | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "chalk": "^1.1.1", |     "chalk": "^1.1.1", | ||||||
|  |     "commander": "^2.9.0", | ||||||
|     "copy": "^0.1.3", |     "copy": "^0.1.3", | ||||||
|     "fresca": "~0.2.4", |     "fresca": "~0.2.4", | ||||||
|     "fresh-themes": "~0.9.3-beta", |     "fresh-themes": "~0.9.3-beta", | ||||||
|   | |||||||
| @@ -67,8 +67,7 @@ Error-handling routines for HackMyResume. | |||||||
|             break; |             break; | ||||||
|  |  | ||||||
|           case HACKMYSTATUS.invalidCommand: |           case HACKMYSTATUS.invalidCommand: | ||||||
|             msg = chalk.yellow('Please ') + chalk.yellow.bold('specify the output resume file') + |             msg = chalk.yellow('Invalid command: "') + chalk.yellow.bold(ex.attempted) + chalk.yellow('"'); | ||||||
|               chalk.yellow(' that should be created.'); |  | ||||||
|             break; |             break; | ||||||
|  |  | ||||||
|           case HACKMYSTATUS.resumeNotFoundAlt: |           case HACKMYSTATUS.resumeNotFoundAlt: | ||||||
| @@ -116,7 +115,7 @@ Error-handling routines for HackMyResume. | |||||||
|       } |       } | ||||||
|  |  | ||||||
|       // Let the error code be the process's return code. |       // Let the error code be the process's return code. | ||||||
|       if( shouldExit ) |       if( shouldExit || ex.shouldExit ) | ||||||
|         process.exit( exitCode ); |         process.exit( exitCode ); | ||||||
|  |  | ||||||
|     } |     } | ||||||
|   | |||||||
							
								
								
									
										182
									
								
								src/index.js
									
									
									
									
									
								
							
							
						
						
									
										182
									
								
								src/index.js
									
									
									
									
									
								
							| @@ -18,8 +18,9 @@ var SPAWNW = require('./core/spawn-watch') | |||||||
|   , HACKMYSTATUS = require('./core/status-codes') |   , HACKMYSTATUS = require('./core/status-codes') | ||||||
|   , opts = { } |   , opts = { } | ||||||
|   , title = chalk.white.bold('\n*** HackMyResume v' + PKG.version + ' ***') |   , title = chalk.white.bold('\n*** HackMyResume v' + PKG.version + ' ***') | ||||||
|   , _ = require('underscore'); |   , StringUtils = require('./utils/string.js') | ||||||
|  |   , _ = require('underscore') | ||||||
|  |   , Command = require('commander').Command; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -31,46 +32,175 @@ catch( ex ) { | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /** | ||||||
|  | Kick off the HackMyResume application. | ||||||
|  | */ | ||||||
| function main() { | function main() { | ||||||
|  |  | ||||||
|   // Setup |   var args = initialize(); | ||||||
|   var a = ARGS( process.argv.slice(2) ); |  | ||||||
|   if( a._.length === 0 ) { throw { fluenterror: 4 }; } |  | ||||||
|   opts = getOpts( a ); |  | ||||||
|   logMsg( title ); |  | ||||||
|  |  | ||||||
|   // Get the action to be performed |   function execCommand() { | ||||||
|   var params = a._.map( function(p){ return p.toLowerCase().trim(); }); |     var argsArray = Array.prototype.slice.call(arguments); | ||||||
|   var verb = opts.help ? 'help' : params[0]; |     //console.log(argsArray); | ||||||
|   if( !FCMD.verbs[ verb ] && !FCMD.alias[ verb ] ) { |     return FCMD.verbs[ this.name() ].apply( null, argsArray ); | ||||||
|     logMsg(chalk.yellow('Invalid command: "') + chalk.yellow.bold(verb) + chalk.yellow('"')); |  | ||||||
|     return; |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   // Create the top-level (application) command... | ||||||
|  |   var program = new Command('hackmyresume') | ||||||
|  |     .version(PKG.version) | ||||||
|  |     .description(chalk.yellow.bold('*** HackMyResume ***')) | ||||||
|  |     .option('-s, --silent', 'Run in silent mode.') | ||||||
|  |     .usage('COMMAND <sources> [TO <targets>]'); | ||||||
|  |  | ||||||
|  |   // Create the NEW command | ||||||
|  |   program | ||||||
|  |     .command('new') | ||||||
|  |     .arguments('<sources...>') | ||||||
|  |     .option('-f --format <fmt>', 'FRESH or JRS format', 'FRESH') | ||||||
|  |     .alias('create') | ||||||
|  |     .description('Create resume(s) in FRESH or JSON RESUME format.') | ||||||
|  |     .action(function( sources ) { | ||||||
|  |       execCommand.call( this, sources, [], this.opts(), logMsg ); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |   // Create the VALIDATE command | ||||||
|  |   program | ||||||
|  |     .command('validate') | ||||||
|  |     .arguments('<sources...>') | ||||||
|  |     .description('Validate a resume in FRESH or JSON RESUME format.') | ||||||
|  |     .action(function(sources) { | ||||||
|  |       execCommand.call(this, sources, [], this.opts(), logMsg); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |   // Create the CONVERT command | ||||||
|  |   program | ||||||
|  |     .command('convert') | ||||||
|  |     //.arguments('<sources...>') | ||||||
|  |     .description('Convert a resume to/from FRESH or JSON RESUME format.') | ||||||
|  |     .action(function() { | ||||||
|  |       var x = splitSrcDest.call( this ); | ||||||
|  |       execCommand.call( this, x.src, x.dst, this.opts(), logMsg ); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |   // Create the ANALYZE command | ||||||
|  |   program | ||||||
|  |     .command('analyze') | ||||||
|  |     .arguments('<sources...>') | ||||||
|  |     .description('Analyze one or more resumes.') | ||||||
|  |     .action(function() { | ||||||
|  |       execCommand.call(this, sources, [], this.opts(), logMsg); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |   // Create the BUILD command | ||||||
|  |   program | ||||||
|  |     .command('build') | ||||||
|  |     .alias('generate') | ||||||
|  |     //.arguments('<sources> TO [targets]') | ||||||
|  |     //.usage('...') | ||||||
|  |     .option('-t --theme <theme>', 'Theme name or path') | ||||||
|  |     .option('-p --prettify', 'Preffity HTML output.') | ||||||
|  |     .description('Generate resume to multiple formats') | ||||||
|  |     .action(function( sources, targets, options ) { | ||||||
|  |       var x = splitSrcDest.call( this ); | ||||||
|  |       execCommand.call( this, x.src, x.dst, opts, logMsg ); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |   // program.on('--help', function(){ | ||||||
|  |   //   console.log('  Examples:'); | ||||||
|  |   //   console.log(''); | ||||||
|  |   //   console.log('    $ custom-help --help'); | ||||||
|  |   //   console.log('    $ custom-help -h'); | ||||||
|  |   //   console.log(''); | ||||||
|  |   // }); | ||||||
|  |  | ||||||
|  |   program.parse( args ); | ||||||
|  |  | ||||||
|  |   if (!program.args.length) { throw { fluenterror: 4 }; } | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /** | ||||||
|  | Split multiple command-line filenames by the 'TO' keyword | ||||||
|  | */ | ||||||
|  | function splitSrcDest() { | ||||||
|  |  | ||||||
|  |   var params = this.parent.args.filter(function(j) { return String.is(j); }); | ||||||
|  |   if( params.length === 0 ) | ||||||
|  |     throw { fluenterror: HACKMYSTATUS.resumeNotFound }; | ||||||
|  |  | ||||||
|   // Find the TO keyword, if any |   // Find the TO keyword, if any | ||||||
|   var splitAt = _.indexOf( params, 'to' ); |   var splitAt = _.findIndex( params, function(p) { | ||||||
|   if( splitAt === a._.length - 1 && splitAt !== -1 ) { |     return p.toLowerCase() === 'to'; | ||||||
|     // 'TO' cannot be the last argument |   }); | ||||||
|     logMsg(chalk.yellow('Please ') + chalk.yellow.bold('specify an output file') + |  | ||||||
|       chalk.yellow(' for this operation or ') + chalk.yellow.bold('omit the TO keyword') + |   // TO can't be the last keyword | ||||||
|  |   if( splitAt === params.length - 1 && splitAt !== -1 ) { | ||||||
|  |     logMsg(chalk.yellow('Please ') + | ||||||
|  |       chalk.yellow.bold('specify an output file') + | ||||||
|  |       chalk.yellow(' for this operation or ') + | ||||||
|  |       chalk.yellow.bold('omit the TO keyword') + | ||||||
|       chalk.yellow('.') ); |       chalk.yellow('.') ); | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Massage inputs and outputs |   return { | ||||||
|   var src = a._.slice(1, splitAt === -1 ? undefined : splitAt ); |     src: params.slice(0, splitAt === -1 ? undefined : splitAt ), | ||||||
|   var dst = splitAt === -1 ? [] : a._.slice( splitAt + 1 ); |     dst: splitAt === -1 ? [] : params.slice( splitAt + 1 ) | ||||||
|  |   }; | ||||||
|   // Invoke the action |  | ||||||
|   (FCMD.verbs[verb] || FCMD.alias[verb]).apply(null, [src, dst, opts, logMsg]); |  | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /** | ||||||
|  | Massage command-line args and setup Commander.js. | ||||||
|  | */ | ||||||
|  | function initialize() { | ||||||
|  |  | ||||||
|  |   // Support case-insensitive sub-commands (build, generate, validate, etc.).. | ||||||
|  |   var oVerb, verb = '', args = process.argv.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(); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Handle invalid verbs here (a bit easier here than in commander.js)... | ||||||
|  |   if( !FCMD.verbs[ verb ] && !FCMD.alias[ verb ] ) { | ||||||
|  |     throw { fluenterror: HACKMYSTATUS.invalidCommand, shouldExit: true, | ||||||
|  |             attempted: oVerb }; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Override the .missingArgument behavior | ||||||
|  |   Command.prototype.missingArgument = function(name) { | ||||||
|  |     throw { fluenterror: HACKMYSTATUS.resumeNotFound }; | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   // Override the .helpInformation behavior | ||||||
|  |   Command.prototype.helpInformation = function() { | ||||||
|  |     var manPage = FS.readFileSync( PATH.join(__dirname, 'use.txt'), 'utf8' ); | ||||||
|  |     return chalk.green.bold(manPage); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   return args; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /** | ||||||
|  | Simple logging placeholder. | ||||||
|  | */ | ||||||
| function logMsg( msg ) { | function logMsg( msg ) { | ||||||
|   opts.silent || console.log( msg ); |   opts.silent || console.log( msg ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /** | ||||||
|  | Fetch options from command line arguments. | ||||||
|  | */ | ||||||
| function getOpts( args ) { | function getOpts( args ) { | ||||||
|   var noPretty = args.nopretty || args.n; |   var noPretty = args.nopretty || args.n; | ||||||
|   noPretty = noPretty && (noPretty === true || noPretty === 'true'); |   noPretty = noPretty && (noPretty === true || noPretty === 'true'); | ||||||
|   | |||||||
| @@ -11,7 +11,8 @@ Implementation of the 'convert' verb for HackMyResume. | |||||||
|  |  | ||||||
|  |  | ||||||
|   var ResumeFactory = require('../core/resume-factory') |   var ResumeFactory = require('../core/resume-factory') | ||||||
|     , chalk = require('chalk'); |     , chalk = require('chalk') | ||||||
|  |     , HACKMYSTATUS = require('../core/status-codes'); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -24,12 +25,19 @@ Implementation of the 'convert' verb for HackMyResume. | |||||||
|     var _log = logger || console.log; |     var _log = logger || console.log; | ||||||
|     if( !srcs || !srcs.length ) { throw { fluenterror: 6 }; } |     if( !srcs || !srcs.length ) { throw { fluenterror: 6 }; } | ||||||
|     if( !dst || !dst.length ) { |     if( !dst || !dst.length ) { | ||||||
|       if( srcs.length === 1 ) { throw { fluenterror: 5 }; } |       if( srcs.length === 1 ) { | ||||||
|       else if( srcs.length === 2 ) { dst = dst || []; dst.push( srcs.pop() ); } |         throw { fluenterror: HACKMYSTATUS.inputOutputParity }; | ||||||
|       else { throw { fluenterror: 5 }; } |       } | ||||||
|  |       else if( srcs.length === 2 ) { | ||||||
|  |         dst = dst || []; dst.push( srcs.pop() ); | ||||||
|  |       } | ||||||
|  |       else { | ||||||
|  |         throw { fluenterror: HACKMYSTATUS.inputOutputParity }; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     if(srcs && dst && srcs.length && dst.length && srcs.length !== dst.length){ | ||||||
|  |       throw { fluenterror: HACKMYSTATUS.inputOutputParity }; | ||||||
|     } |     } | ||||||
|     if( srcs && dst && srcs.length && dst.length && |  | ||||||
|         srcs.length !== dst.length ) { throw { fluenterror: 7 }; } |  | ||||||
|  |  | ||||||
|     // Load source resumes |     // Load source resumes | ||||||
|     srcs.forEach( function( src, idx ) { |     srcs.forEach( function( src, idx ) { | ||||||
| @@ -46,7 +54,7 @@ Implementation of the 'convert' verb for HackMyResume. | |||||||
|  |  | ||||||
|       // TODO: Core should not log |       // TODO: Core should not log | ||||||
|       _log( chalk.green('Converting ') + chalk.green.bold(rinfo.file) + |       _log( chalk.green('Converting ') + chalk.green.bold(rinfo.file) + | ||||||
|         chalk.green(' (' + srcFmt + ') to ') + chalk.green.bold(dst[0]) + |         chalk.green(' (' + srcFmt + ') to ') + chalk.green.bold(dst[idx]) + | ||||||
|         chalk.green(' (' + targetFormat + ').')); |         chalk.green(' (' + targetFormat + ').')); | ||||||
|  |  | ||||||
|       // Save it to the destination format |       // Save it to the destination format | ||||||
|   | |||||||
| @@ -15,6 +15,7 @@ Implementation of the 'create' verb for HackMyResume. | |||||||
|   Create a new empty resume in either FRESH or JRS format. |   Create a new empty resume in either FRESH or JRS format. | ||||||
|   */ |   */ | ||||||
|   module.exports = function create( src, dst, opts, logger ) { |   module.exports = function create( src, dst, opts, logger ) { | ||||||
|  |     //console.log(src); | ||||||
|     var _log = logger || console.log; |     var _log = logger || console.log; | ||||||
|     if( !src || !src.length ) throw { fluenterror: 8 }; |     if( !src || !src.length ) throw { fluenterror: 8 }; | ||||||
|     src.forEach( function( t ) { |     src.forEach( function( t ) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user