From d3f40d70e25d86a692f5d1ec846b326ef58dc958 Mon Sep 17 00:00:00 2001 From: Leah Amelia Chen Date: Tue, 22 Jul 2025 16:14:53 +0000 Subject: [PATCH] terminal/osc: allow empty payloads xterm docs explicitly say that empty payloads should be permitted and are used to clear the selected clipboards, so we need to implement that correctly. The GTK apprt still shows a "Copied to Clipboard" toast though and we might want to change that too --- src/terminal/osc.zig | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/terminal/osc.zig b/src/terminal/osc.zig index 9c35bd07e..7875f2037 100644 --- a/src/terminal/osc.zig +++ b/src/terminal/osc.zig @@ -800,6 +800,9 @@ pub const Parser = struct { self.temp_state = .{ .str = &self.command.clipboard_contents.data }; self.buf_start = self.buf_idx; self.prepAllocableString(); + + // See clipboard_kind_end + self.complete = true; }, else => { self.command.clipboard_contents.kind = c; @@ -812,6 +815,11 @@ pub const Parser = struct { self.temp_state = .{ .str = &self.command.clipboard_contents.data }; self.buf_start = self.buf_idx; self.prepAllocableString(); + + // OSC 52 can have empty payloads (quoting xterm ctlseqs): + // "If the second parameter is neither a base64 string nor ?, + // then the selection is cleared." + self.complete = true; }, else => self.state = .invalid, }, @@ -1928,6 +1936,21 @@ test "OSC: get/set clipboard with allocator" { try testing.expect(std.mem.eql(u8, "?", cmd.clipboard_contents.data)); } +test "OSC: clear clipboard" { + const testing = std.testing; + + var p: Parser = .{ .alloc = testing.allocator }; + defer p.deinit(); + + const input = "52;;"; + for (input) |ch| p.next(ch); + + const cmd = p.end(null).?; + try testing.expect(cmd == .clipboard_contents); + try testing.expect(cmd.clipboard_contents.kind == 'c'); + try testing.expect(std.mem.eql(u8, "", cmd.clipboard_contents.data)); +} + test "OSC: report pwd" { const testing = std.testing;