1 /* 2 * SPDX-FileCopyrightText: 2017-2017 CSSlayer <wengxt@gmail.com> 3 * 4 * SPDX-License-Identifier: LGPL-2.1-or-later 5 * 6 */ 7 #ifndef _TABLE_TABLEDICTRESOLVER_H_ 8 #define _TABLE_TABLEDICTRESOLVER_H_ 9 10 #include <fcitx-config/configuration.h> 11 #include <fcitx-config/enum.h> 12 #include <fcitx-utils/i18n.h> 13 #include <fcitx-utils/log.h> 14 #include <fcitx/candidatelist.h> 15 #include <libime/core/userlanguagemodel.h> 16 #include <libime/table/tablebaseddictionary.h> 17 #include <tuple> 18 19 namespace fcitx { 20 21 FCITX_CONFIG_ENUM(OrderPolicy, No, Freq, Fast); 22 FCITX_CONFIG_ENUM_NAME(CandidateLayoutHint, "Not set", "Vertical", 23 "Horizontal"); 24 FCITX_CONFIG_ENUM_I18N_ANNOTATION(CandidateLayoutHint, N_("Not set"), 25 N_("Vertical"), N_("Horizontal")); 26 27 struct NoSaveAnnotation { skipDescriptionNoSaveAnnotation28 bool skipDescription() { return true; } skipSaveNoSaveAnnotation29 bool skipSave() { return true; } dumpDescriptionNoSaveAnnotation30 void dumpDescription(RawConfig &) const {} 31 }; 32 33 template <typename T> 34 using NoSaveOption = OptionWithAnnotation<T, NoSaveAnnotation>; 35 36 FCITX_CONFIGURATION( 37 TableConfig, NoSaveOption<std::string> file{this, "File", _("File")}; 38 KeyListOption prevPage{ 39 this, 40 "PrevPage", 41 _("Prev page"), 42 {Key(FcitxKey_Up)}, 43 KeyListConstrain(KeyConstrainFlag::AllowModifierLess)}; 44 KeyListOption nextPage{ 45 this, 46 "NextPage", 47 _("Next page"), 48 {Key(FcitxKey_Down)}, 49 KeyListConstrain(KeyConstrainFlag::AllowModifierLess)}; 50 KeyListOption prevCandidate{ 51 this, 52 "PrevCandidate", 53 _("Prev Candidate"), 54 {Key("Left")}, 55 KeyListConstrain(KeyConstrainFlag::AllowModifierLess)}; 56 KeyListOption nextCandidate{ 57 this, 58 "NextCandidate", 59 _("Next Candidate"), 60 {Key("Right")}, 61 KeyListConstrain(KeyConstrainFlag::AllowModifierLess)}; 62 KeyListOption secondCandidate{ 63 this, 64 "SecondCandidate", 65 _("Select Second Candidate"), 66 {}, 67 KeyListConstrain({KeyConstrainFlag::AllowModifierLess, 68 KeyConstrainFlag::AllowModifierOnly})}; 69 KeyListOption thirdCandidate{ 70 this, 71 "ThirdCandidate", 72 _("Select Third Candidate"), 73 {}, 74 KeyListConstrain({KeyConstrainFlag::AllowModifierLess, 75 KeyConstrainFlag::AllowModifierOnly})}; 76 NoSaveOption<KeyList> selection{ 77 this, 78 "Selection", 79 _("Selection"), 80 {Key(FcitxKey_1), Key(FcitxKey_2), Key(FcitxKey_3), Key(FcitxKey_4), 81 Key(FcitxKey_5), Key(FcitxKey_6), Key(FcitxKey_7), Key(FcitxKey_8), 82 Key(FcitxKey_9), Key(FcitxKey_0)}}; 83 Option<int, IntConstrain> pageSize{this, "PageSize", _("Page size"), 5, 84 IntConstrain(3, 10)}; 85 // Fcitx 4 default behavior. 86 Option<bool> commitAfterSelect{this, "CommitAfterSelect", 87 _("Commit after auto select candidates"), 88 true}; 89 Option<bool> commitWhenDeactivate{ 90 this, "CommitWhenDeactivate", 91 _("Commit buffer when deactivating input method"), true}; 92 OptionWithAnnotation<bool, ToolTipAnnotation> commitInvalidSegment{ 93 this, 94 "CommitInvalidSegment", 95 _("Commit Invalid Segment"), 96 false, 97 {}, 98 {}, 99 ToolTipAnnotation( 100 _("Commit the segment that does not exist in the table. This " 101 "option is useful for some latin/compose based table."))}; 102 Option<bool> useFullWidth{this, "UseFullWidth", _("Use full width"), true}; 103 Option<bool> ignorePunc{this, "IgnorePunc", 104 _("Ignore built in punctuation"), false}; 105 Option<bool> firstCandidateAsPreedit{this, "FirstCandidateAsPreedit", 106 _("First candidate as Preedit"), 107 false}; 108 Option<Key, KeyConstrain> quickphrase{ 109 this, 110 "QuickPhraseKey", 111 _("Key to trigger quickphrase"), 112 Key{}, 113 {KeyConstrainFlag::AllowModifierLess}}; 114 OptionWithAnnotation<std::string, ToolTipAnnotation> quickphraseText{ 115 this, 116 "QuickPhraseText", 117 _("Text to trigger quickphrase"), 118 "", 119 {}, 120 {}, 121 {_("When a new character is typed, if it matches any character in this " 122 "string, all the existing text will be put into quickphrase " 123 "buffer.")}}; 124 NoSaveOption<std::string> icon{this, "Icon", _("Icon")}; 125 Option<int> noSortInputLength{this, "NoSortInputLength", 126 _("Don't sort word shorter than")}; 127 Option<OrderPolicy> orderPolicy{this, "OrderPolicy", _("Order policy")}; 128 OptionWithAnnotation<bool, ToolTipAnnotation> useSystemLanguageModel{ 129 this, 130 "UseSystemLanguageModel", 131 _("Use system language model"), 132 true, 133 {}, 134 {}, 135 ToolTipAnnotation(_("When available, system language model will be " 136 "loaded for given language and provide ability to " 137 "give better context based order."))}; 138 OptionWithAnnotation<bool, ToolTipAnnotation> useContextBasedOrder{ 139 this, 140 "UseContextRelatedOrder", 141 _("Sort candidates based on current context"), 142 true, 143 {}, 144 {}, 145 ToolTipAnnotation( 146 _("Order the candidate based on the word you already typed. You " 147 "may want to disable this option if you want the candidate order " 148 "to be stable regardless of the history."))}; 149 Option<Key, KeyConstrain> matchingKey{ 150 this, 151 "MatchingKey", 152 _("Wildcard matching Key"), 153 Key(), 154 {KeyConstrainFlag::AllowModifierLess}}; 155 Option<Key, KeyConstrain> pinyinKey{this, 156 "PinyinKey", 157 _("Prefix key to trigger Pinyin"), 158 Key(), 159 {KeyConstrainFlag::AllowModifierLess}}; 160 161 Option<bool> autoSelect{this, "AutoSelect", _("Auto select candidate")}; 162 OptionWithAnnotation<int, ToolTipAnnotation> autoSelectLength{ 163 this, 164 "AutoSelectLength", 165 _("Length limit of selecting the only candidate"), 166 0, 167 {}, 168 {}, 169 ToolTipAnnotation( 170 _("When current input length is greater than or equal to the limit " 171 "and there is only one candidate available, automatically select " 172 "this candidate. -1 Means the maximum code length of the table. " 173 "0 means this behavior is disabled."))}; 174 OptionWithAnnotation<std::string, ToolTipAnnotation> autoSelectRegex{ 175 this, 176 "AutoSelectRegex", 177 _("Regular expression for selecting the only candidate"), 178 "", 179 {}, 180 {}, 181 ToolTipAnnotation(_("When current input matches the regular expression " 182 "and there is only one candidate available, " 183 "automatically select this candidate."))}; 184 OptionWithAnnotation<int, ToolTipAnnotation> noMatchAutoSelectLength{ 185 this, 186 "NoMatchAutoSelectLength", 187 _("Auto select when no match is found"), 188 0, 189 {}, 190 {}, 191 ToolTipAnnotation( 192 _("When typing a new character, if the current input length is " 193 "greater than or equal to the limit, and the existing segment " 194 "with the new character does not have any matched entries in the " 195 "table, select the current candidate and then type in the new " 196 "character. -1 means the maximum code length of the table. 0 " 197 "means this behavior is disabled."))}; 198 OptionWithAnnotation<std::string, ToolTipAnnotation> noMatchAutoSelectRegex{ 199 this, 200 "NoMatchAutoSelectRegex", 201 _("Regular expression for auto select when no match is found"), 202 "", 203 {}, 204 {}, 205 ToolTipAnnotation( 206 _("When typing a new character, if the current input matches the " 207 "regular expression and the existing segment " 208 "with the new character does not have any matched entries in the " 209 "table, select the current candidate and then type in the new " 210 "character."))}; 211 NoSaveOption<KeyList> endKey{this, "EndKey", _("End key")}; 212 OptionWithAnnotation<int, ToolTipAnnotation> autoPhraseLength{ 213 this, 214 "AutoPhraseLength", 215 _("Auto phrase length"), 216 -1, 217 {}, 218 {}, 219 ToolTipAnnotation( 220 _("After committing every character, learn the new phrase based on " 221 "the input history. If certain word is seen for multiple times " 222 "or selected by user once, it will be added as user phrase. -1 " 223 "means the maximum code length of the table. 0 means disable " 224 "this feature. "))}; 225 Option<std::string> markerForAutoPhrase{ 226 this, "MarkerForAutoPhrase", 227 _("Marker for auto phrase in the candidates"), "*"}; 228 OptionWithAnnotation<int, ToolTipAnnotation> saveAutoPhraseAfter{ 229 this, 230 "SaveAutoPhraseAfter", 231 _("Save auto phrase after being typed for ... times"), 232 -1, 233 {}, 234 {}, 235 ToolTipAnnotation( 236 _("If the value less than 0, means this feature is disabled. If " 237 "auto phrase is enabled, selecting auto phrase candidate " 238 "explicitly will still add the word as a new user phrase."))}; 239 Option<bool> exactMatch{this, "ExactMatch", _("Exact Match")}; 240 Option<bool> learning{this, "Learning", _("Learning"), true}; 241 Option<bool> hint{this, "Hint", _("Display Hint for word")}; 242 Option<bool> displayCustomHint{this, "DisplayCustomHint", 243 _("Display custom hint")}; 244 Option<std::string> hintSeparator{ 245 this, "HintSeparator", _("Separator text between hint and candidate"), 246 " ~ "}; 247 OptionWithAnnotation<CandidateLayoutHint, CandidateLayoutHintI18NAnnotation> 248 candidateLayoutHint{this, "CandidateLayoutHint", 249 _("Candidate List orientation"), 250 CandidateLayoutHint::NotSet}; 251 NoSaveOption<std::vector<std::string>> autoRuleSet{this, "AutoRuleSet", 252 _("Auto rule set")};); 253 254 FCITX_CONFIGURATION(PartialIMInfo, HiddenOption<std::string> languageCode{ 255 this, "LangCode", "Language Code"};); 256 257 FCITX_CONFIGURATION(TableConfigRoot, 258 Option<TableConfig> config{this, "Table", "Table"}; 259 Option<PartialIMInfo, NoConstrain<PartialIMInfo>, 260 DefaultMarshaller<PartialIMInfo>, NoSaveAnnotation> 261 im{this, "InputMethod", "InputMethod"};); 262 263 struct TableData { 264 TableConfigRoot root; 265 std::unique_ptr<libime::TableBasedDictionary> dict; 266 std::unique_ptr<libime::UserLanguageModel> model; 267 }; 268 269 class TableIME { 270 public: 271 TableIME(libime::LanguageModelResolver *lmResolver); 272 273 const TableConfig &config(const std::string &name); 274 275 std::tuple<libime::TableBasedDictionary *, libime::UserLanguageModel *, 276 const TableConfig *> 277 requestDict(const std::string &name); 278 void saveDict(const std::string &name); 279 void saveAll(); 280 void updateConfig(const std::string &name, const RawConfig &config); 281 282 void releaseUnusedDict(const std::unordered_set<std::string> &names); 283 284 private: 285 libime::LanguageModelResolver *lm_; 286 std::unordered_map<std::string, TableData> tables_; 287 }; 288 289 FCITX_DECLARE_LOG_CATEGORY(table_logcategory); 290 291 #define TABLE_DEBUG() FCITX_LOGC(::fcitx::table_logcategory, Debug) 292 #define TABLE_ERROR() FCITX_LOGC(::fcitx::table_logcategory, Error) 293 } // namespace fcitx 294 295 #endif // _TABLE_TABLEDICTRESOLVER_H_ 296