Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ input letter.
resolution (no flash.nvim dependency)
- `match.lua` — matching domain: segmentation parser, punctuation classes,
language-lock markers, mixed-mode compiler
- `patches.lua` — flash.nvim patches (C-c dispatch, prompt lock display)
- `patches.lua` — flash.nvim patches (C-c dispatch, prompt lock display, char-motion f/t/F/T search-mode wrap)
- `util.lua` — shared helpers
- `labeler.lua` — flash labeler: next-letter prediction (from spellings or the Rust matcher's per-match predictions), skip-set, monotonic label pool
- `rust.lua` — bridge to the native matcher: persistent UDS server transport (Unix, zero config), per-keystroke spawn fallback, JSON protocol, circuit breaker to the vim-regex path
Expand Down
27 changes: 27 additions & 0 deletions README.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ Neovim ≥ 0.10 と [flash.nvim](https://github.com/folke/flash.nvim) が必要
},
priority = { "zhcn", "ja", "ko" },
mixed_input = true,
motions = { char = true, search = true },
}
```

Expand All @@ -89,6 +90,24 @@ Neovim ≥ 0.10 と [flash.nvim](https://github.com/folke/flash.nvim) が必要

1 回のクエリに、異なる言語の入力コードを混在させられます。入力例は下の使い方の「混合入力」を参照してください。

### `motions`

flash.nvim 自身が持つモーションへの統括設定です。現時点では flash の `modes.char` と `/` 検索モードに対応しており、将来的に他の flash 自身の入口もここに追加されます。

#### `char`

flash.nvim 内蔵の拡張文字モーション(flash の `modes.char`、デフォルトで有効)を CJK 対応にします。入力した 1 文字が、`s` ジャンプと同じ多言語エンジンでマッチされます。`fv` で「中」へジャンプでき(小鶴双拼の zhong の頭文字 `v`)、`ft` なら「中」(日本語訓令式ローマ字 `tyuu`)や「梯」(ピンイン `ti`)に到達します。`;`/`,` の循環、カウント、オペレータ待機時の挙動は flash ネイティブのモーションとまったく同じです。マッチングは 1 文字のみで、複数キーの読みを入力したい場合は `s` を使ってください。`setup({ motions = { char = false } })` を設定すると、flash ネイティブの ASCII 専用の挙動に戻ります。

#### `search`

flash.nvim の検索統合を通して、`/` と `?` のラベルオーバーレイを CJK 対応にします。これには flash 自身の検索モードが必要で、flash では**デフォルトで無効**です。flash の設定で有効にしてください:

```lua
{ modes = { search = { enabled = true } } }
```

クエリ(ピンイン/ローマ字)を入力すると、CJK のマッチに flash-cjk の予測ラベルが表示され、ラベル文字を押すだけでジャンプできます。ラベルが入力の続きになりそうな文字と衝突することはないため、クエリを打ち続けていて意図せずジャンプしてしまうことはありません。`<cr>` を押せばクエリをそのまま検索として確定し、`n`/`N` はネイティブな vim の挙動のままです。vim 正規表現のメタ文字(`\ . * [ ] ^ $ ~ /`)や非 ASCII バイトを含むクエリはネイティブな vim 正規表現としてそのまま渡されるため、`/.*` や `/^func` は従来どおり動作します。`/` パスでの句読点の CJK クラスは非メタ文字キー(`, ; : ' "` など)のみを対象とし、`s` ジャンプでは `.` `?` `[` `]` を含む完全なセットが引き続き使えます。

## ⌨️ 使い方

操作は flash.nvim とほぼ同じです。`s` を押し、目的のテキストに対応する入力コードを入力するだけです。以下の例では、トリガーキー `s` を含めた完全なキー列で示します。
Expand All @@ -105,6 +124,14 @@ English, a中文,日本語, 한국어. Hello, 你好,こんにちは、안

`sav` と入力すると「a中」にマッチします。`a` は ASCII としてリテラルマッチし、`v` は小鶴双拼における「中」の入力コードのプレフィックスです。

### 文字モーション

同じエンジンは `f`/`t`/`F`/`T`(flash の拡張文字モーション)にも作用します。上のサンプル行では、`fv` で「中」へジャンプできます。

### 検索

flash の検索モードを有効にすれば、`/ti` と入力したときに 梯/ち に flash-cjk のラベルが表示され、ラベルを押すとジャンプします。

### 多言語マッチング

