<commit_before>package t9.remoting.jsonrpc.cli;

import haxe.remoting.JsonRpc;
import js.npm.Commander;

using Lambda;
using StringTools;

class CommanderTools
{
	public static function parseCliArgs(definitions :Array<RemoteMethodDefinition>) :RequestDef
	{
		var program :Commander = js.Node.require('commander');
		var requestDef :RequestDef = null;

		addCommands(program, definitions, function(def) {
			requestDef = def;
		});
		if (js.Node.process.argv.slice(2).length == 0) {
			program.outputHelp();
		} else {
			program.parse(js.Node.process.argv);
		}

		return requestDef;
	}

	public static function addCommands(program :Commander, definitions :Array<RemoteMethodDefinition>, jsonrpcCallback :RequestDef->Void)
	{
		for (definition in definitions) {
			var commandName = definition.alias != null ? definition.alias : definition.method;
			var nonOptionalArgs = definition.args.filter(function(v) return !v.optional);
			for (i in 0...nonOptionalArgs.length) {
				var arg = nonOptionalArgs[i];
				commandName += ' [${arg.name}]';
				if (i == (nonOptionalArgs.length - 1) && arg.type.startsWith('Array<')) {
					//Last argument can be variadic
					commandName += ' [more${arg.name}...]';
				}
			}
			var command = program.command(commandName);
			command.description(definition.doc);
			for (arg in definition.args.filter(function(v) return v.optional)) {
				var optionalArgString = '--${arg.name} [${arg.name}]';
				if (arg.short != null) {
					optionalArgString = '-${arg.short}, ' + optionalArgString;
				}

				if (arg.type.startsWith('Array<')) {
					var collectedVal = [];

					command.option(optionalArgString, arg.doc, function(val, memo) {trace('val=$val'); memo.push(val); return memo;}, []);
				} else {
					command.option(optionalArgString, arg.doc, getConverter(arg.type));
				}
			}

			command.action(function(arg1 :Dynamic, arg2 :Dynamic, arg3 :Dynamic, arg4 :Dynamic, arg5 :Dynamic, arg6 :Dynamic, arg7 :Dynamic, arg8 :Dynamic, arg9 :Dynamic, arg10 :Dynamic, arg11 :Dynamic) {
				var arguments :Array<Dynamic> = untyped __js__('Array.prototype.slice.call(arguments)');
				arguments.pop();
				var request :RequestDef = {
					id: JsonRpcConstants.JSONRPC_NULL_ID,
					jsonrpc: JsonRpcConstants.JSONRPC_VERSION_2,
					method: definition.alias != null ? definition.alias : definition.method,
					params: {}
				}
				var requiredArgs = definition.args.filter(function(v) return !v.optional).array();
				var optionalArgs = definition.args.filter(function(v) return v.optional).array();
				for (i in 0...requiredArgs.length) {
					var arg = requiredArgs[i];
					var converter = getConverter(arg.type);
					if (arg.type.startsWith('Array<') && i == (requiredArgs.length - 1) && arguments[i + 1] != null) {
						var arrArgs :Array<Dynamic> = arguments[i + 1];
						if (arguments[i] != null) {
							arrArgs.unshift(arguments[i]);
						}
						Reflect.setField(request.params, arg.name, arrArgs.map(converter));
					} else {
						Reflect.setField(request.params, arg.name, converter(arguments[i]));
					}
				}
				for (arg in optionalArgs) {
					if (Reflect.hasField(command, arg.name)) {
						Reflect.setField(request.params, arg.name, Reflect.field(command, arg.name));
					}
				}
				jsonrpcCallback(request);
			});
			if (definition.docCustom != null) {
				command.on('--help', function() {
					js.Node.process.stdout.write(definition.docCustom + '\n');
				});
			}
		}
	}

