public void Can_parse_verb_noun_format_with_no_arguments()
 {
     var parser = new CommandLineParser();
     var commandLine = (parser.Parse(new[] { "add-wrap" }) as CommandLineParser.Success).CommandLine;
     commandLine.Noun.ShouldBe("wrap");
     commandLine.Verb.ShouldBe("add");
     commandLine.Arguments.ShouldBeEmpty();
 }
 public void Can_parse_verb_noun_format()
 {
     var parser = new CommandLineParser();
     var commandLine = (parser.Parse(new[] { "add-wrap", "foo", "bar" }) as CommandLineParser.Success).CommandLine;
     commandLine.Noun.ShouldBe("wrap");
     commandLine.Verb.ShouldBe("add");
     commandLine.Arguments.ShouldHaveSameElementsAs(new[] { "foo", "bar" });
 }
        public IEnumerable<ICommandOutput> Execute(IEnumerable<string> strings)
        {
            var parser = new CommandLineParser();
            var parseResult = parser.Parse(strings);
            if (parseResult is CommandLineParser.NotEnoughArgumentsFailure)
            {
                yield return new NotEnoughParameters();
                yield break;
            }

            var commandLine = ((CommandLineParser.Success)parseResult).CommandLine;
            var matchingNouns = _commands.Nouns.Where(x => x.StartsWith(commandLine.Noun, StringComparison.OrdinalIgnoreCase)).ToList();
            if (matchingNouns.Count != 1)
            {
                yield return new NamespaceNotFound(matchingNouns);
                yield break;
            }
            var noun = matchingNouns[0];

            var matchingVerbs = _commands.Verbs.Where(x => x.StartsWith(commandLine.Verb, StringComparison.OrdinalIgnoreCase)).ToList();
            if (matchingVerbs.Count != 1)
            {
                yield return new UnknownCommand(commandLine.Verb, matchingVerbs);
                yield break;
            }

            var verb = matchingVerbs[0];

            var command = _commands.Get(noun, verb);

            var inputsFromCommandLine = ParseInputsFromCommandLine(commandLine.Arguments).ToLookup(x => x.Key, x => x.Value);

            var unnamedCommandInputsFromCommandLine = inputsFromCommandLine[null].ToList();
            List<ParsedInput> assignedNamedInputValues = null;
            AmbiguousInputNameException exception = null;
            try
            {
                assignedNamedInputValues = (from namedValues in inputsFromCommandLine
                                            where namedValues.Key != null
                                            let value = namedValues.LastOrDefault()
                                            let commandInput = FindCommandInputDescriptor(command, namedValues.Key)
                                            let parsedValue = commandInput != null ? commandInput.ValidateValue(value) : null
                                            select new ParsedInput
                                            {
                                                    InputName = namedValues.Key,
                                                    RawValue = value,
                                                    Input = commandInput,
                                                    ParsedValue = parsedValue
                                            }).ToList();
            }
            catch(AmbiguousInputNameException e)
            {
                exception = e;
            }
            if (exception != null)
            {
                yield return exception;
                yield break;
            }
            var namedInputsNameNotFound = assignedNamedInputValues.FirstOrDefault(x => x.Input == null);
            if (namedInputsNameNotFound != null)
            {
                yield return new UnknownCommandInput(namedInputsNameNotFound.InputName);
                yield break;
            }

            var namedInputsValueNotParsed = assignedNamedInputValues.FirstOrDefault(x => x.RawValue == null);

            var inputNamesAlreadyFilled = assignedNamedInputValues.Select(x => x.InputName).ToList();

            // now got a clean set of input names that pass. Now on to the unnamed ones.
            var unfullfilledCommandInputs = (from input in command.Inputs
                                             where !inputNamesAlreadyFilled.Contains(input.Key, StringComparer.OrdinalIgnoreCase)
                                                   && input.Value.Position != null && input.Value.Position >= 0
                                             orderby input.Value.Position ascending
                                             select input.Value).ToList();

            if (unnamedCommandInputsFromCommandLine.Count > unfullfilledCommandInputs.Count)
            {
                yield return new InvalidCommandValue(unnamedCommandInputsFromCommandLine);
                yield break;
            }

            var assignedUnnamedInputValues = (from unnamedValue in unnamedCommandInputsFromCommandLine
                                              let input = unfullfilledCommandInputs[unnamedCommandInputsFromCommandLine.IndexOf(unnamedValue)]
                                              let commandValue = input.ValidateValue(unnamedValue)
                                              select new ParsedInput
                                              {
                                                  InputName = null,
                                                  RawValue = unnamedValue,
                                                  Input = input,
                                                  ParsedValue = commandValue
                                              }).ToList();

            var unnamedFailed = assignedUnnamedInputValues.Where(x => x.ParsedValue == null).ToList();
            if (unnamedFailed.Count > 0)
            {
                yield return new InvalidCommandValue(unnamedCommandInputsFromCommandLine);
                yield break;
            }

            var allAssignedInputs = assignedNamedInputValues.Concat(assignedUnnamedInputValues);

            allAssignedInputs = TryAssignSwitchParameters(allAssignedInputs, command.Inputs);

            var missingRequiredInputs = command.Inputs.Select(x => x.Value)
                                              .Where(x => !allAssignedInputs.Select(i => i.Input).Contains(x) && x.IsRequired)
                                              .ToList();
            if (missingRequiredInputs.Count > 0)
            {
                yield return new MissingCommandValue(missingRequiredInputs);
                yield break;
            }

            var missingInputValues = allAssignedInputs.Select(x => x.Input);
            // all clear, assign and run
            var commandInstance = command.Create();
            foreach (var namedInput in allAssignedInputs)
                namedInput.Input.SetValue(commandInstance, namedInput.ParsedValue);
            var enumerator = commandInstance.Execute().GetEnumerator();
            MoveNextResult result;
            do
            {
                ICommandOutput msg;
                Exception error;
                result = enumerator.TryMoveNext(out msg, out error);
                if (result == MoveNextResult.Moved)
                    yield return msg;
                else if (result == MoveNextResult.End)
                    yield break;
                else if (result == MoveNextResult.Error)
                    yield return new ExceptionError(error);
            } while (result == MoveNextResult.Moved);
        }
 public void Cannot_parse_single_argument_without_dash()
 {
     var parser = new CommandLineParser();
     var result = parser.Parse(new[] { "fail" }) as CommandLineParser.NotEnoughArgumentsFailure;
     result.ShouldNotBeNull();
 }
 public void Cannot_parse_empty_command_line()
 {
     var parser = new CommandLineParser();
     var result = parser.Parse(new string[0]) as CommandLineParser.NotEnoughArgumentsFailure;
     result.ShouldNotBeNull();
 }