`sn` と入力すると、クエリ文字 `n` が次のすべてに同時にマッチします:
Expand Down
27 changes: 27 additions & 0 deletions README.ko.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ Neovim ≥ 0.10과 [flash.nvim](https://github.com/folke/flash.nvim)이 필요
},
priority = { "zhcn", "ja", "ko" },
mixed_input = true,
motions = { char = true, search = true },
}
```

Expand All @@ -89,6 +90,24 @@ Neovim ≥ 0.10과 [flash.nvim](https://github.com/folke/flash.nvim)이 필요

하나의 쿼리에 서로 다른 언어의 입력 코드를 섞어 사용할 수 있습니다. 아래 사용법 예시의 혼합 입력을 참고하세요.

### `motions`

flash.nvim 자체 모션에 대한 통합 설정 묶음입니다. 현재는 flash의 `modes.char`와 `/` 검색 모드를 지원하며, 향후 다른 flash 자체 진입점도 여기서 설정하게 됩니다.

#### `char`

flash.nvim 내장 확장 문자 모션(flash의 `modes.char`, 기본 활성화)도 CJK 매칭을 지원하게 합니다. 입력한 한 글자가 `s` 점프와 동일한 다국어 엔진으로 매칭됩니다. `fv`로 「中」에 점프할 수 있고(샤오헤 쌍병음에서 zhong의 초성 `v`), `ft`면 「中」(일본어 훈레이식 로마자 `tyuu`)이나 「梯」(병음 `ti`)에 도달합니다. `;`/`,` 순환, 카운트, 오퍼레이터 대기 동작은 flash 네이티브 모션과 완전히 같습니다. 매칭은 한 글자만 지원하며, 여러 키로 이루어진 읽기를 입력하려면 `s`를 사용하세요. `setup({ motions = { char = false } })`로 설정하면 flash 네이티브의 ASCII 전용 동작으로 되돌아갑니다.

#### `search`

flash.nvim의 검색 통합을 통해 `/`와 `?`의 라벨 오버레이를 CJK 매칭으로 확장합니다. 이 기능은 flash 자체의 검색 모드가 필요한데, flash에서는 **기본 비활성화**입니다. flash 설정에서 활성화하세요:

```lua
{ modes = { search = { enabled = true } } }
```

쿼리(병음/로마자)를 입력하면 CJK 매칭에 flash-cjk의 예측 라벨이 표시되고, 라벨 문자를 누르면 점프합니다. 라벨은 이어 입력할 가능성이 있는 문자와 절대 충돌하지 않으므로, 쿼리를 계속 입력하다가 의도치 않게 점프하는 일은 없습니다. `<cr>`을 누르면 쿼리를 그대로 검색으로 확정하고, `n`/`N`은 네이티브 vim 동작을 유지합니다. vim 정규식 메타 문자(`\ . * [ ] ^ $ ~ /`)나 비 ASCII 바이트를 포함한 쿼리는 네이티브 vim 정규식으로 그대로 전달되므로 `/.*`와 `/^func`는 이전과 똑같이 동작합니다. `/` 경로에서 문장 부호 CJK 클래스는 메타 문자가 아닌 키(`, ; : ' "` 등)만 다루며, `s` 점프는 `.` `?` `[` `]`를 포함한 전체 집합을 계속 유지합니다.

## ⌨️ 사용법

사용 방법은 flash.nvim과 거의 같습니다. `s`를 누른 다음 대상 텍스트의 입력 코드를 입력하면 됩니다. 아래 예시에서는 트리거 키 `s`를 포함한 전체 키 시퀀스를 보여 줍니다.
Expand All @@ -105,6 +124,14 @@ English, a中文,日本語, 한국어. Hello, 你好,こんにちは、안

`sav`를 입력하면 「a中」에 매칭됩니다. `a`는 ASCII로 리터럴 매칭되고, `v`는 샤오헤 쌍병음에서 「中」의 입력 코드 접두사입니다.

### 문자 모션

같은 엔진은 `f`/`t`/`F`/`T`(flash의 확장 문자 모션)에도 적용됩니다. 위 샘플 행에서 `fv`를 입력하면 「中」로 점프합니다.

### 검색

flash의 검색 모드를 활성화하면 `/ti` 입력 시 梯/ち에 flash-cjk 라벨이 표시되고, 라벨을 누르면 점프합니다.

### 다국어 매칭

