Esempio n. 1
0
        public override bool TryGetOption <T>(string name, out T value, T @default = default)
        {
            OptionRun matchingOption = _run.Options.FirstOrDefault(r => r.Option.HasName(name));

            if (matchingOption is null)
            {
                value = default;
                return(false);
            }

            if (matchingOption.Occurrences == 0)
            {
                value = matchingOption.Assigned ? (T)matchingOption.Value : @default;
                return(true);
            }

            object resolvedValue = matchingOption.Value;

            if (resolvedValue != null)
            {
                Type valueType = resolvedValue.GetType();
                if (!typeof(T).IsAssignableFrom(valueType))
                {
                    throw new InvalidOperationException($"The option's value is of type '{valueType.FullName}' is not assignable to the specified type of '{typeof(T).FullName}'.");
                }
            }

            value = (T)resolvedValue;
            return(true);
        }
Esempio n. 2
0
        /// <summary>
        ///     Resolves an <see cref="Option" />'s value based on it's usage details. See the
        ///     <see cref="OptionRun.GetOptionValueType(Option)" /> method for details on how the
        ///     resolution is done.
        /// </summary>
        /// <param name="optionRun">The <see cref="OptionRun" /> instance, whose option to resolve.</param>
        /// <returns>The value of the option.</returns>
        private static object ResolveOptionParameterValues(OptionRun optionRun)
        {
            switch (optionRun.ValueType)
            {
            case OptionValueType.Count:
                return(optionRun.Occurrences);

            case OptionValueType.Flag:
                return(optionRun.Occurrences > 0);

            case OptionValueType.List:
                IList list = optionRun.CreateCollection(optionRun.Parameters.Count);
                foreach (string parameter in optionRun.Parameters)
                {
                    list.Add(optionRun.ResolveValue(parameter));
                }
                return(list);

            case OptionValueType.Object:
                return(optionRun.ResolveValue(optionRun.Parameters[0]));
            }

            throw new ParserException(-1, "Should never reach here");
        }
Esempio n. 3
0
        /// <inheritdoc/>
        public override IEnumerable <string> IdentifyTokens(IEnumerable <string> tokens, IReadOnlyList <OptionRun> options,
                                                            ArgGrouping grouping)
        {
            ArgumentType previousType = ArgumentType.NotSet;
            ArgumentType currentType  = ArgumentType.NotSet;

            foreach (string token in tokens)
            {
                VerifyCommandLineGrouping(previousType, currentType, grouping);

                previousType = currentType;

                var optionMatch = OptionPattern.Match(token);
                if (!optionMatch.Success)
                {
                    currentType = ArgumentType.Argument;
                    yield return(token);
                }
                else
                {
                    currentType = ArgumentType.Option;

                    string specifiedOptionName = optionMatch.Groups[groupnum : 1].Value;

                    // Find the corresponding option run for the specified option name.
                    // If not found, throw a parse exception.
                    OptionRun availableOption = options.SingleOrDefault(or => or.Option.HasName(specifiedOptionName));
                    if (availableOption is null)
                    {
                        throw new ParserException(ParserException.Codes.InvalidOptionSpecified,
                                                  string.Format(Messages.InvalidOptionSpecified, specifiedOptionName));
                    }

                    // Increase the number of occurrences of the option run.
                    availableOption.Occurrences += 1;

                    // If no option parameters are specified, we're done with this option.
                    // Continue the loop to process the next token.
                    if (token.Length == specifiedOptionName.Length + 1)
                    {
                        continue;
                    }

                    // Option name and its parameters must be separated by a colon.
                    // If not, throw a parse exception.
                    if (token[specifiedOptionName.Length + 1] != ':')
                    {
                        throw new ParserException(ParserException.Codes.InvalidOptionParameterSpecifier,
                                                  string.Format(Messages.InvalidOptionParameterSpecifier, specifiedOptionName));
                    }

                    // Match any parameters and add to the option run's Parameters property.
                    var parameterMatches = OptionParameterPattern.Matches(token, optionMatch.Length + 1);
                    foreach (Match parameterMatch in parameterMatches)
                    {
                        string value = parameterMatch.Groups[groupnum : 1].Value;
                        if (value.StartsWith(",", StringComparison.OrdinalIgnoreCase))
                        {
                            value = value.Remove(startIndex: 0, count: 1);
                        }
                        availableOption.Parameters.Add(value);
                    }
                }
            }

            VerifyCommandLineGrouping(previousType, currentType, grouping);
        }
