From bfc8e5ea82f0ee4b3d399d2d1075045f2310423e Mon Sep 17 00:00:00 2001 From: Andrii Dokhniak Date: Sun, 28 Jul 2024 17:17:06 +0200 Subject: [PATCH] Added AppState, made theme use AppState --- src/list.rs | 15 +++-- src/main.rs | 25 ++++++--- src/running_command.rs | 123 +++++++++++++++++++++++------------------ src/state.rs | 6 ++ src/theme.rs | 11 +--- 5 files changed, 99 insertions(+), 81 deletions(-) create mode 100644 src/state.rs diff --git a/src/list.rs b/src/list.rs index b564bdea..8a193897 100644 --- a/src/list.rs +++ b/src/list.rs @@ -1,4 +1,4 @@ -use crate::{float::floating_window, theme::*}; +use crate::{float::floating_window, state::AppState}; use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use ego_tree::{tree, NodeId}; use ratatui::{ @@ -130,9 +130,8 @@ impl CustomList { } /// Draw our custom widget to the frame - pub fn draw(&mut self, frame: &mut Frame, area: Rect) { + pub fn draw(&mut self, frame: &mut Frame, area: Rect, state: &AppState) { // Get the last element in the `visit_stack` vec - let theme = get_theme(); let curr = self .inner_tree .get(*self.visit_stack.last().unwrap()) @@ -143,7 +142,7 @@ impl CustomList { // to go up the tree // icons:   if !self.at_root() { - items.push(Line::from(format!("{} ..", theme.dir_icon)).style(theme.dir_color)); + items.push(Line::from(format!("{} ..", state.theme.dir_icon)).style(state.theme.dir_color)); } // Iterate through all the children @@ -152,13 +151,13 @@ impl CustomList { // it's a directory and will be handled as such if node.has_children() { items.push( - Line::from(format!("{} {}", theme.dir_icon, node.value().name)) - .style(theme.dir_color), + Line::from(format!("{} {}", state.theme.dir_icon, node.value().name)) + .style(state.theme.dir_color), ); } else { items.push( - Line::from(format!("{} {}", theme.cmd_icon, node.value().name)) - .style(theme.cmd_color), + Line::from(format!("{} {}", state.theme.cmd_icon, node.value().name)) + .style(state.theme.cmd_color), ); } } diff --git a/src/main.rs b/src/main.rs index 7acfcfb0..0d05f95a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ mod float; mod list; mod running_command; +pub mod state; mod theme; use std::{ @@ -22,7 +23,8 @@ use ratatui::{ Terminal, }; use running_command::RunningCommand; -use theme::set_theme; +use state::AppState; +use theme::THEMES; /// This is a binary :), Chris, change this to update the documentation on -h #[derive(Debug, Parser)] @@ -34,16 +36,23 @@ struct Args { fn main() -> std::io::Result<()> { let args = Args::parse(); - if args.compat { - set_theme(0); - } + + let theme = if args.compat { + THEMES[0].clone() + } else { + THEMES[1].clone() + }; + + let state = AppState { + theme, + }; stdout().execute(EnterAlternateScreen)?; enable_raw_mode()?; let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?; terminal.clear()?; - run(&mut terminal)?; + run(&mut terminal, &state)?; // restore terminal disable_raw_mode()?; @@ -55,7 +64,7 @@ fn main() -> std::io::Result<()> { Ok(()) } -fn run(terminal: &mut Terminal) -> io::Result<()> { +fn run(terminal: &mut Terminal, state: &AppState) -> io::Result<()> { let mut command_opt: Option = None; let mut custom_list = CustomList::new(); @@ -63,9 +72,9 @@ fn run(terminal: &mut Terminal) -> io::Result<()> { // Always redraw terminal .draw(|frame| { - custom_list.draw(frame, frame.size()); + custom_list.draw(frame, frame.size(), state); if let Some(ref mut command) = &mut command_opt { - command.draw(frame); + command.draw(frame, state); } }) .unwrap(); diff --git a/src/running_command.rs b/src/running_command.rs index 9d159ef7..ad3196ae 100644 --- a/src/running_command.rs +++ b/src/running_command.rs @@ -11,7 +11,7 @@ use portable_pty::{ }; use ratatui::{ layout::Size, - style::{Color, Style, Stylize}, + style::{Style, Stylize}, text::{Line, Span}, widgets::{Block, Borders}, Frame, @@ -21,7 +21,14 @@ use tui_term::{ widget::PseudoTerminal, }; -use crate::{float::floating_window, theme::get_theme}; +use crate::{float::floating_window, state::AppState}; + +#[derive(Clone)] +pub enum Command { + Raw(&'static str), + LocalFile(&'static str), + None, // Directory +} /// This is a struct for storing everything connected to a running command // Create a new instance on every new command you want to run @@ -50,14 +57,22 @@ pub struct RunningCommand { } impl RunningCommand { - pub fn new(command: &str) -> Self { + pub fn new(command: Command, state: &AppState) -> Self { let pty_system = NativePtySystem::default(); - let mut cmd = CommandBuilder::new("sh"); - cmd.arg("-c"); - cmd.arg(command); - let cwd = std::env::current_dir().unwrap(); - cmd.cwd(cwd); + let mut cmd = CommandBuilder::new("sh"); + match command { + Command::Raw(prompt) => { + cmd.arg("-c"); + cmd.arg(prompt); + } + Command::LocalFile(file) => { + cmd.arg(file); + } + Command::None => panic!("Command::None was treated as a command"), + } + + cmd.cwd(&state.temp_path); let pair = pty_system .openpty(PtySize { @@ -153,59 +168,57 @@ impl RunningCommand { } } - pub fn draw(&mut self, frame: &mut Frame) { - { - let theme = get_theme(); - // Funny name - let floater = floating_window(frame.size()); + pub fn draw(&mut self, frame: &mut Frame, state: &AppState) { + // Funny name + let floater = floating_window(frame.size()); - let inner_size = Size { - width: floater.width - 2, // Because we add a `Block` with a border - height: floater.height - 2, - }; + let inner_size = Size { + width: floater.width - 2, // Because we add a `Block` with a border + height: floater.height - 2, + }; - // When the command is running - let term_border = if !self.is_finished() { - Block::default() - .borders(Borders::ALL) - .title_top(Line::from("Running the command....").centered()) - .title_style(Style::default().reversed()) - .title_bottom(Line::from("Press Ctrl-C to KILL the command")) - } else { - // This portion is just for pretty colors. - // You can use multiple `Span`s with different styles each, to construct a line, - // which can be used as a list item, or in this case a `Block` title + // When the command is running + let term_border = if !self.is_finished() { + Block::default() + .borders(Borders::ALL) + .title_top(Line::from("Running the command....").centered()) + .title_style(Style::default().reversed()) + .title_bottom(Line::from("Press Ctrl-C to KILL the command")) + } else { + // This portion is just for pretty colors. + // You can use multiple `Span`s with different styles each, to construct a line, + // which can be used as a list item, or in this case a `Block` title - let mut title_line = if self.get_exit_status().success() { - Line::from( - Span::default() - .content("SUCCESS!") - .style(Style::default().fg(theme.success_color).reversed()), - ) - } else { - Line::from( - Span::default() - .content("FAILED!") - .style(Style::default().fg(theme.fail_color).reversed()), - ) - }; - - title_line.push_span( + let mut title_line = if self.get_exit_status().success() { + Line::from( Span::default() - .content(" press to close this window ") - .style(Style::default()), - ); - - Block::default() - .borders(Borders::ALL) - .title_top(title_line.centered()) + .content("SUCCESS!") + .style(Style::default().fg(state.theme.success_color).reversed()), + ) + } else { + Line::from( + Span::default() + .content("FAILED!") + .style(Style::default().fg(state.theme.fail_color).reversed()), + ) }; - let screen = self.screen(inner_size); // when the terminal is changing a lot, there - // will be 1 frame of lag on resizing - let pseudo_term = PseudoTerminal::new(&screen).block(term_border); - frame.render_widget(pseudo_term, floater); - } + + title_line.push_span( + Span::default() + .content(" press to close this window ") + .style(Style::default()), + ); + + Block::default() + .borders(Borders::ALL) + .title_top(title_line.centered()) + }; + let screen = self.screen(inner_size); // when the terminal is changing a lot, there + // will be 1 frame of lag on resizing + let pseudo_term = PseudoTerminal::new(&screen).block(term_border); + frame.render_widget(pseudo_term, floater); } + /// Send SIGHUB signal, *not* SIGKILL or SIGTERM, to the child process pub fn kill_child(&mut self) { if !self.is_finished() { diff --git a/src/state.rs b/src/state.rs new file mode 100644 index 00000000..a7de1ebf --- /dev/null +++ b/src/state.rs @@ -0,0 +1,6 @@ +use crate::theme::Theme; + +pub struct AppState { + /// Selected theme + pub theme: Theme, +} diff --git a/src/theme.rs b/src/theme.rs index 71413752..4792cddc 100644 --- a/src/theme.rs +++ b/src/theme.rs @@ -1,7 +1,6 @@ use ratatui::style::Color; -pub static mut THEME_IDX: usize = 1; - +#[derive(Clone)] pub struct Theme { pub dir_color: Color, pub cmd_color: Color, @@ -29,11 +28,3 @@ pub const THEMES: [Theme; 2] = [ success_color: Color::Rgb(5, 255, 55), }, ]; - -pub fn get_theme() -> &'static Theme { - &THEMES[unsafe { THEME_IDX }] -} - -pub fn set_theme(idx: usize) { - unsafe { THEME_IDX = idx }; -}