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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
extern crate chrono;
extern crate dirs;
extern crate serde;
extern crate toml;

use std::fs::*;
use std::io::prelude::*;
use std::io::Result;
use std::path::*;
use std::str::from_utf8;
use utils::home_dir_string;

#[derive(Deserialize, Serialize, Debug)]
/// Structure that loads setting information from file and mapping
pub struct Config {
    memos_dir: Option<String>,
    editor: Option<String>,
    selector: Option<String>,
    grep_command: Option<String>,
    template_file_path: Option<String>,
    pub enter_time_in_filename: Option<bool>,
}

impl Config {
    /// Read the file in which the setting file is described.
    /// If not, create it
    pub fn load_config() -> Result<Config> {
        let mut file = Config::load_or_create_config_file();

        let mut buf = vec![];
        file.read_to_end(&mut buf)?;
        let toml_str = match from_utf8(&buf) {
            Ok(toml_str) => toml_str,
            Err(e) => panic!(e),
        };

        let config: Config = if toml_str.is_empty() {
            let config = Config::default();
            let toml_str = toml::to_string(&config).unwrap();

            match file.write_all(toml_str.as_bytes()) {
                Ok(_) => config,
                Err(e) => panic!(e),
            }
        } else {
            match toml::from_str(toml_str) {
                Ok(config) => config,
                _ => panic!("Analysis of configuration file failed"),
            }
        };

        Ok(config)
    }

    ///Get the file pointer of the setting file.
    ///When there is no file, a setting file is created.
    pub fn load_or_create_config_file() -> File {
        //FIXME Not compatible with windows
        let dir = match dirs::home_dir() {
            Some(dir) => Path::new(&dir.to_str().unwrap().to_string()).join(".config/rmemo/"),
            None => panic!("faild fetch home_dir name"),
        };

        DirBuilder::new()
            .recursive(true)
            .create(dir.clone())
            .unwrap();

        let filepath = &dir.join("config.toml");

        match OpenOptions::new()
            .create(true)
            .write(true)
            .append(true)
            .read(true)
            .open(filepath)
        {
            Ok(file) => file,
            Err(e) => panic!(e),
        }
    }

    /// Unwrap and return the memo_dir property
    pub fn memos_dir(&self) -> &String {
        match self.memos_dir {
            Some(ref dir) => dir,
            None => panic!("Memos directory is not set"),
        }
    }

    /// Unwrap and return the enter_time_in_filename property
    pub fn enter_time_in_filename(&self) -> bool {
        match self.enter_time_in_filename {
            Some(true) => true,
            _ => false,
        }
    }

    /// Unwrap and return the editor property
    pub fn editor(&self) -> &String {
        match self.editor {
            Some(ref editor) => editor,
            None => panic!("Editor is not set"),
        }
    }

    /// Unwrap and return the selector property
    pub fn selector(&self) -> &String {
        match self.selector {
            Some(ref selector) => selector,
            None => panic!("Editor is not set"),
        }
    }

    /// Unwrap and return the grep_command property
    pub fn grep_command(&self) -> &String {
        match self.grep_command {
            Some(ref grep_command) => grep_command,
            None => panic!("grep_command is not set"),
        }
    }

    /// Unwrap and return the template_file_path property
    pub fn template_file_path(&self) -> &String {
        match self.template_file_path {
            Some(ref template_file_path) => template_file_path,
            None => panic!("template_file_path is not set"),
        }
    }
}

impl Default for Config {
    fn default() -> Self {
        let memos_dir = Some(home_dir_string() + "/.config/rmemo/memos");
        let editor = Some(String::from("vim"));
        let selector = Some(String::from("fzf"));
        let grep_command = Some(String::from("grep"));
        let template_file_path = Some(String::from(""));
        let enter_time_in_filename = Some(true);

        Config {
            memos_dir,
            editor,
            selector,
            grep_command,
            template_file_path,
            enter_time_in_filename,
        }
    }
}