11use std:: env;
2+ use std:: ffi:: OsString ;
23use std:: sync:: Arc ;
34
4- use clap:: Parser ;
5+ use clap:: { Parser , Subcommand } ;
56use comfy_table:: { Attribute , Cell , ContentArrangement , Table , presets} ;
67use errors:: CliError ;
78use miden_client:: account:: AccountHeader ;
@@ -38,7 +39,24 @@ mod utils;
3839const CLIENT_CONFIG_FILE_NAME : & str = "miden-client.toml" ;
3940
4041/// Client binary name.
41- pub const CLIENT_BINARY_NAME : & str = "miden-client" ;
42+ /// Note: If, for whatever reason, we fail to obtain the client's executable
43+ /// name, then we simply display the standard "miden-client".
44+ pub fn client_binary_name ( ) -> OsString {
45+ std:: env:: current_exe ( )
46+ . map ( |executable| {
47+ executable
48+ . file_name ( )
49+ . expect ( "ERROR: failed to obtain the executable's file name" )
50+ . to_os_string ( )
51+ } )
52+ . inspect_err ( |e| {
53+ eprintln ! (
54+ "WARNING: Couldn't obtain the name of the current executable because of {e}.\
55+ Defaulting to miden-client."
56+ ) ;
57+ } )
58+ . unwrap_or ( OsString :: from ( "miden-client" ) )
59+ }
4260
4361/// Number of blocks that must elapse after a transaction’s reference block before it is marked
4462/// stale and discarded.
@@ -52,14 +70,53 @@ const TX_GRACEFUL_BLOCK_DELTA: u32 = 20;
5270 version,
5371 rename_all = "kebab-case"
5472) ]
55- pub struct Cli {
73+ #[ command( multicall( true ) ) ]
74+ pub struct MidenClientCli {
5675 #[ command( subcommand) ]
57- action : Command ,
76+ behavior : Behavior ,
77+ }
78+
79+ impl From < MidenClientCli > for Cli {
80+ fn from ( value : MidenClientCli ) -> Self {
81+ match value. behavior {
82+ Behavior :: MidenClient { cli } => cli,
83+ Behavior :: External ( args) => Cli :: parse_from ( args) . set_external ( ) ,
84+ }
85+ }
86+ }
5887
88+ #[ derive( Debug , Subcommand ) ]
89+ #[ command( rename_all = "kebab-case" ) ]
90+ enum Behavior {
91+ /// The Miden toolchain installer
92+ MidenClient {
93+ #[ command( flatten) ]
94+ cli : Cli ,
95+ } ,
96+
97+ /// Used when the Miden Client CLI is called under a different name, like it
98+ /// is the case in [Midenup](https://github.com/0xMiden/midenup).
99+ #[ command( external_subcommand) ]
100+ External ( Vec < OsString > ) ,
101+ }
102+
103+ #[ derive( Parser , Debug ) ]
104+ #[ command( name = "miden-client" ) ]
105+ pub struct Cli {
59106 /// Activates the executor's debug mode, which enables debug output for scripts
60107 /// that were compiled and executed with this mode.
61108 #[ arg( short, long, default_value_t = false ) ]
62109 debug : bool ,
110+
111+ #[ command( subcommand) ]
112+ action : Command ,
113+
114+ /// Indicates whether the client's CLI is being called directly, or
115+ /// externally under an alias (like in the case of
116+ /// [Midenup](https://github.com/0xMiden/midenup).
117+ #[ arg( skip) ]
118+ #[ allow( unused) ]
119+ external : bool ,
63120}
64121
65122/// CLI actions.
@@ -150,6 +207,11 @@ impl Cli {
150207 Command :: ConsumeNotes ( consume_notes) => consume_notes. execute ( client) . await ,
151208 }
152209 }
210+
211+ fn set_external ( mut self ) -> Self {
212+ self . external = true ;
213+ self
214+ }
153215}
154216
155217pub fn create_dynamic_table ( headers : & [ & str ] ) -> Table {
0 commit comments