tags:

views:

91

answers:

5

What I want is to add possibility to interact with application, and be able to extract information from application or event ask it to change some states.

For that purpose I though of building cli utility. The utility will connect to the application and send user commands (one line strings) to the application and wait for response from the application.

The command should contain: - command name (e.g. display-session-table/set-log-level etc.) - optionally command may have several arguments (e.g. log-level=10)

The question to choose syntax and to learn parse it fast and correctly.

I don't want to reinvent the wheel, so maybe there's already an answer out there.

+1  A: 

boost::program_options is worth a look.

David
I need to support several commands at once, each one with each own list of arguments. Can the lib handle it?
dimba
+2  A: 

Take a look at the interpreter example (example usage) from Boost.FunctionTypes. Note however that as it is it only supports free functions.

Georg Fritzsche
A: 

I would suggest using a JSON library.

Paul Nathan
+1  A: 

The Readline library could be useful.

caf
+1 Obviously :))
dimba
A: 

I use an unholy mix of readline, boost::spirit, and the factory pattern to handle all that. It wouldn't be nearly as unholy if it weren't for readlines unapologetic C syntax :)

The outer loop looks like this

    while(true)
    {
            char *line(NULL);
            line = readline((cmd.leaf() + " > ").c_str());
            if (line && *line)
            {
                    add_history(line);
                    int error = ParseLine(line,*s_g, std::cout);
                    free(line);

                    if (error == ErrQuit)
                            break;
                    if (error == ErrSave)
                    ....

Each command has a completion function and a parser/completion function

char **completeCreate(const std::vector<std::string> &, const char *text, int depth)
{
    switch (depth)
    {
            case 1:
            case 2:
            {
                    return  rl_completion_matches(text, rl_filename_completion_function);
                    break;
            }
            case 3:
            {
                    return rl_completion_matches(text, rulesFill);
                    break;
            }
    }
    return NULL;
}

Defines the completer for a command that takes two arguments, a filename and a string, which gets registered with the completion mechanism of readline through a factory + macro, that lets me register everything with something that looks like this

REG_COMP(Create, completeCreate);

On the parser side, I have a similar factory setup

int parseCreate(const std::vector<std::string> &names, Game &g, std::ostream &out)
{
    if (names.size() != 4)
            return parseHelpC(names, g, out);

    if (!CreateGame(names[1],names[2],names[3],g))
            return ErrGameCreation;

    return ErrNone;
}
REG_PARSE(Create,"CardList PowerList RuleSet");

that provides the actual logic and help text

I've left out huge swaths of code that glues everything together, but would be happy to share the hideousness that is the code base (it is currently a private git repository) I look forward to see if someone has something that works better.

McBeth