mod ls;
mod mkdir;
mod osstr;
mod touch;
use std::ffi::{OsStr, OsString};
use std::path::Path;
const EXIT_CODE_INVALID_USAGE: i32 = 1;
const EXIT_CODE_NO_CWD: i32 = 2;
const EXIT_CODE_READ_DIR: i32 = 3;
const EXIT_CODE_UNKNOWN_ERR: i32 = 255;
fn main() {
match main_code() {
Some(exit_code) => std::process::exit(exit_code),
None => return
}
}
fn main_code() -> Option<i32> {
let mut args: Vec<_> = std::env::args_os().collect();
if args.len() == 0 {
print_usage();
return Some(EXIT_CODE_INVALID_USAGE)
} else {
let cmd = match executable_name(&args[0]) {
Some(cmd) => cmd,
None => {
print_usage();
return Some(EXIT_CODE_INVALID_USAGE)
}
};
if cmd == "busycrate" {
if args.len() < 2 {
print_usage();
return None
}
return run_with_args(cmd, &args[1..])
} else {
if let Some(exe) = executable_name(&args[0]) {
let cmd_name = exe.to_os_string();
args[0] = cmd_name;
}
return run_with_args(OsStr::new("busycrate"), &args[0..])
}
}
}
fn executable_name(first_cli_arg: &OsStr) -> Option<&OsStr> {
let cmd: &Path = first_cli_arg.as_ref();
let cmd = match cmd.file_name() {
Some(c) => c,
None => {
eprintln!("{}: not a command", cmd.display());
return None
}
};
Some(cmd)
}
fn run_with_args(busycrate: &OsStr, args: &[OsString]) -> Option<i32> {
use clap::{App, Arg, SubCommand};
fn map_os_args_to_path_vec<'a>(os_args: clap::OsValues<'a>) -> Vec<&'a Path> {
os_args.map(|os_str| os_str.as_ref()).collect()
};
let cmd = [busycrate.to_os_string()];
let args = cmd.iter().chain(args);
let app = App::new("BusyCrate")
.version(clap::crate_version!())
.author(clap::crate_authors!("\n"))
.about("List directory contents")
.subcommand(SubCommand::with_name("ls")
.arg(Arg::with_name("dirs")
.takes_value(true)
.multiple(true)
)
.arg(Arg::with_name("all")
.short("a")
.long("all")
)
)
.subcommand(SubCommand::with_name("touch")
.arg(Arg::with_name("fpaths")
.takes_value(true)
.multiple(true)
)
)
.subcommand(SubCommand::with_name("mkdir")
.arg(Arg::with_name("dpaths")
.takes_value(true)
.multiple(true)
)
);
let matches = app.get_matches_from(args);
if let Some(ls_args) = matches.subcommand_matches("ls") {
let paths = if let Some(values) = ls_args.values_of_os("dirs") {
map_os_args_to_path_vec(values)
} else {
Vec::new()
};
let ls_args = ls::Args {
paths,
all: ls_args.is_present("all"),
};
return Some(ls::main(ls_args))
} if let Some(touch_args) = matches.subcommand_matches("touch") {
let paths = if let Some(values) = touch_args.values_of_os("fpaths") {
map_os_args_to_path_vec(values)
} else {
Vec::new()
};
let touch_args = touch::Args {
paths
};
return Some(touch::main(touch_args))
} if let Some(mkdir_args) = matches.subcommand_matches("mkdir") {
let paths = if let Some(values) = mkdir_args.values_of_os("dpaths") {
map_os_args_to_path_vec(values)
} else {
Vec::new()
};
let mkdir_args = mkdir::Args {
create_parents: false,
paths,
};
return Some(mkdir::main(mkdir_args))
} else {
print_usage();
return Some(1)
}
}
fn print_usage() {
println!("Usage: busycrate [--help] <command> [options]
<command> [options]");
}