Man machine interface command syntax and parsing - c++

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.

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

boost::program_options is worth a look.

The Readline library could be useful.

I would suggest using a JSON library.

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.

Related

Interactive shell via UART serial for Arduino?

I would like to implement an interactive shell via UART serial port for Arduino, with pure C++ OOP style code. But I think if there are too many if-else judgements when judging the user input commands in the code, it will be a bit ugly,
So I would like to ask that, is there any way to avoid using if-else statement? For example,
BEFORE:
while(Serial.available())
{
serialReceive = Serial.readString();// read the incoming data as string
Serial.println(serialReceive);
}
if(serialReceive.equals("factory-reset"))
{
MyService::ResetSettings();
}
else if(serialReceive.equals("get-freeheap"))
{
MyService::PrintFreeHeap();
}
else if(serialReceive.equals("get-version"))
{
MyService::PrintVersion();
}
AFTER:
while(Serial.available())
{
serialReceive = Serial.readString();// read the incoming data as string
Serial.println(serialReceive);
}
MagicClass::AssignCommand("factory-reset", MyService::ResetSettings);
MagicClass::AssignCommand("get-freeheap", MyService::PrintFreeHeap);
MagicClass::AssignCommand("get-version", MyService::PrintVersion);
You can have an array that stores a function pointer along with the string that triggers the command (you can create a struct to store both).
Unfortunately Arduino does not support the std::vector class so for my example I will use c type arrays. However there is a library for Arduino that adds some STL support for Arduino https://github.com/maniacbug/StandardCplusplus (also with this library you can use the functional library to make passing functions as arguments easier)
//struct that stores function to call and trigger word (can actually have spaces and special characters
struct shellCommand_t
{
//function pointer that accepts functions that look like "void test(){...}"
void (*f)(void);
String cmd;
};
//array to store the commands
shellCommand_t* commands;
With this you can either initialize the command array to one size on start or resize it every time you add a command, it just depends on your use case.
A basic function that assumes you have already allocated enough space in the array for adding a command could look like this
int nCommands = 0;
void addCommand(String cmd, void (*f)(void))
{
shellCommand_t sc;
sc.cmd = cmd;
sc.f = f;
commands[nCommands++] = sc;
}
Then inside your setup function you can add your commands in a similar fashion as you have above
addCommand("test", test);
addCommand("hello world", helloWorld);
Lastly in your loop function you can use a for loop to look through all of the commands check the input string against all of the command strings.
You can call the function of the matched command like this
(*(commands[i].f))();

What is the proper C++ way of mapping objects to functions?

What I mean is, I'm making a program that takes parameters from the user (as many as he wishes to enter at one time) by means of the console, e.g.
-p /users/me/myFolder/myHtmlFile.html -d /users/me/myOtherFolder -n myHmtlFileStyles -r
would set the parameters -p, -d and -n, then run the program (cause that's what -r does). I've already written a function that goes through each substring surrounded by whitespace in the input string. So I suspect the n00b design pattern would be something like
if (this_substring == "-p")
{
// ... run some procedure
}
else if (this_substring == "-d")
{
// ... run some procedure
}
else if (this_substring == "-n")
{
// ... run some procedure
}
else if (this_substring == "-r")
{
// ... run some procedure
}
else
{
// ... trigger not recognized; throw an error
}
but I'm sure there is a more elegant and proper way to do it. For instance, is there a way of mapping strings to functions? Does there exist something like
std::map<std::string, function> triggerMap = {{"-p", function1()}, {"-d", function2()}, "-n", function3()}, {"-r", function4()}};
??????
You can build an std::unordered_map from strings to function objects, initialize the function object with a lambda and call it based on its key:
std::unordered_map<std::string, std::function<void()>> fns {
{
"-p",
[]() {
// do stuff
}
},
{
"-d",
[]() {
// do something else
}
}
};
fns[param]();
It depends upon which standard you are following. I strongly suggest to use C++11 (e.g. with a recent GCC 4.9 compiler, using -std=c++11). Then use std::function and anonymous lambdas closures.
BTW, you could use (if on Linux) glibc parsing program arguments facilities.
Of course, you can use function pointers.
But I would recommend you to just use getopt
See: http://www.gnu.org/software/libc/manual/html_node/Example-of-Getopt.html
In your case:
while ((c = getopt (argc, argv, "p:d:n:r:")) != -1)
{
switch (c)
{
case 'p':
function(optarg);
break;
case 'd':
function(optarg);
break;
case 'n':
function(optarg);
break;
case 'r':
function(optarg);
break;
}
}
Use switch and a bunch of cases. Identify the flags (-r, -n, etc), extract the character and use that as the case label. Not as elegant, perhaps, as anonymous lambda closures, but more generically C++.

Access pre-compiled functions within a class C++/11

