summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNora Widdecke <nora@sequoia-pgp.org>2022-06-29 15:51:16 +0200
committerNora Widdecke <nora@sequoia-pgp.org>2022-07-05 13:51:48 +0200
commitf0d8b06ce5b0bbd889af7278c3ea43a96cffd50b (patch)
tree4068902770782686b82203b82e49ba479e17f5b3
parent4e519cdec81b59f75fe28c46415cf8dac1ae34f1 (diff)
sq: Derive top level command.
-rw-r--r--sq/Cargo.toml3
-rw-r--r--sq/build.rs4
-rw-r--r--sq/src/sq_cli.rs119
3 files changed, 65 insertions, 61 deletions
diff --git a/sq/Cargo.toml b/sq/Cargo.toml
index 7c12a9bd..a807f700 100644
--- a/sq/Cargo.toml
+++ b/sq/Cargo.toml
@@ -31,7 +31,6 @@ sequoia-openpgp = { path = "../openpgp", version = "1.1", default-features = fal
sequoia-autocrypt = { path = "../autocrypt", version = "0.24", default-features = false, optional = true }
sequoia-net = { path = "../net", version = "0.24", default-features = false }
anyhow = "1.0.18"
-cfg-if = "1"
chrono = "0.4.10"
clap = { version = "3", features = ["derive", "wrap_help"] }
itertools = "0.10"
@@ -42,7 +41,7 @@ rpassword = "5.0"
[build-dependencies]
anyhow = "1.0.18"
-clap = "3"
+clap = { version = "3", features = ["derive", "wrap_help"] }
clap_complete = "3"
sequoia-openpgp = { path = "../openpgp", version = "1.0.0", default-features = false }
subplot-build = "0.4.0"
diff --git a/sq/build.rs b/sq/build.rs
index 8e0ccabb..2264c000 100644
--- a/sq/build.rs
+++ b/sq/build.rs
@@ -17,9 +17,7 @@ fn main() {
subplot_build::codegen(Path::new("sq-subplot.md"))
.expect("failed to generate code with Subplot");
- let mut sq = sq_cli::configure(
- clap::Command::new("sq").term_width(80),
- );
+ let mut sq = sq_cli::build().term_width(80);
let mut main = fs::File::create("src/sq-usage.rs").unwrap();
dump_help(&mut main,
&mut sq,
diff --git a/sq/src/sq_cli.rs b/sq/src/sq_cli.rs
index d012e6c6..0fb2021a 100644
--- a/sq/src/sq_cli.rs
+++ b/sq/src/sq_cli.rs
@@ -1,5 +1,5 @@
/// Command-line parser for sq.
-use clap::{Arg, ArgGroup, Command, ArgEnum, Args, Subcommand};
+use clap::{ArgGroup, Command, ArgEnum, Args, Subcommand};
use clap::{CommandFactory, Parser};
use sequoia_openpgp as openpgp;
@@ -8,10 +8,18 @@ use openpgp::types::SymmetricAlgorithm;
use openpgp::fmt::hex;
pub fn build() -> Command<'static> {
- configure(Command::new("sq"))
+ let sq_version = Box::leak(
+ format!(
+ "{} (sequoia-openpgp {}, using {})",
+ env!("CARGO_PKG_VERSION"),
+ sequoia_openpgp::VERSION,
+ sequoia_openpgp::crypto::backend()
+ )
+ .into_boxed_str(),
+ ) as &str;
+ SqCommand::command().version(sq_version)
}
-// TODO: use clap_derive for the whole CLI
/// Defines the CLI.
///
/// The order of top-level subcommands is:
@@ -22,22 +30,11 @@ pub fn build() -> Command<'static> {
/// - Key discovery & networking (4xx)
/// - Armor (5xx)
/// - Inspection & packet manipulation (6xx)
-pub fn configure(
- app: Command<'static>
-) -> Command<'static> {
- let version = Box::leak(
- format!("{} (sequoia-openpgp {}, using {})",
- env!("CARGO_PKG_VERSION"),
- sequoia_openpgp::VERSION,
- sequoia_openpgp::crypto::backend())
- .into_boxed_str()) as &str;
-
- let app = app
- .version(version)
- .about("A command-line frontend for Sequoia, \
- an implementation of OpenPGP")
- .long_about(
-"A command-line frontend for Sequoia, an implementation of OpenPGP
+#[derive(Parser, Debug)]
+#[clap(
+ name = "sq",
+ about = "A command-line frontend for Sequoia, an implementation of OpenPGP",
+ long_about = "A command-line frontend for Sequoia, an implementation of OpenPGP
Functionality is grouped and available using subcommands. Currently,
this interface is completely stateless. Therefore, you need to supply
@@ -50,42 +47,52 @@ by default.
We use the term \"certificate\", or cert for short, to refer to OpenPGP
keys that do not contain secrets. Conversely, we use the term \"key\"
to refer to OpenPGP keys that do contain secrets.
-")
- .subcommand_required(true)
- .arg_required_else_help(true)
- .disable_colored_help(true)
- .arg(Arg::new("force")
- .short('f').long("force")
- .help("Overwrites existing files"))
- .arg(Arg::new("known-notation")
- .long("known-notation").value_name("NOTATION")
- .multiple_occurrences(true)
- .help("Adds NOTATION to the list of known notations")
- .long_help("Adds NOTATION to the list of known notations. \
- This is used when validating signatures. \
- Signatures that have unknown notations with the \
- critical bit set are considered invalid."));
-
- cfg_if::cfg_if! {
- if #[cfg(feature = "autocrypt")] {
- let app = app.subcommand(autocrypt::AutocryptCommand::command());
- }
- };
-
- app.subcommand(ArmorCommand::command())
- .subcommand(DearmorCommand::command())
- .subcommand(SignCommand::command())
- .subcommand(VerifyCommand::command())
- .subcommand(WkdCommand::command())
- .subcommand(KeyserverCommand::command())
- .subcommand(RevokeCommand::command())
- .subcommand(PacketCommand::command())
- .subcommand(CertifyCommand::command())
- .subcommand(KeyringCommand::command())
- .subcommand(KeyCommand::command())
- .subcommand(InspectCommand::command())
- .subcommand(EncryptCommand::command())
- .subcommand(DecryptCommand::command())
+",
+ subcommand_required = true,
+ arg_required_else_help = true,
+ disable_colored_help = true,
+)]
+struct SqCommand {
+ #[clap(
+ short = 'f',
+ long = "force",
+ help = "Overwrites existing files",
+ )]
+ pub force: bool,
+ #[clap(
+ long = "known-notation",
+ value_name = "NOTATION",
+ multiple_occurrences = true,
+ help = "Adds NOTATION to the list of known notations",
+ long_help = "Adds NOTATION to the list of known notations. \
+ This is used when validating signatures. \
+ Signatures that have unknown notations with the \
+ critical bit set are considered invalid."
+ )]
+ // TODO is this the right type?
+ pub known_notation: Vec<String>,
+ #[clap(subcommand)]
+ pub subcommand: SqSubcommands,
+}
+
+#[derive(Debug, Subcommand)]
+pub enum SqSubcommands {
+ Armor(ArmorCommand),
+ Dearmor(DearmorCommand),
+ Sign(SignCommand),
+ Verify(VerifyCommand),
+ Wkd(WkdCommand),
+ Keyserver(KeyserverCommand),
+ Revoke(RevokeCommand),
+ Packet(PacketCommand),
+ Certify(CertifyCommand),
+ Keyring(KeyringCommand),
+ Key(KeyCommand),
+ Inspect(InspectCommand),
+ Encrypt(EncryptCommand),
+ Decrypt(DecryptCommand),
+ #[cfg(feature = "autocrypt")]
+ Autocrypt(autocrypt::AutocryptCommand),
}
#[derive(Debug, Args)]
@@ -2250,7 +2257,7 @@ $ sq inspect message.pgp
$ sq inspect message.sig
",
)]
-struct InspectCommand {
+pub struct InspectCommand {
#[clap(
value_name = "FILE",
help = "Reads from FILE or stdin if omitted",