mirror of
				https://github.com/flynx/argv.js.git
				synced 2025-10-31 03:30:08 +00:00 
			
		
		
		
	added better error reporting and exceptions...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
		
							parent
							
								
									241c259da0
								
							
						
					
					
						commit
						09be10556f
					
				
							
								
								
									
										27
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								README.md
									
									
									
									
									
								
							| @ -54,6 +54,8 @@ This code is an evolution of that parser. | |||||||
| 	- [Contents](#contents) | 	- [Contents](#contents) | ||||||
| 	- [Installation](#installation) | 	- [Installation](#installation) | ||||||
| 	- [Basic usage](#basic-usage) | 	- [Basic usage](#basic-usage) | ||||||
|  | 	- [Error reporting](#error-reporting) | ||||||
|  | 	- [XXX add subsections by task](#xxx-add-subsections-by-task) | ||||||
| 	- [Configuration](#configuration) | 	- [Configuration](#configuration) | ||||||
| 		- [Option/command configuration](#optioncommand-configuration) | 		- [Option/command configuration](#optioncommand-configuration) | ||||||
| 			- [`<option>.handler(..)`](#optionhandler) | 			- [`<option>.handler(..)`](#optionhandler) | ||||||
| @ -83,10 +85,11 @@ This code is an evolution of that parser. | |||||||
| 		- [Nested parsers](#nested-parsers) | 		- [Nested parsers](#nested-parsers) | ||||||
| 	- [Components and API](#components-and-api) | 	- [Components and API](#components-and-api) | ||||||
| 		- [`THEN`, `STOP` and `ERROR`](#then-stop-and-error) | 		- [`THEN`, `STOP` and `ERROR`](#then-stop-and-error) | ||||||
|  | 		- [`ParserError(..)`](#parsererror) | ||||||
| 		- [`Parser(..)`](#parser) | 		- [`Parser(..)`](#parser) | ||||||
| 			- [`<parser>.then(..)`](#parserthen) | 			- [`<parser>.then(..)`](#parserthen) | ||||||
| 			- [`<parser>.stop(..)`](#parserstop) | 			- [`<parser>.stop(..)`](#parserstop) | ||||||
| 			- [`<parser>.error(..)`](#parsererror) | 			- [`<parser>.error(..)`](#parsererror-1) | ||||||
| 			- [`<parser>.off(..)`](#parseroff) | 			- [`<parser>.off(..)`](#parseroff) | ||||||
| 			- [`<parser>(..)`](#parser-1) | 			- [`<parser>(..)`](#parser-1) | ||||||
| 	- [Advanced parser API](#advanced-parser-api) | 	- [Advanced parser API](#advanced-parser-api) | ||||||
| @ -228,6 +231,17 @@ $ ./script.js -fb | |||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
|  | ## Error reporting | ||||||
|  | 
 | ||||||
|  | XXX | ||||||
|  | 
 | ||||||
|  | ## XXX add subsections by task | ||||||
|  | 
 | ||||||
|  | XXX | ||||||
|  | 
 | ||||||
|  | XXX might be a good idea to split out the rest to a INDETAIL.md or similar... | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| ## Configuration | ## Configuration | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
| @ -687,6 +701,17 @@ Values that if returned by option/command handlers can control the parse flow. | |||||||
| - `ERROR` – Stop parsing, call `<parser>.error(..)` callbacks and | - `ERROR` – Stop parsing, call `<parser>.error(..)` callbacks and | ||||||
|   exit with an error. |   exit with an error. | ||||||
| 
 | 
 | ||||||
|  | ### `ParserError(..)`  | ||||||
|  | 
 | ||||||
|  | A base error constructor, if an instance of `ParseError` is thrown by the  | ||||||
|  | handler it has the same effect as returning `ERROR` with one difference being | ||||||
|  | that the error `.name`/`.message` will get printed. | ||||||
|  | 
 | ||||||
|  | The following error constructors are also defined: | ||||||
|  | - `ParserTypeError(..)` | ||||||
|  | - `ParserValueError(..)` | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| ### `Parser(..)`  | ### `Parser(..)`  | ||||||
| 
 | 
 | ||||||
| Construct a parser instance | Construct a parser instance | ||||||
|  | |||||||
							
								
								
									
										43
									
								
								argv.js
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								argv.js
									
									
									
									
									
								
							| @ -37,6 +37,18 @@ module.ERROR = | |||||||
| 	{doc: 'option processing error, triggers .error(..) handlers'} | 	{doc: 'option processing error, triggers .error(..) handlers'} | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | module.ParserError =  | ||||||
|  | 	object.Constructor('ParserError', Error, { | ||||||
|  | 		// NOTE: I do not get why JavaScript's Error implements this 
 | ||||||
|  | 		// 		statically...
 | ||||||
|  | 		get name(){ | ||||||
|  | 			return this.constructor.name }, }) | ||||||
|  | module.ParserTypeError =  | ||||||
|  | 	object.Constructor('ParserTypeError', module.ParserError, {}) | ||||||
|  | module.ParserValueError =  | ||||||
|  | 	object.Constructor('ParserValueError', module.ParserError, {}) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| //---------------------------------------------------------------------
 | //---------------------------------------------------------------------
 | ||||||
| // Helpers...
 | // Helpers...
 | ||||||
| @ -215,20 +227,18 @@ function(name, pre, post){ | |||||||
| // 		will think about it when we need this feature more than once...
 | // 		will think about it when we need this feature more than once...
 | ||||||
| //
 | //
 | ||||||
| // XXX should type handlers produce errors???
 | // XXX should type handlers produce errors???
 | ||||||
| // XXX add support for ParserError exception handling...
 |  | ||||||
| // XXX should -help work for any command? ..not just nested parsers?
 | // XXX should -help work for any command? ..not just nested parsers?
 | ||||||
| // 		...should we indicate which thinks have more "-help"??
 | // 		...should we indicate which thinks have more "-help"??
 | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| var Parser = | var Parser = | ||||||
| module.Parser = | module.Parser = | ||||||
| object.Constructor('Parser', { | object.Constructor('Parser', { | ||||||
| 	// Signature:
 |  | ||||||
| 	//
 | 	//
 | ||||||
| 	// 	handler(value, ...options)
 | 	// 	handler(value, ...options)
 | ||||||
| 	// 		-> value
 | 	// 		-> value
 | ||||||
| 	//
 | 	//
 | ||||||
|  | 	// NOTE: options are passed to the definition in the option handler, 
 | ||||||
|  | 	// 		i.e. the list of values separated by '|' after the type 
 | ||||||
|  | 	// 		definition.
 | ||||||
| 	typeHandlers: { | 	typeHandlers: { | ||||||
| 		string: function(v){ return v.toString() }, | 		string: function(v){ return v.toString() }, | ||||||
| 		bool: function(v){ return !!v }, | 		bool: function(v){ return !!v }, | ||||||
| @ -242,11 +252,11 @@ object.Constructor('Parser', { | |||||||
| 				.map(function(e){ return e.trim() }) }, | 				.map(function(e){ return e.trim() }) }, | ||||||
| 	}, | 	}, | ||||||
| 
 | 
 | ||||||
| 	// Signature:
 |  | ||||||
| 	// 
 | 	// 
 | ||||||
| 	// 	handler(value, stored_value, key, ...options)
 | 	// 	handler(value, stored_value, key, ...options)
 | ||||||
| 	// 		-> stored_value
 | 	// 		-> stored_value
 | ||||||
| 	//
 | 	//
 | ||||||
|  | 	// For more info see docs for .typeHandlers
 | ||||||
| 	valueCollectors: { | 	valueCollectors: { | ||||||
| 		// format: 'string' | 'string|<separator>'
 | 		// format: 'string' | 'string|<separator>'
 | ||||||
| 		string: function(v, cur, _, sep){  | 		string: function(v, cur, _, sep){  | ||||||
| @ -290,7 +300,6 @@ object.Constructor('Parser', { | |||||||
| 	// 		...
 | 	// 		...
 | ||||||
| 	// 	]
 | 	// 	]
 | ||||||
| 	//
 | 	//
 | ||||||
| 	// XXX do we need to output <doc> here???
 |  | ||||||
| 	options: function(...prefix){ | 	options: function(...prefix){ | ||||||
| 		var that = this | 		var that = this | ||||||
| 		prefix = prefix.length == 0 ? | 		prefix = prefix.length == 0 ? | ||||||
| @ -824,6 +833,9 @@ object.Constructor('Parser', { | |||||||
| 
 | 
 | ||||||
| 		// helpers...
 | 		// helpers...
 | ||||||
| 		var handleError = function(reason, arg, rest){ | 		var handleError = function(reason, arg, rest){ | ||||||
|  | 			reason = reason instanceof Error ? | ||||||
|  | 				[reason.name, reason.message].join(': ') | ||||||
|  | 				: reason | ||||||
| 			parsed.error(reason, arg, rest) | 			parsed.error(reason, arg, rest) | ||||||
| 			parsed.handleErrorExit | 			parsed.handleErrorExit | ||||||
| 				&& parsed.handleErrorExit(arg, reason) } | 				&& parsed.handleErrorExit(arg, reason) } | ||||||
| @ -851,11 +863,24 @@ object.Constructor('Parser', { | |||||||
| 				parsed.printError('value missing:', arg+'=?') | 				parsed.printError('value missing:', arg+'=?') | ||||||
| 				return module.ERROR } | 				return module.ERROR } | ||||||
| 
 | 
 | ||||||
|  | 			try { | ||||||
| 				// run handler...
 | 				// run handler...
 | ||||||
| 				var res = parsed.handle(handler, rest, arg, value) | 				var res = parsed.handle(handler, rest, arg, value) | ||||||
| 
 | 
 | ||||||
|  | 			} catch(err){ | ||||||
|  | 				// re-throw the error...
 | ||||||
|  | 				// NOTE: do not like that this can mask the location of 
 | ||||||
|  | 				// 		the original error.
 | ||||||
|  | 				if(!(err instanceof module.ParserError)){ | ||||||
|  | 					throw err }  | ||||||
|  | 				res = err } | ||||||
|  | 
 | ||||||
|  | 			// NOTE: we also need to handle the errors passed to us from 
 | ||||||
|  | 			// 		nested parsers...
 | ||||||
| 			res === module.STOP | 			res === module.STOP | ||||||
| 				&& parsed.stop(arg, rest) | 				&& parsed.stop(arg, rest) | ||||||
|  | 			res instanceof module.ParserError | ||||||
|  | 				&& handleError(res, arg, rest) | ||||||
| 			res === module.ERROR | 			res === module.ERROR | ||||||
| 				&& handleError('unknown', arg, rest) | 				&& handleError('unknown', arg, rest) | ||||||
| 			return res } | 			return res } | ||||||
| @ -924,7 +949,9 @@ object.Constructor('Parser', { | |||||||
| 				var res = runHandler(handler, arg, rest) | 				var res = runHandler(handler, arg, rest) | ||||||
| 
 | 
 | ||||||
| 				// handle stop conditions...
 | 				// handle stop conditions...
 | ||||||
| 				if(res === module.STOP || res === module.ERROR){ | 				if(res === module.STOP  | ||||||
|  | 						|| res === module.ERROR  | ||||||
|  | 						|| res instanceof module.ParserError){ | ||||||
| 					return nested ? | 					return nested ? | ||||||
| 						res | 						res | ||||||
| 						: parsed } | 						: parsed } | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|   "name": "ig-argv", |   "name": "ig-argv", | ||||||
|   "version": "2.4.2", |   "version": "2.5.0", | ||||||
|   "description": "simple argv parser", |   "description": "simple argv parser", | ||||||
|   "main": "argv.js", |   "main": "argv.js", | ||||||
|   "scripts": { |   "scripts": { | ||||||
|  | |||||||
							
								
								
									
										13
									
								
								test.js
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								test.js
									
									
									
									
									
								
							| @ -17,6 +17,10 @@ var argv = require('./argv') | |||||||
| //---------------------------------------------------------------------
 | //---------------------------------------------------------------------
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | argv.Parser.typeHandlers.error = function(){ | ||||||
|  | 	throw new argv.ParserTypeError('type error') } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| var p =  | var p =  | ||||||
| module.p = | module.p = | ||||||
| argv.Parser({ | argv.Parser({ | ||||||
| @ -79,6 +83,15 @@ argv.Parser({ | |||||||
| 		'-sh': { | 		'-sh': { | ||||||
| 			doc: 'short option', }, | 			doc: 'short option', }, | ||||||
| 
 | 
 | ||||||
|  | 		'-type-error': { | ||||||
|  | 			doc: 'throw an type error', | ||||||
|  | 			type: 'error',  | ||||||
|  | 		}, | ||||||
|  | 		'-error': { | ||||||
|  | 			doc: 'throw an error', | ||||||
|  | 			handler: function(){ | ||||||
|  | 				throw argv.ParserError('error') }}, | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| 		'-test': argv.Parser({ | 		'-test': argv.Parser({ | ||||||
| 			env: 'TEST', | 			env: 'TEST', | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user