Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
BrookJeynes committed Nov 4, 2024
0 parents commit 1cee380
Show file tree
Hide file tree
Showing 12 changed files with 859 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
zig-out/
.zig-cache/
27 changes: 27 additions & 0 deletions README
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
zysys
-----

A simple unix system fetch tool.

```
bjeyn@fedora
--------------
distro Fedora Linux 40 (Workstation Edition) x86_64
uptime 6 13 57
kernel 6.10.12-200.fc40.x86_64
desktop river
shell zsh
memory 17170 / 63572 MB (27%)
battery 96% (Charging)
cpu AMD Ryzen 7 7840U w/ Radeon 780M Graphics
disk 30G / 1.9T (2%)
```

An example config can be found in `./example-config.ziggy` with its schema
defined in `./config.ziggy-schema`.

The config will first read from `$XDG_CONFIG_HOME/zysys/config.ziggy`, falling
back to `$HOME/.config/zysys/config.ziggy` if not set.


This project is built using Zig `v0.14.0-dev.2126+e27b4647d`.
75 changes: 75 additions & 0 deletions build.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
const std = @import("std");

const release_targets: []const std.Target.Query = &.{
.{ .cpu_arch = .aarch64, .os_tag = .macos },
.{ .cpu_arch = .aarch64, .os_tag = .linux },
.{ .cpu_arch = .x86_64, .os_tag = .linux },
.{ .cpu_arch = .x86_64, .os_tag = .macos },
};

pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});

// Build targets for release.
const build_all = b.option(bool, "all-targets", "Build all targets in ReleaseSafe mode.") orelse false;
if (build_all) {
try build_targets(b);
return;
}

const ziggy_dep = b.dependency("ziggy", .{
.target = target,
.optimize = optimize,
});
const ziggy = ziggy_dep.module("ziggy");

