Replace debug console

This commit is contained in:
fvanroie 2020-11-19 00:38:49 +01:00
parent 8ad8a41722
commit 343d90ac5c
3 changed files with 853 additions and 171 deletions

560
lib/Console/Console.cpp Normal file
View File

@ -0,0 +1,560 @@
/* MIT License - Copyright (c) 2020 Francis Van Roie francis@netwize.be
For full license information read the LICENSE file in the project folder */
#include "Console.h"
#define TERM_CLEAR_LINE "\e[1000D\e[0K"
#define KEY_BUFFERED 0
#define KEY_FN 512
#define KEY_CTRL(n) (n - 64)
// Definitions
const int Console::KEY_NONE;
const int Console::KEY_UNKNOWN;
const int Console::KEY_BACKSPACE;
const int Console::KEY_LF;
const int Console::KEY_CR;
const int Console::KEY_UP;
const int Console::KEY_DOWN;
const int Console::KEY_LEFT;
const int Console::KEY_RIGHT;
const int Console::KEY_PAGE_UP;
const int Console::KEY_PAGE_DOWN;
const int Console::KEY_INSERT;
const int Console::KEY_DELETE;
const int Console::KEY_HOME;
const int Console::KEY_END;
const int Console::MOD_SHIFT;
const int Console::MOD_CTRL;
const int Console::MOD_CMND;
const int Console::MOD_ALT;
const int Console::MOD_ALT_GR;
uint16_t Console::end_sequence(uint16_t key)
{
if(key != 0) {
stream->println((int16_t)key);
}
// Clear escape sequence buffer
memset(esc_sequence, 0, sizeof(esc_sequence));
return key;
}
Console::Console(Stream * serial)
{
stream = serial;
end_sequence(0);
memset(input_buf, 0, sizeof(input_buf));
insert_mode = true;
debug_mode = false;
auto_update = true;
history_index = 0;
caret_pos = 0;
last_read = millis();
}
int Console::available(void)
{
return stream->available();
}
int Console::peek(void)
{
return stream->peek();
}
int Console::read(void)
{
last_read = millis();
return stream->read();
}
void Console::flush(void)
{
stream->flush();
}
size_t Console::write(uint8_t c)
{
return stream->write(c);
}
void Console::do_backspace()
{
history_index = 0;
// history scrolling can make it go out-of-bounds
size_t len = strnlen(input_buf, sizeof(input_buf));
if(caret_pos > len) caret_pos = len;
if(caret_pos <= 0) return;
caret_pos--;
char * src = input_buf + caret_pos + 1;
char * dst = input_buf + caret_pos;
memmove(dst, src, len - caret_pos);
}
void Console::do_delete()
{
history_index = 0;
size_t len = strnlen(input_buf, sizeof(input_buf));
char * dst = input_buf + caret_pos;
char * src = input_buf + caret_pos + 1;
memmove(dst, src, len - caret_pos);
}
bool Console::insertCharacter(char ch, size_t pos)
{
history_index = 0;
// stream->print(ch);
size_t len = strnlen(input_buf, sizeof(input_buf));
// history invoke can make the index go out-of-bounds
if(pos > len) pos = len;
if(pos == len && pos < sizeof(input_buf) - 2) {
// expand 1 character to the right
if(input_buf[pos + 1] != 0) {
// shift right needed
char * dst = input_buf + len + 1;
char * src = input_buf + len;
memmove(dst, src, sizeof(input_buf) - len - 1);
} else {
// we still have room
}
}
// Insert character if we have room
if(pos < sizeof(input_buf) - 2) {
if(pos + 1 >= len) input_buf[pos + 1] = 0;
input_buf[pos] = ch;
pos++;
return true;
}
// Buffer is full
return false;
}
bool Console::insertCharacter(char ch)
{
if(insertCharacter(ch, caret_pos)) {
caret_pos++;
return true;
}
return false;
}
// Get the position of the caret on the input buffer
int16_t Console::getCaret()
{
return caret_pos;
}
// Set the position of the caret on the input buffer
void Console::setCaret(int16_t index)
{
history_index = 0;
size_t len = strnlen(input_buf, sizeof(input_buf));
if(index > (int16_t)len) {
caret_pos = len;
} else if(index < 0) {
caret_pos = 0;
} else {
caret_pos = index;
}
}
// Print current input buffer
void Console::update()
{
stream->print(F(TERM_CLEAR_LINE)); // Move all the way left + Clear the line
stream->print(F("hasp > "));
if(debug_mode) {
for(uint i = 0; i < sizeof(input_buf); i++) {
if(input_buf[i] == 0) {
stream->print("|");
} else {
stream->print((char)input_buf[i]);
}
}
stream->print(history_index);
stream->print("/");
/*stream->print(debugHistorycount());*/
} else {
stream->print(input_buf);
}
stream->print("\e[1000D"); // Move all the way left again
/*if(caret_pos > 0)*/ {
stream->print("\e[");
stream->print(caret_pos + 7); // Move caret to index
stream->print("C");
}
}
int16_t Console::append_esc_char()
{
char key;
// no input available
if(!stream->available()) {
last_read = millis();
return 0;
}
// buffer position not available, read but don't buffer
if(esc_sequence[sizeof(esc_sequence) - 1] != 0) return stream->read();
// it's zero terminated
size_t pos = strnlen(esc_sequence, sizeof(esc_sequence));
key = stream->read();
esc_sequence[pos] = key;
for(int i = 1; i < sizeof(esc_sequence); i++) {
stream->printf("%2X %c", esc_sequence[i], esc_sequence[i]);
}
stream->println("append");
return key;
}
int16_t Console::getChar(uint8_t index)
{
int16_t key;
// flush buffer if sequence is not closed in timely fashion
if(esc_sequence[index] != 0x00 && ((uint16_t)millis() - last_read) > 100) {
key = esc_sequence[index];
memmove(esc_sequence, esc_sequence + 1, sizeof(esc_sequence) - 1);
esc_sequence[sizeof(esc_sequence) - 1] = 0;
return key; // flush one char at the time
}
// no input available
if(!stream->available()) {
last_read = millis();
return 0;
}
// buffer position not available
if(index >= sizeof(esc_sequence)) return stream->read();
// buffer position available and used
if(esc_sequence[index] != 0x00) return esc_sequence[index];
// buffer position available but not used
key = stream->read();
esc_sequence[index] = key;
for(int i = 1; i < sizeof(esc_sequence); i++) {
stream->printf("%2X %c", esc_sequence[i], esc_sequence[i]);
}
stream->println("get");
return key;
}
void Console::lineCallback()
{}
const char * Console::getLine()
{
return input_buf;
}
void Console::pushLine()
{}
void Console::clearLine()
{
size_t len = strnlen(input_buf, sizeof(input_buf));
memset(input_buf, 0, len);
caret_pos = 0;
}
size_t Console::debugHistorycount()
{
size_t count = 0;
for(size_t i = 1; i < sizeof(input_buf); i++) {
if(input_buf[i] == 0 && input_buf[i - 1] != 0) count++;
}
return count;
}
size_t Console::debugHistoryIndex(size_t num)
{
size_t pos = 0;
while(num > 0 && pos < sizeof(input_buf) - 2) {
if(input_buf[pos] == 0) {
num--;
// skip extra \0s
while(input_buf[pos] == 0) {
pos++;
}
} else {
pos++;
}
}
return pos;
}
void Console::debugShowHistory()
{
size_t num = debugHistorycount();
stream->println();
for(size_t i = 0; i <= num; i++) {
stream->print("[");
stream->print(i);
stream->print("] ");
size_t pos = debugHistoryIndex(i);
if(pos < sizeof(input_buf)) stream->println((char *)(input_buf + pos));
}
}
// Read a key from the terminal or -1 if no key pressed
int16_t Console::readKey()
{
int16_t key;
key = getChar(0);
if(key <= 0) return 0;
if(key == 0x1b) { /* escape sequence */
key = getChar(1);
if(key <= 0) return 0;
switch(key) {
case '[': { // CSI mode
char appended_key = append_esc_char();
if(appended_key <= 0) return 0;
switch(appended_key) {
case 0x30 ... 0x3F: // parameter bytes
case 0x20 ... 0x2F: // intermediate bytes
return KEY_NONE; // More data in flight
case 'A':
// size_t count = debugHistorycount();
// if(history_index < count) {
// history_index++;
// debugGetHistoryLine(history_index);
// }
end_sequence(0);
return KEY_UP;
case 'B':
// if(history_index > 0) {
// history_index--;
// debugGetHistoryLine(history_index);
// }
end_sequence(0);
return KEY_DOWN;
case 'C':
setCaret(caret_pos + 1);
end_sequence(0);
return KEY_RIGHT;
case 'D':
setCaret(caret_pos - 1);
end_sequence(0);
return KEY_LEFT;
case 'E' ... 0x7D: // End Characters, esc_sequence is complete
case '@':
stream->println("UNKNOWN");
end_sequence(0);
return KEY_UNKNOWN;
case '~':
if(!strncmp_P(esc_sequence, PSTR("\e[1~"), sizeof(esc_sequence))) {
setCaret(strlen(input_buf));
end_sequence(0);
return KEY_HOME;
} else if(!strncmp_P(esc_sequence, PSTR("\e[2~"), sizeof(esc_sequence))) {
end_sequence(0);
return KEY_INSERT;
} else if(!strncmp_P(esc_sequence, PSTR("\e[3~"), sizeof(esc_sequence))) {
do_delete();
end_sequence(0);
return KEY_DELETE;
} else if(!strncmp_P(esc_sequence, PSTR("\e[4~"), sizeof(esc_sequence))) {
setCaret(strlen(input_buf));
end_sequence(0);
return KEY_END;
} else if(!strncmp_P(esc_sequence, PSTR("\e[5~"), sizeof(esc_sequence))) {
end_sequence(0);
return KEY_PAGE_UP;
} else if(!strncmp_P(esc_sequence, PSTR("\e[6~"), sizeof(esc_sequence))) {
end_sequence(0);
return KEY_PAGE_DOWN;
} else if(!strncmp_P(esc_sequence, PSTR("\e[15~"), sizeof(esc_sequence))) {
stream->println("F5");
end_sequence(0);
} else if(!strncmp_P(esc_sequence, PSTR("\e[17~"), sizeof(esc_sequence))) {
stream->println("F6");
end_sequence(0);
} else if(!strncmp_P(esc_sequence, PSTR("\e[18~"), sizeof(esc_sequence))) {
stream->println("F7");
end_sequence(0);
} else if(!strncmp_P(esc_sequence, PSTR("\e[19~"), sizeof(esc_sequence))) {
stream->println("F8");
end_sequence(0);
} else if(!strncmp_P(esc_sequence, PSTR("\e[20~"), sizeof(esc_sequence))) {
stream->println("F9");
end_sequence(0);
} else if(!strncmp_P(esc_sequence, PSTR("\e[21~"), sizeof(esc_sequence))) {
stream->println("F10");
end_sequence(0);
} else if(!strncmp_P(esc_sequence, PSTR("\e[23~"), sizeof(esc_sequence))) {
stream->println("F11");
end_sequence(0);
} else if(!strncmp_P(esc_sequence, PSTR("\e[24~"), sizeof(esc_sequence))) {
stream->println("F12");
end_sequence(0);
}
end_sequence(0);
return KEY_UNKNOWN;
default:
// should not happen
stream->println("WARNGING !!!");
return KEY_UNKNOWN;
}
break;
} // CSI mode
case 'O': { // CSO mode
key = getChar(2);
if(key < 0) return 0;
switch(key) {
case 'P':
stream->println("F1");
end_sequence(0);
return KEY_FN + 1;
case 'Q':
stream->println("F2");
end_sequence(0);
return KEY_FN + 2;
case 'R':
stream->println("F3");
end_sequence(0);
return KEY_FN + 3;
case 'S':
stream->println("F4");
end_sequence(0);
return KEY_FN + 4;
default:
stream->println("UNKNOWN");
return KEY_UNKNOWN;
}
break;
} // CSO mode
default:
return KEY_UNKNOWN;
}
}
end_sequence(0);
switch(key) {
case KEY_CTRL('A')... KEY_CTRL('Z'): { // Ctrl + CHAR
switch(key) {
case KEY_CTRL('A'): // ^A = goto begin
caret_pos = 0;
history_index = 0;
return KEY_CTRL('A');
case KEY_CTRL('B'): // ^B = go back
caret_pos = strnlen(input_buf, sizeof(input_buf));
history_index = 0;
return KEY_CTRL('B');
case KEY_CTRL('C'): // ^C = Break
caret_pos = 0;
history_index = 0;
return KEY_CTRL('C');
case KEY_CTRL('E'): // ^E = goto end
caret_pos = strnlen(input_buf, sizeof(input_buf));
history_index = 0;
return KEY_CTRL('E');
case KEY_CTRL('F'): // ^F = go forward
caret_pos = strnlen(input_buf, sizeof(input_buf));
history_index = 0;
return KEY_CTRL('F');
case 8: // Backspace
do_backspace();
stream->println("Backspace");
return KEY_BACKSPACE;
case 9: // Delete
do_delete();
stream->println("Delete");
return KEY_DELETE;
case KEY_LF ... KEY_CR: { // LF, VT, FF, CR
// if(input_buf[0] != 0) {
// stream->println();
// dispatchTextLine(input_buf);
// size_t numchars = 1;
// memmove(input_buf + numchars, input_buf,
// sizeof(input_buf) - numchars); // Shift chars right
// caret_pos = 0;
// input_buf[0] = 0;
// history_index = 0;
// debugShowHistory();
return key;
}
case 0x1a: // PAUSE
return KEY_PAUSE;
}
return end_sequence(KEY_BUFFERED);
} // Ctrl + CHAR
case 32 ... 126:
case 128 ... 254:
insertCharacter(key);
return key;
case 0x7f: // DELETE
do_backspace();
return KEY_BACKSPACE;
}
return key;
}

