Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

CommandExecutor

Description

CommandExecutor is a parser that calls a function defined by a string. To do this, CommandExecutor searches for a ConsoleCommand with the given name, parses the arguments and calls the command. CommandExecutor is also able to give hints to a function (what the function does) and to complete classnames, functionnames and arguments (see ArgumentCompleter).

All existing ConsoleCommands are stored in maps: Commands belonging to a class are stored in the Identifier of the class while shortcuts are stored in a map located in the CommandExecutor itself.

Another feature: CommandExecutor can evaluate a given command without calling it. To achieve this, CommandExecutor returns a CommandEvaluation, containing a pointer to the ConsoleCommand and all arguments stored in MultiTypes, already converted to the requested type. This allows you to execute an evaluated command really fast, which is of interest if you execute the same command over and over.

To execute more complex commands, CommandExecutor uses TclBind.

Usage

execute()

execute(string) parses the string and searches a ConsoleCommand with the given name. Given arguments (separated by spaces) are used to execute the ConsoleCommand.

string has to be a complete ConsoleCommand (complete in the sense that the command exists and all needed arguments are given), otherwise the CommandExecutor returns false and sends an error message to the output.

  • Example 1:
    CommandExecutor::execute("myfunction 10");
    

This is equal to myfunction(10) provided that "myfunction" was declared as a ConsoleCommand.

  • Example 2:
    CommandExecutor::execute("MyClass myfunction 0.1 0.2 0.3");
    

This is equal to MyClass::myfunction(0.1, 0.2, 0.3) provided that the function "myfunction" of the class "MyClass" was declared as a ConsoleCommand.

The execute function optionally takes a second argument: execute(string, bUseTcl). If bUseTcl is set to true (this is the default!) a command is first passed to Tcl (see TclBind for more information). Tcl parses the command, executes all Tcl-related code and if it finds a ConsoleCommand only known to Orxonox it passes the command back to CommandExecutor::execute with bUseTcl = false.

  • Example 3:
    CommandExecutor::execute("MyClass myfunction [expr 10+10]");
    

This command will be sent to Tcl. Tcl first evaluates the subcommand within brackets expr 10+10 which results 20 and then returns "MyClass myfunction 20" back to Orxonox where it will be executed equivalent to MyClass::myfunction(20).

hint()

hint(string) returns a help message providing some information about an incomplete command (incomplete in the sense that not all possible arguments are yet given). This includes a list of the requested arguments and default-values (if any). If there's a description of the command, it is displayed too.

If string doesn't describe a unique ConsoleCommand, hint returns a list of possible commands matching the already given fragment. It also returns a list of possible arguments if there's an ArgumentCompleter declared for the current argument.

  • Example 1 (function description, argument list, default values):
    class MyClass
    {
        static void myfunction(int value, bool condition, const std::string& name);
    };
    
    SetConsoleCommand(MyClass, myfunction, true)
        .defaultValue(1, false)     // 1 refers to the second argument (condition)
        .defaultValue(2, "Default") // 2 refers to the third argument (name)
        .description("This is a useless testfunction!");
    
    // Get the hint:
    CommandExecutor::hint("MyClass myfunction");
    
    // Output:
     > This is a useless testfunction!
     > myfunction: {int} [bool=false] [string=Default]
    
  • Example 2 (possible classes and functions, possible arguments):
    class MyClass
    {
        static void myfunction(int value, bool condition, const std::string& name);
    };
    
    SetConsoleCommand(MyClass, myfunction, true)
        .defaultValue(1, false)     // 1 refers to the second argument (condition)
        .defaultValue(2, "Default") // 2 refers to the third argument (name)
        .description("This is a useless testfunction!")
        .argumentCompleter(2, autocompletion::mynames()); // argument completion for the name
    
    // First try an empty string: We get a list of all possible classes and functions
    CommandExecutor::hint("");
     > myfunction
     > MyClass
    
    // Now start typing the classname: We get a list of all possible
    // classnames (only MyClass in our example)
    CommandExecutor::hint("mycl");
     > MyClasses
    
    // We've finished the classname, now we get a list of all functions
    // of this class (only myfunction in our example)
    CommandExecutor::hint("MyClass ");
     > myfunction
    
    // There's still only one possible function:
    CommandExecutor::hint("MyClass myfunc");
     > myfunction
    
    // Now we get the hint from example 1
    CommandExecutor::hint("MyClass myfunction ");
     > This is a useless testfunction!
     > myfunction: {int} [bool=false] [string=Default]
    
    // As soon as we start typing the third argument (notice the space after the
    // second argument) we get a list of all possible arguments for "name" because
    // we've added an ArgumentCompletor:
    CommandExecutor::hint("MyClass myfunction 10 true ");
     > Adam Bernd Claude Default Eric Elton Fred Hank
    
    // We start typing the third argument, the list of possible arguments reduces
    // to arguments starting with the given letter:
    CommandExecutor::hint("MyClass myfunction 10 true e");
     > Eric Elton
    
    // We type another letter and the list reduces even more:
    CommandExecutor::hint("MyClass myfunction 10 true er");
     > Eric
    

complete()

complete(string) looks at the list of possible classnames, functionnames and arguments (like hint() in example 2) and trys to complete the command if there's only one possibility.

Note: If there's only one possible class with only one function and only one possible argument, complete() returns the whole command.

  • Example 2:
    // Existing functions:
    // abc, function1, function2, test, temporary
    
    CommandExecutor::complete("a");
    // returns "abc" because it's the only possibility
    
    CommandExecutor::complete("fun");
    // returns "function" because function1 and function2 are possible and
    // "function" is the common begin of both
    
    CommandExecutor::complete("t");
    // returns "te" because it's the common begin of "test" and "temporary"
    
  • Example 2:
    // Existing classes:
    // MyClass
    
    // Existing functions in MyClass:
    // myfunction
    
    // Possible arguments of MyClass::myfunction:
    // 10
    
    CommandExecutor::complete("m");
    // returns "MyClass myfunction 10"
    

evaluate()

evaluate(string) parses string just as execute() but doesn't execute the command. Instead an instance of CommandEvaluation is returned, containing the command split up into a a pointer to the ConsoleCommand and a list of all arguments stored in MultiTypes already converted to the desired type.

With this you can separate between parsing and execution of a command which is useful if you need good performance (for example if a command is bound to a key and pressed 20 times per second).

Illustration

The illustration shows how the CommandExecutor executes a ConsoleCommand by searching for the specified command in the shortcut list and the lists of all Identifiers and then executes the command by calling the Functor. At the end, it stores the returnvalue.

Last modified 8 years ago Last modified on Apr 12, 2017, 10:41:41 PM

Attachments (1)

Download all attachments as: .zip