summaryrefslogtreecommitdiff
path: root/helix-view
diff options
context:
space:
mode:
Diffstat (limited to 'helix-view')
-rw-r--r--helix-view/src/graphics.rs101
-rw-r--r--helix-view/src/gutter.rs4
-rw-r--r--helix-view/src/theme.rs23
3 files changed, 95 insertions, 33 deletions
diff --git a/helix-view/src/graphics.rs b/helix-view/src/graphics.rs
index 6c854fd0..01344748 100644
--- a/helix-view/src/graphics.rs
+++ b/helix-view/src/graphics.rs
@@ -315,6 +315,44 @@ impl From<Color> for crossterm::style::Color {
}
}
+#[derive(Debug, Clone, Copy, PartialEq)]
+pub enum UnderlineStyle {
+ Reset,
+ Line,
+ Curl,
+ Dotted,
+ Dashed,
+ DoubleLine,
+}
+
+impl FromStr for UnderlineStyle {
+ type Err = &'static str;
+
+ fn from_str(modifier: &str) -> Result<Self, Self::Err> {
+ match modifier {
+ "line" => Ok(Self::Line),
+ "curl" => Ok(Self::Curl),
+ "dotted" => Ok(Self::Dotted),
+ "dashed" => Ok(Self::Dashed),
+ "double_line" => Ok(Self::DoubleLine),
+ _ => Err("Invalid underline style"),
+ }
+ }
+}
+
+impl From<UnderlineStyle> for crossterm::style::Attribute {
+ fn from(style: UnderlineStyle) -> Self {
+ match style {
+ UnderlineStyle::Line => crossterm::style::Attribute::Underlined,
+ UnderlineStyle::Curl => crossterm::style::Attribute::Undercurled,
+ UnderlineStyle::Dotted => crossterm::style::Attribute::Underdotted,
+ UnderlineStyle::Dashed => crossterm::style::Attribute::Underdashed,
+ UnderlineStyle::DoubleLine => crossterm::style::Attribute::DoubleUnderlined,
+ UnderlineStyle::Reset => crossterm::style::Attribute::NoUnderline,
+ }
+ }
+}
+
bitflags! {
/// Modifier changes the way a piece of text is displayed.
///
@@ -332,22 +370,11 @@ bitflags! {
const BOLD = 0b0000_0000_0000_0001;
const DIM = 0b0000_0000_0000_0010;
const ITALIC = 0b0000_0000_0000_0100;
- const UNDERLINED = 0b0000_0000_0000_1000;
const SLOW_BLINK = 0b0000_0000_0001_0000;
const RAPID_BLINK = 0b0000_0000_0010_0000;
const REVERSED = 0b0000_0000_0100_0000;
const HIDDEN = 0b0000_0000_1000_0000;
const CROSSED_OUT = 0b0000_0001_0000_0000;
- const UNDERCURLED = 0b0000_0010_0000_0000;
- const UNDERDOTTED = 0b0000_0100_0000_0000;
- const UNDERDASHED = 0b0000_1000_0000_0000;
- const DOUBLE_UNDERLINED = 0b0001_0000_0000_0000;
-
- const ANY_UNDERLINE = Self::UNDERLINED.bits
- | Self::UNDERCURLED.bits
- | Self::UNDERDOTTED.bits
- | Self::UNDERDASHED.bits
- | Self::DOUBLE_UNDERLINED.bits;
}
}
@@ -359,16 +386,11 @@ impl FromStr for Modifier {
"bold" => Ok(Self::BOLD),
"dim" => Ok(Self::DIM),
"italic" => Ok(Self::ITALIC),
- "underlined" => Ok(Self::UNDERLINED),
"slow_blink" => Ok(Self::SLOW_BLINK),
"rapid_blink" => Ok(Self::RAPID_BLINK),
"reversed" => Ok(Self::REVERSED),
"hidden" => Ok(Self::HIDDEN),
"crossed_out" => Ok(Self::CROSSED_OUT),
- "undercurled" => Ok(Self::UNDERCURLED),
- "underdotted" => Ok(Self::UNDERDOTTED),
- "underdashed" => Ok(Self::UNDERDASHED),
- "double_underlined" => Ok(Self::DOUBLE_UNDERLINED),
_ => Err("Invalid modifier"),
}
}
@@ -389,7 +411,7 @@ impl FromStr for Modifier {
/// just S3.
///
/// ```rust
-/// # use helix_view::graphics::{Rect, Color, Modifier, Style};
+/// # use helix_view::graphics::{Rect, Color, UnderlineStyle, Modifier, Style};
/// # use helix_tui::buffer::Buffer;
/// let styles = [
/// Style::default().fg(Color::Blue).add_modifier(Modifier::BOLD | Modifier::ITALIC),
@@ -405,7 +427,8 @@ impl FromStr for Modifier {
/// fg: Some(Color::Yellow),
/// bg: Some(Color::Red),
/// add_modifier: Modifier::BOLD,
-/// underline: Some(Color::Reset),
+/// underline_color: Some(Color::Reset),
+/// underline_style: Some(UnderlineStyle::Reset),
/// sub_modifier: Modifier::empty(),
/// },
/// buffer[(0, 0)].style(),
@@ -416,7 +439,7 @@ impl FromStr for Modifier {
/// reset all properties until that point use [`Style::reset`].
///
/// ```
-/// # use helix_view::graphics::{Rect, Color, Modifier, Style};
+/// # use helix_view::graphics::{Rect, Color, UnderlineStyle, Modifier, Style};
/// # use helix_tui::buffer::Buffer;
/// let styles = [
/// Style::default().fg(Color::Blue).add_modifier(Modifier::BOLD | Modifier::ITALIC),
@@ -430,7 +453,8 @@ impl FromStr for Modifier {
/// Style {
/// fg: Some(Color::Yellow),
/// bg: Some(Color::Reset),
-/// underline: Some(Color::Reset),
+/// underline_color: Some(Color::Reset),
+/// underline_style: Some(UnderlineStyle::Reset),
/// add_modifier: Modifier::empty(),
/// sub_modifier: Modifier::empty(),
/// },
@@ -442,7 +466,8 @@ impl FromStr for Modifier {
pub struct Style {
pub fg: Option<Color>,
pub bg: Option<Color>,
- pub underline: Option<Color>,
+ pub underline_color: Option<Color>,
+ pub underline_style: Option<UnderlineStyle>,
pub add_modifier: Modifier,
pub sub_modifier: Modifier,
}
@@ -452,7 +477,8 @@ impl Default for Style {
Style {
fg: None,
bg: None,
- underline: None,
+ underline_color: None,
+ underline_style: None,
add_modifier: Modifier::empty(),
sub_modifier: Modifier::empty(),
}
@@ -465,7 +491,8 @@ impl Style {
Style {
fg: Some(Color::Reset),
bg: Some(Color::Reset),
- underline: Some(Color::Reset),
+ underline_color: None,
+ underline_style: None,
add_modifier: Modifier::empty(),
sub_modifier: Modifier::all(),
}
@@ -507,12 +534,27 @@ impl Style {
///
/// ```rust
/// # use helix_view::graphics::{Color, Style};
- /// let style = Style::default().underline(Color::Blue);
- /// let diff = Style::default().underline(Color::Red);
- /// assert_eq!(style.patch(diff), Style::default().underline(Color::Red));
+ /// let style = Style::default().underline_color(Color::Blue);
+ /// let diff = Style::default().underline_color(Color::Red);
+ /// assert_eq!(style.patch(diff), Style::default().underline_color(Color::Red));
+ /// ```
+ pub fn underline_color(mut self, color: Color) -> Style {
+ self.underline_color = Some(color);
+ self
+ }
+
+ /// Changes the underline style.
+ ///
+ /// ## Examples
+ ///
+ /// ```rust
+ /// # use helix_view::graphics::{UnderlineStyle, Style};
+ /// let style = Style::default().underline_style(UnderlineStyle::Line);
+ /// let diff = Style::default().underline_style(UnderlineStyle::Curl);
+ /// assert_eq!(style.patch(diff), Style::default().underline_style(UnderlineStyle::Curl));
/// ```
- pub fn underline(mut self, color: Color) -> Style {
- self.underline = Some(color);
+ pub fn underline_style(mut self, style: UnderlineStyle) -> Style {
+ self.underline_style = Some(style);
self
}
@@ -572,7 +614,8 @@ impl Style {
pub fn patch(mut self, other: Style) -> Style {
self.fg = other.fg.or(self.fg);
self.bg = other.bg.or(self.bg);
- self.underline = other.underline.or(self.underline);
+ self.underline_color = other.underline_color.or(self.underline_color);
+ self.underline_style = other.underline_style.or(self.underline_style);
self.add_modifier.remove(other.sub_modifier);
self.add_modifier.insert(other.add_modifier);
diff --git a/helix-view/src/gutter.rs b/helix-view/src/gutter.rs
index ab0e2986..2c207d27 100644
--- a/helix-view/src/gutter.rs
+++ b/helix-view/src/gutter.rs
@@ -1,7 +1,7 @@
use std::fmt::Write;
use crate::{
- graphics::{Color, Modifier, Style},
+ graphics::{Color, Style, UnderlineStyle},
Document, Editor, Theme, View,
};
@@ -147,7 +147,7 @@ pub fn breakpoints<'doc>(
.find(|breakpoint| breakpoint.line == line)?;
let mut style = if breakpoint.condition.is_some() && breakpoint.log_message.is_some() {
- error.add_modifier(Modifier::UNDERLINED)
+ error.underline_style(UnderlineStyle::Line)
} else if breakpoint.condition.is_some() {
error
} else if breakpoint.log_message.is_some() {
diff --git a/helix-view/src/theme.rs b/helix-view/src/theme.rs
index 5ce1b2c5..90185937 100644
--- a/helix-view/src/theme.rs
+++ b/helix-view/src/theme.rs
@@ -10,6 +10,7 @@ use once_cell::sync::Lazy;
use serde::{Deserialize, Deserializer};
use toml::Value;
+use crate::graphics::UnderlineStyle;
pub use crate::graphics::{Color, Modifier, Style};
pub static DEFAULT_THEME: Lazy<Theme> = Lazy::new(|| {
@@ -263,20 +264,38 @@ impl ThemePalette {
.ok_or(format!("Theme: invalid modifier: {}", value))
}
+ pub fn parse_underline_style(value: &Value) -> Result<UnderlineStyle, String> {
+ value
+ .as_str()
+ .and_then(|s| s.parse().ok())
+ .ok_or(format!("Theme: invalid underline_style: {}", value))
+ }
+
pub fn parse_style(&self, style: &mut Style, value: Value) -> Result<(), String> {
if let Value::Table(entries) = value {
for (name, value) in entries {
match name.as_str() {
"fg" => *style = style.fg(self.parse_color(value)?),
"bg" => *style = style.bg(self.parse_color(value)?),
- "underline" => *style = style.underline(self.parse_color(value)?),
+ "underline_color" => *style = style.underline_color(self.parse_color(value)?),
+ "underline_style" => {
+ warn!("found style");
+ *style = style.underline_style(Self::parse_underline_style(&value)?)
+ }
"modifiers" => {
let modifiers = value
.as_array()
.ok_or("Theme: modifiers should be an array")?;
for modifier in modifiers {
- *style = style.add_modifier(Self::parse_modifier(modifier)?);
+ if modifier
+ .as_str()
+ .map_or(false, |modifier| modifier == "underlined")
+ {
+ *style = style.underline_style(UnderlineStyle::Line);
+ } else {
+ *style = style.add_modifier(Self::parse_modifier(modifier)?);
+ }
}
}
_ => return Err(format!("Theme: invalid style attribute: {}", name)),