@@ -18,6 +18,7 @@ pub struct NewCommand {
18
18
pub template_id : String ,
19
19
20
20
/// The name of the new application or component.
21
+ #[ clap( value_parser = validate_name) ]
21
22
pub name : String ,
22
23
23
24
/// The directory in which to create the new application or component.
@@ -125,13 +126,22 @@ fn merge_values(from_file: &mut HashMap<String, String>, from_cli: &[ParameterVa
125
126
126
127
lazy_static:: lazy_static! {
127
128
static ref PATH_UNSAFE_CHARACTERS : regex:: Regex = regex:: Regex :: new( "[^-_.a-zA-Z0-9]" ) . expect( "Invalid path safety regex" ) ;
129
+ static ref PROJECT_NAME : regex:: Regex = regex:: Regex :: new( "^[a-zA-Z].*" ) . expect( "Invalid project name regex" ) ;
128
130
}
129
131
130
132
fn path_safe ( text : & str ) -> PathBuf {
131
133
let path = PATH_UNSAFE_CHARACTERS . replace_all ( text, "_" ) ;
132
134
PathBuf :: from ( path. to_string ( ) )
133
135
}
134
136
137
+ fn validate_name ( name : & str ) -> Result < String , String > {
138
+ if PROJECT_NAME . is_match ( name) {
139
+ Ok ( name. to_owned ( ) )
140
+ } else {
141
+ Err ( "Name must start with a letter" . to_owned ( ) )
142
+ }
143
+ }
144
+
135
145
#[ cfg( test) ]
136
146
mod tests {
137
147
use std:: io:: Write ;
@@ -203,4 +213,13 @@ mod tests {
203
213
merge_values ( & mut values, & from_cli) ;
204
214
assert_eq ! ( want, values) ;
205
215
}
216
+
217
+ #[ test]
218
+ fn project_names_must_start_with_letter ( ) {
219
+ assert_eq ! ( "hello" , validate_name( "hello" ) . unwrap( ) ) ;
220
+ assert_eq ! ( "Proj123!.456" , validate_name( "Proj123!.456" ) . unwrap( ) ) ;
221
+ validate_name ( "123" ) . unwrap_err ( ) ;
222
+ validate_name ( "1hello" ) . unwrap_err ( ) ;
223
+ validate_name ( "_foo" ) . unwrap_err ( ) ;
224
+ }
206
225
}
0 commit comments