home
tpb

repository View

feat(OSC52): added tmux autodetect

change ID
zxwnlotmtutmrlqukwosowvplolnynvu
git commit
2178c4d83916eadade432906838e844efd7f63d1
author
Grace Yoder <grace_yoder@outlook.com> - 2026-07-06T14:22:52-06:00
committer
Grace Yoder <grace_yoder@outlook.com> - 2026-07-06T17:15:47-06:00
parents
wltktvzrqsqo
refs
refs/tags/0.1.2
signature
Present (not validated)
feat(OSC52): added tmux autodetect

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 6016 bytes
file src/Clip.zig 1560 bytes
file src/main.zig 3003 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.1",
+    .version = "0.1.2",
     .fingerprint = 0x203a601c46df0265,
     .minimum_zig_version = "0.16.0",
     .paths = .{

src/Clip/OSC52.zig

modified (file → file)

--- a/src/Clip/OSC52.zig
+++ b/src/Clip/OSC52.zig
@@ -12,19 +12,29 @@
 leftover_bytes: [3]u8,
 leftover_count: u8,
 
+/// This is to wrap the OSC buffer in the tmux passthrough sequence. This lets
+/// OSC52 clipboard requests go directly to the host instead of going to a tmux
+/// buffer.
+/// https://github.com/tmux/tmux/wiki/FAQ#what-is-the-passthrough-escape-sequence-and-how-do-i-use-it
+/// Since tmux v3.7, there is a `get-clipboard` option and when it is set to
+/// `request` any OSC52 query that comes to it will cause the tmux buffer to
+/// update before sending the information.
+/// https://raw.githubusercontent.com/tmux/tmux/3.7b/CHANGES
+/// This still wraps the tmux session in an escape whenever one is detected
+/// since this option is still incredibly new.
 is_tmux: bool,
 
 const base64encoder =
     std.base64.Base64Encoder.init(std.base64.standard_alphabet_chars, '=');
 
-pub fn init(alloc: std.mem.Allocator, io: std.Io, buf_size: usize) !OSC52 {
+pub fn init(alloc: std.mem.Allocator, io: std.Io, buf_size: usize, is_tmux: bool) !OSC52 {
     return .{
         .alloc = alloc,
         .io = io,
         .base64buffer = try std.ArrayList(u8).initCapacity(alloc, buf_size),
         .leftover_bytes = undefined,
         .leftover_count = 0,
-        .is_tmux = false,
+        .is_tmux = is_tmux,
     };
 }
 
@@ -125,7 +135,7 @@
 }
 
 test "basic base64 encode" {
-    var osc = try OSC52.init(std.testing.allocator, std.testing.io, 1024);
+    var osc = try OSC52.init(std.testing.allocator, std.testing.io, 1024, false);
     defer osc.free();
     try osc.writeCopyBuffer("part1");
     try osc.encodeRemaining();
@@ -133,7 +143,7 @@
 }
 
 test "multi part base64 encode" {
-    var osc = try OSC52.init(std.testing.allocator, std.testing.io, 1024);
+    var osc = try OSC52.init(std.testing.allocator, std.testing.io, 1024, false);
     defer osc.free();
     try osc.writeCopyBuffer("part1");
     try osc.writeCopyBuffer("part2");
@@ -142,7 +152,7 @@
 }
 
 test "tiny buffers base64 encode" {
-    var osc = try OSC52.init(std.testing.allocator, std.testing.io, 1024);
+    var osc = try OSC52.init(std.testing.allocator, std.testing.io, 1024, false);
     defer osc.free();
     try osc.writeCopyBuffer("part1");
     try osc.writeCopyBuffer("part2");
@@ -158,7 +168,7 @@
 }
 
 test "big buffers base64 encode" {
-    var osc = try OSC52.init(std.testing.allocator, std.testing.io, 1024);
+    var osc = try OSC52.init(std.testing.allocator, std.testing.io, 1024, false);
     defer osc.free();
     try osc.writeCopyBuffer("part1part1part1part1part1part1part1part1part1|");
     try osc.writeCopyBuffer("part2part2part2part2part2part2part2part2part2");

src/main.zig

modified (file → file)

--- a/src/main.zig
+++ b/src/main.zig
@@ -28,8 +28,11 @@
         init.environ_map.get("SSH_CLIENT") != null or
         init.environ_map.get("SSH_TTY") != null;
 
+    const is_tmux =
+        init.environ_map.get("TMUX") != null;
+
     if (is_ssh) {
-        var clip = try Clip.OSC52.init(alloc, io, size);
+        var clip = try Clip.OSC52.init(alloc, io, size, is_tmux);
         defer clip.free();
         try run(io, &clip);
         return;
@@ -61,7 +64,7 @@
     }
 
     // Fallback Clipboard
-    var clip = try Clip.OSC52.init(alloc, io, size);
+    var clip = try Clip.OSC52.init(alloc, io, size, is_tmux);
     defer clip.free();
     try run(io, &clip);
 }