예제 #1
0
        /// <summary>
        ///     Generates help info for the given command.
        /// </summary>
        /// <param name="prog">The program from which the help command is being run.</param>
        /// <param name="cmd">The command for which to generate the help info.</param>
        /// <returns>A string containing the help information.</returns>
        /// <seealso cref="Help()" />
        /// <seealso cref="Help(Commander.Program,Commander.Cog)" />
        public string Help(Program program, CommandObj cmd)
        {
            /*
             * [Command Name]
             * Description:
             * <description>
             *
             * Usage:
             * <usage>
             *
             * Examples:
             * <examples>
             */

            var cmdName = program.IsCaseSensitive ? cmd.Name : cmd.Name.ToLower();
            var info    = new StringBuilder();

            info.Append('[').Append(cmdName).Append("]\n").Append("Description:\n").Append(cmd.Description);
            info.Append("\n\nUsage:\n").Append(cmd.Usage(program));

            if (cmd.Examples.Length > 0)
            {
                info.Append("\n\nExamples:\n");
                foreach (var example in cmd.Examples)
                {
                    info.Append(example).Append('\n');
                }

                // remove trailing \n char
                info.Remove(info.Length - 1, 1);
            }

            return(info.ToString());
        }
예제 #2
0
 public void AddChild(CommandObj cmd)
 {
     if (Children.ContainsKey(cmd.Name))
     {
         return;
     }
     Children.Add(cmd.Name, cmd);
     cmd._parent = this;
 }
예제 #3
0
        public CommandObj(object cog, CommandObj parent, MethodInfo methodInfo, bool invokable, string name,
                          string description, string[] examples)
        {
            _cog    = cog;
            _parent = null;

            Name        = name;
            Description = description;
            Examples    = examples;
            Invokable   = invokable;
            _methodInfo = methodInfo;
            Children    = new Dictionary <string, CommandObj>();

            parent?.AddChild(this);
        }
예제 #4
0
        /// <summary>
        ///     Generates the call string for the given command.
        /// </summary>
        /// <param name="cmd">The command for which to generate the call string.</param>
        /// <returns>The call string for the given command.</returns>
        public static string CallString(CommandObj cmd)
        {
            var names = new Stack <string>();

            while (cmd != null)
            {
                names.Push(cmd.Name);
                cmd = cmd._parent;
            }

            var callstring = "";
            var name       = "";

            while (names.TryPop(out name))
            {
                callstring += name + " ";
            }

            callstring = callstring.Substring(0, callstring.Length - 1);
            return(callstring);
        }
예제 #5
0
        public Cog(Program prog, string name = "", string description = "")
        {
            IsCaseSensitive = prog.IsCaseSensitive;
            IsGroup         = false;
            Commands        = new Dictionary <string, CommandObj>();

            // process attributes
            // set name, description and IsGroup based on presence of attributes and variables
            var attr = GetType().GetCustomAttribute(typeof(CommandGroup));

            if (attr != null)
            {
                var cmdGrp = attr as CommandGroup;
                Name        = IsCaseSensitive ? cmdGrp.Name.ToLower() : cmdGrp.Name;
                Description = StringProcessor.Process(cmdGrp.Description, prog);
                IsGroup     = true;
                Commands.Add(Name, new CommandObj(this, null, false, Name, Description, new string[] { }));
            }
            else
            {
                if (name.Length == 0)
                {
                    Name = GetType().Name;
                }
                else
                {
                    Name = name;
                }

                if (description.Length == 0)
                {
                    Description = "Not given.";
                }
                else
                {
                    Description = StringProcessor.Process(description, prog);
                }
            }

            Utils.Debug($"Cog: {Name}, {Description}\nIsGroup: {IsGroup.ToString()}");

            CommandObj group = null;

            if (IsGroup)
            {
                @group = Commands[Name];
            }

            // process functions
            var methodInfo = GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance);

            foreach (var method in methodInfo)
            {
                var rawAttrib = method.GetCustomAttribute(typeof(Command));
                if (rawAttrib == null)
                {
                    continue;
                }

                var attrib = rawAttrib as Command;

                // process command

                // check that command function return value is string
                if (method.ReturnType != typeof(string))
                {
                    throw new AttributeError($"cog: {Name}.{method.Name}() does not return a string");
                }

                var cmdName = attrib.Name == null ? method.Name : attrib.Name;

                // parse examples
                var examples = new List <string>();
                var attribs  = method.GetCustomAttributes(typeof(Example));
                foreach (var a in attribs)
                {
                    examples.Add((a as Example).Val);
                }

                CommandObj parent = null;

                // check if command is a subcommand
                if (attrib.Parent != null)
                {
                    var attrParent = IsCaseSensitive ? attrib.Parent : attrib.Parent.ToLower();
                    if (Commands.ContainsKey(attrParent))
                    {
                        parent = Commands[attrParent];
                    }
                    else
                    {
                        CommandObj FindParent(CommandObj command, string strParent)
                        {
                            var p     = IsCaseSensitive ? strParent : strParent.ToLower();
                            var cName = IsCaseSensitive ? command.Name : command.Name.ToLower();

                            if (cName == p)
                            {
                                return(command);
                            }

                            return(command.AllChildren().Select(commandObj => FindParent(commandObj, strParent))
                                   .FirstOrDefault());
                        }

                        parent = Commands.Values.Select(c => FindParent(c, attrParent)).FirstOrDefault();
                        if (parent == null)
                        {
                            throw new AttributeError($"could not find parent: {attrParent} in the scope of this cog");
                        }
                    }
                }

                var cmd = new CommandObj(this, parent, method, true, cmdName, attrib.Description, examples.ToArray());
                cmd.Description = StringProcessor.Process(cmd.Description, prog, cmd);
                for (var i = 0; i < cmd.Examples.Length; i++)
                {
                    cmd.Examples[i] = StringProcessor.Process(cmd.Examples[i], prog, cmd);
                }

                if (group != null && parent == null)
                {
                    @group.AddChild(cmd);
                }
                else if (parent == null)
                {
                    Commands.Add(cmdName, cmd);
                }
            }
        }
