-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcli.rs
125 lines (110 loc) · 3.76 KB
/
cli.rs
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
use std::env::{current_dir, temp_dir};
use std::error::Error;
use std::fs::{create_dir_all, File, OpenOptions};
use std::io;
use std::io::Write;
use std::path::{PathBuf};
use clap::{Command, CommandFactory, Parser, ValueHint};
use clap_complete::{generate, Generator, Shell};
use crate::{Config, normalize};
#[derive(Parser, Debug)]
#[clap(version, about, long_about = None)]
pub(crate) struct Args {
/// Generate completion script
#[clap(long = "generate", value_enum)]
generator: Option<Shell>,
/// Run as system mode (eg. systemd hook on linux)
#[clap(long)]
system: bool,
/// Path to config file
#[clap(short, long, value_hint = ValueHint::DirPath)]
config: Option<String>,
/// Print information and exit
#[clap(short, long)]
pub info: bool,
/// Path to source directory (copy content into ramdisk on mount)
#[clap(short, long, value_hint = ValueHint::DirPath)]
pub(crate) source: Option<String>,
/// Unlink / remove instead of create (ignore source option)
#[clap(short, long)]
pub(crate) remove: bool,
/// target folder to link to ramdisk
#[clap(value_parser, value_hint = ValueHint::DirPath)]
pub(crate) link_target: Option<String>,
}
pub(crate) fn parse_args() -> Args {
let args: Args = Args::parse();
if let Some(generator) = args.generator {
let mut cmd = Args::command();
if generator == Shell::Bash {
eprintln!("Saving completion file to ~.local/share/bash-completion/completions");
} else {
eprintln!("Generating completion file for {:?}...", generator);
}
print_completions(generator, &mut cmd, if generator == Shell::Bash { Some(dirs::home_dir().expect("Home dir").join(".local/share/bash-completion/completions/lnshm")) } else { None });
}
args
}
fn print_completions<G: Generator>(gen: G, cmd: &mut Command, save: Option<PathBuf>) {
if let Some(save) = save {
let mut file = if let Ok(true) = save.try_exists() {
OpenOptions::new().write(true).truncate(true).open(save).expect("Open completion file")
} else {
create_dir_all(save.parent().expect("parent dir")).expect("Create completion folder");
File::create(save).expect("Open completion file")
};
generate(gen, cmd, cmd.get_name().to_string(), &mut file);
} else {
generate(gen, cmd, cmd.get_name().to_string(), &mut io::stdout());
}
}
impl Args {
pub fn get_config(&self) -> Result<InternalConfig, Box<dyn Error>> {
let config_file = if let Some(config) = &self.config {
if config.starts_with('/') {
PathBuf::from(config)
} else {
normalize(¤t_dir()?.join(config))
}
} else if self.system && cfg!(target_os = "linux") {
PathBuf::from("/etc/lnshm/config.toml")
} else {
dirs::home_dir().map(|it| it.join(".config/lnshm/config.toml")).unwrap_or_else(|| PathBuf::from("config.toml"))
};
let config_path = normalize(&config_file);
if !config_path.exists() {
if let Some(parent) = config_path.parent() {
create_dir_all(parent)?;
}
#[cfg(not(target_os = "windows"))]
let shm_path = if PathBuf::from("/dev/shm").exists() {// check if /dev/shm existed otherwise use temp directory
"/dev/shm/ln-shm".to_string()
} else {
temp_dir().join("ln-shm").to_string_lossy().to_string()
};
#[cfg(target_os = "windows")]
let shm_path = {
// Drive R: usually mounted as ramdisk drive
if PathBuf::from("R:\\").exists() {
"R:\\ln-shm".to_string()
} else {
temp_dir().join("ln-shm").to_string_lossy().to_string()
}
};
println!("Can't find config file creating new file..");
let data = Config {
shm_path,
configs: Default::default(),
};
let default_config = toml::to_string(&data)?;
let mut file = File::create(&config_file)?;
file.write_all(default_config.as_bytes())?;
};
Ok(InternalConfig {
config_file
})
}
}
pub(crate) struct InternalConfig {
pub config_file: PathBuf,
}