From d8794f8fd6b3d525f6130633f515e06b5caa3032 Mon Sep 17 00:00:00 2001 From: Parsifa1 Date: Sun, 21 Sep 2025 21:55:23 +0800 Subject: [PATCH] feat(Squirrel cli): add --ascii --nascii --getascii --- sources/Main.swift | 34 ++++++++++++++++ sources/SquirrelApplicationDelegate.swift | 17 ++++++++ sources/SquirrelInputController.swift | 47 +++++++++++++++++++++++ 3 files changed, 98 insertions(+) diff --git a/sources/Main.swift b/sources/Main.swift index dca533ba3..cb2d56e2d 100644 --- a/sources/Main.swift +++ b/sources/Main.swift @@ -80,6 +80,37 @@ struct SquirrelApp { case "--sync": DistributedNotificationCenter.default().postNotificationName(.init("SquirrelSyncNotification"), object: nil) return true + case "--ascii": + DistributedNotificationCenter.default().postNotificationName(.init("SquirrelToggleASCIIModeNotification"), object: "ascii") + return true + case "--nascii": + DistributedNotificationCenter.default().postNotificationName(.init("SquirrelToggleASCIIModeNotification"), object: "nascii") + return true + case "--getascii": + var responseReceived = false + var asciiStatus = "" + let observer = DistributedNotificationCenter.default().addObserver( + forName: .init("SquirrelASCIIModeResponse"), + object: nil, + queue: .main + ) { notification in + if let status = notification.object as? String { + asciiStatus = status + responseReceived = true + } + } + DistributedNotificationCenter.default().postNotificationName(.init("SquirrelGetASCIIModeNotification"), object: nil) + let timeout = Date().addingTimeInterval(2.0) + while !responseReceived && Date() < timeout { + RunLoop.current.run(until: Date().addingTimeInterval(0.01)) + } + DistributedNotificationCenter.default().removeObserver(observer) + if responseReceived { + print(asciiStatus) + } else { + print("nascii") + } + return true case "--help": print(helpDoc) return true @@ -139,6 +170,9 @@ Perform actions: --reload deploy --sync sync user data --build build all schemas in current directory + --ascii turn on ASCII mode + --nascii turn off ASCII mode + --getascii get current ASCII mode status Install Squirrel: --install, --register-input-source register input source --enable-input-source [source id...] input source list optional diff --git a/sources/SquirrelApplicationDelegate.swift b/sources/SquirrelApplicationDelegate.swift index c60376040..3e111569f 100644 --- a/sources/SquirrelApplicationDelegate.swift +++ b/sources/SquirrelApplicationDelegate.swift @@ -225,6 +225,8 @@ final class SquirrelApplicationDelegate: NSObject, NSApplicationDelegate, SPUSta let notifCenter = DistributedNotificationCenter.default() notifCenter.addObserver(forName: .init("SquirrelReloadNotification"), object: nil, queue: nil, using: rimeNeedsReload) notifCenter.addObserver(forName: .init("SquirrelSyncNotification"), object: nil, queue: nil, using: rimeNeedsSync) + notifCenter.addObserver(forName: .init("SquirrelToggleASCIIModeNotification"), object: nil, queue: nil, using: rimeToggleASCIIMode) + notifCenter.addObserver(forName: .init("SquirrelGetASCIIModeNotification"), object: nil, queue: nil, using: rimeGetASCIIMode) } func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply { @@ -307,6 +309,21 @@ private extension SquirrelApplicationDelegate { self.syncUserData() } + func rimeToggleASCIIMode(_ notification: Notification) { + guard let mode = notification.object as? String else { return } + let enableASCII = mode == "ascii" + + if enableASCII { + NotificationCenter.default.post(name: .init("SquirrelSetASCIIModeNotification"), object: true) + } else { + NotificationCenter.default.post(name: .init("SquirrelSetASCIIModeNotification"), object: false) + } + } + + func rimeGetASCIIMode(_: Notification) { + NotificationCenter.default.post(name: .init("SquirrelReportASCIIModeNotification"), object: nil) + } + func createDirIfNotExist(path: URL) { let fileManager = FileManager.default if !fileManager.fileExists(atPath: path.path()) { diff --git a/sources/SquirrelInputController.swift b/sources/SquirrelInputController.swift index bad53d9f1..f87f58ed8 100644 --- a/sources/SquirrelInputController.swift +++ b/sources/SquirrelInputController.swift @@ -189,6 +189,26 @@ final class SquirrelInputController: IMKInputController { // print("[DEBUG] initWithServer: \(server ?? .init()) delegate: \(delegate ?? "nil") client:\(client ?? "nil")") super.init(server: server, delegate: delegate, client: client) createSession() + + // Listen for ASCII mode toggle notifications + NotificationCenter.default.addObserver( + forName: .init("SquirrelSetASCIIModeNotification"), + object: nil, + queue: nil + ) { [weak self] notification in + self?.handleASCIIModeToggle(notification) + } + + // Listen for ASCII mode status requests + NotificationCenter.default.addObserver( + forName: .init("SquirrelReportASCIIModeNotification"), + object: nil, + queue: nil + ) { [weak self] notification in + self?.reportASCIIMode(notification) + } + + } override func deactivateServer(_ sender: Any!) { @@ -589,4 +609,31 @@ private extension SquirrelInputController { highlighted: highlighted, page: page, lastPage: lastPage, update: true) } } + + private func handleASCIIModeToggle(_ notification: Notification) { + guard let enableASCII = notification.object as? Bool else { return } + guard session != 0 && rimeAPI.find_session(session) else { return } + + rimeAPI.set_option(session, "ascii_mode", enableASCII) + + // Force update the UI to reflect the mode change + rimeUpdate() + } + + private func reportASCIIMode(_: Notification) { + // Only active input controller should respond + guard let client = client else { return } + guard session != 0 && rimeAPI.find_session(session) else { return } + + let isASCIIMode = rimeAPI.get_option(session, "ascii_mode") + let status = isASCIIMode ? "ascii" : "nascii" + + // Directly respond with the status + DistributedNotificationCenter.default().postNotificationName( + .init("SquirrelASCIIModeResponse"), + object: status + ) + } + + }