hchunhui / librime-cloud

72 stars 12 forks source link

无法使用 keybind 触发云查词 #1

Closed amosbird closed 4 years ago

amosbird commented 4 years ago

非常感谢分享!我已经成功测试了通过lua获取百度云词,但是rime在加载 lua_processor@baidu_processor 似乎遇到了问题,log中显示

E0315 15:24:49.094590 502823 lua_gears.cc:113] LuaProcessor::ProcessKeyEvent error(2): attempt to call a nil value

请问这个如何解决呢

amosbird commented 4 years ago

我在 INFO log里找到了原因

I0315 15:44:21.357102 569752 modules.cc:24] rime.lua error: error loading module 'socket.core' from file

'/usr/lib/lua/5.1/socket/core.so':

    /usr/lib/lua/5.1/socket/core.so: undefined symbol: lua_gettop

https://github.com/diegonehab/luasocket/issues/87#issuecomment-64002323

看来我们需要显式导出一些lua符号

hchunhui commented 4 years ago

是否是因为 lua 和 luasocket 之间的版本不匹配导致的? 从路径看用现在找到的 luasocket 是 linux 发行版自带的,且是针对 lua 5.1 的。是否可以确认 librime 也是采用系统的 lua 5.1 编译而来?

amosbird commented 4 years ago

是采用系统的 lua 5.1 编译而来?

对 用的luajit。不过我觉得这个限制不值得折腾了,我现在直接用 io.popen 调用外部脚本来取词。

但是有两个问题——

  1. 双拼码并没有转成全拼进行查询
  2. 上屏的词似乎没有保存进userdict <--- 这个我研究了一段时间没有想明白
hchunhui commented 4 years ago

好的,我自己用的是 lua 5.3,没有遇到符号找不到的问题。luajit 可能要靠你来帮忙解决。

后面两个问题也比较好理解,因为云输入和拼音是走的两个独立的 translator,所以转码和造词云输入这边看不到。前者也许比较好解决,好像以前有 issue 还讨论过。后者较复杂,除了跨 translator 的原因外,还因为云输入出来的候选项是 SimpleCandidate,这种类型好像是不能参与造词的。 后者需要继续研究,并要涉及更新 librime-lua 的代码。

hchunhui commented 4 years ago

补充一下 undefined symbol 的问题。如果你用的是 fcitx-rime,可试着修改 /usr/share/fcitx/addon/fcitx-rime.conf,把 LoadLocal=True 改为 LoadLocal=False。 当 LoadLocal=True 时,fcitx 会把 librime 导出符号隐藏,导致 lua 载入新模块时找不到符号。

amosbird commented 4 years ago

luajit 可能要靠你来帮忙解决。

没问题

fcitx 会把 librime 导出符号隐藏,导致 lua 载入新模块时找不到符号。

但是 librime 并不会导出lua符号,参见 https://github.com/diegonehab/luasocket/issues/87#issuecomment-64002323

前者也许比较好解决,好像以前有 issue 还讨论过。

这个我尝试搜索了不少issue 都没有找到,我试着用 context:get_preedit().text ,context:get_commit_text() 以及 context:get_script_text() 均没有效果。是不是有方法可以在translator中做一次双拼的转码呢

amosbird commented 4 years ago

目前的 Processor 似乎不太稳定,我尝试多次按 control-t 有时候会出现candlist更新丢失

hchunhui commented 4 years ago

但是 librime 并不会导出lua符号,参见 diegonehab/luasocket#87 (comment)

调整 LoadLocal 实际上就是对应链接中第一种解决方案。或者我的理解不对,能不能发个 pull request ?

目前的 Processor 似乎不太稳定,我尝试多次按 control-t 有时候会出现candlist更新丢失

每次按键时会触发一次网络请求,但是不是每次都能成功(有时是超时,有时可能是百度限流了,返回 error),所以不成功时就不会得到候选。如果在这做一个缓存应该会好。

