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
|
/*
* This source code is released into the public domain.
*/
module;
#include <functional>
#include <iostream>
#include <map>
#include <string>
#include <utility>
export module nihil.cli:command_map;
import nihil.util;
import :usage_error;
/*
* command_map represents a hierarchical list of commands. At each level,
* a command is mapped to a handler, which can either be a function, in
* which case we execute the function, or another command_map, in which
* case we invoke the new map
*/
namespace nihil {
export struct command;
/*
* Register a command; used by command<>::command().
*/
auto register_command(std::string_view path, command *) noexcept -> void;
/*
* A command that can be invoked. Instantiating a command adds this command
* to the global command table. If an error occurs, the program will abort.
*/
export struct command {
command(std::string_view path, std::string_view usage, auto &&fn)
: m_path(path)
, m_usage(usage)
, m_handler(std::forward<decltype(fn)>(fn))
{
register_command(path, this);
}
[[nodiscard]] auto path(this command const &self) -> std::string_view
{
return self.m_path;
}
auto invoke(this command const &self, int argc, char **argv) -> int
{
return std::invoke(self.m_handler, argc, argv);
}
private:
std::string_view m_path;
std::string_view m_usage;
std::function<int (int, char **)> m_handler;
};
// The public API.
export [[nodiscard]] auto dispatch_command(int argc, char **argv) -> int;
export auto print_usage(std::string_view prefix) -> void;
} // namespace nihil
|