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());
        }
예제 #2
0
        /// <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());
        }
예제 #3
0
        /// <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);
                }
            }
        }
예제 #5
0
 /// <summary>
 /// Print usage with default settings.
 /// </summary>
 public static void PrintUsage(
     [NotNull] this CmdLineRules rules,
     [NotNull] TextWriter writer)
 {
     PrintUsage(rules, writer, new PrintUsageSettings());
 }
예제 #6
0
 /// <summary>
 /// Check command line semantics.
 /// </summary>
 public static void Check(CmdLineNode commandLine, CmdLineRules rules)
 {
     CommandLineChecker.Check(commandLine, rules);
 }
예제 #7
0
 /// <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)
 {
 }