diff --git a/sample/lua/script_translator.lua b/sample/lua/script_translator.lua new file mode 100644 index 0000000..fac3955 --- /dev/null +++ b/sample/lua/script_translator.lua @@ -0,0 +1,81 @@ +#! /usr/bin/env lua +-- +-- script_translator.lua +-- Copyright (C) 2023 Shewer Lu +-- +-- Distributed under terms of the MIT license. +-- + +--[[ + +''' custom.yaml' +patch: + engine/translators/+: + - lua_translator@*table_translator@translator + - lua_translator@*script_translator@cangjie +```` +------- methods return +env.tran:start_session false function() +env.tran:finish_session false function() +env.tran:discard_session false function() +env.tran:query false function(inp, seg) +env.tran:memorize false function(commit_entrys) +env.tran:update_entry false function(entry, state, prefix_str) +env.tran.memorize_callback = function(self, commit_entry) +------- vars_set +env.tran.spelling_hints = int >0 +env.tran.initial_quality = double +env.tran.contextual_suggestions = boolean +env.tran.enable_completion = boolean +env.tran.always_show_comments = boolean +env.tran.strict_spelling = boolean +env.tran.max_homophones = int +env.tran.enable_correction = boolean +env.tran.tag = string +env.tran.delimiters = string + +------- vars_get +res = env.tran.spelling_hints 0 number +res = env.tran.initial_quality 0.0 number +res = env.tran.contextual_suggestions false boolean +res = env.tran.enable_completion true boolean +res = env.tran.always_show_comments false boolean +res = env.tran.strict_spelling false boolean +res = env.tran.max_homophones 1 number +res = env.tran.enable_correction false boolean +res = env.tran.tag abc string +res = env.tran.delimiters ' string + +--]] +local M={} +local function simple_callback(self, commits) + local context = self.engine.context + if true then + return self:memorize(commits) + end +end +local function callback(self, commits) -- self : env.tran commits : list + local context = self.engine.context + for i, entry in ipairs(commits:get()) do + self:update_entry(entry,0,"") -- do nothing to userdict + -- self:update_entry(entry,1,"") -- update entry to userdict + -- self:update_entry(entry,-1,"") -- delete entry to userdict + end +end +function M.init(env) + env.tran = Component.ScriptTranslator(env.engine, env.name_space, "script_translator") + env.tran:memorize_callback(simple_callback) +end + +function M.fini(env) +end + +function M.func(inp, seg, env) + local t = env.tran:query(inp,seg) + if not t then return end + for cand in t:iter() do + yield(cand) + end +end + +return M diff --git a/sample/lua/table_translator.lua b/sample/lua/table_translator.lua new file mode 100644 index 0000000..aa92681 --- /dev/null +++ b/sample/lua/table_translator.lua @@ -0,0 +1,84 @@ +#! /usr/bin/env lua +-- +-- table_translator.lua +-- Copyright (C) 2023 Shewer Lu +-- +-- Distributed under terms of the MIT license. +-- +--[[ +-- +''' custom.yaml' +patch: + engine/translators/+: + - lua_translator@*table_translator@translator + - lua_translator@*script_translator@cangjie +```` + +------- methods +env.tran:finish_session bool function() +env.tran:start_session bool function() +env.tran:discard_session bool function() +env.tran:query translation function(inp, seg) +env.tran:memorize bool function(commit_entrys) +env.tran:update_entry bool function(entry) + +------- vars_set 設定值 +env.tran.max_homophones = number +env.tran.spelling_hints = number +env.tran.enable_correction = boolean +env.tran.memorize_callback = function(self, commits) +env.tran.enable_completion = false boolean +env.tran.delimiters = false string +env.tran.strict_spelling = boolean +env.tran.contextual_suggestions = boolean +env.tran.initial_quality = double +env.tran.always_show_comments = boolean +env.tran.tag = string + +------- vars_get 取值 +res = env.tran.max_homophones 1 number +res = env.tran.spelling_hints 0 number +res = env.tran.enable_correction false boolean +res = env.tran.enable_completion true boolean +res = env.tran.delimiters ' string +res = env.tran.strict_spelling false boolean +res = env.tran.contextual_suggestions false boolean +res = env.tran.initial_quality 0.0 number +res = env.tran.always_show_comments false boolean +res = env.tran.tag cangjie string + + +--]] + +local M={} +local function simple_callback(self, commits) + local context = self.engine.context + if true then + return self:memorize(commits) + end +end +local function callback(self, commits) -- self : env.tran commits : list + local context = self.engine.context + for i, entry in ipairs(commits:get()) do + self:update_entry(entry, 0,"") -- do nothing to userdict + -- self:update_entry(entry,1,"") -- update entry to userdict + -- self:update_entry(entry,-1,"") -- delete entry to userdict + end +end +function M.init(env) + env.tran = Component.TableTranslator(env.engine, env.name_space, "table_translator") + env.tran:memorize_callback(simple_callback) +end + +function M.fini(env) +end + +function M.func(inp, seg, env) + local t = env.tran:query(inp,seg) + if not t then return end + for cand in t:iter() do + yield(cand) + end +end + +return M diff --git a/sample/luna_pinyin.custom.yaml b/sample/luna_pinyin.custom.yaml new file mode 100644 index 0000000..dc85bd3 --- /dev/null +++ b/sample/luna_pinyin.custom.yaml @@ -0,0 +1,6 @@ +patch: + engine/translators/+: + - lua_translator@*table_translator@translator + - lua_translator@*script_translator@cangjie + + diff --git a/src/script_translator.cc b/src/script_translator.cc new file mode 100644 index 0000000..e604955 --- /dev/null +++ b/src/script_translator.cc @@ -0,0 +1,178 @@ +/* + * table_translator.cc + * Copyright (C) 2023 Shewer Lu + * + * Distributed under terms of the MIT license. + */ + +#include +#include +#include +#include + + +#include "translator.h" + +using namespace rime; + +namespace { +namespace ScriptTranslatorReg { + + class LScriptTranslator : public ScriptTranslator { + public: + LScriptTranslator(const Ticket& ticket, Lua* lua) + : ScriptTranslator(ticket), lua_(lua) {}; + + virtual bool Memorize(const CommitEntry& commit_entry); + bool memorize(const CommitEntry& commit_entry); + bool update_entry(const DictEntry& index, + int commits, const string& new_entory_prefix); + + SET_(memorize_callback, an); + bool memorize_callback(); + + // TranslatorOptions + SET_(contextual_suggestions, bool); + SET_(delimiters, string&); + SET_(preedit_formatter, Projection&); + SET_(comment_formatter, Projection&); + bool reload_user_dict_disabling_patterns(an); + + // ScriptTranslator member + ACCESS_(spelling_hints, int); + ACCESS_(always_show_comments, bool); + ACCESS_(max_homophones, int); + GET_(enable_correction, bool); + void set_enable_correction(bool); + + protected: + Lua* lua_; + an memorize_callback_; + void init_correction(); + }; + + using T = LScriptTranslator; + + bool T::memorize_callback() { + return (memorize_callback_) ? true : false; + } + + bool T::memorize(const CommitEntry& commit_entry) { + return ScriptTranslator::Memorize(commit_entry); + } + + bool T::Memorize(const CommitEntry& commit_entry) { + if (!memorize_callback_) { + return memorize(commit_entry); + } + + auto r = lua_->call, LScriptTranslator*, const CommitEntry&>( + memorize_callback_, this, commit_entry); + if (!r.ok()) { + auto e = r.get_err(); + LOG(ERROR) << "LScriptTranslator of " << name_space_ + << ": memorize_callback error(" << e.status << "): " << e.e; + return false; + } + return r.get(); + } + + void T::init_correction() { + if (auto* corrector = Corrector::Require("corrector")) { + Ticket ticket(engine_, name_space_); + corrector_.reset(corrector->Create(ticket)); + } + } + + void T::set_enable_correction(bool enable) { + if (enable_correction_ = enable && !corrector_) + init_correction(); + } + + bool T::update_entry(const DictEntry& entry, + int commits, const string& new_entory_prefix) { + if (user_dict_ && user_dict_->loaded()) + return user_dict_->UpdateEntry(entry, commits, new_entory_prefix); + + return false; + } + + bool T::reload_user_dict_disabling_patterns(an cl) { + return cl ? user_dict_disabling_patterns_.Load(cl) : false; + } + + static const luaL_Reg funcs[] = { + {NULL, NULL}, + }; + + static const luaL_Reg methods[] = { + {"query", WRAPMEM(T, Query)}, // string, segment + {"start_session", WRAPMEM(T, StartSession)}, + {"finish_session", WRAPMEM(T, FinishSession)}, + {"discard_session", WRAPMEM(T, DiscardSession)}, + WMEM(memorize), // delegate TableTransaltor::Momorize + WMEM(update_entry), // delegate UserDictionary::UpdateEntry + WMEM(reload_user_dict_disabling_patterns), + Set_WMEM(memorize_callback), // an callback function + {NULL, NULL}, + }; + + static const luaL_Reg vars_get[] = { + Get_WMEM(name_space), // string + Set_WMEM(memorize_callback), // an callback function + // ScriptTranslator member + Get_WMEM(max_homophones), // int + Get_WMEM(spelling_hints), // int + Get_WMEM(always_show_comments), // bool + Get_WMEM(enable_correction), // bool + //TranslatorOptions + Get_WMEM(delimiters), // string& + Get_WMEM(tag), // string + Get_WMEM(enable_completion), // bool + Get_WMEM(contextual_suggestions), // bool + Get_WMEM(strict_spelling), // bool + Get_WMEM(initial_quality), // double + Get_WMEM(preedit_formatter), // Projection& + Get_WMEM(comment_formatter), // Projection& + // Memory + Get_WMEM(dict), + Get_WMEM(user_dict), + {NULL, NULL}, + }; + + static const luaL_Reg vars_set[] = { + // ScriptTranslator member + Set_WMEM(max_homophones), // int + Set_WMEM(spelling_hints), // int + Set_WMEM(always_show_comments), // bool + Set_WMEM(enable_correction), // bool + // TranslatorOptions + Set_WMEM(delimiters), // string& + Set_WMEM(tag), // string + Set_WMEM(enable_completion), // bool + Set_WMEM(contextual_suggestions), // bool + Set_WMEM(strict_spelling), // bool + Set_WMEM(initial_quality), // double + Set_WMEM(preedit_formatter), // Projection& + Set_WMEM(comment_formatter), // Projection& + {NULL, NULL}, + }; + + void reg_Component(lua_State* L) { + lua_getglobal(L, "Component"); + if (lua_type(L, -1) != LUA_TTABLE) { + LOG(ERROR) << "table of _G[\"Component\"] not found."; + } else { + lua_pushcfunction(L, raw_make_translator); + lua_setfield(L, -2, "ScriptTranslator"); + } + lua_pop(L, 1); + } + +} // namespace ScriptTranslatorReg +} // namespace + +void LUAWRAPPER_LOCAL script_translator_init(lua_State* L) { + EXPORT(ScriptTranslatorReg, L); + ScriptTranslatorReg::reg_Component(L); +} diff --git a/src/table_translator.cc b/src/table_translator.cc new file mode 100644 index 0000000..b2647f4 --- /dev/null +++ b/src/table_translator.cc @@ -0,0 +1,223 @@ +/* + * table_translator.cc + * Copyright (C) 2023 Shewer Lu + * + * Distributed under terms of the MIT license. + */ + +#include +#include +#include +#include +#include + +#include "translator.h" + +using namespace rime; + +namespace { +namespace TableTranslatorReg { + + class LTableTranslator : public TableTranslator { + public: + LTableTranslator(const Ticket& ticket, Lua* lua) + : TableTranslator(ticket), lua_(lua) {}; + + virtual bool Memorize(const CommitEntry& commit_entry); + bool memorize(const CommitEntry& commit_entry); + bool update_entry(const DictEntry& index, + int commits, const string& new_entory_prefix); + + SET_(memorize_callback, an); + bool memorize_callback(); + + // TranslatorOptions + void set_contextual_suggestions(bool); + SET_(delimiters, string&); + SET_(preedit_formatter, Projection&); + SET_(comment_formatter, Projection&); + bool reload_user_dict_disabling_patterns(an); + + // TableTranslator member + ACCESS_(encode_commit_history, bool); + ACCESS_(max_phrase_length, int); + ACCESS_(max_homographs, int); + ACCESS_(enable_charset_filter, bool); + GET_(sentence_over_completion, bool); + void set_sentence_over_completion(bool); + GET_(enable_encoder, bool); + void set_enable_encoder(bool); + GET_(enable_sentence, bool); + void set_enable_sentence(bool); + + protected: + Lua* lua_; + an memorize_callback_; + bool init_poet(); + bool init_encoder(); + }; + + + using T = LTableTranslator; + + bool T::memorize_callback() { + return (memorize_callback_) ? true : false; + } + bool T::memorize(const CommitEntry& commit_entry) { + return TableTranslator::Memorize(commit_entry); + } + + bool T::Memorize(const CommitEntry& commit_entry) { + if (!memorize_callback_) { + return memorize(commit_entry); + } + + auto r = lua_->call, LTableTranslator*, const CommitEntry&>( + memorize_callback_, this, commit_entry); + if (!r.ok()) { + auto e = r.get_err(); + LOG(ERROR) << "LTableTranslator of " << name_space_ + << ": memorize_callback error(" << e.status << "): " << e.e; + return false; + } + return r.get(); + } + + bool T::update_entry(const DictEntry& entry, + int commits, const string& new_entory_prefix) { + if (user_dict_ && user_dict_->loaded()) + return user_dict_->UpdateEntry(entry, commits, new_entory_prefix); + + return false; + } + + // enable_encoder + bool T::init_encoder() { + if (!user_dict_) + return false; + encoder_.reset(new UnityTableEncoder(user_dict_.get())); + Ticket ticket(engine_, name_space_); + encoder_->Load(ticket); + if (!encoder_) { + LOG(WARNING) << "init encoder failed"; + return false; + } + return true; + } + + void T::set_enable_encoder(bool enable) { + if (enable_encoder_ = enable && user_dict_ && !encoder_){ + init_encoder(); + } + } + // enable sentence contextual + bool T::init_poet() { + Config* config = engine_->schema()->config(); + poet_.reset(new Poet(language(), config, Poet::LeftAssociateCompare)); + if (!poet_) { + LOG(WARNING) << "init poet failed"; + return false; + } + return true; + } + + void T::set_enable_sentence(bool enable) { + if (enable_sentence_ = enable && !poet_) + init_poet(); + } + + void T::set_sentence_over_completion(bool enable) { + if (sentence_over_completion_ = enable && !poet_ ) + init_poet(); + } + + void T::set_contextual_suggestions(bool enable) { + if (contextual_suggestions_ = enable && !poet_) + init_poet(); + } + bool T::reload_user_dict_disabling_patterns(an cl) { + return cl ? user_dict_disabling_patterns_.Load(cl) : false; + } + + static const luaL_Reg funcs[] = { + {NULL, NULL}, + }; + + static const luaL_Reg methods[] = { + {"query", WRAPMEM(T, Query)}, // string, segment + {"start_session", WRAPMEM(T, StartSession)}, + {"finish_session", WRAPMEM(T, FinishSession)}, + {"discard_session", WRAPMEM(T, DiscardSession)}, + WMEM(memorize), // delegate TableTransaltor::Momorize + WMEM(update_entry), // delegate UserDictionary::UpdateEntry + WMEM(reload_user_dict_disabling_patterns), + Set_WMEM(memorize_callback), // an callback function + {NULL, NULL}, + }; + + static const luaL_Reg vars_get[] = { + // class translator member + Get_WMEM(name_space), // string + Get_WMEM(memorize_callback), // an callback function + // TabletTranslator member + Get_WMEM(enable_charset_filter), // bool + Get_WMEM(enable_encoder), // bool + Get_WMEM(enable_sentence), // bool + Get_WMEM(sentence_over_completion), // bool + Get_WMEM(encode_commit_history), // int + Get_WMEM(max_phrase_length), // int + Get_WMEM(max_homographs), // bool + // TranslatorOptions + Get_WMEM(delimiters), // string& + Get_WMEM(tag), // string + Get_WMEM(enable_completion), // bool + Get_WMEM(contextual_suggestions), // bool + Get_WMEM(strict_spelling), // bool + Get_WMEM(initial_quality), // double + Get_WMEM(preedit_formatter), // Projection& + Get_WMEM(comment_formatter), // Projection& + // Memory + Get_WMEM(dict), + Get_WMEM(user_dict), + {NULL, NULL}, + }; + + static const luaL_Reg vars_set[] = { + // TableTranslator member + Set_WMEM(enable_charset_filter), // bool + Set_WMEM(enable_encoder), // bool + Set_WMEM(enable_sentence), // bool + Set_WMEM(sentence_over_completion), // bool + Set_WMEM(encode_commit_history), // bool + Set_WMEM(max_phrase_length), // int + Set_WMEM(max_homographs), // int + // TranslatorOptions + Set_WMEM(delimiters), // string& + Set_WMEM(tag), // string + Set_WMEM(enable_completion), // bool + Set_WMEM(contextual_suggestions), // bool + Set_WMEM(strict_spelling), // bool + Set_WMEM(initial_quality), // double + Set_WMEM(preedit_formatter), // Projection& + Set_WMEM(comment_formatter), // Projection& + {NULL, NULL}, + }; + + void reg_Component(lua_State* L) { + lua_getglobal(L, "Component"); + if (lua_type(L, -1) != LUA_TTABLE) { + LOG(ERROR) << "table of _G[\"Component\"] not found."; + } else { + lua_pushcfunction(L, raw_make_translator); + lua_setfield(L, -2, "TableTranslator"); + } + lua_pop(L, 1); + } + +} // namespace TableTranslatorReg +} // namespace + +void LUAWRAPPER_LOCAL table_translator_init(lua_State* L) { + EXPORT(TableTranslatorReg, L); + TableTranslatorReg::reg_Component(L); +} diff --git a/src/translator.h b/src/translator.h new file mode 100644 index 0000000..d5bd9b2 --- /dev/null +++ b/src/translator.h @@ -0,0 +1,69 @@ +/* + * script_translator.h + * Copyright (C) 2023 Shewer Lu + * + * Distributed under terms of the MIT license. + */ + +#ifndef _LUA_TRANSLATOR_H +#define _LUA_TRANSLATOR_H + +#include +#include +#include +#include +#include +#include +#include "lib/lua_export_type.h" + +#define SET_(name, type) \ + void set_##name(const type data) { \ + name##_ = data; \ + } +#define GET_(name, type) \ + type name() { \ + return name##_; \ + } +#define ACCESS_(name, type) \ + SET_(name, type); \ + GET_(name, type) + +#define Set_WMEM(name) \ + { #name, WRAPMEM(T, set_##name) } +#define WMEM(name) \ + { #name, WRAPMEM(T, name) } +#define Get_WMEM(name) \ + { #name, WRAPMEM(T, name) } + +#if LUA_VERSION_NUM < 502 +#define lua_absindex(L, i) abs_index((L), (i)) +#endif + + +template +int raw_make_translator(lua_State* L){ + int n = lua_gettop(L); + if (3 > n || 4 < n) + return 0; + + C_State C; + rime::Ticket ticket( + LuaType::todata(L, 1), + LuaType::todata(L, -2, &C), + LuaType::todata(L, -1, &C) + ); + DLOG(INFO) << "check Ticket:" << ticket.klass << "@" <::todata(L, 2) ); //overwrite schema + Lua* lua= Lua::from_state(L); + rime::an obj = rime::New(ticket, lua); + if (obj) { + LuaType>::pushdata(L, obj); + return 1; + } + else { + //LOG(ERROR) << "error creating " << typeid(O).name() << ": '" << ticket.klass << "'"; + return 0; + } +}; +#endif /* !_LUA_TRANSLATOR_H */ diff --git a/src/types_ext.cc b/src/types_ext.cc index 66670ec..a69d033 100644 --- a/src/types_ext.cc +++ b/src/types_ext.cc @@ -16,11 +16,9 @@ #include "lib/lua_export_type.h" #include "optional.h" - #include using namespace rime; - namespace { template using void_t = void; @@ -253,11 +251,11 @@ namespace UserDbReg{ an make_leveldb(const string& db_name) { return make(db_name, "userdb"); } - + an make_tabledb(const string& db_name) { return make(db_name, "plain_userdb"); } - + optional fetch(an t, const string& key) { string res; if ( t->Fetch(key,&res) ) @@ -274,7 +272,7 @@ namespace UserDbReg{ } an Query(T &t, const string& key) { return t.Query(key); } - + static const luaL_Reg funcs[] = { {"UserDb", WRAP(make)},// an LevelDb( db_file, db_name) {"LevelDb", WRAP(make_leveldb)},// an LevelDb( db_file, db_name) @@ -290,7 +288,7 @@ namespace UserDbReg{ {"fetch", WRAP(fetch)}, // fetch(key) return value {"update", WRAP(Update)}, // update(key,value) return bool {"erase", WRAP(Erase)}, // erase(key) return bool - + {"loaded",WRAPMEM(T, loaded)}, {"disable", WRAPMEM(T, disable)}, {"enable", WRAPMEM(T, enable)}, @@ -343,6 +341,7 @@ namespace ComponentReg{ } }; + static const luaL_Reg funcs[] = { {"Processor", raw_create

}, {"Segmentor" , raw_create}, @@ -360,6 +359,9 @@ namespace ComponentReg{ } +void table_translator_init(lua_State *L); +void script_translator_init(lua_State *L); + void LUAWRAPPER_LOCAL types_ext_init(lua_State *L) { EXPORT(ProcessorReg, L); EXPORT(SegmentorReg, L); @@ -369,4 +371,7 @@ void LUAWRAPPER_LOCAL types_ext_init(lua_State *L) { EXPORT(DbAccessorReg, L); EXPORT(UserDbReg, L); ComponentReg::init(L); + // add LtableTranslator ScriptTranslator in Component + table_translator_init(L); + script_translator_init(L); }