sqish/src/shell/config.rs

205 lines
6.6 KiB
Rust

use users::{get_user_by_uid, get_current_uid};
use termion::{color, style};
use std::{env, fs};
use std::collections::HashMap;
use regex::Regex;
extern crate dirs;
extern crate yaml_rust;
use yaml_rust::{YamlLoader, Yaml};
#[derive(Debug)]
pub struct SqishConf {
pub promptline: String,
pub promptline_base: String,
pub aliases: HashMap<String, String>,
pub hotkeys: HashMap<String, String>,
pub init: String,
}
impl SqishConf {
pub fn from_sqishrc() -> Result<SqishConf, String> {
let mut conf_path = match dirs::home_dir() {
Some(p) => p,
None => {
return Err(String::from("Home dir could not be determined."));
},
};
conf_path.push(".sqishrc");
let sqishrc_file = match fs::read_to_string(conf_path) {
Ok(s) => s,
Err(_) => {
return Err(String::from("Could not read ~/.sqishrc"));
},
};
let sqishrc = match YamlLoader::load_from_str(&sqishrc_file) {
Ok(s) => s,
Err(_) => {
return Err(String::from("sqishrc is not valid yaml"));
},
};
let sqishrc = &sqishrc[0];
let out_str = String::from(sqishrc["prompt"].as_str().unwrap_or("$ "));
let startup = String::from(sqishrc["init"].as_str().unwrap_or(""));
//Loading hotkeys and aliases from yaml
//They can be empty, be careful...
let aliases_yaml = &sqishrc["aliases"];
let aliases = Self::yaml_dict2hashmap(aliases_yaml);
let hotkeys_yaml = &sqishrc["hotkeys"];
let hotkeys = Self::yaml_dict2hashmap(hotkeys_yaml);
let mut out_conf = SqishConf {
promptline: out_str.clone(),
promptline_base: out_str,
aliases: aliases,
hotkeys: hotkeys,
init: startup,
};
out_conf.handle_rgb();
out_conf.handle_colors();
return Ok(out_conf);
}
#[warn(unused_assignments)]
pub fn update_prompt(&mut self, hist_nbr: i32) {
let user = String::from(
get_user_by_uid(get_current_uid())
.unwrap()
.name()
.to_str()
.unwrap()
);
let host = String::from(
gethostname::gethostname()
.to_str()
.unwrap()
);
let current_dir = String::from(
env::current_dir()
.unwrap()
.to_str()
.unwrap()
);
let s = current_dir.split('/');
let dir_last = String::from(
s.last()
.unwrap()
);
let hist_nbr = hist_nbr.to_string();
let mut prompt = self.promptline_base.replace("$USER_", &user);
prompt = prompt.replace("$HOSTNAME_", &host);
prompt = prompt.replace("$DIR_", &dir_last);
prompt = prompt.replace("$HISTNUMBER_", &hist_nbr);
prompt = prompt.to_owned();
self.promptline = prompt;
self.handle_colors();
self.handle_rgb();
}
fn handle_colors(&mut self) {
//Colors
let reset = format!("{}", color::Fg(color::Reset));
let green = format!("{}", color::Fg(color::Green));
let blue = format!("{}", color::Fg(color::Blue));
let red = format!("{}", color::Fg(color::Red));
let black = format!("{}", color::Fg(color::Black));
let white = format!("{}", color::Fg(color::White));
let cyan = format!("{}", color::Fg(color::Cyan));
let lightblack = format!("{}", color::Fg(color::LightBlack));
//Styles
let ita = format!("{}", style::Italic);
let bold = format!("{}", style::Bold);
let stylereset = format!("{}", style::Reset);
//Colors replace
let mut prompt = self.promptline.replace("$COLORGREEN_", &green);
prompt = prompt.replace("$COLORBLUE_", &blue);
prompt = prompt.replace("$COLORRED_", &red);
prompt = prompt.replace("$COLORBLACK_", &black);
prompt = prompt.replace("$COLORWHITE_", &white);
prompt = prompt.replace("$COLORCYAN_", &cyan);
prompt = prompt.replace("$COLORLBLACK_", &lightblack);
prompt = prompt.replace("$COLORRESET_", &reset);
//Styles replace
prompt = prompt.replace("$ITA_", &ita);
prompt = prompt.replace("$BOLD_", &bold);
prompt = prompt.replace("$STYLERESET_", &stylereset);
let promptown = prompt.to_owned();
self.promptline = promptown;
}
fn handle_rgb(&mut self) {
let re = Regex::new(r"\$RGB[^_]*_").unwrap();
let promptline_copy = &self.promptline.clone();
let matches = re.find_iter(promptline_copy);
//println!("Matches : {:?}", &matches.count());
for m in matches {
//Copy of the text used for parsing by replacement
let mut matchtext = String::from(m.as_str());
//Keep a copy of the original...
let matchtext_copy = matchtext.clone();
//Start replacing...
matchtext = matchtext.replace("$RGB", "");
matchtext = matchtext.replace("_", "");
matchtext = matchtext.replace("|", " ");
matchtext = String::from(matchtext.trim());
let matchvalues = matchtext
.split_whitespace()
.collect::<Vec<&str>>();
//We now have a Vector of values that must
//converted to u8 before being used by termion
//println!("MATCH {:?}", matchvalues);
//Get the color...
let red: u8 = matchvalues[0].parse().unwrap_or(108);
let green: u8 = matchvalues[1].parse().unwrap_or(84);
let blue: u8 = matchvalues[0].parse().unwrap_or(30);
let color = color::Fg(color::Rgb {
0: red,
1: green,
2: blue,
});
let color_display = format!("{}", color);
//...and replace in promptline
let out_str = self.promptline.replace(&matchtext_copy, &color_display);
let out_str = out_str.to_owned();
*&mut self.promptline = out_str;
}
}
///Takes a YAML dict and converts it into an hashmap.
fn yaml_dict2hashmap(yaml_dict: &Yaml) -> HashMap<String, String> {
let mut my_hashmap = HashMap::new();
if let Yaml::Hash(h) = yaml_dict {
for (k, v) in h.iter() {
if let (Yaml::String(k), Yaml::String(v)) = (k, v) {
my_hashmap.insert(k.clone(), v.clone());
}
}
}
return my_hashmap;
}
}