1- use std:: { env, sync:: Arc } ;
1+ use std:: { env, ffi :: OsString , sync:: Arc } ;
22
3- use clap:: Parser ;
3+ use clap:: { Parser , Subcommand } ;
44use comfy_table:: { Attribute , Cell , ContentArrangement , Table , presets} ;
55use errors:: CliError ;
66use miden_client:: {
@@ -41,7 +41,24 @@ mod utils;
4141const CLIENT_CONFIG_FILE_NAME : & str = "miden-client.toml" ;
4242
4343/// Client binary name.
44- pub const CLIENT_BINARY_NAME : & str = "miden-client" ;
44+ /// Note: If, for whatever reason, we fail to obtain the client's executable
45+ /// name, then we simply display the standard "miden-client".
46+ pub fn client_binary_name ( ) -> OsString {
47+ std:: env:: current_exe ( )
48+ . map ( |executable| {
49+ executable
50+ . file_name ( )
51+ . expect ( "ERROR: failed to obtain the executable's file name" )
52+ . to_os_string ( )
53+ } )
54+ . inspect_err ( |e| {
55+ eprintln ! (
56+ "WARNING: Couldn't obtain the name of the current executable because of {e}.\
57+ Defaulting to miden-client."
58+ ) ;
59+ } )
60+ . unwrap_or ( OsString :: from ( "miden-client" ) )
61+ }
4562
4663/// Number of blocks that must elapse after a transaction’s reference block before it is marked
4764/// stale and discarded.
@@ -55,14 +72,53 @@ const TX_GRACEFUL_BLOCK_DELTA: u32 = 20;
5572 version,
5673 rename_all = "kebab-case"
5774) ]
58- pub struct Cli {
75+ #[ command( multicall( true ) ) ]
76+ pub struct MidenClientCLI {
5977 #[ command( subcommand) ]
60- action : Command ,
78+ behavior : Behavior ,
79+ }
80+
81+ impl From < MidenClientCLI > for Cli {
82+ fn from ( value : MidenClientCLI ) -> Self {
83+ match value. behavior {
84+ Behavior :: MidenClient { cli } => cli,
85+ Behavior :: External ( args) => Cli :: parse_from ( args) . set_external ( ) ,
86+ }
87+ }
88+ }
6189
90+ #[ derive( Debug , Subcommand ) ]
91+ #[ command( rename_all = "kebab-case" ) ]
92+ enum Behavior {
93+ /// The Miden toolchain installer
94+ MidenClient {
95+ #[ command( flatten) ]
96+ cli : Cli ,
97+ } ,
98+
99+ /// Used when the Miden Client CLI is called under a different name, like it
100+ /// is the case in [Midenup](https://github.com/0xMiden/midenup).
101+ #[ command( external_subcommand) ]
102+ External ( Vec < OsString > ) ,
103+ }
104+
105+ #[ derive( Parser , Debug ) ]
106+ #[ command( name = "miden-client" ) ]
107+ pub struct Cli {
62108 /// Activates the executor's debug mode, which enables debug output for scripts
63109 /// that were compiled and executed with this mode.
64110 #[ arg( short, long, default_value_t = false ) ]
65111 debug : bool ,
112+
113+ #[ command( subcommand) ]
114+ action : Command ,
115+
116+ /// Indicates whether the client's CLI is being called directly, or
117+ /// externally under an alias (like in the case of
118+ /// [Midenup](https://github.com/0xMiden/midenup).
119+ #[ arg( skip) ]
120+ #[ allow( unused) ]
121+ external : bool ,
66122}
67123
68124/// CLI actions.
@@ -153,6 +209,11 @@ impl Cli {
153209 Command :: ConsumeNotes ( consume_notes) => consume_notes. execute ( client) . await ,
154210 }
155211 }
212+
213+ fn set_external ( mut self ) -> Self {
214+ self . external = true ;
215+ self
216+ }
156217}
157218
158219pub fn create_dynamic_table ( headers : & [ & str ] ) -> Table {
0 commit comments