osc: conemu cleanup

- Add more comments, and make existing ones more consistent.
- Rename commands so they consitently have a `conemu_` prefix.
- Ensure that OSC 9 desktop notifications can be sent in the maximum
  number of circumstances. There are still many notifications that can't
  be sent because of our support for the ConEmu OSCs but that's the
  tradeoff we have chosen. We recommend that you switch to OSC 777 to
  ensure desktop notifications can be sent in all circumstances.
- Make sure that the tests that exercise the ConEmu OSCs have a
  consistent naming structure. That will make them easier to find
  through searching as well as make it easier to filter only the ConEmu
  OSC tests.
- Add more tests to make sure that desktop notifications are sent
  properly.
This commit is contained in:
Jeffrey C. Ollie
2025-08-26 21:28:50 -05:00
parent c1ab41afac
commit 64d8492836
2 changed files with 329 additions and 142 deletions

View File

@@ -147,25 +147,25 @@ pub const Command = union(enum) {
/// End a hyperlink (OSC 8)
hyperlink_end: void,
/// Sleep (OSC 9;1)
sleep: struct {
/// ConEmu sleep (OSC 9;1)
conemu_sleep: struct {
duration_ms: u16,
},
/// Show GUI message Box (OSC 9;2)
show_message_box: []const u8,
/// ConEmu show GUI message box (OSC 9;2)
conemu_show_message_box: []const u8,
/// Change ConEmu tab (OSC 9;3)
change_conemu_tab_title: union(enum) {
reset: void,
/// ConEmu change tab title (OSC 9;3)
conemu_change_tab_title: union(enum) {
reset,
value: []const u8,
},
/// Set progress state (OSC 9;4)
progress_report: ProgressReport,
/// ConEmu progress report (OSC 9;4)
conemu_progress_report: ProgressReport,
/// Wait input (OSC 9;5)
wait_input: void,
/// ConEmu wait input (OSC 9;5)
conemu_wait_input,
/// ConEmu GUI macro (OSC 9;6)
conemu_guimacro: []const u8,
@@ -961,19 +961,37 @@ pub const Parser = struct {
.osc_9 => switch (c) {
'1' => {
self.state = .conemu_sleep;
// This will end up being either a ConEmu sleep OSC 9;1,
// or a desktop notification OSC 9 that begins with '1', so
// mark as complete.
self.complete = true;
},
'2' => {
self.state = .conemu_message_box;
// This will end up being either a ConEmu message box OSC 9;2,
// or a desktop notification OSC 9 that begins with '2', so
// mark as complete.
self.complete = true;
},
'3' => {
self.state = .conemu_tab;
// This will end up being either a ConEmu message box OSC 9;3,
// or a desktop notification OSC 9 that begins with '3', so
// mark as complete.
self.complete = true;
},
'4' => {
self.state = .conemu_progress_prestate;
// This will end up being either a ConEmu progress report
// OSC 9;4, or a desktop notification OSC 9 that begins with
// '4', so mark as complete.
self.complete = true;
},
'5' => {
// Note that sending an OSC 9 desktop notification that
// starts with 5 is impossible due to this.
self.state = .swallow;
self.command = .{ .wait_input = {} };
self.command = .conemu_wait_input;
self.complete = true;
},
'6' => {
@@ -984,91 +1002,106 @@ pub const Parser = struct {
self.complete = true;
},
// Todo: parse out other ConEmu operating system commands.
// Even if we don't support them we probably don't want
// them showing up as desktop notifications.
// Todo: parse out other ConEmu operating system commands. Even
// if we don't support them we probably don't want them showing
// up as desktop notifications.
else => self.showDesktopNotification(),
},
.conemu_sleep => switch (c) {
';' => {
self.command = .{ .sleep = .{ .duration_ms = 100 } };
self.command = .{ .conemu_sleep = .{ .duration_ms = 100 } };
self.buf_start = self.buf_idx;
self.complete = true;
self.state = .conemu_sleep_value;
},
else => self.state = .invalid,
},
.conemu_message_box => switch (c) {
';' => {
self.command = .{ .show_message_box = undefined };
self.temp_state = .{ .str = &self.command.show_message_box };
self.buf_start = self.buf_idx;
self.complete = true;
self.prepAllocableString();
},
else => self.state = .invalid,
// OSC 9;1 <something other than semicolon> is a desktop
// notification.
else => self.showDesktopNotification(),
},
.conemu_sleep_value => switch (c) {
else => self.complete = true,
},
.conemu_message_box => switch (c) {
';' => {
self.command = .{ .conemu_show_message_box = undefined };
self.temp_state = .{ .str = &self.command.conemu_show_message_box };
self.buf_start = self.buf_idx;
self.complete = true;
self.prepAllocableString();
},
// OSC 9;2 <something other than semicolon> is a desktop
// notification.
else => self.showDesktopNotification(),
},
.conemu_tab => switch (c) {
';' => {
self.state = .conemu_tab_txt;
self.command = .{ .change_conemu_tab_title = .{ .reset = {} } };
self.command = .{ .conemu_change_tab_title = .reset };
self.buf_start = self.buf_idx;
self.complete = true;
},
else => self.state = .invalid,
// OSC 9;3 <something other than semicolon> is a desktop
// notification.
else => self.showDesktopNotification(),
},
.conemu_tab_txt => {
self.command = .{ .change_conemu_tab_title = .{ .value = undefined } };
self.temp_state = .{ .str = &self.command.change_conemu_tab_title.value };
self.command = .{ .conemu_change_tab_title = .{ .value = undefined } };
self.temp_state = .{ .str = &self.command.conemu_change_tab_title.value };
self.complete = true;
self.prepAllocableString();
},
.conemu_progress_prestate => switch (c) {
';' => {
self.command = .{ .progress_report = .{
self.command = .{ .conemu_progress_report = .{
.state = undefined,
} };
self.state = .conemu_progress_state;
},
// OSC 9;4 <something other than semicolon> is a desktop
// notification.
else => self.showDesktopNotification(),
},
.conemu_progress_state => switch (c) {
'0' => {
self.command.progress_report.state = .remove;
self.command.conemu_progress_report.state = .remove;
self.state = .swallow;
self.complete = true;
},
'1' => {
self.command.progress_report.state = .set;
self.command.progress_report.progress = 0;
self.command.conemu_progress_report.state = .set;
self.command.conemu_progress_report.progress = 0;
self.state = .conemu_progress_prevalue;
},
'2' => {
self.command.progress_report.state = .@"error";
self.command.conemu_progress_report.state = .@"error";
self.complete = true;
self.state = .conemu_progress_prevalue;
},
'3' => {
self.command.progress_report.state = .indeterminate;
self.command.conemu_progress_report.state = .indeterminate;
self.complete = true;
self.state = .swallow;
},
'4' => {
self.command.progress_report.state = .pause;
self.command.conemu_progress_report.state = .pause;
self.complete = true;
self.state = .conemu_progress_prevalue;
},
// OSC 9;4; <something other than 0-4> is a desktop
// notification.
else => self.showDesktopNotification(),
},
@@ -1077,6 +1110,8 @@ pub const Parser = struct {
self.state = .conemu_progress_value;
},
// OSC 9;4;<0-4> <something other than semicolon> is a desktop
// notification.
else => self.showDesktopNotification(),
},
@@ -1088,8 +1123,16 @@ pub const Parser = struct {
// If we aren't a set substate, then we don't care
// about the value.
const p = &self.command.progress_report;
if (p.state != .set and p.state != .@"error" and p.state != .pause) break :value;
const p = &self.command.conemu_progress_report;
switch (p.state) {
.remove,
.indeterminate,
=> break :value,
.set,
.@"error",
.pause,
=> {},
}
if (p.state == .set)
assert(p.progress != null)
@@ -1123,6 +1166,7 @@ pub const Parser = struct {
self.state = .string;
self.complete = true;
},
// OSC 9;6 <something other than semicolon> is a desktop
// notification.
else => self.showDesktopNotification(),
@@ -1361,7 +1405,7 @@ pub const Parser = struct {
fn endConEmuSleepValue(self: *Parser) void {
switch (self.command) {
.sleep => |*v| v.duration_ms = value: {
.conemu_sleep => |*v| v.duration_ms = value: {
const str = self.buf[self.buf_start..self.buf_idx];
if (str.len == 0) break :value 100;
@@ -1624,12 +1668,26 @@ pub const Parser = struct {
.hyperlink_uri => self.endHyperlink(),
.string => self.endString(),
.conemu_sleep_value => self.endConEmuSleepValue(),
.conemu_guimacro => {
// We received OSC 9;6 ST, but nothing else, finish off as a
// desktop notification with "6" as the body.
// We received OSC 9;X ST, but nothing else, finish off as a
// desktop notification with "X" as the body.
.conemu_sleep,
.conemu_message_box,
.conemu_tab,
.conemu_progress_prestate,
.conemu_progress_state,
.conemu_guimacro,
=> {
self.showDesktopNotification();
self.endString();
},
// A ConEmu progress report that has reached these states is
// complete, don't do anything to them.
.conemu_progress_prevalue,
.conemu_progress_value,
=> {},
.allocable_string => self.endAllocableString(),
.kitty_color_protocol_key => self.endKittyColorProtocolOption(.key_only, true),
.kitty_color_protocol_value => self.endKittyColorProtocolOption(.key_and_value, true),
@@ -2805,7 +2863,7 @@ test "OSC: OSC104: empty palette index" {
try std.testing.expect(it.next() == null);
}
test "OSC: conemu sleep" {
test "OSC: OSC 9;1 ConEmu sleep" {
const testing = std.testing;
var p: Parser = .init();
@@ -2815,11 +2873,11 @@ test "OSC: conemu sleep" {
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .sleep);
try testing.expectEqual(420, cmd.sleep.duration_ms);
try testing.expect(cmd == .conemu_sleep);
try testing.expectEqual(420, cmd.conemu_sleep.duration_ms);
}
test "OSC: conemu sleep with no value default to 100ms" {
test "OSC: OSC 9;1 ConEmu sleep with no value default to 100ms" {
const testing = std.testing;
var p: Parser = .init();
@@ -2829,11 +2887,11 @@ test "OSC: conemu sleep with no value default to 100ms" {
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .sleep);
try testing.expectEqual(100, cmd.sleep.duration_ms);
try testing.expect(cmd == .conemu_sleep);
try testing.expectEqual(100, cmd.conemu_sleep.duration_ms);
}
test "OSC: conemu sleep cannot exceed 10000ms" {
test "OSC: OSC 9;1 conemu sleep cannot exceed 10000ms" {
const testing = std.testing;
var p: Parser = .init();
@@ -2843,11 +2901,11 @@ test "OSC: conemu sleep cannot exceed 10000ms" {
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .sleep);
try testing.expectEqual(10000, cmd.sleep.duration_ms);
try testing.expect(cmd == .conemu_sleep);
try testing.expectEqual(10000, cmd.conemu_sleep.duration_ms);
}
test "OSC: conemu sleep invalid input" {
test "OSC: OSC 9;1 conemu sleep invalid input" {
const testing = std.testing;
var p: Parser = .init();
@@ -2857,11 +2915,39 @@ test "OSC: conemu sleep invalid input" {
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .sleep);
try testing.expectEqual(100, cmd.sleep.duration_ms);
try testing.expect(cmd == .conemu_sleep);
try testing.expectEqual(100, cmd.conemu_sleep.duration_ms);
}
test "OSC: show desktop notification" {
test "OSC: OSC 9;1 conemu sleep -> desktop notification 1" {
const testing = std.testing;
var p: Parser = .init();
const input = "9;1";
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .show_desktop_notification);
try testing.expectEqualStrings("1", cmd.show_desktop_notification.body);
}
test "OSC: OSC 9;1 conemu sleep -> desktop notification 2" {
const testing = std.testing;
var p: Parser = .init();
const input = "9;1a";
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .show_desktop_notification);
try testing.expectEqualStrings("1a", cmd.show_desktop_notification.body);
}
test "OSC: OSC 9 show desktop notification" {
const testing = std.testing;
var p: Parser = .init();
@@ -2875,7 +2961,7 @@ test "OSC: show desktop notification" {
try testing.expectEqualStrings("Hello world", cmd.show_desktop_notification.body);
}
test "OSC: show single character desktop notification" {
test "OSC: OSC 9 show single character desktop notification" {
const testing = std.testing;
var p: Parser = .init();
@@ -2889,7 +2975,7 @@ test "OSC: show single character desktop notification" {
try testing.expectEqualStrings("H", cmd.show_desktop_notification.body);
}
test "OSC: show desktop notification with title" {
test "OSC: OSC 777 show desktop notification with title" {
const testing = std.testing;
var p: Parser = .init();
@@ -2903,7 +2989,7 @@ test "OSC: show desktop notification with title" {
try testing.expectEqualStrings(cmd.show_desktop_notification.body, "Body");
}
test "OSC: conemu message box" {
test "OSC: OSC 9;2 ConEmu message box" {
const testing = std.testing;
var p: Parser = .init();
@@ -2912,11 +2998,11 @@ test "OSC: conemu message box" {
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .show_message_box);
try testing.expectEqualStrings("hello world", cmd.show_message_box);
try testing.expect(cmd == .conemu_show_message_box);
try testing.expectEqualStrings("hello world", cmd.conemu_show_message_box);
}
test "OSC: conemu message box invalid input" {
test "OSC: 9;2 ConEmu message box invalid input" {
const testing = std.testing;
var p: Parser = .init();
@@ -2924,11 +3010,12 @@ test "OSC: conemu message box invalid input" {
const input = "9;2";
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b');
try testing.expect(cmd == null);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .show_desktop_notification);
try testing.expectEqualStrings("2", cmd.show_desktop_notification.body);
}
test "OSC: conemu message box empty message" {
test "OSC: 9;2 ConEmu message box empty message" {
const testing = std.testing;
var p: Parser = .init();
@@ -2937,11 +3024,11 @@ test "OSC: conemu message box empty message" {
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .show_message_box);
try testing.expectEqualStrings("", cmd.show_message_box);
try testing.expect(cmd == .conemu_show_message_box);
try testing.expectEqualStrings("", cmd.conemu_show_message_box);
}
test "OSC: conemu message box spaces only message" {
test "OSC: 9;2 ConEmu message box spaces only message" {
const testing = std.testing;
var p: Parser = .init();
@@ -2950,11 +3037,39 @@ test "OSC: conemu message box spaces only message" {
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .show_message_box);
try testing.expectEqualStrings(" ", cmd.show_message_box);
try testing.expect(cmd == .conemu_show_message_box);
try testing.expectEqualStrings(" ", cmd.conemu_show_message_box);
}
test "OSC: conemu change tab title" {
test "OSC: OSC 9;2 message box -> desktop notification 1" {
const testing = std.testing;
var p: Parser = .init();
const input = "9;2";
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .show_desktop_notification);
try testing.expectEqualStrings("2", cmd.show_desktop_notification.body);
}
test "OSC: OSC 9;2 message box -> desktop notification 2" {
const testing = std.testing;
var p: Parser = .init();
const input = "9;2a";
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .show_desktop_notification);
try testing.expectEqualStrings("2a", cmd.show_desktop_notification.body);
}
test "OSC: 9;3 ConEmu change tab title" {
const testing = std.testing;
var p: Parser = .init();
@@ -2963,11 +3078,11 @@ test "OSC: conemu change tab title" {
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .change_conemu_tab_title);
try testing.expectEqualStrings("foo bar", cmd.change_conemu_tab_title.value);
try testing.expect(cmd == .conemu_change_tab_title);
try testing.expectEqualStrings("foo bar", cmd.conemu_change_tab_title.value);
}
test "OSC: conemu change tab reset title" {
test "OSC: 9;3 ConEmu change tab title reset" {
const testing = std.testing;
var p: Parser = .init();
@@ -2977,11 +3092,11 @@ test "OSC: conemu change tab reset title" {
const cmd = p.end('\x1b').?;
const expected_command: Command = .{ .change_conemu_tab_title = .{ .reset = {} } };
const expected_command: Command = .{ .conemu_change_tab_title = .reset };
try testing.expectEqual(expected_command, cmd);
}
test "OSC: conemu change tab spaces only title" {
test "OSC: 9;3 ConEmu change tab title spaces only" {
const testing = std.testing;
var p: Parser = .init();
@@ -2991,11 +3106,11 @@ test "OSC: conemu change tab spaces only title" {
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .change_conemu_tab_title);
try testing.expectEqualStrings(" ", cmd.change_conemu_tab_title.value);
try testing.expect(cmd == .conemu_change_tab_title);
try testing.expectEqualStrings(" ", cmd.conemu_change_tab_title.value);
}
test "OSC: conemu change tab invalid input" {
test "OSC: OSC 9;3 change tab title -> desktop notification 1" {
const testing = std.testing;
var p: Parser = .init();
@@ -3003,11 +3118,27 @@ test "OSC: conemu change tab invalid input" {
const input = "9;3";
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b');
try testing.expect(cmd == null);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .show_desktop_notification);
try testing.expectEqualStrings("3", cmd.show_desktop_notification.body);
}
test "OSC: OSC9 progress set" {
test "OSC: OSC 9;3 message box -> desktop notification 2" {
const testing = std.testing;
var p: Parser = .init();
const input = "9;3a";
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .show_desktop_notification);
try testing.expectEqualStrings("3a", cmd.show_desktop_notification.body);
}
test "OSC: OSC 9;4 ConEmu progress set" {
const testing = std.testing;
var p: Parser = .init();
@@ -3016,12 +3147,12 @@ test "OSC: OSC9 progress set" {
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .progress_report);
try testing.expect(cmd.progress_report.state == .set);
try testing.expect(cmd.progress_report.progress == 100);
try testing.expect(cmd == .conemu_progress_report);
try testing.expect(cmd.conemu_progress_report.state == .set);
try testing.expect(cmd.conemu_progress_report.progress == 100);
}
test "OSC: OSC9 progress set overflow" {
test "OSC: OSC 9;4 ConEmu progress set overflow" {
const testing = std.testing;
var p: Parser = .init();
@@ -3030,12 +3161,12 @@ test "OSC: OSC9 progress set overflow" {
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .progress_report);
try testing.expect(cmd.progress_report.state == .set);
try testing.expect(cmd.progress_report.progress == 100);
try testing.expect(cmd == .conemu_progress_report);
try testing.expect(cmd.conemu_progress_report.state == .set);
try testing.expectEqual(100, cmd.conemu_progress_report.progress);
}
test "OSC: OSC9 progress set single digit" {
test "OSC: OSC 9;4 ConEmu progress set single digit" {
const testing = std.testing;
var p: Parser = .init();
@@ -3044,12 +3175,12 @@ test "OSC: OSC9 progress set single digit" {
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .progress_report);
try testing.expect(cmd.progress_report.state == .set);
try testing.expect(cmd.progress_report.progress == 9);
try testing.expect(cmd == .conemu_progress_report);
try testing.expect(cmd.conemu_progress_report.state == .set);
try testing.expect(cmd.conemu_progress_report.progress == 9);
}
test "OSC: OSC9 progress set double digit" {
test "OSC: OSC 9;4 ConEmu progress set double digit" {
const testing = std.testing;
var p: Parser = .init();
@@ -3058,12 +3189,12 @@ test "OSC: OSC9 progress set double digit" {
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .progress_report);
try testing.expect(cmd.progress_report.state == .set);
try testing.expect(cmd.progress_report.progress == 94);
try testing.expect(cmd == .conemu_progress_report);
try testing.expect(cmd.conemu_progress_report.state == .set);
try testing.expectEqual(94, cmd.conemu_progress_report.progress);
}
test "OSC: OSC9 progress set extra semicolon ignored" {
test "OSC: OSC 9;4 ConEmu progress set extra semicolon ignored" {
const testing = std.testing;
var p: Parser = .init();
@@ -3072,12 +3203,12 @@ test "OSC: OSC9 progress set extra semicolon ignored" {
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .progress_report);
try testing.expect(cmd.progress_report.state == .set);
try testing.expect(cmd.progress_report.progress == 100);
try testing.expect(cmd == .conemu_progress_report);
try testing.expect(cmd.conemu_progress_report.state == .set);
try testing.expectEqual(100, cmd.conemu_progress_report.progress);
}
test "OSC: OSC9 progress remove with no progress" {
test "OSC: OSC 9;4 ConEmu progress remove with no progress" {
const testing = std.testing;
var p: Parser = .init();
@@ -3086,12 +3217,12 @@ test "OSC: OSC9 progress remove with no progress" {
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .progress_report);
try testing.expect(cmd.progress_report.state == .remove);
try testing.expect(cmd.progress_report.progress == null);
try testing.expect(cmd == .conemu_progress_report);
try testing.expect(cmd.conemu_progress_report.state == .remove);
try testing.expect(cmd.conemu_progress_report.progress == null);
}
test "OSC: OSC9 progress remove with double semicolon" {
test "OSC: OSC 9;4 ConEmu progress remove with double semicolon" {
const testing = std.testing;
var p: Parser = .init();
@@ -3100,12 +3231,12 @@ test "OSC: OSC9 progress remove with double semicolon" {
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .progress_report);
try testing.expect(cmd.progress_report.state == .remove);
try testing.expect(cmd.progress_report.progress == null);
try testing.expect(cmd == .conemu_progress_report);
try testing.expect(cmd.conemu_progress_report.state == .remove);
try testing.expect(cmd.conemu_progress_report.progress == null);
}
test "OSC: OSC9 progress remove ignores progress" {
test "OSC: OSC 9;4 ConEmu progress remove ignores progress" {
const testing = std.testing;
var p: Parser = .init();
@@ -3114,12 +3245,12 @@ test "OSC: OSC9 progress remove ignores progress" {
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .progress_report);
try testing.expect(cmd.progress_report.state == .remove);
try testing.expect(cmd.progress_report.progress == null);
try testing.expect(cmd == .conemu_progress_report);
try testing.expect(cmd.conemu_progress_report.state == .remove);
try testing.expect(cmd.conemu_progress_report.progress == null);
}
test "OSC: OSC9 progress remove extra semicolon" {
test "OSC: OSC 9;4 ConEmu progress remove extra semicolon" {
const testing = std.testing;
var p: Parser = .init();
@@ -3128,11 +3259,11 @@ test "OSC: OSC9 progress remove extra semicolon" {
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .progress_report);
try testing.expect(cmd.progress_report.state == .remove);
try testing.expect(cmd == .conemu_progress_report);
try testing.expect(cmd.conemu_progress_report.state == .remove);
}
test "OSC: OSC9 progress error" {
test "OSC: OSC 9;4 ConEmu progress error" {
const testing = std.testing;
var p: Parser = .init();
@@ -3141,12 +3272,12 @@ test "OSC: OSC9 progress error" {
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .progress_report);
try testing.expect(cmd.progress_report.state == .@"error");
try testing.expect(cmd.progress_report.progress == null);
try testing.expect(cmd == .conemu_progress_report);
try testing.expect(cmd.conemu_progress_report.state == .@"error");
try testing.expect(cmd.conemu_progress_report.progress == null);
}
test "OSC: OSC9 progress error with progress" {
test "OSC: OSC 9;4 ConEmu progress error with progress" {
const testing = std.testing;
var p: Parser = .init();
@@ -3155,12 +3286,12 @@ test "OSC: OSC9 progress error with progress" {
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .progress_report);
try testing.expect(cmd.progress_report.state == .@"error");
try testing.expect(cmd.progress_report.progress == 100);
try testing.expect(cmd == .conemu_progress_report);
try testing.expect(cmd.conemu_progress_report.state == .@"error");
try testing.expect(cmd.conemu_progress_report.progress == 100);
}
test "OSC: OSC9 progress pause" {
test "OSC: OSC 9;4 progress pause" {
const testing = std.testing;
var p: Parser = .init();
@@ -3169,12 +3300,12 @@ test "OSC: OSC9 progress pause" {
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .progress_report);
try testing.expect(cmd.progress_report.state == .pause);
try testing.expect(cmd.progress_report.progress == null);
try testing.expect(cmd == .conemu_progress_report);
try testing.expect(cmd.conemu_progress_report.state == .pause);
try testing.expect(cmd.conemu_progress_report.progress == null);
}
test "OSC: OSC9 progress pause with progress" {
test "OSC: OSC 9;4 ConEmu progress pause with progress" {
const testing = std.testing;
var p: Parser = .init();
@@ -3183,12 +3314,68 @@ test "OSC: OSC9 progress pause with progress" {
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .progress_report);
try testing.expect(cmd.progress_report.state == .pause);
try testing.expect(cmd.progress_report.progress == 100);
try testing.expect(cmd == .conemu_progress_report);
try testing.expect(cmd.conemu_progress_report.state == .pause);
try testing.expect(cmd.conemu_progress_report.progress == 100);
}
test "OSC: OSC9 conemu wait input" {
test "OSC: OSC 9;4 progress -> desktop notification 1" {
const testing = std.testing;
var p: Parser = .init();
const input = "9;4";
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .show_desktop_notification);
try testing.expectEqualStrings("4", cmd.show_desktop_notification.body);
}
test "OSC: OSC 9;4 progress -> desktop notification 2" {
const testing = std.testing;
var p: Parser = .init();
const input = "9;4;";
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .show_desktop_notification);
try testing.expectEqualStrings("4;", cmd.show_desktop_notification.body);
}
test "OSC: OSC 9;4 progress -> desktop notification 3" {
const testing = std.testing;
var p: Parser = .init();
const input = "9;4;5";
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .show_desktop_notification);
try testing.expectEqualStrings("4;5", cmd.show_desktop_notification.body);
}
test "OSC: OSC 9;4 progress -> desktop notification 4" {
const testing = std.testing;
var p: Parser = .init();
const input = "9;4;5a";
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .show_desktop_notification);
try testing.expectEqualStrings("4;5a", cmd.show_desktop_notification.body);
}
test "OSC: OSC 9;5 ConEmu wait input" {
const testing = std.testing;
var p: Parser = .init();
@@ -3197,10 +3384,10 @@ test "OSC: OSC9 conemu wait input" {
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .wait_input);
try testing.expect(cmd == .conemu_wait_input);
}
test "OSC: OSC9 conemu wait ignores trailing characters" {
test "OSC: OSC 9;5 ConEmu wait ignores trailing characters" {
const testing = std.testing;
var p: Parser = .init();
@@ -3209,7 +3396,7 @@ test "OSC: OSC9 conemu wait ignores trailing characters" {
for (input) |ch| p.next(ch);
const cmd = p.end('\x1b').?;
try testing.expect(cmd == .wait_input);
try testing.expect(cmd == .conemu_wait_input);
}
test "OSC: empty param" {

View File

@@ -1598,17 +1598,17 @@ pub fn Stream(comptime Handler: type) type {
} else log.warn("unimplemented OSC callback: {}", .{cmd});
},
.progress_report => |v| {
.conemu_progress_report => |v| {
if (@hasDecl(T, "handleProgressReport")) {
try self.handler.handleProgressReport(v);
return;
} else log.warn("unimplemented OSC callback: {}", .{cmd});
},
.sleep,
.show_message_box,
.change_conemu_tab_title,
.wait_input,
.conemu_sleep,
.conemu_show_message_box,
.conemu_change_tab_title,
.conemu_wait_input,
.conemu_guimacro,
=> {
log.warn("unimplemented OSC callback: {}", .{cmd});