LibreService / my_rime

Free and Open Source online Chinese IME powered by RIME. 自由开源在线中文输入法 拼音 双拼 粤语 注音 五笔 仓颉 速成

Home Page:https://my-rime.vercel.app/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

新的问题

bczhc opened this issue · comments

  1. 我的方案配置中有一句:

     - { accept: space, send: Escape, when: composing } #无候选时(空码)空格清屏

    期待是空码时按空格清除空码,无任何其他操作。但是实际它会清码后再上一个空格。按空格时控制台写的是simulate key sequence: 。我开了debug=on,发送apo apo为空码),就会出现多上一个空格的问题;但发送apo{space},就正常。看来应该得向librime传{space}

  2. Tab键不映射

        - { accept: Tab, send: apostrophe, when: always }
        - { accept: Release+Tab, send: Release+apostrophe, when: always }
  3. 左右Alt不映射

        - { when: has_menu, accept: Alt_R, send: 3 } # 三选
        - { when: has_menu, accept: Alt_L, send: 4 } # 四选
  4. dependencies都得在schemas.json中定义出来,这就导致它们都会在方案列表中显现出来,即使它们并不是实际使用的方案。就像这样,那些没中文名的就是辅助方案:

    image

以及感谢对lua的支持!现在我的方案终于能用了,基本所有功能都是正常的,就是上面测试的几个问题。超过我的预想。没想到竟还有环境变量hh
image

哦还有,我的emoji引导不知道为什么不编码提示了。就emoji引导不行,其他的都可以。
Peek
Peek 2023-03-16 17-54

4最简单,你按文档里加disabled: true就行了。
你的schemas.json贴一下我好测。

我这个方案可能有些复杂。不知其他过多不相关的东西会不会影响到。

[
  {
    "id": "luna_pinyin",
    "name": "朙月拼音",
    "emoji": true,
    "target": "luna-pinyin",
    "dependencies": ["stroke"],
    "license": "LGPL-3.0-only"
  },
  {
    "id": "stroke",
    "name": "五笔画",
    "target": "stroke",
    "dependencies": ["luna_pinyin"],
    "variants": [],
    "license": "LGPL-3.0-only"
  },
  {
    "id": "tiger",
    "name": "虎码",
    "target": "bczhc/rime-demo",
    "dependencies": [
      "tiger_core2022",
      "PY_c",
      "emoji",
      "html_chars",
      "latin_international",
      "ipa_yunlong",
      "short_punct",
      "named_ipa_diacritics"
    ]
  },
  {
    "id": "tiger_guihu",
    "name": "九重鬼虎",
    "target": "bczhc/rime-demo",
    "dependencies": [
      "tiger_core2022",
      "PY_c",
      "emoji",
      "html_chars",
      "latin_international",
      "ipa_yunlong",
      "short_punct",
      "named_ipa_diacritics"
    ]
  },
  {
    "id": "zrm_pinyin",
    "name": "自然码+辅助码",
    "target": "bczhc/rime-demo",
    "dependencies": ["chaizi"]
  },
  {
    "id": "kongmingma",
    "name": "空明码",
    "target": "bczhc/rime-demo",
    "dependencies": []
  },
  {
    "id": "tiger_core2022",
    "name": "tiger_core2022",
    "target": "bczhc/rime-demo",
    "dependencies": []
  },
  {
    "id": "PY_c",
    "name": "PY_c",
    "target": "bczhc/rime-demo",
    "dependencies": ["stroke"]
  },
  {
    "id": "emoji",
    "name": "emoji",
    "target": "bczhc/rime-demo",
    "dependencies": []
  },
  {
    "id": "html_chars",
    "name": "html_chars",
    "target": "bczhc/rime-demo",
    "dependencies": []
  },
  {
    "id": "latin_international",
    "name": "latin_international",
    "target": "bczhc/rime-demo",
    "dependencies": []
  },
  {
    "id": "ipa_yunlong",
    "name": "ipa_yunlong",
    "target": "bczhc/rime-demo",
    "dependencies": ["named_ipa_diacritics"]
  },
  {
    "id": "short_punct",
    "name": "short_punct",
    "target": "bczhc/rime-demo",
    "dependencies": []
  },
  {
    "id": "named_ipa_diacritics",
    "name": "named_ipa_diacritics",
    "target": "bczhc/rime-demo",
    "dependencies": []
  },
  {
    "id": "chaizi",
    "name": "chaizi",
    "target": "bczhc/rime-demo",
    "dependencies": []
  }
]

左右Alt是在这个地方return掉了,但不是按这里说的,在edit模式下会发送所有keydown。我没办法让它simulate左右Alt。所谓的edit模式是什么?

// In edit mode, rime handles every keydown;
// In non-edit mode, only when the textarea is focused and a printable key is down (w/o modifier) will activate rime.
if (!editing.value) {
if (document.activeElement !== textarea || !isPrintableKey) {
return
}
// Don't send Control+x, Meta+x, Alt+x to librime, but allow them with Shift
if (isShortcut && !hasShift) {
return
}
}

