@@ -13,7 +13,7 @@ use crate::util::{
13
13
print_available_packages, print_available_tests,
14
14
} ;
15
15
use crate :: CargoResult ;
16
- use anyhow:: bail;
16
+ use anyhow:: { anyhow , bail} ;
17
17
use cargo_util:: paths;
18
18
use cargo_util_schemas:: manifest:: ProfileName ;
19
19
use cargo_util_schemas:: manifest:: RegistryName ;
@@ -173,7 +173,11 @@ pub trait CommandExt: Sized {
173
173
) -> Self {
174
174
self . _arg ( flag ( "lib" , lib) . help_heading ( heading:: TARGET_SELECTION ) )
175
175
. _arg ( flag ( "bins" , bins) . help_heading ( heading:: TARGET_SELECTION ) )
176
- . _arg ( optional_multi_opt ( "bin" , "NAME" , bin) . help_heading ( heading:: TARGET_SELECTION ) )
176
+ . _arg (
177
+ optional_multi_opt ( "bin" , "NAME" , bin)
178
+ . help_heading ( heading:: TARGET_SELECTION )
179
+ . add ( clap_complete:: ArgValueCandidates :: new ( get_bin_candidates) ) ,
180
+ )
177
181
. _arg ( flag ( "examples" , examples) . help_heading ( heading:: TARGET_SELECTION ) )
178
182
. _arg (
179
183
optional_multi_opt ( "example" , "NAME" , example)
@@ -188,21 +192,27 @@ pub trait CommandExt: Sized {
188
192
example : & ' static str ,
189
193
examples : & ' static str ,
190
194
) -> Self {
191
- self . _arg ( optional_multi_opt ( "bin" , "NAME" , bin) . help_heading ( heading:: TARGET_SELECTION ) )
192
- . _arg ( flag ( "bins" , bins) . help_heading ( heading:: TARGET_SELECTION ) )
193
- . _arg (
194
- optional_multi_opt ( "example" , "NAME" , example)
195
- . help_heading ( heading:: TARGET_SELECTION ) ,
196
- )
197
- . _arg ( flag ( "examples" , examples) . help_heading ( heading:: TARGET_SELECTION ) )
195
+ self . _arg (
196
+ optional_multi_opt ( "bin" , "NAME" , bin)
197
+ . help_heading ( heading:: TARGET_SELECTION )
198
+ . add ( clap_complete:: ArgValueCandidates :: new ( get_bin_candidates) ) ,
199
+ )
200
+ . _arg ( flag ( "bins" , bins) . help_heading ( heading:: TARGET_SELECTION ) )
201
+ . _arg (
202
+ optional_multi_opt ( "example" , "NAME" , example) . help_heading ( heading:: TARGET_SELECTION ) ,
203
+ )
204
+ . _arg ( flag ( "examples" , examples) . help_heading ( heading:: TARGET_SELECTION ) )
198
205
}
199
206
200
207
fn arg_targets_bin_example ( self , bin : & ' static str , example : & ' static str ) -> Self {
201
- self . _arg ( optional_multi_opt ( "bin" , "NAME" , bin) . help_heading ( heading:: TARGET_SELECTION ) )
202
- . _arg (
203
- optional_multi_opt ( "example" , "NAME" , example)
204
- . help_heading ( heading:: TARGET_SELECTION ) ,
205
- )
208
+ self . _arg (
209
+ optional_multi_opt ( "bin" , "NAME" , bin)
210
+ . help_heading ( heading:: TARGET_SELECTION )
211
+ . add ( clap_complete:: ArgValueCandidates :: new ( get_bin_candidates) ) ,
212
+ )
213
+ . _arg (
214
+ optional_multi_opt ( "example" , "NAME" , example) . help_heading ( heading:: TARGET_SELECTION ) ,
215
+ )
206
216
}
207
217
208
218
fn arg_features ( self ) -> Self {
@@ -333,7 +343,10 @@ pub trait CommandExt: Sized {
333
343
. value_name ( "VCS" )
334
344
. value_parser ( [ "git" , "hg" , "pijul" , "fossil" , "none" ] ) ,
335
345
)
336
- . _arg ( flag ( "bin" , "Use a binary (application) template [default]" ) )
346
+ . _arg (
347
+ flag ( "bin" , "Use a binary (application) template [default]" )
348
+ . add ( clap_complete:: ArgValueCandidates :: new ( get_bin_candidates) ) ,
349
+ )
337
350
. _arg ( flag ( "lib" , "Use a library template" ) )
338
351
. _arg (
339
352
opt ( "edition" , "Edition to set for the crate generated" )
@@ -1027,6 +1040,42 @@ pub fn lockfile_path(
1027
1040
return Ok ( Some ( path) ) ;
1028
1041
}
1029
1042
1043
+ fn get_bin_candidates ( ) -> Vec < clap_complete:: CompletionCandidate > {
1044
+ get_bins_from_manifest ( )
1045
+ . map ( |bins| {
1046
+ bins. into_iter ( )
1047
+ . map ( |bin| clap_complete:: CompletionCandidate :: new ( bin) )
1048
+ . collect ( )
1049
+ } )
1050
+ . unwrap_or ( vec ! [ ] )
1051
+ }
1052
+
1053
+ fn get_bins_from_manifest ( ) -> Option < Vec < String > > {
1054
+ let manifest = get_manifest_with_table ( ) . ok ( ) ?;
1055
+ let mut bins = vec ! [ ] ;
1056
+
1057
+ let bins_array = manifest. get ( "bin" ) ?. as_array ( ) ?;
1058
+
1059
+ for bin in bins_array {
1060
+ let name = bin. as_table ( ) ?. get ( "name" ) ?. as_str ( ) ?;
1061
+ bins. push ( name. to_owned ( ) ) ;
1062
+ }
1063
+
1064
+ Some ( bins)
1065
+ }
1066
+
1067
+ fn get_manifest_with_table ( ) -> CargoResult < toml:: Table > {
1068
+ let menifest = env ! ( "CARGO_MANIFEST_DIR" ) ;
1069
+ let menifest = Path :: new ( menifest) . join ( "Cargo.toml" ) ;
1070
+
1071
+ let value = toml:: from_str :: < toml:: Value > ( & std:: fs:: read_to_string ( menifest) ?) ?;
1072
+
1073
+ match value {
1074
+ toml:: Value :: Table ( table) => Ok ( table) ,
1075
+ _ => Err ( anyhow ! ( "Error parsing Cargo.toml" ) ) ,
1076
+ }
1077
+ }
1078
+
1030
1079
#[ track_caller]
1031
1080
pub fn ignore_unknown < T : Default > ( r : Result < T , clap:: parser:: MatchesError > ) -> T {
1032
1081
match r {
0 commit comments