From 43023e16d840e9cf5b11d66b1c3e426875b2dcfe Mon Sep 17 00:00:00 2001 From: InfinityLoop1309 <96324692+InfinityLoop1309@users.noreply.github.com> Date: Thu, 23 Jun 2022 22:02:35 +0800 Subject: [PATCH] feat: delete selected candidate (#557) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: delete selected candidate * chore: trivial code cleanup Co-authored-by: kedwjao <96324692+kedwjao@users.noreply.github.com> Co-authored-by: 居戎氏 --- src/rime/context.cc | 22 +++++++++++++--- src/rime/context.h | 2 ++ src/rime_api.cc | 63 +++++++++++++++++++++++++++++++-------------- src/rime_api.h | 4 +++ 4 files changed, 67 insertions(+), 24 deletions(-) diff --git a/src/rime/context.cc b/src/rime/context.cc index b8e64b5740..c3f62f2942 100644 --- a/src/rime/context.cc +++ b/src/rime/context.cc @@ -123,19 +123,33 @@ bool Context::Select(size_t index) { return false; } -bool Context::DeleteCurrentSelection() { +bool Context::DeleteCandidate( + function (Segment& seg)> get_candidate) { if (composition_.empty()) return false; Segment& seg(composition_.back()); - if (auto cand = seg.GetSelectedCandidate()) { - DLOG(INFO) << "Deleting: '" << cand->text() - << "', selected_index = " << seg.selected_index; + if (auto cand = get_candidate(seg)) { + DLOG(INFO) << "Deleting candidate: '" << cand->text(); delete_notifier_(this); return true; // CAVEAT: this doesn't mean anything is deleted for sure } return false; } +bool Context::DeleteCandidate(size_t index) { + return DeleteCandidate( + [index](Segment& seg) { + return seg.GetCandidateAt(index); + }); +} + +bool Context::DeleteCurrentSelection() { + return DeleteCandidate( + [](Segment& seg) { + return seg.GetSelectedCandidate(); + }); +} + bool Context::ConfirmCurrentSelection() { if (composition_.empty()) return false; diff --git a/src/rime/context.h b/src/rime/context.h index d8bc285c81..d624f02037 100644 --- a/src/rime/context.h +++ b/src/rime/context.h @@ -45,6 +45,7 @@ class Context { // return false if there is no candidate at index bool Select(size_t index); + bool DeleteCandidate(size_t index); // return false if there's no candidate for current segment bool ConfirmCurrentSelection(); bool DeleteCurrentSelection(); @@ -92,6 +93,7 @@ class Context { private: string GetSoftCursor() const; + bool DeleteCandidate(function(Segment& seg)> get_candidate); string input_; size_t caret_pos_ = 0; diff --git a/src/rime_api.cc b/src/rime_api.cc index 1c974139d9..edaf24bc27 100644 --- a/src/rime_api.cc +++ b/src/rime_api.cc @@ -938,38 +938,59 @@ size_t RimeGetCaretPos(RimeSessionId session_id) { return ctx->caret_pos(); } -Bool RimeSelectCandidate(RimeSessionId session_id, size_t index) { +static bool do_with_candidate(RimeSessionId session_id, size_t index, + bool (Context::* verb)(size_t index)) { an session(Service::instance().GetSession(session_id)); if (!session) - return False; - Context *ctx = session->context(); - if (!ctx) - return False; - return Bool(ctx->Select(index)); + return False; + Context *ctx = session->context(); + if (!ctx) + return False; + return (ctx->*verb)(index); } -Bool RimeSelectCandidateOnCurrentPage(RimeSessionId session_id, size_t index) { +static bool do_with_candidate_on_current_page( + RimeSessionId session_id, size_t index, + bool (Context::* verb)(size_t index)) { an session(Service::instance().GetSession(session_id)); if (!session) - return False; - Context *ctx = session->context(); - if (!ctx || !ctx->HasMenu()) - return False; - Schema *schema = session->schema(); - if (!schema) - return False; - size_t page_size = (size_t)schema->page_size(); - if (index >= page_size) - return False; - const auto& seg(ctx->composition().back()); - size_t page_start = seg.selected_index / page_size * page_size; - return Bool(ctx->Select(page_start + index)); + return False; + Context *ctx = session->context(); + if (!ctx || !ctx->HasMenu()) + return False; + Schema *schema = session->schema(); + if (!schema) + return False; + size_t page_size = (size_t)schema->page_size(); + if (index >= page_size) + return False; + const auto& seg(ctx->composition().back()); + size_t page_start = seg.selected_index / page_size * page_size; + return (ctx->*verb)(page_start + index); +} + + +Bool RimeSelectCandidate(RimeSessionId session_id, size_t index) { + return do_with_candidate(session_id, index, &Context::Select); +} + +Bool RimeSelectCandidateOnCurrentPage(RimeSessionId session_id, size_t index) { + return do_with_candidate_on_current_page(session_id, index, &Context::Select); } const char* RimeGetVersion() { return RIME_VERSION; } +Bool RimeDeleteCandidate(RimeSessionId session_id, size_t index) { + return do_with_candidate(session_id, index, &Context::DeleteCandidate); +} + +Bool RimeDeleteCandidateOnCurrentPage(RimeSessionId session_id, size_t index) { + return do_with_candidate_on_current_page( + session_id, index, &Context::DeleteCandidate); +} + void RimeSetCaretPos(RimeSessionId session_id, size_t caret_pos) { an session(Service::instance().GetSession(session_id)); if (!session) @@ -1115,6 +1136,8 @@ RIME_API RimeApi* rime_get_api() { s_api.context_proto = nullptr; s_api.status_proto = nullptr; s_api.get_state_label = &RimeGetStateLabel; + s_api.delete_candidate = &RimeDeleteCandidate; + s_api.delete_candidate_on_current_page = &RimeDeleteCandidateOnCurrentPage; } return &s_api; } diff --git a/src/rime_api.h b/src/rime_api.h index 91d8a02307..9975fc73e8 100644 --- a/src/rime_api.h +++ b/src/rime_api.h @@ -552,6 +552,10 @@ typedef struct rime_api_t { void (*status_proto)(RimeSessionId session_id, RIME_PROTO_BUILDER* status_builder); const char* (*get_state_label)(RimeSessionId session_id, const char *option_name, Bool state); + //! delete a candidate at the given index in candidate list. + Bool (*delete_candidate)(RimeSessionId session_id, size_t index); + //! delete a candidate from current page. + Bool (*delete_candidate_on_current_page)(RimeSessionId session_id, size_t index); } RimeApi; //! API entry