11use std:: { error:: Error , path:: PathBuf } ;
22
3- use clap:: { Args , Parser , Subcommand , builder:: TypedValueParser } ;
3+ use clap:: { Args , Command , Parser , Subcommand , ValueHint , builder:: TypedValueParser } ;
4+ use clap_complete:: { Generator , Shell , generate} ;
45use color_eyre:: Result ;
56use strum:: VariantNames ;
67
@@ -10,6 +11,17 @@ use crate::{
1011 util:: types:: DockerImageUrl ,
1112} ;
1213
14+ #[ derive( Parser , Debug ) ]
15+ #[ command( author, version = version( ) , about) ]
16+ pub struct Cli {
17+ /// Tick rate, i.e. number of ticks per second
18+ #[ arg( short, long, value_name = "FLOAT" , default_value_t = 4.0 ) ]
19+ pub tick_rate : f64 ,
20+
21+ #[ command( subcommand) ]
22+ pub command : Option < CliCommands > ,
23+ }
24+
1325#[ derive( Subcommand , Debug ) ]
1426#[ allow( clippy:: large_enum_variant) ]
1527pub enum CliCommands {
@@ -19,25 +31,38 @@ pub enum CliCommands {
1931 Cscs {
2032 #[ command( subcommand) ]
2133 command : CscsCommands ,
22- #[ clap( short, long, help = "override compute system (e.g. 'eiger', 'daint')" ) ]
34+ #[ clap( short, long, help = "override compute system (e.g. 'eiger', 'daint')" , value_hint= ValueHint :: Other ) ]
2335 system : Option < String > ,
24- #[ clap( short, long, ignore_case=true , value_parser=clap:: builder:: PossibleValuesParser :: new( ComputePlatform :: VARIANTS ) . map( |s|s. parse:: <ComputePlatform >( ) . unwrap( ) ) , help = "override compute platform (one of 'hpc', 'ml' or 'cw')" ) ]
36+ #[ clap(
37+ short,
38+ long,
39+ ignore_case=true ,
40+ value_parser=clap:: builder:: PossibleValuesParser :: new( ComputePlatform :: VARIANTS ) . map(
41+ |s|s. parse:: <ComputePlatform >( ) . unwrap( ) ) ,
42+ help = "override compute platform (one of 'hpc', 'ml' or 'cw')" ,
43+ value_hint=ValueHint :: Other ) ]
2544 platform : Option < ComputePlatform > ,
26- #[ clap( short, long, help = "override compute account to use (project or user)" ) ]
45+ #[ clap( short, long, help = "override compute account to use (project or user)" , value_hint= ValueHint :: Other ) ]
2746 account : Option < String > ,
2847 } ,
2948 #[ clap( about = "Create a new project configuration file" ) ]
3049 Init {
31- #[ clap( help = "destination folder to create config in (default = current directory)" ) ]
50+ #[ clap( help = "destination folder to create config in (default = current directory)" , value_hint= ValueHint :: DirPath ) ]
3251 destination : Option < PathBuf > ,
33- #[ clap( help = "project name to use" ) ]
52+ #[ clap( help = "project name to use" , value_hint= ValueHint :: Other ) ]
3453 name : Option < String > ,
3554 } ,
3655 #[ clap( about = "Manage configuration" ) ]
3756 Config {
3857 #[ command( subcommand) ]
3958 command : ConfigCommands ,
4059 } ,
60+ #[ clap( about = "Generate shell completions" ) ]
61+ Completions {
62+ /// generate shell completions
63+ #[ clap( value_enum) ]
64+ generator : Shell ,
65+ } ,
4166}
4267
4368#[ derive( Subcommand , Debug ) ]
@@ -51,13 +76,13 @@ pub enum ConfigCommands {
5176 help = "whether to change the global config or the project local one"
5277 ) ]
5378 global : bool ,
54- #[ clap( help = "Config key path, e.g. `cscs.current_system`" ) ]
79+ #[ clap( help = "Config key path, e.g. `cscs.current_system`" , value_hint= ValueHint :: Other ) ]
5580 key_path : String ,
56- #[ clap( help = "Value to set" , value_parser = parse_toml_value) ]
81+ #[ clap( help = "Value to set" , value_parser = parse_toml_value, value_hint= ValueHint :: Other ) ]
5782 value : toml_edit:: Value ,
5883 } ,
5984 Get {
60- #[ clap( help = "Config key path, e.g. `cscs.current_system`" ) ]
85+ #[ clap( help = "Config key path, e.g. `cscs.current_system`" , value_hint= ValueHint :: Other ) ]
6186 key_path : String ,
6287 } ,
6388}
@@ -95,9 +120,9 @@ pub struct ScriptSpec {
95120 help = "generate and upload script file based on template (on by default unless `--local` or `--remote` are passed)"
96121 ) ]
97122 generate_script : bool ,
98- #[ arg( long, value_name = "PATH" , help = "upload local script file" ) ]
123+ #[ arg( long, value_name = "PATH" , help = "upload local script file" , value_hint= ValueHint :: FilePath ) ]
99124 local_script : Option < PathBuf > ,
100- #[ arg( long, value_name = "PATH" , help = "use script file already present on remote" ) ]
125+ #[ arg( long, value_name = "PATH" , help = "use script file already present on remote" , value_hint= ValueHint :: Other ) ]
101126 remote_script : Option < PathBuf > ,
102127}
103128impl Default for ScriptSpec {
@@ -130,9 +155,9 @@ pub struct EdfSpec {
130155 help = "generate and upload edf file based on template (on by default unless `--local` or `--remote` are passed)"
131156 ) ]
132157 generate_edf : bool ,
133- #[ arg( long, value_name = "PATH" , help = "upload local edf file" ) ]
158+ #[ arg( long, value_name = "PATH" , help = "upload local edf file" , value_hint= ValueHint :: FilePath ) ]
134159 local_edf : Option < PathBuf > ,
135- #[ arg( long, value_name = "PATH" , help = "use edf file already present on remote" ) ]
160+ #[ arg( long, value_name = "PATH" , help = "use edf file already present on remote" , value_hint= ValueHint :: Other ) ]
136161 remote_edf : Option < PathBuf > ,
137162}
138163
@@ -164,65 +189,84 @@ pub enum CscsJobCommands {
164189 #[ clap( alias( "ls" ) , about = "List all jobs [aliases: ls]" ) ]
165190 List ,
166191 #[ clap( alias( "g" ) , about = "Get metadata for a specific job [aliases: g]" ) ]
167- Get { job_id : i64 } ,
192+ Get {
193+ #[ arg( help="id of the job" , value_hint=ValueHint :: Other ) ]
194+ job_id : i64 ,
195+ } ,
168196 #[ clap( about = "Get the stdout of a job" ) ]
169197 Log {
170198 #[ clap( short, long, action, help = "whether to get stderr instead of stdout" ) ]
171199 stderr : bool ,
200+ #[ arg( help="id of the job" , value_hint=ValueHint :: Other ) ]
172201 job_id : i64 ,
173202 } ,
174203
175204 #[ clap( alias( "s" ) , about = "Submit a new compute job [aliases: s]" ) ]
176205 Submit {
177- #[ clap( short, long, help = "name of the job" ) ]
206+ #[ clap( short, long, help = "name of the job" , value_hint= ValueHint :: Other ) ]
178207 name : Option < String > ,
179208 #[ clap(
180209 short,
181210 long,
182- help = "the working directory path inside the container (note this is different from the working directory that the srun command is executed from)"
211+ help = "the working directory path inside the container (note this is different from the working directory that the srun command is executed from)" ,
212+ value_hint=ValueHint :: Other
183213 ) ]
184214 workdir : Option < String > ,
185- #[ clap( short='E' , value_name="KEY=VALUE" , value_parser=parse_key_val:: <String , String >, help="Environment variables to set in the container" ) ]
215+ #[ clap( short='E' ,
216+ value_name="KEY=VALUE" ,
217+ value_parser=parse_key_val:: <String , String >,
218+ help="Environment variables to set in the container" ,
219+ value_hint=ValueHint :: Other ) ]
186220 env : Vec < ( String , String ) > ,
187- #[ clap( short='M' , value_name="PATH:CONTAINER_PATH" , value_parser=parse_key_val_colon:: <String , String >, help="Paths to mount inside container" ) ]
221+ #[ clap( short='M' ,
222+ value_name="PATH:CONTAINER_PATH" ,
223+ value_parser=parse_key_val_colon:: <String , String >,
224+ help="Paths to mount inside container" ,
225+ value_hint=ValueHint :: Other ) ]
188226 mount : Vec < ( String , String ) > ,
189- #[ clap( short, long, help = "The docker image to use" ) ]
227+ #[ clap( short, long, help = "The docker image to use" , value_hint= ValueHint :: Other ) ]
190228 image : Option < DockerImageUrl > ,
191- #[ clap( long, help = "Path where stdout of the job gets written to" ) ]
229+ #[ clap( long, help = "Path where stdout of the job gets written to" , value_hint= ValueHint :: Other ) ]
192230 stdout : Option < PathBuf > ,
193- #[ clap( long, help = "Path where stderr of the job gets written to" ) ]
231+ #[ clap( long, help = "Path where stderr of the job gets written to" , value_hint= ValueHint :: Other ) ]
194232 stderr : Option < PathBuf > ,
195233 #[ command( flatten) ]
196234 edf_spec : Option < EdfSpec > ,
197235 #[ command( flatten) ]
198236 script_spec : Option < ScriptSpec > ,
199- #[ clap( trailing_var_arg = true , help = "The command to run in the container" ) ]
237+ #[ clap( trailing_var_arg = true , help = "The command to run in the container" , value_hint= ValueHint :: Other ) ]
200238 command : Option < Vec < String > > ,
201239 } ,
202240 #[ clap(
203241 alias( "c" ) ,
204242 about = "Cancel a running job, fails if the job isn't running [aliases: c]"
205243 ) ]
206- Cancel { job_id : i64 } ,
244+ Cancel {
245+ #[ clap( help="id of the job" , value_hint=ValueHint :: Other ) ]
246+ job_id : i64 ,
247+ } ,
207248}
208249
209250#[ derive( Subcommand , Debug ) ]
210251pub enum CscsFileCommands {
211252 #[ clap( alias( "ls" ) , about = "List folders and files in a remote path [aliases: ls]" ) ]
212- List { path : PathBuf } ,
253+ List {
254+ #[ arg( help ="remote path to list" , value_hint=ValueHint :: Other ) ]
255+ path : PathBuf ,
256+ } ,
213257 #[ clap( alias( "dl" ) , about = "Download a remote file [aliases: dl]" ) ]
214258 Download {
215- #[ clap( help = "The path in the cluster to download" ) ]
259+ #[ clap( help = "The path in the cluster to download" , value_hint= ValueHint :: Other ) ]
216260 remote : PathBuf ,
217- #[ clap( help = "The local path to download the file to" ) ]
261+ #[ clap( help = "The local path to download the file to" , value_hint= ValueHint :: AnyPath ) ]
218262 local : PathBuf ,
219263 } ,
220264 #[ clap( alias( "ul" ) , about = "Upload a file to remote storage [aliases: ul]" ) ]
221265 Upload {
222- #[ clap( help = "The local path to upload to the cluster" ) ]
266+ #[ clap( help = "The local path to upload to the cluster" , value_hint= ValueHint :: AnyPath ) ]
223267 local : PathBuf ,
224268
225- #[ clap( help = "the path in the cluster to upload to" ) ]
269+ #[ clap( help = "the path in the cluster to upload to" , value_hint= ValueHint :: Other ) ]
226270 remote : PathBuf ,
227271 } ,
228272}
@@ -238,22 +282,11 @@ pub enum CscsSystemCommands {
238282 Set {
239283 #[ clap( short, long, action, help = "set in global config instead of project-local one" ) ]
240284 global : bool ,
241- #[ clap( help = "System name to use" ) ]
285+ #[ clap( help = "System name to use" , value_hint= ValueHint :: Other ) ]
242286 system_name : String ,
243287 } ,
244288}
245289
246- #[ derive( Parser , Debug ) ]
247- #[ command( author, version = version( ) , about) ]
248- pub struct Cli {
249- /// Tick rate, i.e. number of ticks per second
250- #[ arg( short, long, value_name = "FLOAT" , default_value_t = 4.0 ) ]
251- pub tick_rate : f64 ,
252-
253- #[ command( subcommand) ]
254- pub command : Option < CliCommands > ,
255- }
256-
257290const VERSION_MESSAGE : & str = concat ! (
258291 env!( "CARGO_PKG_VERSION" ) ,
259292 "-" ,
@@ -335,3 +368,7 @@ fn is_bare_string(value_str: &str) -> bool {
335368 true // empty or whitespace only
336369 }
337370}
371+
372+ pub fn print_completions < G : Generator > ( generator : G , cmd : & mut Command ) {
373+ generate ( generator, cmd, cmd. get_name ( ) . to_string ( ) , & mut std:: io:: stdout ( ) ) ;
374+ }
0 commit comments