mirror of
https://github.com/coteditor/CotEditor.git
synced 2024-09-11 11:25:57 +03:00
Use UTType in file setting managers
This commit is contained in:
parent
91d9756d1e
commit
7f9195308e
@ -16,6 +16,7 @@ Change Log
|
||||
- Detect the line ending in documents more intelligently.
|
||||
- Optimize syntax parsing.
|
||||
- Deprecate the feature to replace `$LN` in the outline menu template with the line number of the occurrence.
|
||||
- Prefer using .yml for syntax definition files over .yaml.
|
||||
- [trivial] Replace `\n` with `\R` for the new line meta character in the regular expression reference.
|
||||
- [trivial] Tweak Anura theme.
|
||||
|
||||
|
@ -392,8 +392,8 @@
|
||||
2A9082F31D32A9B500228F50 /* ThemeManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A9082F11D32A9B500228F50 /* ThemeManager.swift */; };
|
||||
2A91C3181D1BE91E007CF8BE /* DefaultSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A91C3171D1BE91E007CF8BE /* DefaultSettings.swift */; };
|
||||
2A91C3191D1BE91E007CF8BE /* DefaultSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A91C3171D1BE91E007CF8BE /* DefaultSettings.swift */; };
|
||||
2A91C31B1D1BFE47007CF8BE /* DocumentType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A91C31A1D1BFE47007CF8BE /* DocumentType.swift */; };
|
||||
2A91C31C1D1BFE47007CF8BE /* DocumentType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A91C31A1D1BFE47007CF8BE /* DocumentType.swift */; };
|
||||
2A91C31B1D1BFE47007CF8BE /* UTType+SettingFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A91C31A1D1BFE47007CF8BE /* UTType+SettingFile.swift */; };
|
||||
2A91C31C1D1BFE47007CF8BE /* UTType+SettingFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A91C31A1D1BFE47007CF8BE /* UTType+SettingFile.swift */; };
|
||||
2A91C31E1D1C3963007CF8BE /* PrintPaneController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A91C31D1D1C3963007CF8BE /* PrintPaneController.swift */; };
|
||||
2A91C31F1D1C3963007CF8BE /* PrintPaneController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A91C31D1D1C3963007CF8BE /* PrintPaneController.swift */; };
|
||||
2A91C3211D1C40E4007CF8BE /* FileDropPaneController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A91C3201D1C40E4007CF8BE /* FileDropPaneController.swift */; };
|
||||
@ -1168,7 +1168,7 @@
|
||||
2A9082EE1D325ED900228F50 /* GeometryTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeometryTests.swift; sourceTree = "<group>"; };
|
||||
2A9082F11D32A9B500228F50 /* ThemeManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThemeManager.swift; sourceTree = "<group>"; };
|
||||
2A91C3171D1BE91E007CF8BE /* DefaultSettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultSettings.swift; sourceTree = "<group>"; };
|
||||
2A91C31A1D1BFE47007CF8BE /* DocumentType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DocumentType.swift; sourceTree = "<group>"; };
|
||||
2A91C31A1D1BFE47007CF8BE /* UTType+SettingFile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UTType+SettingFile.swift"; sourceTree = "<group>"; };
|
||||
2A91C31D1D1C3963007CF8BE /* PrintPaneController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrintPaneController.swift; sourceTree = "<group>"; };
|
||||
2A91C3201D1C40E4007CF8BE /* FileDropPaneController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileDropPaneController.swift; sourceTree = "<group>"; };
|
||||
2A94FC781BE2256F00B454A8 /* cot */ = {isa = PBXFileReference; explicitFileType = text.script.python; name = cot; path = cot/cot; sourceTree = SOURCE_ROOT; };
|
||||
@ -1655,6 +1655,7 @@
|
||||
2AACB1DA1D19B1440073775B /* Key Binding Managers */,
|
||||
2A8DA9431D286C53003D0C4B /* ScriptManager.swift */,
|
||||
2AC13A0824F112D800799A93 /* CommandLineToolManager.swift */,
|
||||
2A91C31A1D1BFE47007CF8BE /* UTType+SettingFile.swift */,
|
||||
);
|
||||
name = Managers;
|
||||
sourceTree = "<group>";
|
||||
@ -1724,7 +1725,6 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2AC2462D1D1BC70C00E46CFA /* AppDelegate.swift */,
|
||||
2A91C31A1D1BFE47007CF8BE /* DocumentType.swift */,
|
||||
2A8961911DB76A3400E9E0EC /* MainMenu.swift */,
|
||||
2A78BFBB1D1B376000A583D2 /* ServicesProvider.swift */,
|
||||
2A78BFB21D1B240900A583D2 /* UpdaterManager.swift */,
|
||||
@ -2891,7 +2891,6 @@
|
||||
2AD616CD1D3E583D0016EFB6 /* DocumentController.swift in Sources */,
|
||||
2A50AA63204D513500D10A10 /* DocumentFile.swift in Sources */,
|
||||
2AAB4BFA1D2435AC0049A68B /* DocumentInspectorViewController.swift in Sources */,
|
||||
2A91C31C1D1BFE47007CF8BE /* DocumentType.swift in Sources */,
|
||||
2AED70EF1D2E36EF006FFBCE /* DocumentViewController.swift in Sources */,
|
||||
2A71BC7C1DDC50530085AE1C /* DocumentViewController+TouchBar.swift in Sources */,
|
||||
2A17A3171D2D4319001DD717 /* DocumentWindow.swift in Sources */,
|
||||
@ -3111,6 +3110,7 @@
|
||||
2A1A4EAC24FB7BDE00B50AA0 /* UserDefaults+DefaultKey.swift in Sources */,
|
||||
2A222C3024FA8E0500251084 /* UserDefaults.Publisher.swift in Sources */,
|
||||
2AFD218A27E0434100E83E88 /* UTType.swift in Sources */,
|
||||
2A91C31C1D1BFE47007CF8BE /* UTType+SettingFile.swift in Sources */,
|
||||
2A78BFB11D1B168E00A583D2 /* WebDocumentViewController.swift in Sources */,
|
||||
2A17A3141D2D16F1001DD717 /* WindowContentViewController.swift in Sources */,
|
||||
2A78BFA51D1B02ED00A583D2 /* WindowPaneController.swift in Sources */,
|
||||
@ -3207,7 +3207,6 @@
|
||||
2AAB4BF91D2435AC0049A68B /* DocumentInspectorViewController.swift in Sources */,
|
||||
2AED70EE1D2E36EF006FFBCE /* DocumentViewController.swift in Sources */,
|
||||
2A71BC7B1DDC50530085AE1C /* DocumentViewController+TouchBar.swift in Sources */,
|
||||
2A91C31B1D1BFE47007CF8BE /* DocumentType.swift in Sources */,
|
||||
2A17A3161D2D4319001DD717 /* DocumentWindow.swift in Sources */,
|
||||
2AA749C31D3C263300850802 /* DocumentWindowController.swift in Sources */,
|
||||
2ACDC0911D1726BD009B72D6 /* DotView.swift in Sources */,
|
||||
@ -3426,6 +3425,7 @@
|
||||
2A1A4EAD24FB7BDE00B50AA0 /* UserDefaults+DefaultKey.swift in Sources */,
|
||||
2A222C3124FA8E0500251084 /* UserDefaults.Publisher.swift in Sources */,
|
||||
2AFD218B27E0434100E83E88 /* UTType.swift in Sources */,
|
||||
2A91C31B1D1BFE47007CF8BE /* UTType+SettingFile.swift in Sources */,
|
||||
2A78BFB01D1B168E00A583D2 /* WebDocumentViewController.swift in Sources */,
|
||||
2A17A3131D2D16F1001DD717 /* WindowContentViewController.swift in Sources */,
|
||||
2A78BFA41D1B02ED00A583D2 /* WindowPaneController.swift in Sources */,
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
import Combine
|
||||
import Cocoa
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
private extension NSSound {
|
||||
|
||||
@ -228,9 +229,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
let documentURLs = filenames.map { URL(fileURLWithPath: $0) }
|
||||
.filter {
|
||||
// ask installation if the file is CotEditor theme file
|
||||
DocumentType.theme.extensions.contains($0.pathExtension)
|
||||
? !self.askThemeInstallation(fileURL: $0)
|
||||
: true
|
||||
$0.conforms(to: .cotTheme) ? !self.askThemeInstallation(fileURL: $0) : true
|
||||
}
|
||||
|
||||
guard !documentURLs.isEmpty else { return NSApp.reply(toOpenOrPrint: .success) }
|
||||
@ -406,7 +405,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
/// - Returns: Whether the given file was handled as a theme file.
|
||||
private func askThemeInstallation(fileURL url: URL) -> Bool {
|
||||
|
||||
assert(DocumentType.theme.extensions.contains(url.pathExtension))
|
||||
assert(url.conforms(to: .cotTheme))
|
||||
|
||||
// ask whether theme file should be opened as a text file
|
||||
let alert = NSAlert()
|
||||
|
@ -27,6 +27,7 @@
|
||||
import Combine
|
||||
import Cocoa
|
||||
import AudioToolbox
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
final class AppearancePaneController: NSViewController, NSMenuItemValidation, NSTableViewDelegate, NSTableViewDataSource, NSTextFieldDelegate, NSMenuDelegate, ThemeViewControllerDelegate {
|
||||
|
||||
@ -239,7 +240,7 @@ final class AppearancePaneController: NSViewController, NSMenuItemValidation, NS
|
||||
let pboard = info.draggingPasteboard
|
||||
let objects = pboard.readObjects(forClasses: [NSURL.self],
|
||||
options: [.urlReadingFileURLsOnly: true,
|
||||
.urlReadingContentsConformToTypes: [DocumentType.theme.utType]])
|
||||
.urlReadingContentsConformToTypes: [UTType.cotTheme.identifier]])
|
||||
|
||||
guard let urls = objects, !urls.isEmpty else { return [] }
|
||||
|
||||
@ -258,7 +259,7 @@ final class AppearancePaneController: NSViewController, NSMenuItemValidation, NS
|
||||
|
||||
info.enumerateDraggingItems(for: tableView, classes: [NSURL.self],
|
||||
searchOptions: [.urlReadingFileURLsOnly: true,
|
||||
.urlReadingContentsConformToTypes: [DocumentType.theme.utType]])
|
||||
.urlReadingContentsConformToTypes: [UTType.cotTheme.identifier]])
|
||||
{ [unowned self] (draggingItem, _, _) in
|
||||
|
||||
guard let fileURL = draggingItem.item as? URL else { return }
|
||||
@ -486,7 +487,7 @@ final class AppearancePaneController: NSViewController, NSMenuItemValidation, NS
|
||||
savePanel.isExtensionHidden = true
|
||||
savePanel.nameFieldLabel = "Export As:".localized
|
||||
savePanel.nameFieldStringValue = settingName
|
||||
savePanel.allowedFileTypes = [ThemeManager.shared.filePathExtension]
|
||||
savePanel.allowedContentTypes = [ThemeManager.shared.fileType]
|
||||
|
||||
Task {
|
||||
guard await savePanel.beginSheetModal(for: self.view.window!) == .OK else { return }
|
||||
@ -508,7 +509,7 @@ final class AppearancePaneController: NSViewController, NSMenuItemValidation, NS
|
||||
openPanel.resolvesAliases = true
|
||||
openPanel.allowsMultipleSelection = true
|
||||
openPanel.canChooseDirectories = false
|
||||
openPanel.allowedFileTypes = [ThemeManager.shared.filePathExtension]
|
||||
openPanel.allowedContentTypes = [ThemeManager.shared.fileType]
|
||||
|
||||
Task {
|
||||
guard await openPanel.beginSheetModal(for: self.view.window!) == .OK else { return }
|
||||
|
@ -219,10 +219,9 @@ final class FormatPaneController: NSViewController, NSMenuItemValidation, NSTabl
|
||||
|
||||
// get file URLs from pasteboard
|
||||
let pboard = info.draggingPasteboard
|
||||
let urls = pboard.readObjects(forClasses: [NSURL.self],
|
||||
options: [.urlReadingFileURLsOnly: true])?
|
||||
let urls = pboard.readObjects(forClasses: [NSURL.self], options: [.urlReadingFileURLsOnly: true])?
|
||||
.compactMap { $0 as? URL }
|
||||
.filter { SyntaxManager.shared.filePathExtensions.contains($0.pathExtension) } ?? []
|
||||
.filter { $0.conforms(to: SyntaxManager.shared.fileType) } ?? []
|
||||
|
||||
guard !urls.isEmpty else { return [] }
|
||||
|
||||
@ -245,7 +244,7 @@ final class FormatPaneController: NSViewController, NSMenuItemValidation, NSTabl
|
||||
|
||||
guard
|
||||
let fileURL = draggingItem.item as? URL,
|
||||
SyntaxManager.shared.filePathExtensions.contains(fileURL.pathExtension)
|
||||
fileURL.conforms(to: SyntaxManager.shared.fileType)
|
||||
else { return }
|
||||
|
||||
self.importSyntaxStyle(fileURL: fileURL)
|
||||
@ -349,7 +348,7 @@ final class FormatPaneController: NSViewController, NSMenuItemValidation, NSTabl
|
||||
savePanel.isExtensionHidden = true
|
||||
savePanel.nameFieldLabel = "Export As:".localized
|
||||
savePanel.nameFieldStringValue = settingName
|
||||
savePanel.allowedFileTypes = [SyntaxManager.shared.filePathExtension]
|
||||
savePanel.allowedContentTypes = [SyntaxManager.shared.fileType]
|
||||
|
||||
Task {
|
||||
guard await savePanel.beginSheetModal(for: self.view.window!) == .OK else { return }
|
||||
@ -371,7 +370,7 @@ final class FormatPaneController: NSViewController, NSMenuItemValidation, NSTabl
|
||||
openPanel.resolvesAliases = true
|
||||
openPanel.allowsMultipleSelection = true
|
||||
openPanel.canChooseDirectories = false
|
||||
openPanel.allowedFileTypes = SyntaxManager.shared.filePathExtensions
|
||||
openPanel.allowedContentTypes = [SyntaxManager.shared.fileType]
|
||||
|
||||
Task {
|
||||
guard await openPanel.beginSheetModal(for: self.view.window!) == .OK else { return }
|
||||
|
@ -8,7 +8,7 @@
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// © 2017-2021 1024jp
|
||||
// © 2017-2022 1024jp
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -26,6 +26,7 @@
|
||||
import Combine
|
||||
import Cocoa
|
||||
import AudioToolbox
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
final class MultipleReplacementListViewController: NSViewController, NSMenuItemValidation, MultipleReplacementPanelViewControlling {
|
||||
|
||||
@ -201,7 +202,7 @@ final class MultipleReplacementListViewController: NSViewController, NSMenuItemV
|
||||
savePanel.isExtensionHidden = true
|
||||
savePanel.nameFieldLabel = "Export As:".localized
|
||||
savePanel.nameFieldStringValue = settingName
|
||||
savePanel.allowedFileTypes = ReplacementManager.shared.filePathExtensions
|
||||
savePanel.allowedContentTypes = [ReplacementManager.shared.fileType]
|
||||
|
||||
Task {
|
||||
guard await savePanel.beginSheetModal(for: self.view.window!) == .OK else { return }
|
||||
@ -223,7 +224,7 @@ final class MultipleReplacementListViewController: NSViewController, NSMenuItemV
|
||||
openPanel.resolvesAliases = true
|
||||
openPanel.allowsMultipleSelection = false
|
||||
openPanel.canChooseDirectories = false
|
||||
openPanel.allowedFileTypes = [ReplacementManager.shared.filePathExtension]
|
||||
openPanel.allowedContentTypes = [ReplacementManager.shared.fileType]
|
||||
|
||||
Task {
|
||||
guard await openPanel.beginSheetModal(for: self.view.window!) == .OK else { return }
|
||||
@ -409,7 +410,7 @@ extension MultipleReplacementListViewController: NSTableViewDataSource {
|
||||
let pboard = info.draggingPasteboard
|
||||
let objects = pboard.readObjects(forClasses: [NSURL.self],
|
||||
options: [.urlReadingFileURLsOnly: true,
|
||||
.urlReadingContentsConformToTypes: [DocumentType.replacement.utType]])
|
||||
.urlReadingContentsConformToTypes: [UTType.cotReplacement.identifier]])
|
||||
|
||||
guard let urls = objects, !urls.isEmpty else { return [] }
|
||||
|
||||
@ -428,7 +429,7 @@ extension MultipleReplacementListViewController: NSTableViewDataSource {
|
||||
|
||||
info.enumerateDraggingItems(for: tableView, classes: [NSURL.self],
|
||||
searchOptions: [.urlReadingFileURLsOnly: true,
|
||||
.urlReadingContentsConformToTypes: [DocumentType.replacement.utType]])
|
||||
.urlReadingContentsConformToTypes: [UTType.cotReplacement.identifier]])
|
||||
{ [weak self] (draggingItem, _, _) in
|
||||
|
||||
guard let fileURL = draggingItem.item as? URL else { return }
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
import Combine
|
||||
import Foundation
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
final class ReplacementManager: SettingFileManaging {
|
||||
|
||||
@ -41,8 +42,7 @@ final class ReplacementManager: SettingFileManaging {
|
||||
let didUpdateSetting: PassthroughSubject<SettingChange, Never> = .init()
|
||||
|
||||
static let directoryName: String = "Replacements"
|
||||
let filePathExtensions: [String] = DocumentType.replacement.extensions
|
||||
let settingFileType: SettingFileType = .replacement
|
||||
let fileType: UTType = .cotReplacement
|
||||
|
||||
@Published var settingNames: [String] = []
|
||||
let bundledSettingNames: [String] = []
|
||||
|
@ -8,7 +8,7 @@
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// © 2016-2020 1024jp
|
||||
// © 2016-2022 1024jp
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -26,6 +26,7 @@
|
||||
import Combine
|
||||
import Foundation
|
||||
import AppKit.NSApplication
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
enum SettingFileType {
|
||||
|
||||
@ -81,11 +82,8 @@ protocol SettingFileManaging: SettingManaging {
|
||||
/// directory name in both Application Support and bundled Resources
|
||||
static var directoryName: String { get }
|
||||
|
||||
/// path extensions for user setting file
|
||||
var filePathExtensions: [String] { get }
|
||||
|
||||
/// setting file type
|
||||
var settingFileType: SettingFileType { get }
|
||||
/// UTType of user setting file
|
||||
var fileType: UTType { get }
|
||||
|
||||
/// list of names of setting file name (without extension)
|
||||
var settingNames: [String] { get set }
|
||||
@ -133,20 +131,13 @@ extension SettingFileManaging {
|
||||
|
||||
// MARK: Public Methods
|
||||
|
||||
/// default path extension for user setting file
|
||||
var filePathExtension: String {
|
||||
|
||||
return self.filePathExtensions.first!
|
||||
}
|
||||
|
||||
|
||||
/// file urls for user settings
|
||||
var userSettingFileURLs: [URL] {
|
||||
|
||||
return (try? FileManager.default.contentsOfDirectory(at: self.userSettingDirectoryURL,
|
||||
includingPropertiesForKeys: nil,
|
||||
options: [.skipsSubdirectoryDescendants, .skipsHiddenFiles]))?
|
||||
.filter { self.filePathExtensions.contains($0.pathExtension) } ?? []
|
||||
.filter { $0.conforms(to: self.fileType) } ?? []
|
||||
}
|
||||
|
||||
|
||||
@ -167,7 +158,7 @@ extension SettingFileManaging {
|
||||
/// return a setting file URL in the application's Resources domain or nil if not exists
|
||||
func urlForBundledSetting(name: String) -> URL? {
|
||||
|
||||
return Bundle.main.url(forResource: name, withExtension: self.filePathExtension, subdirectory: Self.directoryName)
|
||||
return Bundle.main.url(forResource: name, withExtension: self.fileType.preferredFilenameExtension, subdirectory: Self.directoryName)
|
||||
}
|
||||
|
||||
|
||||
@ -183,7 +174,7 @@ extension SettingFileManaging {
|
||||
/// return a setting file URL in the user's Application Support domain (don't care if it exists)
|
||||
func preparedURLForUserSetting(name: String) -> URL {
|
||||
|
||||
return self.userSettingDirectoryURL.appendingPathComponent(name).appendingPathExtension(self.filePathExtension)
|
||||
return self.userSettingDirectoryURL.appendingPathComponent(name, conformingTo: self.fileType)
|
||||
}
|
||||
|
||||
|
||||
@ -364,7 +355,7 @@ extension SettingFileManaging {
|
||||
guard name.caseInsensitiveCompare(importName) == .orderedSame else { continue }
|
||||
|
||||
guard self.urlForUserSetting(name: name) == nil else { // duplicated
|
||||
throw ImportDuplicationError(name: name, type: self.settingFileType, replacingClosure: { [unowned self] in
|
||||
throw ImportDuplicationError(name: name, type: self.fileType, replacingClosure: { [unowned self] in
|
||||
try self.overwriteSetting(fileURL: fileURL)
|
||||
})
|
||||
}
|
||||
@ -523,19 +514,21 @@ struct SettingFileError: LocalizedError {
|
||||
struct ImportDuplicationError: LocalizedError, RecoverableError {
|
||||
|
||||
var name: String
|
||||
var type: SettingFileType
|
||||
var type: UTType
|
||||
var replacingClosure: (() throws -> Void)
|
||||
|
||||
|
||||
var errorDescription: String? {
|
||||
|
||||
switch self.type {
|
||||
case .syntaxStyle:
|
||||
case .yaml:
|
||||
return String(format: "A new style named “%@” will be installed, but a custom style with the same name already exists.".localized, self.name)
|
||||
case .theme:
|
||||
case .cotTheme:
|
||||
return String(format: "A new theme named “%@” will be installed, but a custom theme with the same name already exists.".localized, self.name)
|
||||
case .replacement:
|
||||
case .cotReplacement:
|
||||
return String(format: "A new replacement definition named “%@” will be installed, but a definition with the same name already exists.".localized, self.name)
|
||||
default:
|
||||
fatalError()
|
||||
}
|
||||
}
|
||||
|
||||
@ -543,12 +536,14 @@ struct ImportDuplicationError: LocalizedError, RecoverableError {
|
||||
var recoverySuggestion: String? {
|
||||
|
||||
switch self.type {
|
||||
case .syntaxStyle:
|
||||
case .yaml:
|
||||
return "Do you want to replace it?\nReplaced style can’t be restored.".localized
|
||||
case .theme:
|
||||
case .cotTheme:
|
||||
return "Do you want to replace it?\nReplaced theme can’t be restored.".localized
|
||||
case .replacement:
|
||||
case .cotReplacement:
|
||||
return "Do you want to replace it?\nReplaced definition can’t be restored.".localized
|
||||
default:
|
||||
fatalError()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
import Combine
|
||||
import Foundation
|
||||
import UniformTypeIdentifiers
|
||||
import Yams
|
||||
|
||||
@objc protocol SyntaxHolder: AnyObject {
|
||||
@ -64,8 +65,7 @@ final class SyntaxManager: SettingFileManaging {
|
||||
let didUpdateSetting: PassthroughSubject<SettingChange, Never> = .init()
|
||||
|
||||
static let directoryName: String = "Syntaxes"
|
||||
let filePathExtensions: [String] = ["yml", "yaml"]
|
||||
let settingFileType: SettingFileType = .syntaxStyle
|
||||
let fileType: UTType = .yaml
|
||||
|
||||
@Published var settingNames: [SettingName] = []
|
||||
let bundledSettingNames: [SettingName]
|
||||
|
@ -26,6 +26,7 @@
|
||||
import Combine
|
||||
import Foundation
|
||||
import AppKit
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
@objc protocol ThemeHolder: AnyObject {
|
||||
|
||||
@ -51,8 +52,7 @@ final class ThemeManager: SettingFileManaging {
|
||||
let didUpdateSetting: PassthroughSubject<SettingChange, Never> = .init()
|
||||
|
||||
static let directoryName: String = "Themes"
|
||||
let filePathExtensions: [String] = DocumentType.theme.extensions
|
||||
let settingFileType: SettingFileType = .theme
|
||||
let fileType: UTType = .cotTheme
|
||||
|
||||
@Published var settingNames: [String] = []
|
||||
private(set) var bundledSettingNames: [String] = []
|
||||
@ -66,7 +66,7 @@ final class ThemeManager: SettingFileManaging {
|
||||
private init() {
|
||||
|
||||
// cache bundled setting names
|
||||
self.bundledSettingNames = Bundle.main.urls(forResourcesWithExtension: self.filePathExtension, subdirectory: Self.directoryName)!
|
||||
self.bundledSettingNames = Bundle.main.urls(forResourcesWithExtension: self.fileType.preferredFilenameExtension, subdirectory: Self.directoryName)!
|
||||
.map { self.settingName(from: $0) }
|
||||
.sorted(options: [.localized, .caseInsensitive])
|
||||
|
||||
|
@ -1,14 +1,14 @@
|
||||
//
|
||||
// DocumentType.swift
|
||||
// UTType+SettingFile.swift
|
||||
//
|
||||
// CotEditor
|
||||
// https://coteditor.com
|
||||
//
|
||||
// Created by 1024jp on 2016-06-23.
|
||||
// Created by 1024jp on 2022-03-15.
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// © 2016-2020 1024jp
|
||||
// © 2022 1024jp
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -23,12 +23,10 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
struct DocumentType {
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
extension UTType {
|
||||
|
||||
var utType: String
|
||||
var extensions: [String]
|
||||
|
||||
|
||||
static let theme = Self(utType: "com.coteditor.CotEditor.theme", extensions: ["cottheme"])
|
||||
static let replacement = Self(utType: "com.coteditor.CotEditor.replacement", extensions: ["cotrpl"])
|
||||
static let cotTheme = UTType("com.coteditor.CotEditor.theme")!
|
||||
static let cotReplacement = UTType("com.coteditor.CotEditor.replacement")!
|
||||
}
|
@ -9,7 +9,7 @@
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// © 2016-2020 1024jp
|
||||
// © 2016-2022 1024jp
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -25,6 +25,7 @@
|
||||
//
|
||||
|
||||
import XCTest
|
||||
import UniformTypeIdentifiers
|
||||
@testable import CotEditor
|
||||
|
||||
final class ThemeTests: XCTestCase {
|
||||
@ -72,7 +73,7 @@ final class ThemeTests: XCTestCase {
|
||||
let enumerator = FileManager.default.enumerator(at: themeDirectoryURL, includingPropertiesForKeys: nil, options: [.skipsSubdirectoryDescendants, .skipsHiddenFiles])!
|
||||
|
||||
for case let url as URL in enumerator {
|
||||
guard DocumentType.theme.extensions.contains(url.pathExtension) else { continue }
|
||||
guard UTType.cotTheme.filenameExtensions.contains(url.pathExtension) else { continue }
|
||||
|
||||
_ = try Theme.theme(contentsOf: url)
|
||||
}
|
||||
@ -86,7 +87,7 @@ private extension ThemeTests {
|
||||
|
||||
func loadThemeWithName(_ name: String) throws -> Theme? {
|
||||
|
||||
let url = self.bundle.url(forResource: name, withExtension: DocumentType.theme.extensions[0], subdirectory: themeDirectoryName)
|
||||
let url = self.bundle.url(forResource: name, withExtension: UTType.cotTheme.preferredFilenameExtension, subdirectory: themeDirectoryName)
|
||||
|
||||
return try Theme.theme(contentsOf: url!)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user