예제 #1
0
        public static bool TryParseAsEnumFlags <TEnum>(
            IEnumerable <string>?values,
            string optionName,
            out TEnum result,
            TEnum?defaultValue           = null,
            OptionValueProvider?provider = null) where TEnum : struct
        {
            result = (TEnum)(object)0;

            if (values?.Any() != true)
            {
                if (defaultValue != null)
                {
                    result = (TEnum)(object)defaultValue;
                }

                return(true);
            }

            int flags = 0;

            foreach (string value in values)
            {
                if (!TryParseAsEnum(value, optionName, out TEnum result2, provider: provider))
                {
                    return(false);
                }

                flags |= (int)(object)result2;
            }

            result = (TEnum)(object)flags;

            return(true);
        }
예제 #2
0
        public static bool TryParseAsEnumValues <TEnum>(
            IEnumerable <string>?values,
            string optionName,
            out ImmutableArray <TEnum> result,
            ImmutableArray <TEnum> defaultValue = default,
            OptionValueProvider?provider        = null) where TEnum : struct
        {
            if (values?.Any() != true)
            {
                result = (defaultValue.IsDefault) ? ImmutableArray <TEnum> .Empty : defaultValue;

                return(true);
            }

            ImmutableArray <TEnum> .Builder builder = ImmutableArray.CreateBuilder <TEnum>();

            foreach (string value in values)
            {
                if (!TryParseAsEnum(value, optionName, out TEnum result2, provider: provider))
                {
                    return(false);
                }

                builder.Add(result2);
            }

            result = builder.ToImmutableArray();

            return(true);
        }
예제 #3
0
 internal static void WriteOptionValueError(
     string value,
     OptionValue optionValue,
     OptionValueProvider?provider = null)
 {
     WriteOptionValueError(value, optionValue, OptionValueProviders.GetHelpText(provider, multiline: true));
 }
예제 #4
0
 public static bool TryParseHighlightOptions(
     IEnumerable <string> values,
     out HighlightOptions highlightOptions,
     HighlightOptions?defaultValue = null,
     OptionValueProvider?provider  = null)
 {
     return(TryParseHighlightOptions(
                values,
                out highlightOptions,
                defaultValue,
                default(ContentDisplayStyle?),
                provider));
 }
예제 #5
0
        public static bool TryParseHighlightOptions(
            IEnumerable <string> values,
            out HighlightOptions highlightOptions,
            HighlightOptions?defaultValue           = null,
            ContentDisplayStyle?contentDisplayStyle = null,
            OptionValueProvider?provider            = null)
        {
            if (contentDisplayStyle == ContentDisplayStyle.Value ||
                contentDisplayStyle == ContentDisplayStyle.ValueDetail)
            {
                defaultValue = HighlightOptions.None;
            }

            if (values.Any())
            {
                string[] arr = values.ToArray();

                for (int i = 0; i < arr.Length; i++)
                {
                    switch (arr[i])
                    {
                    case "new-line":
                        {
                            LogHelpers.WriteObsoleteWarning($"Value '{arr[i]}' is obsolete. "
                                                            + $"Use value '{OptionValues.HighlightOptions_Newline.HelpValue}' instead.");

                            arr[i] = OptionValues.HighlightOptions_Newline.Value;
                            break;
                        }

                    case "nl":
                    {
                        LogHelpers.WriteObsoleteWarning($"Value '{arr[i]}' is obsolete. "
                                                        + $"Use value '{OptionValues.HighlightOptions_Newline.HelpValue}' instead.");

                        arr[i] = OptionValues.HighlightOptions_Newline.Value;
                        break;
                    }
                    }
                }

                values = arr;
            }

            return(TryParseAsEnumFlags(
                       values,
                       OptionNames.Highlight,
                       out highlightOptions,
                       defaultValue: defaultValue,
                       provider: provider ?? OptionValueProviders.HighlightOptionsProvider));
        }
예제 #6
0
        public static bool TryParseAsEnum <TEnum>(
            string value,
            string optionName,
            out TEnum result,
            TEnum?defaultValue           = null,
            OptionValueProvider?provider = null) where TEnum : struct
        {
            if (!TryParseAsEnum(value, out result, defaultValue, provider))
            {
                string allowedValues = OptionValueProviders.GetHelpText(provider, multiline: true) ?? OptionValue.GetDefaultHelpText <TEnum>(multiline: true);

                WriteOptionError(value, optionName, allowedValues);
                return(false);
            }

            return(true);
        }
