tiempo 1.6.0

A command line time tracker
Documentation
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.first() {
        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() })
    }
}