`sn`을 입력하면 쿼리 문자 `n`이 다음 항목을 동시에 매칭합니다:
Expand Down
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ Default configuration:
},
priority = { "zhcn", "ja", "ko" },
mixed_input = true,
motions = { char = true, search = true },
}
```

Expand All @@ -89,6 +90,24 @@ When multiple languages match at once, `priority = { "zhcn", "ja", "ko" }` deter

Allows a single query to mix input codes from different languages. See Mixed input in the usage examples below.

### `motions`

Groups the integrations on motions flash.nvim itself owns. Today that is flash's `modes.char` and the `/` search mode; future flash-owned surfaces would be configured here as well.

#### `char`

Makes flash.nvim's built-in enhanced char motions (flash's `modes.char`, enabled by default) CJK-aware. A single typed character is matched through the same multi-language engine as `s`-jumps: `fv` jumps to `中` (Xiaohe `v` initial for zhong), while `ft` reaches `中` (Japanese kunrei-shiki `tyuu`) or `梯` (pinyin `ti`). `;`/`,` cycling, counts, and operator-pending behave exactly like flash's native motions. Matching is single-character only — press `s` for full multi-key readings. Set `setup({ motions = { char = false } })` to restore flash's native ASCII-only behavior.

#### `search`

Makes the `/` and `?` label overlays CJK-aware through flash.nvim's search integration. This requires flash's own search mode, which is **off by default in flash** — enable it in your flash opts:

```lua
{ modes = { search = { enabled = true } } }
```

Type the query (pinyin/romaji letters) and flash-cjk's predictive labels appear on CJK matches; press a label char to jump. Labels never collide with likely continuation letters, so extending the query never jumps you somewhere unexpected. Pressing `<cr>` commits the search as typed, and `n`/`N` keep native vim semantics. Queries containing vim regex metacharacters (`\ . * [ ] ^ $ ~ /`) or non-ASCII bytes pass through as native vim regex, so `/.*` and `/^func` keep working exactly as before. On the `/` path, punctuation CJK classes cover only non-metacharacter keys (e.g. `, ; : ' "`); the `s`-jump keeps the full set including `.` `?` `[` `]`.

## ⌨️ Usage

Usage is almost identical to flash.nvim: press `s`, then type the input code for the target text. The examples below include the trigger key `s` as part of the full key sequence.
Expand All @@ -105,6 +124,14 @@ Type `si` (`s` starts flash-cjk and `i` is the query) to match the `i` in `Engli

Type `sav` to match `a中`: `a` is matched literally as ASCII, while `v` is the Xiaohe double pinyin code prefix for `中`.

### Char motions

The same engine also powers `f`/`t`/`F`/`T` (flash's enhanced char motions). On the sample line above, `fv` jumps to `中`.

### Search

With flash's search mode enabled, `/ti` shows flash-cjk labels on 梯/ち; press the label to jump.

### Multi-language matching

Type `sn`, and the query character `n` matches all of the following at once:
Expand Down
27 changes: 27 additions & 0 deletions README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ https://github.com/user-attachments/assets/37599dab-b0c6-4d90-8463-cb4706841ac3
},
priority = { "zhcn", "ja", "ko" },
mixed_input = true,
motions = { char = true, search = true },
}
```

Expand All @@ -89,6 +90,24 @@ https://github.com/user-attachments/assets/37599dab-b0c6-4d90-8463-cb4706841ac3

允许一次查询同时包含不同语言的输入码,见下方使用示例中的混合输入。

### `motions`

用于集中配置 flash.nvim 自有移动方式的集成。目前包括 flash 的 `modes.char` 和 `/` 搜索模式,未来其他 flash 自有的入口也会放在这里配置。

#### `char`

让 flash.nvim 内置的增强字符移动(flash 的 `modes.char`,默认开启)也支持 CJK 匹配。输入的单个字符会通过与 `s` 跳转相同的多语言引擎匹配:`fv` 可以跳到「中」(小鹤双拼中 zhong 的声母 `v`),`ft` 则能到达「中」(日语训令式罗马字 `tyuu`)或「梯」(拼音 `ti`)。`;`/`,` 循环、计数和 operator-pending 行为与 flash 原生移动完全一致。匹配只支持单个字符——需要完整的多键输入码时请按 `s`。设置 `setup({ motions = { char = false } })` 即可恢复 flash 原生的纯 ASCII 行为。

#### `search`

