Merge pull request #2 from utox39/feat/user-config

Feat/user config
This commit is contained in:
utox39
2025-05-28 17:47:27 +02:00
committed by GitHub
7 changed files with 457 additions and 78 deletions

View File

@@ -1,5 +1,13 @@
# Zigfetch
- [Description](#description)
- [Requirements](#requirements)
- [Installation](#installation)
- [Usage](#usage)
- [Configuration](#configuration)
- [Roadtrip](#roadtrip)
- [Contributing](#contributing)
## Description
Zigfetch is a minimal [neofetch](https://github.com/dylanaraps/neofetch)/[fastfetch](https://github.com/fastfetch-cli/fastfetch) like system information tool
@@ -21,7 +29,7 @@ $ cd path/to/zigfetch
$ zig build -Doptimize=ReleaseSafe
# Then move it somewhere in your $PATH. Here is an example:
$ mv ./zig-out/zigfetch ~/bin
$ mv ./zig-out/zigfetch ~/bin/
```
## Usage
@@ -30,12 +38,36 @@ $ mv ./zig-out/zigfetch ~/bin
$ zigfetch
```
### Configuration
> [!IMPORTANT]
> Currently, Zig does not have a built-in library for JSON validation via JSON schema, so it is very important to follow the pattern shown in the default configuration file ([config.json](https://github.com/utox39/zigfetch/blob/feat/user-config/config.json)) to avoid errors
- Create the config folder
```console
$ mkdir -p ~/.config/zigfetch
```
- Create the config file
```console
$ cd ~/.config/zigfetch
$ touch config.json
```
- Or copy the default config (preferred way)
```console
$ cp /path/to/zigfetch/config.json ~/.config/zigfetch/config.json
```
## Roadtrip
- [ ] Add ASCII art for each operating system and Linux distro
- [ ] Add GPU info for Linux
- [ ] Add packages info for Linux
- [ ] Add user customization
- [x] Add user customization
## 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.

View File

@@ -10,7 +10,7 @@
// This is a [Semantic Version](https://semver.org/).
// In a future version of Zig it will be used for package deduplication.
.version = "0.3.1",
.version = "0.4.0",
// Together with name, this represents a globally unique package
// identifier. This field is generated by the Zig toolchain when the

69
config.json Normal file
View File

@@ -0,0 +1,69 @@
{
"modules": [
{
"type": "os",
"key": "OS",
"key_color": "#f5c543"
},
{
"type": "kernel",
"key": "Kernel",
"key_color": "#f5c543"
},
{
"type": "uptime",
"key": "Uptime",
"key_color": "#f5c543"
},
{
"type": "packages",
"key": "Packages",
"key_color": "#f5c543"
},
{
"type": "shell",
"key": "Shell",
"key_color": "#f5c543"
},
{
"type": "cpu",
"key": "Cpu",
"key_color": "#f5c543"
},
{
"type": "gpu",
"key": "Gpu",
"key_color": "#f5c543"
},
{
"type": "ram",
"key": "Ram",
"key_color": "#f5c543"
},
{
"type": "swap",
"key": "Swap",
"key_color": "#f5c543"
},
{
"type": "disk",
"key": "Disk",
"key_color": "#f5c543"
},
{
"type": "net",
"key": "Local IP",
"key_color": "#f5c543"
},
{
"type": "terminal",
"key": "Terminal",
"key_color": "#f5c543"
},
{
"type": "locale",
"key": "Locale",
"key_color": "#f5c543"
}
]
}

View File

@@ -12,6 +12,58 @@ pub const White = "\x1b[37m";
pub fn selectAscii() void {}
inline fn parseHexChar(c: u8) !u8 {
return switch (c) {
'0'...'9' => c - '0',
'a'...'f' => c - 'a' + 10,
'A'...'F' => c - 'A' + 10,
else => error.InvalidHexChar,
};
}
fn parseHexByte(s: []const u8) !u8 {
if (s.len != 2) return error.InvalidHexByteLength;
const hi = try parseHexChar(s[0]);
const lo = try parseHexChar(s[1]);
// Example: ff
// hi = 0b00001111 (15)
// lo = 0b00001111 (15)
//
// hi << 4 -> 0b11110000 (240)
//
// (hi << 4) | lo -> 0b11110000 | 0b00001111
// => 0b11111111 (255)
return (hi << 4) | lo;
}
/// Converts a hex color to rgb
pub fn hexColorToRgb(color: []const u8) !struct { r: u8, g: u8, b: u8 } {
if (color.len < 6 or color.len > 7) return error.InvalidHexColorLength;
var start: usize = 0;
if (color[0] == '#') start = 1;
return .{
.r = try parseHexByte(color[start .. start + 2]),
.g = try parseHexByte(color[start + 2 .. start + 4]),
.b = try parseHexByte(color[start + 4 ..]),
};
}
test "parse #ffffff" {
const result = try hexColorToRgb("#ffffff");
try std.testing.expect((result.r == 255) and (result.g == 255) and (result.b == 255));
}
test "parse ffffff" {
const result = try hexColorToRgb("ffffff");
try std.testing.expect((result.r == 255) and (result.g == 255) and (result.b == 255));
}
pub fn printAscii(allocator: std.mem.Allocator, sys_info_list: std.ArrayList([]u8)) !void {
const stdout_file = std.io.getStdOut().writer();
var bw = std.io.bufferedWriter(stdout_file);

65
src/config.zig Normal file
View File

@@ -0,0 +1,65 @@
const std = @import("std");
const builtin = @import("builtin");
const ascii = @import("ascii.zig");
pub const Module = struct {
type: []u8,
key: []u8,
key_color: []u8,
};
pub const Config = struct {
modules: []Module,
};
pub const ModuleType = enum {
os,
kernel,
uptime,
packages,
shell,
cpu,
gpu,
ram,
swap,
disk,
terminal,
locale,
net,
};
pub fn getModulesTypes(allocator: std.mem.Allocator, config: ?std.json.Parsed(Config)) !std.ArrayList(ModuleType) {
var modules_list = std.ArrayList(ModuleType).init(allocator);
if (config) |c| {
for (c.value.modules) |module| {
const module_enum = std.meta.stringToEnum(ModuleType, module.type);
if (module_enum) |m| {
try modules_list.append(m);
} else {
return error.InvalidModule;
}
}
}
return modules_list;
}
pub fn readConfigFile(allocator: std.mem.Allocator) !?std.json.Parsed(Config) {
const home = try std.process.getEnvVarOwned(allocator, "HOME");
defer allocator.free(home);
const config_abs_path = try std.mem.concat(allocator, u8, &.{ home, "/.config/zigfetch/config.json" });
defer allocator.free(config_abs_path);
const file = std.fs.openFileAbsolute(config_abs_path, .{ .mode = .read_only }) catch |err| switch (err) {
error.FileNotFound => return null,
else => return err,
};
defer file.close();
const data = try file.readToEndAlloc(allocator, std.math.maxInt(usize));
defer allocator.free(data);
return try std.json.parseFromSlice(Config, allocator, data, .{ .allocate = .alloc_always });
}

210
src/formatters.zig Normal file
View File

@@ -0,0 +1,210 @@
const builtin = @import("builtin");
const std = @import("std");
const ascii = @import("ascii.zig");
const detection = @import("detection.zig").os_module;
pub const formatters = [_]*const fn (allocator: std.mem.Allocator, key: []const u8, key_color: []const u8) anyerror![]u8{
&getFormattedOsInfo,
&getFormattedKernelInfo,
&getFormattedUptimeInfo,
&getFormattedPackagesInfo,
&getFormattedShellInfo,
&getFormattedCpuInfo,
&getFormattedGpuInfo,
&getFormattedRamInfo,
&getFormattedSwapInfo,
&getFormattedDiskInfo,
&getFormattedTerminalNameInfo,
&getFormattedLocaleInfo,
};
pub const default_formatters = [_]*const fn (allocator: std.mem.Allocator) anyerror![]u8{
&getDefaultFormattedOsInfo,
&getDefaultFormattedKernelInfo,
&getDefaultFormattedUptimeInfo,
&getDefaultFormattedPackagesInfo,
&getDefaultFormattedShellInfo,
&getDefaultFormattedCpuInfo,
&getDefaultFormattedGpuInfo,
&getDefaultFormattedRamInfo,
&getDefaultFormattedSwapInfo,
&getDefaultFormattedDiskInfo,
&getDefaultFormattedTerminalNameInfo,
&getDefaultFormattedLocaleInfo,
};
pub fn getDefaultFormattedKernelInfo(allocator: std.mem.Allocator) ![]u8 {
return try getFormattedKernelInfo(allocator, "Kernel", ascii.Yellow);
}
pub fn getFormattedKernelInfo(allocator: std.mem.Allocator, key: []const u8, key_color: []const u8) ![]u8 {
const kernel_info = try detection.system.getKernelInfo(allocator);
defer allocator.free(kernel_info.kernel_name);
defer allocator.free(kernel_info.kernel_release);
var buf: [1024]u8 = undefined;
return try std.fmt.allocPrint(allocator, "{s}{s}:{s} {s}", .{ key_color, key, ascii.Reset, try kernel_info.toStr(&buf) });
}
pub fn getDefaultFormattedOsInfo(allocator: std.mem.Allocator) ![]u8 {
return try getFormattedOsInfo(allocator, "OS", ascii.Yellow);
}
pub fn getFormattedOsInfo(allocator: std.mem.Allocator, key: []const u8, key_color: []const u8) ![]u8 {
const os_info = try detection.system.getOsInfo(allocator);
defer allocator.free(os_info);
return try std.fmt.allocPrint(allocator, "{s}{s}:{s} {s}", .{ key_color, key, ascii.Reset, os_info });
}
pub fn getDefaultFormattedLocaleInfo(allocator: std.mem.Allocator) ![]u8 {
return try getFormattedLocaleInfo(allocator, "Locale", ascii.Yellow);
}
pub fn getFormattedLocaleInfo(allocator: std.mem.Allocator, key: []const u8, key_color: []const u8) ![]u8 {
const locale = try detection.system.getLocale(allocator);
defer allocator.free(locale);
return try std.fmt.allocPrint(allocator, "{s}{s}:{s} {s}", .{ key_color, key, ascii.Reset, locale });
}
pub fn getDefaultFormattedUptimeInfo(allocator: std.mem.Allocator) ![]u8 {
return try getFormattedUptimeInfo(allocator, "Uptime", ascii.Yellow);
}
pub fn getFormattedUptimeInfo(allocator: std.mem.Allocator, key: []const u8, key_color: []const u8) ![]u8 {
const uptime = try detection.system.getSystemUptime();
var buf: [1024]u8 = undefined;
return try std.fmt.allocPrint(allocator, "{s}{s}:{s} {s}", .{ key_color, key, ascii.Reset, try uptime.toStr(&buf) });
}
pub fn getDefaultFormattedPackagesInfo(allocator: std.mem.Allocator) ![]u8 {
return try getFormattedPackagesInfo(allocator, "Packages", ascii.Yellow);
}
pub fn getFormattedPackagesInfo(allocator: std.mem.Allocator, key: []const u8, key_color: []const u8) ![]u8 {
if (builtin.os.tag == .macos) {
const packages_info = try detection.packages.getPackagesInfo(allocator);
defer allocator.free(packages_info);
return try std.fmt.allocPrint(allocator, "{s}{s}:{s}{s}", .{ key_color, key, ascii.Reset, packages_info });
} else if (builtin.os.tag == .linux) {
return try std.fmt.allocPrint(allocator, "{s}{s}:{s} WIP", .{ key_color, key, ascii.Reset });
}
}
pub fn getDefaultFormattedShellInfo(allocator: std.mem.Allocator) ![]u8 {
return try getFormattedShellInfo(allocator, "Shell", ascii.Yellow);
}
pub fn getFormattedShellInfo(allocator: std.mem.Allocator, key: []const u8, key_color: []const u8) ![]u8 {
const shell = try detection.user.getShell(allocator);
defer allocator.free(shell);
return try std.fmt.allocPrint(allocator, "{s}{s}:{s} {s}", .{ key_color, key, ascii.Reset, shell[0..(shell.len - 1)] });
}
pub fn getDefaultFormattedCpuInfo(allocator: std.mem.Allocator) ![]u8 {
return try getFormattedCpuInfo(allocator, "Cpu", ascii.Yellow);
}
pub fn getFormattedCpuInfo(allocator: std.mem.Allocator, key: []const u8, key_color: []const u8) ![]u8 {
const cpu_info = try detection.hardware.getCpuInfo(allocator);
defer allocator.free(cpu_info.cpu_name);
var buf: [1024]u8 = undefined;
return try std.fmt.allocPrint(allocator, "{s}{s}:{s} {s}", .{ key_color, key, ascii.Reset, try cpu_info.toStr(&buf) });
}
pub fn getDefaultFormattedGpuInfo(allocator: std.mem.Allocator) ![]u8 {
return try getFormattedGpuInfo(allocator, "Gpu", ascii.Yellow);
}
pub fn getFormattedGpuInfo(allocator: std.mem.Allocator, key: []const u8, key_color: []const u8) ![]u8 {
if (builtin.os.tag == .macos) {
const gpu_info = try detection.hardware.getGpuInfo(allocator);
defer allocator.free(gpu_info.gpu_name);
var buf: [1024]u8 = undefined;
return try std.fmt.allocPrint(allocator, "{s}{s}:{s} {s}", .{ key_color, key, ascii.Reset, try gpu_info.toStr(&buf) });
} else if (builtin.os.tag == .linux) {
return try std.fmt.allocPrint(allocator, "{s}{s}:{s} WIP", .{ key_color, key, ascii.Reset });
}
}
pub fn getDefaultFormattedRamInfo(allocator: std.mem.Allocator) ![]u8 {
return try getFormattedRamInfo(allocator, "Ram", ascii.Yellow);
}
pub fn getFormattedRamInfo(allocator: std.mem.Allocator, key: []const u8, key_color: []const u8) ![]u8 {
var ram_info = detection.hardware.RamInfo{
.ram_size = 0.0,
.ram_usage = 0.0,
.ram_usage_percentage = 0,
};
if (builtin.os.tag == .macos) {
ram_info = try detection.hardware.getRamInfo();
} else if (builtin.os.tag == .linux) {
ram_info = try detection.hardware.getRamInfo(allocator);
}
var buf: [1024]u8 = undefined;
return try std.fmt.allocPrint(allocator, "{s}{s}:{s} {s}", .{ key_color, key, ascii.Reset, try ram_info.toStr(&buf) });
}
pub fn getDefaultFormattedSwapInfo(allocator: std.mem.Allocator) ![]u8 {
return try getFormattedSwapInfo(allocator, "Swap", ascii.Yellow);
}
pub fn getFormattedSwapInfo(allocator: std.mem.Allocator, key: []const u8, key_color: []const u8) ![]u8 {
var buf: [1024]u8 = undefined;
const swap_info = if (builtin.os.tag == .macos) try detection.hardware.getSwapInfo() else if (builtin.os.tag == .linux) try detection.hardware.getSwapInfo(allocator);
if (swap_info) |s| {
return try std.fmt.allocPrint(allocator, "{s}{s}:{s} {s}", .{ key_color, key, ascii.Reset, try s.toStr(&buf) });
} else {
return try std.fmt.allocPrint(allocator, "{s}{s}:{s} Disabled", .{ key_color, key, ascii.Reset });
}
}
pub fn getDefaultFormattedDiskInfo(allocator: std.mem.Allocator) ![]u8 {
return try getFormattedDiskInfo(allocator, "Disk", ascii.Yellow);
}
pub fn getFormattedDiskInfo(allocator: std.mem.Allocator, key: []const u8, key_color: []const u8) ![]u8 {
const disk_info = try detection.hardware.getDiskSize("/");
var buf: [1024]u8 = undefined;
return try std.fmt.allocPrint(allocator, "{s}{s}{s} {s}", .{ key_color, key, ascii.Reset, try disk_info.toStr(&buf) });
}
pub fn getDefaultFormattedTerminalNameInfo(allocator: std.mem.Allocator) ![]u8 {
return try getFormattedTerminalNameInfo(allocator, "Terminal", ascii.Yellow);
}
pub fn getFormattedTerminalNameInfo(allocator: std.mem.Allocator, key: []const u8, key_color: []const u8) ![]u8 {
const terminal_name = try detection.user.getTerminalName(allocator);
defer allocator.free(terminal_name);
return try std.fmt.allocPrint(allocator, "{s}{s}:{s} {s}", .{ key_color, key, ascii.Reset, terminal_name });
}
pub fn getDefaultFormattedNetInfo(allocator: std.mem.Allocator) ![]u8 {
return try getFormattedNetInfo(allocator, "Local IP", ascii.Yellow);
}
pub fn getFormattedNetInfo(allocator: std.mem.Allocator, key: []const u8, key_color: []const u8) !std.ArrayList([]u8) {
var formatted_net_info_list = std.ArrayList([]u8).init(allocator);
var buf: [1024]u8 = undefined;
var net_info_list = try detection.network.getNetInfo(allocator);
for (net_info_list.items) |n| {
try formatted_net_info_list.append(try std.fmt.allocPrint(allocator, "{s}{s} {s}{s}", .{ key_color, key, ascii.Reset, try n.toStr(&buf) }));
allocator.free(n.interface_name);
allocator.free(n.ipv4_addr);
@memset(&buf, 0);
}
net_info_list.deinit();
return formatted_net_info_list;
}

View File

@@ -2,6 +2,8 @@ const std = @import("std");
const builtin = @import("builtin");
const detection = @import("detection.zig").os_module;
const ascii = @import("ascii.zig");
const config = @import("config.zig");
const formatters = @import("formatters.zig");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
@@ -17,19 +19,22 @@ pub fn main() !void {
}
}
var buf1: [1024]u8 = undefined;
var buf2: [1024]u8 = undefined;
const conf = try config.readConfigFile(allocator);
defer if (conf) |c| c.deinit();
const modules_types = try config.getModulesTypes(allocator, conf);
defer modules_types.deinit();
const username = try detection.user.getUsername(allocator);
const hostname = try detection.system.getHostname(allocator);
try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}{s}{s}@{s}{s}{s}", .{
try sys_info_list.append(try std.fmt.allocPrint(allocator, "{s}{s}{s}@{s}{s}{s}", .{
ascii.Yellow,
username,
ascii.Reset,
ascii.Magenta,
hostname,
ascii.Reset,
})));
}));
allocator.free(hostname);
allocator.free(username);
@@ -37,82 +42,28 @@ pub fn main() !void {
@memset(separtor_buffer, '-');
try sys_info_list.append(separtor_buffer);
const kernel_info = try detection.system.getKernelInfo(allocator);
try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Kernel:{s} {s}", .{ ascii.Yellow, ascii.Reset, try kernel_info.toStr(&buf2) })));
allocator.free(kernel_info.kernel_name);
allocator.free(kernel_info.kernel_release);
if (modules_types.items.len == 0) {
inline for (0..formatters.formatters.len) |i| {
try sys_info_list.append(try formatters.default_formatters[i](allocator));
}
} else if (conf) |c| {
for (modules_types.items, c.value.modules) |module_type, module| {
var buf: [32]u8 = undefined;
const rgb = try ascii.hexColorToRgb(module.key_color);
const key_color = try std.fmt.bufPrint(&buf, "\x1b[38;2;{d};{d};{d}m", .{ rgb.r, rgb.g, rgb.b });
const os_info = try detection.system.getOsInfo(allocator);
try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}OS:{s} {s}", .{ ascii.Yellow, ascii.Reset, os_info })));
allocator.free(os_info);
if (module_type == config.ModuleType.net) {
var formatted_net_info_list = try formatters.getFormattedNetInfo(allocator, module.key, key_color);
defer formatted_net_info_list.deinit();
const locale = try detection.system.getLocale(allocator);
try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Locale:{s} {s}", .{ ascii.Yellow, ascii.Reset, locale })));
allocator.free(locale);
try sys_info_list.appendSlice(formatted_net_info_list.items);
const uptime = try detection.system.getSystemUptime();
try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Uptime:{s} {s}", .{ ascii.Yellow, ascii.Reset, try uptime.toStr(&buf2) })));
if (builtin.os.tag == .macos) {
const packages_info = try detection.packages.getPackagesInfo(allocator);
try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Packages:{s}{s}", .{ ascii.Yellow, ascii.Reset, packages_info })));
allocator.free(packages_info);
} else if (builtin.os.tag == .linux) {
try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Packages:{s} WIP", .{ ascii.Yellow, ascii.Reset })));
continue;
}
const shell = try detection.user.getShell(allocator);
try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Shell:{s} {s}", .{ ascii.Yellow, ascii.Reset, shell[0..(shell.len - 1)] })));
allocator.free(shell);
const cpu_info = try detection.hardware.getCpuInfo(allocator);
try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Cpu:{s} {s}", .{ ascii.Yellow, ascii.Reset, try cpu_info.toStr(&buf2) })));
allocator.free(cpu_info.cpu_name);
if (builtin.os.tag == .macos) {
const gpu_info = try detection.hardware.getGpuInfo(allocator);
try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Gpu:{s} {s}", .{ ascii.Yellow, ascii.Reset, try gpu_info.toStr(&buf2) })));
allocator.free(gpu_info.gpu_name);
} else if (builtin.os.tag == .linux) {
try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Gpu:{s} WIP", .{ ascii.Yellow, ascii.Reset })));
try sys_info_list.append(try formatters.formatters[@intFromEnum(module_type)](allocator, module.key, key_color));
}
var ram_info = detection.hardware.RamInfo{
.ram_size = 0.0,
.ram_usage = 0.0,
.ram_usage_percentage = 0,
};
if (builtin.os.tag == .macos) {
ram_info = try detection.hardware.getRamInfo();
} else if (builtin.os.tag == .linux) {
ram_info = try detection.hardware.getRamInfo(allocator);
}
try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Ram:{s} {s}", .{ ascii.Yellow, ascii.Reset, try ram_info.toStr(&buf2) })));
const swap_info = if (builtin.os.tag == .macos) try detection.hardware.getSwapInfo() else if (builtin.os.tag == .linux) try detection.hardware.getSwapInfo(allocator);
if (swap_info) |s| {
try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Swap:{s} {s}", .{ ascii.Yellow, ascii.Reset, try s.toStr(&buf2) })));
} else {
try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Swap:{s} Disabled", .{ ascii.Yellow, ascii.Reset })));
}
const disk_info = try detection.hardware.getDiskSize("/");
try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Disk{s} {s}", .{ ascii.Yellow, ascii.Reset, try disk_info.toStr(&buf2) })));
const terminal_name = try detection.user.getTerminalName(allocator);
try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Terminal:{s} {s}", .{ ascii.Yellow, ascii.Reset, terminal_name })));
allocator.free(terminal_name);
const net_info_list = try detection.network.getNetInfo(allocator);
for (net_info_list.items) |n| {
try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Local IP {s}{s}", .{ ascii.Yellow, ascii.Reset, try n.toStr(&buf2) })));
allocator.free(n.interface_name);
allocator.free(n.ipv4_addr);
}
net_info_list.deinit();
@memset(&buf1, 0);
@memset(&buf2, 0);
try ascii.printAscii(allocator, sys_info_list);
}