@@ -2,25 +2,51 @@ use url::percent_encoding::percent_decode;
2
2
3
3
use structopt:: StructOpt ;
4
4
use failure:: Error ;
5
+ use std:: io:: { self , Read } ;
6
+ use atty:: Stream ;
5
7
pub type Result < T > = std:: result:: Result < T , Error > ;
6
8
7
9
#[ derive( StructOpt , Debug ) ]
8
10
struct Opt {
9
11
#[ structopt( name = "INPUT" ) ]
10
- input : String ,
12
+ input : Option < String > ,
11
13
}
12
14
15
+ fn read_from_stdin ( ) -> Result < String > {
16
+ let mut buf = String :: new ( ) ;
17
+ let stdin = io:: stdin ( ) ;
18
+ let mut handle = stdin. lock ( ) ;
19
+ handle. read_to_string ( & mut buf) ?;
20
+ Ok ( buf)
21
+ }
22
+
23
+ fn is_stdin ( input : Option < & String > ) -> bool {
24
+ let is_request = match input {
25
+ Some ( i) if i == "-" => true ,
26
+ _ => false ,
27
+ } ;
28
+ let is_pipe = ! atty:: is ( Stream :: Stdin ) ;
29
+ is_request || is_pipe
30
+ }
31
+
32
+
13
33
fn main ( ) -> Result < ( ) > {
14
34
let opt = Opt :: from_args ( ) ;
15
- Ok ( println ! ( "{}" , decode( & opt. input) ?) )
16
- }
17
35
18
- //fn main() -> Result<()> {
19
- // let args: Vec<String> = std::env::args().collect();
20
- // let input = &args[1];
21
- //
22
- // Ok(println!("{}", decode(input)?))
23
- //}
36
+ if opt. input . is_none ( ) && ! is_stdin ( opt. input . as_ref ( ) ) {
37
+ Opt :: clap ( ) . print_help ( ) ?;
38
+ std:: process:: exit ( 1 ) ;
39
+ }
40
+ let input = match opt. input {
41
+ Some ( i) => i,
42
+ None => read_from_stdin ( ) ?
43
+ } ;
44
+ if input. is_empty ( ) {
45
+ Opt :: clap ( ) . get_matches ( ) . usage ( ) ;
46
+ }
47
+
48
+ Ok ( println ! ( "{}" , decode( & input) ?) )
49
+ }
24
50
25
51
fn decode ( input : & str ) -> Result < String > {
26
52
let decoded = percent_decode ( input. as_bytes ( ) ) . decode_utf8 ( ) ?;
0 commit comments