From dfcd814389c49a791544530e2ab8b5029d2396a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Tue, 21 May 2024 04:34:36 +0900 Subject: [PATCH] tui: Constify functions, shrink Margin representation --- helix-term/src/ui/completion.rs | 4 +- helix-term/src/ui/info.rs | 7 ++- helix-term/src/ui/lsp.rs | 4 +- helix-term/src/ui/markdown.rs | 2 +- helix-term/src/ui/picker.rs | 20 ++++---- helix-term/src/ui/popup.rs | 6 +-- helix-term/src/ui/prompt.rs | 7 ++- helix-tui/src/layout.rs | 16 +++--- helix-tui/src/widgets/block.rs | 48 +++++++++--------- helix-tui/src/widgets/list.rs | 2 +- helix-tui/src/widgets/paragraph.rs | 2 +- helix-tui/tests/widgets_paragraph.rs | 10 ++-- helix-tui/tests/widgets_table.rs | 12 ++--- helix-view/src/graphics.rs | 74 +++++++++++++--------------- 14 files changed, 102 insertions(+), 112 deletions(-) diff --git a/helix-term/src/ui/completion.rs b/helix-term/src/ui/completion.rs index f793dd484..372e3e5ef 100644 --- a/helix-term/src/ui/completion.rs +++ b/helix-term/src/ui/completion.rs @@ -532,8 +532,8 @@ fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut Context) { surface.clear_with(doc_area, background); if cx.editor.popup_border() { - use tui::widgets::{Block, Borders, Widget}; - Widget::render(Block::default().borders(Borders::ALL), doc_area, surface); + use tui::widgets::{Block, Widget}; + Widget::render(Block::bordered(), doc_area, surface); } markdown_doc.render(doc_area, surface, cx); diff --git a/helix-term/src/ui/info.rs b/helix-term/src/ui/info.rs index 651e5ca93..217cee6b3 100644 --- a/helix-term/src/ui/info.rs +++ b/helix-term/src/ui/info.rs @@ -3,7 +3,7 @@ use helix_view::info::Info; use tui::buffer::Buffer as Surface; use tui::text::Text; -use tui::widgets::{Block, Borders, Paragraph, Widget}; +use tui::widgets::{Block, Paragraph, Widget}; impl Component for Info { fn render(&mut self, viewport: Rect, surface: &mut Surface, cx: &mut Context) { @@ -23,13 +23,12 @@ fn render(&mut self, viewport: Rect, surface: &mut Surface, cx: &mut Context) { )); surface.clear_with(area, popup_style); - let block = Block::default() + let block = Block::bordered() .title(self.title.as_str()) - .borders(Borders::ALL) .border_style(popup_style); let margin = Margin::horizontal(1); - let inner = block.inner(area).inner(&margin); + let inner = block.inner(area).inner(margin); block.render(area, surface); Paragraph::new(&Text::from(self.text.as_str())) diff --git a/helix-term/src/ui/lsp.rs b/helix-term/src/ui/lsp.rs index d845be4a7..b6491085b 100644 --- a/helix-term/src/ui/lsp.rs +++ b/helix-term/src/ui/lsp.rs @@ -126,7 +126,7 @@ fn render(&mut self, area: Rect, surface: &mut Buffer, cx: &mut Context) { let (_, sig_text_height) = crate::ui::text::required_size(&sig_text, area.width); let sig_text_area = area.clip_top(1).with_height(sig_text_height); - let sig_text_area = sig_text_area.inner(&margin).intersection(surface.area); + let sig_text_area = sig_text_area.inner(margin).intersection(surface.area); let sig_text_para = Paragraph::new(&sig_text).wrap(Wrap { trim: false }); sig_text_para.render(sig_text_area, surface); @@ -153,7 +153,7 @@ fn render(&mut self, area: Rect, surface: &mut Buffer, cx: &mut Context) { let sig_doc_para = Paragraph::new(&sig_doc) .wrap(Wrap { trim: false }) .scroll((cx.scroll.unwrap_or_default() as u16, 0)); - sig_doc_para.render(sig_doc_area.inner(&margin), surface); + sig_doc_para.render(sig_doc_area.inner(margin), surface); } fn required_size(&mut self, viewport: (u16, u16)) -> Option<(u16, u16)> { diff --git a/helix-term/src/ui/markdown.rs b/helix-term/src/ui/markdown.rs index 81499d039..96614443f 100644 --- a/helix-term/src/ui/markdown.rs +++ b/helix-term/src/ui/markdown.rs @@ -351,7 +351,7 @@ fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut Context) { .scroll((cx.scroll.unwrap_or_default() as u16, 0)); let margin = Margin::all(1); - par.render(area.inner(&margin), surface); + par.render(area.inner(margin), surface); } fn required_size(&mut self, viewport: (u16, u16)) -> Option<(u16, u16)> { diff --git a/helix-term/src/ui/picker.rs b/helix-term/src/ui/picker.rs index c2728888a..b8ec57d51 100644 --- a/helix-term/src/ui/picker.rs +++ b/helix-term/src/ui/picker.rs @@ -17,7 +17,7 @@ buffer::Buffer as Surface, layout::Constraint, text::{Span, Spans}, - widgets::{Block, BorderType, Borders, Cell, Table}, + widgets::{Block, BorderType, Cell, Table}, }; use tui::widgets::Widget; @@ -539,13 +539,12 @@ fn render_picker(&mut self, area: Rect, surface: &mut Surface, cx: &mut Context) let background = cx.editor.theme.get("ui.background"); surface.clear_with(area, background); - // don't like this but the lifetime sucks - let block = Block::default().borders(Borders::ALL); + const BLOCK: Block<'_> = Block::bordered(); // calculate the inner area inside the box - let inner = block.inner(area); + let inner = BLOCK.inner(area); - block.render(area, surface); + BLOCK.render(area, surface); // -- Render the input bar: @@ -690,15 +689,14 @@ fn render_preview(&mut self, area: Rect, surface: &mut Surface, cx: &mut Context let text = cx.editor.theme.get("ui.text"); surface.clear_with(area, background); - // don't like this but the lifetime sucks - let block = Block::default().borders(Borders::ALL); + const BLOCK: Block<'_> = Block::bordered(); // calculate the inner area inside the box - let inner = block.inner(area); + let inner = BLOCK.inner(area); // 1 column gap on either side let margin = Margin::horizontal(1); - let inner = inner.inner(&margin); - block.render(area, surface); + let inner = inner.inner(margin); + BLOCK.render(area, surface); if let Some((path, range)) = self.current_file(cx.editor) { let preview = self.get_preview(path, cx.editor); @@ -921,7 +919,7 @@ fn handle_event(&mut self, event: &Event, ctx: &mut Context) -> EventResult { } fn cursor(&self, area: Rect, editor: &Editor) -> (Option, CursorKind) { - let block = Block::default().borders(Borders::ALL); + let block = Block::bordered(); // calculate the inner area inside the box let inner = block.inner(area); diff --git a/helix-term/src/ui/popup.rs b/helix-term/src/ui/popup.rs index 5362bdc7f..2cefaf61b 100644 --- a/helix-term/src/ui/popup.rs +++ b/helix-term/src/ui/popup.rs @@ -5,7 +5,7 @@ }; use tui::{ buffer::Buffer as Surface, - widgets::{Block, Borders, Widget}, + widgets::{Block, Widget}, }; use helix_core::Position; @@ -323,8 +323,8 @@ fn render(&mut self, viewport: Rect, surface: &mut Surface, cx: &mut Context) { let mut inner = area; if render_borders { - inner = area.inner(&Margin::all(1)); - Widget::render(Block::default().borders(Borders::ALL), area, surface); + inner = area.inner(Margin::all(1)); + Widget::render(Block::bordered(), area, surface); } let border = usize::from(render_borders); diff --git a/helix-term/src/ui/prompt.rs b/helix-term/src/ui/prompt.rs index a6ee7f05d..3e4e8e137 100644 --- a/helix-term/src/ui/prompt.rs +++ b/helix-term/src/ui/prompt.rs @@ -7,7 +7,7 @@ use std::sync::Arc; use std::{borrow::Cow, ops::RangeFrom}; use tui::buffer::Buffer as Surface; -use tui::widgets::{Block, Borders, Widget}; +use tui::widgets::{Block, Widget}; use helix_core::{ unicode::segmentation::GraphemeCursor, unicode::width::UnicodeWidthStr, Position, @@ -457,12 +457,11 @@ pub fn render_prompt(&self, area: Rect, surface: &mut Surface, cx: &mut Context) let background = theme.get("ui.help"); surface.clear_with(area, background); - let block = Block::default() + let block = Block::bordered() // .title(self.title.as_str()) - .borders(Borders::ALL) .border_style(background); - let inner = block.inner(area).inner(&Margin::horizontal(1)); + let inner = block.inner(area).inner(Margin::horizontal(1)); block.render(area, surface); text.render(inner, surface, cx); diff --git a/helix-tui/src/layout.rs b/helix-tui/src/layout.rs index 1f3ddc6e6..50a16415f 100644 --- a/helix-tui/src/layout.rs +++ b/helix-tui/src/layout.rs @@ -83,24 +83,22 @@ pub fn constraints(mut self, constraints: C) -> Layout self } - pub fn margin(mut self, margin: u16) -> Layout { + pub const fn margin(mut self, margin: u16) -> Layout { self.margin = Margin::all(margin); self } - pub fn horizontal_margin(mut self, horizontal: u16) -> Layout { - self.margin.left = horizontal; - self.margin.right = horizontal; + pub const fn horizontal_margin(mut self, horizontal: u16) -> Layout { + self.margin.horizontal = horizontal; self } - pub fn vertical_margin(mut self, vertical: u16) -> Layout { - self.margin.top = vertical; - self.margin.bottom = vertical; + pub const fn vertical_margin(mut self, vertical: u16) -> Layout { + self.margin.vertical = vertical; self } - pub fn direction(mut self, direction: Direction) -> Layout { + pub const fn direction(mut self, direction: Direction) -> Layout { self.direction = direction; self } @@ -191,7 +189,7 @@ fn split(area: Rect, layout: &Layout) -> Vec { .map(|_| Rect::default()) .collect::>(); - let dest_area = area.inner(&layout.margin); + let dest_area = area.inner(layout.margin); for (i, e) in elements.iter().enumerate() { vars.insert(e.x, (i, 0)); vars.insert(e.y, (i, 1)); diff --git a/helix-tui/src/widgets/block.rs b/helix-tui/src/widgets/block.rs index a6fdde4c0..8b8141ea9 100644 --- a/helix-tui/src/widgets/block.rs +++ b/helix-tui/src/widgets/block.rs @@ -1,7 +1,7 @@ use crate::{ buffer::Buffer, symbols::line, - text::{Span, Spans}, + text::Spans, widgets::{Borders, Widget}, }; use helix_view::graphics::{Rect, Style}; @@ -58,6 +58,22 @@ pub struct Block<'a> { } impl<'a> Block<'a> { + pub const fn new() -> Self { + Self { + title: None, + borders: Borders::empty(), + border_style: Style::new(), + border_type: BorderType::Plain, + style: Style::new(), + } + } + + pub const fn bordered() -> Self { + let mut block = Self::new(); + block.borders = Borders::ALL; + block + } + pub fn title(mut self, title: T) -> Block<'a> where T: Into>, @@ -66,34 +82,22 @@ pub fn title(mut self, title: T) -> Block<'a> self } - #[deprecated( - since = "0.10.0", - note = "You should use styling capabilities of `text::Spans` given as argument of the `title` method to apply styling to the title." - )] - pub fn title_style(mut self, style: Style) -> Block<'a> { - if let Some(t) = self.title { - let title = String::from(&t); - self.title = Some(Spans::from(Span::styled(title, style))); - } - self - } - - pub fn border_style(mut self, style: Style) -> Block<'a> { + pub const fn border_style(mut self, style: Style) -> Block<'a> { self.border_style = style; self } - pub fn style(mut self, style: Style) -> Block<'a> { + pub const fn style(mut self, style: Style) -> Block<'a> { self.style = style; self } - pub fn borders(mut self, flag: Borders) -> Block<'a> { + pub const fn borders(mut self, flag: Borders) -> Block<'a> { self.borders = flag; self } - pub fn border_type(mut self, border_type: BorderType) -> Block<'a> { + pub const fn border_type(mut self, border_type: BorderType) -> Block<'a> { self.border_type = border_type; self } @@ -413,9 +417,7 @@ fn inner_takes_into_account_the_borders() { // All borders assert_eq!( - Block::default() - .borders(Borders::ALL) - .inner(Rect::default()), + Block::bordered().inner(Rect::default()), Rect { x: 0, y: 0, @@ -425,7 +427,7 @@ fn inner_takes_into_account_the_borders() { "all borders, width=0, height=0" ); assert_eq!( - Block::default().borders(Borders::ALL).inner(Rect { + Block::bordered().inner(Rect { x: 0, y: 0, width: 1, @@ -440,7 +442,7 @@ fn inner_takes_into_account_the_borders() { "all borders, width=1, height=1" ); assert_eq!( - Block::default().borders(Borders::ALL).inner(Rect { + Block::bordered().inner(Rect { x: 0, y: 0, width: 2, @@ -455,7 +457,7 @@ fn inner_takes_into_account_the_borders() { "all borders, width=2, height=2" ); assert_eq!( - Block::default().borders(Borders::ALL).inner(Rect { + Block::bordered().inner(Rect { x: 0, y: 0, width: 3, diff --git a/helix-tui/src/widgets/list.rs b/helix-tui/src/widgets/list.rs index e913ce788..4b0fc02f4 100644 --- a/helix-tui/src/widgets/list.rs +++ b/helix-tui/src/widgets/list.rs @@ -72,7 +72,7 @@ pub fn height(&self) -> usize { /// # use helix_tui::style::{Style, Color, Modifier}; /// let items = [ListItem::new("Item 1"), ListItem::new("Item 2"), ListItem::new("Item 3")]; /// List::new(items) -/// .block(Block::default().title("List").borders(Borders::ALL)) +/// .block(Block::bordered().title("List")) /// .style(Style::default().fg(Color::White)) /// .highlight_style(Style::default().add_modifier(Modifier::ITALIC)) /// .highlight_symbol(">>"); diff --git a/helix-tui/src/widgets/paragraph.rs b/helix-tui/src/widgets/paragraph.rs index 9c8ae127c..79beb0516 100644 --- a/helix-tui/src/widgets/paragraph.rs +++ b/helix-tui/src/widgets/paragraph.rs @@ -37,7 +37,7 @@ fn get_line_offset(line_width: u16, text_area_width: u16, alignment: Alignment) /// Spans::from(Span::styled("Second line", Style::default().fg(Color::Red))), /// ]); /// Paragraph::new(&text) -/// .block(Block::default().title("Paragraph").borders(Borders::ALL)) +/// .block(Block::bordered().title("Paragraph")) /// .style(Style::default().fg(Color::White).bg(Color::Black)) /// .alignment(Alignment::Center) /// .wrap(Wrap { trim: true }); diff --git a/helix-tui/tests/widgets_paragraph.rs b/helix-tui/tests/widgets_paragraph.rs index 3d2ac467b..dcfc6b13f 100644 --- a/helix-tui/tests/widgets_paragraph.rs +++ b/helix-tui/tests/widgets_paragraph.rs @@ -23,7 +23,7 @@ // let size = f.size(); // let text = Text::from(SAMPLE_STRING); // let paragraph = Paragraph::new(&text) -// .block(Block::default().borders(Borders::ALL)) +// .block(Block::bordered()) // .alignment(alignment) // .wrap(Wrap { trim: true }); // f.render_widget(paragraph, size); @@ -90,7 +90,7 @@ // let size = f.size(); // let text = Text::from(s); // let paragraph = Paragraph::new(&text) -// .block(Block::default().borders(Borders::ALL)) +// .block(Block::bordered()) // .wrap(Wrap { trim: true }); // f.render_widget(paragraph, size); // }) @@ -122,7 +122,7 @@ // let size = f.size(); // let text = Text::from(s); // let paragraph = Paragraph::new(&text) -// .block(Block::default().borders(Borders::ALL)) +// .block(Block::bordered()) // .wrap(Wrap { trim: true }); // f.render_widget(paragraph, size); // }) @@ -156,7 +156,7 @@ // .draw(|f| { // let size = f.size(); // let text = Text::from(line); -// let paragraph = Paragraph::new(&text).block(Block::default().borders(Borders::ALL)); +// let paragraph = Paragraph::new(&text).block(Block::bordered()); // f.render_widget(paragraph, size); // }) // .unwrap(); @@ -175,7 +175,7 @@ // "段落现在可以水平滚动了!\nParagraph can scroll horizontally!\nShort line", // ); // let paragraph = Paragraph::new(&text) -// .block(Block::default().borders(Borders::ALL)) +// .block(Block::bordered()) // .alignment(alignment) // .scroll(scroll); // f.render_widget(paragraph, size); diff --git a/helix-tui/tests/widgets_table.rs b/helix-tui/tests/widgets_table.rs index badf32745..2ec6e3ddb 100644 --- a/helix-tui/tests/widgets_table.rs +++ b/helix-tui/tests/widgets_table.rs @@ -24,7 +24,7 @@ // Row::new(vec!["Row41", "Row42", "Row43"]), // ]) // .header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1)) -// .block(Block::default().borders(Borders::ALL)) +// .block(Block::bordered()) // .widths(&[ // Constraint::Length(5), // Constraint::Length(5), @@ -122,7 +122,7 @@ // Row::new(vec!["Row41", "Row42", "Row43"]), // ]) // .header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1)) -// .block(Block::default().borders(Borders::ALL)) +// .block(Block::bordered()) // .widths(widths); // f.render_widget(table, size); // }) @@ -210,7 +210,7 @@ // Row::new(vec!["Row41", "Row42", "Row43"]), // ]) // .header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1)) -// .block(Block::default().borders(Borders::ALL)) +// .block(Block::bordered()) // .widths(widths) // .column_spacing(0); // f.render_widget(table, size); @@ -316,7 +316,7 @@ // Row::new(vec!["Row41", "Row42", "Row43"]), // ]) // .header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1)) -// .block(Block::default().borders(Borders::ALL)) +// .block(Block::bordered()) // .widths(widths); // f.render_widget(table, size); // }) @@ -425,7 +425,7 @@ // Row::new(vec!["Row41", "Row42", "Row43"]), // ]) // .header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1)) -// .block(Block::default().borders(Borders::ALL)) +// .block(Block::bordered()) // .widths(widths) // .column_spacing(0); // f.render_widget(table, size); @@ -530,7 +530,7 @@ // Row::new(vec!["Row41", "Row42", "Row43"]).height(2), // ]) // .header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1)) -// .block(Block::default().borders(Borders::ALL)) +// .block(Block::bordered()) // .highlight_symbol(">> ") // .widths(&[ // Constraint::Length(5), diff --git a/helix-view/src/graphics.rs b/helix-view/src/graphics.rs index 046db86a1..a26823b97 100644 --- a/helix-view/src/graphics.rs +++ b/helix-view/src/graphics.rs @@ -25,62 +25,52 @@ fn default() -> Self { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Margin { - pub left: u16, - pub right: u16, - pub top: u16, - pub bottom: u16, + pub horizontal: u16, + pub vertical: u16, } impl Margin { pub fn none() -> Self { Self { - left: 0, - right: 0, - top: 0, - bottom: 0, + horizontal: 0, + vertical: 0, } } /// Set uniform margin for all sides. - pub fn all(value: u16) -> Self { + pub const fn all(value: u16) -> Self { Self { - left: value, - right: value, - top: value, - bottom: value, + horizontal: value, + vertical: value, } } /// Set the margin of left and right sides to specified value. - pub fn horizontal(value: u16) -> Self { + pub const fn horizontal(value: u16) -> Self { Self { - left: value, - right: value, - top: 0, - bottom: 0, + horizontal: value, + vertical: 0, } } /// Set the margin of top and bottom sides to specified value. - pub fn vertical(value: u16) -> Self { + pub const fn vertical(value: u16) -> Self { Self { - left: 0, - right: 0, - top: value, - bottom: value, + horizontal: 0, + vertical: value, } } /// Get the total width of the margin (left + right) - pub fn width(&self) -> u16 { - self.left + self.right + pub const fn width(&self) -> u16 { + self.horizontal * 2 } /// Get the total height of the margin (top + bottom) - pub fn height(&self) -> u16 { - self.top + self.bottom + pub const fn height(&self) -> u16 { + self.vertical * 2 } } @@ -181,13 +171,13 @@ pub fn with_width(self, width: u16) -> Rect { Self::new(self.x, self.y, width, self.height) } - pub fn inner(self, margin: &Margin) -> Rect { + pub fn inner(self, margin: Margin) -> Rect { if self.width < margin.width() || self.height < margin.height() { Rect::default() } else { Rect { - x: self.x + margin.left, - y: self.y + margin.top, + x: self.x + margin.horizontal, + y: self.y + margin.vertical, width: self.width - margin.width(), height: self.height - margin.height(), } @@ -459,7 +449,13 @@ pub struct Style { } impl Default for Style { - fn default() -> Style { + fn default() -> Self { + Self::new() + } +} + +impl Style { + pub const fn new() -> Self { Style { fg: None, bg: None, @@ -469,12 +465,10 @@ fn default() -> Style { sub_modifier: Modifier::empty(), } } -} -impl Style { /// Returns a `Style` resetting all properties. - pub fn reset() -> Style { - Style { + pub const fn reset() -> Self { + Self { fg: Some(Color::Reset), bg: Some(Color::Reset), underline_color: None, @@ -494,7 +488,7 @@ pub fn reset() -> Style { /// let diff = Style::default().fg(Color::Red); /// assert_eq!(style.patch(diff), Style::default().fg(Color::Red)); /// ``` - pub fn fg(mut self, color: Color) -> Style { + pub const fn fg(mut self, color: Color) -> Style { self.fg = Some(color); self } @@ -509,7 +503,7 @@ pub fn fg(mut self, color: Color) -> Style { /// let diff = Style::default().bg(Color::Red); /// assert_eq!(style.patch(diff), Style::default().bg(Color::Red)); /// ``` - pub fn bg(mut self, color: Color) -> Style { + pub const fn bg(mut self, color: Color) -> Style { self.bg = Some(color); self } @@ -524,7 +518,7 @@ pub fn bg(mut self, color: Color) -> Style { /// let diff = Style::default().underline_color(Color::Red); /// assert_eq!(style.patch(diff), Style::default().underline_color(Color::Red)); /// ``` - pub fn underline_color(mut self, color: Color) -> Style { + pub const fn underline_color(mut self, color: Color) -> Style { self.underline_color = Some(color); self } @@ -539,7 +533,7 @@ pub fn underline_color(mut self, color: Color) -> Style { /// let diff = Style::default().underline_style(UnderlineStyle::Curl); /// assert_eq!(style.patch(diff), Style::default().underline_style(UnderlineStyle::Curl)); /// ``` - pub fn underline_style(mut self, style: UnderlineStyle) -> Style { + pub const fn underline_style(mut self, style: UnderlineStyle) -> Style { self.underline_style = Some(style); self }