예제 #7
0
 public static bool TryParse(
     IEnumerable <string> values,
     string optionName,
     OptionValueProvider provider,
     out Filter?filter,
     bool allowNull = false,
     OptionValueProvider?namePartProvider  = null,
     FileNamePart defaultNamePart          = FileNamePart.Name,
     PatternOptions includedPatternOptions = PatternOptions.None)
 {
     return(TryParse(
                values: values,
                optionName: optionName,
                provider: provider,
                filter: out filter,
                namePart: out _,
                allowNull: allowNull,
                namePartProvider: namePartProvider,
                defaultNamePart: defaultNamePart,
                includedPatternOptions: includedPatternOptions));
 }
예제 #8
0
        public static bool TryParseAsEnum <TEnum>(
            string value,
            out TEnum result,
            TEnum?defaultValue           = null,
            OptionValueProvider?provider = default) where TEnum : struct
        {
            if (value == null &&
                defaultValue != null)
            {
                result = defaultValue.Value;
                return(true);
            }

            if (provider != null)
            {
                return(provider.TryParseEnum(value, out result));
            }
            else
            {
                return(Enum.TryParse(value?.Replace("-", ""), ignoreCase: true, out result));
            }
        }
예제 #9
0
        private static bool TryGetProvider(CommandOption option, [NotNullWhen(true)] out OptionValueProvider?provider)
        {
            if (option.ValueProviderName != null)
            {
                return(OptionValueProviders.ProvidersByName.TryGetValue(option.ValueProviderName, out provider));
            }

            if (option.MetaValue != null &&
                OptionValueProviders.ProvidersByName.TryGetValue(option.MetaValue, out provider))
            {
                return(true);
            }

            Match match = OptionValueProvider.MetaValueRegex.Match(option.MetaValue);

            if (match.Success)
            {
                return(OptionValueProviders.ProvidersByName.TryGetValue(match.Value, out provider));
            }

            provider = null;
            return(false);
        }
