Support vasum-cli to be a script interpreter (1/2) 68/42768/10
authorKrzysztof Dynowski <k.dynowski@samsung.com>
Wed, 1 Jul 2015 15:29:32 +0000 (17:29 +0200)
committerJan Olszak <j.olszak@samsung.com>
Wed, 15 Jul 2015 13:35:00 +0000 (06:35 -0700)
[Feature]       vasum-cli as script interpreter
[Cause]         n/a
[Solution]      file/pipe processing
[Verification]  Build, run vasum-cli script, vasum-cli -f script, cat script|vasum-cli

Change-Id: I6b8ff93fb359e429119e120d93a0851e2ae7e72e

cli/main.cpp

index dcb6891..1a01af9 100644 (file)
 #include <string>
 #include <iostream>
 #include <algorithm>
+#include <istream>
 #include <sstream>
+#include <fstream>
 #include <iterator>
 #include <iomanip>
+#include <boost/algorithm/string/predicate.hpp>
+
 #include <readline/readline.h>
 #include <readline/history.h>
 
@@ -40,6 +44,7 @@ using namespace vasum::cli;
 
 namespace {
 
+static int interactiveMode = 0;
 std::map<std::string, CommandLineInterface> commands = {
     {
         "lock_queue", {
@@ -472,45 +477,64 @@ char** completion(const char* text, int start, int /*end*/)
     return matches;
 }
 
-// handlers for the modes
+static bool readline_from(const std::string& prompt, std::istream& stream, std::string& ln)
+{
+    if (interactiveMode) {
+        char *cmd = ::readline(prompt.c_str());
+        if (cmd == NULL) {
+            return false;
+        }
+        ln = cmd;
+        free(cmd);
+    } else {
+        std::getline(stream, ln);
+        if (!stream) return false;
+    }
+
+    if (interactiveMode && !ln.empty()) {
+        ::add_history(ln.c_str());
+    }
 
-int interactiveMode()
+    return true;
+}
+
+static int processStream(std::istream& stream)
 {
     if (connect() != EXIT_SUCCESS)
         return EXIT_FAILURE;
 
-    ::rl_attempted_completion_function = completion;
-
-    for (;;) {
-        char *line = ::readline(">>> ");
+    std::string ln;
+    while (readline_from(">>> ", stream, ln)) {
+        if (ln == "" || boost::starts_with(ln, "#")) //skip empty line or comment
+             continue;
 
-        if (line == NULL) {
-            break;
-        }
-        if (line[0] == '\0') {
-            free(line);
-            continue;
-        }
-
-        std::istringstream iss(line);
+        std::istringstream iss(ln);
         Args argv{std::istream_iterator<std::string>{iss},
                   std::istream_iterator<std::string>{}};
 
         if (commands.count(argv[0]) == 0) {
             printUsage(std::cout, "", MODE_INTERACTIVE);
-            free(line);
             continue;
         }
 
         executeCommand(argv, MODE_INTERACTIVE);
-        ::add_history(line);
-        free(line);
     }
 
     disconnect();
     return EXIT_SUCCESS;
 }
 
+static int processFile(const std::string& fn)
+{
+    std::ifstream stream(fn);
+    if (!stream.is_open()) {
+        std::cerr << "Can't open file " << fn << std::endl;
+        return EXIT_FAILURE;
+    }
+
+    return processStream(stream);
+}
+
 int bashComplMode()
 {
     for (const auto& command : commands) {
@@ -544,15 +568,34 @@ int cliMode(const int argc, const char** argv)
 } // namespace
 
 
-int main(const int argc, const char** argv)
+int main(const int argc, const char *argv[])
 {
-    if (argc == 1) {
-        return interactiveMode();
-    }
+    if (argc > 1) {
+        //process arguments
+        if (std::string(argv[1]) == "--bash-completion") {
+            return bashComplMode();
+        }
 
-    if (std::string(argv[1]) == "--bash-completion") {
-        return bashComplMode();
+        if (std::string(argv[1]) == "-f") {
+            if (argc < 3) {
+                std::cerr << "filename expected" << std::endl;
+                return EXIT_FAILURE;
+            }
+            return processFile(std::string(argv[2]));
+        }
+
+        if (commands.find(argv[1]) == commands.end()) {
+            if (processFile(std::string(argv[1])) == EXIT_SUCCESS) {
+                return EXIT_SUCCESS;
+            }
+        }
+
+        return cliMode(argc, argv);
     }
 
-    return cliMode(argc, argv);
+    if (isatty(0) == 1) {
+        interactiveMode = 1;
+        ::rl_attempted_completion_function = completion;
+    }
+    return processStream(std::cin);
 }