#![forbid(unsafe_code)]
use std::borrow::Cow;
use std::convert::AsRef;
use core::fmt;
use std::env::{self, VarError};
use std::process::{Command, ExitStatus};
pub fn get_editor(override_editor: Option<Cow<str>>) -> Result<Cow<str>, VarError> {
if let Some(z) = override_editor {
return Ok(z);
}
match env::var("VISUAL") {
Ok(result) => return Ok(result.into()),
Err(VarError::NotPresent) => {},
Err(error) => return Err(error),
}
match env::var("EDITOR") {
Ok(result) => return Ok(result.into()),
Err(VarError::NotPresent) => {},
Err(error) => return Err(error),
}
Ok("vi".into())
}
#[derive(Debug)]
pub enum SEError {
Process(std::io::Error),
Var(VarError),
}
impl std::error::Error for SEError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
SEError::Process(source) => Some(&*source),
SEError::Var(source) => Some(&*source),
}
}
}
impl fmt::Display for SEError {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match self {
SEError::Process(_) => {
formatter.write_str("editor spawning/waiting failed")
}
SEError::Var(_) => {
formatter.write_str("got invalid environment variable")
}
}
}
}
type SEResult = Result<ExitStatus, SEError>;
pub fn spawn_editor(override_editor: Option<&str>, extra_args: &[&str]) -> SEResult {
let editor: std::borrow::Cow<str> = get_editor(override_editor.map(Into::into)).map_err(SEError::Var)?;
Ok(Command::new(&*editor)
.args(extra_args)
.spawn()
.and_then(|mut c| c.wait())
.map_err(SEError::Process)?)
}
pub fn spawn_editor_generic<Ta, Tb>(override_editor: Option<Ta>, extra_args: &[Tb]) -> SEResult
where
Ta: AsRef<str>,
Tb: AsRef<str>,
{
let real_oore = override_editor.as_ref().map(|x| x.as_ref());
let xar: Vec<_> = extra_args.iter().map(|x| x.as_ref()).collect();
spawn_editor(real_oore, &xar[..])
}
#[inline]
pub fn spawn_editor_with_args<Tb: AsRef<str>>(extra_args: &[Tb]) -> SEResult {
spawn_editor_generic::<&str, Tb>(None, extra_args)
}
#[cfg(test)]
mod tests {
use super::*;
mod default_editor {
use std::env;
fn it_falls_back_to_vi() {
env::remove_var("VISUAL");
env::remove_var("EDITOR");
assert_eq!(crate::get_editor(None), Ok("vi".into()));
}
fn it_returns_visual() {
env::set_var("VISUAL", "test1");
env::remove_var("EDITOR");
assert_eq!(crate::get_editor(None), Ok("test1".to_string().into()));
}
fn it_returns_editor() {
env::remove_var("VISUAL");
env::set_var("EDITOR", "test2");
assert_eq!(crate::get_editor(None), Ok("test2".to_string().into()));
}
fn it_returns_visual_before_editor() {
env::set_var("VISUAL", "test3");
env::set_var("EDITOR", "test4");
assert_eq!(crate::get_editor(None), Ok("test3".to_string().into()));
}
#[test]
fn all_tests() {
it_falls_back_to_vi();
it_returns_visual();
it_returns_editor();
it_returns_visual_before_editor();
}
}
#[test]
#[ignore]
fn testit() {
let _ = spawn_editor_with_args(&["src/lib.rs"]);
}
}