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
+ )
+ }
+
+
}