diff options
Diffstat (limited to 'nihil.cli')
| -rw-r--r-- | nihil.cli/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | nihil.cli/command_tree.ccm | 16 | ||||
| -rw-r--r-- | nihil.cli/command_tree.test.cc | 45 | ||||
| -rw-r--r-- | nihil.cli/dispatch_command.test.cc (renamed from nihil.cli/test.cc) | 0 |
4 files changed, 54 insertions, 10 deletions
diff --git a/nihil.cli/CMakeLists.txt b/nihil.cli/CMakeLists.txt index 41fae52..091c34f 100644 --- a/nihil.cli/CMakeLists.txt +++ b/nihil.cli/CMakeLists.txt @@ -25,8 +25,9 @@ if(NIHIL_TESTS) enable_testing() add_executable(nihil.cli.test - test.cc command.test.cc + command_tree.test.cc + dispatch_command.test.cc ) target_link_libraries(nihil.cli.test PRIVATE nihil.cli diff --git a/nihil.cli/command_tree.ccm b/nihil.cli/command_tree.ccm index 6cfabe9..7399357 100644 --- a/nihil.cli/command_tree.ccm +++ b/nihil.cli/command_tree.ccm @@ -120,18 +120,15 @@ private: }; // The command tree stores commands in a tree structure suitable for searching. -struct command_tree +export struct command_tree { // Add a node to the tree. Returns false if the node already exists. - auto insert(this command_tree &self, std::ranges::range auto &&path, - std::shared_ptr<command> command) -> void - requires(std::constructible_from<std::string_view, - std::ranges::range_value_t<decltype(path)>>) + auto insert(this command_tree &self, std::shared_ptr<command> command) -> void { auto *this_node = &self.m_root_node; // Find the node for this key. - for (auto &&this_word : path) + for (auto &&this_word : command->path() | std::views::split(' ')) this_node = this_node->get_or_create_child(std::string_view(this_word)); // Set the new value. @@ -143,7 +140,7 @@ struct command_tree requires(std::constructible_from<std::string_view, std::ranges::range_value_t<decltype(args)>>) { - auto const *this_node = &self.m_root_node; + auto *this_node = &self.m_root_node; auto rest = args | std::views::take_while([&](auto &&str) { @@ -169,9 +166,10 @@ private: { auto tree = command_tree(); - for (auto &&command : get_registered_commands()) + for (auto &&command : get_registered_commands()) { // Throws std::logic_error on duplicates. - tree.insert(command->path() | std::views::split(' '), command); + tree.insert(command); + } return tree; } diff --git a/nihil.cli/command_tree.test.cc b/nihil.cli/command_tree.test.cc new file mode 100644 index 0000000..a1e7d32 --- /dev/null +++ b/nihil.cli/command_tree.test.cc @@ -0,0 +1,45 @@ +// This source code is released into the public domain. + +#include <catch2/catch_test_macros.hpp> + +import nihil.std; +import nihil.cli; + +namespace { + +inline auto constexpr *test_tags = "[nihil][nihil.cli]"; + +SCENARIO("Inserting and retrieving nodes in a command_tree", test_tags) +{ + GIVEN ("A command tree") { + auto tree = nihil::command_tree(); + + THEN ("We can insert nodes into the tree") { + tree.insert(std::make_shared<nihil::command>("cmd1 sub1")); + tree.insert(std::make_shared<nihil::command>("cmd1 sub2")); + tree.insert(std::make_shared<nihil::command>("cmd2 sub1")); + + AND_THEN ("We can retrieve nodes from the tree") { + auto c1s1 = tree.find(std::vector{"cmd1", "sub1"}); + REQUIRE(c1s1.first->command().path() == "cmd1 sub1"); + + auto c1s2 = tree.find(std::vector{"cmd1", "sub2"}); + REQUIRE(c1s2.first->command().path() == "cmd1 sub2"); + + auto c2s1 = tree.find(std::vector{"cmd2", "sub1"}); + REQUIRE(c2s1.first->command().path() == "cmd2 sub1"); + } + + AND_THEN ("Fetching an unknown command returns the root node") { + auto cmd = tree.find(std::vector{"cmd3", "sub1"}); + REQUIRE(cmd.first->command().path() == ""); + } + + AND_THEN ("Fetching an unknown subcommand returns the cmd1 node") { + auto cmd = tree.find(std::vector{"cmd1", "sub3"}); + REQUIRE(cmd.first->command().path() == "cmd1"); + } + } + } +} +} // anonymous namespace diff --git a/nihil.cli/test.cc b/nihil.cli/dispatch_command.test.cc index 8253bdc..8253bdc 100644 --- a/nihil.cli/test.cc +++ b/nihil.cli/dispatch_command.test.cc |
