| Shellminator V3.0.1
    Simple Terminal | 
Until now, we’ve focused on how to configure the terminal, but we haven’t yet talked about what to actually do with the commands that are entered.
Of course, you could take a simple approach and use a massive if-else chain in the execution function to check if the received text matches certain strings. However, once you have more than 10–15 commands, this becomes inefficient and hard to maintain. And let’s not even get started on the complications that arise if the command includes arguments.
While it’s certainly possible to handle this manually, we’re happy to tell you there’s a much better solution. We’ve developed a command processor called the Commander API. This API is a standalone project, designed to be highly optimized while remaining user-friendly. It took quite a bit of effort to get it to this level, but the end result is something we think you’ll really appreciate.
In the following examples, we’ll show you how to connect Shellminator with the Commander API to take your command-line functionality to the next level. Let’s get started!
First, we need to install the Commander API, just like we did with Shellminator. If you need extra guidance, the Commander API website provides detailed instructions for installation.
Next, we include the necessary libraries:
Just like Shellminator, the Commander API operates by deriving an object that will handle tasks for us:
Now comes the design phase. We need to decide how many commands the system will support. The great news is that the system can be expanded or reduced at any time (as long as backward compatibility is not an issue). For this example, let’s define three commands: cat, dog, and sum.
cat and dog will simply print text. sum, however, will perform a calculation—it will add two numbers if valid arguments are provided.To implement these commands, we need to create callback functions. Similar to Shellminator, the Commander API is designed with a non-blocking architecture, so you’ll use callbacks to define external hooks for each command:
The structure of callback functions in Commander API is fixed: 
bool char *args, CommandCaller* caller You’re free to name your callback functions however you like. These callbacks will form the foundation for handling your commands efficiently.
The next step is crucial for ensuring everything works properly. We need to tell our Commander object which commands it should recognize. The easiest way to do this is by creating a command tree. This "tree" is essentially an array where each element is a structure that contains:
At first, this might sound a bit abstract, but don’t worry—we’ve created a macro to make this process much simpler:
The command tree must always be of type Commander::systemCommand_t. Each element should be defined using the systemCommand macro in the following format:
Once the command tree is set up, it’s time to connect it to Shellminator. In the previous examples, we derived a class from the Shellminator class to create a terminal interface. However, when using Commander, we need to start from the ShellminatorCommanderInterface class instead. This class is built on top of Shellminator and comes pre-configured to work seamlessly with Commander. The usage is almost identical, so there’s no need to worry about any steep learning curve.
Here’s how to create the terminal object with Commander integration:
For Commander to function correctly, it must be initialized. Under the hood, Commander performs some abstract but essential tasks during this initialization phase. During this time, it temporarily uses a fair amount of stack memory to create an optimized internal structure. This structure allows Commander to efficiently process commands later on.
To avoid issues with memory, it’s best to initialize Commander as early as possible in your program. Additionally, you can assign a debug channel for easier troubleshooting in case something doesn’t work as expected. Here’s how to initialize Commander:
The final step to complete the setup is implementing the callback functions we declared earlier. Let’s focus on the callback for the sum command, as it’s the most complex of the three:
args: This is a simple C-style string containing the arguments passed to the command (if any). For the sum command, it should contain two integers separated by a space.caller: This is a pointer to the Commander object that invoked this function. It acts as an interface for communicating back to the user. For example, you can print messages or errors using its print and println methods.sscanf to extract two integers (a and b) from the args string. caller->print and then returns false to indicate failure.caller->print and caller->println to display the result in the following format: a + b = sumtrue to indicate successful execution.caller->print() and caller->println(): When writing output in Commander callbacks, always use these methods. They ensure the output is correctly routed to the response channel.true, when the command was executed without problem. When any problem occurs, it must return with false.
Here are a few things you might want to try out in the demo below:
cat → Executes the cat command, and you'll see the response from the cat_func callback. Cat → You'll get a Command "Cat" not found! error because the system is case-sensitive. dog → Executes the dog command, and you'll see the response from the dog_func callback. help → The help command still works as expected. ? → Does the same thing as help, just a shortcut. sum → Error message: _"Executes the cat command, and you'll see the response from the cat_func callback."_ sum command. sum? → Displays information on how to use the sum command. sum 10 20 → Adds the two numbers and prints the result: 30.