From b8805b4a887de4df7b7ff6b352b76e45a0ba73aa Mon Sep 17 00:00:00 2001 From: Steven Roose Date: Thu, 7 Mar 2019 11:04:46 +0000 Subject: [PATCH] Refactor of argument structures --- src/bin/hal/cmd/address/create.rs | 21 +-- src/bin/hal/cmd/address/inspect.rs | 8 +- src/bin/hal/cmd/address/mod.rs | 3 +- src/bin/hal/cmd/bip32/derive.rs | 17 +- src/bin/hal/cmd/bip32/mod.rs | 2 +- src/bin/hal/cmd/ln/invoice/decode.rs | 13 +- src/bin/hal/cmd/ln/invoice/mod.rs | 4 +- src/bin/hal/cmd/ln/mod.rs | 2 +- src/bin/hal/cmd/mod.rs | 44 ++++- src/bin/hal/cmd/psbt/create.rs | 35 ++-- src/bin/hal/cmd/psbt/decode.rs | 16 +- src/bin/hal/cmd/psbt/edit.rs | 232 +++++++++++---------------- src/bin/hal/cmd/psbt/merge.rs | 40 ++--- src/bin/hal/cmd/psbt/mod.rs | 13 +- src/bin/hal/cmd/script/decode.rs | 7 +- src/bin/hal/cmd/script/mod.rs | 2 +- src/bin/hal/cmd/tx/decode.rs | 13 +- src/bin/hal/cmd/tx/encode.rs | 12 +- src/bin/hal/cmd/tx/mod.rs | 3 +- src/bin/hal/main.rs | 49 +++--- 20 files changed, 226 insertions(+), 310 deletions(-) diff --git a/src/bin/hal/cmd/address/create.rs b/src/bin/hal/cmd/address/create.rs index f8ee427..755f502 100644 --- a/src/bin/hal/cmd/address/create.rs +++ b/src/bin/hal/cmd/address/create.rs @@ -5,22 +5,11 @@ use cmd; use hal; pub fn subcommand<'a>() -> clap::App<'a, 'a> { - clap::SubCommand::with_name("create") - .about("create addresses") - .args(&cmd::args_networks()) - .arg(cmd::arg_yaml()) - .args(&[ - clap::Arg::with_name("pubkey") - .long("pubkey") - .help("a public key in hex") - .takes_value(true) - .required(false), - clap::Arg::with_name("script") - .long("script") - .help("a script in hex") - .takes_value(true) - .required(false), - ]) + cmd::subcommand("create", "create addresses").args(&cmd::opts_networks()).args(&[ + cmd::opt_yaml(), + cmd::opt("pubkey", "a public key in hex").takes_value(true).required(false), + cmd::opt("script", "a script in hex").takes_value(true).required(false), + ]) } pub fn execute<'a>(matches: &clap::ArgMatches<'a>) { diff --git a/src/bin/hal/cmd/address/inspect.rs b/src/bin/hal/cmd/address/inspect.rs index 7d703ed..5551194 100644 --- a/src/bin/hal/cmd/address/inspect.rs +++ b/src/bin/hal/cmd/address/inspect.rs @@ -6,10 +6,10 @@ use cmd; use hal; pub fn subcommand<'a>() -> clap::App<'a, 'a> { - clap::SubCommand::with_name("inspect") - .about("inspect addresses") - .arg(cmd::arg_yaml()) - .arg(clap::Arg::with_name("address").help("the address").takes_value(true).required(true)) + cmd::subcommand("inspect", "inspect addresses").args(&[ + cmd::opt_yaml(), + cmd::opt("address", "the address").takes_value(true).required(true), + ]) } pub fn execute<'a>(matches: &clap::ArgMatches<'a>) { diff --git a/src/bin/hal/cmd/address/mod.rs b/src/bin/hal/cmd/address/mod.rs index 20f573f..e5f72d6 100644 --- a/src/bin/hal/cmd/address/mod.rs +++ b/src/bin/hal/cmd/address/mod.rs @@ -6,8 +6,7 @@ mod create; mod inspect; pub fn subcommand<'a>() -> clap::App<'a, 'a> { - cmd::new_subcommand("address") - .about("work with addresses") + cmd::subcommand_group("address", "work with addresses") .subcommand(create::subcommand()) .subcommand(inspect::subcommand()) } diff --git a/src/bin/hal/cmd/bip32/derive.rs b/src/bin/hal/cmd/bip32/derive.rs index 7941f92..f1b7970 100644 --- a/src/bin/hal/cmd/bip32/derive.rs +++ b/src/bin/hal/cmd/bip32/derive.rs @@ -7,19 +7,10 @@ use std::str::FromStr; use cmd; pub fn subcommand<'a>() -> clap::App<'a, 'a> { - clap::SubCommand::with_name("derive") - .about("derive keys from an extended key") - .arg(cmd::arg_yaml()) - .args(&[ - clap::Arg::with_name("ext-key") - .help("extended public or private key") - .takes_value(true) - .required(true), - clap::Arg::with_name("derivation-path") - .help("the derivation path") - .takes_value(true) - .required(true), - ]) + cmd::subcommand("derive", "derive keys from an extended key").arg(cmd::opt_yaml()).args(&[ + cmd::opt("ext-key", "extended public or private key").takes_value(true).required(true), + cmd::opt("derivation-path", "the derivation path").takes_value(true).required(true), + ]) } pub fn execute<'a>(matches: &clap::ArgMatches<'a>) { diff --git a/src/bin/hal/cmd/bip32/mod.rs b/src/bin/hal/cmd/bip32/mod.rs index 8ae2c8a..30ed6c4 100644 --- a/src/bin/hal/cmd/bip32/mod.rs +++ b/src/bin/hal/cmd/bip32/mod.rs @@ -5,7 +5,7 @@ use cmd; mod derive; pub fn subcommand<'a>() -> clap::App<'a, 'a> { - cmd::new_subcommand("bip32").about("BIP-32 key derivation").subcommand(derive::subcommand()) + cmd::subcommand_group("bip32", "BIP-32 key derivation").subcommand(derive::subcommand()) } pub fn execute<'a>(matches: &clap::ArgMatches<'a>) { diff --git a/src/bin/hal/cmd/ln/invoice/decode.rs b/src/bin/hal/cmd/ln/invoice/decode.rs index bea96b4..ce2cfc3 100644 --- a/src/bin/hal/cmd/ln/invoice/decode.rs +++ b/src/bin/hal/cmd/ln/invoice/decode.rs @@ -5,16 +5,9 @@ use cmd; use hal; pub fn subcommand<'a>() -> clap::App<'a, 'a> { - clap::SubCommand::with_name("decode") - .about("decode Lightning invoices") - .args(&cmd::args_networks()) - .arg(cmd::arg_yaml()) - .arg( - clap::Arg::with_name("invoice") - .help("the invoice in bech32") - .takes_value(true) - .required(true), - ) + cmd::subcommand("decode", "decode Lightning invoices") + .args(&cmd::opts_networks()) + .args(&[cmd::opt_yaml(), cmd::arg("invoice", "the invoice in bech32").required(true)]) } pub fn execute<'a>(matches: &clap::ArgMatches<'a>) { diff --git a/src/bin/hal/cmd/ln/invoice/mod.rs b/src/bin/hal/cmd/ln/invoice/mod.rs index 1941833..b6a5455 100644 --- a/src/bin/hal/cmd/ln/invoice/mod.rs +++ b/src/bin/hal/cmd/ln/invoice/mod.rs @@ -5,9 +5,7 @@ use cmd; mod decode; pub fn subcommand<'a>() -> clap::App<'a, 'a> { - cmd::new_subcommand("invoice") - .about("handle Lightning invoices") - .subcommand(decode::subcommand()) + cmd::subcommand_group("invoice", "handle Lightning invoices").subcommand(decode::subcommand()) } pub fn execute<'a>(matches: &clap::ArgMatches<'a>) { diff --git a/src/bin/hal/cmd/ln/mod.rs b/src/bin/hal/cmd/ln/mod.rs index 0139845..dff9f44 100644 --- a/src/bin/hal/cmd/ln/mod.rs +++ b/src/bin/hal/cmd/ln/mod.rs @@ -5,7 +5,7 @@ use cmd; mod invoice; pub fn subcommand<'a>() -> clap::App<'a, 'a> { - cmd::new_subcommand("ln").about("everything Lightning").subcommand(invoice::subcommand()) + cmd::subcommand_group("ln", "everything Lightning").subcommand(invoice::subcommand()) } pub fn execute<'a>(matches: &clap::ArgMatches<'a>) { diff --git a/src/bin/hal/cmd/mod.rs b/src/bin/hal/cmd/mod.rs index 5f09f98..95c820e 100644 --- a/src/bin/hal/cmd/mod.rs +++ b/src/bin/hal/cmd/mod.rs @@ -7,15 +7,49 @@ pub mod tx; use bitcoin::Network; -/// Create a new subcommand using the template that sets all the common settings. -pub fn new_subcommand<'a>(name: &'static str) -> clap::App<'a, 'a> { +/// Build a list of all built-in subcommands. +pub fn subcommands<'a>() -> Vec> { + vec![ + address::subcommand(), + ln::subcommand(), + tx::subcommand(), + psbt::subcommand(), + script::subcommand(), + bip32::subcommand(), + ] +} + +/// Construct a new command option. +pub fn opt<'a>(name: &'static str, help: &'static str) -> clap::Arg<'a, 'a> { + clap::Arg::with_name(name).long(name).help(help) +} + +/// Construct a new positional argument. +pub fn arg<'a>(name: &'static str, help: &'static str) -> clap::Arg<'a, 'a> { + clap::Arg::with_name(name).help(help).takes_value(true) +} + +/// Create a new subcommand group using the template that sets all the common settings. +/// This is not intended for actual commands, but for subcommands that host a bunch of other +/// subcommands. +pub fn subcommand_group<'a>(name: &'static str, about: &'static str) -> clap::App<'a, 'a> { clap::SubCommand::with_name(name) + .about(about) .setting(clap::AppSettings::SubcommandRequiredElseHelp) - .setting(clap::AppSettings::AllowExternalSubcommands) + //.setting(clap::AppSettings::AllowExternalSubcommands) + .setting(clap::AppSettings::DisableHelpSubcommand) + .setting(clap::AppSettings::VersionlessSubcommands) +} + +/// Create a new subcommand using the template that sets all the common settings. +pub fn subcommand<'a>(name: &'static str, about: &'static str) -> clap::App<'a, 'a> { + clap::SubCommand::with_name(name) + .about(about) + .setting(clap::AppSettings::ArgRequiredElseHelp) .setting(clap::AppSettings::DisableHelpSubcommand) } -pub fn args_networks<'a>() -> Vec> { +pub fn opts_networks<'a>() -> Vec> { vec![ clap::Arg::with_name("testnet") .long("testnet") @@ -41,7 +75,7 @@ pub fn network<'a>(matches: &clap::ArgMatches<'a>) -> Network { } } -pub fn arg_yaml<'a>() -> clap::Arg<'a, 'a> { +pub fn opt_yaml<'a>() -> clap::Arg<'a, 'a> { clap::Arg::with_name("yaml") .long("yaml") .short("y") diff --git a/src/bin/hal/cmd/psbt/create.rs b/src/bin/hal/cmd/psbt/create.rs index 32200f7..c9aa4a2 100644 --- a/src/bin/hal/cmd/psbt/create.rs +++ b/src/bin/hal/cmd/psbt/create.rs @@ -9,30 +9,19 @@ use bitcoin::consensus::{deserialize, serialize}; use bitcoin::util::psbt; use bitcoin::Transaction; +use cmd; + pub fn subcommand<'a>() -> clap::App<'a, 'a> { - clap::SubCommand::with_name("create") - .about("create a PSBT from an unsigned raw transaction") - .arg( - clap::Arg::with_name("raw-tx") - .help("the raw transaction in hex") - .takes_value(true) - .required(true), - ) - .arg( - clap::Arg::with_name("output") - .long("output") - .short("o") - .help("where to save the merged PSBT output") - .takes_value(true) - .required(false), - ) - .arg( - clap::Arg::with_name("raw-stdout") - .long("raw") - .short("r") - .help("output the raw bytes of the result to stdout") - .required(false), - ) + cmd::subcommand("create", "create a PSBT from an unsigned raw transaction").args(&[ + cmd::arg("raw-tx", "the raw transaction in hex").required(true), + cmd::opt("output", "where to save the merged PSBT output") + .short("o") + .takes_value(true) + .required(false), + cmd::opt("raw-stdout", "output the raw bytes of the result to stdout") + .short("r") + .required(false), + ]) } pub fn execute<'a>(matches: &clap::ArgMatches<'a>) { diff --git a/src/bin/hal/cmd/psbt/decode.rs b/src/bin/hal/cmd/psbt/decode.rs index fa7afeb..5510d7d 100644 --- a/src/bin/hal/cmd/psbt/decode.rs +++ b/src/bin/hal/cmd/psbt/decode.rs @@ -6,16 +6,12 @@ use bitcoin::util::psbt; use cmd; pub fn subcommand<'a>() -> clap::App<'a, 'a> { - clap::SubCommand::with_name("decode") - .about("decode a PSBT to JSON") - .args(&cmd::args_networks()) - .arg(cmd::arg_yaml()) - .arg( - clap::Arg::with_name("psbt") - .help("the PSBT file or raw PSBT in hex") - .takes_value(true) - .required(true), - ) + cmd::subcommand("decode", "decode a PSBT to JSON").args(&cmd::opts_networks()).args(&[ + cmd::opt_yaml(), + cmd::opt("psbt", "the PSBT file or raw PSBT in base64/hex") + .takes_value(true) + .required(true), + ]) } pub fn execute<'a>(matches: &clap::ArgMatches<'a>) { diff --git a/src/bin/hal/cmd/psbt/edit.rs b/src/bin/hal/cmd/psbt/edit.rs index 3da598a..564bf27 100644 --- a/src/bin/hal/cmd/psbt/edit.rs +++ b/src/bin/hal/cmd/psbt/edit.rs @@ -11,148 +11,98 @@ use bitcoin::util::bip32; use bitcoin::util::psbt; use bitcoin::PublicKey; +use cmd; + pub fn subcommand<'a>() -> clap::App<'a, 'a> { - clap::SubCommand::with_name("edit") - .about("edit a PSBT") - .arg( - clap::Arg::with_name("psbt") - .help("PSBT to edit, either hex or a file reference") - .takes_value(true) - .required(true), - ) - .arg( - clap::Arg::with_name("input-idx") - .long("nin") - .help("the input index to edit") - .display_order(1) - .takes_value(true) - .required(false), - ) - .arg( - clap::Arg::with_name("output-idx") - .long("nout") - .help("the output index to edit") - .display_order(2) - .takes_value(true) - .required(false), - ) - .arg( - clap::Arg::with_name("output") - .long("output") - .short("o") - .help("where to save the resulting PSBT file -- in place if omitted") - .display_order(3) - .next_line_help(true) - .takes_value(true) - .required(false), - ) - .arg( - clap::Arg::with_name("raw-stdout") - .long("raw") - .short("r") - .help("output the raw bytes of the result to stdout") - .required(false), - ) - .args( - // values used in inputs and outputs - &[ - clap::Arg::with_name("redeem-script") - .long("redeem-script") - .help("the redeem script") - .display_order(99) - .next_line_help(true) - .takes_value(true) - .required(false), - clap::Arg::with_name("witness-script") - .long("witness-script") - .help("the witness script") - .display_order(99) - .next_line_help(true) - .takes_value(true) - .required(false), - clap::Arg::with_name("hd-keypaths") - .long("hd-keypaths") - .help("the HD wallet keypaths `::,...`") - .display_order(99) - .next_line_help(true) - .takes_value(true) - .required(false), - clap::Arg::with_name("hd-keypaths-add") - .long("hd-keypaths-add") - .help("add an HD wallet keypath `::`") - .display_order(99) - .next_line_help(true) - .takes_value(true) - .required(false), - ], - ) - .args( - // input values - &[ - clap::Arg::with_name("non-witness-utxo") - .long("non-witness-utxo") - .help("the non-witness UTXO field in hex (full transaction)") - .display_order(99) - .next_line_help(true) - .takes_value(true) - .required(false), - clap::Arg::with_name("witness-utxo") - .long("witness-utxo") - .help("the witness UTXO field in hex (only output)") - .display_order(99) - .next_line_help(true) - .takes_value(true) - .required(false), - clap::Arg::with_name("partial-sigs") - .long("partial-sigs") - .help("set partial sigs `:,...`") - .display_order(99) - .next_line_help(true) - .takes_value(true) - .required(false), - clap::Arg::with_name("partial-sigs-add") - .long("partial-sigs-add") - .help("add a partial sig pair `:`") - .display_order(99) - .next_line_help(true) - .takes_value(true) - .required(false), - clap::Arg::with_name("sighash-type") - .long("sighash-type") - .help("the sighash type") - .display_order(99) - .next_line_help(true) - .takes_value(true) - .required(false), - // redeem-script - // witness-script - // hd-keypaths - // hd-keypaths-add - clap::Arg::with_name("final-script-sig") - .long("final-script-sig") - .help("set final script signature") - .display_order(99) - .next_line_help(true) - .takes_value(true) - .required(false), - clap::Arg::with_name("final-script-witness") - .long("final-script-witness") - .help("set final script witness as comma-separated hex values") - .display_order(99) - .next_line_help(true) - .takes_value(true) - .required(false), - ], - ) - .args( - // output values - &[ - // redeem-script - // witness-script - // hd-keypaths - // hd-keypaths-add - ], - ) + cmd::subcommand("edit", "edit a PSBT").args(&[ + cmd::arg("psbt", "PSBT to edit, either base64/hex or a file path").required(true), + cmd::opt("input-idx", "the input index to edit") + .display_order(1) + .takes_value(true) + .required(false), + cmd::opt("output-idx", "the output index to edit") + .display_order(2) + .takes_value(true) + .required(false), + cmd::opt("output", "where to save the resulting PSBT file -- in place if omitted") + .short("o") + .display_order(3) + .next_line_help(true) + .takes_value(true) + .required(false), + cmd::opt("raw-stdout", "output the raw bytes of the result to stdout") + .short("r") + .required(false), + // + // values used in both inputs and outputs + cmd::opt("redeem-script", "the redeem script") + .display_order(99) + .next_line_help(true) + .takes_value(true) + .required(false), + cmd::opt("witness-script", "the witness script") + .display_order(99) + .next_line_help(true) + .takes_value(true) + .required(false), + cmd::opt("hd-keypaths", "the HD wallet keypaths `::,...`") + .display_order(99) + .next_line_help(true) + .takes_value(true) + .required(false), + cmd::opt("hd-keypaths-add", "add an HD wallet keypath `::`") + .display_order(99) + .next_line_help(true) + .takes_value(true) + .required(false), + // + // input values + cmd::opt("non-witness-utxo", "the non-witness UTXO field in hex (full transaction)") + .display_order(99) + .next_line_help(true) + .takes_value(true) + .required(false), + cmd::opt("witness-utxo", "the witness UTXO field in hex (only output)") + .display_order(99) + .next_line_help(true) + .takes_value(true) + .required(false), + cmd::opt("partial-sigs", "set partial sigs `:,...`") + .display_order(99) + .next_line_help(true) + .takes_value(true) + .required(false), + cmd::opt("partial-sigs-add", "add a partial sig pair `:`") + .display_order(99) + .next_line_help(true) + .takes_value(true) + .required(false), + cmd::opt("sighash-type", "the sighash type") + .display_order(99) + .next_line_help(true) + .takes_value(true) + .required(false), + // (omitted) redeem-script + // (omitted) witness-script + // (omitted) hd-keypaths + // (omitted) hd-keypaths-add + cmd::opt("final-script-sig", "set final script signature") + .display_order(99) + .next_line_help(true) + .takes_value(true) + .required(false), + cmd::opt("final-script-witness", "set final script witness as comma-separated hex values") + .display_order(99) + .next_line_help(true) + .takes_value(true) + .required(false), + // + // output values + // (omitted) redeem-script + // (omitted) witness-script + // (omitted) hd-keypaths + // (omitted) hd-keypaths-add + ]) } /// Parses a `:` pair. diff --git a/src/bin/hal/cmd/psbt/merge.rs b/src/bin/hal/cmd/psbt/merge.rs index 11fd424..26cfaf2 100644 --- a/src/bin/hal/cmd/psbt/merge.rs +++ b/src/bin/hal/cmd/psbt/merge.rs @@ -1,37 +1,27 @@ use std::fs::File; use std::io::Write; +use clap; + use bitcoin::consensus::deserialize; use bitcoin::consensus::serialize; use bitcoin::util::psbt; -use clap; +use cmd; pub fn subcommand<'a>() -> clap::App<'a, 'a> { - clap::SubCommand::with_name("merge") - .about("merge multiple PSBT files into one") - .arg( - clap::Arg::with_name("psbts") - .help("PSBTs to merge; can be files or hex") - .takes_value(true) - .multiple(true) - .required(true), - ) - .arg( - clap::Arg::with_name("output") - .long("output") - .short("o") - .help("where to save the merged PSBT output") - .takes_value(true) - .required(false), - ) - .arg( - clap::Arg::with_name("raw-stdout") - .long("raw") - .short("r") - .help("output the raw bytes of the result to stdout") - .required(false), - ) + cmd::subcommand("merge", "merge multiple PSBT files into one").args(&[ + cmd::arg("psbts", "PSBTs to merge; can be file paths or base64/hex") + .multiple(true) + .required(true), + cmd::opt("output", "where to save the merged PSBT output") + .short("o") + .takes_value(true) + .required(false), + cmd::opt("raw-stdout", "output the raw bytes of the result to stdout") + .short("r") + .required(false), + ]) } pub fn execute<'a>(matches: &clap::ArgMatches<'a>) { diff --git a/src/bin/hal/cmd/psbt/mod.rs b/src/bin/hal/cmd/psbt/mod.rs index d79f163..c181287 100644 --- a/src/bin/hal/cmd/psbt/mod.rs +++ b/src/bin/hal/cmd/psbt/mod.rs @@ -5,16 +5,15 @@ use base64; use clap; use hex; +use cmd; + mod create; mod decode; mod edit; mod merge; pub fn subcommand<'a>() -> clap::App<'a, 'a> { - clap::SubCommand::with_name("psbt") - .about("partially signed Bitcoin transactions") - .setting(clap::AppSettings::SubcommandRequiredElseHelp) - .setting(clap::AppSettings::DisableHelpSubcommand) + cmd::subcommand_group("psbt", "partially signed Bitcoin transactions") .subcommand(create::subcommand()) .subcommand(decode::subcommand()) .subcommand(edit::subcommand()) @@ -42,10 +41,10 @@ pub enum PsbtSource { /// the content bytes. /// Also returns an enum value indicating which source worked. pub fn file_or_raw(flag: &str) -> (Vec, PsbtSource) { - if let Ok(raw) = hex::decode(&flag) { - (raw, PsbtSource::Hex) - } else if let Ok(raw) = base64::decode(&flag) { + if let Ok(raw) = base64::decode(&flag) { (raw, PsbtSource::Base64) + } else if let Ok(raw) = hex::decode(&flag) { + (raw, PsbtSource::Hex) } else if let Ok(mut file) = File::open(&flag) { let mut buf = Vec::new(); file.read_to_end(&mut buf).expect("error reading file"); diff --git a/src/bin/hal/cmd/script/decode.rs b/src/bin/hal/cmd/script/decode.rs index f56f112..eb3f039 100644 --- a/src/bin/hal/cmd/script/decode.rs +++ b/src/bin/hal/cmd/script/decode.rs @@ -2,10 +2,11 @@ use bitcoin::Script; use clap; use hex; +use cmd; + pub fn subcommand<'a>() -> clap::App<'a, 'a> { - clap::SubCommand::with_name("decode").about("decode hex script").arg( - clap::Arg::with_name("hex-script").help("script in hex").takes_value(true).required(true), - ) + cmd::subcommand("decode", "decode hex script") + .arg(cmd::opt("hex-script", "script in hex").takes_value(true).required(true)) } pub fn execute<'a>(matches: &clap::ArgMatches<'a>) { diff --git a/src/bin/hal/cmd/script/mod.rs b/src/bin/hal/cmd/script/mod.rs index 0aa3b47..c802fa6 100644 --- a/src/bin/hal/cmd/script/mod.rs +++ b/src/bin/hal/cmd/script/mod.rs @@ -5,7 +5,7 @@ use cmd; mod decode; pub fn subcommand<'a>() -> clap::App<'a, 'a> { - cmd::new_subcommand("script").about("manipulate scripts").subcommand(decode::subcommand()) + cmd::subcommand_group("script", "manipulate scripts").subcommand(decode::subcommand()) } pub fn execute<'a>(matches: &clap::ArgMatches<'a>) { diff --git a/src/bin/hal/cmd/tx/decode.rs b/src/bin/hal/cmd/tx/decode.rs index 4e2cbc8..3d85bc8 100644 --- a/src/bin/hal/cmd/tx/decode.rs +++ b/src/bin/hal/cmd/tx/decode.rs @@ -6,16 +6,9 @@ use cmd; use hal; pub fn subcommand<'a>() -> clap::App<'a, 'a> { - clap::SubCommand::with_name("decode") - .about("decode a raw transaction to JSON") - .args(&cmd::args_networks()) - .arg(cmd::arg_yaml()) - .arg( - clap::Arg::with_name("raw-tx") - .help("the raw transaction in hex") - .takes_value(true) - .required(true), - ) + cmd::subcommand("decode", "decode a raw transaction to JSON") + .args(&cmd::opts_networks()) + .args(&[cmd::opt_yaml(), cmd::arg("raw-tx", "the raw transaction in hex").required(true)]) } pub fn execute<'a>(matches: &clap::ArgMatches<'a>) { diff --git a/src/bin/hal/cmd/tx/encode.rs b/src/bin/hal/cmd/tx/encode.rs index 57e20b2..5865da0 100644 --- a/src/bin/hal/cmd/tx/encode.rs +++ b/src/bin/hal/cmd/tx/encode.rs @@ -3,18 +3,14 @@ use std::io::Write; use bitcoin::consensus::encode::serialize; use bitcoin::{Network, OutPoint, Script, Transaction, TxIn, TxOut}; +use cmd; use hal; pub fn subcommand<'a>() -> clap::App<'a, 'a> { - clap::SubCommand::with_name("encode").about("encode a raw transaction from JSON").args(&[ - clap::Arg::with_name("tx-info") - .help("the transaction info in JSON") - .takes_value(true) - .required(true), - clap::Arg::with_name("raw-stdout") - .long("raw") + cmd::subcommand("encode", "encode a raw transaction from JSON").args(&[ + cmd::arg("tx-info", "the transaction info in JSON").required(true), + cmd::opt("raw-stdout", "output the raw bytes of the result to stdout") .short("r") - .help("output the raw bytes of the result to stdout") .required(false), ]) } diff --git a/src/bin/hal/cmd/tx/mod.rs b/src/bin/hal/cmd/tx/mod.rs index 2b00723..964c8ef 100644 --- a/src/bin/hal/cmd/tx/mod.rs +++ b/src/bin/hal/cmd/tx/mod.rs @@ -6,8 +6,7 @@ mod decode; mod encode; pub fn subcommand<'a>() -> clap::App<'a, 'a> { - cmd::new_subcommand("tx") - .about("manipulate transactions") + cmd::subcommand_group("tx", "manipulate transactions") .subcommand(decode::subcommand()) .subcommand(encode::subcommand()) } diff --git a/src/bin/hal/main.rs b/src/bin/hal/main.rs index bfb15b4..f0b8f04 100644 --- a/src/bin/hal/main.rs +++ b/src/bin/hal/main.rs @@ -16,7 +16,7 @@ extern crate hal; use std::panic; use std::process; -mod cmd; +pub mod cmd; fn setup_logger(lvl: log::LevelFilter) { fern::Dispatch::new() @@ -27,6 +27,26 @@ fn setup_logger(lvl: log::LevelFilter) { .expect("error setting up logger"); } +fn init_app<'a, 'b>() -> clap::App<'a, 'b> { + clap::App::new("hal") + .version("0.0.0") + .author("Steven Roose ") + .about("hal - the Bitcoin companion") + .setting(clap::AppSettings::GlobalVersion) + .setting(clap::AppSettings::VersionlessSubcommands) + .setting(clap::AppSettings::SubcommandRequiredElseHelp) + .setting(clap::AppSettings::AllowExternalSubcommands) + .setting(clap::AppSettings::DisableHelpSubcommand) + .setting(clap::AppSettings::AllArgsOverrideSelf) + .subcommands(cmd::subcommands()) + .arg( + cmd::opt("verbose", "print verbose logging output to stderr") + .short("v") + .takes_value(false) + .global(true), + ) +} + fn main() { // Apply a custom panic hook to print a more user-friendly message // in case the execution fails. @@ -36,35 +56,14 @@ fn main() { } else if let Some(m) = info.payload().downcast_ref::<&str>() { m } else { - "No message provided" + "No error message provided" }; println!("Execution failed: {}", message); process::exit(1); })); - let matches = clap::App::new("hal") - .version("0.0.0") - .author("Steven Roose ") - .about("hal - the Bitcoin companion") - .setting(clap::AppSettings::VersionlessSubcommands) - .setting(clap::AppSettings::SubcommandRequiredElseHelp) - .setting(clap::AppSettings::AllowExternalSubcommands) - .setting(clap::AppSettings::DisableHelpSubcommand) - .setting(clap::AppSettings::AllArgsOverrideSelf) - .subcommand(cmd::address::subcommand()) - .subcommand(cmd::ln::subcommand()) - .subcommand(cmd::tx::subcommand()) - .subcommand(cmd::psbt::subcommand()) - .subcommand(cmd::script::subcommand()) - .subcommand(cmd::bip32::subcommand()) - .arg( - clap::Arg::with_name("verbose") - .short("v") - .takes_value(false) - .help("print verbose logging output to stderr") - .global(true), - ) - .get_matches(); + let app = init_app(); + let matches = app.get_matches(); // Enable logging in verbose mode. match matches.is_present("verbose") {