diff --git a/src/configure.rs b/src/configure.rs index 8f3e4b05..b8e3812c 100644 --- a/src/configure.rs +++ b/src/configure.rs @@ -5,18 +5,38 @@ use std::process::Command; const STD_EDITOR: &str = "vi"; pub fn edit_configuration() { - let editor = get_editor(); let config_path = get_config_path(); + let editor_cmd = get_editor(); + + let mut cmd_iter = editor_cmd + .to_str() + .expect("environment variable contains invalid unicode") + .split_whitespace(); + + let editor = cmd_iter.next().unwrap_or(STD_EDITOR); + let args: Vec<_> = cmd_iter.collect(); Command::new(editor) + .args(args) .arg(config_path) .status() .expect("failed to open file"); } -fn get_editor() -> String { - let editor = env::var("VISUAL").or_else(|_| env::var("EDITOR")); - editor.unwrap_or_else(|_| STD_EDITOR.to_string()) +fn get_editor() -> OsString { + get_editor_internal(env::var_os("VISUAL"), env::var_os("EDITOR")) +} + +fn get_editor_internal(visual: Option, editor: Option) -> OsString { + let mut editor_name = visual.unwrap_or_else(|| "".into()); + if !editor_name.is_empty() { + return editor_name; + } + editor_name = editor.unwrap_or_else(|| "".into()); + if !editor_name.is_empty() { + return editor_name; + } + STD_EDITOR.into() } fn get_config_path() -> OsString { @@ -26,3 +46,58 @@ fn get_config_path() -> OsString { .as_os_str() .to_owned() } + +#[cfg(test)] +mod tests { + use super::*; + + // This is every possible permutation, 3² = 9. + + #[test] + fn visual_set_editor_set() { + let actual = get_editor_internal(Some("foo".into()), Some("bar".into())); + assert_eq!("foo", actual); + } + #[test] + fn visual_set_editor_empty() { + let actual = get_editor_internal(Some("foo".into()), None); + assert_eq!("foo", actual); + } + #[test] + fn visual_set_editor_not_set() { + let actual = get_editor_internal(Some("foo".into()), None); + assert_eq!("foo", actual); + } + + #[test] + fn visual_empty_editor_set() { + let actual = get_editor_internal(Some("".into()), Some("bar".into())); + assert_eq!("bar", actual); + } + #[test] + fn visual_empty_editor_empty() { + let actual = get_editor_internal(Some("".into()), Some("".into())); + assert_eq!("vi", actual); + } + #[test] + fn visual_empty_editor_not_set() { + let actual = get_editor_internal(Some("".into()), None); + assert_eq!("vi", actual); + } + + #[test] + fn visual_not_set_editor_set() { + let actual = get_editor_internal(None, Some("bar".into())); + assert_eq!("bar", actual); + } + #[test] + fn visual_not_set_editor_empty() { + let actual = get_editor_internal(None, Some("".into())); + assert_eq!("vi", actual); + } + #[test] + fn visual_not_set_editor_not_set() { + let actual = get_editor_internal(None, None); + assert_eq!("vi", actual); + } +}