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
use rustc_serialize::Decodable;
use docopt;
use std::process;

use command;
use errors::CommandError;
use results::CommandResult;
use message::Message;
use config::Config;
use Slate;

const USAGE: &'static str = "
Slate: Manage your snippets from your command line.

Note that Slate will use the file ~/.slate to save
its contents.

Usage:
  slate <command> [<args>...]
  slate [options]

Options:
  -h --help      Show this screen.
  -v --version   Show version.

Commands:
   set     Write a new key and value.
   get     Read a key.
   list    List all keys.
   rename  Rename a key.
   remove  Delete a key.
   exec    Run a key value as a command.
   snippet Get a key and replace all placeholders with new data.
";

#[derive(Debug, RustcDecodable)]
enum Command {
    Set,
    Get,
    List,
    Remove,
    Rename,
    Exec,
    Snippet,
}

impl Command {
    fn run(self, slate: &Slate, argv: &Vec<String>) -> CommandResult {
        match self {
            Command::Set => command::set::run(slate, argv),
            Command::Get => command::get::run(slate, argv),
            Command::List => command::list::run(slate, argv),
            Command::Remove => command::remove::run(slate, argv),
            Command::Rename => command::rename::run(slate, argv),
            Command::Exec => command::exec::run(slate, argv),
            Command::Snippet => command::snippet::run(slate, argv),
        }
    }
}

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_command: Command,
    flag_help: bool,
    flag_version: bool,
}

/// Main entry point of the command.
///
/// It executes the given command and handles its output and errors.
pub fn run(argv: Vec<String>) {
    let args: Args = parse_main_args(USAGE, &argv).unwrap_or_else(|e| e.exit());

    let command = args.arg_command;

    let config = Config::new();
    let slate: Slate = From::from(&config);

    match command.run(&slate, &argv) {
        Err(e) => error(e),
        Ok(message) => out(message),
    };
}

/// Parse arguments based on a USAGE slice string.
///
/// This is used mainly by subcommands.
pub fn parse_args<T>(usage: &str, argv: &Vec<String>) -> Result<T, docopt::Error>
    where T: Decodable
{
    docopt::Docopt::new(usage).and_then(|d| {
        d.argv(argv)
            .version(Some(super::version()))
            .decode()
    })
}

/// Parse arguments for the main command.
fn parse_main_args<T>(usage: &str, argv: &Vec<String>) -> Result<T, docopt::Error>
    where T: Decodable
{
    docopt::Docopt::new(usage).and_then(|d| {
        d.argv(argv)
            .options_first(true)
            .version(Some(super::version()))
            .decode()
    })
}

/// Show errors to the user.
fn error(err: CommandError) {
    println!("{}", err);
    process::exit(1);
}

/// Show program messages to the user.
fn out(message: Option<Message>) {
    if let Some(msg) = message {
        print!("{}", msg);
    };
    process::exit(0);
}