diff options
| author | Vladislav Stepanov <8uk.8ak@gmail.com> | 2023-04-14 23:18:58 +0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-04-14 20:18:58 +0100 |
| commit | c05d2850420a2c163b8f62c33a6cef7c0ae1ad8d (patch) | |
| tree | 2c44a44eda7e76fa74e78ac1fd02f55c1ed4d804 /src/ratatui/widgets/paragraph.rs | |
| parent | Switch to uuidv7 (#864) (diff) | |
| download | atuin-c05d2850420a2c163b8f62c33a6cef7c0ae1ad8d.zip | |
Workspace reorder (#868)
* Try different workspace structure
Move main crate (atuin) to be on the same level with other crates in
this workspace
* extract common dependencies to the workspace definition
* fix base64 v0.21 deprecation warning
* questionable: update deps & fix chrono deprecations
possible panic sites are unchanged, they're just more visible now
* Revert "questionable: update deps & fix chrono deprecations"
This reverts commit 993e60f8dea81a1625a04285a617959ad09a0866.
Diffstat (limited to 'src/ratatui/widgets/paragraph.rs')
| -rw-r--r-- | src/ratatui/widgets/paragraph.rs | 214 |
1 files changed, 0 insertions, 214 deletions
diff --git a/src/ratatui/widgets/paragraph.rs b/src/ratatui/widgets/paragraph.rs deleted file mode 100644 index 5edfe08e..00000000 --- a/src/ratatui/widgets/paragraph.rs +++ /dev/null @@ -1,214 +0,0 @@ -use crate::ratatui::{ - buffer::Buffer, - layout::{Alignment, Rect}, - style::Style, - text::{StyledGrapheme, Text}, - widgets::{ - reflow::{LineComposer, LineTruncator, WordWrapper}, - Block, Widget, - }, -}; -use std::iter; -use unicode_width::UnicodeWidthStr; - -fn get_line_offset(line_width: u16, text_area_width: u16, alignment: Alignment) -> u16 { - match alignment { - Alignment::Center => (text_area_width / 2).saturating_sub(line_width / 2), - Alignment::Right => text_area_width.saturating_sub(line_width), - Alignment::Left => 0, - } -} - -/// A widget to display some text. -/// -/// # Examples -/// -/// ``` -/// # use ratatui::text::{Text, Spans, Span}; -/// # use ratatui::widgets::{Block, Borders, Paragraph, Wrap}; -/// # use ratatui::style::{Style, Color, Modifier}; -/// # use ratatui::layout::{Alignment}; -/// let text = vec![ -/// Spans::from(vec![ -/// Span::raw("First"), -/// Span::styled("line",Style::default().add_modifier(Modifier::ITALIC)), -/// Span::raw("."), -/// ]), -/// Spans::from(Span::styled("Second line", Style::default().fg(Color::Red))), -/// ]; -/// Paragraph::new(text) -/// .block(Block::default().title("Paragraph").borders(Borders::ALL)) -/// .style(Style::default().fg(Color::White).bg(Color::Black)) -/// .alignment(Alignment::Center) -/// .wrap(Wrap { trim: true }); -/// ``` -#[derive(Debug, Clone)] -pub struct Paragraph<'a> { - /// A block to wrap the widget in - block: Option<Block<'a>>, - /// Widget style - style: Style, - /// How to wrap the text - wrap: Option<Wrap>, - /// The text to display - text: Text<'a>, - /// Scroll - scroll: (u16, u16), - /// Alignment of the text - alignment: Alignment, -} - -/// Describes how to wrap text across lines. -/// -/// ## Examples -/// -/// ``` -/// # use ratatui::widgets::{Paragraph, Wrap}; -/// # use ratatui::text::Text; -/// let bullet_points = Text::from(r#"Some indented points: -/// - First thing goes here and is long so that it wraps -/// - Here is another point that is long enough to wrap"#); -/// -/// // With leading spaces trimmed (window width of 30 chars): -/// Paragraph::new(bullet_points.clone()).wrap(Wrap { trim: true }); -/// // Some indented points: -/// // - First thing goes here and is -/// // long so that it wraps -/// // - Here is another point that -/// // is long enough to wrap -/// -/// // But without trimming, indentation is preserved: -/// Paragraph::new(bullet_points).wrap(Wrap { trim: false }); -/// // Some indented points: -/// // - First thing goes here -/// // and is long so that it wraps -/// // - Here is another point -/// // that is long enough to wrap -/// ``` -#[derive(Debug, Clone, Copy)] -pub struct Wrap { - /// Should leading whitespace be trimmed - pub trim: bool, -} - -impl<'a> Paragraph<'a> { - pub fn new<T>(text: T) -> Paragraph<'a> - where - T: Into<Text<'a>>, - { - Paragraph { - block: None, - style: Default::default(), - wrap: None, - text: text.into(), - scroll: (0, 0), - alignment: Alignment::Left, - } - } - - pub fn block(mut self, block: Block<'a>) -> Paragraph<'a> { - self.block = Some(block); - self - } - - pub fn style(mut self, style: Style) -> Paragraph<'a> { - self.style = style; - self - } - - pub fn wrap(mut self, wrap: Wrap) -> Paragraph<'a> { - self.wrap = Some(wrap); - self - } - - pub fn scroll(mut self, offset: (u16, u16)) -> Paragraph<'a> { - self.scroll = offset; - self - } - - pub fn alignment(mut self, alignment: Alignment) -> Paragraph<'a> { - self.alignment = alignment; - self - } -} - -impl<'a> Widget for Paragraph<'a> { - fn render(mut self, area: Rect, buf: &mut Buffer) { - buf.set_style(area, self.style); - let text_area = match self.block.take() { - Some(b) => { - let inner_area = b.inner(area); - b.render(area, buf); - inner_area - } - None => area, - }; - - if text_area.height < 1 { - return; - } - - let style = self.style; - let mut styled = self.text.lines.iter().flat_map(|spans| { - spans - .0 - .iter() - .flat_map(|span| span.styled_graphemes(style)) - // Required given the way composers work but might be refactored out if we change - // composers to operate on lines instead of a stream of graphemes. - .chain(iter::once(StyledGrapheme { - symbol: "\n", - style: self.style, - })) - }); - - let mut line_composer: Box<dyn LineComposer> = if let Some(Wrap { trim }) = self.wrap { - Box::new(WordWrapper::new(&mut styled, text_area.width, trim)) - } else { - let mut line_composer = Box::new(LineTruncator::new(&mut styled, text_area.width)); - if let Alignment::Left = self.alignment { - line_composer.set_horizontal_offset(self.scroll.1); - } - line_composer - }; - let mut y = 0; - while let Some((current_line, current_line_width)) = line_composer.next_line() { - if y >= self.scroll.0 { - let mut x = get_line_offset(current_line_width, text_area.width, self.alignment); - for StyledGrapheme { symbol, style } in current_line { - let width = symbol.width(); - if width == 0 { - continue; - } - buf.get_mut(text_area.left() + x, text_area.top() + y - self.scroll.0) - .set_symbol(if symbol.is_empty() { - // If the symbol is empty, the last char which rendered last time will - // leave on the line. It's a quick fix. - " " - } else { - symbol - }) - .set_style(*style); - x += width as u16; - } - } - y += 1; - if y >= text_area.height + self.scroll.0 { - break; - } - } - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn zero_width_char_at_end_of_line() { - let line = "foo\0"; - let paragraph = Paragraph::new(line); - let mut buf = Buffer::with_lines(vec![line]); - paragraph.render(*buf.area(), &mut buf); - } -} |