amosbird commented 4 years ago

调整 LoadLocal 实际上就是对应链接中第一种解决方案

哦,是我的理解问题,我验证了确实可以

每次按键时会触发一次网络请求,但是不是每次都能成功

这个我外部脚本 dump出来都成功了,不是获取云词的问题

amosbird commented 4 years ago

双拼的编码问题我在lua里打表解决了。现在就差让rime记录下云词了 😃

hchunhui commented 4 years ago

强!不能造词我比较确定跟 SimpleCandidate 有关,但具体要怎么做才能造词,特别是跨翻译器的情况,需要明确。你可以到 librime 那边问问。弄清楚后,我可以协助在 librime-lua 里面加接口,这样就完美了。

amosbird commented 4 years ago

SimpleCandidate

请问除了 Simple 以外还有什么类型呢 我看了样例有 date number 但是找不到其他相关资料了

hchunhui commented 4 years ago

要看 librime 的代码。Candidate 是 librime 里面一个类似于接口的 class,它有 SimpleCandidate, ShadowCandidate, Phrase 等好几种实现,可以在 src/rime/candidate.hsrc/rime/gear/translator_commons.h 里面看到定义。

在 lua 中,目前只支持 SimpleCandidate,脚本里面的 Candidate(....) 实际就是 SimpleCandidate 的构造函数,别的构造不了。然而据我了解好像 Phrase 才能用于造词。

所以现在的任务应该是:在 lua 中加入 Phrase 等的构造函数,然后将云输入的候选项改为这种类型,使 lua 生成的候选项可用于造词。

以上是我的理解。首先得确定这个理解有没有问题。其次是具体来说要加入哪些类型,每个参数要搞清楚是什么意思。最后是在 librime-lua 中绑定和修改云输入脚本。我看到这些 class 的定义还是相当复杂的,涉及的相关 class 也不少,所以建议先去 librime 那边问一下。

amosbird commented 4 years ago

我看了一下librime代码,大致明白了

https://github.com/rime/librime/blob/master/src/rime/gear/memory.cc#L108

为了简化,我们需要先保证只有一个segment,这对云输入来说也挺合理的。然后需要弄出Phrase Candidate并且选择相应的语言即可。只要recognized = true 就会被user dict 记录在案

amosbird commented 4 years ago

临时的 DictEntry 创建 似乎可以参考 https://github.com/rime/librime/blob/master/src/rime/dict/dictionary.cc#L85

amosbird commented 4 years ago

我实现了一个版本,不过需要patch librime,否则 DictEntry的custom_code无法传递。这个构词和translator完全耦合了,我觉得一个可能的实现方式是让LuaTranslator继承ScriptTranslator然后override,否则很难按照正常的办法DFSEncode出一个Phrase。不过目前凑合可用了 🙂

hchunhui commented 4 years ago

强!我都没有找到这几个关键的地方,一直不知如何下手。希望能找到不 patch librime 的方法,至少也是干静一些的 patch。继承 ScriptTranslator 感觉也有点太重量级了。

amosbird commented 4 years ago

搞了个不错的补全方案,贴这分享一下 😀

#!/usr/bin/env bash

input=$1
len=$2

curl -s "https://www.baidu.com/sugrec?prod=pc&wd=$input" | jq '.g[]|.q' | perl -MEncode -MList::Util=uniq -nE 'if (decode("UTF-8", $_) =~ /^"(\p{Han}{'$len'})/) {push @words, encode("UTF-8", $1)} END { $,=" "; print uniq @words }'
trysh commented 4 years ago

强!我都没有找到这几个关键的地方,一直不知如何下手。希望能找到不 patch librime 的方法,至少也是干静一些的 patch。继承 ScriptTranslator 感觉也有点太重量级了。

希望能早日实现 “找到不 patch librime 的方法,至少也是干静一些的 patch”