Skip to content

hide candidate in librime#1115

Merged
lotem merged 1 commit intorime:masterfrom
MokOopsing:master
Jan 2, 2026
Merged

hide candidate in librime#1115
lotem merged 1 commit intorime:masterfrom
MokOopsing:master

Conversation

@MokOopsing
Copy link
Contributor

@MokOopsing MokOopsing commented Dec 25, 2025

Pull request

Issue tracker

Fixes will automatically close the related issue

Fixes #1112

Feature

This pull request introduces the ability to control whether the candidate list is displayed through a Rime option (_hide_candidate).

When the option _hide_candidate is enabled, Rime sets num_candidates to 0. once the frontends like squirrel and weasel detect that num_candidates is 0, they will skip populating and showing the candidate list, allowing users or schemas to dynamically hide candidates without relying on theme configuration.

Unit test

  • Done

Manual test

  • Done

Code Review

  1. Unit and manual test pass
  2. GitHub Action CI pass
  3. At least one contributor reviews and votes
  4. Can be merged clean without conflicts
  5. PR will be merged by rebase upstream base

Additional Info

@lotem
Copy link
Member

lotem commented Dec 25, 2025

真是執着啊。

@fxliang
Copy link
Contributor

fxliang commented Dec 27, 2025

这样还是不够环保

可能这样?将每次RimeGetContext里的高频操作改成ctx->set_option的低频操作,代价是context要多一个成员

