This commit is contained in:
Jacob Anderson 2025-07-02 19:08:21 +02:00 committed by GitHub
commit e46877f013
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 70 additions and 2 deletions

View file

@ -637,6 +637,24 @@ fn setup_terminal(tui: &mut Tui, state: &mut State, vt_parser: &mut vt::Parser)
tui.setup_indexed_colors(indexed_colors);
}
// Detects if edit is running on an "old" version of terminal.app on Mac OS. If it detects
// the terminal.app is older than version 460, which added truecolor support,
// is_old_macos_terminal gets set to true, and sets ColorMode to Color256.
let is_old_macos_terminal = {
if env::var("TERM_PROGRAM").as_deref() == Ok("Apple_Terminal") {
env::var("TERM_PROGRAM_VERSION")
.ok()
.and_then(|s| s.split('.').next()?.parse::<u32>().ok())
.map_or(false, |v| v < 460)
} else {
false
}
};
if is_old_macos_terminal {
tui.setup_color_mode(framebuffer::ColorMode::Color256);
}
RestoreModes
}

View file

@ -53,6 +53,14 @@ pub enum IndexedColor {
Foreground,
}
/// Color modes used in format_color function
#[derive(Clone, Copy, Default)]
pub enum ColorMode {
#[default]
TrueColor,
Color256,
}
/// Number of indices used by [`IndexedColor`].
pub const INDEXED_COLORS_COUNT: usize = 18;
@ -105,6 +113,8 @@ pub struct Framebuffer {
contrast_colors: [Cell<(u32, u32)>; CACHE_TABLE_SIZE],
background_fill: u32,
foreground_fill: u32,
// The color mode, either truecolor(default) or color256
color_mode: ColorMode,
}
impl Framebuffer {
@ -121,6 +131,7 @@ impl Framebuffer {
contrast_colors: [const { Cell::new((0, 0)) }; CACHE_TABLE_SIZE],
background_fill: DEFAULT_THEME[IndexedColor::Background as usize],
foreground_fill: DEFAULT_THEME[IndexedColor::Foreground as usize],
color_mode: ColorMode::default(),
}
}
@ -537,6 +548,12 @@ impl Framebuffer {
result
}
// Sets the color rendering mode, either truecolor(default) or color256, determined by the
// setup_terminal function in main.rs
pub fn set_color_mode(&mut self, mode: ColorMode) {
self.color_mode = mode;
}
fn format_color(&self, dst: &mut ArenaString, fg: bool, mut color: u32) {
let typ = if fg { '3' } else { '4' };
@ -567,7 +584,35 @@ impl Framebuffer {
let r = color & 0xff;
let g = (color >> 8) & 0xff;
let b = (color >> 16) & 0xff;
_ = write!(dst, "\x1b[{typ}8;2;{r};{g};{b}m");
// If the terminal doesn't support truecolor, the rgb channel needs to be
// downsampled to display properly.
match self.color_mode {
ColorMode::TrueColor => {
_ = write!(dst, "\x1b[{typ}8;2;{r};{g};{b}m");
}
ColorMode::Color256 => {
let index: u8 = if r == g && g == b {
// grayscale path
if r < 8 {
16
} else if r > 248 {
231
} else {
let gray_index = ((r - 8 + 5) / 10).min(23);
232 + gray_index
}
} else {
// Color path
let r_idx = (r * 6 / 256) as u32;
let g_idx = (g * 6 / 256) as u32;
let b_idx = (b * 6 / 256) as u32;
(16 + 36 * r_idx + 6 * g_idx + b_idx) as u32
} as u8;
_ = write!(dst, "\x1b[{typ}8;5;{index}m");
}
}
}
}

View file

@ -154,7 +154,7 @@ use crate::buffer::{CursorMovement, MoveLineDirection, RcTextBuffer, TextBuffer,
use crate::cell::*;
use crate::clipboard::Clipboard;
use crate::document::WriteableDocument;
use crate::framebuffer::{Attributes, Framebuffer, INDEXED_COLORS_COUNT, IndexedColor};
use crate::framebuffer::{Attributes, ColorMode, Framebuffer, INDEXED_COLORS_COUNT, IndexedColor};
use crate::hash::*;
use crate::helpers::*;
use crate::input::{InputKeyMod, kbmod, vk};
@ -429,6 +429,11 @@ impl Tui {
self.framebuffer.set_indexed_colors(colors);
}
/// Sets the color rendering mode based on terminal capabilities.
pub fn setup_color_mode(&mut self, mode: ColorMode) {
self.framebuffer.set_color_mode(mode);
}
/// Set up translations for Ctrl/Alt/Shift modifiers.
pub fn setup_modifier_translations(&mut self, translations: ModifierTranslations) {
self.modifier_translations = translations;