use anyhow::Result;
use ratatui::prelude::*;
use std::path::{Path, PathBuf};
use super::*;
use std::process::Command;
#[derive(Clone)]
pub(super) enum Action {
AddNode,
EditNode {
original: String,
},
SaveConf {
content: String,
original: Option<PathBuf>,
was_up: bool,
},
}
pub(super) struct EditorReq {
pub(super) tmp: PathBuf,
pub(super) original: Option<PathBuf>,
pub(super) was_up: bool,
pub(super) seed: String,
}
pub(super) fn write_conf(name: &str, cfg: &str) -> String {
let path = format!("out/{name}.conf");
match std::fs::create_dir_all("out").and_then(|_| std::fs::write(&path, cfg)) {
Ok(()) => path,
Err(e) => format!("(couldn't write out/: {e})"),
}
}
pub(super) fn stem(path: &Path) -> String {
path.file_stem()
.and_then(|s| s.to_str())
.unwrap_or("")
.to_string()
}
pub(super) fn write_temp(content: &str) -> std::io::Result<PathBuf> {
let mut p = std::env::temp_dir();
p.push(format!("ewg-edit-{}.conf", std::process::id()));
std::fs::write(&p, content)?;
Ok(p)
}
pub(super) fn backup(path: &Path) -> Option<PathBuf> {
if !path.exists() {
return None;
}
let epoch = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map(|d| d.as_secs())
.unwrap_or(0);
let mut bak = path.as_os_str().to_os_string();
bak.push(format!(".bak.{epoch}"));
let bak = PathBuf::from(bak);
std::fs::copy(path, &bak).ok().map(|_| bak)
}
pub(super) fn act(path: Option<PathBuf>, up: bool) -> String {
let Some(path) = path else {
return "no interface selected".into();
};
let name = path
.file_stem()
.and_then(|s| s.to_str())
.unwrap_or("")
.to_string();
match if up { wg::up(&path) } else { wg::down(&path) } {
Ok(()) => format!("{} {name}", if up { "brought up" } else { "took down" }),
Err(e) => format!("error: {e}"),
}
}
pub(super) fn run_editor<B: Backend>(
terminal: &mut Terminal<B>,
app: &mut App,
req: EditorReq,
) -> Result<()> {
let enhanced = supports_keyboard_enhancement().unwrap_or(false);
if enhanced {
let _ = execute!(stdout(), PopKeyboardEnhancementFlags);
}
disable_raw_mode()?;
execute!(stdout(), LeaveAlternateScreen)?;
let editor = std::env::var_os("VISUAL")
.or_else(|| std::env::var_os("EDITOR"))
.unwrap_or_else(|| "vi".into());
let status = Command::new(&editor).arg(&req.tmp).status();
enable_raw_mode()?;
execute!(stdout(), EnterAlternateScreen)?;
if enhanced {
let _ = execute!(
stdout(),
PushKeyboardEnhancementFlags(KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES)
);
}
terminal.clear()?;
match status {
Ok(_) => app.editor_done(req),
Err(e) => {
let _ = std::fs::remove_file(&req.tmp);
app.set_status(format!(
"couldn't launch editor `{}`: {e}",
editor.to_string_lossy()
));
}
}
Ok(())
}