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