diff --git a/rage/src/bin/rage-keygen/cli.rs b/rage/src/bin/rage-keygen/cli.rs new file mode 100644 index 0000000..60b4372 --- /dev/null +++ b/rage/src/bin/rage-keygen/cli.rs @@ -0,0 +1,34 @@ +use clap::{builder::Styles, ArgAction, Parser}; + +use crate::fl; + +#[derive(Debug, Parser)] +#[command(display_name = "rage-keygen")] +#[command(name = "rage-keygen")] +#[command(version)] +#[command(help_template = format!("\ +{{before-help}}{{about-with-newline}} +{}{}:{} {{usage}} + +{{all-args}}{{after-help}}\ + ", + Styles::default().get_usage().render(), + fl!("usage-header"), + Styles::default().get_usage().render_reset()))] +#[command(next_help_heading = fl!("flags-header"))] +#[command(disable_help_flag(true))] +#[command(disable_version_flag(true))] +pub(crate) struct AgeOptions { + #[arg(action = ArgAction::Help, short, long)] + #[arg(help = fl!("help-flag-help"))] + pub(crate) help: Option, + + #[arg(action = ArgAction::Version, short = 'V', long)] + #[arg(help = fl!("help-flag-version"))] + pub(crate) version: Option, + + #[arg(short, long)] + #[arg(value_name = fl!("output"))] + #[arg(help = fl!("keygen-help-flag-output"))] + pub(crate) output: Option, +} diff --git a/rage/src/bin/rage-keygen/main.rs b/rage/src/bin/rage-keygen/main.rs index 9f7e318..d374a3b 100644 --- a/rage/src/bin/rage-keygen/main.rs +++ b/rage/src/bin/rage-keygen/main.rs @@ -1,7 +1,7 @@ #![forbid(unsafe_code)] use age::{cli_common::file_io, secrecy::ExposeSecret}; -use clap::{builder::Styles, ArgAction, Parser}; +use clap::Parser; use i18n_embed::{ fluent::{fluent_language_loader, FluentLanguageLoader}, DesktopLanguageRequester, @@ -10,6 +10,7 @@ use lazy_static::lazy_static; use rust_embed::RustEmbed; use std::io::Write; +mod cli; mod error; #[derive(RustEmbed)] @@ -31,37 +32,6 @@ macro_rules! fl { }}; } -#[derive(Debug, Parser)] -#[command(display_name = "rage-keygen")] -#[command(name = "rage-keygen")] -#[command(version)] -#[command(help_template = format!("\ -{{before-help}}{{about-with-newline}} -{}{}:{} {{usage}} - -{{all-args}}{{after-help}}\ - ", - Styles::default().get_usage().render(), - fl!("usage-header"), - Styles::default().get_usage().render_reset()))] -#[command(next_help_heading = fl!("flags-header"))] -#[command(disable_help_flag(true))] -#[command(disable_version_flag(true))] -struct AgeOptions { - #[arg(action = ArgAction::Help, short, long)] - #[arg(help = fl!("help-flag-help"))] - help: Option, - - #[arg(action = ArgAction::Version, short = 'V', long)] - #[arg(help = fl!("help-flag-version"))] - version: Option, - - #[arg(short, long)] - #[arg(value_name = fl!("output"))] - #[arg(help = fl!("keygen-help-flag-output"))] - output: Option, -} - fn main() -> Result<(), error::Error> { env_logger::builder() .format_timestamp(None) @@ -76,7 +46,7 @@ fn main() -> Result<(), error::Error> { // Isolation Marks, so we disable them for now. LANGUAGE_LOADER.set_use_isolating(false); - let opts = AgeOptions::parse(); + let opts = cli::AgeOptions::parse(); let mut output = file_io::OutputWriter::new( opts.output, diff --git a/rage/src/bin/rage-mount/cli.rs b/rage/src/bin/rage-mount/cli.rs new file mode 100644 index 0000000..f2b44fc --- /dev/null +++ b/rage/src/bin/rage-mount/cli.rs @@ -0,0 +1,53 @@ +use clap::{builder::Styles, ArgAction, Parser}; + +use crate::fl; + +#[derive(Debug, Parser)] +#[command(display_name = "rage-mount")] +#[command(name = "rage-mount")] +#[command(version)] +#[command(help_template = format!("\ +{{before-help}}{{about-with-newline}} +{}{}:{} {{usage}} + +{{all-args}}{{after-help}}\ + ", + Styles::default().get_usage().render(), + fl!("usage-header"), + Styles::default().get_usage().render_reset()))] +#[command(next_help_heading = fl!("flags-header"))] +#[command(disable_help_flag(true))] +#[command(disable_version_flag(true))] +pub(crate) struct AgeMountOptions { + #[arg(help_heading = fl!("args-header"))] + #[arg(value_name = fl!("mnt-filename"))] + #[arg(help = fl!("help-arg-mnt-filename"))] + pub(crate) filename: String, + + #[arg(help_heading = fl!("args-header"))] + #[arg(value_name = fl!("mnt-mountpoint"))] + #[arg(help = fl!("help-arg-mnt-mountpoint"))] + pub(crate) mountpoint: String, + + #[arg(action = ArgAction::Help, short, long)] + #[arg(help = fl!("help-flag-help"))] + pub(crate) help: Option, + + #[arg(action = ArgAction::Version, short = 'V', long)] + #[arg(help = fl!("help-flag-version"))] + pub(crate) version: Option, + + #[arg(short, long)] + #[arg(value_name = fl!("mnt-types"))] + #[arg(help = fl!("help-arg-mnt-types", types = "\"tar\", \"zip\""))] + pub(crate) types: String, + + #[arg(long, value_name = "WF")] + #[arg(help = fl!("help-flag-max-work-factor"))] + pub(crate) max_work_factor: Option, + + #[arg(short, long)] + #[arg(value_name = fl!("identity"))] + #[arg(help = fl!("help-flag-identity"))] + pub(crate) identity: Vec, +} diff --git a/rage/src/bin/rage-mount/main.rs b/rage/src/bin/rage-mount/main.rs index 6030b8c..4e7485b 100644 --- a/rage/src/bin/rage-mount/main.rs +++ b/rage/src/bin/rage-mount/main.rs @@ -5,7 +5,7 @@ use age::{ cli_common::{read_identities, read_secret}, stream::StreamReader, }; -use clap::{builder::Styles, ArgAction, CommandFactory, Parser}; +use clap::{CommandFactory, Parser}; use fuse_mt::FilesystemMT; use fuser::MountOption; use i18n_embed::{ @@ -21,6 +21,7 @@ use std::fs::File; use std::io; use std::sync::mpsc; +mod cli; mod tar; mod zip; @@ -32,6 +33,7 @@ lazy_static! { static ref LANGUAGE_LOADER: FluentLanguageLoader = fluent_language_loader!(); } +#[macro_export] macro_rules! fl { ($message_id:literal) => {{ i18n_embed_fl::fl!($crate::LANGUAGE_LOADER, $message_id) @@ -125,56 +127,6 @@ impl fmt::Debug for Error { } } -#[derive(Debug, Parser)] -#[command(display_name = "rage-mount")] -#[command(name = "rage-mount")] -#[command(version)] -#[command(help_template = format!("\ -{{before-help}}{{about-with-newline}} -{}{}:{} {{usage}} - -{{all-args}}{{after-help}}\ - ", - Styles::default().get_usage().render(), - fl!("usage-header"), - Styles::default().get_usage().render_reset()))] -#[command(next_help_heading = fl!("flags-header"))] -#[command(disable_help_flag(true))] -#[command(disable_version_flag(true))] -struct AgeMountOptions { - #[arg(help_heading = fl!("args-header"))] - #[arg(value_name = fl!("mnt-filename"))] - #[arg(help = fl!("help-arg-mnt-filename"))] - filename: String, - - #[arg(help_heading = fl!("args-header"))] - #[arg(value_name = fl!("mnt-mountpoint"))] - #[arg(help = fl!("help-arg-mnt-mountpoint"))] - mountpoint: String, - - #[arg(action = ArgAction::Help, short, long)] - #[arg(help = fl!("help-flag-help"))] - help: Option, - - #[arg(action = ArgAction::Version, short = 'V', long)] - #[arg(help = fl!("help-flag-version"))] - version: Option, - - #[arg(short, long)] - #[arg(value_name = fl!("mnt-types"))] - #[arg(help = fl!("help-arg-mnt-types", types = "\"tar\", \"zip\""))] - types: String, - - #[arg(long, value_name = "WF")] - #[arg(help = fl!("help-flag-max-work-factor"))] - max_work_factor: Option, - - #[arg(short, long)] - #[arg(value_name = fl!("identity"))] - #[arg(help = fl!("help-flag-identity"))] - identity: Vec, -} - fn mount_fs( open: F, mountpoint: String, @@ -242,11 +194,11 @@ fn main() -> Result<(), Error> { LANGUAGE_LOADER.set_use_isolating(false); if console::user_attended() && args().len() == 1 { - AgeMountOptions::command().print_help()?; + cli::AgeMountOptions::command().print_help()?; return Ok(()); } - let opts = AgeMountOptions::parse(); + let opts = cli::AgeMountOptions::parse(); if opts.filename.is_empty() { return Err(Error::MissingFilename); diff --git a/rage/src/bin/rage/cli.rs b/rage/src/bin/rage/cli.rs new file mode 100644 index 0000000..2918941 --- /dev/null +++ b/rage/src/bin/rage/cli.rs @@ -0,0 +1,130 @@ +use std::path::Path; + +use clap::{builder::Styles, ArgAction, Parser}; + +use crate::fl; + +fn binary_name() -> String { + if let Some(arg) = std::env::args_os().next() { + Path::new(&arg) + .file_name() + .expect("is not directory") + .to_string_lossy() + .to_string() + } else { + "rage".into() + } +} + +fn usage() -> String { + let binary_name = binary_name(); + let recipient = fl!("recipient"); + let identity = fl!("identity"); + let input = fl!("input"); + let output = fl!("output"); + + format!( + "{binary_name} [--encrypt] -r {recipient} [-i {identity}] [-a] [-o {output}] [{input}]\n \ + {binary_name} --decrypt [-i {identity}] [-o {output}] [{input}]", + ) +} + +fn after_help() -> String { + let binary_name = binary_name(); + let keygen_name = format!("{}-keygen", binary_name); + let example_a = format!("$ {} -o key.txt", keygen_name); + let example_a_output = "age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p"; + let example_b = format!( + "$ tar cvz ~/data | {} -r {} > data.tar.gz.age", + binary_name, example_a_output, + ); + let example_c = format!( + "$ {} -d -i key.txt -o data.tar.gz data.tar.gz.age", + binary_name, + ); + + fl!( + "rage-after-help", + keygen_name = keygen_name, + example_a = example_a, + example_a_output = example_a_output, + example_b = example_b, + example_c = example_c, + ) +} + +#[derive(Debug, Parser)] +#[command(version)] +#[command(help_template = format!("\ +{{before-help}}{{about-with-newline}} +{}{}:{} {{usage}} + +{{all-args}}{{after-help}}\ + ", + Styles::default().get_usage().render(), + fl!("usage-header"), + Styles::default().get_usage().render_reset()))] +#[command(override_usage(usage()))] +#[command(next_help_heading = fl!("flags-header"))] +#[command(disable_help_flag(true))] +#[command(disable_version_flag(true))] +#[command(after_help(after_help()))] +pub(crate) struct AgeOptions { + #[arg(help_heading = fl!("args-header"))] + #[arg(value_name = fl!("input"))] + #[arg(help = fl!("help-arg-input"))] + pub(crate) input: Option, + + #[arg(action = ArgAction::Help, short, long)] + #[arg(help = fl!("help-flag-help"))] + pub(crate) help: Option, + + #[arg(action = ArgAction::Version, short = 'V', long)] + #[arg(help = fl!("help-flag-version"))] + pub(crate) version: Option, + + #[arg(short, long)] + #[arg(help = fl!("help-flag-encrypt"))] + pub(crate) encrypt: bool, + + #[arg(short, long)] + #[arg(help = fl!("help-flag-decrypt"))] + pub(crate) decrypt: bool, + + #[arg(short, long)] + #[arg(help = fl!("help-flag-passphrase"))] + pub(crate) passphrase: bool, + + #[arg(long, value_name = "WF")] + #[arg(help = fl!("help-flag-max-work-factor"))] + pub(crate) max_work_factor: Option, + + #[arg(short, long)] + #[arg(help = fl!("help-flag-armor"))] + pub(crate) armor: bool, + + #[arg(short, long)] + #[arg(value_name = fl!("recipient"))] + #[arg(help = fl!("help-flag-recipient"))] + pub(crate) recipient: Vec, + + #[arg(short = 'R', long)] + #[arg(value_name = fl!("recipients-file"))] + #[arg(help = fl!("help-flag-recipients-file"))] + pub(crate) recipients_file: Vec, + + #[arg(short, long)] + #[arg(value_name = fl!("identity"))] + #[arg(help = fl!("help-flag-identity"))] + pub(crate) identity: Vec, + + #[arg(short = 'j')] + #[arg(value_name = fl!("plugin-name"))] + #[arg(help = fl!("help-flag-plugin-name"))] + pub(crate) plugin_name: Option, + + #[arg(short, long)] + #[arg(value_name = fl!("output"))] + #[arg(help = fl!("help-flag-output"))] + pub(crate) output: Option, +} diff --git a/rage/src/bin/rage/main.rs b/rage/src/bin/rage/main.rs index d2adbeb..a389c58 100644 --- a/rage/src/bin/rage/main.rs +++ b/rage/src/bin/rage/main.rs @@ -9,7 +9,7 @@ use age::{ secrecy::ExposeSecret, Identity, IdentityFile, IdentityFileEntry, Recipient, }; -use clap::{builder::Styles, ArgAction, CommandFactory, Parser}; +use clap::{CommandFactory, Parser}; use i18n_embed::{ fluent::{fluent_language_loader, FluentLanguageLoader}, DesktopLanguageRequester, @@ -20,6 +20,9 @@ use std::fs::File; use std::io::{self, BufRead, BufReader}; use std::path::Path; +mod cli; +use cli::AgeOptions; + mod error; #[derive(RustEmbed)] @@ -233,131 +236,6 @@ fn read_recipients( Ok(recipients) } -fn binary_name() -> String { - if let Some(arg) = std::env::args_os().next() { - Path::new(&arg) - .file_name() - .expect("is not directory") - .to_string_lossy() - .to_string() - } else { - "rage".into() - } -} - -fn usage() -> String { - let binary_name = binary_name(); - let recipient = fl!("recipient"); - let identity = fl!("identity"); - let input = fl!("input"); - let output = fl!("output"); - - format!( - "{binary_name} [--encrypt] -r {recipient} [-i {identity}] [-a] [-o {output}] [{input}]\n \ - {binary_name} --decrypt [-i {identity}] [-o {output}] [{input}]", - ) -} - -fn after_help() -> String { - let binary_name = binary_name(); - let keygen_name = format!("{}-keygen", binary_name); - let example_a = format!("$ {} -o key.txt", keygen_name); - let example_a_output = "age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p"; - let example_b = format!( - "$ tar cvz ~/data | {} -r {} > data.tar.gz.age", - binary_name, example_a_output, - ); - let example_c = format!( - "$ {} -d -i key.txt -o data.tar.gz data.tar.gz.age", - binary_name, - ); - - fl!( - "rage-after-help", - keygen_name = keygen_name, - example_a = example_a, - example_a_output = example_a_output, - example_b = example_b, - example_c = example_c, - ) -} - -#[derive(Debug, Parser)] -#[command(version)] -#[command(help_template = format!("\ -{{before-help}}{{about-with-newline}} -{}{}:{} {{usage}} - -{{all-args}}{{after-help}}\ - ", - Styles::default().get_usage().render(), - fl!("usage-header"), - Styles::default().get_usage().render_reset()))] -#[command(override_usage(usage()))] -#[command(next_help_heading = fl!("flags-header"))] -#[command(disable_help_flag(true))] -#[command(disable_version_flag(true))] -#[command(after_help(after_help()))] -struct AgeOptions { - #[arg(help_heading = fl!("args-header"))] - #[arg(value_name = fl!("input"))] - #[arg(help = fl!("help-arg-input"))] - input: Option, - - #[arg(action = ArgAction::Help, short, long)] - #[arg(help = fl!("help-flag-help"))] - help: Option, - - #[arg(action = ArgAction::Version, short = 'V', long)] - #[arg(help = fl!("help-flag-version"))] - version: Option, - - #[arg(short, long)] - #[arg(help = fl!("help-flag-encrypt"))] - encrypt: bool, - - #[arg(short, long)] - #[arg(help = fl!("help-flag-decrypt"))] - decrypt: bool, - - #[arg(short, long)] - #[arg(help = fl!("help-flag-passphrase"))] - passphrase: bool, - - #[arg(long, value_name = "WF")] - #[arg(help = fl!("help-flag-max-work-factor"))] - max_work_factor: Option, - - #[arg(short, long)] - #[arg(help = fl!("help-flag-armor"))] - armor: bool, - - #[arg(short, long)] - #[arg(value_name = fl!("recipient"))] - #[arg(help = fl!("help-flag-recipient"))] - recipient: Vec, - - #[arg(short = 'R', long)] - #[arg(value_name = fl!("recipients-file"))] - #[arg(help = fl!("help-flag-recipients-file"))] - recipients_file: Vec, - - #[arg(short, long)] - #[arg(value_name = fl!("identity"))] - #[arg(help = fl!("help-flag-identity"))] - identity: Vec, - - #[arg(short = 'j')] - #[arg(value_name = fl!("plugin-name"))] - #[arg(help = fl!("help-flag-plugin-name"))] - plugin_name: Option, - - #[arg(short, long)] - #[arg(value_name = fl!("output"))] - #[arg(help = fl!("help-flag-output"))] - output: Option, -} - fn set_up_io( input: Option, output: Option,