diff --git a/src/rime/context.cc b/src/rime/context.cc
index ec840a3e..4a976e8a 100644
--- a/src/rime/context.cc
+++ b/src/rime/context.cc
@@ -284,6 +284,8 @@ void Context::set_input(const string& value) {
 }
 
 void Context::set_option(const string& name, bool value) {
+  if (name == "_hide_candidate")
+    is_hide_candidate_on_ = value;
   options_[name] = value;
   DLOG(INFO) << "Context::set_option " << name << " = " << value;
   option_update_notifier_(this, name);
diff --git a/src/rime/context.h b/src/rime/context.h
index d5261300..2820c95f 100644
--- a/src/rime/context.h
+++ b/src/rime/context.h
@@ -81,6 +81,7 @@ class RIME_DLL Context {
   // options and properties starting with '_' are local to schema;
   // others are session scoped.
   void ClearTransientOptions();
+  bool is_hide_candidate_on() const { return is_hide_candidate_on_; }
 
   Notifier& commit_notifier() { return commit_notifier_; }
   Notifier& select_notifier() { return select_notifier_; }
@@ -104,6 +105,7 @@ class RIME_DLL Context {
   CommitHistory commit_history_;
   map<string, bool> options_;
   map<string, string> properties_;
+  bool is_hide_candidate_on_ = false;
 
   Notifier commit_notifier_;
   Notifier select_notifier_;
diff --git a/src/rime_api_impl.h b/src/rime_api_impl.h
index 6e906cfe..94fce741 100644
--- a/src/rime_api_impl.h
+++ b/src/rime_api_impl.h
@@ -247,8 +247,11 @@ RIME_DEPRECATED Bool RimeGetContext(RimeSessionId session_id,
       context->menu.page_no = page_no;
       context->menu.is_last_page = Bool(page->is_last_page);
       context->menu.highlighted_candidate_index = selected_index % page_size;
+      context->menu.num_candidates =
+          ctx->is_hide_candidate_on() ? 0 : page->candidates.size();
+      if (ctx->is_hide_candidate_on())
+        return True;
       int i = 0;
-      context->menu.num_candidates = page->candidates.size();
       context->menu.candidates = new RimeCandidate[page->candidates.size()];
       for (const an<Candidate>& cand : page->candidates) {
         RimeCandidate* dest = &context->menu.candidates[i++];

@jimmy54
Copy link
Contributor

jimmy54 commented Dec 30, 2025

这个不应该是前端的能力嘛?真要放到librime里面嘛?

@jimmy54
Copy link
Contributor

jimmy54 commented Dec 30, 2025

如果真想实现是不是自己写个lua的filter呢。

@lotem
Copy link
Member

lotem commented Dec 30, 2025

这个不应该是前端的能力嘛?真要放到librime里面嘛?

確實是前端的功能。
在 librime 裏做不會浪費——就沒有必要填候選信息了。又能無需修改全面支持各種前端。
現在傾向於這個做法。
核心關注是不影響正常顯示候選,減少額外開銷。

@lotem
Copy link
Member

lotem commented Dec 30, 2025

这样还是不够环保

可能这样?将每次RimeGetContext里的高频操作改成ctx->set_option的低频操作,代价是context要多一个成员

diff --git a/src/rime/context.cc b/src/rime/context.cc
index ec840a3e..4a976e8a 100644
--- a/src/rime/context.cc
+++ b/src/rime/context.cc
@@ -284,6 +284,8 @@ void Context::set_input(const string& value) {
 }
 
 void Context::set_option(const string& name, bool value) {
+  if (name == "_hide_candidate")
+    is_hide_candidate_on_ = value;
   options_[name] = value;
   DLOG(INFO) << "Context::set_option " << name << " = " << value;
   option_update_notifier_(this, name);
diff --git a/src/rime/context.h b/src/rime/context.h
index d5261300..2820c95f 100644
--- a/src/rime/context.h
+++ b/src/rime/context.h
@@ -81,6 +81,7 @@ class RIME_DLL Context {
   // options and properties starting with '_' are local to schema;
   // others are session scoped.
   void ClearTransientOptions();
+  bool is_hide_candidate_on() const { return is_hide_candidate_on_; }
 
   Notifier& commit_notifier() { return commit_notifier_; }
   Notifier& select_notifier() { return select_notifier_; }
@@ -104,6 +105,7 @@ class RIME_DLL Context {
   CommitHistory commit_history_;
   map<string, bool> options_;
   map<string, string> properties_;
+  bool is_hide_candidate_on_ = false;
 
   Notifier commit_notifier_;
   Notifier select_notifier_;
diff --git a/src/rime_api_impl.h b/src/rime_api_impl.h
index 6e906cfe..94fce741 100644
--- a/src/rime_api_impl.h
+++ b/src/rime_api_impl.h
@@ -247,8 +247,11 @@ RIME_DEPRECATED Bool RimeGetContext(RimeSessionId session_id,
       context->menu.page_no = page_no;
       context->menu.is_last_page = Bool(page->is_last_page);
       context->menu.highlighted_candidate_index = selected_index % page_size;
+      context->menu.num_candidates =
+          ctx->is_hide_candidate_on() ? 0 : page->candidates.size();
+      if (ctx->is_hide_candidate_on())
+        return True;
       int i = 0;
-      context->menu.num_candidates = page->candidates.size();
       context->menu.candidates = new RimeCandidate[page->candidates.size()];
       for (const an<Candidate>& cand : page->candidates) {
         RimeCandidate* dest = &context->menu.candidates[i++];

不要吧,雖然優化了,但這樣寫容易亂。


我考慮呢,想再漂亮一點,就定義一個 UiOptions 結構體,把 _horizontal 之類都放進去,偵聽 option_update_notifier 更新;供 rime_api 以及 navigator 等組件訪問。

Copy link
Member

@lotem lotem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@MokOopsing
Copy link
Contributor Author

这样还是不够环保
可能这样?将每次RimeGetContext里的高频操作改成ctx->set_option的低频操作,代价是context要多一个成员

diff --git a/src/rime/context.cc b/src/rime/context.cc
index ec840a3e..4a976e8a 100644
--- a/src/rime/context.cc
+++ b/src/rime/context.cc
@@ -284,6 +284,8 @@ void Context::set_input(const string& value) {
 }
 
 void Context::set_option(const string& name, bool value) {
+  if (name == "_hide_candidate")
+    is_hide_candidate_on_ = value;
   options_[name] = value;
   DLOG(INFO) << "Context::set_option " << name << " = " << value;
   option_update_notifier_(this, name);
diff --git a/src/rime/context.h b/src/rime/context.h
index d5261300..2820c95f 100644
--- a/src/rime/context.h
+++ b/src/rime/context.h
@@ -81,6 +81,7 @@ class RIME_DLL Context {
   // options and properties starting with '_' are local to schema;
   // others are session scoped.
   void ClearTransientOptions();
+  bool is_hide_candidate_on() const { return is_hide_candidate_on_; }
 
   Notifier& commit_notifier() { return commit_notifier_; }
   Notifier& select_notifier() { return select_notifier_; }
@@ -104,6 +105,7 @@ class RIME_DLL Context {
   CommitHistory commit_history_;
   map<string, bool> options_;
   map<string, string> properties_;
+  bool is_hide_candidate_on_ = false;
 
   Notifier commit_notifier_;
   Notifier select_notifier_;
diff --git a/src/rime_api_impl.h b/src/rime_api_impl.h
index 6e906cfe..94fce741 100644
--- a/src/rime_api_impl.h
+++ b/src/rime_api_impl.h
@@ -247,8 +247,11 @@ RIME_DEPRECATED Bool RimeGetContext(RimeSessionId session_id,
       context->menu.page_no = page_no;
       context->menu.is_last_page = Bool(page->is_last_page);
       context->menu.highlighted_candidate_index = selected_index % page_size;
+      context->menu.num_candidates =
+          ctx->is_hide_candidate_on() ? 0 : page->candidates.size();
+      if (ctx->is_hide_candidate_on())
+        return True;
       int i = 0;
-      context->menu.num_candidates = page->candidates.size();
       context->menu.candidates = new RimeCandidate[page->candidates.size()];
       for (const an<Candidate>& cand : page->candidates) {
         RimeCandidate* dest = &context->menu.candidates[i++];

不要吧,雖然優化了,但這樣寫容易亂。

我考慮呢,想再漂亮一點,就定義一個 UiOptions 結構體,把 _horizontal 之類都放進去,偵聽 option_update_notifier 更新;供 rime_api 以及 navigator 等組件訪問。

改动太多,您亲自操刀吧,加入experimental分支,我来测试

@lotem lotem merged commit 2350b77 into rime:master Jan 2, 2026
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

盲選模式:不顯示候選字

4 participants