diff --git a/CodeEdit.xcodeproj/project.pbxproj b/CodeEdit.xcodeproj/project.pbxproj index fda81b3782..d78da7221b 100644 --- a/CodeEdit.xcodeproj/project.pbxproj +++ b/CodeEdit.xcodeproj/project.pbxproj @@ -45,6 +45,7 @@ 283BDCBD2972EEBD002AFF81 /* Package.resolved in Resources */ = {isa = PBXBuildFile; fileRef = 283BDCBC2972EEBD002AFF81 /* Package.resolved */; }; 283BDCC52972F236002AFF81 /* AcknowledgementsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 283BDCC42972F236002AFF81 /* AcknowledgementsTests.swift */; }; 2847019E27FDDF7600F87B6B /* OutlineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2847019D27FDDF7600F87B6B /* OutlineView.swift */; }; + 284D384E29CF6CC500E37E86 /* String+Encoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 284D384D29CF6CC500E37E86 /* String+Encoding.swift */; }; 284DC84F2978B7B400BF2770 /* ContributorsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 284DC84E2978B7B400BF2770 /* ContributorsView.swift */; }; 284DC8512978BA2600BF2770 /* .all-contributorsrc in Resources */ = {isa = PBXBuildFile; fileRef = 284DC8502978BA2600BF2770 /* .all-contributorsrc */; }; 285FEC7027FE4B9800E57D53 /* OutlineTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 285FEC6F27FE4B9800E57D53 /* OutlineTableViewCell.swift */; }; @@ -450,6 +451,7 @@ 283BDCBC2972EEBD002AFF81 /* Package.resolved */ = {isa = PBXFileReference; lastKnownFileType = text; name = Package.resolved; path = CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved; sourceTree = ""; }; 283BDCC42972F236002AFF81 /* AcknowledgementsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AcknowledgementsTests.swift; sourceTree = ""; }; 2847019D27FDDF7600F87B6B /* OutlineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OutlineView.swift; sourceTree = ""; }; + 284D384D29CF6CC500E37E86 /* String+Encoding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Encoding.swift"; sourceTree = ""; }; 284DC84E2978B7B400BF2770 /* ContributorsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContributorsView.swift; sourceTree = ""; }; 284DC8502978BA2600BF2770 /* .all-contributorsrc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ".all-contributorsrc"; sourceTree = ""; }; 285FEC6D27FE4B4A00E57D53 /* OutlineViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OutlineViewController.swift; sourceTree = ""; }; @@ -1851,6 +1853,7 @@ isa = PBXGroup; children = ( 58D01C8E293167DC00C5B6B4 /* String+MD5.swift */, + 284D384D29CF6CC500E37E86 /* String+Encoding.swift */, D7E201AD27E8B3C000CB86D0 /* String+Ranges.swift */, 58D01C8D293167DC00C5B6B4 /* String+RemoveOccurrences.swift */, 58D01C8C293167DC00C5B6B4 /* String+SHA256.swift */, @@ -2549,6 +2552,7 @@ 587B9DA029300ABD00AC7927 /* PanelDivider.swift in Sources */, 58822534292C280D00E83CDE /* CursorLocation.swift in Sources */, 201169E52837B40300F92B46 /* SourceControlNavigatorRepositoriesView.swift in Sources */, + 284D384E29CF6CC500E37E86 /* String+Encoding.swift in Sources */, 587B9E6A29301D8F00AC7927 /* GitLabPermissions.swift in Sources */, B6EA1FF529DA380E001BF195 /* TextEditingSettingsView.swift in Sources */, D7DC4B76298FFBE900D6C83D /* OutlintViewController+OutlineTableViewCellDelegate.swift in Sources */, diff --git a/CodeEdit/Features/CodeFile/CodeFile.swift b/CodeEdit/Features/CodeFile/CodeFile.swift index 7a8d18c58e..552dd09e8e 100644 --- a/CodeEdit/Features/CodeFile/CodeFile.swift +++ b/CodeEdit/Features/CodeFile/CodeFile.swift @@ -23,6 +23,8 @@ final class CodeFileDocument: NSDocument, ObservableObject, QLPreviewItem { @Published var content = "" + @AppSettings(\.textEditing.defaultTextEncoding) var defaultTextEncoding + /* This is the main type of the document. For example, if the file is end with '.png', it will be an image, @@ -96,7 +98,10 @@ final class CodeFileDocument: NSDocument, ObservableObject, QLPreviewItem { /// This function is used for decoding files. /// It should not throw error as unsupported files can still be opened by QLPreviewView. override func read(from data: Data, ofType _: String) throws { - guard let content = String(data: data, encoding: .utf8) else { return } + guard let content = String( + data: data, + encoding: defaultTextEncoding + ) else { return } self.content = content } } diff --git a/CodeEdit/Features/Settings/Pages/TextEditingSettings/Models/TextEditingSettings.swift b/CodeEdit/Features/Settings/Pages/TextEditingSettings/Models/TextEditingSettings.swift index e9bbe63e0b..a80df0d172 100644 --- a/CodeEdit/Features/Settings/Pages/TextEditingSettings/Models/TextEditingSettings.swift +++ b/CodeEdit/Features/Settings/Pages/TextEditingSettings/Models/TextEditingSettings.swift @@ -30,6 +30,9 @@ extension SettingsData { /// A multiplier for setting the line height. Defaults to `1.45` var lineHeightMultiple: Double = 1.45 + /// The default text encoding used, defaults to `.utf8` + var defaultTextEncoding: String.Encoding = .utf8 + /// Default initializer init() { self.populateCommands() diff --git a/CodeEdit/Features/Settings/Pages/TextEditingSettings/TextEditingSettingsView.swift b/CodeEdit/Features/Settings/Pages/TextEditingSettings/TextEditingSettingsView.swift index 4ed39e592d..2e7e2a5b5b 100644 --- a/CodeEdit/Features/Settings/Pages/TextEditingSettings/TextEditingSettingsView.swift +++ b/CodeEdit/Features/Settings/Pages/TextEditingSettings/TextEditingSettingsView.swift @@ -25,6 +25,7 @@ struct TextEditingSettingsView: View { Section { autocompleteBraces enableTypeOverCompletion + textEncoding } } } @@ -90,4 +91,15 @@ private extension TextEditingSettingsView { .foregroundColor(.secondary) } } + + private var textEncoding: some View { + Picker("Default Text Encoding", selection: $textEditing.defaultTextEncoding) { + ForEach(String.Encoding.allGroups, id: \.self) { group in + ForEach(group, id: \.rawValue) { encoding in + Text(encoding.description) + .tag(encoding) + } + } + } + } } diff --git a/CodeEdit/Utils/Extensions/String/String+Encoding.swift b/CodeEdit/Utils/Extensions/String/String+Encoding.swift new file mode 100644 index 0000000000..79b029770d --- /dev/null +++ b/CodeEdit/Utils/Extensions/String/String+Encoding.swift @@ -0,0 +1,73 @@ +// +// String+Encoding.swift +// CodeEdit +// +// Created by Lukas Pistrol on 25.03.23. +// + +import Foundation + +extension String.Encoding: Codable { + static var allGroups: [[String.Encoding]] { + [ + Self.allUnicodes, + Self.allAscii, + Self.allLatin, + Self.allJapanese, + Self.allWindows, + Self.others + ] + } + + static var allAscii: [String.Encoding] { + [ + .ascii, + .nonLossyASCII + ] + } + + static var allJapanese: [String.Encoding] { + [ + .iso2022JP, + .japaneseEUC + ] + } + + static var allLatin: [String.Encoding] { + [ + .isoLatin1, + .isoLatin2, + .macOSRoman + ] + } + + static var allUnicodes: [String.Encoding] { + [ + .utf8, + .utf16, + .utf16BigEndian, + .utf16LittleEndian, + .utf32, + .utf32BigEndian, + .utf32LittleEndian + ] + } + + static var allWindows: [String.Encoding] { + [ + .windowsCP1250, + .windowsCP1251, + .windowsCP1252, + .windowsCP1253, + .windowsCP1254 + ] + } + + static var others: [String.Encoding] { + [ + .nextstep, + .shiftJIS, + .symbol + ] + } +}