native macOS codings agent orchestrator
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

Match Ghostty pane focus after close

khoi 5c3d79f0 3611cf33

+54 -1
+12
supacode/Features/Terminal/Models/SplitTree.swift
··· 164 164 } 165 165 } 166 166 167 + func focusTargetAfterClosing(_ node: Node) -> ViewType? { 168 + guard let root else { return nil } 169 + 170 + // Match Ghostty's macOS controller: closing the leftmost leaf moves to the next 171 + // surface, otherwise we move to the previous one. 172 + if root.leftmostLeaf() === node.leftmostLeaf() { 173 + return focusTarget(for: .next, from: node) 174 + } else { 175 + return focusTarget(for: .previous, from: node) 176 + } 177 + } 178 + 167 179 func equalized() -> Self { 168 180 guard let root else { return self } 169 181 let newRoot = root.equalize()
+5 -1
supacode/Features/Terminal/Models/WorktreeTerminalState.swift
··· 845 845 surfaces.removeValue(forKey: view.id) 846 846 return 847 847 } 848 + let nextSurface = 849 + focusedSurfaceIdByTab[tabId] == view.id 850 + ? tree.focusTargetAfterClosing(node) 851 + : nil 848 852 let newTree = tree.removing(node) 849 853 view.closeSurface() 850 854 surfaces.removeValue(forKey: view.id) ··· 860 864 trees[tabId] = newTree 861 865 updateRunningState(for: tabId) 862 866 if focusedSurfaceIdByTab[tabId] == view.id { 863 - if let nextSurface = newTree.root?.leftmostLeaf() { 867 + if let nextSurface { 864 868 focusSurface(nextSurface, in: tabId) 865 869 } else { 866 870 focusedSurfaceIdByTab.removeValue(forKey: tabId)
+37
supacodeTests/SplitTreeTests.swift
··· 1 + import AppKit 2 + import Testing 3 + 4 + @testable import supacode 5 + 6 + @MainActor 7 + struct SplitTreeTests { 8 + @Test func focusTargetAfterClosingUsesNextForLeftmostLeaf() throws { 9 + let first = SplitTreeTestView() 10 + let second = SplitTreeTestView() 11 + let third = SplitTreeTestView() 12 + 13 + let tree = try SplitTree(view: first) 14 + .inserting(view: second, at: first, direction: .right) 15 + .inserting(view: third, at: second, direction: .right) 16 + 17 + let node = try #require(tree.find(id: first.id)) 18 + #expect(tree.focusTargetAfterClosing(node) === second) 19 + } 20 + 21 + @Test func focusTargetAfterClosingUsesPreviousForNonLeftmostLeaf() throws { 22 + let first = SplitTreeTestView() 23 + let second = SplitTreeTestView() 24 + let third = SplitTreeTestView() 25 + 26 + let tree = try SplitTree(view: first) 27 + .inserting(view: second, at: first, direction: .right) 28 + .inserting(view: third, at: second, direction: .right) 29 + 30 + let node = try #require(tree.find(id: third.id)) 31 + #expect(tree.focusTargetAfterClosing(node) === second) 32 + } 33 + } 34 + 35 + private final class SplitTreeTestView: NSView, Identifiable { 36 + let id = UUID() 37 + }