30 #include <boost/tokenizer.hpp>
39 main(
int argc,
char** argv)
41 std::vector<std::string> args(argv + 1, argv + argc);
51 if (args[0] ==
"-V" || args[0] ==
"--version") {
58 std::string noun, verb;
63 auto processLine = [&parser] (
const std::vector<std::string>& line) -> Command {
69 catch (
const std::invalid_argument& e) {
70 int ret =
help(std::cout, parser, line);
72 std::cerr << e.what() << std::endl;
73 return {
"",
"", {},
nullptr};
77 std::list<Command> commands;
79 if (args[0] ==
"-f" || args[0] ==
"--batch") {
80 if (args.size() != 2) {
81 std::cerr <<
"ERROR: Invalid command line arguments: " << args[0] <<
" should follow with batch-file."
82 <<
" Use -h for more detail." << std::endl;
86 auto processIstream = [&commands,&processLine] (std::istream& is,
const std::string& inputFile) {
88 size_t lineCounter = 0;
89 while (std::getline(is, line)) {
92 auto hasEscapeSlash = [] (
const std::string& str) {
93 auto count = std::count(str.rbegin(), str.rend(),
'\\');
94 return (count % 2) == 1;
96 while (!line.empty() && hasEscapeSlash(line)) {
97 std::string extraLine;
98 const auto& hasMore = std::getline(is, extraLine);
100 line = line.substr(0, line.size() - 1) + extraLine;
105 boost::tokenizer<boost::escaped_list_separator<char>> tokenizer(
107 boost::escaped_list_separator<char>(
"\\",
" \t",
"\"'"));
109 auto firstNonEmptyToken = tokenizer.begin();
110 while (firstNonEmptyToken != tokenizer.end() && firstNonEmptyToken->empty()) {
111 ++firstNonEmptyToken;
116 if (firstNonEmptyToken == tokenizer.end() || (*firstNonEmptyToken)[0] ==
'#') {
120 std::vector<std::string> lineArgs;
121 std::copy_if(firstNonEmptyToken, tokenizer.end(),
122 std::back_inserter<std::vector<std::string>>(lineArgs),
123 [] (
const std::string& t) { return !t.empty(); });
125 auto cmd = processLine(lineArgs);
126 if (cmd.noun.empty()) {
127 std::cerr <<
" >> Syntax error on line " << lineCounter <<
" of the batch in "
128 << inputFile << std::endl;
131 commands.push_back(std::move(cmd));
136 if (args[1] ==
"-") {
137 auto retval = processIstream(std::cin,
"standard input");
143 std::ifstream iff(args[1]);
145 std::cerr <<
"ERROR: Could not open `" << args[1] <<
"` batch file "
146 <<
"(" << strerror(errno) <<
")" << std::endl;
149 auto retval = processIstream(iff, args[1]);
156 commands.push_back(processLine(args));
162 Controller controller(face, keyChain);
163 size_t commandCounter = 0;
164 for (
auto& command : commands) {
167 std::cout, std::cerr, face, keyChain, controller};
168 command.execute(ctx);
170 if (ctx.exitCode != 0) {
171 if (commands.size() > 1) {
172 std::cerr <<
" >> Failed to execute command on line " << commandCounter
173 <<
" of the batch file " << args[1] << std::endl;
174 std::cerr <<
" Note that nfdc has executed all commands on previous lines and "
175 <<
"stopped processing at this line" << std::endl;
183 catch (
const std::exception& e) {
184 std::cerr << e.what() << std::endl;
context for command execution
int main(int argc, char **argv)
Copyright (c) 2014-2015, Regents of the University of California, Arizona Board of Regents,...
const char NFD_VERSION_BUILD_STRING[]
NFD version string, including git commit information if NFD is build from a specific git commit.