1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
/*
* This source code is released into the public domain.
*/
module;
#include <map>
#include <memory>
#include <optional>
#include <ranges>
#include <vector>
export module nihil.cli:command_tree;
import :command;
namespace nihil {
/*
* command_tree_node represents a possibly-empty node in the command tree.
* For example, if two commands "add foo" and "add bar" are defined,
* then "add" will be implicitly created as an empty node.
*/
struct command_tree_node final {
command_tree_node();
command_tree_node(command_tree_node *parent,
std::string_view this_word);
command_tree_node(command_tree_node *parent,
std::string_view this_word,
std::shared_ptr<command_node> command);
/*
* Return a child node, or NULL if the child doesn't exist.
*/
[[nodiscard]] auto get_child(this command_tree_node const &self,
std::string_view child)
-> command_tree_node const *;
[[nodiscard]] auto get_child(this command_tree_node &self,
std::string_view child)
-> command_tree_node *;
/*
* Return a child node if it exists, or insert a new empty node.
*/
[[nodiscard]] auto get_or_create_child(this command_tree_node &self,
std::string_view child)
-> command_tree_node *;
/*
* Set or get this node's command.
*/
[[nodiscard]] auto command(this command_tree_node const &self)
-> std::shared_ptr<command_node> const &;
auto command(this command_tree_node &self,
std::shared_ptr<command_node>)
-> void;
/*
* Get the path of this command_node.
*/
[[nodiscard]] auto path(this command_tree_node const &self)
-> std::string_view;
/*
* Print this node's children in a form useful to humans.
*/
auto print_commands(this command_tree_node const &self) -> void;
private:
command_tree_node *m_parent = nullptr;
std::string m_this_word;
std::shared_ptr<command_node> m_command;
std::map<std::string, command_tree_node>
m_children;
};
/*
* The command tree stores commands in a tree structure suitable for searching.
*/
struct command_tree {
/*
* Add a node to the tree. Returns false if the node already exists.
*/
auto insert(this command_tree &self,
std::vector<std::string_view> const &path,
std::shared_ptr<command_node> command)
-> void;
/*
* Find a node in the tree.
*/
auto find(this command_tree const &self, int &argc, char **&argv)
-> command_tree_node const *;
private:
command_tree_node m_root_node;
};
/*
* Build a command tree from the registry.
*/
[[nodiscard]] auto build_command_tree() -> command_tree;
} // namespace nihil
|