通过 flash.nvim 的搜索集成,让 `/` 和 `?` 的标签覆盖层支持 CJK 匹配。它依赖 flash 自身的搜索模式,而该模式在 flash 中**默认关闭**——需要在 flash 的配置中开启:

```lua
{ modes = { search = { enabled = true } } }
```

输入查询(拼音/罗马字字母)后,flash-cjk 的预测式标签会出现在 CJK 匹配项上,按下标签字符即可跳转。标签绝不会与可能的后续输入字母冲突,因此继续输入查询不会被意外跳走。直接按 `<cr>` 会按原样提交搜索,`n`/`N` 保持原生 vim 语义。包含 vim 正则元字符(`\ . * [ ] ^ $ ~ /`)或非 ASCII 字节的查询会原样交给原生 vim 正则处理,所以 `/.*`、`/^func` 的行为和以前完全一样。在 `/` 路径上,标点的 CJK 匹配类只覆盖非元字符键(如 `, ; : ' "`);`s` 跳转仍保留包括 `.` `?` `[` `]` 在内的完整集合。

## ⌨️ 使用

用法和 flash.nvim 基本一致:按下 `s`,再输入目标文本的输入码即可。下面的示例会把触发键 `s` 一并写入完整按键序列。
Expand All @@ -105,6 +124,14 @@ English, a中文,日本語, 한국어. Hello, 你好,こんにちは、안

输入 `sav` 可以匹配「a中」:`a` 使用 ASCII 字面匹配,`v` 是小鹤双拼中「中」的输入码前缀。

### 字符移动

同样的引擎也作用于 `f`/`t`/`F`/`T`(flash 的增强字符移动)。在上面这行示例中,`fv` 会跳到「中」。

### 搜索

开启 flash 的搜索模式后,输入 `/ti` 会在 梯/ち 上显示 flash-cjk 标签,按下标签即可跳转。

### 多语言匹配

输入 `sn` 后,查询字符 `n` 会同时匹配:
Expand Down
26 changes: 26 additions & 0 deletions lua/flash-cjk/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ M.config = {
},
priority = { "zhcn", "ja", "ko" },
mixed_input = true,
-- integrations on flash-owned entry points (char: CJK-aware
-- f/t/F/T, search: CJK-aware / and ?)
motions = { char = true, search = true },
}

---Normalizes one languages[lang] value: true -> enabled, false ->
Expand Down Expand Up @@ -57,6 +60,29 @@ function M.normalize_language(lang, value)
return normalized
end

---Normalizes a motions value: known motion flags must be booleans (a
---non-boolean like the string "false" is truthy in Lua and would
---silently enable the integration). Unknown fields are ignored
---(forward compatibility).
---@param motions table
---@return table normalized { char?: boolean, search?: boolean }
function M.normalize_motions(motions)
local normalized = {}
if motions.char ~= nil then
if type(motions.char) ~= "boolean" then
error("flash-cjk: motions.char must be a boolean")
end
normalized.char = motions.char
end
if motions.search ~= nil then
if type(motions.search) ~= "boolean" then
error("flash-cjk: motions.search must be a boolean")
end
normalized.search = motions.search
end
return normalized
end

---Base entry a language's setup() merge starts from: the built-in
---defaults for en, an empty table elsewhere (existing entries merge
---onto themselves).
Expand Down
18 changes: 18 additions & 0 deletions lua/flash-cjk/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ local function build_opts(langs)
-- lock is configured; everything else keeps flash's behavior.
patches.get_char_patch()
patches.prompt_patch()
patches.char_mode_patch()
patches.search_mode_patch()
local defaults = {
labels = "asdfghjklqwertyuiopzxcvbnm",
search = {
Expand Down Expand Up @@ -114,10 +116,26 @@ function M.setup(opts)
if type(opts.mixed_input) == "boolean" then
M.config.mixed_input = opts.mixed_input
end
if opts.motions ~= nil then
if type(opts.motions) ~= "table" then
error("flash-cjk: motions must be a table")
end
M.config.motions = vim.tbl_deep_extend(
"force",
{},
M.config.motions,
config.normalize_motions(opts.motions)
)
end
if opts.priority ~= nil then
-- labeler-layer only: the mix mode does not read it
M.config.priority = config.normalize_priority(opts.priority)
end
-- also installed here so ftFT and `/` are CJK-aware before the
-- first jump: flash-cjk loads before flash's first f/F/t/T press
-- or `/` search
patches.char_mode_patch()
patches.search_mode_patch()
end

return M
Loading