summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNora Widdecke <nora@sequoia-pgp.org>2022-07-19 13:10:46 +0200
committerNora Widdecke <nora@sequoia-pgp.org>2022-07-20 10:22:25 +0200
commit4ab507c6e4ad158382e66568085813deaba80559 (patch)
treed483f4580096ad79aab8873f30c7fc00f7a2be87
parent7f9e9712abe0aaae4c80a702b24a7c898ba56da7 (diff)
sq: Fix help generation for docs.
- Use clap-provided mechanisms instead of manually parsing --help output. - Fixes #872.
-rw-r--r--sq/build.rs92
-rw-r--r--sq/sq-usage.md223
2 files changed, 140 insertions, 175 deletions
diff --git a/sq/build.rs b/sq/build.rs
index 218144d7..04336019 100644
--- a/sq/build.rs
+++ b/sq/build.rs
@@ -1,8 +1,9 @@
use std::env;
use std::fs;
-use std::io::{self, Write};
+use std::io::Write;
use std::path::Path;
use clap_complete::Shell;
+use anyhow::Result;
pub mod sq_cli {
include!("src/sq_cli.rs");
@@ -15,20 +16,18 @@ fn main() {
subplot_build::codegen(Path::new("sq-subplot.md"))
.expect("failed to generate code with Subplot");
- // Dump help output of all commands and subcommands, for inlcusion in docs
- let mut sq = sq_cli::build().term_width(80);
- let mut main = fs::File::create("sq-usage.md").unwrap();
- dump_help(&mut main,
- &mut sq,
- vec![],
- "#").unwrap();
+ let mut sq = sq_cli::build();
+
+ // Dump help output of all commands and subcommands, for inclusion in docs
+ dump_help(sq.clone()).unwrap();
+ // Generate shell completions
let outdir = match env::var_os("CARGO_TARGET_DIR") {
None => return,
Some(outdir) => outdir,
};
+
fs::create_dir_all(&outdir).unwrap();
- let mut sq = sq_cli::build();
for shell in &[Shell::Bash, Shell::Fish, Shell::Zsh, Shell::PowerShell,
Shell::Elvish] {
@@ -37,36 +36,32 @@ fn main() {
};
}
-fn dump_help(sink: &mut dyn Write,
- sq: &mut clap::Command,
- cmd: Vec<String>,
- heading: &str)
- -> io::Result<()>
-{
-
- if cmd.is_empty() {
- writeln!(sink, "A command-line frontend for Sequoia.")?;
- writeln!(sink, "")?;
- writeln!(sink, "# Usage")?;
- } else {
- writeln!(sink, "")?;
- writeln!(sink, "{} Subcommand {}", heading, cmd.join(" "))?;
- }
+fn dump_help(mut cmd: clap::Command) -> Result<()> {
+ cmd = cmd.term_width(80);
+ cmd.build();
+ let mut sink = fs::File::create("sq-usage.md")?;
- writeln!(sink, "")?;
+ writeln!(sink, "A command-line frontend for Sequoia.")?;
+ writeln!(sink)?;
+ writeln!(sink, "# Usage")?;
+ dump_help_inner(&mut sink, &mut cmd, "##")
+}
- let args = std::iter::once("sq")
- .chain(cmd.iter().map(|s| s.as_str()))
- .chain(std::iter::once("--help"))
- .collect::<Vec<_>>();
+fn dump_help_inner(
+ sink: &mut dyn Write,
+ cmd: &mut clap::Command,
+ heading: &str,
+) -> Result<()> {
+ writeln!(sink)?;
- let help = sq.try_get_matches_from_mut(&args)
- .unwrap_err().to_string();
+ let mut buffer = Vec::new();
+ let _ = cmd.write_long_help(&mut buffer);
+ let help = std::str::from_utf8(buffer.as_slice())?;
writeln!(sink, "```text")?;
for line in help.trim_end().split('\n').skip(1) {
if line.is_empty() {
- writeln!(sink, "")?;
+ writeln!(sink)?;
} else {
writeln!(sink, "{}", line.trim_end())?;
}
@@ -74,26 +69,19 @@ fn dump_help(sink: &mut dyn Write,
writeln!(sink, "```")?;
// Recurse.
- let mut found_subcommands = false;
- for subcmd in help.split('\n').filter_map(move |line| {
- if line == "SUBCOMMANDS:" {
- found_subcommands = true;
- None
- } else if found_subcommands {
- if line.chars().nth(4).map(|c| ! c.is_ascii_whitespace())
- .unwrap_or(false)
- {
- line.trim_start().split(' ').next()
- } else {
- None
- }
- } else {
- None
- }
- }).filter(|subcmd| *subcmd != "help") {
- let mut c = cmd.clone();
- c.push(subcmd.into());
- dump_help(sink, sq, c, &format!("{}#", heading))?;
+ for subcommand in cmd
+ .get_subcommands_mut()
+ .filter(|sc| sc.get_name() != "help")
+ {
+ writeln!(sink)?;
+ let heading_name = subcommand
+ // cmd.build() in dump_help makes sure every subcommand has a display_name
+ .get_display_name()
+ .unwrap()
+ .replace('-', " ");
+ writeln!(sink, "{} Subcommand {}", heading, heading_name)?;
+
+ dump_help_inner(sink, subcommand, &format!("{}#", heading))?;
}
Ok(())
diff --git a/sq/sq-usage.md b/sq/sq-usage.md
index 392ed1be..68d5b8bc 100644
--- a/sq/sq-usage.md
+++ b/sq/sq-usage.md
@@ -82,7 +82,7 @@ SUBCOMMANDS:
Print this message or the help of the given subcommand(s)
```
-## Subcommand encrypt
+## Subcommand sq encrypt
```text
Encrypts a message
@@ -157,7 +157,7 @@ $ sq encrypt --recipient-cert romeo.pgp --signer-key juliet.pgp message.txt
$ sq encrypt --symmetric message.txt
```
-## Subcommand decrypt
+## Subcommand sq decrypt
```text
Decrypts a message
@@ -232,7 +232,7 @@ $ sq decrypt --recipient-key juliet.pgp --signer-cert romeo.pgp ciphertext.pgp
$ sq decrypt ciphertext.pgp
```
-## Subcommand sign
+## Subcommand sq sign
```text
Signs messages or data files
@@ -301,7 +301,7 @@ $ sq sign --signer-key juliet.pgp message.txt
$ sq sign --detached --signer-key juliet.pgp message.txt
```
-## Subcommand verify
+## Subcommand sq verify
```text
Verifies signed messages or detached signatures
@@ -362,7 +362,7 @@ If you are looking for a standalone program to verify detached
signatures, consider using sequoia-sqv.
```
-## Subcommand key
+## Subcommand sq key
```text
Manages keys
@@ -399,7 +399,7 @@ SUBCOMMANDS:
Print this message or the help of the given subcommand(s)
```
-### Subcommand key generate
+### Subcommand sq key generate
```text
Generates a new key
@@ -504,7 +504,7 @@ $ sq key generate --userid "<juliet@example.org>" --with-password
$ sq key generate --userid "<juliet@example.org>" --userid "Juliet Capulet"
```
-### Subcommand key password
+### Subcommand sq key password
```text
Changes password protecting secrets
@@ -547,7 +547,7 @@ $ sq key password < juliet.key.pgp > juliet.encrypted_key.pgp
$ sq key password --clear < juliet.encrypted_key.pgp > juliet.decrypted_key.pgp
```
-### Subcommand key userid
+### Subcommand sq key userid
```text
Manages User IDs
@@ -570,7 +570,7 @@ SUBCOMMANDS:
Print this message or the help of the given subcommand(s)
```
-#### Subcommand key userid add
+#### Subcommand sq key userid add
```text
Adds a User ID
@@ -628,7 +628,7 @@ $ sq key userid add --userid "Juliet" juliet.key.pgp \
--output juliet-new.key.pgp
```
-#### Subcommand key userid strip
+#### Subcommand sq key userid strip
```text
Strips a User ID
@@ -683,7 +683,7 @@ $ sq key userid strip --userid "<juliet@example.org>" \
--output juliet-new.key.pgp juliet.key.pgp
```
-### Subcommand key extract-cert
+### Subcommand sq key extract cert
```text
Converts a key to a cert
@@ -719,7 +719,7 @@ $ sq key generate --userid "<juliet@example.org>" --export juliet.key.pgp
$ sq key extract-cert --output juliet.cert.pgp juliet.key.pgp
```
-### Subcommand key attest-certifications
+### Subcommand sq key attest certifications
```text
@@ -767,7 +767,7 @@ $ sq key attest-certifications juliet.pgp
$ sq key attest-certifications --none juliet.pgp
```
-### Subcommand key adopt
+### Subcommand sq key adopt
```text
Binds keys from one certificate to another
@@ -811,7 +811,7 @@ EXAMPLES:
$ sq key adopt --keyring juliet-old.pgp --key 0123456789ABCDEF -- juliet-new.pgp
```
-## Subcommand keyring
+## Subcommand sq keyring
```text
Manages collections of keys or certs
@@ -846,7 +846,7 @@ SUBCOMMANDS:
Print this message or the help of the given subcommand(s)
```
-### Subcommand keyring list
+### Subcommand sq keyring list
```text
Lists keys in a keyring
@@ -878,7 +878,7 @@ $ sq keyring list certs.pgp
$ sq keyring filter --domain example.org certs.pgp | sq keyring list
```
-### Subcommand keyring split
+### Subcommand sq keyring split
```text
Splits a keyring into individual keys
@@ -915,7 +915,7 @@ $ sq keyring split certs.pgp
$ sq keyring merge certs.pgp | sq keyring split
```
-### Subcommand keyring join
+### Subcommand sq keyring join
```text
Joins keys or keyrings into a single keyring
@@ -948,7 +948,7 @@ EXAMPLES:
$ sq keyring join juliet.pgp romeo.pgp alice.pgp
```
-### Subcommand keyring merge
+### Subcommand sq keyring merge
```text
Merges keys or keyrings into a single keyring
@@ -981,7 +981,7 @@ EXAMPLES:
$ sq keyring merge certs.pgp romeo-updates.pgp
```
-### Subcommand keyring filter
+### Subcommand sq keyring filter
```text
Joins keys into a keyring applying a filter
@@ -1065,7 +1065,7 @@ $ sq keyring filter --domain example.org keys.pgp | \
$ sq keyring filter --domain example.org --prune-certs certs.pgp
```
-## Subcommand certify
+## Subcommand sq certify
```text
Certifies a User ID for a Certificate
@@ -1184,7 +1184,7 @@ EXAMPLES:
$ sq certify juliet.pgp romeo.pgp "<romeo@example.org>"
```
-## Subcommand autocrypt
+## Subcommand sq autocrypt
```text
Communicates certificates using Autocrypt
@@ -1212,7 +1212,7 @@ SUBCOMMANDS:
Print this message or the help of the given subcommand(s)
```
-### Subcommand autocrypt decode
+### Subcommand sq autocrypt decode
```text
Reads Autocrypt-encoded certificates
@@ -1245,7 +1245,7 @@ EXAMPLES:
$ sq autocrypt decode autocrypt.eml
```
-### Subcommand autocrypt encode-sender
+### Subcommand sq autocrypt encode sender
```text
Encodes a certificate into an Autocrypt header
@@ -1293,7 +1293,7 @@ $ sq autocrypt encode-sender --email juliet@example.org juliet.pgp
$ sq autocrypt encode-sender --prefer-encrypt mutual juliet.pgp
```
-## Subcommand keyserver
+## Subcommand sq keyserver
```text
Interacts with keyservers
@@ -1306,19 +1306,24 @@ OPTIONS:
Print help information
-p, --policy <NETWORK-POLICY>
- Sets the network policy to use [default: encrypted] [possible
- values: offline, anonymized, encrypted, insecure]
+ Sets the network policy to use
+
+ [default: encrypted]
+ [possible values: offline, anonymized, encrypted, insecure]
-s, --server <URI>
Sets the keyserver to use
SUBCOMMANDS:
- get Retrieves a key
- help Print this message or the help of the given subcommand(s)
- send Sends a key
+ get
+ Retrieves a key
+ help
+ Print this message or the help of the given subcommand(s)
+ send
+ Sends a key
```
-### Subcommand keyserver get
+### Subcommand sq keyserver get
```text
Retrieves a key
@@ -1327,16 +1332,22 @@ USAGE:
sq keyserver get [OPTIONS] <QUERY>
ARGS:
- <QUERY> Retrieve certificate(s) using QUERY. This may be a
- fingerprint, a KeyID, or an email address.
+ <QUERY>
+ Retrieve certificate(s) using QUERY. This may be a fingerprint, a
+ KeyID, or an email address.
OPTIONS:
- -B, --binary Emits binary data
- -h, --help Print help information
- -o, --output <FILE> Writes to FILE or stdout if omitted
+ -B, --binary
+ Emits binary data
+
+ -h, --help
+ Print help information
+
+ -o, --output <FILE>
+ Writes to FILE or stdout if omitted
```
-### Subcommand keyserver send
+### Subcommand sq keyserver send
```text
Sends a key
@@ -1345,13 +1356,15 @@ USAGE:
sq keyserver send [FILE]
ARGS:
- <FILE> Reads from FILE or stdin if omitted
+ <FILE>
+ Reads from FILE or stdin if omitted
OPTIONS:
- -h, --help Print help information
+ -h, --help
+ Print help information
```
-## Subcommand wkd
+## Subcommand sq wkd
```text
Interacts with Web Key Directories
@@ -1361,24 +1374,28 @@ USAGE:
OPTIONS:
-n, --network-policy <NETWORK-POLICY>
- Sets the network policy to use [default: encrypted] [possible
- values: offline, anonymized, encrypted, insecure]
+ Sets the network policy to use
+
+ [default: encrypted]
+ [possible values: offline, anonymized, encrypted, insecure]
-h, --help
Print help information
SUBCOMMANDS:
- generate Generates a Web Key Directory for the given domain and
- keys.
- get Queries for certs using Web Key Directory
- direct-url Prints the direct Web Key Directory URL of an email
- address.
- url Prints the advanced Web Key Directory URL of an email
- address.
- help Print this message or the help of the given subcommand(s)
+ generate
+ Generates a Web Key Directory for the given domain and keys.
+ get
+ Queries for certs using Web Key Directory
+ direct-url
+ Prints the direct Web Key Directory URL of an email address.
+ url
+ Prints the advanced Web Key Directory URL of an email address.
+ help
+ Print this message or the help of the given subcommand(s)
```
-### Subcommand wkd generate
+### Subcommand sq wkd generate
```text
Generates a Web Key Directory for the given domain and keys. If the WKD exists,
@@ -1430,7 +1447,7 @@ EXAMPLES:
$ sq wkd generate /tmp/wkdroot example.com certs.ppg
```
-### Subcommand wkd get
+### Subcommand sq wkd get
```text
Queries for certs using Web Key Directory
@@ -1439,15 +1456,21 @@ USAGE:
sq wkd get [OPTIONS] <ADDRESS>
ARGS:
- <ADDRESS> Queries a cert for ADDRESS
+ <ADDRESS>
+ Queries a cert for ADDRESS
OPTIONS:
- -B, --binary Emits binary data
- -h, --help Print help information
- -o, --output <FILE> Writes to FILE or stdout if omitted
+ -B, --binary
+ Emits binary data
+
+ -h, --help
+ Print help information
+
+ -o, --output <FILE>
+ Writes to FILE or stdout if omitted
```
-### Subcommand wkd direct-url
+### Subcommand sq wkd direct url
```text
Prints the direct Web Key Directory URL of an email address.
@@ -1456,13 +1479,15 @@ USAGE:
sq wkd direct-url <ADDRESS>
ARGS:
- <ADDRESS> Queries for ADDRESS
+ <ADDRESS>
+ Queries for ADDRESS
OPTIONS:
- -h, --help Print help information
+ -h, --help
+ Print help information
```
-### Subcommand wkd url
+### Subcommand sq wkd url
```text
Prints the advanced Web Key Directory URL of an email address.
@@ -1471,13 +1496,15 @@ USAGE:
sq wkd url <ADDRESS>
ARGS:
- <ADDRESS> Queries for ADDRESS
+ <ADDRESS>
+ Queries for ADDRESS
OPTIONS:
- -h, --help Print help information
+ -h, --help
+ Print help information
```
-## Subcommand armor
+## Subcommand sq armor
```text
Converts binary to ASCII
@@ -1518,7 +1545,7 @@ $ sq armor binary-juliet.pgp
$ sq armor binary-message.pgp
```
-## Subcommand dearmor
+## Subcommand sq dearmor
```text
Converts ASCII to binary
@@ -1554,7 +1581,7 @@ $ sq dearmor ascii-juliet.pgp
$ sq dearmor ascii-message.pgp
```
-## Subcommand inspect
+## Subcommand sq inspect
```text
Inspects data, like file(1)
@@ -1593,7 +1620,7 @@ $ sq inspect message.pgp
$ sq inspect message.sig
```
-## Subcommand packet
+## Subcommand sq packet
```text
Low-level packet manipulation
@@ -1624,7 +1651,7 @@ SUBCOMMANDS:
Print this message or the help of the given subcommand(s)
```
-### Subcommand packet dump
+### Subcommand sq packet dump
```text
@@ -1676,7 +1703,7 @@ $ sq packet dump --hex juliet.pgp
$ sq packet dump --session-key AAAABBBBCCCC... ciphertext.pgp
```
-### Subcommand packet decrypt
+### Subcommand sq packet decrypt
```text
Unwraps an encryption container
@@ -1720,7 +1747,7 @@ EXAMPLES:
$ sq packet decrypt --recipient-key juliet.pgp ciphertext.pgp
```
-### Subcommand packet split
+### Subcommand sq packet split
```text
Splits a message into packets
@@ -1752,7 +1779,7 @@ EXAMPLES:
$ sq packet split juliet.pgp
```
-### Subcommand packet join
+### Subcommand sq packet join
```text
Joins packets split across files
@@ -1795,7 +1822,7 @@ $ sq packet split juliet.pgp
$ sq packet join juliet.pgp-[0-3]*
```
-## Subcommand revoke
+## Subcommand sq revoke
```text
Generates revocation certificates.
@@ -1848,7 +1875,7 @@ $ sq revoke userid --time 20220101 --certificate juliet.pgp \
"Juliet <juliet@capuleti.it>" retired "I've left the family."
```
-### Subcommand revoke certificate
+### Subcommand sq revoke certificate
```text
Revokes a certificate
@@ -1944,7 +1971,7 @@ OPTIONS:
certificate's creation time
```
-### Subcommand revoke subkey
+### Subcommand sq revoke subkey
```text
Revokes a subkey
@@ -2041,7 +2068,7 @@ OPTIONS:
certificate's creation time
```
-### Subcommand revoke userid
+### Subcommand sq revoke userid
```text
Revokes a User ID
@@ -2125,53 +2152,3 @@ OPTIONS:
Chooses keys valid at the specified time and sets the revocation
certificate's creation time
```
-
-### Subcommand revoke EXAMPLES:
-
-```text
-
-USAGE:
- sq revoke <SUBCOMMAND>
-
-For more information try --help
-```
-
-### Subcommand revoke #
-
-```text
-
-USAGE:
- sq revoke <SUBCOMMAND>
-
-For more information try --help
-```
-
-### Subcommand revoke compromised
-
-```text
-
-USAGE:
- sq revoke <SUBCOMMAND>
-
-For more information try --help
-```
-
-### Subcommand revoke #
-
-```text
-
-USAGE:
- sq revoke <SUBCOMMAND>
-
-For more information try --help
-```
-
-### Subcommand revoke "Juliet
-
-```text
-
-USAGE:
- sq revoke <SUBCOMMAND>
-
-For more information try --help
-```