b754aa5 修复了emoji的问题。在我集成emoji时tips: none还不是默认(这个commit改的),导致每个emoji后面都有文字rime/rime-emoji#24 (comment) ,于是我把emoji后面的comment全屏蔽了。现在默认显示所有comment,提供了hideComment: "emoji"专门屏蔽emoji的comment。

edit模式是我自造的,就是指候选词popover弹出来的状态。
ebb8a49 支持了左右Alt键,因为是edit模式,所以是在你找的代码块后边。

非edit模式下,Tab有明确的转移焦点的默认行为,所以不支持。你可以改代码强行支持。
onKeydown打一个断点,然后按Tab键,单步执行,就会发现是

走的默认行为,于是可以把上一行的条件改成document.activeElement !== textarea || (!isPrintableKey && key !== 'Tab'),就可以把Tab也交给librime。
类似的操作也可以在onKeyup搞一遍,结果是把
if (editing.value && isPrintable(key)) {
改成(editing.value && isPrintable(key)) || key === 'Tab'

好吧,既然

keydown的handler是异步的(因为我让librime跑在worker线程),在第一个await之前必须决定是否prevendDefault,所以只要让librime处理就不可能走默认行为了。

的话,那就只能没法处理非composing模式下的Tab了。

就是在composing模式下,Release+Tab好像没处理。处理下这个就好了。

就是在composing模式下,Release+Tab好像没处理。处理下这个就好了。

可以,5c14af4 处理了。当时过滤是因为onKeyup只是为了宫保拼音加的,没考虑定制需求。

1的话我用KeySequence::Parse空格字符和{space},效果是一样的。所以问题应该不是发送{space} 之前的区别。

debug on之后,比如那个虎码的cpo是空码,我在下面发送key的地方输入cpo回车,再输单一一个空格,再回车,这时上方文本框会多出一个空格,非预期行为;但我如果一次性输入cpo_(_是空格),回车,上方不会上那多的一个空格。

不表达那么多,简明的测试例子就是:

a_cpo_b_ -> 来如

a_cpo, _, b_ -> 来 如

它们俩应是一样的,即来如

空格是在这里上屏的:

} else { // REJECTED
editing.value = false
showMenu.value = false
if (isPrintable(rimeKey)) {
insert(rimeKey)
}
}

写着REJECTED,但事实上这里空格应该是被消费的,也就是RimeProcessKey会返回True,所以这里不应该来到这个if分支。

我不太懂Emscripten WASM和前端,似乎没看到Module.ccall('process', ...相应的C函数?而且rime_api好像也并没有一个叫process的函数吧。本来就是想看一下这个process的返回值是哪里构建的,据我看的librime源码,RimeSimulateKeySequence好像不能直接从它的返回值得知是否被processors消费掉,741行的返回值并没有使用,返回False只是代表着Parse失败:
https://github.com/rime/librime/blob/d0d227c70daa25c9671e8355b042c0c1697c2de4/src/rime_api.cc#L730-L744

只有RimeProcessKey可以反映出:
https://github.com/rime/librime/blob/d0d227c70daa25c9671e8355b042c0c1697c2de4/src/rime/engine.cc#L96-L115

process定义在

const process: (input: string) => Promise<string> = worker.register('process')

到这里还是在主线程。我把worker通信逻辑(postMessage)封装在了https://github.com/LibreService/my_worker

然后这里就已经是worker线程了

my_rime/src/worker.ts

Lines 91 to 93 in 5c14af4

process (input: string): string {
return Module.ccall('process', 'string', ['string'], [input])
}

ccall能调的函数要么是被EMSCRIPTEN_KEEPALIVE修饰,要么是在emcc/em++时显式export
'-s', 'EXPORTED_FUNCTIONS=_init,_set_option,_set_ime,_process',

最终找到https://github.com/LibreService/my_rime/blob/master/wasm/api.cpp ,封装了librime,把结果以json形式传给前端。

哦看到了。刚才IDEA发毛病了,全局搜索没搜到。似乎不应以是否commit了来判断key event是否被消费掉?

我也试着写了个rime-tui,就是用的之前我说的,如果processors没处理再执行默认行为。用的就是RimeProcessKey。没有问题。
https://github.com/bczhc/rime-tui/blob/cc5c7894c48bf8fe4b15fe49c962bb5f8c9948e2/src/main.rs#L85-L99
https://github.com/bczhc/librime-rs/blob/8b745820b8b28d7a007f436605f3bcc882ede72e/src/lib.rs#L129-L132

ba81732 解决了。我本来打算在前端搞,然后发现你说的对,这其实是后端没能区分是透传还是丢弃。但是rime api没开我要的口子(既parse又给process返回值),我就用上一步有没有pre edit来区分了。反正测试都在,要是还有特殊情况我再想办法。