[Lldb-commits] [lldb] [lldb] improve the heuristics for checking if a terminal supports Unicode (PR #171491)
Charles Zablit via lldb-commits
lldb-commits at lists.llvm.org
Wed Dec 10 04:50:36 PST 2025
https://github.com/charles-zablit updated https://github.com/llvm/llvm-project/pull/171491
>From 409c6fef0b7824ab5256ddb17a1b0312b0afd6ba Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Tue, 9 Dec 2025 19:06:16 +0000
Subject: [PATCH 1/2] [lldb] improve the heuristics for checking if a terminal
supports Unicode
---
lldb/include/lldb/Host/Terminal.h | 12 ++++++++++++
.../lldb/Host/common/DiagnosticsRendering.h | 19 ++++++++++++++++++-
.../Host/common/DiagnosticsRendering.cpp | 11 +++++------
lldb/source/Host/common/Terminal.cpp | 15 +++++++++++++++
.../Host/common/DiagnosticsRenderingTest.cpp | 2 +-
5 files changed, 51 insertions(+), 8 deletions(-)
diff --git a/lldb/include/lldb/Host/Terminal.h b/lldb/include/lldb/Host/Terminal.h
index da0d05e8bd265..3d66515c18812 100644
--- a/lldb/include/lldb/Host/Terminal.h
+++ b/lldb/include/lldb/Host/Terminal.h
@@ -68,6 +68,18 @@ class Terminal {
llvm::Error SetHardwareFlowControl(bool enabled);
+ /// Returns whether or not the current terminal supports Unicode rendering.
+ ///
+ /// The value is cached after the first computation.
+ ///
+ /// On POSIX systems, we check if the LANG environment variable contains the
+ /// substring "UTF-8", case insensitive.
+ ///
+ /// On Windows, we always return true since we use the `WriteConsoleW` API
+ /// internally. Note that the default Windows codepage (437) does not support
+ /// all Unicode characters. This function does not check the codepage.
+ static bool SupportsUnicode();
+
protected:
struct Data;
diff --git a/lldb/include/lldb/Host/common/DiagnosticsRendering.h b/lldb/include/lldb/Host/common/DiagnosticsRendering.h
index dd33d671c24a5..3eea0647da37e 100644
--- a/lldb/include/lldb/Host/common/DiagnosticsRendering.h
+++ b/lldb/include/lldb/Host/common/DiagnosticsRendering.h
@@ -59,10 +59,27 @@ struct DiagnosticDetail {
StructuredData::ObjectSP Serialize(llvm::ArrayRef<DiagnosticDetail> details);
+/// Renders an array of DiagnosticDetail instances.
+///
+/// \param[in] stream
+/// The stream to render the diagnostics to.
+/// \param offset_in_command
+/// An optional offset to the column position of the diagnostic in the
+/// source.
+/// \param show_inline
+/// Whether to show the diagnostics inline.
+/// \param details
+/// The array of DiagnosticsDetail to render.
+/// \param force_ascii
+/// Whether to force ascii rendering. If false, Unicode characters will be
+/// used if the output file supports them.
+///
+/// \see lldb_private::Terminal::SupportsUnicode
void RenderDiagnosticDetails(Stream &stream,
std::optional<uint16_t> offset_in_command,
bool show_inline,
- llvm::ArrayRef<DiagnosticDetail> details);
+ llvm::ArrayRef<DiagnosticDetail> details,
+ bool force_ascii = false);
class DiagnosticError
: public llvm::ErrorInfo<DiagnosticError, CloneableECError> {
diff --git a/lldb/source/Host/common/DiagnosticsRendering.cpp b/lldb/source/Host/common/DiagnosticsRendering.cpp
index f2cd3968967fb..2c9d33a6c325c 100644
--- a/lldb/source/Host/common/DiagnosticsRendering.cpp
+++ b/lldb/source/Host/common/DiagnosticsRendering.cpp
@@ -7,6 +7,8 @@
//===----------------------------------------------------------------------===//
#include "lldb/Host/common/DiagnosticsRendering.h"
+#include "lldb/Host/Terminal.h"
+
#include <cstdint>
using namespace lldb_private;
@@ -85,7 +87,8 @@ static llvm::raw_ostream &PrintSeverity(Stream &stream,
void RenderDiagnosticDetails(Stream &stream,
std::optional<uint16_t> offset_in_command,
bool show_inline,
- llvm::ArrayRef<DiagnosticDetail> details) {
+ llvm::ArrayRef<DiagnosticDetail> details,
+ bool force_ascii) {
if (details.empty())
return;
@@ -97,12 +100,8 @@ void RenderDiagnosticDetails(Stream &stream,
return;
}
- // Since there is no other way to find this out, use the color
- // attribute as a proxy for whether the terminal supports Unicode
- // characters. In the future it might make sense to move this into
- // Host so it can be customized for a specific platform.
llvm::StringRef cursor, underline, vbar, joint, hbar, spacer;
- if (stream.AsRawOstream().colors_enabled()) {
+ if (Terminal::SupportsUnicode() && !force_ascii) {
cursor = "˄";
underline = "˜";
vbar = "│";
diff --git a/lldb/source/Host/common/Terminal.cpp b/lldb/source/Host/common/Terminal.cpp
index 436dfd8130d9b..dd1dc75133f45 100644
--- a/lldb/source/Host/common/Terminal.cpp
+++ b/lldb/source/Host/common/Terminal.cpp
@@ -400,6 +400,21 @@ llvm::Error Terminal::SetHardwareFlowControl(bool enabled) {
#endif // LLDB_ENABLE_TERMIOS
}
+bool Terminal::SupportsUnicode() {
+ static std::optional<bool> result;
+ if (result)
+ return result.value();
+#ifdef _WIN32
+ return true;
+#else
+ const char *lang_var = std::getenv("LANG");
+ if (!lang_var)
+ return false;
+ result = llvm::StringRef(lang_var).lower().find("utf-8") != std::string::npos;
+#endif
+ return result.value();
+}
+
TerminalState::TerminalState(Terminal term, bool save_process_group)
: m_tty(term) {
Save(term, save_process_group);
diff --git a/lldb/unittests/Host/common/DiagnosticsRenderingTest.cpp b/lldb/unittests/Host/common/DiagnosticsRenderingTest.cpp
index 851b478def32e..78fc52ae11ad1 100644
--- a/lldb/unittests/Host/common/DiagnosticsRenderingTest.cpp
+++ b/lldb/unittests/Host/common/DiagnosticsRenderingTest.cpp
@@ -10,7 +10,7 @@ class ErrorDisplayTest : public ::testing::Test {};
std::string Render(std::vector<DiagnosticDetail> details) {
StreamString stream;
- RenderDiagnosticDetails(stream, 0, true, details);
+ RenderDiagnosticDetails(stream, 0, true, details, true);
return stream.GetData();
}
} // namespace
>From 27f07b4f0a672ac98ee5ed9b76c5459e693bc791 Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Wed, 10 Dec 2025 12:50:18 +0000
Subject: [PATCH 2/2] address comments
---
lldb/source/Host/common/Terminal.cpp | 11 ++++++-----
.../Host/common/DiagnosticsRenderingTest.cpp | 2 +-
2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/lldb/source/Host/common/Terminal.cpp b/lldb/source/Host/common/Terminal.cpp
index dd1dc75133f45..d3647835e3937 100644
--- a/lldb/source/Host/common/Terminal.cpp
+++ b/lldb/source/Host/common/Terminal.cpp
@@ -401,18 +401,19 @@ llvm::Error Terminal::SetHardwareFlowControl(bool enabled) {
}
bool Terminal::SupportsUnicode() {
- static std::optional<bool> result;
- if (result)
- return result.value();
+ static std::optional<bool> g_result;
+ if (g_result)
+ return g_result.value();
#ifdef _WIN32
return true;
#else
const char *lang_var = std::getenv("LANG");
if (!lang_var)
return false;
- result = llvm::StringRef(lang_var).lower().find("utf-8") != std::string::npos;
+ g_result =
+ llvm::StringRef(lang_var).lower().find("utf-8") != std::string::npos;
#endif
- return result.value();
+ return g_result.value();
}
TerminalState::TerminalState(Terminal term, bool save_process_group)
diff --git a/lldb/unittests/Host/common/DiagnosticsRenderingTest.cpp b/lldb/unittests/Host/common/DiagnosticsRenderingTest.cpp
index 78fc52ae11ad1..896ce1995fe1c 100644
--- a/lldb/unittests/Host/common/DiagnosticsRenderingTest.cpp
+++ b/lldb/unittests/Host/common/DiagnosticsRenderingTest.cpp
@@ -10,7 +10,7 @@ class ErrorDisplayTest : public ::testing::Test {};
std::string Render(std::vector<DiagnosticDetail> details) {
StreamString stream;
- RenderDiagnosticDetails(stream, 0, true, details, true);
+ RenderDiagnosticDetails(stream, 0, true, details, /*force_ascii=*/true);
return stream.GetData();
}
} // namespace
More information about the lldb-commits
mailing list