Added AppState, made theme use AppState

This commit is contained in:
Andrii Dokhniak 2024-07-28 17:17:06 +02:00
parent 8e8476cda5
commit bfc8e5ea82
5 changed files with 99 additions and 81 deletions

View File

@ -1,4 +1,4 @@
use crate::{float::floating_window, theme::*}; use crate::{float::floating_window, state::AppState};
use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use crossterm::event::{KeyCode, KeyEvent, KeyEventKind};
use ego_tree::{tree, NodeId}; use ego_tree::{tree, NodeId};
use ratatui::{ use ratatui::{
@ -130,9 +130,8 @@ impl CustomList {
} }
/// Draw our custom widget to the frame /// 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 // Get the last element in the `visit_stack` vec
let theme = get_theme();
let curr = self let curr = self
.inner_tree .inner_tree
.get(*self.visit_stack.last().unwrap()) .get(*self.visit_stack.last().unwrap())
@ -143,7 +142,7 @@ impl CustomList {
// to go up the tree // to go up the tree
// icons:   // icons:  
if !self.at_root() { 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 // Iterate through all the children
@ -152,13 +151,13 @@ impl CustomList {
// it's a directory and will be handled as such // it's a directory and will be handled as such
if node.has_children() { if node.has_children() {
items.push( items.push(
Line::from(format!("{} {}", theme.dir_icon, node.value().name)) Line::from(format!("{} {}", state.theme.dir_icon, node.value().name))
.style(theme.dir_color), .style(state.theme.dir_color),
); );
} else { } else {
items.push( items.push(
Line::from(format!("{} {}", theme.cmd_icon, node.value().name)) Line::from(format!("{} {}", state.theme.cmd_icon, node.value().name))
.style(theme.cmd_color), .style(state.theme.cmd_color),
); );
} }
} }

View File

@ -1,6 +1,7 @@
mod float; mod float;
mod list; mod list;
mod running_command; mod running_command;
pub mod state;
mod theme; mod theme;
use std::{ use std::{
@ -22,7 +23,8 @@ use ratatui::{
Terminal, Terminal,
}; };
use running_command::RunningCommand; 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 /// This is a binary :), Chris, change this to update the documentation on -h
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
@ -34,16 +36,23 @@ struct Args {
fn main() -> std::io::Result<()> { fn main() -> std::io::Result<()> {
let args = Args::parse(); 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)?; stdout().execute(EnterAlternateScreen)?;
enable_raw_mode()?; enable_raw_mode()?;
let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?; let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?;
terminal.clear()?; terminal.clear()?;
run(&mut terminal)?; run(&mut terminal, &state)?;
// restore terminal // restore terminal
disable_raw_mode()?; disable_raw_mode()?;
@ -55,7 +64,7 @@ fn main() -> std::io::Result<()> {
Ok(()) Ok(())
} }
fn run<B: Backend>(terminal: &mut Terminal<B>) -> io::Result<()> { fn run<B: Backend>(terminal: &mut Terminal<B>, state: &AppState) -> io::Result<()> {
let mut command_opt: Option<RunningCommand> = None; let mut command_opt: Option<RunningCommand> = None;
let mut custom_list = CustomList::new(); let mut custom_list = CustomList::new();
@ -63,9 +72,9 @@ fn run<B: Backend>(terminal: &mut Terminal<B>) -> io::Result<()> {
// Always redraw // Always redraw
terminal terminal
.draw(|frame| { .draw(|frame| {
custom_list.draw(frame, frame.size()); custom_list.draw(frame, frame.size(), state);
if let Some(ref mut command) = &mut command_opt { if let Some(ref mut command) = &mut command_opt {
command.draw(frame); command.draw(frame, state);
} }
}) })
.unwrap(); .unwrap();

View File

@ -11,7 +11,7 @@ use portable_pty::{
}; };
use ratatui::{ use ratatui::{
layout::Size, layout::Size,
style::{Color, Style, Stylize}, style::{Style, Stylize},
text::{Line, Span}, text::{Line, Span},
widgets::{Block, Borders}, widgets::{Block, Borders},
Frame, Frame,
@ -21,7 +21,14 @@ use tui_term::{
widget::PseudoTerminal, 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 /// This is a struct for storing everything connected to a running command
// Create a new instance on every new command you want to run // Create a new instance on every new command you want to run
@ -50,14 +57,22 @@ pub struct RunningCommand {
} }
impl RunningCommand { impl RunningCommand {
pub fn new(command: &str) -> Self { pub fn new(command: Command, state: &AppState) -> Self {
let pty_system = NativePtySystem::default(); let pty_system = NativePtySystem::default();
let mut cmd = CommandBuilder::new("sh");
cmd.arg("-c");
cmd.arg(command);
let cwd = std::env::current_dir().unwrap(); let mut cmd = CommandBuilder::new("sh");
cmd.cwd(cwd); 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 let pair = pty_system
.openpty(PtySize { .openpty(PtySize {
@ -153,59 +168,57 @@ impl RunningCommand {
} }
} }
pub fn draw(&mut self, frame: &mut Frame) { pub fn draw(&mut self, frame: &mut Frame, state: &AppState) {
{ // Funny name
let theme = get_theme(); let floater = floating_window(frame.size());
// Funny name
let floater = floating_window(frame.size());
let inner_size = Size { let inner_size = Size {
width: floater.width - 2, // Because we add a `Block` with a border width: floater.width - 2, // Because we add a `Block` with a border
height: floater.height - 2, height: floater.height - 2,
}; };
// When the command is running // When the command is running
let term_border = if !self.is_finished() { let term_border = if !self.is_finished() {
Block::default() Block::default()
.borders(Borders::ALL) .borders(Borders::ALL)
.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"))
} else { } else {
// This portion is just for pretty colors. // This portion is just for pretty colors.
// You can use multiple `Span`s with different styles each, to construct a line, // 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 // 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() { let mut title_line = if self.get_exit_status().success() {
Line::from( 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(
Span::default() Span::default()
.content(" press <ENTER> to close this window ") .content("SUCCESS!")
.style(Style::default()), .style(Style::default().fg(state.theme.success_color).reversed()),
); )
} else {
Block::default() Line::from(
.borders(Borders::ALL) Span::default()
.title_top(title_line.centered()) .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 title_line.push_span(
let pseudo_term = PseudoTerminal::new(&screen).block(term_border); Span::default()
frame.render_widget(pseudo_term, floater); .content(" press <ENTER> 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 /// Send SIGHUB signal, *not* SIGKILL or SIGTERM, to the child process
pub fn kill_child(&mut self) { pub fn kill_child(&mut self) {
if !self.is_finished() { if !self.is_finished() {

6
src/state.rs Normal file
View File

@ -0,0 +1,6 @@
use crate::theme::Theme;
pub struct AppState {
/// Selected theme
pub theme: Theme,
}

View File

@ -1,7 +1,6 @@
use ratatui::style::Color; use ratatui::style::Color;
pub static mut THEME_IDX: usize = 1; #[derive(Clone)]
pub struct Theme { pub struct Theme {
pub dir_color: Color, pub dir_color: Color,
pub cmd_color: Color, pub cmd_color: Color,
@ -29,11 +28,3 @@ pub const THEMES: [Theme; 2] = [
success_color: Color::Rgb(5, 255, 55), 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 };
}