Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/commands/pull.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Pull latest main and update all submodules to their latest remote main. No commi
## Steps

1. `git pull origin main`
2. For each submodule (ghostty, vendor/bonsplit):
2. For each submodule (ghostty):
- `cd <submodule>`
- `git fetch origin`
- Check if behind: `git rev-list HEAD..origin/main --count`
Expand Down
4 changes: 2 additions & 2 deletions .claude/commands/sync-branch.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Get the current branch ready: update all submodules to their latest remote main,
## Steps

1. **Update submodules to latest**
- For each submodule (ghostty, vendor/bonsplit):
- For each submodule (ghostty):
- `cd <submodule>`
- `git fetch origin`
- Check if behind: `git rev-list HEAD..origin/main --count`
Expand All @@ -18,7 +18,7 @@ Get the current branch ready: update all submodules to their latest remote main,
2. **Commit submodule updates on main**
- `git checkout main && git pull origin main`
- Check if any submodules changed: `git diff --name-only` (look for submodule paths)
- If changed, stage and commit: `git add ghostty vendor/bonsplit && git commit -m "Update submodules: <brief description>"`
- If changed, stage and commit: `git add ghostty && git commit -m "Update submodules: <brief description>"`
- **Do not push.** Ask the user if they want to push.

3. **Rebase current branch on main**
Expand Down
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,3 @@
path = ghostty
url = https://github.com/darkroomengineering/ghostty.git
branch = main
[submodule "vendor/bonsplit"]
path = vendor/bonsplit
url = https://github.com/manaflow-ai/bonsplit.git
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ The app has a **Debug** menu in the macOS menu bar (only in DEBUG builds). Use i
- `TabItemView` in `ContentView.swift`: uses `Equatable` conformance + `.equatable()` to skip body re-evaluation during typing. Do not add `@EnvironmentObject`, `@ObservedObject` (besides `tab`), or `@Binding` properties without updating the `==` function. Do not remove `.equatable()` from the ForEach call site. Do not read `tabManager` or `notificationStore` in the body; use the precomputed `let` parameters instead.
- `TerminalSurface.forceRefresh()` in `GhosttyTerminalView.swift`: called on every keystroke. Do not add allocations, file I/O, or formatting here.
- **Terminal find layering contract:** `SurfaceSearchOverlay` must be mounted from `GhosttySurfaceScrollView` in `Sources/GhosttyTerminalView.swift` (AppKit portal layer), not from SwiftUI panel containers such as `Sources/Panels/TerminalPanelView.swift`. Portal-hosted terminal views can sit above SwiftUI during split/workspace churn.
- **Submodule safety:** When modifying a submodule (ghostty, vendor/bonsplit, etc.), always push the submodule commit to its remote `main` branch BEFORE committing the updated pointer in the parent repo. Never commit on a detached HEAD or temporary branch — the commit will be orphaned and lost. Verify with: `cd <submodule> && git merge-base --is-ancestor HEAD origin/main`.
- **Submodule safety:** When modifying a submodule (ghostty), always push the submodule commit to its remote `main` branch BEFORE committing the updated pointer in the parent repo. Never commit on a detached HEAD or temporary branch — the commit will be orphaned and lost. Verify with: `cd <submodule> && git merge-base --is-ancestor HEAD origin/main`. Note: `vendor/bonsplit` is NOT a submodule — it is vendored in-tree (MIT, from the manaflow-ai fork); edit and commit it like any other source directory.
- **All user-facing strings must be localized.** Use `String(localized: "key.name", defaultValue: "English text")` for every string shown in the UI (labels, buttons, menus, dialogs, tooltips, error messages). Keys go in `Resources/Localizable.xcstrings` with translations for all supported languages (currently English and Japanese). Never use bare string literals in SwiftUI `Text()`, `Button()`, alert titles, etc.
- **Shortcut policy:** Every new Programa-owned keyboard shortcut must be added to `KeyboardShortcutSettings`, visible/editable in Settings, supported in `~/.config/programa/settings.json`, and documented in the keyboard shortcut and configuration docs.

