feat(cli): print completion scripts and the man page to stdout
`completions install` writes into a home directory, which a package build does not have. `completions print <shell>` and `man` give it the files to put under /usr/share instead.
This commit is contained in:
@@ -236,6 +236,9 @@ this skill file into the local agent directories, or remove it: `agent`,
|
||||
completion script where bash, zsh, or fish looks for it, or take it back
|
||||
again: `shell`, `path`, `action`. For a human at a prompt, not for you.
|
||||
|
||||
**`completions print <shell>`** and **`man`** — the completion script or the
|
||||
man page on stdout, raw rather than records. For whoever builds a package.
|
||||
|
||||
## Idioms
|
||||
|
||||
```bash
|
||||
|
||||
@@ -249,6 +249,9 @@ pub enum Commands {
|
||||
/// Tab completion for bash, zsh, and fish
|
||||
#[command(subcommand)]
|
||||
Completions(CompletionsCommand),
|
||||
|
||||
/// Print the man page to stdout, for packaging
|
||||
Man,
|
||||
}
|
||||
|
||||
#[derive(Args, Debug, Default)]
|
||||
@@ -315,6 +318,12 @@ pub enum CompletionsCommand {
|
||||
|
||||
/// Remove the completion script again
|
||||
Uninstall(CompletionsArgs),
|
||||
|
||||
/// Print the completion script to stdout, for packaging
|
||||
Print {
|
||||
#[arg(value_enum)]
|
||||
shell: Shell,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
|
||||
use super::{unwritable, xdg};
|
||||
use crate::cli::{Cli, CompletionsArgs, CompletionsCommand, Shell};
|
||||
use crate::output::{CliError, CliResult, CompletionRecord, Out};
|
||||
use crate::output::{CliError, CliResult, CompletionRecord, Exit, Out};
|
||||
use clap::CommandFactory;
|
||||
use directories::UserDirs;
|
||||
use std::io::Write;
|
||||
use std::io::{ErrorKind, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
/// The command being completed, and the file name the scripts are written as.
|
||||
@@ -65,6 +65,27 @@ pub fn run(out: &Out, command: &CompletionsCommand) -> CliResult {
|
||||
match command {
|
||||
CompletionsCommand::Install(args) => install(out, &targets(args)?),
|
||||
CompletionsCommand::Uninstall(args) => uninstall(out, &targets(args)?),
|
||||
CompletionsCommand::Print { shell } => print(&script(*shell)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn man() -> CliResult {
|
||||
let mut page = Vec::new();
|
||||
clap_mangen::Man::new(Cli::command().about("Soulseek client in Rust"))
|
||||
.render(&mut page)
|
||||
.expect("a Vec accepts every write");
|
||||
print(&page)
|
||||
}
|
||||
|
||||
fn print(bytes: &[u8]) -> CliResult {
|
||||
match std::io::stdout().write_all(bytes) {
|
||||
Err(error) if error.kind() != ErrorKind::BrokenPipe => {
|
||||
Err(CliError::new(
|
||||
Exit::Failure,
|
||||
format!("cannot write stdout: {error}"),
|
||||
))
|
||||
}
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -330,7 +330,8 @@ fn dispatch(ctx: &Ctx, command: Commands) -> CliResult {
|
||||
| Commands::Config(_)
|
||||
| Commands::Shares(_)
|
||||
| Commands::Skills(_)
|
||||
| Commands::Completions(_) => {
|
||||
| Commands::Completions(_)
|
||||
| Commands::Man => {
|
||||
Err(CliError::usage("handled without a session; see main::run"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,14 @@ pub fn run(mut cli: Cli, out: &Out) -> CliResult {
|
||||
}
|
||||
}
|
||||
|
||||
match &cli.command {
|
||||
Some(Commands::Completions(command)) => {
|
||||
return crate::commands::completions::run(out, command);
|
||||
}
|
||||
Some(Commands::Man) => return crate::commands::completions::man(),
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let config_path = config_path(&cli);
|
||||
let file_config = match &config_path {
|
||||
Some(path) => crate::persist::config::FileConfig::load(path)
|
||||
@@ -84,9 +92,6 @@ pub fn run(mut cli: Cli, out: &Out) -> CliResult {
|
||||
resolved.username.as_deref(),
|
||||
);
|
||||
}
|
||||
Commands::Completions(ref command) => {
|
||||
return crate::commands::completions::run(out, command);
|
||||
}
|
||||
Commands::Config(ConfigCommand::Path) => {
|
||||
return crate::commands::settings::config_path(out, &store);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user