Don't suggest paths when leaf values are expected

Issue: https://tree.taiga.io/project/jktjkt-netconf-cli/issue/122
Change-Id: I1d5588f07558895277b0fdcc6b45c4ad1def8eaf
diff --git a/src/ast_handlers.hpp b/src/ast_handlers.hpp
index fd7f52e..9fd65ff 100644
--- a/src/ast_handlers.hpp
+++ b/src/ast_handlers.hpp
@@ -327,6 +327,15 @@
     }
 };
 
+struct space_separator_class {
+    template <typename T, typename Iterator, typename Context>
+    void on_success(Iterator const&, Iterator const&, T&, Context const& context)
+    {
+        auto& parserContext = x3::get<parser_context_tag>(context);
+        parserContext.m_suggestions.clear();
+    }
+};
+
 struct create_class {
     template <typename Iterator, typename Exception, typename Context>
     x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
diff --git a/src/grammars.hpp b/src/grammars.hpp
index 95814e7..2c511ad 100644
--- a/src/grammars.hpp
+++ b/src/grammars.hpp
@@ -37,6 +37,7 @@
 x3::rule<leaf_path_class, dataPath_> const leafPath = "leafPath";
 x3::rule<presenceContainerPath_class, dataPath_> const presenceContainerPath = "presenceContainerPath";
 x3::rule<listInstancePath_class, dataPath_> const listInstancePath = "listInstancePath";
+x3::rule<space_separator_class, x3::unused_type> const space_separator = "space_separator";
 
 x3::rule<leaf_data_class, leaf_data_> const leaf_data = "leaf_data";
 x3::rule<leaf_data_enum_class, enum_> const leaf_data_enum = "leaf_data_enum";
@@ -180,7 +181,7 @@
 auto const trailingSlash_def =
     x3::omit['/'] >> x3::attr(TrailingSlash::Present);
 
-auto const space_separator =
+auto const space_separator_def =
     x3::omit[x3::no_skip[space]];
 
 // This is a pseudo-parser, that fails if we're not completing a command
@@ -365,6 +366,7 @@
 BOOST_SPIRIT_DEFINE(leafPath)
 BOOST_SPIRIT_DEFINE(presenceContainerPath)
 BOOST_SPIRIT_DEFINE(listInstancePath)
+BOOST_SPIRIT_DEFINE(space_separator)
 BOOST_SPIRIT_DEFINE(schemaPath)
 BOOST_SPIRIT_DEFINE(dataPath)
 BOOST_SPIRIT_DEFINE(dataNodeList)
diff --git a/tests/path_completion.cpp b/tests/path_completion.cpp
index 6744aed..5adb7ff 100644
--- a/tests/path_completion.cpp
+++ b/tests/path_completion.cpp
@@ -6,10 +6,21 @@
  *
 */
 
+#include <experimental/iterator>
 #include "trompeloeil_doctest.h"
 #include "parser.hpp"
 #include "static_schema.hpp"
 
+namespace std {
+std::ostream& operator<<(std::ostream& s, const std::set<std::string> set)
+{
+    s << std::endl << "{";
+    std::copy(set.begin(), set.end(), std::experimental::make_ostream_joiner(s, ", "));
+    s << "}" << std::endl;
+    return s;
+}
+}
+
 TEST_CASE("path_completion")
 {
     auto schema = std::make_shared<StaticSchema>();
@@ -29,6 +40,7 @@
     schema->addList("", "example:ovocezelenina", {"name"});
     schema->addContainer("example:list", "example:contInList");
     schema->addList("", "example:twoKeyList", {"number", "name"});
+    schema->addLeaf("", "example:leafInt", yang::LeafDataTypes::Int32);
     Parser parser(schema);
     std::string input;
     std::ostringstream errorStream;
@@ -39,13 +51,13 @@
         SECTION("ls ")
         {
             input = "ls ";
-            expected = {"example:ano", "example:anoda", "example:bota", "second:amelie", "example:list", "example:twoKeyList", "example:ovoce", "example:ovocezelenina"};
+            expected = {"example:ano", "example:anoda", "example:bota", "example:leafInt", "example:list", "example:ovoce", "example:ovocezelenina", "example:twoKeyList", "second:amelie"};
         }
 
         SECTION("ls e")
         {
             input = "ls e";
-            expected = {"example:ano", "example:anoda", "example:bota", "example:list", "example:twoKeyList", "example:ovoce", "example:ovocezelenina"};
+            expected = {"example:ano", "example:anoda", "example:bota", "example:leafInt", "example:list", "example:ovoce", "example:ovocezelenina", "example:twoKeyList"};
         }
 
         SECTION("ls example:ano")
@@ -69,13 +81,14 @@
         SECTION("ls /")
         {
             input = "ls /";
-            expected = {"example:ano", "example:anoda", "example:bota", "second:amelie", "example:list", "example:twoKeyList", "example:ovoce", "example:ovocezelenina"};
+            expected = {"example:ano", "example:anoda", "example:bota", "example:leafInt", "example:list", "example:ovoce", "example:ovocezelenina", "example:twoKeyList", "second:amelie"};
         }
 
         SECTION("ls /e")
         {
             input = "ls /e";
-            expected = {"example:ano", "example:anoda", "example:bota", "example:list", "example:twoKeyList", "example:ovoce", "example:ovocezelenina"};
+            expected = {"example:ano", "example:anoda", "example:bota", "example:leafInt", "example:list", "example:ovoce", "example:ovocezelenina", "example:twoKeyList"};
+
         }
 
         SECTION("ls /s")
@@ -202,5 +215,11 @@
         }
     }
 
+    SECTION("clear completions when no longer inputting path")
+    {
+        input = "set example:leafInt ";
+        expected = {};
+    }
+
     REQUIRE(parser.completeCommand(input, errorStream) == expected);
 }