use crate::text::{Span, Spans}; use helix_view::graphics::{Color, Modifier, Rect, Style}; pub use termwiz::surface::Surface as Buffer; use termwiz::{cell::*, surface::*}; pub struct Cell<'a> { surface: &'a mut Surface, } impl<'a> Cell<'a> { pub fn set_symbol<'b>(self, symbol: &'b str) -> Cell<'a> { self.surface.add_change(Change::Text(symbol.into())); self } pub fn set_style(self, style: Style) -> Cell<'a> { if let Some(fg) = style.fg { self.surface .add_change(Change::Attribute(AttributeChange::Foreground(fg.into()))); } if let Some(bg) = style.bg { self.surface .add_change(Change::Attribute(AttributeChange::Background(bg.into()))); } self.surface .add_change(Change::Attribute(AttributeChange::Intensity( if style.add_modifier.contains(Modifier::BOLD) { Intensity::Bold } else if style.add_modifier.contains(Modifier::DIM) { Intensity::Half } else { Intensity::Normal }, ))); self.surface .add_change(Change::Attribute(AttributeChange::Italic( style.add_modifier.contains(Modifier::ITALIC), ))); self.surface .add_change(Change::Attribute(AttributeChange::Underline( if style.add_modifier.contains(Modifier::UNDERLINED) { Underline::Single } else { Underline::None }, ))); self.surface .add_change(Change::Attribute(AttributeChange::Reverse( style.add_modifier.contains(Modifier::REVERSED), ))); self.surface .add_change(Change::Attribute(AttributeChange::Invisible( style.add_modifier.contains(Modifier::HIDDEN), ))); self.surface .add_change(Change::Attribute(AttributeChange::StrikeThrough( style.add_modifier.contains(Modifier::CROSSED_OUT), ))); self.surface .add_change(Change::Attribute(AttributeChange::Blink( if style.add_modifier.contains(Modifier::SLOW_BLINK) { Blink::Slow } else if style.add_modifier.contains(Modifier::RAPID_BLINK) { Blink::Rapid } else { Blink::None }, ))); self } } pub trait SurfaceExt { // fn set_style(&mut self, area: Rect, style: Style) {} fn clear_with(&mut self, area: Rect, style: Style) {} fn set_string(&mut self, x: u16, y: u16, string: S, style: Style) where S: AsRef, { self.set_stringn(x, y, string, usize::MAX, style); } fn set_stringn( &mut self, x: u16, y: u16, string: S, width: usize, style: Style, ) -> (u16, u16) where S: AsRef; fn set_spans<'a>(&mut self, x: u16, y: u16, spans: &Spans<'a>, width: u16) -> (u16, u16) { let mut remaining_width = width; let mut x = x; for span in &spans.0 { if remaining_width == 0 { break; } let pos = self.set_stringn( x, y, span.content.as_ref(), remaining_width as usize, span.style, ); let w = pos.0.saturating_sub(x); x = pos.0; remaining_width = remaining_width.saturating_sub(w); } (x, y) } fn set_span<'a>(&mut self, x: u16, y: u16, span: &Span<'a>, width: u16) -> (u16, u16) { self.set_stringn(x, y, span.content.as_ref(), width as usize, span.style) } fn set_string_truncated( &mut self, x: u16, y: u16, string: &str, width: usize, style: impl Fn(usize) -> Style, // Map a grapheme's string offset to a style ellipsis: bool, truncate_start: bool, ) { // TODO } fn get_mut(&mut self, x: u16, y: u16) -> Cell; } impl SurfaceExt for termwiz::surface::Surface { // //fn set_style(&mut self, area: Rect, style: Style) { // // //} fn set_stringn( &mut self, x: u16, y: u16, string: S, width: usize, style: Style, ) -> (u16, u16) where S: AsRef, { // TODO: style and limit to width self.add_change(Change::CursorPosition { x: Position::Absolute(x as usize), y: Position::Absolute(y as usize), }); let fg = style.fg.unwrap_or(Color::Reset); self.add_change(Change::Attribute(AttributeChange::Foreground(fg.into()))); let bg = style.bg.unwrap_or(Color::Reset); self.add_change(Change::Attribute(AttributeChange::Background(bg.into()))); self.add_change(Change::Text(string.as_ref().to_owned())); (0, 0) } fn get_mut(&mut self, x: u16, y: u16) -> Cell { self.add_change(Change::CursorPosition { x: Position::Absolute(x as usize), y: Position::Absolute(y as usize), }); Cell { surface: self } } }