use anyhow::{Context, Result};
use std::path::Path;
use std::process::Command;
pub fn open_in_editor(path: &Path, line: Option<usize>) -> Result<()> {
use crossterm::{
cursor::MoveTo,
event::{DisableMouseCapture, EnableMouseCapture},
execute,
terminal::{
disable_raw_mode, enable_raw_mode, Clear, ClearType, EnterAlternateScreen,
LeaveAlternateScreen,
},
};
use std::io;
let editor = std::env::var("EDITOR")
.or_else(|_| std::env::var("VISUAL"))
.unwrap_or_else(|_| "vim".to_string());
let mut cmd = Command::new(&editor);
match (editor.as_str(), line) {
("vim" | "nvim" | "vi", Some(n)) => {
cmd.arg(format!("+{}", n));
cmd.arg(path);
}
("code" | "code-insiders", Some(n)) => {
cmd.arg("--goto");
cmd.arg(format!("{}:{}", path.display(), n));
}
("emacs", Some(n)) => {
cmd.arg(format!("+{}", n));
cmd.arg(path);
}
("subl" | "sublime" | "sublime_text", Some(n)) => {
cmd.arg(format!("{}:{}", path.display(), n));
}
("hx" | "helix", Some(n)) => {
cmd.arg(format!("{}:{}", path.display(), n));
}
("nano", Some(n)) => {
cmd.arg(format!("+{}", n));
cmd.arg(path);
}
_ => {
cmd.arg(path);
}
}
disable_raw_mode().context("Failed to disable raw mode")?;
execute!(io::stdout(), LeaveAlternateScreen, DisableMouseCapture)
.context("Failed to leave alternate screen")?;
execute!(io::stdout(), Clear(ClearType::All), MoveTo(0, 0))
.context("Failed to clear screen")?;
let status = cmd
.status()
.with_context(|| format!("Failed to launch editor: {}", editor))?;
execute!(io::stdout(), EnterAlternateScreen, EnableMouseCapture)
.context("Failed to re-enter alternate screen")?;
enable_raw_mode().context("Failed to re-enable raw mode")?;
use crossterm::event;
while event::poll(std::time::Duration::from_millis(0))? {
let _ = event::read()?;
}
if !status.success() {
anyhow::bail!("Editor exited with status: {}", status);
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use std::path::PathBuf;
#[test]
#[ignore] fn test_editor_command_construction() {
let path = PathBuf::from("/tmp/test.rs");
std::env::set_var("EDITOR", "true");
let result = open_in_editor(&path, Some(42));
assert!(result.is_ok());
}
}