Move file drop snippet operation to EditorTextViewController

This commit is contained in:
1024jp 2024-05-06 22:47:49 +09:00
parent 2ec42fe5f1
commit a2a94bb839
2 changed files with 54 additions and 48 deletions

View File

@ -37,6 +37,12 @@ private extension NSAttributedString.Key {
final class EditorTextView: NSTextView, Themable, CurrentLineHighlighting, MultiCursorEditing {
@MainActor protocol Delegate: AnyObject {
func editorTextView(_ textView: EditorTextView, readDroppedURLs URLs: [URL]) -> Bool
}
// MARK: Notification Names
static let didBecomeFirstResponderNotification = Notification.Name("TextViewDidBecomeFirstResponder")
@ -1013,7 +1019,7 @@ final class EditorTextView: NSTextView, Themable, CurrentLineHighlighting, Multi
// on file drop
if pboard.name == .drag,
let urls = pboard.readObjects(forClasses: [NSURL.self]) as? [URL],
self.insertDroppedFiles(urls)
(self.delegate as? any Delegate)?.editorTextView(self, readDroppedURLs: urls) == true
{
return true
}
@ -1295,13 +1301,6 @@ final class EditorTextView: NSTextView, Themable, CurrentLineHighlighting, Multi
// MARK: Private Methods
/// The file URL of the document representing the text view contents.
private var documentURL: URL? {
(self.window?.windowController?.document as? Document)?.fileURL
}
/// Updates coloring settings with the current theme.
private func applyTheme() {
@ -1434,46 +1433,6 @@ final class EditorTextView: NSTextView, Themable, CurrentLineHighlighting, Multi
}
/// Inserts string representation of dropped files applying the user's file drop settings.
///
/// - Parameter urls: The file URLs of dropped files.
/// - Returns: Whether the file drop was performed.
private func insertDroppedFiles(_ urls: [URL]) -> Bool {
guard !urls.isEmpty else { return false }
let fileDropItems = UserDefaults.standard[.fileDropArray].map(FileDropItem.init(dictionary:))
let replacementString = urls.reduce(into: "") { (string, url) in
if url.pathExtension == "textClipping", let textClipping = try? TextClipping(contentsOf: url) {
string += textClipping.string
return
}
if let fileDropItem = fileDropItems.first(where: { $0.supports(extension: url.pathExtension, scope: self.syntaxName) }) {
string += fileDropItem.dropText(forFileURL: url, documentURL: self.documentURL)
return
}
// just insert the absolute path if no specific setting for the file type was found
// -> This is the default behavior of NSTextView by file dropping.
if !string.isEmpty {
string += self.lineEnding.string
}
string += url.isFileURL ? url.path : url.absoluteString
}
// insert drop text to view
guard self.shouldChangeText(in: self.rangeForUserTextChange, replacementString: replacementString) else { return false }
self.replaceCharacters(in: self.rangeForUserTextChange, with: replacementString)
self.didChangeText()
return true
}
/// Highlights the brace matching to the brace next to the cursor.
private func highlightMatchingBrace() {

View File

@ -449,6 +449,53 @@ extension EditorTextViewController: NSUserInterfaceValidations {
}
extension EditorTextViewController: EditorTextView.Delegate {
/// Inserts string representation of dropped files applying the user's file drop snippets.
///
/// - Parameter urls: The file URLs of dropped files.
/// - Returns: Whether the file drop was performed.
func editorTextView(_ textView: EditorTextView, readDroppedURLs urls: [URL]) -> Bool {
guard !urls.isEmpty else { return false }
let fileDropItems = UserDefaults.standard[.fileDropArray].map(FileDropItem.init(dictionary:))
guard !fileDropItems.isEmpty else { return false }
let replacementString = urls.reduce(into: "") { (string, url) in
if url.pathExtension == "textClipping", let textClipping = try? TextClipping(contentsOf: url) {
string += textClipping.string
return
}
if let fileDropItem = fileDropItems.first(where: { $0.supports(extension: url.pathExtension, scope: textView.syntaxName) }) {
string += fileDropItem.dropText(forFileURL: url, documentURL: self.document.fileURL)
return
}
// just insert the absolute path if no specific setting for the file type was found
// -> This is the default behavior of NSTextView by file dropping.
if !string.isEmpty {
string += textView.lineEnding.string
}
string += url.isFileURL ? url.path : url.absoluteString
}
guard replacementString.isEmpty else { return true }
// insert snippets to view
guard textView.shouldChangeText(in: textView.rangeForUserTextChange, replacementString: replacementString) else { return false }
textView.replaceCharacters(in: textView.rangeForUserTextChange, with: replacementString)
textView.didChangeText()
return true
}
}
extension EditorTextViewController: NSFontChanging {