• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

veeso / tui-realm-stdlib / 22147789116

09 Feb 2026 04:20PM UTC coverage: 77.303% (+4.8%) from 72.482%
22147789116

push

github

hasezoey
refactor(table): switch to use "CommonProps"

18 of 90 new or added lines in 1 file covered. (20.0%)

405 existing lines in 20 files now uncovered.

3944 of 5102 relevant lines covered (77.3%)

4.92 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

61.11
/src/components/span.rs
1
use tuirealm::command::{Cmd, CmdResult};
2
use tuirealm::props::{
3
    AttrValue, Attribute, Color, HorizontalAlignment, PropPayload, PropValue, Props, SpanStatic,
4
    Style, TextModifiers,
5
};
6
use tuirealm::ratatui::{
7
    layout::Rect,
8
    text::{Line, Span as RSpan, Text},
9
    widgets::Paragraph,
10
};
11
use tuirealm::{Frame, MockComponent, State};
12

13
use crate::prop_ext::CommonProps;
14
use crate::utils;
15

16
/// A Span represents single-line, multi-style text, without any container support.
17
///
18
/// If single-style text is wanted, use [`Label`](super::Label).
19
/// If multi-style, mutli-line, with container support is wanted, use [`Paragraph`](super::Paragraph).
20
#[derive(Default)]
21
#[must_use]
22
pub struct Span {
23
    common: CommonProps,
24
    props: Props,
25
}
26

27
impl Span {
28
    /// Set the main foreground color. This may get overwritten by individual text styles.
29
    pub fn foreground(mut self, fg: Color) -> Self {
2✔
30
        self.attr(Attribute::Foreground, AttrValue::Color(fg));
2✔
31
        self
2✔
32
    }
2✔
33

34
    /// Set the main background color. This may get overwritten by individual text styles.
35
    pub fn background(mut self, bg: Color) -> Self {
2✔
36
        self.attr(Attribute::Background, AttrValue::Color(bg));
2✔
37
        self
2✔
38
    }
2✔
39

40
    /// Set the main text modifiers. This may get overwritten by individual text styles.
41
    pub fn modifiers(mut self, m: TextModifiers) -> Self {
2✔
42
        self.attr(Attribute::TextProps, AttrValue::TextModifiers(m));
2✔
43
        self
2✔
44
    }
2✔
45

46
    /// Set the main style. This may get overwritten by individual text styles.
47
    ///
48
    /// This option will overwrite any previous [`foreground`](Self::foreground), [`background`](Self::background) and [`modifiers`](Self::modifiers)!
UNCOV
49
    pub fn style(mut self, style: Style) -> Self {
×
UNCOV
50
        self.attr(Attribute::Style, AttrValue::Style(style));
×
UNCOV
51
        self
×
UNCOV
52
    }
×
53

54
    /// Set the horizontal text alignment.
55
    pub fn alignment_horizontal(mut self, a: HorizontalAlignment) -> Self {
2✔
56
        self.attr(
2✔
57
            Attribute::AlignmentHorizontal,
2✔
58
            AttrValue::AlignmentHorizontal(a),
2✔
59
        );
1✔
60
        self
2✔
61
    }
2✔
62

63
    /// Set the Text content.
64
    pub fn spans<T>(mut self, s: impl IntoIterator<Item = T>) -> Self
10✔
65
    where
10✔
66
        T: Into<SpanStatic>,
10✔
67
    {
5✔
68
        self.attr(
10✔
69
            Attribute::Text,
10✔
70
            AttrValue::Payload(PropPayload::Vec(
10✔
71
                s.into_iter()
10✔
72
                    .map(Into::into)
10✔
73
                    .map(PropValue::TextSpan)
10✔
74
                    .collect(),
10✔
75
            )),
10✔
76
        );
5✔
77
        self
10✔
78
    }
10✔
79
}
80

