openMSX
Completer.hh
Go to the documentation of this file.
1#ifndef COMPLETER_HH
2#define COMPLETER_HH
3
4#include "inline.hh"
5
6#include <concepts>
7#include <span>
8#include <string>
9#include <string_view>
10#include <vector>
11
12namespace openmsx {
13
14class FileContext;
15class Interpreter;
16class InterpreterOutput;
17class TclObject;
18
20{
21public:
22 Completer(const Completer&) = delete;
23 Completer(Completer&&) = delete;
24 Completer& operator=(const Completer&) = delete;
26
27 [[nodiscard]] const std::string& getName() const { return theName; }
28
31 [[nodiscard]] virtual std::string help(std::span<const TclObject> tokens) const = 0;
32
38 virtual void tabCompletion(std::vector<std::string>& tokens) const = 0;
39
40 [[nodiscard]] virtual Interpreter& getInterpreter() const = 0;
41
42 template<typename ITER>
43 static void completeString(std::vector<std::string>& tokens,
44 ITER begin, ITER end,
45 bool caseSensitive = true);
46 template<typename RANGE>
47 static void completeString(std::vector<std::string>& tokens,
48 RANGE&& possibleValues,
49 bool caseSensitive = true);
50 template<typename RANGE>
51 static void completeFileName(std::vector<std::string>& tokens,
52 const FileContext& context,
53 const RANGE& extra);
54 static void completeFileName(std::vector<std::string>& tokens,
55 const FileContext& context);
56
57 static std::vector<std::string> formatListInColumns(
58 std::span<const std::string_view> input);
59
60 // helper functions to check the number of arguments
61 struct AtLeast { unsigned min; };
62 struct Between { unsigned min; unsigned max; };
63 struct Prefix { unsigned n; }; // how many items from 'tokens' to show in error
64 void checkNumArgs(std::span<const TclObject> tokens, unsigned exactly, const char* errMessage) const;
65 void checkNumArgs(std::span<const TclObject> tokens, AtLeast atLeast, const char* errMessage) const;
66 void checkNumArgs(std::span<const TclObject> tokens, Between between, const char* errMessage) const;
67 void checkNumArgs(std::span<const TclObject> tokens, unsigned exactly, Prefix prefix, const char* errMessage) const;
68 void checkNumArgs(std::span<const TclObject> tokens, AtLeast atLeast, Prefix prefix, const char* errMessage) const;
69 void checkNumArgs(std::span<const TclObject> tokens, Between between, Prefix prefix, const char* errMessage) const;
70
71 // should only be called by CommandConsole
72 static void setOutput(InterpreterOutput* output_) { output = output_; }
73
74protected:
75 template<typename String>
76 requires(!std::same_as<Completer, std::remove_cvref_t<String>>) // don't block copy-constructor
77 explicit Completer(String&& name_)
78 : theName(std::forward<String>(name_))
79 {
80 }
81
82 ~Completer() = default;
83
84private:
85 static bool equalHead(std::string_view s1, std::string_view s2, bool caseSensitive);
86 template<typename ITER>
87 static std::vector<std::string_view> filter(
88 std::string_view str, ITER begin, ITER end, bool caseSensitive);
89 template<typename RANGE>
90 static std::vector<std::string_view> filter(
91 std::string_view str, RANGE&& range, bool caseSensitive);
92 static bool completeImpl(std::string& str, std::vector<std::string_view> matches,
93 bool caseSensitive);
94 static void completeFileNameImpl(std::vector<std::string>& tokens,
95 const FileContext& context,
96 std::vector<std::string_view> matches);
97
98 const std::string theName;
99 static inline InterpreterOutput* output = nullptr;
100};
101
102
103template<typename ITER>
104NEVER_INLINE std::vector<std::string_view> Completer::filter(
105 std::string_view str, ITER begin, ITER end, bool caseSensitive)
106{
107 std::vector<std::string_view> result;
108 for (auto it = begin; it != end; ++it) {
109 if (equalHead(str, *it, caseSensitive)) {
110 result.push_back(*it);
111 }
112 }
113 return result;
114}
115
116template<typename RANGE>
117inline std::vector<std::string_view> Completer::filter(
118 std::string_view str, RANGE&& range, bool caseSensitive)
119{
120 return filter(str, std::begin(range), std::end(range), caseSensitive);
121}
122
123template<typename RANGE>
125 std::vector<std::string>& tokens,
126 RANGE&& possibleValues,
127 bool caseSensitive)
128{
129 auto& str = tokens.back();
130 if (completeImpl(str,
131 filter(str, std::forward<RANGE>(possibleValues), caseSensitive),
132 caseSensitive)) {
133 tokens.emplace_back();
134 }
135}
136
137template<typename ITER>
139 std::vector<std::string>& tokens,
140 ITER begin, ITER end,
141 bool caseSensitive)
142{
143 auto& str = tokens.back();
144 if (completeImpl(str,
145 filter(str, begin, end, caseSensitive),
146 caseSensitive)) {
147 tokens.emplace_back();
148 }
149}
150
151template<typename RANGE>
153 std::vector<std::string>& tokens,
154 const FileContext& context,
155 const RANGE& extra)
156{
157 completeFileNameImpl(tokens, context, filter(tokens.back(), extra, true));
158}
159
160} // namespace openmsx
161
162#endif
Completer(String &&name_)
Definition Completer.hh:77
static void completeFileName(std::vector< std::string > &tokens, const FileContext &context, const RANGE &extra)
Definition Completer.hh:152
static void setOutput(InterpreterOutput *output_)
Definition Completer.hh:72
virtual void tabCompletion(std::vector< std::string > &tokens) const =0
Attempt tab completion for this command.
static void completeString(std::vector< std::string > &tokens, ITER begin, ITER end, bool caseSensitive=true)
Definition Completer.hh:138
Completer(Completer &&)=delete
virtual std::string help(std::span< const TclObject > tokens) const =0
Print help for this command.
static std::vector< std::string > formatListInColumns(std::span< const std::string_view > input)
Definition Completer.cc:59
const std::string & getName() const
Definition Completer.hh:27
Completer & operator=(Completer &&)=delete
~Completer()=default
virtual Interpreter & getInterpreter() const =0
void checkNumArgs(std::span< const TclObject > tokens, unsigned exactly, const char *errMessage) const
Definition Completer.cc:181
Completer & operator=(const Completer &)=delete
Completer(const Completer &)=delete
#define NEVER_INLINE
Definition inline.hh:17
This file implemented 3 utility functions:
Definition Autofire.cc:11
bool matches(const Event &self, const Event &other)
Does this event 'match' the given event.
Definition Event.cc:211
constexpr auto begin(const zstring_view &x)
constexpr auto end(const zstring_view &x)