diff --git a/src/terminal/osc.zig b/src/terminal/osc.zig index 7e93b48d7..34bc46745 100644 --- a/src/terminal/osc.zig +++ b/src/terminal/osc.zig @@ -641,7 +641,7 @@ pub const Parser = struct { .@"7" => switch (c) { ';' => { self.command = .{ .report_pwd = .{ .value = "" } }; - + self.complete = true; self.state = .string; self.temp_state = .{ .str = &self.command.report_pwd.value }; self.buf_start = self.buf_idx; @@ -1382,6 +1382,18 @@ test "OSC: report pwd" { try testing.expect(std.mem.eql(u8, "file:///tmp/example", cmd.report_pwd.value)); } +test "OSC: report pwd empty" { + const testing = std.testing; + + var p: Parser = .{}; + + const input = "7;"; + for (input) |ch| p.next(ch); + const cmd = p.end(null).?; + try testing.expect(cmd == .report_pwd); + try testing.expect(std.mem.eql(u8, "", cmd.report_pwd.value)); +} + test "OSC: pointer cursor" { const testing = std.testing; @@ -1395,17 +1407,6 @@ test "OSC: pointer cursor" { try testing.expect(std.mem.eql(u8, "pointer", cmd.mouse_shape.value)); } -test "OSC: report pwd empty" { - const testing = std.testing; - - var p: Parser = .{}; - - const input = "7;"; - for (input) |ch| p.next(ch); - - try testing.expect(p.end(null) == null); -} - test "OSC: longer than buffer" { const testing = std.testing; diff --git a/src/termio/stream_handler.zig b/src/termio/stream_handler.zig index 66c8359bd..dd7763334 100644 --- a/src/termio/stream_handler.zig +++ b/src/termio/stream_handler.zig @@ -1,5 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); +const assert = std.debug.assert; const Allocator = std.mem.Allocator; const xev = @import("xev"); const apprt = @import("../apprt.zig"); @@ -1048,6 +1049,28 @@ pub const StreamHandler = struct { } pub fn reportPwd(self: *StreamHandler, url: []const u8) !void { + // Special handling for the empty URL. We treat the empty URL + // as resetting the pwd as if we never saw a pwd. I can't find any + // other terminal that does this but it seems like a reasonable + // behavior that enables some useful features. For example, the macOS + // proxy icon can be hidden when a program reports it doesn't know + // the pwd rather than showing a stale pwd. + if (url.len == 0) { + // Blank value can never fail because no allocs happen. + self.terminal.setPwd("") catch unreachable; + + // If we haven't seen a title, we're using the pwd as our title. + // Set it to blank which will reset our title behavior. + if (!self.seen_title) { + try self.changeWindowTitle(""); + assert(!self.seen_title); + } + + // Report the change. + self.surfaceMessageWriter(.{ .pwd_change = .{ .stable = "" } }); + return; + } + if (builtin.os.tag == .windows) { log.warn("reportPwd unimplemented on windows", .{}); return;