spiegel-keyman/mac/KeymanSettings/Sources/Model/Keyboard.swift
Shawn Schantz b77b255ac6 feat(mac): throw error for missing kmx file
add TODO comments and change their format
2026-05-29 11:44:49 -04:00

99 lines
3.4 KiB
Swift

/*
* Keyman is copyright (C) SIL Global. MIT License.
*
* Created by Shawn Schantz on 2026-02-24
*
* Object that represents a Keyman keyboard
* Each keyboard can be marked as enabled/disabled
*
*/
import Foundation
import AppKit
public class Keyboard: Identifiable, Hashable, Equatable {
public var id = UUID()
public var enabled: Bool
public var name: String
public var keyboardId: String
// the directory we are reading the keyboard from
public var keyboardDirectoryUrl: URL
// the URL of the .kmx file for the package
public let kmxFileUrl: URL
// a key to uniquely identify the keyboard
// in the UserDefaults this key is used for the selected Keyboard and enabled keyboards properties
// the key is in the form "/[package directory]/[package name].kmx"
// for example, "/khmer_angkor/khmer_angkor.kmx"
public let keyboardKey: String
public init(keyboardSource: KeyboardSource, directoryUrl: URL) {
self.enabled = true
self.name = keyboardSource.name
self.keyboardId = keyboardSource.id
self.keyboardDirectoryUrl = directoryUrl
self.kmxFileUrl = Keyboard.deriveKmxFileUrl(from: self.keyboardDirectoryUrl, keyboardId: self.keyboardId)
self.keyboardKey = Keyboard.deriveKeyboardSettingsKey(from: self.keyboardDirectoryUrl, keyboardId: self.keyboardId)
// print("keyboard created for: \(keyboardSource.id) \r with kmxFileUrl: \(self.kmxFileUrl) \r and settingsKey: \(self.keyboardKey)")
}
/**
* initializer that does not rely on package source -- provided to create unit test data
*/
public init(name: String, keyboardId: String, keyboardDirectoryUrl: URL, enabled: Bool) {
self.name = name
self.keyboardId = keyboardId
self.keyboardDirectoryUrl = keyboardDirectoryUrl
self.kmxFileUrl = Keyboard.deriveKmxFileUrl(from: self.keyboardDirectoryUrl, keyboardId: self.keyboardId)
self.enabled = enabled
self.keyboardKey = Keyboard.deriveKeyboardSettingsKey(from: self.keyboardDirectoryUrl, keyboardId: self.keyboardId)
}
/**
* provided for Equatable conformance
*/
public static func == (lhs: Keyboard, rhs: Keyboard) -> Bool {
return lhs.keyboardId == rhs.keyboardId && lhs.enabled == rhs.enabled
}
/**
* provided for Hashable conformance
*/
public func hash(into hasher: inout Hasher) {
hasher.combine(keyboardId)
}
/**
* generate the url for the keyboard's kmx file
*/
static func deriveKmxFileUrl(from keyboardDirectory: URL, keyboardId: String) -> URL {
return keyboardDirectory.appendingPathComponent("\(keyboardId).kmx")
}
/**
* generate the keyboard's key
* see the above comment for `keyboardKey` for a description of the format of the key
*/
static func deriveKeyboardSettingsKey(from keyboardDirectory: URL, keyboardId: String) -> String {
// get parent directory
let parentDirectoryName = keyboardDirectory.lastPathComponent
// get filename from keyboardId
let kmxFilename = "\(keyboardId).kmx"
let settingsKey = "/\(parentDirectoryName)/\(kmxFilename)"
return settingsKey
}
/**
* validate whether a corresponding kmx file exists for this keyboard
*/
public func validateKmxFile() throws {
if !FileManager.default.fileExists(atPath: self.kmxFileUrl.path) {
print("** error: could not find kmx file \(self.kmxFileUrl.path)")
throw LoadPackageError.missingKmxFile
}
}
}