예제 #10
0
        public static bool TryParseDisplay(
            IEnumerable <string> values,
            string optionName,
            out ContentDisplayStyle?contentDisplayStyle,
            out PathDisplayStyle?pathDisplayStyle,
            out LineDisplayOptions lineDisplayOptions,
            out LineContext lineContext,
            out DisplayParts displayParts,
            out ImmutableArray <FileProperty> fileProperties,
            out string?indent,
            out string?separator,
            out bool noAlign,
            OptionValueProvider?contentDisplayStyleProvider = null,
            OptionValueProvider?pathDisplayStyleProvider    = null)
        {
            contentDisplayStyle = null;
            pathDisplayStyle    = null;
            lineDisplayOptions  = LineDisplayOptions.None;
            lineContext         = default;
            displayParts        = DisplayParts.None;
            fileProperties      = ImmutableArray <FileProperty> .Empty;
            indent    = null;
            separator = null;
            noAlign   = false;

            ImmutableArray <FileProperty> .Builder?builder = null;

            foreach (string value in values)
            {
                int index = value.IndexOf('=');

                if (index >= 0)
                {
                    string key    = value.Substring(0, index);
                    string value2 = value.Substring(index + 1);

                    if (key == "t")
                    {
                        LogHelpers.WriteObsoleteWarning($"Value '{key}' is obsolete. "
                                                        + $"Use value '{OptionValues.Display_Context.HelpValue}' instead.");

                        key = OptionValues.Display_Context.ShortKey;
                    }
                    else if (key == "ta")
                    {
                        LogHelpers.WriteObsoleteWarning($"Value '{key}' is obsolete. "
                                                        + $"Use value '{OptionValues.Display_ContextAfter.HelpValue}' instead.");

                        key = OptionValues.Display_ContextAfter.ShortKey;
                    }
                    else if (key == "tb")
                    {
                        LogHelpers.WriteObsoleteWarning($"Value '{key}' is obsolete. "
                                                        + $"Use value '{OptionValues.Display_ContextBefore.HelpValue}' instead.");

                        key = OptionValues.Display_ContextBefore.ShortKey;
                    }

                    if (OptionValues.Display_Content.IsKeyOrShortKey(key))
                    {
                        if (!TryParseAsEnum(
                                value2,
                                optionName,
                                out ContentDisplayStyle contentDisplayStyle2,
                                provider: contentDisplayStyleProvider))
                        {
                            return(false);
                        }

                        contentDisplayStyle = contentDisplayStyle2;
                    }
                    else if (OptionValues.Display_Path.IsKeyOrShortKey(key))
                    {
                        if (!TryParseAsEnum(
                                value2,
                                optionName,
                                out PathDisplayStyle pathDisplayStyle2,
                                provider: pathDisplayStyleProvider))
                        {
                            return(false);
                        }

                        pathDisplayStyle = pathDisplayStyle2;
                    }
                    else if (OptionValues.Display_Indent.IsKeyOrShortKey(key))
                    {
                        indent = value2;
                    }
                    else if (OptionValues.Display_Separator.IsKeyOrShortKey(key))
                    {
                        separator = RegexEscape.ConvertCharacterEscapes(value2);
                    }
                    else if (OptionValues.Display_Context.IsKeyOrShortKey(key))
                    {
                        if (!TryParseCount(value2, OptionNames.Display, out int count, value))
                        {
                            return(false);
                        }

                        lineContext = new LineContext(count);
                    }
                    else if (OptionValues.Display_ContextBefore.IsKeyOrShortKey(key))
                    {
                        if (!TryParseCount(value2, OptionNames.Display, out int before, value))
                        {
                            return(false);
                        }

                        lineContext = lineContext.WithBefore(before);
                    }
                    else if (OptionValues.Display_ContextAfter.IsKeyOrShortKey(key))
                    {
                        if (!TryParseCount(value2, OptionNames.Display, out int after, value))
                        {
                            return(false);
                        }

                        lineContext = lineContext.WithAfter(after);
                    }
                    else
                    {
                        WriteOptionError(value, optionName, OptionValueProviders.DisplayProvider);
                        return(false);
                    }
                }
                else if (OptionValues.Display_Summary.IsValueOrShortValue(value))
                {
                    displayParts |= DisplayParts.Summary;
                }
                else if (OptionValues.Display_Count.IsValueOrShortValue(value))
                {
                    displayParts |= DisplayParts.Count;
                }
                else if (OptionValues.Display_CreationTime.IsValueOrShortValue(value))
                {
                    (builder ??= ImmutableArray.CreateBuilder <FileProperty>()).Add(FileProperty.CreationTime);
                }
                else if (OptionValues.Display_ModifiedTime.IsValueOrShortValue(value))
                {
                    (builder ??= ImmutableArray.CreateBuilder <FileProperty>()).Add(FileProperty.ModifiedTime);
                }
                else if (OptionValues.Display_Size.IsValueOrShortValue(value))
                {
                    (builder ??= ImmutableArray.CreateBuilder <FileProperty>()).Add(FileProperty.Size);
                }
                else if (OptionValues.Display_LineNumber.IsValueOrShortValue(value))
                {
                    lineDisplayOptions |= LineDisplayOptions.IncludeLineNumber;
                }
                else if (OptionValues.Display_TrimLine.IsValueOrShortValue(value))
                {
                    lineDisplayOptions |= LineDisplayOptions.TrimLine;
                }
                else if (OptionValues.Display_TrimLine.IsValueOrShortValue(value))
                {
                    lineDisplayOptions |= LineDisplayOptions.TrimLine;
                }
                else if (OptionValues.Display_TrimLine.IsValueOrShortValue(value))
                {
                    lineDisplayOptions |= LineDisplayOptions.TrimLine;
                }
                else if (OptionValues.Display_NoAlign.IsValueOrShortValue(value))
                {
                    noAlign = true;
                }
                else
                {
                    WriteOptionError(value, optionName, OptionValueProviders.DisplayProvider);
                    return(false);
                }
            }

            if (builder != null)
            {
                fileProperties = builder.ToImmutableArray();
            }

            return(true);
        }
