edtui/view/
status_line.rs

1use ratatui_core::{
2    buffer::Buffer,
3    layout::{Alignment, Constraint, Layout, Rect},
4    style::Style,
5    text::{Line, Span},
6    widgets::Widget,
7};
8use ratatui_widgets::paragraph::Paragraph;
9
10use super::theme::{DARK_GRAY, WHITE};
11
12/// An optional status line for Editor.
13#[derive(Debug, Clone)]
14pub struct EditorStatusLine {
15    /// Displays the current editor mode in the status line.
16    mode: String,
17    /// The current search buffer. Shown only in search mode.
18    search: Option<String>,
19    /// The style for the content of the sidebar
20    style_text: Style,
21    /// The style for the line itself
22    style_line: Style,
23    // Whether to align content to the left (true) or the right (false)
24    align_left: bool,
25}
26
27impl Default for EditorStatusLine {
28    /// Creates a new instance of [`EditorStatusLine`].
29    ///
30    /// This constructor initializes with default style.
31    fn default() -> Self {
32        Self {
33            mode: String::new(),
34            search: None,
35            style_text: Style::default().fg(WHITE).bg(DARK_GRAY).bold(),
36            style_line: Style::default().fg(WHITE).bg(DARK_GRAY),
37            align_left: true,
38        }
39    }
40}
41
42impl EditorStatusLine {
43    /// Overwrite the style for the status lines content.
44    ///
45    /// This method allows you to customize the appearance of the
46    /// status lines content.
47    #[must_use]
48    pub fn style_text(mut self, style: Style) -> Self {
49        self.style_text = style;
50        self
51    }
52
53    /// Overwrite the style for the status lines.
54    ///
55    /// This method allows you to customize the appearance of the
56    /// status line.
57    #[must_use]
58    pub fn style_line(mut self, style: Style) -> Self {
59        self.style_line = style;
60        self
61    }
62
63    /// Overwrite the mode content for the status line.
64    ///
65    /// This method is used internally to dynamically set the editors mode.
66    #[must_use]
67    pub fn mode<S: Into<String>>(mut self, mode: S) -> Self {
68        self.mode = mode.into();
69        self
70    }
71
72    /// Overwrite the search content for the status line.
73    ///
74    /// This method is used internally to dynamically set the editors mode.
75    #[must_use]
76    pub fn search<S: Into<String>>(mut self, search: Option<S>) -> Self {
77        self.search = search.map(Into::into);
78        self
79    }
80
81    /// Set the alignment for the status line content.
82    ///
83    /// Set to true to align content to the left, false to align to the right.
84    #[must_use]
85    pub fn align_left(mut self, align_left: bool) -> Self {
86        self.align_left = align_left;
87        self
88    }
89}
90
91impl Widget for EditorStatusLine {
92    fn render(self, area: Rect, buf: &mut Buffer) {
93        // Split the layout horizontally.
94        let constraints = if self.align_left {
95            [Constraint::Length(10), Constraint::Min(0)]
96        } else {
97            [Constraint::Min(0), Constraint::Length(10)]
98        };
99        let [left, right] = Layout::horizontal(constraints).areas(area);
100
101        // Build the content and block widgets
102        let mode_paragraph = Paragraph::new(Line::from(Span::from(self.mode)))
103            .alignment(Alignment::Center)
104            .style(self.style_text);
105        let search_text = self.search.map_or(String::new(), |s| format!("/{s}"));
106        let search_paragraph = Paragraph::new(Line::from(Span::from(search_text)))
107            .alignment(Alignment::Left)
108            .style(self.style_line);
109
110        // Determine the alignment position
111        if self.align_left {
112            mode_paragraph.render(left, buf);
113            search_paragraph.render(right, buf);
114        } else {
115            search_paragraph.render(left, buf);
116            mode_paragraph.render(right, buf);
117        };
118    }
119}