diff --git a/src/rime/gear/navigator.cc b/src/rime/gear/navigator.cc index a83d9ca69..b57298f28 100644 --- a/src/rime/gear/navigator.cc +++ b/src/rime/gear/navigator.cc @@ -66,6 +66,10 @@ Navigator::Navigator(const Ticket& ticket) Config* config = engine_->schema()->config(); LoadConfig(config, "navigator", Horizontal); LoadConfig(config, "navigator/vertical", Vertical); + config->GetBool("navigator/stop_before_delimiter", &stop_before_delimiter_); + if (stop_before_delimiter_) { + config->GetString("speller/delimiter", &delimiters_); + } select_connection_ = engine_->context()->select_notifier().connect( [this](Context* ctx) { OnSelect(ctx); }); @@ -120,8 +124,11 @@ bool Navigator::LeftByCharNoLoop(Context* ctx) { bool Navigator::Rewind(Context* ctx) { BeginMove(ctx); // take a jump leftwards when there are multiple spans, - // but not from the middle of a span. - if (spans_.Count() > 1 && spans_.HasVertex(ctx->caret_pos())) { + // but not from the middle of a span + size_t caret_pos = ctx->caret_pos(); + if (stop_before_delimiter_) + caret_pos = SkipDelimiterForward(caret_pos); + if (spans_.Count() > 1 && spans_.HasVertex(caret_pos)) { size_t confirmed_pos = ctx->composition().GetConfirmedPosition(); JumpLeft(ctx, confirmed_pos, true); } else { @@ -132,7 +139,10 @@ bool Navigator::Rewind(Context* ctx) { bool Navigator::Forward(Context* ctx) { BeginMove(ctx); - if (spans_.Count() > 1 && spans_.HasVertex(ctx->caret_pos())) { + size_t caret_pos = SkipDelimiterForward(ctx->caret_pos()); + if (stop_before_delimiter_) + caret_pos = SkipDelimiterForward(caret_pos); + if (spans_.Count() > 1 && spans_.HasVertex(caret_pos)) { size_t confirmed_pos = ctx->composition().GetConfirmedPosition(); JumpRight(ctx, confirmed_pos, true); } else { @@ -197,6 +207,8 @@ void Navigator::BeginMove(Context* ctx) { bool Navigator::JumpLeft(Context* ctx, size_t start_pos, bool loop) { DLOG(INFO) << "jump left."; size_t caret_pos = ctx->caret_pos(); + if (stop_before_delimiter_) + caret_pos = SkipDelimiterForward(caret_pos); size_t end_of_translation = spans_.end(); size_t end_of_input = ctx->input().length(); size_t new_pos = @@ -212,6 +224,8 @@ bool Navigator::JumpLeft(Context* ctx, size_t start_pos, bool loop) { : (std::max)(start_pos, spans_.PreviousStop(end_of_input)) // 跳至前一個切分點 : (std::max)(start_pos, spans_.PreviousStop(caret_pos)); + if (stop_before_delimiter_) + new_pos = SkipDelimiterBackward(new_pos); if (new_pos != caret_pos) { ctx->set_caret_pos(new_pos); return true; @@ -222,6 +236,8 @@ bool Navigator::JumpLeft(Context* ctx, size_t start_pos, bool loop) { bool Navigator::JumpRight(Context* ctx, size_t start_pos, bool loop) { DLOG(INFO) << "jump right."; size_t caret_pos = ctx->caret_pos(); + if (stop_before_delimiter_) + caret_pos = SkipDelimiterForward(caret_pos); size_t end_of_translation = spans_.end(); size_t end_of_input = ctx->input().length(); size_t new_pos = @@ -231,6 +247,8 @@ bool Navigator::JumpRight(Context* ctx, size_t start_pos, bool loop) { : (caret_pos >= end_of_translation) ? end_of_input // 跳至後一個切分點 : spans_.NextStop(caret_pos); + if (stop_before_delimiter_) + new_pos = SkipDelimiterBackward(new_pos); if (new_pos != caret_pos) { ctx->set_caret_pos(new_pos); return true; @@ -290,4 +308,17 @@ bool Navigator::GoToEnd(Context* ctx) { return false; } +size_t Navigator::SkipDelimiterBackward(size_t pos) { + while (pos > 0 && delimiters_.find(input_[pos - 1]) != string::npos) + pos--; + return pos; +} + +size_t Navigator::SkipDelimiterForward(size_t pos) { + while (pos < input_.length() - 1 && + delimiters_.find(input_[pos]) != string::npos) + pos++; + return pos; +} + } // namespace rime diff --git a/src/rime/gear/navigator.h b/src/rime/gear/navigator.h index 6280796cc..47fb06f38 100644 --- a/src/rime/gear/navigator.h +++ b/src/rime/gear/navigator.h @@ -54,6 +54,12 @@ class Navigator : public Processor, public KeyBindingProcessor { Spans spans_; connection select_connection_; + + private: + string delimiters_; + bool stop_before_delimiter_ = false; + size_t SkipDelimiterBackward(size_t pos); + size_t SkipDelimiterForward(size_t pos); }; } // namespace rime