Skip to content

Commit 8445909

Browse files
[lldb] improve the heuristics for checking if a terminal supports Unicode (#171491)
1 parent fb8a7c7 commit 8445909

File tree

5 files changed

+52
-8
lines changed

5 files changed

+52
-8
lines changed

lldb/include/lldb/Host/Terminal.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,18 @@ class Terminal {
6868

6969
llvm::Error SetHardwareFlowControl(bool enabled);
7070

71+
/// Returns whether or not the current terminal supports Unicode rendering.
72+
///
73+
/// The value is cached after the first computation.
74+
///
75+
/// On POSIX systems, we check if the LANG environment variable contains the
76+
/// substring "UTF-8", case insensitive.
77+
///
78+
/// On Windows, we always return true since we use the `WriteConsoleW` API
79+
/// internally. Note that the default Windows codepage (437) does not support
80+
/// all Unicode characters. This function does not check the codepage.
81+
static bool SupportsUnicode();
82+
7183
protected:
7284
struct Data;
7385

lldb/include/lldb/Host/common/DiagnosticsRendering.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,27 @@ struct DiagnosticDetail {
5959

6060
StructuredData::ObjectSP Serialize(llvm::ArrayRef<DiagnosticDetail> details);
6161

62+
/// Renders an array of DiagnosticDetail instances.
63+
///
64+
/// \param[in] stream
65+
/// The stream to render the diagnostics to.
66+
/// \param offset_in_command
67+
/// An optional offset to the column position of the diagnostic in the
68+
/// source.
69+
/// \param show_inline
70+
/// Whether to show the diagnostics inline.
71+
/// \param details
72+
/// The array of DiagnosticsDetail to render.
73+
/// \param force_ascii
74+
/// Whether to force ascii rendering. If false, Unicode characters will be
75+
/// used if the output file supports them.
76+
///
77+
/// \see lldb_private::Terminal::SupportsUnicode
6278
void RenderDiagnosticDetails(Stream &stream,
6379
std::optional<uint16_t> offset_in_command,
6480
bool show_inline,
65-
llvm::ArrayRef<DiagnosticDetail> details);
81+
llvm::ArrayRef<DiagnosticDetail> details,
82+
bool force_ascii = false);
6683

6784
class DiagnosticError
6885
: public llvm::ErrorInfo<DiagnosticError, CloneableECError> {

lldb/source/Host/common/DiagnosticsRendering.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "lldb/Host/common/DiagnosticsRendering.h"
10+
#include "lldb/Host/Terminal.h"
11+
1012
#include <cstdint>
1113

1214
using namespace lldb_private;
@@ -85,7 +87,8 @@ static llvm::raw_ostream &PrintSeverity(Stream &stream,
8587
void RenderDiagnosticDetails(Stream &stream,
8688
std::optional<uint16_t> offset_in_command,
8789
bool show_inline,
88-
llvm::ArrayRef<DiagnosticDetail> details) {
90+
llvm::ArrayRef<DiagnosticDetail> details,
91+
bool force_ascii) {
8992
if (details.empty())
9093
return;
9194

@@ -97,12 +100,8 @@ void RenderDiagnosticDetails(Stream &stream,
97100
return;
98101
}
99102

100-
// Since there is no other way to find this out, use the color
101-
// attribute as a proxy for whether the terminal supports Unicode
102-
// characters. In the future it might make sense to move this into
103-
// Host so it can be customized for a specific platform.
104103
llvm::StringRef cursor, underline, vbar, joint, hbar, spacer;
105-
if (stream.AsRawOstream().colors_enabled()) {
104+
if (Terminal::SupportsUnicode() && !force_ascii) {
106105
cursor = "˄";
107106
underline = "˜";
108107
vbar = "";

lldb/source/Host/common/Terminal.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,22 @@ llvm::Error Terminal::SetHardwareFlowControl(bool enabled) {
400400
#endif // LLDB_ENABLE_TERMIOS
401401
}
402402

403+
bool Terminal::SupportsUnicode() {
404+
static std::optional<bool> g_result;
405+
if (g_result)
406+
return g_result.value();
407+
#ifdef _WIN32
408+
return true;
409+
#else
410+
const char *lang_var = std::getenv("LANG");
411+
if (!lang_var)
412+
return false;
413+
g_result =
414+
llvm::StringRef(lang_var).lower().find("utf-8") != std::string::npos;
415+
#endif
416+
return g_result.value();
417+
}
418+
403419
TerminalState::TerminalState(Terminal term, bool save_process_group)
404420
: m_tty(term) {
405421
Save(term, save_process_group);

lldb/unittests/Host/common/DiagnosticsRenderingTest.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class ErrorDisplayTest : public ::testing::Test {};
1010

1111
std::string Render(std::vector<DiagnosticDetail> details) {
1212
StreamString stream;
13-
RenderDiagnosticDetails(stream, 0, true, details);
13+
RenderDiagnosticDetails(stream, 0, true, details, /*force_ascii=*/true);
1414
return stream.GetData();
1515
}
1616
} // namespace

0 commit comments

Comments
 (0)