mirror of
https://github.com/sbrow/envr.git
synced 2026-06-28 02:58:33 -04:00
Compare commits
1 Commits
b3ebf7cadb
...
2043e20b88
| Author | SHA1 | Date | |
|---|---|---|---|
| 2043e20b88 |
2
.envrc
2
.envrc
@@ -1,4 +1,4 @@
|
||||
use flake
|
||||
|
||||
ROOT="."
|
||||
ROOT="/home/spencer/Desktop/envr"
|
||||
export PATH=".:${ROOT}/deps/zig:${ROOT}/deps/zls:$PATH"
|
||||
|
||||
@@ -177,7 +177,7 @@ pub fn list(self: *@This(), gpa: std.mem.Allocator) ![]EnvFile {
|
||||
return stmt.all(EnvFile, gpa, .{}, .{});
|
||||
}
|
||||
|
||||
pub const EnvFile = struct {
|
||||
const EnvFile = struct {
|
||||
// TODO: Should use file_name in the struct and derive from the path.
|
||||
path: []const u8,
|
||||
|
||||
|
||||
59
src/main.zig
59
src/main.zig
@@ -44,7 +44,7 @@ fn run(
|
||||
var stdout_file_writer: Io.File.Writer = .init(.stdout(), io, &stdout_buffer);
|
||||
const stdout_writer = &stdout_file_writer.interface;
|
||||
|
||||
return envr.deps(
|
||||
return deps(
|
||||
io,
|
||||
stdout_writer,
|
||||
environ_map.get("PATH").?,
|
||||
@@ -75,6 +75,63 @@ fn version(writer: *Io.Writer) !void {
|
||||
try writer.flush();
|
||||
}
|
||||
|
||||
// Display dependency statuses
|
||||
fn deps(
|
||||
io: Io,
|
||||
writer: *Io.Writer,
|
||||
path: []const u8,
|
||||
) !void {
|
||||
const feats: Features = try .scan(io, path);
|
||||
|
||||
// FIXME: Draw as a table
|
||||
try writer.print("features: {}", .{feats});
|
||||
try writer.flush();
|
||||
}
|
||||
|
||||
const Features = packed struct {
|
||||
git: bool = false,
|
||||
fd: bool = false,
|
||||
const all_features: Features = .{
|
||||
.git = true,
|
||||
.fd = true,
|
||||
};
|
||||
|
||||
/// Scans your PATH variable for programs.
|
||||
pub fn scan(io: Io, path: []const u8) !@This() {
|
||||
var feats: Features = .{};
|
||||
|
||||
var dirs = std.mem.splitScalar(u8, path, std.fs.path.delimiter);
|
||||
|
||||
loop: while (dirs.next()) |dir| {
|
||||
const dirt = Io.Dir.openDir(Io.Dir.cwd(), io, dir, .{ .follow_symlinks = true, .iterate = true }) catch continue;
|
||||
defer dirt.close(io);
|
||||
|
||||
var dir_paths = dirt.iterate();
|
||||
|
||||
while (try dir_paths.next(io)) |file| {
|
||||
// FIXME: Check if executable
|
||||
if (std.mem.eql(u8, std.fs.path.basename(file.name), "git")) {
|
||||
feats.git = true;
|
||||
|
||||
if (feats == Features.all_features) {
|
||||
break :loop;
|
||||
}
|
||||
}
|
||||
|
||||
if (std.mem.eql(u8, std.fs.path.basename(file.name), "fd")) {
|
||||
feats.fd = true;
|
||||
|
||||
if (feats == Features.all_features) {
|
||||
break :loop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return feats;
|
||||
}
|
||||
};
|
||||
|
||||
fn fallback_to_go(
|
||||
io: Io,
|
||||
arena: std.mem.Allocator,
|
||||
|
||||
76
src/root.zig
76
src/root.zig
@@ -63,63 +63,6 @@ pub const root: Command = .new(.{
|
||||
},
|
||||
});
|
||||
|
||||
// Display dependency statuses
|
||||
pub fn deps(
|
||||
io: Io,
|
||||
writer: *Io.Writer,
|
||||
path: []const u8,
|
||||
) !void {
|
||||
const feats: Features = try .scan(io, path);
|
||||
|
||||
// FIXME: Draw as a table
|
||||
try writer.print("features: {}", .{feats});
|
||||
try writer.flush();
|
||||
}
|
||||
|
||||
const Features = packed struct {
|
||||
git: bool = false,
|
||||
fd: bool = false,
|
||||
const all_features: Features = .{
|
||||
.git = true,
|
||||
.fd = true,
|
||||
};
|
||||
|
||||
/// Scans your PATH variable for programs.
|
||||
pub fn scan(io: Io, path: []const u8) !@This() {
|
||||
var feats: Features = .{};
|
||||
|
||||
var dirs = std.mem.splitScalar(u8, path, std.fs.path.delimiter);
|
||||
|
||||
loop: while (dirs.next()) |dir| {
|
||||
const dirt = Io.Dir.openDir(Io.Dir.cwd(), io, dir, .{ .follow_symlinks = true, .iterate = true }) catch continue;
|
||||
defer dirt.close(io);
|
||||
|
||||
var dir_paths = dirt.iterate();
|
||||
|
||||
while (try dir_paths.next(io)) |file| {
|
||||
// FIXME: Check if executable
|
||||
if (std.mem.eql(u8, std.fs.path.basename(file.name), "git")) {
|
||||
feats.git = true;
|
||||
|
||||
if (feats == Features.all_features) {
|
||||
break :loop;
|
||||
}
|
||||
}
|
||||
|
||||
if (std.mem.eql(u8, std.fs.path.basename(file.name), "fd")) {
|
||||
feats.fd = true;
|
||||
|
||||
if (feats == Features.all_features) {
|
||||
break :loop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return feats;
|
||||
}
|
||||
};
|
||||
|
||||
pub fn list(
|
||||
io: Io,
|
||||
arena: std.mem.Allocator,
|
||||
@@ -129,13 +72,10 @@ pub fn list(
|
||||
) !void {
|
||||
// TODO: Don't hardcode
|
||||
const cfgPath = try std.fs.path.join(arena, &.{ home, ".envr", "config.json" });
|
||||
defer arena.free(cfgPath);
|
||||
|
||||
var cfg = (try Config.load(io, arena, cfgPath));
|
||||
defer cfg.deinit();
|
||||
const cfg: Config = (try Config.load(io, arena, cfgPath)).value;
|
||||
|
||||
var db: Db = try .open(io, arena, .{
|
||||
.config = cfg.value,
|
||||
.config = cfg,
|
||||
.home = home,
|
||||
.tmp = tmp,
|
||||
});
|
||||
@@ -143,14 +83,15 @@ pub fn list(
|
||||
const files = try db.list(arena);
|
||||
defer arena.free(files);
|
||||
|
||||
const table: tabula.Table(Db.EnvFile, .initOne(.path)) = .{ .items = files };
|
||||
const table = tabula.Table(@TypeOf(files[0]));
|
||||
try out.print("{f}", .{table});
|
||||
try out.flush();
|
||||
|
||||
try db.close(io, arena); // TODO: Defer this
|
||||
|
||||
for (files) |*file| {
|
||||
file.deinit(arena);
|
||||
// TODO: Is this bad?
|
||||
for (files) |file| {
|
||||
@constCast(&file).deinit(arena);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,9 +199,6 @@ test "list returns a table" {
|
||||
tmp,
|
||||
);
|
||||
|
||||
const got = try out.toOwnedSlice();
|
||||
defer gpa.free(got);
|
||||
|
||||
try std.testing.expectEqualStrings(
|
||||
\\┌────────────────────────┐
|
||||
\\│ path │
|
||||
@@ -268,5 +206,5 @@ test "list returns a table" {
|
||||
\\│ ~/project/.env.example │
|
||||
\\└────────────────────────┘
|
||||
\\
|
||||
, got);
|
||||
, try out.toOwnedSlice());
|
||||
}
|
||||
|
||||
@@ -27,37 +27,38 @@ pub fn Table(
|
||||
|
||||
// Print body
|
||||
for (self.items) |item| {
|
||||
try writer.writeAll(sep);
|
||||
_ = try writer.write(sep);
|
||||
|
||||
comptime var itr = fields.iterator();
|
||||
comptime var i: usize = 0;
|
||||
inline while (comptime itr.next()) |c| : (i += 1) {
|
||||
try writer.writeByte(' ');
|
||||
_ = try writer.write(" ");
|
||||
try write_aligned(writer, @field(item, @tagName(c)), max_column_widths[i], .left);
|
||||
try writer.print(" {s}", .{sep});
|
||||
}
|
||||
|
||||
try writer.writeAll("\n");
|
||||
_ = try writer.write("\n");
|
||||
}
|
||||
|
||||
// Print post-body
|
||||
{
|
||||
try writer.writeAll(bl);
|
||||
_ = try writer.write(bl);
|
||||
|
||||
var itr = fields.iterator();
|
||||
var i: usize = 0;
|
||||
while (itr.next()) |_| : (i += 1) {
|
||||
if (i > 0) {
|
||||
try writer.writeAll(bm);
|
||||
_ = try writer.write(bm);
|
||||
}
|
||||
|
||||
const padding = max_column_widths[i] + 2;
|
||||
for (0..padding) |_| {
|
||||
try writer.writeAll(hor);
|
||||
_ = try writer.write(hor);
|
||||
}
|
||||
}
|
||||
|
||||
try writer.writeAll(br ++ "\n");
|
||||
_ = try writer.write(br);
|
||||
_ = try writer.write("\n");
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -95,29 +96,29 @@ fn header(
|
||||
|
||||
// Print Pre-Header
|
||||
{
|
||||
try writer.writeAll(tl);
|
||||
_ = try writer.write(tl);
|
||||
|
||||
inline for (0..comptime fields.count()) |i| {
|
||||
if (i > 0) {
|
||||
try writer.writeAll(tm);
|
||||
_ = try writer.write(tm);
|
||||
}
|
||||
const padding = max_column_widths[i] + 2;
|
||||
for (0..padding) |_| {
|
||||
try writer.writeAll(hor);
|
||||
_ = try writer.write(hor);
|
||||
}
|
||||
}
|
||||
|
||||
try writer.writeAll(tr ++ "\n");
|
||||
_ = try writer.write(tr ++ "\n");
|
||||
}
|
||||
|
||||
// Main Header
|
||||
{
|
||||
try writer.writeAll(sep);
|
||||
_ = try writer.write(sep);
|
||||
|
||||
comptime var itr = fields.iterator();
|
||||
comptime var i: usize = 0;
|
||||
inline while (comptime itr.next()) |field| : (i += 1) {
|
||||
try writer.writeByte(' ');
|
||||
_ = try writer.write(" ");
|
||||
try write_aligned(
|
||||
writer,
|
||||
@tagName(field),
|
||||
@@ -127,24 +128,24 @@ fn header(
|
||||
try writer.print(" {s}", .{sep});
|
||||
}
|
||||
|
||||
try writer.writeByte('\n');
|
||||
try writer.print("\n", .{});
|
||||
}
|
||||
|
||||
// Print post-header
|
||||
{
|
||||
try writer.writeAll(ml);
|
||||
_ = try writer.write(ml);
|
||||
|
||||
inline for (0..comptime fields.count()) |i| {
|
||||
if (i > 0) {
|
||||
try writer.writeAll(mm);
|
||||
_ = try writer.write(mm);
|
||||
}
|
||||
const padding = max_column_widths[i] + 2;
|
||||
for (0..padding) |_| {
|
||||
try writer.writeAll(hor);
|
||||
_ = try writer.write(hor);
|
||||
}
|
||||
}
|
||||
|
||||
try writer.writeAll(mr ++ "\n");
|
||||
_ = try writer.write(mr ++ "\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,9 +155,6 @@ fn write_aligned(
|
||||
max_width: usize,
|
||||
alignment: Alignment,
|
||||
) !void {
|
||||
std.debug.assert(data.len > 0);
|
||||
std.debug.assert(max_width >= data.len);
|
||||
|
||||
const padding: [2]usize = switch (alignment) {
|
||||
.left => .{ 0, max_width - data.len },
|
||||
.right => .{ max_width - data.len, 0 },
|
||||
@@ -168,13 +166,13 @@ fn write_aligned(
|
||||
};
|
||||
|
||||
for (0..padding[0]) |_| {
|
||||
try writer.writeByte(' ');
|
||||
_ = try writer.write(" ");
|
||||
}
|
||||
|
||||
try writer.writeAll(data);
|
||||
_ = try writer.write(data);
|
||||
|
||||
for (0..padding[1]) |_| {
|
||||
try writer.writeByte(' ');
|
||||
_ = try writer.write(" ");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user