From a4daabb28afbfcc97afb42a939518861803934bc Mon Sep 17 00:00:00 2001 From: Daniel Patterson Date: Fri, 27 Dec 2024 14:44:33 +0000 Subject: [PATCH 1/3] Rename `goto_split` top/bottom directions to up/down. --- include/ghostty.h | 4 ++-- macos/Sources/App/macOS/AppDelegate.swift | 4 ++-- .../Terminal/BaseTerminalController.swift | 4 ++-- macos/Sources/Ghostty/Ghostty.SplitNode.swift | 4 ++-- macos/Sources/Ghostty/Package.swift | 18 +++++++++--------- src/apprt/action.zig | 4 ++-- src/apprt/gtk/Split.zig | 4 ++-- src/config/Config.zig | 8 ++++---- src/input/Binding.zig | 4 ++-- 9 files changed, 27 insertions(+), 27 deletions(-) diff --git a/include/ghostty.h b/include/ghostty.h index 61c3aad32..4b8d409e9 100644 --- a/include/ghostty.h +++ b/include/ghostty.h @@ -375,9 +375,9 @@ typedef enum { typedef enum { GHOSTTY_GOTO_SPLIT_PREVIOUS, GHOSTTY_GOTO_SPLIT_NEXT, - GHOSTTY_GOTO_SPLIT_TOP, + GHOSTTY_GOTO_SPLIT_UP, GHOSTTY_GOTO_SPLIT_LEFT, - GHOSTTY_GOTO_SPLIT_BOTTOM, + GHOSTTY_GOTO_SPLIT_DOWN, GHOSTTY_GOTO_SPLIT_RIGHT, } ghostty_action_goto_split_e; diff --git a/macos/Sources/App/macOS/AppDelegate.swift b/macos/Sources/App/macOS/AppDelegate.swift index 7b0ff6fc2..b1af97b25 100644 --- a/macos/Sources/App/macOS/AppDelegate.swift +++ b/macos/Sources/App/macOS/AppDelegate.swift @@ -358,8 +358,8 @@ class AppDelegate: NSObject, syncMenuShortcut(config, action: "toggle_split_zoom", menuItem: self.menuZoomSplit) syncMenuShortcut(config, action: "goto_split:previous", menuItem: self.menuPreviousSplit) syncMenuShortcut(config, action: "goto_split:next", menuItem: self.menuNextSplit) - syncMenuShortcut(config, action: "goto_split:top", menuItem: self.menuSelectSplitAbove) - syncMenuShortcut(config, action: "goto_split:bottom", menuItem: self.menuSelectSplitBelow) + syncMenuShortcut(config, action: "goto_split:up", menuItem: self.menuSelectSplitAbove) + syncMenuShortcut(config, action: "goto_split:down", menuItem: self.menuSelectSplitBelow) syncMenuShortcut(config, action: "goto_split:left", menuItem: self.menuSelectSplitLeft) syncMenuShortcut(config, action: "goto_split:right", menuItem: self.menuSelectSplitRight) syncMenuShortcut(config, action: "resize_split:up,10", menuItem: self.menuMoveSplitDividerUp) diff --git a/macos/Sources/Features/Terminal/BaseTerminalController.swift b/macos/Sources/Features/Terminal/BaseTerminalController.swift index 68c243004..8ce4af2c9 100644 --- a/macos/Sources/Features/Terminal/BaseTerminalController.swift +++ b/macos/Sources/Features/Terminal/BaseTerminalController.swift @@ -536,11 +536,11 @@ class BaseTerminalController: NSWindowController, } @IBAction func splitMoveFocusAbove(_ sender: Any) { - splitMoveFocus(direction: .top) + splitMoveFocus(direction: .up) } @IBAction func splitMoveFocusBelow(_ sender: Any) { - splitMoveFocus(direction: .bottom) + splitMoveFocus(direction: .down) } @IBAction func splitMoveFocusLeft(_ sender: Any) { diff --git a/macos/Sources/Ghostty/Ghostty.SplitNode.swift b/macos/Sources/Ghostty/Ghostty.SplitNode.swift index f863eeada..63128deb4 100644 --- a/macos/Sources/Ghostty/Ghostty.SplitNode.swift +++ b/macos/Sources/Ghostty/Ghostty.SplitNode.swift @@ -64,10 +64,10 @@ extension Ghostty { let node: SplitNode switch (direction) { - case .previous, .top, .left: + case .previous, .up, .left: node = container.bottomRight - case .next, .bottom, .right: + case .next, .down, .right: node = container.topLeft } diff --git a/macos/Sources/Ghostty/Package.swift b/macos/Sources/Ghostty/Package.swift index 65f928443..d09100212 100644 --- a/macos/Sources/Ghostty/Package.swift +++ b/macos/Sources/Ghostty/Package.swift @@ -66,7 +66,7 @@ extension Ghostty { /// An enum that is used for the directions that a split focus event can change. enum SplitFocusDirection { - case previous, next, top, bottom, left, right + case previous, next, up, down, left, right /// Initialize from a Ghostty API enum. static func from(direction: ghostty_action_goto_split_e) -> Self? { @@ -77,11 +77,11 @@ extension Ghostty { case GHOSTTY_GOTO_SPLIT_NEXT: return .next - case GHOSTTY_GOTO_SPLIT_TOP: - return .top + case GHOSTTY_GOTO_SPLIT_UP: + return .up - case GHOSTTY_GOTO_SPLIT_BOTTOM: - return .bottom + case GHOSTTY_GOTO_SPLIT_DOWN: + return .down case GHOSTTY_GOTO_SPLIT_LEFT: return .left @@ -102,11 +102,11 @@ extension Ghostty { case .next: return GHOSTTY_GOTO_SPLIT_NEXT - case .top: - return GHOSTTY_GOTO_SPLIT_TOP + case .up: + return GHOSTTY_GOTO_SPLIT_UP - case .bottom: - return GHOSTTY_GOTO_SPLIT_BOTTOM + case .down: + return GHOSTTY_GOTO_SPLIT_DOWN case .left: return GHOSTTY_GOTO_SPLIT_LEFT diff --git a/src/apprt/action.zig b/src/apprt/action.zig index 527535ffa..de6758d6c 100644 --- a/src/apprt/action.zig +++ b/src/apprt/action.zig @@ -332,9 +332,9 @@ pub const GotoSplit = enum(c_int) { previous, next, - top, + up, left, - bottom, + down, right, }; diff --git a/src/apprt/gtk/Split.zig b/src/apprt/gtk/Split.zig index 83ba04da0..2d428acb2 100644 --- a/src/apprt/gtk/Split.zig +++ b/src/apprt/gtk/Split.zig @@ -316,7 +316,7 @@ pub fn directionMap(self: *const Split, from: Side) DirectionMap { // This behavior matches the behavior of macOS at the time of writing // this. There is an open issue (#524) to make this depend on the // actual physical location of the current split. - result.put(.top, prev.surface); + result.put(.up, prev.surface); result.put(.left, prev.surface); } } @@ -324,7 +324,7 @@ pub fn directionMap(self: *const Split, from: Side) DirectionMap { if (self.directionNext(from)) |next| { result.put(.next, next.surface); if (!next.wrapped) { - result.put(.bottom, next.surface); + result.put(.down, next.surface); result.put(.right, next.surface); } } diff --git a/src/config/Config.zig b/src/config/Config.zig index a5ba71b25..8e8ec7242 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -2202,12 +2202,12 @@ pub fn default(alloc_gpa: Allocator) Allocator.Error!Config { try result.keybind.set.put( alloc, .{ .key = .{ .translated = .up }, .mods = .{ .ctrl = true, .alt = true } }, - .{ .goto_split = .top }, + .{ .goto_split = .up }, ); try result.keybind.set.put( alloc, .{ .key = .{ .translated = .down }, .mods = .{ .ctrl = true, .alt = true } }, - .{ .goto_split = .bottom }, + .{ .goto_split = .down }, ); try result.keybind.set.put( alloc, @@ -2465,12 +2465,12 @@ pub fn default(alloc_gpa: Allocator) Allocator.Error!Config { try result.keybind.set.put( alloc, .{ .key = .{ .translated = .up }, .mods = .{ .super = true, .alt = true } }, - .{ .goto_split = .top }, + .{ .goto_split = .up }, ); try result.keybind.set.put( alloc, .{ .key = .{ .translated = .down }, .mods = .{ .super = true, .alt = true } }, - .{ .goto_split = .bottom }, + .{ .goto_split = .down }, ); try result.keybind.set.put( alloc, diff --git a/src/input/Binding.zig b/src/input/Binding.zig index b451b5ec9..f8cc71d04 100644 --- a/src/input/Binding.zig +++ b/src/input/Binding.zig @@ -469,9 +469,9 @@ pub const Action = union(enum) { previous, next, - top, + up, left, - bottom, + down, right, }; From 8cbf8d500377173694801d099bbba97c35186085 Mon Sep 17 00:00:00 2001 From: Daniel Patterson Date: Fri, 27 Dec 2024 14:44:33 +0000 Subject: [PATCH 2/3] Fix broken macOS changes --- macos/Sources/Ghostty/Ghostty.SplitNode.swift | 12 ++++++------ macos/Sources/Ghostty/Ghostty.TerminalSplit.swift | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/macos/Sources/Ghostty/Ghostty.SplitNode.swift b/macos/Sources/Ghostty/Ghostty.SplitNode.swift index 63128deb4..899825d37 100644 --- a/macos/Sources/Ghostty/Ghostty.SplitNode.swift +++ b/macos/Sources/Ghostty/Ghostty.SplitNode.swift @@ -51,7 +51,7 @@ extension Ghostty { /// Returns the view that would prefer receiving focus in this tree. This is always the /// top-left-most view. This is used when creating a split or closing a split to find the /// next view to send focus to. - func preferredFocus(_ direction: SplitFocusDirection = .top) -> SurfaceView { + func preferredFocus(_ direction: SplitFocusDirection = .up) -> SurfaceView { let container: Container switch (self) { case .leaf(let leaf): @@ -431,12 +431,12 @@ extension Ghostty { struct Neighbors { var left: SplitNode? var right: SplitNode? - var top: SplitNode? - var bottom: SplitNode? + var up: SplitNode? + var down: SplitNode? /// These are the previous/next nodes. It will certainly be one of the above as well /// but we keep track of these separately because depending on the split direction - /// of the containing node, previous may be left OR top (same for next). + /// of the containing node, previous may be left OR up (same for next). var previous: SplitNode? var next: SplitNode? @@ -448,8 +448,8 @@ extension Ghostty { let map: [SplitFocusDirection : KeyPath] = [ .previous: \.previous, .next: \.next, - .top: \.top, - .bottom: \.bottom, + .up: \.up, + .down: \.down, .left: \.left, .right: \.right, ] diff --git a/macos/Sources/Ghostty/Ghostty.TerminalSplit.swift b/macos/Sources/Ghostty/Ghostty.TerminalSplit.swift index 272cdabdb..cc3bef149 100644 --- a/macos/Sources/Ghostty/Ghostty.TerminalSplit.swift +++ b/macos/Sources/Ghostty/Ghostty.TerminalSplit.swift @@ -308,7 +308,7 @@ extension Ghostty { resizeIncrements: .init(width: 1, height: 1), resizePublisher: container.resizeEvent, left: { - let neighborKey: WritableKeyPath = container.direction == .horizontal ? \.right : \.bottom + let neighborKey: WritableKeyPath = container.direction == .horizontal ? \.right : \.down TerminalSplitNested( node: closeableTopLeft(), @@ -318,7 +318,7 @@ extension Ghostty { ]) ) }, right: { - let neighborKey: WritableKeyPath = container.direction == .horizontal ? \.left : \.top + let neighborKey: WritableKeyPath = container.direction == .horizontal ? \.left : \.up TerminalSplitNested( node: closeableBottomRight(), From 3e11476d3277b35a090f89a3163919e0e2c4ae98 Mon Sep 17 00:00:00 2001 From: Daniel Patterson Date: Sat, 28 Dec 2024 01:02:27 +0000 Subject: [PATCH 3/3] Add "top" and "bottom" aliases --- src/input/Binding.zig | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/src/input/Binding.zig b/src/input/Binding.zig index f8cc71d04..94e8e96de 100644 --- a/src/input/Binding.zig +++ b/src/input/Binding.zig @@ -473,6 +473,38 @@ pub const Action = union(enum) { left, down, right, + + pub fn parse(input: []const u8) !SplitFocusDirection { + return std.meta.stringToEnum(SplitFocusDirection, input) orelse { + // For backwards compatibility we map "top" and "bottom" onto the enum + // values "up" and "down" + if (std.mem.eql(u8, input, "top")) { + return .up; + } else if (std.mem.eql(u8, input, "bottom")) { + return .down; + } else { + return Error.InvalidFormat; + } + }; + } + + test "parse" { + const testing = std.testing; + + try testing.expectEqual(.previous, try SplitFocusDirection.parse("previous")); + try testing.expectEqual(.next, try SplitFocusDirection.parse("next")); + + try testing.expectEqual(.up, try SplitFocusDirection.parse("up")); + try testing.expectEqual(.left, try SplitFocusDirection.parse("left")); + try testing.expectEqual(.down, try SplitFocusDirection.parse("down")); + try testing.expectEqual(.right, try SplitFocusDirection.parse("right")); + + try testing.expectEqual(.up, try SplitFocusDirection.parse("top")); + try testing.expectEqual(.down, try SplitFocusDirection.parse("bottom")); + + try testing.expectError(error.InvalidFormat, SplitFocusDirection.parse("")); + try testing.expectError(error.InvalidFormat, SplitFocusDirection.parse("green")); + } }; pub const SplitResizeDirection = enum { @@ -515,7 +547,16 @@ pub const Action = union(enum) { comptime field: std.builtin.Type.UnionField, param: []const u8, ) !field.type { - return switch (@typeInfo(field.type)) { + const field_info = @typeInfo(field.type); + + // Fields can provide a custom "parse" function + if (field_info == .Struct or field_info == .Union or field_info == .Enum) { + if (@hasDecl(field.type, "parse") and @typeInfo(@TypeOf(field.type.parse)) == .Fn) { + return field.type.parse(param); + } + } + + return switch (field_info) { .Enum => try parseEnum(field.type, param), .Int => try parseInt(field.type, param), .Float => try parseFloat(field.type, param),