Created
March 10, 2020 09:53
-
-
Save ZaneHannanAU/389c0761e6975abceec74d72d378feeb to your computer and use it in GitHub Desktop.
stupid structopt thing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "structopt-example" | |
version = "0.1.0" | |
authors = ["Zane Hannan <[email protected]>"] | |
edition = "2018" | |
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | |
[dependencies] | |
structopt = { version = "0.3.11", features = [ "paw" ] } | |
paw = "1.0.0" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::{ | |
error::Error as Er, | |
ffi::OsStr, | |
fmt::{self, Display}, | |
fs::{create_dir_all, metadata, File, FileType}, | |
io::stdout, | |
path::PathBuf, | |
}; | |
use structopt::{clap::Shell, StructOpt}; | |
#[derive(StructOpt, Debug)] | |
#[non_exhaustive] | |
/// A stupid program | |
enum Opt { | |
/// Generate completions | |
Completions { | |
/// File or folder to generate completions in (- = stdout) | |
#[structopt(short = "f", long)] | |
to: Option<PathBuf>, | |
/// Shell(s) to generate completions for | |
shells: Vec<Shell>, | |
}, | |
} | |
#[paw::main] | |
fn main(opt: Opt) -> Result<(), Box<dyn Er>> { | |
match opt { | |
Opt::Completions { mut shells, mut to } => { | |
#[derive(Debug)] | |
struct BadFileType(PathBuf, FileType); | |
#[derive(Debug)] | |
struct NoShells; | |
#[derive(Debug)] | |
struct TooManyShells; | |
impl Display for BadFileType { | |
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
let BadFileType(path, file_type) = self; | |
let display = path.display(); | |
write!( | |
fmt, | |
"Bad file type: {} is not a file or folder (file type: {:?}).", | |
display, file_type | |
) | |
} | |
} | |
impl Display for NoShells { | |
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
fmt.write_str("No shells") | |
} | |
} | |
impl Display for TooManyShells { | |
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
fmt.write_str("Too many shells") | |
} | |
} | |
impl Er for BadFileType {} | |
impl Er for NoShells {} | |
impl Er for TooManyShells {} | |
let pkg = &std::env::args() | |
.nth(0) | |
.map(PathBuf::from) | |
.and_then(|bin| bin.file_name().and_then(OsStr::to_str).map(String::from)) | |
.unwrap_or_else(|| env!("CARGO_PKG_NAME").into()); | |
let mut cl = Opt::clap(); | |
if let Some(path) = to.as_ref() { | |
let fill = |shells: &mut Vec<Shell>| { | |
if shells.len() == 0 { | |
shells.extend({ | |
Shell::variants() | |
.iter() | |
.filter_map(|s| s.parse::<Shell>().ok()) | |
}); | |
} | |
}; | |
if path.is_dir() { | |
fill(&mut shells); | |
for shell in shells { | |
cl.gen_completions(pkg, shell, path); | |
} | |
} else if !path.exists() || path.is_file() { | |
if shells.len() == 1 { | |
let mut file = File::create(path)?; | |
cl.gen_completions_to(pkg, shells[0], &mut file); | |
} else { | |
fill(&mut shells); | |
create_dir_all(path)?; | |
for shell in shells { | |
cl.gen_completions(pkg, shell, path); | |
} | |
} | |
} else { | |
let meta = metadata(path.to_path_buf())?.file_type(); | |
Err(BadFileType(to.take().unwrap(), meta))?; | |
} | |
} else { | |
if shells.len() > 1 { | |
Err(TooManyShells)? | |
} else if shells.len() == 0 { | |
Err(NoShells)? | |
} | |
let st = stdout(); | |
cl.gen_completions_to(pkg, shells[0], &mut st.lock()); | |
} | |
} | |
} | |
Ok(()) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment