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
extern crate clap;
extern crate colored;
extern crate git2;
extern crate hostname;
#[macro_use]
extern crate serde_json;
use clap::{App,Arg,ArgGroup,ArgMatches,SubCommand};
use std::path;
use std::env;
use std::process;
use std::ffi;
pub use self::error::Error;
pub use self::result::Result;
pub mod error;
pub mod result;
mod config;
mod destroy;
mod home;
mod init;
mod link;
mod unlink;
pub fn run(matches : &ArgMatches) -> Result<()> {
match matches.subcommand() {
("config", Some(sub_matches)) => config::run(&sub_matches),
("destroy", Some(sub_matches)) => destroy::run(&sub_matches),
("home", Some(sub_matches)) => home::run(&sub_matches),
("init", Some(sub_matches)) => init::run(&sub_matches),
("link", Some(sub_matches)) => link::run(&sub_matches),
("unlink", Some(sub_matches)) => unlink::run(&sub_matches),
_ => Ok(())
}
}
pub fn app<'a, 'b>() -> App<'a, 'b> {
App::new("Ellipsis")
.author("Andrew Lee <andrewtl@stanford.edu>")
.about("Manages your dotfiles")
.subcommand(SubCommand::with_name("config")
.about("Manages the configuation file")
.arg(Arg::with_name("edit")
.long("edit")
.short("e")
.help("Open the config file for editing")))
.subcommand(SubCommand::with_name("destroy")
.about("Destroy the current installation")
.arg(Arg::with_name("force")
.long("force")
.short("f")
.help("Force the deletion of the given files. Without this option,
this command will not modify the filesystem."))
.arg(Arg::with_name("dry-run")
.long("dry-run")
.short("n")
.help("Don't actually do anything, just show what would happen"))
.group(ArgGroup::with_name("effect")
.args(&["force", "dry-run"])
.required(true)))
.subcommand(SubCommand::with_name("home")
.about("Print the ellipsis home directory"))
.subcommand(SubCommand::with_name("init")
.about("Init the repository")
.arg(Arg::with_name("URI")
.index(1)
.required(true)
.help("The repository to fetch")))
.subcommand(SubCommand::with_name("link")
.about("Properly symlink files"))
.subcommand(SubCommand::with_name("unlink")
.about("Delete symlinks"))
}
pub fn home_dir() -> Option<path::PathBuf> {
if let Ok(str) = env::var("XDG_DATA_HOME") {
Some(path::PathBuf::from(str).join("ellipsis"))
} else {
if let Some(myhome) = env::home_dir() {
Some(myhome.join(".ellipsis"))
} else {
None
}
}
}
pub fn config_file() -> Option<path::PathBuf> {
if let Some(home) = home_dir() {
if let Some(hname) = hostname::get_hostname() {
Some(home.join(format!("{}.dot.json", hname)))
} else {
None
}
} else {
None
}
}
pub fn editor<P: AsRef<ffi::OsStr>>(path : P) -> Result<()> {
process::Command::new(
env::var("EDITOR").unwrap_or(String::from("vi")))
.arg(path)
.status()?;
Ok(())
}
#[cfg(test)]
mod test;