const exe = b.addExecutable(.{
.name = "zysys",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
exe.root_module.addImport("ziggy", ziggy);
b.installArtifact(exe);

const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| {
run_cmd.addArgs(args);
}

const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
}

fn build_targets(b: *std.Build) !void {
for (release_targets) |t| {
const target = b.resolveTargetQuery(t);

const ziggy_dep = b.dependency("ziggy", .{
.target = target,
.optimize = .ReleaseSafe,
});
const ziggy = ziggy_dep.module("ziggy");

const exe = b.addExecutable(.{
.name = "zysys",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = .ReleaseSafe,
});
exe.root_module.addImport("ziggy", ziggy);
b.installArtifact(exe);

const target_output = b.addInstallArtifact(exe, .{
.dest_dir = .{
.override = .{
.custom = try t.zigTriple(b.allocator),
},
},
});

b.getInstallStep().dependOn(&target_output.step);
}
}
20 changes: 20 additions & 0 deletions build.zig.zon
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.{
.name = "zysys",
.version = "0.1.0",
.minimum_zig_version = "0.14.0-dev.2126+e27b4647d",

.dependencies = .{
// Move to https://github.com/kristoff-it/ziggy/tree/zig-0.14.0-dev
// once https://github.com/kristoff-it/ziggy/pull/43 has been merged.
.ziggy = .{
.url = "git+https://github.com/BrookJeynes/ziggy?ref=add-enum-support#fb224b22f0a30005e521bde9a874bc959463362b",
.hash = "122034c46e43d6d7bc031caad233eb2547352df32e2a2b00fa494742ef6bca52d161",
},
},

.paths = .{
"build.zig",
"build.zig.zon",
"src",
},
}
17 changes: 17 additions & 0 deletions config.ziggy-schema
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
root = Config

@widgets = enum {
distro,
uptime,
kernel,
desktop,
shell,
memory,
battery,
cpu,
disk,
},

struct Config {
widgets: [@widgets],
}
11 changes: 11 additions & 0 deletions example-config.ziggy
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.widgets = [
@widgets("distro"),
@widgets("uptime"),
@widgets("kernel"),
@widgets("desktop"),
@widgets("shell"),
@widgets("memory"),
@widgets("battery"),
@widgets("cpu"),
@widgets("disk"),
],
29 changes: 29 additions & 0 deletions src/buffered_file_iter.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
const std = @import("std");

const BufferedFileIterator = @This();

alloc: std.mem.Allocator,
buf_reader: std.io.BufferedReader(4096, std.io.AnyReader),
line: std.ArrayList(u8),

pub fn init(alloc: std.mem.Allocator, reader: std.io.AnyReader) BufferedFileIterator {
return BufferedFileIterator{
.alloc = alloc,
.buf_reader = std.io.bufferedReader(reader),
.line = std.ArrayList(u8).init(alloc),
};
}

pub fn deinit(self: BufferedFileIterator) void {
self.line.deinit();
}

pub fn next(self: *BufferedFileIterator) !?[]const u8 {
self.line.clearRetainingCapacity();
const writer = self.line.writer();
self.buf_reader.reader().streamUntilDelimiter(writer, '\n', null) catch |err| switch (err) {
error.EndOfStream => return null,
else => return err,
};
return self.line.items;
}
28 changes: 28 additions & 0 deletions src/environment.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const std = @import("std");

pub fn get_home_dir() !?std.fs.Dir {
return try std.fs.openDirAbsolute(std.posix.getenv("HOME") orelse {
return null;
}, .{ .iterate = true });
}

pub fn get_xdg_config_home_dir() !?std.fs.Dir {
return try std.fs.openDirAbsolute(std.posix.getenv("XDG_CONFIG_HOME") orelse {
return null;
}, .{ .iterate = true });
}

pub fn file_exists(dir: std.fs.Dir, path: []const u8) bool {
const result = blk: {
_ = dir.openFile(path, .{}) catch |err| {
switch (err) {
error.FileNotFound => break :blk false,
else => {
break :blk true;
},
}
};
break :blk true;
};
return result;
}
180 changes: 180 additions & 0 deletions src/main.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
const std = @import("std");
const builtin = @import("builtin");
const stats = @import("stats.zig");
const sys_info = @import("sys_info.zig");
const environment = @import("environment.zig");
const ziggy = @import("ziggy");

const padding: u8 = 9;

const Widgets = enum {
distro,
uptime,
kernel,
desktop,
shell,
memory,
battery,
cpu,
disk,
};

const Config = struct {
widgets: []const Widgets,
};

const default_config = Config{
.widgets = &[_]Widgets{
.distro,
.uptime,
.kernel,
.desktop,
.shell,
.memory,
.battery,
.cpu,
.disk,
},
};

pub fn main() !void {
const stdout = std.io.getStdOut().writer();
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
var arena = std.heap.ArenaAllocator.init(gpa.allocator());
defer _ = arena.deinit();
var alloc = arena.allocator();

// Read config
const config = lbl: {
var config_path: []u8 = undefined;
defer alloc.free(config_path);

var config_home: std.fs.Dir = undefined;
defer config_home.close();

if (try environment.get_xdg_config_home_dir()) |path| {
config_home = path;
config_path = try std.fs.path.join(alloc, &.{ "zysys", "config.ziggy" });
} else {
if (try environment.get_home_dir()) |path| {
config_home = path;
config_path = try std.fs.path.join(alloc, &.{ ".config", "zysys", "config.ziggy" });
}
}

if (!environment.file_exists(config_home, config_path)) {
break :lbl default_config;
}

const contents = config_home.readFileAlloc(alloc, config_path, 4096) catch break :lbl default_config;
defer alloc.free(contents);
const contentsZ = try alloc.dupeZ(u8, contents);
defer alloc.free(contentsZ);
break :lbl ziggy.parseLeaky(Config, alloc, contentsZ, .{}) catch default_config;
};

// Print header
const user_env = try sys_info.getUser(alloc);
defer alloc.free(user_env);
const distro_id = try sys_info.getDistroId(alloc);
defer alloc.free(distro_id);

var header_buf: [1024]u8 = undefined;
const header = try std.fmt.bufPrint(&header_buf, "{s}@{s}\n", .{ user_env, distro_id });

try stdout.writeAll(header);
try stdout.print("{s[str]:-<[count]}\n", .{ .str = "-", .count = header.len + 1 });

// Print widgets
for (config.widgets) |widget| {
switch (widget) {
.distro => {
const distro = sys_info.getDistro(alloc) catch continue;
defer alloc.free(distro);

try stdout.print(
"{s[header]: <[padding]}{s[stat]}\n",
.{ .header = "distro", .stat = distro, .padding = padding },
);
},
.uptime => {
const uptime = stats.getUptime() catch continue;

try stdout.print(
"{s[header]: <[padding]}{[days]} {[hours]} {[minutes]}\n",
.{
.header = "uptime",
.days = uptime.days,
.hours = uptime.hours,
.minutes = uptime.minutes,
.padding = padding,
},
);
},
.kernel => {
const utsname = std.posix.uname();
const release = std.mem.sliceTo(&utsname.release, 0);

try stdout.print(
"{s[header]: <[padding]}{s[stat]}\n",
.{ .header = "kernel", .stat = release, .padding = padding },
);
},
.desktop => {
const desktop = sys_info.getDesktop(alloc) catch continue;
defer alloc.free(desktop);

try stdout.print(
"{s[header]: <[padding]}{s[stat]}\n",
.{ .header = "desktop", .stat = desktop, .padding = padding },
);
},
.shell => {
const shell = sys_info.getShell(alloc) catch continue;
defer alloc.free(shell);

try stdout.print(
"{s[header]: <[padding]}{s[stat]}\n",
.{ .header = "shell", .stat = shell, .padding = padding },
);
},
.memory => {
const mem = stats.getMemory(alloc, .{ .mb = true }) catch continue;
defer alloc.free(mem);

try stdout.print(
"{s[header]: <[padding]}{s[stat]}\n",
.{ .header = "memory", .stat = mem, .padding = padding },
);
},
.battery => {
const battery = stats.getBattery(alloc) catch continue;
defer alloc.free(battery);

try stdout.print(
"{s[header]: <[padding]}{s[stat]}\n",
.{ .header = "battery", .stat = battery, .padding = padding },
);
},
.cpu => {
const cpu = sys_info.getCpu(alloc) catch continue;
defer alloc.free(cpu);

try stdout.print(
"{s[header]: <[padding]}{s[stat]}\n",
.{ .header = "cpu", .stat = cpu, .padding = padding },
);
},
.disk => {
const disk = sys_info.getDisk(alloc) catch continue;
defer alloc.free(disk);

try stdout.print(
"{s[header]: <[padding]}{s[stat]}\n",
.{ .header = "disk", .stat = disk, .padding = padding },
);
},
}
}
}
Loading

0 comments on commit 1cee380

Please sign in to comment.