Skip to content

Commit 0511d78

Browse files
refractor, optimization, conditional fetching, aur package setup
1 parent ffcbaad commit 0511d78

25 files changed

+1209
-365
lines changed

.SRCINFO

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
pkgbase = lifetch-git
2+
pkgdesc = Fast system information fetcher written in zig
3+
pkgver = 0.1.1.r23.gffcbaad
4+
pkgrel = 1
5+
url = https://github.com/nuiipointerexception/lifetch
6+
arch = x86_64
7+
arch = aarch64
8+
license = MIT
9+
makedepends = zig
10+
makedepends = git
11+
depends = glibc
12+
source = git+https://github.com/nuiipointerexception/lifetch.git
13+
sha256sums = SKIP
14+
15+
pkgname = lifetch-git

.gitignore

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,13 @@
11
.zig-cache/*
2-
zig-out/*
2+
zig-out/*
3+
4+
# PKGBUILD
5+
*.tar.gz
6+
*.pkg.tar.zst
7+
*.pkg.tar.xz
8+
*.pkg.tar.bz2
9+
*.pkg.tar
10+
*.pkg.tar.gz
11+
*.pkg.tar.bz2
12+
*.pkg.tar.xz
13+
*.pkg.tar.zst

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of
44

55
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
66

7-
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

PKGBUILD

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,37 @@
11
# Maintainer: viable <hi@viable.gg>
2-
pkgname=lifetch
3-
pkgver=0.1.0
2+
pkgname=lifetch-git
3+
pkgver=0.1.1.r23.gffcbaad
44
pkgrel=1
55
pkgdesc="Fast system information fetcher written in zig"
6-
arch=('x86_64')
6+
arch=('x86_64' 'aarch64')
77
url="https://github.com/nuiipointerexception/lifetch"
88
license=('MIT')
9-
depends=()
10-
makedepends=('zig')
9+
depends=('glibc')
10+
makedepends=('zig' 'git')
1111
source=("git+${url}.git")
1212
sha256sums=('SKIP')
1313

14+
pkgver() {
15+
cd "$pkgname"
16+
git describe --long --tags --abbrev=7 --match="v*" HEAD 2>/dev/null || \
17+
echo "0.1.1.r$(git rev-list --count HEAD).g$(git rev-parse --short=7 HEAD)"
18+
}
19+
20+
prepare() {
21+
cd "$pkgname"
22+
}
23+
1424
build() {
1525
cd "$pkgname"
16-
zig build -Doptimize=ReleaseSafe
26+
zig build \
27+
--summary all \
28+
-Doptimize=ReleaseFast \
29+
-Dcpu=native
1730
}
1831

1932
package() {
2033
cd "$pkgname"
2134
install -Dm755 zig-out/bin/lifetch "$pkgdir/usr/bin/lifetch"
2235
install -Dm644 README.md "$pkgdir/usr/share/doc/$pkgname/README.md"
2336
install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
24-
}
37+
}

README.md

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,39 @@
11
# lifetch
2+
23
the fastest way to fetch your system info!
34

4-
sub 1ms execution time!
5+
```bash
6+
~ zig build --release=fast && hyperfine --warmup 10 --runs 1000 'zig-out/bin/lifetch'
7+
Benchmark 1: zig-out/bin/lifetch
8+
Time (mean ± σ): 264.4 µs ± 144.3 µs [User: 253.7 µs, System: 492.1 µs]
9+
Range (min … max): 0.0 µs … 906.6 µs 1000 runs
10+
```
11+
12+
## tested on
13+
14+
- archlinux
15+
16+
more to come!
17+
18+
## prerequisites
19+
20+
- [zig master](https://ziglang.org/)
21+
22+
i recommend installing `zig-nightly-bin` from the aur if you are on archlinux.
23+
24+
## config
25+
26+
generated inside your home directory at
27+
`~/.config/lifetch/config.ini`
28+
29+
## building
30+
31+
```bash
32+
zig build --release=fast
33+
```
34+
35+
## running
536

637
```bash
7-
hyperfine --warmup 10 --runs 100 './lifetch'
8-
Benchmark 1: ./lifetch
9-
Time (mean ± σ): 919.1 µs ± 638.6 µs [User: 141.0 µs, System: 1166.9 µs]
10-
Range (min … max): 0.0 µs … 1999.5 µs 100 runs
38+
zig build run --release=fast
1139
```

build.zig

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,19 @@ pub fn build(b: *std.Build) void {
44
const target = b.standardTargetOptions(.{});
55
const optimize = b.standardOptimizeOption(.{});
66

7-
const exe_mod = b.createModule(.{
7+
const mod = b.createModule(.{
88
.root_source_file = b.path("src/main.zig"),
99
.target = target,
1010
.optimize = optimize,
1111
});
1212

13+
mod.addAnonymousImport("config", .{
14+
.root_source_file = b.path("config.ini"),
15+
});
16+
1317
const exe = b.addExecutable(.{
1418
.name = "lifetch",
15-
.root_module = exe_mod,
19+
.root_module = mod,
1620
});
1721

1822
b.installArtifact(exe);
@@ -21,7 +25,4 @@ pub fn build(b: *std.Build) void {
2125
run_cmd.step.dependOn(b.getInstallStep());
2226
const run_step = b.step("run", "fetch your system info");
2327
run_step.dependOn(&run_cmd.step);
24-
25-
const check_step = b.step("check", "zls diagnostics");
26-
check_step.dependOn(b.getInstallStep());
2728
}

build.zig.zon

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
.{
22
.name = "lifetch",
3-
.version = "0.0.1",
3+
.version = "0.1.1",
44
.paths = .{
55
"build.zig",
66
"build.zig.zon",
77
"src",
8+
"config.ini",
9+
"README.md",
10+
"LICENSE",
811
},
912
}

config.ini

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Lifetch Configuration
2+
#
3+
# Format your output using these placeholders:
4+
# {user} - Current username
5+
# {host} - Hostname
6+
# {shell} - Current shell
7+
# {term} - Terminal name
8+
# {uptime} - System uptime
9+
# {pkgs} - Package count
10+
# {session} - Wayland/X11
11+
# {wm} - Window manager
12+
# {distro} - Linux distribution (short form)
13+
# {distro_pretty} - Linux distribution (pretty name)
14+
#
15+
# Colors and Styles:
16+
# Basic colors: {red}text{/red}, {green}text{/green}, etc.
17+
# RGB colors: {rgb(255,0,0)}text{/rgb}
18+
# Styles: {bold}text{/bold}, {underline}text{/underline}, etc.
19+
#
20+
# Example formats:
21+
# format = "{bold}{red}{user}@{host}{/red}{/bold} on {green}{term}{/green}"
22+
# format = "{rgb(255,165,0)}os{/rgb}: {host} | {bold}shell{/bold}: {shell}"
23+
24+
format = {bold}{cyan}{user}@{host}{/cyan}{/bold} since: {uptime}
25+
{green}{shell}{/green} on {yellow}{term}{/yellow}
26+
{magenta}{pkgs}{/magenta} pkgs on {blue}{distro} / {blue}{wm} / {blue}{session}{/blue}

src/color.zig

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const std = @import("std");
2-
const builtin = @import("builtin");
32
const os = std.os;
43
const fs = std.fs;
4+
const builtin = @import("builtin");
55

66
pub const ColorSupport = struct {
77
truecolor: bool = false,
@@ -29,7 +29,7 @@ pub const ColorSupport = struct {
2929
}
3030
};
3131

32-
fn parseColorTag(tag: []const u8) ?Color {
32+
pub fn parseColorTag(tag: []const u8) ?Color {
3333
return switch (tag[0]) {
3434
'b' => if (std.mem.eql(u8, tag, "black")) .black else if (std.mem.eql(u8, tag, "blue")) .blue else null,
3535
'r' => if (std.mem.eql(u8, tag, "red")) .red else null,
@@ -42,7 +42,7 @@ pub const ColorSupport = struct {
4242
};
4343
}
4444

45-
fn parseStyleTag(tag: []const u8) ?[]const u8 {
45+
pub fn parseStyleTag(tag: []const u8) ?[]const u8 {
4646
return switch (tag[0]) {
4747
'b' => if (std.mem.eql(u8, tag, "bold")) Style.bold else if (std.mem.eql(u8, tag, "blink")) Style.blink else null,
4848
'd' => if (std.mem.eql(u8, tag, "dim")) Style.dim else null,
@@ -55,7 +55,7 @@ pub const ColorSupport = struct {
5555
};
5656
}
5757

58-
fn parseRgbTag(tag: []const u8) !Rgb {
58+
pub fn parseRgbTag(tag: []const u8) !Rgb {
5959
if (!std.mem.startsWith(u8, tag, "rgb(") or !std.mem.endsWith(u8, tag, ")")) {
6060
return error.InvalidColorFormat;
6161
}
@@ -126,34 +126,56 @@ pub const ColorSupport = struct {
126126

127127
pub fn formatText(self: *const ColorSupport, text: []const u8, writer: anytype) !void {
128128
var i: usize = 0;
129-
while (i < text.len) : (i += 1) {
130-
if (text[i] == '{') {
131-
const end_idx = std.mem.indexOfScalarPos(u8, text, i, '}') orelse break;
129+
const len = text.len;
130+
131+
while (i < len) {
132+
if (text[i] == '{' and i + 1 < len) {
133+
const start_idx = i;
134+
const end_idx = std.mem.indexOfScalarPos(u8, text, i, '}') orelse {
135+
try writer.writeByte(text[i]);
136+
i += 1;
137+
continue;
138+
};
139+
132140
const tag = text[i + 1 .. end_idx];
133141

134-
if (std.mem.startsWith(u8, tag, "/")) {
142+
if (tag.len > 0 and tag[0] == '/') {
135143
try writer.writeAll("\x1b[0m");
136-
i = end_idx;
144+
i = end_idx + 1;
137145
continue;
138146
}
139147

148+
var processed = false;
149+
140150
if (std.mem.startsWith(u8, tag, "rgb(")) {
141151
if (self.truecolor) {
142-
const rgb = ColorSupport.parseRgbTag(tag) catch continue;
143-
try writer.print("\x1b[38;2;{};{};{}m", .{ rgb.r, rgb.g, rgb.b });
152+
if (ColorSupport.parseRgbTag(tag)) |rgb| {
153+
try writer.print("\x1b[38;2;{};{};{}m", .{ rgb.r, rgb.g, rgb.b });
154+
processed = true;
155+
} else |_| {}
144156
}
145-
} else if (ColorSupport.parseColorTag(tag)) |c| {
146-
if (self.basic) {
157+
} else if (self.basic) {
158+
if (ColorSupport.parseColorTag(tag)) |c| {
147159
try writer.writeAll(c.ansiSequence());
160+
processed = true;
148161
}
149-
} else if (ColorSupport.parseStyleTag(tag)) |s| {
150-
try writer.writeAll(s);
151-
} else {
152-
try writer.writeAll(text[i .. end_idx + 1]);
153162
}
154-
i = end_idx;
163+
164+
if (!processed) {
165+
if (ColorSupport.parseStyleTag(tag)) |s| {
166+
try writer.writeAll(s);
167+
processed = true;
168+
}
169+
}
170+
171+
if (!processed) {
172+
try writer.writeAll(text[start_idx .. end_idx + 1]);
173+
}
174+
175+
i = end_idx + 1;
155176
} else {
156177
try writer.writeByte(text[i]);
178+
i += 1;
157179
}
158180
}
159181
}
@@ -305,7 +327,6 @@ pub const Style = struct {
305327
}
306328
};
307329

308-
// Initialize color support at runtime
309330
var color_support: ?ColorSupport = null;
310331

311332
pub fn getColorSupport() ColorSupport {

0 commit comments

Comments
 (0)