	static function getConverter(type :String) :Dynamic->Dynamic
	{
		if (type.startsWith('Array<')) {
			type = type.replace('Array<', '').replace('>', '');
		}
		return switch(type) {
			case 'Int': Std.parseInt;
			case 'Float': Std.parseFloat;
			case 'Bool': function(val) {
				var s = val + '';
				return s == 'true' || s == 'True' || s == 'TRUE' || s == '1';
			}
			default: function(v) return v;
		}<commit_msg>Minor tweak<commit_after>package t9.remoting.jsonrpc.cli;

import haxe.remoting.JsonRpc;
import js.npm.Commander;

using Lambda;
using StringTools;

class CommanderTools
{
	public static function parseCliArgs(definitions :Array<RemoteMethodDefinition>) :RequestDef
	{
		var program :Commander = js.Node.require('commander');
		var requestDef :RequestDef = null;

		addCommands(program, definitions, function(def) {
			requestDef = def;
		});
		if (js.Node.process.argv.slice(2).length == 0) {
			program.outputHelp();
		} else {
			program.parse(js.Node.process.argv);
		}

		return requestDef;
	}

	public static function addCommands(program :Commander, definitions :Array<RemoteMethodDefinition>, jsonrpcCallback :RequestDef->Void)
	{
		for (definition in definitions) {
			addCommand(program, definition, jsonrpcCallback);
		}
	}

	public static function addCommand(program :Commander, definition :RemoteMethodDefinition, jsonrpcCallback :RequestDef->Void)
	{
		var commandName = definition.alias != null ? definition.alias : definition.method;
		var nonOptionalArgs = definition.args.filter(function(v) return !v.optional);
		for (i in 0...nonOptionalArgs.length) {
			var arg = nonOptionalArgs[i];
			commandName += ' [${arg.name}]';
			if (i == (nonOptionalArgs.length - 1) && arg.type.startsWith('Array<')) {
				//Last argument can be variadic
				commandName += ' [more${arg.name}...]';
			}
		}
		var command = program.command(commandName);
		command.description(definition.doc);
		for (arg in definition.args.filter(function(v) return v.optional)) {
			var optionalArgString = '--${arg.name} [${arg.name}]';
			if (arg.short != null) {
				optionalArgString = '-${arg.short}, ' + optionalArgString;
			}

			if (arg.type.startsWith('Array<')) {
				var collectedVal = [];

				command.option(optionalArgString, arg.doc, function(val, memo) {trace('val=$val'); memo.push(val); return memo;}, []);
			} else {
				command.option(optionalArgString, arg.doc, getConverter(arg.type));
			}
		}

		command.action(function(arg1 :Dynamic, arg2 :Dynamic, arg3 :Dynamic, arg4 :Dynamic, arg5 :Dynamic, arg6 :Dynamic, arg7 :Dynamic, arg8 :Dynamic, arg9 :Dynamic, arg10 :Dynamic, arg11 :Dynamic) {
			var arguments :Array<Dynamic> = untyped __js__('Array.prototype.slice.call(arguments)');
			arguments.pop();
			var request :RequestDef = {
				id: JsonRpcConstants.JSONRPC_NULL_ID,
				jsonrpc: JsonRpcConstants.JSONRPC_VERSION_2,
				method: definition.alias != null ? definition.alias : definition.method,
				params: {}
			}
			var requiredArgs = definition.args.filter(function(v) return !v.optional).array();
			var optionalArgs = definition.args.filter(function(v) return v.optional).array();
			for (i in 0...requiredArgs.length) {
				var arg = requiredArgs[i];
				var converter = getConverter(arg.type);
				if (arg.type.startsWith('Array<') && i == (requiredArgs.length - 1) && arguments[i + 1] != null) {
					var arrArgs :Array<Dynamic> = arguments[i + 1];
					if (arguments[i] != null) {
						arrArgs.unshift(arguments[i]);
					}
					Reflect.setField(request.params, arg.name, arrArgs.map(converter));
				} else {
					Reflect.setField(request.params, arg.name, converter(arguments[i]));
				}
			}
			for (arg in optionalArgs) {
				if (Reflect.hasField(command, arg.name)) {
					Reflect.setField(request.params, arg.name, Reflect.field(command, arg.name));
				}
			}
			jsonrpcCallback(request);
		});
		if (definition.docCustom != null) {
			command.on('--help', function() {
				js.Node.process.stdout.write(definition.docCustom + '\n');
			});
		}
	}

	static function getConverter(type :String) :Dynamic->Dynamic
	{
		if (type.startsWith('Array<')) {
			type = type.replace('Array<', '').replace('>', '');
		}
		return switch(type) {
			case 'Int': Std.parseInt;
			case 'Float': Std.parseFloat;
			case 'Bool': function(val) {
				var s = val + '';
				return s == 'true' || s == 'True' || s == 'TRUE' || s == '1';
			}
			default: function(v) return v;
		}
{'fraction_non_alphanumeric': 0.1580826109127996, 'fraction_numerical': 0.006119326874043855, 'mean_word_length': 3.812883435582822, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 18, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1455336', 'n_tokens_mistral': 2966, 'n_tokens_neox': 2515, 'n_words': 535}