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,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::theme::Theme;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use crossterm::{
|
use crossterm::{
|
||||||
cursor::RestorePosition,
|
cursor::RestorePosition,
|
||||||
|
@ -25,9 +26,8 @@ use ratatui::{
|
||||||
};
|
};
|
||||||
use state::AppState;
|
use state::AppState;
|
||||||
use tempdir::TempDir;
|
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)]
|
#[derive(Debug, Parser)]
|
||||||
struct Args {
|
struct Args {
|
||||||
/// Enable compatibility mode (disable icons and RGB colors)
|
/// Enable compatibility mode (disable icons and RGB colors)
|
||||||
|
@ -36,23 +36,22 @@ struct Args {
|
||||||
#[arg(long, default_value_t = false)]
|
#[arg(long, default_value_t = false)]
|
||||||
#[clap(help = "Show all available options, disregarding compatibility checks (UNSAFE)")]
|
#[clap(help = "Show all available options, disregarding compatibility checks (UNSAFE)")]
|
||||||
override_validation: bool,
|
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<()> {
|
fn main() -> std::io::Result<()> {
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
|
|
||||||
let theme = if args.compat {
|
|
||||||
THEMES[0].clone()
|
|
||||||
} else {
|
|
||||||
THEMES[1].clone()
|
|
||||||
};
|
|
||||||
let commands_dir = include_dir!("src/commands");
|
let commands_dir = include_dir!("src/commands");
|
||||||
let temp_dir: TempDir = TempDir::new("linutil_scripts").unwrap();
|
let temp_dir: TempDir = TempDir::new("linutil_scripts").unwrap();
|
||||||
commands_dir
|
commands_dir
|
||||||
.extract(temp_dir.path())
|
.extract(temp_dir.path())
|
||||||
.expect("Failed to extract the saved directory");
|
.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)?;
|
stdout().execute(EnterAlternateScreen)?;
|
||||||
enable_raw_mode()?;
|
enable_raw_mode()?;
|
||||||
|
|
22
src/state.rs
22
src/state.rs
|
@ -71,7 +71,7 @@ impl AppState {
|
||||||
let longest_tab_display_len = self
|
let longest_tab_display_len = self
|
||||||
.tabs
|
.tabs
|
||||||
.iter()
|
.iter()
|
||||||
.map(|tab| tab.name.len() + self.theme.tab_icon.len())
|
.map(|tab| tab.name.len() + self.theme.tab_icon().len())
|
||||||
.max()
|
.max()
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
|
|
||||||
|
@ -94,15 +94,15 @@ impl AppState {
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let tab_hl_style = if let Focus::TabList = self.focus {
|
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 {
|
} else {
|
||||||
Style::new().fg(self.theme.tab_color)
|
Style::new().fg(self.theme.tab_color())
|
||||||
};
|
};
|
||||||
|
|
||||||
let list = List::new(tabs)
|
let list = List::new(tabs)
|
||||||
.block(Block::default().borders(Borders::ALL))
|
.block(Block::default().borders(Borders::ALL))
|
||||||
.highlight_style(tab_hl_style)
|
.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);
|
frame.render_stateful_widget(list, left_chunks[1], &mut self.current_tab);
|
||||||
|
|
||||||
let chunks = Layout::default()
|
let chunks = Layout::default()
|
||||||
|
@ -128,7 +128,7 @@ impl AppState {
|
||||||
let mut items: Vec<Line> = Vec::new();
|
let mut items: Vec<Line> = Vec::new();
|
||||||
if !self.at_root() {
|
if !self.at_root() {
|
||||||
items.push(
|
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, ..
|
node, has_children, ..
|
||||||
}| {
|
}| {
|
||||||
if *has_children {
|
if *has_children {
|
||||||
Line::from(format!("{} {}", self.theme.dir_icon, node.name))
|
Line::from(format!("{} {}", self.theme.dir_icon(), node.name))
|
||||||
.style(self.theme.dir_color)
|
.style(self.theme.dir_color())
|
||||||
} else {
|
} else {
|
||||||
Line::from(format!("{} {}", self.theme.cmd_icon, node.name))
|
Line::from(format!("{} {}", self.theme.cmd_icon(), node.name))
|
||||||
.style(self.theme.cmd_color)
|
.style(self.theme.cmd_color())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
@ -202,6 +202,8 @@ impl AppState {
|
||||||
self.refresh_tab();
|
self.refresh_tab();
|
||||||
}
|
}
|
||||||
KeyCode::Char('/') => self.enter_search(),
|
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 {
|
Focus::List if key.kind != KeyEventKind::Release => match key.code {
|
||||||
|
@ -218,6 +220,8 @@ impl AppState {
|
||||||
}
|
}
|
||||||
KeyCode::Char('/') => self.enter_search(),
|
KeyCode::Char('/') => self.enter_search(),
|
||||||
KeyCode::Tab => self.focus = Focus::TabList,
|
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;
|
use ratatui::style::Color;
|
||||||
|
|
||||||
#[derive(Clone)]
|
// Add the Theme name here for a new theme
|
||||||
pub struct Theme {
|
// This is more secure than the previous list
|
||||||
pub dir_color: Color,
|
// We cannot index out of bounds, and we are giving
|
||||||
pub cmd_color: Color,
|
// names to our various themes, making it very clear
|
||||||
pub tab_color: Color,
|
// This will make it easy to add new themes
|
||||||
pub dir_icon: &'static str,
|
#[derive(Clone, Debug, PartialEq, Default, ValueEnum, Copy)]
|
||||||
pub cmd_icon: &'static str,
|
pub enum Theme {
|
||||||
pub tab_icon: &'static str,
|
#[default]
|
||||||
pub success_color: Color,
|
Default,
|
||||||
pub fail_color: Color,
|
Compatible,
|
||||||
pub focused_color: Color,
|
|
||||||
pub unfocused_color: Color,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const THEMES: [Theme; 2] = [
|
impl Theme {
|
||||||
Theme {
|
pub fn dir_color(&self) -> Color {
|
||||||
dir_color: Color::Blue,
|
match self {
|
||||||
cmd_color: Color::LightGreen,
|
Theme::Default => Color::Blue,
|
||||||
tab_color: Color::Yellow,
|
Theme::Compatible => Color::Blue,
|
||||||
dir_icon: "[DIR]",
|
}
|
||||||
cmd_icon: "[CMD]",
|
}
|
||||||
tab_icon: ">> ",
|
|
||||||
success_color: Color::Green,
|
pub fn cmd_color(&self) -> Color {
|
||||||
fail_color: Color::Red,
|
match self {
|
||||||
focused_color: Color::LightBlue,
|
Theme::Default => Color::Rgb(204, 224, 208),
|
||||||
unfocused_color: Color::Gray,
|
Theme::Compatible => Color::LightGreen,
|
||||||
},
|
}
|
||||||
Theme {
|
}
|
||||||
dir_color: Color::Blue,
|
|
||||||
cmd_color: Color::Rgb(204, 224, 208),
|
pub fn tab_color(&self) -> Color {
|
||||||
tab_color: Color::Rgb(255, 255, 85),
|
match self {
|
||||||
dir_icon: " ",
|
Theme::Default => Color::Rgb(255, 255, 85),
|
||||||
cmd_icon: " ",
|
Theme::Compatible => Color::Yellow,
|
||||||
tab_icon: " ",
|
}
|
||||||
fail_color: Color::Rgb(199, 55, 44),
|
}
|
||||||
success_color: Color::Rgb(5, 255, 55),
|
|
||||||
focused_color: Color::LightBlue,
|
pub fn dir_icon(&self) -> &'static str {
|
||||||
unfocused_color: Color::Gray,
|
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