Add --panel flag to new-split command (#10)
* Add --panel flag to new-split command
Allows splitting a specific panel without changing focus first.
Usage: cmuxterm new-split <direction> [--panel <id|index>]
Example: cmuxterm new-split down --panel 1
* Return new panel ID from new-split command
new-split now returns the UUID of the newly created panel, enabling
reliable chaining of split operations without index drift issues.
Before: OK
After: OK F2675177-3838-49AF-A1A0-1744C0048E99
Example workflow to create left + 2x2 grid on right:
RIGHT=$(cmuxterm new-split right | awk '{print $2}')
BOTTOM=$(cmuxterm new-split down --panel $RIGHT | awk '{print $2}')
cmuxterm new-split right --panel $RIGHT
cmuxterm new-split right --panel $BOTTOM
This commit is contained in:
parent
7bae1216ff
commit
600683cd7d
4 changed files with 45 additions and 16 deletions
|
|
@ -192,10 +192,12 @@ struct CMUXCLI {
|
|||
print(response)
|
||||
|
||||
case "new-split":
|
||||
guard let direction = commandArgs.first else {
|
||||
let (panelArg, remaining) = parseOption(commandArgs, name: "--panel")
|
||||
guard let direction = remaining.first else {
|
||||
throw CLIError(message: "new-split requires a direction")
|
||||
}
|
||||
let response = try client.send(command: "new_split \(direction)")
|
||||
let cmd = panelArg != nil ? "new_split \(direction) \(panelArg!)" : "new_split \(direction)"
|
||||
let response = try client.send(command: cmd)
|
||||
print(response)
|
||||
|
||||
case "list-panels":
|
||||
|
|
@ -509,7 +511,7 @@ struct CMUXCLI {
|
|||
ping
|
||||
list-tabs
|
||||
new-tab
|
||||
new-split <left|right|up|down>
|
||||
new-split <left|right|up|down> [--panel <id|index>]
|
||||
list-panels [--tab <id|index>]
|
||||
focus-panel --panel <id|index>
|
||||
close-tab --tab <id|index>
|
||||
|
|
|
|||
|
|
@ -429,7 +429,7 @@ class GhosttyApp {
|
|||
return false
|
||||
}
|
||||
return performOnMain {
|
||||
tabManager.newSplit(tabId: tabId, surfaceId: surfaceId, direction: direction)
|
||||
tabManager.newSplit(tabId: tabId, surfaceId: surfaceId, direction: direction) != nil
|
||||
}
|
||||
case GHOSTTY_ACTION_GOTO_SPLIT:
|
||||
guard let tabId = surfaceView.tabId,
|
||||
|
|
|
|||
|
|
@ -764,9 +764,9 @@ class TabManager: ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
func newSplit(tabId: UUID, surfaceId: UUID, direction: SplitTree<TerminalSurface>.NewDirection) -> Bool {
|
||||
guard let tab = tabs.first(where: { $0.id == tabId }) else { return false }
|
||||
return tab.newSplit(from: surfaceId, direction: direction) != nil
|
||||
func newSplit(tabId: UUID, surfaceId: UUID, direction: SplitTree<TerminalSurface>.NewDirection) -> UUID? {
|
||||
guard let tab = tabs.first(where: { $0.id == tabId }) else { return nil }
|
||||
return tab.newSplit(from: surfaceId, direction: direction)?.id
|
||||
}
|
||||
|
||||
func moveSplitFocus(tabId: UUID, surfaceId: UUID, direction: SplitTree<TerminalSurface>.FocusDirection) -> Bool {
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ class TerminalController {
|
|||
ping - Check if server is running
|
||||
list_tabs - List all tabs with IDs
|
||||
new_tab - Create a new tab
|
||||
new_split <direction> - Split focused surface (left/right/up/down)
|
||||
new_split <direction> [panel] - Split surface (left/right/up/down), optionally specify panel
|
||||
list_surfaces [tab] - List surfaces for tab (current tab if omitted)
|
||||
focus_surface <id|idx> - Focus surface by ID or index (current tab)
|
||||
close_tab <id> - Close tab by ID
|
||||
|
|
@ -311,24 +311,51 @@ class TerminalController {
|
|||
return "OK \(newTabId?.uuidString ?? "unknown")"
|
||||
}
|
||||
|
||||
private func newSplit(_ directionArg: String) -> String {
|
||||
private func newSplit(_ args: String) -> String {
|
||||
guard let tabManager = tabManager else { return "ERROR: TabManager not available" }
|
||||
|
||||
let trimmed = directionArg.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
guard let direction = parseSplitDirection(trimmed) else {
|
||||
let trimmed = args.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
let parts = trimmed.split(separator: " ", maxSplits: 1).map(String.init)
|
||||
guard !parts.isEmpty else {
|
||||
return "ERROR: Invalid direction. Use left, right, up, or down."
|
||||
}
|
||||
|
||||
var success = false
|
||||
let directionArg = parts[0]
|
||||
let panelArg = parts.count > 1 ? parts[1] : ""
|
||||
|
||||
guard let direction = parseSplitDirection(directionArg) else {
|
||||
return "ERROR: Invalid direction. Use left, right, up, or down."
|
||||
}
|
||||
|
||||
var result = "ERROR: Failed to create split"
|
||||
DispatchQueue.main.sync {
|
||||
guard let tabId = tabManager.selectedTabId,
|
||||
let tab = tabManager.tabs.first(where: { $0.id == tabId }),
|
||||
let surfaceId = tab.focusedSurfaceId else {
|
||||
let tab = tabManager.tabs.first(where: { $0.id == tabId }) else {
|
||||
return
|
||||
}
|
||||
success = tabManager.newSplit(tabId: tabId, surfaceId: surfaceId, direction: direction)
|
||||
|
||||
// If panel arg provided, resolve it; otherwise use focused surface
|
||||
let surfaceId: UUID?
|
||||
if !panelArg.isEmpty {
|
||||
surfaceId = resolveSurfaceId(from: panelArg, tab: tab)
|
||||
if surfaceId == nil {
|
||||
result = "ERROR: Panel not found"
|
||||
return
|
||||
}
|
||||
} else {
|
||||
surfaceId = tab.focusedSurfaceId
|
||||
}
|
||||
|
||||
guard let targetSurface = surfaceId else {
|
||||
result = "ERROR: No surface to split"
|
||||
return
|
||||
}
|
||||
|
||||
if let newPanelId = tabManager.newSplit(tabId: tabId, surfaceId: targetSurface, direction: direction) {
|
||||
result = "OK \(newPanelId.uuidString)"
|
||||
}
|
||||
}
|
||||
return success ? "OK" : "ERROR: Failed to create split"
|
||||
return result
|
||||
}
|
||||
|
||||
private func listSurfaces(_ tabArg: String) -> String {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue