18
18
19
19
use std:: cell:: { Cell , RefCell } ;
20
20
use std:: collections:: { HashMap , HashSet } ;
21
+ use std:: fs;
21
22
use std:: io:: ErrorKind ;
22
23
use std:: path:: { Component , Path , PathBuf } ;
23
24
use std:: rc:: Rc ;
24
25
use std:: time:: Instant ;
25
- use std:: { env, fs} ;
26
26
27
27
use html5ever:: tendril:: ByteTendril ;
28
28
use html5ever:: tokenizer:: {
@@ -110,10 +110,20 @@ macro_rules! t {
110
110
} ;
111
111
}
112
112
113
+ struct Cli {
114
+ docs : PathBuf ,
115
+ }
116
+
113
117
fn main ( ) {
114
- let docs = env:: args_os ( ) . nth ( 1 ) . expect ( "doc path should be first argument" ) ;
115
- let docs = env:: current_dir ( ) . unwrap ( ) . join ( docs) ;
116
- let mut checker = Checker { root : docs. clone ( ) , cache : HashMap :: new ( ) } ;
118
+ let cli = match parse_cli ( ) {
119
+ Ok ( cli) => cli,
120
+ Err ( err) => {
121
+ eprintln ! ( "error: {err}" ) ;
122
+ usage_and_exit ( 1 ) ;
123
+ }
124
+ } ;
125
+
126
+ let mut checker = Checker { root : cli. docs . clone ( ) , cache : HashMap :: new ( ) } ;
117
127
let mut report = Report {
118
128
errors : 0 ,
119
129
start : Instant :: now ( ) ,
@@ -125,14 +135,45 @@ fn main() {
125
135
intra_doc_exceptions : 0 ,
126
136
has_broken_urls : false ,
127
137
} ;
128
- checker. walk ( & docs, & mut report) ;
138
+ checker. walk ( & cli . docs , & mut report) ;
129
139
report. report ( ) ;
130
140
if report. errors != 0 {
131
141
println ! ( "found some broken links" ) ;
132
142
std:: process:: exit ( 1 ) ;
133
143
}
134
144
}
135
145
146
+ fn parse_cli ( ) -> Result < Cli , String > {
147
+ fn to_canonical_path ( arg : & str ) -> Result < PathBuf , String > {
148
+ PathBuf :: from ( arg) . canonicalize ( ) . map_err ( |e| format ! ( "could not canonicalize {arg}: {e}" ) )
149
+ }
150
+
151
+ let mut verbatim = false ;
152
+ let mut docs = None ;
153
+
154
+ let mut args = std:: env:: args ( ) . skip ( 1 ) ;
155
+ while let Some ( arg) = args. next ( ) {
156
+ if !verbatim && arg == "--" {
157
+ verbatim = true ;
158
+ } else if !verbatim && ( arg == "-h" || arg == "--help" ) {
159
+ usage_and_exit ( 0 )
160
+ } else if !verbatim && arg. starts_with ( '-' ) {
161
+ return Err ( format ! ( "unknown flag: {arg}" ) ) ;
162
+ } else if docs. is_none ( ) {
163
+ docs = Some ( arg) ;
164
+ } else {
165
+ return Err ( "too many positional arguments" . into ( ) ) ;
166
+ }
167
+ }
168
+
169
+ Ok ( Cli { docs : to_canonical_path ( & docs. ok_or ( "missing first positional argument" ) ?) ? } )
170
+ }
171
+
172
+ fn usage_and_exit ( code : i32 ) -> ! {
173
+ eprintln ! ( "usage: linkchecker <path>" ) ;
174
+ std:: process:: exit ( code)
175
+ }
176
+
136
177
struct Checker {
137
178
root : PathBuf ,
138
179
cache : Cache ,
0 commit comments