aboutsummaryrefslogtreecommitdiffstats
path: root/nihil.cli/command_map.ccm
blob: 8cf9d9c49457b0aff6a30c9609bccfa6b06b04a2 (plain) (blame)
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