Skip to content

Commit

Permalink
zig fmt: support directories
Browse files Browse the repository at this point in the history
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
  • Loading branch information
andrewrk committed Jun 18, 2018
1 parent cd4676a commit 1ca90b5
Showing 1 changed file with 55 additions and 8 deletions.
63 changes: 55 additions & 8 deletions src-self-hosted/main.zig
Expand Up @@ -700,6 +700,36 @@ const args_fmt_spec = []Flag{
}),
};

const Fmt = struct {
seen: std.HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8),
queue: std.LinkedList([]const u8),
any_error: bool,

// file_path must outlive Fmt
fn addToQueue(self: *Fmt, file_path: []const u8) !void {
const new_node = try self.seen.allocator.construct(std.LinkedList([]const u8).Node{
.prev = undefined,
.next = undefined,
.data = file_path,
});

if (try self.seen.put(file_path, {})) |_| return;

self.queue.append(new_node);
}

fn addDirToQueue(self: *Fmt, file_path: []const u8) !void {
var dir = try std.os.Dir.open(self.seen.allocator, file_path);
defer dir.close();
while (try dir.next()) |entry| {
if (entry.kind == std.os.Dir.Entry.Kind.Directory or mem.endsWith(u8, entry.name, ".zig")) {
const full_path = try os.path.join(self.seen.allocator, file_path, entry.name);
try self.addToQueue(full_path);
}
}
}
};

fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
var flags = try Args.parse(allocator, args_fmt_spec, args);
defer flags.deinit();
Expand Down Expand Up @@ -728,21 +758,38 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
}
};

var fmt_errors = false;
var fmt = Fmt{
.seen = std.HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8).init(allocator),
.queue = std.LinkedList([]const u8).init(),
.any_error = false,
};

for (flags.positionals.toSliceConst()) |file_path| {
try fmt.addToQueue(file_path);
}

while (fmt.queue.popFirst()) |node| {
const file_path = node.data;

var file = try os.File.openRead(allocator, file_path);
defer file.close();

const source_code = io.readFileAlloc(allocator, file_path) catch |err| {
try stderr.print("unable to open '{}': {}\n", file_path, err);
fmt_errors = true;
continue;
const source_code = io.readFileAlloc(allocator, file_path) catch |err| switch (err) {
error.IsDir => {
try fmt.addDirToQueue(file_path);
continue;
},
else => {
try stderr.print("unable to open '{}': {}\n", file_path, err);
fmt.any_error = true;
continue;
},
};
defer allocator.free(source_code);

var tree = std.zig.parse(allocator, source_code) catch |err| {
try stderr.print("error parsing file '{}': {}\n", file_path, err);
fmt_errors = true;
fmt.any_error = true;
continue;
};
defer tree.deinit();
Expand All @@ -755,7 +802,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
try errmsg.printToFile(&stderr_file, msg, color);
}
if (tree.errors.len != 0) {
fmt_errors = true;
fmt.any_error = true;
continue;
}

Expand All @@ -769,7 +816,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
}
}

if (fmt_errors) {
if (fmt.any_error) {
os.exit(1);
}
}
Expand Down

0 comments on commit 1ca90b5

Please sign in to comment.