示例#1
0
        private static void ParseOptions(ref DidactClient client, string[] args, string parentName)
        {
            for (var i = 1; i < args.Length; i++)
            {
                var option = client.Options.FirstOrDefault(o => args[i - 1] == o.ShortCommand || args[i - 1] == o.LongCommand && o.ParentName == parentName);
                if (option != null)
                {
                    // Read option argument - null if not present
                    var val = args.Length >= i ? args[i] : null;

                    // Parse
                    if (option.Parse != null)
                    {
                        val = option.Parse(val);
                    }

                    // Validate
                    if (option.Validate == null)
                    {
                        option.Value = val;
                    }
                    else
                    {
                        if (option.Validate(val))
                        {
                            option.Value = val;
                        }
                        else
                        {
                            throw new FormatException($"The option '{option.ShortCommand}' failed data validation.");
                        }
                    }
                }
            }
        }
        public static DidactClient Command(this DidactClient didact, string commandStr, string description,
                                           Action <Dictionary <string, string>, Dictionary <string, string> > action)
        {
            if (action == null)
            {
                throw new ArgumentNullException($"The {nameof(action)} argument cannot be null", nameof(action));
            }

            return(didact.Command(commandStr, description, action: action, actionAsync: null));
        }
示例#3
0
 public static void Parse(this DidactClient didact, string[] args)
 {
     try
     {
         didact.ParseAsync(args).Wait();
     }
     catch (AggregateException ex)
     {
         ExceptionDispatchInfo.Capture(ex.Flatten().InnerExceptions.First()).Throw();
     }
 }
        public static DidactClient Option(this DidactClient didact, string flags,
                                          string description, Func <string, bool> validate = null,
                                          Func <string, string> parse = null, string defaultValue = default(string))
        {
            var parentName = didact.Commands.LastOrDefault()?.Name;
            var option     = new Option
            {
                DefaultValue = defaultValue,
                Description  = description,
                Flags        = flags,
                OptionType   = parentName == null ? OptionType.Global : OptionType.Command,
                ParentName   = parentName,
                Parse        = parse,
                Validate     = validate
            };

            // Check format of flags
            var match = Regex.Match(flags, @"(\-[a-z]),[ ]([\-]{2}[a-z\-]+)[ ]?([\<\>\[\]a-z0-9\- ]+)?", RegexOptions.IgnoreCase);

            if (!match.Success || match.Groups.Count != 4)
            {
                throw new ArgumentException($"The Flags format is malformed for '{flags}'.", nameof(flags));
            }

            option.ShortCommand = match.Groups[1].Value;
            option.LongCommand  = match.Groups[2].Value;

            // Parse arguments out from flags
            var arguments = match.Groups[3].Value.Trim().Split(' ');

            if (arguments.Count() > 1)
            {
                throw new ArgumentException($"The Flags format is malformed for the argument. You can have only one argument on an option.", nameof(flags));
            }

            if (arguments.Any())
            {
                var argument = arguments.First();
                var argRegex = Regex.Match(argument, @"(\<[a-z]+[a-z0-9\-]+\>|\[[a-z]+[a-z0-9\-]+\])", RegexOptions.IgnoreCase);
                if (!argRegex.Success)
                {
                    throw new ArgumentException($"The Flags format is malformed for the argument '{argument}'.", nameof(flags));
                }

                option.IsRequired = argument.StartsWith("<");
                option.Name       = argument.Trim('<', '>', '[', ']');
            }

            didact.Options.Add(option);

            return(didact);
        }
        internal static void PrintHelp(DidactClient client)
        {
            if (client.Metadata.Usage == null)
            {
                // Generate Usage
                var sb = new StringBuilder();
                sb.Append(client.Metadata.CliName);
                if (client.Commands.Any())
                {
                    sb.Append(" [command]");
                }
                if (client.Commands.Any(c => c.Arguments.Any()))
                {
                    sb.Append(" [arguments]");
                }
                if (client.Options.Any(o => o.OptionType == OptionType.Command))
                {
                    sb.Append(" [command-options]");
                }
                if (client.Options.Any(o => o.OptionType == OptionType.Global))
                {
                    sb.Append(" [global-options]");
                }

                client.Metadata.Usage = sb.ToString();
            }

            WriteLine();
            Write(client.Metadata.Name);
            if (client.Metadata.Version != null)
            {
                Write($" - ({client.Metadata.Version})");
            }
            Write("\n");
            WriteLine();
            WriteLine($"Usage: {client.Metadata.Usage}");
            WriteLine();

            // Print Global Options
            WriteLine("Global Options:");
            var options             = client.Options.Where(o => o.OptionType == OptionType.Global);
            var largestLinePosition = 4 + options.OrderByDescending(o => o.ShortCommand.Length).First().ShortCommand.Length + options.OrderByDescending(o => o.LongCommand.Length).First().LongCommand.Length;

            foreach (var option in options)
            {
                var line    = $"  {option.ShortCommand}, {option.LongCommand}";
                var padding = largestLinePosition - line.Length;
                WriteLine($"{line.PadRight(padding, ' ')} {option.Description}");
            }

            // TODO: print commands with their respective options
        }
        private static DidactClient Command(this DidactClient didact, string commandStr, string description,
                                            Action <Dictionary <string, string>, Dictionary <string, string> > action         = null,
                                            Func <Dictionary <string, string>, Dictionary <string, string>, Task> actionAsync = null)
        {
            var command = new Command
            {
                CommandStr  = commandStr,
                Action      = action,
                ActionAsync = actionAsync
            };

            var match = Regex.Match(commandStr, @"([a-z]+[a-z0-9\-]+)[ ]?([\<\>\[\]a-z0-9 ]+)?", RegexOptions.IgnoreCase);

            if (!match.Success || match.Groups.Count != 3)
            {
                throw new ArgumentException($"The Command format is malformed for '{commandStr}'.", nameof(commandStr));
            }

            command.Name = match.Groups[1].Value;

            var arguments = match.Groups[2].Value.Trim().Split(' ');

            foreach (var argumentStr in arguments)
            {
                if (string.IsNullOrWhiteSpace(argumentStr))
                {
                    continue;
                }

                var trimmedArgumentStr = argumentStr.Trim('<', '>', '[', ']');
                var argument           = new Argument
                {
                    Name       = trimmedArgumentStr,
                    IsRequired = argumentStr.StartsWith("<")
                };

                var argRegex = Regex.Match(argumentStr, @"(\<[a-z]+[a-z0-9\-]+\>|\[[a-z]+[a-z0-9\-]+\])", RegexOptions.IgnoreCase);
                if (!argRegex.Success)
                {
                    throw new ArgumentException($"The Command format is malformed for the argument '{argumentStr}'.", nameof(commandStr));
                }

                command.Arguments.Add(argument);
            }

            didact.Commands.Add(command);
            return(didact);
        }
        public static void DebugPrintValues(this DidactClient client)
        {
            WriteLine();
            WriteLine("Printing Internal Values");
            WriteLine();
            WriteLine($"  Global Options");
            foreach (var option in client.Options.Where(o => o.OptionType == OptionType.Global))
            {
                WriteLine($"    {option.ShortCommand}, {option.LongCommand} - {option.Value}");
            }
            WriteLine();
            WriteLine($"  Commands");
            foreach (var command in client.Commands)
            {
                WriteLine($"  {command.Name}'s Details");
                WriteLine($"    Arguments");
                foreach (var argument in command.Arguments)
                {
                    WriteLine($"      {argument.Name} - {argument.Value}");
                }

                WriteLine($"    Arguments");
                foreach (var argument in command.Arguments)
                {
                    WriteLine($"      {argument.Name} - {argument.Value}");
                }

                WriteLine($"    Options");
                foreach (var option in client.Options.Where(o => o.ParentName == command.Name))
                {
                    WriteLine($"      {option.ShortCommand}, {option.LongCommand} - {option.Value}");
                }

                WriteLine();
            }
        }
