diff --git a/core/src/config.rs b/core/src/config.rs index d4f5e5c5..cf040758 100644 --- a/core/src/config.rs +++ b/core/src/config.rs @@ -1,6 +1,5 @@ use serde::Deserialize; -use std::path::Path; -use std::process; +use std::{path::Path, process}; #[derive(Deserialize)] pub struct Config { diff --git a/core/src/inner.rs b/core/src/inner.rs index 9d2e7162..0fadae80 100644 --- a/core/src/inner.rs +++ b/core/src/inner.rs @@ -1,3 +1,7 @@ +use crate::{Command, ListNode, Tab}; +use ego_tree::{NodeMut, Tree}; +use include_dir::{include_dir, Dir}; +use serde::Deserialize; use std::{ fs::File, io::{BufRead, BufReader, Read}, @@ -6,11 +10,6 @@ use std::{ path::{Path, PathBuf}, rc::Rc, }; - -use crate::{Command, ListNode, Tab}; -use ego_tree::{NodeMut, Tree}; -use include_dir::{include_dir, Dir}; -use serde::Deserialize; use temp_dir::TempDir; const TAB_DATA: Dir = include_dir!("$CARGO_MANIFEST_DIR/tabs"); diff --git a/tui/src/confirmation.rs b/tui/src/confirmation.rs index f9ae42ad..3a4e9578 100644 --- a/tui/src/confirmation.rs +++ b/tui/src/confirmation.rs @@ -3,7 +3,8 @@ use ratatui::{ crossterm::event::{KeyCode, KeyEvent, MouseEvent, MouseEventKind}, layout::Alignment, prelude::*, - widgets::{Block, Borders, Clear, List}, + symbols::border, + widgets::{Block, Clear, List}, }; use std::borrow::Cow; @@ -22,10 +23,17 @@ pub struct ConfirmPrompt { impl ConfirmPrompt { pub fn new(names: &[&str]) -> Self { + let max_count_str = format!("{}", names.len()); let names = names .iter() .zip(1..) - .map(|(name, n)| format!(" {n}. {name}")) + .map(|(name, n)| { + let count_str = format!("{n}"); + let space_str = (0..(max_count_str.len() - count_str.len())) + .map(|_| ' ') + .collect::(); + format!("{space_str}{n}. {name}") + }) .collect(); Self { @@ -51,17 +59,15 @@ impl ConfirmPrompt { impl FloatContent for ConfirmPrompt { fn draw(&mut self, frame: &mut Frame, area: Rect, theme: &theme::Theme) { - let block = Block::default() - .borders(Borders::ALL) - .border_set(ratatui::symbols::border::ROUNDED) + let block = Block::bordered() + .border_set(border::ROUNDED) .title(" Confirm selections ") .title_bottom(Line::from(vec![ - Span::styled(" [", Style::default()), + Span::raw(" ["), Span::styled("y", Style::default().fg(theme.success_color())), - Span::styled("] to continue ", Style::default()), - Span::styled("[", Style::default()), + Span::raw("] to continue ["), Span::styled("n", Style::default().fg(theme.fail_color())), - Span::styled("] to abort ", Style::default()), + Span::raw("] to abort "), ])) .title_alignment(Alignment::Center) .title_style(Style::default().bold()) diff --git a/tui/src/filter.rs b/tui/src/filter.rs index bc62bfa7..734db164 100644 --- a/tui/src/filter.rs +++ b/tui/src/filter.rs @@ -2,11 +2,9 @@ use crate::{state::ListEntry, theme::Theme}; use linutil_core::{ego_tree::NodeId, Tab}; use ratatui::{ crossterm::event::{KeyCode, KeyEvent, KeyModifiers}, - layout::{Position, Rect}, - style::Style, - text::Span, - widgets::{Block, Borders, Paragraph}, - Frame, + prelude::*, + symbols::border, + widgets::{Block, Paragraph}, }; use unicode_width::UnicodeWidthChar; @@ -118,9 +116,8 @@ impl Filter { //Create the search bar widget let search_bar = Paragraph::new(display_text) .block( - Block::default() - .borders(Borders::ALL) - .border_set(ratatui::symbols::border::ROUNDED) + Block::bordered() + .border_set(border::ROUNDED) .title(" Search "), ) .style(Style::default().fg(search_color)); diff --git a/tui/src/float.rs b/tui/src/float.rs index d9c8d6de..9f29bff3 100644 --- a/tui/src/float.rs +++ b/tui/src/float.rs @@ -1,7 +1,7 @@ use crate::{hint::Shortcut, theme::Theme}; use ratatui::{ crossterm::event::{KeyCode, KeyEvent, MouseEvent}, - layout::{Constraint, Direction, Layout, Rect}, + layout::{Constraint, Layout, Rect}, Frame, }; @@ -29,23 +29,19 @@ impl Float { } fn floating_window(&self, size: Rect) -> Rect { - let hor_float = Layout::default() - .constraints([ - Constraint::Percentage((100 - self.width_percent) / 2), - Constraint::Percentage(self.width_percent), - Constraint::Percentage((100 - self.width_percent) / 2), - ]) - .direction(Direction::Horizontal) - .split(size)[1]; + let hor_float = Layout::horizontal([ + Constraint::Percentage((100 - self.width_percent) / 2), + Constraint::Percentage(self.width_percent), + Constraint::Percentage((100 - self.width_percent) / 2), + ]) + .split(size)[1]; - Layout::default() - .constraints([ - Constraint::Percentage((100 - self.height_percent) / 2), - Constraint::Percentage(self.height_percent), - Constraint::Percentage((100 - self.height_percent) / 2), - ]) - .direction(Direction::Vertical) - .split(hor_float)[1] + Layout::vertical([ + Constraint::Percentage((100 - self.height_percent) / 2), + Constraint::Percentage(self.height_percent), + Constraint::Percentage((100 - self.height_percent) / 2), + ]) + .split(hor_float)[1] } pub fn draw(&mut self, frame: &mut Frame, parent_area: Rect, theme: &Theme) { diff --git a/tui/src/floating_text.rs b/tui/src/floating_text.rs index 18074ddb..c2077de5 100644 --- a/tui/src/floating_text.rs +++ b/tui/src/floating_text.rs @@ -2,11 +2,9 @@ use crate::{float::FloatContent, hint::Shortcut, theme::Theme}; use linutil_core::Command; use ratatui::{ crossterm::event::{KeyCode, KeyEvent, MouseEvent, MouseEventKind}, - layout::Rect, - style::{Color, Style, Stylize}, - text::{Line, Span, Text}, + prelude::*, + symbols::border, widgets::{Block, Borders, Clear, Paragraph, Wrap}, - Frame, }; use tree_sitter_bash as hl_bash; use tree_sitter_highlight::{self as hl, HighlightEvent}; @@ -177,9 +175,9 @@ impl<'a> FloatContent for FloatingText<'a> { fn draw(&mut self, frame: &mut Frame, area: Rect, _theme: &Theme) { let block = Block::default() .borders(Borders::ALL) - .border_set(ratatui::symbols::border::ROUNDED) + .border_set(border::ROUNDED) .title(self.mode_title.as_str()) - .title_alignment(ratatui::layout::Alignment::Center) + .title_alignment(Alignment::Center) .title_style(Style::default().reversed()) .style(Style::default()); diff --git a/tui/src/hint.rs b/tui/src/hint.rs index 2ab4b99d..0f77f7a5 100644 --- a/tui/src/hint.rs +++ b/tui/src/hint.rs @@ -5,8 +5,8 @@ use ratatui::{ use std::borrow::Cow; pub struct Shortcut { - pub key_sequences: Vec>, - pub desc: &'static str, + key_sequences: Vec>, + desc: &'static str, } fn add_spacing(list: Vec>) -> Line { @@ -18,7 +18,7 @@ fn add_spacing(list: Vec>) -> Line { .collect() } -pub fn span_vec_len(span_vec: &[Span]) -> usize { +fn span_vec_len(span_vec: &[Span]) -> usize { span_vec.iter().rfold(0, |init, s| init + s.width()) } @@ -38,7 +38,7 @@ pub fn create_shortcut_list( let columns = (render_width as usize / (max_shortcut_width + 4)).max(1); let rows = (shortcut_spans.len() + columns - 1) / columns; - let mut lines: Vec> = Vec::new(); + let mut lines: Vec> = Vec::with_capacity(rows); for row in 0..rows { let row_spans: Vec<_> = (0..columns) @@ -73,13 +73,7 @@ impl Shortcut { let description = Span::styled(self.desc, Style::default().italic()); self.key_sequences .iter() - .flat_map(|seq| { - [ - Span::default().content("["), - seq.clone(), - Span::default().content("] "), - ] - }) + .flat_map(|seq| [Span::raw("["), seq.clone(), Span::raw("] ")]) .chain(std::iter::once(description)) .collect() } diff --git a/tui/src/main.rs b/tui/src/main.rs index 1f03fc1b..ee0c3235 100644 --- a/tui/src/main.rs +++ b/tui/src/main.rs @@ -25,7 +25,7 @@ use ratatui::{ }; use state::AppState; use std::{ - io::{self, stdout}, + io::{stdout, Result, Stdout}, path::PathBuf, time::Duration, }; @@ -53,7 +53,7 @@ pub struct Args { size_bypass: bool, } -fn main() -> io::Result<()> { +fn main() -> Result<()> { let args = Args::parse(); let mut state = AppState::new(args); @@ -77,10 +77,7 @@ fn main() -> io::Result<()> { Ok(()) } -fn run( - terminal: &mut Terminal>, - state: &mut AppState, -) -> io::Result<()> { +fn run(terminal: &mut Terminal>, state: &mut AppState) -> Result<()> { loop { terminal.draw(|frame| state.draw(frame)).unwrap(); // Wait for an event diff --git a/tui/src/running_command.rs b/tui/src/running_command.rs index 9a9ea7a9..a3248c95 100644 --- a/tui/src/running_command.rs +++ b/tui/src/running_command.rs @@ -6,14 +6,13 @@ use portable_pty::{ }; use ratatui::{ crossterm::event::{KeyCode, KeyEvent, KeyModifiers, MouseEvent, MouseEventKind}, - layout::{Rect, Size}, - style::{Style, Stylize}, - text::Line, - widgets::{Block, Borders}, - Frame, + prelude::*, + symbols::border, + widgets::Block, }; use std::{ - io::Write, + fs::File, + io::{Result, Write}, sync::{Arc, Mutex}, thread::JoinHandle, }; @@ -47,9 +46,8 @@ impl FloatContent for RunningCommand { // Define the block for the terminal display let block = if !self.is_finished() { // Display a block indicating the command is running - Block::default() - .borders(Borders::ALL) - .border_set(ratatui::symbols::border::ROUNDED) + Block::bordered() + .border_set(border::ROUNDED) .title_top(Line::from("Running the command....").centered()) .title_style(Style::default().reversed()) .title_bottom(Line::from("Press Ctrl-C to KILL the command")) @@ -68,16 +66,15 @@ impl FloatContent for RunningCommand { }; let log_path = if let Some(log_path) = &self.log_path { - Line::from(format!(" Log saved: {} ", log_path)).centered() + Line::from(format!(" Log saved: {} ", log_path)) } else { - Line::from(" Press 'l' to save command log ").centered() + Line::from(" Press 'l' to save command log ") }; - Block::default() - .borders(Borders::ALL) - .border_set(ratatui::symbols::border::ROUNDED) + Block::bordered() + .border_set(border::ROUNDED) .title_top(title_line.centered()) - .title_bottom(log_path) + .title_bottom(log_path.centered()) }; // Calculate the inner size of the terminal area, considering borders @@ -300,7 +297,7 @@ impl RunningCommand { } } - fn save_log(&self) -> std::io::Result { + fn save_log(&self) -> Result { let mut log_path = std::env::temp_dir(); let date_format = format_description!("[year]-[month]-[day]-[hour]-[minute]-[second]"); log_path.push(format!( @@ -311,7 +308,7 @@ impl RunningCommand { .unwrap() )); - let mut file = std::fs::File::create(&log_path)?; + let mut file = File::create(&log_path)?; let buffer = self.buffer.lock().unwrap(); file.write_all(&buffer)?; diff --git a/tui/src/state.rs b/tui/src/state.rs index c80eb763..af29b5f0 100644 --- a/tui/src/state.rs +++ b/tui/src/state.rs @@ -12,12 +12,10 @@ use crate::{ use linutil_core::{ego_tree::NodeId, Command, Config, ListNode, TabList}; use ratatui::{ crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyModifiers, MouseEvent, MouseEventKind}, - layout::{Alignment, Constraint, Direction, Flex, Layout, Position, Rect}, - style::{Style, Stylize}, + layout::Flex, + prelude::*, symbols::border, - text::{Line, Span, Text}, widgets::{Block, List, ListState, Paragraph}, - Frame, }; use std::rc::Rc; @@ -242,6 +240,8 @@ impl AppState { Shortcut::new("Previous theme", ["T"]), Shortcut::new("Next tab", ["Tab"]), Shortcut::new("Previous tab", ["Shift-Tab"]), + Shortcut::new("Important actions guide", ["g"]), + Shortcut::new("Multi-selection mode", ["v"]), ]), ), diff --git a/tui/src/theme.rs b/tui/src/theme.rs index 9e10ce70..f09c6b53 100644 --- a/tui/src/theme.rs +++ b/tui/src/theme.rs @@ -14,91 +14,91 @@ pub enum Theme { } impl Theme { - pub fn dir_color(&self) -> Color { + pub const fn dir_color(&self) -> Color { match self { Theme::Default => Color::Blue, Theme::Compatible => Color::Blue, } } - pub fn cmd_color(&self) -> Color { + pub const fn cmd_color(&self) -> Color { match self { Theme::Default => Color::Rgb(204, 224, 208), Theme::Compatible => Color::LightGreen, } } - pub fn multi_select_disabled_color(&self) -> Color { + pub const fn multi_select_disabled_color(&self) -> Color { match self { Theme::Default => Color::DarkGray, Theme::Compatible => Color::DarkGray, } } - pub fn tab_color(&self) -> Color { + pub const fn tab_color(&self) -> Color { match self { Theme::Default => Color::Rgb(255, 255, 85), Theme::Compatible => Color::Yellow, } } - pub fn dir_icon(&self) -> &'static str { + pub const fn dir_icon(&self) -> &'static str { match self { Theme::Default => "  ", Theme::Compatible => "[DIR]", } } - pub fn cmd_icon(&self) -> &'static str { + pub const fn cmd_icon(&self) -> &'static str { match self { Theme::Default => "  ", Theme::Compatible => "[CMD]", } } - pub fn tab_icon(&self) -> &'static str { + pub const fn tab_icon(&self) -> &'static str { match self { Theme::Default => " ", Theme::Compatible => ">> ", } } - pub fn multi_select_icon(&self) -> &'static str { + pub const fn multi_select_icon(&self) -> &'static str { match self { Theme::Default => "", Theme::Compatible => "*", } } - pub fn success_color(&self) -> Color { + pub const fn success_color(&self) -> Color { match self { Theme::Default => Color::Rgb(5, 255, 55), Theme::Compatible => Color::Green, } } - pub fn fail_color(&self) -> Color { + pub const fn fail_color(&self) -> Color { match self { Theme::Default => Color::Rgb(199, 55, 44), Theme::Compatible => Color::Red, } } - pub fn focused_color(&self) -> Color { + pub const fn focused_color(&self) -> Color { match self { Theme::Default => Color::LightBlue, Theme::Compatible => Color::LightBlue, } } - pub fn search_preview_color(&self) -> Color { + pub const fn search_preview_color(&self) -> Color { match self { Theme::Default => Color::DarkGray, Theme::Compatible => Color::DarkGray, } } - pub fn unfocused_color(&self) -> Color { + pub const fn unfocused_color(&self) -> Color { match self { Theme::Default => Color::Gray, Theme::Compatible => Color::Gray, diff --git a/tui/src/tips.rs b/tui/src/tips.rs index 046b5cb6..17341c79 100644 --- a/tui/src/tips.rs +++ b/tui/src/tips.rs @@ -8,7 +8,6 @@ pub fn get_random_tip() -> &'static str { return ""; } - let mut rng = rand::thread_rng(); - let random_index = rng.gen_range(0..tips.len()); + let random_index = rand::thread_rng().gen_range(0..tips.len()); tips[random_index] }