Program Listing for File CommandLineApp.h#
↰ Return to documentation for file (src/cli/CommandLineApp.h)
#pragma once
/* internal */
#include "CommandLine.h"
#include "StringCommandProcessor.h"
namespace Coral
{
static constexpr std::size_t default_max_line = 256;
static constexpr std::size_t default_max_commands = 16;
template <std::size_t max_commands = default_max_commands,
std::size_t depth = default_max_line,
std::size_t max_args = default_max_args, typename element_t = char,
class T = PrintfLogger>
class ElementCommandLineApp : public HasLogInterface<T>
{
public:
using CommandLine = ElementCommandLine<element_t, T>;
using Processor = StringCommandProcessor<depth, element_t, max_args>;
using Handler = std::function<void(CommandLine &)>;
using CommandRegistration = std::function<void(ElementCommandLineApp &)>;
ElementCommandLineApp(CommandRegistration register_commands,
typename Processor::Buffer &input,
LogInterface<T> *_log = nullptr)
: HasLogInterface<T>(_log),
processor(/* LCOV_EXCL_LINE */
input,
[this](const element_t **argv, std::size_t argc) {
process(argv, argc);
},
true /* auto_poll */),
commands(), command_index(0)
{
add_handler("help", [this](CommandLine &cli) { help(cli); });
register_commands(*this);
}
/* interface for registering a command */
void add_handler(const element_t *command, Handler handler,
const char *help = nullptr,
LogInterface<T> *_log = nullptr)
{
this->log(_log, "Added command handler for '%s'.\n", command);
commands[command_index].command = command;
commands[command_index].handler = handler;
commands[command_index].help = help;
command_index++;
}
void process(const element_t **argv, std::size_t argc)
{
CommandLine cli(argv, argc, this->logger);
bool handled = false;
for (std::size_t i = 0; i < command_index; i++)
{
auto &cmd = commands[i];
handled = cmd.handle(cli);
if (handled)
{
break;
}
}
if (not handled)
{
this->log(nullptr, "Command '%s' not found.\n",
cli.get_command().c_str());
help(cli);
}
}
protected:
Processor processor;
void help(CommandLine &cli)
{
(void)cli;
this->log(nullptr, "%zu commands registered:\n", command_index);
for (std::size_t i = 0; i < command_index; i++)
{
auto &cmd = commands[i];
this->log(nullptr, " %s: %s\n", cmd.command,
(cmd.help) ? cmd.help : "(unknown)");
}
}
struct Command
{
const element_t *command;
Handler handler;
const char *help = nullptr;
bool handle(CommandLine &cli)
{
bool should_handle =
strcmp(command, cli.get_command().c_str()) == 0;
if (should_handle)
{
handler(cli);
}
return should_handle;
}
};
std::array<Command, max_commands> commands;
std::size_t command_index;
};
using CommandLineApp = ElementCommandLineApp<>;
} // namespace Coral