feat(ui): status bar icon reflects ascii_mode#1122
Conversation
Add an NSStatusItem that shows "中" when Squirrel is in Chinese input mode and "A" when ascii_mode is toggled on (e.g. via Shift). The icon auto-hides when the active input source is not Squirrel, driven by a kTISNotifySelectedKeyboardInputSourceChanged observer. The Rime notification handler is refactored to extract optionName so the ascii_mode toggle can drive the status icon update, without disturbing the existing schema / option notification paths. No changes to IMKInputController, its right-click menu, or system input source enablement. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
How to turn it off if user doesn't want an extra icon? |
|
有人說能用狀態圖標替換輸入法圖標,有這種 API 嗎? https://github.com/orgs/rime/discussions/1214#discussioncomment-16610551 |
|
|
||
| func applyStatusIcon(asciiMode: Bool) { | ||
| guard let button = statusItem?.button else { return } | ||
| button.title = asciiMode ? "A" : "中" |
There was a problem hiding this comment.
We can use get_state_label_abbreviated to display the status label defined in the input schema.
| delegate.updateStatusIcon(asciiMode: state) | ||
| } | ||
| // off | ||
| if !delegate.enableNotifications { |
There was a problem hiding this comment.
} else if delegate.enableNotifications {
// 顯示狀態消息框
}
| } | ||
|
|
||
| // off | ||
| if !delegate.enableNotifications { |
There was a problem hiding this comment.
if delegate.enableNotifications {
// 顯示狀態消息框
}
| optionName = nil | ||
| } | ||
| if optionName == "ascii_mode" { | ||
| delegate.updateStatusIcon(asciiMode: state) |
There was a problem hiding this comment.
在此測試狀態圖標開關選項。
若顯示狀態圖標,則無須顯示消息框,對吧?
There was a problem hiding this comment.
我觉得还是根据需要显示,不需要做成互斥的。
希望两个地方都可以有显示。
Add a new top-level boolean key in squirrel.yaml (default true) so users
can hide the 中/A menu-bar icon with a custom patch:
patch:
show_status_icon: false
Re-reads the value in loadSettings() and creates / removes the
NSStatusItem via refreshStatusItem(), so "Squirrel --reload" picks up
the toggle without relaunching.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
metalbreeze
left a comment
There was a problem hiding this comment.
我觉得还是根据需要显示,不需要做成互斥的。
我希望两个地方都可以有显示。
Previously the ascii_mode menu-bar icon hardcoded "A" / "中", ignoring each schema's own states: declaration (e.g. luna_pinyin_simp defines [中文, 西文]). This commit: 1. Calls get_state_label_abbreviated in the option-notification path and reuses the short label for the icon, so the icon respects the active schema's convention by default. 2. Adds two optional yaml keys, status_icon/ascii and status_icon/chinese, that let users pin compact single-character glyphs when the schema's label is too wide for the menu bar. Resolution order for the button title: user override -> schema short label -> hardcoded "A"/"中" fallback. Restructures the option-notification handler so the label fetch is shared between the icon and the status bubble -- the bubble remains generic (fires for any option when enableNotifications is on), while the icon is still gated to ascii_mode. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Before, the three status-icon settings had inconsistent styles:
show_status_icon: true (flat, underscored)
status_icon/ascii: A (subtree, slashed)
status_icon/chinese: 中 (subtree, slashed)
Unify under one status_icon/ subtree, matching Rime's convention for
grouped settings (ascii_composer/switch_key, key_binder/bindings, ...):
status_icon:
show: true
ascii: A
chinese: 中
show_status_icon was only introduced in the previous commit on this
feature branch (3dad524) and has not been released, so the rename is a
pure pre-merge cleanup with no user migration needed outside this PR.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
get_state_label_abbreviated returns a RimeStringSlice whose .str points
to a null-terminated C string but whose .length may be shorter — for
abbreviated=true without an explicit `abbrev:` field, librime clips
.length to the first Unicode character (see switches.cc
first_unicode_byte_length).
The Swift side was using String(cString: slice.str), which ignores
.length and reads to the null terminator. As a result:
- The "short" label for ascii_mode on luna_pinyin_simp
(states: [中文, 西文]) came through as "中文" / "西文" instead of
the intended "中" / "西".
- The menu-bar icon, which defaults to this short label when no
user override is set, showed "中文" / "西文" taking up far more
menu-bar space than a status glyph should.
Add a private RimeStringSlice.asString that constructs a Swift String
from Data(bytes:count:) using the slice's own length, and switch both
notificationHandler conversions (long + short) to use it. The long path
is unchanged in behavior (long always has full length) but now goes
through the same helper for consistency.
After this fix the icon, with default config on luna_pinyin_simp, will
correctly show "中" / "西" — no user override needed.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
很抱歉,我以爲 get_state_label_abbreviated 能直接從方案裏得到「中」「A」,當時這個 API 是設計爲這樣用的,但需要在方案中設定好,如這份測試方案 我驚覺主要的方案都還沒有把 ascii_mode 的文字更新爲「ABC」,因此目前無法取得預想效果。 理想中,方案設定的短標籤應優先於全局配置,比如爲少數民族語文設計的輸入方案,就應當能換掉「中」字。 現在這麼複雜的代碼無法發揮作用。麻煩你改回在代碼裏寫定「中」「A」(要不要寫成全角的 以後可能要先在方案中普及「ABC」標籤,再切換到 |
The reviewer asked to drop the schema-label complexity in favour of hardcoded glyphs, since mainstream schemas don't yet declare `abbrev:` for ascii_mode and so `get_state_label_abbreviated` returns wide labels like "中文" / "西文" that are unsuitable for a menu-bar glyph. Take a middle path that satisfies the simplification request without giving up forward compatibility: - Drop the user-facing `status_icon/ascii` and `status_icon/chinese` config keys (and the cached instance properties that backed them). - Drop the `RimeStringSlice.asString` length-aware helper from the prior commit. `String(cString:)` reads `.str` to its null terminator, which gives the correct abbrev for schemas that declare it (the reviewer's referenced `librime/data/minimal/luna_pinyin.schema.yaml` has `abbrev: [中, A]` -> `.str` is "中\0" -> reads "中") and the full `states:` value otherwise. No client-side slicing necessary. - Hardcode the fallback at full-width "中" / "A" (per reviewer suggestion) for schemas that don't define `states:` at all. - Keep the `status_icon/show` subtree key untouched. Net effect: schemas that declare `abbrev: [中, A]` get compact glyphs for free; schemas that don't see their `states:` value as-is and can opt into compactness by adding `abbrev:` themselves; the codebase no longer carries the per-state config knobs the reviewer rejected. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
感謝仔細評審。已按你的建議簡化:
有一處細節想聽聽你的意見:注意到你引用的 所以我保留了「讀取方案 short state label」這條通路,但沒在客戶端做 這樣代碼比之前簡單很多,方案以後逐步添加 |
Summary
NSStatusItemthat shows中when Squirrel is in Chinese mode andAwhenascii_modeis on, driven by the Rime option-change notification.kTISNotifySelectedKeyboardInputSourceChangedobserver.optionbranch of the Rime notification handler sooptionNamecan be extracted and fed to the status-icon update, preserving existing schema/option paths.SquirrelInstaller.currentInputSourceID()added for the visibility check.Notes for reviewer
SquirrelInputController, its IMK right-click menu,Info.plist, or input source enablement logic.Test plan
make release)中while Squirrel is active in Chinese modeAwhile Squirrel is activeGenerated with Claude Code