From cf4747c52be0c31076101656baae5560415fbf05 Mon Sep 17 00:00:00 2001 From: Donovan Glover Date: Sun, 28 Jul 2024 22:44:26 -0400 Subject: [PATCH] feat: add man pages and shell completions Auto-generated with clap. --- Cargo.lock | 49 ++++++++++++++++++++++++++++++++++------- Cargo.toml | 5 +++++ build.rs | 49 +++++++++++++++++++++++++++++++++++++++++ src/cli.rs | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 63 +++-------------------------------------------------- 5 files changed, 159 insertions(+), 68 deletions(-) create mode 100644 build.rs create mode 100644 src/cli.rs diff --git a/Cargo.lock b/Cargo.lock index 3815db3..d01c6ed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -127,6 +127,8 @@ dependencies = [ "anyhow", "chrono", "clap", + "clap_complete", + "clap_mangen", "cpal", "crossbeam", "crossterm 0.27.0", @@ -270,9 +272,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.1" +version = "4.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da" +checksum = "35723e6a11662c2afb578bcf0b88bf6ea8e21282a953428f240574fcc3a2b5b3" dependencies = [ "clap_builder", "clap_derive", @@ -280,9 +282,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.1" +version = "4.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb" +checksum = "49eb96cbfa7cfa35017b7cd548c75b14c3118c98b423041d70562665e07fb0fa" dependencies = [ "anstream", "anstyle", @@ -290,13 +292,22 @@ dependencies = [ "strsim", ] +[[package]] +name = "clap_complete" +version = "4.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6ae69fbb0833c6fcd5a8d4b8609f108c7ad95fc11e248d853ff2c42a90df26a" +dependencies = [ + "clap", +] + [[package]] name = "clap_derive" -version = "4.5.0" +version = "4.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" +checksum = "5d029b67f89d30bbb547c89fd5161293c0aec155fc691d7924b64550662db93e" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", "syn 2.0.49", @@ -308,6 +319,16 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +[[package]] +name = "clap_mangen" +version = "0.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17415fd4dfbea46e3274fcd8d368284519b358654772afb700dc2e8d2b24eeb" +dependencies = [ + "clap", + "roff", +] + [[package]] name = "colorchoice" version = "1.0.0" @@ -646,6 +667,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hound" version = "3.5.1" @@ -1190,6 +1217,12 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +[[package]] +name = "roff" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88f8660c1ff60292143c98d08fc6e2f654d722db50410e3f3797d40baaf9d8f3" + [[package]] name = "rustc-hash" version = "1.1.0" @@ -1302,7 +1335,7 @@ version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a3417fc93d76740d974a01654a09777cb500428cc874ca9f45edfe0c4d4cd18" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "rustversion", diff --git a/Cargo.toml b/Cargo.toml index 6e12d7e..4e753f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,11 @@ rand = "0.8.5" ratatui = "0.26.1" smallvec = "1.13.1" +[build-dependencies] +clap = { version = "4.5.4", features = ["derive"] } +clap_complete = "4.5.2" +clap_mangen = "0.2.20" + [features] default = ["cpal"] jack = ["cpal/jack"] diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..18e4fcc --- /dev/null +++ b/build.rs @@ -0,0 +1,49 @@ +include!("src/cli.rs"); + +use clap::Command; +use clap::CommandFactory; +use clap_complete::generate_to; +use clap_complete::Shell::{Bash, Fish, Zsh}; +use clap_mangen::Man; +use std::fs; +use std::path::PathBuf; + +static NAME: &str = "asak"; + +fn generate_man_pages(cmd: Command) { + let man_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("target/man"); + let mut buffer = Vec::default(); + + Man::new(cmd.clone()).render(&mut buffer).unwrap(); + fs::create_dir_all(&man_dir).unwrap(); + fs::write(man_dir.join(NAME.to_owned() + ".1"), buffer).unwrap(); + + for subcommand in cmd.get_subcommands() { + let mut buffer = Vec::default(); + + Man::new(subcommand.clone()).render(&mut buffer).unwrap(); + fs::write( + man_dir.join(NAME.to_owned() + "-" + subcommand.get_name() + ".1"), + buffer, + ) + .unwrap(); + } +} + +fn generate_shell_completions(mut cmd: Command) { + let comp_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("target/completions"); + + fs::create_dir_all(&comp_dir).unwrap(); + + for shell in [Bash, Fish, Zsh] { + generate_to(shell, &mut cmd, NAME, &comp_dir).unwrap(); + } +} + +fn main() { + let mut cmd = Cli::command(); + cmd.set_bin_name(NAME); + + generate_man_pages(cmd.clone()); + generate_shell_completions(cmd); +} diff --git a/src/cli.rs b/src/cli.rs new file mode 100644 index 0000000..47ca49f --- /dev/null +++ b/src/cli.rs @@ -0,0 +1,61 @@ +use clap::{Args, Parser, Subcommand}; + +/// Audio Swiss Army knife written in Rust. Like Sox but interactive with TUI. +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] +pub struct Cli { + #[command(subcommand)] + pub command: Commands, + + /// The audio device to use + #[arg(short, long, default_value_t = String::from("default"))] + pub device: String, + + /// Use the JACK host + #[cfg(all( + any( + target_os = "linux", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "netbsd" + ), + feature = "jack" + ))] + #[arg(short, long)] + #[allow(dead_code)] + pub jack: bool, +} + +#[derive(Debug, Subcommand)] +pub enum Commands { + /// Record an audio file + Rec(RecArgs), + /// Play an audio file + Play(PlayArgs), + /// Monitor audio input with scopes + Monitor(MonitorArgs), +} + +/// Arguments used for the `rec` command +#[derive(Args, Debug)] +pub struct RecArgs { + /// Path for the output audio file, e.g. `output` + #[arg(required = false)] + pub output: Option, +} + +/// Arguments used for the `play` command +#[derive(Args, Debug)] +pub struct PlayArgs { + /// Path to the audio file to play; must be wav format for now, e.g. `input.wav` + #[arg(required = false)] + pub input: Option, +} + +/// Arguments used for the `monitor` command +#[derive(Args, Debug)] +pub struct MonitorArgs { + /// Buffer size for the audio input monitoring, defaults to 1024, the higher the value the more latency + #[arg(required = false, short, long)] + pub buffer_size: Option, +} diff --git a/src/main.rs b/src/main.rs index 922199d..4ce8eb5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use clap::{Args, Parser, Subcommand}; +use clap::Parser; mod record; use inquire::{InquireError, Select, Text}; @@ -10,65 +10,8 @@ use playback::play_audio; mod monitor; use monitor::start_monitoring; -/// Audio Swiss Army knife written in Rust. Like Sox but interactive with TUI. -#[derive(Parser, Debug)] -#[command(author, version, about, long_about = None)] -struct Cli { - #[command(subcommand)] - command: Commands, - - /// The audio device to use - #[arg(short, long, default_value_t = String::from("default"))] - device: String, - - /// Use the JACK host - #[cfg(all( - any( - target_os = "linux", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "netbsd" - ), - feature = "jack" - ))] - #[arg(short, long)] - #[allow(dead_code)] - jack: bool, -} - -#[derive(Debug, Subcommand)] -enum Commands { - /// Record an audio file - Rec(RecArgs), - /// Play an audio file - Play(PlayArgs), - /// Monitor audio input with scopes - Monitor(MonitorArgs), -} - -/// Arguments used for the `rec` command -#[derive(Args, Debug)] -struct RecArgs { - /// Path for the output audio file, e.g. `output` - #[arg(required = false)] - output: Option, -} - -/// Arguments used for the `play` command -#[derive(Args, Debug)] -struct PlayArgs { - /// Path to the audio file to play; must be wav format for now, e.g. `input.wav` - #[arg(required = false)] - input: Option, -} - -/// Arguments used for the `monitor` command -#[derive(Args, Debug)] -struct MonitorArgs { - /// Buffer size for the audio input monitoring, defaults to 1024, the higher the value the more latency - #[arg(required = false, short, long)] - buffer_size: Option, -} +mod cli; +use cli::{Cli, Commands}; fn main() { let cli = Cli::parse();