6#include <initializer_list>
14#define WIN32_LEAN_AND_MEAN
25#if defined(__sun) || defined(__illumos__)
26#include <sys/termios.h>
33std::unique_ptr<Terminal::Quirks> g_quirks;
34bool g_color_support_detected =
false;
36bool& ColorSupportDetected() {
37 return g_color_support_detected;
40Terminal::Quirks& GetQuirksInternal() {
42 g_quirks = std::make_unique<Terminal::Quirks>();
44 g_quirks->SetBlockCharacters(
false);
45 g_quirks->SetCursorHiding(
false);
46 g_quirks->SetComponentAscii(
true);
52Dimensions& FallbackSize() {
53#if defined(__EMSCRIPTEN__)
57 constexpr int fallback_width = 140;
58 constexpr int fallback_height = 43;
63 constexpr int fallback_width = 80;
64 constexpr int fallback_height = 24;
66 static Dimensions g_fallback_size{
70 return g_fallback_size;
73bool Contains(std::string_view s, std::string_view key) {
77 const auto it = std::search(
78 s.begin(), s.end(), key.begin(), key.end(), [](
char a,
char b) {
79 return std::tolower(static_cast<unsigned char>(a)) ==
80 std::tolower(static_cast<unsigned char>(b));
85bool ContainsAny(std::string_view s,
86 std::initializer_list<std::string_view> keys) {
87 for (
const std::string_view key : keys) {
88 if (Contains(s, key)) {
96 static const std::vector<int> empty_capabilities;
99 util::GetEnv(
"TERM_PROGRAM"),
"unknown",
"unknown", empty_capabilities);
107 bool block_characters =
true;
108 bool cursor_hiding =
true;
109 bool component_ascii =
false;
113Quirks::Quirks() : impl_(std::make_unique<Impl>()) {}
114Quirks::~Quirks() =
default;
115Quirks::Quirks(
const Quirks& other)
116 : impl_(std::make_unique<Impl>(*other.impl_)) {}
117Quirks& Quirks::operator=(
const Quirks& other) {
118 if (
this != &other) {
119 *impl_ = *other.impl_;
123Quirks::Quirks(Quirks&&) noexcept = default;
124Quirks& Quirks::operator=(Quirks&&) noexcept = default;
126bool Quirks::BlockCharacters()
const {
127 return impl_->block_characters;
129void Quirks::SetBlockCharacters(
bool v) {
130 impl_->block_characters = v;
133bool Quirks::CursorHiding()
const {
134 return impl_->cursor_hiding;
136void Quirks::SetCursorHiding(
bool v) {
137 impl_->cursor_hiding = v;
140bool Quirks::ComponentAscii()
const {
141 return impl_->component_ascii;
143void Quirks::SetComponentAscii(
bool v) {
144 impl_->component_ascii = v;
147Color Quirks::ColorSupport()
const {
148 return impl_->color_support;
150void Quirks::SetColorSupport(Color v) {
151 impl_->color_support = v;
154struct TerminalInfo::Impl {
156 std::string colorterm;
157 std::string term_program;
158 std::string terminal_name;
159 std::string terminal_emulator_name;
160 std::vector<int> capabilities;
163TerminalInfo::TerminalInfo() : impl_(std::make_unique<Impl>()) {}
164TerminalInfo::~TerminalInfo() =
default;
165TerminalInfo::TerminalInfo(TerminalInfo&&) noexcept = default;
166TerminalInfo& TerminalInfo::operator=(TerminalInfo&&) noexcept = default;
168void TerminalInfo::SetTerm(std::string_view term) {
171void TerminalInfo::SetColorterm(std::string_view colorterm) {
172 impl_->colorterm = colorterm;
174void TerminalInfo::SetTermProgram(std::string_view term_program) {
175 impl_->term_program = term_program;
177void TerminalInfo::SetTerminalName(std::string_view terminal_name) {
178 impl_->terminal_name = terminal_name;
180void TerminalInfo::SetTerminalEmulatorName(
181 std::string_view terminal_emulator_name) {
182 impl_->terminal_emulator_name = terminal_emulator_name;
184void TerminalInfo::SetCapabilities(std::vector<int> capabilities) {
185 impl_->capabilities = std::move(capabilities);
197 std::string_view colorterm,
198 std::string_view term_program,
199 std::string_view terminal_name,
200 std::string_view terminal_emulator_name,
201 const std::vector<int>& capabilities) {
204 info.SetColorterm(colorterm);
205 info.SetTermProgram(term_program);
206 info.SetTerminalName(terminal_name);
207 info.SetTerminalEmulatorName(terminal_emulator_name);
208 info.SetCapabilities(capabilities);
209 return info.ComputeColorSupport();
212Color TerminalInfo::ComputeColorSupport()
const {
219 if (util::GetEnv(
"NO_COLOR")[0] !=
'\0') {
220 return Terminal::Color::Palette1;
224#if defined(__EMSCRIPTEN__)
225 return Terminal::Color::TrueColor;
229 auto stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
231 if (GetConsoleMode(stdout_handle, &out_mode)) {
232 const int enable_virtual_terminal_processing = 0x0004;
233 const int disable_newline_auto_return = 0x0008;
234 out_mode |= enable_virtual_terminal_processing;
235 out_mode |= disable_newline_auto_return;
236 if (!SetConsoleMode(stdout_handle, out_mode)) {
237 return Terminal::Color::Palette16;
240 return Terminal::Color::TrueColor;
244 if (util::GetEnv(
"WT_SESSION")[0] !=
'\0') {
245 return Terminal::Color::TrueColor;
249 if (ContainsAny(impl_->colorterm, {
"24bit",
"truecolor"})) {
250 return Terminal::Color::TrueColor;
252 if (ContainsAny(impl_->term,
253 {
"direct",
"truecolor",
"kitty",
"alacritty",
"foot"})) {
254 return Terminal::Color::TrueColor;
256 if (ContainsAny(impl_->colorterm, {
"256"}) ||
257 ContainsAny(impl_->term, {
"256",
"xterm",
"screen",
"tmux"})) {
258 return Terminal::Color::Palette256;
262 if (ContainsAny(impl_->term_program, {
269 return Terminal::Color::TrueColor;
273 if (Contains(impl_->term_program,
"apple_terminal")) {
274 return Terminal::Color::Palette256;
280 if (!impl_->terminal_emulator_name.empty() &&
281 impl_->terminal_emulator_name !=
"unknown") {
282 return Terminal::Color::TrueColor;
284 if (impl_->terminal_name ==
"xterm") {
285 return Terminal::Color::TrueColor;
287 for (
const int x : impl_->capabilities) {
293 return Terminal::Color::Palette256;
297 return Terminal::Color::Palette16;
304#if defined(__EMSCRIPTEN__)
308 return FallbackSize();
310 CONSOLE_SCREEN_BUFFER_INFO csbi;
312 if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) {
313 return Dimensions{csbi.srWindow.Right - csbi.srWindow.Left + 1,
314 csbi.srWindow.Bottom - csbi.srWindow.Top + 1};
317 return FallbackSize();
320 const int status = ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
323 if (w.ws_col == 0 || w.ws_row == 0 || status < 0) {
324 return FallbackSize();
326 return Dimensions{w.ws_col, w.ws_row};
332void SetFallbackSize(
const Dimensions& fallbackSize) {
333 FallbackSize() = fallbackSize;
339 if (!ColorSupportDetected()) {
340 GetQuirksInternal().SetColorSupport(ComputeColorSupportInternal());
341 ColorSupportDetected() =
true;
343 return GetQuirksInternal().ColorSupport();
349 GetQuirksInternal().SetColorSupport(color);
350 ColorSupportDetected() =
true;
356 if (!ColorSupportDetected()) {
357 GetQuirksInternal().SetColorSupport(ComputeColorSupportInternal());
358 ColorSupportDetected() =
true;
360 return GetQuirksInternal();
365void SetQuirks(
const Quirks& quirks) {
366 GetQuirksInternal() = quirks;
367 ColorSupportDetected() =
true;
Color
Color est une énumération qui représente le support des couleurs du terminal.
L'espace de noms ftxui::Terminal:: de FTXUI.
Color ComputeColorSupport(std::string_view term, std::string_view colorterm, std::string_view term_program, std::string_view terminal_name, std::string_view terminal_emulator_name, const std::vector< int > &capabilities)
Calcule la prise en charge des couleurs en fonction des variables d'environnement et de l'identificat...
const char * GetEnv(const char *name)
L'espace de noms FTXUI ftxui::