Add ls

Change-Id: I86f799ff9577940c7df8e01cda6c6b7867de8e7e
diff --git a/src/ast_commands.cpp b/src/ast_commands.cpp
index 9ef9044..89e2f74 100644
--- a/src/ast_commands.cpp
+++ b/src/ast_commands.cpp
@@ -24,6 +24,11 @@
     return this->m_path == b.m_path;
 }
 
+bool ls_::operator==(const ls_& b) const
+{
+    return this->m_path == b.m_path;
+}
+
 bool enum_::operator==(const enum_& b) const
 {
     return this->m_value == b.m_value;
diff --git a/src/ast_commands.hpp b/src/ast_commands.hpp
index 90af8ea..d7d47c9 100644
--- a/src/ast_commands.hpp
+++ b/src/ast_commands.hpp
@@ -28,6 +28,11 @@
 
 using keyValue_ = std::pair<std::string, std::string>;
 
+struct ls_ : x3::position_tagged {
+    bool operator==(const ls_& b) const;
+    boost::optional<path_> m_path;
+};
+
 struct cd_ : x3::position_tagged {
     bool operator==(const cd_& b) const;
     path_ m_path;
@@ -63,8 +68,9 @@
     leaf_data_ m_data;
 };
 
-using command_ = boost::variant<cd_, create_, delete_, set_>;
+using command_ = boost::variant<ls_, cd_, create_, delete_, set_>;
 
+BOOST_FUSION_ADAPT_STRUCT(ls_, m_path)
 BOOST_FUSION_ADAPT_STRUCT(cd_, m_path)
 BOOST_FUSION_ADAPT_STRUCT(create_, m_path)
 BOOST_FUSION_ADAPT_STRUCT(delete_, m_path)
diff --git a/src/ast_handlers.hpp b/src/ast_handlers.hpp
index b58613c..2953dad 100644
--- a/src/ast_handlers.hpp
+++ b/src/ast_handlers.hpp
@@ -204,6 +204,8 @@
 };
 
 
+struct ls_class;
+
 struct cd_class {
     template <typename Iterator, typename Exception, typename Context>
     x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& x, Context const& context)
diff --git a/src/grammars.hpp b/src/grammars.hpp
index ed21e31..06e1bf8 100644
--- a/src/grammars.hpp
+++ b/src/grammars.hpp
@@ -34,6 +34,7 @@
 x3::rule<leaf_data_uint_class, uint32_t> const leaf_data_uint = "leaf_data_uint";
 x3::rule<leaf_data_string_class, std::string> const leaf_data_string = "leaf_data_string";
 
+x3::rule<ls_class, ls_> const ls = "ls";
 x3::rule<cd_class, cd_> const cd = "cd";
 x3::rule<set_class, set_> const set = "set";
 x3::rule<create_class, create_> const create = "create";
@@ -125,6 +126,9 @@
 auto const space_separator =
         x3::omit[x3::no_skip[space]];
 
+auto const ls_def =
+        lit("ls") >> -path;
+
 auto const cd_def =
         lit("cd") >> space_separator > path;
 
@@ -138,7 +142,7 @@
         lit("set") >> space_separator > leafPath > leaf_data;
 
 auto const command_def =
-        x3::expect[cd | create | delete_rule | set] >> x3::eoi;
+        x3::expect[cd | create | delete_rule | set | ls] >> x3::eoi;
 
 #if __clang__
 #pragma GCC diagnostic pop
@@ -165,6 +169,7 @@
 BOOST_SPIRIT_DEFINE(leaf_data_uint)
 BOOST_SPIRIT_DEFINE(leaf_data_string)
 BOOST_SPIRIT_DEFINE(set)
+BOOST_SPIRIT_DEFINE(ls)
 BOOST_SPIRIT_DEFINE(cd)
 BOOST_SPIRIT_DEFINE(create)
 BOOST_SPIRIT_DEFINE(delete_rule)
diff --git a/src/interpreter.cpp b/src/interpreter.cpp
index 19a163b..f71c12f 100644
--- a/src/interpreter.cpp
+++ b/src/interpreter.cpp
@@ -45,6 +45,14 @@
     std::cout << "Presence container " << cont.m_name << " deleted." << std::endl;
 }
 
+void Interpreter::operator()(const ls_& ls) const
+{
+    std::cout << "Possible nodes:" << std::endl;
+
+    for (const auto& it : m_parser.availableNodes(ls.m_path))
+        std::cout << it << std::endl;
+}
+
 Interpreter::Interpreter(Parser& parser, Schema&)
     : m_parser(parser)
 {
diff --git a/src/interpreter.hpp b/src/interpreter.hpp
index 64cc0e9..8acf8bd 100644
--- a/src/interpreter.hpp
+++ b/src/interpreter.hpp
@@ -18,6 +18,7 @@
     void operator()(const cd_&) const;
     void operator()(const create_&) const;
     void operator()(const delete_&) const;
+    void operator()(const ls_&) const;
 
 private:
     Parser& m_parser;
diff --git a/src/parser.cpp b/src/parser.cpp
index ac3ba84..0eb94fd 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -53,3 +53,11 @@
 {
     return pathToDataString(m_curDir);
 }
+
+std::set<std::string> Parser::availableNodes(const boost::optional<path_>& path) const
+{
+    auto pathArg = m_curDir;
+    if (path)
+        pathArg.m_nodes.insert(pathArg.m_nodes.end(), path->m_nodes.begin(), path->m_nodes.end());
+    return m_schema->childNodes(pathArg);
+}
diff --git a/src/parser.hpp b/src/parser.hpp
index 05e636e..0f1fd79 100644
--- a/src/parser.hpp
+++ b/src/parser.hpp
@@ -30,6 +30,7 @@
     command_ parseCommand(const std::string& line, std::ostream& errorStream);
     void changeNode(const path_& name);
     std::string currentNode() const;
+    std::set<std::string> availableNodes(const boost::optional<path_>& path) const;
 
 private:
     const std::shared_ptr<const Schema> m_schema;