1
0
mirror of https://github.com/Llewellynvdm/starship.git synced 2024-06-04 01:20:51 +00:00
starship/src/configure.rs
Tilmann Meyer 2233683410
feat: add error messaging (#1576)
This creates a custom logger for the log crate which logs everything to a file (/tmp/starship/session_$STARSHIP_SESSION_KEY.log) and it logs everything above Warn to stderr, but only if the log file does not contain the line that should be logged resulting in an error or warning to be only logged at the first starship invocation after opening the shell.
2020-09-28 16:38:50 -04:00

171 lines
5.0 KiB
Rust

use std::env;
use std::ffi::OsString;
use std::io::ErrorKind;
use std::process;
use std::process::Command;
use starship::config::StarshipConfig;
use std::fs::File;
use std::io::Write;
use toml::map::Map;
use toml::Value;
#[cfg(not(windows))]
const STD_EDITOR: &str = "vi";
#[cfg(windows)]
const STD_EDITOR: &str = "notepad.exe";
pub fn update_configuration(name: &str, value: &str) {
let config_path = get_config_path();
let keys: Vec<&str> = name.split('.').collect();
if keys.len() != 2 {
log::error!("Please pass in a config key with a '.'");
process::exit(1);
}
let starship_config = StarshipConfig::initialize();
let mut config = starship_config
.config
.expect("Failed to load starship config");
if let Some(table) = config.as_table_mut() {
if !table.contains_key(keys[0]) {
table.insert(keys[0].to_string(), Value::Table(Map::new()));
}
if let Some(values) = table.get(keys[0]).unwrap().as_table() {
let mut updated_values = values.clone();
if value.parse::<bool>().is_ok() {
updated_values.insert(
keys[1].to_string(),
Value::Boolean(value.parse::<bool>().unwrap()),
);
} else if value.parse::<i64>().is_ok() {
updated_values.insert(
keys[1].to_string(),
Value::Integer(value.parse::<i64>().unwrap()),
);
} else {
updated_values.insert(keys[1].to_string(), Value::String(value.to_string()));
}
table.insert(keys[0].to_string(), Value::Table(updated_values));
}
let config_str =
toml::to_string_pretty(&table).expect("Failed to serialize the config to string");
File::create(&config_path)
.and_then(|mut file| file.write_all(config_str.as_ref()))
.expect("Error writing starship config");
}
}
pub fn edit_configuration() {
let config_path = get_config_path();
let editor_cmd = shell_words::split(&get_editor()).expect("Unmatched quotes found in $EDITOR.");
let command = Command::new(&editor_cmd[0])
.args(&editor_cmd[1..])
.arg(config_path)
.status();
match command {
Ok(_) => (),
Err(error) => match error.kind() {
ErrorKind::NotFound => {
eprintln!(
"Error: editor {:?} was not found. Did you set your $EDITOR or $VISUAL \
environment variables correctly?",
editor_cmd
);
std::process::exit(1)
}
other_error => panic!("failed to open file: {:?}", other_error),
},
};
}
fn get_editor() -> String {
get_editor_internal(env::var("VISUAL").ok(), env::var("EDITOR").ok())
}
fn get_editor_internal(visual: Option<String>, editor: Option<String>) -> String {
let editor_name = visual.unwrap_or_else(|| "".into());
if !editor_name.is_empty() {
return editor_name;
}
let editor_name = editor.unwrap_or_else(|| "".into());
if !editor_name.is_empty() {
return editor_name;
}
STD_EDITOR.into()
}
fn get_config_path() -> OsString {
if let Some(config_path) = env::var_os("STARSHIP_CONFIG") {
return config_path;
}
dirs_next::home_dir()
.expect("couldn't find home directory")
.join(".config")
.join("starship.toml")
.into()
}
#[cfg(test)]
mod tests {
use super::*;
// This is every possible permutation, 3² = 9.
#[test]
fn visual_set_editor_set() {
let actual = get_editor_internal(Some("foo".into()), Some("bar".into()));
assert_eq!("foo", actual);
}
#[test]
fn visual_set_editor_empty() {
let actual = get_editor_internal(Some("foo".into()), None);
assert_eq!("foo", actual);
}
#[test]
fn visual_set_editor_not_set() {
let actual = get_editor_internal(Some("foo".into()), None);
assert_eq!("foo", actual);
}
#[test]
fn visual_empty_editor_set() {
let actual = get_editor_internal(Some("".into()), Some("bar".into()));
assert_eq!("bar", actual);
}
#[test]
fn visual_empty_editor_empty() {
let actual = get_editor_internal(Some("".into()), Some("".into()));
assert_eq!(STD_EDITOR, actual);
}
#[test]
fn visual_empty_editor_not_set() {
let actual = get_editor_internal(Some("".into()), None);
assert_eq!(STD_EDITOR, actual);
}
#[test]
fn visual_not_set_editor_set() {
let actual = get_editor_internal(None, Some("bar".into()));
assert_eq!("bar", actual);
}
#[test]
fn visual_not_set_editor_empty() {
let actual = get_editor_internal(None, Some("".into()));
assert_eq!(STD_EDITOR, actual);
}
#[test]
fn visual_not_set_editor_not_set() {
let actual = get_editor_internal(None, None);
assert_eq!(STD_EDITOR, actual);
}
}