librime-lua icon indicating copy to clipboard operation
librime-lua copied to clipboard

动态更改menu/page_size时,调用apply_schema报错

Open AlienKevin opened this issue 3 years ago • 38 comments

我在开发一个韩文输入法,目标是平常输入韩文的时候不显示menu (page_size = 0),menu只在反查汉字的时候显示。基于PR135,我写了一个简单版本的processor,当按下F10键时会改变朙月拼音的page_size。不过env.engine.apply_schema报错说attempt to call a nil value (field 'apply_schema'),env.engine:apply_schema也有类似报错。

报错message:

E0930 14:06:07.148494 44123520 lua_gears.cc:150] LuaProcessor::ProcessKeyEvent error(2): /Users/kevin/Library/Rime/lua/page_size_processor.lua:20: attempt to call a nil value (field 'apply_schema')

processor代码如下:

local function init(env)
  log.info("===================== init page_size_processor =====================")
end

local function processor(key,env)
  log.info("-------------- start of page_size_processor --------------")
  local Rejected,Accepted,Noop=0,1,2
  local config=env.engine.schema.config
  if key:repr() == "F10" then
    config:set_int("menu/page_size", 10)
    -- reload schema to activate config
    env.engine.apply_schema(env.engine.schema.schema_id)
    return Accepted
  end 
  return Noop
end

local function fini(env)
  print("===================== fini page_size_processor =====================")
end

return { init = init, func = processor, fini = fini }

版本

squirrel master branch最新commit

AlienKevin avatar Sep 30 '22 18:09 AlienKevin

报错含义就是 Engine 里面没有 apply_schema 方法。 大概因为 librime-lua 插件不是最新的?

LawssssCat avatar Sep 30 '22 22:09 LawssssCat

感谢答复,我是今天用东风破安装的librime-lua,不确定东风破安装的是不是最新版?我手动检查了位于package/hchunhui/librime-lua/src/types.cc文件,发现里面有apply_schema的定义:

  static void apply_schema(T *engine, the<Schema> &schema) {
    engine->ApplySchema(schema.release());
  }

AlienKevin avatar Sep 30 '22 23:09 AlienKevin

用 engine:apply_schema( env.engine.schema) 很容易 出問題的 commit: 日 schema: cangjie5 / 倉頡五代 status: (not composing) {F9} double free or corruption (out) -- [1] 1065960 IOT instruction (core dumped) ./rime_api_console

查詢一下 isuue 有個 檢查 librime-lua 版本的function

Rime fcitx-rime 5.0.14 (id:f802202b-a976-4d1a-b171-7fba1e1d29f4) Ver: librime 1.7.3 librime-lua 185 lua Lua 5.4

shewer avatar Sep 30 '22 23:09 shewer

我运行了检查版本的log,结果报错:

E0930 20:13:41.337082 44123520 lua_gears.cc:44] Lua error:(2): /Users/kevin/Library/Rime/lua/page_size_processor.lua:3: attempt to call a nil value (field 'get_distribution_name')

这是我的版本打印程序:

local function init(env)
  log.info("===================== init page_size_processor =====================")
  log.info(rime_api.get_distribution_name())
  log.info(rime_api.get_distribution_version())
  log.info(rime_api.get_distribution_code_name())
  log.info(rime_api.get_user_id())
end

我使用的是macOS Monterey (M1),今天新装了squirrel的最新commit,会不会造成报错?我发现新版本的squirrel会在系统输入法那里注册简体和繁体两个选项。我可以试试删除新版本的squirrel然后在老版本从新测试。

我本机之前从来没有装过lua,不过这样能排除lua版本的问题吗?

Update: 我退到稳定版本的squirrel后有同样的版本报错。

AlienKevin avatar Oct 01 '22 00:10 AlienKevin

把產生出來的 string 看是要作成 lua_translator 中的字典 或是 lua_processor 的 commit_text

-- processor
function proc.func(key,env)
   ......
    if  context.input == "/ver" or key:eq("EventKey('F12") ) then
        context:clear() 
        env.engine:commit_text(  ver func)
        return Accepted -- 1
    end
 end
-- lua_translator
 function tran.func(inp,seg,env)
    if inp== "/ver" then
       yield( Candidate("ver", seg.start, seg._end, Ver_info() , ""))
    end
end
function Version()
  local ver
  if rime_api.get_distribution_name then
    return 185
  elseif LevelDb then
    return 177
  elseif Opencc then
    return 147
  elseif KeySequence and KeySequence().repr then
    return 139
  elseif  ConfigMap and ConfigMap().keys then
    return 127
  elseif Projection then
    return 102
  elseif KeyEvent then
    return 100
  elseif Memory then
    return 80
  elseif rime_api.get_user_data_dir then
    return 9
  elseif log then
    return 9
  else
    return 0
  end
