From 741067ed1d0d63572dd1259c9924f1e69ff4f275 Mon Sep 17 00:00:00 2001 From: William Laverty Date: Sun, 1 Feb 2026 23:13:58 -0800 Subject: [PATCH 1/2] fix: select name for editing when creating new files or folders Fixes #2029 When creating a new file or folder via the context menu, the name is now automatically selected for editing. This matches the expected macOS UX behavior where new items can be immediately renamed. Changes: - Added renameFile() call after creating new file in newFile() - Added renameFile() call after creating new folder in newFolder() Note: The newFileFromClipboard() already had this behavior, this makes the other creation methods consistent. --- .../OutlineView/ProjectNavigatorMenuActions.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CodeEdit/Features/NavigatorArea/ProjectNavigator/OutlineView/ProjectNavigatorMenuActions.swift b/CodeEdit/Features/NavigatorArea/ProjectNavigator/OutlineView/ProjectNavigatorMenuActions.swift index 1aa65af926..b9d4e18201 100644 --- a/CodeEdit/Features/NavigatorArea/ProjectNavigator/OutlineView/ProjectNavigatorMenuActions.swift +++ b/CodeEdit/Features/NavigatorArea/ProjectNavigator/OutlineView/ProjectNavigatorMenuActions.swift @@ -90,6 +90,7 @@ extension ProjectNavigatorMenu { if let newFile = try workspace?.workspaceFileManager?.addFile(fileName: "untitled", toFile: item) { workspace?.listenerModel.highlightedFileItem = newFile workspace?.editorManager?.openTab(item: newFile) + renameFile() } } catch { let alert = NSAlert(error: error) @@ -147,6 +148,7 @@ extension ProjectNavigatorMenu { do { if let newFolder = try workspace?.workspaceFileManager?.addFolder(folderName: "untitled", toFile: item) { workspace?.listenerModel.highlightedFileItem = newFolder + renameFile() } } catch { let alert = NSAlert(error: error) From 118afcd5411ff4219add68d4bba8a7a24cc5c8bc Mon Sep 17 00:00:00 2001 From: William Laverty Date: Fri, 13 Feb 2026 04:03:53 -0800 Subject: [PATCH 2/2] =?UTF-8?q?Add=20=E2=87=A7=E2=8C=98T=20keyboard=20shor?= =?UTF-8?q?tcut=20to=20reopen=20closed=20editor=20tabs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #1656 Implements a closed-tab history stack on the Editor model that tracks recently closed files. Pressing ⇧⌘T (Shift+Command+T) reopens the most recently closed tab, similar to web browsers and VS Code. Changes: - Editor: Added closedTabs stack (capped at 25 entries) - Editor.closeTab: Pushes closed files onto the stack - Editor+History: Added reopenClosedTab() and canReopenClosedTab - CodeEditWindowController: Added reopenClosedTab action - FileCommands: Added 'Reopen Closed Tab' menu item with ⇧⌘T shortcut The stack is per-editor instance and skips files that are already open. --- .../CodeEditWindowController.swift | 4 ++++ .../Editor/Models/Editor/Editor+History.swift | 19 +++++++++++++++++++ .../Editor/Models/Editor/Editor.swift | 13 +++++++++++++ .../WindowCommands/FileCommands.swift | 9 +++++++++ 4 files changed, 45 insertions(+) diff --git a/CodeEdit/Features/Documents/Controllers/CodeEditWindowController.swift b/CodeEdit/Features/Documents/Controllers/CodeEditWindowController.swift index be082d6fee..967324b2b2 100644 --- a/CodeEdit/Features/Documents/Controllers/CodeEditWindowController.swift +++ b/CodeEdit/Features/Documents/Controllers/CodeEditWindowController.swift @@ -198,6 +198,10 @@ final class CodeEditWindowController: NSWindowController, NSToolbarDelegate, Obs } } + @IBAction func reopenClosedTab(_ sender: Any) { + workspace?.editorManager?.activeEditor.reopenClosedTab() + } + @IBAction func closeActiveEditor(_ sender: Any) { if workspace?.editorManager?.editorLayout.findSomeEditor( except: workspace?.editorManager?.activeEditor diff --git a/CodeEdit/Features/Editor/Models/Editor/Editor+History.swift b/CodeEdit/Features/Editor/Models/Editor/Editor+History.swift index 8dfcf228d5..570c88b942 100644 --- a/CodeEdit/Features/Editor/Models/Editor/Editor+History.swift +++ b/CodeEdit/Features/Editor/Models/Editor/Editor+History.swift @@ -39,6 +39,25 @@ extension Editor { } } + /// Reopens the most recently closed tab. + /// Pops from the ``closedTabs`` stack and opens it as a new tab. + func reopenClosedTab() { + guard let file = closedTabs.popLast() else { return } + // Skip files that are already open. + if tabs.contains(where: { $0.file == file }) { + // Already open — select it instead and try the next closed tab. + setSelectedTab(file) + reopenClosedTab() + return + } + openTab(file: file) + } + + /// Whether there are closed tabs available to reopen. + var canReopenClosedTab: Bool { + !closedTabs.isEmpty + } + // TODO: move to @Observable so this works better /// Warning: NOT published! var canGoBackInHistory: Bool { diff --git a/CodeEdit/Features/Editor/Models/Editor/Editor.swift b/CodeEdit/Features/Editor/Models/Editor/Editor.swift index 782b956b71..7b0dc8bed6 100644 --- a/CodeEdit/Features/Editor/Models/Editor/Editor.swift +++ b/CodeEdit/Features/Editor/Models/Editor/Editor.swift @@ -52,6 +52,10 @@ final class Editor: ObservableObject, Identifiable { /// - Warning: Use the ``addToHistory(_:)`` or ``clearFuture()`` methods to modify this. Do not modify directly. @Published var history: Deque = [] + /// Stack of recently closed tabs, used for ⇧⌘T reopen functionality. + /// Most recently closed tab is at the end. + @Published var closedTabs: [CEWorkspaceFile] = [] + /// Currently selected tab. @Published private(set) var selectedTab: Tab? @@ -145,6 +149,15 @@ final class Editor: ObservableObject, Identifiable { func closeTab(file: CEWorkspaceFile, fromHistory: Bool = false) { guard canCloseTab(file: file) else { return } + // Track closed tab for ⇧⌘T reopen. Avoid duplicates at the top of the stack. + if closedTabs.last != file { + closedTabs.append(file) + // Cap the stack to avoid unbounded growth. + if closedTabs.count > 25 { + closedTabs.removeFirst() + } + } + if temporaryTab?.file == file { temporaryTab = nil } diff --git a/CodeEdit/Features/WindowCommands/FileCommands.swift b/CodeEdit/Features/WindowCommands/FileCommands.swift index 130ce0e5b1..297db94971 100644 --- a/CodeEdit/Features/WindowCommands/FileCommands.swift +++ b/CodeEdit/Features/WindowCommands/FileCommands.swift @@ -51,6 +51,15 @@ struct FileCommands: Commands { } .keyboardShortcut("w") + Button("Reopen Closed Tab") { + NSApp.sendAction( + #selector(CodeEditWindowController.reopenClosedTab(_:)), + to: nil, + from: nil + ) + } + .keyboardShortcut("t", modifiers: [.shift, .command]) + Button("Close Editor") { if NSApp.target(forAction: #selector(CodeEditWindowController.closeActiveEditor(_:))) != nil { NSApp.sendAction(