1use std::env;
2use std::ffi::OsString;
3use std::fs::OpenOptions;
4use std::io;
5use std::io::prelude::*;
6
7
8extern crate subprocess;
9use subprocess::{Exec, Redirection};
10
11#[derive(Debug)]
16pub enum Error {
17 NoEditor(&'static str),
18 IOError(io::Error),
19 SubprocessError(subprocess::PopenError),
20}
21
22impl From<io::Error> for Error {
23 fn from(e: io::Error) -> Self {
24 Error::IOError(e)
25 }
26}
27
28impl From<subprocess::PopenError> for Error {
29 fn from(e: subprocess::PopenError) -> Self {
30 Error::SubprocessError(e)
31 }
32}
33
34fn is_terminal_dumb() -> bool {
35 match env::var("TERM") {
36 Err(_) => true,
37 Ok(term) => term == "dumb".to_string(),
38 }
39}
40
41pub fn text_editor() -> Result<OsString, Error> {
42 let mut editor = env::var_os("EDITRS_EDITOR");
43 let terminal_is_dumb = is_terminal_dumb();
44
45 if editor == None && !terminal_is_dumb {
46 editor = env::var_os("VISUAL");
47 }
48 if editor == None {
49 editor = env::var_os("EDITOR");
50 }
51
52 if editor == None && terminal_is_dumb {
53 return Err(Error::NoEditor("Terminal is dumb, but EDITOR unset"));
54 }
55
56 let editor = editor.unwrap_or_else(|| {
57 println!("Using vi as default text editor. To change this behavior, set the EDITRS_EDITOR environment variable.");
58 OsString::from("vi".to_string())
59 });
60 Ok(editor)
61}
62
63pub fn get_input(default_value: &str) -> Result<String, Error> {
64 let file = OpenOptions::new().write(true).create(true).open(".EDITRS_EDITOR_INPUT")?;
65 file.set_len(0)?;
67 Exec::cmd("echo").arg(default_value).stdout(Redirection::File(file)).join()?;
68
69
70 Exec::cmd(text_editor()?).arg(".EDITRS_EDITOR_INPUT").join()?;
72 let mut file = OpenOptions::new().read(true).open(".EDITRS_EDITOR_INPUT")?;
73 let mut file_buffer = String::new();
74 file.read_to_string(&mut file_buffer)?;
75 Ok(file_buffer.trim().to_string())
76}