Euphoria
console.cc
Go to the documentation of this file.
1 #include "core/console.h"
2 
3 #include "base/stringutils.h"
4 #include "base/stringbuilder.h"
5 
6 
7 namespace eu::core
8 {
9 
10 
12 {
13  register_command("help", [this](PrintFunction print, const Args& arg) {
14  this->print_help(print, arg);
15  });
16 }
17 
18 
19 void
20 VirtualConsole::register_command(const std::string& name, ActionFunction callback)
21 {
22  callbacks[to_lower(name)] = callback;
23 }
24 
25 
26 void
27 VirtualConsole::run(PrintFunction print, const std::string& cmd)
28 {
29  if(cmd.empty())
30  {
31  return;
32  }
33  const auto line = parse_commandline(cmd);
34  if(line.empty())
35  {
36  return;
37  }
38  const auto name = line[0];
39  auto found = callbacks.find(to_lower(name));
40  if(found == callbacks.end())
41  {
42  // unable to find cmd
43  print(fmt::format("Unknown command {}", name));
44  // todo(Gustav): list commands that are the closest match
45  return;
46  }
47 
48  ActionFunction callback = found->second;
49  callback(print, std::vector<std::string> {line.begin() + 1, line.end()});
50 }
51 
52 
53 void
55 {
56  print("Available commands:");
57  for(const auto& c: callbacks)
58  {
59  print(fmt::format(" {}", c.first));
60  }
61  print("");
62 }
63 
64 
65 namespace
66 {
67  bool
68  is_space(char c)
69  {
70  switch (c)
71  {
72  case '\t':
73  case ' ': return true;
74  default: return false;
75  }
76  }
77 
78  bool
79  is_quote(char c)
80  {
81  switch (c)
82  {
83  case '\"':
84  case '\'': return true;
85  default: return false;
86  }
87  }
88 
89  char
90  handle_escape_character(char c)
91  {
92  switch (c)
93  {
94  case 'n': return '\n';
95  case 't': return '\t';
96  default: return c;
97  }
98  }
99 }
100 
101 
102 std::vector<std::string>
103 parse_commandline(const std::string& str)
104 {
105  std::vector<std::string> ret;
106 
107  bool escape = false;
108  char current_string_character = 0;
109  auto buffer = StringBuilder{};
110 
111  for (char c : str)
112  {
113  if (escape)
114  {
115  buffer.add_char(handle_escape_character(c));
116  escape = false;
117  }
118  else
119  {
120  if (c == '\\')
121  {
122  escape = true;
123  }
124  else
125  {
126  if (current_string_character != 0)
127  {
128  if (c == current_string_character)
129  {
130  current_string_character = 0;
131  ret.emplace_back(buffer.to_string());
132  buffer.clear();
133  }
134  else
135  {
136  buffer.add_char(c);
137  }
138  }
139  else
140  {
141  // not within string
142  if (is_quote(c) || is_space(c))
143  {
144  if (is_quote(c))
145  {
146  current_string_character = c;
147  }
148  const auto b = buffer.to_string();
149  buffer.clear();
150  if (!b.empty())
151  {
152  ret.emplace_back(b);
153  }
154  }
155  else
156  {
157  // neither quote nor space
158  buffer.add_char(c);
159  }
160  }
161  }
162  }
163  }
164 
165  const auto rest = buffer.to_string();
166  if (!rest.empty() || current_string_character != 0)
167  {
168  ret.emplace_back(rest);
169  }
170 
171  return ret;
172 }
173 
174 
175 
176 }
std::string to_lower(const std::string &str)
Generate a string containing only lower characters.
Definition: stringutils.cc:143
std::vector< std::string > parse_commandline(const std::string &str)
Definition: console.cc:103
int line
Definition: nlp_sentence.cc:91
std::string buffer
Definition: nlp_sentence.cc:87
String utility functions.
std::vector< std::string > Args
Definition: console.h:16
std::function< void(const std::string &)> PrintFunction
Definition: console.h:17
void run(PrintFunction print, const std::string &cmd)
Definition: console.cc:27
void register_command(const std::string &name, ActionFunction callback)
Definition: console.cc:20
void print_help(VirtualConsole::PrintFunction print, const Args &)
Definition: console.cc:54
std::function< void(PrintFunction, const Args &)> ActionFunction
Definition: console.h:18
bool escape
Definition: ui_text.cc:135