use directories;
pub use rayon::prelude::*;
use std::env::current_dir;
use std::fs;
use std::path::PathBuf;
pub mod log {
pub use urs::log;
pub use urs::log::LogType::*;
}
pub enum ConfigDir {
RootDir,
KnifeDir,
LocalDir,
}
pub fn get_config_dir(d: ConfigDir) -> Option<PathBuf> {
let base_dir = directories::BaseDirs::new()?;
let root = base_dir.config_dir().join("autosway");
match d {
ConfigDir::RootDir => Some(root),
ConfigDir::KnifeDir => Some(root.join("knifes")),
ConfigDir::LocalDir => Some(if let Ok(p) = current_dir() {
p.join(".autosway")
} else {
log::log!([fatal] "Failed to get local config directory");
}),
}
}
pub struct AutoswayLocalConfig {
pub knife_dir: PathBuf,
}
impl Default for AutoswayLocalConfig {
fn default() -> Self {
let local_dir = if let Some(p) = get_config_dir(ConfigDir::LocalDir) {
p
} else {
log::log!([fatal] "Failed to get local autosway directory");
};
let mut knife_dir = local_dir.join("knifes");
if let Ok(mut f) = std::fs::File::open(local_dir.join("config")) {
if let Ok(c) = urs::misc::config::parse_config_file(&mut f) {
if let Some(dir) = c.get(&"knife_dir".to_string()) {
knife_dir = if let Ok(p) = current_dir() {
p.join(PathBuf::from(dir))
} else {
log::log!([fatal] "Failed to get `knife_dir` option");
}
}
}
}
Self { knife_dir }
}
}
#[derive(Debug, Clone)]
pub struct Knife {
pub path: PathBuf,
pub name: String,
pub init: String,
}
pub fn get_knifes() -> Vec<Knife> {
use std::sync::{Arc, RwLock};
let knifes = Arc::new(RwLock::new(vec![]));
let push_knife = |path: PathBuf, knifes: &mut Vec<Knife>| {
let name = if let Some(name) = path.file_name() {
match name.to_owned().to_str() {
Some(s) => s.to_owned(),
None => return,
}
} else {
return;
};
let init = path.join("init.lua");
if init.exists() {
let init_str = match init.to_str() {
Some(s) => s.to_owned(),
None => return,
};
knifes.push(Knife {
path,
name,
init: init_str,
});
}
};
if let Some(knife_dir) = get_config_dir(ConfigDir::KnifeDir) {
match fs::read_dir(&knife_dir) {
Ok(read) => {
read.par_bridge().for_each(|e| {
if let Ok(e) = e {
if e.path().is_dir() {
let mut lock = knifes.write().unwrap();
push_knife(e.path(), &mut lock);
}
}
});
}
Err(e) => {
urs::log!([warn] "Global knife directory not found: {e}");
}
};
}
let local_dir = AutoswayLocalConfig::default().knife_dir;
let read = match fs::read_dir(local_dir) {
Ok(read_dir) => read_dir,
Err(_) => {
let lock = knifes.read().unwrap();
return (*lock).clone();
}
};
read.par_bridge().for_each(|e| {
if let Ok(e) = e {
if e.path().is_dir() {
let mut lock = knifes.write().unwrap();
push_knife(e.path(), &mut lock);
}
}
});
let lock = knifes.read().unwrap();
(*lock).clone()
}
#[derive(Default)]
pub struct StateOptions {
pub verbose: bool,
}
pub struct State {
pub lua: mlua::Lua,
pub knifes: Vec<Knife>,
pub options: StateOptions,
}
impl Default for State {
fn default() -> Self {
Self::new()
}
}
impl State {
pub fn new() -> Self {
let mut state = Self {
lua: mlua::Lua::new(),
knifes: get_knifes(),
options: StateOptions::default(),
};
match state.setup_lua() {
Ok(()) => {}
Err(e) => {
log::log!([fatal] "{e}");
}
}
state
}
}