1- use clap:: { ArgAction , CommandFactory , Parser } ;
1+ use clap:: { ArgAction , CommandFactory , Parser , ValueEnum } ;
22use futures:: future:: join_all;
33use indicatif:: { ProgressBar , ProgressStyle } ;
44use open;
5- use serde_json:: json;
5+ use serde_json:: { json, Value } ;
66use std:: fs:: File ;
77use std:: io:: { self , BufRead , BufReader , BufWriter , Write } ;
88use std:: path:: { Path , PathBuf } ;
@@ -33,6 +33,12 @@ use tokio::sync::Semaphore;
3333
3434const HISTORY_TEMP_FILE : & str = "todo_history_temp.json" ;
3535
36+ #[ derive( Copy , Clone , PartialEq , Eq , PartialOrd , Ord , ValueEnum , Debug ) ]
37+ enum OutputFormat {
38+ Html ,
39+ Json ,
40+ }
41+
3642#[ derive( Parser , Debug ) ]
3743#[ command(
3844 name = "todoctor" ,
@@ -58,6 +64,10 @@ struct Cli {
5864 #[ arg( short = 'E' , long, action = ArgAction :: Append ) ]
5965 exclude_keywords : Vec < String > ,
6066
67+ /// Output format
68+ #[ arg( short, long, default_value = "html" ) ]
69+ output_format : OutputFormat ,
70+
6171 /// Output directory
6272 #[ arg( short, long, default_value = "todoctor" ) ]
6373 output : String ,
@@ -91,6 +101,8 @@ async fn main() {
91101 . map ( |values| values. map ( String :: from) . collect ( ) )
92102 . unwrap_or_else ( Vec :: new) ;
93103
104+ let output_format = args. get_one :: < OutputFormat > ( "output_format" ) . unwrap ( ) ;
105+
94106 let output_directory = args. get_one :: < String > ( "output" ) . unwrap ( ) ;
95107
96108 if !check_git_repository ( "." ) . await {
@@ -358,41 +370,60 @@ async fn main() {
358370 "version" : version,
359371 } ) ;
360372
361- let mut escaped_json_data = json_data. clone ( ) ;
362- escape_json_values ( & mut escaped_json_data) ;
363-
364- let escaped_json_string = serde_json:: to_string ( & escaped_json_data)
365- . expect ( "Error: Could not serializing JSON" ) ;
373+ generate_output ( * output_format, output_directory, json_data) . await ;
374+ }
366375
367- let dist_path: PathBuf =
368- get_dist_path ( ) . expect ( "Error: Could not get current dist path." ) ;
376+ async fn generate_output (
377+ output_format : OutputFormat ,
378+ output_directory : & str ,
379+ json_data : Value ,
380+ ) {
381+ match output_format {
382+ OutputFormat :: Html => {
383+ let dist_path: PathBuf = get_dist_path ( )
384+ . expect ( "Error: Could not get current dist path." ) ;
385+
386+ copy_dir_recursive ( & dist_path, Path :: new ( output_directory) )
387+ . await
388+ . expect ( "Error copying directory" ) ;
369389
370- copy_dir_recursive ( & dist_path, Path :: new ( output_directory) )
371- . await
372- . expect ( "Error copying directory" ) ;
390+ let mut escaped_json_data = json_data. clone ( ) ;
391+ escape_json_values ( & mut escaped_json_data) ;
373392
374- let index_path = Path :: new ( output_directory) . join ( "index.html" ) ;
375- if fs:: metadata ( & index_path) . await . is_ok ( ) {
376- let mut index_content = fs:: read_to_string ( & index_path)
377- . await
378- . expect ( "Error reading index.html" ) ;
393+ let escaped_json_string = serde_json:: to_string ( & escaped_json_data)
394+ . expect ( "Error: Could not serializing JSON" ) ;
379395
380- if let Some ( pos) = index_content. find ( "</head>" ) {
381- let script_tag: String = format ! (
382- "<script>window.data = {};</script>" ,
383- escaped_json_string
384- ) ;
385- index_content. insert_str ( pos, & script_tag) ;
396+ let index_path = Path :: new ( output_directory) . join ( "index.html" ) ;
397+ if fs:: metadata ( & index_path) . await . is_ok ( ) {
398+ let mut index_content = fs:: read_to_string ( & index_path)
399+ . await
400+ . expect ( "Error reading index.html" ) ;
401+
402+ if let Some ( pos) = index_content. find ( "</head>" ) {
403+ let script_tag = format ! (
404+ "<script>window.data = {};</script>" ,
405+ escaped_json_string
406+ ) ;
407+ index_content. insert_str ( pos, & script_tag) ;
408+
409+ fs:: write ( & index_path, index_content)
410+ . await
411+ . expect ( "Error writing modified index.html" ) ;
412+ } else {
413+ eprintln ! ( "Error: No </head> tag found in index.html" ) ;
414+ }
386415
387- fs:: write ( & index_path, index_content)
388- . await
389- . expect ( "Error writing modified index.html" ) ;
390- } else {
391- eprintln ! ( "Error: No </head> tag found in index.html" ) ;
416+ if let Err ( e) = open:: that ( & index_path) {
417+ eprintln ! ( "Error: Cannot open index.html: {:?}" , e) ;
418+ }
419+ }
420+ }
421+ OutputFormat :: Json => {
422+ let json_path = Path :: new ( output_directory) . join ( "report.json" ) ;
423+ let mut file = File :: create ( & json_path)
424+ . expect ( "Failed to create JSON report file" ) ;
425+ file. write_all ( json_data. to_string ( ) . as_bytes ( ) )
426+ . expect ( "Failed to write JSON data" ) ;
392427 }
393- }
394-
395- if let Err ( e) = open:: that ( & index_path) {
396- eprintln ! ( "Error: Cannot open index.html: {:?}" , e) ;
397428 }
398429}
0 commit comments