88
lib/Console/Console.h Normal file
View File

@ -0,0 +1,88 @@
#ifndef CONSOLE_H
#define CONSOLE_H
#include <Arduino.h>
class Console : public Stream {
private:
Stream * stream;
char esc_sequence[10]; // escape sequence buffer
char input_buf[220]; // input buffer and with history
uint16_t last_read;
size_t caret_pos;
size_t history_index;
bool insert_mode;
bool debug_mode;
bool enable_history;
bool auto_update;
uint16_t end_sequence(uint16_t key);
int16_t append_esc_char();
void do_backspace();
void do_delete();
public:
// Declaration, initialization.
static const int KEY_NONE = -1;
static const int KEY_UNKNOWN = 401;
static const int KEY_LF = 0x0a;
static const int KEY_CR = 0x0d;
static const int KEY_PAUSE = 0x1a;
static const int KEY_ESC = 0x1b;
static const int KEY_BACKSPACE = 0x7f;
static const int KEY_UP = 256;
static const int KEY_DOWN = 257;
static const int KEY_LEFT = 258;
static const int KEY_RIGHT = 259;
static const int KEY_PAGE_UP = 260;
static const int KEY_PAGE_DOWN = 261;
static const int KEY_INSERT = 262;
static const int KEY_DELETE = 263;
static const int KEY_HOME = 264;
static const int KEY_END = 265;
static const int MOD_SHIFT = 1 << 10;
static const int MOD_CTRL = 1 << 11;
static const int MOD_CMND = 1 << 12;
static const int MOD_ALT = 1 << 13;
static const int MOD_ALT_GR = 1 << 14;
Console(Stream *);
int16_t readKey();
int16_t getChar(uint8_t index);
bool insertCharacter(char ch);
bool insertCharacter(char ch, size_t pos);
void setCaret(int16_t index);
int16_t getCaret(void);
void update(void);
void lineCallback();
const char * getLine();
void pushLine();
void clearLine();
size_t debugHistorycount();
size_t debugHistoryIndex(size_t num);
void debugShowHistory();
virtual int available(void);
virtual int peek(void);
virtual int read(void);
virtual void flush(void);
virtual size_t write(uint8_t);
using Print::write;
};
#endif

