native macOS codings agent orchestrator
6
fork

Configure Feed

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

Merge remote-tracking branch 'upstream/main'

onevcat 4c141d34 44ab7157

+62 -9
+8 -8
supacode.xcodeproj/project.pbxproj
··· 440 440 CODE_SIGN_STYLE = Automatic; 441 441 COMBINE_HIDPI_IMAGES = YES; 442 442 COMPILATION_CACHE_ENABLE_CACHING = YES; 443 - CURRENT_PROJECT_VERSION = 112; 443 + CURRENT_PROJECT_VERSION = 113; 444 444 DEAD_CODE_STRIPPING = YES; 445 445 DEBUG_INFORMATION_FORMAT = dwarf; 446 446 DEVELOPMENT_TEAM = ""; ··· 462 462 "@executable_path/../Frameworks", 463 463 ); 464 464 MACOSX_DEPLOYMENT_TARGET = 26.0; 465 - MARKETING_VERSION = 0.6.7; 465 + MARKETING_VERSION = 0.6.8; 466 466 OTHER_LDFLAGS = ( 467 467 "$(inherited)", 468 468 "-lc++", ··· 496 496 CODE_SIGN_STYLE = Automatic; 497 497 COMBINE_HIDPI_IMAGES = YES; 498 498 COMPILATION_CACHE_ENABLE_CACHING = NO; 499 - CURRENT_PROJECT_VERSION = 112; 499 + CURRENT_PROJECT_VERSION = 113; 500 500 DEAD_CODE_STRIPPING = YES; 501 501 DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 502 502 DEVELOPMENT_TEAM = ""; ··· 518 518 "@executable_path/../Frameworks", 519 519 ); 520 520 MACOSX_DEPLOYMENT_TARGET = 26.0; 521 - MARKETING_VERSION = 0.6.7; 521 + MARKETING_VERSION = 0.6.8; 522 522 OTHER_LDFLAGS = ( 523 523 "$(inherited)", 524 524 "-lc++", ··· 547 547 buildSettings = { 548 548 BUNDLE_LOADER = "$(TEST_HOST)"; 549 549 CODE_SIGN_STYLE = Automatic; 550 - CURRENT_PROJECT_VERSION = 112; 550 + CURRENT_PROJECT_VERSION = 113; 551 551 DEAD_CODE_STRIPPING = YES; 552 552 DEVELOPMENT_TEAM = ""; 553 553 GENERATE_INFOPLIST_FILE = YES; 554 554 MACOSX_DEPLOYMENT_TARGET = 26.1; 555 - MARKETING_VERSION = 0.6.7; 555 + MARKETING_VERSION = 0.6.8; 556 556 PRODUCT_BUNDLE_IDENTIFIER = app.supabit.supacodeTests; 557 557 PRODUCT_NAME = "$(TARGET_NAME)"; 558 558 STRING_CATALOG_GENERATE_SYMBOLS = NO; ··· 569 569 buildSettings = { 570 570 BUNDLE_LOADER = "$(TEST_HOST)"; 571 571 CODE_SIGN_STYLE = Automatic; 572 - CURRENT_PROJECT_VERSION = 112; 572 + CURRENT_PROJECT_VERSION = 113; 573 573 DEAD_CODE_STRIPPING = YES; 574 574 DEVELOPMENT_TEAM = ""; 575 575 GENERATE_INFOPLIST_FILE = YES; 576 576 MACOSX_DEPLOYMENT_TARGET = 26.1; 577 - MARKETING_VERSION = 0.6.7; 577 + MARKETING_VERSION = 0.6.8; 578 578 PRODUCT_BUNDLE_IDENTIFIER = app.supabit.supacodeTests; 579 579 PRODUCT_NAME = "$(TARGET_NAME)"; 580 580 STRING_CATALOG_GENERATE_SYMBOLS = NO;
+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
··· 861 861 surfaces.removeValue(forKey: view.id) 862 862 return 863 863 } 864 + let nextSurface = 865 + focusedSurfaceIdByTab[tabId] == view.id 866 + ? tree.focusTargetAfterClosing(node) 867 + : nil 864 868 let newTree = tree.removing(node) 865 869 view.closeSurface() 866 870 surfaces.removeValue(forKey: view.id) ··· 876 880 trees[tabId] = newTree 877 881 updateRunningState(for: tabId) 878 882 if focusedSurfaceIdByTab[tabId] == view.id { 879 - if let nextSurface = newTree.root?.leftmostLeaf() { 883 + if let nextSurface { 880 884 focusSurface(nextSurface, in: tabId) 881 885 } else { 882 886 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 + }