Skip to content

Commit

Permalink
1/4 Remember configUrl alongside config
Browse files Browse the repository at this point in the history
Needed for the next commits

#215
  • Loading branch information
nikitabobko committed May 19, 2024
1 parent b4e7075 commit 3f74a6a
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 34 deletions.
4 changes: 2 additions & 2 deletions Sources/AppBundle/MenuBar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public func menuBar(viewModel: TrayMenuModel) -> some Scene {
let editor = getTextEditorToOpenConfig()
Button("Open config in '\(editor.lastPathComponent)'") {
let fallbackConfig: URL = FileManager.default.homeDirectoryForCurrentUser.appending(path: configDotfileName)
switch getConfigFileUrl() {
switch findCustomConfigUrl() {
case .file(let url):
url.open(with: editor)
case .noCustomConfigExists:
Expand Down Expand Up @@ -64,7 +64,7 @@ public func menuBar(viewModel: TrayMenuModel) -> some Scene {
}

func getTextEditorToOpenConfig() -> URL {
NSWorkspace.shared.urlForApplication(toOpen: getConfigFileUrl().urlOrNil ?? defaultConfigUrl)?
NSWorkspace.shared.urlForApplication(toOpen: findCustomConfigUrl().urlOrNil ?? defaultConfigUrl)?
.takeIf { $0.lastPathComponent != "Xcode.app" } // Blacklist Xcode. It is too heavy to open plain text files
?? URL(filePath: "/System/Applications/TextEdit.app")
}
27 changes: 14 additions & 13 deletions Sources/AppBundle/command/ReloadConfigCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,24 @@ struct ReloadConfigCommand: Command {
}
}

func reloadConfig() -> Bool {
func reloadConfig(forceConfigUrl: URL? = nil) -> Bool {
var devNull = ""
return reloadConfig(stdout: &devNull)
return reloadConfig(forceConfigUrl: forceConfigUrl, stdout: &devNull)
}

func loadConfig(_ newConfig: Config) {
resetHotKeys()
config = newConfig
activateMode(mainModeId)
syncStartAtLogin()
}

func reloadConfig(args: ReloadConfigCmdArgs = ReloadConfigCmdArgs(), stdout: inout String) -> Bool {
switch readConfig() {
case .success(let parsedConfig):
func reloadConfig(
args: ReloadConfigCmdArgs = ReloadConfigCmdArgs(),
forceConfigUrl: URL? = nil,
stdout: inout String
) -> Bool {
switch readConfig(forceConfigUrl: forceConfigUrl) {
case .success(let (parsedConfig, url)):
if !args.dryRun {
loadConfig(parsedConfig)
resetHotKeys()
config = parsedConfig
configUrl = url
activateMode(mainModeId)
syncStartAtLogin()
}
return true
case .failure(let msg):
Expand Down
13 changes: 7 additions & 6 deletions Sources/AppBundle/config/Config.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,27 @@ import HotKey
import Common

let mainModeId = "main"
var defaultConfigUrl: URL { Bundle.main.url(forResource: "default-config", withExtension: "toml")! }
let defaultConfig: Config = {
let defaultConfig: URL
var defaultConfigUrl: URL {
if isUnitTest {
var url = URL(filePath: #file)
while !FileManager.default.fileExists(atPath: url.appending(component: ".git").path) {
url.deleteLastPathComponent()
}
let projectRoot: URL = url
defaultConfig = projectRoot.appending(component: "docs/config-examples/default-config.toml")
return projectRoot.appending(component: "docs/config-examples/default-config.toml")
} else {
defaultConfig = defaultConfigUrl
return Bundle.main.url(forResource: "default-config", withExtension: "toml")!
}
let parsedConfig = parseConfig(try! String(contentsOf: defaultConfig))
}
let defaultConfig: Config = {
let parsedConfig = parseConfig(try! String(contentsOf: defaultConfigUrl))
if !parsedConfig.errors.isEmpty {
error("Can't parse default config: \(parsedConfig.errors)")
}
return parsedConfig.config
}()
var config: Config = defaultConfig
var configUrl: URL = defaultConfigUrl

struct Config: Copyable {
var afterLoginCommand: [any Command] = []
Expand Down
2 changes: 1 addition & 1 deletion Sources/AppBundle/config/ConfigFile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Foundation
import Common

let configDotfileName = isDebug ? ".aerospace-debug.toml" : ".aerospace.toml"
func getConfigFileUrl() -> ConfigFile {
func findCustomConfigUrl() -> ConfigFile {
let fileName = isDebug ? "aerospace-debug.toml" : "aerospace.toml"
let xdgConfigHome = ProcessInfo.processInfo.environment["XDG_CONFIG_HOME"]?.lets { URL(filePath: $0) }
?? FileManager.default.homeDirectoryForCurrentUser.appending(path: ".config/")
Expand Down
20 changes: 9 additions & 11 deletions Sources/AppBundle/config/parseConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,26 @@ import AppKit
import HotKey
import TOMLKit

func readConfig() -> Result<Config, String> {
let configUrl: URL?
switch getConfigFileUrl() {
case .file(let url):
configUrl = url
case .noCustomConfigExists:
configUrl = nil
func readConfig(forceConfigUrl: URL? = nil) -> Result<(Config, URL), String> {
let customConfigUrl: URL
switch findCustomConfigUrl() {
case .file(let url): customConfigUrl = url
case .noCustomConfigExists: customConfigUrl = defaultConfigUrl
case .ambiguousConfigError(let candidates):
let msg = """
Ambiguous config error. Several configs found:
\(candidates.map(\.path).joined(separator: "\n"))
"""
return .failure(msg)
}
let (parsedConfig, errors) = configUrl.flatMap { try? String(contentsOf: $0) }.map { parseConfig($0) }
?? (defaultConfig, [])
let configUrl: URL = forceConfigUrl ?? customConfigUrl
let (parsedConfig, errors) = (try? String(contentsOf: configUrl)).map { parseConfig($0) } ?? (defaultConfig, [])

if errors.isEmpty {
return .success(parsedConfig)
return .success((parsedConfig, configUrl))
} else {
let msg = """
Failed to parse \(configUrl?.absoluteURL.path ?? "nil-configUrl")
Failed to parse \(configUrl.absoluteURL.path)
\(errors.map(\.description).joined(separator: "\n\n"))
"""
Expand Down
2 changes: 1 addition & 1 deletion Sources/AppBundle/initAppBundle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public func initAppBundle() {
}
let startedAtLogin = CommandLine.arguments.getOrNil(atIndex: 1) == "--started-at-login"
if !reloadConfig() {
loadConfig(defaultConfig)
check(reloadConfig(forceConfigUrl: defaultConfigUrl))
}
if startedAtLogin && !config.startAtLogin {
terminateApp()
Expand Down
1 change: 1 addition & 0 deletions Sources/AppBundleTests/testUtil.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ let projectRoot: URL = {

func setUpWorkspacesForTests() {
config = defaultConfig
configUrl = defaultConfigUrl
config.enableNormalizationFlattenContainers = false // Make layout tests more predictable
config.enableNormalizationOppositeOrientationForNestedContainers = false // Make layout tests more predictable
config.defaultRootContainerOrientation = .horizontal // Make default layout predictable
Expand Down

0 comments on commit 3f74a6a

Please sign in to comment.