@@ -4,7 +4,7 @@ use std:: {
44
55use xml:: { self , reader:: XmlEvent , EventReader } ;
66use xml:: common:: { TextPosition , Position } ;
7- use colored:: Colorize ;
7+ use colored:: { ColoredString , Colorize } ;
88
99mod lexer;
1010mod server;
@@ -13,7 +13,7 @@ mod model;
1313use crate :: model:: { InMemoryModel , Model , SqliteModel } ;
1414
1515/* Parse all the text (Character Events) from the XML File */
16- fn read_xml_file ( file_path : & Path ) -> Result < String , ( ) > {
16+ fn parse_xml_file ( file_path : & Path ) -> Result < String , ( ) > {
1717 let file = File :: open ( file_path) . map_err ( |err| {
1818 eprintln ! ( "{}: Could not open file {file_path}: {err}" , "ERROR" . bold( ) . red( ) , file_path = file_path. display( ) ) ;
1919 } ) ?;
@@ -84,21 +84,22 @@ fn append_folder_to_model(dir_path: &Path, model: &mut dyn Model) -> Result<(),
8484
8585 // Recursively index all the folders
8686 if file_type. is_dir ( ) {
87- let _ = append_folder_to_model ( & file_path, model) ;
87+ append_folder_to_model ( & file_path, model) ? ;
8888 continue ' step;
8989 }
9090
9191 println ! ( "Indexing {} ..." , file_path_str. bright_cyan( ) ) ;
9292
93- let content = match read_xml_file ( & file_path) {
93+ let content = match parse_xml_file ( & file_path) {
9494 Ok ( content) => content. chars ( ) . collect :: < Vec < _ > > ( ) ,
9595 Err ( err) => {
9696 eprintln ! ( "{error}: Failed to read xml file {fp}: {msg:?}" , error = "ERROR" . bold( ) . red( ) , fp = file_path. to_str( ) . unwrap( ) . bright_blue( ) , msg = err) ;
9797 continue ' step;
9898 }
9999 } ;
100100
101- let _ = model. add_document ( file_path, & content) ;
101+ // Core Operation
102+ model. add_document ( file_path, & content) ?;
102103 }
103104 Ok ( ( ) )
104105}
@@ -110,25 +111,28 @@ fn check_index(index_path: &str) -> Result<(), ()> {
110111 exit ( 1 ) ;
111112 } ) ?;
112113
113- println ! ( "{info}: Reading file {file}" , info = "INFO" . bright_cyan ( ) , file = index_path. bright_blue( ) ) ;
114+ println ! ( "{info}: Reading file {file}" , info = "INFO" . cyan ( ) , file = index_path. bright_blue( ) ) ;
114115 let model: InMemoryModel = serde_json:: from_reader ( BufReader :: new ( index_file) ) . map_err ( |err| {
115116 eprintln ! ( "{}: Serde could not read file {file} as \" {err}\" " , "ERROR" . bold( ) . red( ) , file = index_path. bright_blue( ) , err = err. to_string( ) . red( ) ) ;
116117 exit ( 1 ) ;
117118 } ) ?;
118- println ! ( "{info}: Index file has {entries} entries" , info = "INFO" . bright_cyan ( ) , entries = model. tf_index. len( ) ) ;
119+ println ! ( "{info}: Index file has {entries} entries" , info = "INFO" . cyan ( ) , entries = model. tf_index. len( ) ) ;
119120 Ok ( ( ) )
120121}
121122
122- const DEFAULT_INDEX_FILE_PATH : & str = "index.json" ;
123+ const DEFAULT_INDEX_JSON_PATH : & str = "index.json" ;
124+ const DEFAULT_INDEX_SQLITE_DB_PATH : & str = "index.db" ;
125+
123126
124127fn fetch_model ( index_path : & str ) -> Result < InMemoryModel , ( ) > {
125128 let index_file = fs:: File :: open ( & index_path) . map_err ( |err| {
126129 eprintln ! ( "{}: Could not open file {file_path} as \" {err}\" " , "ERROR" . bold( ) . red( ) , file_path = index_path. bright_blue( ) , err = err. to_string( ) . red( ) ) ;
127- } ) ? ;
130+ } ) . unwrap ( ) ;
128131
129132 let model: InMemoryModel = serde_json:: from_reader ( BufReader :: new ( index_file) ) . map_err ( |err| {
130133 eprintln ! ( "{}: Serde failed to read {file_path} as \" {err}\" " , "ERROR" . bold( ) . red( ) , file_path = index_path. bright_blue( ) , err = err. to_string( ) . red( ) ) ;
131- } ) ?;
134+ } ) . unwrap ( ) ;
135+
132136 return Ok ( model) ;
133137}
134138
@@ -143,12 +147,11 @@ fn usage(program: &String) {
143147
144148fn entry ( ) -> Result < ( ) , ( ) > {
145149 let mut args = env:: args ( ) ;
146- let program = args. next ( ) . expect ( "Path to program must be provided. " ) ;
150+ let program = args. next ( ) . expect ( "path to program is provided" ) ;
147151
148- let mut use_sqlite_mode = false ;
149152 let mut subcommand = None ;
153+ let mut use_sqlite_mode = false ;
150154
151- // Look for --sqlite flag
152155 while let Some ( arg) = args. next ( ) {
153156 match arg. as_str ( ) {
154157 "--sqlite" => use_sqlite_mode = true ,
@@ -159,28 +162,29 @@ fn entry() -> Result<(), ()> {
159162 }
160163 }
161164
162- let subcommand = args . next ( ) . unwrap_or_else ( || {
165+ let subcommand = subcommand . ok_or_else ( || {
163166 usage ( & program) ;
164- eprintln ! ( "{}: no subcommand is provided." , "ERROR" . bold( ) . red( ) ) ;
165- exit ( 0 ) ;
166- } ) ;
167-
167+ eprintln ! ( "ERROR: no subcommand is provided" ) ;
168+ } ) ?;
168169
169170 match subcommand. as_str ( ) {
170171 "index" => {
171- let dir_path = args. next ( ) . unwrap_or_else ( || {
172+ let dir_path = args. next ( ) . ok_or_else ( || {
173+ usage ( & program) ;
172174 eprintln ! ( "{}: No directory path is provided for {} subcommand." , "ERROR" . bold( ) . red( ) , subcommand. bold( ) . bright_blue( ) ) ;
173- exit ( 1 ) ;
174- } ) ;
175+ } ) ?;
175176
176177 if use_sqlite_mode {
177178 let index_path = "index.db" ;
178179
179180 // Remove previous index.db to update
180- if let Err ( err) = fs:: remove_file ( index_path) {
181- eprintln ! ( "{}: Could not delete file {path} as \" {err:?}\" " , "ERROR" . bold( ) . red( ) , path = dir_path. bold( ) . bright_blue( ) , err = err. to_string( ) . red( ) ) ;
182- return Err ( ( ) ) ;
181+ if Path :: exists ( Path :: new ( index_path) ) {
182+ if let Err ( err) = fs:: remove_file ( index_path) {
183+ eprintln ! ( "{}: Could not delete file {path} as \" {err}\" " , "ERROR" . bold( ) . red( ) , path = index_path. bold( ) . bright_blue( ) , err = err. to_string( ) . red( ) ) ;
184+ return Err ( ( ) ) ;
185+ }
183186 }
187+
184188 let mut model = SqliteModel :: open ( Path :: new ( index_path) ) . unwrap ( ) ;
185189 model. begin ( ) ?;
186190 append_folder_to_model ( Path :: new ( & dir_path) , & mut model) ?;
@@ -195,15 +199,15 @@ fn entry() -> Result<(), ()> {
195199 }
196200
197201 "search" => {
198- let index_path = args. next ( ) . unwrap_or_else ( || {
202+ let index_path = args. next ( ) . ok_or_else ( || {
203+ usage ( & program) ;
199204 eprintln ! ( "{}: Index file path must provided for {} subcommand." , "ERROR" . bold( ) . red( ) , subcommand. bold( ) . bright_blue( ) ) ;
200- exit ( 1 ) ;
201- } ) ;
205+ } ) ?;
202206
203- let prompt = args. next ( ) . unwrap_or_else ( || {
207+ let prompt = args. next ( ) . ok_or_else ( || {
208+ usage ( & program) ;
204209 eprintln ! ( "{}: Prompt must be provided for {} subcommand." , "ERROR" . bold( ) . red( ) , subcommand. bold( ) . bright_blue( ) ) ;
205- exit ( 1 ) ;
206- } ) . chars ( ) . collect :: < Vec < char > > ( ) ;
210+ } ) ?. chars ( ) . collect :: < Vec < char > > ( ) ;
207211
208212
209213 if use_sqlite_mode {
@@ -222,35 +226,43 @@ fn entry() -> Result<(), ()> {
222226 }
223227
224228 "check" => {
225- // TODO: Make it compatible with Sqlite db
226- let index_path = args. next ( ) . unwrap_or ( DEFAULT_INDEX_FILE_PATH . to_string ( ) ) ;
227- check_index ( & index_path) . unwrap ( ) ;
229+ if use_sqlite_mode {
230+ let index_path = args. next ( ) . unwrap_or ( DEFAULT_INDEX_SQLITE_DB_PATH . to_string ( ) ) ;
231+ let model = SqliteModel :: open ( Path :: new ( & index_path) ) ?;
232+ println ! ( "{info}: Database has {count} entries." , info = "INFO" . cyan( ) , count = model. check( ) . unwrap( ) ) ;
233+ } else {
234+ let index_path = args. next ( ) . unwrap_or ( DEFAULT_INDEX_JSON_PATH . to_string ( ) ) ;
235+ check_index ( & index_path) . unwrap ( ) ;
236+ }
228237 }
229238
230239 "serve" => {
231- let index_path = args. next ( ) . unwrap_or_else ( || {
240+ let index_path = args. next ( ) . ok_or_else ( || {
241+ usage ( & program) ;
232242 eprintln ! ( "{}: Index file path must provided for {} subcommand." , "ERROR" . bold( ) . red( ) , subcommand. bold( ) . bright_blue( ) ) ;
233- exit ( 1 ) ;
234- } ) ;
235-
243+ } ) ?;
244+
236245 // Default address
237246 let address = args. next ( ) . unwrap_or ( "127.0.0.1:6969" . to_string ( ) ) ;
238247
239248 if use_sqlite_mode {
240249 let model = SqliteModel :: open ( Path :: new ( & index_path) ) ?;
241250 return server:: start ( & address, & model) ;
251+
242252 } else {
243- let model: InMemoryModel = fetch_model ( & index_path) . unwrap ( ) ;
253+ let model: InMemoryModel = fetch_model ( & index_path) . unwrap_or_else ( |( ) | {
254+ eprintln ! ( "{}: Failed to fetch model for {}." , "ERROR" . bold( ) . red( ) , index_path. bright_blue( ) ) ;
255+ exit ( 1 ) ;
256+ } ) ;
244257 return server:: start ( & address, & model) ;
245258 }
246-
247259 }
248260
249261 _ => {
250262
251263 usage ( & program) ;
252264 eprintln ! ( "{}: Unknown subcommand {}" , "ERROR" . bold( ) . red( ) , subcommand. bold( ) . bright_blue( ) ) ;
253- exit ( 1 ) ;
265+ return Err ( ( ) ) ;
254266 }
255267 }
256268 Ok ( ( ) )
0 commit comments