diff --git a/CodeEdit.xcodeproj/project.pbxproj b/CodeEdit.xcodeproj/project.pbxproj index a94c6245a..481b553e0 100644 --- a/CodeEdit.xcodeproj/project.pbxproj +++ b/CodeEdit.xcodeproj/project.pbxproj @@ -24,19 +24,11 @@ 201169E52837B40300F92B46 /* SourceControlNavigatorRepositoriesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 201169E42837B40300F92B46 /* SourceControlNavigatorRepositoriesView.swift */; }; 201169E72837B5CA00F92B46 /* SourceControlModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 201169E62837B5CA00F92B46 /* SourceControlModel.swift */; }; 2072FA13280D74ED00C7F8D4 /* HistoryInspectorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2072FA12280D74ED00C7F8D4 /* HistoryInspectorModel.swift */; }; - 2072FA16280D83A500C7F8D4 /* FileTypeList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2072FA15280D83A500C7F8D4 /* FileTypeList.swift */; }; - 2072FA18280D871200C7F8D4 /* TextEncoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2072FA17280D871200C7F8D4 /* TextEncoding.swift */; }; - 2072FA1A280D872600C7F8D4 /* LineEndings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2072FA19280D872600C7F8D4 /* LineEndings.swift */; }; - 2072FA1C280D874000C7F8D4 /* IndentUsing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2072FA1B280D874000C7F8D4 /* IndentUsing.swift */; }; - 2072FA1E280D891500C7F8D4 /* FileLocation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2072FA1D280D891500C7F8D4 /* FileLocation.swift */; }; 20D839AB280DEB2900B27357 /* NoSelectionInspectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20D839AA280DEB2900B27357 /* NoSelectionInspectorView.swift */; }; 20D839AE280E0CA700B27357 /* HistoryPopoverView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20D839AD280E0CA700B27357 /* HistoryPopoverView.swift */; }; 20EBB501280C325D00F3A5DA /* FileInspectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20EBB500280C325D00F3A5DA /* FileInspectorView.swift */; }; 20EBB503280C327C00F3A5DA /* HistoryInspectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20EBB502280C327C00F3A5DA /* HistoryInspectorView.swift */; }; 20EBB505280C329800F3A5DA /* HistoryInspectorItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20EBB504280C329800F3A5DA /* HistoryInspectorItemView.swift */; }; - 20EBB507280C32D300F3A5DA /* QuickHelpInspectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20EBB506280C32D300F3A5DA /* QuickHelpInspectorView.swift */; }; - 20EBB50D280C383700F3A5DA /* LanguageType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20EBB50C280C383700F3A5DA /* LanguageType.swift */; }; - 20EBB50F280C389300F3A5DA /* FileInspectorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20EBB50E280C389300F3A5DA /* FileInspectorModel.swift */; }; 2806E9022979588B000040F4 /* Contributor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2806E9012979588B000040F4 /* Contributor.swift */; }; 2806E904297958B9000040F4 /* ContributorRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2806E903297958B9000040F4 /* ContributorRowView.swift */; }; 2813F93827ECC4AA00E305E4 /* FindNavigatorResultList.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7E201B327E9989900CB86D0 /* FindNavigatorResultList.swift */; }; @@ -269,6 +261,7 @@ 6C2C155A29B4F4CC00EA60A5 /* Variadic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C2C155929B4F4CC00EA60A5 /* Variadic.swift */; }; 6C2C155D29B4F4E500EA60A5 /* SplitViewReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C2C155C29B4F4E500EA60A5 /* SplitViewReader.swift */; }; 6C2C156129B4F52F00EA60A5 /* SplitViewModifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C2C156029B4F52F00EA60A5 /* SplitViewModifiers.swift */; }; + 6C2C20172A4016FF0047EDF2 /* (null) in Frameworks */ = {isa = PBXBuildFile; }; 6C4104E3297C87A000F472BA /* BlurButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C4104E2297C87A000F472BA /* BlurButtonStyle.swift */; }; 6C4104E6297C884F00F472BA /* AboutDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C4104E5297C884F00F472BA /* AboutDetailView.swift */; }; 6C4104E9297C970F00F472BA /* AboutDefaultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C4104E8297C970F00F472BA /* AboutDefaultView.swift */; }; @@ -318,15 +311,16 @@ 6CB9144B29BEC7F100BC47F2 /* (null) in Sources */ = {isa = PBXBuildFile; }; 6CBA0D512A1BF524002C6FAA /* SegmentedControlImproved.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CBA0D502A1BF524002C6FAA /* SegmentedControlImproved.swift */; }; 6CBD1BC62978DE53006639D5 /* Font+Caption3.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CBD1BC52978DE53006639D5 /* Font+Caption3.swift */; }; - 6CC81CEC2A16BB8F00487975 /* CodeEditTextView in Frameworks */ = {isa = PBXBuildFile; productRef = 6CC81CEB2A16BB8F00487975 /* CodeEditTextView */; }; 6CC9E4B229B5669900C97388 /* Environment+ActiveTabGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC9E4B129B5669900C97388 /* Environment+ActiveTabGroup.swift */; }; 6CD0375F2A3504540071C4DA /* FuzzySearch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD0375E2A3504540071C4DA /* FuzzySearch.swift */; }; 6CD03B6A29FC773F001BD1D0 /* SettingsInjector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD03B6929FC773F001BD1D0 /* SettingsInjector.swift */; }; + 6CD601B52A420E0900E8C324 /* CodeEditTextView in Frameworks */ = {isa = PBXBuildFile; productRef = 6CD601B42A420E0900E8C324 /* CodeEditTextView */; }; 6CDA84AD284C1BA000C1CC3A /* TabBarContextMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CDA84AC284C1BA000C1CC3A /* TabBarContextMenu.swift */; }; 6CDEFC9629E22C2700B7C684 /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = 6CDEFC9529E22C2700B7C684 /* Introspect */; }; 6CE622692A2A174A0013085C /* InspectorTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CE622682A2A174A0013085C /* InspectorTab.swift */; }; 6CE6226B2A2A1C730013085C /* DebugAreaTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CE6226A2A2A1C730013085C /* DebugAreaTab.swift */; }; 6CE6226E2A2A1CDE0013085C /* NavigatorTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CE6226D2A2A1CDE0013085C /* NavigatorTab.swift */; }; + 6CED16E42A3E660D000EC962 /* String+Lines.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CED16E32A3E660D000EC962 /* String+Lines.swift */; }; 6CFF967429BEBCC300182D6F /* FindCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CFF967329BEBCC300182D6F /* FindCommands.swift */; }; 6CFF967629BEBCD900182D6F /* FileCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CFF967529BEBCD900182D6F /* FileCommands.swift */; }; 6CFF967829BEBCF600182D6F /* MainCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CFF967729BEBCF600182D6F /* MainCommands.swift */; }; @@ -481,19 +475,11 @@ 201169E42837B40300F92B46 /* SourceControlNavigatorRepositoriesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceControlNavigatorRepositoriesView.swift; sourceTree = "<group>"; }; 201169E62837B5CA00F92B46 /* SourceControlModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceControlModel.swift; sourceTree = "<group>"; }; 2072FA12280D74ED00C7F8D4 /* HistoryInspectorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryInspectorModel.swift; sourceTree = "<group>"; }; - 2072FA15280D83A500C7F8D4 /* FileTypeList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileTypeList.swift; sourceTree = "<group>"; }; - 2072FA17280D871200C7F8D4 /* TextEncoding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextEncoding.swift; sourceTree = "<group>"; }; - 2072FA19280D872600C7F8D4 /* LineEndings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineEndings.swift; sourceTree = "<group>"; }; - 2072FA1B280D874000C7F8D4 /* IndentUsing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IndentUsing.swift; sourceTree = "<group>"; }; - 2072FA1D280D891500C7F8D4 /* FileLocation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileLocation.swift; sourceTree = "<group>"; }; 20D839AA280DEB2900B27357 /* NoSelectionInspectorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoSelectionInspectorView.swift; sourceTree = "<group>"; }; 20D839AD280E0CA700B27357 /* HistoryPopoverView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryPopoverView.swift; sourceTree = "<group>"; }; 20EBB500280C325D00F3A5DA /* FileInspectorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileInspectorView.swift; sourceTree = "<group>"; }; 20EBB502280C327C00F3A5DA /* HistoryInspectorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryInspectorView.swift; sourceTree = "<group>"; }; 20EBB504280C329800F3A5DA /* HistoryInspectorItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryInspectorItemView.swift; sourceTree = "<group>"; }; - 20EBB506280C32D300F3A5DA /* QuickHelpInspectorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickHelpInspectorView.swift; sourceTree = "<group>"; }; - 20EBB50C280C383700F3A5DA /* LanguageType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LanguageType.swift; sourceTree = "<group>"; }; - 20EBB50E280C389300F3A5DA /* FileInspectorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileInspectorModel.swift; sourceTree = "<group>"; }; 28052DFB29730DE300F4F90A /* Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; }; 28052DFC29730DF600F4F90A /* Alpha.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Alpha.xcconfig; sourceTree = "<group>"; }; 28052DFD29730E0300F4F90A /* Beta.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Beta.xcconfig; sourceTree = "<group>"; }; @@ -774,6 +760,7 @@ 6CE622682A2A174A0013085C /* InspectorTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InspectorTab.swift; sourceTree = "<group>"; }; 6CE6226A2A2A1C730013085C /* DebugAreaTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugAreaTab.swift; sourceTree = "<group>"; }; 6CE6226D2A2A1CDE0013085C /* NavigatorTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigatorTab.swift; sourceTree = "<group>"; }; + 6CED16E32A3E660D000EC962 /* String+Lines.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Lines.swift"; sourceTree = "<group>"; }; 6CFF967329BEBCC300182D6F /* FindCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FindCommands.swift; sourceTree = "<group>"; }; 6CFF967529BEBCD900182D6F /* FileCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileCommands.swift; sourceTree = "<group>"; }; 6CFF967729BEBCF600182D6F /* MainCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainCommands.swift; sourceTree = "<group>"; }; @@ -872,15 +859,16 @@ 6C0F3A3C2A1D0D5000223D19 /* CodeEditKit in Frameworks */, 6C5BE5222A3D5666002DA0FC /* WindowManagement in Frameworks */, 6C66C31329D05CDC00DE9ED2 /* GRDB in Frameworks */, + 6CD601B52A420E0900E8C324 /* CodeEditTextView in Frameworks */, 58F2EB1E292FB954004A9BDE /* Sparkle in Frameworks */, 6C2149412A1BB9AB00748382 /* LogStream in Frameworks */, - 6CC81CEC2A16BB8F00487975 /* CodeEditTextView in Frameworks */, 6C147C4529A329350089B630 /* OrderedCollections in Frameworks */, 6C6BD6F429CD142C00235D17 /* CollectionConcurrencyKit in Frameworks */, 5879828A292ED15F0085B254 /* SwiftTerm in Frameworks */, 6CDEFC9629E22C2700B7C684 /* Introspect in Frameworks */, 2816F594280CF50500DD548B /* CodeEditSymbols in Frameworks */, 6C6BD6F829CD14D100235D17 /* CodeEditKit in Frameworks */, + 6C2C20172A4016FF0047EDF2 /* (null) in Frameworks */, 6C81916B29B41DD300B75C92 /* DequeModule in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -961,14 +949,6 @@ path = Repositories; sourceTree = "<group>"; }; - 2072FA14280D838800C7F8D4 /* Lists */ = { - isa = PBXGroup; - children = ( - 2072FA15280D83A500C7F8D4 /* FileTypeList.swift */, - ); - path = Lists; - sourceTree = "<group>"; - }; 20D839AC280E0C9400B27357 /* Popover */ = { isa = PBXGroup; children = ( @@ -985,7 +965,6 @@ 20EBB502280C327C00F3A5DA /* HistoryInspectorView.swift */, 20EBB504280C329800F3A5DA /* HistoryInspectorItemView.swift */, 200412EE280F3EAC00BCAF5C /* HistoryInspectorNoHistoryView.swift */, - 20EBB506280C32D300F3A5DA /* QuickHelpInspectorView.swift */, 20D839AA280DEB2900B27357 /* NoSelectionInspectorView.swift */, ); path = Views; @@ -994,14 +973,7 @@ 20EBB50B280C382800F3A5DA /* Models */ = { isa = PBXGroup; children = ( - 2072FA14280D838800C7F8D4 /* Lists */, - 20EBB50C280C383700F3A5DA /* LanguageType.swift */, - 20EBB50E280C389300F3A5DA /* FileInspectorModel.swift */, 2072FA12280D74ED00C7F8D4 /* HistoryInspectorModel.swift */, - 2072FA17280D871200C7F8D4 /* TextEncoding.swift */, - 2072FA19280D872600C7F8D4 /* LineEndings.swift */, - 2072FA1B280D874000C7F8D4 /* IndentUsing.swift */, - 2072FA1D280D891500C7F8D4 /* FileLocation.swift */, ); path = Models; sourceTree = "<group>"; @@ -1976,6 +1948,7 @@ children = ( 58D01C8E293167DC00C5B6B4 /* String+MD5.swift */, D7E201AD27E8B3C000CB86D0 /* String+Ranges.swift */, + 6CED16E32A3E660D000EC962 /* String+Lines.swift */, 58D01C8D293167DC00C5B6B4 /* String+RemoveOccurrences.swift */, 58D01C8C293167DC00C5B6B4 /* String+SHA256.swift */, ); @@ -2504,9 +2477,9 @@ 6C66C31229D05CDC00DE9ED2 /* GRDB */, 6C2149402A1BB9AB00748382 /* LogStream */, 6CDEFC9529E22C2700B7C684 /* Introspect */, - 6CC81CEB2A16BB8F00487975 /* CodeEditTextView */, 6C0F3A3B2A1D0D5000223D19 /* CodeEditKit */, 6C5BE5212A3D5666002DA0FC /* WindowManagement */, + 6CD601B42A420E0900E8C324 /* CodeEditTextView */, ); productName = CodeEdit; productReference = B658FB2C27DA9E0F00EA4DBD /* CodeEdit.app */; @@ -2600,9 +2573,9 @@ 6C66C31129D05CC800DE9ED2 /* XCRemoteSwiftPackageReference "GRDB.swift" */, 6C21493F2A1BB9AB00748382 /* XCRemoteSwiftPackageReference "LogStream" */, 6CDEFC9429E22C2700B7C684 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */, - 6CC81CEA2A16BB8F00487975 /* XCRemoteSwiftPackageReference "CodeEditTextView" */, 6C0F3A3A2A1D0D5000223D19 /* XCRemoteSwiftPackageReference "CodeEditKit" */, 6C5BE5202A3D5666002DA0FC /* XCRemoteSwiftPackageReference "SwiftUI-WindowManagement" */, + 6CD601B32A420E0900E8C324 /* XCRemoteSwiftPackageReference "CodeEditTextView" */, ); productRefGroup = B658FB2D27DA9E0F00EA4DBD /* Products */; projectDirPath = ""; @@ -2752,7 +2725,6 @@ 6C82D6C629C012AD00495C54 /* NSApp+openWindow.swift in Sources */, 6C14CEB028777D3C001468FE /* FindNavigatorListViewController.swift in Sources */, 587B9E7F29301D8F00AC7927 /* GitHubUserRouter.swift in Sources */, - 20EBB50D280C383700F3A5DA /* LanguageType.swift in Sources */, B62AEDBC2A210DBB009A9F52 /* DebugAreaTerminalTab.swift in Sources */, B61A606129F188AB009B43F9 /* ExternalLink.swift in Sources */, 587B9E9729301D8F00AC7927 /* BitBucketAccount+Token.swift in Sources */, @@ -2789,6 +2761,7 @@ D7E201AE27E8B3C000CB86D0 /* String+Ranges.swift in Sources */, 6CE6226E2A2A1CDE0013085C /* NavigatorTab.swift in Sources */, 6C48D8F72972E5F300D6D205 /* WindowObserver.swift in Sources */, + 6CED16E42A3E660D000EC962 /* String+Lines.swift in Sources */, 587B9E6B29301D8F00AC7927 /* GitLabAvatarURL.swift in Sources */, 58798233292E30B90085B254 /* FeedbackToolbar.swift in Sources */, 587B9E6829301D8F00AC7927 /* GitLabAccountModel.swift in Sources */, @@ -2799,7 +2772,6 @@ 6C82D6BC29C00CD900495C54 /* FirstResponderPropertyWrapper.swift in Sources */, 58D01C9B293167DC00C5B6B4 /* CodeEditKeychainConstants.swift in Sources */, B640A99E29E2184700715F20 /* SettingsForm.swift in Sources */, - 20EBB50F280C389300F3A5DA /* FileInspectorModel.swift in Sources */, B62AEDD12A27B264009A9F52 /* View+paneToolbar.swift in Sources */, 5878DAB1291D627C00DD95A3 /* PathBarComponent.swift in Sources */, 587B9E6E29301D8F00AC7927 /* GitLabProject.swift in Sources */, @@ -2816,7 +2788,6 @@ 587B9E9429301D8F00AC7927 /* BitBucketTokenConfiguration.swift in Sources */, 581BFB672926431000D251EC /* WelcomeWindowView.swift in Sources */, 58A5DFA329339F6400D1BD5D /* CommandManager.swift in Sources */, - 2072FA1C280D874000C7F8D4 /* IndentUsing.swift in Sources */, 58798284292ED0FB0085B254 /* TerminalEmulatorView.swift in Sources */, 6C82D6B329BFD88700495C54 /* NavigateCommands.swift in Sources */, B66A4E4C29C9179B004573B4 /* CodeEditApp.swift in Sources */, @@ -2869,12 +2840,10 @@ 587B9E8729301D8F00AC7927 /* GitHubRepositories.swift in Sources */, 6CE6226B2A2A1C730013085C /* DebugAreaTab.swift in Sources */, 587B9DA329300ABD00AC7927 /* SettingsTextEditor.swift in Sources */, - 2072FA1A280D872600C7F8D4 /* LineEndings.swift in Sources */, B6F0517B29D9E46400D72287 /* SourceControlSettingsView.swift in Sources */, 6C147C4D29A32AA30089B630 /* WorkspaceTabGroupView.swift in Sources */, 587B9E7B29301D8F00AC7927 /* GitHubRouter.swift in Sources */, 201169E22837B3D800F92B46 /* SourceControlNavigatorChangesView.swift in Sources */, - 20EBB507280C32D300F3A5DA /* QuickHelpInspectorView.swift in Sources */, 850C631029D6B01D00E1444C /* SettingsView.swift in Sources */, DE6405A62817734700881FDF /* TabBarNative.swift in Sources */, 581550CF29FBD30400684881 /* StandardTableViewCell.swift in Sources */, @@ -2897,7 +2866,6 @@ 20D839AE280E0CA700B27357 /* HistoryPopoverView.swift in Sources */, B6E41C7029DD157F0088F9F4 /* AccountsSettingsView.swift in Sources */, 6CFF967A29BEBD2400182D6F /* ViewCommands.swift in Sources */, - 2072FA1E280D891500C7F8D4 /* FileLocation.swift in Sources */, 850C631229D6B03400E1444C /* SettingsPage.swift in Sources */, 587B9E6729301D8F00AC7927 /* GitLabEventData.swift in Sources */, B66A4E4529C8E86D004573B4 /* CommandsFixes.swift in Sources */, @@ -2996,7 +2964,6 @@ B68C7C212A01DEFE004EA6D6 /* GitHubComment.swift in Sources */, 6C48D8F42972DB1A00D6D205 /* Env+Window.swift in Sources */, 6C5FDF7A29E6160000BC08C0 /* AppSettings.swift in Sources */, - 2072FA18280D871200C7F8D4 /* TextEncoding.swift in Sources */, 58F2EB07292FB2B0004A9BDE /* GeneralSettings.swift in Sources */, B6041F4D29D7A4E9000F3454 /* SettingsPageView.swift in Sources */, 587B9E9A29301D8F00AC7927 /* GitType.swift in Sources */, @@ -3007,7 +2974,6 @@ B6041F5229D7D6D6000F3454 /* SettingsWindow.swift in Sources */, B6EA1FF829DB78DB001BF195 /* ThemeSettingThemeRow.swift in Sources */, 587B9E7629301D8F00AC7927 /* GitTime.swift in Sources */, - 2072FA16280D83A500C7F8D4 /* FileTypeList.swift in Sources */, 587B9E5D29301D8F00AC7927 /* GitLabUserRouter.swift in Sources */, 588847692992ABCA00996D95 /* Array+CEWorkspaceFile.swift in Sources */, 58822530292C280D00E83CDE /* FilterTextField.swift in Sources */, @@ -3203,6 +3169,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = CodeEdit/CodeEdit.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; DEAD_CODE_STRIPPING = YES; @@ -3292,7 +3259,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = OpenWithCodeEdit/OpenWithCodeEdit.entitlements; CODE_SIGN_IDENTITY = "-"; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 35; @@ -3391,6 +3358,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = CodeEdit/CodeEdit.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; DEAD_CODE_STRIPPING = YES; @@ -3480,7 +3448,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = OpenWithCodeEdit/OpenWithCodeEdit.entitlements; CODE_SIGN_IDENTITY = "-"; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 35; @@ -3546,7 +3514,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = OpenWithCodeEdit/OpenWithCodeEdit.entitlements; CODE_SIGN_IDENTITY = "-"; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 35; @@ -3750,6 +3718,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = CodeEdit/CodeEdit.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; DEAD_CODE_STRIPPING = YES; @@ -4038,12 +4007,12 @@ minimumVersion = 0.2.0; }; }; - 6CC81CEA2A16BB8F00487975 /* XCRemoteSwiftPackageReference "CodeEditTextView" */ = { + 6CD601B32A420E0900E8C324 /* XCRemoteSwiftPackageReference "CodeEditTextView" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/CodeEditApp/CodeEditTextView"; requirement = { - kind = exactVersion; - version = 0.6.4; + kind = upToNextMajorVersion; + minimumVersion = 0.6.6; }; }; 6CDEFC9429E22C2700B7C684 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */ = { @@ -4121,9 +4090,9 @@ package = 6C147C4329A329350089B630 /* XCRemoteSwiftPackageReference "swift-collections" */; productName = DequeModule; }; - 6CC81CEB2A16BB8F00487975 /* CodeEditTextView */ = { + 6CD601B42A420E0900E8C324 /* CodeEditTextView */ = { isa = XCSwiftPackageProductDependency; - package = 6CC81CEA2A16BB8F00487975 /* XCRemoteSwiftPackageReference "CodeEditTextView" */; + package = 6CD601B32A420E0900E8C324 /* XCRemoteSwiftPackageReference "CodeEditTextView" */; productName = CodeEditTextView; }; 6CDEFC9529E22C2700B7C684 /* Introspect */ = { diff --git a/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 39b4b71b3..1cb61ef03 100644 --- a/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -23,8 +23,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/CodeEditApp/CodeEditLanguages.git", "state" : { - "revision" : "02bdf65b5536e1968c69e93ebb1c2413c7a13570", - "version" : "0.1.15" + "revision" : "aa7d922b2aa783ae6f2a1a2cb7010ae62b700e17", + "version" : "0.1.16" } }, { @@ -41,8 +41,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/CodeEditApp/CodeEditTextView", "state" : { - "revision" : "8150e91dd81c698fde068e7cdf06a6f43d7ddd17", - "version" : "0.6.4" + "revision" : "cc28ae52c8083c313b650784706e339b727646d9", + "version" : "0.6.6" } }, { @@ -95,8 +95,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/ChimeHQ/JSONRPC", "state" : { - "revision" : "afc20d00e38674774f84edc325424a32ae3b9e01", - "version" : "0.7.0" + "revision" : "aa785ad404bdcf7ec692908b3905dd4c87e87141", + "version" : "0.7.1" } }, { @@ -113,8 +113,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/ChimeHQ/LanguageServerProtocol", "state" : { - "revision" : "192bcfdcf7a013da49c6fa1b95de66254ce7c614", - "version" : "0.9.1" + "revision" : "cae01173f45b0518ae5533b083edd153633af984", + "version" : "0.9.2" } }, { diff --git a/CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFile.swift b/CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFile.swift index 39789637a..7edea75f8 100644 --- a/CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFile.swift +++ b/CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFile.swift @@ -171,6 +171,34 @@ final class CEWorkspaceFile: Codable, Comparable, Hashable, Identifiable, TabBar typeHidden ? url.deletingPathExtension().lastPathComponent : name } + /// Generates a string based on user's file name preferences. + /// - Returns: A `String` suitable for display. + func labelFileName() -> String { + let prefs = Settings.shared.preferences.general + switch prefs.fileExtensionsVisibility { + case .hideAll: + return self.fileName(typeHidden: true) + case .showAll: + return self.fileName(typeHidden: false) + case .showOnly: + return self.fileName(typeHidden: !prefs.shownFileExtensions.extensions.contains(self.type.rawValue)) + case .hideOnly: + return self.fileName(typeHidden: prefs.hiddenFileExtensions.extensions.contains(self.type.rawValue)) + } + } + + func validateFileName(for newName: String) -> Bool { + guard newName != labelFileName() else { return true } + + guard !newName.isEmpty && newName.isValidFilename && + !FileManager.default.fileExists( + atPath: self.url.deletingLastPathComponent().appendingPathComponent(newName).path + ) + else { return false } + + return true + } + // MARK: Statics /// The default `FileManager` instance static let fileManger = FileManager.default diff --git a/CodeEdit/Features/CodeFile/CodeFile.swift b/CodeEdit/Features/CodeFile/CodeFile.swift index 7a8d18c58..36827c3dc 100644 --- a/CodeEdit/Features/CodeFile/CodeFile.swift +++ b/CodeEdit/Features/CodeFile/CodeFile.swift @@ -10,6 +10,8 @@ import Foundation import SwiftUI import UniformTypeIdentifiers import QuickLookUI +import CodeEditTextView +import CodeEditLanguages enum CodeFileError: Error { case failedToDecode @@ -23,6 +25,22 @@ final class CodeFileDocument: NSDocument, ObservableObject, QLPreviewItem { @Published var content = "" + /// Used to override detected languages. + @Published + var language: CodeLanguage? + + /// Document-specific overriden indent option. + @Published + var indentOption: SettingsData.TextEditingSettings.IndentOption? + + /// Document-specific overriden tab width. + @Published + var defaultTabWidth: Int? + + /// Document-specific overriden line wrap preference. + @Published + var wrapLines: Bool? + /* This is the main type of the document. For example, if the file is end with '.png', it will be an image, diff --git a/CodeEdit/Features/CodeFile/CodeFileView.swift b/CodeEdit/Features/CodeFile/CodeFileView.swift index c25bd9d75..7e6a9ea83 100644 --- a/CodeEdit/Features/CodeFile/CodeFileView.swift +++ b/CodeEdit/Features/CodeFile/CodeFileView.swift @@ -17,7 +17,7 @@ struct CodeFileView: View { private var codeFile: CodeFileDocument @AppSettings(\.textEditing.defaultTabWidth) var defaultTabWidth - @AppSettings(\.textEditing.indentOption) var settingsIndentOption + @AppSettings(\.textEditing.indentOption) var indentOption @AppSettings(\.textEditing.lineHeightMultiple) var lineHeightMultiple @AppSettings(\.textEditing.wrapLinesToEditorWidth) var wrapLinesToEditorWidth @AppSettings(\.textEditing.font) var settingsFont @@ -90,17 +90,6 @@ struct CodeFileView: View { } }() - // Tab is a placeholder value, is overriden immediately in `init`. - @State - private var indentOption: IndentOption = { - switch Settings[\.textEditing].indentOption.indentType { - case .tab: - return .tab - case .spaces: - return .spaces(count: Settings[\.textEditing].indentOption.spaceCount) - } - }() - @Environment(\.edgeInsets) private var edgeInsets @@ -113,10 +102,10 @@ struct CodeFileView: View { language: getLanguage(), theme: selectedTheme.editor.editorTheme, font: font, - tabWidth: defaultTabWidth, - indentOption: indentOption, + tabWidth: codeFile.defaultTabWidth ?? defaultTabWidth, + indentOption: (codeFile.indentOption ?? indentOption).textViewOption(), lineHeight: lineHeightMultiple, - wrapLines: wrapLinesToEditorWidth, + wrapLines: codeFile.wrapLines ?? wrapLinesToEditorWidth, cursorPosition: $codeFile.cursorPosition, useThemeBackground: useThemeBackground, contentInsets: edgeInsets.nsEdgeInsets, @@ -124,6 +113,7 @@ struct CodeFileView: View { letterSpacing: letterSpacing, bracketPairHighlight: bracketPairHighlight ) + .id(codeFile.fileURL) .background { if colorScheme == .dark { @@ -152,21 +142,17 @@ struct CodeFileView: View { .onChange(of: bracketHighlight) { _ in bracketPairHighlight = getBracketPairHighlight() } - .onChange(of: settingsIndentOption) { option in - switch option.indentType { - case .tab: - self.indentOption = .tab - case .spaces: - self.indentOption = .spaces(count: option.spaceCount) - } - } } private func getLanguage() -> CodeLanguage { guard let url = codeFile.fileURL else { return .default } - return .detectLanguageFrom(url: url) + return codeFile.language ?? CodeLanguage.detectLanguageFrom( + url: url, + prefixBuffer: codeFile.content.getFirstLines(5), + suffixBuffer: codeFile.content.getLastLines(5) + ) } private func getBracketPairHighlight() -> BracketPairHighlight? { @@ -186,3 +172,16 @@ struct CodeFileView: View { } } } + +// This extension is kept here because it should not be used elsewhere in the app and may cause confusion +// due to the similar type name from the CETV module. +private extension SettingsData.TextEditingSettings.IndentOption { + func textViewOption() -> IndentOption { + switch self.indentType { + case .spaces: + return IndentOption.spaces(count: spaceCount) + case .tab: + return IndentOption.tab + } + } +} diff --git a/CodeEdit/Features/InspectorSidebar/InspectorSidebarView.swift b/CodeEdit/Features/InspectorSidebar/InspectorSidebarView.swift index 801b325ee..a15cdbe3d 100644 --- a/CodeEdit/Features/InspectorSidebar/InspectorSidebarView.swift +++ b/CodeEdit/Features/InspectorSidebar/InspectorSidebarView.swift @@ -21,26 +21,14 @@ struct InspectorSidebarView: View { var sidebarPosition: SettingsData.SidebarTabBarPosition @State - private var selection: InspectorTab? = .quickhelp - - var path: String? { - tabManager.activeTabGroup.selected?.fileDocument?.fileURL?.path(percentEncoded: false) - } - - var fileTreeAndGitHistory: [InspectorTab] { - guard let workspaceURL = workspace.fileURL, let path else { - return [] - } - - return [ - .file(workspaceURL: workspaceURL, fileURL: path), - .gitHistory(workspaceURL: workspaceURL, fileURL: path) - ] - } + private var selection: InspectorTab? = .file private var items: [InspectorTab] { - fileTreeAndGitHistory + [InspectorTab.quickhelp] + - extensionManager + [ + .file, + .gitHistory + ] + + extensionManager .extensions .map { ext in ext.availableFeatures.compactMap { diff --git a/CodeEdit/Features/InspectorSidebar/InspectorTab.swift b/CodeEdit/Features/InspectorSidebar/InspectorTab.swift index 9983e7157..62bcf53d6 100644 --- a/CodeEdit/Features/InspectorSidebar/InspectorTab.swift +++ b/CodeEdit/Features/InspectorSidebar/InspectorTab.swift @@ -10,9 +10,8 @@ import CodeEditKit import ExtensionFoundation enum InspectorTab: AreaTab { - case file(workspaceURL: URL, fileURL: String) - case gitHistory(workspaceURL: URL, fileURL: String) - case quickhelp + case file + case gitHistory case uiExtension(endpoint: AppExtensionIdentity, data: ResolvedSidebar.SidebarStore) var systemImage: String { @@ -21,8 +20,6 @@ enum InspectorTab: AreaTab { return "doc" case .gitHistory: return "clock" - case .quickhelp: - return "questionmark.circle" case .uiExtension(_, let data): return data.icon ?? "e.square" } @@ -41,8 +38,6 @@ enum InspectorTab: AreaTab { return "File Inspector" case .gitHistory: return "History Inspector" - case .quickhelp: - return "Quick Help Inspector" case .uiExtension(_, let data): return data.help ?? data.sceneID } @@ -50,12 +45,10 @@ enum InspectorTab: AreaTab { var body: some View { switch self { - case let .file(workspaceURL, fileURL): - FileInspectorView(workspaceURL: workspaceURL, fileURL: fileURL) - case let .gitHistory(workspaceURL, fileURL): - HistoryInspectorView(workspaceURL: workspaceURL, fileURL: fileURL) - case .quickhelp: - QuickHelpInspectorView().padding(5) + case .file: + FileInspectorView() + case .gitHistory: + HistoryInspectorView() case let .uiExtension(endpoint, data): ExtensionSceneView(with: endpoint, sceneID: data.sceneID) } diff --git a/CodeEdit/Features/InspectorSidebar/Models/FileInspectorModel.swift b/CodeEdit/Features/InspectorSidebar/Models/FileInspectorModel.swift deleted file mode 100644 index bff0d6dd4..000000000 --- a/CodeEdit/Features/InspectorSidebar/Models/FileInspectorModel.swift +++ /dev/null @@ -1,101 +0,0 @@ -// -// FileInspectorModel.swift -// CodeEdit -// -// Created by Nanashi Li on 2022/04/17. -// - -import SwiftUI - -public final class FileInspectorModel: ObservableObject { - - /// The base URL of the workspace - private(set) var workspaceURL: URL - - @Published - var fileTypeSelection: LanguageType.ID = "swift" - @Published - var fileURL: String = "" - @Published - var fileName: String = "" - - @Published - var locationSelection: FileLocation.ID = "relative_group" - @Published - var textEncodingSelection: TextEncoding.ID = "utf8" - @Published - var lineEndingsSelection: LineEndings.ID = "macos" - @Published - var indentUsingSelection: IndentUsing.ID = "spaces" - - @Published - var languageTypeObjCList = FileTypeList.init().languageTypeObjCList - @Published - var sourcecodeCList = FileTypeList.init().sourcecodeCList - @Published - var sourcecodeCPlusList = FileTypeList.init().sourcecodeCPlusList - @Published - var sourcecodeSwiftList = FileTypeList.init().sourcecodeSwiftList - @Published - var sourcecodeAssemblyList = FileTypeList.init().sourcecodeAssemblyList - @Published - var sourcecodeScriptList = FileTypeList.init().sourcecodeScriptList - @Published - var sourcecodeVariousList = FileTypeList.init().sourcecodeVariousList - @Published - var propertyList = FileTypeList.init().propertyList - @Published - var shellList = FileTypeList.init().shellList - @Published - var machOList = FileTypeList.init().machOList - @Published - var textList = FileTypeList.init().textList - @Published - var audioList = FileTypeList.init().audioList - @Published - var imageList = FileTypeList.init().imageList - @Published - var videoList = FileTypeList.init().videoList - @Published - var archiveList = FileTypeList.init().archiveList - @Published - var otherList = FileTypeList.init().otherList - - @Published - var locationList = [FileLocation(name: "Absolute Path", id: "absolute"), - FileLocation(name: "Relative to Group", id: "relative_group"), - FileLocation(name: "Relative to Project", id: "relative_project"), - FileLocation(name: "Relative to Developer Directory", id: "relative_developer_dir"), - FileLocation(name: "Relative to Build Projects", id: "relative_build_projects"), - FileLocation(name: "Relative to SDK", id: "relative_sdk")] - - @Published - var textEncodingList = [TextEncoding(name: "Unicode (UTF-8)", id: "utf8"), - TextEncoding(name: "Unicode (UTF-16)", id: "utf16"), - TextEncoding(name: "Unicode (UTF-16BE)", id: "utf16_be"), - TextEncoding(name: "Unicode (UTF-16LE)", id: "utf16_le")] - - @Published - var lineEndingsList = [LineEndings(name: "macOS / Unix (LF)", id: "macos"), - LineEndings(name: "Classic macOS (CR)", id: "classic"), - LineEndings(name: "Windows (CRLF)", id: "windows")] - - @Published - var indentUsingList = [IndentUsing(name: "Spaces", id: "spaces"), - IndentUsing(name: "Tabs", id: "tabs")] - - @Published - var tabWidth: Int = 4 - - @Published - var indentWidth: Int = 4 - - @Published - var wrapLines: Bool = true - - public init(workspaceURL: URL, fileURL: String) { - self.workspaceURL = workspaceURL - self.fileURL = fileURL - self.fileName = (fileURL as NSString).lastPathComponent - } -} diff --git a/CodeEdit/Features/InspectorSidebar/Models/FileLocation.swift b/CodeEdit/Features/InspectorSidebar/Models/FileLocation.swift deleted file mode 100644 index 3e1dc42aa..000000000 --- a/CodeEdit/Features/InspectorSidebar/Models/FileLocation.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// FileLocation.swift -// CodeEdit -// -// Created by Nanashi Li on 2022/04/18. -// - -import Foundation - -struct FileLocation: Identifiable, Hashable { - let name: String - let id: String -} diff --git a/CodeEdit/Features/InspectorSidebar/Models/HistoryInspectorModel.swift b/CodeEdit/Features/InspectorSidebar/Models/HistoryInspectorModel.swift index ac40d2d56..471ffe593 100644 --- a/CodeEdit/Features/InspectorSidebar/Models/HistoryInspectorModel.swift +++ b/CodeEdit/Features/InspectorSidebar/Models/HistoryInspectorModel.swift @@ -10,28 +10,41 @@ import Foundation final class HistoryInspectorModel: ObservableObject { /// A GitClient instance - private(set) var gitClient: GitClient + private(set) var gitClient: GitClient? /// The base URL of the workspace - private(set) var workspaceURL: URL + private(set) var workspaceURL: URL? /// The base URL of the workspace - private(set) var fileURL: String + private(set) var fileURL: String? /// The selected branch from the GitClient @Published - var commitHistory: [GitCommit] - - /// Initialize with a GitClient - /// - Parameter workspaceURL: the current workspace URL - /// - init(workspaceURL: URL, fileURL: String) { - self.workspaceURL = workspaceURL - self.fileURL = fileURL + var commitHistory: [GitCommit] = [] + + func setWorkspace(url: URL?) { + if workspaceURL != url { + workspaceURL = url + updateCommitHistory() + } + } + + func setFile(url: String?) { + if fileURL != url { + fileURL = url + updateCommitHistory() + } + } + + func updateCommitHistory() { + guard let workspaceURL, let fileURL else { + commitHistory = [] + return + } gitClient = GitClient(directoryURL: workspaceURL, shellClient: currentWorld.shellClient) do { - let commitHistory = try gitClient.getCommitHistory(entries: 40, fileLocalPath: fileURL) - self.commitHistory = commitHistory + let commitHistory = try gitClient?.getCommitHistory(entries: 40, fileLocalPath: fileURL) + self.commitHistory = commitHistory ?? [] } catch { commitHistory = [] } diff --git a/CodeEdit/Features/InspectorSidebar/Models/IndentUsing.swift b/CodeEdit/Features/InspectorSidebar/Models/IndentUsing.swift deleted file mode 100644 index 3a22bd68c..000000000 --- a/CodeEdit/Features/InspectorSidebar/Models/IndentUsing.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// IndentUsing.swift -// CodeEdit -// -// Created by Nanashi Li on 2022/04/18. -// - -import Foundation - -struct IndentUsing: Identifiable, Hashable { - let name: String - let id: String -} diff --git a/CodeEdit/Features/InspectorSidebar/Models/LanguageType.swift b/CodeEdit/Features/InspectorSidebar/Models/LanguageType.swift deleted file mode 100644 index cf646e288..000000000 --- a/CodeEdit/Features/InspectorSidebar/Models/LanguageType.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// LanguageType.swift -// CodeEdit -// -// Created by Nanashi Li on 2022/04/17. -// - -import Foundation - -struct LanguageType: Identifiable, Hashable { - let name: String - let id: String -} diff --git a/CodeEdit/Features/InspectorSidebar/Models/LineEndings.swift b/CodeEdit/Features/InspectorSidebar/Models/LineEndings.swift deleted file mode 100644 index de300a162..000000000 --- a/CodeEdit/Features/InspectorSidebar/Models/LineEndings.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// LineEndings.swift -// CodeEdit -// -// Created by Nanashi Li on 2022/04/18. -// - -import Foundation - -struct LineEndings: Identifiable, Hashable { - let name: String - let id: String -} diff --git a/CodeEdit/Features/InspectorSidebar/Models/Lists/FileTypeList.swift b/CodeEdit/Features/InspectorSidebar/Models/Lists/FileTypeList.swift deleted file mode 100644 index 3b94b487c..000000000 --- a/CodeEdit/Features/InspectorSidebar/Models/Lists/FileTypeList.swift +++ /dev/null @@ -1,135 +0,0 @@ -// -// FileTypeList.swift -// CodeEdit -// -// Created by Nanashi Li on 2022/04/18. -// - -import Foundation - -// TODO: Get the right extension names for files -// TODO: Extension Name - -/// A collection of file types and their associated extensions, -/// which can be selected in the inspector to override default values -final class FileTypeList { - - var languageTypeObjCList = [LanguageType(name: "Objective-C Preprocessed Source", id: "obj_c_pre_source"), - LanguageType(name: "Objective-C Source", id: "m"), - LanguageType(name: "Objective-C++ Preprocessed Source", id: "obj_c_++_pre_source"), - LanguageType(name: "Objective-C++ Source", id: "m")] - - var sourcecodeCList = [LanguageType(name: "C Header", id: "h"), - LanguageType(name: "C Preprocessed Source", id: "obj_c_source"), - LanguageType(name: "C Source", id: "c")] - - var sourcecodeCPlusList = [LanguageType(name: "C++ Header", id: "hh"), - LanguageType(name: "C++ Preprocessed Source", id: "i"), - LanguageType(name: "C++ Source", id: "cpp")] - - var sourcecodeSwiftList = [LanguageType(name: "Swift Source", id: "swift")] - - var sourcecodeAssemblyList = [LanguageType(name: "Assembly", id: "asm"), - LanguageType(name: "LLVM Assembly", id: "obj_c_source"), - LanguageType(name: "NASM Assembly", id: "obj_c_++_pre_source"), - LanguageType(name: "PPC Assembly", id: "obj_c_++_source")] - - var sourcecodeScriptList = [LanguageType(name: "AppleScript Uncompiled Source", id: "obj_c_pre_source"), - LanguageType(name: "JavaScript Source", id: "js"), - LanguageType(name: "PHP Script", id: "php"), - LanguageType(name: "Perl Script", id: "pl"), - LanguageType(name: "Python Script", id: "py"), - LanguageType(name: "Ruby Script", id: "rb")] - - var sourcecodeVariousList = [LanguageType(name: "Ada Source", id: "obj_c_pre_source"), - LanguageType(name: "CLIPS Source", id: "obj_c_source"), - LanguageType(name: "DTrace Source", id: "obj_c_++_pre_source"), - LanguageType(name: "Fortran 77 Source", id: "obj_c_++_source"), - LanguageType(name: "Fortran 90 Source", id: "obj_c_++_source"), - LanguageType(name: "Fortran Source", id: "obj_c_++_source"), - LanguageType(name: "lig Source", id: "obj_c_++_source"), - LanguageType(name: "JAM Source", id: "obj_c_++_source"), - LanguageType(name: "Java Source", id: "obj_c_++_source"), - LanguageType(name: "Lex Source", id: "obj_c_++_source"), - LanguageType(name: "Metal Shader Source", id: "obj_c_++_source"), - LanguageType(name: "MiG Source", id: "obj_c_++_source"), - LanguageType(name: "OpenCL Source", id: "obj_c_++_source"), - LanguageType(name: "OpenGL Shading Language Source", id: "obj_c_++_source"), - LanguageType(name: "Pascal Source", id: "obj_c_++_source"), - LanguageType(name: "Rez Source", id: "obj_c_++_source"), - LanguageType(name: "Yacc Source", id: "obj_c_++_source")] - - var propertyList = [LanguageType(name: "Info plist XML", id: "info-xml"), - LanguageType(name: "Property List Binary", id: "prp_bin"), - LanguageType(name: "Property List Text", id: "prp_txt"), - LanguageType(name: "Property List XML", id: "prp_xml"), - LanguageType(name: "XML", id: "xml")] - - var shellList = [LanguageType(name: "Bash Shell Script", id: "bash"), - LanguageType(name: "Shell Script", id: "sh"), - LanguageType(name: "CSH Shell Script", id: "csh")] - - var machOList = [LanguageType(name: "Mach-O Core Dump", id: "mach-o-core-dump"), - LanguageType(name: "Mach-O Dynamic Library", id: "mach-o-dyn-lib"), - LanguageType(name: "Mach-O FVM Library", id: "mach-o-fvm-lib"), - LanguageType(name: "Mach-O Object Code", id: "mach-o-obj"), - LanguageType(name: "Mach-O Preload Data", id: "mach-o-pre-data"), - LanguageType(name: "Mach-O Bundle", id: "mach-o-bundle")] - - var textList = [LanguageType(name: "Cascading Style Sheets", id: "css"), - LanguageType(name: "HTML", id: "html"), - LanguageType(name: "JSON", id: "json"), - LanguageType(name: "Markdown Text", id: "md"), - LanguageType(name: "Plain Text", id: "txt"), - LanguageType(name: "Rich Text Format", id: "rtf"), - LanguageType(name: "YAML", id: "yaml")] - - var audioList = [LanguageType(name: "AIFF Audio", id: "aiff"), - LanguageType(name: "MIDI Audio", id: "midi"), - LanguageType(name: "MP3 Audio", id: "mp3"), - LanguageType(name: "WAV Audio", id: "wav"), - LanguageType(name: "AU Audio", id: "au")] - - var imageList = [LanguageType(name: "BMP Image", id: "bmp"), - LanguageType(name: "GIF Image", id: "gif"), - LanguageType(name: "Icon", id: "icon"), - LanguageType(name: "JPEG Image", id: "jpeg"), - LanguageType(name: "Microsoft Icon", id: "ico"), - LanguageType(name: "PICT Image", id: "pict"), - LanguageType(name: "PNG Image", id: "png"), - LanguageType(name: "TIFF Image", id: "tiff")] - - var videoList = [LanguageType(name: "AVI Video", id: "avi"), - LanguageType(name: "MPEG Video", id: "mpeg"), - LanguageType(name: "QuickTime Video", id: "quicktime")] - - var archiveList = [LanguageType(name: "AppleScript Dictionary Archivo", id: "obj_c_pre_source"), - LanguageType(name: "Archive", id: "archive"), - LanguageType(name: "BinHex Archive", id: "obj_c_++_pre_source"), - LanguageType(name: "J2EE Enterprise Archive", id: "obj_c_++_source"), - LanguageType(name: "Java Archive", id: "obj_c_++_source"), - LanguageType(name: "MacBinary Archive", id: "obj_c_++_source"), - LanguageType(name: "PPOB Archive", id: "obj_c_++_source"), - LanguageType(name: "Resource Archive", id: "obj_c_++_source"), - LanguageType(name: "Stuffit Archive", id: "obj_c_++_source"), - LanguageType(name: "Web Application Archive", id: "obj_c_++_source"), - LanguageType(name: "Zip Archive", id: "zip"), - LanguageType(name: "gzip Archive", id: "gzip"), - LanguageType(name: "tar Archive", id: "tar")] - - var otherList = [LanguageType(name: "API Notes", id: "obj_c_pre_source"), - LanguageType(name: "AppleScript Script Suite Definition", id: "obj_c_source"), - LanguageType(name: "AppleScript Script Terminology Definition", id: "obj_c_++_pre_source"), - LanguageType(name: "Data", id: "obj_c_++_source"), - LanguageType(name: "Exported Symbols", id: "obj_c_++_source"), - LanguageType(name: "Java Bundle", id: "aab"), - LanguageType(name: "Java Bytecode", id: "class"), - LanguageType(name: "LLVM Module Map", id: "obj_c_++_source"), - LanguageType(name: "Object Code", id: "obj_c_++_source"), - LanguageType(name: "PDF document", id: "pdf"), - LanguageType(name: "Quartz Composer Composition", id: "obj_c_++_source"), - LanguageType(name: "Text-Based Dynamic Library Definition", id: "obj_c_++_source"), - LanguageType(name: "Worksheet Script", id: "obj_c_++_source"), - LanguageType(name: "Makefile", id: "make")] - -} diff --git a/CodeEdit/Features/InspectorSidebar/Models/TextEncoding.swift b/CodeEdit/Features/InspectorSidebar/Models/TextEncoding.swift deleted file mode 100644 index d30025d6b..000000000 --- a/CodeEdit/Features/InspectorSidebar/Models/TextEncoding.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// TextEncoding.swift -// CodeEdit -// -// Created by Nanashi Li on 2022/04/18. -// - -import Foundation - -struct TextEncoding: Identifiable, Hashable { - let name: String - let id: String -} diff --git a/CodeEdit/Features/InspectorSidebar/Views/FileInspectorView.swift b/CodeEdit/Features/InspectorSidebar/Views/FileInspectorView.swift index a68396a7b..bfddf9bd1 100644 --- a/CodeEdit/Features/InspectorSidebar/Views/FileInspectorView.swift +++ b/CodeEdit/Features/InspectorSidebar/Views/FileInspectorView.swift @@ -5,179 +5,190 @@ // Created by Nanashi Li on 2022/03/24. // import SwiftUI +import CodeEditLanguages struct FileInspectorView: View { + @EnvironmentObject + private var workspace: WorkspaceDocument - @ObservedObject - private var inspectorModel: FileInspectorModel + @EnvironmentObject + private var tabManager: TabManager - /// Initialize with GitClient - /// - Parameter gitClient: a GitClient - init(workspaceURL: URL, fileURL: String) { - self.inspectorModel = .init(workspaceURL: workspaceURL, fileURL: fileURL) - } + @AppSettings(\.textEditing) + private var textEditing - var body: some View { - Form { - Section("Identity and Type") { - fileName - fileType - } - Section { - location - } - Section("Text Settings") { - textEncoding - lineEndings - } - Section { - indentUsing - tabWidths - wrapLines - } - } - } + @State + private var file: CEWorkspaceFile? - private var fileName: some View { - TextField("Name", text: $inspectorModel.fileName) - } + @State + private var fileName: String = "" - private var fileType: some View { - Picker("Type", selection: $inspectorModel.fileTypeSelection) { - Group { - Section(header: Text("Sourcecode Objective-C")) { - ForEach(inspectorModel.languageTypeObjCList) { - Text($0.name) - } - } - Section(header: Text("Sourcecode C")) { - ForEach(inspectorModel.sourcecodeCList) { - Text($0.name) - } - } - Section(header: Text("Sourcecode C++")) { - ForEach(inspectorModel.sourcecodeCPlusList) { - Text($0.name) - } - } - Section(header: Text("Sourcecode Swift")) { - ForEach(inspectorModel.sourcecodeSwiftList) { - Text($0.name) - } - } - Section(header: Text("Sourcecode Assembly")) { - ForEach(inspectorModel.sourcecodeAssemblyList) { - Text($0.name) - } - } - } - Group { - Section(header: Text("Sourcecode Objective-C")) { - ForEach(inspectorModel.sourcecodeScriptList) { - Text($0.name) - } - } - Section(header: Text("Property List / XML")) { - ForEach(inspectorModel.propertyList) { - Text($0.name) - } - } - Section(header: Text("Shell Script")) { - ForEach(inspectorModel.shellList) { - Text($0.name) - } - } - Section(header: Text("Mach-O")) { - ForEach(inspectorModel.machOList) { - Text($0.name) - } - } - Section(header: Text("Text")) { - ForEach(inspectorModel.textList) { - Text($0.name) - } - } - } - Group { - Section(header: Text("Audio")) { - ForEach(inspectorModel.audioList) { - Text($0.name) - } - } - Section(header: Text("Image")) { - ForEach(inspectorModel.imageList) { - Text($0.name) + // File settings overrides + + @State + private var language: CodeLanguage? + + @State + var indentOption: SettingsData.TextEditingSettings.IndentOption = .init(indentType: .tab) + + @State + var defaultTabWidth: Int = 0 + + @State + var wrapLines: Bool = false + + var body: some View { + Group { + if file != nil { + Form { + Section("Identity and Type") { + fileNameField + fileType } - } - Section(header: Text("Video")) { - ForEach(inspectorModel.videoList) { - Text($0.name) + Section { + location } - } - Section(header: Text("Archive")) { - ForEach(inspectorModel.archiveList) { - Text($0.name) - } - } - Section(header: Text("Other")) { - ForEach(inspectorModel.otherList) { - Text($0.name) + Section("Text Settings") { + indentUsing + widthOptions + wrapLinesToggle } } + } else { + NoSelectionInspectorView() } } + .onReceive(tabManager.activeTabGroup.objectWillChange) { _ in + file = tabManager.activeTabGroup.selected + fileName = file?.name ?? "" + language = file?.fileDocument?.language + indentOption = file?.fileDocument?.indentOption ?? textEditing.indentOption + defaultTabWidth = file?.fileDocument?.defaultTabWidth ?? textEditing.defaultTabWidth + wrapLines = file?.fileDocument?.wrapLines ?? textEditing.wrapLinesToEditorWidth + } + .onAppear { + file = tabManager.activeTabGroup.selected + fileName = file?.name ?? "" + language = file?.fileDocument?.language + indentOption = file?.fileDocument?.indentOption ?? textEditing.indentOption + defaultTabWidth = file?.fileDocument?.defaultTabWidth ?? textEditing.defaultTabWidth + wrapLines = file?.fileDocument?.wrapLines ?? textEditing.wrapLinesToEditorWidth + } + .onChange(of: textEditing) { newValue in + indentOption = file?.fileDocument?.indentOption ?? newValue.indentOption + defaultTabWidth = file?.fileDocument?.defaultTabWidth ?? newValue.defaultTabWidth + wrapLines = file?.fileDocument?.wrapLines ?? newValue.wrapLinesToEditorWidth + } } - private var location: some View { - Group { - LabeledContent("Location") { - Button("Choose...") { - // open open dialog + @ViewBuilder + private var fileNameField: some View { + if let file { + TextField("Name", text: $fileName) + .background( + file.validateFileName(for: fileName) ? Color.clear : Color(errorRed) + ) + .onSubmit { + if file.validateFileName(for: fileName) { + let destinationURL = file.url + .deletingLastPathComponent() + .appendingPathComponent(fileName) + if !file.isFolder { + tabManager.tabGroups.closeAllTabs(of: file) + } + DispatchQueue.main.async { + file.move(to: destinationURL) + let newItem = CEWorkspaceFile(url: destinationURL) + newItem.parent = file.parent + if !newItem.isFolder { + tabManager.openTab(item: newItem) + } + } + } else { + fileName = file.labelFileName() + } } - } - ExternalLink(showInFinder: true, destination: URL(fileURLWithPath: inspectorModel.fileURL)) { - Text(inspectorModel.fileURL) - .font(.footnote) - .foregroundColor(.secondary) - } } } - private var textEncoding: some View { - Picker("Text Encoding", selection: $inspectorModel.textEncodingSelection) { - ForEach(inspectorModel.textEncodingList) { - Text($0.name) + @ViewBuilder + private var fileType: some View { + Picker( + "Type", + selection: $language + ) { + Text("Default - Detected").tag(nil as CodeLanguage?) + Divider() + ForEach(CodeLanguage.allLanguages, id: \.id) { language in + Text(language.id.rawValue.capitalized).tag(language as CodeLanguage?) } } + .onChange(of: language) { newValue in + file?.fileDocument?.language = newValue + } } - private var lineEndings: some View { - Picker("Line Endings", selection: $inspectorModel.lineEndingsSelection) { - ForEach(inspectorModel.lineEndingsList) { - Text($0.name) + private var location: some View { + Group { + if let file { + LabeledContent("Location") { + Button("Choose...") { + guard let newURL = chooseNewFileLocation() else { + return + } + if !file.isFolder { + tabManager.tabGroups.closeAllTabs(of: file) + } + // This is ugly but if the tab is opened at the same time as closing the others, it doesn't open + // And if the files are re-built at the same time as the tab is opened, it causes a memory error + DispatchQueue.main.async { + file.move(to: newURL) + // If the parent directory doesn't exist in the workspace, don't open it in a tab. + if let newParent = try? workspace.workspaceFileManager?.getFile( + newURL.deletingLastPathComponent().path + ) { + let newItem = CEWorkspaceFile(url: newURL) + newItem.parent = newParent + if !file.isFolder { + tabManager.openTab(item: newItem) + } + DispatchQueue.main.async { + _ = try? workspace.workspaceFileManager?.rebuildFiles(fromItem: newParent) + } + } + } + } + } + ExternalLink(showInFinder: true, destination: file.url) { + Text(file.url.path(percentEncoded: false)) + .font(.footnote) + .foregroundColor(.secondary) + } } } } private var indentUsing: some View { - Picker("Indent Using", selection: $inspectorModel.indentUsingSelection) { - ForEach(inspectorModel.indentUsingList) { - Text($0.name) - } + Picker("Indent using", selection: $indentOption.indentType) { + Text("Spaces").tag(SettingsData.TextEditingSettings.IndentOption.IndentType.spaces) + Text("Tabs").tag(SettingsData.TextEditingSettings.IndentOption.IndentType.tab) + } + .onChange(of: indentOption) { newValue in + file?.fileDocument?.indentOption = newValue == textEditing.indentOption ? nil : newValue } } - private var tabWidths: some View { + private var widthOptions: some View { LabeledContent("Widths") { HStack(spacing: 5) { VStack(alignment: .center, spacing: 0) { Stepper( "", value: Binding<Double>( - get: { Double(inspectorModel.tabWidth) }, - set: { inspectorModel.tabWidth = Int($0) } + get: { Double(defaultTabWidth) }, + set: { defaultTabWidth = Int($0) } ), - in: 1...8, + in: 1...16, step: 1, format: .number ) @@ -186,14 +197,15 @@ struct FileInspectorView: View { .foregroundColor(.primary) .font(.footnote) } + .help("The visual width of tab characters") VStack(alignment: .center, spacing: 0) { Stepper( "", value: Binding<Double>( - get: { Double(inspectorModel.indentWidth) }, - set: { inspectorModel.indentWidth = Int($0) } + get: { Double(indentOption.spaceCount) }, + set: { indentOption.spaceCount = Int($0) } ), - in: 1...8, + in: 1...10, step: 1, format: .number ) @@ -202,13 +214,31 @@ struct FileInspectorView: View { .foregroundColor(.primary) .font(.footnote) } + .help("The number of spaces to insert when the tab key is pressed.") } } + .onChange(of: defaultTabWidth) { newValue in + file?.fileDocument?.defaultTabWidth = newValue == textEditing.defaultTabWidth ? nil : newValue + } + } + + private var wrapLinesToggle: some View { + Toggle("Wrap lines", isOn: $wrapLines) + .onChange(of: wrapLines) { newValue in + file?.fileDocument?.wrapLines = newValue == textEditing.wrapLinesToEditorWidth ? nil : newValue + } } - private var wrapLines: some View { - Toggle(isOn: $inspectorModel.wrapLines) { - Text("Wrap lines") + private func chooseNewFileLocation() -> URL? { + guard let file else { return nil } + let dialogue = NSSavePanel() + dialogue.title = "Save File" + dialogue.directoryURL = file.url.deletingLastPathComponent() + dialogue.nameFieldStringValue = file.name + if dialogue.runModal() == .OK { + return dialogue.url + } else { + return nil } } } diff --git a/CodeEdit/Features/InspectorSidebar/Views/HistoryInspectorView.swift b/CodeEdit/Features/InspectorSidebar/Views/HistoryInspectorView.swift index 279f06b6a..7d845166b 100644 --- a/CodeEdit/Features/InspectorSidebar/Views/HistoryInspectorView.swift +++ b/CodeEdit/Features/InspectorSidebar/Views/HistoryInspectorView.swift @@ -7,6 +7,11 @@ import SwiftUI struct HistoryInspectorView: View { + @EnvironmentObject + private var workspace: WorkspaceDocument + + @EnvironmentObject + private var tabManager: TabManager @ObservedObject private var model: HistoryInspectorModel @@ -15,24 +20,37 @@ struct HistoryInspectorView: View { /// Initialize with GitClient /// - Parameter gitClient: a GitClient - init(workspaceURL: URL, fileURL: String) { - self.model = .init(workspaceURL: workspaceURL, fileURL: fileURL) + init() { + self.model = .init() } var body: some View { - VStack { - if model.commitHistory.isEmpty { - HistoryInspectorNoHistoryView() - .frame(maxWidth: .infinity, maxHeight: .infinity) - } else { - List(selection: $selectedCommitHistory) { - ForEach(model.commitHistory) { commit in - HistoryInspectorItemView(commit: commit, selection: $selectedCommitHistory) - .tag(commit) + Group { + if model.gitClient != nil { + VStack { + if model.commitHistory.isEmpty { + HistoryInspectorNoHistoryView() + .frame(maxWidth: .infinity, maxHeight: .infinity) + } else { + List(selection: $selectedCommitHistory) { + ForEach(model.commitHistory) { commit in + HistoryInspectorItemView(commit: commit, selection: $selectedCommitHistory) + .tag(commit) + } + } + .listStyle(.inset) } } - .listStyle(.inset) + } else { + NoSelectionInspectorView() } } + .onReceive(tabManager.activeTabGroup.objectWillChange) { _ in + model.setFile(url: tabManager.activeTabGroup.selected?.url.path) + } + .onAppear { + model.setWorkspace(url: workspace.fileURL) + model.setFile(url: tabManager.activeTabGroup.selected?.url.path) + } } } diff --git a/CodeEdit/Features/InspectorSidebar/Views/QuickHelpInspectorView.swift b/CodeEdit/Features/InspectorSidebar/Views/QuickHelpInspectorView.swift deleted file mode 100644 index dd361a545..000000000 --- a/CodeEdit/Features/InspectorSidebar/Views/QuickHelpInspectorView.swift +++ /dev/null @@ -1,35 +0,0 @@ -// -// QuickHelpInspectorView.swift -// CodeEdit -// -// Created by Nanashi Li on 2022/03/24. -// -import SwiftUI - -struct QuickHelpInspectorView: View { - - var body: some View { - VStack(alignment: .leading) { - Text("Quick Help") - .foregroundColor(.secondary) - .fontWeight(.bold) - .font(.system(size: 13)) - VStack { - Text("No Quick Help") - .foregroundColor(.secondary) - .font(.system(size: 16)) - .fontWeight(.medium) - .padding(.top, 10) - .padding(.bottom, 10) - - Button("Search Documentation") { - // Open documentation - } - .controlSize(.small) - } - .frame(maxWidth: .infinity) - Divider().padding(.top, 15) - } - .frame(maxWidth: .infinity).padding(5) - } -} diff --git a/CodeEdit/Features/NavigatorSidebar/OutlineView/FileSystemTableViewCell.swift b/CodeEdit/Features/NavigatorSidebar/OutlineView/FileSystemTableViewCell.swift index d887f6649..de9cfa58c 100644 --- a/CodeEdit/Features/NavigatorSidebar/OutlineView/FileSystemTableViewCell.swift +++ b/CodeEdit/Features/NavigatorSidebar/OutlineView/FileSystemTableViewCell.swift @@ -49,8 +49,8 @@ class FileSystemTableViewCell: StandardTableViewCell { fileItem = item icon.image = image icon.contentTintColor = color(for: item) - toolTip = label(for: item) - label.stringValue = label(for: item) + toolTip = item.labelFileName() + label.stringValue = item.labelFileName() } func addModel() { @@ -85,22 +85,6 @@ class FileSystemTableViewCell: StandardTableViewCell { } } - /// Generates a string based on user's file name preferences. - /// - Parameter item: The FileItem to generate the name for. - /// - Returns: A `String` with the name to display. - func label(for item: CEWorkspaceFile) -> String { - switch prefs.fileExtensionsVisibility { - case .hideAll: - return item.fileName(typeHidden: true) - case .showAll: - return item.fileName(typeHidden: false) - case .showOnly: - return item.fileName(typeHidden: !prefs.shownFileExtensions.extensions.contains(item.type.rawValue)) - case .hideOnly: - return item.fileName(typeHidden: prefs.hiddenFileExtensions.extensions.contains(item.type.rawValue)) - } - } - /// Get the appropriate color for the items icon depending on the users preferences. /// - Parameter item: The `FileItem` to get the color for /// - Returns: A `NSColor` for the given `FileItem`. @@ -116,28 +100,17 @@ class FileSystemTableViewCell: StandardTableViewCell { let errorRed = NSColor(red: 1, green: 0, blue: 0, alpha: 0.2) extension FileSystemTableViewCell: NSTextFieldDelegate { func controlTextDidChange(_ obj: Notification) { - label.backgroundColor = validateFileName(for: label?.stringValue ?? "") ? .none : errorRed + label.backgroundColor = fileItem.validateFileName(for: label?.stringValue ?? "") ? .none : errorRed } func controlTextDidEndEditing(_ obj: Notification) { - label.backgroundColor = validateFileName(for: label?.stringValue ?? "") ? .none : errorRed - if validateFileName(for: label?.stringValue ?? "") { + label.backgroundColor = fileItem.validateFileName(for: label?.stringValue ?? "") ? .none : errorRed + if fileItem.validateFileName(for: label?.stringValue ?? "") { fileItem.move(to: fileItem.url.deletingLastPathComponent() .appendingPathComponent(label?.stringValue ?? "")) } else { - label?.stringValue = label(for: fileItem) + label?.stringValue = fileItem.labelFileName() } } - - func validateFileName(for newName: String) -> Bool { - guard newName != label(for: fileItem) else { return true } - - guard !newName.isEmpty && newName.isValidFilename && - !FileManager.default.fileExists(atPath: - fileItem.url.deletingLastPathComponent().appendingPathComponent(newName).path) - else { return false } - - return true - } } extension String { diff --git a/CodeEdit/Features/NavigatorSidebar/ProjectNavigator/OutlineView/ProjectNavigatorTableViewCell.swift b/CodeEdit/Features/NavigatorSidebar/ProjectNavigator/OutlineView/ProjectNavigatorTableViewCell.swift index 389488a8f..538e41492 100644 --- a/CodeEdit/Features/NavigatorSidebar/ProjectNavigator/OutlineView/ProjectNavigatorTableViewCell.swift +++ b/CodeEdit/Features/NavigatorSidebar/ProjectNavigator/OutlineView/ProjectNavigatorTableViewCell.swift @@ -51,14 +51,14 @@ final class ProjectNavigatorTableViewCell: FileSystemTableViewCell { } override func controlTextDidEndEditing(_ obj: Notification) { - label.backgroundColor = validateFileName(for: label?.stringValue ?? "") ? .none : errorRed - if validateFileName(for: label?.stringValue ?? "") { + label.backgroundColor = fileItem.validateFileName(for: label?.stringValue ?? "") ? .none : errorRed + if fileItem.validateFileName(for: label?.stringValue ?? "") { let destinationURL = fileItem.url .deletingLastPathComponent() .appendingPathComponent(label?.stringValue ?? "") delegate?.moveFile(file: fileItem, to: destinationURL) } else { - label?.stringValue = fileItem.name + label?.stringValue = fileItem.labelFileName() } } } diff --git a/CodeEdit/Features/NavigatorSidebar/ProjectNavigator/OutlineView/ProjectNavigatorViewController+OutlineTableViewCellDelegate.swift b/CodeEdit/Features/NavigatorSidebar/ProjectNavigator/OutlineView/ProjectNavigatorViewController+OutlineTableViewCellDelegate.swift index 1f23f4f13..4f2a4ab6f 100644 --- a/CodeEdit/Features/NavigatorSidebar/ProjectNavigator/OutlineView/ProjectNavigatorViewController+OutlineTableViewCellDelegate.swift +++ b/CodeEdit/Features/NavigatorSidebar/ProjectNavigator/OutlineView/ProjectNavigatorViewController+OutlineTableViewCellDelegate.swift @@ -16,7 +16,7 @@ extension ProjectNavigatorViewController: OutlineTableViewCellDelegate { } file.move(to: destination) if !file.isFolder { - workspace?.tabManager.openTab(item: file) + workspace?.tabManager.openTab(item: .init(url: destination)) } } diff --git a/CodeEdit/Features/Settings/Pages/TextEditingSettings/TextEditingSettingsView.swift b/CodeEdit/Features/Settings/Pages/TextEditingSettings/TextEditingSettingsView.swift index 7ea3e93fc..ea55c2f88 100644 --- a/CodeEdit/Features/Settings/Pages/TextEditingSettings/TextEditingSettingsView.swift +++ b/CodeEdit/Features/Settings/Pages/TextEditingSettings/TextEditingSettingsView.swift @@ -122,7 +122,7 @@ private extension TextEditingSettingsView { get: { Double(textEditing.defaultTabWidth) }, set: { textEditing.defaultTabWidth = Int($0) } ), - in: 1...8, + in: 1...16, step: 1, format: .number ) diff --git a/CodeEdit/Utils/Extensions/String/String+Lines.swift b/CodeEdit/Utils/Extensions/String/String+Lines.swift new file mode 100644 index 000000000..b6eacb853 --- /dev/null +++ b/CodeEdit/Utils/Extensions/String/String+Lines.swift @@ -0,0 +1,54 @@ +// +// String+Lines.swift +// CodeEdit +// +// Created by Khan Winter on 6/17/23. +// + +import Foundation + +extension String { + /// Calculates the first `n` lines and returns them as a new string. + /// - Parameters: + /// - lines: The number of lines to return. + /// - maxLength: The maximum number of characters to copy. + /// - Returns: A new string containing the lines. + func getFirstLines(_ lines: Int = 1, maxLength: Int = 512) -> String { + var string = "" + var foundLines = 0 + var totalLength = 0 + for char in self.lazy { + if char.isNewline { + foundLines += 1 + } + totalLength += 1 + if foundLines >= lines || totalLength >= maxLength { + break + } + string.append(char) + } + return string + } + + /// Calculates the last `n` lines and returns them as a new string. + /// - Parameters: + /// - lines: The number of lines to return. + /// - maxLength: The maximum number of characters to copy. + /// - Returns: A new string containing the lines. + func getLastLines(_ lines: Int = 1, maxLength: Int = 512) -> String { + var string = "" + var foundLines = 0 + var totalLength = 0 + for char in self.lazy.reversed() { + if char.isNewline { + foundLines += 1 + } + totalLength += 1 + if foundLines >= lines || totalLength >= maxLength { + break + } + string = String(char) + string + } + return string + } +}