end
function Ver_info()
  local msg1 = rime_api.get_user_id and string.format(" %s %s %s (id:%s) ",
  rime_api.get_distribution_name(),
  rime_api.get_distribution_code_name(),
  rime_api.get_distribution_version(),
  rime_api.get_user_id()) or ""

  local msg2 = string.format(" Ver: librime %s librime-lua %s lua %s",
  rime_api.get_rime_version() , Version() ,_VERSION )
  return msg1 .. msg2
end

shewer avatar Oct 01 '22 01:10 shewer

感谢🙏,我把你的script放到了rime.lua里面,然后luna_pinyin.schema.yaml里面加了两行调用processor和translator。

成功获取了版本号! Ver: librime 1.7.3 librime-lua 9 lua Lua 5.4

AlienKevin avatar Oct 01 '22 01:10 AlienKevin

調換一下順序 ( proc tran 擇一即可 ) Version() Ver_info() -- call Version

module function -- call Ver_info() https://github.com/hchunhui/librime-lua/suites/8448091896/artifacts/374612908 #195 版本 for osx win10

shewer avatar Oct 01 '22 01:10 shewer

问题1:这个是我改过之后的rime.lua,我把Ver_info放到了Version前面。想确认一下调换顺序就是指把Version和Ver_info两个函数的位置调换吗?

rime.lua
-- processor
function version_processor(key,env)
   local Rejected,Accepted,Noop=0,1,2
    if context.input == "/ver" or key:eq("EventKey('F12") then
        context:clear() 
        env.engine:commit_text(Ver_info())
        return Accepted -- 1
    end
 end
-- lua_translator
 function version_translator(inp,seg,env)
    if inp == "/ver" then
       yield(Candidate("ver", seg.start, seg._end, Ver_info() , ""))
    end
end

function Ver_info()
  local msg1 = rime_api.get_user_id and string.format(" %s %s %s (id:%s) ",
  rime_api.get_distribution_name(),
  rime_api.get_distribution_code_name(),
  rime_api.get_distribution_version(),
  rime_api.get_user_id()) or ""

  local msg2 = string.format(" Ver: librime %s librime-lua %s lua %s",
  rime_api.get_rime_version() , Version() ,_VERSION )
  return msg1 .. msg2
end

function Version()
  local ver
  if rime_api.get_distribution_name then
    return 185
  elseif LevelDb then
    return 177
  elseif Opencc then
    return 147
  elseif KeySequence and KeySequence().repr then
    return 139
  elseif  ConfigMap and ConfigMap().keys then
    return 127
  elseif Projection then
    return 102
  elseif KeyEvent then
    return 100
  elseif Memory then
    return 80
  elseif rime_api.get_user_data_dir then
    return 9
  elseif log then
    return 9
  else
    return 0
  end
end

问题2: 直接用你发的版本来代替Squirrel.app/Content里面的这三个executable就可以了吗?其他的executable会不会出现不兼容现象?

Screen Shot 2022-09-30 at 10 07 04 PM

AlienKevin avatar Oct 01 '22 02:10 AlienKevin

不曉得 , window 是這樣的 ,把 rime.dll 替換即可

shewer avatar Oct 01 '22 02:10 shewer

Ok, 我查了下dylib在macOS和dll等同。我尝试用你的librime.1.dylib替换了我的,不过architecture不吻合,所以Squirrel报错: Library not loaded: '@rpath/librime.1.dylib' ... mach-o file, but is an incompatible architecture (have (x86_64), need (arm64e)))

有什么办法我可以自己build librime或者哪里可以找到arm版的build?

UPDATE: 我看到你发的版本里面librime是1.7.3,这和我之前用的版本一致,可能问题不在librime?

AlienKevin avatar Oct 01 '22 02:10 AlienKevin

我从librime github release那里下载了librime 1.7.3然后放到了Squirrel里面,现在出现了新的报错:

E0930 22:54:10.376711 14419328 engine.cc:312] error creating processor: 'lua_processor'
E0930 22:54:10.377452 14419328 engine.cc:346] error creating translator: 'lua_translator'

AlienKevin avatar Oct 01 '22 02:10 AlienKevin

我目前用的都是最新的 librime + librime-lua 其他 plugin bsd (osx) and linux 自行編譯應該蠻容易的

git clone https://github.com/rime/librime
cd librime
#   clone  to  ./plugins/
./install-plugin.sh hchunhui/librime-lua
./install-plugins.sh rime/librime-charcode
./install-plugins.sh lotem/librime-octagram
./install-plugins.sh lotem/librime-proto

mkdir  build && cd build 
cmake .. && cmake --build  .   

shewer avatar Oct 01 '22 02:10 shewer

我从librime github release那里下载了librime 1.7.3然后放到了Squirrel里面,现在出现了新的报错:

E0930 22:54:10.376711 14419328 engine.cc:312] error creating processor: 'lua_processor'
E0930 22:54:10.377452 14419328 engine.cc:346] error creating translator: 'lua_translator'

沒有 plugins librime-lua

shewer avatar Oct 01 '22 03:10 shewer

好的🙏,我大概明白了,一会儿试试看

AlienKevin avatar Oct 01 '22 03:10 AlienKevin

