/*----------------------------------------------------------------------------- * Author: Nelso G. Jost (nelsojost@gmail.com) * License: GPLv2 * Purpose: Provide basic GPIO control commands for the REPL. *---------------------------------------------------------------------------*/ #include #include "repl.h" REPL::REPL(REPL_COMMAND * command_map) { this->_fp_map = command_map; this->_history[0] = ""; } void REPL::update(void) { char c; if (!Serial.available()) { yield(); return; } c = Serial.read(); if (c == 8) this->_backspace(); else if (c == 9) this->_clear_line(); else if (c == '[') this->_history_previous(); else if (c == ']') this->_history_next(); else if (c == 32 && !this->_command_buffer.length()) return; else { this->_command_buffer += c; if (c != 13) Serial.write(c); } //Serial.println(int(c)); if (this->_command_buffer.indexOf("\r") != -1 || this->_command_buffer.indexOf("\n") != -1) { this->_command_buffer.trim(); if (this->_command_buffer != "") { if (this->_command_buffer == "help") this->print_help(); else this->_execute_command(); this->_command_buffer = ""; } if (c != 13) Serial.print(this->prompt + " "); } Serial.flush(); } void REPL::_clear_line(void) { if (this->_command_buffer.length()) { this->_complete(); return; } Serial.print("\r \r"); Serial.print("> "); this->_command_buffer = ""; } void REPL::_complete(void) { String partial_name = this->get_arg(0); REPL_COMMAND * rc = this->_fp_map; String full_name; while (rc->name != NULL) { full_name = String(rc->name); if (full_name.startsWith(partial_name)) { Serial.print("\n\n[HELP] " + String(rc->prototype) + "\n" + this->prompt + " " + full_name + " "); this->_command_buffer = full_name + " "; } rc++; } } void REPL::_backspace(void) { if (this->_command_buffer.length() != 0) { Serial.write(8); Serial.write(32); Serial.write(8); this->_history_index = 0; this->_command_buffer.remove(this->_command_buffer.length() - 1); } } void REPL::_history_previous(void) { if (this->_history_index < HISTORY_MAX - 1 && \ this->_history[this->_history_index] != "") { this->_command_buffer = this->_history[this->_history_index]; this->_history_index++; Serial.print("\r \r"); Serial.print(this->prompt + " [" + this->_history_index + "] "); Serial.print(this->_command_buffer); } //this->log("history previous" + String(this->_history_index)); } void REPL::_history_next(void) { if (this->_history_index > 0 && \ this->_history[this->_history_index] != "") { this->_command_buffer = this->_history[this->_history_index]; this->_history_index--; Serial.print("\r \r"); Serial.print(this->prompt + " [" + this->_history_index + "] "); Serial.print(this->_command_buffer); } //this->log("history next" + String(this->_history_index)); } void REPL::_history_save(void) { this->_history_index = 0; if (this->_history[0] != this->_command_buffer) { for (int i=0; i < HISTORY_MAX - 2; i++) { this->_history[i+1] = this->_history[i]; } this->_history[0] = this->_command_buffer; } } int REPL::_execute_command(void) { String command_name = get_arg(0); bool show_help=false; if (command_name.endsWith("?")) { show_help = true; command_name.remove(command_name.length() - 1); } //Serial.print("\n[INFO] executing command \""); //Serial.print(command_str); //Serial.print("\""); REPL_COMMAND * rc = this->_fp_map; while (rc->name != NULL) { if (command_name == rc->name) { if (show_help) { Serial.print("\n\n[HELP] Syntax: "); Serial.println(rc->prototype); Serial.print("\n "); Serial.println(rc->help); return 0; } rc->func(this); this->_history_save(); return 0; } rc++; } Serial.print("\n[ERROR] invalid command \""); Serial.print(command_name); Serial.print("\""); return -1; } void REPL::print_help(void) { REPL_COMMAND * rc = this->_fp_map; Serial.print("\n------------------"); Serial.print("\nAvailable commands"); Serial.print("\n------------------"); while (rc->name != NULL) { Serial.print("\n "); Serial.print(rc->prototype); rc++; } Serial.print("\n------------------"); Serial.print("\nType \"command?\" for more details on the command."); Serial.print("\n------------------"); } void REPL::log(String msg, bool show_buffer) { Serial.print(msg); if (this->_command_buffer.length() > 0 and show_buffer) { Serial.print("\n" + this->prompt + " " + this->_command_buffer); } } String REPL::get_arg(int index) { String arg=""; int count=-1; bool found=false; for (int i=0; i < this->_command_buffer.length(); i++) { if (this->_command_buffer[i] != ' ') { found = true; arg += this->_command_buffer[i]; } else if (found == true) { count += 1; if (count == index) return arg; found = false; arg = ""; } } }