6
6
use std:: collections:: HashMap ;
7
7
use std:: io:: { stdin, stdout, Write } ;
8
8
9
- use clap:: { Clap , ArgMatches , FromArgMatches } ;
9
+ use clap:: { App , ArgEnum , Clap , IntoApp , ValueHint , ArgMatches , FromArgMatches } ;
10
+ use clap_generate:: generators:: { Bash , Elvish , Fish , PowerShell , Zsh } ;
11
+ use clap_generate:: { generate, Generator } ;
10
12
11
13
use crate as deploy;
12
14
@@ -18,16 +20,31 @@ use std::process::Stdio;
18
20
use thiserror:: Error ;
19
21
use tokio:: process:: Command ;
20
22
23
+
24
+ #[ derive( ArgEnum , Debug , Clone , PartialEq ) ]
25
+ pub enum GeneratorChoice {
26
+ Bash ,
27
+ Elvish ,
28
+ Fish ,
29
+ #[ clap( name = "powershell" ) ]
30
+ PowerShell ,
31
+ Zsh ,
32
+ }
33
+
21
34
/// Simple Rust rewrite of a simple Nix Flake deployment tool
22
35
#[ derive( Clap , Debug , Clone ) ]
23
- #[ clap( version = "1.0" , author = "Serokell <https://serokell.io/>" ) ]
36
+ #[ clap( name = "deploy" , version = "1.0" , author = "Serokell <https://serokell.io/>" ) ]
24
37
pub struct Opts {
38
+ /// If provided, outputs the completion file for given shell
39
+ #[ clap( long = "generate" , arg_enum) ]
40
+ generator : Option < GeneratorChoice > ,
41
+
25
42
/// The flake to deploy
26
- #[ clap( group = "deploy" ) ]
43
+ #[ clap( group = "deploy" , value_hint = ValueHint :: DirPath ) ]
27
44
target : Option < String > ,
28
45
29
46
/// A list of flakes to deploy alternatively
30
- #[ clap( long, group = "deploy" ) ]
47
+ #[ clap( long, group = "deploy" , value_hint = ValueHint :: DirPath ) ]
31
48
targets : Option < Vec < String > > ,
32
49
/// Check signatures when using `nix copy`
33
50
#[ clap( short, long) ]
@@ -91,6 +108,10 @@ pub struct Opts {
91
108
rollback_succeeded : Option < bool > ,
92
109
}
93
110
111
+ fn print_completions < G : Generator > ( app : & mut App ) {
112
+ generate :: < G , _ > ( app, app. get_name ( ) . to_string ( ) , & mut stdout ( ) ) ;
113
+ }
114
+
94
115
/// Returns if the available Nix installation supports flakes
95
116
async fn test_flake_support ( ) -> Result < bool , std:: io:: Error > {
96
117
debug ! ( "Checking for flake support" ) ;
@@ -619,6 +640,19 @@ pub async fn run(args: Option<&ArgMatches>) -> Result<(), RunError> {
619
640
deploy:: LoggerType :: Deploy ,
620
641
) ?;
621
642
643
+ if let Some ( generator) = opts. generator {
644
+ let mut app = Opts :: into_app ( ) ;
645
+ info ! ( "Generating completion file for {:?}..." , generator) ;
646
+ match generator {
647
+ GeneratorChoice :: Bash => print_completions :: < Bash > ( & mut app) ,
648
+ GeneratorChoice :: Elvish => print_completions :: < Elvish > ( & mut app) ,
649
+ GeneratorChoice :: Fish => print_completions :: < Fish > ( & mut app) ,
650
+ GeneratorChoice :: PowerShell => print_completions :: < PowerShell > ( & mut app) ,
651
+ GeneratorChoice :: Zsh => print_completions :: < Zsh > ( & mut app) ,
652
+ } ;
653
+ return Ok ( ( ) )
654
+ }
655
+
622
656
fn maybe_default_target ( target : Option < String > ) -> Vec < String > {
623
657
match ( target, std:: env:: var ( "DEPLOY_RS_DEFAULT_FLAKE_ROOT" ) , std:: env:: var ( "DEPLOY_RS_DEFAULT_NODE" ) ) {
624
658
( None , _, _) => vec ! [ "." . to_string( ) ] ,
0 commit comments