Joedb 10.4.3
The Journal-Only Embedded Database
Loading...
Searching...
No Matches
Command_Interpreter.cpp
Go to the documentation of this file.
3#include "joedb/ui/type_io.h"
4
5#include <sstream>
6#include <ctype.h>
7#include <fstream>
8
9namespace joedb
10{
11 ////////////////////////////////////////////////////////////////////////////
12 void Command_Interpreter::after_command
13 ////////////////////////////////////////////////////////////////////////////
14 (
15 std::ostream &out,
16 int64_t line_number,
17 const std::string_view line,
18 const Exception *exception
19 ) const
20 {
21 if (exception)
22 {
23 std::ostringstream error;
24 error << exception->what();
25 error << "\nLine " << line_number << ": " << line << '\n';
26
27 if (rethrow)
28 throw Exception(error.str());
29 else
30 out << "Exception caught: " << error.str();
31 }
32 else if (echo)
33 out << "OK: " << line << '\n';
34 }
35
36 ////////////////////////////////////////////////////////////////////////////
38 ////////////////////////////////////////////////////////////////////////////
39 (
40 const std::string_view command,
41 std::istream &parameters,
42 std::istream &in,
43 std::ostream &out
44 )
45 {
46 if (command.empty() || command[0] == '#') /////////////////////////////////
47 {
48 }
49 else if (command == "about") //////////////////////////////////////////////
50 {
51 about_joedb(out);
52 }
53 else if (command == "echo") ///////////////////////////////////////////////
54 {
55 std::string parameter;
56 parameters >> parameter;
57
58 if (parameter == "on")
59 set_echo(true);
60 else if (parameter == "off")
61 set_echo(false);
62 }
63 else if (command == "prompt") /////////////////////////////////////////////
64 {
65 std::string parameter;
66 parameters >> parameter;
67
68 if (parameter == "on")
69 set_prompt(true);
70 else if (parameter == "off")
71 set_prompt(false);
72 }
73 else if (command == "help") ///////////////////////////////////////////////
74 {
75 out << R"RRR(
76General commands
77~~~~~~~~~~~~~~~~
78 about
79 help|?
80 quit
81 abort
82 echo on|off
83 prompt on|off
84 include "file_name"
85
86)RRR";
87
88 return Status::ok;
89 }
90 else if (command == "include") ////////////////////////////////////////////
91 {
92 const std::string file_name = read_string(parameters);
93 std::ifstream ifs(file_name);
94
95 if (ifs)
96 {
97 struct Recursion
98 {
99 int &depth;
100 Recursion(int &depth_init): depth(depth_init) {++depth;}
101 ~Recursion() {--depth;}
102 }
103 recursion(recursion_depth);
104
105 constexpr int max_recursion_depth = 42;
106
107 if (recursion_depth > max_recursion_depth)
108 throw Exception("Reached max recursion depth");
109 else
110 main_loop(ifs, out);
111 }
112 else
113 throw Exception("error opening " + file_name);
114 }
115 else if (command == "quit") ///////////////////////////////////////////////
116 return Status::quit;
117 else if (command == "abort") //////////////////////////////////////////////
118 return Status::abort;
119 else
120 return Status::not_found;
121
122 return Status::done;
123 }
124
125 ////////////////////////////////////////////////////////////////////////////
127 ////////////////////////////////////////////////////////////////////////////
128 {
129 add_processor(*static_cast<Command_Processor *>(this));
130 }
131
132 ////////////////////////////////////////////////////////////////////////////
134 ////////////////////////////////////////////////////////////////////////////
135 {
136 processors.emplace_back(processor);
137 }
138
139 ////////////////////////////////////////////////////////////////////////////
140 void Command_Interpreter::set_parent(const Command_Interpreter *new_parent)
141 ////////////////////////////////////////////////////////////////////////////
142 {
143 parent = new_parent;
144
145 if (parent)
146 {
147 echo = parent->echo;
148 rethrow = parent->rethrow;
149 prompt = parent->prompt;
151 }
152
153 ////////////////////////////////////////////////////////////////////////////
154 void Command_Interpreter::write_prompt(std::ostream &out) const
155 ////////////////////////////////////////////////////////////////////////////
156 {
157 out << prompt_string;
158 }
159
160 ////////////////////////////////////////////////////////////////////////////
161 void Command_Interpreter::write_whole_prompt(std::ostream &out) const
162 ////////////////////////////////////////////////////////////////////////////
163 {
164 out << "\x1b[36m";
165
166 if (parent)
168 parent->write_prompt(out);
169 out << '/';
170 }
171
172 write_prompt(out);
173 out << "> \x1b[0m";
174 out.flush();
175 }
176
177 ////////////////////////////////////////////////////////////////////////////
178 void Command_Interpreter::main_loop(std::istream &in, std::ostream &out)
179 ////////////////////////////////////////////////////////////////////////////
180 {
181 int64_t line_number = 0;
182 bool abort = false;
183
184 while(true)
185 {
186 if (prompt)
188
189 std::string line;
190 if (!std::getline(in, line))
191 break;
192 while (!line.empty() && isspace(line.back()))
193 line.pop_back();
194
195 last_line_empty = line.empty();
196
197 line_number++;
198 std::istringstream iss(line);
199 std::string command;
200 iss >> command;
201
202 if (command == "?")
203 command = "help";
204
205 try
206 {
207 bool found = false;
208 bool quit = false;
209
210 for (const auto &processor: processors)
211 {
212 const Command_Processor::Status status =
213 processor.get().process_command(command, iss, in, out);
214
216 found = true;
217
219 {
220 quit = true;
221 break;
222 }
223
225 {
226 abort = true;
227 break;
228 }
229
231 break;
232 }
233
234 if (!found)
235 {
236 throw Exception
237 (
238 "Unknown command. For a list of available commands, try \"help\"."
239 );
240 }
241
242 after_command(out, line_number, line, nullptr);
243
244 if (quit || abort)
245 break;
246 }
247 catch (const Exception &e)
248 {
249 after_command(out, line_number, line, &e);
250 }
251 }
252
253 if (abort)
254 throw Exception("aborted");
255 }
256}
void set_parent(const Command_Interpreter *new_parent)
void main_loop(std::istream &in, std::ostream &out)
void write_whole_prompt(std::ostream &out) const
void add_processor(Command_Processor &processor)
virtual void write_prompt(std::ostream &out) const
Status process_command(std::string_view command, std::istream &parameters, std::istream &in, std::ostream &out) override
virtual Status process_command(std::string_view command, std::istream &parameters, std::istream &in, std::ostream &out)=0
void about_joedb(std::ostream &out)
std::string read_string(std::istream &in)
Definition type_io.cpp:12