1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
extern crate failure; #[macro_use] extern crate failure_derive; extern crate rprompt; extern crate toml; extern crate xdg; #[macro_use] extern crate log; use std::fs::File; use std::io::prelude::*; use std::path::Path; use std::fs::OpenOptions; use failure::Error; #[derive(Fail, Debug)] #[fail(display = "Expected {} to be a string, but it wasn't", key)] struct NotStringError { key: String, } pub struct PsstApplication { xdg_dirs: xdg::BaseDirectories, } impl PsstApplication { pub fn get(&self, key: &str) -> Result<String, Error> { let path = self.xdg_dirs.place_data_file("psst.toml")?; if !Path::exists(&path) { File::create(&path)?; } let current_content = { let mut file = File::open(&path)?; let mut content = String::new(); file.read_to_string(&mut content)?; content }; let mut table = current_content.parse::<toml::Value>()?; { if let Some(value) = table.get(key) { debug!("Using {} value from {:?}", key, path); if let Some(str_value) = value.as_str() { return Ok(str_value.to_string()); } else { Err(NotStringError { key: key.to_string(), })?; } } } let new_value = self.get_new_value_for(key)?; let new_table = table.as_table_mut().unwrap(); new_table.insert(key.to_string(), toml::Value::String(new_value.to_string())); let new_toml = toml::to_string(&new_table)?; debug!("Updating {:?} with new value", path); let mut file = OpenOptions::new().write(true).open(&path)?; file.write_all(new_toml.as_bytes())?; Ok(new_value) } fn get_new_value_for(&self, key: &str) -> Result<String, Error> { debug!("Prompting for new value for {}", key); let reply = rprompt::prompt_reply_stdout(&format!("Please provide a value for {}: ", key))?; Ok(reply) } } pub fn new(application: &str) -> Result<PsstApplication, Error> { let xdg_dirs = xdg::BaseDirectories::with_prefix(application)?; Ok(PsstApplication { xdg_dirs }) }