use std::io::{Read, Write};
use std::path::{Path, PathBuf};
use usage::error::UsageErr;
use usage::Spec;
mod completion;
mod completion_init;
mod fig;
mod json;
mod manpage;
mod markdown;
mod sdk;
#[derive(clap::Args)]
#[clap(visible_alias = "g")]
pub struct Generate {
#[clap(subcommand)]
pub command: Command,
}
#[derive(clap::Subcommand)]
pub enum Command {
Completion(completion::Completion),
CompletionInit(completion_init::CompletionInit),
Fig(fig::Fig),
Json(json::Json),
Manpage(manpage::Manpage),
Markdown(markdown::Markdown),
Sdk(sdk::Sdk),
}
impl Generate {
pub fn run(&self) -> miette::Result<()> {
match &self.command {
Command::Completion(cmd) => cmd.run(),
Command::CompletionInit(cmd) => cmd.run(),
Command::Fig(cmd) => cmd.run(),
Command::Json(cmd) => cmd.run(),
Command::Manpage(cmd) => cmd.run(),
Command::Markdown(cmd) => cmd.run(),
Command::Sdk(cmd) => cmd.run(),
}
}
}
pub fn file_or_spec(file: &Option<PathBuf>, spec: &Option<String>) -> Result<Spec, UsageErr> {
if let Some(file) = file {
if file.as_os_str() == "-" {
read_spec_from_stdin()
} else {
Spec::parse_file(file)
}
} else {
spec.as_ref().unwrap().parse()
}
}
pub fn parse_file_or_stdin(file: &Path) -> Result<Spec, UsageErr> {
if file.as_os_str() == "-" {
read_spec_from_stdin()
} else {
Spec::parse_file(file)
}
}
pub fn write_or_stdout(out_file: Option<&Path>, contents: &str) -> Result<(), UsageErr> {
match out_file {
Some(path) if path.as_os_str() != "-" => {
eprintln!("writing to {}", path.display());
xx::file::write(path, contents)?;
}
_ => write_stdout(contents)?,
}
Ok(())
}
fn write_stdout(contents: &str) -> Result<(), UsageErr> {
let mut stdout = std::io::stdout().lock();
let wrote = stdout.write_all(contents.as_bytes()).and_then(|_| {
stdout.flush()
});
match wrote {
Err(err) if err.kind() == std::io::ErrorKind::BrokenPipe => Ok(()),
other => Ok(other?),
}
}
fn read_spec_from_stdin() -> Result<Spec, UsageErr> {
let mut input = String::new();
std::io::stdin().read_to_string(&mut input)?;
input.parse()
}