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