Repository navigation
Add new workspace above and below actions #5644
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -126,6 +126,11 @@ enum NewWorkspacePlacement: String, CaseIterable, Identifiable { | |
| } | ||
| } | ||
|
|
||
| enum WorkspaceAdjacentInsertionPosition: Sendable { | ||
| case above | ||
| case below | ||
| } | ||
|
|
||
| enum WorkspaceAutoReorderSettings { | ||
| static let key = "workspaceAutoReorderOnNotification" | ||
| static let defaultValue = true | ||
|
|
@@ -2612,11 +2617,12 @@ class TabManager: ObservableObject { | |
| select: Bool = true, | ||
| eagerLoadTerminal: Bool = false, | ||
| placementOverride: NewWorkspacePlacement? = nil, | ||
| sourceWorkspaceOverride: Workspace? = nil, | ||
| autoWelcomeIfNeeded: Bool = true, | ||
| autoRefreshMetadata: Bool = true, | ||
| normalizeWorkspaceGroupsAfterInsert: Bool = true | ||
| ) -> Workspace { | ||
| let sourceWorkspace = selectedWorkspace | ||
| let sourceWorkspace = sourceWorkspaceOverride ?? selectedWorkspace | ||
| let capturedTabs = tabs | ||
| // Snapshot the selected tab from the pinned workspace instead of rereading the | ||
| // @Published selectedTabId storage after the inheritance helpers. The arm64 Nightly | ||
|
|
@@ -4273,6 +4279,122 @@ class TabManager: ObservableObject { | |
| return newWorkspace | ||
| } | ||
|
|
||
| @discardableResult | ||
| func createWorkspaceAdjacent( | ||
| to referenceWorkspaceId: UUID, | ||
| position: WorkspaceAdjacentInsertionPosition, | ||
| select: Bool = true | ||
| ) -> Workspace? { | ||
| guard let referenceWorkspace = tabs.first(where: { $0.id == referenceWorkspaceId }) else { | ||
| return nil | ||
| } | ||
|
|
||
| if let groupId = referenceWorkspace.groupId, | ||
| let group = workspaceGroups.first(where: { $0.id == groupId }) { | ||
| if group.anchorWorkspaceId == referenceWorkspaceId { | ||
| return createWorkspaceAdjacentToGroup( | ||
| groupId: groupId, | ||
| position: position, | ||
| select: select | ||
| ) | ||
| } | ||
| return createWorkspaceAdjacentWithinGroup( | ||
| to: referenceWorkspace, | ||
| groupId: groupId, | ||
| position: position, | ||
| select: select | ||
| ) | ||
| } | ||
|
|
||
| let newWorkspace = addWorkspace( | ||
| select: select, | ||
| placementOverride: .end, | ||
| sourceWorkspaceOverride: referenceWorkspace | ||
| ) | ||
| reorderCreatedWorkspace( | ||
| newWorkspace.id, | ||
| adjacentTo: referenceWorkspaceId, | ||
| position: position | ||
| ) | ||
|
Comment on lines
+4309
to
+4318
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Preserve pin tier for adjacent insertion targets. Line 4314 / Line 4339 / Line 4366 reorder a newly created workspace that is always unpinned. Because Suggested fix@@
func createWorkspaceAdjacent(
to referenceWorkspaceId: UUID,
position: WorkspaceAdjacentInsertionPosition,
select: Bool = true
) -> Workspace? {
@@
let newWorkspace = addWorkspace(
select: select,
placementOverride: .end,
sourceWorkspaceOverride: referenceWorkspace
)
+ newWorkspace.isPinned = referenceWorkspace.isPinned
reorderCreatedWorkspace(
newWorkspace.id,
adjacentTo: referenceWorkspaceId,
position: position
)
return newWorkspace
}
@@
private func createWorkspaceAdjacentWithinGroup(
to referenceWorkspace: Workspace,
groupId: UUID,
position: WorkspaceAdjacentInsertionPosition,
select: Bool
@@
let newWorkspace = addWorkspace(
workingDirectory: cwd,
inheritWorkingDirectory: cwd == nil,
select: select,
placementOverride: .end,
sourceWorkspaceOverride: referenceWorkspace,
autoWelcomeIfNeeded: false
)
+ newWorkspace.isPinned = referenceWorkspace.isPinned
assignGroup(workspaceId: newWorkspace.id, groupId: groupId)
reorderCreatedWorkspace(
newWorkspace.id,
adjacentTo: referenceWorkspace.id,
position: position
)
@@
private func createWorkspaceAdjacentToGroup(
groupId: UUID,
position: WorkspaceAdjacentInsertionPosition,
select: Bool
) -> Workspace? {
@@
let newWorkspace = addWorkspace(
select: select,
placementOverride: .end,
sourceWorkspaceOverride: anchorWorkspace
)
+ newWorkspace.isPinned = group.isPinned
let groupMemberIds = tabs.filter { $0.groupId == groupId && $0.id != newWorkspace.id }.map(\.id)
switch position {Also applies to: 4330-4343, 4357-4371 🤖 Prompt for AI Agents |
||
| return newWorkspace | ||
| } | ||
|
|
||
| private func createWorkspaceAdjacentWithinGroup( | ||
| to referenceWorkspace: Workspace, | ||
| groupId: UUID, | ||
| position: WorkspaceAdjacentInsertionPosition, | ||
| select: Bool | ||
| ) -> Workspace? { | ||
| guard let group = workspaceGroups.first(where: { $0.id == groupId }) else { return nil } | ||
| let cwd = tabs.first(where: { $0.id == group.anchorWorkspaceId })?.currentDirectory | ||
| let newWorkspace = addWorkspace( | ||
| workingDirectory: cwd, | ||
| inheritWorkingDirectory: cwd == nil, | ||
|
Comment on lines
+4329
to
+4332
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When this action is invoked from a workspace row inside a group whose current directory differs from the group anchor, the new workspace is created with the anchor's Useful? React with 👍 / 👎. |
||
| select: select, | ||
| placementOverride: .end, | ||
| sourceWorkspaceOverride: referenceWorkspace, | ||
| autoWelcomeIfNeeded: false | ||
| ) | ||
| assignGroup(workspaceId: newWorkspace.id, groupId: groupId) | ||
| reorderCreatedWorkspace( | ||
| newWorkspace.id, | ||
| adjacentTo: referenceWorkspace.id, | ||
| position: position | ||
| ) | ||
| expandGroupIfNeeded(groupId: groupId, select: select) | ||
| return newWorkspace | ||
| } | ||
|
|
||
| private func createWorkspaceAdjacentToGroup( | ||
| groupId: UUID, | ||
| position: WorkspaceAdjacentInsertionPosition, | ||
| select: Bool | ||
| ) -> Workspace? { | ||
| guard let group = workspaceGroups.first(where: { $0.id == groupId }), | ||
| let anchorWorkspace = tabs.first(where: { $0.id == group.anchorWorkspaceId }) else { | ||
| return nil | ||
| } | ||
| let newWorkspace = addWorkspace( | ||
| select: select, | ||
| placementOverride: .end, | ||
| sourceWorkspaceOverride: anchorWorkspace | ||
| ) | ||
| let groupMemberIds = tabs.filter { $0.groupId == groupId && $0.id != newWorkspace.id }.map(\.id) | ||
| switch position { | ||
| case .above: | ||
| if let firstGroupWorkspaceId = groupMemberIds.first { | ||
| _ = reorderWorkspace(tabId: newWorkspace.id, before: firstGroupWorkspaceId) | ||
| } | ||
| case .below: | ||
| if let lastGroupWorkspaceId = groupMemberIds.last { | ||
| _ = reorderWorkspace(tabId: newWorkspace.id, after: lastGroupWorkspaceId) | ||
| } | ||
| } | ||
| return newWorkspace | ||
| } | ||
|
|
||
| private func reorderCreatedWorkspace( | ||
| _ workspaceId: UUID, | ||
| adjacentTo referenceWorkspaceId: UUID, | ||
| position: WorkspaceAdjacentInsertionPosition | ||
| ) { | ||
| switch position { | ||
| case .above: | ||
| _ = reorderWorkspace(tabId: workspaceId, before: referenceWorkspaceId) | ||
| case .below: | ||
| _ = reorderWorkspace(tabId: workspaceId, after: referenceWorkspaceId) | ||
| } | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pinned adjacent insert misplaces workspaceMedium Severity Adjacent workspace creation appends via Additional Locations (1)Reviewed by Cursor Bugbot for commit 4e0f350. Configure here. |
||
|
|
||
| private func expandGroupIfNeeded(groupId: UUID, select: Bool) { | ||
| guard select, | ||
| let idx = workspaceGroups.firstIndex(where: { $0.id == groupId }), | ||
| workspaceGroups[idx].isCollapsed else { | ||
| return | ||
| } | ||
| workspaceGroups[idx].isCollapsed = false | ||
| } | ||
|
|
||
| /// Move an existing group member to the requested in-group slot. Called | ||
| /// after `createWorkspaceInGroup` and any other path that needs to | ||
| /// pin the new member relative to the group's members. | ||
|
|
||


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The catalog already contains 20 locales —
ar,bs,da,de,es,fr,it,km,ko,nb,pl,pt-BR,ru,th,tr,uk,zh-Hans, andzh-Hantin addition toenandja— but all four new keys (command.newWorkspaceAbove.title,command.newWorkspaceBelow.title,contextMenu.newWorkspaceAbove,contextMenu.newWorkspaceBelow) only supplyenandjaentries. Every other supported locale will fall back to theendefault value at runtime, leaving users of the other 18 locales with untranslated strings.Rule Used: Flag production user-facing text that is not fully... (source)
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!