66 lines
1.8 KiB
Rust
66 lines
1.8 KiB
Rust
use std::process::{Command, Stdio};
|
|
use std::io::{Read, Write, Seek, SeekFrom};
|
|
|
|
use tempfile::NamedTempFile;
|
|
|
|
use crate::error::{Error::*, Result};
|
|
|
|
/// Launches the specified editor editing a temporary file and returns the
|
|
/// contents written by the user.
|
|
///
|
|
/// If prev_contents is Some(s) then the temporary file is started with those
|
|
/// contents.
|
|
pub fn get_string(note_editor: Option<&str>, prev_contents: Option<String>) -> Result<String> {
|
|
let note_editor = if let Some(note_editor) = note_editor {
|
|
note_editor.to_owned()
|
|
} else if let Ok(editor_env) = std::env::var("EDITOR") {
|
|
editor_env
|
|
} else {
|
|
return Err(EditorIsEmpty);
|
|
};
|
|
|
|
let parts: Vec<_> = note_editor.split(' ').filter(|p| !p.is_empty()).collect();
|
|
let editor = if let Some(name) = parts.get(0) {
|
|
name.to_owned()
|
|
} else {
|
|
return Err(EditorIsEmpty);
|
|
};
|
|
|
|
let mut c = Command::new(editor);
|
|
|
|
if parts.len() > 1 {
|
|
for part in &parts[1..] {
|
|
c.arg(part);
|
|
}
|
|
}
|
|
|
|
let mut tmpfile = NamedTempFile::new().map_err(|e| NoTmpFile(e.to_string()))?;
|
|
|
|
if let Some(contents) = prev_contents {
|
|
tmpfile.write_all(contents.as_bytes())?;
|
|
tmpfile.seek(SeekFrom::Start(0))?;
|
|
}
|
|
|
|
c.arg(tmpfile.as_ref());
|
|
|
|
let status = c
|
|
.stdin(Stdio::inherit())
|
|
.stdout(Stdio::inherit())
|
|
.stderr(Stdio::inherit())
|
|
.output().map_err(|e| EditorFailed {
|
|
editor: note_editor.clone(),
|
|
error: e.to_string(),
|
|
})?
|
|
.status;
|
|
|
|
if status.success() {
|
|
let mut note = String::new();
|
|
|
|
tmpfile.read_to_string(&mut note).map_err(|e| CouldntReadTmpFile(e.to_string()))?;
|
|
|
|
Ok(note.trim().to_owned())
|
|
} else {
|
|
Err(EditorFailed { editor: note_editor.clone(), error: status.to_string() })
|
|
}
|
|
}
|