PrefMgr // Add ability to dump pref data as a shell script.
This commit is contained in:
parent
238845fb1d
commit
82dea233b6
|
@ -8,6 +8,7 @@
|
|||
|
||||
import InputMethodKit
|
||||
import Shared
|
||||
import SwiftExtension
|
||||
import SwiftUI
|
||||
|
||||
// MARK: ObservableProject.
|
||||
|
@ -68,3 +69,75 @@ public extension PrefMgr {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Print share-safe UserDefaults into a bunch of "defaults write" commands.
|
||||
|
||||
public extension PrefMgr {
|
||||
@discardableResult func dumpShellScriptBackup() -> String? {
|
||||
let mirror = Mirror(reflecting: PrefMgr.shared)
|
||||
guard let bundleIdentifier = Bundle.main.bundleIdentifier else { return nil }
|
||||
let strDoubleDashLine = String(String(repeating: "=", count: 70))
|
||||
let consoleOutput = NSMutableString(string: "#!/bin/sh\n\n")
|
||||
consoleOutput.append("# \(strDoubleDashLine)\n")
|
||||
consoleOutput.append("# vChewing Preferences Migration Script\n")
|
||||
consoleOutput.append("# - vChewing IME v\(IMEApp.appVersionLabel)\n")
|
||||
consoleOutput.append("# \(strDoubleDashLine)\n\n")
|
||||
for case let (_, value) in mirror.children {
|
||||
// 為了讓接下來的命令抓到客體管理器的內容既存資料:
|
||||
let rawCells = "\(value)".replacingOccurrences(of: "String, Bool", with: "String,Bool").components(separatedBy: " ")
|
||||
guard rawCells.count >= 4 else { continue }
|
||||
let strKeyName = rawCells[1].dropLast(2).dropFirst(1).replacingOccurrences(of: "\n", with: "\\n")
|
||||
guard let theUserDef = UserDef(rawValue: strKeyName) else { continue }
|
||||
var strTypeParam = String(describing: theUserDef.dataType)
|
||||
// 忽略會被 Sandbox 擋到的選項、以及其他一些雜項。
|
||||
let blackList: [UserDef] = [
|
||||
.kUserDataFolderSpecified, .kCassettePath, .kAppleLanguages, .kFailureFlagForUOMObservation,
|
||||
.kMostRecentInputMode,
|
||||
]
|
||||
guard !blackList.contains(theUserDef) else { continue }
|
||||
var strValue = rawCells[3].dropLast(1).replacingOccurrences(of: "\n", with: "")
|
||||
typeCheck: switch theUserDef.dataType {
|
||||
case .double: strTypeParam = strTypeParam.replacingOccurrences(of: "double", with: "float")
|
||||
case .dictionary:
|
||||
if let valParsed = value as? AppProperty<[String: Bool]> {
|
||||
strTypeParam = strTypeParam.replacingOccurrences(of: "ionary", with: "")
|
||||
let stack = NSMutableString()
|
||||
valParsed.wrappedValue.forEach { currentPair in
|
||||
stack.append("\(currentPair.key) \(currentPair.value) ")
|
||||
}
|
||||
strValue = stack.replacingOccurrences(of: "\n", with: "\\n")
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
case .array:
|
||||
if let valParsed = value as? AppProperty<[String]> {
|
||||
strValue = valParsed.wrappedValue.joined(separator: " ")
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
case .other: continue // 忽略對終端機單行輸入不友好的選項。
|
||||
default: break typeCheck
|
||||
}
|
||||
if let metaData = theUserDef.metaData {
|
||||
let strDashLine = String(String(repeating: "-", count: 70))
|
||||
let texts: [String] = [
|
||||
strDashLine, metaData.shortTitle,
|
||||
strDashLine, metaData.prompt,
|
||||
metaData.popupPrompt, metaData.description, metaData.toolTip,
|
||||
].compactMap { $0 }.map(\.localized)
|
||||
texts.forEach { currentLines in
|
||||
currentLines.split(separator: "\n").forEach { currentLine in
|
||||
consoleOutput.append("# \(currentLine)\n")
|
||||
}
|
||||
}
|
||||
metaData.options?.sorted(by: { $0.key < $1.key }).forEach { pair in
|
||||
consoleOutput.append("# - \(pair.key): \(pair.value.localized)\n")
|
||||
}
|
||||
} else {
|
||||
consoleOutput.append("# No comments supplied by the engineer.\n")
|
||||
}
|
||||
consoleOutput.append("\ndefaults write \(bundleIdentifier) \(strKeyName) -\(strTypeParam) \(strValue)\n\n")
|
||||
}
|
||||
return consoleOutput.description
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue