From 873f648e9b5639f9a4a55a6875ac5cd0b27c73db Mon Sep 17 00:00:00 2001 From: Chen Gong Date: Sat, 5 Sep 2020 20:40:43 +0800 Subject: [PATCH] feat(api): implement capnproto api --- src/rime_api.cc | 100 +++++++++++++++++++++++++++++++++++++++++++ src/rime_api.h | 8 ++++ src/rime_proto.capnp | 4 +- 3 files changed, 111 insertions(+), 1 deletion(-) diff --git a/src/rime_api.cc b/src/rime_api.cc index d394b3329a..a9927a0818 100644 --- a/src/rime_api.cc +++ b/src/rime_api.cc @@ -322,6 +322,71 @@ RIME_API Bool RimeFreeContext(RimeContext* context) { return True; } +void RimeContextProto(RimeSessionId session_id, RIME_PROTO_BUILDER* context_builder) { + an session = Service::instance().GetSession(session_id); + if (!session) + return; + Context *ctx = session->context(); + if (!ctx) + return; + auto* context = (rime::proto::Context::Builder*)context_builder; + context->setInput(ctx->input()); + context->setCaretPos(ctx->caret_pos()); + if (ctx->IsComposing()) { + auto composition = context->getComposition(); + Preedit preedit = ctx->GetPreedit(); + composition.setLength(preedit.text.length()); + composition.setPreedit(preedit.text); + composition.setCursorPos(preedit.caret_pos); + composition.setSelStart(preedit.sel_start); + composition.setSelEnd(preedit.sel_end); + string commit_text = ctx->GetCommitText(); + if (!commit_text.empty()) { + composition.setCommitTextPreview(commit_text); + } + } + if (ctx->HasMenu()) { + auto menu = context->getMenu(); + Segment &seg = ctx->composition().back(); + Schema *schema = session->schema(); + int page_size = schema ? schema->page_size() : 5; + int selected_index = seg.selected_index; + int page_number = selected_index / page_size; + the page(seg.menu->CreatePage(page_size, page_number)); + if (page) { + menu.setPageSize(page_size); + menu.setPageNumber(page_number); + menu.setIsLastPage(page->is_last_page); + menu.setHighlightedCandidateIndex(selected_index % page_size); + auto dest_candidates = menu.initCandidates(page->candidates.size()); + auto dest = dest_candidates.begin(); + for (const an &src : page->candidates) { + dest->setText(src->text()); + string comment = src->comment(); + if (!comment.empty()) { + dest->setComment(comment); + } + ++dest; + } + if (schema) { + const string& select_keys = schema->select_keys(); + if (!select_keys.empty()) { + menu.setSelectKeys(select_keys); + } + Config* config = schema->config(); + an select_labels = config->GetList("menu/alternative_select_labels"); + if (select_labels && (size_t)page_size <= select_labels->size()) { + auto dest_select_labels = menu.initSelectLabels(page_size); + for (size_t i = 0; i < (size_t)page_size; ++i) { + an value = select_labels->GetValueAt(i); + dest_select_labels.set(i, value->str()); + } + } + } + } + } +} + RIME_API Bool RimeGetCommit(RimeSessionId session_id, RimeCommit* commit) { if (!commit) return False; @@ -347,6 +412,18 @@ RIME_API Bool RimeFreeCommit(RimeCommit* commit) { return True; } +void RimeCommitProto(RimeSessionId session_id, RIME_PROTO_BUILDER* commit_builder) { + an session(Service::instance().GetSession(session_id)); + if (!session) + return; + const string& commit_text(session->commit_text()); + if (!commit_text.empty()) { + auto* commit = (rime::proto::Commit::Builder*)commit_builder; + commit->setText(commit_text); + session->ResetCommitText(); + } +} + RIME_API Bool RimeGetStatus(RimeSessionId session_id, RimeStatus* status) { if (!status || status->data_size <= 0) return False; @@ -381,6 +458,26 @@ RIME_API Bool RimeFreeStatus(RimeStatus* status) { return True; } +void RimeStatusProto(RimeSessionId session_id, RIME_PROTO_BUILDER* status_builder) { + an session(Service::instance().GetSession(session_id)); + if (!session) + return; + Schema *schema = session->schema(); + Context *ctx = session->context(); + if (!schema || !ctx) + return; + auto* status = (rime::proto::Status::Builder*)status_builder; + status->setSchemaId(schema->schema_id()); + status->setSchemaName(schema->schema_name()); + status->setIsDisabled(Service::instance().disabled()); + status->setIsComposing(ctx->IsComposing()); + status->setIsAsciiMode(ctx->get_option("ascii_mode")); + status->setIsFullShape(ctx->get_option("full_shape")); + status->setIsSimplified(ctx->get_option("simplification")); + status->setIsTraditional(ctx->get_option("traditional")); + status->setIsAsciiPunct(ctx->get_option("ascii_punct")); +} + // Accessing candidate list RIME_API Bool RimeCandidateListFromIndex(RimeSessionId session_id, @@ -1067,6 +1164,9 @@ RIME_API RimeApi* rime_get_api() { s_api.candidate_list_from_index = &RimeCandidateListFromIndex; s_api.get_prebuilt_data_dir = &RimeGetPrebuiltDataDir; s_api.get_staging_dir = &RimeGetStagingDir; + s_api.commit_proto = &RimeCommitProto; + s_api.context_proto = &RimeContextProto; + s_api.status_proto = &RimeStatusProto; } return &s_api; } diff --git a/src/rime_api.h b/src/rime_api.h index 6f9664806c..1b6c324e7e 100644 --- a/src/rime_api.h +++ b/src/rime_api.h @@ -55,6 +55,9 @@ typedef int Bool; //! Define a variable of Type #define RIME_STRUCT(Type, var) Type var = {0}; RIME_STRUCT_INIT(Type, var); +//! For passing pointer to capnproto builder as opaque pointer through C API. +#define RIME_PROTO_BUILDER void + //! Rime traits structure /*! * Should be initialized by calling RIME_STRUCT_INIT(Type, var) @@ -542,6 +545,11 @@ typedef struct rime_api_t { const char* (*get_prebuilt_data_dir)(); //! staging directory, stores data files deployed to a Rime client. const char* (*get_staging_dir)(); + + //! capnproto API. + void (*commit_proto)(RimeSessionId session_id, RIME_PROTO_BUILDER* commit_builder); + void (*context_proto)(RimeSessionId session_id, RIME_PROTO_BUILDER* context_builder); + void (*status_proto)(RimeSessionId session_id, RIME_PROTO_BUILDER* status_builder); } RimeApi; //! API entry diff --git a/src/rime_proto.capnp b/src/rime_proto.capnp index 13941e6543..29782a7509 100644 --- a/src/rime_proto.capnp +++ b/src/rime_proto.capnp @@ -29,7 +29,7 @@ struct Context { struct Menu { # Menu of text candidates. pageSize @0 :Int32; - pageNo @1 :Int32; + pageNumber @1 :Int32; isLastPage @2 :Bool; highlightedCandidateIndex @3 :Int32; candidates @4 :List(Candidate); @@ -39,6 +39,8 @@ struct Context { composition @0 :Composition; menu @1 :Menu; + input @2 :Text; + caretPos @3 :Int32; } struct Status {