View File

@ -3,6 +3,7 @@
#include "ArduinoJson.h"
#include "ArduinoLog.h"
#include "Console.h"
#include "lvgl.h"
//#include "time.h"
@ -13,7 +14,7 @@
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#elif defined(ARDUINO_ARCH_ESP32)
#include <Wifi.h>
#include <WiFi.h>
#include <WiFiUdp.h>
#endif
@ -70,12 +71,14 @@ WiFiUDP * syslogClient;
#endif // USE_SYSLOG
// Serial Settings
uint16_t serialInputIndex = 0; // Empty buffer
char serialInputBuffer[220] = "";
uint16_t historyIndex = sizeof(serialInputBuffer) - 1; // Empty buffer
uint16_t debugSerialBaud = SERIAL_SPEED / 10; // Multiplied by 10
bool debugSerialStarted = false;
bool debugAnsiCodes = true;
// uint16_t serialInputIndex = 0; // Empty buffer
// char serialInputBuffer[220] = "";
// uint16_t historyIndex = sizeof(serialInputBuffer) - 1; // Empty buffer
uint16_t debugSerialBaud = SERIAL_SPEED / 10; // Multiplied by 10
bool debugSerialStarted = false;
bool debugAnsiCodes = true;
Console console(&Serial);
//#define TERM_COLOR_Black "\u001b[30m"
#define TERM_COLOR_GRAY "\e[37m"
@ -134,8 +137,8 @@ void debugStart()
void debugSetup()
{
memset(serialInputBuffer, 0, sizeof(serialInputBuffer));
serialInputIndex = 0;
// memset(serialInputBuffer, 0, sizeof(serialInputBuffer));
// serialInputIndex = 0;
#if HASP_USE_SYSLOG > 0
// syslog = new Syslog(syslogClient, debugSyslogProtocol == 0 ? SYSLOG_PROTO_IETF : SYSLOG_PROTO_BSD);
@ -226,7 +229,7 @@ inline void debugSendAnsiCode(const __FlashStringHelper * code, Print * _logOutp
{
if(debugAnsiCodes) _logOutput->print(code);
}
/*
size_t debugHistorycount()
{
size_t count = 0;
@ -308,14 +311,15 @@ void debugPrintPrompt()
Serial.print(debugHistorycount());
// Serial.print(serialInputBuffer);
Serial.print("\e[1000D"); // Move all the way left again
/*if(serialInputIndex > 0)*/ {
Serial.print("\e[");
Serial.print(serialInputIndex + 7); // Move cursor too index
Serial.print("C");
}
// Serial.flush();
/*if(serialInputIndex > 0)*/
/*{
Serial.print("\e[");
Serial.print(serialInputIndex + 7); // Move cursor too index
Serial.print("C");
}
// Serial.flush();
}
*/
static void debugPrintTimestamp(int level, Print * _logOutput)
{ /* Print Current Time */
time_t rawtime;
@ -584,7 +588,7 @@ void debugPrintSuffix(uint8_t tag, int level, Print * _logOutput)
_logOutput->print("hasp > ");
if(_logOutput == &Serial) debugPrintPrompt();
// if(_logOutput == &Serial) debugPrintPrompt();
// syslogSend(level, debugOutput);
}
@ -654,165 +658,195 @@ void debugLvgl(lv_log_level_t level, const char * file, uint32_t line, const cha
void debugLoop()
{
while(Serial.available()) {
char ch = Serial.read();
// Serial.println((byte)ch);
switch(ch) {
case 1: // ^A = goto begin
serialInputIndex = 0;
historyIndex = 0;
break;
case 3: // ^C
serialInputIndex = 0;
historyIndex = 0;
break;
case 5: // ^E = goto end
serialInputIndex = strlen(serialInputBuffer);
historyIndex = 0;
break;
case 8: // Backspace
{
if(serialInputIndex > strlen(serialInputBuffer)) {
serialInputIndex = strlen(serialInputBuffer);
}
if(serialInputIndex > 0) {
serialInputIndex--;
size_t len = strlen(serialInputBuffer);
char * currchar = serialInputBuffer + serialInputIndex;
memmove(currchar, currchar + 1, len - serialInputIndex);
}
historyIndex = 0;
} break;
case 9: // Delete
{
size_t len = strlen(serialInputBuffer);
char * nextchar = serialInputBuffer + serialInputIndex;
char * remainingchars = serialInputBuffer + serialInputIndex + 1;
memmove(nextchar, remainingchars, len - serialInputIndex);
historyIndex = 0;
} break;
case 10 ... 13: // LF, VT, FF, CR
if(serialInputBuffer[0] != 0) {
Serial.println();
dispatchTextLine(serialInputBuffer);
uint16_t key = console.getKey();
size_t numchars = 1;
memmove(serialInputBuffer + numchars, serialInputBuffer,
sizeof(serialInputBuffer) - numchars); // Shift chars right
}
serialInputIndex = 0;
serialInputBuffer[0] = 0;
historyIndex = 0;
debugShowHistory();
break;
switch(key) {
case 27:
/*if(Serial.peek() >= 0)*/ {
char nextchar = Serial.read();
if(nextchar == 91 /*&& Serial.peek() >= 0*/) {
nextchar = Serial.read();
switch(nextchar) {
case 51: // Del
/*if(Serial.peek() >= 0)*/ {
nextchar = Serial.read();
}
if(nextchar == 126) {
size_t len = strlen(serialInputBuffer);
char * nextchar = serialInputBuffer + serialInputIndex;
char * remainingchars = serialInputBuffer + serialInputIndex + 1;
memmove(nextchar, remainingchars, len - serialInputIndex);
}
break;
case 53: // Page Up
/*if(Serial.peek() >= 0)*/ {
nextchar = Serial.read();
}
if(nextchar == 126) {
dispatchPageNext();
}
historyIndex = 0;
break;
case 54: // Page Down
/*if(Serial.peek() >= 0)*/ {
nextchar = Serial.read();
if(nextchar == 126) {
dispatchPagePrev();
}
}
historyIndex = 0;
break;
case 65: {
size_t count = debugHistorycount();
if(historyIndex < count) {
historyIndex++;
debugGetHistoryLine(historyIndex);
}
break;
}
case 66:
if(historyIndex > 0) {
historyIndex--;
debugGetHistoryLine(historyIndex);
}
break;
case 68: // Left
if(serialInputIndex > 0) {
serialInputIndex--;
}
historyIndex = 0;
break;
case 67: // Right
if(serialInputIndex < strlen(serialInputBuffer)) {
serialInputIndex++;
}
historyIndex = 0;
break;
// default:
// Serial.println((byte)nextchar);
}
}
/* } else { // ESC, clear buffer
serialInputIndex = 0;
serialInputBuffer[serialInputIndex] = 0;*/
}
break;
case Console::KEY_LF... Console::KEY_CR:
console.print("You typed :");
console.println(console.getLine());
console.clearLine();
break;
case 32 ... 126:
case 128 ... 254: {
Serial.print(ch);
size_t len = strlen(serialInputBuffer);
if(serialInputIndex > len) serialInputIndex = len;
case Console::KEY_PAGE_UP:
console.println("PAGE_UP pressed");
break;
if(serialInputIndex == len && serialInputIndex < sizeof(serialInputBuffer) - 2) {
// expand needed
if(serialInputBuffer[serialInputIndex + 1] != 0) {
// shift right needed
char * dst = serialInputBuffer + len + 1;
char * src = serialInputBuffer + len;
memmove(dst, src, sizeof(serialInputBuffer) - len - 1);
}
}
if(serialInputIndex < sizeof(serialInputBuffer) - 2) {
if((size_t)1 + serialInputIndex >= strlen(serialInputBuffer))
serialInputBuffer[serialInputIndex + 1] = 0;
serialInputBuffer[serialInputIndex++] = ch;
}
} break;
case 127: // DEL
break;
// default:
// if(strcmp(serialInputBuffer, "jsonl=") == 0) {
// dispatchJsonl(Serial);
// serialInputIndex = 0;
// }
}
debugPrintPrompt();
case Console::KEY_PAGE_DOWN:
console.println("PAGE_DOWN pressed");
break;
}
if(key == Console::KEY_LF) {
console.print("You typed :");
console.println(console.getLine());
console.clearLine();
}
dispatchTextLine
if(key > 0) console.update();
// while(Serial.available()) {
// char ch = Serial.read();
// // Serial.println((byte)ch);
// switch(ch) {
// case 1: // ^A = goto begin
// serialInputIndex = 0;
// historyIndex = 0;
// break;
// case 3: // ^C
// serialInputIndex = 0;
// historyIndex = 0;
// break;
// case 5: // ^E = goto end
// serialInputIndex = strlen(serialInputBuffer);
// historyIndex = 0;
// break;
// case 8: // Backspace
// {
// if(serialInputIndex > strlen(serialInputBuffer)) {
// serialInputIndex = strlen(serialInputBuffer);
// }
// if(serialInputIndex > 0) {
// serialInputIndex--;
// size_t len = strlen(serialInputBuffer);
// char * currchar = serialInputBuffer + serialInputIndex;
// memmove(currchar, currchar + 1, len - serialInputIndex);
// }
// historyIndex = 0;
// } break;
// case 9: // Delete
// {
// size_t len = strlen(serialInputBuffer);
// char * nextchar = serialInputBuffer + serialInputIndex;
// char * remainingchars = serialInputBuffer + serialInputIndex + 1;
// memmove(nextchar, remainingchars, len - serialInputIndex);
// historyIndex = 0;
// } break;
// case 10 ... 13: // LF, VT, FF, CR
// if(serialInputBuffer[0] != 0) {
// Serial.println();
// dispatchTextLine(serialInputBuffer);
// size_t numchars = 1;
// memmove(serialInputBuffer + numchars, serialInputBuffer,
// sizeof(serialInputBuffer) - numchars); // Shift chars right
// }
// serialInputIndex = 0;
// serialInputBuffer[0] = 0;
// historyIndex = 0;
// debugShowHistory();
// break;
// case 27:
// /*if(Serial.peek() >= 0)*/ {
// char nextchar = Serial.read();
// if(nextchar == 91 /*&& Serial.peek() >= 0*/) {
// nextchar = Serial.read();
// switch(nextchar) {
// case 51: // Del
// /*if(Serial.peek() >= 0)*/ {
// nextchar = Serial.read();
// }
// if(nextchar == 126) {
// size_t len = strlen(serialInputBuffer);
// char * nextchar = serialInputBuffer + serialInputIndex;
// char * remainingchars = serialInputBuffer + serialInputIndex + 1;
// memmove(nextchar, remainingchars, len - serialInputIndex);
// }
// break;
// case 53: // Page Up
// /*if(Serial.peek() >= 0)*/ {
// nextchar = Serial.read();
// }
// if(nextchar == 126) {
// dispatchPageNext();
// }
// historyIndex = 0;
// break;
// case 54: // Page Down
// /*if(Serial.peek() >= 0)*/ {
// nextchar = Serial.read();
// if(nextchar == 126) {
// dispatchPagePrev();
// }
// }
// historyIndex = 0;
// break;
// case 65: {
// size_t count = debugHistorycount();
// if(historyIndex < count) {
// historyIndex++;
// debugGetHistoryLine(historyIndex);
// }
// break;
// }
// case 66:
// if(historyIndex > 0) {
// historyIndex--;
// debugGetHistoryLine(historyIndex);
// }
// break;
// case 68: // Left
// if(serialInputIndex > 0) {
// serialInputIndex--;
// }
// historyIndex = 0;
// break;
// case 67: // Right
// if(serialInputIndex < strlen(serialInputBuffer)) {
// serialInputIndex++;
// }
// historyIndex = 0;
// break;
// // default:
// // Serial.println((byte)nextchar);
// }
// }
// /* } else { // ESC, clear buffer
// serialInputIndex = 0;
// serialInputBuffer[serialInputIndex] = 0;*/
// }
// break;
// case 32 ... 126:
// case 128 ... 254: {
// Serial.print(ch);
// size_t len = strlen(serialInputBuffer);
// if(serialInputIndex > len) serialInputIndex = len;
// if(serialInputIndex == len && serialInputIndex < sizeof(serialInputBuffer) - 2) {
// // expand needed
// if(serialInputBuffer[serialInputIndex + 1] != 0) {
// // shift right needed
// char * dst = serialInputBuffer + len + 1;
// char * src = serialInputBuffer + len;
// memmove(dst, src, sizeof(serialInputBuffer) - len - 1);
// }
// }
// if(serialInputIndex < sizeof(serialInputBuffer) - 2) {
// if((size_t)1 + serialInputIndex >= strlen(serialInputBuffer))
// serialInputBuffer[serialInputIndex + 1] = 0;
// serialInputBuffer[serialInputIndex++] = ch;
// }
// } break;
// case 127: // DEL
// break;
// // default:
// // if(strcmp(serialInputBuffer, "jsonl=") == 0) {
// // dispatchJsonl(Serial);
// // serialInputIndex = 0;
// // }
// }
// debugPrintPrompt();
// }
}
/*void printLocalTime()