12 if (newUart ==
nullptr) {
27static bool isBackspace_(
char receivedChar) {
32static bool isNewline_(
char receivedChar) {
33 return receivedChar ==
'\n' || receivedChar ==
'\r';
39void tokenizeWhitespace(
const std::string& line,
41 std::queue<std::string>& outArgs)
44 while (!outArgs.empty()) {
50 if (token.empty()) {
return;}
51 if (outCmd.empty()) {outCmd = token;}
52 else {outArgs.push(token);}
56 for (
char ch : line) {
57 if (ch ==
' ' || ch ==
'\t') {flush();}
65 bool consumedInputThisCall =
false;
67 while (uart_->available() > 0) {
68 consumedInputThisCall =
true;
69 const char receivedChar =
static_cast<char>(uart_->read());
71 if (isBackspace_(receivedChar)) {
74 }
else if (isNewline_(receivedChar)) {
75 if (lastWasCR_ && receivedChar ==
'\n') {
79 lastWasCR_ = (receivedChar ==
'\r');
83 handleChar_(receivedChar);
87 if (consumedInputThisCall) {
88 lastInteractionTimestamp_ =
static_cast<uint32_t
>(millis());
92void CommandLine::handleBackspace_() {
93 if (fullLine_.empty()) {
return;}
95 uart_->print(
"\b \b");
98void CommandLine::handleNewline_() {
101 std::string line = fullLine_;
110 std::string cmd = {
""};
111 std::queue<std::string> args = {};
112 tokenizeWhitespace(line, cmd, args);
121void CommandLine::handleChar_(
char receivedChar) {
123 if (
static_cast<unsigned char>(receivedChar) <=
kCommandCharsAsciiEnd && receivedChar !=
'\t') {
return;}
127 uart_->println(
"Buffer overflow, input ignored.");
133 fullLine_ += receivedChar;
134 uart_->print(receivedChar);
139void CommandLine::addCommand(
const std::string& longName,
const std::string& shortName, std::function<
void(std::queue<std::string>, std::string&)> funcPtr) {
140 Command newCommand{ longName, shortName, funcPtr };
141 commands_.push_back(newCommand);
147 if (command ==
"help" || command ==
"?") {
152 std::string response;
153 for (
const auto& cmd : commands_) {
154 if (cmd.longName == command || cmd.shortName == command) {
156 cmd.funcPtr(arguments, response);
162 uart_->println(
"Command not found: " + String(command.c_str()));
163 uart_->println(
"Type 'help' or '?' to see available commands.");
167void CommandLine::help(){
168 if (commands_.empty()) {
169 uart_->
println(
"No commands available.");
174 for (
const auto& cmd : commands_) {
175 uart_->println(String(cmd.longName.c_str()) +
"<" + String(cmd.shortName.c_str()) +
">");
177 uart_->println(
"help<?>");
181void CommandLine::trimSpaces(std::string& str) {
183 size_t start = str.find_first_not_of(
" ");
185 if (start != std::string::npos) {
187 size_t end = str.find_last_not_of(
" ");
188 str = str.substr(start, end - start + 1);
constexpr int kCommandCharsAsciiEnd
constexpr int kUartBufferSize
constexpr const char * kShellPrompt
CommandLine(Stream *uartStream)
void switchUART(Stream *newUart)
void executeCommand(const std::string &command, std::queue< std::string > arguments)
void addCommand(const std::string &longName, const std::string &shortName, std::function< void(std::queue< std::string > argumentQueue, std::string &)> funcPtr)
void println(const T &message)