use crate::irust::IRust;
use crate::utils::VecTools;
use crossterm::Color;
use std::io::Write;
mod parser;
#[derive(Clone)]
pub struct Options {
pub add_irust_cmd_to_history: bool,
pub add_shell_cmd_to_history: bool,
pub ok_color: Color,
pub show_color: Color,
pub eval_color: Color,
pub irust_color: Color,
pub irust_warn_color: Color,
pub out_color: Color,
pub shell_color: Color,
pub err_color: Color,
pub input_color: Color,
pub insert_color: Color,
pub welcome_msg: String,
pub welcome_color: Color,
pub enable_racer: bool,
pub racer_color: Color,
}
impl Default for Options {
fn default() -> Self {
Self {
add_irust_cmd_to_history: false,
add_shell_cmd_to_history: false,
ok_color: Color::Blue,
show_color: Color::DarkCyan,
eval_color: Color::White,
irust_color: Color::DarkBlue,
irust_warn_color: Color::Cyan,
out_color: Color::Red,
shell_color: Color::DarkYellow,
err_color: Color::DarkRed,
input_color: Color::Yellow,
insert_color: Color::White,
welcome_msg: String::new(),
welcome_color: Color::DarkBlue,
#[cfg(unix)]
enable_racer: true,
#[cfg(windows)]
enable_racer: false,
racer_color: Color::DarkYellow,
}
}
}
impl Options {
pub fn new() -> std::io::Result<Self> {
if let Some(config_path) = Options::config_path() {
match std::fs::File::open(&config_path) {
Ok(config_file) => Options::parse(config_file),
Err(_) => Options::create_config(config_path),
}
} else {
Ok(Options::default())
}
}
pub fn reset_config(config_path: std::path::PathBuf) {
let _ = Options::create_config(config_path);
}
pub fn config_path() -> Option<std::path::PathBuf> {
let config_dir = match dirs::config_dir() {
Some(dir) => dir.join("irust"),
None => return None,
};
let _ = std::fs::create_dir(&config_dir);
let config_path = config_dir.join("config");
Some(config_path)
}
fn create_config(config_path: std::path::PathBuf) -> std::io::Result<Options> {
let config = Options::default_config();
let mut config_file = std::fs::File::create(&config_path)?;
write!(config_file, "{}", config)?;
Ok(Options::default())
}
}
impl Options {
fn str_to_bool(value: &str) -> bool {
match value {
"true" => true,
"false" => false,
value => {
eprintln!("Unknown option value: {}", value);
false
}
}
}
fn str_to_color(value: &str) -> Result<Color, &str> {
match value.to_lowercase().as_ref() {
"black" => Ok(Color::Black),
"red" => Ok(Color::Red),
"darkred" => Ok(Color::DarkRed),
"green" => Ok(Color::Green),
"darkgreen" => Ok(Color::DarkGreen),
"yellow" => Ok(Color::Yellow),
"darkyellow" => Ok(Color::DarkYellow),
"blue" => Ok(Color::Blue),
"darkblue" => Ok(Color::DarkBlue),
"magenta" => Ok(Color::Magenta),
"darkmagenta" => Ok(Color::DarkMagenta),
"cyan" => Ok(Color::Cyan),
"darkcyan" => Ok(Color::DarkCyan),
"grey" => Ok(Color::Grey),
"white" => Ok(Color::White),
value => {
eprintln!("Unknown option value: {}", value);
Err("Unknown option value")
}
}
}
fn get_section(lines: &[String], section_name: String) -> Vec<(String, String)> {
let sec_start = match VecTools::index(lines, §ion_name).get(0) {
Some(idx) => *idx,
None => {
eprintln!("Section {} not found", section_name);
return Vec::new();
}
};
let sec_end = VecTools::index(lines, "[")
.into_iter()
.find(|elem| *elem > sec_start)
.unwrap_or_else(|| lines.len());
lines[sec_start + 1..sec_end]
.iter()
.filter_map(|line| {
let lines_part = line.split('=').map(str::trim).collect::<Vec<&str>>();
if lines_part.len() == 2 {
Some((lines_part[0].to_string(), lines_part[1].to_string()))
} else {
eprintln!("Unknown line: {}", line);
None
}
})
.collect()
}
}
impl IRust {
pub fn should_push_to_history(&self, buffer: &str) -> bool {
let buffer: Vec<char> = buffer.chars().collect();
if buffer.is_empty() {
return false;
}
if buffer.len() == 1 {
return buffer[0] != ':';
}
let irust_cmd = buffer[0] == ':' && buffer[1] != ':';
let shell_cmd = buffer[0] == ':' && buffer[1] == ':';
(irust_cmd && self.options.add_irust_cmd_to_history)
|| (shell_cmd && self.options.add_shell_cmd_to_history)
|| (!irust_cmd && !shell_cmd)
}
}