OXYGENHUB
◆ main openmsx / src / commands / InfoCommand.cc
2.8 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#include "InfoCommand.hh"
2
3
#include "CommandException.hh"
4
#include "TclObject.hh"
5
#include "join.hh"
6
7
#include <cassert>
8
#include <iostream>
9
#include <ranges>
10
11
namespace openmsx {
12
13
InfoCommand::InfoCommand(CommandController& commandController_, const std::string& name_)
14
	: Command(commandController_, name_)
15
{
16
}
17
18
InfoCommand::~InfoCommand()
19
{
20
	assert(infoTopics.empty());
21
}
22
23
void InfoCommand::registerTopic(const InfoTopic& topic)
24
{
25
#ifndef NDEBUG
26
	if (infoTopics.contains(topic.getName())) {
27
		std::cerr << "INTERNAL ERROR: already have an info topic with "
28
		             "name " << topic.getName() << '\n';
29
		assert(false);
30
	}
31
#endif
32
	infoTopics.insert_noDuplicateCheck(&topic);
33
}
34
35
void InfoCommand::unregisterTopic(const InfoTopic& topic)
36
{
37
	if (!infoTopics.contains(topic.getName())) {
38
		std::cerr << "INTERNAL ERROR: can't unregister topic with name "
39
		          << topic.getName() << ", not found!\n";
40
		assert(false);
41
	}
42
	infoTopics.erase(topic.getName());
43
}
44
45
// Command
46
47
void InfoCommand::execute(std::span<const TclObject> tokens,
48
                          TclObject& result)
49
{
50
	switch (tokens.size()) {
51
	case 1:
52
		// list topics
53
		result.addListElements(std::views::transform(
54
			infoTopics, [](auto* t) { return t->getName(); }));
55
		break;
56
	default:
57
		// show info about topic
58
		assert(tokens.size() >= 2);
59
		const auto& topic = tokens[1].getString();
60
		auto it = infoTopics.find(topic);
61
		if (it == end(infoTopics)) {
62
			throw CommandException("No info on: ", topic);
63
		}
64
		(*it)->execute(tokens, result);
65
		break;
66
	}
67
}
68
69
std::string InfoCommand::help(std::span<const TclObject> tokens) const
70
{
71
	std::string result;
72
	switch (tokens.size()) {
73
	case 1: {
74
		// show help on info cmd
75
		auto topics = to_vector(std::views::transform(infoTopics, &InfoTopic::getName));
76
		std::ranges::sort(topics);
77
		result = strCat(
78
			"Show info on a certain topic\n"
79
			"  ", getName(), " <topic> [...]\n",
80
			"Possible topics are:\n  ", join(topics, "\n  "), "\n",
81
			"Use \"help ", getName(), " <topic>\" for more info on that specific topic.");
82
		break;
83
	}
84
	default:
85
		// show help on a certain topic
86
		assert(tokens.size() >= 2);
87
		auto topic = tokens[1].getString();
88
		auto it = infoTopics.find(topic);
89
		if (it == end(infoTopics)) {
90
			throw CommandException("No info on: ", topic);
91
		}
92
		result = (*it)->help(tokens);
93
		break;
94
	}
95
	return result;
96
}
97
98
void InfoCommand::tabCompletion(std::vector<std::string>& tokens) const
99
{
100
	switch (tokens.size()) {
101
	case 2: {
102
		// complete topic
103
		completeString(tokens, std::views::transform(infoTopics,
104
			[](auto* t) -> std::string_view { return t->getName(); }));
105
		break;
106
	}
107
	default:
108
		// show help on a certain topic
109
		assert(tokens.size() >= 3);
110
		if (auto it = infoTopics.find(tokens[1]); it != end(infoTopics)) {
111
			(*it)->tabCompletion(tokens);
112
		}
113
		break;
114
	}
115
}
116
117
} // namespace openmsx