keyman/src/config.rs

107 lines
3.2 KiB
Rust

use anyhow::Result;
use crate::{ platform::Platform, input };
use flexbuffers::{ FlexbufferSerializer, Reader };
use std::collections::BTreeSet;
use std::fs;
use std::path;
use serde::{ Serialize, Deserialize };
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Host {
pub platform: Platform,
pub id: String,
pub user: String,
pub host: String,
pub port: i16,
pub config: String
}
impl std::fmt::Display for Host {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(std::format_args!("{} via {}@{}", self.platform, self.user, self.host))
}
}
impl Host {
pub fn edit(&mut self) -> Result<Self> {
let mut data = toml::to_string_pretty(self)?;
{
let t = mktemp::Temp::new_file().unwrap();
fs::write(t.to_owned(), data)?;
let editor = std::env::var("EDITOR").expect("EDITOR is not set");
std::process::Command::new(editor)
.arg(t.to_owned().to_string_lossy().to_string())
.spawn()?.wait()?;
data = fs::read_to_string(t)?;
}
Ok(toml::from_str(&data)?)
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ConfigManager {
#[serde(skip)]
pub config_dir: path::PathBuf,
#[serde(skip)]
pub search_path: path::PathBuf,
pub configs: BTreeSet<Host>,
}
impl ConfigManager {
pub fn new(given_config_root: Option<String>, search_path: Option<String>) -> Result<Self> {
let config_root = match given_config_root {
Some(c) => path::Path::new(&c).to_owned(),
None => dirs::data_local_dir().unwrap().join("keyman/"),
};
if !fs::try_exists(config_root.to_owned()).unwrap_or(false) {
fs::create_dir_all(config_root.to_owned())?;
}
let search_path = match search_path {
Some(s) => std::path::Path::new(&s).to_owned(),
None => dirs::home_dir().unwrap().join(".ssh/"),
};
match fs::read(config_root.join("config")) {
Ok(c) => {
let root = Reader::get_root(c.as_slice())?;
match ConfigManager::deserialize(root) {
Ok(mut mgr) => {
mgr.config_dir = config_root;
mgr.search_path = search_path;
Ok(mgr)
},
Err(_) => Ok(Self { config_dir: config_root, search_path, configs: BTreeSet::new() }),
}
}
Err(_) => Ok(Self { config_dir: config_root, search_path, configs: BTreeSet::new() }),
}
}
pub fn save(&mut self) {
let mut s = FlexbufferSerializer::new();
self.serialize(&mut s).unwrap();
fs::write(self.config_dir.to_owned().join("config"), s.view()).unwrap();
}
pub fn new_host(&mut self) -> Result<Host> {
let platform = input::get_platform()?;
let host = platform.new_host(self)?;
self.configs.insert(host.to_owned());
self.save();
Ok(host)
}
}
impl Drop for ConfigManager {
fn drop(&mut self) {
self.save();
}
}