77use env_logger;
88#[ macro_use]
99extern crate failure;
10- use getopts;
1110#[ macro_use]
1211extern crate log;
1312use regex;
@@ -16,10 +15,13 @@ use serde_json as json;
1615
1716use std:: collections:: HashSet ;
1817use std:: io:: { self , BufRead } ;
19- use std:: { env , process} ;
18+ use std:: process;
2019
2120use regex:: Regex ;
2221
22+ use structopt:: clap:: AppSettings ;
23+ use structopt:: StructOpt ;
24+
2325/// The default pattern of files to format.
2426///
2527/// We only want to format rust files by default.
@@ -53,26 +55,40 @@ impl From<io::Error> for FormatDiffError {
5355 }
5456}
5557
56- fn main ( ) {
57- env_logger:: init ( ) ;
58+ #[ derive( StructOpt , Debug ) ]
59+ #[ structopt(
60+ name = "rustfmt-format-diff" ,
61+ author = "" ,
62+ about = "" ,
63+ raw( setting = "AppSettings::DisableVersion" ) ,
64+ raw( setting = "AppSettings::NextLineHelp" )
65+ ) ]
66+ pub struct Opts {
67+ /// Skip the smallest prefix containing NUMBER slashes
68+ #[ structopt(
69+ short = "p" ,
70+ long = "skip-prefix" ,
71+ value_name = "NUMBER" ,
72+ default_value = "0"
73+ ) ]
74+ skip_prefix : u32 ,
5875
59- let mut opts = getopts:: Options :: new ( ) ;
60- opts. optflag ( "h" , "help" , "show this message" ) ;
61- opts. optopt (
62- "p" ,
63- "skip-prefix" ,
64- "skip the smallest prefix containing NUMBER slashes" ,
65- "NUMBER" ,
66- ) ;
67- opts. optopt (
68- "f" ,
69- "filter" ,
70- "custom pattern selecting file paths to reformat" ,
71- "PATTERN" ,
72- ) ;
76+ /// Custom pattern selecting file paths to reformat
77+ #[ structopt(
78+ short = "f" ,
79+ long = "filter" ,
80+ value_name = "PATTERN" ,
81+ raw( default_value = "DEFAULT_PATTERN" )
82+ ) ]
83+ filter : String ,
84+ }
7385
74- if let Err ( e) = run ( & opts) {
75- println ! ( "{}" , opts. usage( & e. to_string( ) ) ) ;
86+ fn main ( ) {
87+ env_logger:: init ( ) ;
88+ let opts = Opts :: from_args ( ) ;
89+ if let Err ( e) = run ( opts) {
90+ println ! ( "{}" , e) ;
91+ Opts :: clap ( ) . print_help ( ) . expect ( "cannot write to stdout" ) ;
7692 process:: exit ( 1 ) ;
7793 }
7894}
@@ -83,25 +99,8 @@ struct Range {
8399 range : [ u32 ; 2 ] ,
84100}
85101
86- fn run ( opts : & getopts:: Options ) -> Result < ( ) , FormatDiffError > {
87- let matches = opts. parse ( env:: args ( ) . skip ( 1 ) ) ?;
88-
89- if matches. opt_present ( "h" ) {
90- println ! ( "{}" , opts. usage( "usage: " ) ) ;
91- return Ok ( ( ) ) ;
92- }
93-
94- let filter = matches
95- . opt_str ( "f" )
96- . unwrap_or_else ( || DEFAULT_PATTERN . to_owned ( ) ) ;
97-
98- let skip_prefix = matches
99- . opt_str ( "p" )
100- . and_then ( |p| p. parse :: < u32 > ( ) . ok ( ) )
101- . unwrap_or ( 0 ) ;
102-
103- let ( files, ranges) = scan_diff ( io:: stdin ( ) , skip_prefix, & filter) ?;
104-
102+ fn run ( opts : Opts ) -> Result < ( ) , FormatDiffError > {
103+ let ( files, ranges) = scan_diff ( io:: stdin ( ) , opts. skip_prefix , & opts. filter ) ?;
105104 run_rustfmt ( & files, & ranges)
106105}
107106
@@ -238,3 +237,60 @@ fn scan_simple_git_diff() {
238237 ]
239238 ) ;
240239}
240+
241+ #[ cfg( test) ]
242+ mod cmd_line_tests {
243+ use super :: * ;
244+
245+ #[ test]
246+ fn default_options ( ) {
247+ let empty: Vec < String > = vec ! [ ] ;
248+ let o = Opts :: from_iter ( & empty) ;
249+ assert_eq ! ( DEFAULT_PATTERN , o. filter) ;
250+ assert_eq ! ( 0 , o. skip_prefix) ;
251+ }
252+
253+ #[ test]
254+ fn good_options ( ) {
255+ let o = Opts :: from_iter ( & [ "test" , "-p" , "10" , "-f" , r".*\.hs" ] ) ;
256+ assert_eq ! ( r".*\.hs" , o. filter) ;
257+ assert_eq ! ( 10 , o. skip_prefix) ;
258+ }
259+
260+ #[ test]
261+ fn unexpected_option ( ) {
262+ assert ! (
263+ Opts :: clap( )
264+ . get_matches_from_safe( & [ "test" , "unexpected" ] )
265+ . is_err( )
266+ ) ;
267+ }
268+
269+ #[ test]
270+ fn unexpected_flag ( ) {
271+ assert ! (
272+ Opts :: clap( )
273+ . get_matches_from_safe( & [ "test" , "--flag" ] )
274+ . is_err( )
275+ ) ;
276+ }
277+
278+ #[ test]
279+ fn overridden_option ( ) {
280+ assert ! (
281+ Opts :: clap( )
282+ . get_matches_from_safe( & [ "test" , "-p" , "10" , "-p" , "20" ] )
283+ . is_err( )
284+ ) ;
285+ }
286+
287+ #[ test]
288+ fn negative_filter ( ) {
289+ assert ! (
290+ Opts :: clap( )
291+ . get_matches_from_safe( & [ "test" , "-p" , "-1" ] )
292+ . is_err( )
293+ ) ;
294+ }
295+
296+ }
0 commit comments