aboutsummaryrefslogtreecommitdiff
path: root/helix-view
diff options
context:
space:
mode:
authorPascal Kuthe2022-10-01 00:15:25 +0000
committerPascal Kuthe2022-10-01 17:29:46 +0000
commit71ee589bbc723e7a55585ddc2ca43c29ee93fabe (patch)
treef64805cc305349a2430cae837355e7ef6ee7546c /helix-view
parent79d3d44c3db48365597eefd274e868bc1e15de57 (diff)
make underline_style a seperate option
Underline styles are mutally exclusive and overwrite each other. Therefore implementing as an modifier lead to incorrect behaviour when the underline style is overwritten. For backwards compatability the "underline" modified is retained (but deprecated). Instead the "underline_style" and "underline_color" optios should be used to style underlines.
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)),