示例#1
0
        /// <summary>
        /// Parses the specified content to a new <see cref="InfoContext"/>.
        /// </summary>
        public static InfoContext Parse(string content)
        {
            var   ctx = new InfoContext();
            Match m   = new Regex(MAIN_PARSER).Match(content);

            ctx.Content = content;

            if (!m.Success)
            {
                ctx.ErrorReason = "The content specified failed to successfully parse.";
                return(ctx);
            }

            ctx.Modules = new Regex(MODULE_PARSER)
                          .Matches(m.Groups[1].Value)
                          .Where(x => x.Success)
                          .Select(x => x.Groups[1].Value);

            ctx.Groups = new Regex(GROUP_PARSER)
                         .Matches(m.Groups[2].Value)
                         .Where(x => x.Success)
                         .Select(x => x.Groups[1].Value);

            ctx.Root = m.Groups[2].Value + m.Groups[3].Value;

            ctx.HasPriority = m.Groups[4].Success;

            if (ctx.HasPriority)
            {
                ctx.Priority = int.TryParse(m.Groups[4].Value, out int index) ? index : 0;
            }

            ctx.Type = GetTypeValue(m.Groups[5].Value);

            // If an overload index is specified AND the type (if specified) is not a command
            if (ctx.Type.GetValueOrDefault(InfoType.Command) != InfoType.Command && m.Groups[4].Success)
            {
                ctx.ErrorReason = $"{ctx.Type?.ToString()}s do not support overload indexing.";
                return(ctx);
            }

            ctx.Parameter = m.Groups[6].Value;

            // If a parameter is specified AND the type (if specified) is not a command
            if (ctx.Type.GetValueOrDefault(InfoType.Command) != InfoType.Command && Check.NotNull(m.Groups[6].Value))
            {
                ctx.ErrorReason = $"{ctx.Type.ToString()}s do not support parameters.";
                return(ctx);
            }

            ctx.Page = (int.TryParse(m.Groups[7].Value, out int page) ? page : 1) - 1;

            return(ctx);
        }
示例#2
0
        public ContextNode Search(string content)
        {
            InfoContext ctx = InfoContext.Parse(content);

            InfoType type = InfoType.Unknown;

            if (!ctx.IsSuccess)
            {
                throw new Exception($"The InfoContext failed to parse: {ctx.ErrorReason}");
            }

            // Get the initial location of the parent to peek
            ModuleInfo module = GetInnerModule(ctx);
            ModuleInfo group  = GetInnerGroup(ctx, module);
            IEnumerable <CommandInfo> commands  = null;
            ParameterInfo             parameter = null;

            // If a type wasn't initialized, find the closest matching value
            type = ctx.Type.GetValueOrDefault(GetValue(ctx.Root, group ?? module).Type);

            switch (type)
            {
            case InfoType.Module:
                module = GetModule(ctx.Root, group ?? module);
                break;

            case InfoType.Group:
                group = GetGroup(ctx.Root, group ?? module);
                break;

            case InfoType.Command:
                commands = GetCommands(ctx.Root, group ?? module);
                break;
            }

            if (type == InfoType.Command)
            {
                if (!Check.NotNullOrEmpty(commands))
                {
                    throw new ValueNotFoundException($"No commands could be found that matched the name '{ctx.Root}'.");
                }

                // If a priority was specified, slim the search down to that specific command
                if (ctx.HasPriority)
                {
                    commands = commands.Where(x => x.Priority == ctx.Priority);

                    if (!Check.NotNullOrEmpty(commands))
                    {
                        throw new ValueNotFoundException($"The priority for the specified command does not exist.");
                    }

                    if (commands.Count() > 1)
                    {
                        throw new MultiMatchException("The priority for the specified command exists in more than one instance.");
                    }

                    type = InfoType.Overload;
                }

                // If a parameter was specified, attempt to find the best match possible
                if (Check.NotNull(ctx.Parameter))
                {
                    IEnumerable <ParameterInfo> parameters = new List <ParameterInfo>();
                    commands.ForEach(x => parameters = parameters.Concat(GetParameters(x, ctx.Parameter)));

                    if (!Check.NotNullOrEmpty(parameters))
                    {
                        throw new ValueNotFoundException("The parameter specified could not be found within any of the commands");
                    }

                    if (parameters.Count() > 1)
                    {
                        throw new MultiMatchException($"The parameter enlisted is specified for multiple commands.");
                    }

                    parameter = parameters.First();
                    type      = InfoType.Parameter;
                }
            }

            // Return the node value based on the finalized type that was found or given
            return(type switch
            {
                InfoType.Module => new ModuleNode(module),
                InfoType.Group => new ModuleNode(group),
                InfoType.Overload => new OverloadNode(commands.First()),
                InfoType.Command => new CommandNode(commands),
                InfoType.Parameter => new ParameterNode(parameter),
                _ => throw new ValueNotFoundException("A ContextNode value could not be created with the given context.")
            });