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

veeso / tui-realm-stdlib / 22147729940

07 Feb 2026 04:09PM UTC coverage: 72.482% (-0.004%) from 72.486%
22147729940

push

github

hasezoey
feat: rename "alignment" functions to "alignment_horizontal"

6 of 6 new or added lines in 3 files covered. (100.0%)

43 existing lines in 3 files now uncovered.

3677 of 5073 relevant lines covered (72.48%)

4.16 hits per line

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

60.38
/src/components/span.rs
1
//! ## Span
2
//!
3
//! `Span` represents a read-only text component without any container, but with the possibility to define multiple text parts.
4
//! The main difference with `Label` is that the Span allows different styles inside the same component for the texsts.
5

6
use tuirealm::command::{Cmd, CmdResult};
7
use tuirealm::props::{
8
    AttrValue, Attribute, Color, HorizontalAlignment, PropPayload, PropValue, Props, SpanStatic,
9
    Style, TextModifiers,
10
};
11
use tuirealm::ratatui::{
12
    layout::Rect,
13
    text::{Line, Span as RSpan, Text},
14
    widgets::Paragraph,
15
};
16
use tuirealm::{Frame, MockComponent, State};
17

18
use crate::utils;
19

20
// -- Component
21

22
/// ## Span
23
///
24
/// Represents a read-only, single-line text component without any container, but with multi-style text parts
25
#[derive(Default)]
26
#[must_use]
27
pub struct Span {
28
    props: Props,
29
}
30

31
impl Span {
32
    pub fn foreground(mut self, fg: Color) -> Self {
2✔
33
        self.attr(Attribute::Foreground, AttrValue::Color(fg));
2✔
34
        self
2✔
35
    }
2✔
36

37
    pub fn background(mut self, bg: Color) -> Self {
2✔
38
        self.attr(Attribute::Background, AttrValue::Color(bg));
2✔
39
        self
2✔
40
    }
2✔
41

42
    pub fn modifiers(mut self, m: TextModifiers) -> Self {
2✔
43
        self.attr(Attribute::TextProps, AttrValue::TextModifiers(m));
2✔
44
        self
2✔
45
    }
2✔
46

47
    pub fn alignment_horizontal(mut self, a: HorizontalAlignment) -> Self {
2✔
48
        self.attr(
2✔
49
            Attribute::AlignmentHorizontal,
2✔
50
            AttrValue::AlignmentHorizontal(a),
2✔
51
        );
1✔
52
        self
2✔
53
    }
2✔
54

55
    pub fn spans<T>(mut self, s: impl IntoIterator<Item = T>) -> Self
10✔
56
    where
10✔
57
        T: Into<SpanStatic>,
10✔
58
    {
5✔
59
        self.attr(
10✔
60
            Attribute::Text,
10✔
61
            AttrValue::Payload(PropPayload::Vec(
10✔
62
                s.into_iter()
10✔
63
                    .map(Into::into)
10✔
64
                    .map(PropValue::TextSpan)
10✔
65
                    .collect(),
10✔
66
            )),
10✔
67
        );
5✔
68
        self
10✔
69
    }
10✔
70
}
71

72
impl MockComponent for Span {
UNCOV
73
    fn view(&mut self, render: &mut Frame, area: Rect) {
×
74
        // Make a Span
75
        if self.props.get_or(Attribute::Display, AttrValue::Flag(true)) == AttrValue::Flag(true) {
×
76
            // Make text
77
            let foreground = self
×
78
                .props
×
79
                .get_or(Attribute::Foreground, AttrValue::Color(Color::Reset))
×
80
                .unwrap_color();
×
81
            let background = self
×
UNCOV
82
                .props
×
83
                .get_or(Attribute::Background, AttrValue::Color(Color::Reset))
×
84
                .unwrap_color();
×
85
            // binding required as "spans" is a reference and otherwise would not live long enough
86
            let payload = self
×
87
                .props
×
88
                .get_ref(Attribute::Text)
×
89
                .and_then(|x| x.as_payload());
×
90
            let text = match payload {
×
UNCOV
91
                Some(PropPayload::Vec(lines)) => {
×
92
                    let lines: Vec<RSpan> = lines
×
93
                        .iter()
×
94
                        // this will skip any "PropValue" that is not a "TextSpan", instead of panicing
95
                        .filter_map(|x| x.as_textspan())
×
UNCOV
96
                        .map(utils::borrow_clone_span)
×
97
                        .collect();
×
UNCOV
98
                    Text::from(Line::from(lines))
×
99
                }
100
                _ => Text::default(),
×
101
            };
102
            // Text properties
103
            let alignment: HorizontalAlignment = self
×
104
                .props
×
105
                .get_or(
×
106
                    Attribute::AlignmentHorizontal,
×
107
                    AttrValue::AlignmentHorizontal(HorizontalAlignment::Left),
×
108
                )
UNCOV
109
                .unwrap_alignment_horizontal();
×
110
            render.render_widget(
×
111
                Paragraph::new(text)
×
UNCOV
112
                    .alignment(alignment)
×
113
                    .style(Style::default().bg(background).fg(foreground)),
×
114
                area,
×
115
            );
UNCOV
116
        }
×
UNCOV
117
    }
×
118

UNCOV
119
    fn query(&self, attr: Attribute) -> Option<AttrValue> {
×
UNCOV
120
        self.props.get(attr)
×
UNCOV
121
    }
×
122

123
    fn attr(&mut self, attr: Attribute, value: AttrValue) {
18✔
124
        self.props.set(attr, value);
18✔
125
    }
18✔
126

127
    fn state(&self) -> State {
2✔
128
        State::None
2✔
129
    }
2✔
130

UNCOV
131
    fn perform(&mut self, _cmd: Cmd) -> CmdResult {
×
UNCOV
132
        CmdResult::None
×
UNCOV
133
    }
×
134
}
135

136
#[cfg(test)]
137
mod tests {
138

139
    use super::*;
140

141
    use pretty_assertions::assert_eq;
142
    use tuirealm::{props::SpanStatic, ratatui::style::Stylize};
143

144
    #[test]
145
    fn test_components_span() {
2✔
146
        let component = Span::default()
2✔
147
            .background(Color::Blue)
2✔
148
            .foreground(Color::Red)
2✔
149
            .modifiers(TextModifiers::BOLD)
2✔
150
            .alignment_horizontal(HorizontalAlignment::Center)
2✔
151
            .spans([
2✔
152
                SpanStatic::from("Press "),
2✔
153
                SpanStatic::from("<ESC>").fg(Color::Cyan).bold(),
2✔
154
                SpanStatic::from(" to quit"),
2✔
155
            ]);
2✔
156
        // Get value
1✔
157
        assert_eq!(component.state(), State::None);
2✔
158
    }
2✔
159

160
    #[test]
161
    fn various_spans_types() {
2✔
162
        // Vec
1✔
163
        let _ = Span::default().spans(vec![SpanStatic::raw("hello")]);
2✔
164
        // static array
1✔
165
        let _ = Span::default().spans([SpanStatic::raw("hello")]);
2✔
166
        // boxed array
1✔
167
        let _ = Span::default().spans(vec![SpanStatic::raw("hello")].into_boxed_slice());
2✔
168
        // already a iterator
1✔
169
        let _ = Span::default().spans(["Hello"].map(SpanStatic::raw));
2✔
170
    }
2✔
171
}
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