Skip to content

Commit 1ca90b5

Browse files
committedJun 18, 2018
zig fmt: support directories
zig fmt accepts any number of file paths. For each one, if it is a file, then it formats the file. If it is a directory, then zig recursively scans the directory, formatting all files that end in `.zig`. it maintains a map of paths that have been seen already, to avoid softlink loops. closes #1068
·
0.15.20.3.0
1 parent cd4676a commit 1ca90b5

File tree

1 file changed

+55
-8
lines changed

1 file changed

+55
-8
lines changed
 

‎src-self-hosted/main.zig‎

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
703733
fn 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

Comments
 (0)
Please sign in to comment.