1use crate::utils;
2
3use app_dirs::{get_app_root, AppDataType, AppInfo};
4use clap::ArgMatches;
5use mkdirp::mkdirp;
6use snafu::{ensure, Snafu};
7
8use std::error;
9use std::path::{Path, PathBuf};
10
11#[derive(Debug, Snafu)]
12pub enum Error {
13 #[snafu(display("app_name cannot be empty"))]
14 AppNameEmpty {},
15 #[snafu(display("app_author cannot be empty"))]
16 AppAuthorEmpty {},
17 #[snafu(display("tmux command cannot be empty"))]
18 TmuxCommandEmpty {},
19 #[snafu(display("config-dir {:?} should be a directory", path))]
20 ConfigDirIsNotADirectory { path: PathBuf },
21}
22
23pub struct Config {
24 pub app_name: &'static str,
25 pub app_author: &'static str,
26 pub tmux_command: Option<String>,
27 pub config_dir: Option<PathBuf>,
28}
29
30impl Config {
31 pub fn from_args(
32 app_name: &'static str,
33 app_author: &'static str,
34 matches: &ArgMatches,
35 ) -> Config {
36 let tmux_command = matches.value_of_lossy("tmux_command").map(String::from);
37 let config_dir = matches.value_of_os("config_dir").map(PathBuf::from);
38
39 Config {
40 app_name,
41 app_author,
42 tmux_command,
43 config_dir,
44 }
45 }
46
47 pub fn check(self) -> Result<Self, Box<dyn error::Error>> {
48 ensure!(!&self.app_name.is_empty(), AppNameEmpty {});
49 ensure!(!&self.app_author.is_empty(), AppAuthorEmpty {});
50
51 if let Some(config_dir) = &self.config_dir {
52 let path = PathBuf::from(config_dir);
53 ensure!(!path.is_file(), ConfigDirIsNotADirectory { path });
54
55 mkdirp(&config_dir)?;
56 };
57
58 Ok(self)
59 }
60
61 pub fn get_config_dir<P>(&self, sub_path: P) -> Result<PathBuf, Box<dyn error::Error>>
62 where
63 P: AsRef<Path>,
64 {
65 let path;
66 if let Some(dir) = &self.config_dir {
67 path = PathBuf::from(dir);
68 } else {
69 path = get_app_root(
70 AppDataType::UserConfig,
71 &AppInfo {
72 name: &self.app_name,
73 author: &self.app_author,
74 },
75 )?;
76 };
77
78 let path = path.join(&sub_path);
79 mkdirp(&path)?;
80
81 Ok(path)
82 }
83
84 pub fn get_projects_dir<P>(&self, sub_path: P) -> Result<PathBuf, Box<dyn error::Error>>
85 where
86 P: AsRef<Path>,
87 {
88 self.get_config_dir(sub_path)
89 }
90
91 pub fn get_tmux_command(
92 &self,
93 args: &[&str],
94 ) -> Result<(String, Vec<String>), Box<dyn error::Error>> {
95 let command = self
96 .tmux_command
97 .to_owned()
98 .unwrap_or_else(|| String::from("tmux"));
99
100 utils::parse_command(&command, args)
101 }
102}
103
104#[cfg(test)]
105#[path = "test/config.rs"]
106mod tests;