mirror of
https://github.com/bobwen-dev/hunter
synced 2025-04-12 00:55:41 +02:00
252 lines
7.5 KiB
Rust
252 lines
7.5 KiB
Rust
use lazy_static;
|
|
use clap;
|
|
|
|
use std::sync::RwLock;
|
|
|
|
use crate::paths;
|
|
|
|
use crate::fail::{HError, HResult, ErrorLog};
|
|
use crate::keybind::KeyBinds;
|
|
|
|
|
|
#[derive(Clone)]
|
|
// These are options, so we know if they have been set or not
|
|
struct ArgvConfig {
|
|
animation: Option<bool>,
|
|
show_hidden: Option<bool>,
|
|
icons: Option<bool>,
|
|
graphics: Option<String>,
|
|
}
|
|
|
|
impl ArgvConfig {
|
|
fn new() -> Self {
|
|
ArgvConfig {
|
|
animation: None,
|
|
show_hidden: None,
|
|
icons: None,
|
|
graphics: None
|
|
}
|
|
}
|
|
}
|
|
|
|
lazy_static! {
|
|
static ref ARGV_CONFIG: RwLock<ArgvConfig> = RwLock::new(ArgvConfig::new());
|
|
}
|
|
|
|
|
|
pub fn set_argv_config(args: clap::ArgMatches) -> HResult<()> {
|
|
let animation = args.is_present("animation-off");
|
|
let show_hidden = args.is_present("show-hidden");
|
|
let icons = args.is_present("icons");
|
|
|
|
let mut config = ArgvConfig::new();
|
|
|
|
if animation == true {
|
|
config.animation = Some(false);
|
|
}
|
|
|
|
if show_hidden == true {
|
|
config.show_hidden = Some(true);
|
|
}
|
|
|
|
if icons == true {
|
|
config.icons = Some(true)
|
|
}
|
|
|
|
if let Some(mode) = args.value_of("graphics") {
|
|
if mode == "auto" {
|
|
config.graphics = Some(detect_g_mode());
|
|
} else {
|
|
config.graphics = Some(String::from(mode));
|
|
}
|
|
}
|
|
|
|
*ARGV_CONFIG.write()? = config;
|
|
Ok(())
|
|
}
|
|
|
|
fn get_argv_config() -> HResult<ArgvConfig> {
|
|
Ok(ARGV_CONFIG.try_read()?.clone())
|
|
}
|
|
|
|
fn infuse_argv_config(mut config: Config) -> Config {
|
|
let argv_config = get_argv_config().unwrap_or(ArgvConfig::new());
|
|
|
|
argv_config.animation.map(|val| config.animation = val);
|
|
argv_config.show_hidden.map(|val| config.show_hidden = val);
|
|
argv_config.icons.map(|val| config.icons = val);
|
|
argv_config.graphics.map(|val| config.graphics = val);
|
|
|
|
config
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct Config {
|
|
pub animation: bool,
|
|
pub animation_refresh_frequency: usize,
|
|
pub show_hidden: bool,
|
|
pub select_cmd: String,
|
|
pub cd_cmd: String,
|
|
pub icons: bool,
|
|
pub media_autoplay: bool,
|
|
pub media_mute: bool,
|
|
pub media_previewer: String,
|
|
pub media_previewer_exists: bool,
|
|
pub ratios: Vec::<usize>,
|
|
pub graphics: String,
|
|
pub keybinds: KeyBinds,
|
|
}
|
|
|
|
|
|
impl Config {
|
|
pub fn new() -> Config {
|
|
let config = Config::default();
|
|
|
|
infuse_argv_config(config)
|
|
}
|
|
|
|
pub fn default() -> Config {
|
|
Config {
|
|
animation: true,
|
|
animation_refresh_frequency: 60,
|
|
show_hidden: false,
|
|
select_cmd: "find -type f | fzf -m".to_string(),
|
|
cd_cmd: "find -type d | fzf".to_string(),
|
|
icons: false,
|
|
media_autoplay: false,
|
|
media_mute: false,
|
|
media_previewer: "hunter-media".to_string(),
|
|
media_previewer_exists: false,
|
|
ratios: vec![20,30,49],
|
|
graphics: detect_g_mode(),
|
|
keybinds: KeyBinds::default(),
|
|
}
|
|
}
|
|
|
|
pub fn load() -> HResult<Config> {
|
|
let config_path = paths::config_path()?;
|
|
|
|
if !config_path.exists() {
|
|
return Ok(infuse_argv_config(Config::new()));
|
|
}
|
|
|
|
let config_string = std::fs::read_to_string(config_path)?;
|
|
|
|
let config = config_string.lines().fold(Config::new(), |mut config, line| {
|
|
match Config::prep_line(line) {
|
|
Ok(("animation", "on")) => config.animation = true,
|
|
Ok(("animation", "off")) => config.animation = false,
|
|
Ok(("animation_refresh_frequency", frequency)) => {
|
|
match frequency.parse::<usize>() {
|
|
Ok(parsed_freq) => config.animation_refresh_frequency = parsed_freq,
|
|
_ => HError::config_error::<Config>(line.to_string()).log()
|
|
}
|
|
}
|
|
Ok(("show_hidden", "on")) => config.show_hidden = true,
|
|
Ok(("show_hidden", "off")) => config.show_hidden = false,
|
|
Ok(("icons", "on")) => config.icons = true,
|
|
Ok(("icons", "off")) => config.icons = false,
|
|
Ok(("select_cmd", cmd)) => {
|
|
let cmd = cmd.to_string();
|
|
config.select_cmd = cmd;
|
|
}
|
|
Ok(("cd_cmd", cmd)) => {
|
|
let cmd = cmd.to_string();
|
|
config.cd_cmd = cmd;
|
|
}
|
|
Ok(("media_autoplay", "on")) => config.media_autoplay = true,
|
|
Ok(("media_autoplay", "off")) => config.media_autoplay = false,
|
|
Ok(("media_mute", "on")) => config.media_mute = true,
|
|
Ok(("media_mute", "off")) => config.media_mute = false,
|
|
Ok(("media_previewer", cmd)) => {
|
|
let cmd = cmd.to_string();
|
|
config.media_previewer = cmd;
|
|
},
|
|
Ok(("ratios", ratios)) => {
|
|
let ratios_str = ratios.to_string();
|
|
if ratios_str.chars().all(|x| x.is_digit(10) || x.is_whitespace()
|
|
|| x == ':' || x == ',' ) {
|
|
let ratios: Vec<usize> = ratios_str.split([',', ':'].as_ref())
|
|
.map(|r| r.trim()
|
|
.parse().unwrap())
|
|
.collect();
|
|
let ratios_sum: usize = ratios.iter().sum();
|
|
if ratios.len() == 3 && ratios_sum > 0 &&
|
|
ratios
|
|
.iter()
|
|
.filter(|&r| *r > u16::max_value() as usize)
|
|
.next() == None {
|
|
config.ratios = ratios;
|
|
}
|
|
}
|
|
}
|
|
#[cfg(feature = "sixel")]
|
|
Ok(("graphics",
|
|
"sixel")) => config.graphics = "sixel".to_string(),
|
|
Ok(("graphics",
|
|
"kitty")) => config.graphics = "kitty".to_string(),
|
|
Ok(("graphics",
|
|
"auto")) => config.graphics = detect_g_mode(),
|
|
_ => { HError::config_error::<Config>(line.to_string()).log(); }
|
|
}
|
|
|
|
#[cfg(feature = "img")]
|
|
match has_media_previewer(&config.media_previewer) {
|
|
t @ _ => config.media_previewer_exists = t
|
|
}
|
|
|
|
config
|
|
});
|
|
|
|
let mut config = infuse_argv_config(config);
|
|
|
|
//use std::iter::Extend;
|
|
KeyBinds::load()
|
|
.map(|kb| config.keybinds = kb)
|
|
.log();
|
|
|
|
Ok(config)
|
|
}
|
|
|
|
fn prep_line<'a>(line: &'a str) -> HResult<(&'a str, &'a str)> {
|
|
let setting = line.split("=").collect::<Vec<&str>>();
|
|
if setting.len() == 2 {
|
|
Ok((setting[0], setting[1]))
|
|
} else {
|
|
HError::config_error(line.to_string())
|
|
}
|
|
|
|
}
|
|
|
|
pub fn animate(&self) -> bool {
|
|
self.animation
|
|
}
|
|
|
|
pub fn show_hidden(&self) -> bool {
|
|
self.show_hidden
|
|
}
|
|
|
|
pub fn media_available(&self) -> bool {
|
|
self.media_previewer_exists
|
|
}
|
|
}
|
|
|
|
fn detect_g_mode() -> String {
|
|
let term = std::env::var("TERM").unwrap_or(String::new());
|
|
match term.as_str() {
|
|
"xterm-kitty" => "kitty",
|
|
#[cfg(feature = "sixel")]
|
|
"xterm" => "sixel",
|
|
_ => "unicode"
|
|
}.to_string()
|
|
}
|
|
|
|
fn has_media_previewer(name: &str) -> bool {
|
|
use crate::minibuffer::find_bins;
|
|
let previewer = std::path::Path::new(name);
|
|
match previewer.is_absolute() {
|
|
true => previewer.exists(),
|
|
false => find_bins(name).is_ok()
|
|
}
|
|
}
|