mirror of
https://github.com/ChrisTitusTech/linutil.git
synced 2024-11-05 21:28:48 +00:00
Merge remote-tracking branch 'upstream/main' into simple_additions
This commit is contained in:
commit
3b87cfafdb
BIN
build/linutil
BIN
build/linutil
Binary file not shown.
Binary file not shown.
15
src/main.rs
15
src/main.rs
|
@ -10,6 +10,7 @@ use std::{
|
|||
time::Duration,
|
||||
};
|
||||
|
||||
use crate::theme::Theme;
|
||||
use clap::Parser;
|
||||
use crossterm::{
|
||||
cursor::RestorePosition,
|
||||
|
@ -25,9 +26,8 @@ use ratatui::{
|
|||
};
|
||||
use state::AppState;
|
||||
use tempdir::TempDir;
|
||||
use theme::THEMES;
|
||||
|
||||
/// This is a binary :), Chris, change this to update the documentation on -h
|
||||
// Linux utility toolbox
|
||||
#[derive(Debug, Parser)]
|
||||
struct Args {
|
||||
/// Enable compatibility mode (disable icons and RGB colors)
|
||||
|
@ -36,23 +36,22 @@ struct Args {
|
|||
#[arg(long, default_value_t = false)]
|
||||
#[clap(help = "Show all available options, disregarding compatibility checks (UNSAFE)")]
|
||||
override_validation: bool,
|
||||
#[arg(short, long, value_enum)]
|
||||
#[arg(default_value_t = Theme::Default)]
|
||||
#[arg(help = "Set the theme to use in the application")]
|
||||
theme: Theme,
|
||||
}
|
||||
|
||||
fn main() -> std::io::Result<()> {
|
||||
let args = Args::parse();
|
||||
|
||||
let theme = if args.compat {
|
||||
THEMES[0].clone()
|
||||
} else {
|
||||
THEMES[1].clone()
|
||||
};
|
||||
let commands_dir = include_dir!("src/commands");
|
||||
let temp_dir: TempDir = TempDir::new("linutil_scripts").unwrap();
|
||||
commands_dir
|
||||
.extract(temp_dir.path())
|
||||
.expect("Failed to extract the saved directory");
|
||||
|
||||
let mut state = AppState::new(theme, temp_dir.path(), args.override_validation);
|
||||
let mut state = AppState::new(args.theme, temp_dir.path(), args.override_validation);
|
||||
|
||||
stdout().execute(EnterAlternateScreen)?;
|
||||
enable_raw_mode()?;
|
||||
|
|
22
src/state.rs
22
src/state.rs
|
@ -71,7 +71,7 @@ impl AppState {
|
|||
let longest_tab_display_len = self
|
||||
.tabs
|
||||
.iter()
|
||||
.map(|tab| tab.name.len() + self.theme.tab_icon.len())
|
||||
.map(|tab| tab.name.len() + self.theme.tab_icon().len())
|
||||
.max()
|
||||
.unwrap_or(0);
|
||||
|
||||
|
@ -94,15 +94,15 @@ impl AppState {
|
|||
.collect::<Vec<_>>();
|
||||
|
||||
let tab_hl_style = if let Focus::TabList = self.focus {
|
||||
Style::default().reversed().fg(self.theme.tab_color)
|
||||
Style::default().reversed().fg(self.theme.tab_color())
|
||||
} else {
|
||||
Style::new().fg(self.theme.tab_color)
|
||||
Style::new().fg(self.theme.tab_color())
|
||||
};
|
||||
|
||||
let list = List::new(tabs)
|
||||
.block(Block::default().borders(Borders::ALL))
|
||||
.highlight_style(tab_hl_style)
|
||||
.highlight_symbol(self.theme.tab_icon);
|
||||
.highlight_symbol(self.theme.tab_icon());
|
||||
frame.render_stateful_widget(list, left_chunks[1], &mut self.current_tab);
|
||||
|
||||
let chunks = Layout::default()
|
||||
|
@ -128,7 +128,7 @@ impl AppState {
|
|||
let mut items: Vec<Line> = Vec::new();
|
||||
if !self.at_root() {
|
||||
items.push(
|
||||
Line::from(format!("{} ..", self.theme.dir_icon)).style(self.theme.dir_color),
|
||||
Line::from(format!("{} ..", self.theme.dir_icon())).style(self.theme.dir_color()),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -137,11 +137,11 @@ impl AppState {
|
|||
node, has_children, ..
|
||||
}| {
|
||||
if *has_children {
|
||||
Line::from(format!("{} {}", self.theme.dir_icon, node.name))
|
||||
.style(self.theme.dir_color)
|
||||
Line::from(format!("{} {}", self.theme.dir_icon(), node.name))
|
||||
.style(self.theme.dir_color())
|
||||
} else {
|
||||
Line::from(format!("{} {}", self.theme.cmd_icon, node.name))
|
||||
.style(self.theme.cmd_color)
|
||||
Line::from(format!("{} {}", self.theme.cmd_icon(), node.name))
|
||||
.style(self.theme.cmd_color())
|
||||
}
|
||||
},
|
||||
));
|
||||
|
@ -202,6 +202,8 @@ impl AppState {
|
|||
self.refresh_tab();
|
||||
}
|
||||
KeyCode::Char('/') => self.enter_search(),
|
||||
KeyCode::Char('t') => self.theme = self.theme.next(),
|
||||
KeyCode::Char('T') => self.theme = self.theme.prev(),
|
||||
_ => {}
|
||||
},
|
||||
Focus::List if key.kind != KeyEventKind::Release => match key.code {
|
||||
|
@ -218,6 +220,8 @@ impl AppState {
|
|||
}
|
||||
KeyCode::Char('/') => self.enter_search(),
|
||||
KeyCode::Tab => self.focus = Focus::TabList,
|
||||
KeyCode::Char('t') => self.theme = self.theme.next(),
|
||||
KeyCode::Char('T') => self.theme = self.theme.prev(),
|
||||
_ => {}
|
||||
},
|
||||
_ => {}
|
||||
|
|
136
src/theme.rs
136
src/theme.rs
|
@ -1,42 +1,102 @@
|
|||
use clap::ValueEnum;
|
||||
use ratatui::style::Color;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Theme {
|
||||
pub dir_color: Color,
|
||||
pub cmd_color: Color,
|
||||
pub tab_color: Color,
|
||||
pub dir_icon: &'static str,
|
||||
pub cmd_icon: &'static str,
|
||||
pub tab_icon: &'static str,
|
||||
pub success_color: Color,
|
||||
pub fail_color: Color,
|
||||
pub focused_color: Color,
|
||||
pub unfocused_color: Color,
|
||||
// Add the Theme name here for a new theme
|
||||
// This is more secure than the previous list
|
||||
// We cannot index out of bounds, and we are giving
|
||||
// names to our various themes, making it very clear
|
||||
// This will make it easy to add new themes
|
||||
#[derive(Clone, Debug, PartialEq, Default, ValueEnum, Copy)]
|
||||
pub enum Theme {
|
||||
#[default]
|
||||
Default,
|
||||
Compatible,
|
||||
}
|
||||
|
||||
pub const THEMES: [Theme; 2] = [
|
||||
Theme {
|
||||
dir_color: Color::Blue,
|
||||
cmd_color: Color::LightGreen,
|
||||
tab_color: Color::Yellow,
|
||||
dir_icon: "[DIR]",
|
||||
cmd_icon: "[CMD]",
|
||||
tab_icon: ">> ",
|
||||
success_color: Color::Green,
|
||||
fail_color: Color::Red,
|
||||
focused_color: Color::LightBlue,
|
||||
unfocused_color: Color::Gray,
|
||||
},
|
||||
Theme {
|
||||
dir_color: Color::Blue,
|
||||
cmd_color: Color::Rgb(204, 224, 208),
|
||||
tab_color: Color::Rgb(255, 255, 85),
|
||||
dir_icon: " ",
|
||||
cmd_icon: " ",
|
||||
tab_icon: " ",
|
||||
fail_color: Color::Rgb(199, 55, 44),
|
||||
success_color: Color::Rgb(5, 255, 55),
|
||||
focused_color: Color::LightBlue,
|
||||
unfocused_color: Color::Gray,
|
||||
},
|
||||
];
|
||||
impl Theme {
|
||||
pub fn dir_color(&self) -> Color {
|
||||
match self {
|
||||
Theme::Default => Color::Blue,
|
||||
Theme::Compatible => Color::Blue,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cmd_color(&self) -> Color {
|
||||
match self {
|
||||
Theme::Default => Color::Rgb(204, 224, 208),
|
||||
Theme::Compatible => Color::LightGreen,
|
||||
}
|
||||
}
|
||||
|
||||
pub 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 {
|
||||
match self {
|
||||
Theme::Default => " ",
|
||||
Theme::Compatible => "[DIR]",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cmd_icon(&self) -> &'static str {
|
||||
match self {
|
||||
Theme::Default => " ",
|
||||
Theme::Compatible => "[CMD]",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tab_icon(&self) -> &'static str {
|
||||
match self {
|
||||
Theme::Default => " ",
|
||||
Theme::Compatible => ">> ",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn success_color(&self) -> Color {
|
||||
match self {
|
||||
Theme::Default => Color::Rgb(199, 55, 44),
|
||||
Theme::Compatible => Color::Green,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fail_color(&self) -> Color {
|
||||
match self {
|
||||
Theme::Default => Color::Rgb(5, 255, 55),
|
||||
Theme::Compatible => Color::Red,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn focused_color(&self) -> Color {
|
||||
match self {
|
||||
Theme::Default => Color::LightBlue,
|
||||
Theme::Compatible => Color::LightBlue,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unfocused_color(&self) -> Color {
|
||||
match self {
|
||||
Theme::Default => Color::Gray,
|
||||
Theme::Compatible => Color::Gray,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Theme {
|
||||
#[allow(unused)]
|
||||
pub fn next(self) -> Self {
|
||||
let position = self as usize;
|
||||
let types = Theme::value_variants();
|
||||
types[(position + 1) % types.len()].into()
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn prev(self) -> Self {
|
||||
let position = self as usize;
|
||||
let types = Theme::value_variants();
|
||||
types[(position + types.len() - 1) % types.len()].into()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user