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
+    }
+}