Main // Use IME module to manage (+un)installation, etc.
This commit is contained in:
parent
3ccaa5260b
commit
d2b096c35e
|
@ -22,15 +22,19 @@ import Cocoa
|
|||
|
||||
static let dlgOpenPath = NSOpenPanel();
|
||||
|
||||
// MARK: - Functions
|
||||
|
||||
// Print debug information to the console.
|
||||
// MARK: - Print debug information to the console.
|
||||
@objc static func prtDebugIntel(_ strPrint: String) {
|
||||
if mgrPrefs.isDebugModeEnabled {
|
||||
NSLog("vChewingErrorCallback: %@", strPrint)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Tell whether this IME is running with Root privileges.
|
||||
@objc static var isSudoMode: Bool {
|
||||
NSUserName() == "root"
|
||||
}
|
||||
|
||||
// MARK: - Initializing Language Models.
|
||||
@objc static func initLangModels(userOnly: Bool) {
|
||||
if !userOnly {
|
||||
mgrLangModel.loadDataModels() // 這句還是不要砍了。
|
||||
|
@ -43,6 +47,7 @@ import Cocoa
|
|||
mgrLangModel.loadUserAssociatedPhrases()
|
||||
}
|
||||
|
||||
// MARK: - System Dark Mode Status Detector.
|
||||
@objc static func isDarkMode() -> Bool {
|
||||
if #available(macOS 10.15, *) {
|
||||
let appearanceDescription = NSApplication.shared.effectiveAppearance.debugDescription.lowercased()
|
||||
|
@ -58,4 +63,106 @@ import Cocoa
|
|||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// MARK: - Trash a file if it exists.
|
||||
@discardableResult static func trashTargetIfExists(_ path: String) -> Bool {
|
||||
do {
|
||||
if FileManager.default.fileExists(atPath: path) {
|
||||
// 塞入垃圾桶
|
||||
try FileManager.default.trashItem(at: URL(fileURLWithPath: path), resultingItemURL: nil)
|
||||
} else {
|
||||
NSLog("Item doesn't exist: \(path)")
|
||||
}
|
||||
} catch let error as NSError {
|
||||
NSLog("Failed from removing this object: \(path) || Error: \(error)")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
// MARK: - Uninstalling the input method.
|
||||
@discardableResult static func uninstall(isSudo: Bool = false, selfKill: Bool = true) -> Int32 {
|
||||
// 輸入法自毀處理。這裡不用「Bundle.main.bundleURL」是為了方便使用者以 sudo 身分來移除被錯誤安裝到系統目錄內的輸入法。
|
||||
guard let bundleID = Bundle.main.bundleIdentifier else {
|
||||
NSLog("Failed to ensure the bundle identifier.")
|
||||
return -1
|
||||
}
|
||||
|
||||
let kTargetBin = "vChewing"
|
||||
let kTargetBundle = "/vChewing.app"
|
||||
let pathLibrary = isSudo ? "/Library" : FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask)[0].path
|
||||
let pathIMELibrary = isSudo ? "/Library/Input Methods" : FileManager.default.urls(for: .inputMethodsDirectory, in: .userDomainMask)[0].path
|
||||
let pathUnitKeyboardLayouts = "/Keyboard Layouts"
|
||||
let arrKeyLayoutFiles = ["/vChewing ETen.keylayout", "/vChewingKeyLayout.bundle", "/vChewing MiTAC.keylayout", "/vChewing IBM.keylayout", "/vChewing FakeSeigyou.keylayout", "/vChewing Dachen.keylayout"]
|
||||
|
||||
// 先移除各種鍵盤佈局。
|
||||
for objPath in arrKeyLayoutFiles {
|
||||
let objFullPath = pathLibrary + pathUnitKeyboardLayouts + objPath
|
||||
if !IME.trashTargetIfExists(objFullPath) { return -1 }
|
||||
}
|
||||
if CommandLine.arguments.count > 2 && CommandLine.arguments[2] == "--all" && CommandLine.arguments[1] == "uninstall" {
|
||||
// 再處理是否需要移除放在預設使用者資料夾內的檔案的情況。
|
||||
// 如果使用者有在輸入法偏好設定內將該目錄改到別的地方(而不是用 symbol link)的話,則不處理。
|
||||
// 目前暫時無法應對 symbol link 的情況。
|
||||
IME.trashTargetIfExists(mgrLangModel.dataFolderPath(isDefaultFolder: true))
|
||||
IME.trashTargetIfExists(pathLibrary + "/Preferences/" + bundleID + ".plist") // 之後移除 App 偏好設定
|
||||
}
|
||||
if !IME.trashTargetIfExists(pathIMELibrary + kTargetBundle) { return -1 } // 最後移除 App 自身
|
||||
// 幹掉殘留在記憶體內的執行緒。
|
||||
if selfKill {
|
||||
let killTask = Process()
|
||||
killTask.launchPath = "/usr/bin/killall"
|
||||
killTask.arguments = ["-9", kTargetBin]
|
||||
killTask.launch()
|
||||
killTask.waitUntilExit()
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// MARK: - Registering the input method.
|
||||
@discardableResult static func registerInputMethod() -> Int32 {
|
||||
guard let bundleID = Bundle.main.bundleIdentifier else {
|
||||
return -1
|
||||
}
|
||||
let bundleUrl = Bundle.main.bundleURL
|
||||
var maybeInputSource = InputSourceHelper.inputSource(for: bundleID)
|
||||
|
||||
if maybeInputSource == nil {
|
||||
NSLog("Registering input source \(bundleID) at \(bundleUrl.absoluteString)");
|
||||
// then register
|
||||
let status = InputSourceHelper.registerTnputSource(at: bundleUrl)
|
||||
|
||||
if !status {
|
||||
NSLog("Fatal error: Cannot register input source \(bundleID) at \(bundleUrl.absoluteString).")
|
||||
return -1
|
||||
}
|
||||
|
||||
maybeInputSource = InputSourceHelper.inputSource(for: bundleID)
|
||||
}
|
||||
|
||||
guard let inputSource = maybeInputSource else {
|
||||
NSLog("Fatal error: Cannot find input source \(bundleID) after registration.")
|
||||
return -1
|
||||
}
|
||||
|
||||
if !InputSourceHelper.inputSourceEnabled(for: inputSource) {
|
||||
NSLog("Enabling input source \(bundleID) at \(bundleUrl.absoluteString).")
|
||||
let status = InputSourceHelper.enable(inputSource: inputSource)
|
||||
if !status {
|
||||
NSLog("Fatal error: Cannot enable input source \(bundleID).")
|
||||
return -1
|
||||
}
|
||||
if !InputSourceHelper.inputSourceEnabled(for: inputSource) {
|
||||
NSLog("Fatal error: Cannot enable input source \(bundleID).")
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
if CommandLine.arguments.count > 2 && CommandLine.arguments[2] == "--all" {
|
||||
let enabled = InputSourceHelper.enableAllInputMode(for: bundleID)
|
||||
NSLog(enabled ? "All input sources enabled for \(bundleID)" : "Cannot enable all input sources for \(bundleID), but this is ignored")
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -20,56 +20,15 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR TH
|
|||
import Cocoa
|
||||
import InputMethodKit
|
||||
|
||||
private func install() -> Int32 {
|
||||
guard let bundleID = Bundle.main.bundleIdentifier else {
|
||||
return -1
|
||||
}
|
||||
let bundleUrl = Bundle.main.bundleURL
|
||||
var maybeInputSource = InputSourceHelper.inputSource(for: bundleID)
|
||||
|
||||
if maybeInputSource == nil {
|
||||
NSLog("Registering input source \(bundleID) at \(bundleUrl.absoluteString)");
|
||||
// then register
|
||||
let status = InputSourceHelper.registerTnputSource(at: bundleUrl)
|
||||
|
||||
if !status {
|
||||
NSLog("Fatal error: Cannot register input source \(bundleID) at \(bundleUrl.absoluteString).")
|
||||
return -1
|
||||
}
|
||||
|
||||
maybeInputSource = InputSourceHelper.inputSource(for: bundleID)
|
||||
}
|
||||
|
||||
guard let inputSource = maybeInputSource else {
|
||||
NSLog("Fatal error: Cannot find input source \(bundleID) after registration.")
|
||||
return -1
|
||||
}
|
||||
|
||||
if !InputSourceHelper.inputSourceEnabled(for: inputSource) {
|
||||
NSLog("Enabling input source \(bundleID) at \(bundleUrl.absoluteString).")
|
||||
let status = InputSourceHelper.enable(inputSource: inputSource)
|
||||
if !status {
|
||||
NSLog("Fatal error: Cannot enable input source \(bundleID).")
|
||||
return -1
|
||||
}
|
||||
if !InputSourceHelper.inputSourceEnabled(for: inputSource) {
|
||||
NSLog("Fatal error: Cannot enable input source \(bundleID).")
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
if CommandLine.arguments.count > 2 && CommandLine.arguments[2] == "--all" {
|
||||
let enabled = InputSourceHelper.enableAllInputMode(for: bundleID)
|
||||
NSLog(enabled ? "All input sources enabled for \(bundleID)" : "Cannot enable all input sources for \(bundleID), but this is ignored")
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
let kConnectionName = "vChewing_1_Connection"
|
||||
|
||||
if CommandLine.arguments.count > 1 {
|
||||
if CommandLine.arguments[1] == "install" {
|
||||
let exitCode = install()
|
||||
let exitCode = IME.registerInputMethod()
|
||||
exit(exitCode)
|
||||
}
|
||||
if CommandLine.arguments[1] == "uninstall" {
|
||||
let exitCode = IME.uninstall(isSudo: IME.isSudoMode)
|
||||
exit(exitCode)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue