Showing preview only (2,562K chars total). Download the full file or copy to clipboard to get everything.
Repository: CodeEditApp/CodeEdit
Branch: main
Commit: cec6287a49a0
Files: 801
Total size: 2.3 MB
Directory structure:
gitextract_uziqjivf/
├── .all-contributorsrc
├── .github/
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.yml
│ │ └── feature_request.yml
│ ├── pull_request_template.md
│ ├── release-drafter.yml
│ ├── scripts/
│ │ ├── remove_todos.sh
│ │ ├── test_app.sh
│ │ └── test_version_number.sh
│ ├── stale.yml
│ └── workflows/
│ ├── CI-bump-build-number.yml
│ ├── CI-pre-release.yml
│ ├── CI-pull-request.yml
│ ├── CI-release-notes.yml
│ ├── add-to-project.yml
│ ├── appcast.yml
│ ├── issue.yml
│ ├── lint.yml
│ ├── pre-release.yml
│ ├── release-drafter.yml
│ └── tests.yml
├── .gitignore
├── .swiftlint.yml
├── AppCast/
│ ├── .gitignore
│ ├── Gemfile
│ ├── _config.yml
│ ├── _includes/
│ │ └── appcast.inc
│ ├── _plugins/
│ │ └── signature_filter.rb
│ ├── appcast.xml
│ └── appcast_pre.xml
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── CodeEdit/
│ ├── AppDelegate.swift
│ ├── Assets.xcassets/
│ │ ├── AccentColor.colorset/
│ │ │ └── Contents.json
│ │ ├── AppIcon.appiconset/
│ │ │ └── Contents.json
│ │ ├── AppIconAlpha.appiconset/
│ │ │ └── Contents.json
│ │ ├── AppIconBeta.appiconset/
│ │ │ └── Contents.json
│ │ ├── AppIconDev.appiconset/
│ │ │ └── Contents.json
│ │ ├── AppIconPre.appiconset/
│ │ │ └── Contents.json
│ │ ├── Contents.json
│ │ ├── Custom Colors/
│ │ │ ├── Amber.colorset/
│ │ │ │ └── Contents.json
│ │ │ ├── Contents.json
│ │ │ ├── CoolGray.colorset/
│ │ │ │ └── Contents.json
│ │ │ ├── FolderBlue.colorset/
│ │ │ │ └── Contents.json
│ │ │ ├── InspectorBackgroundColor.colorset/
│ │ │ │ └── Contents.json
│ │ │ ├── Scarlet.colorset/
│ │ │ │ └── Contents.json
│ │ │ └── Steel.colorset/
│ │ │ └── Contents.json
│ │ ├── Icons/
│ │ │ ├── BitBucketIcon.imageset/
│ │ │ │ └── Contents.json
│ │ │ ├── Contents.json
│ │ │ ├── GitHubIcon.imageset/
│ │ │ │ └── Contents.json
│ │ │ └── GitLabIcon.imageset/
│ │ │ └── Contents.json
│ │ ├── line.3.horizontal.decrease.chevron.filled.imageset/
│ │ │ └── Contents.json
│ │ └── line.3.horizontal.decrease.chevron.imageset/
│ │ └── Contents.json
│ ├── CodeEdit.entitlements
│ ├── CodeEditApp.swift
│ ├── Features/
│ │ ├── About/
│ │ │ ├── AboutFooterView.swift
│ │ │ ├── AboutSubtitleView.swift
│ │ │ ├── Acknowledgements/
│ │ │ │ ├── ViewModels/
│ │ │ │ │ └── AcknowledgementsViewModel.swift
│ │ │ │ └── Views/
│ │ │ │ ├── AcknowledgementRowView.swift
│ │ │ │ ├── AcknowledgementsView.swift
│ │ │ │ └── ParsePackagesResolved.swift
│ │ │ ├── BlurButtonStyle.swift
│ │ │ └── Contributors/
│ │ │ ├── ContributorRowView.swift
│ │ │ ├── ContributorsView.swift
│ │ │ └── Model/
│ │ │ └── Contributor.swift
│ │ ├── ActivityViewer/
│ │ │ ├── ActivityViewer.swift
│ │ │ ├── Models/
│ │ │ │ └── TaskNotificationModel.swift
│ │ │ ├── Notifications/
│ │ │ │ ├── CECircularProgressView.swift
│ │ │ │ ├── TaskNotificationHandler.swift
│ │ │ │ ├── TaskNotificationView.swift
│ │ │ │ └── TaskNotificationsDetailView.swift
│ │ │ └── Tasks/
│ │ │ ├── ActiveTaskView.swift
│ │ │ ├── DropdownMenuItemStyleModifier.swift
│ │ │ ├── OptionMenuItemView.swift
│ │ │ ├── SchemeDropDownView.swift
│ │ │ ├── TaskDropDownView.swift
│ │ │ ├── TaskView.swift
│ │ │ ├── TasksPopoverMenuItem.swift
│ │ │ └── WorkspaceMenuItemView.swift
│ │ ├── CEWorkspace/
│ │ │ └── Models/
│ │ │ ├── CEWorkspaceFile+Recursion.swift
│ │ │ ├── CEWorkspaceFile.swift
│ │ │ ├── CEWorkspaceFileIcon.swift
│ │ │ ├── CEWorkspaceFileManager+DirectoryEvents.swift
│ │ │ ├── CEWorkspaceFileManager+Error.swift
│ │ │ ├── CEWorkspaceFileManager+FileManagement.swift
│ │ │ ├── CEWorkspaceFileManager.swift
│ │ │ └── DirectoryEventStream.swift
│ │ ├── CEWorkspaceSettings/
│ │ │ ├── Models/
│ │ │ │ ├── CETask.swift
│ │ │ │ ├── CEWorkspaceSettings.swift
│ │ │ │ ├── CEWorkspaceSettingsData+ProjectSettings.swift
│ │ │ │ └── CEWorkspaceSettingsData.swift
│ │ │ └── Views/
│ │ │ ├── AddCETaskView.swift
│ │ │ ├── CETaskFormView.swift
│ │ │ ├── CEWorkspaceSettingsTaskListView.swift
│ │ │ ├── CEWorkspaceSettingsView.swift
│ │ │ ├── EditCETaskView.swift
│ │ │ └── EnvironmentVariableListItem.swift
│ │ ├── CodeEditUI/
│ │ │ ├── Styles/
│ │ │ │ ├── IconButtonStyle.swift
│ │ │ │ ├── IconToggleStyle.swift
│ │ │ │ ├── MenuWithButtonStyle.swift
│ │ │ │ └── OverlayButtonStyle.swift
│ │ │ └── Views/
│ │ │ ├── CEContentUnavailableView.swift
│ │ │ ├── CEOutlineGroup.swift
│ │ │ ├── Divided.swift
│ │ │ ├── EffectView.swift
│ │ │ ├── ErrorDescriptionLabel.swift
│ │ │ ├── FeatureIcon.swift
│ │ │ ├── GlassEffectView.swift
│ │ │ ├── HelpButton.swift
│ │ │ ├── InstantPopoverModifier.swift
│ │ │ ├── KeyValueTable.swift
│ │ │ ├── PaneTextField.swift
│ │ │ ├── PanelDivider.swift
│ │ │ ├── PopoverContainer.swift
│ │ │ ├── PressActionsModifier.swift
│ │ │ ├── ScrollOffsetPreferenceKey.swift
│ │ │ ├── SearchField.swift
│ │ │ ├── SearchPanel.swift
│ │ │ ├── SearchPanelView.swift
│ │ │ ├── SegmentedControl.swift
│ │ │ ├── SettingsTextEditor.swift
│ │ │ ├── ToolbarBranchPicker.swift
│ │ │ ├── TrackableScrollView.swift
│ │ │ ├── WorkspacePanelTabBar.swift
│ │ │ └── WorkspacePanelView.swift
│ │ ├── Commands/
│ │ │ ├── ViewModels/
│ │ │ │ └── QuickActionsViewModel.swift
│ │ │ └── Views/
│ │ │ └── QuickActionsView.swift
│ │ ├── Documents/
│ │ │ ├── CodeFileDocument/
│ │ │ │ ├── CodeFileDocument.swift
│ │ │ │ └── FileEncoding.swift
│ │ │ ├── Controllers/
│ │ │ │ ├── CodeEditDocumentController.swift
│ │ │ │ ├── CodeEditSplitViewController.swift
│ │ │ │ ├── CodeEditWindowController+Panels.swift
│ │ │ │ ├── CodeEditWindowController+Toolbar.swift
│ │ │ │ ├── CodeEditWindowController.swift
│ │ │ │ └── CodeEditWindowControllerExtensions.swift
│ │ │ ├── Indexer/
│ │ │ │ ├── AsyncFileIterator.swift
│ │ │ │ ├── FileHelper.swift
│ │ │ │ ├── SearchIndexer+Add.swift
│ │ │ │ ├── SearchIndexer+AsyncController.swift
│ │ │ │ ├── SearchIndexer+File.swift
│ │ │ │ ├── SearchIndexer+InternalMethods.swift
│ │ │ │ ├── SearchIndexer+Memory.swift
│ │ │ │ ├── SearchIndexer+ProgressiveSearch.swift
│ │ │ │ ├── SearchIndexer+Search.swift
│ │ │ │ ├── SearchIndexer+Terms.swift
│ │ │ │ └── SearchIndexer.swift
│ │ │ └── WorkspaceDocument/
│ │ │ ├── WorkspaceDocument+Find.swift
│ │ │ ├── WorkspaceDocument+FindAndReplace.swift
│ │ │ ├── WorkspaceDocument+Index.swift
│ │ │ ├── WorkspaceDocument+Listeners.swift
│ │ │ ├── WorkspaceDocument+SearchState.swift
│ │ │ ├── WorkspaceDocument.swift
│ │ │ └── WorkspaceStateKey.swift
│ │ ├── Editor/
│ │ │ ├── JumpBar/
│ │ │ │ └── Views/
│ │ │ │ ├── EditorJumpBarComponent.swift
│ │ │ │ ├── EditorJumpBarMenu.swift
│ │ │ │ └── EditorJumpBarView.swift
│ │ │ ├── Models/
│ │ │ │ ├── Editor/
│ │ │ │ │ ├── Editor+History.swift
│ │ │ │ │ ├── Editor+TabSwitch.swift
│ │ │ │ │ └── Editor.swift
│ │ │ │ ├── EditorInstance.swift
│ │ │ │ ├── EditorLayout/
│ │ │ │ │ ├── EditorLayout+StateRestoration.swift
│ │ │ │ │ └── EditorLayout.swift
│ │ │ │ ├── EditorManager.swift
│ │ │ │ ├── Environment+ActiveEditor.swift
│ │ │ │ └── Restoration/
│ │ │ │ ├── EditorStateRestoration.swift
│ │ │ │ └── UndoManagerRegistration.swift
│ │ │ ├── TabBar/
│ │ │ │ ├── Tabs/
│ │ │ │ │ ├── Tab/
│ │ │ │ │ │ ├── EditorFileTabCloseButton.swift
│ │ │ │ │ │ ├── EditorTabBackground.swift
│ │ │ │ │ │ ├── EditorTabButtonStyle.swift
│ │ │ │ │ │ ├── EditorTabCloseButton.swift
│ │ │ │ │ │ ├── EditorTabView.swift
│ │ │ │ │ │ └── Models/
│ │ │ │ │ │ ├── EditorItemID.swift
│ │ │ │ │ │ ├── EditorTabFileObserver.swift
│ │ │ │ │ │ └── EditorTabRepresentable.swift
│ │ │ │ │ └── Views/
│ │ │ │ │ ├── EditorTabs.swift
│ │ │ │ │ └── EditorTabsOverflowShadow.swift
│ │ │ │ └── Views/
│ │ │ │ ├── EditorHistoryMenus.swift
│ │ │ │ ├── EditorTabBarAccessory.swift
│ │ │ │ ├── EditorTabBarContextMenu.swift
│ │ │ │ ├── EditorTabBarDivider.swift
│ │ │ │ ├── EditorTabBarLeadingAccessories.swift
│ │ │ │ ├── EditorTabBarTrailingAccessories.swift
│ │ │ │ └── EditorTabBarView.swift
│ │ │ └── Views/
│ │ │ ├── AnyFileView.swift
│ │ │ ├── CodeFileView.swift
│ │ │ ├── EditorAreaFileView.swift
│ │ │ ├── EditorAreaView.swift
│ │ │ ├── EditorLayoutView.swift
│ │ │ ├── ImageFileView.swift
│ │ │ ├── LoadingFileView.swift
│ │ │ ├── NonTextFileView.swift
│ │ │ ├── PDFFileView.swift
│ │ │ └── WindowCodeFileView.swift
│ │ ├── Extensions/
│ │ │ ├── Commands+ForEach.swift
│ │ │ ├── ExtensionActivatorView.swift
│ │ │ ├── ExtensionDetailView.swift
│ │ │ ├── ExtensionDiscovery.swift
│ │ │ ├── ExtensionInfo.swift
│ │ │ ├── ExtensionManagerWindow.swift
│ │ │ ├── ExtensionSceneView.swift
│ │ │ ├── ExtensionsListView.swift
│ │ │ ├── ExtensionsManager.swift
│ │ │ └── codeedit.extension.appextensionpoint
│ │ ├── Feedback/
│ │ │ ├── Controllers/
│ │ │ │ └── FeedbackWindowController.swift
│ │ │ ├── FeedbackView.swift
│ │ │ ├── HelperView/
│ │ │ │ └── FeedbackToolbar.swift
│ │ │ └── Model/
│ │ │ ├── FeedbackIssueArea.swift
│ │ │ ├── FeedbackModel.swift
│ │ │ └── FeedbackType.swift
│ │ ├── InspectorArea/
│ │ │ ├── FileInspector/
│ │ │ │ └── FileInspectorView.swift
│ │ │ ├── HistoryInspector/
│ │ │ │ ├── HistoryInspectorItemView.swift
│ │ │ │ ├── HistoryInspectorModel.swift
│ │ │ │ ├── HistoryInspectorView.swift
│ │ │ │ └── HistoryPopoverView.swift
│ │ │ ├── InternalDevelopmentInspector/
│ │ │ │ ├── InternalDevelopmentInspectorView.swift
│ │ │ │ ├── InternalDevelopmentNotificationsView.swift
│ │ │ │ └── InternalDevelopmentOutputView.swift
│ │ │ ├── Models/
│ │ │ │ └── InspectorTab.swift
│ │ │ ├── ViewModels/
│ │ │ │ └── InspectorAreaViewModel.swift
│ │ │ └── Views/
│ │ │ ├── InspectorAreaView.swift
│ │ │ ├── InspectorField.swift
│ │ │ ├── InspectorSection.swift
│ │ │ └── NoSelectionInspectorView.swift
│ │ ├── Keybindings/
│ │ │ ├── CommandManager.swift
│ │ │ ├── KeybindingManager.swift
│ │ │ ├── ModifierKeysObserver.swift
│ │ │ └── default_keybindings.json
│ │ ├── LSP/
│ │ │ ├── Features/
│ │ │ │ ├── DocumentSync/
│ │ │ │ │ └── LSPContentCoordinator.swift
│ │ │ │ └── SemanticTokens/
│ │ │ │ ├── SemanticTokenHighlightProvider.swift
│ │ │ │ ├── SemanticTokenMap.swift
│ │ │ │ ├── SemanticTokenMapRangeProvider.swift
│ │ │ │ └── SemanticTokenStorage/
│ │ │ │ ├── GenericSemanticTokenStorage.swift
│ │ │ │ ├── SemanticTokenRange.swift
│ │ │ │ └── SemanticTokenStorage.swift
│ │ │ ├── LSPUtil.swift
│ │ │ ├── LanguageServer/
│ │ │ │ ├── Capabilities/
│ │ │ │ │ ├── LanguageServer+CallHierarchy.swift
│ │ │ │ │ ├── LanguageServer+ColorPresentation.swift
│ │ │ │ │ ├── LanguageServer+Completion.swift
│ │ │ │ │ ├── LanguageServer+Declaration.swift
│ │ │ │ │ ├── LanguageServer+Definition.swift
│ │ │ │ │ ├── LanguageServer+Diagnostics.swift
│ │ │ │ │ ├── LanguageServer+DocumentColor.swift
│ │ │ │ │ ├── LanguageServer+DocumentHighlight.swift
│ │ │ │ │ ├── LanguageServer+DocumentLink.swift
│ │ │ │ │ ├── LanguageServer+DocumentSymbol.swift
│ │ │ │ │ ├── LanguageServer+DocumentSync.swift
│ │ │ │ │ ├── LanguageServer+FoldingRange.swift
│ │ │ │ │ ├── LanguageServer+Formatting.swift
│ │ │ │ │ ├── LanguageServer+Hover.swift
│ │ │ │ │ ├── LanguageServer+Implementation.swift
│ │ │ │ │ ├── LanguageServer+InlayHint.swift
│ │ │ │ │ ├── LanguageServer+References.swift
│ │ │ │ │ ├── LanguageServer+Rename.swift
│ │ │ │ │ ├── LanguageServer+SelectionRange.swift
│ │ │ │ │ ├── LanguageServer+SemanticTokens.swift
│ │ │ │ │ ├── LanguageServer+SignatureHelp.swift
│ │ │ │ │ └── LanguageServer+TypeDefinition.swift
│ │ │ │ ├── LSPCache+Data.swift
│ │ │ │ ├── LSPCache.swift
│ │ │ │ ├── LanguageServer.swift
│ │ │ │ └── LanguageServerFileMap.swift
│ │ │ ├── LanguageServerDocument.swift
│ │ │ ├── Registry/
│ │ │ │ ├── Errors/
│ │ │ │ │ ├── PackageManagerError.swift
│ │ │ │ │ └── RegistryManagerError.swift
│ │ │ │ ├── Model/
│ │ │ │ │ ├── InstallationMethod.swift
│ │ │ │ │ ├── PackageManagerType.swift
│ │ │ │ │ ├── PackageSource.swift
│ │ │ │ │ ├── RegistryItem+Source.swift
│ │ │ │ │ └── RegistryItem.swift
│ │ │ │ ├── PackageManagerProtocol.swift
│ │ │ │ ├── PackageManagers/
│ │ │ │ │ ├── Install/
│ │ │ │ │ │ ├── InstallStepConfirmation.swift
│ │ │ │ │ │ ├── PackageManagerInstallOperation.swift
│ │ │ │ │ │ ├── PackageManagerInstallStep.swift
│ │ │ │ │ │ └── PackageManagerProgressModel.swift
│ │ │ │ │ └── Sources/
│ │ │ │ │ ├── CargoPackageManager.swift
│ │ │ │ │ ├── GithubPackageManager.swift
│ │ │ │ │ ├── GolangPackageManager.swift
│ │ │ │ │ ├── NPMPackageManager.swift
│ │ │ │ │ └── PipPackageManager.swift
│ │ │ │ ├── PackageSourceParser/
│ │ │ │ │ ├── PackageSourceParser+Cargo.swift
│ │ │ │ │ ├── PackageSourceParser+Gem.swift
│ │ │ │ │ ├── PackageSourceParser+Golang.swift
│ │ │ │ │ ├── PackageSourceParser+NPM.swift
│ │ │ │ │ ├── PackageSourceParser+PYPI.swift
│ │ │ │ │ └── PackageSourceParser.swift
│ │ │ │ ├── RegistryItemTemplateParser.swift
│ │ │ │ ├── RegistryManager+HandleRegistryFile.swift
│ │ │ │ └── RegistryManager.swift
│ │ │ └── Service/
│ │ │ ├── LSPService+Events.swift
│ │ │ ├── LSPService.swift
│ │ │ └── LSPServiceError.swift
│ │ ├── NavigatorArea/
│ │ │ ├── FindNavigator/
│ │ │ │ ├── FindModePicker.swift
│ │ │ │ ├── FindNavigatorForm.swift
│ │ │ │ ├── FindNavigatorIndexBar.swift
│ │ │ │ ├── FindNavigatorResultList/
│ │ │ │ │ ├── FindNavigatorListViewController.swift
│ │ │ │ │ ├── FindNavigatorMatchListCell.swift
│ │ │ │ │ └── FindNavigatorResultList.swift
│ │ │ │ ├── FindNavigatorToolbarBottom.swift
│ │ │ │ └── FindNavigatorView.swift
│ │ │ ├── Models/
│ │ │ │ └── NavigatorTab.swift
│ │ │ ├── OutlineView/
│ │ │ │ ├── FileSystemTableViewCell.swift
│ │ │ │ ├── StandardTableViewCell.swift
│ │ │ │ └── TextTableViewCell.swift
│ │ │ ├── ProjectNavigator/
│ │ │ │ ├── OutlineView/
│ │ │ │ │ ├── ProjectNavigatorMenu.swift
│ │ │ │ │ ├── ProjectNavigatorMenuActions.swift
│ │ │ │ │ ├── ProjectNavigatorNSOutlineView.swift
│ │ │ │ │ ├── ProjectNavigatorOutlineView.swift
│ │ │ │ │ ├── ProjectNavigatorTableViewCell.swift
│ │ │ │ │ ├── ProjectNavigatorViewController+NSMenuDelegate.swift
│ │ │ │ │ ├── ProjectNavigatorViewController+NSOutlineViewDataSource.swift
│ │ │ │ │ ├── ProjectNavigatorViewController+NSOutlineViewDelegate.swift
│ │ │ │ │ ├── ProjectNavigatorViewController+OutlineTableViewCellDelegate.swift
│ │ │ │ │ └── ProjectNavigatorViewController.swift
│ │ │ │ ├── ProjectNavigatorToolbarBottom.swift
│ │ │ │ └── ProjectNavigatorView.swift
│ │ │ ├── SourceControlNavigator/
│ │ │ │ ├── Changes/
│ │ │ │ │ └── Views/
│ │ │ │ │ ├── SourceControlNavigatorChangesCommitView.swift
│ │ │ │ │ ├── SourceControlNavigatorChangesList.swift
│ │ │ │ │ ├── SourceControlNavigatorChangesView.swift
│ │ │ │ │ ├── SourceControlNavigatorNoRemotesView.swift
│ │ │ │ │ └── SourceControlNavigatorSyncView.swift
│ │ │ │ ├── History/
│ │ │ │ │ └── Views/
│ │ │ │ │ ├── CommitDetailsHeaderView.swift
│ │ │ │ │ ├── CommitDetailsView.swift
│ │ │ │ │ ├── CommitListItemView.swift
│ │ │ │ │ └── SourceControlNavigatorHistoryView.swift
│ │ │ │ ├── Repository/
│ │ │ │ │ ├── Models/
│ │ │ │ │ │ └── RepoOutlineGroupItem.swift
│ │ │ │ │ └── Views/
│ │ │ │ │ ├── SourceControlNavigatorRepositoryItem.swift
│ │ │ │ │ ├── SourceControlNavigatorRepositoryView+contextMenu.swift
│ │ │ │ │ ├── SourceControlNavigatorRepositoryView+outlineGroupData.swift
│ │ │ │ │ └── SourceControlNavigatorRepositoryView.swift
│ │ │ │ └── Views/
│ │ │ │ ├── ChangedFile/
│ │ │ │ │ ├── GitChangedFileLabel.swift
│ │ │ │ │ └── GitChangedFileListView.swift
│ │ │ │ ├── SourceControlNavigatorToolbarBottom.swift
│ │ │ │ └── SourceControlNavigatorView.swift
│ │ │ ├── ViewModels/
│ │ │ │ └── NavigatorAreaViewModel.swift
│ │ │ └── Views/
│ │ │ └── NavigatorAreaView.swift
│ │ ├── Notifications/
│ │ │ ├── Models/
│ │ │ │ └── CENotification.swift
│ │ │ ├── NotificationManager+Delegate.swift
│ │ │ ├── NotificationManager+System.swift
│ │ │ ├── NotificationManager.swift
│ │ │ ├── ViewModels/
│ │ │ │ └── NotificationPanelViewModel.swift
│ │ │ └── Views/
│ │ │ ├── NotificationBannerView.swift
│ │ │ ├── NotificationPanelView.swift
│ │ │ └── NotificationToolbarItem.swift
│ │ ├── OpenQuickly/
│ │ │ ├── ViewModels/
│ │ │ │ └── OpenQuicklyViewModel.swift
│ │ │ └── Views/
│ │ │ ├── NSTableViewWrapper.swift
│ │ │ ├── OpenQuicklyListItemView.swift
│ │ │ ├── OpenQuicklyPreviewView.swift
│ │ │ └── OpenQuicklyView.swift
│ │ ├── Search/
│ │ │ ├── Extensions/
│ │ │ │ └── String+SafeOffset.swift
│ │ │ ├── FuzzySearch/
│ │ │ │ ├── Collection+FuzzySearch.swift
│ │ │ │ ├── FuzzySearchModels.swift
│ │ │ │ ├── FuzzySearchUIModel.swift
│ │ │ │ ├── FuzzySearchable.swift
│ │ │ │ ├── String+LengthOfMatchingPrefix.swift
│ │ │ │ └── String+Normalise.swift
│ │ │ ├── Model/
│ │ │ │ ├── SearchModeModel.swift
│ │ │ │ ├── SearchResultMatchModel.swift
│ │ │ │ └── SearchResultModel.swift
│ │ │ └── Views/
│ │ │ └── QuickSearchResultLabel.swift
│ │ ├── Settings/
│ │ │ ├── Models/
│ │ │ │ ├── AppSettings.swift
│ │ │ │ ├── GlobPattern.swift
│ │ │ │ ├── PageAndSettings.swift
│ │ │ │ ├── Settings.swift
│ │ │ │ ├── SettingsData.swift
│ │ │ │ ├── SettingsInjector.swift
│ │ │ │ ├── SettingsPage.swift
│ │ │ │ ├── SettingsSearchResult.swift
│ │ │ │ └── SettingsSidebarFix.swift
│ │ │ ├── Pages/
│ │ │ │ ├── AccountsSettings/
│ │ │ │ │ ├── AccountSelectionView.swift
│ │ │ │ │ ├── AccountsSettingsAccountLink.swift
│ │ │ │ │ ├── AccountsSettingsDetailsView.swift
│ │ │ │ │ ├── AccountsSettingsProviderRow.swift
│ │ │ │ │ ├── AccountsSettingsSigninView.swift
│ │ │ │ │ ├── AccountsSettingsView.swift
│ │ │ │ │ ├── CreateSSHKeyView.swift
│ │ │ │ │ └── Models/
│ │ │ │ │ ├── AccountsSettings.swift
│ │ │ │ │ └── SourceControlAccount.swift
│ │ │ │ ├── DeveloperSettings/
│ │ │ │ │ ├── DeveloperSettingsView.swift
│ │ │ │ │ └── Models/
│ │ │ │ │ └── DeveloperSettings.swift
│ │ │ │ ├── Extensions/
│ │ │ │ │ ├── LanguageServerInstallView.swift
│ │ │ │ │ ├── LanguageServerRowView.swift
│ │ │ │ │ ├── LanguageServersView.swift
│ │ │ │ │ └── Models/
│ │ │ │ │ └── LanguageServerSettings.swift
│ │ │ │ ├── GeneralSettings/
│ │ │ │ │ ├── GeneralSettingsView.swift
│ │ │ │ │ ├── Models/
│ │ │ │ │ │ └── GeneralSettings.swift
│ │ │ │ │ └── View+actionBar.swift
│ │ │ │ ├── Keybindings/
│ │ │ │ │ └── Models/
│ │ │ │ │ └── KeybindingsSettings.swift
│ │ │ │ ├── LocationsSettings/
│ │ │ │ │ ├── LocationsSettingsView.swift
│ │ │ │ │ └── Models/
│ │ │ │ │ └── LocationsSettings.swift
│ │ │ │ ├── NavigationSettings/
│ │ │ │ │ ├── Models/
│ │ │ │ │ │ └── NavigationSettings.swift
│ │ │ │ │ └── NavigationSettingsView.swift
│ │ │ │ ├── SearchSettings/
│ │ │ │ │ ├── Models/
│ │ │ │ │ │ ├── SearchSettings.swift
│ │ │ │ │ │ └── SearchSettingsModel.swift
│ │ │ │ │ ├── SearchSettingsIgnoreGlobPatternItemView.swift
│ │ │ │ │ └── SearchSettingsView.swift
│ │ │ │ ├── SourceControlSettings/
│ │ │ │ │ ├── IgnoredFilesListView.swift
│ │ │ │ │ ├── Models/
│ │ │ │ │ │ ├── IgnorePatternModel.swift
│ │ │ │ │ │ └── SourceControlSettings.swift
│ │ │ │ │ ├── SourceControlGeneralView.swift
│ │ │ │ │ ├── SourceControlGitView.swift
│ │ │ │ │ └── SourceControlSettingsView.swift
│ │ │ │ ├── TerminalSettings/
│ │ │ │ │ ├── Models/
│ │ │ │ │ │ └── TerminalSettings.swift
│ │ │ │ │ └── TerminalSettingsView.swift
│ │ │ │ ├── TextEditingSettings/
│ │ │ │ │ ├── InvisiblesSettingsView.swift
│ │ │ │ │ ├── Models/
│ │ │ │ │ │ ├── NSFont+WithWeight.swift
│ │ │ │ │ │ └── TextEditingSettings.swift
│ │ │ │ │ └── TextEditingSettingsView.swift
│ │ │ │ └── ThemeSettings/
│ │ │ │ ├── Models/
│ │ │ │ │ ├── Theme+FuzzySearchable.swift
│ │ │ │ │ ├── Theme.swift
│ │ │ │ │ ├── ThemeModel+CRUD.swift
│ │ │ │ │ ├── ThemeModel.swift
│ │ │ │ │ └── ThemeSettings.swift
│ │ │ │ ├── ThemeSettingThemeRow.swift
│ │ │ │ ├── ThemeSettingsColorPreview.swift
│ │ │ │ ├── ThemeSettingsThemeDetails.swift
│ │ │ │ ├── ThemeSettingsThemeToken.swift
│ │ │ │ └── ThemeSettingsView.swift
│ │ │ ├── SettingsView.swift
│ │ │ ├── SettingsWindow.swift
│ │ │ ├── SoftwareUpdater.swift
│ │ │ └── Views/
│ │ │ ├── ExternalLink.swift
│ │ │ ├── FontWeightPicker.swift
│ │ │ ├── GlobPatternList.swift
│ │ │ ├── GlobPatternListItem.swift
│ │ │ ├── InvisibleCharacterWarningList.swift
│ │ │ ├── MonospacedFontPicker.swift
│ │ │ ├── SettingsColorPicker.swift
│ │ │ ├── SettingsForm.swift
│ │ │ ├── SettingsPageView.swift
│ │ │ ├── View+ConstrainHeightToWindow.swift
│ │ │ ├── View+HideSidebarToggle.swift
│ │ │ ├── View+NavigationBarBackButtonVisible.swift
│ │ │ └── WarningCharactersView.swift
│ │ ├── SourceControl/
│ │ │ ├── Accounts/
│ │ │ │ ├── Bitbucket/
│ │ │ │ │ ├── BitBucketAccount+Token.swift
│ │ │ │ │ ├── BitBucketAccount.swift
│ │ │ │ │ ├── BitBucketOAuthConfiguration.swift
│ │ │ │ │ ├── BitBucketTokenConfiguration.swift
│ │ │ │ │ ├── Model/
│ │ │ │ │ │ ├── BitBucketRepositories.swift
│ │ │ │ │ │ └── BitBucketUser.swift
│ │ │ │ │ └── Routers/
│ │ │ │ │ ├── BitBucketOAuthRouter.swift
│ │ │ │ │ ├── BitBucketRepositoryRouter.swift
│ │ │ │ │ ├── BitBucketTokenRouter.swift
│ │ │ │ │ └── BitBucketUserRouter.swift
│ │ │ │ ├── GitHub/
│ │ │ │ │ ├── GitHubAccount.swift
│ │ │ │ │ ├── GitHubConfiguration.swift
│ │ │ │ │ ├── GitHubOpenness.swift
│ │ │ │ │ ├── GitHubPreviewHeader.swift
│ │ │ │ │ ├── Model/
│ │ │ │ │ │ ├── GitHubAccount+deleteReference.swift
│ │ │ │ │ │ ├── GitHubComment.swift
│ │ │ │ │ │ ├── GitHubFiles.swift
│ │ │ │ │ │ ├── GitHubGist.swift
│ │ │ │ │ │ ├── GitHubIssue.swift
│ │ │ │ │ │ ├── GitHubPullRequest.swift
│ │ │ │ │ │ ├── GitHubRepositories.swift
│ │ │ │ │ │ ├── GitHubReview.swift
│ │ │ │ │ │ └── GitHubUser.swift
│ │ │ │ │ ├── PublicKey.swift
│ │ │ │ │ └── Routers/
│ │ │ │ │ ├── GitHubGistRouter.swift
│ │ │ │ │ ├── GitHubIssueRouter.swift
│ │ │ │ │ ├── GitHubPullRequestRouter.swift
│ │ │ │ │ ├── GitHubRepositoryRouter.swift
│ │ │ │ │ ├── GitHubReviewsRouter.swift
│ │ │ │ │ ├── GitHubRouter.swift
│ │ │ │ │ └── GitHubUserRouter.swift
│ │ │ │ ├── GitLab/
│ │ │ │ │ ├── GitLabAccount.swift
│ │ │ │ │ ├── GitLabConfiguration.swift
│ │ │ │ │ ├── GitLabOAuthConfiguration.swift
│ │ │ │ │ ├── Model/
│ │ │ │ │ │ ├── GitLabAccountModel.swift
│ │ │ │ │ │ ├── GitLabAvatarURL.swift
│ │ │ │ │ │ ├── GitLabCommit.swift
│ │ │ │ │ │ ├── GitLabEvent.swift
│ │ │ │ │ │ ├── GitLabEventData.swift
│ │ │ │ │ │ ├── GitLabEventNote.swift
│ │ │ │ │ │ ├── GitLabGroupAccess.swift
│ │ │ │ │ │ ├── GitLabNamespace.swift
│ │ │ │ │ │ ├── GitLabPermissions.swift
│ │ │ │ │ │ ├── GitLabProject.swift
│ │ │ │ │ │ ├── GitLabProjectAccess.swift
│ │ │ │ │ │ ├── GitLabProjectHook.swift
│ │ │ │ │ │ └── GitLabUser.swift
│ │ │ │ │ └── Routers/
│ │ │ │ │ ├── GitLabCommitRouter.swift
│ │ │ │ │ ├── GitLabOAuthRouter.swift
│ │ │ │ │ ├── GitLabProjectRouter.swift
│ │ │ │ │ └── GitLabUserRouter.swift
│ │ │ │ ├── Networking/
│ │ │ │ │ ├── GitJSONPostRouter.swift
│ │ │ │ │ ├── GitRouter.swift
│ │ │ │ │ └── GitURLSession.swift
│ │ │ │ ├── Parameters.swift
│ │ │ │ └── Utils/
│ │ │ │ ├── GitTime.swift
│ │ │ │ ├── String+PercentEncoding.swift
│ │ │ │ └── String+QueryParameters.swift
│ │ │ ├── Client/
│ │ │ │ ├── GitClient+Branches.swift
│ │ │ │ ├── GitClient+Clone.swift
│ │ │ │ ├── GitClient+Commit.swift
│ │ │ │ ├── GitClient+CommitHistory.swift
│ │ │ │ ├── GitClient+Fetch.swift
│ │ │ │ ├── GitClient+Initiate.swift
│ │ │ │ ├── GitClient+Pull.swift
│ │ │ │ ├── GitClient+Push.swift
│ │ │ │ ├── GitClient+Remote.swift
│ │ │ │ ├── GitClient+Stash.swift
│ │ │ │ ├── GitClient+Status.swift
│ │ │ │ ├── GitClient+Validate.swift
│ │ │ │ ├── GitClient.swift
│ │ │ │ ├── GitConfigClient.swift
│ │ │ │ ├── GitConfigExtensions.swift
│ │ │ │ └── GitConfigRepresentable.swift
│ │ │ ├── Clone/
│ │ │ │ ├── GitCheckoutBranchView.swift
│ │ │ │ ├── GitCloneView.swift
│ │ │ │ └── ViewModels/
│ │ │ │ ├── GitCheckoutBranchViewModel.swift
│ │ │ │ └── GitCloneViewModel.swift
│ │ │ ├── Models/
│ │ │ │ ├── GitBranch.swift
│ │ │ │ ├── GitBranchesGroup.swift
│ │ │ │ ├── GitChangedFile.swift
│ │ │ │ ├── GitCommit.swift
│ │ │ │ ├── GitRemote.swift
│ │ │ │ ├── GitStashEntry.swift
│ │ │ │ └── GitStatus.swift
│ │ │ ├── SourceControlManager+GitClient.swift
│ │ │ ├── SourceControlManager.swift
│ │ │ └── Views/
│ │ │ ├── RemoteBranchPicker.swift
│ │ │ ├── SourceControlAddExistingRemoteView.swift
│ │ │ ├── SourceControlFetchView.swift
│ │ │ ├── SourceControlNewBranchView.swift
│ │ │ ├── SourceControlPullView.swift
│ │ │ ├── SourceControlPushView.swift
│ │ │ ├── SourceControlRenameBranchView.swift
│ │ │ ├── SourceControlStashView.swift
│ │ │ └── SourceControlSwitchView.swift
│ │ ├── SplitView/
│ │ │ ├── Model/
│ │ │ │ ├── CodeEditDividerStyle.swift
│ │ │ │ ├── Environment+ContentInsets.swift
│ │ │ │ ├── Environment+SplitEditor.swift
│ │ │ │ ├── SplitViewData.swift
│ │ │ │ └── SplitViewItem.swift
│ │ │ └── Views/
│ │ │ ├── SplitView.swift
│ │ │ ├── SplitViewControllerView.swift
│ │ │ ├── SplitViewModifiers.swift
│ │ │ ├── SplitViewReader.swift
│ │ │ └── Variadic.swift
│ │ ├── StatusBar/
│ │ │ ├── Models/
│ │ │ │ └── ImageDimensions.swift
│ │ │ ├── ViewModels/
│ │ │ │ └── StatusBarViewModel.swift
│ │ │ ├── ViewModifiers/
│ │ │ │ └── UpdateStatusBarInfo.swift
│ │ │ └── Views/
│ │ │ ├── StatusBarIcon.swift
│ │ │ ├── StatusBarItems/
│ │ │ │ ├── StatusBarBreakpointButton.swift
│ │ │ │ ├── StatusBarCursorPositionLabel.swift
│ │ │ │ ├── StatusBarEncodingSelector.swift
│ │ │ │ ├── StatusBarFileInfoView.swift
│ │ │ │ ├── StatusBarIndentSelector.swift
│ │ │ │ ├── StatusBarLineEndSelector.swift
│ │ │ │ ├── StatusBarMenuStyle.swift
│ │ │ │ └── StatusBarToggleUtilityAreaButton.swift
│ │ │ └── StatusBarView.swift
│ │ ├── Tasks/
│ │ │ ├── Models/
│ │ │ │ ├── CEActiveTask.swift
│ │ │ │ └── CETaskStatus.swift
│ │ │ ├── TaskManager.swift
│ │ │ ├── ToolbarItems/
│ │ │ │ ├── StartTaskToolbarItem.swift
│ │ │ │ └── StopTaskToolbarItem.swift
│ │ │ └── Views/
│ │ │ ├── StartTaskToolbarButton.swift
│ │ │ └── StopTaskToolbarButton.swift
│ │ ├── TerminalEmulator/
│ │ │ ├── Model/
│ │ │ │ ├── CurrentUser.swift
│ │ │ │ ├── Shell.swift
│ │ │ │ ├── ShellIntegration.swift
│ │ │ │ └── TerminalCache.swift
│ │ │ └── Views/
│ │ │ ├── CEActiveTaskTerminalView.swift
│ │ │ ├── CELocalShellTerminalView.swift
│ │ │ ├── CETerminalView.swift
│ │ │ ├── TerminalEmulatorView+Coordinator.swift
│ │ │ └── TerminalEmulatorView.swift
│ │ ├── UtilityArea/
│ │ │ ├── DebugUtility/
│ │ │ │ ├── TaskOutputActionsView.swift
│ │ │ │ ├── TaskOutputView.swift
│ │ │ │ └── UtilityAreaDebugView.swift
│ │ │ ├── Models/
│ │ │ │ ├── UtilityAreaTab.swift
│ │ │ │ └── UtilityAreaTerminal.swift
│ │ │ ├── OutputUtility/
│ │ │ │ ├── Model/
│ │ │ │ │ ├── Sources/
│ │ │ │ │ │ ├── ExtensionUtilityAreaOutputSource.swift
│ │ │ │ │ │ ├── InternalDevelopmentOutputSource.swift
│ │ │ │ │ │ └── LanguageServerLogContainer.swift
│ │ │ │ │ ├── UtilityAreaLogLevel.swift
│ │ │ │ │ └── UtilityAreaOutputSource.swift
│ │ │ │ └── View/
│ │ │ │ ├── UtilityAreaOutputLogList.swift
│ │ │ │ ├── UtilityAreaOutputSourcePicker.swift
│ │ │ │ └── UtilityAreaOutputView.swift
│ │ │ ├── TerminalUtility/
│ │ │ │ ├── UtilityAreaTerminalPicker.swift
│ │ │ │ ├── UtilityAreaTerminalSidebar.swift
│ │ │ │ ├── UtilityAreaTerminalTab.swift
│ │ │ │ └── UtilityAreaTerminalView.swift
│ │ │ ├── Toolbar/
│ │ │ │ ├── UtilityAreaClearButton.swift
│ │ │ │ ├── UtilityAreaFilterTextField.swift
│ │ │ │ ├── UtilityAreaMaximizeButton.swift
│ │ │ │ └── UtilityAreaSplitTerminalButton.swift
│ │ │ ├── ViewModels/
│ │ │ │ ├── UtilityAreaTabViewModel.swift
│ │ │ │ └── UtilityAreaViewModel.swift
│ │ │ └── Views/
│ │ │ ├── PaneToolbar.swift
│ │ │ ├── UtilityAreaTabView.swift
│ │ │ ├── UtilityAreaView.swift
│ │ │ └── View+paneToolbar.swift
│ │ ├── Welcome/
│ │ │ ├── GitCloneButton.swift
│ │ │ ├── NewFileButton.swift
│ │ │ ├── OpenFileOrFolderButton.swift
│ │ │ └── WelcomeSubtitleView.swift
│ │ └── WindowCommands/
│ │ ├── CodeEditCommands.swift
│ │ ├── EditorCommands.swift
│ │ ├── ExtensionCommands.swift
│ │ ├── FileCommands.swift
│ │ ├── FindCommands.swift
│ │ ├── HelpCommands.swift
│ │ ├── MainCommands.swift
│ │ ├── NavigateCommands.swift
│ │ ├── SourceControlCommands.swift
│ │ ├── TasksCommands.swift
│ │ ├── Utils/
│ │ │ ├── CommandsFixes.swift
│ │ │ ├── FirstResponderPropertyWrapper.swift
│ │ │ ├── KeyWindowControllerObserver.swift
│ │ │ ├── RecentProjectsMenu.swift
│ │ │ └── WindowControllerPropertyWrapper.swift
│ │ ├── ViewCommands.swift
│ │ └── WindowCommands.swift
│ ├── Info.plist
│ ├── Localization/
│ │ ├── Localized+Ex.swift
│ │ └── en.lproj/
│ │ └── Localizable.strings
│ ├── Preview Content/
│ │ └── Preview Assets.xcassets/
│ │ └── Contents.json
│ ├── SceneID.swift
│ ├── ShellIntegration/
│ │ ├── codeedit_shell_integration.bash
│ │ ├── codeedit_shell_integration_env.zsh
│ │ ├── codeedit_shell_integration_login.zsh
│ │ ├── codeedit_shell_integration_profile.zsh
│ │ └── codeedit_shell_integration_rc.zsh
│ ├── Utils/
│ │ ├── DependencyInjection/
│ │ │ ├── LazyServiceWrapper.swift
│ │ │ ├── ServiceContainer.swift
│ │ │ ├── ServiceType.swift
│ │ │ └── ServiceWrapper.swift
│ │ ├── Environment/
│ │ │ ├── Env+IsFullscreen.swift
│ │ │ └── Env+Window.swift
│ │ ├── Extensions/
│ │ │ ├── Array/
│ │ │ │ ├── Array+Index.swift
│ │ │ │ └── Array+SortURLs.swift
│ │ │ ├── Bundle/
│ │ │ │ └── Bundle+Info.swift
│ │ │ ├── Collection/
│ │ │ │ └── Collection+subscript_safe.swift
│ │ │ ├── Color/
│ │ │ │ └── Color+HEX.swift
│ │ │ ├── Date/
│ │ │ │ └── Date+Formatted.swift
│ │ │ ├── FileManager/
│ │ │ │ └── FileManager+MakeExecutable.swift
│ │ │ ├── Int/
│ │ │ │ └── Int+HexString.swift
│ │ │ ├── LanguageIdentifier/
│ │ │ │ └── LanguageIdentifier+CodeLanguage.swift
│ │ │ ├── LocalProcess/
│ │ │ │ └── LocalProcess+sendText.swift
│ │ │ ├── NSApplication/
│ │ │ │ └── NSApp+openWindow.swift
│ │ │ ├── NSTableView/
│ │ │ │ └── NSTableView+Background.swift
│ │ │ ├── NSWindow/
│ │ │ │ └── NSWindow+Child.swift
│ │ │ ├── OperatingSystemVersion/
│ │ │ │ └── OperatingSystemVersion+String.swift
│ │ │ ├── SemanticToken/
│ │ │ │ └── SemanticToken+Position.swift
│ │ │ ├── String/
│ │ │ │ ├── String+AppearancesOfSubstring.swift
│ │ │ │ ├── String+Character.swift
│ │ │ │ ├── String+Escaped.swift
│ │ │ │ ├── String+HighlightOccurrences.swift
│ │ │ │ ├── String+Lines.swift
│ │ │ │ ├── String+MD5.swift
│ │ │ │ ├── String+Ranges.swift
│ │ │ │ ├── String+RemoveOccurrences.swift
│ │ │ │ ├── String+SHA256.swift
│ │ │ │ └── String+ValidFileName.swift
│ │ │ ├── SwiftTerm/
│ │ │ │ └── Color/
│ │ │ │ └── SwiftTerm+Color+Init.swift
│ │ │ ├── Text/
│ │ │ │ └── Font+Caption3.swift
│ │ │ ├── TextView/
│ │ │ │ ├── TextView+LSPRange.swift
│ │ │ │ └── TextView+SemanticTokenRangeProvider.swift
│ │ │ ├── URL/
│ │ │ │ ├── URL+Filename.swift
│ │ │ │ ├── URL+FindWorkspace.swift
│ │ │ │ ├── URL+FuzzySearchable.swift
│ │ │ │ ├── URL+Identifiable.swift
│ │ │ │ ├── URL+LSPURI.swift
│ │ │ │ ├── URL+ResouceValues.swift
│ │ │ │ ├── URL+URLParameters.swift
│ │ │ │ ├── URL+absolutePath.swift
│ │ │ │ └── URL+componentCompare.swift
│ │ │ ├── View/
│ │ │ │ ├── View+focusedValue.swift
│ │ │ │ ├── View+if.swift
│ │ │ │ └── View+isHovering.swift
│ │ │ └── ZipFoundation/
│ │ │ └── ZipFoundation+ErrorDescrioption.swift
│ │ ├── FocusedValues.swift
│ │ ├── Formatters/
│ │ │ ├── RegexFormatter.swift
│ │ │ └── TrimWhitespaceFormatter.swift
│ │ ├── KeyChain/
│ │ │ ├── CodeEditKeychain.swift
│ │ │ ├── CodeEditKeychainConstants.swift
│ │ │ └── KeychainSwiftAccessOptions.swift
│ │ ├── Limiter.swift
│ │ ├── Protocols/
│ │ │ ├── Loopable.swift
│ │ │ └── SearchableSettingsPage.swift
│ │ ├── ShellClient/
│ │ │ └── Models/
│ │ │ └── ShellClient.swift
│ │ └── withTimeout.swift
│ ├── WindowObserver.swift
│ ├── WorkspaceSheets.swift
│ ├── WorkspaceView.swift
│ └── World.swift
├── CodeEdit.xcodeproj/
│ ├── project.pbxproj
│ ├── project.xcworkspace/
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata/
│ │ └── swiftpm/
│ │ └── Package.resolved
│ └── xcshareddata/
│ └── xcschemes/
│ ├── CodeEdit.xcscheme
│ └── OpenWithCodeEdit.xcscheme
├── CodeEditTestPlan.xctestplan
├── CodeEditTests/
│ ├── Features/
│ │ ├── Acknowledgements/
│ │ │ └── AcknowledgementsTests.swift
│ │ ├── ActivityViewer/
│ │ │ └── TaskNotificationHandlerTests.swift
│ │ ├── CodeEditUI/
│ │ │ ├── CodeEditUITests-Bridging-Header.h
│ │ │ └── CodeEditUITests.swift
│ │ ├── CodeFile/
│ │ │ ├── CodeFileDocument+UTTypeTests.swift
│ │ │ └── CodeFileDocumentTests.swift
│ │ ├── Documents/
│ │ │ ├── DocumentsUnitTests.swift
│ │ │ ├── Indexer/
│ │ │ │ ├── AsyncIndexingTests.swift
│ │ │ │ ├── MemoryIndexingTests.swift
│ │ │ │ ├── MemorySearchTests.swift
│ │ │ │ └── TemporaryFile.swift
│ │ │ ├── Mocks/
│ │ │ │ └── NSHapticFeedbackPerformerMock.swift
│ │ │ ├── WorkspaceDocument+SearchState+FindAndReplaceTests.swift
│ │ │ ├── WorkspaceDocument+SearchState+FindTests.swift
│ │ │ └── WorkspaceDocument+SearchState+IndexTests.swift
│ │ ├── Editor/
│ │ │ ├── EditorStateRestorationTests.swift
│ │ │ └── UndoManagerRegistrationTests.swift
│ │ ├── LSP/
│ │ │ ├── BufferingServerConnection.swift
│ │ │ ├── LanguageServer+CodeFileDocument.swift
│ │ │ ├── LanguageServer+DocumentObjects.swift
│ │ │ ├── Registry.swift
│ │ │ └── SemanticTokens/
│ │ │ ├── SemanticTokenMapTests.swift
│ │ │ └── SemanticTokenStorageTests.swift
│ │ ├── Search/
│ │ │ └── FuzzySearch/
│ │ │ └── FuzzySearchTests.swift
│ │ ├── SourceControl/
│ │ │ └── GitClientTests.swift
│ │ ├── Tasks/
│ │ │ ├── CEActiveTaskTests.swift
│ │ │ └── TaskManagerTests.swift
│ │ ├── TerminalEmulator/
│ │ │ └── ShellIntegrationTests.swift
│ │ ├── UtilityArea/
│ │ │ └── UtilityAreaViewModelTests.swift
│ │ ├── Welcome/
│ │ │ └── RecentProjectsTests.swift
│ │ └── WorkspaceSettings/
│ │ └── CEWorkspaceSettingsTests.swift
│ └── Utils/
│ ├── CEWorkspaceFileManager/
│ │ └── CEWorkspaceFileManagerTests.swift
│ ├── UnitTests_Extensions.swift
│ ├── waitForExpectation.swift
│ └── withTempDir.swift
├── CodeEditUI/
│ └── src/
│ └── Preferences/
│ └── ViewOffsetPreferenceKey.swift
├── CodeEditUITests/
│ ├── App.swift
│ ├── Extensions/
│ │ └── XCUITest+waitForNonExistence.swift
│ ├── Features/
│ │ ├── ActivityViewer/
│ │ │ └── Tasks/
│ │ │ └── TasksMenuUITests.swift
│ │ ├── NavigatorArea/
│ │ │ └── ProjectNavigator/
│ │ │ ├── ProjectNavigatorFileManagementUITests.swift
│ │ │ └── ProjectNavigatorUITests.swift
│ │ └── UtilityArea/
│ │ └── TerminalUtility/
│ │ └── TerminalUtilityUITests.swift
│ ├── Other Tests/
│ │ ├── HideInterfaceTests.swift
│ │ └── WindowCloseCommandTests.swift
│ ├── ProjectPath.swift
│ ├── Query.swift
│ └── UI TESTING.md
├── Configs/
│ ├── Alpha.xcconfig
│ ├── Beta.xcconfig
│ ├── Debug.xcconfig
│ ├── Pre.xcconfig
│ └── Release.xcconfig
├── DefaultThemes/
│ ├── Basic.cetheme
│ ├── Civic.cetheme
│ ├── Classic (Dark).cetheme
│ ├── Classic (Light).cetheme
│ ├── Default (Dark).cetheme
│ ├── Default (Light).cetheme
│ ├── Dusk.cetheme
│ ├── GitHub (Dark).cetheme
│ ├── GitHub (Light).cetheme
│ ├── High Contrast (Dark).cetheme
│ ├── High Contrast (Light).cetheme
│ ├── Low Key.cetheme
│ ├── Midnight.cetheme
│ ├── Presentation (Dark).cetheme
│ ├── Presentation (Light).cetheme
│ ├── Solarized (Dark).cetheme
│ ├── Solarized (Light).cetheme
│ └── Sunset.cetheme
├── Documentation.docc/
│ ├── About/
│ │ └── About Window.md
│ ├── App Window/
│ │ ├── Adding New Tab Type.md
│ │ ├── App Window.md
│ │ ├── InspectorSidebarView.md
│ │ ├── NavigatorSidebarView.md
│ │ ├── StatusBarView.md
│ │ ├── TabBarView.md
│ │ └── UtilityAreaView.md
│ ├── AppPreferences/
│ │ ├── AppPreferences.md
│ │ ├── Create a View.md
│ │ ├── Getting Started.md
│ │ ├── Sections/
│ │ │ ├── AccountPreferencesView.md
│ │ │ ├── GeneralPreferencesView.md
│ │ │ ├── KeybindingsPreferencesView.md
│ │ │ ├── SourceControlPreferencesView.md
│ │ │ ├── TerminalPreferencesView.md
│ │ │ ├── TextEditingPreferencesView.md
│ │ │ └── ThemePreferencesView.md
│ │ └── Themes.md
│ ├── CodeEditUI/
│ │ ├── CodeEditUI.md
│ │ ├── HelpButton.md
│ │ ├── SegmentedControl.md
│ │ └── ToolbarBranchPicker.md
│ ├── Documentation.md
│ ├── FileManagement/
│ │ └── FileManagement.md
│ ├── Git/
│ │ └── Git.md
│ ├── KeyChain/
│ │ ├── CodeEditKeychain.md
│ │ └── What is Keychain.md
│ ├── Keybindings/
│ │ └── KeybindingManager.md
│ └── Welcome/
│ └── Welcome Window.md
├── LICENSE.md
├── OpenWithCodeEdit/
│ ├── FinderSync.swift
│ ├── Info.plist
│ ├── Media.xcassets/
│ │ └── Contents.json
│ └── OpenWithCodeEdit.entitlements
└── README.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .all-contributorsrc
================================================
{
"files": [
"README.md"
],
"imageSize": 100,
"commit": false,
"contributors": [
{
"login": "austincondiff",
"name": "Austin Condiff",
"avatar_url": "https://avatars.githubusercontent.com/u/806104?v=4",
"profile": "http://www.austincondiff.com",
"contributions": [
"design",
"code"
]
},
{
"login": "lukepistrol",
"name": "Lukas Pistrol",
"avatar_url": "https://avatars.githubusercontent.com/u/9460130?v=4",
"profile": "http://lukaspistrol.com",
"contributions": [
"infra",
"test",
"code"
]
},
{
"login": "thecoolwinter",
"name": "Khan Winter",
"avatar_url": "https://avatars.githubusercontent.com/u/35942988?v=4",
"profile": "https://blog.windchillmedia.com",
"contributions": [
"code",
"bug"
]
},
{
"login": "matthijseikelenboom",
"name": "Matthijs Eikelenboom",
"avatar_url": "https://avatars.githubusercontent.com/u/1364843?v=4",
"profile": "https://github.com/matthijseikelenboom",
"contributions": [
"code",
"bug"
]
},
{
"login": "Wouter01",
"name": "Wouter Hennen",
"avatar_url": "https://avatars.githubusercontent.com/u/62355975?v=4",
"profile": "https://github.com/Wouter01",
"contributions": [
"code"
]
},
{
"login": "0xWDG",
"name": "Wesley De Groot",
"avatar_url": "https://avatars.githubusercontent.com/u/1290461?v=4",
"profile": "https://wdg.codes",
"contributions": [
"infra",
"test",
"code"
]
},
{
"login": "KaiTheRedNinja",
"name": "KaiTheRedNinja",
"avatar_url": "https://avatars.githubusercontent.com/u/88234730?v=4",
"profile": "https://github.com/KaiTheRedNinja",
"contributions": [
"code"
]
},
{
"login": "pkasila",
"name": "Pavel Kasila",
"avatar_url": "https://avatars.githubusercontent.com/u/17158860?v=4",
"profile": "https://github.com/pkasila",
"contributions": [
"infra",
"test",
"code"
]
},
{
"login": "MarcoCarnevali",
"name": "Marco Carnevali",
"avatar_url": "https://avatars.githubusercontent.com/u/9656572?v=4",
"profile": "https://github.com/MarcoCarnevali",
"contributions": [
"infra",
"test",
"code"
]
},
{
"login": "nanashili",
"name": "Nanashi Li",
"avatar_url": "https://avatars.githubusercontent.com/u/63672227?v=4",
"profile": "https://github.com/nanashili",
"contributions": [
"code"
]
},
{
"login": "RayZhao1998",
"name": "ninjiacoder",
"avatar_url": "https://avatars.githubusercontent.com/u/22616933?v=4",
"profile": "https://ninjiacoder.me",
"contributions": [
"code"
]
},
{
"login": "Jeehut",
"name": "Cihat Gündüz",
"avatar_url": "https://avatars.githubusercontent.com/u/6942160?v=4",
"profile": "https://twitch.tv/Jeehut",
"contributions": [
"code"
]
},
{
"login": "MysteryCoder456",
"name": "Rehatbir Singh",
"avatar_url": "https://avatars.githubusercontent.com/u/43755491?v=4",
"profile": "https://github.com/MysteryCoder456",
"contributions": [
"code"
]
},
{
"login": "Angelk90",
"name": "Angelk90",
"avatar_url": "https://avatars.githubusercontent.com/u/20476002?v=4",
"profile": "https://github.com/Angelk90",
"contributions": [
"code"
]
},
{
"login": "StefKors",
"name": "Stef Kors",
"avatar_url": "https://avatars.githubusercontent.com/u/11800807?v=4",
"profile": "https://www.stefkors.com",
"contributions": [
"code"
]
},
{
"login": "akring",
"name": "Chris Akring",
"avatar_url": "https://avatars.githubusercontent.com/u/6525286?v=4",
"profile": "https://akringblog.com/",
"contributions": [
"code"
]
},
{
"login": "highjeans",
"name": "highjeans",
"avatar_url": "https://avatars.githubusercontent.com/u/77588045?v=4",
"profile": "https://github.com/highjeans",
"contributions": [
"code"
]
},
{
"login": "jasonplatts",
"name": "Jason Platts",
"avatar_url": "https://avatars.githubusercontent.com/u/48892071?v=4",
"profile": "https://github.com/jasonplatts",
"contributions": [
"infra",
"plugin"
]
},
{
"login": "dzign1",
"name": "Rob Hughes",
"avatar_url": "https://avatars.githubusercontent.com/u/44317715?v=4",
"profile": "https://github.com/dzign1",
"contributions": [
"code"
]
},
{
"login": "lilingxi01",
"name": "Lingxi Li",
"avatar_url": "https://avatars.githubusercontent.com/u/36816148?v=4",
"profile": "https://lingxi.li",
"contributions": [
"code",
"bug"
]
},
{
"login": "octree",
"name": "HZ.Liu",
"avatar_url": "https://avatars.githubusercontent.com/u/7934444?v=4",
"profile": "https://github.com/octree",
"contributions": [
"code",
"bug"
]
},
{
"login": "richardtop",
"name": "Richard Topchii",
"avatar_url": "https://avatars.githubusercontent.com/u/8013017?v=4",
"profile": "https://www.youtube.com/channel/UCx1gvWpy5zjOd7yZyDwmXEA?sub_confirmation=1",
"contributions": [
"code"
]
},
{
"login": "Pythonen",
"name": "Pythonen",
"avatar_url": "https://avatars.githubusercontent.com/u/53183345?v=4",
"profile": "https://github.com/Pythonen",
"contributions": [
"code"
]
},
{
"login": "jav-solo",
"name": "Javier Solorzano",
"avatar_url": "https://avatars.githubusercontent.com/u/10246220?v=4",
"profile": "https://github.com/jav-solo",
"contributions": [
"code",
"bug"
]
},
{
"login": "AngCosmin",
"name": "Cosmin Anghel",
"avatar_url": "https://avatars.githubusercontent.com/u/8146514?v=4",
"profile": "http://angcosmin.com",
"contributions": [
"code"
]
},
{
"login": "mmshivesh",
"name": "Shivesh",
"avatar_url": "https://avatars.githubusercontent.com/u/23611514?v=4",
"profile": "http://mmshivesh.ml",
"contributions": [
"code"
]
},
{
"login": "drucelweisse",
"name": "Andrey Plotnikov",
"avatar_url": "https://avatars.githubusercontent.com/u/36012972?v=4",
"profile": "https://github.com/drucelweisse",
"contributions": [
"code"
]
},
{
"login": "POPOBE97",
"name": "POPOBE97",
"avatar_url": "https://avatars.githubusercontent.com/u/7891810?v=4",
"profile": "https://github.com/POPOBE97",
"contributions": [
"code"
]
},
{
"login": "nrudnyk",
"name": "nrudnyk",
"avatar_url": "https://avatars.githubusercontent.com/u/20221382?v=4",
"profile": "https://github.com/nrudnyk",
"contributions": [
"code"
]
},
{
"login": "benkoska",
"name": "Ben Koska",
"avatar_url": "https://avatars.githubusercontent.com/u/17319613?v=4",
"profile": "https://github.com/benkoska",
"contributions": [
"code"
]
},
{
"login": "evolify",
"name": "evolify",
"avatar_url": "https://avatars.githubusercontent.com/u/12669069?v=4",
"profile": "https://github.com/evolify",
"contributions": [
"bug"
]
},
{
"login": "shibotong",
"name": "Shibo Tong",
"avatar_url": "https://avatars.githubusercontent.com/u/44807628?v=4",
"profile": "https://github.com/shibotong",
"contributions": [
"code"
]
},
{
"login": "GetToSet",
"name": "Ethan Wong",
"avatar_url": "https://avatars.githubusercontent.com/u/8158163?v=4",
"profile": "https://ethanwong.me",
"contributions": [
"code"
]
},
{
"login": "gantoreno",
"name": "Gabriel Moreno",
"avatar_url": "https://avatars.githubusercontent.com/u/43397475?v=4",
"profile": "http://gantoreno.com",
"contributions": [
"bug"
]
},
{
"login": "Prince213",
"name": "Sizhe Zhao",
"avatar_url": "https://avatars.githubusercontent.com/u/25235514?v=4",
"profile": "https://github.com/Prince213",
"contributions": [
"bug"
]
},
{
"login": "Muhammed9991",
"name": "Muhammed Mahmood",
"avatar_url": "https://avatars.githubusercontent.com/u/80204376?v=4",
"profile": "https://github.com/Muhammed9991",
"contributions": [
"code",
"maintenance"
]
},
{
"login": "muescha",
"name": "Muescha",
"avatar_url": "https://avatars.githubusercontent.com/u/184316?v=4",
"profile": "https://github.com/muescha",
"contributions": [
"code"
]
},
{
"login": "avdept",
"name": "Alex Sinelnikov",
"avatar_url": "https://avatars.githubusercontent.com/u/1757017?v=4",
"profile": "https://alexsinelnikov.io/",
"contributions": [
"code"
]
},
{
"login": "Pribess",
"name": "Heewon Cho",
"avatar_url": "https://avatars.githubusercontent.com/u/72389357?v=4",
"profile": "http://pribess.github.io",
"contributions": [
"bug"
]
},
{
"login": "MattKiazyk",
"name": "Matt Kiazyk",
"avatar_url": "https://avatars.githubusercontent.com/u/1119565?v=4",
"profile": "https://www.xcodes.app",
"contributions": [
"code"
]
},
{
"login": "DingoBits",
"name": "DingoBits",
"avatar_url": "https://avatars.githubusercontent.com/u/107956274?v=4",
"profile": "https://github.com/DingoBits",
"contributions": [
"code"
]
},
{
"login": "sk409",
"name": "Shoto Kobayashi",
"avatar_url": "https://avatars.githubusercontent.com/u/25968819?v=4",
"profile": "https://github.com/sk409",
"contributions": [
"bug",
"code"
]
},
{
"login": "aaryankotharii",
"name": "Aaryan Kothari",
"avatar_url": "https://avatars.githubusercontent.com/u/53724307?v=4",
"profile": "http://www.linkedin.com/in/aaryankotharii",
"contributions": [
"bug"
]
},
{
"login": "Kyle-Ye",
"name": "Kyle",
"avatar_url": "https://avatars.githubusercontent.com/u/43724855?v=4",
"profile": "http://kyleye.top/",
"contributions": [
"code"
]
},
{
"login": "NakaokaRei",
"name": "Nakaoka Rei",
"avatar_url": "https://avatars.githubusercontent.com/u/39183069?v=4",
"profile": "https://github.com/NakaokaRei",
"contributions": [
"code",
"bug"
]
},
{
"login": "alexdeem",
"name": "Alex Deem",
"avatar_url": "https://avatars.githubusercontent.com/u/404584?v=4",
"profile": "https://github.com/alexdeem",
"contributions": [
"maintenance"
]
},
{
"login": "denizak",
"name": "deni zakya",
"avatar_url": "https://avatars.githubusercontent.com/u/1758456?v=4",
"profile": "https://github.com/denizak",
"contributions": [
"bug"
]
},
{
"login": "ahmdyasser",
"name": "Ahmad Yasser",
"avatar_url": "https://avatars.githubusercontent.com/u/42544598?v=4",
"profile": "https://github.com/ahmdyasser",
"contributions": [
"bug"
]
},
{
"login": "ezraberch",
"name": "ezraberch",
"avatar_url": "https://avatars.githubusercontent.com/u/49635435?v=4",
"profile": "https://github.com/ezraberch",
"contributions": [
"code"
]
},
{
"login": "Eliulm",
"name": "Elias Wahl",
"avatar_url": "https://avatars.githubusercontent.com/u/82230675?v=4",
"profile": "https://github.com/Eliulm",
"contributions": [
"bug"
]
},
{
"login": "bombardier200",
"name": "bombardier200",
"avatar_url": "https://avatars.githubusercontent.com/u/25121427?v=4",
"profile": "https://github.com/bombardier200",
"contributions": [
"code"
]
},
{
"login": "yapryntsev",
"name": "Alex Yapryntsev",
"avatar_url": "https://avatars.githubusercontent.com/u/18378212?v=4",
"profile": "https://github.com/yapryntsev",
"contributions": [
"code"
]
},
{
"login": "Code-DJ",
"name": "Code-DJ",
"avatar_url": "https://avatars.githubusercontent.com/u/8212554?v=4",
"profile": "https://github.com/Code-DJ",
"contributions": [
"code",
"bug"
]
},
{
"login": "neilZon",
"name": "Neilzon Viloria",
"avatar_url": "https://avatars.githubusercontent.com/u/46465568?v=4",
"profile": "https://github.com/neilZon",
"contributions": [
"bug"
]
},
{
"login": "Cubik65536",
"name": "Cubik",
"avatar_url": "https://avatars.githubusercontent.com/u/72877496?v=4",
"profile": "https://cubik65536.top",
"contributions": [
"bug",
"code"
]
},
{
"login": "RenanGreca",
"name": "Renan Greca",
"avatar_url": "https://avatars.githubusercontent.com/u/5760386?v=4",
"profile": "https://twitter.com/RenanGreca",
"contributions": [
"code"
]
},
{
"login": "maxkel",
"name": "maxkel",
"avatar_url": "https://avatars.githubusercontent.com/u/46418077?v=4",
"profile": "https://github.com/maxkel",
"contributions": [
"bug",
"code"
]
},
{
"login": "scrapp08",
"name": "Scrap",
"avatar_url": "https://avatars.githubusercontent.com/u/105889363?v=4",
"profile": "https://scrapp08.xyz",
"contributions": [
"code"
]
},
{
"login": "iggy890",
"name": "iggy890",
"avatar_url": "https://avatars.githubusercontent.com/u/98705626?v=4",
"profile": "https://github.com/iggy890",
"contributions": [
"code"
]
},
{
"login": "stavares843",
"name": "Sara Tavares",
"avatar_url": "https://avatars.githubusercontent.com/u/29093946?v=4",
"profile": "https://github.com/stavares843",
"contributions": [
"bug",
"code"
]
},
{
"login": "luah5",
"name": "luah5",
"avatar_url": "https://avatars.githubusercontent.com/u/128280019?v=4",
"profile": "https://github.com/luah5",
"contributions": [
"code"
]
},
{
"login": "evanlwang",
"name": "Evan Wang",
"avatar_url": "https://avatars.githubusercontent.com/u/71157264?v=4",
"profile": "https://github.com/evanlwang",
"contributions": [
"code"
]
},
{
"login": "dscyrescotti",
"name": "Dscyre Scotti",
"avatar_url": "https://avatars.githubusercontent.com/u/67727096?v=4",
"profile": "https://github.com/dscyrescotti",
"contributions": [
"code"
]
},
{
"login": "dvandyy",
"name": "Tomáš Boďa",
"avatar_url": "https://avatars.githubusercontent.com/u/40064599?v=4",
"profile": "http://tomasboda.com",
"contributions": [
"bug"
]
},
{
"login": "Ahattalla",
"name": "Ahmed Attalla",
"avatar_url": "https://avatars.githubusercontent.com/u/53402452?v=4",
"profile": "https://github.com/Ahattalla",
"contributions": [
"bug",
"code"
]
},
{
"login": "EstebanBorai",
"name": "Esteban Borai",
"avatar_url": "https://avatars.githubusercontent.com/u/34756077?v=4",
"profile": "http://estebanborai.com",
"contributions": [
"code"
]
},
{
"login": "avinizhanov",
"name": "avinizhanov",
"avatar_url": "https://avatars.githubusercontent.com/u/42622715?v=4",
"profile": "https://github.com/avinizhanov",
"contributions": [
"bug",
"code"
]
},
{
"login": "kmohsin11",
"name": "kmohsin11",
"avatar_url": "https://avatars.githubusercontent.com/u/28269317?v=4",
"profile": "https://github.com/kmohsin11",
"contributions": [
"bug"
]
},
{
"login": "armartinez",
"name": "Axel Martinez",
"avatar_url": "https://avatars.githubusercontent.com/u/1909987?v=4",
"profile": "https://github.com/armartinez",
"contributions": [
"bug",
"code"
]
},
{
"login": "FezVrasta",
"name": "Federico Zivolo",
"avatar_url": "https://avatars.githubusercontent.com/u/5382443?v=4",
"profile": "https://nivora.app",
"contributions": [
"code"
]
},
{
"login": "ElvisWong213",
"name": "Elvis Wong",
"avatar_url": "https://avatars.githubusercontent.com/u/40566101?v=4",
"profile": "https://github.com/ElvisWong213",
"contributions": [
"bug"
]
},
{
"login": "ibrahimcetin",
"name": "İbrahim Çetin",
"avatar_url": "https://avatars.githubusercontent.com/u/33904390?v=4",
"profile": "http://ibrahimcetin.dev",
"contributions": [
"bug"
]
},
{
"login": "phlpsong",
"name": "phlpsong",
"avatar_url": "https://avatars.githubusercontent.com/u/103433299?v=4",
"profile": "https://github.com/phlpsong",
"contributions": [
"bug"
]
},
{
"login": "infinitepower18",
"name": "Ahnaf Mahmud",
"avatar_url": "https://avatars.githubusercontent.com/u/44692189?v=4",
"profile": "http://ahnafmahmud.com",
"contributions": [
"code"
]
},
{
"login": "DanKlaver15",
"name": "Dan K",
"avatar_url": "https://avatars.githubusercontent.com/u/9391497?v=4",
"profile": "https://github.com/DanKlaver15",
"contributions": [
"code"
]
},
{
"login": "knotbin",
"name": "Roscoe Rubin-Rottenberg",
"avatar_url": "https://avatars.githubusercontent.com/u/118622417?v=4",
"profile": "http://knotbin.xyz",
"contributions": [
"code"
]
},
{
"login": "plbstl",
"name": "Paul Ebose",
"avatar_url": "https://avatars.githubusercontent.com/u/49006567?v=4",
"profile": "https://github.com/plbstl",
"contributions": [
"bug"
]
},
{
"login": "danielzsh",
"name": "Daniel Zhu",
"avatar_url": "https://avatars.githubusercontent.com/u/65467530?v=4",
"profile": "http://danielz.xyz",
"contributions": [
"bug"
]
},
{
"login": "simonwhitaker",
"name": "Simon Whitaker",
"avatar_url": "https://avatars.githubusercontent.com/u/116432?v=4",
"profile": "https://github.com/simonwhitaker",
"contributions": [
"bug"
]
},
{
"login": "LeonardoLarranaga",
"name": "Leonardo",
"avatar_url": "https://avatars.githubusercontent.com/u/83844690?v=4",
"profile": "https://github.com/LeonardoLarranaga",
"contributions": [
"code"
]
},
{
"login": "scaredcr6w",
"name": "Levente Anda",
"avatar_url": "https://avatars.githubusercontent.com/u/85457088?v=4",
"profile": "https://github.com/scaredcr6w",
"contributions": [
"code"
]
},
{
"login": "NobelLiu",
"name": "Nobel",
"avatar_url": "https://avatars.githubusercontent.com/u/10796646?v=4",
"profile": "https://nobelliu.github.com",
"contributions": [
"code"
]
},
{
"login": "SavelyUkuren",
"name": "Savely",
"avatar_url": "https://avatars.githubusercontent.com/u/125015568?v=4",
"profile": "https://github.com/SavelyUkuren",
"contributions": [
"code"
]
},
{
"login": "Kihron",
"name": "Kihron",
"avatar_url": "https://avatars.githubusercontent.com/u/30128800?v=4",
"profile": "https://github.com/Kihron",
"contributions": [
"bug"
]
},
{
"login": "pro100filipp",
"name": "Filipp Kuznetsov",
"avatar_url": "https://avatars.githubusercontent.com/u/12880697?v=4",
"profile": "https://github.com/pro100filipp",
"contributions": [
"code"
]
},
{
"login": "rustemd02",
"name": "rustemd02",
"avatar_url": "https://avatars.githubusercontent.com/u/11714456?v=4",
"profile": "https://github.com/rustemd02",
"contributions": [
"bug",
"code"
]
},
{
"login": "SimonKudsk",
"name": "Simon Kudsk",
"avatar_url": "https://avatars.githubusercontent.com/u/10168417?v=4",
"profile": "https://github.com/SimonKudsk",
"contributions": [
"code"
]
},
{
"login": "Syrux64",
"name": "Surya",
"avatar_url": "https://avatars.githubusercontent.com/u/118998822?v=4",
"profile": "https://github.com/Syrux64",
"contributions": [
"code"
]
},
{
"login": "georgetchelidze",
"name": "George Tchelidze",
"avatar_url": "https://avatars.githubusercontent.com/u/96194129?v=4",
"profile": "https://github.com/georgetchelidze",
"contributions": [
"code"
]
},
{
"login": "zhrispineda",
"name": "Chris Pineda",
"avatar_url": "https://avatars.githubusercontent.com/u/148818634?v=4",
"profile": "http://zhr.is",
"contributions": [
"code"
]
}
],
"contributorsPerLine": 7,
"projectName": "CodeEdit",
"projectOwner": "CodeEditApp",
"repoType": "github",
"repoHost": "https://github.com",
"skipCi": true,
"commitConvention": "angular",
"commitType": "docs"
}
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
github: [CodeEditApp, austincondiff]
patreon: # Replace with a single Patreon username
open_collective: codeeditapp
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.yml
================================================
name: 🐞 Bug report
description: Something is not working as expected.
title: 🐞 <bug title>
labels: bug
body:
- type: textarea
attributes:
label: Description
placeholder: >-
A clear and concise description of what the bug is...
validations:
required: true
- type: textarea
attributes:
label: To Reproduce
description: >-
Steps to reliably reproduce the behavior.
placeholder: |
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
validations:
required: true
- type: textarea
attributes:
label: Expected Behavior
placeholder: >-
A clear and concise description of what you expected to happen...
validations:
required: true
- type: textarea
attributes:
label: Version Information
description: >-
click on the version number on the welcome screen
value: |
CodeEdit: [e.g. 0.0.x-alpha.y]
macOS: [e.g. 13.2.1]
Xcode: [e.g. 14.2]
- type: textarea
attributes:
label: Additional Context
placeholder: >-
Any other context or considerations about the bug...
- type: textarea
attributes:
label: Screenshots
placeholder: >-
If applicable, please provide relevant screenshots or screen recordings...
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.yml
================================================
name: ✨ Feature request
description: Suggest an idea for this project
title: ✨ <feature title>
labels: enhancement
body:
- type: textarea
attributes:
label: Description
placeholder: >-
A clear and concise description of what you would like to happen...
validations:
required: true
- type: textarea
attributes:
label: Alternatives Considered
placeholder: >-
Any alternative solutions or features you've considered...
- type: textarea
attributes:
label: Additional Context
placeholder: >-
Any other context or considerations about the feature request...
- type: textarea
attributes:
label: Screenshots
placeholder: >-
If applicable, please provide relevant screenshots or screen recordings...
================================================
FILE: .github/pull_request_template.md
================================================
<!--- IMPORTANT: If this PR addresses multiple unrelated issues, it will be closed until separated. -->
### Description
<!--- REQUIRED: Describe what changed in detail -->
### Related Issues
<!--- REQUIRED: Tag all related issues (e.g. * #123) -->
<!--- If this PR resolves the issue please specify (e.g. * closes #123) -->
<!--- If this PR addresses multiple issues, these issues must be related to one other -->
* #ISSUE_NUMBER
### Checklist
<!--- Add things that are not yet implemented above -->
- [ ] I read and understood the [contributing guide](https://github.com/CodeEditApp/CodeEdit/blob/main/CONTRIBUTING.md) as well as the [code of conduct](https://github.com/CodeEditApp/CodeEdit/blob/main/CODE_OF_CONDUCT.md)
- [ ] The issues this PR addresses are related to each other
- [ ] My changes generate no new warnings
- [ ] My code builds and runs on my machine
- [ ] My changes are all related to the related issue above
- [ ] I documented my code
### Screenshots
<!--- REQUIRED: if issue is UI related -->
<!--- IMPORTANT: Fill out all required fields. Otherwise we might close this PR temporarily -->
================================================
FILE: .github/release-drafter.yml
================================================
categories:
- title: '✨ Enhancements'
labels:
- 'enhancement'
- 'feature'
- title: '🐞 Bug Fixes'
labels:
- 'bugfix'
- 'bug'
- title: '🧰 Maintenance'
label:
- 'chore'
- 'documentation'
- 'dependencies'
template: |
<!-- Update Template -->
## Changes
$CHANGES
<!-- sparkle:edSignature=xxxxx -->
================================================
FILE: .github/scripts/remove_todos.sh
================================================
#!/bin/bash
grep -rl TODO . | xargs sed -i 's/TODO/notaTODO/g'
grep -rl FIXME . | xargs sed -i 's/FIXME/notaFIXME/g'
================================================
FILE: .github/scripts/test_app.sh
================================================
#!/bin/bash
ARCH=""
if [ $# -eq 0 ]; then
ARCH="x86_64"
elif [ $1 = "arm" ]; then
ARCH="arm64"
fi
echo "Building with Xcode: $(xcodebuild -version)"
echo "Building with arch: ${ARCH}"
echo "SwiftLint Version: $(swiftlint --version)"
export LC_CTYPE=en_US.UTF-8
# xcbeautify flags:
# - renderer: render to gh actions
# - q: quiet output
# - is-ci: include test results in output
set -o pipefail && arch -"${ARCH}" xcodebuild \
-scheme CodeEdit \
-destination "platform=OS X,arch=${ARCH}" \
-skipPackagePluginValidation \
clean test | xcbeautify --renderer github-actions -q --is-ci
================================================
FILE: .github/scripts/test_version_number.sh
================================================
#!/bin/bash
# get the version number from the Info.plist file using agvtool
VERS=$(xcrun agvtool mvers -terse1)
# if the version number is empty, exit with an error
if [ "$VERS" == "" ]; then
echo "No version number found"
echo "Make sure Info.plist has a CFBundleShortVersionString key"
echo ""
echo "If Info.plist does not have a CFBundleShortVersionString key, add the following to your Info.plist file:"
echo ""
echo "<key>CFBundleShortVersionString</key>"
echo "<string>0.0.1</string>"
echo ""
echo "For more information see https://github.com/CodeEditApp/CodeEdit/pull/1006"
exit 1 # exit with an error
else
echo "Version number is $VERS"
exit 0 # exit with no error
fi
================================================
FILE: .github/stale.yml
================================================
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- pinned
- security
# Label to use when marking an issue as stale
staleLabel: wontfix
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false
================================================
FILE: .github/workflows/CI-bump-build-number.yml
================================================
name: CI - Update Build Number
on:
workflow_dispatch:
jobs:
upadate-build-number:
name: Update Build Number
runs-on: [self-hosted, macOS]
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Bump Build Number
run: |
xcrun agvtool next-version -all
APP_BUILD=$(xcrun agvtool vers -terse)
echo "APP_BUILD=$APP_BUILD" >> $GITHUB_ENV
- name: Commit Changes
env:
APP_BUILD: ${{ env.APP_BUILD }}
run: |
git add .
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git commit -m "bump build number to $APP_BUILD"
- name: Push Changes
uses: ad-m/github-push-action@v0.6.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: temp/bump-build-number
force: true
- name: Create Pull Request
uses: peter-evans/create-pull-request@v4
env:
APP_BUILD: ${{ env.APP_BUILD }}
with:
branch: temp/bump-build-number
delete-branch: true
base: main
title: Bump Build Number to ${{ env.APP_BUILD }}
body: Automatically bump build number of all targets to ${{ env.APP_BUILD }}
================================================
FILE: .github/workflows/CI-pre-release.yml
================================================
name: CI - Pre Release
on:
workflow_dispatch:
jobs:
swiftlint:
name: SwiftLint
uses: ./.github/workflows/lint.yml
secrets: inherit
test:
name: Testing CodeEdit
needs: swiftlint
uses: ./.github/workflows/tests.yml
secrets: inherit
deploy:
if: github.repository_owner == 'CodeEditApp'
name: Deploying CodeEdit [Prerelease]
needs: [swiftlint, test]
uses: ./.github/workflows/pre-release.yml
secrets: inherit
ReleaseDrafter:
name: Release Drafter
needs: [swiftlint, test, deploy]
uses: ./.github/workflows/release-drafter.yml
================================================
FILE: .github/workflows/CI-pull-request.yml
================================================
name: CI - Pull Request
on:
pull_request:
branches:
- 'main'
workflow_dispatch:
jobs:
swiftlint:
name: SwiftLint
uses: ./.github/workflows/lint.yml
secrets: inherit
test:
name: Testing CodeEdit
needs: swiftlint
uses: ./.github/workflows/tests.yml
secrets: inherit
================================================
FILE: .github/workflows/CI-release-notes.yml
================================================
name: Deploy Website on Release Note Changes
on:
workflow_dispatch:
release:
types: [created, edited, deleted]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Send deploy request to Vercel
run: curl -X POST ${{ secrets.VERCEL_DEPLOY_URL }}
================================================
FILE: .github/workflows/add-to-project.yml
================================================
name: Add new issues to project
on:
issues:
types:
- opened
jobs:
add-to-project:
name: Add new issues labeled with enhancement or bug to project
runs-on: ubuntu-latest
steps:
- uses: actions/add-to-project@v0.4.0
with:
# You can target a repository in a different organization
# to the issue
project-url: https://github.com/orgs/CodeEditApp/projects/3
github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}
labeled: enhancement, bug
label-operator: OR
================================================
FILE: .github/workflows/appcast.yml
================================================
name: Build and publish a new appcast file
on:
workflow_dispatch:
jobs:
jekyll:
runs-on: ubuntu-latest
steps:
- name: Checkout 🛎
uses: actions/checkout@v3
with:
# If you're using actions/checkout@v3 you must set persist-credentials to false in most cases for the deployment to work correctly.
persist-credentials: false
- name: Cache 📦
uses: actions/cache@v3.0.8
with:
path: AppCast/vendor/bundle
key: ${{ runner.os }}-gems-v1.0-${{ hashFiles('AppCast/Gemfile') }}
restore-keys: |
${{ runner.os }}-gems-
- name: Ruby ♦️
uses: actions/setup-ruby@v1.1.3
with:
ruby-version: '2.7'
- name: Bundler 💎
working-directory: AppCast
env:
BUNDLE_PATH: vendor/bundle
run: |
gem install bundler
bundle install
- name: Build 🛠
working-directory: AppCast
env:
BUNDLE_PATH: vendor/bundle
JEKYLL_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: bundle exec jekyll build
- name: Publish 🚀
uses: JamesIves/github-pages-deploy-action@releases/v3
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH: gh-pages
FOLDER: AppCast/_site
================================================
FILE: .github/workflows/issue.yml
================================================
name: Labeling new issue
on:
issues:
types: ['opened']
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: Renato66/auto-label@v2
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
ignore-comments: true
labels-synonyms: '{"bug":["error","need fix","not working"],"enhancement":["upgrade"],"question":["help"]}'
labels-not-allowed: '["good first issue", "priority"]'
default-labels: '["triage needed"]'
================================================
FILE: .github/workflows/lint.yml
================================================
name: SwiftLint
on:
workflow_dispatch:
workflow_call:
jobs:
SwiftLint:
runs-on: [self-hosted, macOS] # ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: GitHub Action for SwiftLint
run: swiftlint --reporter github-actions-logging --strict
================================================
FILE: .github/workflows/pre-release.yml
================================================
name: Build and Publish Pre-release
on:
workflow_dispatch:
workflow_call:
jobs:
pre-release:
name: Build and Publish Pre-release
runs-on: [self-hosted, macOS]
steps:
- name: Checkout repository
uses: actions/checkout@v3
############################
# Install Certificate
############################
- name: Install codesign certificate
env:
# DEV_CERT_B64: Base64-encoded developer certificate as .p12
# DEV_CERT_PWD: Developer certificate .p12 password
# PROVISION_PROFILE_B64: Base64-encoded provisioning profile as .provisionprofile
# KEYCHAIN_TIMEOUT: Lock keychain after timeout interval
# https://docs.github.com/en/actions/deployment/deploying-xcode-applications/installing-an-apple-certificate-on-macos-runners-for-xcode-development
DEV_CERT_B64: ${{ secrets.DEV_CERT_B64 }}
DEV_CERT_PWD: ${{ secrets.DEV_CERT_PWD }}
MAC_CERT_B64: ${{ secrets.MAC_CERT_B64 }}
MAC_CERT_PWD: ${{ secrets.MAC_CERT_PWD }}
# PROVISION_PROFILE_B64: ${{ secrets.PROVISION_PROFILE_B64 }}
KEYCHAIN_TIMEOUT: 21600
run: |
DEV_CERT_P12="$RUNNER_TEMP/dev_cert.p12"
MAC_CERT_P12="$RUNNER_TEMP/mac_cert.p12"
KEYCHAIN_DB="$RUNNER_TEMP/keychain.keychain-db"
KEYCHAIN_PWD=$(openssl rand -base64 24)
security create-keychain -p "$KEYCHAIN_PWD" "$KEYCHAIN_DB"
security set-keychain-settings -lut "$KEYCHAIN_TIMEOUT" "$KEYCHAIN_DB"
security unlock-keychain -p "$KEYCHAIN_PWD" "$KEYCHAIN_DB"
echo -n "$DEV_CERT_B64" | base64 --decode -o "$DEV_CERT_P12"
security import "$DEV_CERT_P12" -P "$DEV_CERT_PWD" -A -t cert -f pkcs12 -k "$KEYCHAIN_DB"
echo -n "$MAC_CERT_B64" | base64 --decode -o "$MAC_CERT_P12"
security import "$MAC_CERT_P12" -P "$MAC_CERT_PWD" -A -t cert -f pkcs12 -k "$KEYCHAIN_DB"
security list-keychain -d user -s "$KEYCHAIN_DB"
############################
# Build
############################
- name: Build CodeEdit
env:
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
run: xcodebuild -scheme CodeEdit -configuration Pre -derivedDataPath "$RUNNER_TEMP/DerivedData" -archivePath "$RUNNER_TEMP/CodeEdit.xcarchive" -skipPackagePluginValidation DEVELOPMENT_TEAM=$APPLE_TEAM_ID archive | xcpretty
############################
# Sign
############################
- name: Sign CodeEdit
env:
CODESIGN_SIGN: ${{ secrets.CODESIGN_SIGN }}
run: |
REV=$(git rev-parse --short HEAD)
echo "REV=$REV" >> $GITHUB_ENV
codesign --sign "$CODESIGN_SIGN" -vvv --verbose --strict --options=runtime --prefix app.codeedit.CodeEdit. --force --timestamp "$RUNNER_TEMP/CodeEdit.xcarchive/Products/Applications/CodeEdit.app/Contents/Frameworks/CodeEditKit.framework"
codesign --sign "$CODESIGN_SIGN" -vvv --verbose --strict --options=runtime --prefix app.codeedit.CodeEdit. --force --timestamp "$RUNNER_TEMP/CodeEdit.xcarchive/Products/Applications/CodeEdit.app/Contents/Frameworks/CodeLanguages_Container.framework"
codesign --sign "$CODESIGN_SIGN" -vvv --verbose --strict --options=runtime --prefix app.codeedit.CodeEdit. --force --deep --timestamp "$RUNNER_TEMP/CodeEdit.xcarchive/Products/Applications/CodeEdit.app/Contents/Frameworks/Sparkle.framework"
codesign --sign "$CODESIGN_SIGN" -vvv --verbose --strict --options=runtime --prefix app.codeedit.CodeEdit. --force --timestamp --entitlements "$RUNNER_TEMP/../CodeEdit/CodeEdit/OpenWithCodeEdit/OpenWithCodeEdit.entitlements" "$RUNNER_TEMP/CodeEdit.xcarchive/Products/Applications/CodeEdit.app/Contents/PlugIns/OpenWithCodeEdit.appex"
codesign --sign "$CODESIGN_SIGN" -vvv --verbose --strict --options=runtime --prefix app.codeedit.CodeEdit. --force --timestamp "$RUNNER_TEMP/CodeEdit.xcarchive/Products/Applications/CodeEdit.app"
############################
# DMG & Notarize
############################
- name: Create DMG & Notarize
env:
CODESIGN_SIGN: ${{ secrets.CODESIGN_SIGN }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_ID_PWD: ${{ secrets.APPLE_ID_PWD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
RUNNER_PW: ${{ secrets.RUNNER_PW }}
run: |
REV=$(git rev-parse --short HEAD)
echo "REV=$REV" >> $GITHUB_ENV
security unlock-keychain -p "$RUNNER_PW"
xcrun notarytool store-credentials CodeEdit --apple-id "$APPLE_ID" --team-id "$APPLE_TEAM_ID" --password "$APPLE_ID_PWD"
cp "$RUNNER_TEMP/../CodeEdit/CodeEdit/Resources/dmgBackground.png" "$RUNNER_TEMP/.background.png"
epochdate=$(($(date +'%s * 1000 + %-N / 1000000')))
tcc_service_appleevents="replace into access (service,client,client_type,auth_value,auth_reason,auth_version,indirect_object_identifier_type,indirect_object_identifier,flags,last_modified) values (\"kTCCServiceAppleEvents\",\"/usr/sbin/sshd\",1,2,4,1,0,\"com.apple.finder\",0,$epochdate);"
echo $RUNNER_PW | sudo -S sqlite3 "/Users/administrator/Library/Application Support/com.apple.TCC/TCC.db" "$tcc_service_appleevents"
create-dmg \
--volname "CodeEdit" \
--window-pos 200 120 \
--window-size 699 518 \
--background "$RUNNER_TEMP/.background.png" \
--icon-size 128 \
--icon "CodeEdit.app" 170 210 \
--hide-extension "CodeEdit.app" \
--app-drop-link 530 210 \
--codesign "$CODESIGN_SIGN" \
--notarize "CodeEdit" \
"$RUNNER_TEMP/CodeEdit.dmg" \
"$RUNNER_TEMP/CodeEdit.xcarchive/Products/Applications/"
echo $RUNNER_PW | sudo -S security lock-keychain
############################
# Get Version and Build number
############################
- name: Get Version and Build number
run: |
APP_VERSION=$(xcrun agvtool mvers -terse1)
APP_BUILD=$(xcrun agvtool vers -terse)
echo "APP_VERSION=$APP_VERSION" >> $GITHUB_ENV
echo "APP_BUILD=$APP_BUILD" >> $GITHUB_ENV
############################
# Upload dSYMs Artifact
############################
- name: Upload dSYMs Artifact
uses: actions/upload-artifact@v4
with:
name: "CodeEdit-${{ env.APP_BUILD }}-dSYMs"
path: "${{ RUNNER.TEMP }}/CodeEdit.xcarchive/dSYMs"
if-no-files-found: error
# overwrite files for the same build number
overwrite: true
# these can be big, use maximum compression
compression-level: 9
############################
# Sparkle Appcast
############################
- name: Update Sparkle appcast
env:
# SPARKLE_KEY: Sparkle EdDSA key exported from `generate_keys -x` as plain text
# SPARKLE_CHANNEL: Seperate dev builds from default channel, to be specified in [SPUUpdaterDelegate allowedChannelsForUpdater:]
# SPARKLE_DL_PREFIX: Prefix for the URL from where updates will be downloaded
# SPARKLE_LINK: CodeEdit Website
# https://github.com/CodeEditApp/CodeEdit/releases/download/0.0.1-alpha.11/CodeEdit-9113dc5.dmg
# RELEASE_NOTES_PREFIX: The URL to prefix before an update link:
# https://codeedit.app/whats-new/raw/{v0.1.0} -- data in {} is inserted by sparkle
# RELEASE_NOTES_URL: The URL of the entire release notes page: https://codeedit.app/whats-new
SPARKLE_KEY: ${{ secrets.SPARKLE_KEY }}
SPARKLE_CHANNEL: dev
SPARKLE_DL_PREFIX: "https://github.com/CodeEditApp/CodeEdit/releases/download"
SPARKLE_LINK: "https://github.com/CodeEditApp/CodeEdit"
APP_VERSION: ${{ env.APP_VERSION }}
APP_BUILD: ${{ env.APP_BUILD }}
RELEASE_NOTES_URL: "https://codeedit.app/whats-new/"
RELEASE_NOTES_PREFIX: "https://codeedit.app/sparkle/"
run: |
SPARKLE_BIN="$RUNNER_TEMP/DerivedData/SourcePackages/artifacts/sparkle/Sparkle/bin"
SPARKLE_ARCHIVE="$RUNNER_TEMP/Sparkle_Archive"
echo -n "$SPARKLE_KEY" | tee "$RUNNER_TEMP/sparkle_key"
mkdir "$SPARKLE_ARCHIVE"
cp "$RUNNER_TEMP/CodeEdit.dmg" "$SPARKLE_ARCHIVE"
SPARKLE_SIG=$("$SPARKLE_BIN/sign_update" --ed-key-file "$RUNNER_TEMP/sparkle_key" "$SPARKLE_ARCHIVE/CodeEdit.dmg" | cut -d\" -f2)
echo "<!DOCTYPE>" > "$SPARKLE_ARCHIVE/CodeEdit.html" # Need a blank html doc with the DOCTYPE tag to trick sparkle into loading our remote release notes.
"$SPARKLE_BIN/generate_appcast" --ed-key-file "$RUNNER_TEMP/sparkle_key" --download-url-prefix "${{ env.SPARKLE_DL_PREFIX }}/v${{ env.APP_VERSION }}/" --link "$SPARKLE_LINK" --channel "$SPARKLE_CHANNEL" --maximum-deltas 0 "$SPARKLE_ARCHIVE" --release-notes-url-prefix "${{ env.RELEASE_NOTES_PREFIX }}v${{ env.APP_VERSION }}/" --full-release-notes-url "$RELEASE_NOTES_URL"
############################
# Publish Pre Release
############################
- name: Publish Pre-release
uses: marvinpinto/action-automatic-releases@latest
env:
APP_VERSION: ${{ env.APP_VERSION }}
APP_BUILD: ${{ env.APP_BUILD }}
with:
title: "v${{ env.APP_VERSION }}"
files: |
${{ RUNNER.TEMP }}/Sparkle_Archive/CodeEdit.dmg
${{ RUNNER.TEMP }}/Sparkle_Archive/appcast.xml
automatic_release_tag: "v${{ env.APP_VERSION }}"
prerelease: false
repo_token: "${{ secrets.GITHUB_TOKEN }}"
draft: true
############################
# Cleanup Secrets
############################
- name: Clean up keychain and provisioning profile
if: ${{ always() }}
run: |
security delete-keychain "$RUNNER_TEMP/keychain.keychain-db"
rm -rf "~/Library/MobileDevice/Provisioning Profiles"
================================================
FILE: .github/workflows/release-drafter.yml
================================================
name: Release Drafter
on:
# Allow running it manually in case we forget to label a PR before merging
workflow_dispatch:
workflow_call:
jobs:
update_release_draft:
runs-on: ubuntu-latest
steps:
- id: release
uses: release-drafter/release-drafter@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
================================================
FILE: .github/workflows/tests.yml
================================================
name: Tests
on:
workflow_dispatch:
workflow_call:
jobs:
test:
name: Testing CodeEdit
runs-on: [self-hosted, macOS]
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Check Version Number exists
run: exec ./.github/scripts/test_version_number.sh
- name: Testing App
run: exec ./.github/scripts/test_app.sh arm
================================================
FILE: .gitignore
================================================
.DS_Store
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## User settings
xcuserdata/
## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
*.xcscmblueprint
*.xccheckout
## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
build/
DerivedData/
*.moved-aside
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
## Obj-C/Swift specific
*.hmap
## App packaging
*.ipa
*.dSYM.zip
*.dSYM
## Playgrounds
timeline.xctimeline
playground.xcworkspace
# Swift Package Manager
#
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
# Packages/
# Package.pins
# Package.resolved
# *.xcodeproj
#
# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
# hence it is not needed unless you have added a package configuration file to your project
# .swiftpm
.build/
# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# Pods/
#
# Add this line if you want to avoid checking in source code from the Xcode workspace
# *.xcworkspace
# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts
Carthage/Build/
# Accio dependency management
Dependencies/
.accio/
# fastlane
#
# It is recommended to not store the screenshots in the git repo.
# Instead, use fastlane to re-generate the screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://docs.fastlane.tools/best-practices/source-control/#source-control
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots/**/*.png
fastlane/test_output
# Code Injection
#
# After new code Injection tools there's a generated folder /iOSInjectionProject
# https://github.com/johnno1962/injectionforxcode
iOSInjectionProject/
# System files
.DS_Store
.codeedit
.idea
.vscode
================================================
FILE: .swiftlint.yml
================================================
disabled_rules:
- todo
- trailing_comma
- nesting
type_name:
excluded:
- ID
identifier_name:
allowed_symbols: ["$", "_"]
excluded:
- id
- vc
# paths to ignore during linting.
excluded:
- CodeEditModules/.build # Where Swift Package Manager checks out dependency sources
- DerivedData
opt_in_rules:
- attributes
- empty_count
- closure_spacing
- contains_over_first_not_nil
- missing_docs
# - implicit_return
- modifier_order
- convenience_type
- pattern_matching_keywords
- multiline_parameters_brackets
- multiline_arguments_brackets
custom_rules:
spaces_over_tabs:
included: ".*\\.swift"
name: "Spaces over Tabs"
regex: "\t"
message: "Prefer spaces for indents over tabs. See Xcode setting: 'Text Editing' -> 'Indentation'"
severity: warning
================================================
FILE: AppCast/.gitignore
================================================
_site
.sass-cache
.jekyll-metadata
================================================
FILE: AppCast/Gemfile
================================================
source "https://rubygems.org"
# Hello! This is where you manage which Jekyll version is used to run.
# When you want to use a different version, change it below, save the
# file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
#
# bundle exec jekyll serve
#
# This will help ensure the proper Jekyll version is running.
# Happy Jekylling!
gem "jekyll", "~> 3.9.0"
gem "jekyll-github-metadata", group: :jekyll_plugins
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
# and associated library.
install_if -> { RUBY_PLATFORM =~ %r!mingw|mswin|java! } do
gem "tzinfo", "~> 1.2"
gem "tzinfo-data"
end
# Performance-booster for watching directories on Windows
gem "wdm", "~> 0.1.0", :install_if => Gem.win_platform?
# kramdown v2 ships without the gfm parser by default. If you're using
# kramdown v1, comment out this line.
gem "kramdown-parser-gfm"
================================================
FILE: AppCast/_config.yml
================================================
# Welcome to Jekyll!
#
# This config file is meant for settings that affect your whole blog, values
# which you are expected to set up once and rarely edit after that. If you find
# yourself editing this file very often, consider using Jekyll's data files
# feature for the data you need to update frequently.
#
# For technical reasons, this file is *NOT* reloaded automatically when you use
# 'bundle exec jekyll serve'. If you change this file, please restart the server process.
# Site settings
# These are used to personalize your new site. If you look in the HTML files,
# you will see them accessed via {{ site.title }}, {{ site.email }}, and so on.
# You can create any custom variable you would like, and they will be accessible
# in the templates via {{ site.myvariable }}.
title: CodeEdit.app
description: >- # this means to ignore newlines until "baseurl:"
baseurl: "" # the subpath of your site, e.g. /blog
url: "" # the base hostname & protocol for your site, e.g. http://example.com
# Build settings
markdown: kramdown
plugins:
- "jekyll-github-metadata"
# Exclude from processing.
# The following items will not be processed, by default. Create a custom list
# to override the default setting.
# exclude:
# - Gemfile
# - Gemfile.lock
# - node_modules
# - vendor/bundle/
# - vendor/cache/
# - vendor/gems/
# - vendor/ruby/
================================================
FILE: AppCast/_includes/appcast.inc
================================================
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
<title>{{ site.github.project_title }}</title>
<description>Most recent changes with links to updates.</description>
<language>en</language>
{% for release in site.github.releases %}
{% unless release.draft %}
{% unless release.prerelease and page.release_only %}
<item>
<title>{{ release.name }}</title>
<description><![CDATA[{{ release.body | markdownify }}]]></description>
<pubDate>{{ release.published_at | date_to_rfc822 }}</pubDate>
{% for asset in release.assets limit:1 %}
{% assign signature = release.body | sparkle_signature %}
{% assign build_nums = release.tag_name | replace_first:'v','' | replace_first:'b',',' | split:',' %}
{% if build_nums.size == 2 %}
{% assign version_number = build_nums[0] %}
{% assign build_number = build_nums[1] %}
<enclosure
url="{{ asset.browser_download_url }}"
sparkle:version="{{ build_number }}"
sparkle:shortVersionString="{{ version_number }}"
sparkle:edSignature="{{ signature }}"
length="{{ asset.size }}"
type="application/octet-stream" />
{% else %}
{% assign version = release.tag_name | remove_first:'v' %}
<enclosure
url="{{ asset.browser_download_url }}"
sparkle:version="{{ version }}"
sparkle:edSignature="{{ signature }}"
length="{{ asset.size }}"
type="application/octet-stream" />
{% endif %}
{% endfor %}
</item>
{% endunless %}
{% endunless %}
{% endfor %}
</channel>
</rss>
================================================
FILE: AppCast/_plugins/signature_filter.rb
================================================
module Jekyll
module SignatureFilter
def sparkle_signature(release_body)
regex = /<!-- sparkle:edSignature=(?<signature>.*) -->/m
signature = release_body.match(regex).named_captures["signature"]
raise "Didn't find a signature in the release body." if signature.empty?
signature
end
end
end
Liquid::Template.register_filter(Jekyll::SignatureFilter)
================================================
FILE: AppCast/appcast.xml
================================================
---
release_only: true
---
{%include appcast.inc %}
================================================
FILE: AppCast/appcast_pre.xml
================================================
---
release_only: false
---
{%include appcast.inc %}
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Repeated low-quality pull requests or pull requests not in accordance to project goals especially after warning from a project maintainer or administrator
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
[Github Issues](https://github.com/CodeEditApp/CodeEdit/issues/new).
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
================================================
FILE: CONTRIBUTING.md
================================================
# Contribute to CodeEdit
Feel free to join and collaborate on our [Discord Server](https://discord.gg/vChUXVf9Em).
> [!WARNING]
> Please do not submit `localization` related pull requests at this time.
> Once we are ready to support more languages we will let you know with a guide on how to contribute here and on our [Discord Server](https://discord.gg/vChUXVf9Em).
## Fork & Clone CodeEdit
Tap the **"Fork"** button on the top of the site. After forking clone the forked repository to your Mac.
## Explore Issues
Find issues from the [Issues tab](https://github.com/CodeEditApp/CodeEdit/issues) or from the To Do column in our [project](https://github.com/orgs/CodeEditApp/projects/3). If you find an issue you want to work on, please indicate it in the issue and/or attach a draft PR once available. An admin or maintainer will then assign the Issue and/or PR to you.
> [!IMPORTANT]
> Please make sure to first comment under an issue or ask a maintainer to assign you to the issue before working on it. This helps prevent multiple people from working on the same
> thing, which could result in your work not being merged. Additionally, some issues might be reserved for those with more in-depth knowledge of the codebase.
## Getting Started
Please read the [Getting Started](https://github.com/CodeEditApp/CodeEdit/wiki/Getting-Started) guide in our wiki.
We also have a [troubleshooting guide](https://github.com/CodeEditApp/CodeEdit/wiki/Troubleshooting) that provides common resolutions.
## Code Style
Please read our guide on [Code Style](https://github.com/CodeEditApp/CodeEdit/wiki/Code-Style) in our wiki.
## Pull Request
Once you are happy with your changes, submit a `Pull Request`.
The pull request opens with a template loaded. Fill out all fields that are relevant.
The `PR` should include following information:
* A descriptive **title** on what changed.
* A detailed **description** of changes.
* If you made changes to the UI please add a **screenshot** or **video** as well.
* If there is a related issue please add a **reference to the issue**. If not, create one beforehand and link it.
* If your PR is still in progress mark it as **Draft**.
### Checks, Tests & Documentation
Request a review from one of our admins @austincondiff, @lukepistrol, @MarcoCarnevali, @jasonplatts, @pkasila or maintainers @cstef, @linusS1, @RayZhao1998, @wdg.
> [!TIP]
> If it is your first PR, an admin will need to request a review for you.
> [!IMPORTANT]
> Please resolve all `Violation` errors in Xcode (except: _TODO:_ warnings). Otherwise the swiftlint check on GitHub will fail.
Once you submit the `PR` GitHub will run a couple of actions which run tests and `SwiftLint` (this can take a couple of minutes). Should a test fail, it cannot be merged until tests succeed.
Make sure to resolve all merge-conflicts otherwise the `PR` cannot be merged.
> [!IMPORTANT]
> Make sure your code is well documented so others can interact with your code easily!
================================================
FILE: CodeEdit/AppDelegate.swift
================================================
//
// AppDelegate.swift
// CodeEdit
//
// Created by Pavel Kasila on 12.03.22.
//
import SwiftUI
import CodeEditSymbols
import CodeEditSourceEditor
import OSLog
@MainActor
final class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject {
private let logger = Logger(subsystem: Bundle.main.bundleIdentifier ?? "", category: "AppDelegate")
private let updater = SoftwareUpdater()
@Environment(\.openWindow)
var openWindow
@LazyService var lspService: LSPService
func applicationDidFinishLaunching(_ notification: Notification) {
enableWindowSizeSaveOnQuit()
Settings.shared.preferences.general.appAppearance.applyAppearance()
checkForFilesToOpen()
NSApp.closeWindow(.welcome, .about)
DispatchQueue.main.async {
var needToHandleOpen = true
// If no windows were reopened by NSQuitAlwaysKeepsWindows, do default behavior.
// Non-WindowGroup SwiftUI Windows are still in NSApp.windows when they are closed,
// So we need to think about those.
if NSApp.windows.count > NSApp.openSwiftUIWindows {
needToHandleOpen = false
}
for index in 0..<CommandLine.arguments.count {
if CommandLine.arguments[index] == "--open" && (index + 1) < CommandLine.arguments.count {
let path = CommandLine.arguments[index+1]
let url = URL(fileURLWithPath: path)
CodeEditDocumentController.shared.reopenDocument(
for: url,
withContentsOf: url,
display: true
) { document, _, _ in
document?.windowControllers.first?.synchronizeWindowTitleWithDocumentName()
}
needToHandleOpen = false
}
}
if needToHandleOpen {
self.handleOpen()
}
}
}
func applicationWillTerminate(_ aNotification: Notification) {
}
func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool {
true
}
func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool {
guard flag else {
handleOpen()
return false
}
/// Check if all windows are either miniaturized or not visible.
/// If so, attempt to find the first miniaturized window and deminiaturize it.
guard sender.windows.allSatisfy({ $0.isMiniaturized || !$0.isVisible }) else { return false }
sender.windows.first(where: { $0.isMiniaturized })?.deminiaturize(sender)
return false
}
func applicationShouldOpenUntitledFile(_ sender: NSApplication) -> Bool {
false
}
func handleOpen() {
let behavior = Settings.shared.preferences.general.reopenBehavior
switch behavior {
case .welcome:
if !tryFocusWindow(id: .welcome) {
openWindow(sceneID: .welcome)
}
case .openPanel:
CodeEditDocumentController.shared.openDocument(self)
case .newDocument:
CodeEditDocumentController.shared.newDocument(self)
}
}
/// Handle urls with the form `codeedit://file/{filepath}:{line}:{column}`
func application(_ application: NSApplication, open urls: [URL]) {
for url in urls {
let file = URL(fileURLWithPath: url.path).path.split(separator: ":")
let filePath = URL(fileURLWithPath: String(file[0]))
let line = file.count > 1 ? Int(file[1]) ?? 0 : 0
let column = file.count > 2 ? Int(file[2]) ?? 1 : 1
CodeEditDocumentController.shared
.openDocument(withContentsOf: filePath, display: true) { document, _, error in
if let error {
NSAlert(error: error).runModal()
return
}
if line > 0, let document = document as? CodeFileDocument {
document.openOptions = CodeFileDocument.OpenOptions(
cursorPositions: [CursorPosition(line: line, column: column > 0 ? column : 1)]
)
}
}
}
}
// MARK: - Should Terminate
/// Defers the application terminate message until we've finished cleanup.
///
/// All paths _must_ call `NSApplication.shared.reply(toApplicationShouldTerminate: true)` as soon as possible.
///
/// The two things needing deferring are:
/// - Language server cancellation
/// - Outstanding document changes.
///
/// Things that don't need deferring (happen immediately):
/// - Task termination.
/// These are called immediately if no documents need closing, and are called by
/// ``documentController(_:didCloseAll:contextInfo:)`` if there are documents we need to defer for.
///
/// See ``terminateLanguageServers()`` and ``documentController(_:didCloseAll:contextInfo:)`` for deferring tasks.
func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply {
let projects: [String] = CodeEditDocumentController.shared.documents
.compactMap { ($0 as? WorkspaceDocument)?.fileURL?.path }
UserDefaults.standard.set(projects, forKey: AppDelegate.recoverWorkspacesKey)
let areAllDocumentsClean = CodeEditDocumentController.shared.documents.allSatisfy { !$0.isDocumentEdited }
guard areAllDocumentsClean else {
CodeEditDocumentController.shared.closeAllDocuments(
withDelegate: self,
didCloseAllSelector: #selector(documentController(_:didCloseAll:contextInfo:)),
contextInfo: nil
)
// `documentController(_:didCloseAll:contextInfo:)` will call `terminateLanguageServers()`
return .terminateLater
}
terminateTasks()
terminateLanguageServers()
return .terminateLater
}
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
false
}
// MARK: - Open windows
@IBAction private func openWelcome(_ sender: Any) {
openWindow(sceneID: .welcome)
}
@IBAction private func openAbout(_ sender: Any) {
openWindow(sceneID: .about)
}
@IBAction func openFeedback(_ sender: Any) {
if tryFocusWindow(of: FeedbackView.self) { return }
FeedbackView().showWindow()
}
@IBAction private func checkForUpdates(_ sender: Any) {
updater.checkForUpdates()
}
/// Tries to focus a window with specified view content type.
/// - Parameter type: The type of viewContent which hosted in a window to be focused.
/// - Returns: `true` if window exist and focused, otherwise - `false`
private func tryFocusWindow<T: View>(of type: T.Type) -> Bool {
guard let window = NSApp.windows.filter({ ($0.contentView as? NSHostingView<T>) != nil }).first
else { return false }
window.makeKeyAndOrderFront(self)
return true
}
/// Tries to focus a window with specified sceneId
/// - Parameter type: Id of a window to be focused.
/// - Returns: `true` if window exist and focused, otherwise - `false`
private func tryFocusWindow(id: SceneID) -> Bool {
guard let window = NSApp.windows.filter({ $0.identifier?.rawValue == id.rawValue }).first
else { return false }
window.makeKeyAndOrderFront(self)
return true
}
// MARK: - Open With CodeEdit (Extension) functions
private func checkForFilesToOpen() {
guard let defaults = UserDefaults.init(
suiteName: "app.codeedit.CodeEdit.shared"
) else {
print("Failed to get/init shared defaults")
return
}
// Register enableOpenInCE (enable Open In CodeEdit
defaults.register(defaults: ["enableOpenInCE": true])
if let filesToOpen = defaults.string(forKey: "openInCEFiles") {
let files = filesToOpen.split(separator: ";")
for filePath in files {
let fileURL = URL(fileURLWithPath: String(filePath))
CodeEditDocumentController.shared.reopenDocument(
for: fileURL,
withContentsOf: fileURL,
display: true
) { document, _, _ in
document?.windowControllers.first?.synchronizeWindowTitleWithDocumentName()
}
}
defaults.removeObject(forKey: "openInCEFiles")
}
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in
self?.checkForFilesToOpen()
}
}
/// Enable window size restoring on app relaunch after quitting.
private func enableWindowSizeSaveOnQuit() {
// This enables window restoring on normal quit (instead of only on force-quit).
UserDefaults.standard.setValue(true, forKey: "NSQuitAlwaysKeepsWindows")
}
// MARK: NSDocumentController delegate
@objc
func documentController(_ docController: NSDocumentController, didCloseAll: Bool, contextInfo: Any) {
if didCloseAll {
terminateTasks()
terminateLanguageServers()
}
}
/// Terminates running language servers. Used during app termination to ensure resources are freed.
private func terminateLanguageServers() {
Task { @MainActor in
let task = TaskNotificationModel(
id: "appdelegate.terminate_language_servers",
title: "Stopping Language Servers",
message: "Stopping running language server processes...",
isLoading: true
)
if !lspService.languageClients.isEmpty {
TaskNotificationHandler.postTask(action: .create, model: task)
}
try? await withTimeout(
duration: .seconds(2.0),
onTimeout: {
// Stop-gap measure to ensure we don't hang on CMD-Q
await self.lspService.killAllServers()
},
operation: {
await self.lspService.stopAllServers()
}
)
TaskNotificationHandler.postTask(action: .delete, model: task)
NSApplication.shared.reply(toApplicationShouldTerminate: true)
}
}
/// Terminates all running tasks. Used during app termination to ensure resources are freed.
private func terminateTasks() {
let task = TaskNotificationModel(
id: "appdelegate.terminate_tasks",
title: "Terminating Tasks",
message: "Interrupting all running tasks before quitting...",
isLoading: true
)
let taskManagers = CodeEditDocumentController.shared.documents
.compactMap({ $0 as? WorkspaceDocument })
.compactMap({ $0.taskManager })
if taskManagers.reduce(0, { $0 + $1.activeTasks.count }) > 0 {
TaskNotificationHandler.postTask(action: .create, model: task)
}
taskManagers.forEach { manager in
manager.stopAllTasks()
}
TaskNotificationHandler.postTask(action: .delete, model: task)
}
}
extension AppDelegate {
static let recoverWorkspacesKey = "recover.workspaces"
}
================================================
FILE: CodeEdit/Assets.xcassets/AccentColor.colorset/Contents.json
================================================
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: CodeEdit/Assets.xcassets/AppIcon.appiconset/Contents.json
================================================
{
"images" : [
{
"filename" : "CodeEdit-16.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "16x16"
},
{
"filename" : "CodeEdit-16@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "16x16"
},
{
"filename" : "CodeEdit-32.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "32x32"
},
{
"filename" : "CodeEdit-32@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "32x32"
},
{
"filename" : "CodeEdit-128.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "128x128"
},
{
"filename" : "CodeEdit-128@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "128x128"
},
{
"filename" : "CodeEdit-256.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "256x256"
},
{
"filename" : "CodeEdit-256@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "256x256"
},
{
"filename" : "CodeEdit-512.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "512x512"
},
{
"filename" : "CodeEdit-512@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "512x512"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: CodeEdit/Assets.xcassets/AppIconAlpha.appiconset/Contents.json
================================================
{
"images" : [
{
"filename" : "CodeEditAlpha-16.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "16x16"
},
{
"filename" : "CodeEditAlpha-16@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "16x16"
},
{
"filename" : "CodeEditAlpha-32.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "32x32"
},
{
"filename" : "CodeEditAlpha-32@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "32x32"
},
{
"filename" : "CodeEditAlpha-128.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "128x128"
},
{
"filename" : "CodeEditAlpha-128@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "128x128"
},
{
"filename" : "CodeEditAlpha-256.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "256x256"
},
{
"filename" : "CodeEditAlpha-256@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "256x256"
},
{
"filename" : "CodeEditAlpha-512.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "512x512"
},
{
"filename" : "CodeEditAlpha-512@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "512x512"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: CodeEdit/Assets.xcassets/AppIconBeta.appiconset/Contents.json
================================================
{
"images" : [
{
"filename" : "CodeEditBeta-16.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "16x16"
},
{
"filename" : "CodeEditBeta-16@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "16x16"
},
{
"filename" : "CodeEditBeta-32.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "32x32"
},
{
"filename" : "CodeEditBeta-32@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "32x32"
},
{
"filename" : "CodeEditBeta-128.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "128x128"
},
{
"filename" : "CodeEditBeta-128@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "128x128"
},
{
"filename" : "CodeEditBeta-256.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "256x256"
},
{
"filename" : "CodeEditBeta-256@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "256x256"
},
{
"filename" : "CodeEditBeta-512.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "512x512"
},
{
"filename" : "CodeEditBeta-512@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "512x512"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: CodeEdit/Assets.xcassets/AppIconDev.appiconset/Contents.json
================================================
{
"images" : [
{
"filename" : "CodeEditDev-16.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "16x16"
},
{
"filename" : "CodeEditDev-16@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "16x16"
},
{
"filename" : "CodeEditDev-32.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "32x32"
},
{
"filename" : "CodeEditDev-32@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "32x32"
},
{
"filename" : "CodeEditDev-128.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "128x128"
},
{
"filename" : "CodeEditDev-128@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "128x128"
},
{
"filename" : "CodeEditDev-256.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "256x256"
},
{
"filename" : "CodeEditDev-256@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "256x256"
},
{
"filename" : "CodeEditDev-512.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "512x512"
},
{
"filename" : "CodeEditDev-512@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "512x512"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: CodeEdit/Assets.xcassets/AppIconPre.appiconset/Contents.json
================================================
{
"images" : [
{
"filename" : "CodeEdit-Icon-Pre-16.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "16x16"
},
{
"filename" : "CodeEdit-Icon-Pre-16@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "16x16"
},
{
"filename" : "CodeEdit-Icon-Pre-32.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "32x32"
},
{
"filename" : "CodeEdit-Icon-Pre-32@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "32x32"
},
{
"filename" : "CodeEdit-Icon-Pre-128.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "128x128"
},
{
"filename" : "CodeEdit-Icon-Pre-128@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "128x128"
},
{
"filename" : "CodeEdit-Icon-Pre-256.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "256x256"
},
{
"filename" : "CodeEdit-Icon-Pre-256@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "256x256"
},
{
"filename" : "CodeEdit-Icon-Pre-512.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "512x512"
},
{
"filename" : "CodeEdit-Icon-Pre-512@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "512x512"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: CodeEdit/Assets.xcassets/Contents.json
================================================
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: CodeEdit/Assets.xcassets/Custom Colors/Amber.colorset/Contents.json
================================================
{
"colors" : [
{
"color" : {
"color-space" : "display-p3",
"components" : {
"alpha" : "1.000",
"blue" : "0.133",
"green" : "0.635",
"red" : "0.784"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "display-p3",
"components" : {
"alpha" : "1.000",
"blue" : "0.302",
"green" : "0.812",
"red" : "0.961"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: CodeEdit/Assets.xcassets/Custom Colors/Contents.json
================================================
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: CodeEdit/Assets.xcassets/Custom Colors/CoolGray.colorset/Contents.json
================================================
{
"colors" : [
{
"color" : {
"color-space" : "display-p3",
"components" : {
"alpha" : "1.000",
"blue" : "0.553",
"green" : "0.541",
"red" : "0.518"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "display-p3",
"components" : {
"alpha" : "1.000",
"blue" : "0.549",
"green" : "0.537",
"red" : "0.525"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: CodeEdit/Assets.xcassets/Custom Colors/FolderBlue.colorset/Contents.json
================================================
{
"colors" : [
{
"color" : {
"color-space" : "display-p3",
"components" : {
"alpha" : "1.000",
"blue" : "0.973",
"green" : "0.698",
"red" : "0.125"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "display-p3",
"components" : {
"alpha" : "1.000",
"blue" : "0.859",
"green" : "0.698",
"red" : "0.365"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: CodeEdit/Assets.xcassets/Custom Colors/InspectorBackgroundColor.colorset/Contents.json
================================================
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0xF7",
"green" : "0xF5",
"red" : "0xF4"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0x25",
"green" : "0x1F",
"red" : "0x1C"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: CodeEdit/Assets.xcassets/Custom Colors/Scarlet.colorset/Contents.json
================================================
{
"colors" : [
{
"color" : {
"color-space" : "display-p3",
"components" : {
"alpha" : "1.000",
"blue" : "0.176",
"green" : "0.303",
"red" : "0.956"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "display-p3",
"components" : {
"alpha" : "1.000",
"blue" : "0.376",
"green" : "0.475",
"red" : "0.960"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: CodeEdit/Assets.xcassets/Custom Colors/Steel.colorset/Contents.json
================================================
{
"colors" : [
{
"color" : {
"color-space" : "display-p3",
"components" : {
"alpha" : "1.000",
"blue" : "0.522",
"green" : "0.463",
"red" : "0.373"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "display-p3",
"components" : {
"alpha" : "1.000",
"blue" : "0.749",
"green" : "0.690",
"red" : "0.585"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: CodeEdit/Assets.xcassets/Icons/BitBucketIcon.imageset/Contents.json
================================================
{
"images" : [
{
"filename" : "BitBucketIcon.png",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: CodeEdit/Assets.xcassets/Icons/Contents.json
================================================
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: CodeEdit/Assets.xcassets/Icons/GitHubIcon.imageset/Contents.json
================================================
{
"images" : [
{
"filename" : "GitHubIcon.png",
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "GitHubIcon-Dark.png",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: CodeEdit/Assets.xcassets/Icons/GitLabIcon.imageset/Contents.json
================================================
{
"images" : [
{
"filename" : "GitLabIcon.png",
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "GitLabIcon-Dark.png",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: CodeEdit/Assets.xcassets/line.3.horizontal.decrease.chevron.filled.imageset/Contents.json
================================================
{
"images" : [
{
"filename" : "line.3.horizontal.decrease.chevron.filled.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "template"
}
}
================================================
FILE: CodeEdit/Assets.xcassets/line.3.horizontal.decrease.chevron.imageset/Contents.json
================================================
{
"images" : [
{
"filename" : "line.3.horizontal.decrease.chevron.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "template"
}
}
================================================
FILE: CodeEdit/CodeEdit.entitlements
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
<key>com.apple.security.files.bookmarks.app-scope</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>app.codeedit.CodeEdit.shared</string>
<string>$(TeamIdentifierPrefix)</string>
</array>
</dict>
</plist>
================================================
FILE: CodeEdit/CodeEditApp.swift
================================================
//
// CodeEditApp.swift
// CodeEdit
//
// Created by Wouter Hennen on 11/03/2023.
//
import SwiftUI
import WelcomeWindow
import AboutWindow
@main
struct CodeEditApp: App {
@NSApplicationDelegateAdaptor var appdelegate: AppDelegate
@ObservedObject var settings = Settings.shared
let updater: SoftwareUpdater = SoftwareUpdater()
init() {
// Register singleton services before anything else
ServiceContainer.register(
LSPService()
)
_ = CodeEditDocumentController.shared
NSMenuItem.swizzle()
NSSplitViewItem.swizzle()
}
var body: some Scene {
Group {
WelcomeWindow(
subtitleView: { WelcomeSubtitleView() },
actions: { dismissWindow in
NewFileButton(dismissWindow: dismissWindow)
GitCloneButton(dismissWindow: dismissWindow)
OpenFileOrFolderButton(dismissWindow: dismissWindow)
},
onDrop: { url, dismissWindow in
Task {
await CodeEditDocumentController.shared.openDocument(at: url, onCompletion: { dismissWindow() })
}
}
)
ExtensionManagerWindow()
AboutWindow(
subtitleView: { AboutSubtitleView() },
actions: {
AboutButton(title: "Contributors", destination: {
ContributorsView()
})
AboutButton(title: "Acknowledgements", destination: {
AcknowledgementsView()
})
},
footer: { AboutFooterView() }
)
SettingsWindow()
.commands {
CodeEditCommands()
}
}
.environment(\.settings, settings.preferences) // Add settings to each window environment
}
}
================================================
FILE: CodeEdit/Features/About/AboutFooterView.swift
================================================
//
// AboutFooterView.swift
// CodeEdit
//
// Created by Giorgi Tchelidze on 08.06.25.
//
import SwiftUI
import AboutWindow
struct AboutFooterView: View {
var body: some View {
FooterView(
primaryView: {
Link(destination: URL(string: "https://github.com/CodeEditApp/CodeEdit/blob/main/LICENSE.md")!) {
Text("MIT License")
.underline()
}
},
secondaryView: {
Text(Bundle.copyrightString ?? "")
}
)
}
}
================================================
FILE: CodeEdit/Features/About/AboutSubtitleView.swift
================================================
//
// AboutSubtitleView.swift
// CodeEdit
//
// Created by Giorgi Tchelidze on 08.06.25.
//
import SwiftUI
struct AboutSubtitleView: View {
@State private var didCopyVersion = false
@State private var isHoveringVersion = false
private var appVersion: String { Bundle.versionString ?? "No Version" }
private var appBuild: String { Bundle.buildString ?? "No Build" }
private var appVersionPostfix: String { Bundle.versionPostfix ?? "" }
var body: some View {
Text("Version \(appVersion)\(appVersionPostfix) (\(appBuild))")
.textSelection(.disabled)
.onTapGesture {
// Create a string suitable for pasting into a bug report
let macOSVersion = ProcessInfo.processInfo.operatingSystemVersion.semverString
NSPasteboard.general.clearContents()
NSPasteboard.general.setString(
"CodeEdit: \(appVersion) (\(appBuild))\nmacOS: \(macOSVersion)",
forType: .string
)
didCopyVersion.toggle()
}
.background(alignment: .leading) {
if isHoveringVersion {
if #available(macOS 14.0, *) {
Image(systemName: "document.on.document.fill")
.font(.caption)
.offset(x: -16, y: 0)
.transition(.opacity)
.symbolEffect(
.bounce.down.wholeSymbol,
options: .nonRepeating.speed(1.8),
value: didCopyVersion
)
} else {
Image(systemName: "document.on.document.fill")
.font(.caption)
.offset(x: -16, y: 0)
.transition(.opacity)
}
}
}
.onHover { hovering in
withAnimation(.easeInOut(duration: 0.1)) {
isHoveringVersion = hovering
}
}
}
}
================================================
FILE: CodeEdit/Features/About/Acknowledgements/ViewModels/AcknowledgementsViewModel.swift
================================================
//
// AcknowledgementsModel.swift
// CodeEditModules/Acknowledgements
//
// Created by Lukas Pistrol on 01.05.22.
//
import SwiftUI
final class AcknowledgementsViewModel: ObservableObject {
@Published private(set) var acknowledgements: [AcknowledgementDependency]
var indexedAcknowledgements: [(index: Int, acknowledgement: AcknowledgementDependency)] {
return Array(zip(acknowledgements.indices, acknowledgements))
}
init(_ dependencies: [AcknowledgementDependency] = []) {
self.acknowledgements = dependencies
if acknowledgements.isEmpty {
fetchDependencies()
}
}
func fetchDependencies() {
self.acknowledgements.removeAll()
do {
if let bundlePath = Bundle.main.path(forResource: "Package", ofType: "resolved") {
let jsonData = try String(contentsOfFile: bundlePath).data(using: .utf8)
let parsedJSON = try JSONDecoder().decode(AcknowledgementObject.self, from: jsonData!)
for dependency in parsedJSON.pins.sorted(by: { $0.identity < $1.identity })
where dependency.identity.range(
of: "[Cc]ode[Ee]dit",
options: .regularExpression,
range: nil,
locale: nil
) == nil {
self.acknowledgements.append(
AcknowledgementDependency(
name: dependency.name,
repositoryLink: dependency.location,
version: dependency.state.version ?? "-"
)
)
}
}
} catch {
print(error)
}
}
}
================================================
FILE: CodeEdit/Features/About/Acknowledgements/Views/AcknowledgementRowView.swift
================================================
//
// AcknowledgementsRowView.swift
// CodeEdit
//
// Created by Austin Condiff on 1/19/23.
//
import SwiftUI
struct AcknowledgementRowView: View {
@Environment(\.openURL)
private var openURL
let acknowledgement: AcknowledgementDependency
var body: some View {
HStack {
Text(acknowledgement.name)
.font(.body)
Spacer()
Button {
openURL(acknowledgement.repositoryURL)
} label: {
Image(systemName: "arrow.right.circle.fill")
.foregroundColor(Color(nsColor: .tertiaryLabelColor))
}
.buttonStyle(.plain)
}
.padding(.vertical, 12)
.frame(maxWidth: .infinity)
}
}
struct AcknowledgementsRowView_Previews: PreviewProvider {
static var previews: some View {
AcknowledgementRowView(acknowledgement: AcknowledgementDependency(
name: "Test",
repositoryLink: "https://www.test.com/",
version: "-"
))
}
}
================================================
FILE: CodeEdit/Features/About/Acknowledgements/Views/AcknowledgementsView.swift
================================================
//
// AcknowledgementsView.swift
// CodeEditModules/Acknowledgements
//
// Created by Shivesh M M on 4/4/22.
//
import SwiftUI
import AboutWindow
struct AcknowledgementsView: View {
@StateObject var model = AcknowledgementsViewModel()
var body: some View {
AboutDetailView(title: "Acknowledgements") {
LazyVStack(spacing: 0) {
ForEach(
model.indexedAcknowledgements,
id: \.acknowledgement.name
) { (index, acknowledgement) in
if index != 0 {
Divider()
.frame(height: 0.5)
.opacity(0.5)
}
AcknowledgementRowView(acknowledgement: acknowledgement)
}
}
}
}
}
================================================
FILE: CodeEdit/Features/About/Acknowledgements/Views/ParsePackagesResolved.swift
================================================
//
// ParsePackagesResolved.swift
// CodeEditModules/Acknowledgements
//
// Created by Shivesh M M on 4/4/22.
//
import Foundation
struct AcknowledgementDependency: Decodable {
var name: String
var repositoryLink: String
var version: String
var repositoryURL: URL {
URL(string: repositoryLink)!
}
}
// MARK: - Object
struct AcknowledgementObject: Codable {
let pins: [AcknowledgementPin]
}
// MARK: - Pin
struct AcknowledgementPin: Codable {
let identity: String
let location: String
let state: AcknowledgementPackageState
var name: String {
location.split(separator: "/").last?.replacingOccurrences(of: ".git", with: "") ?? identity
}
}
// MARK: - State
struct AcknowledgementPackageState: Codable {
let revision: String
let version: String?
}
================================================
FILE: CodeEdit/Features/About/BlurButtonStyle.swift
================================================
//
// BlurButtonStyle.swift
// CodeEdit
//
// Created by Wouter Hennen on 21/01/2023.
//
import SwiftUI
extension ButtonStyle where Self == BlurButtonStyle {
static var blur: BlurButtonStyle { BlurButtonStyle() }
static var secondaryBlur: BlurButtonStyle { BlurButtonStyle(isSecondary: true) }
}
struct BlurButtonStyle: ButtonStyle {
var isSecondary: Bool = false
@Environment(\.controlSize)
var controlSize
@Environment(\.colorScheme)
var colorScheme
var height: CGFloat {
switch controlSize {
case .large:
return 28
default:
return 20
}
}
func makeBody(configuration: Configuration) -> some View {
configuration.label
.padding(.horizontal, 8)
.frame(height: height)
.background {
switch colorScheme {
case .dark:
ZStack {
Color.gray.opacity(0.001)
if isSecondary {
Rectangle()
.fill(.regularMaterial)
} else {
Rectangle()
.fill(.regularMaterial)
.blendMode(.plusLighter)
}
Color.gray.opacity(isSecondary ? 0.10 : 0.30)
Color.white.opacity(configuration.isPressed ? 0.10 : 0.00)
}
case .light:
ZStack {
Color.gray.opacity(0.001)
Rectangle()
.fill(.regularMaterial)
.blendMode(.darken)
Color.gray.opacity(isSecondary ? 0.05 : 0.15)
.blendMode(.plusDarker)
Color.gray.opacity(configuration.isPressed ? 0.10 : 0.00)
}
@unknown default:
Color.black
}
}
.clipShape(RoundedRectangle(cornerRadius: controlSize == .large ? 6 : 5))
}
}
================================================
FILE: CodeEdit/Features/About/Contributors/ContributorRowView.swift
================================================
//
// ContributorRowView.swift
// CodeEdit
//
// Created by Lukas Pistrol on 19.01.23.
//
import SwiftUI
import CodeEditSymbols
struct ContributorRowView: View {
let contributor: Contributor
var body: some View {
HStack {
userImage
VStack(alignment: .leading, spacing: 2) {
HStack {
Text(contributor.name)
.font(.headline)
}
HStack(spacing: 3) {
ForEach(contributor.contributions, id: \.self) { item in
tag(item)
}
}
}
Spacer()
HStack(alignment: .top) {
if let profileURL = contributor.profileURL, profileURL != contributor.gitHubURL {
ActionButton(url: profileURL, image: .init(systemName: "globe"))
}
if let gitHubURL = contributor.gitHubURL {
ActionButton(url: gitHubURL, image: .github)
}
}
}
.padding(.vertical, 8)
}
private var userImage: some View {
AsyncImage(url: contributor.avatarURL) { image in
image
.resizable()
.frame(width: 32, height: 32)
.clipShape(Circle())
.help(contributor.name)
} placeholder: {
Image(systemName: "person.circle.fill")
.resizable()
.frame(width: 32, height: 32)
.help(contributor.name)
}
}
private func tag(_ item: Contributor.Contribution) -> some View {
Text(item.rawValue.capitalized)
.font(.caption)
.padding(.horizontal, 6)
.padding(.vertical, 1)
.foregroundColor(item.color)
.background {
Capsule(style: .continuous)
.strokeBorder(lineWidth: 1)
.foregroundStyle(item.color)
.opacity(0.8)
}
}
private struct ActionButton: View {
@Environment(\.openURL)
private var openURL
@State private var hovering = false
let url: URL
let image: Image
var body: some View {
Button {
openURL(url)
} label: {
image
.imageScale(.medium)
.foregroundColor(hovering ? .primary : .secondary)
}
.buttonStyle(.plain)
.onHover { hover in
hovering = hover
}
}
}
}
struct ContributorRowView_Previews: PreviewProvider {
static var previews: some View {
let contributor = Contributor(
login: "lukepistrol",
name: "Lukas Pistrol",
avatarURLString: "https://avatars.githubusercontent.com/u/9460130?v=4",
profile: "http://lukaspistrol.com",
contributions: [.infra, .test, .code]
)
ContributorRowView(contributor: contributor)
.frame(width: 350)
}
}
================================================
FILE: CodeEdit/Features/About/Contributors/ContributorsView.swift
================================================
//
// ContributorsView.swift
// CodeEdit
//
// Created by Lukas Pistrol on 19.01.23.
//
import SwiftUI
import AboutWindow
struct ContributorsView: View {
@StateObject var model = ContributorsViewModel()
var body: some View {
AboutDetailView(title: "Contributors") {
LazyVStack(spacing: 0) {
ForEach(model.contributors) { contributor in
ContributorRowView(contributor: contributor)
Divider()
.frame(height: 0.5)
.opacity(0.5)
}
}
}
}
}
class ContributorsViewModel: ObservableObject {
@Published private(set) var contributors: [Contributor] = []
init() {
guard let url = Bundle.main.url(
forResource: ".all-contributorsrc",
withExtension: nil
) else { return }
do {
let data = try Data(contentsOf: url)
let root = try JSONDecoder().decode(ContributorsRoot.self, from: data)
self.contributors = root.contributors
} catch {
print(error)
}
}
}
================================================
FILE: CodeEdit/Features/About/Contributors/Model/Contributor.swift
================================================
//
// Contributor.swift
// CodeEdit
//
// Created by Lukas Pistrol on 19.01.23.
//
import SwiftUI
struct ContributorsRoot: Codable {
var contributors: [Contributor]
}
struct Contributor: Codable, Identifiable {
var id: String { login }
var login: String
var name: String
var avatarURLString: String
var profile: String
var contributions: [Contribution]
var avatarURL: URL? {
URL(string: avatarURLString)
}
var gitHubURL: URL? {
URL(string: "https://github.com/\(login)")
}
var profileURL: URL? {
URL(string: profile)
}
enum CodingKeys: String, CodingKey {
case login, name, profile, contributions
case avatarURLString = "avatar_url"
}
enum Contribution: String, Codable {
case design, code, infra, test, bug, maintenance, plugin
var color: Color {
switch self {
case .design: return .blue
case .code: return .indigo
case .infra: return .pink
case .test: return .purple
case .bug: return .red
case .maintenance: return .brown
case .plugin: return .gray
}
}
}
}
================================================
FILE: CodeEdit/Features/ActivityViewer/ActivityViewer.swift
================================================
//
// ActivityViewer.swift
// CodeEdit
//
// Created by Tommy Ludwig on 21.06.24.
//
import SwiftUI
/// A view that shows the activity bar and the current status of any executed task
struct ActivityViewer: View {
@Environment(\.colorScheme)
var colorScheme
var workspaceFileManager: CEWorkspaceFileManager?
@ObservedObject var taskNotificationHandler: TaskNotificationHandler
@ObservedObject var workspaceSettingsManager: CEWorkspaceSettings
// TODO: try to get this from the envrionment
@ObservedObject var taskManager: TaskManager
init(
workspaceFileManager: CEWorkspaceFileManager?,
workspaceSettingsManager: CEWorkspaceSettings,
taskNotificationHandler: TaskNotificationHandler,
taskManager: TaskManager
) {
self.workspaceFileManager = workspaceFileManager
self.workspaceSettingsManager = workspaceSettingsManager
self.taskNotificationHandler = taskNotificationHandler
self.taskManager = taskManager
}
var body: some View {
Group {
if #available(macOS 26, *) {
content
.fixedSize(horizontal: false, vertical: false)
.padding(5)
// TaskNotificationView doesn't have it's own padding
// Also this padding seems weird. However, we want the spinning circle to be padded with the same
// amount from both the top and bottom, as well as the trailing edge. So despite it not being exactly
// the same it *looks* correctly padded
.padding(.trailing, 5)
.clipShape(Capsule())
.frame(minWidth: 200)
} else {
content
.fixedSize(horizontal: false, vertical: false)
.padding(.horizontal, 5)
.padding(.vertical, 1.5)
.frame(height: 22)
.clipped()
.background {
if colorScheme == .dark {
RoundedRectangle(cornerRadius: 5)
.opacity(0.1)
} else {
RoundedRectangle(cornerRadius: 5)
.opacity(0.1)
}
}
}
}
.accessibilityElement(children: .contain)
.accessibilityLabel("Activity Viewer")
}
@ViewBuilder private var content: some View {
HStack(spacing: 0) {
SchemeDropDownView(
workspaceSettingsManager: workspaceSettingsManager,
workspaceFileManager: workspaceFileManager
)
TaskDropDownView(taskManager: taskManager)
Spacer(minLength: 0)
TaskNotificationView(taskNotificationHandler: taskNotificationHandler)
.fixedSize()
}
}
}
================================================
FILE: CodeEdit/Features/ActivityViewer/Models/TaskNotificationModel.swift
================================================
//
// TaskNotificationModel.swift
// CodeEdit
//
// Created by Tommy Ludwig on 21.06.24.
//
import Foundation
/// Represents a notifications or tasks, that are displayed in the activity viewer
struct TaskNotificationModel: Equatable {
var id: String
var title: String
var message: String?
var percentage: Double?
var isLoading: Bool = false
}
================================================
FILE: CodeEdit/Features/ActivityViewer/Notifications/CECircularProgressView.swift
================================================
//
// CECircularProgressView.swift
// CodeEdit
//
// Created by Tommy Ludwig on 21.06.24.
//
import SwiftUI
struct CECircularProgressView: View {
@State private var isAnimating = false
@State private var previousValue: Bool = false
var progress: Double?
var currentTaskCount: Int = 1
let lineWidth: CGFloat = 2
var body: some View {
Circle()
.stroke(style: StrokeStyle(lineWidth: lineWidth))
.foregroundStyle(.tertiary)
.overlay {
if let progress = progress {
Circle()
.trim(from: 0, to: progress)
.stroke(Color.accentColor, style: StrokeStyle(lineWidth: lineWidth, lineCap: .round))
.animation(.easeInOut, value: progress)
} else {
Circle()
.trim(from: 0, to: 0.5)
.stroke(Color.accentColor, style: StrokeStyle(lineWidth: lineWidth, lineCap: .round))
.rotationEffect(
previousValue ?
.degrees(isAnimating ? 0 : -360)
: .degrees(isAnimating ? 360 : 0)
)
.animation(Animation.linear(duration: 1).repeatForever(autoreverses: false), value: isAnimating)
.onAppear {
self.previousValue = isAnimating
self.isAnimating.toggle()
}
}
}
.rotationEffect(.degrees(-90))
.padding(lineWidth/2)
.overlay {
if currentTaskCount > 1 {
Text("\(currentTaskCount)")
.font(.caption)
}
}
.accessibilityElement()
.accessibilityAddTraits(.updatesFrequently)
.accessibilityValue(
progress != nil ? Text(progress!, format: .percent) : Text("working")
)
}
}
#Preview {
Group {
CECircularProgressView(currentTaskCount: 1)
.frame(width: 22, height: 22)
CECircularProgressView(progress: 0.65, currentTaskCount: 1)
.frame(width: 22, height: 22)
}
.padding()
}
================================================
FILE: CodeEdit/Features/ActivityViewer/Notifications/TaskNotificationHandler.swift
================================================
//
// TaskNotificationHandler.swift
// CodeEdit
//
// Created by Tommy Ludwig on 21.06.24.
//
import Foundation
import Combine
/// Manages task-related notifications.
///
/// This class listens for notifications named `.taskNotification` and performs actions
/// such as creating, updating, or deleting tasks based on the notification's content.
///
/// When a task is created, it is added to the end of the array. The activity viewer displays
/// only the first item in the array. To immediately display a notification, use the
/// `"action": "createWithPriority"` option to insert the task at the beginning of the array.
/// *Note: This option should be reserved for important notifications only.*
///
/// It is recommended to use `UUID().uuidString` to generate a unique identifier for each task.
/// This identifier can then be used to update or delete the task. Alternatively, you can use any
/// unique identifier, such as a token sent from a language server.
///
/// Remember to manage your task notifications appropriately. You should either delete task
/// notifications manually or schedule their deletion in advance using the `deleteWithDelay` method.
///
/// Some tasks should be restricted to a specific workspace. To do this, specify the `workspace` attribute in the
/// notification's `userInfo` dictionary as a `URL`, or use the `toWorkspace` parameter on
/// ``TaskNotificationHandler/postTask(toWorkspace:action:model:)``.
///
/// ## Available Methods
/// - `create`:
/// Creates a new Task Notification.
/// Required fields: `id` (String), `action` (String), `title` (String).
/// Optional fields: `message` (String), `percentage` (Double), `isLoading` (Bool), `workspace` (URL).
/// - `createWithPriority`:
/// Creates a new Task Notification and inserts it at the start of the array.
/// This ensures it appears in the activity viewer even if there are other task notifications before it.
/// **Note:** This should only be used for important notifications!
/// Required fields: `id` (String), `action` (String), `title` (String).
/// Optional fields: `message` (String), `percentage` (Double), `isLoading` (Bool), `workspace` (URL).
/// - `update`:
/// Updates an existing task notification. It's important to pass the same `id` to update the correct task.
/// Required fields: `id` (String), `action` (String).
/// Optional fields: `title` (String), `message` (String), `percentage` (Double), `isLoading` (Bool),
/// `workspace` (URL).
/// - `delete`:
/// Deletes an existing task notification.
/// Required fields: `id` (String), `action` (String).
/// Optional field: `workspace` (URL).
/// - `deleteWithDelay`:
/// Deletes an existing task notification after a certain `TimeInterval`.
/// Required fields: `id` (String), `action` (String), `delay` (Double).
/// Optional field: `workspace` (URL).
/// **Important:** When specifying the delay, ensure it's a double.
/// For example, '2' would be invalid because it would count as an integer, use '2.0' instead.
///
/// ## Example Usage:
/// ```swift
/// let uuidString = UUID().uuidString
///
/// func createTask() {
/// let userInfo: [String: Any] = [
/// "id": "uniqueTaskID",
/// "action": "create",
/// "title": "Task Title"
/// ]
/// NotificationCenter.default.post(name: .taskNotification, object: nil, userInfo: userInfo)
/// }
///
/// func createTaskWithPriority() {
/// let userInfo: [String: Any] = [
/// "id": "uniqueTaskID",
/// "action": "createWithPriority",
/// "title": "Priority Task Title"
/// ]
/// NotificationCenter.default.post(name: .taskNotification, object: nil, userInfo: userInfo)
/// }
///
/// func updateTask() {
/// var userInfo: [String: Any] = [
/// "id": "uniqueTaskID",
/// "action": "update",
/// "title": "Updated Task Title",
/// "message": "Updated Task Message",
/// "percentage": 0.5,
/// "isLoading": true
/// ]
/// NotificationCenter.default.post(name: .taskNotification, object: nil, userInfo: userInfo)
/// }
///
/// func deleteTask() {
/// let userInfo: [String: Any] = [
/// "id": "uniqueTaskID",
/// "action": "delete"
/// ]
/// NotificationCenter.default.post(name: .taskNotification, object: nil, userInfo: userInfo)
/// }
///
/// func deleteTaskWithDelay() {
/// let userInfo: [String: Any] = [
/// "id": "uniqueTaskID",
/// "action": "deleteWithDelay",
/// "delay": 4.0 // 4 would be invalid, because it would count as an int
/// ]
/// NotificationCenter.default.post(name: .taskNotification, object: nil, userInfo: userInfo)
/// }
/// ```
///
/// You can also use the static helper method instead of creating dictionaries manually:
/// ```swift
/// TaskNotificationHandler.postTask(action: .create, model: .init(id: "task_id", "title": "New Task"))
/// ```
///
/// - Important: Please refer to ``CodeEdit/TaskNotificationModel`` and ensure you pass the correct values.
final class TaskNotificationHandler: ObservableObject {
@Published private(set) var notifications: [TaskNotificationModel] = []
var workspaceURL: URL?
var cancellables: Set<AnyCancellable> = []
enum Action: String {
case create
case createWithPriority
case update
case delete
case deleteWithDelay
}
/// Post a new task.
/// - Parameters:
/// - toWorkspace: The workspace to restrict the task to. Defaults to `nil`, which is received by all workspaces.
/// - action: The action being taken on the task.
/// - model: The task contents.
@MainActor
static func postTask(toWorkspace: URL? = nil, action: Action, model: TaskNotificationModel) {
NotificationCenter.default.post(name: .taskNotification, object: nil, userInfo: [
"id": model.id,
"title": model.title,
"message": model.message as Any,
"percentage": model.percentage as Any,
"isLoading": model.isLoading,
"action": action.rawValue,
"workspace": toWorkspace as Any
])
}
/// Initialises a new `TaskNotificationHandler` and starts observing for task notifications.
init(workspaceURL: URL? = nil) {
self.workspaceURL = workspaceURL
NotificationCenter.default
.publisher(for: .taskNotification)
.receive(on: DispatchQueue.main)
.sink { notification in
self.handleNotification(notification)
}
.store(in: &cancellables)
}
deinit {
NotificationCenter.default.removeObserver(self, name: .taskNotification, object: nil)
}
/// Handles notifications about task events.
///
/// - Parameter notification: The notification containing task information.
private func handleNotification(_ notification: Notification) {
guard let userInfo = notification.userInfo,
let taskID = userInfo["id"] as? String,
let actionRaw = userInfo["action"] as? String,
let action = Action(rawValue: actionRaw) else { return }
// If a workspace is specified and doesn't match, don't do anything with this task.
if let workspaceURL = userInfo["workspace"] as? URL, workspaceURL != self.workspaceURL {
return
}
switch action {
case .create, .createWithPriority:
createTask(task: userInfo)
case .update:
updateTask(task: userInfo)
case .delete:
deleteTask(taskID: taskID)
case .deleteWithDelay:
if let delay = userInfo["delay"] as? Double {
deleteTaskAfterDelay(taskID: taskID, delay: delay)
}
}
}
/// Creates a new task or inserts it at the beginning of the tasks array based on the action.
///
/// - Parameter task: A dictionary containing task information.
private func createTask(task: [AnyHashable: Any]) {
guard let title = task["title"] as? String,
let id = task["id"] as? String,
let action = task["action"] as? String else {
return
}
let task = TaskNotificationModel(
id: id,
title: title,
message: task["message"] as? String,
percentage: task["percentage"] as? Double,
isLoading: task["isLoading"] as? Bool ?? false
)
if action == "create" {
notifications.append(task)
} else {
notifications.insert(task, at: 0)
}
}
/// Updates an existing task with new information.
///
/// - Parameter task: A dictionary containing task information.
private func updateTask(task: [AnyHashable: Any]) {
guard let taskID = task["id"] as? String else { return }
if let index = self.notifications.firstIndex(where: { $0.id == taskID }) {
if let title = task["title"] as? String {
self.notifications[index].title = title
}
if let message = task["message"] as? String {
self.notifications[index].message = message
}
if let percentage = task["percentage"] as? Double {
self.notifications[index].percentage = percentage
}
if let isLoading = task["isLoading"] as? Bool {
self.notifications[index].isLoading = isLoading
}
}
}
private func deleteTask(taskID: String) {
self.notifications.removeAll { $0.id == taskID }
}
private func deleteTaskAfterDelay(taskID: String, delay: Double) {
DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
self.notifications.removeAll { $0.id == taskID }
}
}
}
extension Notification.Name {
static let taskNotification = Notification.Name("taskNotification")
}
================================================
FILE: CodeEdit/Features/ActivityViewer/Notifications/TaskNotificationView.swift
================================================
//
// TaskNotificationView.swift
// CodeEdit
//
// Created by Tommy Ludwig on 21.06.24.
//
import SwiftUI
struct TaskNotificationView: View {
@Environment(\.controlActiveState)
private var activeState
@ObservedObject var taskNotificationHandler: TaskNotificationHandler
@State private var isPresented: Bool = false
@State var notification: TaskNotificationModel?
var body: some View {
ZStack {
HStack {
if let notification {
HStack {
Text(notification.title)
.font(.subheadline)
.transition(
.asymmetric(insertion: .move(edge: .top), removal: .move(edge: .bottom))
.combined(with: .opacity)
)
.id("NotificationTitle" + notification.title)
}
.transition(.opacity.combined(with: .move(edge: .trailing)))
loaderView(notification: notification)
.transition(.opacity)
.id("Loader")
} else {
Text("")
.id("Loader")
}
}
.opacity(activeState == .inactive ? 0.4 : 1.0)
.padding(3)
.padding(-3)
.popover(isPresented: $isPresented, arrowEdge: .bottom) {
TaskNotificationsDetailView(taskNotificationHandler: taskNotificationHandler)
}
.onTapGesture {
self.isPresented.toggle()
}
}
.animation(.easeInOut, value: notification)
.onChange(of: taskNotificationHandler.notifications) { _, newValue in
withAnimation {
notification = newValue.first
}
}
}
@ViewBuilder
private func loaderView(notification: TaskNotificationModel) -> some View {
if notification.isLoading {
CECircularProgressView(
progress: notification.percentage,
currentTaskCount: taskNotificationHandler.notifications.count
)
.if(.tahoe) {
$0.padding(.leading, 1)
} else: {
$0.padding(.horizontal, -1)
}
.frame(height: 16)
} else {
if taskNotificationHandler.notifications.count > 1 {
Text("\(taskNotificationHandler.notifications.count)")
.font(.caption)
.padding(5)
.background(
Circle()
.foregroundStyle(.gray)
.opacity(0.2)
)
.padding(-5)
}
}
}
}
#Preview {
TaskNotificationView(taskNotificationHandler: TaskNotificationHandler())
}
================================================
FILE: CodeEdit/Features/ActivityViewer/Notifications/TaskNotificationsDetailView.swift
================================================
//
// TaskNotificationsDetailView.swift
// CodeEdit
//
// Created by Tommy Ludwig on 21.06.24.
//
import SwiftUI
struct TaskNotificationsDetailView: View {
@ObservedObject var taskNotificationHandler: TaskNotificationHandler
@State private var selectedTaskNotificationIndex: Int = 0
var body: some View {
ScrollView {
VStack(alignment: .leading, spacing: 15) {
ForEach(taskNotificationHandler.notifications, id: \.id) { notification in
HStack(alignment: .center, spacing: 8) {
CECircularProgressView(progress: notification.percentage)
.frame(width: 16, height: 16)
VStack(alignment: .leading) {
Text(notification.title)
.fixedSize(horizontal: false, vertical: true)
.transition(.identity)
if let message = notification.message, !message.isEmpty {
Text(message)
.font(.subheadline)
.foregroundStyle(.secondary)
}
}
Spacer()
}
}
}
}
.padding(15)
.frame(minWidth: 320)
.onChange(of: taskNotificationHandler.notifications) { _, newValue in
if selectedTaskNotificationIndex >= newValue.count {
selectedTaskNotificationIndex = 0
}
}
}
}
#Preview {
TaskNotificationsDetailView(taskNotificationHandler: TaskNotificationHandler())
}
================================================
FILE: CodeEdit/Features/ActivityViewer/Tasks/ActiveTaskView.swift
================================================
//
// ActiveTaskView.swift
// CodeEdit
//
// Created by Austin Condiff on 8/4/24.
//
import SwiftUI
// We need to observe each active task individually because:
// 1. Active tasks are nested inside TaskManager.
// 2. Reference types (like objects) do not notify observers when their internal state changes.
/// `ActiveTaskView` represents a single active task and observes its state.
/// - Parameter activeTask: The active task to be displayed and observed.
struct ActiveTaskView: View {
@ObservedObject var activeTask: CEActiveTask
var body: some View {
TaskView(task: activeTask.task, status: activeTask.status)
}
}
================================================
FILE: CodeEdit/Features/ActivityViewer/Tasks/DropdownMenuItemStyleModifier.swift
================================================
//
// DropdownMenuItemStyleModifier.swift
// CodeEdit
//
// Created by Tommy Ludwig on 24.06.24.
//
import SwiftUI
extension View {
@ViewBuilder
func dropdownItemStyle() -> some View {
self.modifier(DropdownMenuItemStyleModifier())
}
}
struct DropdownMenuItemStyleModifier: ViewModifier {
@State private var isHovering = false
func body(content: Content) -> some View {
content
.padding(.vertical, 4)
.padding(.horizontal, 8)
.background(
isHovering
? AnyView(EffectView(.selection, blendingMode: .withinWindow, emphasized: true))
: AnyView(Color.clear)
)
.foregroundColor(isHovering ? Color(NSColor.white) : .primary)
.if(.tahoe) {
if #available(macOS 26, *) {
$0.clipShape(ContainerRelativeShape())
}
} else: {
$0.clipShape(RoundedRectangle(cornerRadius: 5))
}
.onHover(perform: { hovering in
self.isHovering = hovering
})
}
}
================================================
FILE: CodeEdit/Features/ActivityViewer/Tasks/OptionMenuItemView.swift
================================================
//
// OptionMenuItemView.swift
// CodeEdit
//
// Created by Tommy Ludwig on 24.06.24.
//
import SwiftUI
struct OptionMenuItemView: View {
var label: String
var action: () -> Void
var body: some View {
HStack {
Text(label)
Spacer()
}
.padding(.horizontal, 20)
.dropdownItemStyle()
.onTapGesture {
action()
}
.accessibilityElement()
.accessibilityAction {
action()
}
.accessibilityLabel(label)
}
}
#Preview {
OptionMenuItemView(label: "Test") {
print("test")
}
}
================================================
FILE: CodeEdit/Features/ActivityViewer/Tasks/SchemeDropDownView.swift
================================================
//
// SchemeDropDownView.swift
// CodeEdit
//
// Created by Tommy Ludwig on 24.06.24.
//
import SwiftUI
struct SchemeDropDownView: View {
@Environment(\.colorScheme)
private var colorScheme
@Environment(\.controlActiveState)
private var activeState
@State var isSchemePopOverPresented: Bool = false
@State private var isHoveringScheme: Bool = false
@ObservedObject var workspaceSettingsManager: CEWorkspaceSettings
var workspaceFileManager: CEWorkspaceFileManager?
var workspaceName: String {
workspaceSettingsManager.settings.project.projectName
}
/// Resolves the name one step further than `workspaceName`.
var workspaceDisplayName: String {
workspaceName.isEmpty
? (workspaceFileManager?.workspaceItem.fileName() ?? "No Project found")
: workspaceName
}
var body: some View {
Group {
if #available(macOS 26, *) {
tahoe
} else {
seqouia
}
}
.onHover(perform: { hovering in
self.isHoveringScheme = hovering
})
.instantPopover(isPresented: $isSchemePopOverPresented, arrowEdge: .top) {
popoverContent
}
.onTapGesture {
isSchemePopOverPresented.toggle()
}
.accessibilityElement(children: .combine)
.accessibilityAddTraits(.isButton)
.accessibilityIdentifier("SchemeDropdown")
.accessibilityValue(workspaceDisplayName)
.accessibilityLabel("Active Scheme")
.accessibilityHint("Open the active scheme menu")
.accessibilityAction {
isSchemePopOverPresented.toggle()
}
}
@available(macOS 26, *)
@ViewBuilder private var tahoe: some View {
HStack(spacing: 4) {
label
chevron
.offset(x: 2)
.opacity(isHoveringScheme || isSchemePopOverPresented ? 0.0 : 1.0)
}
.background {
if isHoveringScheme || isSchemePopOverPresented {
HStack {
Spacer()
chevronDown
}
}
}
.padding(6)
.padding(.leading, 2) // apparently this is cummulative?
.background {
Color(nsColor: colorScheme == .dark ? .white : .black)
.opacity(isHoveringScheme || isSchemePopOverPresented ? 0.05 : 0)
.clipShape(Capsule())
}
}
@ViewBuilder private var seqouia: some View {
label
.padding(.trailing, 11.5)
.padding(.horizontal, 2.5)
.padding(.vertical, 2.5)
.background {
Color(nsColor: colorScheme == .dark ? .white : .black)
.opacity(isHoveringScheme || isSchemePopOverPresented ? 0.05 : 0)
.clipShape(RoundedRectangle(cornerSize: CGSize(width: 4, height: 4)))
HStack {
Spacer()
if isHoveringScheme || isSchemePopOverPresented {
chevronDown
.padding(.trailing, 2)
} else {
chevron
.padding(.trailing, 4)
}
}
}
}
@ViewBuilder private var label: some View {
HStack(spacing: 6) {
Image(systemName: "folder.badge.gearshape")
.imageScale(.medium)
Text(workspaceDisplayName)
.frame(minWidth: 0)
}
.opacity(activeState == .inactive ? 0.4 : 1.0)
.font(.subheadline)
}
@ViewBuilder private var chevron: some View {
Image(systemName: "chevron.compact.right")
.font(.system(size: 9, weight: .medium, design: .default))
.foregroundStyle(.secondary)
.scaleEffect(x: 1.30, y: 1.0, anchor: .center)
.imageScale(.large)
}
@ViewBuilder private var chevronDown: some View {
VStack(spacing: 1) {
Image(systemName: "chevron.down")
}
.font(.system(size: 8, weight: .semibold, design: .default))
.padding(.top, 0.5)
}
@ViewBuilder var popoverContent: some View {
WorkspaceMenuItemView(
workspaceFileManager: workspaceFileManager,
item: workspaceFileManager?.workspaceItem
)
Divider()
.padding(.vertical, 5)
Group {
OptionMenuItemView(label: "Add Folder...") {
// TODO: Implment Add Folder
print("NOT IMPLEMENTED")
}
.disabled(true)
OptionMenuItemView(label: "Workspace Settings...") {
NSApp.sendAction(
#selector(CodeEditWindowController.openWorkspaceSettings(_:)), to: nil, from: nil
)
}
}
}
}
// #Preview {
// SchemeDropDownMenuView()
// }
================================================
FILE: CodeEdit/Features/ActivityViewer/Tasks/TaskDropDownView.swift
================================================
//
// TaskDropDownView.swift
// CodeEdit
//
// Created by Tommy Ludwig on 24.06.24.
//
import SwiftUI
struct TaskDropDownView: View {
@Environment(\.colorScheme)
private var colorScheme
@Environment(\.controlActiveState)
private var activeState
@ObservedObject var taskManager: TaskManager
@State private var isTaskPopOverPresented: Bool = false
@State private var isHoveringTasks: Bool = false
var body: some View {
Group {
if #available(macOS 26, *) {
tahoe
} else {
seqouia
}
}
.onHover { hovering in
self.isHoveringTasks = hovering
}
.instantPopover(isPresented: $isTaskPopOverPresented, arrowEdge: .top) {
taskPopoverContent
}
.onTapGesture {
self.isTaskPopOverPresented.toggle()
}
.accessibilityElement(children: .combine)
.accessibilityAddTraits(.isButton)
.accessibilityIdentifier("TaskDropdown")
.accessibilityValue(taskManager.selectedTask?.name ?? "Create Tasks")
.accessibilityLabel("Active Task")
.accessibilityHint("Open the active task menu")
.accessibilityAction {
isTaskPopOverPresented = true
}
}
@available(macOS 26, *)
@ViewBuilder private var tahoe: some View {
HStack(spacing: 4) {
label
chevronIcon
.opacity(isHoveringTasks || isTaskPopOverPresented ? 1.0 : 0.0)
}
.padding(6)
.background {
Color(nsColor: colorScheme == .dark ? .white : .black)
.opacity(isHoveringTasks || isTaskPopOverPresented ? 0.05 : 0)
.clipShape(Capsule())
}
}
@ViewBuilder private var seqouia: some View {
label
.opacity(activeState == .inactive ? 0.4 : 1.0)
.padding(.trailing, 11.5)
.padding(.horizontal, 2.5)
.padding(.vertical, 2.5)
.background(backgroundColor)
}
@ViewBuilder private var label: some View {
Group {
if let selectedTask = taskManager.selectedTask {
if let selectedActiveTask = taskManager.activeTasks[selectedTask.id] {
ActiveTaskView(activeTask: selectedActiveTask)
.fixedSize()
} else {
TaskView(task: selectedTask, status: CETaskStatus.notRunning)
.fixedSize()
}
} else {
Text("Create Tasks")
.frame(minWidth: 0)
}
}
.font(.subheadline)
}
@ViewBuilder private var backgroundColor: some View {
Color(nsColor: colorScheme == .dark ? .white : .black)
.opacity(isHoveringTasks || isTaskPopOverPresented ? 0.05 : 0)
.clipShape(RoundedRectangle(cornerSize: CGSize(width: 4, height: 4)))
.overlay(
HStack {
Spacer()
if isHoveringTasks || isTaskPopOverPresented {
chevronIcon
}
}
)
}
@ViewBuilder private var chevronIcon: some View {
Image(systemName: "chevron.down")
.font(.system(size: 8, weight: .bold, design: .default))
.padding(.top, 0.5)
.padding(.trailing, 2)
}
@ViewBuilder private var taskPopoverContent: some View {
if !taskManager.availableTasks.isEmpty {
ForEach(taskManager.availableTasks, id: \.id) { task in
TasksPopoverMenuItem(taskManager: taskManager, task: task) {
isTaskPopOverPresented = false
}
}
Divider()
.padding(.vertical, 5)
}
OptionMenuItemView(label: "Add Task...") {
NSApp.sendAction(#selector(CodeEditWindowController.openWorkspaceSettings(_:)), to: nil, from: nil)
}
OptionMenuItemView(label: "Manage Tasks...") {
NSApp.sendAction(#selector(CodeEditWindowController.openWorkspaceSettings(_:)), to: nil, from: nil)
}
}
}
================================================
FILE: CodeEdit/Features/ActivityViewer/Tasks/TaskView.swift
================================================
//
// TaskView.swift
// CodeEdit
//
// Created by Austin Condiff on 8/4/24.
//
import SwiftUI
/// `TaskView` represents a single active task and observes its state.
/// - Parameter task: The task to be displayed and observed.
/// - Parameter status: The status of the task to be displayed.
struct TaskView: View {
@ObservedObject var task: CETask
var status: CETaskStatus
var body: some View {
HStack(spacing: 5) {
Image(systemName: "gearshape")
Text(task.name)
.frame(minWidth: 0)
Spacer(minLength: 0)
}
.padding(.trailing, 7.5)
.overlay(alignment: .trailing) {
Circle()
.fill(status.color)
.frame(width: 5, height: 5)
.padding(.trailing, 2.5)
}
.accessibilityElement()
.accessibilityLabel(task.name)
}
}
================================================
FILE: CodeEdit/Features/ActivityViewer/Tasks/TasksPopoverMenuItem.swift
================================================
//
// TasksPopoverMenuItem.swift
// CodeEdit
//
// Created by Austin Condiff on 8/4/24.
//
import SwiftUI
/// - Note: This view **cannot** use the `dismiss` environment value to dismiss the sheet. It has to negate the boolean
/// value that presented it initially.
/// See ``SwiftUI/View/instantPopover(isPresented:arrowEdge:content:)``
struct TasksPopoverMenuItem: View {
@ObservedObject var taskManager: TaskManager
var task: CETask
var dismiss: () -> Void
var body: some View {
HStack(spacing: 5) {
selectionIndicator
popoverContent
}
.dropdownItemStyle()
.onTapGesture(perform: selectAction)
.accessibilityElement()
.accessibilityLabel(task.name)
.accessibilityAction(.default, selectAction)
.accessibilityAddTraits(taskManager.selectedTaskID == task.id ? [.isSelected] : [])
}
private var selectionIndicator: some View {
Group {
if taskManager.selectedTaskID == task.id {
Image(systemName: "checkmark")
.fontWeight(.bold)
.imageScale(.small)
.frame(width: 10)
} else {
Spacer()
.frame(width: 10)
}
}
}
private var popoverContent: some View {
Group {
if let activeTask = taskManager.activeTasks[task.id] {
ActiveTaskView(activeTask: activeTask)
} else {
TaskView(task: task, status: taskManager.taskStatus(taskID: task.id))
}
}
}
private func selectAction() {
taskManager.selectedTaskID = task.id
dismiss()
}
}
================================================
FILE: CodeEdit/Features/ActivityViewer/Tasks/WorkspaceMenuItemView.swift
================================================
//
// WorkspaceMenuItemView.swift
// CodeEdit
//
// Created by Tommy Ludwig on 24.06.24.
//
import SwiftUI
struct WorkspaceMenuItemView: View {
var workspaceFileManager: CEWorkspaceFileManager?
var item: CEWorkspaceFile?
var body: some View {
HStack(spacing: 5) {
if workspaceFileManager?.workspaceItem.fileName() == item?.name {
Image(systemName: "checkmark")
.fontWeight(.bold)
.imageScale(.small)
.frame(width: 10)
} else {
Spacer()
.frame(width: 10)
}
Image(systemName: "folder.badge.gearshape")
.imageScale(.medium)
Text(item?.name ?? "")
Spacer()
}
.dropdownItemStyle()
.onTapGesture { } // add accessibility action when this is filled in
.clipShape(RoundedRectangle(cornerRadius: 5))
.accessibilityElement()
.accessibilityLabel(item?.name ?? "")
}
}
#Preview {
WorkspaceMenuItemView()
}
================================================
FILE: CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFile+Recursion.swift
================================================
//
// CEWorkspaceFile+Recursion.swift
// CodeEdit
//
// Created by Matthijs Eikelenboom on 30/04/2023.
//
import Foundation
extension CEWorkspaceFile {
/// Flattens the children of `self` recursively with depth.
/// - Parameters:
/// - depth: An int that indicates the how deep the tree files need to be flattened
/// - ignoringFolders: A boolean on whether to ignore files that are Folders
/// - fileManager: The workspace's file manager to use.
/// - Returns: An array of flattened `CEWorkspaceFiles`
func flattenedChildren(
withDepth depth: Int,
ignoringFolders: Bool,
using fileManager: CEWorkspaceFileManager
) -> [CEWorkspaceFile] {
guard depth > 0 else { return [] }
guard self.isFolder else { return [self] }
var childItems: [CEWorkspaceFile] = ignoringFolders ? [] : [self]
fileManager.childrenOfFile(self)?.forEach { child in
childItems.append(contentsOf: child.flattenedChildren(
withDepth: depth - 1,
ignoringFolders: ignoringFolders,
using: fileManager
))
}
return childItems
}
/// Returns a list of `CEWorkspaceFiles` that are sibilings of `self`.
/// The `height` parameter lets the function navigate up the folder hierarchy to
/// select a starting point from which it should start flettening the items.
/// - Parameters:
/// - height: `Int` that tells where to start in the hierarchy
/// - ignoringFolders: Wether the sibling folders should be flattened
/// - fileManager: The workspace's file manager to use.
/// - Returns: A list of `FileSystemItems`
func flattenedSiblings(
withHeight height: Int,
ignoringFolders: Bool,
using fileManager: CEWorkspaceFileManager
) -> [CEWorkspaceFile] {
let topMostParent = self.getParent(withHeight: height)
return topMostParent.flattenedChildren(withDepth: height, ignoringFolders: ignoringFolders, using: fileManager)
}
/// Using the current instance of `FileSystemItem` it will walk back up the Workspace file hiarchy
/// the amount of times specified with the `withHeight` parameter.
/// - Parameter height: The amount of times you want to up a folder.
/// - Returns: The found `FileSystemItem` object, This should always be a folder.
private func getParent(withHeight height: Int) -> CEWorkspaceFile {
var topmostParent = self
for _ in 0..<height {
guard let parent = topmostParent.parent else { break }
topmostParent = parent
}
return topmostParent
}
#if DEBUG
/// Print a debug description of the file.
/// - Parameters:
/// - tabCount: The number of tabs to tab the description over (for recursive calls)
/// - fileManager: The file manager to use to find children.
/// - Returns: A string describing the file and it's children.
/// - Authors: Mattijs Eikelenboom, KaiTheRedNinja. *Moved from 7c27b1e*
func childrenDescription(tabCount: Int = 0, using fileManager: CEWorkspaceFileManager) -> String {
var myDetails = "\(String(repeating: "| ", count: max(tabCount - 1, 0)))\(tabCount != 0 ? "╰--" : "")"
myDetails += "\(url.path(percentEncoded: false))"
if !self.isFolder { // if im a file, just return the url
return myDetails
} else { // if im a folder, return the url and its children's details
var childDetails = "\(myDetails)"
if fileManager.hasLoadedChildrenFor(file: self) {
for child in fileManager.childrenOfFile(self) ?? [] {
childDetails += "\n\(child.childrenDescription(tabCount: tabCount + 1, using: fileManager))"
}
} else {
// Disabling for debug line.
// swiftlint:disable:next line_length
childDetails += "\n\(String(repeating: "| ", count: max(tabCount - 1, 0)))\(tabCount != 0 ? "╰--" : "") Children Not Loaded"
}
return childDetails
}
}
#endif
}
================================================
FILE: CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFile.swift
================================================
//
// FileItem.swift
// CodeEdit
//
// Created by Matthijs Eikelenboom on 07/02/2023.
//
import Foundation
import SwiftUI
import UniformTypeIdentifiers
import Combine
/// An object containing all necessary information and actions for a specific file in the workspace
///
/// The ``CEWorkspaceFile`` represents every type of file that can exist on the file system. Directories, files,
/// symlinks, etc. This class does not assume anything about what it is representing, but it can be interrogated to find
/// out what it represents. All information about the file is derived from the `URL` passed to the initializer of the
/// object.
///
/// This object works to provide a consistent API for any component that needs to work with files, and is as small as
/// possible.
///
/// These objects should be fetched from the ``CEWorkspaceFileManager`` whenever possible. Objects fetched from there
/// will be connected in CodeEdit's file tree, and structural properties like ``CEWorkspaceFile/parent`` will exist.
/// They can, however, be created standalone when necessary. Creating a standalone ``CEWorkspaceFile`` is useful if
/// loading all intermediate subdirectories (from the nearest cached parent to the file) has not been done yet and doing
/// so would be unnecessary.
///
/// An example of this is in the ``OpenQuicklyView``. This view finds a file URL via a search bar, and needs to display
/// a quick preview of the file. There's a good chance the file is deep in some subdirectory of the workspace, so
/// fetching it from the ``CEWorkspaceFileManager`` may require loading and caching multiple directories. Instead, it
/// just makes a disconnected object and uses it for the preview. Then, when opening the file in the workspace it
/// forces the file to be loaded and cached.
final class CEWorkspaceFile: Codable, Comparable, Hashable, Identifiable, EditorTabRepresentable {
/// The id of the ``CEWorkspaceFile``.
var id: String
/// Returns the file name (e.g.: `Package.swift`)
var name: String { url.lastPathComponent.trimmingCharacters(in: .whitespacesAndNewlines) }
/// Returns the extension of the file or an empty string if no extension is present.
var type: FileIcon.FileType {
let filename = url.fileName
/// First, check if there is a valid file extension.
if let type = FileIcon.FileType(rawValue: filename) {
return type
} else {
/// If there's not, verifies every extension for a valid type.
let extensions = filename.dropFirst().components(separatedBy: ".").reversed()
return extensions
.compactMap { FileIcon.FileType(rawValue: $0) }
.first
/// Returns .txt for invalid type.
?? .txt
}
}
/// Returns the URL of the ``CEWorkspaceFile``
let url: URL
/// Returns the resolved symlink url of this object.
lazy var resolvedURL: URL = {
url.isSymbolicLink ? url.resolvingSymlinksInPath() : url
}()
/// Return the icon of the file as `Image`
var icon: Image {
if let customImage = NSImage.symbol(named: systemImage) {
return Image(nsImage: customImage)
} else {
return Image(systemName: systemImage)
}
}
/// Return the icon of the file as `NSImage`
var nsIcon: NSImage {
if let customImage = NSImage.symbol(named: systemImage) {
return customImage
} else {
return NSImage(systemSymbolName: systemImage, accessibilityDescription: systemImage)
?? NSImage(systemSymbolName: "doc", accessibilityDescription: "doc")!
}
}
/// Returns a parent ``CEWorkspaceFile``.
///
/// If the item already is the top-level ``CEWorkspaceFile`` this returns `nil`.
weak var parent: CEWorkspaceFile?
private let fileDocumentSubject = PassthroughSubject<CodeFileDocument?, Never>()
weak var fileDocument: CodeFileDocument? {
didSet {
fileDocumentSubject.send(fileDocument)
}
}
/// Publisher for fileDocument property
var fileDocumentPublisher: AnyPublisher<CodeFileDocument?, Never> {
fileDocumentSubject.eraseToAnyPublisher()
}
var fileIdentifier = UUID().uuidString
/// Returns the Git status of a file as ``GitStatus``
var gitStatus: GitStatus?
/// Returns a boolean that is true if the file is staged for commit
var staged: Bool?
/// Returns the `id` in ``EditorTabID`` enum form
var tabID: EditorTabID { .codeEditor(id) }
/// Returns a boolean that is true if the resource represented by this object is a directory.
lazy var isFolder: Bool = {
resolvedURL.isFolder
}()
/// Returns a boolean that is true if the contents of the directory at this path are
///
/// Does not indicate if this is a folder, see ``isFolder`` to first check if this object is also a directory.
var isEmptyFolder: Bool {
(try? CEWorkspaceFile.fileManager.contentsOfDirectory(
at: resolvedURL,
includingPropertiesForKeys: nil,
options: .skipsSubdirectoryDescendants
).isEmpty) ?? true
}
/// Returns a boolean that is true if the file item is the root folder of the workspace.
var isRoot: Bool { parent == nil }
/// Returns a boolean that is true if the file item actually exists in the file system
var doesExist: Bool { CEWorkspaceFile.fileManager.fileExists(atPath: self.url.path) }
/// Returns a string describing a SFSymbol for the current ``CEWorkspaceFile``
///
/// Use it like this
/// ```swift
/// Image(systemName: item.systemImage)
/// ```
var systemImage: String {
if isFolder {
// item is a folder
return folderIcon()
} else {
// item is a file
return FileIcon.fileIcon(fileType: type)
}
}
/// Return the file's UTType
var contentType: UTType? {
url.contentType
}
/// Returns a `Color` for a specific `fileType`
///
/// If not specified otherwise this will return `Color.accentColor`
var iconColor: Color {
FileIcon.iconColor(fileType: type)
}
init(
id: String,
url: URL,
changeType: GitStatus? = nil,
staged: Bool? = false
) {
self.id = id
self.url = url
self.gitStatus = changeType
self.staged = staged
}
convenience init(
url: URL,
changeType: GitStatus? = nil,
staged: Bool? = false
) {
self.init(
id: url.relativePath,
url: url,
changeType: changeType,
staged: staged
)
}
enum CodingKeys: String, CodingKey {
case id
case name
case url
case changeType
case staged
}
required init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
id = try values.decode(String.self, forKey: .id)
url = try values.decode(URL.self, forKey: .url)
gitStatus = try values.decode(GitStatus.self, forKey: .changeType)
staged = try values.decode(Bool.self, forKey: .staged)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try container.encode(name, forKey: .name)
try container.encode(url, forKey: .url)
try container.encode(gitStatus, forKey: .changeType)
try container.encode(staged, forKey: .staged)
}
/// Returns a string describing a SFSymbol for folders
///
/// If it is the top-level folder this will return `"square.dashed.inset.filled"`.
/// If it is a `.codeedit` folder this will return `"folder.fill.badge.gearshape"`.
/// If it has children this will return `"folder.fill"` otherwise `"folder"`.
private func folderIcon() -> String {
if self.parent == nil {
return "folder.fill.badge.gearshape"
}
if self.name == ".codeedit" {
return "folder.fill.badge.gearshape"
}
return isEmptyFolder ? "folder" : "folder.fill"
}
/// Returns the file name with optional extension (e.g.: `Package.swift`)
func fileName(typeHidden: Bool = false) -> String {
typeHidden ? url.deletingPathExtension()
.lastPathComponent
.trimmingCharacters(in: .whitespacesAndNewlines) : 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 {
// Name must be: new, nonempty, valid characters, and not exist in the filesystem.
guard newName != labelFileName() &&
!newName.isEmpty &&
newName.isValidFilename &&
!FileManager.default.fileExists(
atPath: self.url.deletingLastPathComponent().appending(path: newName).path
) else {
return false
}
return true
}
/// Loads the ``fileDocument`` property with a new ``CodeFileDocument`` and registers it with the shared
/// ``CodeEditDocumentController``.
func loadCodeFile() throws {
let codeFile = try CodeFileDocument(contentsOf: resolvedURL, ofType: contentType?.identifier ?? "")
CodeEditDocumentController.shared.addDocument(codeFile)
self.fileDocument = codeFile
}
// MARK: Statics
/// The default `FileManager` instance
static let fileManager = FileManager.default
// MARK: Intents
/// Allows the user to view the file or folder in the finder application
func showInFinder() {
NSWorkspace.shared.activateFileViewerSelecting([url])
}
/// Allows the user to launch the file or folder as it would be in finder
func openWithExternalEditor() {
NSWorkspace.shared.open(url)
}
/// Nearest folder refers to the parent directory if this is a non-folder item, or itself if the item is a folder.
var nearestFolder: URL {
(self.isFolder ?
self.url :
self.url.deletingLastPathComponent())
}
// MARK: Comparable
static func == (lhs: CEWorkspaceFile, rhs: CEWorkspaceFile) -> Bool {
lhs.id == rhs.id
}
static func < (lhs: CEWorkspaceFile, rhs: CEWorkspaceFile) -> Bool {
lhs.url.lastPathComponent < rhs.url.lastPathComponent
}
// MARK: Hashable
func hash(into hasher: inout Hasher) {
hasher.combine(url)
hasher.combine(id)
}
}
================================================
FILE: CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFileIcon.swift
================================================
//
// FileIcon.swift
//
//
// Created by Nanashi Li on 2022/05/20.
//
import SwiftUI
// TODO: DOCS (Nanashi Li)
enum FileIcon {
// swiftlint:disable identifier_name
enum FileType: String {
case adb
case aif
case avi
case bash
case c
case cetheme
case clj
case cls
case cs
case css
case d
case dart
case elm
case entitlements
case env
case ex
case example
case f95
case fs
case gitignore
case go
case gs
case h
case hs
case html
case ico
case java
case jl
case jpeg
case jpg
case js
case json
case jsx
case kt
case l
case LICENSE
case lock
case lsp
case lua
case m
case Makefile
case md
case mid
case mjs
case mk
case mod
case mov
case mp3
case mp4
case pas
case pdf
case pl
case plist
case png
case py
case resolved
case rb
case rs
case rtf
case scm
case scpt
case sh
case ss
case strings
case sum
case svg
case swift
case ts
case tsx
case txt = "text"
case vue
case wav
case xcconfig
case yml
case zsh
}
// swiftlint:enable identifier_name
/// Returns a string describing a SFSymbol for files
/// If not specified otherwise this will return `"doc"`
static func fileIcon(fileType: FileType?) -> String { // swiftlint:disable:this cyclomatic_complexity function_body_length line_length
switch fileType {
case .json, .yml, .resolved:
return "doc.json"
case .lock:
return "lock.doc"
case .css:
return "curlybraces"
case .js, .mjs:
return "doc.javascript"
case .jsx, .tsx:
return "atom"
case .swift:
return "swift"
case .env, .example:
return "gearshape.fill"
case .gitignore:
return "arrow.triangle.branch"
case .pdf, .png, .jpg, .jpeg, .ico:
return "photo"
case .svg:
return "square.fill.on.circle.fill"
case .entitlements:
return "checkmark.seal"
case .plist:
return "tablecells"
case .md, .txt:
return "doc.plaintext"
case .rtf:
return "doc.richtext"
case .html:
return "chevron.left.forwardslash.chevron.right"
case .LICENSE:
return "key.fill"
case .java:
return "cup.and.saucer"
case .py:
return "doc.python"
case .rb:
return "doc.ruby"
case .strings:
return "text.quote"
case .h:
return "h.square"
case .m:
return "m.square"
case .vue:
return "v.square"
case .go:
return "g.square"
case .sum:
return "s.square"
case .mod:
return "m.square"
case .bash, .sh, .Makefile, .zsh:
return "terminal"
case .rs:
return "r.square"
case .wav, .mp3, .aif, .mid:
return "speaker.wave.2"
case .avi, .mp4, .mov:
return "film"
case .scpt:
return "applescript"
case .xcconfig:
return "gearshape.2"
case .cetheme:
return "paintbrush"
case .adb, .clj, .cls, .cs, .d, .dart, .elm, .ex, .f95, .fs, .gs, .hs,
.jl, .kt, .l, .lsp, .lua, .mk, .pas, .pl, .scm, .ss:
return "doc.plaintext"
default:
return "doc"
}
}
/// Returns a `Color` for a specific `fileType`
/// If not specified otherwise this will return `Color.accentColor`
static func iconColor(fileType: FileType?) -> Color { // swiftlint:disable:this cyclomatic_complexity
switch fileType {
case .swift, .html:
return .orange
case .java, .jpg, .png, .svg, .ts:
return .blue
case .css:
return .teal
case .js, .mjs, .py, .entitlements, .LICENSE:
return Color.amber
case .json, .resolved, .rb, .strings, .yml:
return Color.scarlet
case .jsx, .tsx:
return .cyan
case .plist, .xcconfig, .sh:
return Color.steel
case .c, .cetheme:
return .purple
case .vue:
return Color(red: 0.255, green: 0.722, blue: 0.514, opacity: 1.0)
case .h:
return Color(red: 0.667, green: 0.031, blue: 0.133, opacity: 1.0)
case .m:
return Color(red: 0.271, green: 0.106, blue: 0.525, opacity: 1.0)
case .go:
return Color(red: 0.02, green: 0.675, blue: 0.757, opacity: 1.0)
case .sum, .mod:
return Color(red: 0.925, green: 0.251, blue: 0.478, opacity: 1.0)
case .Makefile:
return Color(red: 0.937, green: 0.325, blue: 0.314, opacity: 1.0)
case .rs:
return .orange
default:
return Color.steel
}
}
}
================================================
FILE: CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFileManager+DirectoryEvents.swift
================================================
//
// CEWorkspaceFileManager+DirectoryEvents.swift
// CodeEdit
//
// Created by Axel Martinez on 5/8/24.
//
import Foundation
/// This extension handles the file system events triggered by changes in the root folder.
extension CEWorkspaceFileManager {
/// Called by `fsEventStream` when an event occurs.
///
/// This method may be called on a background thread, but all work done by this function will be queued on the main
/// thread.
/// - Parameter events: An array of events that occurred.
func fileSystemEventReceived(events: [DirectoryEventStream.Event]) {
DispatchQueue.main.async {
var files: Set<CEWorkspaceFile> = []
for event in events {
// Event returns file/folder that was changed, but in tree we need to update it's parent
guard let parentUrl = URL(string: event.path, relativeTo: self.folderUrl)?.deletingLastPathComponent(),
let parentFileItem = self.flattenedFileItems[parentUrl.path] else {
continue
}
switch event.eventType {
case .changeInDirectory, .itemChangedOwner, .itemModified:
// Can be ignored for now, these I think not related to tree changes
continue
case .rootChanged:
// TODO: #1880 - Handle workspace root changing.
continue
case .itemCreated, .itemCloned, .itemRemoved, .itemRenamed:
do {
try self.rebuildFiles(fromItem: parentFileItem)
} catch {
// swiftlint:disable:next line_length
self.logger.error("Failed to rebuild files for event: \(event.eventType.rawValue), path: \(event.path, privacy: .sensitive)")
}
files.insert(parentFileItem)
}
}
if !files.isEmpty {
self.notifyObservers(updatedItems: files)
}
if Settings.shared.preferences.sourceControl.general.sourceControlIsEnabled &&
Settings.shared.preferences.sourceControl.general.refreshStatusLocally {
self.handleGitEvents(events: events)
}
}
}
func handleGitEvents(events: [DirectoryEventStream.Event]) {
// Changes excluding .git folder
let notGitChanges = events.filter({ !$0.path.contains(".git/") })
// .git folder was changed
let gitFolderChange = events.first(where: {
$0.path == "\(self.folderUrl.relativePath)/.git"
})
// Change made to git index file, staged/unstaged files
let gitIndexChange = events.first(where: {
$0.path == "\(self.folderUrl.relativePath)/.git/index"
})
// Change made to git stash
let gitStashChange = events.first(where: {
$0.path == "\(self.folderUrl.relativePath)/.git/refs/stash"
})
// Changes made to git branches
let gitBranchChange = events.first(where: {
$0.path.contains("\(self.folderUrl.relativePath)/.git/refs/heads")
})
// Changes made to git HEAD - current branch changed
let gitHeadChange = events.first(where: {
$0.path.contains("\(self.folderUrl.relativePath)/.git/HEAD")
})
// Change made to remotes by looking at .git/config
let gitConfigChange = events.first(where: {
$0.path == "\(self.folderUrl.relativePath)/.git/config"
})
// If changes were made to project OR files were staged, refresh changes
if !notGitChanges.isEmpty || gitIndexChange != nil {
Task {
await self.sourceControlManager?.refreshAllChangedFiles()
}
}
// If changes were stashed, refresh stashed entries
if gitStashChange != nil {
Task {
try await self.sourceControlManager?.refreshStashEntries()
}
}
// If branches were added or removed, refresh branches
if gitBranchChange != nil {
Task {
await self.sourceControlManager?.refreshBranches()
}
}
// If HEAD was changed, refresh the current branch
if gitHeadChange != nil {
Task {
await self.sourceControlManager?.refreshCurrentBranch()
}
}
// If git config changed, refresh remotes
if gitConfigChange != nil {
Task {
try await self.sourceControlManager?.refreshRemotes()
}
}
// If .git folder was added or removed, check if repository is valid
if gitFolderChange != nil {
Task {
try await self.sourceControlManager?.validate()
}
}
}
/// Creates or deletes children of the ``CEWorkspaceFile`` so that they are accurate with the file system,
/// instead of creating an entirely new ``CEWorkspaceFile``. Can optionally run a deep rebuild.
///
/// This method will return immediately if the given file item is not a directory.
/// This will also only rebuild *already cached* directories.
/// - Parameters:
/// - fileItem: The ``CEWorkspaceFile`` to correct the children of
/// - deep: Set to `true` if this should perform the rebuild recursively.
func rebuildFiles(fromItem fileItem: CEWorkspaceFile, deep: Bool = false) throws {
// Do not index directories that are not already loaded.
guard childrenMap[fileItem.id] != nil else { return }
// get the actual directory children
let directoryContentsUrls = try fileManager.contentsOfDirectory(
at: fileItem.resolvedURL,
includingPropertiesForKeys: nil
)
// test for deleted children, and remove them from the index
// Folders may or may not have slash at the end, this will normalize check
let directoryContentsUrlsRelativePaths = directoryContentsUrls.map({ $0.relativePath })
for (idx, oldURL) in (childrenMap[fileItem.id] ?? []).map({ URL(filePath: $0) }).enumerated().reversed()
where !directoryContentsUrlsRelativePaths.contains(oldURL.relativePath) {
flattenedFileItems.removeValue(forKey: oldURL.relativePath)
childrenMap[fileItem.id]?.remove(at: idx)
}
// test for new children, and index them
for newContent in directoryContentsUrls {
// if the child has already been indexed, continue to the next item.
guard !ignoredFilesAndFolders.contains(newContent.lastPathComponent) &&
!(childrenMap[fileItem.id]?.contains(newContent.relativePath) ?? true) else { continue }
if fileManager.fileExists(atPath: newContent.path) {
let newFileItem = createChild(newContent, forParent: fileItem)
flattenedFileItems[newFileItem.id] = newFileItem
childrenMap[fileItem.id]?.append(newFileItem.id)
}
}
childrenMap[fileItem.id] = childrenMap[fileItem.id]?
.map { URL(filePath: $0) }
.sortItems(foldersOnTop: true)
.map { $0.relativePath }
if deep && childrenMap[fileItem.id] != nil {
for child in (childrenMap[fileItem.id] ?? []).compactMap({ flattenedFileItems[$0] }) {
try rebuildFiles(fromItem: child)
}
}
}
/// Notify observers that an update occurred in the watched files.
func notifyObservers(updatedItems: Set<CEWorkspaceFile>) {
observers.allObjects.reversed().forEach { delegate in
guard let delegate = delegate as? CEWorkspaceFileManagerObserver else {
observers.remove(delegate)
return
}
delegate.fileManagerUpdated(updatedItems: updatedItems)
}
}
/// Add an observer for file system events.
/// - Parameter observer: The observer to add.
func addObserver(_ observer: CEWorkspaceFileManagerObserver) {
observers.add(observer as AnyObject)
}
/// Remove an observer for file system events.
/// - Parameter observer: The observer to remove.
func removeObserver(_ observer: CEWorkspaceFileManagerObserver) {
observers.remove(observer as AnyObject)
}
}
================================================
FILE: CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFileManager+Error.swift
================================================
//
// CEWorkspaceFileManager+Error.swift
// CodeEdit
//
// Created by Khan Winter on 1/13/25.
//
import Foundation
extension CEWorkspaceFileManager {
/// Localized errors related to actions in the file manager.
/// These errors are suitable for presentation using `NSAlert(error:)`.
enum FileManagerError: LocalizedError {
case fileNotFound
case fileNotIndexed
case originFileNotFound
case destinationFileExists
case invalidFileName
var errorDescription: String? {
switch self {
case .fileNotFound:
return "File not found"
case .fileNotIndexed:
return "File not found in CodeEdit"
case .originFileNotFound:
return "Failed to find origin file"
case .destinationFileExists:
return "Destination already exists"
case .invalidFileName:
return "Invalid file name"
}
}
var recoverySuggestion: String? {
switch self {
case .fileNotIndexed:
return "Reopen the workspace to reindex the file system."
case .fileNotFound, .originFileNotFound:
return "The file may have moved during the operation, try again."
case .destinationFileExists:
return "Use a different file name or remove the conflicting file."
case .invalidFileName:
return "File names must not contain the : character and be less than 256 characters."
}
}
}
}
================================================
FILE: CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFileManager+FileManagement.swift
================================================
//
// CEWorkspaceFileManager+FileSystem.swift
// CodeEdit
//
// Created by Khan Winter on 9/30/23.
//
import Foundation
import AppKit
extension CEWorkspaceFileManager {
/// This function allows creation of folders in the main directory or sub-folders
/// - Parameters:
/// - folderName: The name of the new folder
/// - file: The file to add the new folder to.
/// - Returns: The ``CEWorkspaceFile`` representing the folder in the file manager's cache.
/// - Authors: Mattijs Eikelenboom, KaiTheRedNinja. *Moved from 7c27b1e*
func addFolder(folderName: String, toFile file: CEWorkspaceFile) throws -> CEWorkspaceFile {
// Check if folder, if it is create folder under self, else create on same level.
var folderUrl = (
file.isFolder ? file.url.appending(path: folderName)
: file.url.deletingLastPathComponent().appending(path: folderName)
)
// If a file/folder with the same name exists, add a number to the end.
var fileNumber = 0
while fileManager.fileExists(atPath: folderUrl.path) {
fileNumber += 1
folderUrl = folderUrl.deletingLastPathComponent().appending(path: "\(folderName)\(fileNumber)")
}
// Create the folder
do {
try fileManager.createDirectory(
at: folderUrl,
withIntermediateDirectories: true,
attributes: [:]
)
try rebuildFiles(fromItem: file.isFolder ? file : file.parent ?? file)
notifyObservers(updatedItems: [file.isFolder ? file : file.parent ?? file])
guard let newFolder = getFile(folderUrl.path(), createIfNotFound: true) else {
throw FileManagerError.fileNotFound
}
return newFolder
} catch {
logger.error("Failed to create folder: \(error, privacy: .auto)")
throw error
}
}
/// This function allows creating files in the selected folder or project main directory
/// - Parameters:
/// - fileName: The name of the new file
/// - file: The file to add the new file to.
/// - useExtension: The file extension to use. Leave `nil` to guess using relevant nearby files.
/// - Authors: Mattijs Eikelenboom, KaiTheRedNinja. *Moved from 7c27b1e*
/// - Throws: Throws a `CocoaError.fileWriteUnknown` with the file url if creating the file fails, and calls
/// ``rebuildFiles(fromItem:deep:)`` which throws other `FileManager` errors.
/// - Returns: The ``CEWorkspaceFile`` representing the new file in the file manager's cache.
func addFile(
fileName: String,
toFile file: CEWorkspaceFile,
useExtension: String? = nil,
contents: Data? = nil
) throws -> CEWorkspaceFile {
// check the folder for other files, and see what the most common file extension is
do {
var fileExtension: String
if fileName.contains(".") {
// If we already have a file extension in the name, don't add another one
fileExtension = ""
} else {
fileExtension = useExtension ?? findCommonFileExtension(for: file)
// Don't add a . if the extension is empty, but add it if it's missing.
if !fileExtension.isEmpty && !fileExtension.starts(with: ".") {
fileExtension = "." + fileExtension
}
}
var fileUrl = file.nearestFolder.appending(path: "\(fileName)\(fileExtension)")
// If a file/folder with the same name exists, add a number to the end.
var fileNumber = 0
while fileManager.fileExists(atPath: fileUrl.path) {
fileNumber += 1
fileUrl = fileUrl.deletingLastPathComponent()
.appending(path: "\(fileName)\(fileNumber)\(fileExtension)")
}
guard fileUrl.fileName.isValidFilename else {
throw FileManagerError.invalidFileName
}
// Create the file
guard fileManager.createFile(
atPath: fileUrl.path,
contents: contents,
attributes: [FileAttributeKey.creationDate: Date()]
) else {
throw CocoaError.error(.fileWriteUnknown, url: fileUrl)
}
try rebuildFiles(fromItem: file.isFolder ? file : file.parent ?? file)
notifyObservers(updatedItems: [file.isFolder ? file : file.parent ?? file])
// Create if not found here because this should be indexed if we're creating it.
// It's not often a user makes a file and then doesn't use it.
guard let newFile = getFile(fileUrl.path, createIfNotFound: true) else {
throw FileManagerError.fileNotIndexed
}
return newFile
} catch {
logger.error("Failed to add file: \(error, privacy: .auto)")
throw error
}
}
/// Finds a common file extension in the same directory as a file. Defaults to `txt` if no better alternatives
/// are found.
/// - Parameter file: The file to use to determine a common extension.
/// - Returns: The suggested file extension.
private func findCommonFileExtension(for file: CEWorkspaceFile) -> String {
var fileExtensions: [String: Int] = ["": 0]
for child in (
file.isFolder ? file.flattenedSiblings(withHeight: 2, ignoringFolders: true, using: self)
: file.parent?.flattenedSiblings(withHeight: 2, ignoringFolders: true, using: self)
) ?? []
where !child.isFolder {
// if the file extension was present before, add it now
let childFileName = child.fileName(typeHidden: false)
if let index = childFileName.lastIndex(of: ".") {
let childFileExtension = ".\(childFileName.suffix(from: index).dropFirst())"
fileExtensions[childFileExtension] = (fileExtensions[childFileExtension] ?? 0) + 1
} else {
fileExtensions[""] = (fileExtensions[""] ?? 0) + 1
}
}
return fileExtensions.max(by: { $0.value < $1.value })?.key ?? "txt"
}
/// This function deletes the item or folder from the current project by moving to Trash
/// - Parameters:
/// - file: The file or folder to delete
/// - Authors: Paul Ebose
public func trash(file: CEWorkspaceFile) throws {
do {
guard fileManager.fileExists(atPath: file.url.path) else {
throw FileManagerError.fileNotFound
}
try fileManager.trashItem(at: file.url, resultingItemURL: nil)
} catch {
logger.error("Failed to trash file: \(error, privacy: .auto)")
throw error
}
}
/// This function deletes the item or folder from the current project by erasing immediately.
/// - Parameters:
/// - file: The file to delete
/// - confirmDelete: True to present an alert to confirm the delete.
/// - Authors: Mattijs Eikelenboom, KaiTheRedNinja., Paul Ebose *Moved from 7c27b1e*
public func delete(file: CEWorkspaceFile, confirmDelete: Bool = true) throws {
// This function also has to account for how the
// - file system can change outside of the editor
let fileName = file.name
let deleteConfirmation = NSAlert()
deleteConfirmation.messageText = "Do you want to delete “\(fileName)”?"
deleteConfirmation.informativeText = "This item will be deleted immediately. You can't undo this action."
deleteConfirmation.alertStyle = .critical
deleteConfirmation.addButton(withTitle: "Delete")
deleteConfirmation.buttons.last?.hasDestructiveAction = true
deleteConfirmation.addButton(withTitle: "Cancel")
if !confirmDelete || deleteConfirmation.runModal() == .alertFirstButtonReturn { // "Delete" button
if fileManager.fileExists(atPath: file.url.path) {
try deleteFile(at: file.url)
}
}
}
/// This function deletes multiple files or folders from the current project by erasing immediately.
/// - Parameters:
/// - files: The files to delete
/// - confirmDelete: True to present an alert to confirm the delete.
public func batchDelete(files: Set<CEWorkspaceFile>, confirmDelete: Bool = true) throws {
let deleteConfirmation = NSAlert()
deleteConfirmation.messageText = "Are you sure you want to delete the \(files.count) selected items?"
// swiftlint:disable:next line_length
deleteConfirmation.informativeText = "\(files.count) items will be deleted immediately. You cannot undo this action."
deleteConfirmation.alertStyle = .critical
deleteConfirmation.addButton(withTitle: "Delete")
deleteConfirmation.buttons.last?.hasDestructiveAction = true
deleteConfirmation.addButton(withTitle: "Cancel")
if !confirmDelete || deleteConfirmation.runModal() == .alertFirstButtonReturn {
for file in files where fileManager.fileExists(atPath: file.url.path) {
try deleteFile(at: file.url)
}
}
}
/// Delete a file from the file system.
/// - Note: Use ``trash(file:)`` if the file should be moved to the trash. This is irreversible.
/// - Parameter url: The file URL to delete.
private func deleteFile(at url: URL) throws {
do {
guard fileManager.fileExists(atPath: url.path) else {
throw FileManagerError.fileNotFound
}
try fileManager.removeItem(at: url)
} catch {
logger.error("Failed to delete file: \(error, privacy: .auto)")
throw error
}
}
/// This function duplicates the item or folder
/// - Parameter file: The file to duplicate
/// - Authors: Mattijs Eikelenboom, KaiTheRedNinja. *Moved from 7c27b1e*
public func duplicate(file: CEWorkspaceFile) throws {
// If a file/folder with the same name exists, add "copy" to the end
var fileUrl = file.url
while fileManager.fileExists(atPath: fileUrl.path) {
let previousName = fileUrl.lastPathComponent
let fileExtension = fileUrl.pathExtension.isEmpty ? "" : ".\(fileUrl.pathExtension)"
let fileName = fileExtension.isEmpty ? previousName :
previousName.replacingOccurrences(of: fileExtension, with: "")
fileUrl = fileUrl.deletingLastPathComponent().appending(path: "\(fileName) copy\(fileExtension)")
}
if fileManager.fileExists(atPath: file.url.path) {
do {
try fileManager.copyItem(at: file.url, to: fileUrl)
} catch {
logger.error("Failed to duplicate file: \(error, privacy: .auto)")
throw error
}
}
}
/// This function moves the item or folder if possible
/// - Parameters:
/// - file: The file to move.
/// - newLocation: The destination to move the file to.
/// - Authors: Mattijs Eikelenboom, KaiTheRedNinja. *Moved from 7c27b1e*
/// - Returns: The new file object, if it has been indexed. The file manager does not index folders that have not
/// been revealed to save memory. This may move a file deeper into the tree than is indexed. In that
/// case, it is correct to return nothing. This is intentionally different than `addFile`.
@discardableResult
public func move(file: CEWorkspaceFile, to newLocation: URL) throws -> CEWorkspaceFile? {
do {
guard fileManager.fileExists(atPath: file.url.path(percentEncoded: false)) else {
throw FileManagerError.originFileNotFound
}
guard !fileManager.fileExists(atPath: newLocation.path(percentEncoded: false)) else {
throw FileManagerError.destinationFileExists
}
try createMissingParentDirectory(for: newLocation.deletingLastPathComponent())
try fileManager.moveItem(at: file.url, to: newLocation)
// This function recursively creates missing directories if the file is moved to a directory that does
// not exist
func createMissingParentDirectory(for url: URL, createSelf: Bool = true) throws {
// if the folder's parent folder doesn't exist, create it.
if !fileManager.fileExists(atPath: url.deletingLastPathComponent().path) {
try createMissingParentDirectory(for: url.deletingLastPathComponent())
}
// if the folder doesn't exist and the function was ordered to create it, create it.
if createSelf && !fileManager.fileExists(atPath: url.path) {
// Create the folder
try fileManager.createDirectory(
at: url,
withIntermediateDirectories: true,
attributes: [:]
)
}
}
if let parent = file.parent {
try rebuildFiles(fromItem: parent)
notifyObservers(updatedItems: [parent])
}
// If we have the new parent file, let's rebuild that directory too
if let newFileParent = getFile(newLocation.deletingLastPathComponent().path) {
try rebuildFiles(fromItem: newFileParent)
notifyObservers(updatedItems: [newFileParent])
}
return getFile(newLocation.absoluteURL.path)
} catch {
logger.error("Failed to move file: \(error, privacy: .auto)")
throw error
}
}
/// Copy a file's contents to a new location.
/// - Parameters:
/// - file: The file to copy.
/// - newLocation: The location to copy to.
public func copy(file: CEWorkspaceFile, to newLocation: URL) throws {
do {
guard file.url != newLocation && !fileManager.fileExists(
atPath: newLocation.absoluteURL.path(percentEncoded: false)
) else {
throw FileManagerError.originFileNotFound
}
try fileManager.copyItem(at: file.url, to: newLocation)
} catch {
logger.error("Failed to copy file: \(error, privacy: .auto)")
throw error
}
}
}
================================================
FILE: CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFileManager.swift
================================================
//
// FileSystemClient.swift
// CodeEdit
//
// Created by Matthijs Eikelenboom on 04/02/2023.
//
import Combine
import Foundation
import AppKit
import OSLog
protocol CEWorkspaceFileManagerObserver: AnyObject {
func fileManagerUpdated(updatedItems: Set<CEWorkspaceFile>)
}
/// This class is used to load, modify, and listen to files on a user's machine.
///
/// The workspace file manager provides an API for:
/// - Navigating and loading file items.
/// - Moving and modifying files.
/// - Listening for file system updates and notifying observers.
///
/// File caching in CodeEdit is done lazily. the ``CEWorkspaceFileManager`` will only create ``CEWorkspaceFile``s for
/// from files that are needed for some UI component, and ignores all other files. This is done primarily to prevent
/// CodeEdit from wasting resources finding and caching a potentially large file tree (eg, a user's home directory).
///
/// When the workspace is first loaded, the file manager will only load the contents of the workspace directory. To find
/// files after this, calls to ``CEWorkspaceFileManager/getFile(_:createIfNotFound:)`` or
/// ``CEWorkspaceFileManager/childrenOfFile(_:)`` can cause the children for a file to be loaded into CodeEdit's cache
/// of files.
///
/// Moving and modifying files is done via the methods: ``CEWorkspaceFileManager/addFile(fileName:toFile:)``,
/// ``CEWorkspaceFileManager/addFolder(folderName:toFile:)``, ``CEWorkspaceFileManager/delete(file:)``,
/// ``CEWorkspaceFileManager/copy(file:to:)``, and ``CEWorkspaceFileManager/duplicate(file:)``.
///
/// To listen for updates, the ``CEWorkspaceFileManager`` uses a ``DirectoryEventStream`` to listen to updates for any
/// files under the ``CEWorkspaceFileManager/folderUrl`` u
gitextract_uziqjivf/ ├── .all-contributorsrc ├── .github/ │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.yml │ │ └── feature_request.yml │ ├── pull_request_template.md │ ├── release-drafter.yml │ ├── scripts/ │ │ ├── remove_todos.sh │ │ ├── test_app.sh │ │ └── test_version_number.sh │ ├── stale.yml │ └── workflows/ │ ├── CI-bump-build-number.yml │ ├── CI-pre-release.yml │ ├── CI-pull-request.yml │ ├── CI-release-notes.yml │ ├── add-to-project.yml │ ├── appcast.yml │ ├── issue.yml │ ├── lint.yml │ ├── pre-release.yml │ ├── release-drafter.yml │ └── tests.yml ├── .gitignore ├── .swiftlint.yml ├── AppCast/ │ ├── .gitignore │ ├── Gemfile │ ├── _config.yml │ ├── _includes/ │ │ └── appcast.inc │ ├── _plugins/ │ │ └── signature_filter.rb │ ├── appcast.xml │ └── appcast_pre.xml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── CodeEdit/ │ ├── AppDelegate.swift │ ├── Assets.xcassets/ │ │ ├── AccentColor.colorset/ │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset/ │ │ │ └── Contents.json │ │ ├── AppIconAlpha.appiconset/ │ │ │ └── Contents.json │ │ ├── AppIconBeta.appiconset/ │ │ │ └── Contents.json │ │ ├── AppIconDev.appiconset/ │ │ │ └── Contents.json │ │ ├── AppIconPre.appiconset/ │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── Custom Colors/ │ │ │ ├── Amber.colorset/ │ │ │ │ └── Contents.json │ │ │ ├── Contents.json │ │ │ ├── CoolGray.colorset/ │ │ │ │ └── Contents.json │ │ │ ├── FolderBlue.colorset/ │ │ │ │ └── Contents.json │ │ │ ├── InspectorBackgroundColor.colorset/ │ │ │ │ └── Contents.json │ │ │ ├── Scarlet.colorset/ │ │ │ │ └── Contents.json │ │ │ └── Steel.colorset/ │ │ │ └── Contents.json │ │ ├── Icons/ │ │ │ ├── BitBucketIcon.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── Contents.json │ │ │ ├── GitHubIcon.imageset/ │ │ │ │ └── Contents.json │ │ │ └── GitLabIcon.imageset/ │ │ │ └── Contents.json │ │ ├── line.3.horizontal.decrease.chevron.filled.imageset/ │ │ │ └── Contents.json │ │ └── line.3.horizontal.decrease.chevron.imageset/ │ │ └── Contents.json │ ├── CodeEdit.entitlements │ ├── CodeEditApp.swift │ ├── Features/ │ │ ├── About/ │ │ │ ├── AboutFooterView.swift │ │ │ ├── AboutSubtitleView.swift │ │ │ ├── Acknowledgements/ │ │ │ │ ├── ViewModels/ │ │ │ │ │ └── AcknowledgementsViewModel.swift │ │ │ │ └── Views/ │ │ │ │ ├── AcknowledgementRowView.swift │ │ │ │ ├── AcknowledgementsView.swift │ │ │ │ └── ParsePackagesResolved.swift │ │ │ ├── BlurButtonStyle.swift │ │ │ └── Contributors/ │ │ │ ├── ContributorRowView.swift │ │ │ ├── ContributorsView.swift │ │ │ └── Model/ │ │ │ └── Contributor.swift │ │ ├── ActivityViewer/ │ │ │ ├── ActivityViewer.swift │ │ │ ├── Models/ │ │ │ │ └── TaskNotificationModel.swift │ │ │ ├── Notifications/ │ │ │ │ ├── CECircularProgressView.swift │ │ │ │ ├── TaskNotificationHandler.swift │ │ │ │ ├── TaskNotificationView.swift │ │ │ │ └── TaskNotificationsDetailView.swift │ │ │ └── Tasks/ │ │ │ ├── ActiveTaskView.swift │ │ │ ├── DropdownMenuItemStyleModifier.swift │ │ │ ├── OptionMenuItemView.swift │ │ │ ├── SchemeDropDownView.swift │ │ │ ├── TaskDropDownView.swift │ │ │ ├── TaskView.swift │ │ │ ├── TasksPopoverMenuItem.swift │ │ │ └── WorkspaceMenuItemView.swift │ │ ├── CEWorkspace/ │ │ │ └── Models/ │ │ │ ├── CEWorkspaceFile+Recursion.swift │ │ │ ├── CEWorkspaceFile.swift │ │ │ ├── CEWorkspaceFileIcon.swift │ │ │ ├── CEWorkspaceFileManager+DirectoryEvents.swift │ │ │ ├── CEWorkspaceFileManager+Error.swift │ │ │ ├── CEWorkspaceFileManager+FileManagement.swift │ │ │ ├── CEWorkspaceFileManager.swift │ │ │ └── DirectoryEventStream.swift │ │ ├── CEWorkspaceSettings/ │ │ │ ├── Models/ │ │ │ │ ├── CETask.swift │ │ │ │ ├── CEWorkspaceSettings.swift │ │ │ │ ├── CEWorkspaceSettingsData+ProjectSettings.swift │ │ │ │ └── CEWorkspaceSettingsData.swift │ │ │ └── Views/ │ │ │ ├── AddCETaskView.swift │ │ │ ├── CETaskFormView.swift │ │ │ ├── CEWorkspaceSettingsTaskListView.swift │ │ │ ├── CEWorkspaceSettingsView.swift │ │ │ ├── EditCETaskView.swift │ │ │ └── EnvironmentVariableListItem.swift │ │ ├── CodeEditUI/ │ │ │ ├── Styles/ │ │ │ │ ├── IconButtonStyle.swift │ │ │ │ ├── IconToggleStyle.swift │ │ │ │ ├── MenuWithButtonStyle.swift │ │ │ │ └── OverlayButtonStyle.swift │ │ │ └── Views/ │ │ │ ├── CEContentUnavailableView.swift │ │ │ ├── CEOutlineGroup.swift │ │ │ ├── Divided.swift │ │ │ ├── EffectView.swift │ │ │ ├── ErrorDescriptionLabel.swift │ │ │ ├── FeatureIcon.swift │ │ │ ├── GlassEffectView.swift │ │ │ ├── HelpButton.swift │ │ │ ├── InstantPopoverModifier.swift │ │ │ ├── KeyValueTable.swift │ │ │ ├── PaneTextField.swift │ │ │ ├── PanelDivider.swift │ │ │ ├── PopoverContainer.swift │ │ │ ├── PressActionsModifier.swift │ │ │ ├── ScrollOffsetPreferenceKey.swift │ │ │ ├── SearchField.swift │ │ │ ├── SearchPanel.swift │ │ │ ├── SearchPanelView.swift │ │ │ ├── SegmentedControl.swift │ │ │ ├── SettingsTextEditor.swift │ │ │ ├── ToolbarBranchPicker.swift │ │ │ ├── TrackableScrollView.swift │ │ │ ├── WorkspacePanelTabBar.swift │ │ │ └── WorkspacePanelView.swift │ │ ├── Commands/ │ │ │ ├── ViewModels/ │ │ │ │ └── QuickActionsViewModel.swift │ │ │ └── Views/ │ │ │ └── QuickActionsView.swift │ │ ├── Documents/ │ │ │ ├── CodeFileDocument/ │ │ │ │ ├── CodeFileDocument.swift │ │ │ │ └── FileEncoding.swift │ │ │ ├── Controllers/ │ │ │ │ ├── CodeEditDocumentController.swift │ │ │ │ ├── CodeEditSplitViewController.swift │ │ │ │ ├── CodeEditWindowController+Panels.swift │ │ │ │ ├── CodeEditWindowController+Toolbar.swift │ │ │ │ ├── CodeEditWindowController.swift │ │ │ │ └── CodeEditWindowControllerExtensions.swift │ │ │ ├── Indexer/ │ │ │ │ ├── AsyncFileIterator.swift │ │ │ │ ├── FileHelper.swift │ │ │ │ ├── SearchIndexer+Add.swift │ │ │ │ ├── SearchIndexer+AsyncController.swift │ │ │ │ ├── SearchIndexer+File.swift │ │ │ │ ├── SearchIndexer+InternalMethods.swift │ │ │ │ ├── SearchIndexer+Memory.swift │ │ │ │ ├── SearchIndexer+ProgressiveSearch.swift │ │ │ │ ├── SearchIndexer+Search.swift │ │ │ │ ├── SearchIndexer+Terms.swift │ │ │ │ └── SearchIndexer.swift │ │ │ └── WorkspaceDocument/ │ │ │ ├── WorkspaceDocument+Find.swift │ │ │ ├── WorkspaceDocument+FindAndReplace.swift │ │ │ ├── WorkspaceDocument+Index.swift │ │ │ ├── WorkspaceDocument+Listeners.swift │ │ │ ├── WorkspaceDocument+SearchState.swift │ │ │ ├── WorkspaceDocument.swift │ │ │ └── WorkspaceStateKey.swift │ │ ├── Editor/ │ │ │ ├── JumpBar/ │ │ │ │ └── Views/ │ │ │ │ ├── EditorJumpBarComponent.swift │ │ │ │ ├── EditorJumpBarMenu.swift │ │ │ │ └── EditorJumpBarView.swift │ │ │ ├── Models/ │ │ │ │ ├── Editor/ │ │ │ │ │ ├── Editor+History.swift │ │ │ │ │ ├── Editor+TabSwitch.swift │ │ │ │ │ └── Editor.swift │ │ │ │ ├── EditorInstance.swift │ │ │ │ ├── EditorLayout/ │ │ │ │ │ ├── EditorLayout+StateRestoration.swift │ │ │ │ │ └── EditorLayout.swift │ │ │ │ ├── EditorManager.swift │ │ │ │ ├── Environment+ActiveEditor.swift │ │ │ │ └── Restoration/ │ │ │ │ ├── EditorStateRestoration.swift │ │ │ │ └── UndoManagerRegistration.swift │ │ │ ├── TabBar/ │ │ │ │ ├── Tabs/ │ │ │ │ │ ├── Tab/ │ │ │ │ │ │ ├── EditorFileTabCloseButton.swift │ │ │ │ │ │ ├── EditorTabBackground.swift │ │ │ │ │ │ ├── EditorTabButtonStyle.swift │ │ │ │ │ │ ├── EditorTabCloseButton.swift │ │ │ │ │ │ ├── EditorTabView.swift │ │ │ │ │ │ └── Models/ │ │ │ │ │ │ ├── EditorItemID.swift │ │ │ │ │ │ ├── EditorTabFileObserver.swift │ │ │ │ │ │ └── EditorTabRepresentable.swift │ │ │ │ │ └── Views/ │ │ │ │ │ ├── EditorTabs.swift │ │ │ │ │ └── EditorTabsOverflowShadow.swift │ │ │ │ └── Views/ │ │ │ │ ├── EditorHistoryMenus.swift │ │ │ │ ├── EditorTabBarAccessory.swift │ │ │ │ ├── EditorTabBarContextMenu.swift │ │ │ │ ├── EditorTabBarDivider.swift │ │ │ │ ├── EditorTabBarLeadingAccessories.swift │ │ │ │ ├── EditorTabBarTrailingAccessories.swift │ │ │ │ └── EditorTabBarView.swift │ │ │ └── Views/ │ │ │ ├── AnyFileView.swift │ │ │ ├── CodeFileView.swift │ │ │ ├── EditorAreaFileView.swift │ │ │ ├── EditorAreaView.swift │ │ │ ├── EditorLayoutView.swift │ │ │ ├── ImageFileView.swift │ │ │ ├── LoadingFileView.swift │ │ │ ├── NonTextFileView.swift │ │ │ ├── PDFFileView.swift │ │ │ └── WindowCodeFileView.swift │ │ ├── Extensions/ │ │ │ ├── Commands+ForEach.swift │ │ │ ├── ExtensionActivatorView.swift │ │ │ ├── ExtensionDetailView.swift │ │ │ ├── ExtensionDiscovery.swift │ │ │ ├── ExtensionInfo.swift │ │ │ ├── ExtensionManagerWindow.swift │ │ │ ├── ExtensionSceneView.swift │ │ │ ├── ExtensionsListView.swift │ │ │ ├── ExtensionsManager.swift │ │ │ └── codeedit.extension.appextensionpoint │ │ ├── Feedback/ │ │ │ ├── Controllers/ │ │ │ │ └── FeedbackWindowController.swift │ │ │ ├── FeedbackView.swift │ │ │ ├── HelperView/ │ │ │ │ └── FeedbackToolbar.swift │ │ │ └── Model/ │ │ │ ├── FeedbackIssueArea.swift │ │ │ ├── FeedbackModel.swift │ │ │ └── FeedbackType.swift │ │ ├── InspectorArea/ │ │ │ ├── FileInspector/ │ │ │ │ └── FileInspectorView.swift │ │ │ ├── HistoryInspector/ │ │ │ │ ├── HistoryInspectorItemView.swift │ │ │ │ ├── HistoryInspectorModel.swift │ │ │ │ ├── HistoryInspectorView.swift │ │ │ │ └── HistoryPopoverView.swift │ │ │ ├── InternalDevelopmentInspector/ │ │ │ │ ├── InternalDevelopmentInspectorView.swift │ │ │ │ ├── InternalDevelopmentNotificationsView.swift │ │ │ │ └── InternalDevelopmentOutputView.swift │ │ │ ├── Models/ │ │ │ │ └── InspectorTab.swift │ │ │ ├── ViewModels/ │ │ │ │ └── InspectorAreaViewModel.swift │ │ │ └── Views/ │ │ │ ├── InspectorAreaView.swift │ │ │ ├── InspectorField.swift │ │ │ ├── InspectorSection.swift │ │ │ └── NoSelectionInspectorView.swift │ │ ├── Keybindings/ │ │ │ ├── CommandManager.swift │ │ │ ├── KeybindingManager.swift │ │ │ ├── ModifierKeysObserver.swift │ │ │ └── default_keybindings.json │ │ ├── LSP/ │ │ │ ├── Features/ │ │ │ │ ├── DocumentSync/ │ │ │ │ │ └── LSPContentCoordinator.swift │ │ │ │ └── SemanticTokens/ │ │ │ │ ├── SemanticTokenHighlightProvider.swift │ │ │ │ ├── SemanticTokenMap.swift │ │ │ │ ├── SemanticTokenMapRangeProvider.swift │ │ │ │ └── SemanticTokenStorage/ │ │ │ │ ├── GenericSemanticTokenStorage.swift │ │ │ │ ├── SemanticTokenRange.swift │ │ │ │ └── SemanticTokenStorage.swift │ │ │ ├── LSPUtil.swift │ │ │ ├── LanguageServer/ │ │ │ │ ├── Capabilities/ │ │ │ │ │ ├── LanguageServer+CallHierarchy.swift │ │ │ │ │ ├── LanguageServer+ColorPresentation.swift │ │ │ │ │ ├── LanguageServer+Completion.swift │ │ │ │ │ ├── LanguageServer+Declaration.swift │ │ │ │ │ ├── LanguageServer+Definition.swift │ │ │ │ │ ├── LanguageServer+Diagnostics.swift │ │ │ │ │ ├── LanguageServer+DocumentColor.swift │ │ │ │ │ ├── LanguageServer+DocumentHighlight.swift │ │ │ │ │ ├── LanguageServer+DocumentLink.swift │ │ │ │ │ ├── LanguageServer+DocumentSymbol.swift │ │ │ │ │ ├── LanguageServer+DocumentSync.swift │ │ │ │ │ ├── LanguageServer+FoldingRange.swift │ │ │ │ │ ├── LanguageServer+Formatting.swift │ │ │ │ │ ├── LanguageServer+Hover.swift │ │ │ │ │ ├── LanguageServer+Implementation.swift │ │ │ │ │ ├── LanguageServer+InlayHint.swift │ │ │ │ │ ├── LanguageServer+References.swift │ │ │ │ │ ├── LanguageServer+Rename.swift │ │ │ │ │ ├── LanguageServer+SelectionRange.swift │ │ │ │ │ ├── LanguageServer+SemanticTokens.swift │ │ │ │ │ ├── LanguageServer+SignatureHelp.swift │ │ │ │ │ └── LanguageServer+TypeDefinition.swift │ │ │ │ ├── LSPCache+Data.swift │ │ │ │ ├── LSPCache.swift │ │ │ │ ├── LanguageServer.swift │ │ │ │ └── LanguageServerFileMap.swift │ │ │ ├── LanguageServerDocument.swift │ │ │ ├── Registry/ │ │ │ │ ├── Errors/ │ │ │ │ │ ├── PackageManagerError.swift │ │ │ │ │ └── RegistryManagerError.swift │ │ │ │ ├── Model/ │ │ │ │ │ ├── InstallationMethod.swift │ │ │ │ │ ├── PackageManagerType.swift │ │ │ │ │ ├── PackageSource.swift │ │ │ │ │ ├── RegistryItem+Source.swift │ │ │ │ │ └── RegistryItem.swift │ │ │ │ ├── PackageManagerProtocol.swift │ │ │ │ ├── PackageManagers/ │ │ │ │ │ ├── Install/ │ │ │ │ │ │ ├── InstallStepConfirmation.swift │ │ │ │ │ │ ├── PackageManagerInstallOperation.swift │ │ │ │ │ │ ├── PackageManagerInstallStep.swift │ │ │ │ │ │ └── PackageManagerProgressModel.swift │ │ │ │ │ └── Sources/ │ │ │ │ │ ├── CargoPackageManager.swift │ │ │ │ │ ├── GithubPackageManager.swift │ │ │ │ │ ├── GolangPackageManager.swift │ │ │ │ │ ├── NPMPackageManager.swift │ │ │ │ │ └── PipPackageManager.swift │ │ │ │ ├── PackageSourceParser/ │ │ │ │ │ ├── PackageSourceParser+Cargo.swift │ │ │ │ │ ├── PackageSourceParser+Gem.swift │ │ │ │ │ ├── PackageSourceParser+Golang.swift │ │ │ │ │ ├── PackageSourceParser+NPM.swift │ │ │ │ │ ├── PackageSourceParser+PYPI.swift │ │ │ │ │ └── PackageSourceParser.swift │ │ │ │ ├── RegistryItemTemplateParser.swift │ │ │ │ ├── RegistryManager+HandleRegistryFile.swift │ │ │ │ └── RegistryManager.swift │ │ │ └── Service/ │ │ │ ├── LSPService+Events.swift │ │ │ ├── LSPService.swift │ │ │ └── LSPServiceError.swift │ │ ├── NavigatorArea/ │ │ │ ├── FindNavigator/ │ │ │ │ ├── FindModePicker.swift │ │ │ │ ├── FindNavigatorForm.swift │ │ │ │ ├── FindNavigatorIndexBar.swift │ │ │ │ ├── FindNavigatorResultList/ │ │ │ │ │ ├── FindNavigatorListViewController.swift │ │ │ │ │ ├── FindNavigatorMatchListCell.swift │ │ │ │ │ └── FindNavigatorResultList.swift │ │ │ │ ├── FindNavigatorToolbarBottom.swift │ │ │ │ └── FindNavigatorView.swift │ │ │ ├── Models/ │ │ │ │ └── NavigatorTab.swift │ │ │ ├── OutlineView/ │ │ │ │ ├── FileSystemTableViewCell.swift │ │ │ │ ├── StandardTableViewCell.swift │ │ │ │ └── TextTableViewCell.swift │ │ │ ├── ProjectNavigator/ │ │ │ │ ├── OutlineView/ │ │ │ │ │ ├── ProjectNavigatorMenu.swift │ │ │ │ │ ├── ProjectNavigatorMenuActions.swift │ │ │ │ │ ├── ProjectNavigatorNSOutlineView.swift │ │ │ │ │ ├── ProjectNavigatorOutlineView.swift │ │ │ │ │ ├── ProjectNavigatorTableViewCell.swift │ │ │ │ │ ├── ProjectNavigatorViewController+NSMenuDelegate.swift │ │ │ │ │ ├── ProjectNavigatorViewController+NSOutlineViewDataSource.swift │ │ │ │ │ ├── ProjectNavigatorViewController+NSOutlineViewDelegate.swift │ │ │ │ │ ├── ProjectNavigatorViewController+OutlineTableViewCellDelegate.swift │ │ │ │ │ └── ProjectNavigatorViewController.swift │ │ │ │ ├── ProjectNavigatorToolbarBottom.swift │ │ │ │ └── ProjectNavigatorView.swift │ │ │ ├── SourceControlNavigator/ │ │ │ │ ├── Changes/ │ │ │ │ │ └── Views/ │ │ │ │ │ ├── SourceControlNavigatorChangesCommitView.swift │ │ │ │ │ ├── SourceControlNavigatorChangesList.swift │ │ │ │ │ ├── SourceControlNavigatorChangesView.swift │ │ │ │ │ ├── SourceControlNavigatorNoRemotesView.swift │ │ │ │ │ └── SourceControlNavigatorSyncView.swift │ │ │ │ ├── History/ │ │ │ │ │ └── Views/ │ │ │ │ │ ├── CommitDetailsHeaderView.swift │ │ │ │ │ ├── CommitDetailsView.swift │ │ │ │ │ ├── CommitListItemView.swift │ │ │ │ │ └── SourceControlNavigatorHistoryView.swift │ │ │ │ ├── Repository/ │ │ │ │ │ ├── Models/ │ │ │ │ │ │ └── RepoOutlineGroupItem.swift │ │ │ │ │ └── Views/ │ │ │ │ │ ├── SourceControlNavigatorRepositoryItem.swift │ │ │ │ │ ├── SourceControlNavigatorRepositoryView+contextMenu.swift │ │ │ │ │ ├── SourceControlNavigatorRepositoryView+outlineGroupData.swift │ │ │ │ │ └── SourceControlNavigatorRepositoryView.swift │ │ │ │ └── Views/ │ │ │ │ ├── ChangedFile/ │ │ │ │ │ ├── GitChangedFileLabel.swift │ │ │ │ │ └── GitChangedFileListView.swift │ │ │ │ ├── SourceControlNavigatorToolbarBottom.swift │ │ │ │ └── SourceControlNavigatorView.swift │ │ │ ├── ViewModels/ │ │ │ │ └── NavigatorAreaViewModel.swift │ │ │ └── Views/ │ │ │ └── NavigatorAreaView.swift │ │ ├── Notifications/ │ │ │ ├── Models/ │ │ │ │ └── CENotification.swift │ │ │ ├── NotificationManager+Delegate.swift │ │ │ ├── NotificationManager+System.swift │ │ │ ├── NotificationManager.swift │ │ │ ├── ViewModels/ │ │ │ │ └── NotificationPanelViewModel.swift │ │ │ └── Views/ │ │ │ ├── NotificationBannerView.swift │ │ │ ├── NotificationPanelView.swift │ │ │ └── NotificationToolbarItem.swift │ │ ├── OpenQuickly/ │ │ │ ├── ViewModels/ │ │ │ │ └── OpenQuicklyViewModel.swift │ │ │ └── Views/ │ │ │ ├── NSTableViewWrapper.swift │ │ │ ├── OpenQuicklyListItemView.swift │ │ │ ├── OpenQuicklyPreviewView.swift │ │ │ └── OpenQuicklyView.swift │ │ ├── Search/ │ │ │ ├── Extensions/ │ │ │ │ └── String+SafeOffset.swift │ │ │ ├── FuzzySearch/ │ │ │ │ ├── Collection+FuzzySearch.swift │ │ │ │ ├── FuzzySearchModels.swift │ │ │ │ ├── FuzzySearchUIModel.swift │ │ │ │ ├── FuzzySearchable.swift │ │ │ │ ├── String+LengthOfMatchingPrefix.swift │ │ │ │ └── String+Normalise.swift │ │ │ ├── Model/ │ │ │ │ ├── SearchModeModel.swift │ │ │ │ ├── SearchResultMatchModel.swift │ │ │ │ └── SearchResultModel.swift │ │ │ └── Views/ │ │ │ └── QuickSearchResultLabel.swift │ │ ├── Settings/ │ │ │ ├── Models/ │ │ │ │ ├── AppSettings.swift │ │ │ │ ├── GlobPattern.swift │ │ │ │ ├── PageAndSettings.swift │ │ │ │ ├── Settings.swift │ │ │ │ ├── SettingsData.swift │ │ │ │ ├── SettingsInjector.swift │ │ │ │ ├── SettingsPage.swift │ │ │ │ ├── SettingsSearchResult.swift │ │ │ │ └── SettingsSidebarFix.swift │ │ │ ├── Pages/ │ │ │ │ ├── AccountsSettings/ │ │ │ │ │ ├── AccountSelectionView.swift │ │ │ │ │ ├── AccountsSettingsAccountLink.swift │ │ │ │ │ ├── AccountsSettingsDetailsView.swift │ │ │ │ │ ├── AccountsSettingsProviderRow.swift │ │ │ │ │ ├── AccountsSettingsSigninView.swift │ │ │ │ │ ├── AccountsSettingsView.swift │ │ │ │ │ ├── CreateSSHKeyView.swift │ │ │ │ │ └── Models/ │ │ │ │ │ ├── AccountsSettings.swift │ │ │ │ │ └── SourceControlAccount.swift │ │ │ │ ├── DeveloperSettings/ │ │ │ │ │ ├── DeveloperSettingsView.swift │ │ │ │ │ └── Models/ │ │ │ │ │ └── DeveloperSettings.swift │ │ │ │ ├── Extensions/ │ │ │ │ │ ├── LanguageServerInstallView.swift │ │ │ │ │ ├── LanguageServerRowView.swift │ │ │ │ │ ├── LanguageServersView.swift │ │ │ │ │ └── Models/ │ │ │ │ │ └── LanguageServerSettings.swift │ │ │ │ ├── GeneralSettings/ │ │ │ │ │ ├── GeneralSettingsView.swift │ │ │ │ │ ├── Models/ │ │ │ │ │ │ └── GeneralSettings.swift │ │ │ │ │ └── View+actionBar.swift │ │ │ │ ├── Keybindings/ │ │ │ │ │ └── Models/ │ │ │ │ │ └── KeybindingsSettings.swift │ │ │ │ ├── LocationsSettings/ │ │ │ │ │ ├── LocationsSettingsView.swift │ │ │ │ │ └── Models/ │ │ │ │ │ └── LocationsSettings.swift │ │ │ │ ├── NavigationSettings/ │ │ │ │ │ ├── Models/ │ │ │ │ │ │ └── NavigationSettings.swift │ │ │ │ │ └── NavigationSettingsView.swift │ │ │ │ ├── SearchSettings/ │ │ │ │ │ ├── Models/ │ │ │ │ │ │ ├── SearchSettings.swift │ │ │ │ │ │ └── SearchSettingsModel.swift │ │ │ │ │ ├── SearchSettingsIgnoreGlobPatternItemView.swift │ │ │ │ │ └── SearchSettingsView.swift │ │ │ │ ├── SourceControlSettings/ │ │ │ │ │ ├── IgnoredFilesListView.swift │ │ │ │ │ ├── Models/ │ │ │ │ │ │ ├── IgnorePatternModel.swift │ │ │ │ │ │ └── SourceControlSettings.swift │ │ │ │ │ ├── SourceControlGeneralView.swift │ │ │ │ │ ├── SourceControlGitView.swift │ │ │ │ │ └── SourceControlSettingsView.swift │ │ │ │ ├── TerminalSettings/ │ │ │ │ │ ├── Models/ │ │ │ │ │ │ └── TerminalSettings.swift │ │ │ │ │ └── TerminalSettingsView.swift │ │ │ │ ├── TextEditingSettings/ │ │ │ │ │ ├── InvisiblesSettingsView.swift │ │ │ │ │ ├── Models/ │ │ │ │ │ │ ├── NSFont+WithWeight.swift │ │ │ │ │ │ └── TextEditingSettings.swift │ │ │ │ │ └── TextEditingSettingsView.swift │ │ │ │ └── ThemeSettings/ │ │ │ │ ├── Models/ │ │ │ │ │ ├── Theme+FuzzySearchable.swift │ │ │ │ │ ├── Theme.swift │ │ │ │ │ ├── ThemeModel+CRUD.swift │ │ │ │ │ ├── ThemeModel.swift │ │ │ │ │ └── ThemeSettings.swift │ │ │ │ ├── ThemeSettingThemeRow.swift │ │ │ │ ├── ThemeSettingsColorPreview.swift │ │ │ │ ├── ThemeSettingsThemeDetails.swift │ │ │ │ ├── ThemeSettingsThemeToken.swift │ │ │ │ └── ThemeSettingsView.swift │ │ │ ├── SettingsView.swift │ │ │ ├── SettingsWindow.swift │ │ │ ├── SoftwareUpdater.swift │ │ │ └── Views/ │ │ │ ├── ExternalLink.swift │ │ │ ├── FontWeightPicker.swift │ │ │ ├── GlobPatternList.swift │ │ │ ├── GlobPatternListItem.swift │ │ │ ├── InvisibleCharacterWarningList.swift │ │ │ ├── MonospacedFontPicker.swift │ │ │ ├── SettingsColorPicker.swift │ │ │ ├── SettingsForm.swift │ │ │ ├── SettingsPageView.swift │ │ │ ├── View+ConstrainHeightToWindow.swift │ │ │ ├── View+HideSidebarToggle.swift │ │ │ ├── View+NavigationBarBackButtonVisible.swift │ │ │ └── WarningCharactersView.swift │ │ ├── SourceControl/ │ │ │ ├── Accounts/ │ │ │ │ ├── Bitbucket/ │ │ │ │ │ ├── BitBucketAccount+Token.swift │ │ │ │ │ ├── BitBucketAccount.swift │ │ │ │ │ ├── BitBucketOAuthConfiguration.swift │ │ │ │ │ ├── BitBucketTokenConfiguration.swift │ │ │ │ │ ├── Model/ │ │ │ │ │ │ ├── BitBucketRepositories.swift │ │ │ │ │ │ └── BitBucketUser.swift │ │ │ │ │ └── Routers/ │ │ │ │ │ ├── BitBucketOAuthRouter.swift │ │ │ │ │ ├── BitBucketRepositoryRouter.swift │ │ │ │ │ ├── BitBucketTokenRouter.swift │ │ │ │ │ └── BitBucketUserRouter.swift │ │ │ │ ├── GitHub/ │ │ │ │ │ ├── GitHubAccount.swift │ │ │ │ │ ├── GitHubConfiguration.swift │ │ │ │ │ ├── GitHubOpenness.swift │ │ │ │ │ ├── GitHubPreviewHeader.swift │ │ │ │ │ ├── Model/ │ │ │ │ │ │ ├── GitHubAccount+deleteReference.swift │ │ │ │ │ │ ├── GitHubComment.swift │ │ │ │ │ │ ├── GitHubFiles.swift │ │ │ │ │ │ ├── GitHubGist.swift │ │ │ │ │ │ ├── GitHubIssue.swift │ │ │ │ │ │ ├── GitHubPullRequest.swift │ │ │ │ │ │ ├── GitHubRepositories.swift │ │ │ │ │ │ ├── GitHubReview.swift │ │ │ │ │ │ └── GitHubUser.swift │ │ │ │ │ ├── PublicKey.swift │ │ │ │ │ └── Routers/ │ │ │ │ │ ├── GitHubGistRouter.swift │ │ │ │ │ ├── GitHubIssueRouter.swift │ │ │ │ │ ├── GitHubPullRequestRouter.swift │ │ │ │ │ ├── GitHubRepositoryRouter.swift │ │ │ │ │ ├── GitHubReviewsRouter.swift │ │ │ │ │ ├── GitHubRouter.swift │ │ │ │ │ └── GitHubUserRouter.swift │ │ │ │ ├── GitLab/ │ │ │ │ │ ├── GitLabAccount.swift │ │ │ │ │ ├── GitLabConfiguration.swift │ │ │ │ │ ├── GitLabOAuthConfiguration.swift │ │ │ │ │ ├── Model/ │ │ │ │ │ │ ├── GitLabAccountModel.swift │ │ │ │ │ │ ├── GitLabAvatarURL.swift │ │ │ │ │ │ ├── GitLabCommit.swift │ │ │ │ │ │ ├── GitLabEvent.swift │ │ │ │ │ │ ├── GitLabEventData.swift │ │ │ │ │ │ ├── GitLabEventNote.swift │ │ │ │ │ │ ├── GitLabGroupAccess.swift │ │ │ │ │ │ ├── GitLabNamespace.swift │ │ │ │ │ │ ├── GitLabPermissions.swift │ │ │ │ │ │ ├── GitLabProject.swift │ │ │ │ │ │ ├── GitLabProjectAccess.swift │ │ │ │ │ │ ├── GitLabProjectHook.swift │ │ │ │ │ │ └── GitLabUser.swift │ │ │ │ │ └── Routers/ │ │ │ │ │ ├── GitLabCommitRouter.swift │ │ │ │ │ ├── GitLabOAuthRouter.swift │ │ │ │ │ ├── GitLabProjectRouter.swift │ │ │ │ │ └── GitLabUserRouter.swift │ │ │ │ ├── Networking/ │ │ │ │ │ ├── GitJSONPostRouter.swift │ │ │ │ │ ├── GitRouter.swift │ │ │ │ │ └── GitURLSession.swift │ │ │ │ ├── Parameters.swift │ │ │ │ └── Utils/ │ │ │ │ ├── GitTime.swift │ │ │ │ ├── String+PercentEncoding.swift │ │ │ │ └── String+QueryParameters.swift │ │ │ ├── Client/ │ │ │ │ ├── GitClient+Branches.swift │ │ │ │ ├── GitClient+Clone.swift │ │ │ │ ├── GitClient+Commit.swift │ │ │ │ ├── GitClient+CommitHistory.swift │ │ │ │ ├── GitClient+Fetch.swift │ │ │ │ ├── GitClient+Initiate.swift │ │ │ │ ├── GitClient+Pull.swift │ │ │ │ ├── GitClient+Push.swift │ │ │ │ ├── GitClient+Remote.swift │ │ │ │ ├── GitClient+Stash.swift │ │ │ │ ├── GitClient+Status.swift │ │ │ │ ├── GitClient+Validate.swift │ │ │ │ ├── GitClient.swift │ │ │ │ ├── GitConfigClient.swift │ │ │ │ ├── GitConfigExtensions.swift │ │ │ │ └── GitConfigRepresentable.swift │ │ │ ├── Clone/ │ │ │ │ ├── GitCheckoutBranchView.swift │ │ │ │ ├── GitCloneView.swift │ │ │ │ └── ViewModels/ │ │ │ │ ├── GitCheckoutBranchViewModel.swift │ │ │ │ └── GitCloneViewModel.swift │ │ │ ├── Models/ │ │ │ │ ├── GitBranch.swift │ │ │ │ ├── GitBranchesGroup.swift │ │ │ │ ├── GitChangedFile.swift │ │ │ │ ├── GitCommit.swift │ │ │ │ ├── GitRemote.swift │ │ │ │ ├── GitStashEntry.swift │ │ │ │ └── GitStatus.swift │ │ │ ├── SourceControlManager+GitClient.swift │ │ │ ├── SourceControlManager.swift │ │ │ └── Views/ │ │ │ ├── RemoteBranchPicker.swift │ │ │ ├── SourceControlAddExistingRemoteView.swift │ │ │ ├── SourceControlFetchView.swift │ │ │ ├── SourceControlNewBranchView.swift │ │ │ ├── SourceControlPullView.swift │ │ │ ├── SourceControlPushView.swift │ │ │ ├── SourceControlRenameBranchView.swift │ │ │ ├── SourceControlStashView.swift │ │ │ └── SourceControlSwitchView.swift │ │ ├── SplitView/ │ │ │ ├── Model/ │ │ │ │ ├── CodeEditDividerStyle.swift │ │ │ │ ├── Environment+ContentInsets.swift │ │ │ │ ├── Environment+SplitEditor.swift │ │ │ │ ├── SplitViewData.swift │ │ │ │ └── SplitViewItem.swift │ │ │ └── Views/ │ │ │ ├── SplitView.swift │ │ │ ├── SplitViewControllerView.swift │ │ │ ├── SplitViewModifiers.swift │ │ │ ├── SplitViewReader.swift │ │ │ └── Variadic.swift │ │ ├── StatusBar/ │ │ │ ├── Models/ │ │ │ │ └── ImageDimensions.swift │ │ │ ├── ViewModels/ │ │ │ │ └── StatusBarViewModel.swift │ │ │ ├── ViewModifiers/ │ │ │ │ └── UpdateStatusBarInfo.swift │ │ │ └── Views/ │ │ │ ├── StatusBarIcon.swift │ │ │ ├── StatusBarItems/ │ │ │ │ ├── StatusBarBreakpointButton.swift │ │ │ │ ├── StatusBarCursorPositionLabel.swift │ │ │ │ ├── StatusBarEncodingSelector.swift │ │ │ │ ├── StatusBarFileInfoView.swift │ │ │ │ ├── StatusBarIndentSelector.swift │ │ │ │ ├── StatusBarLineEndSelector.swift │ │ │ │ ├── StatusBarMenuStyle.swift │ │ │ │ └── StatusBarToggleUtilityAreaButton.swift │ │ │ └── StatusBarView.swift │ │ ├── Tasks/ │ │ │ ├── Models/ │ │ │ │ ├── CEActiveTask.swift │ │ │ │ └── CETaskStatus.swift │ │ │ ├── TaskManager.swift │ │ │ ├── ToolbarItems/ │ │ │ │ ├── StartTaskToolbarItem.swift │ │ │ │ └── StopTaskToolbarItem.swift │ │ │ └── Views/ │ │ │ ├── StartTaskToolbarButton.swift │ │ │ └── StopTaskToolbarButton.swift │ │ ├── TerminalEmulator/ │ │ │ ├── Model/ │ │ │ │ ├── CurrentUser.swift │ │ │ │ ├── Shell.swift │ │ │ │ ├── ShellIntegration.swift │ │ │ │ └── TerminalCache.swift │ │ │ └── Views/ │ │ │ ├── CEActiveTaskTerminalView.swift │ │ │ ├── CELocalShellTerminalView.swift │ │ │ ├── CETerminalView.swift │ │ │ ├── TerminalEmulatorView+Coordinator.swift │ │ │ └── TerminalEmulatorView.swift │ │ ├── UtilityArea/ │ │ │ ├── DebugUtility/ │ │ │ │ ├── TaskOutputActionsView.swift │ │ │ │ ├── TaskOutputView.swift │ │ │ │ └── UtilityAreaDebugView.swift │ │ │ ├── Models/ │ │ │ │ ├── UtilityAreaTab.swift │ │ │ │ └── UtilityAreaTerminal.swift │ │ │ ├── OutputUtility/ │ │ │ │ ├── Model/ │ │ │ │ │ ├── Sources/ │ │ │ │ │ │ ├── ExtensionUtilityAreaOutputSource.swift │ │ │ │ │ │ ├── InternalDevelopmentOutputSource.swift │ │ │ │ │ │ └── LanguageServerLogContainer.swift │ │ │ │ │ ├── UtilityAreaLogLevel.swift │ │ │ │ │ └── UtilityAreaOutputSource.swift │ │ │ │ └── View/ │ │ │ │ ├── UtilityAreaOutputLogList.swift │ │ │ │ ├── UtilityAreaOutputSourcePicker.swift │ │ │ │ └── UtilityAreaOutputView.swift │ │ │ ├── TerminalUtility/ │ │ │ │ ├── UtilityAreaTerminalPicker.swift │ │ │ │ ├── UtilityAreaTerminalSidebar.swift │ │ │ │ ├── UtilityAreaTerminalTab.swift │ │ │ │ └── UtilityAreaTerminalView.swift │ │ │ ├── Toolbar/ │ │ │ │ ├── UtilityAreaClearButton.swift │ │ │ │ ├── UtilityAreaFilterTextField.swift │ │ │ │ ├── UtilityAreaMaximizeButton.swift │ │ │ │ └── UtilityAreaSplitTerminalButton.swift │ │ │ ├── ViewModels/ │ │ │ │ ├── UtilityAreaTabViewModel.swift │ │ │ │ └── UtilityAreaViewModel.swift │ │ │ └── Views/ │ │ │ ├── PaneToolbar.swift │ │ │ ├── UtilityAreaTabView.swift │ │ │ ├── UtilityAreaView.swift │ │ │ └── View+paneToolbar.swift │ │ ├── Welcome/ │ │ │ ├── GitCloneButton.swift │ │ │ ├── NewFileButton.swift │ │ │ ├── OpenFileOrFolderButton.swift │ │ │ └── WelcomeSubtitleView.swift │ │ └── WindowCommands/ │ │ ├── CodeEditCommands.swift │ │ ├── EditorCommands.swift │ │ ├── ExtensionCommands.swift │ │ ├── FileCommands.swift │ │ ├── FindCommands.swift │ │ ├── HelpCommands.swift │ │ ├── MainCommands.swift │ │ ├── NavigateCommands.swift │ │ ├── SourceControlCommands.swift │ │ ├── TasksCommands.swift │ │ ├── Utils/ │ │ │ ├── CommandsFixes.swift │ │ │ ├── FirstResponderPropertyWrapper.swift │ │ │ ├── KeyWindowControllerObserver.swift │ │ │ ├── RecentProjectsMenu.swift │ │ │ └── WindowControllerPropertyWrapper.swift │ │ ├── ViewCommands.swift │ │ └── WindowCommands.swift │ ├── Info.plist │ ├── Localization/ │ │ ├── Localized+Ex.swift │ │ └── en.lproj/ │ │ └── Localizable.strings │ ├── Preview Content/ │ │ └── Preview Assets.xcassets/ │ │ └── Contents.json │ ├── SceneID.swift │ ├── ShellIntegration/ │ │ ├── codeedit_shell_integration.bash │ │ ├── codeedit_shell_integration_env.zsh │ │ ├── codeedit_shell_integration_login.zsh │ │ ├── codeedit_shell_integration_profile.zsh │ │ └── codeedit_shell_integration_rc.zsh │ ├── Utils/ │ │ ├── DependencyInjection/ │ │ │ ├── LazyServiceWrapper.swift │ │ │ ├── ServiceContainer.swift │ │ │ ├── ServiceType.swift │ │ │ └── ServiceWrapper.swift │ │ ├── Environment/ │ │ │ ├── Env+IsFullscreen.swift │ │ │ └── Env+Window.swift │ │ ├── Extensions/ │ │ │ ├── Array/ │ │ │ │ ├── Array+Index.swift │ │ │ │ └── Array+SortURLs.swift │ │ │ ├── Bundle/ │ │ │ │ └── Bundle+Info.swift │ │ │ ├── Collection/ │ │ │ │ └── Collection+subscript_safe.swift │ │ │ ├── Color/ │ │ │ │ └── Color+HEX.swift │ │ │ ├── Date/ │ │ │ │ └── Date+Formatted.swift │ │ │ ├── FileManager/ │ │ │ │ └── FileManager+MakeExecutable.swift │ │ │ ├── Int/ │ │ │ │ └── Int+HexString.swift │ │ │ ├── LanguageIdentifier/ │ │ │ │ └── LanguageIdentifier+CodeLanguage.swift │ │ │ ├── LocalProcess/ │ │ │ │ └── LocalProcess+sendText.swift │ │ │ ├── NSApplication/ │ │ │ │ └── NSApp+openWindow.swift │ │ │ ├── NSTableView/ │ │ │ │ └── NSTableView+Background.swift │ │ │ ├── NSWindow/ │ │ │ │ └── NSWindow+Child.swift │ │ │ ├── OperatingSystemVersion/ │ │ │ │ └── OperatingSystemVersion+String.swift │ │ │ ├── SemanticToken/ │ │ │ │ └── SemanticToken+Position.swift │ │ │ ├── String/ │ │ │ │ ├── String+AppearancesOfSubstring.swift │ │ │ │ ├── String+Character.swift │ │ │ │ ├── String+Escaped.swift │ │ │ │ ├── String+HighlightOccurrences.swift │ │ │ │ ├── String+Lines.swift │ │ │ │ ├── String+MD5.swift │ │ │ │ ├── String+Ranges.swift │ │ │ │ ├── String+RemoveOccurrences.swift │ │ │ │ ├── String+SHA256.swift │ │ │ │ └── String+ValidFileName.swift │ │ │ ├── SwiftTerm/ │ │ │ │ └── Color/ │ │ │ │ └── SwiftTerm+Color+Init.swift │ │ │ ├── Text/ │ │ │ │ └── Font+Caption3.swift │ │ │ ├── TextView/ │ │ │ │ ├── TextView+LSPRange.swift │ │ │ │ └── TextView+SemanticTokenRangeProvider.swift │ │ │ ├── URL/ │ │ │ │ ├── URL+Filename.swift │ │ │ │ ├── URL+FindWorkspace.swift │ │ │ │ ├── URL+FuzzySearchable.swift │ │ │ │ ├── URL+Identifiable.swift │ │ │ │ ├── URL+LSPURI.swift │ │ │ │ ├── URL+ResouceValues.swift │ │ │ │ ├── URL+URLParameters.swift │ │ │ │ ├── URL+absolutePath.swift │ │ │ │ └── URL+componentCompare.swift │ │ │ ├── View/ │ │ │ │ ├── View+focusedValue.swift │ │ │ │ ├── View+if.swift │ │ │ │ └── View+isHovering.swift │ │ │ └── ZipFoundation/ │ │ │ └── ZipFoundation+ErrorDescrioption.swift │ │ ├── FocusedValues.swift │ │ ├── Formatters/ │ │ │ ├── RegexFormatter.swift │ │ │ └── TrimWhitespaceFormatter.swift │ │ ├── KeyChain/ │ │ │ ├── CodeEditKeychain.swift │ │ │ ├── CodeEditKeychainConstants.swift │ │ │ └── KeychainSwiftAccessOptions.swift │ │ ├── Limiter.swift │ │ ├── Protocols/ │ │ │ ├── Loopable.swift │ │ │ └── SearchableSettingsPage.swift │ │ ├── ShellClient/ │ │ │ └── Models/ │ │ │ └── ShellClient.swift │ │ └── withTimeout.swift │ ├── WindowObserver.swift │ ├── WorkspaceSheets.swift │ ├── WorkspaceView.swift │ └── World.swift ├── CodeEdit.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── swiftpm/ │ │ └── Package.resolved │ └── xcshareddata/ │ └── xcschemes/ │ ├── CodeEdit.xcscheme │ └── OpenWithCodeEdit.xcscheme ├── CodeEditTestPlan.xctestplan ├── CodeEditTests/ │ ├── Features/ │ │ ├── Acknowledgements/ │ │ │ └── AcknowledgementsTests.swift │ │ ├── ActivityViewer/ │ │ │ └── TaskNotificationHandlerTests.swift │ │ ├── CodeEditUI/ │ │ │ ├── CodeEditUITests-Bridging-Header.h │ │ │ └── CodeEditUITests.swift │ │ ├── CodeFile/ │ │ │ ├── CodeFileDocument+UTTypeTests.swift │ │ │ └── CodeFileDocumentTests.swift │ │ ├── Documents/ │ │ │ ├── DocumentsUnitTests.swift │ │ │ ├── Indexer/ │ │ │ │ ├── AsyncIndexingTests.swift │ │ │ │ ├── MemoryIndexingTests.swift │ │ │ │ ├── MemorySearchTests.swift │ │ │ │ └── TemporaryFile.swift │ │ │ ├── Mocks/ │ │ │ │ └── NSHapticFeedbackPerformerMock.swift │ │ │ ├── WorkspaceDocument+SearchState+FindAndReplaceTests.swift │ │ │ ├── WorkspaceDocument+SearchState+FindTests.swift │ │ │ └── WorkspaceDocument+SearchState+IndexTests.swift │ │ ├── Editor/ │ │ │ ├── EditorStateRestorationTests.swift │ │ │ └── UndoManagerRegistrationTests.swift │ │ ├── LSP/ │ │ │ ├── BufferingServerConnection.swift │ │ │ ├── LanguageServer+CodeFileDocument.swift │ │ │ ├── LanguageServer+DocumentObjects.swift │ │ │ ├── Registry.swift │ │ │ └── SemanticTokens/ │ │ │ ├── SemanticTokenMapTests.swift │ │ │ └── SemanticTokenStorageTests.swift │ │ ├── Search/ │ │ │ └── FuzzySearch/ │ │ │ └── FuzzySearchTests.swift │ │ ├── SourceControl/ │ │ │ └── GitClientTests.swift │ │ ├── Tasks/ │ │ │ ├── CEActiveTaskTests.swift │ │ │ └── TaskManagerTests.swift │ │ ├── TerminalEmulator/ │ │ │ └── ShellIntegrationTests.swift │ │ ├── UtilityArea/ │ │ │ └── UtilityAreaViewModelTests.swift │ │ ├── Welcome/ │ │ │ └── RecentProjectsTests.swift │ │ └── WorkspaceSettings/ │ │ └── CEWorkspaceSettingsTests.swift │ └── Utils/ │ ├── CEWorkspaceFileManager/ │ │ └── CEWorkspaceFileManagerTests.swift │ ├── UnitTests_Extensions.swift │ ├── waitForExpectation.swift │ └── withTempDir.swift ├── CodeEditUI/ │ └── src/ │ └── Preferences/ │ └── ViewOffsetPreferenceKey.swift ├── CodeEditUITests/ │ ├── App.swift │ ├── Extensions/ │ │ └── XCUITest+waitForNonExistence.swift │ ├── Features/ │ │ ├── ActivityViewer/ │ │ │ └── Tasks/ │ │ │ └── TasksMenuUITests.swift │ │ ├── NavigatorArea/ │ │ │ └── ProjectNavigator/ │ │ │ ├── ProjectNavigatorFileManagementUITests.swift │ │ │ └── ProjectNavigatorUITests.swift │ │ └── UtilityArea/ │ │ └── TerminalUtility/ │ │ └── TerminalUtilityUITests.swift │ ├── Other Tests/ │ │ ├── HideInterfaceTests.swift │ │ └── WindowCloseCommandTests.swift │ ├── ProjectPath.swift │ ├── Query.swift │ └── UI TESTING.md ├── Configs/ │ ├── Alpha.xcconfig │ ├── Beta.xcconfig │ ├── Debug.xcconfig │ ├── Pre.xcconfig │ └── Release.xcconfig ├── DefaultThemes/ │ ├── Basic.cetheme │ ├── Civic.cetheme │ ├── Classic (Dark).cetheme │ ├── Classic (Light).cetheme │ ├── Default (Dark).cetheme │ ├── Default (Light).cetheme │ ├── Dusk.cetheme │ ├── GitHub (Dark).cetheme │ ├── GitHub (Light).cetheme │ ├── High Contrast (Dark).cetheme │ ├── High Contrast (Light).cetheme │ ├── Low Key.cetheme │ ├── Midnight.cetheme │ ├── Presentation (Dark).cetheme │ ├── Presentation (Light).cetheme │ ├── Solarized (Dark).cetheme │ ├── Solarized (Light).cetheme │ └── Sunset.cetheme ├── Documentation.docc/ │ ├── About/ │ │ └── About Window.md │ ├── App Window/ │ │ ├── Adding New Tab Type.md │ │ ├── App Window.md │ │ ├── InspectorSidebarView.md │ │ ├── NavigatorSidebarView.md │ │ ├── StatusBarView.md │ │ ├── TabBarView.md │ │ └── UtilityAreaView.md │ ├── AppPreferences/ │ │ ├── AppPreferences.md │ │ ├── Create a View.md │ │ ├── Getting Started.md │ │ ├── Sections/ │ │ │ ├── AccountPreferencesView.md │ │ │ ├── GeneralPreferencesView.md │ │ │ ├── KeybindingsPreferencesView.md │ │ │ ├── SourceControlPreferencesView.md │ │ │ ├── TerminalPreferencesView.md │ │ │ ├── TextEditingPreferencesView.md │ │ │ └── ThemePreferencesView.md │ │ └── Themes.md │ ├── CodeEditUI/ │ │ ├── CodeEditUI.md │ │ ├── HelpButton.md │ │ ├── SegmentedControl.md │ │ └── ToolbarBranchPicker.md │ ├── Documentation.md │ ├── FileManagement/ │ │ └── FileManagement.md │ ├── Git/ │ │ └── Git.md │ ├── KeyChain/ │ │ ├── CodeEditKeychain.md │ │ └── What is Keychain.md │ ├── Keybindings/ │ │ └── KeybindingManager.md │ └── Welcome/ │ └── Welcome Window.md ├── LICENSE.md ├── OpenWithCodeEdit/ │ ├── FinderSync.swift │ ├── Info.plist │ ├── Media.xcassets/ │ │ └── Contents.json │ └── OpenWithCodeEdit.entitlements └── README.md
SYMBOL INDEX (3 symbols across 1 files)
FILE: AppCast/_plugins/signature_filter.rb
type Jekyll (line 1) | module Jekyll
type SignatureFilter (line 2) | module SignatureFilter
function sparkle_signature (line 3) | def sparkle_signature(release_body)
Condensed preview — 801 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,561K chars).
[
{
"path": ".all-contributorsrc",
"chars": 22518,
"preview": "{\n \"files\": [\n \"README.md\"\n ],\n \"imageSize\": 100,\n \"commit\": false,\n \"contributors\": [\n {\n \"login\": \"aus"
},
{
"path": ".github/FUNDING.yml",
"chars": 717,
"preview": "# These are supported funding model platforms\n\ngithub: [CodeEditApp, austincondiff]\npatreon: # Replace with a single Pat"
},
{
"path": ".github/ISSUE_TEMPLATE/bug_report.yml",
"chars": 1385,
"preview": "name: 🐞 Bug report\ndescription: Something is not working as expected.\ntitle: 🐞 <bug title>\nlabels: bug\n\nbody:\n - type: "
},
{
"path": ".github/ISSUE_TEMPLATE/feature_request.yml",
"chars": 821,
"preview": "name: ✨ Feature request\ndescription: Suggest an idea for this project\ntitle: ✨ <feature title>\nlabels: enhancement\n\nbody"
},
{
"path": ".github/pull_request_template.md",
"chars": 1123,
"preview": "<!--- IMPORTANT: If this PR addresses multiple unrelated issues, it will be closed until separated. -->\n\n### Description"
},
{
"path": ".github/release-drafter.yml",
"chars": 367,
"preview": "categories:\n - title: '✨ Enhancements'\n labels:\n - 'enhancement'\n - 'feature'\n - title: '🐞 Bug Fixes'\n "
},
{
"path": ".github/scripts/remove_todos.sh",
"chars": 117,
"preview": "#!/bin/bash\ngrep -rl TODO . | xargs sed -i 's/TODO/notaTODO/g'\ngrep -rl FIXME . | xargs sed -i 's/FIXME/notaFIXME/g'\n"
},
{
"path": ".github/scripts/test_app.sh",
"chars": 640,
"preview": "#!/bin/bash\n\nARCH=\"\"\n\nif [ $# -eq 0 ]; then\n ARCH=\"x86_64\"\nelif [ $1 = \"arm\" ]; then\n ARCH=\"arm64\"\nfi\n\necho \"Build"
},
{
"path": ".github/scripts/test_version_number.sh",
"chars": 702,
"preview": "#!/bin/bash\n\n# get the version number from the Info.plist file using agvtool\nVERS=$(xcrun agvtool mvers -terse1)\n\n# if t"
},
{
"path": ".github/stale.yml",
"chars": 684,
"preview": "# Number of days of inactivity before an issue becomes stale\ndaysUntilStale: 60\n# Number of days of inactivity before a "
},
{
"path": ".github/workflows/CI-bump-build-number.yml",
"chars": 1307,
"preview": "name: CI - Update Build Number\non:\n workflow_dispatch:\njobs:\n upadate-build-number:\n name: Update Build Number\n "
},
{
"path": ".github/workflows/CI-pre-release.yml",
"chars": 592,
"preview": "name: CI - Pre Release\non:\n workflow_dispatch:\njobs:\n swiftlint:\n name: SwiftLint\n uses: ./.github/workflows/lin"
},
{
"path": ".github/workflows/CI-pull-request.yml",
"chars": 310,
"preview": "name: CI - Pull Request\non:\n pull_request:\n branches:\n - 'main'\n workflow_dispatch:\njobs:\n swiftlint:\n nam"
},
{
"path": ".github/workflows/CI-release-notes.yml",
"chars": 278,
"preview": "name: Deploy Website on Release Note Changes\n\non:\n workflow_dispatch:\n release:\n types: [created, edited, deleted]\n"
},
{
"path": ".github/workflows/add-to-project.yml",
"chars": 548,
"preview": "name: Add new issues to project\n\non:\n issues:\n types:\n - opened\n\njobs:\n add-to-project:\n name: Add new issu"
},
{
"path": ".github/workflows/appcast.yml",
"chars": 1276,
"preview": "name: Build and publish a new appcast file\n\non:\n workflow_dispatch:\n\njobs:\n jekyll:\n runs-on: ubuntu-latest\n ste"
},
{
"path": ".github/workflows/issue.yml",
"chars": 476,
"preview": "name: Labeling new issue\non:\n issues:\n types: ['opened']\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n "
},
{
"path": ".github/workflows/lint.yml",
"chars": 282,
"preview": "name: SwiftLint\n\non:\n workflow_dispatch:\n workflow_call:\n\njobs:\n SwiftLint:\n runs-on: [self-hosted, macOS] # ubunt"
},
{
"path": ".github/workflows/pre-release.yml",
"chars": 10138,
"preview": "name: Build and Publish Pre-release\n\non:\n workflow_dispatch:\n workflow_call:\n\njobs:\n pre-release:\n name: Build and"
},
{
"path": ".github/workflows/release-drafter.yml",
"chars": 345,
"preview": "name: Release Drafter\n\non:\n # Allow running it manually in case we forget to label a PR before merging\n workflow_dispa"
},
{
"path": ".github/workflows/tests.yml",
"chars": 387,
"preview": "name: Tests\non:\n workflow_dispatch:\n workflow_call:\njobs:\n test:\n name: Testing CodeEdit\n runs-on: [self-hosted"
},
{
"path": ".gitignore",
"chars": 2232,
"preview": ".DS_Store\n# Xcode\n#\n# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.g"
},
{
"path": ".swiftlint.yml",
"chars": 820,
"preview": "disabled_rules:\n - todo\n - trailing_comma\n - nesting\n\ntype_name:\n excluded:\n - ID\n\nidentifier_name:\n allowed_sym"
},
{
"path": "AppCast/.gitignore",
"chars": 35,
"preview": "_site\n.sass-cache\n.jekyll-metadata\n"
},
{
"path": "AppCast/Gemfile",
"chars": 900,
"preview": "source \"https://rubygems.org\"\n\n# Hello! This is where you manage which Jekyll version is used to run.\n# When you want to"
},
{
"path": "AppCast/_config.yml",
"chars": 1356,
"preview": "# Welcome to Jekyll!\n#\n# This config file is meant for settings that affect your whole blog, values\n# which you are expe"
},
{
"path": "AppCast/_includes/appcast.inc",
"chars": 2485,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<rss version=\"2.0\" xmlns:sparkle=\"http://www.andymatuschak.org/xml-namespaces/spa"
},
{
"path": "AppCast/_plugins/signature_filter.rb",
"chars": 385,
"preview": "module Jekyll\n module SignatureFilter\n def sparkle_signature(release_body)\n regex = /<!-- sparkle:edSignature=("
},
{
"path": "AppCast/appcast.xml",
"chars": 52,
"preview": "---\nrelease_only: true\n---\n{%include appcast.inc %}\n"
},
{
"path": "AppCast/appcast_pre.xml",
"chars": 53,
"preview": "---\nrelease_only: false\n---\n{%include appcast.inc %}\n"
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 5426,
"preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participa"
},
{
"path": "CONTRIBUTING.md",
"chars": 2982,
"preview": "# Contribute to CodeEdit\n\nFeel free to join and collaborate on our [Discord Server](https://discord.gg/vChUXVf9Em).\n\n> ["
},
{
"path": "CodeEdit/AppDelegate.swift",
"chars": 11560,
"preview": "//\n// AppDelegate.swift\n// CodeEdit\n//\n// Created by Pavel Kasila on 12.03.22.\n//\n\nimport SwiftUI\nimport CodeEditSymb"
},
{
"path": "CodeEdit/Assets.xcassets/AccentColor.colorset/Contents.json",
"chars": 123,
"preview": "{\n \"colors\" : [\n {\n \"idiom\" : \"universal\"\n }\n ],\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }"
},
{
"path": "CodeEdit/Assets.xcassets/AppIcon.appiconset/Contents.json",
"chars": 1305,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"CodeEdit-16.png\",\n \"idiom\" : \"mac\",\n \"scale\" : \"1x\",\n \"size\" :"
},
{
"path": "CodeEdit/Assets.xcassets/AppIconAlpha.appiconset/Contents.json",
"chars": 1355,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"CodeEditAlpha-16.png\",\n \"idiom\" : \"mac\",\n \"scale\" : \"1x\",\n \"si"
},
{
"path": "CodeEdit/Assets.xcassets/AppIconBeta.appiconset/Contents.json",
"chars": 1345,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"CodeEditBeta-16.png\",\n \"idiom\" : \"mac\",\n \"scale\" : \"1x\",\n \"siz"
},
{
"path": "CodeEdit/Assets.xcassets/AppIconDev.appiconset/Contents.json",
"chars": 1335,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"CodeEditDev-16.png\",\n \"idiom\" : \"mac\",\n \"scale\" : \"1x\",\n \"size"
},
{
"path": "CodeEdit/Assets.xcassets/AppIconPre.appiconset/Contents.json",
"chars": 1395,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"CodeEdit-Icon-Pre-16.png\",\n \"idiom\" : \"mac\",\n \"scale\" : \"1x\",\n "
},
{
"path": "CodeEdit/Assets.xcassets/Contents.json",
"chars": 63,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }\n}\n"
},
{
"path": "CodeEdit/Assets.xcassets/Custom Colors/Amber.colorset/Contents.json",
"chars": 707,
"preview": "{\n \"colors\" : [\n {\n \"color\" : {\n \"color-space\" : \"display-p3\",\n \"components\" : {\n \"alpha"
},
{
"path": "CodeEdit/Assets.xcassets/Custom Colors/Contents.json",
"chars": 63,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }\n}\n"
},
{
"path": "CodeEdit/Assets.xcassets/Custom Colors/CoolGray.colorset/Contents.json",
"chars": 707,
"preview": "{\n \"colors\" : [\n {\n \"color\" : {\n \"color-space\" : \"display-p3\",\n \"components\" : {\n \"alpha"
},
{
"path": "CodeEdit/Assets.xcassets/Custom Colors/FolderBlue.colorset/Contents.json",
"chars": 707,
"preview": "{\n \"colors\" : [\n {\n \"color\" : {\n \"color-space\" : \"display-p3\",\n \"components\" : {\n \"alpha"
},
{
"path": "CodeEdit/Assets.xcassets/Custom Colors/InspectorBackgroundColor.colorset/Contents.json",
"chars": 689,
"preview": "{\n \"colors\" : [\n {\n \"color\" : {\n \"color-space\" : \"srgb\",\n \"components\" : {\n \"alpha\" : \"1"
},
{
"path": "CodeEdit/Assets.xcassets/Custom Colors/Scarlet.colorset/Contents.json",
"chars": 707,
"preview": "{\n \"colors\" : [\n {\n \"color\" : {\n \"color-space\" : \"display-p3\",\n \"components\" : {\n \"alpha"
},
{
"path": "CodeEdit/Assets.xcassets/Custom Colors/Steel.colorset/Contents.json",
"chars": 707,
"preview": "{\n \"colors\" : [\n {\n \"color\" : {\n \"color-space\" : \"display-p3\",\n \"components\" : {\n \"alpha"
},
{
"path": "CodeEdit/Assets.xcassets/Icons/BitBucketIcon.imageset/Contents.json",
"chars": 163,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"BitBucketIcon.png\",\n \"idiom\" : \"universal\"\n }\n ],\n \"info\" : {\n \""
},
{
"path": "CodeEdit/Assets.xcassets/Icons/Contents.json",
"chars": 63,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }\n}\n"
},
{
"path": "CodeEdit/Assets.xcassets/Icons/GitHubIcon.imageset/Contents.json",
"chars": 362,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"GitHubIcon.png\",\n \"idiom\" : \"universal\"\n },\n {\n \"appearances\""
},
{
"path": "CodeEdit/Assets.xcassets/Icons/GitLabIcon.imageset/Contents.json",
"chars": 362,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"GitLabIcon.png\",\n \"idiom\" : \"universal\"\n },\n {\n \"appearances\""
},
{
"path": "CodeEdit/Assets.xcassets/line.3.horizontal.decrease.chevron.filled.imageset/Contents.json",
"chars": 306,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"line.3.horizontal.decrease.chevron.filled.pdf\",\n \"idiom\" : \"universal\"\n "
},
{
"path": "CodeEdit/Assets.xcassets/line.3.horizontal.decrease.chevron.imageset/Contents.json",
"chars": 299,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"line.3.horizontal.decrease.chevron.pdf\",\n \"idiom\" : \"universal\"\n }\n "
},
{
"path": "CodeEdit/CodeEdit.entitlements",
"chars": 592,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "CodeEdit/CodeEditApp.swift",
"chars": 1984,
"preview": "//\n// CodeEditApp.swift\n// CodeEdit\n//\n// Created by Wouter Hennen on 11/03/2023.\n//\n\nimport SwiftUI\nimport WelcomeWi"
},
{
"path": "CodeEdit/Features/About/AboutFooterView.swift",
"chars": 569,
"preview": "//\n// AboutFooterView.swift\n// CodeEdit\n//\n// Created by Giorgi Tchelidze on 08.06.25.\n//\n\nimport SwiftUI\nimport Abou"
},
{
"path": "CodeEdit/Features/About/AboutSubtitleView.swift",
"chars": 2176,
"preview": "//\n// AboutSubtitleView.swift\n// CodeEdit\n//\n// Created by Giorgi Tchelidze on 08.06.25.\n//\n\nimport SwiftUI\n\nstruct A"
},
{
"path": "CodeEdit/Features/About/Acknowledgements/ViewModels/AcknowledgementsViewModel.swift",
"chars": 1761,
"preview": "//\n// AcknowledgementsModel.swift\n// CodeEditModules/Acknowledgements\n//\n// Created by Lukas Pistrol on 01.05.22.\n//\n"
},
{
"path": "CodeEdit/Features/About/Acknowledgements/Views/AcknowledgementRowView.swift",
"chars": 1054,
"preview": "//\n// AcknowledgementsRowView.swift\n// CodeEdit\n//\n// Created by Austin Condiff on 1/19/23.\n//\n\nimport SwiftUI\n\nstruc"
},
{
"path": "CodeEdit/Features/About/Acknowledgements/Views/AcknowledgementsView.swift",
"chars": 841,
"preview": "//\n// AcknowledgementsView.swift\n// CodeEditModules/Acknowledgements\n//\n// Created by Shivesh M M on 4/4/22.\n//\n\nimpo"
},
{
"path": "CodeEdit/Features/About/Acknowledgements/Views/ParsePackagesResolved.swift",
"chars": 822,
"preview": "//\n// ParsePackagesResolved.swift\n// CodeEditModules/Acknowledgements\n//\n// Created by Shivesh M M on 4/4/22.\n//\n\nimp"
},
{
"path": "CodeEdit/Features/About/BlurButtonStyle.swift",
"chars": 2162,
"preview": "//\n// BlurButtonStyle.swift\n// CodeEdit\n//\n// Created by Wouter Hennen on 21/01/2023.\n//\n\nimport SwiftUI\n\nextension B"
},
{
"path": "CodeEdit/Features/About/Contributors/ContributorRowView.swift",
"chars": 3120,
"preview": "//\n// ContributorRowView.swift\n// CodeEdit\n//\n// Created by Lukas Pistrol on 19.01.23.\n//\n\nimport SwiftUI\nimport Code"
},
{
"path": "CodeEdit/Features/About/Contributors/ContributorsView.swift",
"chars": 1143,
"preview": "//\n// ContributorsView.swift\n// CodeEdit\n//\n// Created by Lukas Pistrol on 19.01.23.\n//\n\nimport SwiftUI\nimport AboutW"
},
{
"path": "CodeEdit/Features/About/Contributors/Model/Contributor.swift",
"chars": 1212,
"preview": "//\n// Contributor.swift\n// CodeEdit\n//\n// Created by Lukas Pistrol on 19.01.23.\n//\n\nimport SwiftUI\n\nstruct Contributo"
},
{
"path": "CodeEdit/Features/ActivityViewer/ActivityViewer.swift",
"chars": 2964,
"preview": "//\n// ActivityViewer.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 21.06.24.\n//\n\nimport SwiftUI\n\n/// A view that"
},
{
"path": "CodeEdit/Features/ActivityViewer/Models/TaskNotificationModel.swift",
"chars": 368,
"preview": "//\n// TaskNotificationModel.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 21.06.24.\n//\n\nimport Foundation\n\n/// R"
},
{
"path": "CodeEdit/Features/ActivityViewer/Notifications/CECircularProgressView.swift",
"chars": 2336,
"preview": "//\n// CECircularProgressView.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 21.06.24.\n//\n\nimport SwiftUI\n\nstruct "
},
{
"path": "CodeEdit/Features/ActivityViewer/Notifications/TaskNotificationHandler.swift",
"chars": 10064,
"preview": "//\n// TaskNotificationHandler.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 21.06.24.\n//\n\nimport Foundation\nimpo"
},
{
"path": "CodeEdit/Features/ActivityViewer/Notifications/TaskNotificationView.swift",
"chars": 2960,
"preview": "//\n// TaskNotificationView.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 21.06.24.\n//\n\nimport SwiftUI\n\nstruct Ta"
},
{
"path": "CodeEdit/Features/ActivityViewer/Notifications/TaskNotificationsDetailView.swift",
"chars": 1711,
"preview": "//\n// TaskNotificationsDetailView.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 21.06.24.\n//\n\nimport SwiftUI\n\nst"
},
{
"path": "CodeEdit/Features/ActivityViewer/Tasks/ActiveTaskView.swift",
"chars": 644,
"preview": "//\n// ActiveTaskView.swift\n// CodeEdit\n//\n// Created by Austin Condiff on 8/4/24.\n//\n\nimport SwiftUI\n\n// We need to o"
},
{
"path": "CodeEdit/Features/ActivityViewer/Tasks/DropdownMenuItemStyleModifier.swift",
"chars": 1132,
"preview": "//\n// DropdownMenuItemStyleModifier.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 24.06.24.\n//\n\nimport SwiftUI\n\n"
},
{
"path": "CodeEdit/Features/ActivityViewer/Tasks/OptionMenuItemView.swift",
"chars": 628,
"preview": "//\n// OptionMenuItemView.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 24.06.24.\n//\n\nimport SwiftUI\n\nstruct Opti"
},
{
"path": "CodeEdit/Features/ActivityViewer/Tasks/SchemeDropDownView.swift",
"chars": 4993,
"preview": "//\n// SchemeDropDownView.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 24.06.24.\n//\n\nimport SwiftUI\n\nstruct Sche"
},
{
"path": "CodeEdit/Features/ActivityViewer/Tasks/TaskDropDownView.swift",
"chars": 4229,
"preview": "//\n// TaskDropDownView.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 24.06.24.\n//\n\nimport SwiftUI\n\nstruct TaskDr"
},
{
"path": "CodeEdit/Features/ActivityViewer/Tasks/TaskView.swift",
"chars": 896,
"preview": "//\n// TaskView.swift\n// CodeEdit\n//\n// Created by Austin Condiff on 8/4/24.\n//\n\nimport SwiftUI\n\n/// `TaskView` repres"
},
{
"path": "CodeEdit/Features/ActivityViewer/Tasks/TasksPopoverMenuItem.swift",
"chars": 1736,
"preview": "//\n// TasksPopoverMenuItem.swift\n// CodeEdit\n//\n// Created by Austin Condiff on 8/4/24.\n//\n\nimport SwiftUI\n\n/// - Not"
},
{
"path": "CodeEdit/Features/ActivityViewer/Tasks/WorkspaceMenuItemView.swift",
"chars": 1077,
"preview": "//\n// WorkspaceMenuItemView.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 24.06.24.\n//\n\nimport SwiftUI\n\nstruct W"
},
{
"path": "CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFile+Recursion.swift",
"chars": 4145,
"preview": "//\n// CEWorkspaceFile+Recursion.swift\n// CodeEdit\n//\n// Created by Matthijs Eikelenboom on 30/04/2023.\n//\n\nimport Fou"
},
{
"path": "CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFile.swift",
"chars": 11316,
"preview": "//\n// FileItem.swift\n// CodeEdit\n//\n// Created by Matthijs Eikelenboom on 07/02/2023.\n//\n\nimport Foundation\nimport Sw"
},
{
"path": "CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFileIcon.swift",
"chars": 5425,
"preview": "//\n// FileIcon.swift\n// \n//\n// Created by Nanashi Li on 2022/05/20.\n//\n\nimport SwiftUI\n\n// TODO: DOCS (Nanashi Li)\nen"
},
{
"path": "CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFileManager+DirectoryEvents.swift",
"chars": 8459,
"preview": "//\n// CEWorkspaceFileManager+DirectoryEvents.swift\n// CodeEdit\n//\n// Created by Axel Martinez on 5/8/24.\n//\n\nimport F"
},
{
"path": "CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFileManager+Error.swift",
"chars": 1605,
"preview": "//\n// CEWorkspaceFileManager+Error.swift\n// CodeEdit\n//\n// Created by Khan Winter on 1/13/25.\n//\n\nimport Foundation\n\n"
},
{
"path": "CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFileManager+FileManagement.swift",
"chars": 14576,
"preview": "//\n// CEWorkspaceFileManager+FileSystem.swift\n// CodeEdit\n//\n// Created by Khan Winter on 9/30/23.\n//\n\nimport Foundat"
},
{
"path": "CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFileManager.swift",
"chars": 9872,
"preview": "//\n// FileSystemClient.swift\n// CodeEdit\n//\n// Created by Matthijs Eikelenboom on 04/02/2023.\n//\n\nimport Combine\nimpo"
},
{
"path": "CodeEdit/Features/CEWorkspace/Models/DirectoryEventStream.swift",
"chars": 7671,
"preview": "//\n// DirectoryEventStream.swift\n// CodeEdit\n//\n// Created by Khan Winter on 6/26/23.\n//\n\nimport Foundation\n\nenum FSE"
},
{
"path": "CodeEdit/Features/CEWorkspaceSettings/Models/CETask.swift",
"chars": 4628,
"preview": "//\n// CETask.swift\n// CodeEdit\n//\n// Created by Axel Martinez on 2/4/24.\n//\n\nimport Foundation\n\n/// CodeEdit task tha"
},
{
"path": "CodeEdit/Features/CEWorkspaceSettings/Models/CEWorkspaceSettings.swift",
"chars": 2551,
"preview": "//\n// CEWorkspaceSettingsManager.swift\n// CodeEdit\n//\n// Created by Axel Martinez on 27/3/24.\n//\n\nimport SwiftUI\nimpo"
},
{
"path": "CodeEdit/Features/CEWorkspaceSettings/Models/CEWorkspaceSettingsData+ProjectSettings.swift",
"chars": 598,
"preview": "//\n// ProjectCEWorkspaceSettings.swift\n// CodeEdit\n//\n// Created by Axel Martinez on 27/3/24.\n//\n\nimport SwiftUI\n\ncla"
},
{
"path": "CodeEdit/Features/CEWorkspaceSettings/Models/CEWorkspaceSettingsData.swift",
"chars": 1476,
"preview": "//\n// CEWorkspaceSettingsData.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 01.07.24.\n//\n\nimport Foundation\n\n///"
},
{
"path": "CodeEdit/Features/CEWorkspaceSettings/Views/AddCETaskView.swift",
"chars": 1283,
"preview": "//\n// AddCETaskView.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 01.07.24.\n//\n\nimport SwiftUI\n\nstruct AddCETask"
},
{
"path": "CodeEdit/Features/CEWorkspaceSettings/Views/CETaskFormView.swift",
"chars": 2996,
"preview": "//\n// CETaskFormView.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 01.07.24.\n//\n\nimport SwiftUI\n\nstruct CETaskFo"
},
{
"path": "CodeEdit/Features/CEWorkspaceSettings/Views/CEWorkspaceSettingsTaskListView.swift",
"chars": 2100,
"preview": "//\n// CEWorkspaceSettingsTaskListView.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 01.07.24.\n//\n\nimport SwiftUI"
},
{
"path": "CodeEdit/Features/CEWorkspaceSettings/Views/CEWorkspaceSettingsView.swift",
"chars": 2574,
"preview": "//\n// CEWorkspaceSettingsView.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 01.07.24.\n//\n\nimport SwiftUI\n\nstruct"
},
{
"path": "CodeEdit/Features/CEWorkspaceSettings/Views/EditCETaskView.swift",
"chars": 1804,
"preview": "//\n// EditCETaskView.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 01.07.24.\n//\n\nimport SwiftUI\n\nstruct EditCETa"
},
{
"path": "CodeEdit/Features/CEWorkspaceSettings/Views/EnvironmentVariableListItem.swift",
"chars": 2287,
"preview": "//\n// EnvironmentVariableListItem.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 01.07.24.\n//\n\nimport SwiftUI\n\nst"
},
{
"path": "CodeEdit/Features/CodeEditUI/Styles/IconButtonStyle.swift",
"chars": 4072,
"preview": "//\n// IconButtonStyle.swift\n// CodeEdit\n//\n// Created by Austin Condiff on 11/9/23.\n//\n\nimport SwiftUI\n\nstruct IconBu"
},
{
"path": "CodeEdit/Features/CodeEditUI/Styles/IconToggleStyle.swift",
"chars": 1626,
"preview": "//\n// IconToggleStyle.swift\n// CodeEdit\n//\n// Created by Austin Condiff on 11/9/23.\n//\n\nimport SwiftUI\n\nstruct IconTo"
},
{
"path": "CodeEdit/Features/CodeEditUI/Styles/MenuWithButtonStyle.swift",
"chars": 964,
"preview": "//\n// MenuWithButtonStyle.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 08.09.24.\n//\n\nimport SwiftUI\n\n/// A menu"
},
{
"path": "CodeEdit/Features/CodeEditUI/Styles/OverlayButtonStyle.swift",
"chars": 1171,
"preview": "import SwiftUI\n\n/// A button style for overlay buttons (like close, action buttons in notifications)\nstruct OverlayButto"
},
{
"path": "CodeEdit/Features/CodeEditUI/Views/CEContentUnavailableView.swift",
"chars": 1827,
"preview": "//\n// CEContentUnavailableView.swift\n// CodeEdit\n//\n// Created by Austin Condiff on 11/17/23.\n//\n\nimport SwiftUI\n\nstr"
},
{
"path": "CodeEdit/Features/CodeEditUI/Views/CEOutlineGroup.swift",
"chars": 2402,
"preview": "//\n// CEOutlineGroup.swift\n// CodeEdit\n//\n// Created by Austin Condiff on 11/27/23.\n//\n\nimport SwiftUI\n\n// This view "
},
{
"path": "CodeEdit/Features/CodeEditUI/Views/Divided.swift",
"chars": 729,
"preview": "//\n// Divided.swift\n// CodeEdit\n//\n// Created by Austin Condiff on 11/18/23.\n//\n\nimport SwiftUI\n\nstruct Divided<Conte"
},
{
"path": "CodeEdit/Features/CodeEditUI/Views/EffectView.swift",
"chars": 2610,
"preview": "//\n// EffectView.swift\n// CodeEditModules/CodeEditUI\n//\n// Created by Rehatbir Singh on 15/03/2022.\n//\n\nimport SwiftU"
},
{
"path": "CodeEdit/Features/CodeEditUI/Views/ErrorDescriptionLabel.swift",
"chars": 816,
"preview": "//\n// ErrorDescriptionLabel.swift\n// CodeEdit\n//\n// Created by Khan Winter on 8/14/25.\n//\n\nimport SwiftUI\n\nstruct Err"
},
{
"path": "CodeEdit/Features/CodeEditUI/Views/FeatureIcon.swift",
"chars": 2681,
"preview": "//\n// FeatureIcon.swift\n// CodeEdit\n//\n// Created by Austin Condiff on 12/2/24.\n//\n\nimport SwiftUI\nimport CodeEditSym"
},
{
"path": "CodeEdit/Features/CodeEditUI/Views/GlassEffectView.swift",
"chars": 789,
"preview": "//\n// GlassEffectView.swift\n// CodeEdit\n//\n// Created by Khan Winter on 9/2/25.\n//\n\nimport SwiftUI\nimport AppKit\n\nstr"
},
{
"path": "CodeEdit/Features/CodeEditUI/Views/HelpButton.swift",
"chars": 1192,
"preview": "//\n// HelpButton.swift\n// CodeEditModules/CodeEditUI\n//\n// Created by Lukas Pistrol on 30.03.22.\n//\n\nimport SwiftUI\n\n"
},
{
"path": "CodeEdit/Features/CodeEditUI/Views/InstantPopoverModifier.swift",
"chars": 5034,
"preview": "//\n// InstantPopoverModifier.swift\n// CodeEdit\n//\n// Created by Kihron on 10/26/24.\n//\n\nimport SwiftUI\n\n/// See ``Swi"
},
{
"path": "CodeEdit/Features/CodeEditUI/Views/KeyValueTable.swift",
"chars": 7057,
"preview": "//\n// KeyValueTable.swift\n// CodeEdit\n//\n// Created by Abe Malla on 5/16/24.\n//\n\nimport SwiftUI\n\nstruct KeyValueItem:"
},
{
"path": "CodeEdit/Features/CodeEditUI/Views/PaneTextField.swift",
"chars": 4000,
"preview": "//\n// PaneTextField.swift\n// CodeEdit\n//\n// Created by Austin Condiff on 11/2/23.\n//\n\nimport SwiftUI\nimport Combine\n\n"
},
{
"path": "CodeEdit/Features/CodeEditUI/Views/PanelDivider.swift",
"chars": 392,
"preview": "//\n// PanelDivider.swift\n// \n//\n// Created by Austin Condiff on 5/10/22.\n//\n\nimport SwiftUI\n\nstruct PanelDivider: Vie"
},
{
"path": "CodeEdit/Features/CodeEditUI/Views/PopoverContainer.swift",
"chars": 754,
"preview": "//\n// PopoverContainer.swift\n// CodeEdit\n//\n// Created by Khan Winter on 8/29/25.\n//\n\nimport SwiftUI\n\n/// Container f"
},
{
"path": "CodeEdit/Features/CodeEditUI/Views/PressActionsModifier.swift",
"chars": 1137,
"preview": "//\n// PressActionsModifier.swift\n// CodeEditModules/CodeEditUI\n//\n// Created by Gabriel Theodoropoulos on 1/11/20.\n//"
},
{
"path": "CodeEdit/Features/CodeEditUI/Views/ScrollOffsetPreferenceKey.swift",
"chars": 290,
"preview": "import SwiftUI\n\n/// Tracks scroll offset in scrollable views\nstruct ScrollOffsetPreferenceKey: PreferenceKey {\n typea"
},
{
"path": "CodeEdit/Features/CodeEditUI/Views/SearchField.swift",
"chars": 1197,
"preview": "//\n// SearchField.swift\n// CodeEdit\n//\n// Created by Austin Condiff on 9/3/24.\n//\n\nimport SwiftUI\n\nstruct SearchField"
},
{
"path": "CodeEdit/Features/CodeEditUI/Views/SearchPanel.swift",
"chars": 916,
"preview": "//\n// SearchPanel.swift\n// CodeEditModules/CodeEditUI\n//\n// Created by Pavel Kasila on 20.03.22.\n//\n\nimport Cocoa\n\nfi"
},
{
"path": "CodeEdit/Features/CodeEditUI/Views/SearchPanelView.swift",
"chars": 7480,
"preview": "//\n// SearchPanelView.swift\n// CodeEdit\n//\n// Created by Khan Winter on 3/17/23.\n//\n\nimport Foundation\nimport SwiftUI"
},
{
"path": "CodeEdit/Features/CodeEditUI/Views/SegmentedControl.swift",
"chars": 3649,
"preview": "//\n// SegmentedControl.swift\n// CodeEditModules/CodeEditUI\n//\n// Created by Lukas Pistrol on 31.03.22.\n//\n\nimport Swi"
},
{
"path": "CodeEdit/Features/CodeEditUI/Views/SettingsTextEditor.swift",
"chars": 2118,
"preview": "//\n// SettingsTextEditor.swift\n// \n//\n// Created by Andrey Plotnikov on 07.05.2022.\n//\n\nimport Foundation\nimport Swif"
},
{
"path": "CodeEdit/Features/CodeEditUI/Views/ToolbarBranchPicker.swift",
"chars": 8699,
"preview": "//\n// ToolbarBranchPicker.swift\n// CodeEditModules/CodeEditUI\n//\n// Created by Lukas Pistrol on 21.04.22.\n//\n\nimport "
},
{
"path": "CodeEdit/Features/CodeEditUI/Views/TrackableScrollView.swift",
"chars": 3850,
"preview": "//\n// TrackableScrollView.swift\n// CodeEdit\n//\n// Created by Lukas Pistrol on 19.01.23.\n//\n\n// Inspired by SwiftUITr"
},
{
"path": "CodeEdit/Features/CodeEditUI/Views/WorkspacePanelTabBar.swift",
"chars": 10691,
"preview": "//\n// WorkspacePanelTabBar.swift\n// CodeEdit\n//\n// Created by Austin Condiff on 5/25/23.\n//\n\nimport SwiftUI\n\nprotocol"
},
{
"path": "CodeEdit/Features/CodeEditUI/Views/WorkspacePanelView.swift",
"chars": 1931,
"preview": "//\n// WorkspacePanelView.swift\n// CodeEdit\n//\n// Created by Austin Condiff on 1/4/25.\n//\n\nimport SwiftUI\n\nstruct Work"
},
{
"path": "CodeEdit/Features/Commands/ViewModels/QuickActionsViewModel.swift",
"chars": 1537,
"preview": "//\n// CommandPaletteViewModel.swift\n// CodeEdit\n//\n// Created by Alex on 25.05.2022.\n//\n\nimport SwiftUI\n\n/// Simple s"
},
{
"path": "CodeEdit/Features/Commands/Views/QuickActionsView.swift",
"chars": 1912,
"preview": "//\n// CommandPaletteView.swift\n// CodeEdit\n//\n// Created by Alex Sinelnikov on 24.05.2022.\n//\n\nimport SwiftUI\n\n/// Qu"
},
{
"path": "CodeEdit/Features/Documents/CodeFileDocument/CodeFileDocument.swift",
"chars": 13680,
"preview": "//\n// CodeFileDocument.swift\n// CodeEditModules/CodeFile\n//\n// Created by Rehatbir Singh on 12/03/2022.\n//\n\nimport Ap"
},
{
"path": "CodeEdit/Features/Documents/CodeFileDocument/FileEncoding.swift",
"chars": 772,
"preview": "//\n// FileEncoding.swift\n// CodeEdit\n//\n// Created by Khan Winter on 5/31/24.\n//\n\nimport Foundation\n\nenum FileEncodin"
},
{
"path": "CodeEdit/Features/Documents/Controllers/CodeEditDocumentController.swift",
"chars": 6258,
"preview": "//\n// CodeEditDocumentController.swift\n// CodeEdit\n//\n// Created by Pavel Kasila on 17.03.22.\n//\n\nimport Cocoa\nimport"
},
{
"path": "CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift",
"chars": 8689,
"preview": "//\n// CodeEditSplitViewController.swift\n// CodeEdit\n//\n// Created by YAPRYNTSEV Aleksey on 31.12.2022.\n//\n\nimport Coc"
},
{
"path": "CodeEdit/Features/Documents/Controllers/CodeEditWindowController+Panels.swift",
"chars": 6848,
"preview": "//\n// CodeEditWindowController+Panels.swift\n// CodeEdit\n//\n// Created by Simon Kudsk on 11/05/2025.\n//\n\nimport SwiftU"
},
{
"path": "CodeEdit/Features/Documents/Controllers/CodeEditWindowController+Toolbar.swift",
"chars": 9167,
"preview": "//\n// CodeEditWindowController+Toolbar.swift\n// CodeEdit\n//\n// Created by Daniel Zhu on 5/10/24.\n//\n\nimport AppKit\nim"
},
{
"path": "CodeEdit/Features/Documents/Controllers/CodeEditWindowController.swift",
"chars": 8360,
"preview": "//\n// CodeEditWindowController.swift\n// CodeEdit\n//\n// Created by Pavel Kasila on 18.03.22.\n//\n\nimport Cocoa\nimport S"
},
{
"path": "CodeEdit/Features/Documents/Controllers/CodeEditWindowControllerExtensions.swift",
"chars": 4960,
"preview": "//\n// CodeEditWindowControllerExtensions.swift\n// CodeEdit\n//\n// Created by Austin Condiff on 10/14/23.\n//\n\nimport Sw"
},
{
"path": "CodeEdit/Features/Documents/Indexer/AsyncFileIterator.swift",
"chars": 1332,
"preview": "//\n// AsyncFileIterator.swift\n// CodeEdit\n//\n// Created by Khan Winter on 12/4/23.\n//\n\nimport Foundation\n\n/// Given a"
},
{
"path": "CodeEdit/Features/Documents/Indexer/FileHelper.swift",
"chars": 608,
"preview": "//\n// FileHelper.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 18.11.23.\n//\n\nimport Foundation\n\nenum FileHelper "
},
{
"path": "CodeEdit/Features/Documents/Indexer/SearchIndexer+Add.swift",
"chars": 5902,
"preview": "//\n// SearchIndexer+Add.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 18.11.23.\n//\n\nimport Foundation\n\nextension"
},
{
"path": "CodeEdit/Features/Documents/Indexer/SearchIndexer+AsyncController.swift",
"chars": 7678,
"preview": "//\n// SearchIndexer+AsyncController.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 18.11.23.\n//\n\nimport Foundatio"
},
{
"path": "CodeEdit/Features/Documents/Indexer/SearchIndexer+File.swift",
"chars": 3372,
"preview": "//\n// SearchIndexer+File.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 18.11.23.\n//\n\nimport Foundation\n\nextensio"
},
{
"path": "CodeEdit/Features/Documents/Indexer/SearchIndexer+InternalMethods.swift",
"chars": 3989,
"preview": "//\n// SearchIndexer+InternalMethods.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 18.11.23.\n//\n\nimport Foundatio"
},
{
"path": "CodeEdit/Features/Documents/Indexer/SearchIndexer+Memory.swift",
"chars": 3082,
"preview": "//\n// SearchIndexer+Memory.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 18.11.23.\n//\n\nimport Foundation\nextensi"
},
{
"path": "CodeEdit/Features/Documents/Indexer/SearchIndexer+ProgressiveSearch.swift",
"chars": 4294,
"preview": "//\n// SearchIndexer+ProgressiveSearch.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 18.11.23.\n//\n\nimport Foundat"
},
{
"path": "CodeEdit/Features/Documents/Indexer/SearchIndexer+Search.swift",
"chars": 1561,
"preview": "//\n// SearchIndexer+Search.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 18.11.23.\n//\n\nimport Foundation\n\nextens"
},
{
"path": "CodeEdit/Features/Documents/Indexer/SearchIndexer+Terms.swift",
"chars": 3056,
"preview": "//\n// SearchIndexer+Terms.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 18.11.23.\n//\n\nimport Foundation\n\nextensi"
},
{
"path": "CodeEdit/Features/Documents/Indexer/SearchIndexer.swift",
"chars": 4784,
"preview": "//\n// SearchIndexer.swift\n// CodeEdit\n//\n// Created by Tom Ludwig on 18.11.23.\n//\n\nimport Foundation\n\n/// Indexer usi"
},
{
"path": "CodeEdit/Features/Documents/WorkspaceDocument/WorkspaceDocument+Find.swift",
"chars": 16303,
"preview": "//\n// WorkspaceDocument+Find.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 02.01.24.\n//\n\nimport Foundation\n\nexte"
},
{
"path": "CodeEdit/Features/Documents/WorkspaceDocument/WorkspaceDocument+FindAndReplace.swift",
"chars": 6729,
"preview": "//\n// WorkspaceDocument+FindAndReplace.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 02.01.24.\n//\n\nimport Founda"
},
{
"path": "CodeEdit/Features/Documents/WorkspaceDocument/WorkspaceDocument+Index.swift",
"chars": 4147,
"preview": "//\n// WorkspaceDocument+Index.swift\n// CodeEdit\n//\n// Created by Tommy Ludwig on 02.01.24.\n//\n\nimport Foundation\n\next"
},
{
"path": "CodeEdit/Features/Documents/WorkspaceDocument/WorkspaceDocument+Listeners.swift",
"chars": 308,
"preview": "//\n// WorkspaceDocument+CommandListeners.swift\n// CodeEdit\n//\n// Created by Khan Winter on 6/5/22.\n//\n\nimport Foundat"
},
{
"path": "CodeEdit/Features/Documents/WorkspaceDocument/WorkspaceDocument+SearchState.swift",
"chars": 2570,
"preview": "//\n// WorkspaceDocument+SearchState.swift\n// CodeEdit\n//\n// Created by Tom Ludwig on 16.01.24.\n//\n\nimport Foundation\n"
},
{
"path": "CodeEdit/Features/Documents/WorkspaceDocument/WorkspaceDocument.swift",
"chars": 10788,
"preview": "//\n// WorkspaceDocument.swift\n// CodeEdit\n//\n// Created by Pavel Kasila on 17.03.22.\n//\n\nimport AppKit\nimport SwiftUI"
},
{
"path": "CodeEdit/Features/Documents/WorkspaceDocument/WorkspaceStateKey.swift",
"chars": 364,
"preview": "//\n// WorkspaceStateKey.swift\n// CodeEdit\n//\n// Created by Khan Winter on 7/3/23.\n//\n\nenum WorkspaceStateKey: String "
},
{
"path": "CodeEdit/Features/Editor/JumpBar/Views/EditorJumpBarComponent.swift",
"chars": 6435,
"preview": "//\n// EditorJumpBar.swift\n// CodeEdit\n//\n// Created by Lukas Pistrol on 18.03.22.\n//\n\nimport SwiftUI\nimport Combine\ni"
},
{
"path": "CodeEdit/Features/Editor/JumpBar/Views/EditorJumpBarMenu.swift",
"chars": 3218,
"preview": "//\n// EditorJumpBarMenu.swift\n// CodeEdit\n//\n// Created by Ziyuan Zhao on 2022/3/29.\n//\n\nimport AppKit\n\nfinal class E"
},
{
"path": "CodeEdit/Features/Editor/JumpBar/Views/EditorJumpBarView.swift",
"chars": 5853,
"preview": "//\n// EditorJumpBarView.swift\n// CodeEdit\n//\n// Created by Lukas Pistrol on 17.03.22.\n//\n\nimport SwiftUI\n\nstruct Edit"
},
{
"path": "CodeEdit/Features/Editor/Models/Editor/Editor+History.swift",
"chars": 2281,
"preview": "//\n// Editor+History.swift\n// CodeEdit\n//\n// Created by Khan Winter on 7/9/24.\n//\n\nimport Foundation\n\n/// Methods for"
},
{
"path": "CodeEdit/Features/Editor/Models/Editor/Editor+TabSwitch.swift",
"chars": 1019,
"preview": "//\n// EditorTabSwitchExtension.swift\n// CodeEdit\n//\n// Created by Roscoe Rubin-Rottenberg on 4/22/24.\n//\n\nimport Foun"
},
{
"path": "CodeEdit/Features/Editor/Models/Editor/Editor.swift",
"chars": 11296,
"preview": "//\n// Editor.swift\n// CodeEdit\n//\n// Created by Wouter Hennen on 16/02/2023.\n//\n\nimport Foundation\nimport OrderedColl"
},
{
"path": "CodeEdit/Features/Editor/Models/EditorInstance.swift",
"chars": 6157,
"preview": "//\n// EditorInstance.swift\n// CodeEdit\n//\n// Created by Khan Winter on 1/4/24.\n//\n\nimport Foundation\nimport AppKit\nim"
},
{
"path": "CodeEdit/Features/Editor/Models/EditorLayout/EditorLayout+StateRestoration.swift",
"chars": 8942,
"preview": "//\n// Editor+StateRestoration.swift\n// CodeEdit\n//\n// Created by Khan Winter on 7/3/23.\n//\n\nimport Foundation\nimport "
},
{
"path": "CodeEdit/Features/Editor/Models/EditorLayout/EditorLayout.swift",
"chars": 3982,
"preview": "//\n// EditorLayout.swift\n// CodeEdit\n//\n// Created by Wouter Hennen on 06/02/2023.\n//\n\nimport Foundation\n\nenum Editor"
},
{
"path": "CodeEdit/Features/Editor/Models/EditorManager.swift",
"chars": 4938,
"preview": "//\n// TabManager.swift\n// CodeEdit\n//\n// Created by Wouter Hennen on 03/03/2023.\n//\n\nimport Combine\nimport Foundation"
},
{
"path": "CodeEdit/Features/Editor/Models/Environment+ActiveEditor.swift",
"chars": 397,
"preview": "//\n// Environment+ActiveEditor.swift\n// CodeEdit\n//\n// Created by Wouter Hennen on 06/03/2023.\n//\n\nimport SwiftUI\n\nst"
},
{
"path": "CodeEdit/Features/Editor/Models/Restoration/EditorStateRestoration.swift",
"chars": 5679,
"preview": "//\n// EditorStateRestoration.swift\n// CodeEdit\n//\n// Created by Khan Winter on 6/20/25.\n//\n\nimport Foundation\nimport "
},
{
"path": "CodeEdit/Features/Editor/Models/Restoration/UndoManagerRegistration.swift",
"chars": 2366,
"preview": "//\n// UndoManagerRegistration.swift\n// CodeEdit\n//\n// Created by Khan Winter on 6/27/25.\n//\n\nimport SwiftUI\nimport Co"
},
{
"path": "CodeEdit/Features/Editor/TabBar/Tabs/Tab/EditorFileTabCloseButton.swift",
"chars": 1381,
"preview": "//\n// FileEditorTabCloseButton.swift\n// CodeEdit\n//\n// Created by Albert Vinizhanau on 10/13/23.\n//\n\nimport Foundatio"
},
{
"path": "CodeEdit/Features/Editor/TabBar/Tabs/Tab/EditorTabBackground.swift",
"chars": 2213,
"preview": "//\n// EditorTabBackground.swift\n// CodeEdit\n//\n// Created by Austin Condiff on 1/17/23.\n//\n\nimport SwiftUI\n\nstruct Ed"
},
{
"path": "CodeEdit/Features/Editor/TabBar/Tabs/Tab/EditorTabButtonStyle.swift",
"chars": 556,
"preview": "//\n// EditorTabButtonStyle.swift\n// CodeEdit\n//\n// Created by Khan Winter on 6/4/22.\n//\n\nimport SwiftUI\n\nstruct Edito"
},
{
"path": "CodeEdit/Features/Editor/TabBar/Tabs/Tab/EditorTabCloseButton.swift",
"chars": 3908,
"preview": "//\n// EditorTabCloseButton.swift\n// CodeEdit\n//\n// Created by Austin Condiff on 1/17/23.\n//\n\nimport SwiftUI\n\nstruct E"
},
{
"path": "CodeEdit/Features/Editor/TabBar/Tabs/Tab/EditorTabView.swift",
"chars": 9440,
"preview": "//\n// EditorTabView.swift\n// CodeEdit\n//\n// Created by Lukas Pistrol on 17.03.22.\n//\n\nimport SwiftUI\n\nstruct EditorTa"
},
{
"path": "CodeEdit/Features/Editor/TabBar/Tabs/Tab/Models/EditorItemID.swift",
"chars": 582,
"preview": "//\n// EditorTabID.swift\n// \n//\n// Created by Pavel Kasila on 30.04.22.\n//\n\nimport Foundation\n\n/// Enum to represent i"
},
{
"path": "CodeEdit/Features/Editor/TabBar/Tabs/Tab/Models/EditorTabFileObserver.swift",
"chars": 719,
"preview": "//\n// EditorTabFileObserver.swift\n// CodeEdit\n//\n// Created by Filipp Kuznetsov on 25.02.2025.\n//\n\nimport Foundation\n"
},
{
"path": "CodeEdit/Features/Editor/TabBar/Tabs/Tab/Models/EditorTabRepresentable.swift",
"chars": 470,
"preview": "//\n// EditorTabRepresentable.swift\n// \n//\n// Created by Pavel Kasila on 30.04.22.\n//\n\nimport SwiftUI\n\n/// Protocol fo"
},
{
"path": "CodeEdit/Features/Editor/TabBar/Tabs/Views/EditorTabs.swift",
"chars": 19670,
"preview": "//\n// EditorTabs.swift\n// CodeEdit\n//\n// Created by Austin Condiff on 9/7/23.\n//\n\nimport SwiftUI\n\n// Disable the rule"
},
{
"path": "CodeEdit/Features/Editor/TabBar/Tabs/Views/EditorTabsOverflowShadow.swift",
"chars": 1338,
"preview": "//\n// EditorTabsOverflowShadow.swift\n// CodeEdit\n//\n// Created by Austin Condiff on 8/22/23.\n//\n\nimport SwiftUI\n\nstru"
},
{
"path": "CodeEdit/Features/Editor/TabBar/Views/EditorHistoryMenus.swift",
"chars": 2635,
"preview": "//\n// EditorHistoryMenus.swift\n// CodeEdit\n//\n// Created by Khan Winter on 7/8/24.\n//\n\nimport SwiftUI\n\nstruct EditorH"
},
{
"path": "CodeEdit/Features/Editor/TabBar/Views/EditorTabBarAccessory.swift",
"chars": 787,
"preview": "//\n// TabBarAccessory.swift\n// CodeEdit\n//\n// Created by Lingxi Li on 4/28/22.\n//\n\nimport SwiftUI\n\n/// Accessory icon"
},
{
"path": "CodeEdit/Features/Editor/TabBar/Views/EditorTabBarContextMenu.swift",
"chars": 5208,
"preview": "//\n// EditorTabBarContextMenu.swift\n// CodeEdit\n//\n// Created by Khan Winter on 6/4/22.\n//\n\nimport SwiftUI\nimport Fou"
},
{
"path": "CodeEdit/Features/Editor/TabBar/Views/EditorTabBarDivider.swift",
"chars": 539,
"preview": "//\n// EditorTabBarDivider.swift\n// CodeEdit\n//\n// Created by Lingxi Li on 4/22/22.\n//\n\nimport SwiftUI\n\n/// The vertic"
},
{
"path": "CodeEdit/Features/Editor/TabBar/Views/EditorTabBarLeadingAccessories.swift",
"chars": 2331,
"preview": "//\n// EditorTabBarLeadingAccessories.swift\n// CodeEdit\n//\n// Created by Austin Condiff on 9/7/23.\n//\n\nimport SwiftUI\n"
},
{
"path": "CodeEdit/Features/Editor/TabBar/Views/EditorTabBarTrailingAccessories.swift",
"chars": 3736,
"preview": "//\n// EditorTabBarTrailingAccessories.swift\n// CodeEdit\n//\n// Created by Austin Condiff on 9/7/23.\n//\n\nimport SwiftUI"
},
{
"path": "CodeEdit/Features/Editor/TabBar/Views/EditorTabBarView.swift",
"chars": 997,
"preview": "//\n// EditorTabBarView.swift\n// CodeEdit\n//\n// Created by Lukas Pistrol and Lingxi Li on 17.03.22.\n//\n\nimport SwiftUI"
},
{
"path": "CodeEdit/Features/Editor/Views/AnyFileView.swift",
"chars": 1238,
"preview": "//\n// AnyFileView.swift\n// CodeEdit\n//\n// Created by Paul Ebose on 2024/5/9.\n//\n\nimport SwiftUI\nimport QuickLookUI\n\n/"
},
{
"path": "CodeEdit/Features/Editor/Views/CodeFileView.swift",
"chars": 9224,
"preview": "//\n// CodeFileView.swift\n// CodeEditModules/CodeFile\n//\n// Created by Marco Carnevali on 17/03/22.\n//\n\nimport Foundat"
},
{
"path": "CodeEdit/Features/Editor/Views/EditorAreaFileView.swift",
"chars": 1598,
"preview": "//\n// EditorAreaFileView.swift\n// CodeEdit\n//\n// Created by Pavel Kasila on 20.03.22.\n//\n\nimport AppKit\nimport AVKit\n"
},
{
"path": "CodeEdit/Features/Editor/Views/EditorAreaView.swift",
"chars": 8833,
"preview": "//\n// EditorAreaView.swift\n// CodeEdit\n//\n// Created by Wouter Hennen on 16/02/2023.\n//\n\nimport SwiftUI\nimport CodeEd"
},
{
"path": "CodeEdit/Features/Editor/Views/EditorLayoutView.swift",
"chars": 3133,
"preview": "//\n// EditorLayoutView.swift\n// CodeEdit\n//\n// Created by Wouter Hennen on 20/02/2023.\n//\n\nimport SwiftUI\n\nstruct Edi"
},
{
"path": "CodeEdit/Features/Editor/Views/ImageFileView.swift",
"chars": 1508,
"preview": "//\n// ImageFileView.swift\n// CodeEdit\n//\n// Created by Paul Ebose on 2024/5/9.\n//\n\nimport SwiftUI\n\n/// A view for pre"
},
{
"path": "CodeEdit/Features/Editor/Views/LoadingFileView.swift",
"chars": 644,
"preview": "//\n// LoadingFileView.swift\n// CodeEdit\n//\n// Created by Paul Ebose on 2024/5/9.\n//\n\nimport SwiftUI\n\n/// A placeholde"
},
{
"path": "CodeEdit/Features/Editor/Views/NonTextFileView.swift",
"chars": 1056,
"preview": "//\n// NonTextFileView.swift\n// CodeEdit\n//\n// Created by Paul Ebose on 2024/5/10.\n//\n\nimport SwiftUI\n\n/// Determines "
},
{
"path": "CodeEdit/Features/Editor/Views/PDFFileView.swift",
"chars": 1856,
"preview": "//\n// PDFFileView.swift\n// CodeEdit\n//\n// Created by Paul Ebose on 2024/5/7.\n//\n\nimport SwiftUI\nimport PDFKit.PDFView"
},
{
"path": "CodeEdit/Features/Editor/Views/WindowCodeFileView.swift",
"chars": 1101,
"preview": "//\n// WindowCodeFileView.swift\n// CodeEdit\n//\n// Created by Khan Winter on 3/19/23.\n//\n\nimport Foundation\nimport Swif"
},
{
"path": "CodeEdit/Features/Extensions/Commands+ForEach.swift",
"chars": 3247,
"preview": "//\n// Commands+ForEach.swift\n// CodeEdit\n//\n// Created by Wouter Hennen on 11/03/2023.\n//\n\nimport SwiftUI\n\n// A custo"
},
{
"path": "CodeEdit/Features/Extensions/ExtensionActivatorView.swift",
"chars": 633,
"preview": "//\n// ExtensionActivatorView.swift\n// CodeEdit\n//\n// Created by Wouter Hennen on 30/12/2022.\n//\n\nimport SwiftUI\nimpor"
},
{
"path": "CodeEdit/Features/Extensions/ExtensionDetailView.swift",
"chars": 1137,
"preview": "//\n// ExtensionDetailView.swift\n// CodeEdit\n//\n// Created by Wouter Hennen on 01/01/2023.\n//\n\nimport SwiftUI\n\nstruct "
},
{
"path": "CodeEdit/Features/Extensions/ExtensionDiscovery.swift",
"chars": 5682,
"preview": "//\n// ExtensionDiscovery.swift\n// CodeEdit\n//\n// Created by Wouter Hennen on 31/12/2022.\n//\n\nimport Foundation\nimport"
},
{
"path": "CodeEdit/Features/Extensions/ExtensionInfo.swift",
"chars": 3742,
"preview": "//\n// ExtensionInfo.swift\n// CodeEdit\n//\n// Created by Wouter Hennen on 31/12/2022.\n//\n\nimport AppKit\nimport CodeEdit"
},
{
"path": "CodeEdit/Features/Extensions/ExtensionManagerWindow.swift",
"chars": 877,
"preview": "//\n// ExtensionManagerWindow.swift\n// CodeEdit\n//\n// Created by Wouter Hennen on 24/03/2023.\n//\n\nimport SwiftUI\n\nstru"
},
{
"path": "CodeEdit/Features/Extensions/ExtensionSceneView.swift",
"chars": 3713,
"preview": "//\n// ExtensionSceneView.swift\n// CodeEdit\n//\n// Created by Wouter Hennen on 31/12/2022.\n//\n\nimport SwiftUI\nimport Co"
}
]
// ... and 601 more files (download for full content)
About this extraction
This page contains the full source code of the CodeEditApp/CodeEdit GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 801 files (2.3 MB), approximately 645.4k tokens, and a symbol index with 3 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.