Esempio n. 4
0
        /// <inheritdoc/>
        public override IEnumerable <string> IdentifyTokens(IEnumerable <string> tokens, IReadOnlyList <OptionRun> options,
                                                            ArgGrouping grouping)
        {
            OptionRun currentOption = null;

            bool forceArguments = false;

            foreach (string token in tokens)
            {
                if (token == "--")
                {
                    forceArguments = true;
                    continue;
                }

                if (forceArguments)
                {
                    yield return(token);

                    continue;
                }

                Match optionMatch = OptionPattern.Match(token);

                // If the token is not an option and we are not iterating over the parameters of an
                // option, then the token is an argument.
                if (!optionMatch.Success)
                {
                    // If we're processing an option (currentOption != null), then it's an argument.
                    // Otherwise, it's a parameter on the current option.
                    if (currentOption is null)
                    {
                        yield return(token);
                    }
                    else
                    {
                        currentOption.Parameters.Add(token);
                    }
                }
                else
                {
                    bool   isShortOption        = optionMatch.Groups[1].Value.Length == 1;
                    string optionName           = optionMatch.Groups[2].Value;
                    string parameterValue       = optionMatch.Groups[3].Value;
                    bool   isParameterSpecified = !string.IsNullOrEmpty(parameterValue);

                    // If multiple short options are specified as a single combined option, then none
                    // of them can have parameters.
                    if (isShortOption && optionName.Length > 1 && isParameterSpecified)
                    {
                        throw new ParserException(-1, $"Cannot specify a parameter for the combined option {optionName}.");
                    }

                    // Get the specified option names.
                    // If a short option name is specified and it has multiple characters, each
                    // character is a short name.
                    string[] optionNames = isShortOption && optionName.Length > 1
                        ? optionName.Select(c => c.ToString()).ToArray()
                        : new[] { optionName };

                    // Add each option to its corresponding option run.
                    foreach (string name in optionNames)
                    {
                        OptionRun matchingOption = options.SingleOrDefault(or => or.Option.HasName(name));
                        if (matchingOption is null)
                        {
                            throw new ParserException(ParserException.Codes.InvalidOptionSpecified,
                                                      string.Format(Messages.InvalidOptionSpecified, optionName));
                        }

                        // Increase the number of occurrences of the option
                        matchingOption.Occurrences += 1;
                    }

                    // If only one option was specified (and not a combined short option set), we deal
                    // with the parameters now.
                    if (optionNames.Length == 1)
                    {
                        // We know its option run exists, so use Single here.
                        OptionRun matchingOption = options.Single(or => or.Option.HasName(optionNames[0]));

                        // If the parameter was specified in the same token with a "=" symbol, then
                        // that is the only parameter we can allow.
                        // Add it and proceed with the next token.
                        if (isParameterSpecified)
                        {
                            matchingOption.Parameters.Add(parameterValue);
                            currentOption = null;
                        }

                        // Otherwise, mark the current option as this one and process all subsequent
                        // tokens as parameters until we encounter another option or we've reached the
                        // max limit of parameters for this option.
                        else
                        {
                            currentOption = matchingOption;
                        }
                    }
                    else
                    {
                        currentOption = null;
                    }
                }

                // If we're on an option (currentOption != null) and the number of parameters has
                // reached the maximum allowed, then we can stop handling that option by setting
                // currentOption to null so that the next arg will be treated as a new option or
                // argument.
                if (currentOption != null && currentOption.Parameters.Count >= currentOption.Option.Usage.MaxParameters)
                {
                    currentOption = null;
                }
            }
        }