예제 #11
0
        public static bool TryParse(
            IEnumerable <string> values,
            string optionName,
            OptionValueProvider provider,
            out Filter?filter,
            out FileNamePart namePart,
            bool allowNull = false,
            OptionValueProvider?namePartProvider  = null,
            FileNamePart defaultNamePart          = FileNamePart.Name,
            PatternOptions includedPatternOptions = PatternOptions.None)
        {
            filter   = null;
            namePart = defaultNamePart;

            string?pattern = values.FirstOrDefault();

            if (pattern == null)
            {
                if (allowNull)
                {
                    return(true);
                }
                else
                {
                    throw new InvalidOperationException($"Option '{OptionNames.GetHelpText(optionName)}' is required.");
                }
            }

            TimeSpan            matchTimeout = Regex.InfiniteMatchTimeout;
            string?             groupName    = null;
            string?             separator    = null;
            Func <string, bool>?predicate    = null;

            List <string>?options = null;

            foreach (string option in values.Skip(1))
            {
                int index = option.IndexOfAny(_equalsOrLessThanOrGreaterThanChars);

                if (index != -1)
                {
                    string key = option.Substring(0, index);

                    if (!provider.ContainsKeyOrShortKey(key))
                    {
                        WriteOptionError(option, optionName, provider);
                        return(false);
                    }

                    string value = option.Substring(index + 1);

                    if (OptionValues.Group.IsKeyOrShortKey(key))
                    {
                        groupName = value;
                        continue;
                    }
                    else if (OptionValues.ListSeparator.IsKeyOrShortKey(key))
                    {
                        separator = value;
                        continue;
                    }
                    else if (OptionValues.Part.IsKeyOrShortKey(key))
                    {
                        if (!TryParseAsEnum(
                                value,
                                out namePart,
                                provider: namePartProvider ?? OptionValueProviders.NamePartKindProvider))
                        {
                            WriteOptionValueError(
                                value,
                                OptionValues.Part,
                                namePartProvider ?? OptionValueProviders.NamePartKindProvider);
                            return(false);
                        }

                        continue;
                    }
                    else if (OptionValues.Timeout.IsKeyOrShortKey(key))
                    {
                        if (!TryParseMatchTimeout(value, out matchTimeout))
                        {
                            WriteOptionValueError(value, OptionValues.Timeout);
                            return(false);
                        }

                        continue;
                    }
                }

                if (Expression.TryParse(option, out Expression? expression))
                {
                    if (OptionValues.Length.IsKeyOrShortKey(expression.Identifier) &&
                        provider.ContainsKeyOrShortKey(expression.Identifier))
                    {
                        try
                        {
                            predicate = PredicateHelpers.GetLengthPredicate(expression);
                            continue;
                        }
                        catch (ArgumentException)
                        {
                            WriteOptionValueError(
                                expression.Value,
                                OptionValues.Length,
                                HelpProvider.GetExpressionsText("  ", includeDate: false));
                            return(false);
                        }
                    }
                    else
                    {
                        WriteOptionError(option, optionName, provider);
                        return(false);
                    }
                }

                (options ??= new List <string>()).Add(option);
            }

            if (!TryParseRegexOptions(
                    options,
                    optionName,
                    out RegexOptions regexOptions,
                    out PatternOptions patternOptions,
                    includedPatternOptions,
                    provider))
            {
                return(false);
            }

            switch (patternOptions & (PatternOptions.WholeWord | PatternOptions.WholeLine))
            {
            case PatternOptions.None:
            case PatternOptions.WholeWord:
            case PatternOptions.WholeLine:
            {
                break;
            }

            default:
            {
                string helpValue = OptionValueProviders.PatternOptionsProvider
                                   .GetValue(nameof(PatternOptions.WholeWord)).HelpValue;

                string helpValue2 = OptionValueProviders.PatternOptionsProvider
                                    .GetValue(nameof(PatternOptions.WholeLine)).HelpValue;

                WriteError($"Values '{helpValue}' and '{helpValue2}' cannot be combined.");

                return(false);
            }
            }

            if ((patternOptions & PatternOptions.FromFile) != 0 &&
                !FileSystemHelpers.TryReadAllText(pattern, out pattern, ex => WriteError(ex)))
            {
                return(false);
            }

            pattern = BuildPattern(pattern, patternOptions, separator);

            if (pattern.Length == 0)
            {
                throw new InvalidOperationException(
                          $"Option '{OptionNames.GetHelpText(optionName)}' is invalid: pattern cannot be empty.");
            }

            Regex?regex = null;

            try
            {
                regex = new Regex(pattern, regexOptions, matchTimeout);
            }
            catch (ArgumentException ex)
            {
                WriteError(ex, $"Could not parse regular expression: {ex.Message}");
                return(false);
            }

            int groupIndex = -1;

            if (groupName != null)
            {
                groupIndex = regex.GroupNumberFromName(groupName);
                if (groupIndex == -1)
                {
                    string message = $"Group '{groupName}' does not exist.";

                    string[] groupNames = regex.GetGroupNames();

                    if (groupNames.Length > 1)
                    {
                        message += " Existing group names: "
                                   + $"{TextHelpers.Join(", ", " and ", groupNames.Where(f => f != "0"))}.";
                    }

                    WriteError(message);
                    return(false);
                }
            }

            filter = new Filter(
                regex,
                isNegative: (patternOptions & PatternOptions.Negative) != 0,
                groupNumber: groupIndex,
                predicate: predicate);

            return(true);
        }
