17 |
#include "TerminalCtrl.h" |
#include "TerminalCtrl.h" |
18 |
#include "CFmt.h" |
#include "CFmt.h" |
19 |
#include "CCursor.h" |
#include "CCursor.h" |
20 |
|
#include "TerminalPrinter.h" |
21 |
|
|
22 |
#include "../common/global.h" |
#include "../common/global.h" |
23 |
#include "../common/global_private.h" |
#include "../common/global_private.h" |
35 |
static String g_goodPortion; |
static String g_goodPortion; |
36 |
static String g_badPortion; |
static String g_badPortion; |
37 |
static String g_suggestedPortion; |
static String g_suggestedPortion; |
38 |
|
static int g_linesActive = 0; |
39 |
static const String g_prompt = "lscp=# "; |
static const String g_prompt = "lscp=# "; |
40 |
static std::vector<String> g_commandHistory; |
static std::vector<String> g_commandHistory; |
41 |
static int g_commandHistoryIndex = -1; |
static int g_commandHistoryIndex = -1; |
270 |
sBad.erase(sBad.find(LSCP_SHK_CURSOR), strlen(LSCP_SHK_CURSOR)); // erase cursor marker |
sBad.erase(sBad.find(LSCP_SHK_CURSOR), strlen(LSCP_SHK_CURSOR)); // erase cursor marker |
271 |
if (sBad.find(LSCP_SHK_SUGGEST_BACK) != string::npos) |
if (sBad.find(LSCP_SHK_SUGGEST_BACK) != string::npos) |
272 |
sBad.erase(sBad.find(LSCP_SHK_SUGGEST_BACK)); // erase auto suggestion portion |
sBad.erase(sBad.find(LSCP_SHK_SUGGEST_BACK)); // erase auto suggestion portion |
273 |
|
if (sBad.find(LSCP_SHK_POSSIBILITIES_BACK) != string::npos) |
274 |
|
sBad.erase(sBad.find(LSCP_SHK_POSSIBILITIES_BACK)); // erase possibilities portion |
275 |
|
|
276 |
// extract portion that is suggested for auto completion |
// extract portion that is suggested for auto completion |
277 |
String sSuggest; |
String sSuggest; |
279 |
sSuggest = s.substr(s.find(LSCP_SHK_SUGGEST_BACK) + strlen(LSCP_SHK_SUGGEST_BACK)); |
sSuggest = s.substr(s.find(LSCP_SHK_SUGGEST_BACK) + strlen(LSCP_SHK_SUGGEST_BACK)); |
280 |
if (sSuggest.find(LSCP_SHK_CURSOR) != string::npos) |
if (sSuggest.find(LSCP_SHK_CURSOR) != string::npos) |
281 |
sSuggest.erase(sSuggest.find(LSCP_SHK_CURSOR), strlen(LSCP_SHK_CURSOR)); // erase cursor marker |
sSuggest.erase(sSuggest.find(LSCP_SHK_CURSOR), strlen(LSCP_SHK_CURSOR)); // erase cursor marker |
282 |
|
if (sSuggest.find(LSCP_SHK_POSSIBILITIES_BACK) != string::npos) |
283 |
|
sSuggest.erase(sSuggest.find(LSCP_SHK_POSSIBILITIES_BACK)); // erase possibilities portion |
284 |
|
} |
285 |
|
|
286 |
|
// extract portion that provides all current possibilities |
287 |
|
// (that is all branches in the current grammar tree) |
288 |
|
String sPossibilities; |
289 |
|
if (s.find(LSCP_SHK_POSSIBILITIES_BACK) != string::npos) { |
290 |
|
sPossibilities = s.substr(s.find(LSCP_SHK_POSSIBILITIES_BACK) + strlen(LSCP_SHK_POSSIBILITIES_BACK)); |
291 |
} |
} |
292 |
|
|
293 |
// extract current cursor position |
// extract current cursor position |
308 |
|
|
309 |
//printf("line '%s' good='%s' bad='%s' suggested='%s' cursor=%d\n", line.c_str(), sGood.c_str(), sBad.c_str(), sSuggest.c_str(), cursorColumn); |
//printf("line '%s' good='%s' bad='%s' suggested='%s' cursor=%d\n", line.c_str(), sGood.c_str(), sBad.c_str(), sSuggest.c_str(), cursorColumn); |
310 |
|
|
311 |
|
// clear current command line on screen |
312 |
|
// (which may have been printed over several lines) |
313 |
CCursor cursor = CCursor::now().toColumn(0).clearLine(); |
CCursor cursor = CCursor::now().toColumn(0).clearLine(); |
314 |
|
for (int i = 0; i < g_linesActive; ++i) |
315 |
|
cursor = cursor.down().clearLine(); |
316 |
|
if (g_linesActive) cursor = cursor.up(g_linesActive).toColumn(0); |
317 |
printPrompt(); |
printPrompt(); |
318 |
|
|
319 |
|
// print out the gathered informations on the screen |
320 |
|
TerminalPrinter p; |
321 |
CFmt cfmt; |
CFmt cfmt; |
322 |
if (code == LSCP_SHU_COMPLETE) cfmt.bold().green(); |
if (code == LSCP_SHU_COMPLETE) cfmt.bold().green(); |
323 |
else cfmt.bold().white(); |
else cfmt.bold().white(); |
324 |
cout << sGood << flush; |
p << sGood; |
325 |
cfmt.reset().red(); |
cfmt.reset().red(); |
326 |
cout << sBad << flush; |
p << sBad; |
327 |
cfmt.bold().yellow(); |
cfmt.bold().yellow(); |
328 |
cout << sSuggest << flush; |
p << sSuggest; |
329 |
|
if (!sPossibilities.empty()) |
330 |
|
p << " <- " << sPossibilities; |
331 |
|
|
332 |
|
// move cursor back to the appropriate input position in |
333 |
|
// the command line (which may be several lines above) |
334 |
|
g_linesActive = p.linesAdvanced(); |
335 |
|
if (p.linesAdvanced()) cursor.up(p.linesAdvanced()); |
336 |
cursor.toColumn(cursorColumn + promptOffset()); |
cursor.toColumn(cursorColumn + promptOffset()); |
337 |
} |
} |
338 |
} else if (line.substr(0,2) == "OK") { // single-line response expected ... |
} else if (line.substr(0,2) == "OK") { // single-line response expected ... |
378 |
while (g_keyboardReader->charAvailable()) { |
while (g_keyboardReader->charAvailable()) { |
379 |
char c = g_keyboardReader->popChar(); |
char c = g_keyboardReader->popChar(); |
380 |
|
|
|
CFmt cfmt; |
|
|
cfmt.white(); |
|
381 |
//std::cout << c << "(" << int(c) << ")" << std::endl << std::flush; |
//std::cout << c << "(" << int(c) << ")" << std::endl << std::flush; |
382 |
if (iKbdEscapeCharsExpected) { // escape sequence (still) expected now ... |
if (iKbdEscapeCharsExpected) { // escape sequence (still) expected now ... |
383 |
iKbdEscapeCharsExpected--; |
iKbdEscapeCharsExpected--; |
398 |
iKbdEscapeCharsExpected = 2; |
iKbdEscapeCharsExpected = 2; |
399 |
continue; // don't send ESC character to LSCP server |
continue; // don't send ESC character to LSCP server |
400 |
} else if (c == KBD_BACKSPACE) { |
} else if (c == KBD_BACKSPACE) { |
401 |
if (promptOffset() < CCursor::now().column()) |
c = '\b'; |
|
cout << "\b \b" << flush; |
|
|
c = '\b'; |
|
402 |
} else if (c == '\t') { // auto completion ... |
} else if (c == '\t') { // auto completion ... |
403 |
autoComplete(); |
autoComplete(); |
404 |
continue; // don't send tab character to LSCP server |
continue; // don't send tab character to LSCP server |
405 |
} else if (c == '\n') { |
} else if (c == '\n') { |
406 |
storeCommandInHistory(g_goodPortion + g_badPortion); |
storeCommandInHistory(g_goodPortion + g_badPortion); |
|
} else { // don't apply RETURN stroke yet, since the typed command might still be corrected by the sampler |
|
|
cout << c << flush; |
|
407 |
} |
} |
408 |
|
|
409 |
g_client->send(c); |
g_client->send(c); |