diff --git a/src/Pane.zig b/src/Pane.zig index 380c3b3..708a82c 100644 --- a/src/Pane.zig +++ b/src/Pane.zig @@ -757,6 +757,10 @@ fn onContentFocus(ctx: ?*anyopaque) void { } fn onSplitClicked(_: *gtk.Button, self: *Pane) callconv(.c) void { + // The button belongs to this pane, which need not be the focused one: a + // header click does not move focus. Focusing it first makes the new + // terminal split this pane and start in this pane's directory. + self.view.setFocused(self); self.view.addPane(.plain(.terminal)) catch |err| { std.log.err("failed to open terminal: {s}", .{@errorName(err)}); }; diff --git a/src/View.zig b/src/View.zig index b6d6631..b1bba4e 100644 --- a/src/View.zig +++ b/src/View.zig @@ -302,7 +302,22 @@ pub fn addPane(self: *View, raw: Pane.Spec) !void { if (raw.kind() == .review and self.reviewPane() != null) { return error.ReviewAlreadyOpen; } - const spec = self.stamp(raw); + + // A terminal opened without a directory of its own starts where the pane + // it splits is working, so a new shell beside a `cd`-ed one lands in the + // same place rather than back in $HOME. Only borrowed for the length of + // `Pane.create`, which spawns the shell before returning. + var dir_buf: [std.fs.max_path_bytes]u8 = undefined; + const inherited: Pane.Spec = switch (raw) { + .terminal => |opts| if (opts.cwd.len == 0 and opts.hc.len == 0) blk: { + const from = self.focusedPane() orelse break :blk raw; + var with_dir = opts; + with_dir.cwd = self.paneDirectory(from, &dir_buf); + break :blk .{ .terminal = with_dir }; + } else raw, + else => raw, + }; + const spec = self.stamp(inherited); const pane = try Pane.create(self.alloc, self, spec); errdefer pane.destroy();