Add recursive ls
Change-Id: Ifab8c9577c01cf7a96cda8d79fe232b12b5538bd
diff --git a/src/ast_commands.cpp b/src/ast_commands.cpp
index 89e2f74..fe2fa84 100644
--- a/src/ast_commands.cpp
+++ b/src/ast_commands.cpp
@@ -26,7 +26,7 @@
bool ls_::operator==(const ls_& b) const
{
- return this->m_path == b.m_path;
+ return this->m_path == b.m_path && this->m_options == b.m_options;
}
bool enum_::operator==(const enum_& b) const
diff --git a/src/ast_commands.hpp b/src/ast_commands.hpp
index 969515e..966f170 100644
--- a/src/ast_commands.hpp
+++ b/src/ast_commands.hpp
@@ -29,8 +29,13 @@
using keyValue_ = std::pair<std::string, std::string>;
+enum class LsOption {
+ Recursive
+};
+
struct ls_ : x3::position_tagged {
bool operator==(const ls_& b) const;
+ std::vector<LsOption> m_options;
boost::optional<path_> m_path;
};
@@ -66,7 +71,7 @@
using command_ = boost::variant<ls_, cd_, create_, delete_, set_, commit_, get_>;
-BOOST_FUSION_ADAPT_STRUCT(ls_, m_path)
+BOOST_FUSION_ADAPT_STRUCT(ls_, m_options, 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/grammars.hpp b/src/grammars.hpp
index 5a3db0f..fddd409 100644
--- a/src/grammars.hpp
+++ b/src/grammars.hpp
@@ -134,8 +134,16 @@
auto const space_separator =
x3::omit[x3::no_skip[space]];
+struct ls_options_table : x3::symbols<LsOption> {
+ ls_options_table()
+ {
+ add
+ ("--recursive", LsOption::Recursive);
+ }
+} const ls_options;
+
auto const ls_def =
- lit("ls") >> -path;
+ lit("ls") >> *(space_separator >> ls_options) >> -(space_separator >> path);
auto const cd_def =
lit("cd") >> space_separator > path;
diff --git a/src/interpreter.cpp b/src/interpreter.cpp
index 4e5d665..bdeecf9 100644
--- a/src/interpreter.cpp
+++ b/src/interpreter.cpp
@@ -60,8 +60,13 @@
void Interpreter::operator()(const ls_& ls) const
{
std::cout << "Possible nodes:" << std::endl;
+ auto recursion{Recursion::NonRecursive};
+ for (auto it : ls.m_options) {
+ if (it == LsOption::Recursive)
+ recursion = Recursion::Recursive;
+ }
- for (const auto& it : m_parser.availableNodes(ls.m_path))
+ for (const auto& it : m_parser.availableNodes(ls.m_path, recursion))
std::cout << it << std::endl;
}
diff --git a/src/parser.cpp b/src/parser.cpp
index c56b561..f25f1a3 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -58,10 +58,10 @@
return "/" + pathToDataString(m_curDir);
}
-std::set<std::string> Parser::availableNodes(const boost::optional<path_>& path) const
+std::set<std::string> Parser::availableNodes(const boost::optional<path_>& path, const Recursion& option) 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);
+ return m_schema->childNodes(pathArg, option);
}
diff --git a/src/parser.hpp b/src/parser.hpp
index 0f1fd79..0318733 100644
--- a/src/parser.hpp
+++ b/src/parser.hpp
@@ -23,14 +23,13 @@
~TooManyArgumentsException() override;
};
-
class Parser {
public:
Parser(const std::shared_ptr<const Schema> schema);
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;
+ std::set<std::string> availableNodes(const boost::optional<path_>& path, const Recursion& option) const;
private:
const std::shared_ptr<const Schema> m_schema;
diff --git a/src/schema.hpp b/src/schema.hpp
index 96176ab..e5827de 100644
--- a/src/schema.hpp
+++ b/src/schema.hpp
@@ -45,6 +45,10 @@
};
}
+enum class Recursion {
+ NonRecursive,
+ Recursive
+};
using NodeType = boost::variant<yang::container, yang::list, yang::leaf, yang::module>;
@@ -75,7 +79,7 @@
virtual bool nodeExists(const std::string& location, const std::string& node) const = 0;
virtual const std::set<std::string> listKeys(const path_& location, const ModuleNodePair& node) const = 0;
virtual yang::LeafDataTypes leafType(const path_& location, const ModuleNodePair& node) const = 0;
- virtual std::set<std::string> childNodes(const path_& path) const = 0;
+ virtual std::set<std::string> childNodes(const path_& path, const Recursion recursion) const = 0;
private:
const std::unordered_map<std::string, NodeType>& children(const std::string& name) const;
diff --git a/src/static_schema.cpp b/src/static_schema.cpp
index 1778c68..ce94218 100644
--- a/src/static_schema.cpp
+++ b/src/static_schema.cpp
@@ -55,7 +55,6 @@
m_nodes.emplace(key, std::unordered_map<std::string, NodeType>());
}
-
bool StaticSchema::listHasKey(const path_& location, const ModuleNodePair& node, const std::string& key) const
{
std::string locationString = pathToAbsoluteSchemaString(location);
@@ -146,7 +145,9 @@
return boost::get<yang::leaf>(children(locationString).at(fullNodeName(location, node))).m_type;
}
-std::set<std::string> StaticSchema::childNodes(const path_& path) const
+// We do not test StaticSchema, so we don't need to implement recursive childNodes
+// for this class.
+std::set<std::string> StaticSchema::childNodes(const path_& path, const Recursion) const
{
std::string locationString = pathToAbsoluteSchemaString(path);
std::set<std::string> res;
diff --git a/src/static_schema.hpp b/src/static_schema.hpp
index 1c261c3..68f1401 100644
--- a/src/static_schema.hpp
+++ b/src/static_schema.hpp
@@ -33,7 +33,7 @@
bool nodeExists(const std::string& location, const std::string& node) const override;
const std::set<std::string> listKeys(const path_& location, const ModuleNodePair& node) const override;
yang::LeafDataTypes leafType(const path_& location, const ModuleNodePair& node) const override;
- std::set<std::string> childNodes(const path_& path) const override;
+ std::set<std::string> childNodes(const path_& path, const Recursion) const override;
void addContainer(const std::string& location, const std::string& name, yang::ContainerTraits isPresence = yang::ContainerTraits::None);
void addLeaf(const std::string& location, const std::string& name, const yang::LeafDataTypes& type);
diff --git a/src/yang_schema.cpp b/src/yang_schema.cpp
index 946162b..6f34ad1 100644
--- a/src/yang_schema.cpp
+++ b/src/yang_schema.cpp
@@ -202,25 +202,35 @@
return res;
}
-std::set<std::string> YangSchema::childNodes(const path_& path) const
+std::set<std::string> YangSchema::childNodes(const path_& path, const Recursion recursion) const
{
using namespace std::string_view_literals;
std::set<std::string> res;
+ std::vector<libyang::S_Schema_Node> nodes;
+
if (path.m_nodes.empty()) {
- const auto& nodeVec = m_context->data_instantiables(0);
- for (const auto it : nodeVec) {
- if (it->module()->name() == "ietf-yang-library"sv)
- continue;
- res.insert(std::string(it->module()->name()) + ":" + it->name());
- }
+ nodes = m_context->data_instantiables(0);
} else {
const auto absolutePath = "/" + pathToAbsoluteSchemaString(path);
const auto set = m_context->find_path(absolutePath.c_str());
- const auto& schemaSet = set->schema();
+ const auto schemaSet = set->schema();
for (auto it = (*schemaSet.begin())->child(); it; it = it->next()) {
- res.insert(std::string(it->module()->name()) + ":" + it->name());
+ nodes.push_back(it);
}
}
+
+ for (const auto node : nodes) {
+ if (node->module()->name() == "ietf-yang-library"sv)
+ continue;
+ if (recursion == Recursion::Recursive) {
+ for (auto it : node->tree_dfs()) {
+ res.insert(it->path(LYS_PATH_FIRST_PREFIX));
+ }
+ } else {
+ res.insert(std::string(node->module()->name()) + ":" + node->name());
+ }
+ }
+
return res;
}
diff --git a/src/yang_schema.hpp b/src/yang_schema.hpp
index d100302..c61232f 100644
--- a/src/yang_schema.hpp
+++ b/src/yang_schema.hpp
@@ -39,7 +39,7 @@
bool nodeExists(const std::string& location, const std::string& node) const override;
const std::set<std::string> listKeys(const path_& location, const ModuleNodePair& node) const override;
yang::LeafDataTypes leafType(const path_& location, const ModuleNodePair& node) const override;
- std::set<std::string> childNodes(const path_& path) const override;
+ std::set<std::string> childNodes(const path_& path, const Recursion recursion) const override;
void registerModuleCallback(const std::function<std::string(const char*, const char*, const char*)>& clb);