public void Add(CommandSpecification comSpec) { if (_syntaxes.TryGetValue(comSpec.Name, out var lst)) { lst.Add(new CommandSyntax(comSpec)); } else { _syntaxes.Add(comSpec.Name, new List <CommandSyntax> { new CommandSyntax(comSpec) }); } }
public ParseError( string description, int position, int index, CommandSpecification commandSpecification, IList <CommandParameterSpecification> commandParameterSpecifications ) { Description = description; Position = position; Index = index; CommandSpecification = commandSpecification; CommandParameterSpecifications = new ReadOnlyCollection <CommandParameterSpecification>(commandParameterSpecifications); }
public void Remove(CommandSpecification comSpec) { if (_syntaxes.TryGetValue(comSpec.Name, out var lst)) { var sytx = lst.Where(x => x.CommandSpecification == comSpec).FirstOrDefault(); if (sytx != null) { lst.Remove(sytx); if (lst.Count == 0) { _syntaxes.Remove(comSpec.Name); } } } }
public bool UnregisterCommand(CommandSpecification comSpec) { if (_commands.TryGetValue(comSpec.Name, out var cmdLst)) { var r = cmdLst.Remove(comSpec); if (r) { _syntaxAnalyzer.Remove(comSpec); } if (cmdLst.Count == 0) { _commands.Remove(comSpec.Name); } return(r); } return(false); }
void PrintCommandHelp( CommandEvaluationContext context, CommandSpecification com, bool shortView = false, bool list = false, int maxcnamelength = -1, int maxcmdtypelength = -1, int maxmodlength = -1, bool singleout = false) { #pragma warning disable IDE0071 // Simplifier l’interpolation #pragma warning disable IDE0071WithoutSuggestion // Simplifier l’interpolation if (maxcnamelength == -1) { maxcnamelength = com.Name.Length + 1; } if (maxcmdtypelength == -1) { maxcmdtypelength = com.DeclaringTypeShortName.Length + 1; } var col = singleout? "": "".PadRight(maxcnamelength, ' '); var f = GetCmd(EchoDirectives.f + "", DefaultForeground.ToString().ToLower()); if (list) { if (!shortView) { context.Out.Echoln($"{Darkcyan}{com.ModuleName.PadRight(maxmodlength, ' ')} {com.DeclaringTypeShortName.PadRight(maxcmdtypelength, ' ')}{Tab}{ColorSettings.Highlight}{com.Name.PadRight(maxcnamelength, ' ')}{Tab}{f}{com.Description}{ColorSettings.Default}"); } else { context.Out.Echoln($"{ColorSettings.Highlight}{com.Name.PadRight(maxcnamelength, ' ')}{f}{Tab}{com.Description}{ColorSettings.Default}"); } } else { if (singleout) { context.Out.Echoln(com.Description); if (com.ParametersCount > 0) { context.Out.Echo($"{Br}{col}{ColorSettings.Label}syntax: {f}{com.ToColorizedString()}{(!shortView ? Br : "")}"); } context.Out.Echoln(GetPrintableDocText(com.LongDescription, list, shortView, 0)); } else { context.Out.Echoln($"{com.Name.PadRight(maxcnamelength, ' ')}{com.Description}"); if (com.ParametersCount > 0) { context.Out.Echo($"{Br}{col}{ColorSettings.Label}syntax: {f}{com.ToColorizedString()}{(!shortView ? Br : "")}"); } context.Out.Echo(GetPrintableDocText(com.LongDescription, list, shortView, maxcnamelength)); } } if (!list) { if (com.ParametersCount > 0) { if (!shortView) { var mpl = com.ParametersSpecifications.Values.Select(x => x.Dump(false).Length).Max() + TabLength; foreach (var p in com.ParametersSpecifications.Values) { var ptype = (!p.IsOption && p.HasValue) ? $"of type: {Darkyellow}{p.ParameterInfo.ParameterType.Name}{f}" : ""; var pdef = (p.HasValue && p.IsOptional && p.HasDefaultValue && p.DefaultValue != null && (!p.IsOption || p.ParameterValueTypeName != typeof(bool).Name)) ? ((ptype != ""?". ":"") + $"default value: {Darkyellow}{DumpAsText(p.DefaultValue)}{f}") : ""; var supdef = $"{ptype}{pdef}"; context.Out.Echoln($"{col}{Tab}{p.ToColorizedString(false)}{"".PadRight(mpl - p.Dump(false).Length, ' ')}{p.Description}"); if (!string.IsNullOrWhiteSpace(supdef)) { context.Out.Echoln($"{col}{Tab}{" ".PadRight(mpl)}{supdef}"); } } if (string.IsNullOrWhiteSpace(com.Documentation)) { context.Out.Echoln(); } context.Out.Echo(GetPrintableDocText(com.Documentation, list, shortView, singleout ? 0 : maxcnamelength)); } else { context.Out.Echoln(GetPrintableDocText(com.Documentation, list, shortView, singleout ? 0 : maxcnamelength)); } } if (!shortView) { context.Out.Echoln($"{col}{ColorSettings.Label}type : {ColorSettings.DarkLabel}{com.DeclaringTypeShortName}"); context.Out.Echoln($"{col}{ColorSettings.Label}module: {ColorSettings.DarkLabel}{com.ModuleName}{ColorSettings.Default}"); } } #pragma warning restore IDE0071WithoutSuggestion // Simplifier l’interpolation #pragma warning restore IDE0071 // Simplifier l’interpolation }
public int RegisterCommandClass( CommandEvaluationContext context, Type type, bool registerAsModule ) { if (type.GetInterface(typeof(ICommandsDeclaringType).FullName) == null) { throw new Exception($"the type '{type.FullName}' must implements interface '{typeof(ICommandsDeclaringType).FullName}' to be registered as a command class"); } var dtNamespaceAttr = type.GetCustomAttribute <CommandsNamespaceAttribute>(); var dtNamespace = (dtNamespaceAttr == null) ? "" : CheckAndNormalizeCommandNamespace(dtNamespaceAttr.Segments); var comsCount = 0; object instance = Activator.CreateInstance(type, new object[] { }); var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); if (registerAsModule && _modules.ContainsKey(type.FullName)) { context.Errorln($"a module with same name than the commands declaring type '{type.FullName}' is already registered"); return(0); } foreach (var method in methods) { var cmd = method.GetCustomAttribute <CommandAttribute>(); if (cmd != null) { if (!method.ReturnType.HasInterface(typeof(ICommandResult))) { context.Errorln($"class={type.FullName} method={method.Name} wrong return type. should be of type '{typeof(ICommandResult).FullName}', but is of type: {method.ReturnType.FullName}"); } else { // ⏺ build the command specification from the method meta-data var cmdNamespaceAttr = method.GetCustomAttribute <CommandNamespaceAttribute>(); var cmdNamespace = cmdNamespaceAttr == null ? dtNamespace : CheckAndNormalizeCommandNamespace(cmdNamespaceAttr.Segments); var cmdAliasesAttrLst = method.GetCustomAttributes <CommandAliasAttribute>(); var cmdAliases = cmdAliasesAttrLst?.Select(x => (x.AliasName, x.AliasText)).ToList(); if (cmdAliases.Count == 0) { cmdAliases = null; // convention } #region init from method parameters attributes var paramspecs = new List <CommandParameterSpecification>(); bool syntaxError = false; var pindex = 0; foreach (var parameter in method.GetParameters()) { if (pindex == 0) { // manadatory: param 0 is CommandEvaluationContext if (parameter.ParameterType != typeof(CommandEvaluationContext)) { context.Errorln($"class={type.FullName} method={method.Name} parameter 0 ('{parameter.Name}') should be of type '{typeof(CommandEvaluationContext).FullName}', but is of type: {parameter.ParameterType.FullName}"); syntaxError = true; break; } } else { CommandParameterSpecification pspec = null; object defval = null; if (!parameter.HasDefaultValue && parameter.ParameterType.IsValueType) { defval = Activator.CreateInstance(parameter.ParameterType); } // param var paramAttr = parameter.GetCustomAttribute <ParameterAttribute>(); if (paramAttr != null) { // TODO: validate command specification (eg. indexs validity) pspec = new CommandParameterSpecification( parameter.Name, paramAttr.Description, paramAttr.IsOptional, paramAttr.Index, null, null, true, parameter.HasDefaultValue, paramAttr.HasDefaultValue ? paramAttr.DefaultValue : ((parameter.HasDefaultValue) ? parameter.DefaultValue : defval), parameter); } // option var optAttr = parameter.GetCustomAttribute <OptionAttribute>(); if (optAttr != null) { var reqParamAttr = parameter.GetCustomAttribute <OptionRequireParameterAttribute>(); try { pspec = new CommandParameterSpecification( parameter.Name, optAttr.Description, optAttr.IsOptional, -1, optAttr.OptionName /*?? parameter.Name*/, optAttr.OptionLongName, optAttr.HasValue, parameter.HasDefaultValue, optAttr.HasDefaultValue ? optAttr.DefaultValue : ((parameter.HasDefaultValue) ? parameter.DefaultValue : defval), parameter, reqParamAttr?.RequiredParameterName); } catch (Exception ex) { context.Errorln(ex.Message); } } if (pspec == null) { syntaxError = true; context.Errorln($"invalid parameter: class={type.FullName} method={method.Name} name={parameter.Name}"); } else { paramspecs.Add(pspec); } } pindex++; } #endregion if (!syntaxError) { var cmdNameAttr = method.GetCustomAttribute <CommandNameAttribute>(); var cmdName = CheckAndNormalizeCommandName( (cmdNameAttr != null && cmdNameAttr.Name != null) ? cmdNameAttr.Name : (cmd.Name ?? method.Name)); bool registered = true; CommandSpecification cmdspec = null; try { cmdspec = new CommandSpecification( cmdNamespace, cmdName, cmd.Description, cmd.LongDescription, cmd.Documentation, method, instance, cmdAliases, paramspecs); } catch (Exception ex) { context.Errorln($"error in command '{cmdName}' specification: {ex.Message}"); } if (cmdspec != null) { if (_commands.TryGetValue(cmdspec.Name, out var cmdlst)) { if (cmdlst.Select(x => x.MethodInfo.DeclaringType == type).Any()) { context.Errorln($"command already registered: '{cmdspec.Name}' in type '{cmdspec.DeclaringTypeFullName}'"); registered = false; } else { cmdlst.Add(cmdspec); } } else { _commands.Add(cmdspec.Name, new List <CommandSpecification> { cmdspec }); } if (registered) { _syntaxAnalyzer.Add(cmdspec); comsCount++; // register command Aliases if (cmdspec.Aliases != null) { foreach (var alias in cmdspec.Aliases) { context.CommandLineProcessor.CommandsAlias.AddOrReplaceAlias( context, alias.name, alias.text ); } } } } } } } } if (registerAsModule) { if (comsCount == 0) { context.Errorln($"no commands found in type '{type.FullName}'"); } else { var descAttr = type.GetCustomAttribute <CommandsAttribute>(); var description = descAttr != null ? descAttr.Description : ""; _modules.Add( type.FullName, // key not from assembly but from type new ModuleSpecification( type.FullName, ModuleUtil.DeclaringTypeShortName(type), description, type.Assembly, new ModuleInfo( 1, comsCount ), type )); } } return(comsCount); }
void _PrintCommandHelp( CommandEvaluationContext context, CommandSpecification com, bool shortView = false, bool verboseView = false, bool list = false, int maxnslength = -1, int maxcnamelength = -1, int maxcmdtypelength = -1, int maxmodlength = -1, bool singleout = false ) { #pragma warning disable IDE0071 // Simplifier l’interpolation #pragma warning disable IDE0071WithoutSuggestion // Simplifier l’interpolation if (maxcnamelength == -1) { maxcnamelength = com.Name.Length + 1; } if (maxnslength == -1) { maxnslength = com.Namespace.Length + 1; } if (maxcmdtypelength == -1) { maxcmdtypelength = com.DeclaringTypeShortName.Length + 1; } var col = singleout ? "" : "".PadRight(maxcnamelength, ' '); var f = GetCmd(EchoDirectives.f + "", context.CommandLineProcessor.Console.DefaultForeground.ToString().ToLower()); if (list) { if (!shortView) { context.Out.Echoln($"{Darkcyan}{com.ModuleName.PadRight(maxmodlength, ' ')} {com.DeclaringTypeShortName.PadRight(maxcmdtypelength, ' ')} {com.Namespace.PadRight(maxnslength, ' ')}{Tab}{context.ShellEnv.Colors.Highlight}{com.Name.PadRight(maxcnamelength, ' ')}{Tab}{f}{com.Description}{context.ShellEnv.Colors.Default}"); } else { context.Out.Echoln($"{context.ShellEnv.Colors.Highlight}{com.Name.PadRight(maxcnamelength, ' ')}{f}{Tab}{com.Description}{context.ShellEnv.Colors.Default}"); } } else { bool hasrtt = com.ReturnType != null; bool hasalias = com.Aliases != null; if (singleout) { context.Out.Echoln(com.Description); context.Out.Echo($"{Br}{col}{context.ShellEnv.Colors.Label}syntax: {f}{com.ToColorizedString(context.ShellEnv.Colors)}", hasrtt | hasalias); if (hasrtt) { context.Out.Echoln($"{col}{context.ShellEnv.Colors.Label}returns: {context.ShellEnv.Colors.TypeName}{com.ReturnType.UnmangledName()}"); } if (hasalias) { context.Out.Echoln($"{col}{context.ShellEnv.Colors.Label}aliases: {context.ShellEnv.Colors.TypeName}{string.Join(",", com.Aliases.Select(x => x.name))}"); } context.Out.Echo(!shortView ? Br : ""); if (!string.IsNullOrWhiteSpace(com.LongDescription)) { context.Out.Echoln(_GetPrintableDocText(com.LongDescription, list, shortView, 0)); } } else { context.Out.Echoln($"{com.Name.PadRight(maxcnamelength, ' ')}{com.Description}"); context.Out.Echoln($"{Br}{col}{context.ShellEnv.Colors.Label}syntax: {f}{com.ToColorizedString(context.ShellEnv.Colors)}"); if (hasrtt) { context.Out.Echoln($"{col}{context.ShellEnv.Colors.Label}returns: {context.ShellEnv.Colors.TypeName}{com.ReturnType.UnmangledName()}"); } if (hasalias) { context.Out.Echoln($"{col}{context.ShellEnv.Colors.Label}aliases: {context.ShellEnv.Colors.TypeName}{string.Join(",", com.Aliases.Select(x => x.name))}"); } context.Out.Echo(!shortView ? Br : ""); if (!string.IsNullOrWhiteSpace(com.LongDescription)) { context.Out.Echo(_GetPrintableDocText(com.LongDescription + "(br)", list, shortView, maxcnamelength)); } } } if (!list) { if (com.ParametersCount > 0) { if (!shortView) { var mpl = (com.ParametersCount > 0 ? com.ParametersSpecifications.Values.Select(x => x.Dump(false).Length).Max() : 0) + context.CommandLineProcessor.Console.TabLength; foreach (var p in com.ParametersSpecifications.Values) { var ptype = (!p.IsOption && p.HasValue) ? $"of type: {context.ShellEnv.Colors.TypeName}{p.ParameterInfo.ParameterType.UnmangledName()}{f}" : ""; var pdef = (p.HasValue && p.IsOptional && p.HasDefaultValue && p.DefaultValue != null && (!p.IsOption || p.ParameterValueTypeName != typeof(bool).Name)) ? ((ptype != "" ? ". " : "") + $"default value: {context.ShellEnv.Colors.OptionValue}{EchoPrimitives.DumpAsText(context, p.DefaultValue)}{f}") : ""; var pleftCol = "".PadRight(mpl - p.Dump(false).Length, ' '); var leftCol = "".PadRight(mpl, ' '); if (p.ParameterInfo.ParameterType.IsEnum) { pdef += $"(br){col}{Tab}{leftCol}possibles values: {context.ShellEnv.Colors.OptionValue}{string.Join(CommandLineSyntax.ParameterTypeListValuesSeparator, Enum.GetNames(p.ParameterInfo.ParameterType))}(rdc)"; } var supdef = $"{ptype}{pdef}"; // method 'Echo if has' else to string context.Out.Echoln($"{col}{Tab}{p.ToColorizedString(context.ShellEnv.Colors, false)}{pleftCol}{p.Description}"); if (!string.IsNullOrWhiteSpace(supdef)) { context.Out.Echoln($"{col}{Tab}{" ".PadRight(mpl)}{supdef}"); } } //if (string.IsNullOrWhiteSpace(com.Documentation)) context.Out.Echoln(); if (!string.IsNullOrWhiteSpace(com.Documentation)) { context.Out.Echo(_GetPrintableDocText("(br)" + com.Documentation, list, shortView, singleout ? 0 : maxcnamelength)); } } else { if (!string.IsNullOrWhiteSpace(com.Documentation)) { context.Out.Echoln(_GetPrintableDocText("(br)" + com.Documentation, list, shortView, singleout ? 0 : maxcnamelength)); } } } if (verboseView) { if (com.ParametersCount > 0) { context.Out.Echoln(""); } context.Out.Echoln($"{col}{context.ShellEnv.Colors.Label}namespace : {context.ShellEnv.Colors.HalfDarkLabel}{com.Namespace}"); context.Out.Echoln($"{col}{context.ShellEnv.Colors.Label}declaring type : {context.ShellEnv.Colors.HalfDarkLabel}{com.DeclaringTypeShortName}"); context.Out.Echoln($"{col}{context.ShellEnv.Colors.Label}module : {context.ShellEnv.Colors.HalfDarkLabel}{com.ModuleName}{context.ShellEnv.Colors.Default}"); } } #pragma warning restore IDE0071WithoutSuggestion // Simplifier l’interpolation #pragma warning restore IDE0071 // Simplifier l’interpolation }
int RegisterCommandsClass(CommandEvaluationContext context, Type type, bool registerAsModule) { if (type.GetInterface(typeof(ICommandsDeclaringType).FullName) == null) { throw new Exception($"the type '{type.FullName}' must implements interface '{typeof(ICommandsDeclaringType).FullName}' to be registered as a command class"); } var comsCount = 0; object instance = Activator.CreateInstance(type, new object[] { }); var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); if (registerAsModule && _modules.ContainsKey(type.FullName)) { Errorln($"a module with same name than commands type '{type.FullName}' is already registered"); return(0); } foreach (var method in methods) { var cmd = method.GetCustomAttribute <CommandAttribute>(); if (cmd != null) { if (!method.ReturnType.HasInterface(typeof(ICommandResult))) { Errorln($"class={type.FullName} method={method.Name} wrong return type. should be of type '{typeof(ICommandResult).FullName}', but is of type: {method.ReturnType.FullName}"); } else { var paramspecs = new List <CommandParameterSpecification>(); bool syntaxError = false; var pindex = 0; foreach (var parameter in method.GetParameters()) { if (pindex == 0) { // manadatory: param 0 is CommandEvaluationContext if (parameter.ParameterType != typeof(CommandEvaluationContext)) { Errorln($"class={type.FullName} method={method.Name} parameter 0 ('{parameter.Name}') should be of type '{typeof(CommandEvaluationContext).FullName}', but is of type: {parameter.ParameterType.FullName}"); syntaxError = true; break; } } else { CommandParameterSpecification pspec = null; var paramAttr = parameter.GetCustomAttribute <ParameterAttribute>(); object defval = null; if (!parameter.HasDefaultValue && parameter.ParameterType.IsValueType) { defval = Activator.CreateInstance(parameter.ParameterType); } if (paramAttr != null) { // TODO: validate command specification (eg. indexs validity) pspec = new CommandParameterSpecification( parameter.Name, paramAttr.Description, paramAttr.IsOptional, paramAttr.Index, null, true, parameter.HasDefaultValue, (parameter.HasDefaultValue) ? parameter.DefaultValue : defval, parameter); } var optAttr = parameter.GetCustomAttribute <OptionAttribute>(); if (optAttr != null) { var reqParamAttr = parameter.GetCustomAttribute <OptionRequireParameterAttribute>(); try { pspec = new CommandParameterSpecification( parameter.Name, optAttr.Description, optAttr.IsOptional, -1, optAttr.OptionName ?? parameter.Name, optAttr.HasValue, parameter.HasDefaultValue, (parameter.HasDefaultValue) ? parameter.DefaultValue : defval, parameter, reqParamAttr?.RequiredParameterName); } catch (Exception ex) { Errorln(ex.Message); } } if (pspec == null) { syntaxError = true; Errorln($"invalid parameter: class={type.FullName} method={method.Name} name={parameter.Name}"); } else { paramspecs.Add(pspec); } } pindex++; } if (!syntaxError) { var cmdNameAttr = method.GetCustomAttribute <CommandNameAttribute>(); var cmdName = (cmdNameAttr != null && cmdNameAttr.Name != null) ? cmdNameAttr.Name : (cmd.Name ?? method.Name.ToLower()); var cmdspec = new CommandSpecification( cmdName, cmd.Description, cmd.LongDescription, cmd.Documentation, method, instance, paramspecs); bool registered = true; if (_commands.TryGetValue(cmdspec.Name, out var cmdlst)) { if (cmdlst.Select(x => x.MethodInfo.DeclaringType == type).Any()) { Errorln($"command already registered: '{cmdspec.Name}' in type '{cmdspec.DeclaringTypeFullName}'"); registered = false; } else { cmdlst.Add(cmdspec); } } else { _commands.Add(cmdspec.Name, new List <CommandSpecification> { cmdspec }); } if (registered) { _syntaxAnalyzer.Add(cmdspec); comsCount++; } } } } } if (registerAsModule) { if (comsCount == 0) { Errorln($"no commands found in type '{type.FullName}'"); } else { var descAttr = type.GetCustomAttribute <CommandsAttribute>(); var description = descAttr != null ? descAttr.Description : ""; _modules.Add(type.FullName, new CommandsModule(CommandsModule.DeclaringTypeShortName(type), description, type.Assembly, 1, comsCount, type)); } } return(comsCount); }