예제 #12
0
        private static bool TryParseRegexOptions(
            IEnumerable <string>?options,
            string optionsParameterName,
            out RegexOptions regexOptions,
            out PatternOptions patternOptions,
            PatternOptions includedPatternOptions = PatternOptions.None,
            OptionValueProvider?provider          = null)
        {
            regexOptions = RegexOptions.None;

            if (!TryParseAsEnumFlags(
                    options,
                    optionsParameterName,
                    out patternOptions,
                    provider: provider ?? OptionValueProviders.PatternOptionsProvider))
            {
                return(false);
            }

            Debug.Assert((patternOptions & (PatternOptions.CaseSensitive | PatternOptions.IgnoreCase))
                         != (PatternOptions.CaseSensitive | PatternOptions.IgnoreCase));

            if ((patternOptions & PatternOptions.CaseSensitive) != 0)
            {
                includedPatternOptions &= ~PatternOptions.IgnoreCase;
            }
            else if ((patternOptions & PatternOptions.IgnoreCase) != 0)
            {
                includedPatternOptions &= ~PatternOptions.CaseSensitive;
            }

            patternOptions |= includedPatternOptions;

            if ((patternOptions & PatternOptions.Compiled) != 0)
            {
                regexOptions |= RegexOptions.Compiled;
            }

            if ((patternOptions & PatternOptions.CultureInvariant) != 0)
            {
                regexOptions |= RegexOptions.CultureInvariant;
            }

            if ((patternOptions & PatternOptions.ECMAScript) != 0)
            {
                regexOptions |= RegexOptions.ECMAScript;
            }

            if ((patternOptions & PatternOptions.ExplicitCapture) != 0)
            {
                regexOptions |= RegexOptions.ExplicitCapture;
            }

            if ((patternOptions & PatternOptions.IgnoreCase) != 0)
            {
                regexOptions |= RegexOptions.IgnoreCase;
            }

            if ((patternOptions & PatternOptions.IgnorePatternWhitespace) != 0)
            {
                regexOptions |= RegexOptions.IgnorePatternWhitespace;
            }

            if ((patternOptions & PatternOptions.Multiline) != 0)
            {
                regexOptions |= RegexOptions.Multiline;
            }

            if ((patternOptions & PatternOptions.RightToLeft) != 0)
            {
                regexOptions |= RegexOptions.RightToLeft;
            }

            if ((patternOptions & PatternOptions.Singleline) != 0)
            {
                regexOptions |= RegexOptions.Singleline;
            }

            return(true);
        }
예제 #13
0
        public override void WriteOptionDescription(CommandOption option)
        {
            _writer.WriteString(option.Description);

            if (TryGetProvider(option, out OptionValueProvider? provider))
            {
                if (!string.IsNullOrEmpty(option.Description))
                {
                    _writer.WriteLine();
                    _writer.WriteLine();
                }

                OptionValueProvider?provider2 = provider;

                if (provider.Parent != null)
                {
                    provider2 = provider.Parent;
                }

                string metaValueUrl = provider2.Name;

                _writer.WriteLink(provider2.Name, "OptionValues.md" + MarkdownHelpers.CreateGitHubHeadingLink(metaValueUrl));

                _writer.WriteString(": ");

                using (IEnumerator <string> en = provider
                                                 .Values
                                                 .Where(f => !f.Hidden)
                                                 .Select(f => f.HelpValue)
                                                 .GetEnumerator())
                {
                    if (en.MoveNext())
                    {
                        while (true)
                        {
                            string value = en.Current;

                            Match metaValueMatch = Regex.Match(value, @"(?<==)\<[\p{Lu}_]+>\z");

                            if (metaValueMatch.Success &&
                                OptionValueProviders.ProvidersByName.ContainsKey(metaValueMatch.Value))
                            {
                                _writer.WriteInlineCode(value.Remove(metaValueMatch.Index));
                                _writer.WriteLink(
                                    metaValueMatch.Value,
                                    "OptionValues.md" + MarkdownHelpers.CreateGitHubHeadingLink(metaValueMatch.Value));
                            }
                            else
                            {
                                _writer.WriteInlineCode(en.Current);
                            }

                            if (en.MoveNext())
                            {
                                _writer.WriteString(", ");
                            }
                            else
                            {
                                break;
                            }
                        }

                        _writer.WriteString(".");
                    }
                }
            }

            if (!string.IsNullOrEmpty(option.Description) ||
                provider != null)
            {
                _writer.WriteLine();
                _writer.WriteLine();
            }
        }
예제 #14
0
 public OptionValueProvider(string name, OptionValueProvider?parent, IEnumerable <OptionValue> values)
 {
     Name   = name;
     Parent = parent;
     Values = values.ToImmutableArray();
 }
예제 #15
0
 public OptionValueProvider(string name, OptionValueProvider?parent, params OptionValue[] values)
 {
     Name   = name;
     Parent = parent;
     Values = values.ToImmutableArray();
 }