diff --git a/src/terminal/osc.zig b/src/terminal/osc.zig index 3063bed40..917de83be 100644 --- a/src/terminal/osc.zig +++ b/src/terminal/osc.zig @@ -72,6 +72,16 @@ pub const Command = union(enum) { kind: u8, data: []const u8, }, + + /// OSC 7. Reports the current working directory of the shell. This is + /// a moderately flawed escape sequence but one that many major terminals + /// support so we also support it. To understand the flaws, read through + /// this terminal-wg issue: https://gitlab.freedesktop.org/terminal-wg/specifications/-/issues/20 + report_pwd: struct { + /// The reported pwd value. This is not checked for validity. It should + /// be a file URL but it is up to the caller to utilize this value. + value: []const u8, + }, }; pub const Parser = struct { @@ -121,6 +131,7 @@ pub const Parser = struct { @"2", @"5", @"52", + @"7", // We're in a semantic prompt OSC command but we aren't sure // what the command is yet, i.e. `133;` @@ -173,6 +184,7 @@ pub const Parser = struct { '1' => self.state = .@"1", '2' => self.state = .@"2", '5' => self.state = .@"5", + '7' => self.state = .@"7", else => self.state = .invalid, }, @@ -228,6 +240,17 @@ pub const Parser = struct { else => self.state = .invalid, }, + .@"7" => switch (c) { + ';' => { + self.command = .{ .report_pwd = .{ .value = undefined } }; + + self.state = .string; + self.temp_state = .{ .str = &self.command.report_pwd.value }; + self.buf_start = self.buf_idx; + }, + else => self.state = .invalid, + }, + .@"52" => switch (c) { ';' => { self.command = .{ .clipboard_contents = undefined }; @@ -557,6 +580,19 @@ test "OSC: get/set clipboard" { try testing.expect(std.mem.eql(u8, "?", cmd.clipboard_contents.data)); } +test "OSC: report pwd" { + const testing = std.testing; + + var p: Parser = .{}; + + const input = "7;file:///tmp/example"; + for (input) |ch| p.next(ch); + + const cmd = p.end().?; + try testing.expect(cmd == .report_pwd); + try testing.expect(std.mem.eql(u8, "file:///tmp/example", cmd.report_pwd.value)); +} + test "OSC: longer than buffer" { const testing = std.testing;