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)
.{
.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)
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,
};
}
}
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();
}
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");
}
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");
}
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)
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;
}
// 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);
}