Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: delete selected candidate #556

Closed
wants to merge 1 commit into from
Closed

feat: delete selected candidate #556

wants to merge 1 commit into from

Conversation

InfinityLoop1308
Copy link
Contributor

@InfinityLoop1308 InfinityLoop1308 commented Jun 18, 2022

Pull request

Issue tracker

Fixes will automatically close the related issue

Fixes #

Feature

This feature supports deleting candidate at arbitrary index, which is useful for quick deleting.

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

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.

Thanks for the pull request.

The struct RimeApi can only be extended from the end for backward compatibility.
Sync the repo, and then add new API functions as the last members of the struct.

I also added a few suggestions about code style.

src/rime_api.cc Outdated
@@ -1083,6 +1083,34 @@ const char* RimeGetVersion() {
return RIME_VERSION;
}

Bool RimeDeleteCandidate(RimeSessionId session_id, size_t index) {
an<Session> session(Service::instance().GetSession(session_id));
Copy link
Member

Choose a reason for hiding this comment

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

avoid repeated code.

extract the common code to helper functions:

static bool do_with_candidate(RimeSessionId session_id, size_t index, bool (Context::* verb)(size_t index)) {
  // ...
  return (ctx->*verb)(index);
}

static bool do_with_candidate_on_current_page(RimeSessionId session_id, size_t index, bool (Context::* verb)(size_t index)) {
  // ...
  return (ctx->*verb)(page_start + index);
}

Then call the helper functions with &Context::Select or &Context::Delete in each version.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry but it turns out I have trouble using this syntax. It first throw error message with
/home/runner/work/trime/trime/app/src/main/jni/librime/src/rime_api.cc:1061:25: error: called object type 'bool

(rime::Context::*)(size_t)' is not a function or function pointer

return Bool(ctx->*verb(index));
                   ~~~~^

/home/runner/work/trime/trime/app/src/main/jni/librime/src/rime_api.cc:1083:53: error: use of undeclared identifier 'Select'; did you mean 'rime::Context::Select'?

return Bool(do_with_candidate(session_id, index, &Select));
                                                  ^~~~~~
                                                  rime::Context::Select

/home/runner/work/trime/trime/app/src/main/jni/librime/src/rime/context.h:47:8: note: 'rime::Context::Select' declared here

bool Select(size_t index);
     ^

and then after I change &Select to &rime::Context::Select it throw error message:

home/runner/work/trime/trime/app/src/main/jni/librime/src/rime_api.cc:1061:25: error: called object type 'bool (rime::Context::*)(size_t)' is not a function or function pointer

return Bool(ctx->*verb(index));
                  ~~~~^

1 error generated.

Copy link
Member

Choose a reason for hiding this comment

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

pointer to member function, if I recall correctly, need to be qualified by class name, try &Context::Select as in the original comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

pointer to member function, if I recall correctly, need to be qualified by class name, try &Context::Select as in the original comment.

it not works either.
I have changed to

Bool RimeSelectCandidate(RimeSessionId session_id, size_t index) {
return Bool(do_with_candidate(session_id, index, &Context::Select));
}

and got error message:

home/runner/work/trime/trime/app/src/main/jni/librime/src/rime_api.cc:1061:25: error: called object type 'bool (rime::Context::*)(size_t)' is not a function or function pointer
return Bool(ctx->*verb(index));

Copy link
Member

Choose a reason for hiding this comment

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

Sorry. It didn't work because .* or ->* has lower precedence than function call. So it should be written with parentheses around the expression ctx->*verb. See also my inline comments.

src/rime_api.h Outdated
@@ -520,6 +520,9 @@ typedef struct rime_api_t {
//! select a candidate at the given index in candidate list.
Bool (*select_candidate)(RimeSessionId session_id, size_t index);

//! delete a candidate at the given index in candidate list.
Bool (*delete_candidate)(RimeSessionId session_id, size_t index);
Copy link
Member

Choose a reason for hiding this comment

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

New API functions must be appended to the struct RimeApi.

@@ -123,6 +123,19 @@ bool Context::Select(size_t index) {
return false;
}

bool Context::Delete(size_t index) {
Copy link
Member

Choose a reason for hiding this comment

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

The name is unclear; it can be confused with deleting characters from the input.
Rename it DeleteCandidate.

Avoid repeated code.
Introduce a private member function (overloaded)

bool Context::DeleteCandidate(function<an<Candidate> (Segment& seg)> get_candidate) {
  // ...
  if (auto cand = get_candidate(seg)) {
  // ...
}

Then call it in each version:

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();
      });
}

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.

Thanks, PTAL

@@ -1170,9 +1186,11 @@ RIME_API RimeApi* rime_get_api() {
s_api.get_input = &RimeGetInput;
s_api.get_caret_pos = &RimeGetCaretPos;
s_api.select_candidate = &RimeSelectCandidate;
s_api.delete_candidate = &RimeDeleteCandidate;
Copy link
Member

Choose a reason for hiding this comment

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

Optional: reorder these to match definition in RimeApi.

@@ -550,6 +550,11 @@ typedef struct rime_api_t {
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);

Copy link
Member

Choose a reason for hiding this comment

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

Merge conflict. Sync the repo.

Copy link
Member

Choose a reason for hiding this comment

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

Sync to latest code.

@@ -123,19 +123,32 @@ bool Context::Select(size_t index) {
return false;
}

bool Context::DeleteCurrentSelection() {
bool Context::DeleteCandidate(function<an<Candidate> (Segment& seg)> get_candidate) {
Copy link
Member

Choose a reason for hiding this comment

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

This memeber function should have a definition in context.h, in the private: or pretected: section.

}

Bool RimeSelectCandidate(RimeSessionId session_id, size_t index) {
return do_with_candidate(session_id, index, Select);
Copy link
Member

@lotem lotem Jun 20, 2022

Choose a reason for hiding this comment

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

Prefer explicit conversion to the returned C type (Bool=int):
return Bool(do_with_candidate(...));

Prefer &Select to make it obvious we are passing a function pointer.

an<Session> session(Service::instance().GetSession(session_id));
if (!session)
return False;
Context *ctx = session->context();
if (!ctx)
return False;
return Bool(ctx->Select(index));
return Bool(ctx->*verb(index));
Copy link
Member

Choose a reason for hiding this comment

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

We need a pair of parentheses around the function part (ctx->*verb)(index).
Remove the Bool( ), because the return type is not Bool.

@@ -1076,13 +1076,29 @@ Bool RimeSelectCandidateOnCurrentPage(RimeSessionId session_id, size_t index) {
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 (ctx->*verb)(page_start + index);
Copy link
Member

Choose a reason for hiding this comment

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

Used correctly here.

@@ -550,6 +550,11 @@ typedef struct rime_api_t {
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);

Copy link
Member

Choose a reason for hiding this comment

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

Sync to latest code.

src/rime_api.cc Outdated
@@ -1083,6 +1083,34 @@ const char* RimeGetVersion() {
return RIME_VERSION;
}

Bool RimeDeleteCandidate(RimeSessionId session_id, size_t index) {
an<Session> session(Service::instance().GetSession(session_id));
Copy link
Member

Choose a reason for hiding this comment

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

Sorry. It didn't work because .* or ->* has lower precedence than function call. So it should be written with parentheses around the expression ctx->*verb. See also my inline comments.

@InfinityLoop1308
Copy link
Contributor Author

Ok so it turns out lacking an build environment made a mess of everything. After I managed to fix the environment, the IDE immediately pointed the mistake and fix it, and everything is working well now. This PR will be closed, and a new PR will be open to make commit tree clean.

Thanks for your patience these days.

@InfinityLoop1308 InfinityLoop1308 deleted the feat_delete_selected_candidate branch June 23, 2022 10:02
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.

2 participants