#author("2026-09-17T10:50:05+09:00","","")
#author("2026-09-19T10:41:04+09:00","","")
* keyevent Event class [#q9b401c0]

KeyEvent
|name|type|desc|
|source|KeyEventSource|発生源 "on_key" | "keymap" | "undefined"|
|type|KeyEventType|"click" | "repeat" | "tap"|
|ng_repeat|boolean|誤判定の可能性あり|
|key|string|押されたkey ex. "j" ( "gj"  の対応は未定 )|
|prev_key|string|直前に押されたキー(なければ"")|
|time|integer|発生経過時間(ms)|
|interval|integer|前回key eventからの経過時間(最初のkey evetの場合はvimが起動してからevent発生までの経過時間)(ms)|
|nt|integer|同一キー連打回数。1から始まる。|
|nr|integer|hold中に発生したrepeat回数。1から始まる。type="repeat"以外では0|
|hold_start|integer|hold開始時間|

廃止した項目と理由

- vim_count : rush.nvim などで独自に取得する

** key, meta parse : <C-j> -> ctrl + j [#p7bbd846]

- 1文字の場合、小文字にしてkeyにセット、大文字の場合shift_maskをmetaにセット
- <?>場合、?を取り出して上記処理をする
- <(?-)*?>場合、全部小文字にする、最後の?をkeyにセット、"?-"の?はKEY_EVENT_META_MASKを使ってmetaにセット
- その他、そのままkeyにセット

** key, meta unparse : ctrl + j -> <C-j> [#i30d6e81]

- すべて <(?-)*?> 形式にする。大文字の場合も"S"をつける

* KeyEvent取得方法 [#pca00764]

** keymap.set 関数で取得 [#y96e2628]

keymap.set 関数内でKeyEvent.keymap_event(typed) の戻り値で取得

** keymap.on_key 関数で取得 [#gd019f79]

keymap.on_keyでcall back関数を設定して取得。詳細は未定

* アルゴリズム [#r821090f]

** interval type (内部関数) [#y408fb72]

- is_hold : config.hold1 <= event.interval <= config.hold2
- is_repeat : config.rep1 <= event.interval <= config.rep2
- is_tap : config.use_tap and event.interval <= config.tap
- is_hold, is_repeat は範囲が重なる場合、両方成立する場合がある

** no_hold | hold state (内部変数) [#c0da6b3b]

- 状態マシンでno_hold, hold の状態を取る
- キーを押しっぱなしの状態がhold, そうでない場合no_holdとする
- ただしこれは推定なので実際の物理的状態を正確には反映しない
- また判定のタイミングは遅れるため最初のキーダウンがhold開始かどうかの判定は次のキー入力まで保留され、リアルタイムではわからない

そのアルゴリズム

- 最初はno_hold stateとする
- no_hold stateでevent.key == event.prev_key and is_hold が発生したらhold stateに移る
- hold stateでevent.key != envent.prev_key or is_repeat 以外が発生したらno_hold stateに移る

** KeyEventType [#a9814343]

キーイベント推定値

- tap : 短い間隔でキーをタイプした
- click : 間隔をあけてキーをタイプした
- repeat : キー押し下げでOSがrepeatした

そのアルゴリズム

- tap : no_hold state で is_tap
- click : no_hold state で is_click
- repeat : hold stateで is_repeat

ng_repeatについて
- ng_repeat : no_hold state で is_repeat の場合true
- type = "click" | "tap" を返す
- 次の可能性がある
-- tap|click だが、たまたま is_repeat 範囲に入った
-- hold state開始の is_hold誤判定
-- no_hold state開始の is_repeat誤判定

** 利用例(アイデア) [#ea270e17]

- keymap.setを使用し、KeyEventの内容をみてreturnする文字列や振る舞いを自由に設定することができる
- rush.nvim :
-- j<hold-j>(タタン)で"2j"
-- タタタンで"4j"
-- 続けてタタンで加速、タンで減速
- dontaka.nvim (作成中)
-- ケーボードをリズミカルに叩くことでnvimとjam session
- キーボードジェスチャーによるローンチャー(on_key callback)
-- 例、n,<hold-n>の場合、検索履歴表示
-- 例、j,kの場合、return <esc> : これはinsert mode向きではない
-- 例、j,<hold-k>の場合、女子高生とのチャットゲーム開始

** rush.nvim [#f55c4d55]

- j<hold-j>の場合:括弧の中は(nt,nr)。以下同様。
- click-j(1,0), tap-j(2,0), repeat-j(2,1), repeat-j(2,2), ... となるので
- nt>=2 and nr!=0なら return 2^nt .. "j" とする
- <hold-j>の場合
- click-j(1,0), repeat-j(1,1), repeat-j(1,2), ... となるので
- nt==1 and nr!=0なら return vim_count .. "j" とする(vim_countはclick-jの時のnvim.v.count)

** 概要 [#u36c1611]

- keymap.set で置き換えたkeymapを監視する。置き換えるキーは具体的には "j", <C-f>, "gj" など。
-- <C-f>, "gj" などはまだ実験していない
- key K を長押しする操作を<hold-K>と表記する
- 同時にon_keyで置き換えていないkey eventを監視する。(<C-f>などの場合どうするかは未定)
- keymap.set で登録した関数が呼び出されるたびにrush eventを発生させる
- rush eventの内容
-- 発生時間(vim.loop.hrtime)
-- 押されたkey
-- 連打開始直前に押されたキー(なければ"")
-- vim_count:連打開始時のvim.v.count 
-- 前回key eventからの時間間隔(最初のkey evetの場合はvimが起動してからevent発生までの時間間隔)
- rush eventの種類
-- tap: 前と同じキーが短時間(おおよそinterval.rep以内)に続けて押された 
--- 同一キー連打回数ntを提供する。連打開始はclickになるので、tapの場合2からはじまる
-- start: キーを押し込んだ最初のeventはtap|clickだが2番目のkey eventはhold-startと判定する
--- start2がよいか?
-- repeat: キーを押し込んだ後3番目以降のkey eventはrepeat rush eventと判定する
--- hold時間を提供する。hold時間とはhold開始からの経過時間。最初は≒interval.hold2+interval.rep
--- repeat回数nrを提供する。repeat回数とはhold中に発生したkey event回数。3から始まる。
-- click: その他のkey event。連打でない場合、時間をおいてタイプの場合に相当する
-- repeat-end: hold終了event。repeatからinterval.rep経過後repat eventがなければ発生する。またはrepeat以外のeventが発生する直前に発生する
- 具体例
-- しばらく時間をおいてから"jjk<hold-k>"と連続タイプした場合のrush event概要
-- click-j(1,0), tap-j(2,0), tap-k(1,0), tap-k(2,0), start-k(2,2), repeat-k(2,3), repeat-k(2,4), ..., repeat-end(2,n)
-- 括弧は(nt,nr)

Front page   Edit Diff History Attach Copy Rename Reload   New Page list Search Recent changes   Help   RSS of recent changes