@@ -315,6 +315,44 @@ impl From<Color> for crossterm::style::Color {
318+#[derive(Debug, Clone, Copy, PartialEq)]
319+pub enum UnderlineStyle {
328+impl FromStr for UnderlineStyle {
329+ type Err = &'static str;
331+ fn from_str(modifier: &str) -> Result<Self, Self::Err> {
333+ "line" => Ok(Self::Line),
334+ "curl" => Ok(Self::Curl),
335+ "dotted" => Ok(Self::Dotted),
336+ "dashed" => Ok(Self::Dashed),
337+ "double_line" => Ok(Self::DoubleLine),
338+ _ => Err("Invalid underline style"),
343+impl From<UnderlineStyle> for crossterm::style::Attribute {
344+ fn from(style: UnderlineStyle) -> Self {
346+ UnderlineStyle::Line => crossterm::style::Attribute::Underlined,
347+ UnderlineStyle::Curl => crossterm::style::Attribute::Undercurled,
348+ UnderlineStyle::Dotted => crossterm::style::Attribute::Underdotted,
349+ UnderlineStyle::Dashed => crossterm::style::Attribute::Underdashed,
350+ UnderlineStyle::DoubleLine => crossterm::style::Attribute::DoubleUnderlined,
351+ UnderlineStyle::Reset => crossterm::style::Attribute::NoUnderline,
318bitflags! {
356bitflags! {
319 /// Modifier changes the way a piece of text is displayed.
357 /// Modifier changes the way a piece of text is displayed.
@@ -332,22 +370,11 @@ bitflags! {
332 const BOLD = 0b0000_0000_0000_0001;
370 const BOLD = 0b0000_0000_0000_0001;
333 const DIM = 0b0000_0000_0000_0010;
371 const DIM = 0b0000_0000_0000_0010;
334 const ITALIC = 0b0000_0000_0000_0100;
372 const ITALIC = 0b0000_0000_0000_0100;
335− const UNDERLINED = 0b0000_0000_0000_1000;
336 const SLOW_BLINK = 0b0000_0000_0001_0000;
373 const SLOW_BLINK = 0b0000_0000_0001_0000;
337 const RAPID_BLINK = 0b0000_0000_0010_0000;
374 const RAPID_BLINK = 0b0000_0000_0010_0000;
338 const REVERSED = 0b0000_0000_0100_0000;
375 const REVERSED = 0b0000_0000_0100_0000;
339 const HIDDEN = 0b0000_0000_1000_0000;
376 const HIDDEN = 0b0000_0000_1000_0000;
340 const CROSSED_OUT = 0b0000_0001_0000_0000;
377 const CROSSED_OUT = 0b0000_0001_0000_0000;
341− const UNDERCURLED = 0b0000_0010_0000_0000;
342− const UNDERDOTTED = 0b0000_0100_0000_0000;
343− const UNDERDASHED = 0b0000_1000_0000_0000;
344− const DOUBLE_UNDERLINED = 0b0001_0000_0000_0000;
346− const ANY_UNDERLINE = Self::UNDERLINED.bits
347− | Self::UNDERCURLED.bits
348− | Self::UNDERDOTTED.bits
349− | Self::UNDERDASHED.bits
350− | Self::DOUBLE_UNDERLINED.bits;
@@ -359,16 +386,11 @@ impl FromStr for Modifier {
359 "bold" => Ok(Self::BOLD),
386 "bold" => Ok(Self::BOLD),
360 "dim" => Ok(Self::DIM),
387 "dim" => Ok(Self::DIM),
361 "italic" => Ok(Self::ITALIC),
388 "italic" => Ok(Self::ITALIC),
362− "underlined" => Ok(Self::UNDERLINED),
363 "slow_blink" => Ok(Self::SLOW_BLINK),
389 "slow_blink" => Ok(Self::SLOW_BLINK),
364 "rapid_blink" => Ok(Self::RAPID_BLINK),
390 "rapid_blink" => Ok(Self::RAPID_BLINK),
365 "reversed" => Ok(Self::REVERSED),
391 "reversed" => Ok(Self::REVERSED),
366 "hidden" => Ok(Self::HIDDEN),
392 "hidden" => Ok(Self::HIDDEN),
367 "crossed_out" => Ok(Self::CROSSED_OUT),
393 "crossed_out" => Ok(Self::CROSSED_OUT),
368− "undercurled" => Ok(Self::UNDERCURLED),
369− "underdotted" => Ok(Self::UNDERDOTTED),
370− "underdashed" => Ok(Self::UNDERDASHED),
371− "double_underlined" => Ok(Self::DOUBLE_UNDERLINED),
372 _ => Err("Invalid modifier"),
394 _ => Err("Invalid modifier"),
@@ -389,7 +411,7 @@ impl FromStr for Modifier {
389/// just S3.
411/// just S3.
391/// ```rust
413/// ```rust
392−/// # use helix_view::graphics::{Rect, Color, Modifier, Style};
414+/// # use helix_view::graphics::{Rect, Color, UnderlineStyle, Modifier, Style};
393/// # use helix_tui::buffer::Buffer;
415/// # use helix_tui::buffer::Buffer;
394/// let styles = [
416/// let styles = [
395/// Style::default().fg(Color::Blue).add_modifier(Modifier::BOLD | Modifier::ITALIC),
417/// Style::default().fg(Color::Blue).add_modifier(Modifier::BOLD | Modifier::ITALIC),
@@ -405,7 +427,8 @@ impl FromStr for Modifier {
405/// fg: Some(Color::Yellow),
427/// fg: Some(Color::Yellow),
406/// bg: Some(Color::Red),
428/// bg: Some(Color::Red),
407/// add_modifier: Modifier::BOLD,
429/// add_modifier: Modifier::BOLD,
408−/// underline: Some(Color::Reset),
430+/// underline_color: Some(Color::Reset),
431+/// underline_style: Some(UnderlineStyle::Reset),
409/// sub_modifier: Modifier::empty(),
432/// sub_modifier: Modifier::empty(),
411/// buffer[(0, 0)].style(),
434/// buffer[(0, 0)].style(),
@@ -416,7 +439,7 @@ impl FromStr for Modifier {
416/// reset all properties until that point use [`Style::reset`].
439/// reset all properties until that point use [`Style::reset`].
419−/// # use helix_view::graphics::{Rect, Color, Modifier, Style};
442+/// # use helix_view::graphics::{Rect, Color, UnderlineStyle, Modifier, Style};
420/// # use helix_tui::buffer::Buffer;
443/// # use helix_tui::buffer::Buffer;
421/// let styles = [
444/// let styles = [
422/// Style::default().fg(Color::Blue).add_modifier(Modifier::BOLD | Modifier::ITALIC),
445/// Style::default().fg(Color::Blue).add_modifier(Modifier::BOLD | Modifier::ITALIC),
@@ -430,7 +453,8 @@ impl FromStr for Modifier {
430/// Style {
453/// Style {
431/// fg: Some(Color::Yellow),
454/// fg: Some(Color::Yellow),
432/// bg: Some(Color::Reset),
455/// bg: Some(Color::Reset),
433−/// underline: Some(Color::Reset),
456+/// underline_color: Some(Color::Reset),
457+/// underline_style: Some(UnderlineStyle::Reset),
434/// add_modifier: Modifier::empty(),
458/// add_modifier: Modifier::empty(),
435/// sub_modifier: Modifier::empty(),
459/// sub_modifier: Modifier::empty(),
@@ -442,7 +466,8 @@ impl FromStr for Modifier {
442pub struct Style {
466pub struct Style {
443 pub fg: Option<Color>,
467 pub fg: Option<Color>,
444 pub bg: Option<Color>,
468 pub bg: Option<Color>,
445− pub underline: Option<Color>,
469+ pub underline_color: Option<Color>,
470+ pub underline_style: Option<UnderlineStyle>,
446 pub add_modifier: Modifier,
471 pub add_modifier: Modifier,
447 pub sub_modifier: Modifier,
472 pub sub_modifier: Modifier,
@@ -452,7 +477,8 @@ impl Default for Style {
453 fg: None,
478 fg: None,
454 bg: None,
479 bg: None,
455− underline: None,
480+ underline_color: None,
481+ underline_style: None,
456 add_modifier: Modifier::empty(),
482 add_modifier: Modifier::empty(),
457 sub_modifier: Modifier::empty(),
483 sub_modifier: Modifier::empty(),
@@ -465,7 +491,8 @@ impl Style {
466 fg: Some(Color::Reset),
492 fg: Some(Color::Reset),
467 bg: Some(Color::Reset),
493 bg: Some(Color::Reset),
468− underline: Some(Color::Reset),
494+ underline_color: None,
495+ underline_style: None,
469 add_modifier: Modifier::empty(),
496 add_modifier: Modifier::empty(),
470 sub_modifier: Modifier::all(),
497 sub_modifier: Modifier::all(),
@@ -507,12 +534,27 @@ impl Style {
508 /// ```rust
535 /// ```rust
509 /// # use helix_view::graphics::{Color, Style};
536 /// # use helix_view::graphics::{Color, Style};
510− /// let style = Style::default().underline(Color::Blue);
537+ /// let style = Style::default().underline_color(Color::Blue);
511− /// let diff = Style::default().underline(Color::Red);
538+ /// let diff = Style::default().underline_color(Color::Red);
512− /// assert_eq!(style.patch(diff), Style::default().underline(Color::Red));
539+ /// assert_eq!(style.patch(diff), Style::default().underline_color(Color::Red));
541+ pub fn underline_color(mut self, color: Color) -> Style {
542+ self.underline_color = Some(color);
546+ /// Changes the underline style.
551+ /// # use helix_view::graphics::{UnderlineStyle, Style};
552+ /// let style = Style::default().underline_style(UnderlineStyle::Line);
553+ /// let diff = Style::default().underline_style(UnderlineStyle::Curl);
554+ /// assert_eq!(style.patch(diff), Style::default().underline_style(UnderlineStyle::Curl));
514− pub fn underline(mut self, color: Color) -> Style {
556+ pub fn underline_style(mut self, style: UnderlineStyle) -> Style {
515− self.underline = Some(color);
557+ self.underline_style = Some(style);
@@ -572,7 +614,8 @@ impl Style {
572 pub fn patch(mut self, other: Style) -> Style {
614 pub fn patch(mut self, other: Style) -> Style {
573 self.fg = other.fg.or(self.fg);
615 self.fg = other.fg.or(self.fg);
574 self.bg = other.bg.or(self.bg);
616 self.bg = other.bg.or(self.bg);
575− self.underline = other.underline.or(self.underline);
617+ self.underline_color = other.underline_color.or(self.underline_color);
618+ self.underline_style = other.underline_style.or(self.underline_style);
577 self.add_modifier.remove(other.sub_modifier);
620 self.add_modifier.remove(other.sub_modifier);
578 self.add_modifier.insert(other.add_modifier);
621 self.add_modifier.insert(other.add_modifier);