From 0c765a608b997c32e0a6a3112bb70b685db047a1 Mon Sep 17 00:00:00 2001 From: Lucas Colombo Date: Fri, 20 Sep 2024 19:55:23 -0300 Subject: [PATCH] =?UTF-8?q?refactor:=20=F0=9F=94=A8=20fix=20linting=20issu?= =?UTF-8?q?es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/widget_text_area.rs | 77 +++++++++++++++++++ lib/cli/tui/framework/component.rs | 1 + .../tui/widgets/textarea/behaviour/cursor.rs | 2 +- .../tui/widgets/textarea/behaviour/input.rs | 50 +++++------- .../tui/widgets/textarea/behaviour/scroll.rs | 2 +- .../tui/widgets/textarea/behaviour/util.rs | 2 +- .../textarea/{textarea => core}/builder.rs | 0 .../textarea/{textarea => core}/getset.rs | 0 .../textarea/{textarea => core}/mod.rs | 2 - .../{textarea => core}/validation/mod.rs | 4 +- .../validation/validators.rs | 2 +- .../textarea/{textarea => core}/widget.rs | 0 lib/cli/tui/widgets/textarea/mod.rs | 4 +- 13 files changed, 108 insertions(+), 38 deletions(-) create mode 100644 examples/widget_text_area.rs rename lib/cli/tui/widgets/textarea/{textarea => core}/builder.rs (100%) rename lib/cli/tui/widgets/textarea/{textarea => core}/getset.rs (100%) rename lib/cli/tui/widgets/textarea/{textarea => core}/mod.rs (99%) rename lib/cli/tui/widgets/textarea/{textarea => core}/validation/mod.rs (91%) rename lib/cli/tui/widgets/textarea/{textarea => core}/validation/validators.rs (68%) rename lib/cli/tui/widgets/textarea/{textarea => core}/widget.rs (100%) diff --git a/examples/widget_text_area.rs b/examples/widget_text_area.rs new file mode 100644 index 0000000..5371833 --- /dev/null +++ b/examples/widget_text_area.rs @@ -0,0 +1,77 @@ +use { + lool::tui::{ + ratatui::{ + backend::CrosstermBackend, + crossterm::{ + event::{self}, + execute, + terminal::{ + disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen, + }, + }, + layout::{Constraint, Direction, Layout}, + Terminal, + }, + widgets::textarea::{Input, Key, TextArea}, + }, + ratatui::widgets::{Block, BorderType, Borders, Padding, Paragraph}, + std::{cmp, io}, +}; + +fn main() -> io::Result<()> { + let stdout = io::stdout(); + let mut stdout = stdout.lock(); + + enable_raw_mode()?; + execute!(stdout, EnterAlternateScreen)?; + let backend = CrosstermBackend::new(stdout); + let mut term = Terminal::new(backend)?; + + let mut textarea = TextArea::default().with_block( + Block::default() + .borders(Borders::ALL) + .border_type(BorderType::Rounded) + .title(" Your name ") + .padding(Padding::horizontal(1)), + ); + + loop { + term.draw(|f| { + const MIN_HEIGHT: usize = 1; + let height = cmp::max(textarea.lines().len(), MIN_HEIGHT) as u16 + 2; + let layout = Layout::default() + .direction(Direction::Vertical) + .constraints([Constraint::Length(height), Constraint::Min(1)]) + .split(f.area()); + + // Render the textarea + f.render_widget(&textarea, layout[0]); + f.render_widget(Paragraph::new("Press to exit"), layout[1]); + })?; + match event::read()?.into() { + Input { key: Key::Esc, .. } + | Input { + key: Key::Char('c'), + shift: false, + ctrl: true, + alt: false, + } + | Input { + key: Key::Enter, + ctrl: false, + shift: false, + alt: false, + } => break, + input => { + textarea.input(input); + } + } + } + + disable_raw_mode()?; + execute!(term.backend_mut(), LeaveAlternateScreen)?; + term.show_cursor()?; + + println!("Lines: {:?}", textarea.lines()); + Ok(()) +} diff --git a/lib/cli/tui/framework/component.rs b/lib/cli/tui/framework/component.rs index 0305629..0ba3e41 100644 --- a/lib/cli/tui/framework/component.rs +++ b/lib/cli/tui/framework/component.rs @@ -261,6 +261,7 @@ pub trait Component: Downcast { /// /// # Returns /// * `Option<&Box>` - A reference to the child component or none. + #[allow(clippy::borrowed_box)] fn child(&mut self, name: &str) -> Option<&Box> { if let Some(children) = self.get_children() { children.get(name) diff --git a/lib/cli/tui/widgets/textarea/behaviour/cursor.rs b/lib/cli/tui/widgets/textarea/behaviour/cursor.rs index 156be0f..afd7935 100644 --- a/lib/cli/tui/widgets/textarea/behaviour/cursor.rs +++ b/lib/cli/tui/widgets/textarea/behaviour/cursor.rs @@ -1,6 +1,6 @@ use { super::util::{find_word_start_backward, find_word_start_forward}, - crate::tui::widgets::textarea::textarea::widget::Viewport, + crate::tui::widgets::textarea::core::widget::Viewport, std::cmp, }; diff --git a/lib/cli/tui/widgets/textarea/behaviour/input.rs b/lib/cli/tui/widgets/textarea/behaviour/input.rs index bfeb91b..4bc44ab 100644 --- a/lib/cli/tui/widgets/textarea/behaviour/input.rs +++ b/lib/cli/tui/widgets/textarea/behaviour/input.rs @@ -3,7 +3,7 @@ use crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers}; /// Backend-agnostic key input kind. /// /// This type is marked as `#[non_exhaustive]` since more keys may be supported in the future. -#[derive(Clone, Copy, Debug, PartialEq, Hash, Eq)] +#[derive(Clone, Copy, Debug, PartialEq, Hash, Eq, Default)] pub enum Key { /// Normal letter key input Char(char), @@ -38,15 +38,10 @@ pub enum Key { /// Paste key. This key is supported by termwiz only Paste, /// An invalid key input (this key is always ignored by [`TextArea`](crate::TextArea)) + #[default] Null, } -impl Default for Key { - fn default() -> Self { - Key::Null - } -} - /// Backend-agnostic key input type. /// /// When `crossterm`, `termion`, `termwiz` features are enabled, converting respective key input types into this @@ -104,7 +99,7 @@ impl Input { ctrl: false, alt: false, .. - } => Some(c.clone()), + } => Some(*c), _ => None, } } @@ -117,30 +112,27 @@ impl Input { /// - Char is \n or \r #[inline] pub fn is_newline_except_enter(&self) -> bool { - match self { + matches!( + self, Input { key: Key::Char('\n' | '\r'), ctrl: false, alt: false, .. - } - | Input { + } | Input { key: Key::Enter, ctrl: true, .. - } - | Input { + } | Input { key: Key::Enter, alt: true, .. - } - | Input { + } | Input { key: Key::Enter, shift: true, .. - } => true, - _ => false, - } + } + ) } /// Returns `true` if the Input represents a new line (including Enter key). @@ -170,67 +162,67 @@ impl Input { /// Returns `true` if the Input is a Tab #[inline] pub fn is_tab(&self) -> bool { - return self.key == Key::Tab && !self.ctrl && !self.alt; + self.key == Key::Tab && !self.ctrl && !self.alt } /// Returns `true` if the Input is Backspace #[inline] pub fn is_backspace(&self) -> bool { - return self.key == Key::Backspace && !self.ctrl && !self.alt; + self.key == Key::Backspace && !self.ctrl && !self.alt } /// Returns `true` if the Input is Delete #[inline] pub fn is_delete(&self) -> bool { - return self.key == Key::Delete && !self.ctrl && !self.alt; + self.key == Key::Delete && !self.ctrl && !self.alt } /// Returns `true` if the Input is key down arrow #[inline] pub fn is_down(&self) -> bool { - return self.key == Key::Down && !self.ctrl && !self.alt; + self.key == Key::Down && !self.ctrl && !self.alt } /// Returns `true` if the Input is key up arrow #[inline] pub fn is_up(&self) -> bool { - return self.key == Key::Up && !self.ctrl && !self.alt; + self.key == Key::Up && !self.ctrl && !self.alt } /// Returns `true` if the Input is key left arrow #[inline] pub fn is_left(&self) -> bool { - return self.key == Key::Left && !self.ctrl && !self.alt; + self.key == Key::Left && !self.ctrl && !self.alt } /// Returns `true` if the Input is key right arrow #[inline] pub fn is_right(&self) -> bool { - return self.key == Key::Right && !self.ctrl && !self.alt; + self.key == Key::Right && !self.ctrl && !self.alt } /// Returns `true` if the Input is key Home #[inline] pub fn is_home(&self) -> bool { - return self.key == Key::Home; + self.key == Key::Home } /// Returns `true` if the Input is key End #[inline] pub fn is_end(&self) -> bool { - return self.key == Key::End; + self.key == Key::End } /// Returns `true` if the Input is ctrl+left #[inline] pub fn is_ctrl_left(&self) -> bool { - return self.key == Key::Left && self.ctrl && !self.alt; + self.key == Key::Left && self.ctrl && !self.alt } /// Returns `true` if the Input is ctrl+right #[inline] pub fn is_ctrl_right(&self) -> bool { - return self.key == Key::Right && self.ctrl && !self.alt; + self.key == Key::Right && self.ctrl && !self.alt } /// Returns a string representing the kind of key input. diff --git a/lib/cli/tui/widgets/textarea/behaviour/scroll.rs b/lib/cli/tui/widgets/textarea/behaviour/scroll.rs index a134fcb..3dd4fff 100644 --- a/lib/cli/tui/widgets/textarea/behaviour/scroll.rs +++ b/lib/cli/tui/widgets/textarea/behaviour/scroll.rs @@ -1,4 +1,4 @@ -use crate::tui::widgets::textarea::textarea::widget::Viewport; +use crate::tui::widgets::textarea::core::widget::Viewport; /// Specify how to scroll the textarea. /// diff --git a/lib/cli/tui/widgets/textarea/behaviour/util.rs b/lib/cli/tui/widgets/textarea/behaviour/util.rs index 3ab143a..ffcdebc 100644 --- a/lib/cli/tui/widgets/textarea/behaviour/util.rs +++ b/lib/cli/tui/widgets/textarea/behaviour/util.rs @@ -59,5 +59,5 @@ pub fn find_word_start_backward(line: &str, start_col: usize) -> Option { } cur = next; } - (cur != CharKind::Space).then(|| 0) + (cur != CharKind::Space).then_some(0) } diff --git a/lib/cli/tui/widgets/textarea/textarea/builder.rs b/lib/cli/tui/widgets/textarea/core/builder.rs similarity index 100% rename from lib/cli/tui/widgets/textarea/textarea/builder.rs rename to lib/cli/tui/widgets/textarea/core/builder.rs diff --git a/lib/cli/tui/widgets/textarea/textarea/getset.rs b/lib/cli/tui/widgets/textarea/core/getset.rs similarity index 100% rename from lib/cli/tui/widgets/textarea/textarea/getset.rs rename to lib/cli/tui/widgets/textarea/core/getset.rs diff --git a/lib/cli/tui/widgets/textarea/textarea/mod.rs b/lib/cli/tui/widgets/textarea/core/mod.rs similarity index 99% rename from lib/cli/tui/widgets/textarea/textarea/mod.rs rename to lib/cli/tui/widgets/textarea/core/mod.rs index 95c8a2b..7b1dc10 100644 --- a/lib/cli/tui/widgets/textarea/textarea/mod.rs +++ b/lib/cli/tui/widgets/textarea/core/mod.rs @@ -512,5 +512,3 @@ impl<'a> TextArea<'a> { hl.into_spans() } } - -// Builder-Pattern methods diff --git a/lib/cli/tui/widgets/textarea/textarea/validation/mod.rs b/lib/cli/tui/widgets/textarea/core/validation/mod.rs similarity index 91% rename from lib/cli/tui/widgets/textarea/textarea/validation/mod.rs rename to lib/cli/tui/widgets/textarea/core/validation/mod.rs index 6884dcb..87ae5d1 100644 --- a/lib/cli/tui/widgets/textarea/textarea/validation/mod.rs +++ b/lib/cli/tui/widgets/textarea/core/validation/mod.rs @@ -7,8 +7,10 @@ pub enum ValidationResult { Invalid(Vec), } +type ValidatorFnType = Arc Result<(), String> + Send + Sync>; + #[derive(Clone)] -pub struct ValidatorFn(Arc Result<(), String> + Send + Sync>); +pub struct ValidatorFn(ValidatorFnType); impl ValidatorFn { pub fn new(f: F) -> Self diff --git a/lib/cli/tui/widgets/textarea/textarea/validation/validators.rs b/lib/cli/tui/widgets/textarea/core/validation/validators.rs similarity index 68% rename from lib/cli/tui/widgets/textarea/textarea/validation/validators.rs rename to lib/cli/tui/widgets/textarea/core/validation/validators.rs index 8065537..d29b9f1 100644 --- a/lib/cli/tui/widgets/textarea/textarea/validation/validators.rs +++ b/lib/cli/tui/widgets/textarea/core/validation/validators.rs @@ -1,6 +1,6 @@ pub fn required_validator(input: &str) -> Result<(), String> { if input.is_empty() { - Err(format!("This field is required")) + Err("This field is required".to_string()) } else { Ok(()) } diff --git a/lib/cli/tui/widgets/textarea/textarea/widget.rs b/lib/cli/tui/widgets/textarea/core/widget.rs similarity index 100% rename from lib/cli/tui/widgets/textarea/textarea/widget.rs rename to lib/cli/tui/widgets/textarea/core/widget.rs diff --git a/lib/cli/tui/widgets/textarea/mod.rs b/lib/cli/tui/widgets/textarea/mod.rs index faad2c7..8aaa199 100644 --- a/lib/cli/tui/widgets/textarea/mod.rs +++ b/lib/cli/tui/widgets/textarea/mod.rs @@ -6,11 +6,11 @@ pub(super) mod behaviour { pub(super) mod util; } -mod textarea; +mod core; pub use { behaviour::input::{Input, Key}, - textarea::{ + core::{ validation::{validators, ValidationResult}, TextArea, },