Sorry if the title is misleading, I'm currently looking for solutions to the following:
I'm developing a library, for other people to use. They have to follow a strict design concept and the way they structure any additional features within the library. They all use Linux and (Vim) and as such as are allowed to use terminal commands (i.e to be able to compile etc..) and we all use clang as a compiler.
My question is this: Let's suppose I write a function called: "checkCode":
template<typename T>
void checkCode(T&& codeSnippet)
{
//// code
}
I want to make this function run so whenever they type "checkCode" in a terminal this function is therefore called. I know using clang thy have similar functionality, however, this is understandable as you're using the whole of clang. So:
1) Is it possible to just compile a class, and then access each of the functions through
the .dylab | .so file?
2) Might it be a better idea, or, better to take a copy of the source of clang, add this functionality and role it out to those using and contributing to the library? This would be like an additional add-on to clang?
Thanks
you could use one executable and symbolic links to it like busybox:
int main(int argc, char **argv)
{
string programName = argv[0];
size_t lastSlash = programName.find_last_of('/');
if(lastSlash != string::npos)
programName = programName.substr(lastSlash + 1);
if(programName == "function_1")
{
function_1();
return 0;
}
if(programName == "function_2")
{
function_2();
return 0;
}
// ...
// normal main code
return 0;
}

boost::program_options : iterating over and printing all options

