Skip to content

Commit 74cbf24

Browse files
feat: Add ⇧⌘T shortcut to reopen closed tabs
Implements #1656 This PR adds the ability to reopen recently closed editor tabs using the ⇧⌘T (Shift+Command+T) keyboard shortcut, a common convention in most editors and browsers. Changes: - Add closedTabsHistory to Editor to track recently closed tabs (up to 20) - Modify closeTab() to save tabs to the closed history before closing - Add reopenLastClosedTab() method to Editor - Add reopenClosedTab action to CodeEditWindowController - Add 'Reopen Closed Tab' menu item to File menu with ⇧⌘T shortcut The history is per-editor, so each split view maintains its own closed tab history. Users can repeatedly press ⇧⌘T to reopen multiple tabs in the order they were closed.
1 parent cec6287 commit 74cbf24

File tree

3 files changed

+59
-0
lines changed

3 files changed

+59
-0
lines changed

CodeEdit/Features/Documents/Controllers/CodeEditWindowController.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,10 @@ final class CodeEditWindowController: NSWindowController, NSToolbarDelegate, Obs
198198
}
199199
}
200200

201+
@IBAction func reopenClosedTab(_ sender: Any) {
202+
workspace?.editorManager?.activeEditor.reopenLastClosedTab()
203+
}
204+
201205
@IBAction func closeActiveEditor(_ sender: Any) {
202206
if workspace?.editorManager?.editorLayout.findSomeEditor(
203207
except: workspace?.editorManager?.activeEditor

CodeEdit/Features/Editor/Models/Editor/Editor.swift

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ final class Editor: ObservableObject, Identifiable {
5252
/// - Warning: Use the ``addToHistory(_:)`` or ``clearFuture()`` methods to modify this. Do not modify directly.
5353
@Published var history: Deque<CEWorkspaceFile> = []
5454

55+
/// Maintains the list of recently closed tabs that can be reopened.
56+
/// The most recently closed tab is at the front of the deque.
57+
@Published var closedTabsHistory: Deque<CEWorkspaceFile> = []
58+
59+
/// Maximum number of closed tabs to remember.
60+
private static let maxClosedTabsHistory = 20
61+
5562
/// Currently selected tab.
5663
@Published private(set) var selectedTab: Tab?
5764

@@ -154,6 +161,10 @@ final class Editor: ObservableObject, Identifiable {
154161
if file != selectedTab?.file {
155162
addToHistory(EditorInstance(workspace: workspace, file: file))
156163
}
164+
165+
// Add to closed tabs history for reopening later
166+
addToClosedTabsHistory(file)
167+
157168
removeTab(file)
158169
if let selectedTab {
159170
addToHistory(selectedTab)
@@ -167,6 +178,45 @@ final class Editor: ObservableObject, Identifiable {
167178
file.fileDocument = nil
168179
}
169180

181+
/// Adds a file to the closed tabs history.
182+
/// - Parameter file: The file to add to the history.
183+
private func addToClosedTabsHistory(_ file: CEWorkspaceFile) {
184+
// Don't add duplicates (in case the same file is closed multiple times)
185+
closedTabsHistory.removeAll(where: { $0 == file })
186+
187+
// Add to the front of the history
188+
closedTabsHistory.prepend(file)
189+
190+
// Trim to max size
191+
while closedTabsHistory.count > Self.maxClosedTabsHistory {
192+
closedTabsHistory.removeLast()
193+
}
194+
}
195+
196+
/// Whether there are closed tabs that can be reopened.
197+
var canReopenClosedTab: Bool {
198+
!closedTabsHistory.isEmpty
199+
}
200+
201+
/// Reopens the most recently closed tab.
202+
/// - Returns: The file that was reopened, or nil if there are no closed tabs.
203+
@discardableResult
204+
func reopenLastClosedTab() -> CEWorkspaceFile? {
205+
guard let file = closedTabsHistory.popFirst() else {
206+
return nil
207+
}
208+
209+
// Only reopen if the tab isn't already open
210+
if !tabs.contains(where: { $0.file == file }) {
211+
openTab(file: file)
212+
} else {
213+
// If already open, just select it
214+
setSelectedTab(file)
215+
}
216+
217+
return file
218+
}
219+
170220
/// Closes the currently opened tab in the tab group.
171221
func closeSelectedTab() {
172222
guard let file = selectedTab?.file else {

CodeEdit/Features/WindowCommands/FileCommands.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ struct FileCommands: Commands {
5151
}
5252
.keyboardShortcut("w")
5353

54+
Button("Reopen Closed Tab") {
55+
NSApp.sendAction(#selector(CodeEditWindowController.reopenClosedTab(_:)), to: nil, from: nil)
56+
}
57+
.keyboardShortcut("t", modifiers: [.command, .shift])
58+
5459
Button("Close Editor") {
5560
if NSApp.target(forAction: #selector(CodeEditWindowController.closeActiveEditor(_:))) != nil {
5661
NSApp.sendAction(

0 commit comments

Comments
 (0)