예제 #6
0
파일: Program.cs 프로젝트: HOWZ1T/Commander
        /// <summary>
        ///     Processes the arguments and dispatches the input to the appropriate cog/command.
        /// </summary>
        /// <param name="args">The input arguments to the program.</param>
        /// <returns>The result of the execution from the program based on the given input arguments.</returns>
        /// <exception cref="ProgramError"></exception>
        private string DispatchCommand(string[] args)
        {
            if (args.Length == 0)
            {
                throw new ProgramError("No command given.");
            }

            // check for command group name
            var name = args[0];

            Utils.ShiftArgs(ref args);

            if (!IsCaseSensitive)
            {
                name = name.ToLower();
            }

            if (UseProgramNamePrefix)
            {
                var pn = IsCaseSensitive ? Name : Name.ToLower();
                if (name != pn)
                {
                    throw new ProgramError("Must prefix command with program name!");
                }

                if (args.Length < 1)
                {
                    throw new ProgramError("No command given!");
                }

                name = args[0];
                Utils.ShiftArgs(ref args);
                if (!IsCaseSensitive)
                {
                    name = name.ToLower();
                }
            }

            // utility function for running the command tree
            CommandObj FindCommand(string cmdName)
            {
                foreach (var pair in _cogs)
                {
                    var obj = pair.Value.GetCommand(cmdName);
                    if (obj != null)
                    {
                        return(obj);
                    }
                }

                return(null);
            }

            // handle help command
            if (name == "help")
            {
                // help called with no args
                if (args.Length <= 0)
                {
                    return(Help.Help());
                }

                var        cogName = args[0];
                var        cg      = GetCog(cogName);
                CommandObj cmd     = null;
                if (cg != null)
                {
                    Utils.ShiftArgs(ref args);
                    if (args.Length <= 0)
                    {
                        return(Help.Help(this, cg));
                    }

                    cmd = cg.GetCommand(args.First());
                }

                // if cmd is still null, perform cog independent search
                if (cmd == null)
                {
                    cmd = FindCommand(args.First());
                }

                if (cmd == null)
                {
                    // help was called on itself
                    if (args.First() == "help" || args.Last() == "help")
                    {
                        return(Help.Help());
                    }

                    throw new ProgramError($@"could not find any command called: {args.First()}");
                }

                return(Help.Help(this, cmd));
            }

            var result = "";
            var cog    = GetCog(name);

            if (cog != null)
            {
                result = cog.Execute(this, name, args);
            }
            else
            {
                Utils.Debug($"cog not found for name: {name}, attempting to find function...");

                // attempt to find function
                var cmd = FindCommand(name);
                if (cmd == null)
                {
                    throw new ProgramError($"could not find any command called: {name}");
                }

                result = cmd.Invoke(this, args);
            }

            return(result);
        }