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

veeso / tui-realm-stdlib / 13283044543

12 Feb 2025 10:16AM UTC coverage: 68.235% (-0.1%) from 68.377%
13283044543

push

github

web-flow
Remove some more clones / allocations (#30)

* style(table): use "row_highlight_style" instead of "highlight_style"

to avoid deprecation warning

* deps(tuirealm): update to 2.1.0

* refactor(components::span::Span::view): use "as_text_span" instead of manual impl

re 913b08075
Also changed behavior to not panic, and instead skip any values that are not "TextSpan"s

* refactor(components::span::Span::view): avoid further clones when getting text

* refactor(components::paragraph::Paragraph::view): avoid clones when getting text

* refactor(components::label::Label::view): avoid clones when getting text

* refactor(components::list::List::view): avoid clones when getting text

* style(components::phantom): fix reference to "Spinner"

* refactor(components::radio::Radio::view): avoid clones when getting choices

* refactor(components::select::Select::view): avoid clones when getting choices

* refactor(components::table::Table::view): avoid clones when getting rows

* refactor(components::table::Table::view): avoid clones when getting headers

also remove "Table::headers" as it is only ever written to and never actually read. (compared to a scoped-variable)

* refactor(components::table::Table::view): avoid clones when getting highlight symbol

also remove "Table::hg_str" as it is only ever written to and never actually read. (compared to a scoped-variable)

* refactor(components::textarea::Textarea::view): avoid clones when getting highlight symbol

also remove "Textarea::hg_str" as it is only ever written to and never actually read. (compared to a scoped-variable)

* refactor(components::textarea::Textarea::view): avoid clones when getting text

0 of 82 new or added lines in 8 files covered. (0.0%)

1 existing line in 1 file now uncovered.

3278 of 4804 relevant lines covered (68.23%)

1.63 hits per line

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

46.39
/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
    Alignment, AttrValue, Attribute, Color, PropPayload, PropValue, Props, Style, TextModifiers,
9
    TextSpan,
10
};
11
use tuirealm::ratatui::text::Line;
12
use tuirealm::ratatui::{
13
    layout::Rect,
14
    text::{Span as TuiSpan, Text},
15
    widgets::Paragraph,
16
};
17
use tuirealm::{Frame, MockComponent, State};
18

19
// -- Component
20

21
/// ## Span
22
///
23
/// represents a read-only text component without any container, but with multy-style text parts
24
#[derive(Default)]
25
pub struct Span {
26
    props: Props,
27
}
28

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

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

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

45
    pub fn alignment(mut self, a: Alignment) -> Self {
1✔
46
        self.attr(Attribute::Alignment, AttrValue::Alignment(a));
1✔
47
        self
1✔
48
    }
1✔
49

50
    pub fn spans(mut self, s: &[TextSpan]) -> Self {
1✔
51
        self.attr(
1✔
52
            Attribute::Text,
1✔
53
            AttrValue::Payload(PropPayload::Vec(
1✔
54
                s.iter().cloned().map(PropValue::TextSpan).collect(),
1✔
55
            )),
1✔
56
        );
1✔
57
        self
1✔
58
    }
1✔
59
}
60

61
impl MockComponent for Span {
62
    fn view(&mut self, render: &mut Frame, area: Rect) {
×
63
        // Make a Span
×
64
        if self.props.get_or(Attribute::Display, AttrValue::Flag(true)) == AttrValue::Flag(true) {
×
65
            // Make text
66
            let foreground = self
×
67
                .props
×
68
                .get_or(Attribute::Foreground, AttrValue::Color(Color::Reset))
×
69
                .unwrap_color();
×
70
            let background = self
×
71
                .props
×
72
                .get_or(Attribute::Background, AttrValue::Color(Color::Reset))
×
73
                .unwrap_color();
×
74
            // binding required as "spans" is a reference and otherwise would not live long enough
×
NEW
75
            let payload = self
×
NEW
76
                .props
×
NEW
77
                .get_ref(Attribute::Text)
×
NEW
78
                .and_then(|x| x.as_payload());
×
79
            let spans: Vec<TuiSpan> = match payload {
×
80
                Some(PropPayload::Vec(ref spans)) => spans
×
81
                    .iter()
×
NEW
82
                    // this will skip any "PropValue" that is not a "TextSpan", instead of panicing
×
NEW
83
                    .flat_map(|x| x.as_text_span())
×
84
                    .map(|x| {
×
85
                        // Keep colors and modifiers, or use default
×
86
                        let (fg, bg, modifiers) =
×
87
                            crate::utils::use_or_default_styles(&self.props, x);
×
88
                        TuiSpan::styled(
×
89
                            &x.content,
×
90
                            Style::default().add_modifier(modifiers).fg(fg).bg(bg),
×
91
                        )
×
92
                    })
×
93
                    .collect(),
×
94
                _ => Vec::new(),
×
95
            };
96
            let text: Text = Text::from(Line::from(spans));
×
97
            // Text properties
×
98
            let alignment: Alignment = self
×
99
                .props
×
100
                .get_or(Attribute::Alignment, AttrValue::Alignment(Alignment::Left))
×
101
                .unwrap_alignment();
×
102
            render.render_widget(
×
103
                Paragraph::new(text)
×
104
                    .alignment(alignment)
×
105
                    .style(Style::default().bg(background).fg(foreground)),
×
106
                area,
×
107
            );
×
108
        }
×
109
    }
×
110

111
    fn query(&self, attr: Attribute) -> Option<AttrValue> {
×
112
        self.props.get(attr)
×
113
    }
×
114

115
    fn attr(&mut self, attr: Attribute, value: AttrValue) {
5✔
116
        self.props.set(attr, value)
5✔
117
    }
5✔
118

119
    fn state(&self) -> State {
1✔
120
        State::None
1✔
121
    }
1✔
122

123
    fn perform(&mut self, _cmd: Cmd) -> CmdResult {
×
124
        CmdResult::None
×
125
    }
×
126
}
127

128
#[cfg(test)]
129
mod tests {
130

131
    use super::*;
132

133
    use pretty_assertions::assert_eq;
134

135
    #[test]
136
    fn test_components_span() {
1✔
137
        let component = Span::default()
1✔
138
            .background(Color::Blue)
1✔
139
            .foreground(Color::Red)
1✔
140
            .modifiers(TextModifiers::BOLD)
1✔
141
            .alignment(Alignment::Center)
1✔
142
            .spans(&[
1✔
143
                TextSpan::from("Press "),
1✔
144
                TextSpan::from("<ESC>").fg(Color::Cyan).bold(),
1✔
145
                TextSpan::from(" to quit"),
1✔
146
            ]);
1✔
147
        // Get value
1✔
148
        assert_eq!(component.state(), State::None);
1✔
149
    }
1✔
150
}
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