| ... | @@ -700,6 +700,36 @@ const args_fmt_spec = []Flag{ | ... | @@ -700,6 +700,36 @@ const args_fmt_spec = []Flag{ |
| 700 | }), | 700 | }), |
| 701 | }; | 701 | }; |
| 702 | | 702 | |
| | 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 | |
| 703 | fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { | 733 | fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { |
| 704 | var flags = try Args.parse(allocator, args_fmt_spec, args); | 734 | var flags = try Args.parse(allocator, args_fmt_spec, args); |
| 705 | defer flags.deinit(); | 735 | defer flags.deinit(); |
| ... | @@ -728,21 +758,38 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { | ... | @@ -728,21 +758,38 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { |
| 728 | } | 758 | } |
| 729 | }; | 759 | }; |
| 730 | | 760 | |
| 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 | |
| 732 | for (flags.positionals.toSliceConst()) |file_path| { | 767 | 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 | |
| 733 | var file = try os.File.openRead(allocator, file_path); | 774 | var file = try os.File.openRead(allocator, file_path); |
| 734 | defer file.close(); | 775 | defer file.close(); |
| 735 | | 776 | |
| 736 | const source_code = io.readFileAlloc(allocator, file_path) catch |err| { | 777 | const source_code = io.readFileAlloc(allocator, file_path) catch |err| switch (err) { |
| 737 | try stderr.print("unable to open '{}': {}\n", file_path, err); | 778 | error.IsDir => { |
| 738 | fmt_errors = true; | 779 | try fmt.addDirToQueue(file_path); |
| 739 | continue; | 780 | continue; |
| | 781 | }, |
| | 782 | else => { |
| | 783 | try stderr.print("unable to open '{}': {}\n", file_path, err); |
| | 784 | fmt.any_error = true; |
| | 785 | continue; |
| | 786 | }, |
| 740 | }; | 787 | }; |
| 741 | defer allocator.free(source_code); | 788 | defer allocator.free(source_code); |
| 742 | | 789 | |
| 743 | var tree = std.zig.parse(allocator, source_code) catch |err| { | 790 | var tree = std.zig.parse(allocator, source_code) catch |err| { |
| 744 | try stderr.print("error parsing file '{}': {}\n", file_path, err); | 791 | try stderr.print("error parsing file '{}': {}\n", file_path, err); |
| 745 | fmt_errors = true; | 792 | fmt.any_error = true; |
| 746 | continue; | 793 | continue; |
| 747 | }; | 794 | }; |
| 748 | defer tree.deinit(); | 795 | defer tree.deinit(); |
| ... | @@ -755,7 +802,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { | ... | @@ -755,7 +802,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { |
| 755 | try errmsg.printToFile(&stderr_file, msg, color); | 802 | try errmsg.printToFile(&stderr_file, msg, color); |
| 756 | } | 803 | } |
| 757 | if (tree.errors.len != 0) { | 804 | if (tree.errors.len != 0) { |
| 758 | fmt_errors = true; | 805 | fmt.any_error = true; |
| 759 | continue; | 806 | continue; |
| 760 | } | 807 | } |
| 761 | | 808 | |
| ... | @@ -769,7 +816,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { | ... | @@ -769,7 +816,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { |
| 769 | } | 816 | } |
| 770 | } | 817 | } |
| 771 | | 818 | |
| 772 | if (fmt_errors) { | 819 | if (fmt.any_error) { |
| 773 | os.exit(1); | 820 | os.exit(1); |
| 774 | } | 821 | } |
| 775 | } | 822 | } |