11use std:: {
22 env, fs,
3- io:: { self , IsTerminal , Read } ,
3+ io:: { self , IsTerminal , Write } ,
44 path:: PathBuf ,
55} ;
66
77use clap:: { CommandFactory , Parser } ;
88
9- use gdscript_formatter:: { formatter:: format_gdscript_with_config, FormatterConfig } ;
9+ use gdscript_formatter:: { FormatterConfig , formatter:: format_gdscript_with_config} ;
1010
1111#[ derive( Parser ) ]
1212#[ clap(
@@ -19,14 +19,16 @@ use gdscript_formatter::{formatter::format_gdscript_with_config, FormatterConfig
1919) ]
2020struct Args {
2121 #[ arg(
22- help = "Input GDScript file to format. If no file path is provided, the program reads from standard input and outputs to standard output." ,
23- value_name = "FILE "
22+ help = "Input GDScript file(s) to format. If no file path is provided, the program reads from standard input and outputs to standard output." ,
23+ value_name = "FILES "
2424 ) ]
25- input : Option < PathBuf > ,
25+ input : Vec < PathBuf > ,
2626 #[ arg(
2727 long,
2828 help = "Output formatted code to stdout instead of overwriting the input file. \
29- This flag is ignored when reading from stdin (stdout is always used)"
29+ If multiple input files are provided, each file's content is preceded by a comment indicating the file name, with the form \
30+ #--file:<file_path> \
31+ This flag is ignored when reading from stdin (stdout is always used)."
3032 ) ]
3133 stdout : bool ,
3234 #[ arg(
@@ -77,47 +79,79 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
7779
7880 let args = Args :: parse ( ) ;
7981
80- let input_content = match & args. input {
81- Some ( file_path) => fs:: read_to_string ( file_path)
82- . map_err ( |e| format ! ( "Failed to read file {}: {}" , file_path. display( ) , e) ) ?,
83- None => {
84- let mut buffer = String :: new ( ) ;
85- io:: stdin ( )
86- . read_to_string ( & mut buffer)
87- . map_err ( |e| format ! ( "Failed to read from stdin: {}" , e) ) ?;
88- buffer
89- }
90- } ;
91-
9282 let config = FormatterConfig {
9383 indent_size : args. indent_size ,
9484 use_spaces : args. use_spaces ,
9585 reorder_code : args. reorder_code ,
9686 safe : args. safe ,
9787 } ;
9888
99- let formatted_content = format_gdscript_with_config ( & input_content, & config) ?;
89+ let input_gdscript_files: Vec < & PathBuf > = args
90+ . input
91+ . iter ( )
92+ . filter ( |path| path. extension ( ) . map_or ( false , |ext| ext == "gd" ) )
93+ . collect ( ) ;
10094
101- if args. check {
102- if input_content != formatted_content {
103- eprintln ! ( "The file is not formatted" ) ;
104- std:: process:: exit ( 1 ) ;
105- }
106- println ! ( "File is formatted" ) ;
107- } else {
108- match ( args. input . as_ref ( ) , args. stdout ) {
109- // If we're reading from a file without the --stdout flag: we overwrite the input file
110- ( Some ( input_file) , false ) => {
111- fs:: write ( input_file, formatted_content) . map_err ( |e| {
112- format ! ( "Failed to write to file {}: {}" , input_file. display( ) , e)
113- } ) ?;
95+ if input_gdscript_files. is_empty ( ) {
96+ eprintln ! (
97+ "Error: No GDScript files found in the arguments provided. Please provide at least one .gd file."
98+ ) ;
99+ std:: process:: exit ( 1 ) ;
100+ }
101+
102+ let total_files = input_gdscript_files. len ( ) ;
103+ let mut all_formatted = true ;
104+
105+ for ( index, file_path) in input_gdscript_files. iter ( ) . enumerate ( ) {
106+ let file_number = index + 1 ;
107+ terminal_clear_line ( ) ;
108+ print ! ( "\r Formatting file {}/{}" , file_number, total_files) ;
109+ io:: stdout ( ) . flush ( ) . unwrap ( ) ;
110+
111+ let input_content = fs:: read_to_string ( file_path)
112+ . map_err ( |error| format ! ( "Failed to read file {}: {}" , file_path. display( ) , error) ) ?;
113+
114+ let formatted_content = format_gdscript_with_config ( & input_content, & config) ?;
115+
116+ if args. check {
117+ if input_content != formatted_content {
118+ all_formatted = false ;
114119 }
115- // Otherwise we output to stdout
116- _ => {
117- print ! ( "{}" , formatted_content) ;
120+ } else if args. stdout {
121+ // Clear the current line before printing formatted files to stdout, to erase the "Formatting file ..." message
122+ terminal_clear_line ( ) ;
123+ // If there are multiple input files we still allow stdout but we print a separator
124+ if total_files > 1 {
125+ println ! ( "#--file:{}" , file_path. display( ) ) ;
118126 }
127+ print ! ( "{}" , formatted_content) ;
128+ } else {
129+ fs:: write ( file_path, formatted_content)
130+ . map_err ( |e| format ! ( "Failed to write to file {}: {}" , file_path. display( ) , e) ) ?;
119131 }
120132 }
121133
134+ if args. check {
135+ if all_formatted {
136+ terminal_clear_line ( ) ;
137+ println ! ( "\r All {} file(s) are formatted" , total_files) ;
138+ } else {
139+ terminal_clear_line ( ) ;
140+ eprintln ! ( "\r Some files are not formatted" ) ;
141+ std:: process:: exit ( 1 ) ;
142+ }
143+ } else if !args. stdout {
144+ terminal_clear_line ( ) ;
145+ println ! (
146+ "\r Formatted {} file{}" ,
147+ total_files,
148+ if total_files == 1 { "" } else { "s" }
149+ ) ;
150+ }
151+
122152 Ok ( ( ) )
123153}
154+
155+ fn terminal_clear_line ( ) {
156+ print ! ( "\r {}" , " " . repeat( 80 ) ) ;
157+ }
0 commit comments