1
- use std:: { env, sync:: Arc } ;
1
+ use std:: { env, ffi :: OsString , sync:: Arc } ;
2
2
3
- use clap:: Parser ;
3
+ use clap:: { Parser , Subcommand } ;
4
4
use comfy_table:: { Attribute , Cell , ContentArrangement , Table , presets} ;
5
5
use errors:: CliError ;
6
6
use miden_client:: {
@@ -41,7 +41,24 @@ mod utils;
41
41
const CLIENT_CONFIG_FILE_NAME : & str = "miden-client.toml" ;
42
42
43
43
/// 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
+ }
45
62
46
63
/// Number of blocks that must elapse after a transaction’s reference block before it is marked
47
64
/// stale and discarded.
@@ -55,14 +72,53 @@ const TX_GRACEFUL_BLOCK_DELTA: u32 = 20;
55
72
version,
56
73
rename_all = "kebab-case"
57
74
) ]
58
- pub struct Cli {
75
+ #[ command( multicall( true ) ) ]
76
+ pub struct MidenClientCli {
59
77
#[ 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
+ }
61
89
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 {
62
108
/// Activates the executor's debug mode, which enables debug output for scripts
63
109
/// that were compiled and executed with this mode.
64
110
#[ arg( short, long, default_value_t = false ) ]
65
111
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 ,
66
122
}
67
123
68
124
/// CLI actions.
@@ -153,6 +209,11 @@ impl Cli {
153
209
Command :: ConsumeNotes ( consume_notes) => consume_notes. execute ( client) . await ,
154
210
}
155
211
}
212
+
213
+ fn set_external ( mut self ) -> Self {
214
+ self . external = true ;
215
+ self
216
+ }
156
217
}
157
218
158
219
pub fn create_dynamic_table ( headers : & [ & str ] ) -> Table {
0 commit comments