private static string GetCommandDescription(CommandRule cmd, CmdLineRules rules, string optPrefix) { var sb = new StringBuilder(cmd.Description); var cmdOpts = rules .Options .Where(opt => opt.DependOnCommands.Contains(cmd.Name)) .ToArray(); var reqOpts = cmdOpts .Where(opt => opt.Required) .Select(opt => GetOptionString(opt, false, optPrefix)) .Join(", "); if (reqOpts.Length > 0) { sb.AppendFormat(" Required: {0}.", reqOpts); } var optOpts = cmdOpts .Where(opt => !opt.Required) .Select(opt => GetOptionString(opt, false, optPrefix)) .Join(", "); if (optOpts.Length > 0) { sb.AppendFormat(" Optional: {0}.", optOpts); } return(sb.ToString()); }
/// <summary> /// Print usage. /// </summary> public static string PrintUsage( [NotNull] this CmdLineRules rules, [NotNull] PrintUsageSettings settings) { var sw = new StringWriter(); PrintUsage(rules, sw, settings); return(sw.ToString()); }
/// <summary> /// Print usage. /// </summary> public static void PrintUsage( [NotNull] this CmdLineRules rules, [NotNull] TextWriter writer, [NotNull] PrintUsageSettings settings) { if (rules == null) { throw new ArgumentNullException(nameof(rules)); } if (writer == null) { throw new ArgumentNullException(nameof(writer)); } if (settings == null) { throw new ArgumentNullException(nameof(settings)); } UsagePrinter.PrintUsage(rules, writer, settings); }
public static void PrintUsage(CmdLineRules rules, TextWriter writer, PrintUsageSettings settings) { var titleExists = false; if (!settings.ProductNameString.IsNullOrEmpty()) { writer.WriteLine(settings.ProductNameString); titleExists = true; } if (!settings.CopyrightString.IsNullOrEmpty()) { writer.WriteLine(settings.CopyrightString); titleExists = true; } if (titleExists) { writer.WriteLine(); } writer.Write("Usage: "); if (!settings.ProgramFileName.IsNullOrEmpty()) { writer.Write(settings.ProgramFileName); } else { var entry = Assembly.GetEntryAssembly(); if (entry == null) { throw new ApplicationException("Could not retrieve program file name. Try to specify it in settings."); } writer.Write(entry.GetName(false).Name); } var hasCmds = rules.Commands.Length > 0; if (hasCmds) { writer.Write(" "); string prefix, suffix; switch (rules.CommandQuantifier) { case CommandQuantifier.ZeroOrOne: prefix = "["; suffix = "]"; break; case CommandQuantifier.ZeroOrMultiple: prefix = "["; suffix = "...]"; break; case CommandQuantifier.One: prefix = "<"; suffix = ">"; break; case CommandQuantifier.OneOrMultiple: prefix = "<"; suffix = "...>"; break; default: throw new ArgumentOutOfRangeException(); } writer.Write( prefix + (settings.RealCommandsInHeadLine ? rules.Commands.Select(cmd => cmd.Name).Join("|") : "command") + suffix); } var hasOpts = rules.Options.Length > 0; string optPrefix; switch (settings.OptionPrefix) { case OptionPrefix.Dash: optPrefix = "-"; break; case OptionPrefix.Slash: optPrefix = "/"; break; default: throw new ArgumentOutOfRangeException(); } if (hasOpts) { writer.Write( " [{0}...]", settings.RealOptionsInHeadLine ? rules.Options.Select(opt => GetOptionString(opt, false, optPrefix)).Join("|") : "options"); } writer.WriteLine(); writer.WriteLine(); if (hasCmds) { writer.WriteLine(" - COMMANDS -"); var cmdDescs = rules .Commands .Select(cmd => new ItemDescriptor(cmd.Name, GetCommandDescription(cmd, rules, optPrefix))) .ToList(); var maxLen = cmdDescs.Max(desc => desc.Name.Length); foreach (var desc in cmdDescs) { writer.WriteLine(" {0} - {1}", desc.Name.PadRight(maxLen), desc.Description); } } if (hasOpts) { writer.WriteLine(" - OPTIONS -"); var optDescs = rules .Options .Select(opt => new ItemDescriptor(GetOptionString(opt, true, optPrefix), GetOptionDescription(opt))) .ToList(); var maxLen = optDescs.Max(desc => desc.Name.Length); foreach (var desc in optDescs) { writer.WriteLine(" {0} - {1}", desc.Name.PadRight(maxLen), desc.Description); } } }
/// <summary> /// Print usage with default settings. /// </summary> public static void PrintUsage( [NotNull] this CmdLineRules rules, [NotNull] TextWriter writer) { PrintUsage(rules, writer, new PrintUsageSettings()); }
/// <summary> /// Check command line semantics. /// </summary> public static void Check(CmdLineNode commandLine, CmdLineRules rules) { CommandLineChecker.Check(commandLine, rules); }
/// <summary> /// Check command line semantics. /// </summary> public static void Check(string commandLine, CmdLineRules rules) { Check(CommandLineParser.ParseCommandLine(commandLine), rules); }
/// <summary> /// Check command line semantics. /// </summary> public static void Check(CmdLineNode commandLine, CmdLineRules rules) { // Check rules consistency var cmds = new HashSet <string>(); foreach (var command in rules.Commands) { if (!cmds.Add(command.Name)) { throw new CommandLineCheckException($"Duplicate commands \'{command.Name}\'"); } } var cmdOpts = LazyDictionary.Create <string, HashSet <string> >(cn => new HashSet <string>(), false); foreach (var cmdOpt in rules .Options .SelectMany( opt => !opt.DependOnCommands.Any() ? new[] { new { Cmd = "", Opt = opt.Name } } : opt.DependOnCommands.Select(cn => new { Cmd = cn, Opt = opt.Name }))) { if (!cmdOpts[cmdOpt.Cmd].Add(cmdOpt.Opt)) { throw new CommandLineCheckException( "Duplicate option {0}{1}" .FormatWith( cmdOpt.Opt, cmdOpt.Cmd == "" ? "" : " in command {0}".FormatWith(cmdOpt.Cmd))); } } // Check command quantity var cmdCount = commandLine.Commands.Length; switch (rules.CommandQuantifier) { case CommandQuantifier.ZeroOrOne: if (cmdCount > 1) { throw new CommandLineCheckException("Maximum one command is allowed."); } break; case CommandQuantifier.ZeroOrMultiple: // Any combination allowed break; case CommandQuantifier.One: if (cmdCount > 1) { throw new CommandLineCheckException("Maximum one command is allowed."); } if (cmdCount == 0) { throw new CommandLineCheckException("Required command not specified."); } break; case CommandQuantifier.OneOrMultiple: if (cmdCount == 0) { throw new CommandLineCheckException("Required command(s) not specified."); } break; default: throw new ArgumentOutOfRangeException(); } // Check for unknown commands var cmdRules = rules.Commands.ToDictionary(cr => cr.Name); var unkCmds = commandLine .Commands .Where(cmd => !cmdRules.ContainsKey(cmd.Text)) .ToArray(); if (unkCmds.Length > 0) { throw new CommandLineCheckException( "Unknown commands :{0}".FormatWith(unkCmds.Select(cmd => "'" + cmd.Text + "'").Join(", "))); } // Check for unknown options var optRules = rules.Options.ToDictionary(cr => cr.Name); var unkOpts = commandLine .Options .Where(opt => !optRules.ContainsKey(opt.Text)) .ToArray(); if (unkOpts.Length > 0) { throw new CommandLineCheckException( "Unknown options :{0}".FormatWith(unkOpts.Select(opt => "'" + opt.Text + "'").Join(", "))); } // Option values check foreach (var option in commandLine.Options) { var rule = optRules[option.Text]; if (rule.Type != option.Type) { switch (rule.Type) { case OptionType.Valueless: throw new CommandLineCheckException("Option '{0}' cannot have value".FormatWith(rule.Name)); case OptionType.Bool: throw new CommandLineCheckException("'+' or '-' must be specified for option '{0}'".FormatWith(rule.Name)); case OptionType.Value: throw new CommandLineCheckException("Value must be specified for option '{0}'".FormatWith(rule.Name)); default: throw new ArgumentOutOfRangeException(); } } } // Options presence check var specCmds = new HashSet <string>(commandLine.Commands.Select(cmd => cmd.Text)); var specOpts = new HashSet <string>(commandLine.Options.Select(opt => opt.Text)); foreach (var optRule in rules.Options) { var existed = specOpts.Contains(optRule.Name); var dependent = optRule.DependOnCommands.Any(); var hasMasterCmd = dependent && optRule.DependOnCommands.Any(specCmds.Contains); if (existed && dependent && !hasMasterCmd) { throw new CommandLineCheckException( "{0} command(s) must be specified for use {1} option." .FormatWith(optRule.DependOnCommands.Select(c => c).Join(", "), optRule.Name)); } if (!existed && optRule.Required && (!dependent || hasMasterCmd)) { throw new CommandLineCheckException("Required option '{0}' absent.".FormatWith(optRule.Name)); } } }
/// <summary> /// Initializes a new instance. /// </summary> public CommandLineService([NotNull] CmdLineRules rules) : this(() => rules) { }