Rebasing onto main
This commit is contained in:
parent
9b6167aad8
commit
86d5794040
3 changed files with 230 additions and 138 deletions
134
crates/terminal/src/color_translation.rs
Normal file
134
crates/terminal/src/color_translation.rs
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
use alacritty_terminal::{ansi::Color as AnsiColor, term::color::Rgb as AlacRgb};
|
||||||
|
use gpui::color::Color;
|
||||||
|
use theme::TerminalStyle;
|
||||||
|
|
||||||
|
///Converts a 2, 8, or 24 bit color ANSI color to the GPUI equivalent
|
||||||
|
pub fn convert_color(alac_color: &AnsiColor, style: &TerminalStyle) -> Color {
|
||||||
|
match alac_color {
|
||||||
|
//Named and theme defined colors
|
||||||
|
alacritty_terminal::ansi::Color::Named(n) => match n {
|
||||||
|
alacritty_terminal::ansi::NamedColor::Black => style.black,
|
||||||
|
alacritty_terminal::ansi::NamedColor::Red => style.red,
|
||||||
|
alacritty_terminal::ansi::NamedColor::Green => style.green,
|
||||||
|
alacritty_terminal::ansi::NamedColor::Yellow => style.yellow,
|
||||||
|
alacritty_terminal::ansi::NamedColor::Blue => style.blue,
|
||||||
|
alacritty_terminal::ansi::NamedColor::Magenta => style.magenta,
|
||||||
|
alacritty_terminal::ansi::NamedColor::Cyan => style.cyan,
|
||||||
|
alacritty_terminal::ansi::NamedColor::White => style.white,
|
||||||
|
alacritty_terminal::ansi::NamedColor::BrightBlack => style.bright_black,
|
||||||
|
alacritty_terminal::ansi::NamedColor::BrightRed => style.bright_red,
|
||||||
|
alacritty_terminal::ansi::NamedColor::BrightGreen => style.bright_green,
|
||||||
|
alacritty_terminal::ansi::NamedColor::BrightYellow => style.bright_yellow,
|
||||||
|
alacritty_terminal::ansi::NamedColor::BrightBlue => style.bright_blue,
|
||||||
|
alacritty_terminal::ansi::NamedColor::BrightMagenta => style.bright_magenta,
|
||||||
|
alacritty_terminal::ansi::NamedColor::BrightCyan => style.bright_cyan,
|
||||||
|
alacritty_terminal::ansi::NamedColor::BrightWhite => style.bright_white,
|
||||||
|
alacritty_terminal::ansi::NamedColor::Foreground => style.foreground,
|
||||||
|
alacritty_terminal::ansi::NamedColor::Background => style.background,
|
||||||
|
alacritty_terminal::ansi::NamedColor::Cursor => style.cursor,
|
||||||
|
alacritty_terminal::ansi::NamedColor::DimBlack => style.dim_black,
|
||||||
|
alacritty_terminal::ansi::NamedColor::DimRed => style.dim_red,
|
||||||
|
alacritty_terminal::ansi::NamedColor::DimGreen => style.dim_green,
|
||||||
|
alacritty_terminal::ansi::NamedColor::DimYellow => style.dim_yellow,
|
||||||
|
alacritty_terminal::ansi::NamedColor::DimBlue => style.dim_blue,
|
||||||
|
alacritty_terminal::ansi::NamedColor::DimMagenta => style.dim_magenta,
|
||||||
|
alacritty_terminal::ansi::NamedColor::DimCyan => style.dim_cyan,
|
||||||
|
alacritty_terminal::ansi::NamedColor::DimWhite => style.dim_white,
|
||||||
|
alacritty_terminal::ansi::NamedColor::BrightForeground => style.bright_foreground,
|
||||||
|
alacritty_terminal::ansi::NamedColor::DimForeground => style.dim_foreground,
|
||||||
|
},
|
||||||
|
//'True' colors
|
||||||
|
alacritty_terminal::ansi::Color::Spec(rgb) => Color::new(rgb.r, rgb.g, rgb.b, u8::MAX),
|
||||||
|
//8 bit, indexed colors
|
||||||
|
alacritty_terminal::ansi::Color::Indexed(i) => get_color_at_index(&(*i as usize), style),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///Converts an 8 bit ANSI color to it's GPUI equivalent.
|
||||||
|
///Accepts usize for compatability with the alacritty::Colors interface,
|
||||||
|
///Other than that use case, should only be called with values in the [0,255] range
|
||||||
|
pub fn get_color_at_index(index: &usize, style: &TerminalStyle) -> Color {
|
||||||
|
match index {
|
||||||
|
//0-15 are the same as the named colors above
|
||||||
|
0 => style.black,
|
||||||
|
1 => style.red,
|
||||||
|
2 => style.green,
|
||||||
|
3 => style.yellow,
|
||||||
|
4 => style.blue,
|
||||||
|
5 => style.magenta,
|
||||||
|
6 => style.cyan,
|
||||||
|
7 => style.white,
|
||||||
|
8 => style.bright_black,
|
||||||
|
9 => style.bright_red,
|
||||||
|
10 => style.bright_green,
|
||||||
|
11 => style.bright_yellow,
|
||||||
|
12 => style.bright_blue,
|
||||||
|
13 => style.bright_magenta,
|
||||||
|
14 => style.bright_cyan,
|
||||||
|
15 => style.bright_white,
|
||||||
|
//16-231 are mapped to their RGB colors on a 0-5 range per channel
|
||||||
|
16..=231 => {
|
||||||
|
let (r, g, b) = rgb_for_index(&(*index as u8)); //Split the index into it's ANSI-RGB components
|
||||||
|
let step = (u8::MAX as f32 / 5.).floor() as u8; //Split the RGB range into 5 chunks, with floor so no overflow
|
||||||
|
Color::new(r * step, g * step, b * step, u8::MAX) //Map the ANSI-RGB components to an RGB color
|
||||||
|
}
|
||||||
|
//232-255 are a 24 step grayscale from black to white
|
||||||
|
232..=255 => {
|
||||||
|
let i = *index as u8 - 232; //Align index to 0..24
|
||||||
|
let step = (u8::MAX as f32 / 24.).floor() as u8; //Split the RGB grayscale values into 24 chunks
|
||||||
|
Color::new(i * step, i * step, i * step, u8::MAX) //Map the ANSI-grayscale components to the RGB-grayscale
|
||||||
|
}
|
||||||
|
//For compatability with the alacritty::Colors interface
|
||||||
|
256 => style.foreground,
|
||||||
|
257 => style.background,
|
||||||
|
258 => style.cursor,
|
||||||
|
259 => style.dim_black,
|
||||||
|
260 => style.dim_red,
|
||||||
|
261 => style.dim_green,
|
||||||
|
262 => style.dim_yellow,
|
||||||
|
263 => style.dim_blue,
|
||||||
|
264 => style.dim_magenta,
|
||||||
|
265 => style.dim_cyan,
|
||||||
|
266 => style.dim_white,
|
||||||
|
267 => style.bright_foreground,
|
||||||
|
268 => style.black, //'Dim Background', non-standard color
|
||||||
|
_ => Color::new(0, 0, 0, 255),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
///Generates the rgb channels in [0, 5] for a given index into the 6x6x6 ANSI color cube
|
||||||
|
///See: [8 bit ansi color](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit).
|
||||||
|
///
|
||||||
|
///Wikipedia gives a formula for calculating the index for a given color:
|
||||||
|
///
|
||||||
|
///index = 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5)
|
||||||
|
///
|
||||||
|
///This function does the reverse, calculating the r, g, and b components from a given index.
|
||||||
|
fn rgb_for_index(i: &u8) -> (u8, u8, u8) {
|
||||||
|
debug_assert!(i >= &16 && i <= &231);
|
||||||
|
let i = i - 16;
|
||||||
|
let r = (i - (i % 36)) / 36;
|
||||||
|
let g = ((i % 36) - (i % 6)) / 6;
|
||||||
|
let b = (i % 36) % 6;
|
||||||
|
(r, g, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Convenience method to convert from a GPUI color to an alacritty Rgb
|
||||||
|
pub fn to_alac_rgb(color: Color) -> AlacRgb {
|
||||||
|
AlacRgb {
|
||||||
|
r: color.r,
|
||||||
|
g: color.g,
|
||||||
|
b: color.g,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
#[test]
|
||||||
|
fn test_rgb_for_index() {
|
||||||
|
//Test every possible value in the color cube
|
||||||
|
for i in 16..=231 {
|
||||||
|
let (r, g, b) = crate::color_translation::rgb_for_index(&(i as u8));
|
||||||
|
assert_eq!(i, 16 + 36 * r + 6 * g + b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,19 +4,23 @@ use alacritty_terminal::{
|
||||||
event_loop::{EventLoop, Msg, Notifier},
|
event_loop::{EventLoop, Msg, Notifier},
|
||||||
grid::Scroll,
|
grid::Scroll,
|
||||||
sync::FairMutex,
|
sync::FairMutex,
|
||||||
term::{color::Rgb as AlacRgb, SizeInfo},
|
term::SizeInfo,
|
||||||
tty::{self, setup_env},
|
tty::{self, setup_env},
|
||||||
Term,
|
Term,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
use dirs::home_dir;
|
use dirs::home_dir;
|
||||||
|
=======
|
||||||
|
use color_translation::{get_color_at_index, to_alac_rgb};
|
||||||
|
>>>>>>> 3fe0d66d (Began working on selections, refactored colors)
|
||||||
use futures::{
|
use futures::{
|
||||||
channel::mpsc::{unbounded, UnboundedSender},
|
channel::mpsc::{unbounded, UnboundedSender},
|
||||||
StreamExt,
|
StreamExt,
|
||||||
};
|
};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, color::Color, elements::*, impl_internal_actions, platform::CursorStyle,
|
actions, elements::*, impl_internal_actions, platform::CursorStyle, ClipboardItem, Entity,
|
||||||
ClipboardItem, Entity, MutableAppContext, View, ViewContext,
|
MutableAppContext, View, ViewContext,
|
||||||
};
|
};
|
||||||
use project::{LocalWorktree, Project, ProjectPath};
|
use project::{LocalWorktree, Project, ProjectPath};
|
||||||
use settings::Settings;
|
use settings::Settings;
|
||||||
|
@ -24,7 +28,7 @@ use smallvec::SmallVec;
|
||||||
use std::{collections::HashMap, path::PathBuf, sync::Arc};
|
use std::{collections::HashMap, path::PathBuf, sync::Arc};
|
||||||
use workspace::{Item, Workspace};
|
use workspace::{Item, Workspace};
|
||||||
|
|
||||||
use crate::terminal_element::{get_color_at_index, TerminalEl};
|
use crate::terminal_element::TerminalEl;
|
||||||
|
|
||||||
//ASCII Control characters on a keyboard
|
//ASCII Control characters on a keyboard
|
||||||
const ETX_CHAR: char = 3_u8 as char; //'End of text', the control code for 'ctrl-c'
|
const ETX_CHAR: char = 3_u8 as char; //'End of text', the control code for 'ctrl-c'
|
||||||
|
@ -38,6 +42,7 @@ const UP_SEQ: &str = "\x1b[A";
|
||||||
const DOWN_SEQ: &str = "\x1b[B";
|
const DOWN_SEQ: &str = "\x1b[B";
|
||||||
const DEFAULT_TITLE: &str = "Terminal";
|
const DEFAULT_TITLE: &str = "Terminal";
|
||||||
|
|
||||||
|
pub mod color_translation;
|
||||||
pub mod gpui_func_tools;
|
pub mod gpui_func_tools;
|
||||||
pub mod terminal_element;
|
pub mod terminal_element;
|
||||||
|
|
||||||
|
@ -63,7 +68,7 @@ pub fn init(cx: &mut MutableAppContext) {
|
||||||
cx.add_action(Terminal::escape);
|
cx.add_action(Terminal::escape);
|
||||||
cx.add_action(Terminal::quit);
|
cx.add_action(Terminal::quit);
|
||||||
cx.add_action(Terminal::del);
|
cx.add_action(Terminal::del);
|
||||||
cx.add_action(Terminal::carriage_return); //TODO figure out how to do this properly. Should we be checking the terminal mode?
|
cx.add_action(Terminal::carriage_return);
|
||||||
cx.add_action(Terminal::left);
|
cx.add_action(Terminal::left);
|
||||||
cx.add_action(Terminal::right);
|
cx.add_action(Terminal::right);
|
||||||
cx.add_action(Terminal::up);
|
cx.add_action(Terminal::up);
|
||||||
|
@ -131,7 +136,6 @@ impl Terminal {
|
||||||
hold: false,
|
hold: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
//Does this mangle the zed Env? I'm guessing it does... do child processes have a seperate ENV?
|
|
||||||
let mut env: HashMap<String, String> = HashMap::new();
|
let mut env: HashMap<String, String> = HashMap::new();
|
||||||
//TODO: Properly set the current locale,
|
//TODO: Properly set the current locale,
|
||||||
env.insert("LC_ALL".to_string(), "en_US.UTF-8".to_string());
|
env.insert("LC_ALL".to_string(), "en_US.UTF-8".to_string());
|
||||||
|
@ -222,24 +226,7 @@ impl Terminal {
|
||||||
AlacTermEvent::ColorRequest(index, format) => {
|
AlacTermEvent::ColorRequest(index, format) => {
|
||||||
let color = self.term.lock().colors()[index].unwrap_or_else(|| {
|
let color = self.term.lock().colors()[index].unwrap_or_else(|| {
|
||||||
let term_style = &cx.global::<Settings>().theme.terminal;
|
let term_style = &cx.global::<Settings>().theme.terminal;
|
||||||
match index {
|
to_alac_rgb(get_color_at_index(&index, term_style))
|
||||||
0..=255 => to_alac_rgb(get_color_at_index(&(index as u8), term_style)),
|
|
||||||
//These additional values are required to match the Alacritty Colors object's behavior
|
|
||||||
256 => to_alac_rgb(term_style.foreground),
|
|
||||||
257 => to_alac_rgb(term_style.background),
|
|
||||||
258 => to_alac_rgb(term_style.cursor),
|
|
||||||
259 => to_alac_rgb(term_style.dim_black),
|
|
||||||
260 => to_alac_rgb(term_style.dim_red),
|
|
||||||
261 => to_alac_rgb(term_style.dim_green),
|
|
||||||
262 => to_alac_rgb(term_style.dim_yellow),
|
|
||||||
263 => to_alac_rgb(term_style.dim_blue),
|
|
||||||
264 => to_alac_rgb(term_style.dim_magenta),
|
|
||||||
265 => to_alac_rgb(term_style.dim_cyan),
|
|
||||||
266 => to_alac_rgb(term_style.dim_white),
|
|
||||||
267 => to_alac_rgb(term_style.bright_foreground),
|
|
||||||
268 => to_alac_rgb(term_style.black), //Dim Background, non-standard
|
|
||||||
_ => AlacRgb { r: 0, g: 0, b: 0 },
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
self.write_to_pty(&Input(format(color)), cx)
|
self.write_to_pty(&Input(format(color)), cx)
|
||||||
}
|
}
|
||||||
|
@ -479,15 +466,6 @@ impl Item for Terminal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Convenience method for less lines
|
|
||||||
fn to_alac_rgb(color: Color) -> AlacRgb {
|
|
||||||
AlacRgb {
|
|
||||||
r: color.r,
|
|
||||||
g: color.g,
|
|
||||||
b: color.g,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_working_directory(wt: &LocalWorktree) -> Option<PathBuf> {
|
fn get_working_directory(wt: &LocalWorktree) -> Option<PathBuf> {
|
||||||
Some(wt.abs_path().to_path_buf())
|
Some(wt.abs_path().to_path_buf())
|
||||||
.filter(|path| path.is_dir())
|
.filter(|path| path.is_dir())
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use alacritty_terminal::{
|
use alacritty_terminal::{
|
||||||
ansi::Color as AnsiColor,
|
|
||||||
grid::{Dimensions, GridIterator, Indexed},
|
grid::{Dimensions, GridIterator, Indexed},
|
||||||
index::Point,
|
index::{Column as GridCol, Line as GridLine, Point, Side},
|
||||||
term::{
|
term::{
|
||||||
cell::{Cell, Flags},
|
cell::{Cell, Flags},
|
||||||
SizeInfo,
|
SizeInfo,
|
||||||
|
@ -24,10 +23,12 @@ use gpui::{
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use ordered_float::OrderedFloat;
|
use ordered_float::OrderedFloat;
|
||||||
use settings::Settings;
|
use settings::Settings;
|
||||||
use std::rc::Rc;
|
use std::{cmp::min, rc::Rc};
|
||||||
use theme::TerminalStyle;
|
use theme::TerminalStyle;
|
||||||
|
|
||||||
use crate::{gpui_func_tools::paint_layer, Input, ScrollTerminal, Terminal};
|
use crate::{
|
||||||
|
color_translation::convert_color, gpui_func_tools::paint_layer, Input, ScrollTerminal, Terminal,
|
||||||
|
};
|
||||||
|
|
||||||
///Scrolling is unbearably sluggish by default. Alacritty supports a configurable
|
///Scrolling is unbearably sluggish by default. Alacritty supports a configurable
|
||||||
///Scroll multiplier that is set to 3 by default. This will be removed when I
|
///Scroll multiplier that is set to 3 by default. This will be removed when I
|
||||||
|
@ -74,6 +75,7 @@ pub struct LayoutState {
|
||||||
cursor: Option<Cursor>,
|
cursor: Option<Cursor>,
|
||||||
background_color: Color,
|
background_color: Color,
|
||||||
cur_size: SizeInfo,
|
cur_size: SizeInfo,
|
||||||
|
display_offset: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TerminalEl {
|
impl TerminalEl {
|
||||||
|
@ -194,6 +196,7 @@ impl Element for TerminalEl {
|
||||||
cur_size,
|
cur_size,
|
||||||
background_rects,
|
background_rects,
|
||||||
background_color: terminal_theme.background,
|
background_color: terminal_theme.background,
|
||||||
|
display_offset: content.display_offset,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -209,10 +212,50 @@ impl Element for TerminalEl {
|
||||||
let clip_bounds = Some(visible_bounds);
|
let clip_bounds = Some(visible_bounds);
|
||||||
paint_layer(cx, clip_bounds, |cx| {
|
paint_layer(cx, clip_bounds, |cx| {
|
||||||
//Elements are ephemeral, only at paint time do we know what could be clicked by a mouse
|
//Elements are ephemeral, only at paint time do we know what could be clicked by a mouse
|
||||||
|
|
||||||
|
/*
|
||||||
|
To set a selection,
|
||||||
|
set the selection variable on the terminal
|
||||||
|
|
||||||
|
CLICK:
|
||||||
|
Get the grid point associated with this mouse click
|
||||||
|
And the side????? - TODO - algorithm for calculating this in Processor::cell_side
|
||||||
|
On single left click -> Clear selection, start empty selection
|
||||||
|
On double left click -> start semantic selection
|
||||||
|
On double triple click -> start line selection
|
||||||
|
|
||||||
|
MOUSE MOVED:
|
||||||
|
Find the new cell the mouse is over
|
||||||
|
Update the selection by calling terminal.selection.update()
|
||||||
|
*/
|
||||||
|
let cur_size = layout.cur_size.clone();
|
||||||
|
let display_offset = layout.display_offset.clone();
|
||||||
cx.scene.push_mouse_region(MouseRegion {
|
cx.scene.push_mouse_region(MouseRegion {
|
||||||
view_id: self.view.id(),
|
view_id: self.view.id(),
|
||||||
mouse_down: Some(Rc::new(|_, cx| cx.focus_parent_view())),
|
mouse_down: Some(Rc::new(move |pos, cx| {
|
||||||
|
let point = grid_cell(pos, cur_size, display_offset);
|
||||||
|
let side = cell_side(cur_size, pos.x() as usize);
|
||||||
|
|
||||||
|
//One problem is we need a terminal
|
||||||
|
//Second problem is that we need # of clicks
|
||||||
|
//Third problem is that dragging reports deltas, and we need locations.
|
||||||
|
//Fourth (minor) is need to render the selection
|
||||||
|
|
||||||
|
// if single_click {
|
||||||
|
// terminal.selection = Some(Selection::new(SelectionType::Simple, point, side))
|
||||||
|
// } else if double_click {
|
||||||
|
// terminal.selection = Some(Selection::new(SelectionType::Semantic, point, side))
|
||||||
|
// } else if triple_click {
|
||||||
|
// terminal.selection = Some(Selection::new(SelectionType::Lines, point, side))
|
||||||
|
// }
|
||||||
|
|
||||||
|
cx.focus_parent_view()
|
||||||
|
})),
|
||||||
bounds: visible_bounds,
|
bounds: visible_bounds,
|
||||||
|
drag: Some(Rc::new(|delta, cx| {
|
||||||
|
//Calculate new point from delta
|
||||||
|
//terminal.selection.update(point, side)
|
||||||
|
})),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -311,6 +354,19 @@ impl Element for TerminalEl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Mouse moved -> WindowEvent::CursorMoved
|
||||||
|
mouse press -> WindowEvent::MouseInput
|
||||||
|
update_selection_scrolling
|
||||||
|
|
||||||
|
|
||||||
|
copy_selection
|
||||||
|
start_selection
|
||||||
|
toggle_selection
|
||||||
|
update_selection
|
||||||
|
clear_selection
|
||||||
|
*/
|
||||||
|
|
||||||
///Configures a text style from the current settings.
|
///Configures a text style from the current settings.
|
||||||
fn make_text_style(font_cache: &FontCache, settings: &Settings) -> TextStyle {
|
fn make_text_style(font_cache: &FontCache, settings: &Settings) -> TextStyle {
|
||||||
TextStyle {
|
TextStyle {
|
||||||
|
@ -430,98 +486,34 @@ fn cell_style(indexed: &Indexed<&Cell>, style: &TerminalStyle, text_style: &Text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///Converts a 2, 8, or 24 bit color ANSI color to the GPUI equivalent
|
///Copied (with modifications) from alacritty/src/input.rs > Processor::cell_side()
|
||||||
fn convert_color(alac_color: &AnsiColor, style: &TerminalStyle) -> Color {
|
fn cell_side(cur_size: SizeInfo, x: usize) -> Side {
|
||||||
match alac_color {
|
let cell_x = x.saturating_sub(cur_size.cell_width() as usize) % cur_size.cell_width() as usize;
|
||||||
//Named and theme defined colors
|
let half_cell_width = (cur_size.cell_width() / 2.0) as usize;
|
||||||
alacritty_terminal::ansi::Color::Named(n) => match n {
|
|
||||||
alacritty_terminal::ansi::NamedColor::Black => style.black,
|
let additional_padding =
|
||||||
alacritty_terminal::ansi::NamedColor::Red => style.red,
|
(cur_size.width() - cur_size.cell_width() * 2.) % cur_size.cell_width();
|
||||||
alacritty_terminal::ansi::NamedColor::Green => style.green,
|
let end_of_grid = cur_size.width() - cur_size.cell_width() - additional_padding;
|
||||||
alacritty_terminal::ansi::NamedColor::Yellow => style.yellow,
|
|
||||||
alacritty_terminal::ansi::NamedColor::Blue => style.blue,
|
if cell_x > half_cell_width
|
||||||
alacritty_terminal::ansi::NamedColor::Magenta => style.magenta,
|
// Edge case when mouse leaves the window.
|
||||||
alacritty_terminal::ansi::NamedColor::Cyan => style.cyan,
|
|| x as f32 >= end_of_grid
|
||||||
alacritty_terminal::ansi::NamedColor::White => style.white,
|
{
|
||||||
alacritty_terminal::ansi::NamedColor::BrightBlack => style.bright_black,
|
Side::Right
|
||||||
alacritty_terminal::ansi::NamedColor::BrightRed => style.bright_red,
|
} else {
|
||||||
alacritty_terminal::ansi::NamedColor::BrightGreen => style.bright_green,
|
Side::Left
|
||||||
alacritty_terminal::ansi::NamedColor::BrightYellow => style.bright_yellow,
|
|
||||||
alacritty_terminal::ansi::NamedColor::BrightBlue => style.bright_blue,
|
|
||||||
alacritty_terminal::ansi::NamedColor::BrightMagenta => style.bright_magenta,
|
|
||||||
alacritty_terminal::ansi::NamedColor::BrightCyan => style.bright_cyan,
|
|
||||||
alacritty_terminal::ansi::NamedColor::BrightWhite => style.bright_white,
|
|
||||||
alacritty_terminal::ansi::NamedColor::Foreground => style.foreground,
|
|
||||||
alacritty_terminal::ansi::NamedColor::Background => style.background,
|
|
||||||
alacritty_terminal::ansi::NamedColor::Cursor => style.cursor,
|
|
||||||
alacritty_terminal::ansi::NamedColor::DimBlack => style.dim_black,
|
|
||||||
alacritty_terminal::ansi::NamedColor::DimRed => style.dim_red,
|
|
||||||
alacritty_terminal::ansi::NamedColor::DimGreen => style.dim_green,
|
|
||||||
alacritty_terminal::ansi::NamedColor::DimYellow => style.dim_yellow,
|
|
||||||
alacritty_terminal::ansi::NamedColor::DimBlue => style.dim_blue,
|
|
||||||
alacritty_terminal::ansi::NamedColor::DimMagenta => style.dim_magenta,
|
|
||||||
alacritty_terminal::ansi::NamedColor::DimCyan => style.dim_cyan,
|
|
||||||
alacritty_terminal::ansi::NamedColor::DimWhite => style.dim_white,
|
|
||||||
alacritty_terminal::ansi::NamedColor::BrightForeground => style.bright_foreground,
|
|
||||||
alacritty_terminal::ansi::NamedColor::DimForeground => style.dim_foreground,
|
|
||||||
},
|
|
||||||
//'True' colors
|
|
||||||
alacritty_terminal::ansi::Color::Spec(rgb) => Color::new(rgb.r, rgb.g, rgb.b, u8::MAX),
|
|
||||||
//8 bit, indexed colors
|
|
||||||
alacritty_terminal::ansi::Color::Indexed(i) => get_color_at_index(i, style),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///Converts an 8 bit ANSI color to it's GPUI equivalent.
|
///Copied (with modifications) from alacritty/src/event.rs > Mouse::point()
|
||||||
pub fn get_color_at_index(index: &u8, style: &TerminalStyle) -> Color {
|
fn grid_cell(pos: Vector2F, cur_size: SizeInfo, display_offset: usize) -> Point {
|
||||||
match index {
|
let col = pos.x() - cur_size.cell_width() / cur_size.cell_width(); //TODO: underflow...
|
||||||
//0-15 are the same as the named colors above
|
let col = min(GridCol(col as usize), cur_size.last_column());
|
||||||
0 => style.black,
|
|
||||||
1 => style.red,
|
|
||||||
2 => style.green,
|
|
||||||
3 => style.yellow,
|
|
||||||
4 => style.blue,
|
|
||||||
5 => style.magenta,
|
|
||||||
6 => style.cyan,
|
|
||||||
7 => style.white,
|
|
||||||
8 => style.bright_black,
|
|
||||||
9 => style.bright_red,
|
|
||||||
10 => style.bright_green,
|
|
||||||
11 => style.bright_yellow,
|
|
||||||
12 => style.bright_blue,
|
|
||||||
13 => style.bright_magenta,
|
|
||||||
14 => style.bright_cyan,
|
|
||||||
15 => style.bright_white,
|
|
||||||
//16-231 are mapped to their RGB colors on a 0-5 range per channel
|
|
||||||
16..=231 => {
|
|
||||||
let (r, g, b) = rgb_for_index(index); //Split the index into it's ANSI-RGB components
|
|
||||||
let step = (u8::MAX as f32 / 5.).floor() as u8; //Split the RGB range into 5 chunks, with floor so no overflow
|
|
||||||
Color::new(r * step, g * step, b * step, u8::MAX) //Map the ANSI-RGB components to an RGB color
|
|
||||||
}
|
|
||||||
//232-255 are a 24 step grayscale from black to white
|
|
||||||
232..=255 => {
|
|
||||||
let i = index - 232; //Align index to 0..24
|
|
||||||
let step = (u8::MAX as f32 / 24.).floor() as u8; //Split the RGB grayscale values into 24 chunks
|
|
||||||
Color::new(i * step, i * step, i * step, u8::MAX) //Map the ANSI-grayscale components to the RGB-grayscale
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///Generates the rgb channels in [0, 5] for a given index into the 6x6x6 ANSI color cube
|
let line = pos.y() - cur_size.padding_y() / cur_size.cell_height();
|
||||||
///See: [8 bit ansi color](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit).
|
let line = min(line as usize, cur_size.bottommost_line().0 as usize);
|
||||||
///
|
|
||||||
///Wikipedia gives a formula for calculating the index for a given color:
|
Point::new(GridLine((line - display_offset) as i32), col)
|
||||||
///
|
|
||||||
///index = 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5)
|
|
||||||
///
|
|
||||||
///This function does the reverse, calculating the r, g, and b components from a given index.
|
|
||||||
fn rgb_for_index(i: &u8) -> (u8, u8, u8) {
|
|
||||||
debug_assert!(i >= &16 && i <= &231);
|
|
||||||
let i = i - 16;
|
|
||||||
let r = (i - (i % 36)) / 36;
|
|
||||||
let g = ((i % 36) - (i % 6)) / 6;
|
|
||||||
let b = (i % 36) % 6;
|
|
||||||
(r, g, b)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///Draws the grid as Alacritty sees it. Useful for checking if there is an inconsistency between
|
///Draws the grid as Alacritty sees it. Useful for checking if there is an inconsistency between
|
||||||
|
@ -554,15 +546,3 @@ fn draw_debug_grid(bounds: RectF, layout: &mut LayoutState, cx: &mut PaintContex
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
#[test]
|
|
||||||
fn test_rgb_for_index() {
|
|
||||||
//Test every possible value in the color cube
|
|
||||||
for i in 16..=231 {
|
|
||||||
let (r, g, b) = crate::terminal_element::rgb_for_index(&(i as u8));
|
|
||||||
assert_eq!(i, 16 + 36 * r + 6 * g + b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue