Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3847bc247a | ||
|
|
784d52eac4 | ||
|
|
f78406448a | ||
|
|
50b592b125 | ||
|
|
7faff1e70d | ||
|
|
c17b97608c | ||
|
|
1e1ad7be17 | ||
|
|
429c0f89b9 | ||
|
|
ad0617a7e5 | ||
|
|
df75b0fdb5 | ||
|
|
89f68fe674 | ||
|
|
89dfeca508 | ||
|
|
a72ede5259 | ||
|
|
7254bda609 | ||
|
|
d8ddd4a18e | ||
|
|
948554d022 | ||
|
|
a9bb9cdeaf | ||
|
|
8132b0fc04 | ||
|
|
d5bb5b19c5 | ||
|
|
1d7a175d29 | ||
|
|
61ceb027a6 | ||
|
|
3e55f6a973 | ||
|
|
a5f4a60d46 | ||
|
|
36ff1857b7 | ||
|
|
48ab100e13 | ||
|
|
1363bad02d |
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@@ -3,6 +3,10 @@ name: Build
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ "main" ]
|
branches: [ "main" ]
|
||||||
|
paths:
|
||||||
|
- 'src/**'
|
||||||
|
- 'build.zig'
|
||||||
|
- 'build.zig.zon'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
|||||||
18
CONTRIBUTING.md
Normal file
18
CONTRIBUTING.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# How to contribute to Zigfetch
|
||||||
|
|
||||||
|
## Did you find a bug?
|
||||||
|
|
||||||
|
- Do not open up a GitHub issue if the bug is a security vulnerability, refer to the [security policy](https://github.com/utox39/zigfetch/blob/main/SECURITY.md).
|
||||||
|
- Ensure the bug was not already reported by searching on GitHub under [Issues](https://github.com/utox39/zigfetch/issues).
|
||||||
|
- If you're unable to find an open issue addressing the problem, open a new one.
|
||||||
|
|
||||||
|
## Do you want to make some changes to the code or documentation?
|
||||||
|
|
||||||
|
1. Fork the repo.
|
||||||
|
2. Create a new branch (because the `main` branch is protected).
|
||||||
|
3. Commit and push the changes to the new branch.
|
||||||
|
4. Open a pull request.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Thank you for your contribution!**
|
||||||
12
README.md
12
README.md
@@ -27,7 +27,7 @@ Zigfetch is a minimal [neofetch](https://github.com/dylanaraps/neofetch)/[fastfe
|
|||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
- \>= [zig v0.15.1](https://ziglang.org/)
|
- \>= [zig v0.15.2](https://ziglang.org/)
|
||||||
|
|
||||||
### Linux only
|
### Linux only
|
||||||
|
|
||||||
@@ -35,6 +35,8 @@ Zigfetch is a minimal [neofetch](https://github.com/dylanaraps/neofetch)/[fastfe
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
### Build from source
|
||||||
|
|
||||||
```console
|
```console
|
||||||
# Clone the repo
|
# Clone the repo
|
||||||
$ git clone https://github.com/utox39/zigfetch.git
|
$ git clone https://github.com/utox39/zigfetch.git
|
||||||
@@ -49,6 +51,12 @@ $ zig build -Doptimize=ReleaseSafe
|
|||||||
$ mv ./zig-out/zigfetch ~/bin/
|
$ mv ./zig-out/zigfetch ~/bin/
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Via [Homebrew](https://brew.sh/)
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ brew install utox39/tap/zigfetch
|
||||||
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```console
|
```console
|
||||||
@@ -168,4 +176,4 @@ To change the Username and Hostname color (HEX colors only):
|
|||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
If you would like to contribute to this project just create a pull request which I will try to review as soon as possible.
|
Please see [CONTIBUTING](https://github.com/utox39/zigfetch/blob/main/CONTRIBUTING.md). Thanks!
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
// This is a [Semantic Version](https://semver.org/).
|
// This is a [Semantic Version](https://semver.org/).
|
||||||
// In a future version of Zig it will be used for package deduplication.
|
// In a future version of Zig it will be used for package deduplication.
|
||||||
.version = "0.23.0",
|
.version = "0.24.2",
|
||||||
|
|
||||||
// Together with name, this represents a globally unique package
|
// Together with name, this represents a globally unique package
|
||||||
// identifier. This field is generated by the Zig toolchain when the
|
// identifier. This field is generated by the Zig toolchain when the
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
// Tracks the earliest Zig version that the package considers to be a
|
// Tracks the earliest Zig version that the package considers to be a
|
||||||
// supported use case.
|
// supported use case.
|
||||||
.minimum_zig_version = "0.15.1",
|
.minimum_zig_version = "0.15.2",
|
||||||
|
|
||||||
// This field is optional.
|
// This field is optional.
|
||||||
// Each dependency must either provide a `url` and `hash`, or a `path`.
|
// Each dependency must either provide a `url` and `hash`, or a `path`.
|
||||||
|
|||||||
@@ -72,9 +72,10 @@ pub fn printAsciiAndModules(allocator: std.mem.Allocator, ascii_art_path: ?[]u8,
|
|||||||
|
|
||||||
var ascii_art_data: []const u8 = undefined;
|
var ascii_art_data: []const u8 = undefined;
|
||||||
if (ascii_art_path) |ascii| {
|
if (ascii_art_path) |ascii| {
|
||||||
var ascii_file = try std.fs.cwd().openFile(ascii, .{});
|
const ascii_file = try std.fs.cwd().openFile(ascii, .{ .mode = .read_only });
|
||||||
defer ascii_file.close();
|
defer ascii_file.close();
|
||||||
ascii_art_data = try ascii_file.readToEndAlloc(allocator, std.math.maxInt(usize));
|
const file_size = (try ascii_file.stat()).size;
|
||||||
|
ascii_art_data = try utils.readFile(allocator, ascii_file, file_size);
|
||||||
} else {
|
} else {
|
||||||
ascii_art_data = @embedFile("./assets/ascii/guy_fawks.txt");
|
ascii_art_data = @embedFile("./assets/ascii/guy_fawks.txt");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const ascii = @import("ascii.zig");
|
const ascii = @import("ascii.zig");
|
||||||
|
const utils = @import("utils.zig");
|
||||||
|
|
||||||
pub const Module = struct {
|
pub const Module = struct {
|
||||||
type: []u8,
|
type: []u8,
|
||||||
@@ -68,14 +69,16 @@ pub fn readConfigFile(allocator: std.mem.Allocator) !?std.json.Parsed(Config) {
|
|||||||
const config_abs_path = try std.mem.concat(allocator, u8, &.{ home, "/.config/zigfetch/config.json" });
|
const config_abs_path = try std.mem.concat(allocator, u8, &.{ home, "/.config/zigfetch/config.json" });
|
||||||
defer allocator.free(config_abs_path);
|
defer allocator.free(config_abs_path);
|
||||||
|
|
||||||
const file = std.fs.openFileAbsolute(config_abs_path, .{ .mode = .read_only }) catch |err| switch (err) {
|
const config_file = std.fs.openFileAbsolute(config_abs_path, .{ .mode = .read_only }) catch |err| switch (err) {
|
||||||
error.FileNotFound => return null,
|
error.FileNotFound => return null,
|
||||||
else => return err,
|
else => return err,
|
||||||
};
|
};
|
||||||
defer file.close();
|
defer config_file.close();
|
||||||
|
|
||||||
const data = try file.readToEndAlloc(allocator, std.math.maxInt(usize));
|
const file_size = (try config_file.stat()).size;
|
||||||
defer allocator.free(data);
|
|
||||||
|
|
||||||
return try std.json.parseFromSlice(Config, allocator, data, .{ .allocate = .alloc_always });
|
const config_data = try utils.readFile(allocator, config_file, file_size);
|
||||||
|
defer allocator.free(config_data);
|
||||||
|
|
||||||
|
return try std.json.parseFromSlice(Config, allocator, config_data, .{ .allocate = .alloc_always });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const utils = @import("../utils.zig");
|
||||||
const c_unistd = @cImport(@cInclude("unistd.h"));
|
const c_unistd = @cImport(@cInclude("unistd.h"));
|
||||||
const c_statvfs = @cImport(@cInclude("sys/statvfs.h"));
|
const c_statvfs = @cImport(@cInclude("sys/statvfs.h"));
|
||||||
const c_libpci = @cImport(@cInclude("pci/pci.h"));
|
const c_libpci = @cImport(@cInclude("pci/pci.h"));
|
||||||
@@ -44,9 +45,16 @@ pub fn getCpuInfo(allocator: std.mem.Allocator) !CpuInfo {
|
|||||||
|
|
||||||
// Reads /proc/cpuinfo
|
// Reads /proc/cpuinfo
|
||||||
const cpuinfo_path = "/proc/cpuinfo";
|
const cpuinfo_path = "/proc/cpuinfo";
|
||||||
var file = try std.fs.cwd().openFile(cpuinfo_path, .{});
|
const cpuinfo_file = try std.fs.cwd().openFile(cpuinfo_path, .{ .mode = .read_only });
|
||||||
defer file.close();
|
defer cpuinfo_file.close();
|
||||||
const cpuinfo_data = try file.readToEndAlloc(allocator, std.math.maxInt(usize));
|
|
||||||
|
// NOTE: procfs is a pseudo-filesystem, so it is not possible to determine the size of a file
|
||||||
|
// https://docs.kernel.org/filesystems/proc.html
|
||||||
|
// https://en.wikipedia.org/wiki/Procfs
|
||||||
|
//
|
||||||
|
// Only the first section (core 0) will be parsed
|
||||||
|
// 512 is more than enough
|
||||||
|
const cpuinfo_data = try utils.readFile(allocator, cpuinfo_file, 512);
|
||||||
defer allocator.free(cpuinfo_data);
|
defer allocator.free(cpuinfo_data);
|
||||||
|
|
||||||
// Parsing /proc/cpuinfo
|
// Parsing /proc/cpuinfo
|
||||||
@@ -77,6 +85,7 @@ pub fn getCpuInfo(allocator: std.mem.Allocator) !CpuInfo {
|
|||||||
|
|
||||||
var cpu_max_freq: f32 = 0.0;
|
var cpu_max_freq: f32 = 0.0;
|
||||||
|
|
||||||
|
// NOTE: this is the preferred approach beacause it is the most accurate
|
||||||
const cpuinfo_max_freq_path = "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq";
|
const cpuinfo_max_freq_path = "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq";
|
||||||
var cmf_exists: bool = true;
|
var cmf_exists: bool = true;
|
||||||
|
|
||||||
@@ -89,14 +98,13 @@ pub fn getCpuInfo(allocator: std.mem.Allocator) !CpuInfo {
|
|||||||
|
|
||||||
if (cmf_exists) {
|
if (cmf_exists) {
|
||||||
// Reads /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq
|
// Reads /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq
|
||||||
var file2 = try std.fs.cwd().openFile(cpuinfo_max_freq_path, .{});
|
const maxfreq_file = try std.fs.cwd().openFile(cpuinfo_max_freq_path, .{ .mode = .read_only });
|
||||||
|
defer maxfreq_file.close();
|
||||||
defer file2.close();
|
const maxfreq_data = try utils.readFile(allocator, maxfreq_file, 32);
|
||||||
const cpuinfo_max_freq_data = try file2.readToEndAlloc(allocator, std.math.maxInt(usize));
|
defer allocator.free(maxfreq_data);
|
||||||
defer allocator.free(cpuinfo_max_freq_data);
|
|
||||||
|
|
||||||
// Parsing /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq
|
// Parsing /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq
|
||||||
const trimmed = std.mem.trim(u8, cpuinfo_max_freq_data, " \n\r");
|
const trimmed = std.mem.trim(u8, maxfreq_data, " \n\r");
|
||||||
const cpu_max_freq_khz: f32 = try std.fmt.parseFloat(f32, trimmed);
|
const cpu_max_freq_khz: f32 = try std.fmt.parseFloat(f32, trimmed);
|
||||||
cpu_max_freq = cpu_max_freq_khz / 1_000_000;
|
cpu_max_freq = cpu_max_freq_khz / 1_000_000;
|
||||||
} else {
|
} else {
|
||||||
@@ -203,9 +211,16 @@ fn parseGpuName(allocator: std.mem.Allocator, name: []u8) !?[]u8 {
|
|||||||
pub fn getRamInfo(allocator: std.mem.Allocator) !RamInfo {
|
pub fn getRamInfo(allocator: std.mem.Allocator) !RamInfo {
|
||||||
// Reads /proc/meminfo
|
// Reads /proc/meminfo
|
||||||
const meminfo_path = "/proc/meminfo";
|
const meminfo_path = "/proc/meminfo";
|
||||||
const file = try std.fs.cwd().openFile(meminfo_path, .{});
|
const meminfo_file = try std.fs.cwd().openFile(meminfo_path, .{ .mode = .read_only });
|
||||||
defer file.close();
|
defer meminfo_file.close();
|
||||||
const meminfo_data = try file.readToEndAlloc(allocator, std.math.maxInt(usize));
|
|
||||||
|
// NOTE: procfs is a pseudo-filesystem, so it is not possible to determine the size of a file
|
||||||
|
// https://docs.kernel.org/filesystems/proc.html
|
||||||
|
// https://en.wikipedia.org/wiki/Procfs
|
||||||
|
//
|
||||||
|
// We only need to read the first few lines
|
||||||
|
// 512 is more than enough
|
||||||
|
const meminfo_data = try utils.readFile(allocator, meminfo_file, 512);
|
||||||
defer allocator.free(meminfo_data);
|
defer allocator.free(meminfo_data);
|
||||||
|
|
||||||
// Parsing /proc/meminfo
|
// Parsing /proc/meminfo
|
||||||
@@ -265,9 +280,16 @@ pub fn getRamInfo(allocator: std.mem.Allocator) !RamInfo {
|
|||||||
pub fn getSwapInfo(allocator: std.mem.Allocator) !?SwapInfo {
|
pub fn getSwapInfo(allocator: std.mem.Allocator) !?SwapInfo {
|
||||||
// Reads /proc/meminfo
|
// Reads /proc/meminfo
|
||||||
const meminfo_path = "/proc/meminfo";
|
const meminfo_path = "/proc/meminfo";
|
||||||
const file = try std.fs.cwd().openFile(meminfo_path, .{});
|
const meminfo_file = try std.fs.cwd().openFile(meminfo_path, .{ .mode = .read_only });
|
||||||
defer file.close();
|
defer meminfo_file.close();
|
||||||
const meminfo_data = try file.readToEndAlloc(allocator, std.math.maxInt(usize));
|
|
||||||
|
// NOTE: procfs is a pseudo-filesystem, so it is not possible to determine the size of a file
|
||||||
|
// https://docs.kernel.org/filesystems/proc.html
|
||||||
|
// https://en.wikipedia.org/wiki/Procfs
|
||||||
|
//
|
||||||
|
// We only need to read the first few lines
|
||||||
|
// 512 is ok
|
||||||
|
const meminfo_data = try utils.readFile(allocator, meminfo_file, 512);
|
||||||
defer allocator.free(meminfo_data);
|
defer allocator.free(meminfo_data);
|
||||||
|
|
||||||
// Parsing /proc/meminfo
|
// Parsing /proc/meminfo
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const utils = @import("../utils.zig");
|
||||||
const c_sysinfo = @cImport(@cInclude("sys/sysinfo.h"));
|
const c_sysinfo = @cImport(@cInclude("sys/sysinfo.h"));
|
||||||
const c_utsname = @cImport(@cInclude("sys/utsname.h"));
|
const c_utsname = @cImport(@cInclude("sys/utsname.h"));
|
||||||
|
|
||||||
@@ -77,9 +78,10 @@ pub fn getKernelInfo(allocator: std.mem.Allocator) !KernelInfo {
|
|||||||
|
|
||||||
pub fn getOsInfo(allocator: std.mem.Allocator) ![]u8 {
|
pub fn getOsInfo(allocator: std.mem.Allocator) ![]u8 {
|
||||||
const os_release_path = "/etc/os-release";
|
const os_release_path = "/etc/os-release";
|
||||||
const file = try std.fs.cwd().openFile(os_release_path, .{});
|
const os_release_file = try std.fs.cwd().openFile(os_release_path, .{ .mode = .read_only });
|
||||||
defer file.close();
|
defer os_release_file.close();
|
||||||
const os_release_data = try file.readToEndAlloc(allocator, std.math.maxInt(usize));
|
const size = (try os_release_file.stat()).size;
|
||||||
|
const os_release_data = try utils.readFile(allocator, os_release_file, size);
|
||||||
defer allocator.free(os_release_data);
|
defer allocator.free(os_release_data);
|
||||||
|
|
||||||
var pretty_name: ?[]const u8 = null;
|
var pretty_name: ?[]const u8 = null;
|
||||||
@@ -119,10 +121,8 @@ pub fn getWindowManagerInfo(allocator: std.mem.Allocator) ![]const u8 {
|
|||||||
defer file.close();
|
defer file.close();
|
||||||
|
|
||||||
// NOTE: https://stackoverflow.com/questions/23534263/what-is-the-maximum-allowed-limit-on-the-length-of-a-process-name
|
// NOTE: https://stackoverflow.com/questions/23534263/what-is-the-maximum-allowed-limit-on-the-length-of-a-process-name
|
||||||
var file_buf: [16]u8 = undefined;
|
const proc_name = try utils.readFile(allocator, file, 16);
|
||||||
var reader = std.fs.File.Reader.init(file, &file_buf);
|
defer allocator.free(proc_name);
|
||||||
const read = try reader.read(&file_buf);
|
|
||||||
const proc_name = file_buf[0..read];
|
|
||||||
|
|
||||||
const proc_name_trimmed = std.mem.trim(u8, proc_name, "\n");
|
const proc_name_trimmed = std.mem.trim(u8, proc_name, "\n");
|
||||||
|
|
||||||
|
|||||||
@@ -114,3 +114,14 @@ test "getLongestAsciiArtRowLen" {
|
|||||||
|
|
||||||
try std.testing.expectEqual(40, try getLongestAsciiArtRowLen(rows[0..]));
|
try std.testing.expectEqual(40, try getLongestAsciiArtRowLen(rows[0..]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn readFile(allocator: std.mem.Allocator, file: std.fs.File, size: usize) ![]const u8 {
|
||||||
|
var file_buf = try allocator.alloc(u8, size);
|
||||||
|
defer allocator.free(file_buf);
|
||||||
|
|
||||||
|
const read = try file.read(file_buf);
|
||||||
|
|
||||||
|
const data = file_buf[0..read];
|
||||||
|
|
||||||
|
return allocator.dupe(u8, data);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user