use anyhow::{Context, Result};
use crossterm::execute;
use crossterm::terminal::{
disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen,
};
use std::io::stdout;
use std::path::Path;
use std::process::{Command, Stdio};
pub fn editor_program() -> String {
crate::runtime::platform::default_editor()
}
pub fn open_editor(path: &Path) -> Result<()> {
let program = editor_program();
disable_raw_mode().ok();
execute!(stdout(), LeaveAlternateScreen).ok();
let status = Command::new(&program)
.arg(path)
.stdin(Stdio::inherit())
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.status();
let _ = enable_raw_mode();
let _ = execute!(stdout(), EnterAlternateScreen);
let status = status.with_context(|| format!("executando editor '{program}'"))?;
if !status.success() {
anyhow::bail!("editor '{program}' encerrou com código {:?}", status.code());
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn fallback_is_platform_aware_when_unset() {
let _env = crate::runtime::platform::lock_env();
let saved_visual = std::env::var("VISUAL").ok();
let saved_editor = std::env::var("EDITOR").ok();
std::env::remove_var("VISUAL");
std::env::remove_var("EDITOR");
assert_eq!(editor_program(), crate::runtime::platform::default_editor());
match saved_visual {
Some(v) => std::env::set_var("VISUAL", v),
None => std::env::remove_var("VISUAL"),
}
match saved_editor {
Some(v) => std::env::set_var("EDITOR", v),
None => std::env::remove_var("EDITOR"),
}
}
#[test]
fn uses_editor_env_when_set() {
let _env = crate::runtime::platform::lock_env();
let saved_visual = std::env::var("VISUAL").ok();
let saved_editor = std::env::var("EDITOR").ok();
std::env::remove_var("VISUAL");
std::env::set_var("EDITOR", "nano");
assert_eq!(editor_program(), "nano");
match saved_visual {
Some(v) => std::env::set_var("VISUAL", v),
None => std::env::remove_var("VISUAL"),
}
match saved_editor {
Some(v) => std::env::set_var("EDITOR", v),
None => std::env::remove_var("EDITOR"),
}
}
}