From a83c593a24313f17dc0f044f0e680f1240ddf640 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 21 Dec 2023 09:44:44 -0700 Subject: [PATCH] Add OneHalfDark theme and script for testing theme --- ansi-colors.sh | 24 ++++++ src/main.rs | 39 +++++---- src/terminal.rs | 125 +--------------------------- src/terminal_theme.rs | 187 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 239 insertions(+), 136 deletions(-) create mode 100755 ansi-colors.sh create mode 100644 src/terminal_theme.rs diff --git a/ansi-colors.sh b/ansi-colors.sh new file mode 100755 index 0000000..63f7251 --- /dev/null +++ b/ansi-colors.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +set -e + +printf " " +for background in $(seq 0 15) +do + printf " %2d " "${background}" +done +printf "\n" + +for foreground in $(seq 0 15) +do + printf "%2d:" "${foreground}" + printf "\x1B[38;5;${foreground}m" + for background in $(seq 0 15) + do + printf "\x1B[48;5;${background}m" + printf " %2d " "${background}" + printf "\x1B[49m" + done + printf "\x1B[39m" + printf "\n" +done diff --git a/src/main.rs b/src/main.rs index fafb9b5..7416f54 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,7 @@ // Copyright 2023 System76 // SPDX-License-Identifier: GPL-3.0-only -use alacritty_terminal::event::Event as TermEvent; +use alacritty_terminal::{event::Event as TermEvent, term::color::Colors as TermColors}; use cosmic::{ app::{Command, Core, Settings}, cosmic_theme, executor, @@ -17,7 +17,7 @@ use cosmic::{ widget::{self, segmented_button}, ApplicationExt, Element, }; -use std::{any::TypeId, sync::Mutex}; +use std::{any::TypeId, collections::HashMap, sync::Mutex}; use tokio::sync::mpsc; use self::terminal::{Terminal, TerminalScroll}; @@ -26,6 +26,8 @@ mod terminal; use self::terminal_box::terminal_box; mod terminal_box; +mod terminal_theme; + /// Runs application with these settings #[rustfmt::skip] fn main() -> Result<(), Box> { @@ -62,6 +64,8 @@ pub struct App { core: Core, tab_model: segmented_button::Model, term_event_tx_opt: Option>, + terminal_theme: String, + terminal_themes: HashMap, } /// Implement [`cosmic::Application`] to integrate with COSMIC. @@ -92,6 +96,8 @@ impl cosmic::Application for App { core, tab_model: segmented_button::ModelBuilder::default().build(), term_event_tx_opt: None, + terminal_theme: "gruvbox-dark".to_string(), + terminal_themes: terminal_theme::terminal_themes(), }; let command = app.update_title(); @@ -127,18 +133,23 @@ impl cosmic::Application for App { return self.update_title(); } Message::TabNew => match &self.term_event_tx_opt { - Some(term_event_tx) => { - let entity = self - .tab_model - .insert() - .text("New Terminal") - .closable() - .activate() - .id(); - let terminal = Terminal::new(entity, term_event_tx.clone()); - self.tab_model - .data_set::>(entity, Mutex::new(terminal)); - } + Some(term_event_tx) => match self.terminal_themes.get(&self.terminal_theme) { + Some(colors) => { + let entity = self + .tab_model + .insert() + .text("New Terminal") + .closable() + .activate() + .id(); + let terminal = Terminal::new(entity, term_event_tx.clone(), colors.clone()); + self.tab_model + .data_set::>(entity, Mutex::new(terminal)); + } + None => { + log::error!("failed to find terminal theme {:?}", self.terminal_theme); + } + }, None => { log::warn!("tried to create new tab before having event channel"); } diff --git a/src/terminal.rs b/src/terminal.rs index 497a8b8..244c74e 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -25,6 +25,8 @@ use std::{ }; use tokio::sync::mpsc; +use crate::terminal_theme; + pub use alacritty_terminal::grid::Scroll as TerminalScroll; #[derive(Clone, Copy, Debug)] @@ -73,124 +75,6 @@ impl EventListener for EventProxy { } } -fn auto_colors() -> Colors { - let mut colors = Colors::default(); - - // These colors come from `ransid`: https://gitlab.redox-os.org/redox-os/ransid/-/blob/master/src/color.rs - /* Indexed colors */ - for value in 16..=231 { - let convert = |value: u8| -> u8 { - match value { - 0 => 0, - _ => value * 0x28 + 0x28, - } - }; - - let r = convert((value - 16) / 36 % 6); - let g = convert((value - 16) / 6 % 6); - let b = convert((value - 16) % 6); - colors[value as usize] = Some(Rgb { r, g, b }); - } - - /* Grays */ - for value in 232..=255 { - let gray = (value - 232) * 10 + 8; - colors[value as usize] = Some(Rgb { - r: gray, - g: gray, - b: gray, - }); - } - - colors -} - -fn gruvbox_dark_colors() -> Colors { - let mut colors = auto_colors(); - - let encode_rgb = |r: u8, g: u8, b: u8| -> Rgb { Rgb { r, g, b } }; - - colors[NamedColor::Black] = Some(encode_rgb(0x28, 0x28, 0x28)); - colors[NamedColor::Red] = Some(encode_rgb(0xcc, 0x24, 0x1d)); - colors[NamedColor::Green] = Some(encode_rgb(0x98, 0x97, 0x1a)); - colors[NamedColor::Yellow] = Some(encode_rgb(0xd7, 0x99, 0x21)); - colors[NamedColor::Blue] = Some(encode_rgb(0x45, 0x85, 0x88)); - colors[NamedColor::Magenta] = Some(encode_rgb(0xb1, 0x62, 0x86)); - colors[NamedColor::Cyan] = Some(encode_rgb(0x68, 0x9d, 0x6a)); - colors[NamedColor::White] = Some(encode_rgb(0xa8, 0x99, 0x84)); - colors[NamedColor::BrightBlack] = Some(encode_rgb(0x92, 0x83, 0x74)); - colors[NamedColor::BrightRed] = Some(encode_rgb(0xfb, 0x49, 0x34)); - colors[NamedColor::BrightGreen] = Some(encode_rgb(0xb8, 0xbb, 0x26)); - colors[NamedColor::BrightYellow] = Some(encode_rgb(0xfa, 0xbd, 0x2f)); - colors[NamedColor::BrightBlue] = Some(encode_rgb(0x83, 0xa5, 0x98)); - colors[NamedColor::BrightMagenta] = Some(encode_rgb(0xd3, 0x86, 0x9b)); - colors[NamedColor::BrightCyan] = Some(encode_rgb(0x8e, 0xc0, 0x7c)); - colors[NamedColor::BrightWhite] = Some(encode_rgb(0xeb, 0xdb, 0xb2)); - - // Set special colors - colors[NamedColor::Foreground] = colors[NamedColor::BrightWhite]; - colors[NamedColor::Background] = colors[NamedColor::Black]; - colors[NamedColor::Cursor] = colors[NamedColor::BrightWhite]; - /*TODO - colors[NamedColor::DimBlack] = colors[NamedColor::]; - colors[NamedColor::DimRed] = colors[NamedColor::]; - colors[NamedColor::DimGreen] = colors[NamedColor::]; - colors[NamedColor::DimYellow] = colors[NamedColor::]; - colors[NamedColor::DimBlue] = colors[NamedColor::]; - colors[NamedColor::DimMagenta] = colors[NamedColor::]; - colors[NamedColor::DimCyan] = colors[NamedColor::]; - colors[NamedColor::DimWhite] = colors[NamedColor::]; - */ - colors[NamedColor::BrightForeground] = colors[NamedColor::BrightWhite]; - //TODO colors[NamedColor::DimForeground] = colors[NamedColor::]; - - colors -} - -fn pop_colors() -> Colors { - let mut colors = auto_colors(); - - let encode_rgb = |r: u8, g: u8, b: u8| -> Rgb { Rgb { r, g, b } }; - - // Pop colors (from pop-desktop gsettings) - colors[NamedColor::Black] = Some(encode_rgb(51, 51, 51)); - colors[NamedColor::Red] = Some(encode_rgb(204, 0, 0)); - colors[NamedColor::Green] = Some(encode_rgb(78, 154, 6)); - colors[NamedColor::Yellow] = Some(encode_rgb(196, 160, 0)); - colors[NamedColor::Blue] = Some(encode_rgb(52, 101, 164)); - colors[NamedColor::Magenta] = Some(encode_rgb(117, 80, 123)); - colors[NamedColor::Cyan] = Some(encode_rgb(6, 152, 154)); - colors[NamedColor::White] = Some(encode_rgb(211, 215, 207)); - colors[NamedColor::BrightBlack] = Some(encode_rgb(136, 128, 124)); - colors[NamedColor::BrightRed] = Some(encode_rgb(241, 93, 34)); - colors[NamedColor::BrightGreen] = Some(encode_rgb(115, 196, 143)); - colors[NamedColor::BrightYellow] = Some(encode_rgb(255, 206, 81)); - colors[NamedColor::BrightBlue] = Some(encode_rgb(72, 185, 199)); - colors[NamedColor::BrightMagenta] = Some(encode_rgb(173, 127, 168)); - colors[NamedColor::BrightCyan] = Some(encode_rgb(52, 226, 226)); - colors[NamedColor::BrightWhite] = Some(encode_rgb(238, 238, 236)); - - // Set special colors - // Pop colors (from pop-desktop gsettings) - colors[NamedColor::Foreground] = Some(encode_rgb(242, 242, 242)); - colors[NamedColor::Background] = Some(encode_rgb(51, 51, 51)); - colors[NamedColor::Cursor] = colors[NamedColor::BrightWhite]; - /*TODO - colors[NamedColor::DimBlack] = colors[NamedColor::]; - colors[NamedColor::DimRed] = colors[NamedColor::]; - colors[NamedColor::DimGreen] = colors[NamedColor::]; - colors[NamedColor::DimYellow] = colors[NamedColor::]; - colors[NamedColor::DimBlue] = colors[NamedColor::]; - colors[NamedColor::DimMagenta] = colors[NamedColor::]; - colors[NamedColor::DimCyan] = colors[NamedColor::]; - colors[NamedColor::DimWhite] = colors[NamedColor::]; - */ - colors[NamedColor::BrightForeground] = colors[NamedColor::BrightWhite]; - //TODO colors[NamedColor::DimForeground] = colors[NamedColor::]; - - colors -} - fn convert_color(colors: &Colors, color: Color) -> cosmic_text::Color { let rgb = match color { Color::Named(named_color) => match colors[named_color] { @@ -213,7 +97,6 @@ fn convert_color(colors: &Colors, color: Color) -> cosmic_text::Color { } pub struct Terminal { - metrics: Metrics, default_attrs: Attrs<'static>, buffer: Arc, size: Size, @@ -228,9 +111,8 @@ impl Terminal { pub fn new( entity: segmented_button::Entity, event_tx: mpsc::Sender<(segmented_button::Entity, Event)>, + colors: Colors, ) -> Self { - let colors = gruvbox_dark_colors(); - let metrics = Metrics::new(14.0, 20.0); //TODO: set color to default fg let default_attrs = Attrs::new() @@ -279,7 +161,6 @@ impl Terminal { Self { colors, - metrics, default_attrs, buffer: Arc::new(buffer), size, diff --git a/src/terminal_theme.rs b/src/terminal_theme.rs new file mode 100644 index 0000000..69a7d6f --- /dev/null +++ b/src/terminal_theme.rs @@ -0,0 +1,187 @@ +use alacritty_terminal::{ + ansi::NamedColor, + term::color::{Colors, Rgb}, +}; +use std::collections::HashMap; + +fn auto_colors() -> Colors { + let mut colors = Colors::default(); + + // These colors come from `ransid`: https://gitlab.redox-os.org/redox-os/ransid/-/blob/master/src/color.rs + /* Indexed colors */ + for value in 16..=231 { + let convert = |value: u8| -> u8 { + match value { + 0 => 0, + _ => value * 0x28 + 0x28, + } + }; + + let r = convert((value - 16) / 36 % 6); + let g = convert((value - 16) / 6 % 6); + let b = convert((value - 16) % 6); + colors[value as usize] = Some(Rgb { r, g, b }); + } + + /* Grays */ + for value in 232..=255 { + let gray = (value - 232) * 10 + 8; + colors[value as usize] = Some(Rgb { + r: gray, + g: gray, + b: gray, + }); + } + + colors +} + +fn gruvbox_dark() -> Colors { + let mut colors = auto_colors(); + + let encode_rgb = |data: u32| -> Rgb { + Rgb { + r: (data >> 16) as u8, + g: (data >> 8) as u8, + b: data as u8, + } + }; + + colors[NamedColor::Black] = Some(encode_rgb(0x282828)); + colors[NamedColor::Red] = Some(encode_rgb(0xcc241d)); + colors[NamedColor::Green] = Some(encode_rgb(0x98971a)); + colors[NamedColor::Yellow] = Some(encode_rgb(0xd79921)); + colors[NamedColor::Blue] = Some(encode_rgb(0x458588)); + colors[NamedColor::Magenta] = Some(encode_rgb(0xb16286)); + colors[NamedColor::Cyan] = Some(encode_rgb(0x689d6a)); + colors[NamedColor::White] = Some(encode_rgb(0xa89984)); + + colors[NamedColor::BrightBlack] = Some(encode_rgb(0x928374)); + colors[NamedColor::BrightRed] = Some(encode_rgb(0xfb4934)); + colors[NamedColor::BrightGreen] = Some(encode_rgb(0xb8bb26)); + colors[NamedColor::BrightYellow] = Some(encode_rgb(0xfabd2f)); + colors[NamedColor::BrightBlue] = Some(encode_rgb(0x83a598)); + colors[NamedColor::BrightMagenta] = Some(encode_rgb(0xd3869b)); + colors[NamedColor::BrightCyan] = Some(encode_rgb(0x8ec07c)); + colors[NamedColor::BrightWhite] = Some(encode_rgb(0xebdbb2)); + + // Set special colors + colors[NamedColor::Foreground] = colors[NamedColor::BrightWhite]; + colors[NamedColor::Background] = colors[NamedColor::Black]; + colors[NamedColor::Cursor] = colors[NamedColor::BrightWhite]; + /*TODO + colors[NamedColor::DimBlack] = colors[NamedColor::]; + colors[NamedColor::DimRed] = colors[NamedColor::]; + colors[NamedColor::DimGreen] = colors[NamedColor::]; + colors[NamedColor::DimYellow] = colors[NamedColor::]; + colors[NamedColor::DimBlue] = colors[NamedColor::]; + colors[NamedColor::DimMagenta] = colors[NamedColor::]; + colors[NamedColor::DimCyan] = colors[NamedColor::]; + colors[NamedColor::DimWhite] = colors[NamedColor::]; + */ + colors[NamedColor::BrightForeground] = colors[NamedColor::BrightWhite]; + //TODO colors[NamedColor::DimForeground] = colors[NamedColor::]; + + colors +} + +fn one_half_dark() -> Colors { + let mut colors = auto_colors(); + + let encode_rgb = |data: u32| -> Rgb { + Rgb { + r: (data >> 16) as u8, + g: (data >> 8) as u8, + b: data as u8, + } + }; + + colors[NamedColor::Black] = Some(encode_rgb(0x282c34)); + colors[NamedColor::Red] = Some(encode_rgb(0xe06c75)); + colors[NamedColor::Green] = Some(encode_rgb(0x98c379)); + colors[NamedColor::Yellow] = Some(encode_rgb(0xe5c07b)); + colors[NamedColor::Blue] = Some(encode_rgb(0x61afef)); + colors[NamedColor::Magenta] = Some(encode_rgb(0xc678dd)); + colors[NamedColor::Cyan] = Some(encode_rgb(0x56b6c2)); + colors[NamedColor::White] = Some(encode_rgb(0xdcdfe4)); + + colors[NamedColor::BrightBlack] = Some(encode_rgb(0x5d677a)); + colors[NamedColor::BrightRed] = Some(encode_rgb(0xe06c75)); + colors[NamedColor::BrightGreen] = Some(encode_rgb(0x98c379)); + colors[NamedColor::BrightYellow] = Some(encode_rgb(0xe5c07b)); + colors[NamedColor::BrightBlue] = Some(encode_rgb(0x61afef)); + colors[NamedColor::BrightMagenta] = Some(encode_rgb(0xc678dd)); + colors[NamedColor::BrightCyan] = Some(encode_rgb(0x56b6c2)); + colors[NamedColor::BrightWhite] = Some(encode_rgb(0xdcdfe4)); + + // Set special colors + colors[NamedColor::Foreground] = colors[NamedColor::BrightWhite]; + colors[NamedColor::Background] = colors[NamedColor::Black]; + colors[NamedColor::Cursor] = colors[NamedColor::BrightWhite]; + /*TODO + colors[NamedColor::DimBlack] = colors[NamedColor::]; + colors[NamedColor::DimRed] = colors[NamedColor::]; + colors[NamedColor::DimGreen] = colors[NamedColor::]; + colors[NamedColor::DimYellow] = colors[NamedColor::]; + colors[NamedColor::DimBlue] = colors[NamedColor::]; + colors[NamedColor::DimMagenta] = colors[NamedColor::]; + colors[NamedColor::DimCyan] = colors[NamedColor::]; + colors[NamedColor::DimWhite] = colors[NamedColor::]; + */ + colors[NamedColor::BrightForeground] = colors[NamedColor::BrightWhite]; + //TODO colors[NamedColor::DimForeground] = colors[NamedColor::]; + + colors +} + +fn pop_dark() -> Colors { + let mut colors = auto_colors(); + + let encode_rgb = |r: u8, g: u8, b: u8| -> Rgb { Rgb { r, g, b } }; + + // Pop colors (from pop-desktop gsettings) + colors[NamedColor::Black] = Some(encode_rgb(51, 51, 51)); + colors[NamedColor::Red] = Some(encode_rgb(204, 0, 0)); + colors[NamedColor::Green] = Some(encode_rgb(78, 154, 6)); + colors[NamedColor::Yellow] = Some(encode_rgb(196, 160, 0)); + colors[NamedColor::Blue] = Some(encode_rgb(52, 101, 164)); + colors[NamedColor::Magenta] = Some(encode_rgb(117, 80, 123)); + colors[NamedColor::Cyan] = Some(encode_rgb(6, 152, 154)); + colors[NamedColor::White] = Some(encode_rgb(211, 215, 207)); + colors[NamedColor::BrightBlack] = Some(encode_rgb(136, 128, 124)); + colors[NamedColor::BrightRed] = Some(encode_rgb(241, 93, 34)); + colors[NamedColor::BrightGreen] = Some(encode_rgb(115, 196, 143)); + colors[NamedColor::BrightYellow] = Some(encode_rgb(255, 206, 81)); + colors[NamedColor::BrightBlue] = Some(encode_rgb(72, 185, 199)); + colors[NamedColor::BrightMagenta] = Some(encode_rgb(173, 127, 168)); + colors[NamedColor::BrightCyan] = Some(encode_rgb(52, 226, 226)); + colors[NamedColor::BrightWhite] = Some(encode_rgb(238, 238, 236)); + + // Set special colors + // Pop colors (from pop-desktop gsettings) + colors[NamedColor::Foreground] = Some(encode_rgb(242, 242, 242)); + colors[NamedColor::Background] = Some(encode_rgb(51, 51, 51)); + colors[NamedColor::Cursor] = colors[NamedColor::BrightWhite]; + /*TODO + colors[NamedColor::DimBlack] = colors[NamedColor::]; + colors[NamedColor::DimRed] = colors[NamedColor::]; + colors[NamedColor::DimGreen] = colors[NamedColor::]; + colors[NamedColor::DimYellow] = colors[NamedColor::]; + colors[NamedColor::DimBlue] = colors[NamedColor::]; + colors[NamedColor::DimMagenta] = colors[NamedColor::]; + colors[NamedColor::DimCyan] = colors[NamedColor::]; + colors[NamedColor::DimWhite] = colors[NamedColor::]; + */ + colors[NamedColor::BrightForeground] = colors[NamedColor::BrightWhite]; + //TODO colors[NamedColor::DimForeground] = colors[NamedColor::]; + + colors +} + +pub fn terminal_themes() -> HashMap { + let mut themes = HashMap::new(); + themes.insert("gruvbox-dark".to_string(), gruvbox_dark()); + themes.insert("OneHalfDark".to_string(), one_half_dark()); + themes.insert("Pop Dark".to_string(), pop_dark()); + themes +}