forked from CodeEditApp/CodeEdit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCodeEditDocumentController.swift
More file actions
179 lines (151 loc) Β· 6.03 KB
/
CodeEditDocumentController.swift
File metadata and controls
179 lines (151 loc) Β· 6.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
//
// CodeEditDocumentController.swift
// CodeEdit
//
// Created by Pavel Kasila on 17.03.22.
//
import Cocoa
import SwiftUI
import WelcomeWindow
final class CodeEditDocumentController: NSDocumentController {
@Environment(\.openWindow)
private var openWindow
@Service var lspService: LSPService
private let fileManager = FileManager.default
@MainActor
func createAndOpenNewDocument(onCompletion: @escaping () -> Void) {
guard let newDocumentUrl = self.newDocumentUrl else { return }
let createdFile = self.fileManager.createFile(
atPath: newDocumentUrl.path,
contents: nil,
attributes: [FileAttributeKey.creationDate: Date()]
)
guard createdFile else {
print("Failed to create new document")
return
}
self.openDocument(withContentsOf: newDocumentUrl, display: true) { _, _, _ in
onCompletion()
}
}
override func newDocument(_ sender: Any?) {
guard let newDocumentUrl = self.newDocumentUrl else { return }
let createdFile = self.fileManager.createFile(
atPath: newDocumentUrl.path,
contents: nil,
attributes: [FileAttributeKey.creationDate: Date()]
)
guard createdFile else {
print("Failed to create new document")
return
}
self.openDocument(withContentsOf: newDocumentUrl, display: true) { _, _, _ in }
}
private var newDocumentUrl: URL? {
let panel = NSSavePanel()
guard panel.runModal() == .OK else {
return nil
}
return panel.url
}
override func openDocument(_ sender: Any?) {
self.openDocument(onCompletion: { document, documentWasAlreadyOpen in
// TODO: handle errors
guard let document else {
print("Failed to unwrap document")
return
}
print(document, documentWasAlreadyOpen)
}, onCancel: {})
}
override func openDocument(
withContentsOf url: URL,
display displayDocument: Bool,
completionHandler: @escaping (NSDocument?, Bool, Error?) -> Void
) {
guard !openFileInExistingWorkspace(url: url) else {
return
}
super.openDocument(withContentsOf: url, display: displayDocument) { document, documentWasAlreadyOpen, error in
if let document {
self.addDocument(document)
} else {
let errorMessage = error?.localizedDescription ?? "unknown error"
print("Unable to open document '\(url)': \(errorMessage)")
}
RecentsStore.documentOpened(at: url)
completionHandler(document, documentWasAlreadyOpen, error)
}
}
/// Attempt to open the file URL in an open workspace, finding the nearest workspace to open it in if possible.
/// - Parameter url: The file URL to open.
/// - Returns: True, if the document was opened in a workspace.
private func openFileInExistingWorkspace(url: URL) -> Bool {
guard !url.isFolder else { return false }
let workspaces = documents.compactMap({ $0 as? WorkspaceDocument })
// Check open workspaces for the file being opened. Sorted by shared components with the url so we
// open the nearest workspace possible.
for workspace in workspaces.sorted(by: {
($0.fileURL?.sharedComponents(url) ?? 0) > ($1.fileURL?.sharedComponents(url) ?? 0)
}) {
// createIfNotFound will still return `nil` if the files don't share a common ancestor.
if let newFile = workspace.workspaceFileManager?.getFile(url.absolutePath, createIfNotFound: true) {
workspace.editorManager?.openTab(item: newFile)
workspace.showWindows()
return true
}
}
return false
}
override func removeDocument(_ document: NSDocument) {
super.removeDocument(document)
if let workspace = document as? WorkspaceDocument, let path = workspace.fileURL?.absoluteURL.path() {
lspService.closeWorkspace(path)
}
if CodeEditDocumentController.shared.documents.isEmpty {
switch Settings[\.general].reopenWindowAfterClose {
case .showWelcomeWindow:
// Opens the welcome window
openWindow(sceneID: .welcome)
case .quit:
// Quits CodeEdit
NSApplication.shared.terminate(nil)
case .doNothing: break
}
}
}
}
extension NSDocumentController {
final func openDocument(onCompletion: @escaping (NSDocument?, Bool) -> Void, onCancel: @escaping () -> Void) {
let dialog = NSOpenPanel()
dialog.title = "Open Workspace or File"
dialog.showsResizeIndicator = true
dialog.showsHiddenFiles = false
dialog.canChooseFiles = true
dialog.canChooseDirectories = true
dialog.begin { result in
if result == NSApplication.ModalResponse.OK, let url = dialog.url {
self.openDocument(withContentsOf: url, display: true) { document, documentWasAlreadyOpen, error in
if let error {
NSAlert(error: error).runModal()
return
}
guard let document else {
let alert = NSAlert()
alert.messageText = NSLocalizedString(
"Failed to get document",
comment: "Failed to get document"
)
alert.runModal()
return
}
onCompletion(document, documentWasAlreadyOpen)
print("Document:", document)
print("Was already open?", documentWasAlreadyOpen)
}
} else if result == NSApplication.ModalResponse.cancel {
onCancel()
}
}
}
}