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; }