终于build好了!Version输出185应该没问题了。不过env.engine.apply_schema(env.engine.schema.schema_id)这一行直接把preedit里面的东西删了,然后候选字数没有变化,而且似乎还把我的squirrel factory reset了(皮肤和自己下载的输入法插件都没了)。我尝试重新sync user data然后deploy,但是任然无法将任何设置恢复,只有log out然后重新登录才能恢复。请问有什么安全有效的方法去改变menu/page_size?或者可以让translator不添加candidate,但是按空格仍然可以lookup词典输出正确的词。

AlienKevin avatar Oct 01 '22 11:10 AlienKevin

我查了 librime source 關於 page_size 都是參照 sechema.page_size() 簡單的方式是 scheam.h 增加 set_page_size(int) & types.cc SchemaReg::vars_set[] 增加 page_size; 是 可行的且穩定 ,你`可以試試 https://github.com/rime/librime/pull/572 不知道這PR是否會通過

//librime/src/rime/schema.h
class Schema{
    void set_page_size(int page_size) { page_size_ = page_size; }
}
//-----
//plugins/lua/src/types.cc
SchemaReg
   luaL_Reg vars_set[]{
      {"page_size" , WRAPMEM(T::set_page_size)},   // <<---- added
}

reload 自身方案 容易出現 memory 錯誤( engine:apply_schema( Schema) : 別的 方案OK )

shewer avatar Oct 01 '22 13:10 shewer

这个方法好,我试试看

AlienKevin avatar Oct 01 '22 15:10 AlienKevin

fork了librime-lua然后加上了你上面提到的那一行到types.cc。之后,我用你的patch-1分支,plugin-install了我的fork版本的librime-lua,然后编译librime成功。不过,当我替换了Squirrel里面的librime.dylib文件,并且重启Squirrel后,在启动时报错:

kevin@Kevins-MacBook-Pro T % /Library/Input\ Methods/Squirrel.app/Contents/MacOS/Squirrel --quit; /Library/Input\ Methods/Squirrel.app/Contents/MacOS/Squirrel
2022-10-01 22:17:09.876 Squirrel[90815:955332] Initializing la rime...
2022-10-01 22:17:09.883 Squirrel[90815:955332] Squirrel reporting!
2022-10-01 22:17:11.561 Squirrel[90815:955332] createSession: com.apple.Spotlight
2022-10-01 22:17:11.843 Squirrel[90815:955332] set app option: ascii_mode = 1
zsh: segmentation fault  /Library/Input\ Methods/Squirrel.app/Contents/MacOS/Squirrel

当我切换回原先build的librime.dylib,Squirrel又可以正常运行。

AlienKevin avatar Oct 02 '22 02:10 AlienKevin

RimeSetPageSize 是給前端用的,應該不影響 我在 rime_api_console 運作正常 還有 page_size 設定 0 會錯誤 跳離app 預設是 5

shewer avatar Oct 02 '22 03:10 shewer

明白了,那有什么办法可以隐藏候选字?

AlienKevin avatar Oct 02 '22 11:10 AlienKevin

這邊有個思路,無奈功力不夠,lua 寫不出來 這邊韓文使用 2set 鍵位

放棄用express_editor,使用 fluency_editor,使得有半上屏狀態,會有完全隱藏候選項的時候, 再靠 lua 每打一個字母都 confirm 一次,只是這樣只有單音,還需修正XD

engine:
  processors:
    - fluency_editor
    

以下還待改善,目前只有單音,無法組字 思路是:如果可以把游標弄到起始位,再回復到末位,再 context:confirm_current_selection(),可能就可以組字?! shift+[QWERTOP] 目前也有問題 另外還須 if 去避掉快捷鍵等因素干擾

local function isintable(value,tb)
  for k,v in pairs(tb) do
    if v == value then
    return true
    end
  end
  return false
end

local function kr1_p(key, env)
  local engine = env.engine
  local context = engine.context
  local arr = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" , "Q", "W", "E", "R", "T" ,"O" ,"P"}
  if (isintable(key:repr(),arr)) then
      context.input = context.input .. key:repr()
      key.keycode = 0
      context:confirm_current_selection()
      return 1 -- kAccepted
  end
  return 2 -- kNoop
end

oniondelta avatar Oct 02 '22 12:10 oniondelta

這邊有個思路,無奈功力不夠,lua 寫不出來 這邊韓文使用 2set 鍵位

放棄用express_editor,使用 fluency_editor,使得有半上屏狀態,會有完全隱藏候選項的時候, 再靠 lua 每打一個字母都 confirm 一次,只是這樣只有單音,還需修正XD

engine:
  processors:
    - fluency_editor
    

以下還待改善,目前只有單音,無法組字 思路是:如果可以把游標弄到起始位,再回復到末位,再 context:confirm_current_selection(),可能就可以組字?! shift+[QWERTOP] 目前也有問題 另外還須 if 去避掉快捷鍵等因素干擾

local function isintable(value,tb)
  for k,v in pairs(tb) do
    if v == value then
    return true
    end
  end
  return false
end

local function kr1_p(key, env)
  local engine = env.engine
  local context = engine.context
  local arr = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" , "Q", "W", "E", "R", "T" ,"O" ,"P"}
  if (isintable(key:repr(),arr)) then
      context.input = context.input .. key:repr()
      key.keycode = 0
      context:confirm_current_selection()
      return 1 -- kAccepted
  end
  return 2 -- kNoop
end
local set_char=Set {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" , "Q", "W", "E", "R", "T" ,"O" ,"P"} --> {a=true,b=true...}
function proc.func(key,env)
  local context = env.engine.context
  if set_char[key:repr()] then
     context.input:push( key:repr()) 
     context:confirm_current_selection()
     return 1
  end
  return 2
end
-- test
function test(func,msg, time)
  local t1=os.clock()
  for i=1,time do  func() end
  print(msg,os.clock() - t1)
end
 
function Set(tab)
   local rtab = {}
   for i,v in ipairs(tab) do  rtab[v]=true  end
   return rtab
end
 ktab={"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" , "Q", "W", "E", "R", "T" ,"O" ,"P"}
key= Set(ktab)

function t1()
   local tab = Set{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" , "Q", "W", "E", "R", "T" ,"O" ,"P"}
   return tab['p']
end

function t2()
   return key['p']
end

function t3()
  return ('p'):match('^[a-zQWERTOP]$') and true
end

function chk(chr, tab)
   for i,v in ipairs(tab) do 
     if chr == v then return true end
   end
end

function t4()
  local  ktab={"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" , "Q", "W", "E", "R", "T" ,"O" ,"P"}
   return chk('p', ktab)
end


function t5()
  return chk('p',ktab)
end

n=10000
test(t1,'init Set in t1 func', n)
test(t2, 'init Set out of t2 func ', n)
test(t3, ' string.match ',n)
test(t4, ' loop chk, init arr in func' , n)
test(t5, ' loop chk  init arr out of func' ,n )

init Set in t1 func 0.058258 init Set out of t2 func 0.00049999999999994 --- best string.match 0.001692 loop chk, init arr in func 0.014537 loop chk init arr out of func 0.0089570000000001

shewer avatar Oct 02 '22 13:10 shewer

這邊有個思路,無奈功力不夠,lua 寫不出來 這邊韓文使用 2set 鍵位

放棄用express_editor,使用 fluency_editor,使得有半上屏狀態,會有完全隱藏候選項的時候, 再靠 lua 每打一個字母都 confirm 一次,只是這樣只有單音,還需修正XD

以下還待改善,目前只有單音,無法組字 思路是:如果可以把游標弄到起始位,再回復到末位,再 context:confirm_current_selection(),可能就可以組字?! shift+[QWERTOP] 目前也有問題 另外還須 if 去避掉快捷鍵等因素干擾

覺得象是 segment 的工作

shewer avatar Oct 02 '22 14:10 shewer

@ shewer 感謝😄 好像是,沒碰過 librime-lua 的 segment 功能,感覺有得研究了!

oniondelta avatar Oct 02 '22 15:10 oniondelta

我写了一个lua translator可以不用词典转换韩文,不过问题是我要把转换好的结果加到一个Candidate里面,所以输入的时候一直会有一个候选字在底下。如果不是完美主义的话问题不大。

韩文我是基于rime-hangyl做的,用的是HNC Romaja,加了一点小改动:f键aliased to ᆼ,double consonant只支持大写字母,如G -> ᆩ,不支持gg。

hanul_translator.lua
local function wrapped_gsub(inp, pattern, repl)
	inp = string.gsub(inp, "([aeiouw])" .. pattern .. "$", "%1" .. repl)
	inp = string.gsub(inp, "([aeiouw])" .. pattern .. "([^aeiouw])", "%1" .. repl .."%2")
	return inp
end

local function rightbound_gsub(inp, pattern, repl)
	inp = string.gsub(inp, pattern .. "$", repl)
	inp = string.gsub(inp, pattern .. "'", repl .. "'")
	inp = string.gsub(inp, pattern .. "([^aeiouw])", repl .. "%1")
	return inp
end

local function ascii_to_jamo(inp)
	log.info(inp)
	if inp == "" then return "" end

	inp = string.gsub(inp, " ", "'")
    inp = string.gsub(inp, "wa", "oa")
    inp = string.gsub(inp, "w[eo]", "ue")
    inp = string.gsub(inp, "f", "x")
    inp = string.gsub(inp, "r", "l")

    -- double final consonants
    inp = wrapped_gsub(inp,"gs", "ᆪ")
    inp = wrapped_gsub(inp, "nj", "ᆬ")
    inp = wrapped_gsub(inp, "nh", "ᆭ")
    inp = wrapped_gsub(inp, "lg", "ᆰ")
    inp = wrapped_gsub(inp, "lm", "ᆱ")
    inp = wrapped_gsub(inp, "lb", "ᆲ")
    inp = wrapped_gsub(inp, "ls", "ᆳ")
    inp = wrapped_gsub(inp, "lt", "ᆴ")
    inp = wrapped_gsub(inp, "lp", "ᆵ")
    inp = wrapped_gsub(inp, "lh", "ᆶ")
    inp = wrapped_gsub(inp, "bs", "ᆹ")

    -- tense and lax consonant pairs
    inp = rightbound_gsub(inp, "G", "ᆩ")
    inp = string.gsub(inp, "G", "ᄁ")
    inp = wrapped_gsub(inp, "g", "ᆨ")
    inp = string.gsub(inp, "g", "ᄀ")

    inp = rightbound_gsub(inp, "S", "ᆻ")
    inp = string.gsub(inp, "S", "ᄊ")
    inp = wrapped_gsub(inp, "s", "ᆺ")
    inp = string.gsub(inp, "s", "ᄉ")

    inp = string.gsub(inp, "B", "ᄈ")
    inp = wrapped_gsub(inp, "b", "ᆸ")
    inp = string.gsub(inp, "b", "ᄇ")

    inp = string.gsub(inp, "D", "ᄄ")
    inp = wrapped_gsub(inp, "d", "ᆮ")
    inp = string.gsub(inp, "d", "ᄃ")

    inp = string.gsub(inp, "J", "ᄍ")
    inp = wrapped_gsub(inp, "j", "ᆽ")
    inp = string.gsub(inp, "j", "ᄌ")

    -- Rest of the consonants
    inp = wrapped_gsub(inp, "l", "ᆯ")
    inp = string.gsub(inp, "l", "ᄅ")

    inp = wrapped_gsub(inp, "m", "ᆷ")
    inp = string.gsub(inp, "m", "ᄆ")

    inp = wrapped_gsub(inp, "h", "ᇂ")
    inp = string.gsub(inp, "h", "ᄒ")

    inp = wrapped_gsub(inp, "n", "ᆫ")
    inp = string.gsub(inp, "n", "ᄂ")

    inp = wrapped_gsub(inp, "c", "ᆾ")
    inp = string.gsub(inp, "c", "ᄎ")

    inp = wrapped_gsub(inp, "p", "ᇁ")
    inp = string.gsub(inp, "p", "ᄑ")

    inp = wrapped_gsub(inp, "t", "ᇀ")
    inp = string.gsub(inp, "t", "ᄐ")

    inp = wrapped_gsub(inp, "k", "ᆿ")
    inp = string.gsub(inp, "k", "ᄏ")

	inp = string.gsub(inp, "([^aeiouw])x", "%1ᄋ")
	inp = string.gsub(inp, "x([aeiouw])", "ᄋ%1")
	inp = string.gsub(inp, "x", "ᆼ")

    inp = string.gsub(inp, "iai", "ᅤ")
    inp = string.gsub(inp, "iei", "ᅨ")
    inp = string.gsub(inp, "uei", "ᅰ")
    inp = string.gsub(inp, "oai", "ᅫ")
    inp = string.gsub(inp, "ai", "ᅢ")
    inp = string.gsub(inp, "ei", "ᅦ")
    inp = string.gsub(inp, "ia", "ᅣ")
    inp = string.gsub(inp, "ie", "ᅧ")
    inp = string.gsub(inp, "io", "ᅭ")
    inp = string.gsub(inp, "iu", "ᅲ")
    inp = string.gsub(inp, "ue", "ᅯ")
    inp = string.gsub(inp, "ui", "ᅱ")
    inp = string.gsub(inp, "wi", "ᅴ")
    inp = string.gsub(inp, "oa", "ᅪ")
    inp = string.gsub(inp, "o", "ᅩ")
    inp = string.gsub(inp, "e", "ᅥ")
    inp = string.gsub(inp, "a", "ᅡ")
    inp = string.gsub(inp, "i", "ᅵ")
    inp = string.gsub(inp, "u", "ᅮ")
    inp = string.gsub(inp, "w", "ᅳ")

	inp = string.gsub(inp, "'", "")
	log.info(inp)
	return inp
end

-- assumes inp has only a single Unicode character
local function is_lpart_jamo(c)
	return 0x1100 <= c and c <= 0x1112
end

-- assumes inp has only a single Unicode character
local function is_vpart_jamo(c)
	return 0x1161 <= c and c <= 0x1175
end

-- assumes inp has only a single Unicode character
local function is_tpart_jamo(c)
    return 0x11A8 <= c and c <= 0x11C2
end

local function jamos_to_hangul(inp)
	local SBase = 0xAC00
	local LBase = 0x1100
	local VBase = 0x1161
	local TBase = 0x11A7
	local LCount = 19
	local VCount = 21
	local TCount = 28
	local NCount = 588    -- VCount * TCount
	local SCount = 11172  -- LCount * NCount

	local l_state = 0
	local v_state = 1
	local t_state = 2

	local part_state = l_state
	local LVIndex = 0

	local hangul = ""

	for _, part in utf8.codes(inp) do
	    print(part)
		if part_state == l_state then -- lpart state
			if is_lpart_jamo(part) then
				LVIndex = (part - LBase) * NCount
				part_state = v_state
			else
				hangul = hangul .. utf8.char(part)
			end
		elseif part_state == v_state then -- vpart state
			if is_vpart_jamo(part) then
				LVIndex = LVIndex + (part - VBase) * TCount
				part_state = t_state
			else
				prev_lpart = LVIndex // NCount + LBase
				if is_lpart_jamo(part) then
					hangul = hangul .. utf8.char(prev_lpart)
					LVIndex = (part - LBase) * NCount
				else
					hangul = hangul .. utf8.char(prev_lpart, part)
					part_state = l_state
				end
			end
		elseif part_state == t_state then -- tpart state
			local s = 0
			local append_hangul = ""
			if is_tpart_jamo(part) then
				TIndex = part - TBase
				s = SBase + LVIndex + TIndex
				part_state = l_state
			elseif is_lpart_jamo(part) then
				s = SBase + LVIndex
				LVIndex = (part - LBase) * NCount
				part_state = v_state
			else
				s = SBase + LVIndex
			append_hangul = utf8.char(part)
				part_state = l_state
			end
			print(s)
			hangul = hangul .. utf8.char(s) .. append_hangul
		end
	end

	if part_state == v_state then
		prev_lpart = LVIndex // NCount + LBase
		hangul = hangul .. utf8.char(prev_lpart)
	elseif part_state == t_state then
		s = SBase + LVIndex
		hangul = hangul .. utf8.char(s)
	end

	return hangul
end

local function translator(inp, seg)
	local hangul = jamos_to_hangul(ascii_to_jamo(inp))
	local cand = Candidate("placeholder", seg.start, seg._end, hangul, "")
	cand.preedit = hangul
	yield(cand)
end

return translator
hnc_romaja_mod.schema.yaml
# Rime schema
# vim: set sw=2 sts=2 et:
# encoding: utf-8

schema:
  schema_id: hnc_romaja_mod
  name: HNC Romaja (mod)
  version: "0.1"
  author:
    - Kevin Li <[email protected]>
    - Patrick <[email protected]>
    - 雪齋 <[email protected]>
  description: |
    HNC Romaja for Rime
    (This is a slightly modified version
    where f is mapped to ㅇ for convenience)
    ㄱg ㄴn ㄷd ㄹl/r ㅁm ㅂb ㅅs ㅇx/f
    ㅈj ㅊc ㅋk ㅌt ㅍp ㅎh
    ㅏaㅐai ㅑia ㅒiai ㅓe ㅔei ㅕie ㅖiei
    ㅗo ㅘoa ㅙoai ㅚoi ㅛio
    ㅜu ㅝue ㅞuei ㅟui ㅠiu
    ㅡw ㅢwi ㅣi/y
  
  dependencies:
    - hnc_hanja_mod

# menu:
#   page_size: 0

switches:
  - name: half_shape
    states: [ 半角, 全角 ]
    reset: 0

engine:
  processors:
    - ascii_composer
    - recognizer
    - key_binder
    - speller
    - punctuator
    - selector
    - navigator
    - express_editor
    # - fluency_editor
  segmentors:
    - ascii_segmentor
    - matcher
    - affix_segmentor@hnc_hanja_mod
    - abc_segmentor
    - punct_segmentor
    - fallback_segmentor
  translators:
    - punct_translator
    - script_translator
    - script_translator@hnc_hanja_mod
    - echo_translator
    - lua_translator@hangul_translator
  filters:
    - simplifier
    - uniquifier
    - reverse_lookup_filter@romaja_reverse_lookup

speller:
  alphabet: 'zyxwvutsrqponmlkjihgfedcbaBDGSJ'
  initials: 'zyxwvutsrqponmlkjihgfedcbaBDGSJ'
  finals: 'zyxwvutsrqponmlkjihgfedcbaGS'
  delimiter: " '"
  algebra:
    # - abbrev/^([gndlmbsqjcktph]).+$/$1/
    # - derive/(^|[ '])x?([aeiouy])/$1$2/
    # - derive/([^aeiou]|^)B/$1bb/
    - derive/'//
    # - derive/x$/ng/
    - derive/x/f/
    - derive/l/r/
    # - derive/p/f/
    - derive/i/y/
    - derive/oa/wa/
    - derive/ue/we/
    - derive/ue/wo/
    - derive/i([aeou])/y$1/
    - derive/^([A-Za-z]+)\d$/$1/

hnc_hanja_mod:
  tag: hnc_hanja_mod
  dictionary: hnc_hanja_mod
  prefix: "`"
  suffix: ";"
  # enable_completion: true
  # overwrite_comment: false
  tips: 〔漢字・한자〕
  preedit_format:
    - xform/ /'/
    - xform/wa/oa/
    - xform/w[eo]/ue/
    - xform/f/x/
    - xform/r/l/

    # double final consonants
    - xform/([aeiouw])gs($|'|[^aeiouw])/$1ᆪ$2/
    - xform/([aeiouw])nj($|'|[^aeiouw])/$1ᆬ$2/
    - xform/([aeiouw])nh($|'|[^aeiouw])/$1ᆭ$2/
    - xform/([aeiouw])lg($|'|[^aeiouw])/$1ᆰ$2/
    - xform/([aeiouw])lm($|'|[^aeiouw])/$1ᆱ$2/
    - xform/([aeiouw])lb($|'|[^aeiouw])/$1ᆲ$2/
    - xform/([aeiouw])ls($|'|[^aeiouw])/$1ᆳ$2/
    - xform/([aeiouw])lt($|'|[^aeiouw])/$1ᆴ$2/
    - xform/([aeiouw])lp($|'|[^aeiouw])/$1ᆵ$2/
    - xform/([aeiouw])lh($|'|[^aeiouw])/$1ᆶ$2/
    - xform/([aeiouw])bs($|'|[^aeiouw])/$1ᆹ$2/

    # tense and lax consonant pairs
    - xform/G($|')/ᆩ$1/
    - xform/G/ᄁ/
    - xform/([aeiouw])g($|'|[^aeiouw])/$1ᆨ$2/
    - xform/g/ᄀ/

    - xform/S($|')/ᆻ$1/
    - xform/S/ᄊ/
    - xform/([aeiouw])s($|'|[^aeiouw])/$1ᆺ$2/
    - xform/s/ᄉ/

    # - derive/([^aeiou]|^)bb/$1B/
    - xform/B/ᄈ/
    - xform/([aeiouw])b($|'|[^aeiouw])/$1ᆸ$2/
    - xform/b/ᄇ/

    - xform/D/ᄄ/
    - xform/([aeiouw])d($|'|[^aeiouw])/$1ᆮ$2/
    - xform/d/ᄃ/

    - xform/J/ᄍ/
    - xform/([aeiouw])j($|'|[^aeiouw])/$1ᆽ$2/
    - xform/j/ᄌ/

    # Rest of the consonants
    - xform/([aeiouw])l($|'|[^aeiouw])/$1ᆯ$2/
    - xform/l/ᄅ/

    - xform/([aeiouw])m($|'|[^aeiouw])/$1ᆷ$2/
    - xform/m/ᄆ/

    - xform/([aeiouw])h($|'|[^aeiouw])/$1ᇂ$2/
    - xform/h/ᄒ/

    - xform/([aeiouw])n($|'|[^aeiouw])/$1ᆫ$2/
    - xform/n/ᄂ/

    - xform/([aeiouw])c($|'|[^aeiouw])/$1ᆾ$2/
    - xform/c/ᄎ/

    - xform/([aeiouw])p($|'|[^aeiouw])/$1ᇁ$2/
    - xform/p/ᄑ/

    - xform/([aeiouw])t($|'|[^aeiouw])/$1ᇀ$2/
    - xform/t/ᄐ/

    - xform/([aeiouw])k($|'|[^aeiouw])/$1ᆿ$2/
    - xform/k/ᄏ/

    - xform/iai/ᅤ/
    - xform/iei/ᅨ/
    - xform/uei/ᅰ/
    - xform/oai/ᅫ/
    - xform/ai/ᅢ/
    - xform/ei/ᅦ/
    - xform/ia/ᅣ/
    - xform/ie/ᅧ/
    - xform/io/ᅭ/
    - xform/iu/ᅲ/
    - xform/ue/ᅯ/
    - xform/ui/ᅱ/
    - xform/wi/ᅴ/
    - xform/oa/ᅪ/
    - xform/o/ᅩ/
    - xform/e/ᅥ/
    - xform/a/ᅡ/
    - xform/i/ᅵ/
    - xform/u/ᅮ/
    - xform/w/ᅳ/
    - xform/(^|'|`)x/ᄋ/
    - xform/x/ᆼ/
    - xform/'//
  comment_format:
    - xform/(^|[ '])x/$1/
    - xform/x/ng/

punctuator:
  import_preset: default
  full_shape:
    "$" : [ ₩, ¥, "$", "€", "£", "¥", "¢", "¤" ]
  half_shape:
    "$" : [ ₩, "$", "€", "£", "¥", "¢", "¤" ]
    "," : { commit: "," }
    "." : { commit: "." }
    "<" : "<"
    ">" : ">"
    "/" : "/"
    "?" : { commit: "?" }
    ";" : { commit: ";" }
    ":" : { commit: ":" }
    "'" : "'"
    "\"" : "\""
    "\\" : "\\"
    "|" : "|"
    "`" : "`"
    "~" : "~"
    "!" : { commit: "!" }
    "@" : "@"
    "#" : "#"
    "%" : "%"
    "^" : "^"
    "&" : "&"
    "*" : "*"
    "(" : "("
    ")" : ")"
    "-" : "-"
    "_" : "_"
    "+" : "+"
    "=" : "="
    "[" : "["
    "]" : "]"
    "{" : "{"
    "}" : "}"

key_binder:
  import_preset: default

recognizer:
  import_preset: default
  patterns:
    hnc_hanja_mod: "^`[a-zA-Z']*;?$"

romaja_reverse_lookup:
  tags: [ hnc_hanja_mod ]
  overwrite_comment: false
  dictionary: hnc_romaja_mod

AlienKevin avatar Oct 02 '22 15:10 AlienKevin

只有一個候選項,之前這邊是用 filter 過濾

context.input:push( key:repr()) 我這邊不知哪邊搞錯,無效且影響後面的 context:confirm_current_selection() 這幾天再繼續研究

oniondelta avatar Oct 02 '22 15:10 oniondelta

怎麼不用Projection 呢
有點感覺 , commit preedit 就可以 不用candidate translator 加上 opencc 韓文-->漢語 如果有產生candidate

function init(env)
  local config= env.engine.schema.config
  lacal pat=config:get_list("hnc_hanja_mod/preedit_format")
  env.pp= Projection()
  env.pp:load(pat)
end
function func(inp,seg,env)
   local text = env.pp:apply(inp) --  ascii 輸出 韓文
   ...
end

shewer avatar Oct 02 '22 16:10 shewer

只有一個候選項,之前這邊是用 filter 過濾

context.input:push( key:repr()) 我這邊不知哪邊搞錯,無效且影響後面的 context:confirm_current_selection() 這幾天再繼續研究

我對 https://github.com/hchunhui/librime-lua/blob/01c61b1d12ff5fb31711b150ad075422e1d7106d/src/types.cc#L52-L60 不了解 , 形碼很少 處理 segment

confirm_current_selection() 是上一次的 ,當 processor accepted 後 又再一次 compose() 如果 input 變更 大有機會 會影響 candidates 排序

shewer avatar Oct 02 '22 16:10 shewer

試出來了!🥳 [a-z]+可以視覺上等同 menu (page_size = 0),零選項 BackSpace 可返回有選單項狀態 如果要直接刪字 shift + BackSpace fluency_editor 因素,數字標點等無法直接上屏,用 commit 解決

ps: 再修改增韓文 2set 會用到的 Shift+[QWERTOP]

engine:
  processors:
    - fluency_editor
local set_char = Set {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" } --> {a=true,b=true...}

local function proc.func(key,env)
  local engine = env.engine
  local context = engine.context
  local ascii_m = context:get_option("ascii_mode")

  local function check_qwertop()
    if key:eq(KeyEvent("Shift+Q")) then
      return true
    elseif key:eq(KeyEvent("Shift+W")) then
      return true
    elseif key:eq(KeyEvent("Shift+E")) then
      return true
    elseif key:eq(KeyEvent("Shift+R")) then
      return true
    elseif key:eq(KeyEvent("Shift+T")) then
      return true
    elseif key:eq(KeyEvent("Shift+O")) then
      return true
    elseif key:eq(KeyEvent("Shift+P")) then
      return true
    else
      return false
    end
  end

  local check_prefix = string.find(context.input, '=[a-z]*$')  --使反查鍵可展示全部選項

  if (not ascii_m) and set_char[key:repr()] and (not check_prefix) or (not ascii_m) and check_qwertop() and (not check_prefix) then
    local addend = string.gsub(key:repr(), 'Shift%+', '')
    context:reopen_previous_segment()
    context.input = context.input .. addend
    context:confirm_current_selection()
    return 1
  end
  return 2
end

oniondelta avatar Oct 03 '22 06:10 oniondelta

試出來了!partying_face [a-z]+可以視覺上等同 menu (page_size = 0),零選項 BackSpace 可返回有選單項狀態 如果要直接刪字 shift + BackSpace fluency_editor 因素,數字標點等無法直接上屏,用 commit 解決

engine:
  processors:
    - fluency_editor

~~local function Set(tab) local rtab = {} for i,v in ipairs(tab) do rtab[v]=true end return rtab end~~ Set + Set Set * Set Set -Set

a=Set{'a','b','c'}
b=Set{'c','d','e'}
a - b --> {'a','b'}
a * b -->  {'c'}
a + b --> { 'a','b','c','d','e'}
-- librime-lua  內含 Set
local set_char = Set {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" , "Q", "W", "E", "R", "T" ,"O" ,"P"} --> {a=true,b=true...}

local function proc.func(key,env)
  local engine = env.engine
  local context = engine.context
  local ascii_m = context:get_option("ascii_mode")
  if set_char[key:repr()] and (not ascii_m) then  -- key:repr() match[a-z QWERTOP]
    local addend = key:repr():match("^[a-z]$") or ''
--     if (not addend_c) then  -- 不是很懂  這段 (QWERTOP]  append = "" ; return ?
--      addend=''
 --     return 2 ---  must be return 0-2
 --   end
    context:reopen_previous_segment()
    context.input = context.input .. addend
    context:confirm_current_selection()
    return 1
  end
  return 2
end

shewer avatar Oct 03 '22 07:10 shewer