home
tpb

repository View

feat: added ForkOut backend and now forks out to `xclip` and `wl-copy` on linux

change ID
rqlxoyoyputsynntntxwznkputwwxtqu
git commit
c228995f20e16a97ad6baff05a0d46d3fffe3295
author
Grace Yoder <grace_yoder@outlook.com> - 2026-07-03T19:43:26-06:00
committer
Grace Yoder <grace_yoder@outlook.com> - 2026-07-03T20:40:06-06:00
parents
wvqnrnltuwux
refs
refs/tags/0.1.1
signature
Present (not validated)
feat: added ForkOut backend and now forks out to `xclip` and `wl-copy` on linux

tree

type name size
file .crow/build.yml 1532 bytes
file .crow/release.yml 566 bytes
file .gitignore 354 bytes
file LICENSE 1073 bytes
file README.md 632 bytes
file build.zig 2345 bytes
file build.zig.zon 247 bytes
file src/Clip/ForkOut.zig 621 bytes
file src/Clip/NSPBBridge.m 382 bytes
file src/Clip/NSPasteboard.zig 1456 bytes
file src/Clip/OSC52.zig 4564 bytes
file src/Clip.zig 1560 bytes
file src/main.zig 2831 bytes

diff

build.zig.zon

modified (file → file)

--- a/build.zig.zon
+++ b/build.zig.zon
@@ -1,6 +1,6 @@
 .{
     .name = .tpb,
-    .version = "0.1.0",
+    .version = "0.1.1",
     .fingerprint = 0x203a601c46df0265,
     .minimum_zig_version = "0.16.0",
     .paths = .{

src/Clip/ForkOut.zig

added (absent → file)

--- a/src/Clip/ForkOut.zig
+++ b/src/Clip/ForkOut.zig
@@ -0,0 +1,24 @@
+/// ForkOut Clipboard backend
+/// Fulfills `Clip` interface
+pub const ForkOut = @This();
+
+const std = @import("std");
+
+extern fn sendPB(text: [*:0]const u8) void;
+extern fn initPB() void;
+
+io: std.Io,
+
+child: std.process.Child,
+
+pub fn init(io: std.Io, argv: []const []const u8) !ForkOut {
+    return .{ .child = try std.process.spawn(io, .{ .argv = argv, .stdin = .pipe }), .io = io };
+}
+
+pub fn writeCopyBuffer(self: *ForkOut, buf: []const u8) anyerror!void {
+    try self.child.stdin.?.writeStreamingAll(self.io, buf);
+}
+
+pub fn writePasteboard(self: *ForkOut) anyerror!void {
+    self.child.stdin.?.close(self.io);
+}

src/Clip.zig

modified (file → file)

--- a/src/Clip.zig
+++ b/src/Clip.zig
@@ -7,6 +7,8 @@
 pub const NSPasteboard =
     if (builtin.target.os.tag == .macos) @import("Clip/NSPasteboard.zig") else void;
 
+pub const ForkOut = @import("Clip/ForkOut.zig");
+
 // I am not sure if this is super idiomatic Zig or if this is bad practice, but
 // by ensuring that all Clip backends implement the same methods, we are able
 // to use the `anytype` type and we are able to have an interface that is able

src/main.zig

modified (file → file)

--- a/src/main.zig
+++ b/src/main.zig
@@ -42,6 +42,22 @@
         return;
     }
 
+    // I don't like this but it will stay until I review how dispatch works
+    // with zig since I will probably be refactoring there
+    linux: {
+        const xdg_type = init.environ_map.get("XDG_SESSION_TYPE") orelse "";
+
+        if (std.mem.eql(u8, xdg_type, "wayland")) {
+            var clip = Clip.ForkOut.init(io, &[_][]const u8{"wl-copy"}) catch break :linux;
+            try run(io, &clip);
+            return;
+        } else if (std.mem.eql(u8, xdg_type, "x11")) {
+            var clip = Clip.ForkOut.init(io, &[_][]const u8{ "xclip", "-selection", "clipboard" }) catch break :linux;
+            try run(io, &clip);
+            return;
+        }
+    }
+
     // Fallback Clipboard
     var clip = try Clip.OSC52.init(alloc, io, size);
     defer clip.free();