81
impl MockComponent for Span {
82
    fn view(&mut self, render: &mut Frame, area: Rect) {
×
83
        if !self.common.display {
×
84
            return;
×
UNCOV
85
        }
×
86

87
        // Make text
88
        // binding required as "spans" is a reference and otherwise would not live long enough
89
        let payload = self
×
90
            .props
×
91
            .get_ref(Attribute::Text)
×
92
            .and_then(|x| x.as_payload());
×
93
        let text = match payload {
×
UNCOV
94
            Some(PropPayload::Vec(lines)) => {
×
95
                let lines: Vec<RSpan> = lines
×
96
                    .iter()
×
97
                    // this will skip any "PropValue" that is not a "TextSpan", instead of panicing
98
                    .filter_map(|x| x.as_textspan())
×
UNCOV
99
                    .map(utils::borrow_clone_span)
×
100
                    .collect();
×
UNCOV
101
                Text::from(Line::from(lines))
×
102
            }
103
            _ => Text::default(),
×
104
        };
105
        // Text properties
106
        let alignment: HorizontalAlignment = self
×
107
            .props
×
UNCOV
108
            .get_or(
×
109
                Attribute::AlignmentHorizontal,
×
110
                AttrValue::AlignmentHorizontal(HorizontalAlignment::Left),
×
111
            )
112
            .unwrap_alignment_horizontal();
×
113
        render.render_widget(
×
114
            Paragraph::new(text)
×
UNCOV
115
                .alignment(alignment)
×
116
                .style(self.common.style),
×
117
            area,
×
118
        );
119
    }
×
120

121
    fn query(&self, attr: Attribute) -> Option<AttrValue> {
×
UNCOV
122
        if let Some(value) = self.common.get(attr) {
×
UNCOV
123
            return Some(value);
×
UNCOV
124
        }
×
125

UNCOV
126
        self.props.get(attr)
×
UNCOV
127
    }
×
128

129
    fn attr(&mut self, attr: Attribute, value: AttrValue) {
18✔
130
        if let Some(value) = self.common.set(attr, value) {
18✔
131
            self.props.set(attr, value);
12✔
132
        }
12✔
133
    }
18✔
134

135
    fn state(&self) -> State {
2✔
136
        State::None
2✔
137
    }
2✔
138

UNCOV
139
    fn perform(&mut self, _cmd: Cmd) -> CmdResult {
×
UNCOV
140
        CmdResult::None
×
UNCOV
141
    }
×
142
}
143

144
#[cfg(test)]
145
mod tests {
146

147
    use super::*;
148

149
    use pretty_assertions::assert_eq;
150
    use tuirealm::{props::SpanStatic, ratatui::style::Stylize};
151

152
    #[test]
153
    fn test_components_span() {
2✔
154
        let component = Span::default()
2✔
155
            .background(Color::Blue)
2✔
156
            .foreground(Color::Red)
2✔
157
            .modifiers(TextModifiers::BOLD)
2✔
158
            .alignment_horizontal(HorizontalAlignment::Center)
2✔
159
            .spans([
2✔
160
                SpanStatic::from("Press "),
2✔
161
                SpanStatic::from("<ESC>").fg(Color::Cyan).bold(),
2✔
162
                SpanStatic::from(" to quit"),
2✔
163
            ]);
2✔
164
        // Get value
1✔
165
        assert_eq!(component.state(), State::None);
2✔
166
    }
2✔
167

168
    #[test]
169
    fn various_spans_types() {
2✔
170
        // Vec
1✔
171
        let _ = Span::default().spans(vec![SpanStatic::raw("hello")]);
2✔
172
        // static array
1✔
173
        let _ = Span::default().spans([SpanStatic::raw("hello")]);
2✔
174
        // boxed array
1✔
175
        let _ = Span::default().spans(vec![SpanStatic::raw("hello")].into_boxed_slice());
2✔
176
        // already a iterator
1✔
177
        let _ = Span::default().spans(["Hello"].map(SpanStatic::raw));
2✔
178
    }
2✔
179
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc