diff options
author | Matan Kushner <hello@matchai.me> | 2019-05-01 16:34:24 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-05-01 16:34:24 -0400 |
commit | c6ee5c6ac16d360ab1a44d097c91fe9f98f20f85 (patch) | |
tree | e06814175f34e508fbae4de66571e3d0042786e7 /src/segment.rs | |
parent | d945b03093cf130bdc702056650f7e8e8869753b (diff) |
Refactor segments into modules (#40)
Diffstat (limited to 'src/segment.rs')
-rw-r--r-- | src/segment.rs | 175 |
1 files changed, 80 insertions, 95 deletions
diff --git a/src/segment.rs b/src/segment.rs index a56e1bf82..0d71af1af 100644 --- a/src/segment.rs +++ b/src/segment.rs @@ -1,58 +1,50 @@ -use ansi_term::Style; +use ansi_term::{ANSIString, ANSIStrings, Style}; +use std::fmt; -#[derive(Clone)] +/// A segment is a single configurable element in a module. This will usually +/// contain a data point to provide context for the prompt's user +/// (e.g. The version that software is running). pub struct Segment { - name: Option<String>, - style: Style, + /// The segment's name, to be used in configuration and logging. + name: String, + + /// The segment's style. If None, will inherit the style of the module containing it. + style: Option<Style>, + + /// The prefix used to preceed the contents of a segment. + prefix: Option<SegmentAffix>, + + /// The string value of the current segment. value: String, - prefix: BoxedSegment, - suffix: BoxedSegment, + + /// The suffix used following the contents of a segment. + suffix: Option<SegmentAffix>, } impl Segment { - /// Creates a new segment with default fields - pub fn new<T>(name: T) -> Segment - where - T: Into<String>, - T: Copy, - { - let default_prefix = Some(Box::new(Segment { - name: Some(format!("{} {}", name.into(), "prefix")), - style: Style::default(), - value: String::from("via "), - prefix: None, - suffix: None, - })); - - let default_suffix = Some(Box::new(Segment { - name: Some(format!("{} {}", name.into(), "suffix")), - style: Style::default(), - value: String::from(" "), + /// Creates a new segment with default fields. + pub fn new(name: &str) -> Segment { + Segment { + name: name.to_string(), + style: None, prefix: None, + value: "".to_string(), suffix: None, - })); - - Segment { - name: Some(name.into()), - style: Style::default(), - value: String::from(""), - prefix: default_prefix, - suffix: default_suffix, } } - /// Sets the style of the segment + /// Sets the style of the segment. /// /// Accepts either `Color` or `Style`. pub fn set_style<T>(&mut self, style: T) -> &mut Segment where T: Into<Style>, { - self.style = style.into(); + self.style = Some(style.into()); self } - /// Sets the value of the segment + /// Sets the value of the segment. pub fn set_value<T>(&mut self, value: T) -> &mut Segment where T: Into<String>, @@ -61,77 +53,70 @@ impl Segment { self } - /// Sets the prefix of the segment - pub fn set_prefix(&mut self, prefix: BoxedSegment) -> &mut Segment { - self.prefix = prefix; - self + // Returns the ANSIString of the segment value, not including its prefix and suffix + fn value_ansi_string(&self) -> ANSIString { + match self.style { + Some(style) => style.paint(&self.value), + None => ANSIString::from(&self.value), + } } - /// Sets the suffix of the segment - pub fn set_suffix(&mut self, suffix: BoxedSegment) -> &mut Segment { - self.suffix = suffix; - self + /// Returns a vector of colored ANSIString elements to be later used with + /// `ANSIStrings()` to optimize ANSI codes + pub fn ansi_strings(&self) -> Vec<ANSIString> { + let prefix = self.prefix.as_ref().and_then(|p| Some(p.ansi_string())); + let suffix = self.suffix.as_ref().and_then(|s| Some(s.ansi_string())); + let value = Some(self.value_ansi_string()); + + // Remove `None` values from the vector + vec![prefix, value, suffix] + .into_iter() + .filter_map(|e| e) + .collect::<Vec<ANSIString>>() } +} - /// Create a string with the formatted contents of a segment - /// - /// Will recursively also format the prefix and suffix of the segment being - /// stringified. - pub fn output(&self) -> String { - let Segment { - name: _name, - prefix, - value, - style, - suffix, - } = self; - - let mut segment_string = String::new(); - - // Skip the prefix for the first segment - if let Some(prefix) = prefix { - segment_string += &prefix.output() - } +impl fmt::Display for Segment { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let ansi_strings = self.ansi_strings(); + write!(f, "{}", ANSIStrings(&ansi_strings)) + } +} - segment_string += &style.paint(value).to_string(); +/// Segment affixes are to be used for the prefix or suffix of a segment. +/// By default they will inherit the styling of its segment, unless otherwise specified. +pub struct SegmentAffix { + /// The affix's name, to be used in configuration and logging. + name: String, - if let Some(suffix) = suffix { - segment_string += &suffix.output(); - } + /// The affix's style. If None, will inherit the style of the segment containing it. + style: Option<Style>, - segment_string - } + /// The string value of the affix. + value: String, +} - /// Create a string with the formatted contents of a segment while skipping the first segment. - /// - /// Will recursively also format the prefix and suffix of the segment being - /// stringified. - pub fn output_index(&self, index: usize) -> String { - let Segment { - name: _name, - prefix, - value, - style, - suffix, - } = self; - - let mut segment_string = String::new(); - - // Skip the prefix for the first segment - if index != 0 { - if let Some(prefix) = prefix { - segment_string += &prefix.output_index(index) - } +impl SegmentAffix { + /// Creates a segment affix with no contents. + pub fn new() -> SegmentAffix { + SegmentAffix { + name: String::new(), + style: None, + value: String::new(), } + } - segment_string += &style.paint(value).to_string(); - - if let Some(suffix) = suffix { - segment_string += &suffix.output(); + /// Generates the colored ANSIString output. + pub fn ansi_string(&self) -> ANSIString { + match self.style { + Some(style) => style.paint(&self.value), + None => ANSIString::from(&self.value), } - - segment_string } } -type BoxedSegment = Option<Box<Segment>>; +impl fmt::Display for SegmentAffix { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.ansi_string()) + } +} |