I have recently started to use boost::program_options and found it to be highly convenient. That said, there is one thing missing that I was unable to code myself in a good way:
I would like to iterate over all options that have been collected in a boost::program_options::variables_map to output them on the screen. This should become a convenience function, that I can simply call to list all options that were set without the need to update the function when I add new options or for each program.
I know that I can check and output individual options, but as said above, this should become a general solution that is oblivious to the actual options. I further know that I can iterate over the contents of variables_map since it is simply an extended std::map. I could then check for the type containd in the stored boost::any variable and use .as<> to convert it back to the appropriate type. But this would mean coding a long switch block with one case for each type. And this doesn't look like good coding style to me.
So the question is, is there a better way to iterate over these options and output them?
As #Rost previously mentioned, Visitor pattern is a good choice here. To use it with PO you need to use notifiers for your options in such a way that if option is passed notifier will fill an entry in your set of boost::variant values. The set should be stored separately. After that you could iterate over your set and automatically process actions (i.e. print) on them using boost::apply_visitor.
For visitors, inherit from boost::static_visitor<>
Actually, I made Visitor and generic approach use more broad.
I created a class MyOption that holds description, boost::variant for value and other options like implicit, default and so on. I fill a vector of objects of the type MyOption in the same way like PO do for their options (see boost::po::options_add()) via templates. In the moment of passing std::string() or double() for boosts::variant initialization you fill type of the value and other things like default, implicit.
After that I used Visitor pattern to fill boost::po::options_description container since boost::po needs its own structures to parse input command line. During the filling I set notifyer for each option - if it will be passed boost::po will automatically fill my original object of MyOption.
Next you need to execute po::parse and po::notify. After that you will be able to use already filled std::vector<MyOption*> via Visitor pattern since it holds boost::variant inside.
What is good about all of this - you have to write your option type only once in the code - when filling your std::vector<MyOption*>.
PS. if using this approach you will face a problem of setting notifyer for an option with no value, refer to this topic to get a solution: boost-program-options: notifier for options with no value
PS2. Example of code:
std::vector<MyOptionDef> options;
OptionsEasyAdd(options)
("opt1", double(), "description1")
("opt2", std::string(), "description2")
...
;
po::options_descripton boost_descriptions;
AddDescriptionAndNotifyerForBoostVisitor add_decr_visitor(boost_descriptions);
// here all notifiers will be set automatically for correct work with each options' value type
for_each(options.begin(), options.end(), boost::apply_visitor(add_descr_visitor));
It's a good case to use Visitor pattern. Unfortunately boost::any doesn't support Visitor pattern like boost::variant does. Nevertheless there are some 3rd party approaches.
Another possible idea is to use RTTI: create map of type_info of known types mapped to type handler functor.
Since you are going to just print them out anyway you can grab original string representation when you parse. (likely there are compiler errors in the code, I ripped it out of my codebase and un-typedefed bunch of things)
std::vector<std::string> GetArgumentList(const std::vector<boost::program_options::option>& raw)
{
std::vector<std::string> args;
BOOST_FOREACH(const boost::program_options::option& option, raw)
{
if(option.unregistered) continue; // Skipping unknown options
if(option.value.empty())
args.push_back("--" + option.string_key));
else
{
// this loses order of positional options
BOOST_FOREACH(const std::string& value, option.value)
{
args.push_back("--" + option.string_key));
args.push_back(value);
}
}
}
return args;
}
Usage:
boost::program_options::parsed_options parsed = boost::program_options::command_line_parser( ...
std::vector<std::string> arguments = GetArgumentList(parsed.options);
// print
I was dealing with just this type of problem today. This is an old question, but perhaps this will help people who are looking for an answer.
The method I came up with is to try a bunch of as<...>() and then ignore the exception. It's not terribly pretty, but I got it to work.
In the below code block, vm is a variables_map from boost program_options. vit is an iterator over vm, making it a pair of std::string and boost::program_options::variable_value, the latter being a boost::any. I can print the name of the variable with vit->first, but vit->second isn't so easy to output because it is a boost::any, ie the original type has been lost. Some should be cast as a std::string, some as a double, and so on.
So, to cout the value of the variable, I can use this:
std::cout << vit->first << "=";
try { std::cout << vit->second.as<double>() << std::endl;
} catch(...) {/* do nothing */ }
try { std::cout << vit->second.as<int>() << std::endl;
} catch(...) {/* do nothing */ }
try { std::cout << vit->second.as<std::string>() << std::endl;
} catch(...) {/* do nothing */ }
try { std::cout << vit->second.as<bool>() << std::endl;
} catch(...) {/* do nothing */ }
I only have 4 types that I use to get information from the command-line/config file, if I added more types, I would have to add more lines. I'll admit that this is a bit ugly.

How to implement grep in C++ so it works with pipes (stdin,etc.)?

I want to implement grep for a Shell I'm doing in Windows (just for learning purpose).
I know that grep has the following syntax:
grep pattern files
So I can make a function like:
int grep(string stringToMatch, string fileName) // just one file
{
// search file for stringToMatch
// print line containing stringToMatch
}
My confusion is, how does grep supposed to work when I use a pipe like this:
ls | grep someword
I implemented "ls" to put all the output in a vector and return that, so I guess then my grep should search the vector for the results. So how should the correct grep function look ? Do I need 2 grep functions ?
Thanks in advance.
You want to see how many command line arguments you've been passed. If there is only one then you assume that you're using stdin instead of a file.
In C++ this can be abstracted by using a reference to a std::istream in your function. Before you call the function you decide (and create) a std::ifstream if appropriate, or use std::cin otherwise.
Thus your function becomes:
int grep(string stringToMatch, std::istream& in) // just one file
{
// search file for stringToMatch
// print line containing stringToMatch
}
And you can use a conditional (using argc and argv in main) to do either:
grep(string, std::cin);
or
std::ifstream file(fileName.c_str());
grep(string, file);
Read up on UNIX filters or here
Unix filters communicate on standard input and standard output. I.e. the standard output of the first process is received on the standard input of the second process.
Standard input and output are essentially binary/text streams
This method can be chained. The shell is typically the party that manages the
- environment
- start, monitoring and exit of processes
- the interconnections
So
0. a user gives a command,e.g. ls
1. the shell finds the command, creates a new process, connects stdin from the terminal and stdout from thte terminal,
2. waits for program execution
3. sets environment with the result of the subprocess
If you say you have 'ls' output in a vector, I'm afraid that you are not really close to programming a shell in the true fashion
If you wanted to do a shell without all the idiosyncrasies of process management, pipes, redirections and whatnot, the most useful vehicle would be std::istream and std::ostream (or Boost IOStreams library).
A very very simple (really very dumb) version of grep could look like this:
#include <iostream>
#include <string>
static bool is_match(const std::string& text, const std::string& pattern)
{
// FIXME TODO use actual (posix?) regex, boost regex, regex++ or whatnot
return std::string::npos != text.find(pattern);
}
int main(int argc, const char* argv[])
{
switch(argc)
{
case 0: case 1:
std::cerr << "specify the pattern" << std::endl;
return 254;
case 2:
break;
default:
std::cerr << "not implemented" << std::endl;
return 255;
}
const std::string pattern(argv[1]);
std::string line;
while (std::getline(std::cin, line))
{
if (is_match(line, argv[1]))
std::cout << line << std::endl;
}
return 0;
}
Better examples exist e.g. here but judging from the question I though this was the next informative step down the road ;)
Note also that Boost IOstreams library seems to contain built-in support for pipelines
Your grep function should work on a FILE * (or the C++ equivalent). If you get a filename passed as an argument, open that file. If not, read from stdin.
When a command appears in such a syntax like you posted, it is supposed to read its input from the standard input. So, what you need to pass to your function isn't a string of the file name, but a open file descriptor or FILE* to a file, being it an file system resident file or the standard input.
Something like:
FILE *f;
if (argc == 3)
f = fopen(argv[2], "r");
else
f = stdin;
grep(argv[1], f);
Notice that if you do "ls | grep bar foo", grep will ignore the output of ls and will match "bar" in the file "foo". So, the above code reflects (with a lot of flaws embedded, and not fully, as grep can match multiple files) the behavior of grep.
You might want to use some library like Boost Regex and compute the result of the pattern entered in your shell.
In the case of pipe, thats a feature of the shell and not grep. You can checkout Boost Interprocess and Boost Asio libraries to implement it. Boost Asio supports many POSIX interprocess communication mechanisms.
reopen stdin when user set second argument.
int grep(string stringToMatch, FILE *fp_in);
int main(int argc, char **argv)
{
if (argc == 2) {
freopen(argv[2], "r", stdin);
}
...
}