1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use crate::notebook::Notebook;

use entry::Entry;
use serde::{Deserialize, Serialize};
use std::{env, fmt, fs, io, io::prelude::*, process::Command};

pub mod argparse;
pub mod config;
pub mod entry;
pub mod notebook;

#[derive(Clone, Debug)]
pub enum Args {
    New(Entry),
    List(usize, u64),
    Read(usize),
    Edit(usize),
    Delete(usize, bool),
    Search(String),
    Unimplemented(),
}

#[derive(Clone, Debug)]
struct Sentiment {
    compound: f64,
    icon: String,
}

impl Sentiment {
    fn new(compound: f64) -> Sentiment {
        let icon = match compound {
            c if c <= -0.7 => "😿",
            c if c <= -0.2 => "😾",
            c if c <= 0.2 => "🐱",
            c if c <= 0.7 => "😺",
            c if c <= 1.0 => "😸",
            _ => "Problemo",
        };

        Sentiment {
            compound,
            icon: icon.to_owned(),
        }
    }
}

impl fmt::Display for Sentiment {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:.3} ≅ {}", self.compound, self.icon)
    }
}

#[derive(Clone, Debug, Serialize, Deserialize)]
struct EncryptionScheme {
    cipher: bool,
    hash: bool,
    salt: bool,
}

fn get_user_confirm<R>(mut reader: R, prompt: String) -> bool
where
    R: io::BufRead,
{
    print!("{prompt} (Y/n) ");
    let _ = io::stdout().flush();
    let mut buffer = String::new();

    reader.read_line(&mut buffer).expect("Error reading input.");

    buffer.starts_with('Y')
}

pub fn create_temp_file(filename: Option<&str>) -> String {
    let mut file_path = env::temp_dir();
    file_path.push(filename.unwrap_or("notebook_rs"));
    fs::File::create(&file_path).expect("Could not create file.");
    file_path.into_os_string().into_string().unwrap()
}

pub fn text_from_editor(path: Option<String>) -> Option<String> {
    let editor = env::var("EDITOR").expect("EDITOR environment variable is missing.");
    let file_path = path.unwrap_or_else(|| create_temp_file(None));

    Command::new(editor)
        .arg(&file_path)
        .status()
        .expect("Something went wrong with the editor.");

    let mut text = String::new();
    fs::File::open(&file_path)
        .expect("Couldn't open temp file.")
        .read_to_string(&mut text)
        .expect("Couldn't load file to string.");

    fs::remove_file(file_path).expect("Couldn't remove temp file.");

    if text.is_empty() {
        None
    } else {
        Some(text)
    }
}

#[cfg(test)]
mod test_util {
    use super::*;

    #[test]
    fn test_missing_editor_variable() {
        env::remove_var("EDITOR");
        let result = std::panic::catch_unwind(|| text_from_editor(None));
        assert!(result.is_err());
    }

    #[test]
    fn test_user_confirm_pos() {
        let pos = b"Y";
        assert!(get_user_confirm(&pos[..], "Prompt".to_string()))
    }

    #[test]
    fn test_user_confirm_neg() {
        let pos = b"n";
        assert_eq!(get_user_confirm(&pos[..], "Prompt".to_string()), false)
    }
}