-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Workspace settings #1670
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
austincondiff
merged 11 commits into
CodeEditApp:main
from
armartinez:workspace-settings
Apr 18, 2024
Merged
Workspace settings #1670
Changes from 8 commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
8874011
Added workspace settings related files
armartinez 449ddf0
Small update
armartinez ef7f42e
Finished implementation
armartinez 03d877c
Updated comments
armartinez f84c8fc
Merge branch 'main' into workspace-settings
armartinez 1ec85aa
Update CodeEditWindowController.swift
armartinez 597abe2
Fixed environment variable list issue
armartinez 11a83ef
SwiftLint fixes
armartinez 6778939
Revert changes to Package.resolved
armartinez a050dc5
Updated documentation and some coding style changes
armartinez eaf5d2b
SwiftLint fixes and bug fixes
armartinez File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
3 changes: 2 additions & 1 deletion
3
CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
35 changes: 35 additions & 0 deletions
35
CodeEdit/Features/CEWorkspace/Extensions/CEWorkspaceSettingsData+ProjectSettings.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| // | ||
| // ProjectCEWorkspaceSettings.swift | ||
| // CodeEdit | ||
| // | ||
| // Created by Axel Martinez on 27/3/24. | ||
| // | ||
|
|
||
| import SwiftUI | ||
|
|
||
| extension CEWorkspaceSettingsData { | ||
| /// The project setting | ||
| struct ProjectSettings: Codable, Hashable, SearchableSettingsPage { | ||
| var searchKeys: [String] { | ||
| [ | ||
| "Project Name", | ||
| ] | ||
| .map { NSLocalizedString($0, comment: "") } | ||
| } | ||
|
|
||
| /// The project name | ||
|
armartinez marked this conversation as resolved.
Outdated
|
||
| var projectName: String = "" | ||
|
|
||
| /// Default initializer | ||
| init() {} | ||
|
|
||
| /// Explicit decoder init for setting default values when key is not present in `JSON` | ||
| init(from decoder: Decoder) throws { | ||
| let container = try decoder.container(keyedBy: CodingKeys.self) | ||
| self.projectName = try container.decodeIfPresent( | ||
| String.self, | ||
| forKey: .projectName | ||
| ) ?? "" | ||
| } | ||
| } | ||
| } | ||
42 changes: 42 additions & 0 deletions
42
CodeEdit/Features/CEWorkspace/Extensions/CEWorkspaceSettingsData+TasksSettings.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| // | ||
| // CEWorkspaceSettingsData+TasksSettings.swift | ||
| // CodeEdit | ||
| // | ||
| // Created by Axel Martinez on 27/3/24. | ||
| // | ||
|
|
||
| import Foundation | ||
| import Collections | ||
|
|
||
| extension CEWorkspaceSettingsData { | ||
| /// The tasks setting | ||
| struct TasksSettings: Codable, Hashable, SearchableSettingsPage { | ||
| var items: [CETask] = [] | ||
|
|
||
| var searchKeys: [String] { | ||
| [ | ||
| "Tasks" | ||
| ] | ||
| .map { NSLocalizedString($0, comment: "") } | ||
| } | ||
|
|
||
| /// The tasks behavior of the app | ||
| var enabled: Bool = true | ||
|
|
||
| /// Default initializer | ||
| init() {} | ||
|
|
||
| /// Explicit decoder init for setting default values when key is not present in `JSON` | ||
| init(from decoder: Decoder) throws { | ||
| let container = try decoder.container(keyedBy: CodingKeys.self) | ||
| self.items = try container.decodeIfPresent( | ||
| [CETask].self, | ||
| forKey: .items | ||
| ) ?? [] | ||
|
armartinez marked this conversation as resolved.
Outdated
|
||
| self.enabled = try container.decodeIfPresent( | ||
| Bool.self, | ||
| forKey: .enabled | ||
| ) ?? true | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| // | ||
| // CETask.swift | ||
| // CodeEdit | ||
| // | ||
| // Created by Axel Martinez on 2/4/24. | ||
| // | ||
|
|
||
| import SwiftUI | ||
|
|
||
| /// Represents a CodeEdit task that will be executed by the a | ||
| /// task manager. | ||
|
armartinez marked this conversation as resolved.
Outdated
|
||
| struct CETask: Identifiable, Hashable, Codable { | ||
| var id = UUID() | ||
| var name: String = "" | ||
| var target: String = "" | ||
| var workingDirectory: String = "" | ||
| var command: String = "" | ||
| var env: [EnvironmentVariable] = [] | ||
|
armartinez marked this conversation as resolved.
Outdated
|
||
|
|
||
| var isInvalid: Bool { | ||
| name.isEmpty || | ||
| command.isEmpty || | ||
| target.isEmpty || | ||
| workingDirectory.isEmpty | ||
| } | ||
|
|
||
| enum CodingKeys: String, CodingKey { | ||
| case name | ||
| case target | ||
| case workingDirectory | ||
| case command | ||
| case env | ||
| } | ||
|
|
||
| struct EnvironmentVariable: Identifiable, Hashable, Codable { | ||
| var id = UUID() | ||
| var name: String = "" | ||
| var value: String = "" | ||
|
|
||
| private struct CodingKeys: CodingKey { | ||
| var stringValue: String | ||
| var intValue: Int? | ||
|
armartinez marked this conversation as resolved.
|
||
|
|
||
| init?(stringValue: String) { | ||
| self.stringValue = stringValue | ||
| self.intValue = nil | ||
| } | ||
|
|
||
| init?(intValue: Int) { | ||
| self.stringValue = "\(intValue)" | ||
| self.intValue = intValue | ||
| } | ||
| } | ||
|
|
||
| init() { | ||
| } | ||
|
armartinez marked this conversation as resolved.
Outdated
|
||
|
|
||
| init(from decoder: Decoder) throws { | ||
| let container = try decoder.container(keyedBy: CodingKeys.self) | ||
| for key in container.allKeys { | ||
| name = key.stringValue | ||
| value = try container.decode(String.self, forKey: key) | ||
| } | ||
| } | ||
|
|
||
| public func encode(to encoder: Encoder) throws { | ||
| var container = encoder.container(keyedBy: CodingKeys.self) | ||
| try container.encode(value, forKey: CodingKeys(stringValue: name)!) | ||
| } | ||
| } | ||
| } | ||
78 changes: 78 additions & 0 deletions
78
CodeEdit/Features/CEWorkspace/Models/CEWorkspaceSettings.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| // | ||
| // CEWorkspaceSettings.swift | ||
| // CodeEdit | ||
| // | ||
| // Created by Axel Martinez on 27/3/24. | ||
| // | ||
|
|
||
| import Foundation | ||
|
armartinez marked this conversation as resolved.
Outdated
|
||
| import SwiftUI | ||
| import Combine | ||
|
|
||
| /// The CodeEdit workspace settings model. | ||
| final class CEWorkspaceSettings: ObservableObject { | ||
| @ObservedObject private var workspace: WorkspaceDocument | ||
| @Published public var preferences: CEWorkspaceSettingsData = .init() | ||
|
|
||
| private var savedSettings = false | ||
| private var storeTask: AnyCancellable! | ||
| private let filemanager = FileManager.default | ||
|
armartinez marked this conversation as resolved.
Outdated
|
||
|
|
||
| private var folderURL: URL? { | ||
| guard let workspaceURL = workspace.fileURL else { | ||
| return nil | ||
| } | ||
|
|
||
| return workspaceURL | ||
| .appendingPathComponent(".codeedit", isDirectory: true) | ||
| } | ||
|
|
||
| private var settingsURL: URL? { | ||
| folderURL? | ||
| .appendingPathComponent("settings") | ||
| .appendingPathExtension("json") | ||
| } | ||
|
|
||
| init(workspaceDocument: WorkspaceDocument) { | ||
| self.workspace = workspaceDocument | ||
|
|
||
| loadSettings() | ||
|
|
||
| self.storeTask = self.$preferences.throttle(for: 2, scheduler: RunLoop.main, latest: true).sink { | ||
| if !self.savedSettings, let folderURL = self.folderURL { | ||
| try? self.filemanager.createDirectory(at: folderURL, withIntermediateDirectories: false) | ||
| self.savedSettings = true | ||
| } | ||
|
|
||
| try? self.savePreferences($0) | ||
| } | ||
| } | ||
|
|
||
| /// Load and construct ``Settings`` model from | ||
| /// `.codeedit/settings.json` | ||
|
armartinez marked this conversation as resolved.
Outdated
|
||
| private func loadSettings() { | ||
| if let settingsURL = settingsURL { | ||
| if filemanager.fileExists(atPath: settingsURL.path) { | ||
| guard let json = try? Data(contentsOf: settingsURL), | ||
| let prefs = try? JSONDecoder().decode(CEWorkspaceSettingsData.self, from: json) | ||
| else { | ||
| return | ||
| } | ||
| self.savedSettings = true | ||
| self.preferences = prefs | ||
| } | ||
| } | ||
| return | ||
| } | ||
|
|
||
| /// Save``Settings`` model to | ||
| /// `.codeedit/settings.json` | ||
|
armartinez marked this conversation as resolved.
Outdated
|
||
| private func savePreferences(_ data: CEWorkspaceSettingsData) throws { | ||
| guard let settingsURL = settingsURL else { return } | ||
|
armartinez marked this conversation as resolved.
|
||
|
|
||
| let data = try JSONEncoder().encode(data) | ||
| let json = try JSONSerialization.jsonObject(with: data) | ||
| let prettyJSON = try JSONSerialization.data(withJSONObject: json, options: [.prettyPrinted]) | ||
| try prettyJSON.write(to: settingsURL, options: .atomic) | ||
| } | ||
| } | ||
50 changes: 50 additions & 0 deletions
50
CodeEdit/Features/CEWorkspace/Models/CEWorkspaceSettingsData.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| // | ||
| // CEWorkspaceSettingsData.swift | ||
| // CodeEdit | ||
| // | ||
| // Created by Axel Martinez on 27/3/24. | ||
| // | ||
|
|
||
| import SwiftUI | ||
| import Foundation | ||
|
|
||
| /// # Workspace Settings | ||
|
armartinez marked this conversation as resolved.
|
||
| /// | ||
| /// The model structure of the workspace settings for `CodeEdit` | ||
|
armartinez marked this conversation as resolved.
Outdated
|
||
| /// | ||
| /// A `JSON` representation is persisted in the workspace's `./codeedit/settings.json`. file | ||
| /// | ||
| /// - Note: Make sure to implement the ``init(from:)`` initializer, decoding | ||
| /// all properties with | ||
| /// [`decodeIfPresent`](https://developer.apple.com/documentation/swift/keyeddecodingcontainer/2921389-decodeifpresent) | ||
| /// and providing a default value. Otherwise all settings get overridden. | ||
|
armartinez marked this conversation as resolved.
Outdated
|
||
| struct CEWorkspaceSettingsData: Codable, Hashable { | ||
| /// The project global settings | ||
| var project: ProjectSettings = .init() | ||
|
|
||
| /// The tasks settings | ||
| var tasks: TasksSettings = .init() | ||
|
|
||
| /// Default initializer | ||
| init() {} | ||
|
|
||
| /// Explicit decoder init for setting default values when key is not present in `JSON` | ||
| init(from decoder: Decoder) throws { | ||
| let container = try decoder.container(keyedBy: CodingKeys.self) | ||
| self.project = try container.decodeIfPresent(ProjectSettings.self, forKey: .project) ?? .init() | ||
| self.tasks = try container.decodeIfPresent(TasksSettings.self, forKey: .tasks) ?? .init() | ||
| } | ||
|
|
||
| func propertiesOf(_ name: CEWorkspaceSettingsPage.Name) -> [CEWorkspaceSettingsPage] { | ||
| var settings: [CEWorkspaceSettingsPage] = [] | ||
|
|
||
| switch name { | ||
| case .project: | ||
| project.searchKeys.forEach { settings.append(.init(name, isSetting: true, settingName: $0)) } | ||
| case .tasks: | ||
| tasks.searchKeys.forEach { settings.append(.init(name, isSetting: true, settingName: $0)) } | ||
| } | ||
|
|
||
| return settings | ||
| } | ||
| } | ||
51 changes: 51 additions & 0 deletions
51
CodeEdit/Features/CEWorkspace/Models/CEWorkspaceSettingsPage.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| // | ||
| // CEWorkspaceSettingsPage.swift | ||
| // CodeEdit | ||
| // | ||
| // Created by Axel Martinez on 27/3/24. | ||
| // | ||
|
|
||
| import Foundation | ||
| import SwiftUI | ||
|
|
||
| /// A struct for a workspace settings page | ||
|
armartinez marked this conversation as resolved.
Outdated
|
||
| struct CEWorkspaceSettingsPage: Hashable, Equatable, Identifiable { | ||
| /// A struct for a sidebar icon, with a base color and SF Symbol | ||
| enum IconResource: Equatable, Hashable { | ||
| case system(_ name: String) | ||
| case symbol(_ name: String) | ||
| case asset(_ name: String) | ||
| } | ||
|
|
||
| /// An enum of all the settings pages | ||
| enum Name: String { | ||
| case project = "Project" | ||
| case tasks = "Tasks" | ||
| } | ||
|
|
||
| let id: UUID = UUID() | ||
|
|
||
| let name: Name | ||
| let baseColor: Color? | ||
| let isSetting: Bool | ||
| let settingName: String | ||
| var nameString: LocalizedStringKey { | ||
| LocalizedStringKey(name.rawValue) | ||
| } | ||
| let icon: IconResource? | ||
|
|
||
| /// Default initializer | ||
| init( | ||
| _ name: Name, | ||
| baseColor: Color? = nil, | ||
| icon: IconResource? = nil, | ||
| isSetting: Bool = false, | ||
| settingName: String = "" | ||
| ) { | ||
| self.name = name | ||
| self.baseColor = baseColor | ||
| self.icon = icon | ||
| self.isSetting = isSetting | ||
| self.settingName = settingName | ||
| } | ||
| } | ||
25 changes: 25 additions & 0 deletions
25
CodeEdit/Features/CEWorkspace/Models/CEWorkspaceSettingsSearchResult.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| // | ||
| // CEWorkpaceSettingsSearchResult.swift | ||
| // CodeEdit | ||
| // | ||
| // Created by Axel Martinez on 27/3/24. | ||
| // | ||
|
|
||
| import Foundation | ||
| import SwiftUI | ||
|
|
||
| // TODO: Extend this struct further to support setting "flashing" | ||
| class CEWorkspaceSettingsSearchResult: Identifiable { | ||
|
armartinez marked this conversation as resolved.
Outdated
|
||
| init( | ||
| pageFound: Bool, | ||
| pages: [CEWorkspaceSettingsPage] | ||
| ) { | ||
| self.pageFound = pageFound | ||
| self.pages = pages | ||
| } | ||
|
|
||
| let id: UUID = UUID() | ||
|
|
||
| let pageFound: Bool | ||
| let pages: [CEWorkspaceSettingsPage] | ||
|
armartinez marked this conversation as resolved.
Outdated
|
||
| } | ||
19 changes: 19 additions & 0 deletions
19
CodeEdit/Features/CEWorkspace/Models/PageAndCEWorkspaceSettings.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| // | ||
| // PageAndCEWorkspaceSettings.swift | ||
| // CodeEdit | ||
| // | ||
| // Created by Axel Martinez on 27/3/24. | ||
| // | ||
|
|
||
| import Foundation | ||
|
|
||
| struct PageAndCEWorkspaceSettings: Identifiable, Equatable { | ||
| let id: UUID = UUID() | ||
| let page: CEWorkspaceSettingsPage | ||
| let settings: [CEWorkspaceSettingsPage] | ||
|
|
||
| init(_ page: CEWorkspaceSettingsPage) { | ||
| self.page = page | ||
| self.settings = CEWorkspaceSettingsData().propertiesOf(page.name) | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.