Expand Down
1 change: 1 addition & 0 deletions THIRD_PARTY_LICENSES.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ SOFTWARE.
- **License:** MIT License
- **Copyright:** Copyright (c) 2026 Alasdair Monk
- **Source:** https://github.com/almonk/bonsplit
- **Vendored:** in-tree at `vendor/bonsplit`, from the manaflow-ai/bonsplit fork at commit `b2788b1e77d43f0c114dcf189aa59cae8abb47de` (Example app, www site, and upstream CI omitted)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
1 change: 0 additions & 1 deletion vendor/bonsplit
Submodule bonsplit deleted from b2788b
59 changes: 59 additions & 0 deletions vendor/bonsplit/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Swift Package Manager
.build/
.swiftpm/
Package.resolved

# Xcode
xcuserdata/
*.xccheckout
*.xcscmblueprint
*.xcodeproj/project.xcworkspace/xcuserdata/
*.xcodeproj/xcuserdata/
*.xcworkspace/xcuserdata/
DerivedData/
*.moved-aside
*.hmap
*.ipa
*.dSYM.zip
*.dSYM

# macOS
.DS_Store
.AppleDouble
.LSOverride
._*

# IDEs
.idea/
.vscode/
*.swp
*.swo
*~

# CocoaPods (if used)
Pods/

# Carthage (if used)
Carthage/Build/
Carthage/Checkouts/

# Fastlane
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots/**/*.png
fastlane/test_output

# Code coverage
*.gcno
*.gcda
*.gcov

# Playgrounds
timeline.xctimeline
playground.xcworkspace

# Archives
*.xcarchive

# Local build output
build/
57 changes: 57 additions & 0 deletions vendor/bonsplit/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Changelog

All notable changes to Bonsplit will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.1.1] - 2025-01-29

### Fixed
- Fixed delegate notifications not being sent when closing tabs ([#2](https://github.com/almonk/bonsplit/issues/2))
- Tabs now correctly communicate through `BonsplitController` for proper delegate callbacks

### Added
- New public method `closeTab(_ tabId: TabID, inPane paneId: PaneID) -> Bool` for efficient tab closing when pane is known

## [1.1.0] - 2025-01-26

### Added

#### Two-Way Synchronization API
- **Geometry Query**: Query pane layout with pixel coordinates for integration with external programs
- `layoutSnapshot()` - Get flat list of pane geometries with pixel coordinates
- `treeSnapshot()` - Get full tree structure for external consumption
- `findSplit(_:)` - Check if a split exists by UUID

- **Programmatic Updates**: Control divider positions from external sources
- `setDividerPosition(_:forSplit:fromExternal:)` - Set divider position with loop prevention
- `setContainerFrame(_:)` - Update container frame when window moves/resizes

- **Geometry Notifications**: Receive callbacks when geometry changes
- `didChangeGeometry` delegate callback - Notified when any pane geometry changes
- `shouldNotifyDuringDrag` delegate callback - Opt-in to real-time notifications during divider drag

#### New Types
- `LayoutSnapshot` - Full tree snapshot with pixel coordinates and timestamp
- `PixelRect` - Pixel rectangle for external consumption (Codable, Sendable)
- `PaneGeometry` - Geometry for a single pane including frame and tab info
- `ExternalTreeNode` - Recursive tree representation (enum: pane or split)
- `ExternalPaneNode` - Pane node for external consumption
- `ExternalSplitNode` - Split node with orientation and divider position
- `ExternalTab` - Tab info for external consumption

#### Debug Tools
- Debug window in Example app for testing synchronization features

## [1.0.0] - Initial Release

### Added
- Tab bar with drag-and-drop reordering
- Horizontal and vertical split panes
- 120fps animations
- Configurable appearance and behavior
- Delegate callbacks for all tab and pane events
- Keyboard navigation between panes
- Content view lifecycle options (recreateOnSwitch, keepAllAlive)
- Configuration presets (default, singlePane, readOnly)
21 changes: 21 additions & 0 deletions vendor/bonsplit/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 Alasdair Monk

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
32 changes: 32 additions & 0 deletions vendor/bonsplit/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// swift-tools-version: 5.9

import PackageDescription

let package = Package(
name: "Bonsplit",
defaultLocalization: "en",
platforms: [
.macOS(.v14)
],
products: [
.library(
name: "Bonsplit",
targets: ["Bonsplit"]
),
],
targets: [
.target(
name: "Bonsplit",
dependencies: [],
path: "Sources/Bonsplit",
resources: [
.process("Resources")
]
),
.testTarget(
name: "BonsplitTests",
dependencies: ["Bonsplit"],
path: "Tests/BonsplitTests"
),
]
)
Loading
Loading