Ejemplo n.º 1
0
        private T MapCommandPositionalOptionsAndOptions(T model, string[] args)
        {
            var command = _mapper.Commands.Get(args[0], _mapper.Settings.StringComparison);

            if (command is null || command.IsDisabled)
            {
                throw new UnknownCommandException(args[0]);
            }

            var commandInstance = _reflectionService.SetValue(command, model);

            var optionsStartIndex = 1;

            for (; optionsStartIndex < args.Length; optionsStartIndex++)
            {
                if (command.Options.Any(x => x.IsPositionalOption))
                {
                    break;
                }

                var arg = args[optionsStartIndex];

                if (arg.IsValidOption())
                {
                    break;
                }

                var subcommand = command.Subcommands.Get(arg, _mapper.Settings.StringComparison);

                if (subcommand is null || subcommand.IsDisabled)
                {
                    throw new UnknownCommandException(arg);
                }

                var subcommandInstance = _reflectionService.SetValue(subcommand, commandInstance);

                command = subcommand;
                commandInstance = subcommandInstance;
            }

            var proceededOptions = new HashSet<Option>();
            var parsedOptions = RawParser.ParseOptions(args, optionsStartIndex);

            var groupedOptions = new Dictionary<Option, List<string>>(
                new OptionPropertyInfoEqualityComparer());

            foreach (var ((key, matchType), values) in parsedOptions)
            {
                var option = command.Options.Get(matchType, 
                    key.RemoveOptionPrefix(), _mapper.Settings.StringComparison);

                if (option is null || option.IsDisabled)
                {
                    throw new UnknownCommandOptionException(command.ToString(), key);
                }

                proceededOptions.Add(option);
                groupedOptions.AddOrMergeValues(option, values);
            }

            var positionalOptionsStartIndex = 0;
            var hasPositionalOptionSeparator = false;

            for (var i = 0; i < args.Length; i++)
            {
                if (!args[i].IsPositionalOptionsSeparator())
                {
                    continue;
                }

                positionalOptionsStartIndex = i + 1;
                hasPositionalOptionSeparator = true;

                break;
            }

            positionalOptionsStartIndex = Math.Max(optionsStartIndex, positionalOptionsStartIndex);

            if (command.Options.Any(x => x.IsPositionalOption && x.Type.IsList()))
            {
                var listPositionalOptionValues = new List<string>();

                for (var i = positionalOptionsStartIndex; i < args.Length; i++)
                {
                    if (!hasPositionalOptionSeparator && args[i].IsValidOption())
                    {
                        break;
                    }

                    listPositionalOptionValues.Add(args[i]);
                }

                if (listPositionalOptionValues.Any())
                {
                    var option = command.Options.GetByPosition(0);

                    _reflectionService.SetValue(option, commandInstance,
                        listPositionalOptionValues, _mapper.Settings.Culture);

                    proceededOptions.Add(option);
                }
            }
            else
            {
                for (var i = positionalOptionsStartIndex; i < args.Length; i++)
                {
                    if (!hasPositionalOptionSeparator && args[i].IsValidOption())
                    {
                        break;
                    }

                    var option = command.Options.GetByPosition(i - positionalOptionsStartIndex);

                    if (option is null)
                    {
                        throw new NoMatchedValueForCommandPositionalOptionException(command.ToString(), args[i]);
                    }

                    _reflectionService.SetValue(option, commandInstance, args[i], _mapper.Settings.Culture);

                    proceededOptions.Add(option);
                }
            }

            foreach (var option in command.Options)
            {
                if (option.IsRequired && !proceededOptions.Contains(option))
                {
                    throw new RequiredCommandOptionException(command.ToString(), option.ToString());
                }
            }

            foreach (var option in command.Options)
            {
                if (proceededOptions.Contains(option))
                {
                    continue;
                }

                _reflectionService.SetValue(option, commandInstance, option.DefaultValue);
            }

            foreach (var (option, values) in groupedOptions)
            {
                _reflectionService.SetValue(option, commandInstance, values, _mapper.Settings.Culture);
            }

            return model;
        }