refactor: 🔨 fix linting issues
This commit is contained in:
parent
97457af448
commit
0c765a608b
77
examples/widget_text_area.rs
Normal file
77
examples/widget_text_area.rs
Normal file
@ -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 <Esc> 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(())
|
||||||
|
}
|
||||||
@ -261,6 +261,7 @@ pub trait Component: Downcast {
|
|||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// * `Option<&Box<dyn Component>>` - A reference to the child component or none.
|
/// * `Option<&Box<dyn Component>>` - A reference to the child component or none.
|
||||||
|
#[allow(clippy::borrowed_box)]
|
||||||
fn child(&mut self, name: &str) -> Option<&Box<dyn Component>> {
|
fn child(&mut self, name: &str) -> Option<&Box<dyn Component>> {
|
||||||
if let Some(children) = self.get_children() {
|
if let Some(children) = self.get_children() {
|
||||||
children.get(name)
|
children.get(name)
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use {
|
use {
|
||||||
super::util::{find_word_start_backward, find_word_start_forward},
|
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,
|
std::cmp,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@ use crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers};
|
|||||||
/// Backend-agnostic key input kind.
|
/// Backend-agnostic key input kind.
|
||||||
///
|
///
|
||||||
/// This type is marked as `#[non_exhaustive]` since more keys may be supported in the future.
|
/// 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 {
|
pub enum Key {
|
||||||
/// Normal letter key input
|
/// Normal letter key input
|
||||||
Char(char),
|
Char(char),
|
||||||
@ -38,15 +38,10 @@ pub enum Key {
|
|||||||
/// Paste key. This key is supported by termwiz only
|
/// Paste key. This key is supported by termwiz only
|
||||||
Paste,
|
Paste,
|
||||||
/// An invalid key input (this key is always ignored by [`TextArea`](crate::TextArea))
|
/// An invalid key input (this key is always ignored by [`TextArea`](crate::TextArea))
|
||||||
|
#[default]
|
||||||
Null,
|
Null,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Key {
|
|
||||||
fn default() -> Self {
|
|
||||||
Key::Null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Backend-agnostic key input type.
|
/// Backend-agnostic key input type.
|
||||||
///
|
///
|
||||||
/// When `crossterm`, `termion`, `termwiz` features are enabled, converting respective key input types into this
|
/// When `crossterm`, `termion`, `termwiz` features are enabled, converting respective key input types into this
|
||||||
@ -104,7 +99,7 @@ impl Input {
|
|||||||
ctrl: false,
|
ctrl: false,
|
||||||
alt: false,
|
alt: false,
|
||||||
..
|
..
|
||||||
} => Some(c.clone()),
|
} => Some(*c),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -117,30 +112,27 @@ impl Input {
|
|||||||
/// - Char is \n or \r
|
/// - Char is \n or \r
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_newline_except_enter(&self) -> bool {
|
pub fn is_newline_except_enter(&self) -> bool {
|
||||||
match self {
|
matches!(
|
||||||
|
self,
|
||||||
Input {
|
Input {
|
||||||
key: Key::Char('\n' | '\r'),
|
key: Key::Char('\n' | '\r'),
|
||||||
ctrl: false,
|
ctrl: false,
|
||||||
alt: false,
|
alt: false,
|
||||||
..
|
..
|
||||||
}
|
} | Input {
|
||||||
| Input {
|
|
||||||
key: Key::Enter,
|
key: Key::Enter,
|
||||||
ctrl: true,
|
ctrl: true,
|
||||||
..
|
..
|
||||||
}
|
} | Input {
|
||||||
| Input {
|
|
||||||
key: Key::Enter,
|
key: Key::Enter,
|
||||||
alt: true,
|
alt: true,
|
||||||
..
|
..
|
||||||
}
|
} | Input {
|
||||||
| Input {
|
|
||||||
key: Key::Enter,
|
key: Key::Enter,
|
||||||
shift: true,
|
shift: true,
|
||||||
..
|
..
|
||||||
} => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the Input represents a new line (including Enter key).
|
/// 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
|
/// Returns `true` if the Input is a Tab
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_tab(&self) -> bool {
|
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
|
/// Returns `true` if the Input is Backspace
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_backspace(&self) -> bool {
|
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
|
/// Returns `true` if the Input is Delete
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_delete(&self) -> bool {
|
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
|
/// Returns `true` if the Input is key down arrow
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_down(&self) -> bool {
|
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
|
/// Returns `true` if the Input is key up arrow
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_up(&self) -> bool {
|
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
|
/// Returns `true` if the Input is key left arrow
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_left(&self) -> bool {
|
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
|
/// Returns `true` if the Input is key right arrow
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_right(&self) -> bool {
|
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
|
/// Returns `true` if the Input is key Home
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_home(&self) -> bool {
|
pub fn is_home(&self) -> bool {
|
||||||
return self.key == Key::Home;
|
self.key == Key::Home
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the Input is key End
|
/// Returns `true` if the Input is key End
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_end(&self) -> bool {
|
pub fn is_end(&self) -> bool {
|
||||||
return self.key == Key::End;
|
self.key == Key::End
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the Input is ctrl+left
|
/// Returns `true` if the Input is ctrl+left
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_ctrl_left(&self) -> bool {
|
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
|
/// Returns `true` if the Input is ctrl+right
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_ctrl_right(&self) -> bool {
|
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.
|
/// Returns a string representing the kind of key input.
|
||||||
|
|||||||
@ -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.
|
/// Specify how to scroll the textarea.
|
||||||
///
|
///
|
||||||
|
|||||||
@ -59,5 +59,5 @@ pub fn find_word_start_backward(line: &str, start_col: usize) -> Option<usize> {
|
|||||||
}
|
}
|
||||||
cur = next;
|
cur = next;
|
||||||
}
|
}
|
||||||
(cur != CharKind::Space).then(|| 0)
|
(cur != CharKind::Space).then_some(0)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -512,5 +512,3 @@ impl<'a> TextArea<'a> {
|
|||||||
hl.into_spans()
|
hl.into_spans()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Builder-Pattern methods
|
|
||||||
@ -7,8 +7,10 @@ pub enum ValidationResult {
|
|||||||
Invalid(Vec<String>),
|
Invalid(Vec<String>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ValidatorFnType = Arc<dyn Fn(&str) -> Result<(), String> + Send + Sync>;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ValidatorFn(Arc<dyn Fn(&str) -> Result<(), String> + Send + Sync>);
|
pub struct ValidatorFn(ValidatorFnType);
|
||||||
|
|
||||||
impl ValidatorFn {
|
impl ValidatorFn {
|
||||||
pub fn new<F>(f: F) -> Self
|
pub fn new<F>(f: F) -> Self
|
||||||
@ -1,6 +1,6 @@
|
|||||||
pub fn required_validator(input: &str) -> Result<(), String> {
|
pub fn required_validator(input: &str) -> Result<(), String> {
|
||||||
if input.is_empty() {
|
if input.is_empty() {
|
||||||
Err(format!("This field is required"))
|
Err("This field is required".to_string())
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -6,11 +6,11 @@ pub(super) mod behaviour {
|
|||||||
pub(super) mod util;
|
pub(super) mod util;
|
||||||
}
|
}
|
||||||
|
|
||||||
mod textarea;
|
mod core;
|
||||||
|
|
||||||
pub use {
|
pub use {
|
||||||
behaviour::input::{Input, Key},
|
behaviour::input::{Input, Key},
|
||||||
textarea::{
|
core::{
|
||||||
validation::{validators, ValidationResult},
|
validation::{validators, ValidationResult},
|
||||||
TextArea,
|
TextArea,
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user