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