From b52e76334ee634df243750065d0dba66ca657a52 Mon Sep 17 00:00:00 2001 From: Damien MEHALA Date: Wed, 1 Jan 2025 17:02:06 +0100 Subject: [PATCH] feat: parse ConEmu OSC9;1 --- src/terminal/osc.zig | 84 ++++++++++++++++++++++++++++++++++++++++- src/terminal/stream.zig | 2 +- 2 files changed, 84 insertions(+), 2 deletions(-) diff --git a/src/terminal/osc.zig b/src/terminal/osc.zig index 19d8212a0..da081daa9 100644 --- a/src/terminal/osc.zig +++ b/src/terminal/osc.zig @@ -67,7 +67,7 @@ pub const Command = union(enum) { /// End of current command. /// - /// The exit-code need not be specified if if there are no options, + /// The exit-code need not be specified if there are no options, /// or if the command was cancelled (no OSC "133;C"), such as by typing /// an interrupt/cancel character (typically ctrl-C) during line-editing. /// Otherwise, it must be an integer code, where 0 means the command @@ -158,6 +158,9 @@ pub const Command = union(enum) { /// End a hyperlink (OSC 8) hyperlink_end: void, + /// Sleep (OSC 9;1) in ms + sleep: u16, + /// Set progress state (OSC 9;4) progress: struct { state: ProgressState, @@ -353,6 +356,8 @@ pub const Parser = struct { osc_9, // ConEmu specific substates + conemu_sleep, + conemu_sleep_value, conemu_progress_prestate, conemu_progress_state, conemu_progress_prevalue, @@ -777,6 +782,9 @@ pub const Parser = struct { }, .osc_9 => switch (c) { + '1' => { + self.state = .conemu_sleep; + }, '4' => { self.state = .conemu_progress_prestate; }, @@ -788,6 +796,21 @@ pub const Parser = struct { else => self.showDesktopNotification(), }, + .conemu_sleep => switch (c) { + ';' => { + self.command = .{ .sleep = 100 }; + self.buf_start = self.buf_idx; + self.complete = true; + self.state = .conemu_sleep_value; + }, + else => self.state = .invalid, + }, + + .conemu_sleep_value => switch (c) { + '0'...'9' => {}, + else => self.state = .invalid, + }, + .conemu_progress_prestate => switch (c) { ';' => { self.command = .{ .progress = .{ @@ -1147,6 +1170,22 @@ pub const Parser = struct { self.temp_state.str.* = self.buf[self.buf_start..self.buf_idx]; } + fn endConEmuSleepValue(self: *Parser) void { + switch (self.command) { + .sleep => |*v| { + const str = self.buf[self.buf_start..self.buf_idx]; + if (str.len != 0) { + if (std.fmt.parseUnsigned(u16, str, 10)) |num| { + v.* = @min(num, 10000); + } else |_| { + v.* = 10000; + } + } + }, + else => {}, + } + } + fn endKittyColorProtocolOption(self: *Parser, kind: enum { key_only, key_and_value }, final: bool) void { if (self.temp_state.key.len == 0) { log.warn("zero length key in kitty color protocol", .{}); @@ -1225,6 +1264,7 @@ pub const Parser = struct { .semantic_option_value => self.endSemanticOptionValue(), .hyperlink_uri => self.endHyperlink(), .string => self.endString(), + .conemu_sleep_value => self.endConEmuSleepValue(), .allocable_string => self.endAllocableString(), .kitty_color_protocol_key => self.endKittyColorProtocolOption(.key_only, true), .kitty_color_protocol_value => self.endKittyColorProtocolOption(.key_and_value, true), @@ -1634,6 +1674,48 @@ test "OSC: set palette color" { try testing.expectEqualStrings(cmd.set_color.value, "rgb:aa/bb/cc"); } +test "OSC: conemu sleep" { + const testing = std.testing; + + var p: Parser = .{}; + + const input = "9;1;420"; + for (input) |ch| p.next(ch); + + const cmd = p.end('\x1b').?; + + try testing.expect(cmd == .sleep); + try testing.expectEqual(420, cmd.sleep); +} + +test "OSC: conemu sleep with no value default to 100ms" { + const testing = std.testing; + + var p: Parser = .{}; + + const input = "9;1;"; + for (input) |ch| p.next(ch); + + const cmd = p.end('\x1b').?; + + try testing.expect(cmd == .sleep); + try testing.expectEqual(100, cmd.sleep); +} + +test "OSC: conemu sleep cannot exceed 10000ms" { + const testing = std.testing; + + var p: Parser = .{}; + + const input = "9;1;12345"; + for (input) |ch| p.next(ch); + + const cmd = p.end('\x1b').?; + + try testing.expect(cmd == .sleep); + try testing.expectEqual(10000, cmd.sleep); +} + test "OSC: show desktop notification" { const testing = std.testing; diff --git a/src/terminal/stream.zig b/src/terminal/stream.zig index 59a8e704d..8772050a9 100644 --- a/src/terminal/stream.zig +++ b/src/terminal/stream.zig @@ -1455,7 +1455,7 @@ pub fn Stream(comptime Handler: type) type { } else log.warn("unimplemented OSC callback: {}", .{cmd}); }, - .progress => { + .progress, .sleep => { log.warn("unimplemented OSC callback: {}", .{cmd}); }, }