private bool TryEvaluateBundle(string arg, out ArgumentEvaluationResult result)
        {
            if (arg == null)
            {
                throw new ArgumentNullException(nameof(arg));
            }

            var match = BundledOptionRegex.Match(arg);

            result = match.Success && match.AreGroupsSuccessful(flag, bundle)
                    ? new ArgumentEvaluationResult(match.GetGroupValue(flag), match.GetGroupValue(bundle))
                    : ArgumentEvaluationResult.Failed;

            if (!(result.IsValid || result.IsBundled))
            {
                return(false);
            }

            /* We could interpolate each of the characters then evaluate Contains and Select,
             * but this works as well, and only Takes what we want. */
            foreach (var y in result.Name.TakeWhile(x => Contains($"{x}")).Select(x => $"{x}"))
            {
                result.Options.Add(Tuple.Create(y, this[y]));
            }

            result.Value = result.Name.Length == result.Options.Count
                ? null
                : result.Name.Substring(result.Options.Count);

            return(true);
        }
        private bool TryEvaluateArgument(string arg, out ArgumentEvaluationResult result)
        {
            if (arg == null)
            {
                throw new ArgumentNullException(nameof(arg));
            }

            var match = ValueOptionRegex.Match(arg);

            result = match.Success && match.AreGroupsSuccessful(flag, name)
                ? new ArgumentEvaluationResult(match.GetGroupValue(flag), match.GetGroupValue(name)
                                               , match.GetGroupValueOrDefault(roo).ToOptionValueType(), match.GetGroupValueOrDefault(val))
                : ArgumentEvaluationResult.Failed;

            if (!result.IsValid)
            {
                return(false);
            }

            // Remember, here we are evaluating the COMMAND LINE ARGUMENT itself.
            result.Options.Add(Tuple.Create(
                                   result.Name
                                   , Contains(result.Name) ? this[result.Name] : GetDefaultOption()
                                   ));

            return(true);
        }
        /// <summary>
        /// Visits a fleshed out <paramref name="context"/> upon each of the selected the
        /// <see cref="ArgumentEvaluationResult.Options"/>, rounding out elements such as
        /// <see cref="OptionContext.Option"/> itself, <see cref="OptionContext.OptionName"/>,
        /// and any <see cref="OptionContext.Parameters"/> that may be required. We will expect
        /// that <see cref="OptionContext.OptionIndex"/> will have been designated by virtual of
        /// the calling Arguments loop.
        /// </summary>
        /// <param name="context">The Current Context, at this stage we are expected to convey
        /// the Option(s), the actual Option Name used to trigger the invocation, as contrasted
        /// with a Option Prototype, and any further Option parameters Values. Once that is
        /// complete we may then trigger the Option Visitation, in which case we literally visit
        /// the Current Context upon the current Option of interest.</param>
        /// <param name="parts">Given the Parts evaluated as either Bundled or Conventional.</param>
        /// <param name="args">We expect to be handed the current view of the Command Line
        /// Arguments starting from the Current, Zero-based Argument. Any Option Parameters
        /// that require relay would either be parsed from the Current Argument, or subsequent
        /// One based Arguments.</param>
        /// <param name="count">Report the Count of the number of Arguments actually consumed
        /// by this Dispatch invocation, not including the Current argument.</param>
        /// <param name="processed">Captures all of the Processed Options.</param>
        /// <returns></returns>
        private bool TryDispatchOptionVisit(OptionContext context, ref ArgumentEvaluationResult parts
                                            , IReadOnlyList <string> args, out int count, out IEnumerable <Option> processed)
        {
            count = 0;

            // ReSharper disable once RedundantEmptyObjectOrCollectionInitializer
            var processedOptions = new Dictionary <Guid, Option> {
            };

            // ReSharper disable once RedundantAssignment
            bool IsBooleanType(Type targetType) => BooleanTypes.Any(t => targetType == t);
            bool IsNotBooleanType(Type targetType) => BooleanTypes.All(t => targetType != t);

            string RenderEnableBoolean(bool enable) => $"{enable}".ToLower();

            bool VerifyIsNeitherBundleNorArgument(params int[] indexes)
            {
                var max = indexes.Max();

                return(args.Count > max &&
                       indexes.All(i => !(TryEvaluateBundle(args[i], out _) || TryEvaluateArgument(args[i], out _))));
            }

            // ReSharper disable once IdentifierTypo
            bool TryUnbundleKeyValuePair(string s, char[] separators, out string[] results)
            => (results = s.Split(separators)).Length == 2;

            // Key is more of a Key at this point than a Name, used to lookup the Option.
            foreach (var(key, option) in parts.Options)
            {
                // Accounting for Parts.Value, Boolean Flags, is transparent with this approach.
                var currentCount = 0;

                /* Having closed the loop with this bookkeeping, then we can focus our undivided
                 * attention on Dispatching the correct Option Parameters to the next Option. */

                context.Option     = option;
                context.OptionName = $"{parts.Flag}{key}";
                context.Parameters.Clear();

                /* TODO: TBD: the dispatch heuristics are a more relax here, just simply because each
                 * individual Option may require a different set of parameters, but we still want to
                 * signal which actual arguments were consumed by either the dispatched bundled value,
                 * or the next value(s) in sequence, etc. */

                // Determine which other Parameters we should be able to furnish the next Dispatch.
                switch (context.Option)
                {
                // No-op in this case, we have what we came here for.
                case ISimpleActionOption _:
                    break;

                case IActionOption _ when parts.HasValue && !parts.EnableBoolean.HasValue:
                    context.Parameters.Add(parts.Value);
                    break;

                case IActionOption _ when parts.EnableBoolean.HasValue && !parts.HasValue:
                    context.Parameters.Add(RenderEnableBoolean(parts.EnableBoolean.Value));
                    break;

                case IActionOption _ when !(parts.HasValue || parts.EnableBoolean.HasValue) &&
                    VerifyIsNeitherBundleNorArgument(1):

                    context.Parameters.Add(args[++currentCount]);
                    break;

                case IKeyValueActionOption _ when parts.HasValue && !parts.EnableBoolean.HasValue &&
                    VerifyIsNeitherBundleNorArgument(1):

                    context.Parameters.Add(parts.Value);
                    context.Parameters.Add(args[++currentCount]);
                    break;

                case IKeyValueActionOption _ when parts.HasValue &&
                    !parts.EnableBoolean.HasValue &&
                    context.HasOption &&
                    TryUnbundleKeyValuePair(parts.Value, context.Option?.Separators?.ToArray(), out var xy):

                    context.Parameters.Add(xy[0]);
                    context.Parameters.Add(xy[1]);
                    break;

                // Always assume the Boolean Shorthand is the Value member of the Key Value Pair.
                case IKeyValueActionOption o when parts.HasValue &&
                    parts.EnableBoolean.HasValue &&
                    o.TryVerifyKeyValueActionOptionTypes(valueTypeCallback: IsBooleanType) :

                        context.Parameters.Add(parts.Value);
                    context.Parameters.Add(RenderEnableBoolean(parts.EnableBoolean.Value));
                    break;

                // After handling the specific leading edge use case, then we may significantly reduce subsequent case load.
                case IKeyValueActionOption o when !parts.HasValue &&
                    parts.EnableBoolean.HasValue &&
                    o.TryVerifyKeyValueActionOptionTypes(IsNotBooleanType, IsBooleanType) &&
                    VerifyIsNeitherBundleNorArgument(1):

                    context.Parameters.Add(args[++currentCount]);
                    context.Parameters.Add(RenderEnableBoolean(parts.EnableBoolean.Value));
                    break;

                case IKeyValueActionOption _ when !(parts.HasValue || parts.EnableBoolean.HasValue) &&
                    VerifyIsNeitherBundleNorArgument(1, 2):

                    context.Parameters.Add(args[++currentCount]);
                    context.Parameters.Add(args[++currentCount]);
                    break;
                }

                // Which culminates in an Option Visit.
                context.Visit();

                // There is nothing further to Report when we encounter the Default Option.
                if (context.Option is IDefaultOption)
                {
                    continue;
                }

                // Relay the Processed Options via the Context driven view.
                processedOptions[context.Option.Id] = context.Option;

                // Pull the Maximum Count forward to be reconciled by the Caller.
                count = Max(count, currentCount);
            }

            return((processed = processedOptions.Values.ToArray()).Any());
        }