Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions lldb/include/lldb/Utility/AnsiTerminal.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,45 @@ inline std::string FormatAnsiTerminalCodes(llvm::StringRef format,
}
return fmt;
}

inline std::string StripAnsiTerminalCodes(llvm::StringRef str) {
std::string stripped;
while (!str.empty()) {
llvm::StringRef left, right;

std::tie(left, right) = str.split(ANSI_ESC_START);
stripped += left;

// ANSI_ESC_START not found.
if (left == str && right.empty())
break;

auto end = llvm::StringRef::npos;
for (size_t i = 0; i < right.size(); i++) {
char c = right[i];
if (c == 'm' || c == 'G') {
end = i;
break;
}
if (isdigit(c) || c == ';')
continue;

break;
}

// ANSI_ESC_END not found.
if (end != llvm::StringRef::npos) {
str = right.substr(end + 1);
continue;
}

stripped += ANSI_ESC_START;
str = right;
}
return stripped;
}

} // namespace ansi
} // namespace lldb_private

#endif
4 changes: 3 additions & 1 deletion lldb/source/Host/common/Editline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "lldb/Host/Editline.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Utility/AnsiTerminal.h"
#include "lldb/Utility/CompletionRequest.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/LLDBAssert.h"
Expand Down Expand Up @@ -85,7 +86,8 @@ bool IsOnlySpaces(const EditLineStringType &content) {
}

static size_t ColumnWidth(llvm::StringRef str) {
return llvm::sys::locale::columnWidth(str);
std::string stripped = ansi::StripAnsiTerminalCodes(str);
return llvm::sys::locale::columnWidth(stripped);
}

static int GetOperation(HistoryOperation op) {
Expand Down
16 changes: 16 additions & 0 deletions lldb/test/API/terminal/TestEditline.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,22 @@ def test_prompt_color(self):
# Column: 1....6.8
self.child.expect(re.escape("\x1b[31m(lldb) \x1b[0m\x1b[8G"))

@skipIfAsan
@skipIfEditlineSupportMissing
def test_prompt_format_color(self):
"""Test that we can change the prompt color with a format string."""
self.launch(use_colors=True)
# Clear the prefix and suffix setting to simplify the output.
self.child.send('settings set prompt-ansi-prefix ""\n')
self.child.send('settings set prompt-ansi-suffix ""\n')
self.child.send('settings set prompt "${ansi.fg.red}(lldb)${ansi.normal} "\n')
self.child.send("foo")
# Make sure this change is reflected immediately. Check that the color
# is set (31) and the cursor position (8) is correct.
# Prompt: (lldb) _
# Column: 1....6.8
self.child.expect(re.escape("\x1b[31m(lldb)\x1b[0m foo"))

@skipIfAsan
@skipIfEditlineSupportMissing
def test_prompt_no_color(self):
Expand Down
15 changes: 15 additions & 0 deletions lldb/unittests/Utility/AnsiTerminalTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,21 @@ TEST(AnsiTerminal, Empty) { EXPECT_EQ("", ansi::FormatAnsiTerminalCodes("")); }

TEST(AnsiTerminal, WhiteSpace) {
EXPECT_EQ(" ", ansi::FormatAnsiTerminalCodes(" "));
EXPECT_EQ(" ", ansi::StripAnsiTerminalCodes(" "));
}

TEST(AnsiTerminal, AtEnd) {
EXPECT_EQ("abc\x1B[30m",
ansi::FormatAnsiTerminalCodes("abc${ansi.fg.black}"));

EXPECT_EQ("abc", ansi::StripAnsiTerminalCodes("abc\x1B[30m"));
}

TEST(AnsiTerminal, AtStart) {
EXPECT_EQ("\x1B[30mabc",
ansi::FormatAnsiTerminalCodes("${ansi.fg.black}abc"));

EXPECT_EQ("abc", ansi::StripAnsiTerminalCodes("\x1B[30mabc"));
}

TEST(AnsiTerminal, KnownPrefix) {
Expand All @@ -45,10 +50,20 @@ TEST(AnsiTerminal, Incomplete) {
TEST(AnsiTerminal, Twice) {
EXPECT_EQ("\x1B[30m\x1B[31mabc",
ansi::FormatAnsiTerminalCodes("${ansi.fg.black}${ansi.fg.red}abc"));

EXPECT_EQ("abc", ansi::StripAnsiTerminalCodes("\x1B[30m\x1B[31mabc"));
}

TEST(AnsiTerminal, Basic) {
EXPECT_EQ(
"abc\x1B[31mabc\x1B[0mabc",
ansi::FormatAnsiTerminalCodes("abc${ansi.fg.red}abc${ansi.normal}abc"));

EXPECT_EQ("abcabcabc",
ansi::StripAnsiTerminalCodes("abc\x1B[31mabc\x1B[0mabc"));
}

TEST(AnsiTerminal, InvalidEscapeCode) {
EXPECT_EQ("abc\x1B[31kabcabc",
ansi::StripAnsiTerminalCodes("abc\x1B[31kabc\x1B[0mabc"));
}
Loading