Use prelude for ratatui imports. Use const for theme functions, add
missing hints
This commit is contained in:
Jeevitha Kannan K S 2024-11-13 02:11:58 +05:30
parent 79aae9eb24
commit 06f13dc5f9
No known key found for this signature in database
GPG Key ID: 5904C34A2F7CE333
12 changed files with 82 additions and 100 deletions

View File

@ -1,6 +1,5 @@
use serde::Deserialize; use serde::Deserialize;
use std::path::Path; use std::{path::Path, process};
use std::process;
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct Config { pub struct Config {

View File

@ -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::{ use std::{
fs::File, fs::File,
io::{BufRead, BufReader, Read}, io::{BufRead, BufReader, Read},
@ -6,11 +10,6 @@ use std::{
path::{Path, PathBuf}, path::{Path, PathBuf},
rc::Rc, 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; use temp_dir::TempDir;
const TAB_DATA: Dir = include_dir!("$CARGO_MANIFEST_DIR/tabs"); const TAB_DATA: Dir = include_dir!("$CARGO_MANIFEST_DIR/tabs");

View File

@ -3,7 +3,8 @@ use ratatui::{
crossterm::event::{KeyCode, KeyEvent, MouseEvent, MouseEventKind}, crossterm::event::{KeyCode, KeyEvent, MouseEvent, MouseEventKind},
layout::Alignment, layout::Alignment,
prelude::*, prelude::*,
widgets::{Block, Borders, Clear, List}, symbols::border,
widgets::{Block, Clear, List},
}; };
use std::borrow::Cow; use std::borrow::Cow;
@ -22,10 +23,17 @@ pub struct ConfirmPrompt {
impl ConfirmPrompt { impl ConfirmPrompt {
pub fn new(names: &[&str]) -> Self { pub fn new(names: &[&str]) -> Self {
let max_count_str = format!("{}", names.len());
let names = names let names = names
.iter() .iter()
.zip(1..) .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::<String>();
format!("{space_str}{n}. {name}")
})
.collect(); .collect();
Self { Self {
@ -51,17 +59,15 @@ impl ConfirmPrompt {
impl FloatContent for ConfirmPrompt { impl FloatContent for ConfirmPrompt {
fn draw(&mut self, frame: &mut Frame, area: Rect, theme: &theme::Theme) { fn draw(&mut self, frame: &mut Frame, area: Rect, theme: &theme::Theme) {
let block = Block::default() let block = Block::bordered()
.borders(Borders::ALL) .border_set(border::ROUNDED)
.border_set(ratatui::symbols::border::ROUNDED)
.title(" Confirm selections ") .title(" Confirm selections ")
.title_bottom(Line::from(vec![ .title_bottom(Line::from(vec![
Span::styled(" [", Style::default()), Span::raw(" ["),
Span::styled("y", Style::default().fg(theme.success_color())), Span::styled("y", Style::default().fg(theme.success_color())),
Span::styled("] to continue ", Style::default()), Span::raw("] to continue ["),
Span::styled("[", Style::default()),
Span::styled("n", Style::default().fg(theme.fail_color())), Span::styled("n", Style::default().fg(theme.fail_color())),
Span::styled("] to abort ", Style::default()), Span::raw("] to abort "),
])) ]))
.title_alignment(Alignment::Center) .title_alignment(Alignment::Center)
.title_style(Style::default().bold()) .title_style(Style::default().bold())

View File

@ -2,11 +2,9 @@ use crate::{state::ListEntry, theme::Theme};
use linutil_core::{ego_tree::NodeId, Tab}; use linutil_core::{ego_tree::NodeId, Tab};
use ratatui::{ use ratatui::{
crossterm::event::{KeyCode, KeyEvent, KeyModifiers}, crossterm::event::{KeyCode, KeyEvent, KeyModifiers},
layout::{Position, Rect}, prelude::*,
style::Style, symbols::border,
text::Span, widgets::{Block, Paragraph},
widgets::{Block, Borders, Paragraph},
Frame,
}; };
use unicode_width::UnicodeWidthChar; use unicode_width::UnicodeWidthChar;
@ -118,9 +116,8 @@ impl Filter {
//Create the search bar widget //Create the search bar widget
let search_bar = Paragraph::new(display_text) let search_bar = Paragraph::new(display_text)
.block( .block(
Block::default() Block::bordered()
.borders(Borders::ALL) .border_set(border::ROUNDED)
.border_set(ratatui::symbols::border::ROUNDED)
.title(" Search "), .title(" Search "),
) )
.style(Style::default().fg(search_color)); .style(Style::default().fg(search_color));

View File

@ -1,7 +1,7 @@
use crate::{hint::Shortcut, theme::Theme}; use crate::{hint::Shortcut, theme::Theme};
use ratatui::{ use ratatui::{
crossterm::event::{KeyCode, KeyEvent, MouseEvent}, crossterm::event::{KeyCode, KeyEvent, MouseEvent},
layout::{Constraint, Direction, Layout, Rect}, layout::{Constraint, Layout, Rect},
Frame, Frame,
}; };
@ -29,23 +29,19 @@ impl<Content: FloatContent + ?Sized> Float<Content> {
} }
fn floating_window(&self, size: Rect) -> Rect { fn floating_window(&self, size: Rect) -> Rect {
let hor_float = Layout::default() let hor_float = Layout::horizontal([
.constraints([ Constraint::Percentage((100 - self.width_percent) / 2),
Constraint::Percentage((100 - self.width_percent) / 2), Constraint::Percentage(self.width_percent),
Constraint::Percentage(self.width_percent), Constraint::Percentage((100 - self.width_percent) / 2),
Constraint::Percentage((100 - self.width_percent) / 2), ])
]) .split(size)[1];
.direction(Direction::Horizontal)
.split(size)[1];
Layout::default() Layout::vertical([
.constraints([ Constraint::Percentage((100 - self.height_percent) / 2),
Constraint::Percentage((100 - self.height_percent) / 2), Constraint::Percentage(self.height_percent),
Constraint::Percentage(self.height_percent), Constraint::Percentage((100 - self.height_percent) / 2),
Constraint::Percentage((100 - self.height_percent) / 2), ])
]) .split(hor_float)[1]
.direction(Direction::Vertical)
.split(hor_float)[1]
} }
pub fn draw(&mut self, frame: &mut Frame, parent_area: Rect, theme: &Theme) { pub fn draw(&mut self, frame: &mut Frame, parent_area: Rect, theme: &Theme) {

View File

@ -2,11 +2,9 @@ use crate::{float::FloatContent, hint::Shortcut, theme::Theme};
use linutil_core::Command; use linutil_core::Command;
use ratatui::{ use ratatui::{
crossterm::event::{KeyCode, KeyEvent, MouseEvent, MouseEventKind}, crossterm::event::{KeyCode, KeyEvent, MouseEvent, MouseEventKind},
layout::Rect, prelude::*,
style::{Color, Style, Stylize}, symbols::border,
text::{Line, Span, Text},
widgets::{Block, Borders, Clear, Paragraph, Wrap}, widgets::{Block, Borders, Clear, Paragraph, Wrap},
Frame,
}; };
use tree_sitter_bash as hl_bash; use tree_sitter_bash as hl_bash;
use tree_sitter_highlight::{self as hl, HighlightEvent}; 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) { fn draw(&mut self, frame: &mut Frame, area: Rect, _theme: &Theme) {
let block = Block::default() let block = Block::default()
.borders(Borders::ALL) .borders(Borders::ALL)
.border_set(ratatui::symbols::border::ROUNDED) .border_set(border::ROUNDED)
.title(self.mode_title.as_str()) .title(self.mode_title.as_str())
.title_alignment(ratatui::layout::Alignment::Center) .title_alignment(Alignment::Center)
.title_style(Style::default().reversed()) .title_style(Style::default().reversed())
.style(Style::default()); .style(Style::default());

View File

@ -5,8 +5,8 @@ use ratatui::{
use std::borrow::Cow; use std::borrow::Cow;
pub struct Shortcut { pub struct Shortcut {
pub key_sequences: Vec<Span<'static>>, key_sequences: Vec<Span<'static>>,
pub desc: &'static str, desc: &'static str,
} }
fn add_spacing(list: Vec<Vec<Span>>) -> Line { fn add_spacing(list: Vec<Vec<Span>>) -> Line {
@ -18,7 +18,7 @@ fn add_spacing(list: Vec<Vec<Span>>) -> Line {
.collect() .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()) 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 columns = (render_width as usize / (max_shortcut_width + 4)).max(1);
let rows = (shortcut_spans.len() + columns - 1) / columns; let rows = (shortcut_spans.len() + columns - 1) / columns;
let mut lines: Vec<Line<'static>> = Vec::new(); let mut lines: Vec<Line<'static>> = Vec::with_capacity(rows);
for row in 0..rows { for row in 0..rows {
let row_spans: Vec<_> = (0..columns) let row_spans: Vec<_> = (0..columns)
@ -73,13 +73,7 @@ impl Shortcut {
let description = Span::styled(self.desc, Style::default().italic()); let description = Span::styled(self.desc, Style::default().italic());
self.key_sequences self.key_sequences
.iter() .iter()
.flat_map(|seq| { .flat_map(|seq| [Span::raw("["), seq.clone(), Span::raw("] ")])
[
Span::default().content("["),
seq.clone(),
Span::default().content("] "),
]
})
.chain(std::iter::once(description)) .chain(std::iter::once(description))
.collect() .collect()
} }

View File

@ -25,7 +25,7 @@ use ratatui::{
}; };
use state::AppState; use state::AppState;
use std::{ use std::{
io::{self, stdout}, io::{stdout, Result, Stdout},
path::PathBuf, path::PathBuf,
time::Duration, time::Duration,
}; };
@ -53,7 +53,7 @@ pub struct Args {
size_bypass: bool, size_bypass: bool,
} }
fn main() -> io::Result<()> { fn main() -> Result<()> {
let args = Args::parse(); let args = Args::parse();
let mut state = AppState::new(args); let mut state = AppState::new(args);
@ -77,10 +77,7 @@ fn main() -> io::Result<()> {
Ok(()) Ok(())
} }
fn run( fn run(terminal: &mut Terminal<CrosstermBackend<Stdout>>, state: &mut AppState) -> Result<()> {
terminal: &mut Terminal<CrosstermBackend<io::Stdout>>,
state: &mut AppState,
) -> io::Result<()> {
loop { loop {
terminal.draw(|frame| state.draw(frame)).unwrap(); terminal.draw(|frame| state.draw(frame)).unwrap();
// Wait for an event // Wait for an event

View File

@ -6,14 +6,13 @@ use portable_pty::{
}; };
use ratatui::{ use ratatui::{
crossterm::event::{KeyCode, KeyEvent, KeyModifiers, MouseEvent, MouseEventKind}, crossterm::event::{KeyCode, KeyEvent, KeyModifiers, MouseEvent, MouseEventKind},
layout::{Rect, Size}, prelude::*,
style::{Style, Stylize}, symbols::border,
text::Line, widgets::Block,
widgets::{Block, Borders},
Frame,
}; };
use std::{ use std::{
io::Write, fs::File,
io::{Result, Write},
sync::{Arc, Mutex}, sync::{Arc, Mutex},
thread::JoinHandle, thread::JoinHandle,
}; };
@ -47,9 +46,8 @@ impl FloatContent for RunningCommand {
// Define the block for the terminal display // Define the block for the terminal display
let block = if !self.is_finished() { let block = if !self.is_finished() {
// Display a block indicating the command is running // Display a block indicating the command is running
Block::default() Block::bordered()
.borders(Borders::ALL) .border_set(border::ROUNDED)
.border_set(ratatui::symbols::border::ROUNDED)
.title_top(Line::from("Running the command....").centered()) .title_top(Line::from("Running the command....").centered())
.title_style(Style::default().reversed()) .title_style(Style::default().reversed())
.title_bottom(Line::from("Press Ctrl-C to KILL the command")) .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 { 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 { } else {
Line::from(" Press 'l' to save command log ").centered() Line::from(" Press 'l' to save command log ")
}; };
Block::default() Block::bordered()
.borders(Borders::ALL) .border_set(border::ROUNDED)
.border_set(ratatui::symbols::border::ROUNDED)
.title_top(title_line.centered()) .title_top(title_line.centered())
.title_bottom(log_path) .title_bottom(log_path.centered())
}; };
// Calculate the inner size of the terminal area, considering borders // Calculate the inner size of the terminal area, considering borders
@ -300,7 +297,7 @@ impl RunningCommand {
} }
} }
fn save_log(&self) -> std::io::Result<String> { fn save_log(&self) -> Result<String> {
let mut log_path = std::env::temp_dir(); let mut log_path = std::env::temp_dir();
let date_format = format_description!("[year]-[month]-[day]-[hour]-[minute]-[second]"); let date_format = format_description!("[year]-[month]-[day]-[hour]-[minute]-[second]");
log_path.push(format!( log_path.push(format!(
@ -311,7 +308,7 @@ impl RunningCommand {
.unwrap() .unwrap()
)); ));
let mut file = std::fs::File::create(&log_path)?; let mut file = File::create(&log_path)?;
let buffer = self.buffer.lock().unwrap(); let buffer = self.buffer.lock().unwrap();
file.write_all(&buffer)?; file.write_all(&buffer)?;

View File

@ -12,12 +12,10 @@ use crate::{
use linutil_core::{ego_tree::NodeId, Command, Config, ListNode, TabList}; use linutil_core::{ego_tree::NodeId, Command, Config, ListNode, TabList};
use ratatui::{ use ratatui::{
crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyModifiers, MouseEvent, MouseEventKind}, crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyModifiers, MouseEvent, MouseEventKind},
layout::{Alignment, Constraint, Direction, Flex, Layout, Position, Rect}, layout::Flex,
style::{Style, Stylize}, prelude::*,
symbols::border, symbols::border,
text::{Line, Span, Text},
widgets::{Block, List, ListState, Paragraph}, widgets::{Block, List, ListState, Paragraph},
Frame,
}; };
use std::rc::Rc; use std::rc::Rc;
@ -242,6 +240,8 @@ impl AppState {
Shortcut::new("Previous theme", ["T"]), Shortcut::new("Previous theme", ["T"]),
Shortcut::new("Next tab", ["Tab"]), Shortcut::new("Next tab", ["Tab"]),
Shortcut::new("Previous tab", ["Shift-Tab"]), Shortcut::new("Previous tab", ["Shift-Tab"]),
Shortcut::new("Important actions guide", ["g"]),
Shortcut::new("Multi-selection mode", ["v"]),
]), ]),
), ),

View File

@ -14,91 +14,91 @@ pub enum Theme {
} }
impl Theme { impl Theme {
pub fn dir_color(&self) -> Color { pub const fn dir_color(&self) -> Color {
match self { match self {
Theme::Default => Color::Blue, Theme::Default => Color::Blue,
Theme::Compatible => Color::Blue, Theme::Compatible => Color::Blue,
} }
} }
pub fn cmd_color(&self) -> Color { pub const fn cmd_color(&self) -> Color {
match self { match self {
Theme::Default => Color::Rgb(204, 224, 208), Theme::Default => Color::Rgb(204, 224, 208),
Theme::Compatible => Color::LightGreen, Theme::Compatible => Color::LightGreen,
} }
} }
pub fn multi_select_disabled_color(&self) -> Color { pub const fn multi_select_disabled_color(&self) -> Color {
match self { match self {
Theme::Default => Color::DarkGray, Theme::Default => Color::DarkGray,
Theme::Compatible => Color::DarkGray, Theme::Compatible => Color::DarkGray,
} }
} }
pub fn tab_color(&self) -> Color { pub const fn tab_color(&self) -> Color {
match self { match self {
Theme::Default => Color::Rgb(255, 255, 85), Theme::Default => Color::Rgb(255, 255, 85),
Theme::Compatible => Color::Yellow, Theme::Compatible => Color::Yellow,
} }
} }
pub fn dir_icon(&self) -> &'static str { pub const fn dir_icon(&self) -> &'static str {
match self { match self {
Theme::Default => "", Theme::Default => "",
Theme::Compatible => "[DIR]", Theme::Compatible => "[DIR]",
} }
} }
pub fn cmd_icon(&self) -> &'static str { pub const fn cmd_icon(&self) -> &'static str {
match self { match self {
Theme::Default => "", Theme::Default => "",
Theme::Compatible => "[CMD]", Theme::Compatible => "[CMD]",
} }
} }
pub fn tab_icon(&self) -> &'static str { pub const fn tab_icon(&self) -> &'static str {
match self { match self {
Theme::Default => "", Theme::Default => "",
Theme::Compatible => ">> ", Theme::Compatible => ">> ",
} }
} }
pub fn multi_select_icon(&self) -> &'static str { pub const fn multi_select_icon(&self) -> &'static str {
match self { match self {
Theme::Default => "", Theme::Default => "",
Theme::Compatible => "*", Theme::Compatible => "*",
} }
} }
pub fn success_color(&self) -> Color { pub const fn success_color(&self) -> Color {
match self { match self {
Theme::Default => Color::Rgb(5, 255, 55), Theme::Default => Color::Rgb(5, 255, 55),
Theme::Compatible => Color::Green, Theme::Compatible => Color::Green,
} }
} }
pub fn fail_color(&self) -> Color { pub const fn fail_color(&self) -> Color {
match self { match self {
Theme::Default => Color::Rgb(199, 55, 44), Theme::Default => Color::Rgb(199, 55, 44),
Theme::Compatible => Color::Red, Theme::Compatible => Color::Red,
} }
} }
pub fn focused_color(&self) -> Color { pub const fn focused_color(&self) -> Color {
match self { match self {
Theme::Default => Color::LightBlue, Theme::Default => Color::LightBlue,
Theme::Compatible => Color::LightBlue, Theme::Compatible => Color::LightBlue,
} }
} }
pub fn search_preview_color(&self) -> Color { pub const fn search_preview_color(&self) -> Color {
match self { match self {
Theme::Default => Color::DarkGray, Theme::Default => Color::DarkGray,
Theme::Compatible => Color::DarkGray, Theme::Compatible => Color::DarkGray,
} }
} }
pub fn unfocused_color(&self) -> Color { pub const fn unfocused_color(&self) -> Color {
match self { match self {
Theme::Default => Color::Gray, Theme::Default => Color::Gray,
Theme::Compatible => Color::Gray, Theme::Compatible => Color::Gray,

View File

@ -8,7 +8,6 @@ pub fn get_random_tip() -> &'static str {
return ""; return "";
} }
let mut rng = rand::thread_rng(); let random_index = rand::thread_rng().gen_range(0..tips.len());
let random_index = rng.gen_range(0..tips.len());
tips[random_index] tips[random_index]
} }