Skip to content

Commit d92a724

Browse files
authored
Merge branch 'rime:master' into master
2 parents 85ed81e + d71168e commit d92a724

21 files changed

Lines changed: 493 additions & 104 deletions

.github/workflows/commit-ci.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,14 @@ jobs:
3030
macos:
3131
needs: lint
3232
uses: ./.github/workflows/macos-build.yml
33+
with:
34+
rime_plugins: hchunhui/librime-lua lotem/librime-octagram rime/librime-predict
3335

3436
windows:
3537
needs: lint
3638
uses: ./.github/workflows/windows-build.yml
39+
with:
40+
rime_plugins: hchunhui/librime-lua lotem/librime-octagram rime/librime-predict
3741

3842
docker:
3943
needs: lint

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
<a name="1.17.0"></a>
2+
## 1.17.0 (2026-06-05)
3+
4+
### Bug 修復 | Bug Fixes
5+
- excluded words cause crashes (#1152) (4218af0)
6+
- forward/rewind 步長視未選定編碼分節數而定 (3a0bafa)
7+
- commit ci should also build with plugins (#1160) (422ad2d)
8+
- space after digit separators shouldn't be translated (aa32d48)
9+
- 不過濾漢字以外的符號 (1300e56)
10+
11+
### 主要功能更新 | Major Updates
12+
- trim leading delimiters (#1147) (4ff27f8)
13+
- 允許跳轉到分隔符之前 (#1142) (2b7ccf2)
14+
- make multiple sentences (d32cd32)
15+
- allow multiple sentence candidates (9422ca7)
16+
17+
**Full Changelog**: https://github.com/rime/squirrel/compare/1.16.1...1.17.0
18+
119
<a name="1.16.1"></a>
220
## 1.16.1 (2026-01-20)
321

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.12)
55
project(rime)
66
set(CMAKE_CXX_STANDARD 17)
77

8-
set(rime_version 1.16.1)
8+
set(rime_version 1.17.0)
99
set(rime_soversion 1)
1010

1111
add_definitions(-DRIME_VERSION="${rime_version}")
@@ -266,7 +266,7 @@ message(STATUS "rime_plugins_libs: ${rime_plugins_deps}")
266266
message(STATUS "rime_plugins_modules: ${rime_plugins_modules}")
267267
set(list "")
268268
foreach(mod ${rime_plugins_modules})
269-
set(list "${list},Q(${mod})")
269+
string(APPEND list "(${mod})")
270270
endforeach()
271271
set(RIME_SETUP_EXTRA_MODULES "${list}")
272272
if(BUILD_SHARED_LIBS AND BUILD_SEPARATE_LIBS AND rime_plugins_objs)

cmake/FindIconv.cmake

Lines changed: 0 additions & 43 deletions
This file was deleted.

src/CMakeLists.txt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ set(rime_dict_deps
5353
${LevelDb_LIBRARY}
5454
${Marisa_LIBRARY})
5555
set(rime_gears_deps
56-
${ICONV_LIBRARIES}
5756
${ICU_LIBRARIES}
5857
${Opencc_LIBRARY})
5958
set(rime_levers_deps "")
@@ -172,7 +171,6 @@ else()
172171
install(TARGETS rime-static DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR})
173172
endif()
174173
if(DEFINED RIME_SETUP_EXTRA_MODULES)
175-
set_property(SOURCE rime/setup.cc
176-
PROPERTY COMPILE_DEFINITIONS
174+
target_compile_definitions(${rime_library} PRIVATE
177175
"RIME_EXTRA_MODULES=${RIME_SETUP_EXTRA_MODULES}")
178176
endif()

src/rime/algo/syllabifier.cc

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,19 @@ int Syllabifier::BuildSyllableGraph(const string& input,
5353

5454
if (current_pos > farthest)
5555
farthest = current_pos;
56-
DLOG(INFO) << "current_pos: " << current_pos;
56+
57+
// consume leading delimiters
58+
size_t begin_pos = current_pos;
59+
while (begin_pos < input.length() &&
60+
delimiters_.find(input[begin_pos]) != string::npos)
61+
++begin_pos;
62+
DLOG(INFO) << "current_pos: " << current_pos
63+
<< ", begin_pos: " << begin_pos;
5764

5865
// see where we can go by advancing a syllable
5966
vector<Prism::Match> matches;
6067
set<SyllableId> exact_match_syllables;
61-
auto current_input = input.substr(current_pos);
68+
auto current_input = input.substr(begin_pos);
6269
prism.CommonPrefixSearch(current_input, &matches);
6370
if (corrector_) {
6471
for (auto& m : matches) {
@@ -78,12 +85,13 @@ int Syllabifier::BuildSyllableGraph(const string& input,
7885
}
7986
}
8087

88+
size_t leading_gap = begin_pos - current_pos;
8189
if (!matches.empty()) {
8290
auto& end_vertices(graph->edges[current_pos]);
8391
for (const auto& m : matches) {
8492
if (m.length == 0)
8593
continue;
86-
size_t end_pos = current_pos + m.length;
94+
size_t end_pos = current_pos + leading_gap + m.length;
8795
// consume trailing delimiters
8896
while (end_pos < input.length() &&
8997
delimiters_.find(input[end_pos]) != string::npos)

src/rime/common.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <string>
1919
#include <utility>
2020
#include <vector>
21+
#include <deque>
2122
#define BOOST_BIND_NO_PLACEHOLDERS
2223
#include <boost/signals2/connection.hpp>
2324
#include <boost/signals2/signal.hpp>
@@ -37,6 +38,7 @@
3738

3839
namespace rime {
3940

41+
using std::deque;
4042
using std::function;
4143
using std::list;
4244
using std::make_pair;

src/rime/config/config_compiler.cc

Lines changed: 76 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
#include <algorithm>
2+
#include <cctype>
3+
#include <cstdlib>
4+
#include <optional>
15
#include <boost/algorithm/string.hpp>
26
#include <rime/common.h>
37
#include <rime/resource.h>
@@ -101,7 +105,9 @@ static bool AppendToString(an<ConfigItemRef> target, an<ConfigValue> value) {
101105
return true;
102106
}
103107

104-
static bool AppendToList(an<ConfigItemRef> target, an<ConfigList> list) {
108+
static bool AppendToList(an<ConfigItemRef> target,
109+
an<ConfigList> list,
110+
std::optional<size_t> insert_pos = std::nullopt) {
105111
if (!list)
106112
return false;
107113
auto existing_list = As<ConfigList>(**target);
@@ -117,9 +123,20 @@ static bool AppendToList(an<ConfigItemRef> target, an<ConfigList> list) {
117123
if (list->empty())
118124
return true;
119125
auto copy = New<ConfigList>(*existing_list);
126+
if (insert_pos && *insert_pos > copy->size()) {
127+
LOG(ERROR) << "list insert position out of range: " << *insert_pos;
128+
return false;
129+
}
130+
size_t current_index = insert_pos.value_or(copy->size());
120131
for (ConfigList::Iterator iter = list->begin(); iter != list->end(); ++iter) {
121-
if (!copy->Append(*iter))
122-
return false;
132+
if (insert_pos) {
133+
if (!copy->Insert(current_index, *iter))
134+
return false;
135+
++current_index;
136+
} else {
137+
if (!copy->Append(*iter))
138+
return false;
139+
}
123140
}
124141
*target = copy;
125142
return true;
@@ -148,25 +165,63 @@ static bool MergeTree(an<ConfigItemRef> target, an<ConfigMap> map) {
148165
static constexpr const char* ADD_SUFFIX_OPERATOR = "/+";
149166
static constexpr const char* EQU_SUFFIX_OPERATOR = "/=";
150167

151-
inline static bool IsAppending(const string& key) {
168+
static std::optional<size_t> ParseIndexedAppend(const string& key) {
169+
if (key.empty() || key.back() != '+')
170+
return std::nullopt;
171+
size_t plus_pos = key.size() - 1;
172+
size_t digit_begin = plus_pos;
173+
while (digit_begin > 0 &&
174+
std::isdigit(static_cast<unsigned char>(key[digit_begin - 1]))) {
175+
--digit_begin;
176+
}
177+
if (digit_begin == plus_pos)
178+
return std::nullopt;
179+
if (digit_begin > 0 && key[digit_begin - 1] != '/')
180+
return std::nullopt;
181+
string index_part = key.substr(digit_begin, plus_pos - digit_begin);
182+
if (index_part.empty())
183+
return std::nullopt;
184+
return static_cast<size_t>(std::strtoull(index_part.c_str(), nullptr, 10));
185+
}
186+
187+
inline static bool IsAppending(const string& key,
188+
const std::optional<size_t>& indexed_append) {
152189
return key == ConfigCompiler::APPEND_DIRECTIVE ||
153-
boost::ends_with(key, ADD_SUFFIX_OPERATOR);
190+
boost::ends_with(key, ADD_SUFFIX_OPERATOR) ||
191+
indexed_append.has_value();
154192
}
155193
inline static bool IsMerging(const string& key,
156194
const an<ConfigItem>& value,
157-
bool merge_tree) {
158-
return key == ConfigCompiler::MERGE_DIRECTIVE ||
159-
boost::ends_with(key, ADD_SUFFIX_OPERATOR) ||
195+
bool merge_tree,
196+
const std::optional<size_t>& indexed_append) {
197+
bool has_plain_add_suffix =
198+
boost::ends_with(key, ADD_SUFFIX_OPERATOR) && !indexed_append.has_value();
199+
return key == ConfigCompiler::MERGE_DIRECTIVE || has_plain_add_suffix ||
160200
(merge_tree && (!value || Is<ConfigMap>(value)) &&
161201
!boost::ends_with(key, EQU_SUFFIX_OPERATOR));
162202
}
163203

164-
inline static string StripOperator(const string& key, bool adding) {
165-
return (key == ConfigCompiler::APPEND_DIRECTIVE ||
166-
key == ConfigCompiler::MERGE_DIRECTIVE)
167-
? ""
168-
: boost::erase_last_copy(
169-
key, adding ? ADD_SUFFIX_OPERATOR : EQU_SUFFIX_OPERATOR);
204+
inline static string StripOperator(
205+
const string& key,
206+
bool adding,
207+
const std::optional<size_t>& indexed_append) {
208+
if (key == ConfigCompiler::APPEND_DIRECTIVE ||
209+
key == ConfigCompiler::MERGE_DIRECTIVE) {
210+
return "";
211+
}
212+
if (indexed_append) {
213+
auto suffix_with_slash =
214+
string("/") + std::to_string(*indexed_append) + "+";
215+
if (boost::ends_with(key, suffix_with_slash)) {
216+
return key.substr(0, key.size() - suffix_with_slash.size());
217+
}
218+
auto suffix_plain = std::to_string(*indexed_append) + "+";
219+
if (boost::ends_with(key, suffix_plain)) {
220+
return key.substr(0, key.size() - suffix_plain.size());
221+
}
222+
}
223+
return boost::erase_last_copy(
224+
key, adding ? ADD_SUFFIX_OPERATOR : EQU_SUFFIX_OPERATOR);
170225
}
171226

172227
// defined in config_data.cc
@@ -180,9 +235,10 @@ static bool EditNode(an<ConfigItemRef> head,
180235
const an<ConfigItem>& value,
181236
bool merge_tree) {
182237
DLOG(INFO) << "edit node: " << key << ", merge_tree: " << merge_tree;
183-
bool appending = IsAppending(key);
184-
bool merging = IsMerging(key, value, merge_tree);
185-
string path = StripOperator(key, appending || merging);
238+
auto indexed_append = ParseIndexedAppend(key);
239+
bool appending = IsAppending(key, indexed_append);
240+
bool merging = IsMerging(key, value, merge_tree, indexed_append);
241+
string path = StripOperator(key, appending || merging, indexed_append);
186242
DLOG(INFO) << "appending: " << appending << ", merging: " << merging
187243
<< ", path: " << path;
188244
auto find_target_node =
@@ -195,8 +251,9 @@ static bool EditNode(an<ConfigItemRef> head,
195251
if ((appending || merging) && **target) {
196252
DLOG(INFO) << "writer: editing node";
197253
return !value || // no-op
198-
(appending && (AppendToString(target, As<ConfigValue>(value)) ||
199-
AppendToList(target, As<ConfigList>(value)))) ||
254+
(appending &&
255+
(AppendToString(target, As<ConfigValue>(value)) ||
256+
AppendToList(target, As<ConfigList>(value), indexed_append))) ||
200257
(merging && MergeTree(target, As<ConfigMap>(value)));
201258
} else {
202259
DLOG(INFO) << "writer: overwriting node";

src/rime/gear/abc_segmentor.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ bool AbcSegmentor::Proceed(Segmentation* segmentation) {
4444
bool expecting_an_initial = true;
4545
for (; k < input.length(); ++k) {
4646
bool is_letter = alphabet_.find(input[k]) != string::npos;
47-
bool is_delimiter = (k != j) && (delimiter_.find(input[k]) != string::npos);
47+
bool is_delimiter = (k != 0) && (delimiter_.find(input[k]) != string::npos);
4848
if (!is_letter && !is_delimiter)
4949
break;
5050
bool is_initial = initials_.find(input[k]) != string::npos;

src/rime/gear/charset_filter.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ bool is_extended_cjk(uint32_t ch) {
2626
(ch >= 0x31350 && ch <= 0x323AF) || // CJK Unified Ideographs Extension H
2727
(ch >= 0x2EBF0 && ch <= 0x2EE5F) || // CJK Unified Ideographs Extension I
2828
(ch >= 0x323B0 && ch <= 0x3347F) || // CJK Unified Ideographs Extension J
29-
(ch >= 0x3300 && ch <= 0x33FF) || // CJK Compatibility
30-
(ch >= 0xFE30 && ch <= 0xFE4F) || // CJK Compatibility Forms
31-
(ch >= 0xF900 && ch <= 0xFAFF) || // CJK Compatibility Ideographs
29+
// (ch >= 0x3300 && ch <= 0x33FF) || // CJK Compatibility
30+
// (ch >= 0xFE30 && ch <= 0xFE4F) || // CJK Compatibility Forms
31+
(ch >= 0xF900 && ch <= 0xFAFF) || // CJK Compatibility Ideographs
3232
(ch >= 0x2F800 &&
3333
ch <= 0x2FA1F)) // CJK Compatibility Ideographs Supplement
3434
return true;

0 commit comments

Comments
 (0)