示例#8
0
        public async static Task ParseAsync(this DidactClient didact, string[] args)
        {
            if (args == null || !args.Any())
            {
                PrintHelp(didact);
                return;
            }

            // Match all global options
            ParseOptions(ref didact, args, null);

            // Check if first command matches any commands
            var command = didact.Commands.FirstOrDefault(c => c.Name == args[0]);

            if (command != null)
            {
                // Parse the next few into commands arguments
                for (var i = 1; i < args.Length; i++)
                {
                    var argument = command.Arguments.ElementAtOrDefault(i - 1);
                    if (argument != null && args.Length >= i)
                    {
                        argument.Value = args[i];
                    }
                }

                // Check if required arguments exist
                var missingArgument = command.Arguments.FirstOrDefault(a => a.Value == null && a.IsRequired);
                if (missingArgument != null)
                {
                    throw new ArgumentException($"The {missingArgument.Name} argument is required.", missingArgument.Name);
                }

                // Parse all command specific options
                ParseOptions(ref didact, args, command.Name);

                // Populate null, non-required, non-validation-failed options with their default values, if they have them
                foreach (var option in didact.Options.Where(o => o.IsRequired && o.DefaultValue != null && o.Value == null))
                {
                    option.Value = option.DefaultValue;
                }

                // Throw exception if a required command is missing
                var missingOption = didact.Options
                                    .FirstOrDefault(o =>
                                                    (o.OptionType == OptionType.Global || o.ParentName == command.Name) && o.IsRequired && o.Value == null);

                if (missingOption != null)
                {
                    throw new ArgumentNullException($"The {missingOption.Name} option is required for this command.");
                }

                // Create dictionaries of arguments and options to pass into the action
                var arguments = command.Arguments
                                .Select(a => new KeyValuePair <string, string>(a.Name, a.Value))
                                .ToDictionary(d => d.Key, d => d.Value);

                var options = didact.Options
                              .Where(o => o.ParentName == command.Name || o.OptionType == OptionType.Global)
                              .Select(a => new KeyValuePair <string, string>(a.ShortCommand.Remove(0, 1), a.Value))
                              .ToDictionary(d => d.Key, d => d.Value);

                if (command.Action != null)
                {
                    command.Action(arguments, options);
                }
                else if (command.ActionAsync != null)
                {
                    await command.ActionAsync(arguments, options);
                }
                else
                {
                    throw new InvalidOperationException("There is no action to call. Help.");
                }
            }

            if (command == null)
            {
                PrintHelp(didact);
            }
        }