@@ -700,6 +700,36 @@ const args_fmt_spec = []Flag{
700700 }),
701701};
702702
703+ const Fmt = struct {
704+ seen : std .HashMap ([]const u8 , void , mem .hash_slice_u8 , mem .eql_slice_u8 ),
705+ queue : std .LinkedList ([]const u8 ),
706+ any_error : bool ,
707+
708+ // file_path must outlive Fmt
709+ fn addToQueue (self : * Fmt , file_path : []const u8 ) ! void {
710+ const new_node = try self .seen .allocator .construct (std .LinkedList ([]const u8 ).Node {
711+ .prev = undefined ,
712+ .next = undefined ,
713+ .data = file_path ,
714+ });
715+
716+ if (try self .seen .put (file_path , {})) | _ | return ;
717+
718+ self .queue .append (new_node );
719+ }
720+
721+ fn addDirToQueue (self : * Fmt , file_path : []const u8 ) ! void {
722+ var dir = try std .os .Dir .open (self .seen .allocator , file_path );
723+ defer dir .close ();
724+ while (try dir .next ()) | entry | {
725+ if (entry .kind == std .os .Dir .Entry .Kind .Directory or mem .endsWith (u8 , entry .name , ".zig" )) {
726+ const full_path = try os .path .join (self .seen .allocator , file_path , entry .name );
727+ try self .addToQueue (full_path );
728+ }
729+ }
730+ }
731+ };
732+
703733fn cmdFmt (allocator : * Allocator , args : []const []const u8 ) ! void {
704734 var flags = try Args .parse (allocator , args_fmt_spec , args );
705735 defer flags .deinit ();
@@ -728,21 +758,38 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
728758 }
729759 };
730760
731- var fmt_errors = false ;
761+ var fmt = Fmt {
762+ .seen = std .HashMap ([]const u8 , void , mem .hash_slice_u8 , mem .eql_slice_u8 ).init (allocator ),
763+ .queue = std .LinkedList ([]const u8 ).init (),
764+ .any_error = false ,
765+ };
766+
732767 for (flags .positionals .toSliceConst ()) | file_path | {
768+ try fmt .addToQueue (file_path );
769+ }
770+
771+ while (fmt .queue .popFirst ()) | node | {
772+ const file_path = node .data ;
773+
733774 var file = try os .File .openRead (allocator , file_path );
734775 defer file .close ();
735776
736- const source_code = io .readFileAlloc (allocator , file_path ) catch | err | {
737- try stderr .print ("unable to open '{}': {}\n " , file_path , err );
738- fmt_errors = true ;
739- continue ;
777+ const source_code = io .readFileAlloc (allocator , file_path ) catch | err | switch (err ) {
778+ error .IsDir = > {
779+ try fmt .addDirToQueue (file_path );
780+ continue ;
781+ },
782+ else = > {
783+ try stderr .print ("unable to open '{}': {}\n " , file_path , err );
784+ fmt .any_error = true ;
785+ continue ;
786+ },
740787 };
741788 defer allocator .free (source_code );
742789
743790 var tree = std .zig .parse (allocator , source_code ) catch | err | {
744791 try stderr .print ("error parsing file '{}': {}\n " , file_path , err );
745- fmt_errors = true ;
792+ fmt . any_error = true ;
746793 continue ;
747794 };
748795 defer tree .deinit ();
@@ -755,7 +802,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
755802 try errmsg .printToFile (& stderr_file , msg , color );
756803 }
757804 if (tree .errors .len != 0 ) {
758- fmt_errors = true ;
805+ fmt . any_error = true ;
759806 continue ;
760807 }
761808
@@ -769,7 +816,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
769816 }
770817 }
771818
772- if (fmt_errors ) {
819+ if (fmt . any_error ) {
773820 os .exit (1 );
774821 }
775822}
0 commit comments