[debugger] Added Ctrl-w
Ctrl-w removes characters from the beginning of the current word until
the cursor.
Reorganized some character constants so that they're usable from the
tests.
DX-879 # Done.
TEST=unit
Change-Id: If64846d03286a26493840777ffabd50ff9a21739
diff --git a/bin/zxdb/console/line_input.cc b/bin/zxdb/console/line_input.cc
index 344e462..3b0444e 100644
--- a/bin/zxdb/console/line_input.cc
+++ b/bin/zxdb/console/line_input.cc
@@ -15,32 +15,17 @@
#include <termios.h>
#endif
-#include "garnet/public/lib/fxl/logging.h"
+#include "lib/fxl/logging.h"
+#include "lib/fxl/strings/split_string.h"
namespace zxdb {
+const char* SpecialCharacters::kTermBeginningOfLine = "\r";
+const char* SpecialCharacters::kTermClearToEnd = "\x1b[0K";
+const char* SpecialCharacters::kTermCursorToColFormat = "\r\x1b[%dC";
+
namespace {
-constexpr char kKeyControlA = 1;
-constexpr char kKeyControlB = 2;
-constexpr char kKeyControlE = 5;
-constexpr char kKeyControlF = 6;
-constexpr char kKeyControlH = 8;
-constexpr char kKeyTab = 9;
-constexpr char kKeyNewline = 10;
-constexpr char kKeyFormFeed = 12;
-constexpr char kKeyEnter = 13;
-constexpr char kKeyControlN = 14;
-constexpr char kKeyControlP = 16;
-constexpr char kKeyControlU = 21;
-constexpr char kKeyEsc = 27;
-constexpr char kKeyBackspace = 127;
-
-// Escape sequences for terminal output.
-const char kTermBeginningOfLine[] = "\r";
-const char kTermClearToEnd[] = "\x1b[0K";
-const char kTermCursorToColFormat[] = "\r\x1b[%dC"; // printf format.
-
size_t GetTerminalMaxCols(int fileno) {
#ifdef __Fuchsia__
pty_window_size_t wsz;
@@ -82,7 +67,7 @@
if (completion_mode_) {
// Special keys for completion mode.
- if (c == kKeyTab) {
+ if (c == SpecialCharacters::kKeyTab) {
HandleTab();
return false;
}
@@ -93,42 +78,45 @@
}
switch (c) {
- case kKeyControlA:
+ case SpecialCharacters::kKeyControlA:
MoveHome();
break;
- case kKeyControlB:
+ case SpecialCharacters::kKeyControlB:
MoveLeft();
break;
- case kKeyControlE:
+ case SpecialCharacters::kKeyControlE:
MoveEnd();
break;
- case kKeyControlF:
+ case SpecialCharacters::kKeyControlF:
MoveRight();
break;
- case kKeyFormFeed:
+ case SpecialCharacters::kKeyFormFeed:
HandleFormFeed();
break;
- case kKeyTab:
+ case SpecialCharacters::kKeyTab:
HandleTab();
break;
- case kKeyNewline:
- case kKeyEnter:
+ case SpecialCharacters::kKeyNewline:
+ case SpecialCharacters::kKeyEnter:
HandleEnter();
return true;
- case kKeyControlN:
+ case SpecialCharacters::kKeyControlN:
MoveDown();
break;
- case kKeyControlP:
+ case SpecialCharacters::kKeyControlP:
MoveUp();
break;
- case kKeyControlU:
+ case SpecialCharacters::kKeyControlU:
HandleNegAck();
break;
- case kKeyEsc:
+ case SpecialCharacters::kKeyControlW:
+ HandleEndOfTransimission();
+ break;
+ case SpecialCharacters::kKeyEsc:
reading_escaped_input_ = true;
break;
- case kKeyControlH:
- case kKeyBackspace:
+ case SpecialCharacters::kKeyControlH:
+ case SpecialCharacters::kKeyBackspace:
HandleBackspace();
break;
default:
@@ -156,8 +144,8 @@
return;
std::string cmd;
- cmd += kTermBeginningOfLine;
- cmd += kTermClearToEnd;
+ cmd += SpecialCharacters::kTermBeginningOfLine;
+ cmd += SpecialCharacters::kTermClearToEnd;
Write(cmd);
EnsureNoRawMode();
@@ -286,6 +274,33 @@
RepaintLine();
}
+void LineInputBase::HandleEndOfTransimission() {
+ const auto& line = cur_line();
+ if (line.empty())
+ return;
+
+ // We search for the last space that's before the cursor.
+ size_t latest_space = 0;
+ for (size_t i = 0; i < line.size(); i++) {
+ if (i >= pos_)
+ break;
+
+ if (line[i] == ' ')
+ latest_space = i;
+ }
+
+ // Ctrl-w removes from the latest space until the cursor.
+ std::string new_line;
+ if (latest_space > 0)
+ new_line.append(line.substr(0, latest_space + 1));
+ new_line.append(line.substr(pos_));
+
+ size_t diff = line.size() - new_line.size();
+ pos_ -= diff;
+ cur_line() = std::move(new_line);
+ RepaintLine();
+}
+
void LineInputBase::HandleFormFeed() {
Write("\033c"); // Form feed.
RepaintLine();
@@ -367,7 +382,7 @@
std::string buf;
buf.reserve(64);
- buf += kTermBeginningOfLine;
+ buf += SpecialCharacters::kTermBeginningOfLine;
// Only print up to max_cols_ - 1 to leave room for the cursor at the end.
std::string line_data = prompt_ + cur_line();
@@ -388,10 +403,11 @@
buf += line_data;
}
- buf += kTermClearToEnd;
+ buf += SpecialCharacters::kTermClearToEnd;
char forward_buf[32];
- snprintf(forward_buf, sizeof(forward_buf), kTermCursorToColFormat,
+ snprintf(forward_buf, sizeof(forward_buf),
+ SpecialCharacters::kTermCursorToColFormat,
static_cast<int>(pos_in_cols));
buf += forward_buf;
diff --git a/bin/zxdb/console/line_input.h b/bin/zxdb/console/line_input.h
index e3ec949..882e66b 100644
--- a/bin/zxdb/console/line_input.h
+++ b/bin/zxdb/console/line_input.h
@@ -14,6 +14,29 @@
namespace zxdb {
+struct SpecialCharacters {
+ static constexpr char kKeyControlA = 1;
+ static constexpr char kKeyControlB = 2;
+ static constexpr char kKeyControlE = 5;
+ static constexpr char kKeyControlF = 6;
+ static constexpr char kKeyControlH = 8;
+ static constexpr char kKeyTab = 9;
+ static constexpr char kKeyNewline = 10;
+ static constexpr char kKeyFormFeed = 12;
+ static constexpr char kKeyEnter = 13;
+ static constexpr char kKeyControlN = 14;
+ static constexpr char kKeyControlP = 16;
+ static constexpr char kKeyControlU = 21;
+ static constexpr char kKeyControlW = 23;
+ static constexpr char kKeyEsc = 27;
+ static constexpr char kKeyBackspace = 127;
+
+ // Escape sequences for terminal output.
+ static const char* kTermBeginningOfLine;
+ static const char* kTermClearToEnd;
+ static const char* kTermCursorToColFormat; // printf format.
+};
+
// This class implements a push model for input of characters, allowing it to
// be used in asynchronous contexts.
//
@@ -84,6 +107,12 @@
virtual void EnsureRawMode() {}
virtual void EnsureNoRawMode() {}
+ // Helper to return the current line of text.
+ std::string& cur_line() { return history_[history_index_]; }
+
+ // Useful for testing.
+ void set_pos(size_t pos) { pos_ = pos; }
+
private:
void HandleEscapedInput(char c);
@@ -94,6 +123,8 @@
void HandleTab();
// NegAck is the name of Ctrl-U in ASCII world.
void HandleNegAck();
+ // EndOfTransimission is the name for Ctrl-W in ASCII world.
+ void HandleEndOfTransimission();
void Insert(char c);
void MoveLeft();
@@ -109,9 +140,6 @@
void RepaintLine();
void ResetLineState();
- // Helper to return the current line of text.
- std::string& cur_line() { return history_[history_index_]; }
-
const std::string prompt_;
size_t max_cols_ = 0;
CompletionCallback completion_callback_ = nullptr;
diff --git a/bin/zxdb/console/line_input_unittest.cc b/bin/zxdb/console/line_input_unittest.cc
index dbc9001..cb1d6c4 100644
--- a/bin/zxdb/console/line_input_unittest.cc
+++ b/bin/zxdb/console/line_input_unittest.cc
@@ -45,6 +45,15 @@
return result;
}
+ void SetLine(const std::string& input) {
+ cur_line() = input;
+ set_pos(input.size());
+ }
+
+ void SetPos(size_t pos) {
+ set_pos(pos);
+ }
+
protected:
void Write(const std::string& data) { output_.append(data); }
@@ -223,12 +232,12 @@
input.BeginReadLine();
// Empty should remain with them prompt.
- EXPECT_FALSE(input.OnInput(21)); // 21 = Control-U
+ EXPECT_FALSE(input.OnInput(SpecialCharacters::kKeyControlU));
EXPECT_EQ(input.line(), "");
// Adding characters and then Control-U should clear.
input.OnInputStr("12345");
- EXPECT_FALSE(input.OnInput(21)); // 21 = Control-U
+ EXPECT_FALSE(input.OnInput(SpecialCharacters::kKeyControlU));
EXPECT_EQ(input.line(), "");
// In the middle of the line should clear until the cursor.
@@ -237,9 +246,55 @@
EXPECT_FALSE(input.OnInputStr(TERM_LEFT));
EXPECT_FALSE(input.OnInputStr(TERM_LEFT));
EXPECT_FALSE(input.OnInputStr(TERM_LEFT));
- EXPECT_FALSE(input.OnInput(21)); // 21 = Control-U
+ EXPECT_FALSE(input.OnInput(SpecialCharacters::kKeyControlU));
EXPECT_EQ(input.line(), "6789");
EXPECT_EQ(input.pos(), 0u);
}
+TEST(LineInput, EndOfTransimission) {
+ TestLineInput input("[zxdb] ");
+ input.BeginReadLine();
+
+ // v
+ input.SetLine("First Second Third");
+ input.SetPos(0);
+ EXPECT_FALSE(input.OnInput(SpecialCharacters::kKeyControlW));
+ EXPECT_EQ(input.line(), "First Second Third");
+
+ // v
+ input.SetLine("First Second Third");
+ input.SetPos(2);
+ EXPECT_FALSE(input.OnInput(SpecialCharacters::kKeyControlW));
+ EXPECT_EQ(input.line(), "rst Second Third");
+
+ // v
+ input.SetLine("First Second Third");
+ input.SetPos(5);
+ EXPECT_FALSE(input.OnInput(SpecialCharacters::kKeyControlW));
+ EXPECT_EQ(input.line(), " Second Third");
+
+ // v
+ input.SetLine("First Second Third");
+ input.SetPos(8);
+ EXPECT_FALSE(input.OnInput(SpecialCharacters::kKeyControlW));
+ EXPECT_EQ(input.line(), "First cond Third");
+
+ // v
+ input.SetLine("First Second Third");
+ input.SetPos(12);
+ EXPECT_FALSE(input.OnInput(SpecialCharacters::kKeyControlW));
+ EXPECT_EQ(input.line(), "First Third");
+
+ // v
+ input.SetLine("First Second Third");
+ input.SetPos(15);
+ EXPECT_FALSE(input.OnInput(SpecialCharacters::kKeyControlW));
+ EXPECT_EQ(input.line(), "First Second ird");
+
+ // v
+ input.SetLine("First Second Third");
+ EXPECT_FALSE(input.OnInput(SpecialCharacters::kKeyControlW));
+ EXPECT_EQ(input.line(), "First Second ");
+}
+
} // namespace zxdb