ellipsis/
lib.rs

1// Argument parsing
2extern crate clap;
3// Colors in the terminal
4extern crate colored;
5// Git stuff
6extern crate git2;
7// Get this machine's hostname
8extern crate hostname;
9// Working with JSON
10#[macro_use]
11extern crate serde_json;
12
13use clap::{App,Arg,ArgGroup,ArgMatches,SubCommand};
14
15use std::path;
16use std::env;
17use std::process;
18use std::ffi;
19
20// Use our error and result classes
21pub use self::error::Error;
22pub use self::result::Result;
23
24// Include error type
25pub mod error;
26pub mod result;
27
28// Include commands
29mod config;
30mod destroy;
31mod home;
32mod init;
33mod link;
34mod unlink;
35
36pub fn run(matches : &ArgMatches) -> Result<()> {
37    match matches.subcommand() {
38        ("config", Some(sub_matches))  => config::run(&sub_matches),
39        ("destroy", Some(sub_matches)) => destroy::run(&sub_matches),
40        ("home",    Some(sub_matches)) => home::run(&sub_matches),
41        ("init",    Some(sub_matches)) => init::run(&sub_matches),
42        ("link",    Some(sub_matches)) => link::run(&sub_matches),
43        ("unlink",  Some(sub_matches)) => unlink::run(&sub_matches),
44        _ => Ok(())
45    }
46}
47
48pub fn app<'a, 'b>() -> App<'a, 'b> {
49    App::new("Ellipsis")
50        .author("Andrew Lee <andrewtl@stanford.edu>")
51        .about("Manages your dotfiles")
52        .subcommand(SubCommand::with_name("config")
53                    .about("Manages the configuation file")
54                    .arg(Arg::with_name("edit")
55                         .long("edit")
56                         .short("e")
57                         .help("Open the config file for editing")))
58        .subcommand(SubCommand::with_name("destroy")
59                     .about("Destroy the current installation")
60                     .arg(Arg::with_name("force")
61                          .long("force")
62                          .short("f")
63                          .help("Force the deletion of the given files. Without this option,
64                       this command will not modify the filesystem."))
65                     .arg(Arg::with_name("dry-run")
66                          .long("dry-run")
67                          .short("n")
68                          .help("Don't actually do anything, just show what would happen"))
69                     .group(ArgGroup::with_name("effect")
70                            .args(&["force", "dry-run"])
71                            .required(true)))
72        .subcommand(SubCommand::with_name("home")
73                    .about("Print the ellipsis home directory"))
74        .subcommand(SubCommand::with_name("init")
75                    .about("Init the repository")
76                    .arg(Arg::with_name("URI")
77                         .index(1)
78                         .required(true)
79                         .help("The repository to fetch")))
80        .subcommand(SubCommand::with_name("link")
81                    .about("Properly symlink files"))
82        .subcommand(SubCommand::with_name("unlink")
83                    .about("Delete symlinks"))
84}
85
86// Return the "home directory" where the config files will be stored
87pub fn home_dir() -> Option<path::PathBuf> {
88    if let Ok(str) = env::var("XDG_DATA_HOME") {
89        Some(path::PathBuf::from(str).join("ellipsis"))
90    } else {
91
92        if let Some(myhome) = env::home_dir() {
93            Some(myhome.join(".ellipsis"))
94        } else {
95            None
96        }
97    }
98}
99
100// Return the location of this device's .dot.json
101pub fn config_file() -> Option<path::PathBuf> {
102    if let Some(home) = home_dir() {
103        if let Some(hname) = hostname::get_hostname() {
104            Some(home.join(format!("{}.dot.json", hname)))
105        } else {
106            None
107        }
108    } else {
109        None
110    }
111}
112
113pub fn editor<P: AsRef<ffi::OsStr>>(path : P) -> Result<()> {
114    process::Command::new(
115        env::var("EDITOR").unwrap_or(String::from("vi")))
116        .arg(path)
117        .status()?;
118    Ok(())
119}
120
121
122#[cfg(test)]
123mod test;