shell line edit: cursor, pos1, end, del, F1..

This commit is contained in:
MichaelDvP
2020-11-01 14:22:57 +01:00
parent 4019ada7ec
commit cb228d8c8b
3 changed files with 111 additions and 71 deletions

View File

@@ -1,6 +1,7 @@
# Changelog # Changelog
### Added ### Added
- function keys in editor: cursor, del, pos1, end. F1=help, F2=show, F10=report
### Fixed ### Fixed

View File

@@ -65,8 +65,8 @@ void Shell::start() {
#endif #endif
line_buffer_.reserve(maximum_command_line_length_); line_buffer_.reserve(maximum_command_line_length_);
oldline_.reserve(maximum_command_line_length_); line_old_.reserve(maximum_command_line_length_);
oldline_.clear(); line_old_.clear();
display_banner(); display_banner();
display_prompt(); display_prompt();
shells_.insert(shared_from_this()); shells_.insert(shared_from_this());
@@ -148,8 +148,7 @@ void Shell::loop_normal() {
// Interrupt (^C) // Interrupt (^C)
line_buffer_.clear(); line_buffer_.clear();
println(); println();
prompt_displayed_ = false; cursor_ = 0;
display_prompt();
break; break;
case '\x04': case '\x04':
@@ -160,51 +159,38 @@ void Shell::loop_normal() {
break; break;
case '\x08': case '\x08':
case '\x7F':
// Backspace (^H) // Backspace (^H)
// Delete (^?) case '\x7F':
if (!line_buffer_.empty()) { // Del/Backspace (^?)
erase_characters(1); if (line_buffer_.length() > cursor_) {
line_buffer_.pop_back(); line_buffer_.erase(line_buffer_.length() - cursor_ - 1, 1);
} }
break; break;
case '\x09': case '\x09':
// Tab (^I) // Tab (^I)
process_completion(); process_completion();
cursor_ = 0;
break; break;
case '\x0A': case '\x0A':
// Line feed (^J) // Line feed (^J)
if (previous_ != '\x0D') { if (previous_ != '\x0D') {
if (!line_buffer_.empty()) {
oldline_ = line_buffer_;
}
process_command(); process_command();
} }
break; break;
case '\x0C':
// New page (^L)
erase_current_line();
prompt_displayed_ = false;
display_prompt();
break;
case '\x0D': case '\x0D':
if (!line_buffer_.empty()) {
oldline_ = line_buffer_;
}
// Carriage return (^M) // Carriage return (^M)
process_command(); process_command();
break; break;
case '\x0C':
// New page (^L)
case '\x15': case '\x15':
// Delete line (^U) // Delete line (^U)
erase_current_line();
prompt_displayed_ = false;
line_buffer_.clear(); line_buffer_.clear();
display_prompt(); cursor_ = 0;
break; break;
case '\x17': case '\x17':
@@ -212,51 +198,91 @@ void Shell::loop_normal() {
delete_buffer_word(true); delete_buffer_word(true);
break; break;
case '\033':
// esc
esc_ = 0x80;
break;
default: default:
if (c >= '\x20' && c <= '\x7E') { if (esc_) {
if (c == '[') {
// start of sequence
} else if (c >= '0' && (c <= '9')) {
// numbers
esc_ = (esc_ & 0x7F) * 10 + c - '0';
} else if (c == 'A') {
// cursor up
line_buffer_ = line_old_;
cursor_ = 0;
esc_ = 0;
} else if (c == 'B') {
// cursor down
line_buffer_.clear();
cursor_ = 0;
esc_ = 0;
} else if (c == 'C') {
// cursor right
if (cursor_) {
cursor_--;
}
esc_ = 0;
} else if (c == 'D') {
// cursor left
if (cursor_ < line_buffer_.length()) {
cursor_++;
}
esc_ = 0;
} else if (c == '~') {
// function keys with number
if ((esc_ == 3) && cursor_) {
// del
cursor_--;
line_buffer_.erase(line_buffer_.length() - cursor_ - 1, 1);
} else if (esc_ == 4) {
// end
cursor_ = 0;
} else if (esc_ == 1) {
// pos1
cursor_ = line_buffer_.length();
} else if (esc_ == 11) {
// F1 and F10
line_buffer_ = "help";
process_command();
} else if (esc_ == 12) {
// F2
line_buffer_ = "show";
process_command();
} else if (esc_ == 20) {
// F9
line_buffer_ = "send telegram \"0B \"";
cursor_ = 1;
} else if (esc_ == 21) {
// F10
line_buffer_ = "call system report";
process_command();
}
esc_ = 0;
} else {
// all other chars end sequence
esc_ = 0;
}
} else if (c >= '\x20' && c <= '\x7E') {
// ASCII text // ASCII text
if (line_buffer_.length() < maximum_command_line_length_) { if (line_buffer_.length() < maximum_command_line_length_) {
line_buffer_.push_back(c); line_buffer_.insert(line_buffer_.length() - cursor_, 1, c);
write((uint8_t)c);
}
// cursor up, get last command
if ((c == 'A') && (previous_ == '[')) {
erase_current_line();
prompt_displayed_ = false;
line_buffer_ = oldline_;
display_prompt();
}
// cursor back, delete cursor chars
if ((c == 'D') && (previous_ == '[')) {
line_buffer_.pop_back();
line_buffer_.pop_back();
// alternative work as backspace
// if (line_buffer_.length() > 0) {
// line_buffer_.pop_back();
// }
erase_current_line();
prompt_displayed_ = false;
display_prompt();
}
// cursor forward, only delete cursor chars
if ((c == 'C') && (previous_ == '[')) {
line_buffer_.pop_back();
line_buffer_.pop_back();
erase_current_line();
prompt_displayed_ = false;
display_prompt();
}
// cursor down(B): Delete line
if ((c == 'B') && (previous_ == '[')) {
erase_current_line();
prompt_displayed_ = false;
line_buffer_.clear();
display_prompt();
} }
} }
break; break;
} }
// common for all, display the complete line
erase_current_line();
prompt_displayed_ = false;
display_prompt();
if (cursor_) {
printf(F("\033[%dD"), cursor_);
}
previous_ = c; previous_ = c;
// This is a hack to let TelnetStream know that command // This is a hack to let TelnetStream know that command
@@ -428,16 +454,24 @@ void Shell::delete_buffer_word(bool display) {
if (pos == std::string::npos) { if (pos == std::string::npos) {
line_buffer_.clear(); line_buffer_.clear();
if (display) { cursor_ = 0;
erase_current_line();
prompt_displayed_ = false;
display_prompt();
}
} else { } else {
if (display) { if (display) {
erase_characters(line_buffer_.length() - pos); size_t pos1 = 0;
pos = 0;
while (pos1 < line_buffer_.length() - cursor_) {
pos = pos1;
pos1 = line_buffer_.find(' ', pos + 1);
} }
line_buffer_.erase(pos, pos1 - pos);
if (line_buffer_.find(' ') == 0) {
line_buffer_.erase(0, 1);
}
cursor_ = line_buffer_.length() - pos;
} else {
line_buffer_.resize(pos); line_buffer_.resize(pos);
cursor_ = 0;
}
} }
} }
@@ -453,7 +487,6 @@ void Shell::maximum_command_line_length(size_t length) {
void Shell::process_command() { void Shell::process_command() {
CommandLine command_line{line_buffer_}; CommandLine command_line{line_buffer_};
line_buffer_.clear();
println(); println();
prompt_displayed_ = false; prompt_displayed_ = false;
@@ -467,8 +500,12 @@ void Shell::process_command() {
} else { } else {
println(F("No commands configured")); println(F("No commands configured"));
} }
line_old_ = line_buffer_;
} }
cursor_ = 0;
line_buffer_.clear();
if (running()) { if (running()) {
display_prompt(); display_prompt();
} }

View File

@@ -903,9 +903,11 @@ class Shell : public std::enable_shared_from_this<Shell>, public uuid::log::Hand
std::list<QueuedLogMessage> log_messages_; /*!< Queued log messages, in the order they were received. @since 0.1.0 */ std::list<QueuedLogMessage> log_messages_; /*!< Queued log messages, in the order they were received. @since 0.1.0 */
size_t maximum_log_messages_ = MAX_LOG_MESSAGES; /*!< Maximum command line length in bytes. @since 0.6.0 */ size_t maximum_log_messages_ = MAX_LOG_MESSAGES; /*!< Maximum command line length in bytes. @since 0.6.0 */
std::string line_buffer_; /*!< Command line buffer. Limited to maximum_command_line_length() bytes. @since 0.1.0 */ std::string line_buffer_; /*!< Command line buffer. Limited to maximum_command_line_length() bytes. @since 0.1.0 */
std::string line_old_; /*!< old Command line buffer.*/
size_t maximum_command_line_length_ = MAX_COMMAND_LINE_LENGTH; /*!< Maximum command line length in bytes. @since 0.6.0 */ size_t maximum_command_line_length_ = MAX_COMMAND_LINE_LENGTH; /*!< Maximum command line length in bytes. @since 0.6.0 */
unsigned char previous_ = 0; /*!< Previous character that was entered on the command line. Used to detect CRLF line endings. @since 0.1.0 */ unsigned char previous_ = 0; /*!< Previous character that was entered on the command line. Used to detect CRLF line endings. @since 0.1.0 */
std::string oldline_; /*!< old Command line buffer.*/ uint8_t cursor_ = 0; /*!< cursor position from end of line */
uint8_t esc_ = 0; /*!< esc sequence running */
Mode mode_ = Mode::NORMAL; /*!< Current execution mode. @since 0.1.0 */ Mode mode_ = Mode::NORMAL; /*!< Current execution mode. @since 0.1.0 */
std::unique_ptr<ModeData> mode_data_ = nullptr; /*!< Data associated with the current execution mode. @since 0.1.0 */ std::unique_ptr<ModeData> mode_data_ = nullptr; /*!< Data associated with the current execution mode. @since 0.1.0 */
bool stopped_ = false; /*!< Indicates that the shell has been stopped. @since 0.1.0 */ bool stopped_ = false; /*!< Indicates that the shell has been stopped. @since 0.1.0 */