Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-tui/src/text.rs')
-rw-r--r--helix-tui/src/text.rs109
1 files changed, 14 insertions, 95 deletions
diff --git a/helix-tui/src/text.rs b/helix-tui/src/text.rs
index a9c36503..8a974ddb 100644
--- a/helix-tui/src/text.rs
+++ b/helix-tui/src/text.rs
@@ -5,12 +5,12 @@
//! - A single line string where all graphemes have the same style is represented by a [`Span`].
//! - A single line string where each grapheme may have its own style is represented by [`Spans`].
//! - A multiple line string where each grapheme may have its own style is represented by a
-//! [`Text`].
+//! [`Text`].
//!
//! These types form a hierarchy: [`Spans`] is a collection of [`Span`] and each line of [`Text`]
//! is a [`Spans`].
//!
-//! Keep in mind that a lot of widgets will use those types to advertise what kind of string is
+//! Keep it mind that a lot of widgets will use those types to advertise what kind of string is
//! supported for their properties. Moreover, `tui` provides convenient `From` implementations so
//! that you can start by using simple `String` or `&str` and then promote them to the previous
//! primitives when you need additional styling capabilities.
@@ -53,14 +53,14 @@ use std::borrow::Cow;
use unicode_segmentation::UnicodeSegmentation;
/// A grapheme associated to a style.
-#[derive(Debug, Clone, PartialEq, Eq)]
+#[derive(Debug, Clone, PartialEq)]
pub struct StyledGrapheme<'a> {
pub symbol: &'a str,
pub style: Style,
}
/// A string where all graphemes have the same style.
-#[derive(Debug, Clone, PartialEq, Eq)]
+#[derive(Debug, Clone, PartialEq)]
pub struct Span<'a> {
pub content: Cow<'a, str>,
pub style: Style,
@@ -134,8 +134,6 @@ impl<'a> Span<'a> {
/// style: Style {
/// fg: Some(Color::Yellow),
/// bg: Some(Color::Black),
- /// underline_color: None,
- /// underline_style: None,
/// add_modifier: Modifier::empty(),
/// sub_modifier: Modifier::empty(),
/// },
@@ -145,8 +143,6 @@ impl<'a> Span<'a> {
/// style: Style {
/// fg: Some(Color::Yellow),
/// bg: Some(Color::Black),
- /// underline_color: None,
- /// underline_style: None,
/// add_modifier: Modifier::empty(),
/// sub_modifier: Modifier::empty(),
/// },
@@ -156,8 +152,6 @@ impl<'a> Span<'a> {
/// style: Style {
/// fg: Some(Color::Yellow),
/// bg: Some(Color::Black),
- /// underline_color: None,
- /// underline_style: None,
/// add_modifier: Modifier::empty(),
/// sub_modifier: Modifier::empty(),
/// },
@@ -167,8 +161,6 @@ impl<'a> Span<'a> {
/// style: Style {
/// fg: Some(Color::Yellow),
/// bg: Some(Color::Black),
- /// underline_color: None,
- /// underline_style: None,
/// add_modifier: Modifier::empty(),
/// sub_modifier: Modifier::empty(),
/// },
@@ -202,17 +194,11 @@ impl<'a> From<&'a str> for Span<'a> {
}
}
-impl<'a> From<Cow<'a, str>> for Span<'a> {
- fn from(s: Cow<'a, str>) -> Span<'a> {
- Span::raw(s)
- }
-}
-
/// A string composed of clusters of graphemes, each with their own style.
-#[derive(Debug, Default, Clone, PartialEq, Eq)]
+#[derive(Debug, Default, Clone, PartialEq)]
pub struct Spans<'a>(pub Vec<Span<'a>>);
-impl Spans<'_> {
+impl<'a> Spans<'a> {
/// Returns the width of the underlying string.
///
/// ## Examples
@@ -243,12 +229,6 @@ impl<'a> From<&'a str> for Spans<'a> {
}
}
-impl<'a> From<Cow<'a, str>> for Spans<'a> {
- fn from(s: Cow<'a, str>) -> Spans<'a> {
- Spans(vec![Span::raw(s)])
- }
-}
-
impl<'a> From<Vec<Span<'a>>> for Spans<'a> {
fn from(spans: Vec<Span<'a>>) -> Spans<'a> {
Spans(spans)
@@ -263,13 +243,10 @@ impl<'a> From<Span<'a>> for Spans<'a> {
impl<'a> From<Spans<'a>> for String {
fn from(line: Spans<'a>) -> String {
- line.0.iter().map(|s| &*s.content).collect()
- }
-}
-
-impl<'a> From<&Spans<'a>> for String {
- fn from(line: &Spans<'a>) -> String {
- line.0.iter().map(|s| &*s.content).collect()
+ line.0.iter().fold(String::new(), |mut acc, s| {
+ acc.push_str(s.content.as_ref());
+ acc
+ })
}
}
@@ -297,7 +274,7 @@ impl<'a> From<&Spans<'a>> for String {
/// text.extend(Text::styled("Some more lines\nnow with more style!", style));
/// assert_eq!(6, text.height());
/// ```
-#[derive(Debug, Default, Clone, PartialEq, Eq)]
+#[derive(Debug, Default, Clone, PartialEq)]
pub struct Text<'a> {
pub lines: Vec<Spans<'a>>,
}
@@ -374,30 +351,6 @@ impl<'a> Text<'a> {
self.lines.len()
}
- /// Patch text with a new style. Only updates fields that are in the new style.
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use helix_tui::text::Text;
- /// # use helix_view::graphics::{Color, Style};
- /// let style1 = Style::default().fg(Color::Yellow);
- /// let style2 = Style::default().fg(Color::Yellow).bg(Color::Black);
- /// let mut half_styled_text = Text::styled(String::from("The first line\nThe second line"), style1);
- /// let full_styled_text = Text::styled(String::from("The first line\nThe second line"), style2);
- /// assert_ne!(half_styled_text, full_styled_text);
- ///
- /// half_styled_text.patch_style(Style::default().bg(Color::Black));
- /// assert_eq!(half_styled_text, full_styled_text);
- /// ```
- pub fn patch_style(&mut self, style: Style) {
- for line in &mut self.lines {
- for span in &mut line.0 {
- span.style = span.style.patch(style);
- }
- }
- }
-
/// Apply a new style to existing text.
///
/// # Examples
@@ -410,13 +363,13 @@ impl<'a> Text<'a> {
/// let styled_text = Text::styled(String::from("The first line\nThe second line"), style);
/// assert_ne!(raw_text, styled_text);
///
- /// raw_text.set_style(style);
+ /// raw_text.patch_style(style);
/// assert_eq!(raw_text, styled_text);
/// ```
- pub fn set_style(&mut self, style: Style) {
+ pub fn patch_style(&mut self, style: Style) {
for line in &mut self.lines {
for span in &mut line.0 {
- span.style = style;
+ span.style = span.style.patch(style);
}
}
}
@@ -434,12 +387,6 @@ impl<'a> From<&'a str> for Text<'a> {
}
}
-impl<'a> From<Cow<'a, str>> for Text<'a> {
- fn from(s: Cow<'a, str>) -> Text<'a> {
- Text::raw(s)
- }
-}
-
impl<'a> From<Span<'a>> for Text<'a> {
fn from(span: Span<'a>) -> Text<'a> {
Text {
@@ -460,34 +407,6 @@ impl<'a> From<Vec<Spans<'a>>> for Text<'a> {
}
}
-impl<'a> From<Text<'a>> for String {
- fn from(text: Text<'a>) -> String {
- String::from(&text)
- }
-}
-
-impl<'a> From<&Text<'a>> for String {
- fn from(text: &Text<'a>) -> String {
- let size = text
- .lines
- .iter()
- .flat_map(|spans| spans.0.iter().map(|span| span.content.len()))
- .sum::<usize>()
- + text.lines.len().saturating_sub(1); // for newline after each line
- let mut output = String::with_capacity(size);
-
- for spans in &text.lines {
- if !output.is_empty() {
- output.push('\n');
- }
- for span in &spans.0 {
- output.push_str(&span.content);
- }
- }
- output
- }
-}
-
impl<'a> IntoIterator for Text<'a> {
type Item = Spans<'a>;
type IntoIter = std::vec::IntoIter<Self::Item>;