2022-12-20 19:23:41 -05:00
|
|
|
use crate::cmd;
|
2022-12-22 19:09:44 -05:00
|
|
|
use clap::{value_parser, Arg, ArgAction, ArgMatches, Command};
|
|
|
|
use clap_complete::{generate_to, shells, Generator};
|
|
|
|
use clap_complete_nushell::Nushell;
|
2022-12-20 19:23:41 -05:00
|
|
|
use clap_mangen::Man;
|
2022-12-22 19:09:44 -05:00
|
|
|
use std::{
|
|
|
|
fs, io,
|
|
|
|
path::{Path, PathBuf},
|
|
|
|
process,
|
|
|
|
};
|
2022-12-20 19:23:41 -05:00
|
|
|
|
2022-12-21 20:19:38 -05:00
|
|
|
const COMMANDS: [fn() -> clap::Command; 8] = [
|
|
|
|
cmd::bootstrap::cli,
|
|
|
|
cmd::echo::cli,
|
|
|
|
cmd::r#false::cli,
|
|
|
|
cmd::head::cli,
|
|
|
|
cmd::hostname::cli,
|
|
|
|
cmd::r#true::cli,
|
|
|
|
cmd::sleep::cli,
|
|
|
|
crate::cli::cli,
|
2022-12-20 19:23:41 -05:00
|
|
|
];
|
2022-12-20 12:05:21 -05:00
|
|
|
|
2022-12-20 18:35:45 -05:00
|
|
|
#[must_use]
|
2022-12-20 12:05:21 -05:00
|
|
|
pub fn cli() -> Command {
|
|
|
|
Command::new("bootstrap")
|
|
|
|
.version(env!("CARGO_PKG_VERSION"))
|
|
|
|
.author("Nathan Fisher")
|
|
|
|
.about("Install shitbox into the filesystem")
|
|
|
|
.long_about("Install symlinks, manpages and shell completions")
|
|
|
|
.args([
|
|
|
|
Arg::new("prefix")
|
|
|
|
.help("The directory path under which to install")
|
|
|
|
.short('p')
|
|
|
|
.long("prefix")
|
|
|
|
.num_args(1)
|
|
|
|
.default_value("/")
|
|
|
|
.required(false),
|
|
|
|
Arg::new("usr")
|
|
|
|
.help("Use /usr")
|
|
|
|
.long_help(
|
|
|
|
"Split the installation so that some applets go into /bin | /sbin\n\
|
|
|
|
while others are placed into /usr/bin | /usr/sbin",
|
|
|
|
)
|
|
|
|
.short('u')
|
|
|
|
.long("usr")
|
|
|
|
.default_value("true")
|
|
|
|
.value_parser(value_parser!(bool)),
|
|
|
|
])
|
|
|
|
.subcommands([
|
|
|
|
Command::new("all").about("Install everything"),
|
|
|
|
Command::new("links")
|
|
|
|
.about("Install links for each applet")
|
|
|
|
.arg(
|
|
|
|
Arg::new("soft")
|
|
|
|
.help("Install soft links instead of hardlinks")
|
|
|
|
.short('s')
|
|
|
|
.long("soft"),
|
|
|
|
),
|
|
|
|
Command::new("manpages")
|
|
|
|
.about("Install Unix man pages")
|
|
|
|
.alias("man"),
|
|
|
|
Command::new("completions")
|
|
|
|
.about("Install shell completions")
|
|
|
|
.alias("comp")
|
|
|
|
.args([
|
|
|
|
Arg::new("all")
|
|
|
|
.help("Install completions for all supported shells")
|
|
|
|
.short('a')
|
2022-12-21 20:19:38 -05:00
|
|
|
.long("all")
|
|
|
|
.action(ArgAction::SetTrue),
|
2022-12-20 12:05:21 -05:00
|
|
|
Arg::new("bash")
|
|
|
|
.help("Bash shell completions")
|
|
|
|
.short('b')
|
2022-12-21 20:19:38 -05:00
|
|
|
.long("bash")
|
|
|
|
.action(ArgAction::SetTrue),
|
2022-12-20 12:05:21 -05:00
|
|
|
Arg::new("fish")
|
|
|
|
.help("Fish shell completions")
|
|
|
|
.short('f')
|
2022-12-21 20:19:38 -05:00
|
|
|
.long("fish")
|
|
|
|
.action(ArgAction::SetTrue),
|
2022-12-20 12:05:21 -05:00
|
|
|
Arg::new("nu")
|
|
|
|
.help("Nushell completions")
|
|
|
|
.short('n')
|
2022-12-21 20:19:38 -05:00
|
|
|
.long("nu")
|
|
|
|
.action(ArgAction::SetTrue),
|
2022-12-20 12:05:21 -05:00
|
|
|
Arg::new("pwsh")
|
|
|
|
.help("PowerShell completions")
|
|
|
|
.short('p')
|
2022-12-21 20:19:38 -05:00
|
|
|
.long("pwsh")
|
|
|
|
.action(ArgAction::SetTrue),
|
2022-12-20 12:05:21 -05:00
|
|
|
]),
|
|
|
|
])
|
|
|
|
}
|
|
|
|
|
2022-12-21 20:19:38 -05:00
|
|
|
fn manpage(prefix: &str, f: &dyn Fn() -> Command) -> Result<(), io::Error> {
|
|
|
|
let cmd = f();
|
|
|
|
let fname = match cmd.get_name() {
|
|
|
|
"bootstrap" => "shitbox-bootstrap.1".to_string(),
|
|
|
|
s => format!("{s}.1"),
|
2022-12-20 19:23:41 -05:00
|
|
|
};
|
|
|
|
let outdir: PathBuf = [prefix, "usr", "share", "man", "man1"].iter().collect();
|
|
|
|
if !outdir.exists() {
|
|
|
|
fs::create_dir_all(&outdir)?;
|
|
|
|
}
|
|
|
|
let mut outfile = outdir;
|
|
|
|
outfile.push(fname);
|
|
|
|
let man = Man::new(cmd);
|
|
|
|
let mut buffer: Vec<u8> = vec![];
|
|
|
|
man.render(&mut buffer)?;
|
|
|
|
fs::write(&outfile, buffer)?;
|
|
|
|
println!(" {}", outfile.display());
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn manpages(prefix: &str) -> Result<(), io::Error> {
|
|
|
|
println!("Generating Unix man pages:");
|
2022-12-22 19:09:44 -05:00
|
|
|
COMMANDS.iter().try_for_each(|cmd| manpage(prefix, &cmd))?;
|
2022-12-21 20:19:38 -05:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2022-12-22 19:09:44 -05:00
|
|
|
fn generate_completions(
|
|
|
|
outdir: &Path,
|
|
|
|
f: &dyn Fn() -> Command,
|
|
|
|
gen: impl Generator,
|
|
|
|
) -> Result<(), io::Error> {
|
2022-12-21 20:19:38 -05:00
|
|
|
let cmd = f();
|
|
|
|
let name = cmd.get_name();
|
|
|
|
let mut cmd = cmd.clone();
|
2022-12-22 19:09:44 -05:00
|
|
|
if !outdir.exists() {
|
|
|
|
fs::create_dir_all(&outdir)?;
|
|
|
|
}
|
|
|
|
let path = generate_to(gen, &mut cmd, name, outdir)?;
|
2022-12-21 20:19:38 -05:00
|
|
|
println!(" {}", path.display());
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn completions(prefix: &str, matches: &ArgMatches) -> Result<(), io::Error> {
|
|
|
|
println!("Generating completions:");
|
|
|
|
if matches.get_flag("bash") || matches.get_flag("all") {
|
|
|
|
let outdir: PathBuf = [prefix, "share", "bash-completion", "completion"]
|
|
|
|
.iter()
|
|
|
|
.collect();
|
2022-12-22 19:09:44 -05:00
|
|
|
COMMANDS
|
|
|
|
.iter()
|
|
|
|
.try_for_each(|cmd| generate_completions(&outdir, &cmd, shells::Bash))?;
|
2022-12-21 20:19:38 -05:00
|
|
|
}
|
|
|
|
if matches.get_flag("fish") || matches.get_flag("all") {
|
2022-12-22 19:09:44 -05:00
|
|
|
let outdir: PathBuf = [prefix, "share", "fish", "completions"].iter().collect();
|
|
|
|
COMMANDS
|
2022-12-21 20:19:38 -05:00
|
|
|
.iter()
|
2022-12-22 19:09:44 -05:00
|
|
|
.try_for_each(|cmd| generate_completions(&outdir, &cmd, shells::Fish))?;
|
2022-12-21 20:19:38 -05:00
|
|
|
}
|
|
|
|
if matches.get_flag("nu") || matches.get_flag("all") {
|
2022-12-22 19:09:44 -05:00
|
|
|
let outdir: PathBuf = [prefix, "share", "nu", "completions"].iter().collect();
|
|
|
|
COMMANDS
|
|
|
|
.iter()
|
|
|
|
.try_for_each(|cmd| generate_completions(&outdir, &cmd, Nushell))?;
|
2022-12-21 20:19:38 -05:00
|
|
|
}
|
|
|
|
if matches.get_flag("pwsh") || matches.get_flag("all") {
|
2022-12-22 19:09:44 -05:00
|
|
|
let outdir: PathBuf = [prefix, "share", "pwsh", "completions"].iter().collect();
|
|
|
|
COMMANDS
|
|
|
|
.iter()
|
|
|
|
.try_for_each(|cmd| generate_completions(&outdir, &cmd, shells::PowerShell))?;
|
2022-12-21 20:19:38 -05:00
|
|
|
}
|
|
|
|
if matches.get_flag("zsh") || matches.get_flag("all") {
|
2022-12-22 19:09:44 -05:00
|
|
|
let outdir: PathBuf = [prefix, "share", "zsh", "site-functions"].iter().collect();
|
|
|
|
COMMANDS
|
|
|
|
.iter()
|
|
|
|
.try_for_each(|cmd| generate_completions(&outdir, &cmd, shells::Zsh))?;
|
2022-12-21 20:19:38 -05:00
|
|
|
}
|
2022-12-20 19:23:41 -05:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn run(matches: &ArgMatches) {
|
|
|
|
if let Some(prefix) = matches.get_one::<String>("prefix") {
|
|
|
|
match matches.subcommand() {
|
|
|
|
Some(("manpages", _matches)) => {
|
2022-12-21 20:19:38 -05:00
|
|
|
if let Err(e) = manpages(prefix) {
|
|
|
|
eprintln!("{e}");
|
|
|
|
process::exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Some(("completions", matches)) => {
|
|
|
|
if let Err(e) = completions(prefix, matches) {
|
|
|
|
eprintln!("{e}");
|
|
|
|
process::exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Some(("all", _matches)) => {
|
|
|
|
if let Err(e) = manpages(prefix) {
|
2022-12-20 19:23:41 -05:00
|
|
|
eprintln!("{e}");
|
|
|
|
process::exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|