Merge branch 'master_jammy' into split
This commit is contained in:
commit
d3afe3f6bc
5 changed files with 292 additions and 26 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -871,6 +871,7 @@ dependencies = [
|
|||
"fork",
|
||||
"i18n-embed",
|
||||
"i18n-embed-fl",
|
||||
"indexmap",
|
||||
"lazy_static",
|
||||
"libcosmic",
|
||||
"log",
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ edition = "2021"
|
|||
alacritty_terminal = "0.20"
|
||||
env_logger = "0.10"
|
||||
lazy_static = "1"
|
||||
indexmap = "2"
|
||||
log = "0.4"
|
||||
serde = { version = "1", features = ["serde_derive"] }
|
||||
tokio = { version = "1", features = ["sync"] }
|
||||
|
|
|
|||
|
|
@ -11,14 +11,82 @@ printf "\n"
|
|||
|
||||
for foreground in $(seq 0 15)
|
||||
do
|
||||
# Add each dim color right above corresponding normal color for easier visual comparisons
|
||||
if ((foreground < 8))
|
||||
then
|
||||
printf "d%d:" "${foreground}"
|
||||
printf "\x1B[2;$((foreground+30))m"
|
||||
|
||||
for background in $(seq 0 15)
|
||||
do
|
||||
printf "\x1B[48;5;${background}m"
|
||||
printf " %2d " "${background}"
|
||||
printf "\x1B[49m"
|
||||
done
|
||||
printf "\x1B[0m"
|
||||
printf "\n"
|
||||
fi
|
||||
|
||||
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 "\x1B[0m"
|
||||
printf "\n"
|
||||
done
|
||||
|
||||
# Underlines
|
||||
|
||||
CNAMES=("BLK" "RED" "GRN" "YEL" "BLU" "MAG" "CYN" "WHT")
|
||||
|
||||
printf "\033[1m" # bold
|
||||
printf "\nUnderline With FG Colors:\n"
|
||||
|
||||
printf "\033[4m" # underline
|
||||
for foreground in $(seq 0 7)
|
||||
do
|
||||
printf "\033[$((foreground+30))m ${CNAMES[$foreground]} "
|
||||
done
|
||||
printf "\x1B[24m\n" # no underline
|
||||
|
||||
printf "\nUnderline Styles And Colors:\n"
|
||||
|
||||
printf "\nFG: "
|
||||
printf "\033[9mStrikeout\033[0m "
|
||||
printf "\033[4mUnderline\033[0m "
|
||||
printf "\033[4:2mDoubleUnderline\033[0m "
|
||||
printf "\033[4:3mCurlyUnderline\033[0m "
|
||||
printf "\033[4:4mDottedUnderline\033[0m "
|
||||
printf "\033[4:5mDashedUnderline\033[0m "
|
||||
printf "\n"
|
||||
|
||||
printf "INV: "
|
||||
printf "\033[7m\033[9mStrikeout\033[0m "
|
||||
printf "\033[7m\033[4mUnderline\033[0m "
|
||||
printf "\033[7m\033[4:2mDoubleUnderline\033[0m "
|
||||
printf "\033[7m\033[4:3mCurlyUnderline\033[0m "
|
||||
printf "\033[7m\033[4:4mDottedUnderline\033[0m "
|
||||
printf "\033[7m\033[4:5mDashedUnderline\033[0m "
|
||||
printf "\n"
|
||||
|
||||
for line_color in $(seq 0 7)
|
||||
do
|
||||
printf "${CNAMES[$line_color]}: "
|
||||
printf " "
|
||||
printf "\033[58:5:"${line_color}m
|
||||
printf "\033[4mUnderline\033[0m "
|
||||
printf "\033[58:5:"${line_color}m
|
||||
printf "\033[4:2mDoubleUnderline\033[0m "
|
||||
printf "\033[58:5:"${line_color}m
|
||||
printf "\033[4:3mCurlyUnderline\033[0m "
|
||||
printf "\033[58:5:"${line_color}m
|
||||
printf "\033[4:4mDottedUnderline\033[0m "
|
||||
printf "\033[58:5:"${line_color}m
|
||||
printf "\033[4:5mDashedUnderline\033[0m "
|
||||
printf "\n"
|
||||
done
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ use cosmic::{
|
|||
use cosmic_text::{
|
||||
Attrs, AttrsList, Buffer, BufferLine, CacheKeyFlags, Family, Metrics, Shaping, Weight, Wrap,
|
||||
};
|
||||
use indexmap::IndexSet;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
collections::HashMap,
|
||||
|
|
@ -163,6 +164,35 @@ impl TerminalPaneGrid {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
|
||||
pub struct Metadata {
|
||||
pub bg: cosmic_text::Color,
|
||||
pub underline_color: cosmic_text::Color,
|
||||
pub flags: Flags,
|
||||
}
|
||||
|
||||
impl Metadata {
|
||||
fn new(bg: cosmic_text::Color, underline_color: cosmic_text::Color) -> Self {
|
||||
let flags = Flags::empty();
|
||||
Self {
|
||||
bg,
|
||||
underline_color,
|
||||
flags,
|
||||
}
|
||||
}
|
||||
|
||||
fn with_underline_color(self, underline_color: cosmic_text::Color) -> Self {
|
||||
Self {
|
||||
underline_color,
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
fn with_flags(self, flags: Flags) -> Self {
|
||||
Self { flags, ..self }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Terminal {
|
||||
default_attrs: Attrs<'static>,
|
||||
buffer: Arc<Buffer>,
|
||||
|
|
@ -177,6 +207,7 @@ pub struct Terminal {
|
|||
pub needs_update: bool,
|
||||
search_regex_opt: Option<RegexSearch>,
|
||||
search_value: String,
|
||||
pub metadata_set: IndexSet<Metadata>,
|
||||
}
|
||||
|
||||
impl Terminal {
|
||||
|
|
@ -197,13 +228,22 @@ impl Terminal {
|
|||
let use_bright_bold = app_config.use_bright_bold;
|
||||
|
||||
let metrics = Metrics::new(14.0, 20.0);
|
||||
|
||||
let default_bg = convert_color(&colors, Color::Named(NamedColor::Background));
|
||||
let default_fg = convert_color(&colors, Color::Named(NamedColor::Foreground));
|
||||
|
||||
let mut metadata_set = IndexSet::new();
|
||||
let default_metada = Metadata::new(default_bg, default_fg);
|
||||
let (default_metada_idx, _) = metadata_set.insert_full(default_metada);
|
||||
|
||||
//TODO: set color to default fg
|
||||
let default_attrs = Attrs::new()
|
||||
.family(Family::Monospace)
|
||||
.weight(Weight(font_weight))
|
||||
.stretch(font_stretch)
|
||||
.color(convert_color(&colors, Color::Named(NamedColor::Foreground)))
|
||||
.metadata(convert_color(&colors, Color::Named(NamedColor::Background)).0 as usize);
|
||||
.color(default_fg)
|
||||
.metadata(default_metada_idx);
|
||||
|
||||
let mut buffer = Buffer::new_empty(metrics);
|
||||
|
||||
let (cell_width, cell_height) = {
|
||||
|
|
@ -251,6 +291,7 @@ impl Terminal {
|
|||
needs_update: true,
|
||||
search_regex_opt: None,
|
||||
search_value: String::new(),
|
||||
metadata_set,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -522,14 +563,19 @@ impl Terminal {
|
|||
}
|
||||
}
|
||||
if changed {
|
||||
self.metadata_set.clear();
|
||||
let default_bg = convert_color(&colors, Color::Named(NamedColor::Background));
|
||||
let default_fg = convert_color(&colors, Color::Named(NamedColor::Foreground));
|
||||
|
||||
let default_metadata = Metadata::new(default_bg, default_fg);
|
||||
let (default_metadata_idx, _) = self.metadata_set.insert_full(default_metadata);
|
||||
|
||||
self.default_attrs = Attrs::new()
|
||||
.family(Family::Monospace)
|
||||
.weight(Weight(config.font_weight))
|
||||
.stretch(config.typed_font_stretch())
|
||||
.color(convert_color(&colors, Color::Named(NamedColor::Foreground)))
|
||||
.metadata(
|
||||
convert_color(&colors, Color::Named(NamedColor::Background)).0 as usize,
|
||||
);
|
||||
.color(default_fg)
|
||||
.metadata(default_metadata_idx);
|
||||
update = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -576,6 +622,9 @@ impl Terminal {
|
|||
|
||||
let instant = Instant::now();
|
||||
|
||||
// Only keep default
|
||||
self.metadata_set.truncate(1);
|
||||
|
||||
//TODO: is redraw needed after all events?
|
||||
//TODO: use LineDamageBounds
|
||||
{
|
||||
|
|
@ -673,8 +722,18 @@ impl Terminal {
|
|||
|
||||
// Convert foreground to linear
|
||||
attrs = attrs.color(linear_color(fg));
|
||||
// Use metadata as background color
|
||||
attrs = attrs.metadata(bg.0 as usize);
|
||||
|
||||
let underline_color = indexed
|
||||
.cell
|
||||
.underline_color()
|
||||
.map(|c| convert_color(&self.colors, c))
|
||||
.unwrap_or(fg);
|
||||
let metadata = Metadata::new(bg, fg)
|
||||
.with_flags(indexed.cell.flags)
|
||||
.with_underline_color(underline_color);
|
||||
let (meta_idx, _) = self.metadata_set.insert_full(metadata);
|
||||
attrs = attrs.metadata(meta_idx);
|
||||
|
||||
//TODO: more flags
|
||||
if indexed.cell.flags.contains(Flags::BOLD) {
|
||||
attrs = attrs.weight(self.bold_font_weight);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
use alacritty_terminal::{
|
||||
index::{Column as TermColumn, Point as TermPoint, Side as TermSide},
|
||||
selection::{Selection, SelectionType},
|
||||
term::TermMode,
|
||||
term::{cell::Flags, TermMode},
|
||||
};
|
||||
use cosmic::{
|
||||
cosmic_theme::palette::{blend::Compose, WithAlpha},
|
||||
|
|
@ -30,6 +30,7 @@ use cosmic::{
|
|||
Renderer,
|
||||
};
|
||||
use cosmic_text::LayoutGlyph;
|
||||
use indexmap::IndexSet;
|
||||
use std::{
|
||||
cell::Cell,
|
||||
cmp,
|
||||
|
|
@ -37,7 +38,7 @@ use std::{
|
|||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
use crate::{Terminal, TerminalScroll};
|
||||
use crate::{terminal::Metadata, Terminal, TerminalScroll};
|
||||
|
||||
pub struct TerminalBox<'a, Message> {
|
||||
terminal: &'a Mutex<Terminal>,
|
||||
|
|
@ -250,7 +251,9 @@ where
|
|||
|
||||
// Render default background
|
||||
{
|
||||
let background_color = cosmic_text::Color(terminal.default_attrs().metadata as u32);
|
||||
let meta = &terminal.metadata_set[terminal.default_attrs().metadata];
|
||||
let background_color = meta.bg;
|
||||
|
||||
//TODO: get shaded background color from theme
|
||||
let mut shade: f32 = 1.0;
|
||||
if !state.is_focused {
|
||||
|
|
@ -262,6 +265,7 @@ where
|
|||
background_color.b() as f32 * shade / 255.0,
|
||||
background_color.a() as f32 * shade / 255.0,
|
||||
);
|
||||
|
||||
renderer.fill_quad(
|
||||
Quad {
|
||||
bounds: Rectangle::new(
|
||||
|
|
@ -279,17 +283,19 @@ where
|
|||
// Render cell backgrounds that do not match default
|
||||
terminal.with_buffer(|buffer| {
|
||||
for run in buffer.layout_runs() {
|
||||
struct BgRect {
|
||||
struct BgRect<'a> {
|
||||
default_metadata: usize,
|
||||
metadata: usize,
|
||||
glyph_font_size: f32,
|
||||
start_x: f32,
|
||||
end_x: f32,
|
||||
line_height: f32,
|
||||
line_top: f32,
|
||||
view_position: Point,
|
||||
metadata_set: &'a IndexSet<Metadata>,
|
||||
}
|
||||
|
||||
impl BgRect {
|
||||
impl<'a> BgRect<'a> {
|
||||
fn update<Renderer: renderer::Renderer>(
|
||||
&mut self,
|
||||
glyph: &LayoutGlyph,
|
||||
|
|
@ -300,6 +306,7 @@ where
|
|||
} else {
|
||||
self.fill(renderer);
|
||||
self.metadata = glyph.metadata;
|
||||
self.glyph_font_size = glyph.font_size;
|
||||
self.start_x = glyph.x;
|
||||
self.end_x = glyph.x + glyph.w;
|
||||
}
|
||||
|
|
@ -310,36 +317,166 @@ where
|
|||
return;
|
||||
}
|
||||
|
||||
let color = cosmic_text::Color(self.metadata as u32);
|
||||
renderer.fill_quad(
|
||||
Quad {
|
||||
bounds: Rectangle::new(
|
||||
self.view_position + Vector::new(self.start_x, self.line_top),
|
||||
Size::new(self.end_x - self.start_x, self.line_height),
|
||||
),
|
||||
border_radius: 0.0.into(),
|
||||
border_width: 0.0,
|
||||
border_color: Color::TRANSPARENT,
|
||||
},
|
||||
let cosmic_text_to_iced_color = |color: cosmic_text::Color| {
|
||||
Color::new(
|
||||
color.r() as f32 / 255.0,
|
||||
color.g() as f32 / 255.0,
|
||||
color.b() as f32 / 255.0,
|
||||
color.a() as f32 / 255.0,
|
||||
),
|
||||
)
|
||||
};
|
||||
|
||||
macro_rules! mk_pos_offset {
|
||||
($x_offset:expr, $bottom_offset:expr) => {
|
||||
Vector::new(
|
||||
self.start_x + $x_offset,
|
||||
self.line_top + self.line_height - $bottom_offset,
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! mk_quad {
|
||||
($pos_offset:expr, $style_line_height:expr, $width:expr) => {
|
||||
Quad {
|
||||
bounds: Rectangle::new(
|
||||
self.view_position + $pos_offset,
|
||||
Size::new($width, $style_line_height),
|
||||
),
|
||||
border_radius: 0.0.into(),
|
||||
border_width: 0.0,
|
||||
border_color: Color::TRANSPARENT,
|
||||
}
|
||||
};
|
||||
($pos_offset:expr, $style_line_height:expr) => {
|
||||
mk_quad!($pos_offset, $style_line_height, self.end_x - self.start_x)
|
||||
};
|
||||
}
|
||||
|
||||
let metadata = &self.metadata_set[self.metadata];
|
||||
let color = metadata.bg;
|
||||
renderer.fill_quad(
|
||||
mk_quad!(mk_pos_offset!(0.0, self.line_height), self.line_height),
|
||||
cosmic_text_to_iced_color(color),
|
||||
);
|
||||
|
||||
if !metadata.flags.is_empty() {
|
||||
let style_line_height =
|
||||
(self.glyph_font_size / 10.0).max(2.0).min(16.0);
|
||||
|
||||
let line_color = cosmic_text_to_iced_color(metadata.underline_color);
|
||||
|
||||
if metadata.flags.contains(Flags::STRIKEOUT) {
|
||||
let bottom_offset = (self.line_height - style_line_height) / 2.0;
|
||||
let pos_offset = mk_pos_offset!(0.0, bottom_offset);
|
||||
let underline_quad = mk_quad!(pos_offset, style_line_height);
|
||||
renderer.fill_quad(underline_quad, line_color);
|
||||
}
|
||||
|
||||
if metadata.flags.contains(Flags::UNDERLINE) {
|
||||
let bottom_offset = style_line_height * 2.0;
|
||||
let pos_offset = mk_pos_offset!(0.0, bottom_offset);
|
||||
let underline_quad = mk_quad!(pos_offset, style_line_height);
|
||||
renderer.fill_quad(underline_quad, line_color);
|
||||
}
|
||||
|
||||
if metadata.flags.contains(Flags::DOUBLE_UNDERLINE) {
|
||||
let style_line_height = style_line_height / 2.0;
|
||||
let gap = style_line_height.max(1.5);
|
||||
let bottom_offset = (style_line_height + gap) * 2.0;
|
||||
|
||||
let pos_offset1 = mk_pos_offset!(0.0, bottom_offset);
|
||||
let underline1_quad = mk_quad!(pos_offset1, style_line_height);
|
||||
|
||||
let pos_offset2 = mk_pos_offset!(0.0, bottom_offset / 2.0);
|
||||
let underline2_quad = mk_quad!(pos_offset2, style_line_height);
|
||||
|
||||
renderer.fill_quad(underline1_quad, line_color);
|
||||
renderer.fill_quad(underline2_quad, line_color);
|
||||
}
|
||||
|
||||
if metadata.flags.contains(Flags::DOTTED_UNDERLINE) {
|
||||
let bottom_offset = style_line_height * 2.0;
|
||||
|
||||
let full_width = self.end_x - self.start_x;
|
||||
let mut accu_width = 0.0;
|
||||
let mut dot_width = 2.0f32.min(full_width - accu_width);
|
||||
|
||||
while accu_width < full_width {
|
||||
dot_width = dot_width.min(full_width - accu_width);
|
||||
let pos_offset = mk_pos_offset!(accu_width, bottom_offset);
|
||||
let underline_quad =
|
||||
mk_quad!(pos_offset, style_line_height, dot_width);
|
||||
renderer.fill_quad(underline_quad, line_color);
|
||||
accu_width += 2.0 * dot_width;
|
||||
}
|
||||
}
|
||||
|
||||
if metadata.flags.contains(Flags::DASHED_UNDERLINE) {
|
||||
let bottom_offset = style_line_height * 2.0;
|
||||
|
||||
let full_width = self.end_x - self.start_x;
|
||||
let mut accu_width = 0.0;
|
||||
let mut dash_width = 6.0f32.min(full_width - accu_width);
|
||||
let gap_width = dash_width / 2.0;
|
||||
|
||||
// gap-width dash first
|
||||
let pos_offset = mk_pos_offset!(accu_width, bottom_offset);
|
||||
let underline_quad =
|
||||
mk_quad!(pos_offset, style_line_height, gap_width);
|
||||
renderer.fill_quad(underline_quad, line_color);
|
||||
accu_width += gap_width * 2.0;
|
||||
|
||||
while accu_width < full_width {
|
||||
dash_width = dash_width.min(full_width - accu_width);
|
||||
let pos_offset = mk_pos_offset!(accu_width, bottom_offset);
|
||||
let underline_quad =
|
||||
mk_quad!(pos_offset, style_line_height, dash_width);
|
||||
renderer.fill_quad(underline_quad, line_color);
|
||||
accu_width += dash_width + gap_width;
|
||||
}
|
||||
}
|
||||
|
||||
if metadata.flags.contains(Flags::UNDERCURL) {
|
||||
let style_line_height = style_line_height.floor();
|
||||
let bottom_offset = style_line_height * 1.5;
|
||||
|
||||
let full_width = self.end_x - self.start_x;
|
||||
let mut accu_width = 0.0;
|
||||
let mut dot_width = 1.0f32.min(full_width - accu_width);
|
||||
|
||||
while accu_width < full_width {
|
||||
dot_width = dot_width.min(full_width - accu_width);
|
||||
|
||||
let dot_bottom_offset = match accu_width as u32 % 8 {
|
||||
3 | 4 | 5 => bottom_offset + style_line_height,
|
||||
2 | 6 => bottom_offset + 2.0 * style_line_height / 3.0,
|
||||
1 | 7 => bottom_offset + 1.0 * style_line_height / 3.0,
|
||||
_ => bottom_offset,
|
||||
};
|
||||
|
||||
let pos_offset = mk_pos_offset!(accu_width, dot_bottom_offset);
|
||||
let underline_quad =
|
||||
mk_quad!(pos_offset, style_line_height, dot_width);
|
||||
renderer.fill_quad(underline_quad, line_color);
|
||||
accu_width += dot_width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let default_metadata = terminal.default_attrs().metadata;
|
||||
let metadata_set = &terminal.metadata_set;
|
||||
let mut bg_rect = BgRect {
|
||||
default_metadata,
|
||||
metadata: default_metadata,
|
||||
glyph_font_size: 0.0,
|
||||
start_x: 0.0,
|
||||
end_x: 0.0,
|
||||
line_height: buffer.metrics().line_height,
|
||||
line_top: run.line_top,
|
||||
view_position,
|
||||
metadata_set,
|
||||
};
|
||||
for glyph in run.glyphs.iter() {
|
||||
bg_rect.update(glyph, renderer);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue