ruvim 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +4 -0
- data/AGENTS.md +84 -0
- data/CLAUDE.md +1 -0
- data/docs/binding.md +23 -0
- data/docs/command.md +85 -0
- data/docs/config.md +2 -2
- data/docs/done.md +21 -0
- data/docs/spec.md +157 -12
- data/docs/todo.md +1 -5
- data/docs/vim_diff.md +94 -172
- data/lib/ruvim/app.rb +882 -69
- data/lib/ruvim/buffer.rb +35 -1
- data/lib/ruvim/cli.rb +12 -3
- data/lib/ruvim/clipboard.rb +2 -0
- data/lib/ruvim/command_invocation.rb +3 -1
- data/lib/ruvim/command_line.rb +2 -0
- data/lib/ruvim/command_registry.rb +2 -0
- data/lib/ruvim/config_dsl.rb +2 -0
- data/lib/ruvim/config_loader.rb +2 -0
- data/lib/ruvim/context.rb +2 -0
- data/lib/ruvim/dispatcher.rb +143 -13
- data/lib/ruvim/display_width.rb +3 -0
- data/lib/ruvim/editor.rb +455 -71
- data/lib/ruvim/ex_command_registry.rb +2 -0
- data/lib/ruvim/global_commands.rb +890 -63
- data/lib/ruvim/highlighter.rb +16 -21
- data/lib/ruvim/input.rb +39 -28
- data/lib/ruvim/keymap_manager.rb +83 -0
- data/lib/ruvim/keyword_chars.rb +2 -0
- data/lib/ruvim/lang/base.rb +25 -0
- data/lib/ruvim/lang/csv.rb +18 -0
- data/lib/ruvim/lang/json.rb +18 -0
- data/lib/ruvim/lang/markdown.rb +170 -0
- data/lib/ruvim/lang/ruby.rb +236 -0
- data/lib/ruvim/lang/scheme.rb +44 -0
- data/lib/ruvim/lang/tsv.rb +19 -0
- data/lib/ruvim/rich_view/markdown_renderer.rb +248 -0
- data/lib/ruvim/rich_view/table_renderer.rb +176 -0
- data/lib/ruvim/rich_view.rb +93 -0
- data/lib/ruvim/screen.rb +503 -106
- data/lib/ruvim/terminal.rb +18 -1
- data/lib/ruvim/text_metrics.rb +2 -0
- data/lib/ruvim/version.rb +1 -1
- data/lib/ruvim/window.rb +2 -0
- data/lib/ruvim.rb +14 -0
- data/test/app_completion_test.rb +73 -0
- data/test/app_dot_repeat_test.rb +13 -0
- data/test/app_motion_test.rb +13 -0
- data/test/app_scenario_test.rb +729 -1
- data/test/app_startup_test.rb +187 -0
- data/test/arglist_test.rb +113 -0
- data/test/buffer_test.rb +49 -30
- data/test/dispatcher_test.rb +322 -0
- data/test/editor_register_test.rb +23 -0
- data/test/highlighter_test.rb +121 -0
- data/test/indent_test.rb +201 -0
- data/test/input_screen_integration_test.rb +40 -2
- data/test/markdown_renderer_test.rb +279 -0
- data/test/on_save_hook_test.rb +150 -0
- data/test/rich_view_test.rb +478 -0
- data/test/screen_test.rb +304 -0
- metadata +33 -2
data/docs/spec.md
CHANGED
|
@@ -89,10 +89,10 @@ RuVim は Vim と同様に、用途ごとに座標系を分けています。
|
|
|
89
89
|
エディタ全体の実行状態です。
|
|
90
90
|
|
|
91
91
|
- buffers / windows 管理
|
|
92
|
-
-
|
|
93
|
-
- tabpages 管理(タブごとに
|
|
92
|
+
- layout tree(ネストしたウィンドウ分割をツリーで管理)
|
|
93
|
+
- tabpages 管理(タブごとに layout tree / current window を保持)
|
|
94
94
|
- current window の管理
|
|
95
|
-
- mode 管理(`:normal`, `:insert`, `:command_line`)
|
|
95
|
+
- mode 管理(`:normal`, `:insert`, `:command_line`, `:rich`)
|
|
96
96
|
- ステータスメッセージ
|
|
97
97
|
- コマンドライン状態
|
|
98
98
|
|
|
@@ -166,7 +166,8 @@ RuVim::ExCommandRegistry.instance.register(
|
|
|
166
166
|
2. `RuVim::App` が mode ごとに処理を分岐
|
|
167
167
|
3. Normal mode のキーは `RuVim::KeymapManager` で解決
|
|
168
168
|
4. `RuVim::Dispatcher` が内部コマンド or Ex コマンドを実行
|
|
169
|
-
5.
|
|
169
|
+
5. Insert mode でキー処理後、stdin に未読データが残っていればレンダリングをスキップして追加のキーを読み取り・処理する(ペースト高速化)
|
|
170
|
+
6. `RuVim::Screen` が再描画
|
|
170
171
|
|
|
171
172
|
## 起動オプション(CLI, 現状)
|
|
172
173
|
|
|
@@ -211,6 +212,17 @@ RuVim::ExCommandRegistry.instance.register(
|
|
|
211
212
|
- `+{cmd}`, `+{line}`, `+`
|
|
212
213
|
- 起動後の Ex 実行 / 行ジャンプ / 最終行ジャンプ
|
|
213
214
|
|
|
215
|
+
補足(現状実装):
|
|
216
|
+
|
|
217
|
+
- `stdin` が non-TTY で、起動引数ファイルがない場合は `stdin` を follow stream として開く
|
|
218
|
+
- バッファ名は `[stdin]`
|
|
219
|
+
- status line に `[stdin/live]`, `[stdin/closed]`, `[stdin/error]` を表示
|
|
220
|
+
- Normal mode の `Ctrl-c` はデフォルトバインドで `stdin` stream stop(上流 PID へ直接 signal は送らない)
|
|
221
|
+
- `Ctrl-z` は全モード共通で suspend
|
|
222
|
+
- suspend 前に terminal を cooked + main screen に戻す
|
|
223
|
+
- `SIGTSTP` を自身に送って停止
|
|
224
|
+
- `fg` 復帰後に raw + alt screen を再有効化して再描画
|
|
225
|
+
|
|
214
226
|
起動時コマンド(`-c`, `+...`)は、初期 buffer / file open / intro screen 構築の後に実行します。
|
|
215
227
|
`--cmd` はそれより前で、user config 読み込み前に実行します。
|
|
216
228
|
|
|
@@ -253,6 +265,7 @@ RuVim::ExCommandRegistry.instance.register(
|
|
|
253
265
|
- `p`, `P`: paste
|
|
254
266
|
- `r<char>`: 1文字置換
|
|
255
267
|
- `c` + motion / `cc`: change(削除して Insert mode)
|
|
268
|
+
- `=` + motion / `==`: auto-indent(Ruby filetype でインデント自動調整。`=j`, `=G` 等)
|
|
256
269
|
- `v`: Visual (characterwise)
|
|
257
270
|
- `V`: Visual (linewise)
|
|
258
271
|
- `Ctrl-v`: Visual (blockwise, 最小)
|
|
@@ -263,6 +276,7 @@ RuVim::ExCommandRegistry.instance.register(
|
|
|
263
276
|
- `N`: 直前検索を逆方向に繰り返し
|
|
264
277
|
- `1..9` + 動作: count(例: `3j`, `2x`)
|
|
265
278
|
- 矢印キー: 移動
|
|
279
|
+
- `Ctrl-z`: shell へ suspend(`fg` で復帰)
|
|
266
280
|
|
|
267
281
|
### Insert mode
|
|
268
282
|
|
|
@@ -273,6 +287,7 @@ RuVim::ExCommandRegistry.instance.register(
|
|
|
273
287
|
- `Esc`: Normal mode に戻る
|
|
274
288
|
- `Ctrl-c`: Normal mode に戻る(終了しない)
|
|
275
289
|
- 矢印キー: 移動
|
|
290
|
+
- `Ctrl-z`: shell へ suspend(`fg` で復帰)
|
|
276
291
|
|
|
277
292
|
### Visual mode(現状)
|
|
278
293
|
|
|
@@ -284,8 +299,20 @@ RuVim::ExCommandRegistry.instance.register(
|
|
|
284
299
|
- `d`: 選択範囲を delete
|
|
285
300
|
- `i`/`a` + object: text object を選択(`iw`, `aw`, `ip`, `ap`, `i"`, `a"`, ``i` ``, ``a` ``, `i)`, `a)`, `i]`, `a]`, `i}`, `a}`)
|
|
286
301
|
- `Esc` / `Ctrl-c`: Normal mode に戻る
|
|
302
|
+
- `Ctrl-z`: shell へ suspend(`fg` で復帰)
|
|
287
303
|
- blockwise の text object 選択 / paste の Vim 互換挙動は未対応
|
|
288
304
|
|
|
305
|
+
### Rich mode
|
|
306
|
+
|
|
307
|
+
- `:rich [format]` / `gr` で入る(トグル)
|
|
308
|
+
- 同一バッファ上で動作(仮想バッファを作らない)
|
|
309
|
+
- Normal mode とほぼ同じキーバインドが使える(移動・検索・yank 等)
|
|
310
|
+
- バッファを変更する操作(insert/delete/change/paste/replace)はブロック
|
|
311
|
+
- `Esc` / `Ctrl-C` で Normal mode に戻る
|
|
312
|
+
- ステータスラインに `-- RICH --` を表示
|
|
313
|
+
- 描画時に表示行をテーブル整形(`TableRenderer` を利用)
|
|
314
|
+
- wrap は強制 OFF
|
|
315
|
+
|
|
289
316
|
### Command-line mode
|
|
290
317
|
|
|
291
318
|
- `:` で入る
|
|
@@ -297,16 +324,36 @@ RuVim::ExCommandRegistry.instance.register(
|
|
|
297
324
|
- `Tab` (`Ctrl-i`) で Ex 補完
|
|
298
325
|
- コマンド名
|
|
299
326
|
- 一部引数(path / buffer / option)
|
|
327
|
+
- `Ctrl-z` で shell へ suspend(`fg` で復帰)
|
|
328
|
+
|
|
329
|
+
### Hit-enter prompt(複数行メッセージ表示)
|
|
330
|
+
|
|
331
|
+
`:ls` や `:set`(引数なし)など、複数行にわたる出力を行うコマンドの結果を表示するモード。
|
|
332
|
+
|
|
333
|
+
- 画面下部にメッセージ行をオーバーレイ描画
|
|
334
|
+
- 最下行に「Press ENTER or type command to continue」を反転表示
|
|
335
|
+
- ステータスラインは非表示(Vim と同様)
|
|
336
|
+
- 対象コマンド: `:ls` / `:buffers`, `:args`, `:set`(引数なし), `:command`(引数なし)
|
|
337
|
+
- 1行以下の出力時は通常の `echo` を使用
|
|
338
|
+
|
|
339
|
+
#### キー操作
|
|
340
|
+
|
|
341
|
+
- `Enter` / `Space` / `Escape` / `Ctrl-C` / その他のキー → dismiss(通常モードに戻る)
|
|
342
|
+
- `:` → dismiss して Command-line mode に入る
|
|
343
|
+
- `/` / `?` → dismiss して検索 Command-line mode に入る
|
|
300
344
|
|
|
301
345
|
## Ex コマンド仕様(現状 builtin)
|
|
302
346
|
|
|
303
347
|
- `:w [path]` / `:write [path]`
|
|
304
348
|
- `:q[!]` / `:quit[!]`
|
|
349
|
+
- `:qa[!]` / `:qall[!]`
|
|
305
350
|
- `:wq[!] [path]`
|
|
351
|
+
- `:wqa[!]` / `:wqall[!]` / `:xa[!]` / `:xall[!]`
|
|
306
352
|
- `:e <path>` / `:edit <path>`
|
|
307
353
|
- `:e[!] [path]` / `:edit[!] [path]`
|
|
308
354
|
- `:help [topic]`
|
|
309
355
|
- `:commands`
|
|
356
|
+
- `:bindings [mode]`
|
|
310
357
|
- `:command[!] <Name> <ex-body>`
|
|
311
358
|
- `:ruby <code>` / `:rb <code>`
|
|
312
359
|
- `:!<command>`
|
|
@@ -323,6 +370,7 @@ RuVim::ExCommandRegistry.instance.register(
|
|
|
323
370
|
- `:vimgrep`, `:lvimgrep`
|
|
324
371
|
- `:copen`, `:cclose`, `:cnext` / `:cn`, `:cprev` / `:cp`
|
|
325
372
|
- `:lopen`, `:lclose`, `:lnext` / `:ln`, `:lprev` / `:lp`
|
|
373
|
+
- `:rich [format]`
|
|
326
374
|
|
|
327
375
|
## 検索仕様(現状)
|
|
328
376
|
|
|
@@ -347,10 +395,20 @@ RuVim::ExCommandRegistry.instance.register(
|
|
|
347
395
|
- `:q` は未保存変更があると拒否
|
|
348
396
|
- `:q` は Vim 寄りに、複数 window 時は current window を閉じる(window が1つで tab が複数なら current tab を閉じる)
|
|
349
397
|
- `:q!` は強制的に window / tab / app を閉じる
|
|
398
|
+
- `:qa` は全ウィンドウ/タブを無視して一括終了(未保存バッファがあると拒否、`:qa!` で強制)
|
|
399
|
+
- `:wqa` は全バッファを保存して一括終了
|
|
350
400
|
- `:e` は未保存変更があると拒否(`!` で破棄可)
|
|
351
401
|
- `:e!`(引数なし)は現在ファイルの再読込(undo/redo クリア)
|
|
352
402
|
- `:buffer!`, `:bnext!`, `:bprev!` は未保存変更があっても切替
|
|
353
403
|
- `:w!` は現状 `:w` と同等に受理(権限昇格などは未実装)
|
|
404
|
+
- `:bindings` は current buffer 文脈の有効 key binding を layer 別(`buffer`, `filetype`, `app`)に一覧表示
|
|
405
|
+
- 任意で mode filter を受ける(例 `:bindings normal`)
|
|
406
|
+
- 大きいファイルを開くときは、閾値以上で段階読み込みになる場合がある
|
|
407
|
+
- status line に `[load/live]`(失敗時 `[load/error]`)
|
|
408
|
+
- デフォルト実装は先頭 `8MB` を先に表示し、残りをバックグラウンド読み込み後に反映
|
|
409
|
+
- 環境変数:
|
|
410
|
+
- `RUVIM_ASYNC_FILE_THRESHOLD_BYTES`
|
|
411
|
+
- `RUVIM_ASYNC_FILE_PREFIX_BYTES`
|
|
354
412
|
|
|
355
413
|
### `:command`(現状仕様)
|
|
356
414
|
|
|
@@ -395,6 +453,16 @@ RuVim::ExCommandRegistry.instance.register(
|
|
|
395
453
|
- バッファ切替時に直前バッファを更新
|
|
396
454
|
- `:buffer #` で切替可能
|
|
397
455
|
|
|
456
|
+
### arglist(引数リスト)
|
|
457
|
+
|
|
458
|
+
- `Editor#arglist` と `Editor#arglist_index` を保持
|
|
459
|
+
- 起動時に複数ファイル引数があるとarglistが初期化される
|
|
460
|
+
- 複数ファイル起動時、レイアウトオプション未指定でも全ファイルをバッファとして読み込む(`:ls` に表示される)
|
|
461
|
+
- `:args` : arglistを表示(現在の引数は `[filename]` で表示)
|
|
462
|
+
- `:next` / `:prev` : arglist内を移動
|
|
463
|
+
- `:first` / `:last` : arglistの最初/最後に移動
|
|
464
|
+
- arglist移動時にalternate bufferも更新される
|
|
465
|
+
|
|
398
466
|
## 画面描画仕様(現状)
|
|
399
467
|
|
|
400
468
|
ANSI エスケープシーケンスによる再描画です。
|
|
@@ -409,19 +477,24 @@ ANSI エスケープシーケンスによる再描画です。
|
|
|
409
477
|
- ファイル未指定起動時は Vim 風 intro screen を表示(RuVim では intro 用の read-only 特殊バッファ)
|
|
410
478
|
- カーソル位置の文字を反転表示(見やすさ向上)
|
|
411
479
|
|
|
412
|
-
### split UI
|
|
480
|
+
### split UI
|
|
413
481
|
|
|
414
482
|
- `:split` / `:vsplit` で複数 window を作成
|
|
415
|
-
-
|
|
416
|
-
- `
|
|
417
|
-
- `
|
|
418
|
-
-
|
|
483
|
+
- レイアウトはツリー構造(ネストした分割に対応)
|
|
484
|
+
- `hsplit`: 上下分割
|
|
485
|
+
- `vsplit`: 左右分割
|
|
486
|
+
- 例: vsplit 後に右ウィンドウを split すると、右カラムだけが上下分割される
|
|
487
|
+
- 同方向の分割は親ノードにマージ(hsplit の中で hsplit しても 1 レベルに統合)
|
|
488
|
+
- `close_window` でツリーを簡略化(子が 1 個になった分割ノードは子に置き換え)
|
|
489
|
+
- `focus_window_direction` は正規化座標空間で最近接ウィンドウを選択
|
|
419
490
|
- 各 window は cursor / scroll を独立して保持
|
|
420
491
|
|
|
421
492
|
### Tabpage(現状)
|
|
422
493
|
|
|
423
494
|
- `:tabnew [path]` で新しいタブを作成
|
|
424
495
|
- `:tabnext`, `:tabprev` で移動
|
|
496
|
+
- `:tabs` で全タブ一覧を表示(各タブのウィンドウとバッファ名)
|
|
497
|
+
- ステータスラインに `tab:n/m` を表示(タブが2つ以上のとき)
|
|
425
498
|
- 各タブは以下を独立に保持
|
|
426
499
|
- window list(表示中 window 群)
|
|
427
500
|
- current window
|
|
@@ -434,6 +507,12 @@ ANSI エスケープシーケンスによる再描画です。
|
|
|
434
507
|
- 入力待機は `stdin + resize通知` を `IO.select` で待つ
|
|
435
508
|
- 描画ごとに `winsize` を再取得して viewport を再計算
|
|
436
509
|
|
|
510
|
+
### suspend / resume(現状)
|
|
511
|
+
|
|
512
|
+
- `Ctrl-z` 入力は app レベルで処理し、モードに関係なく suspend する
|
|
513
|
+
- suspend 時は terminal を cooked + main screen に戻してから `SIGTSTP` を送る
|
|
514
|
+
- `fg` 復帰時は alt screen を再有効化し、`Screen` キャッシュを破棄して全面再描画する
|
|
515
|
+
|
|
437
516
|
### Command-line 改善(現状)
|
|
438
517
|
|
|
439
518
|
- prefix ごとの履歴保持(`:` `/` `?`)
|
|
@@ -518,12 +597,15 @@ Vim 完全互換ではなく、まずは扱いやすい粒度を優先した仕
|
|
|
518
597
|
- `diw`, `daw` : text object word(簡易)
|
|
519
598
|
- `di"`, `da"`, `di)`, `da)` : delimiter text object(簡易・同一行中心)
|
|
520
599
|
|
|
521
|
-
設計上は operator-pending 状態機械を導入しており、`d/y/c
|
|
600
|
+
設計上は operator-pending 状態機械を導入しており、`d/y/c/=` を同じ流れで扱います。
|
|
522
601
|
|
|
523
602
|
補足:
|
|
524
603
|
|
|
525
604
|
- 現状 `y` operator も実装済み(`yy`, `yw`)
|
|
526
605
|
- 現状 `c` operator も実装済み(`cw`, `cc`, `c$`, `ciw`, `caw` など)
|
|
606
|
+
- 現状 `=` operator も実装済み(`==`, `=j`, `=k`, `=G`, `=gg`、Visual `=`)
|
|
607
|
+
- Ruby filetype の場合にネスト構造に基づく自動インデントを適用
|
|
608
|
+
- 他の filetype はフォールバック(現在のインデント維持)
|
|
527
609
|
|
|
528
610
|
### text object(現状)
|
|
529
611
|
|
|
@@ -594,7 +676,7 @@ Vim 完全互換ではなく、まずは扱いやすい粒度を優先した仕
|
|
|
594
676
|
- 代表例:
|
|
595
677
|
- window-local: `number`, `relativenumber`, `wrap`, `linebreak`, `breakindent`, `cursorline`, `scrolloff`, `sidescrolloff`
|
|
596
678
|
- global: `ignorecase`, `smartcase`, `hlsearch`, `incsearch`, `splitbelow`, `splitright`, `hidden`, `clipboard`, `timeoutlen`
|
|
597
|
-
- buffer-local: `tabstop`, `expandtab`, `shiftwidth`, `softtabstop`, `autoindent`, `smartindent`, `filetype`
|
|
679
|
+
- buffer-local: `tabstop`, `expandtab`, `shiftwidth`, `softtabstop`, `autoindent`, `smartindent`, `filetype`, `onsavehook`
|
|
598
680
|
- 詳細な一覧・実装状況は `docs/config.md` を参照
|
|
599
681
|
|
|
600
682
|
## Filetype / ftplugin(現状の基礎)
|
|
@@ -608,19 +690,82 @@ Vim 完全互換ではなく、まずは扱いやすい粒度を優先した仕
|
|
|
608
690
|
- `setlocal` / `setglobal` / `set`(DSL)で option 変更可
|
|
609
691
|
- 同一 buffer の同一 filetype ftplugin は一度だけ読み込む
|
|
610
692
|
|
|
693
|
+
## Lang モジュール on_save フック
|
|
694
|
+
|
|
695
|
+
- Lang モジュールに `on_save(ctx, path)` ライフサイクルフックを定義
|
|
696
|
+
- `:w` でファイル保存後、`onsavehook` オプションが有効(デフォルト `true`)なら `buffer.lang_module.on_save(ctx, target)` を呼び出す
|
|
697
|
+
- `Lang::Base.on_save` はデフォルトで何もしない(no-op)
|
|
698
|
+
- `Lang::Ruby.on_save` は `ruby -wc` で構文チェックを実行し、エラー/警告を quickfix list に展開する
|
|
699
|
+
- エラー出力を `filename:line:` 形式でパースし quickfix items に変換
|
|
700
|
+
- 複数エラー時はヒント `(]q to see next, N total)` を表示
|
|
701
|
+
- 正常時は quickfix list を空にクリアする
|
|
702
|
+
- `:set noonsavehook` で無効化可能
|
|
703
|
+
|
|
611
704
|
## シンタックスハイライト(最小)
|
|
612
705
|
|
|
613
706
|
- 描画時に filetype ごとの regex ベース highlighter を適用
|
|
614
707
|
- 現状の対応 filetype:
|
|
615
708
|
- `ruby`
|
|
616
709
|
- `json`
|
|
710
|
+
- `markdown`(見出し・フェンス・HR・ブロック引用・インライン装飾)
|
|
617
711
|
- 優先度(高 -> 低):
|
|
618
712
|
- cursor / visual
|
|
619
713
|
- search highlight
|
|
620
714
|
- syntax highlight
|
|
621
|
-
- 実装は `lib/ruvim/highlighter.rb`
|
|
715
|
+
- 実装は `lib/ruvim/highlighter.rb`(ディスパッチャ)+ `lib/ruvim/lang/markdown.rb`(言語固有ロジック)
|
|
622
716
|
- Vim の syntax / treesitter 相当の互換性はない(最小実装)
|
|
623
717
|
|
|
718
|
+
## Rich mode(構造化データ表示)
|
|
719
|
+
|
|
720
|
+
構造化データ(TSV/CSV)や Markdown を見やすく整形して表示するモードです。
|
|
721
|
+
Visual mode と同様に Normal mode の上に乗るモードとして設計されています。
|
|
722
|
+
|
|
723
|
+
- **アーキテクチャ**: filetype ごとにレンダラーを登録できる汎用フレームワーク
|
|
724
|
+
- `RuVim::RichView` モジュール(`lib/ruvim/rich_view.rb`)
|
|
725
|
+
- レンダラー登録: `RichView.register(filetype, renderer)`
|
|
726
|
+
- レンダラー: `TableRenderer`(TSV/CSV)、`MarkdownRenderer`(Markdown)
|
|
727
|
+
- **起動方法**:
|
|
728
|
+
- `:rich [format]` Ex コマンド(トグル)
|
|
729
|
+
- `gr` Normal mode キーバインド(トグル)
|
|
730
|
+
- **モード仕様**:
|
|
731
|
+
- 同一バッファ上で動作(仮想バッファを作成しない)
|
|
732
|
+
- `Editor#rich_state` に format/delimiter を保持
|
|
733
|
+
- Normal mode とほぼ同じキーバインドが使える(移動・検索・yank 等)
|
|
734
|
+
- バッファを変更する操作(insert/delete/change/paste/replace)はブロック
|
|
735
|
+
- `Esc` / `Ctrl-C` で Normal mode に戻る
|
|
736
|
+
- ステータスラインに `-- RICH --` を表示
|
|
737
|
+
- wrap は強制 OFF
|
|
738
|
+
- **レンダリング**:
|
|
739
|
+
- `Screen` の `plain_window_render_rows` で `editor.rich_mode?` を判定
|
|
740
|
+
- Rich mode の場合、表示行だけを `RichView.render_visible_lines` で整形
|
|
741
|
+
- バッファ内容は変更せず、描画パイプラインでの変換のみ
|
|
742
|
+
- `render_rich_view_line_sc` は ANSI エスケープシーケンスを幅ゼロとして扱い、横スクロール時もスタイルを正しく維持
|
|
743
|
+
- **横スクロール**:
|
|
744
|
+
- 表示カラム(display column)ベースでスクロール量を管理(`@rich_col_offset_sc`)
|
|
745
|
+
- `renderer.cursor_display_col` で raw バッファの `cursor_x` を整形後の表示カラムに変換し、スクロールオフセットを決定
|
|
746
|
+
- `render_rich_view_line_sc` で各行を同じ表示カラム数だけスキップして描画(CJK/ASCII 混在でも列揃えが保たれる)
|
|
747
|
+
- ワイド文字がビューポート左端をまたぐ場合はスペースで置換(部分表示は不可)
|
|
748
|
+
- カーソルの画面位置も整形後の表示カラム座標で計算
|
|
749
|
+
- **テーブルレンダラー仕様**:
|
|
750
|
+
- 区切り表示: ` | `(スペース+パイプ+スペース)
|
|
751
|
+
- 列幅は画面に見えている行だけから計算(大規模ファイルでも高速)
|
|
752
|
+
- CJK 文字の表示幅を `DisplayWidth.display_width` で正確に計算
|
|
753
|
+
- CSV は最小限の quoted field パース対応
|
|
754
|
+
- 列が1つしかない場合は元の行をそのまま返す
|
|
755
|
+
- **Markdown レンダラー仕様**:
|
|
756
|
+
- インラインマーカー(`#`, `**`, `*`, `` ` `` 等)は残し、ANSI スタイルを重ねる
|
|
757
|
+
- 見出し H1-H6: レベル別 bold + 色
|
|
758
|
+
- インライン装飾: `**bold**`, `*italic*`, `` `code` ``, `[text](url)`, チェックボックス
|
|
759
|
+
- コードブロック: `` ``` ``/`~~~` フェンスで状態追跡、内容を暖色表示
|
|
760
|
+
- コードフェンス状態は `pre_context_lines` で表示領域前の行から引き継ぎ
|
|
761
|
+
- テーブル: `|...|` パターンを検出し、列幅揃え + box-drawing 罫線(`│`, `─`, `┼`, `├`, `┤`)
|
|
762
|
+
- HR: `---`/`***`/`___` を `─` 線に置換
|
|
763
|
+
- ブロック引用: `>` で始まる行を cyan 表示
|
|
764
|
+
- テーブル行のカーソルマッピングはパディング後の位置を計算
|
|
765
|
+
- **filetype 検出**:
|
|
766
|
+
- `.tsv` → `tsv`, `.csv` → `csv`, `.md` → `markdown`
|
|
767
|
+
- `:rich`(引数なし)は filetype から判定、不明なら内容を見て自動推測
|
|
768
|
+
|
|
624
769
|
## シングルトン方針
|
|
625
770
|
|
|
626
771
|
グローバルに共有して良い「定義系」だけシングルトンにしています。
|
data/docs/todo.md
CHANGED
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
- session file(`-S [session]` placeholder 実体化)
|
|
86
86
|
- `wrap` / `linebreak` / `breakindent` / `showbreak` の整合性
|
|
87
87
|
- `wildmenu` / `completeopt` / `pumheight` の UI コンポーネント寄せ
|
|
88
|
-
- arglist
|
|
88
|
+
- arglist 残件(`:args/:next/:prev` の挙動精度向上)
|
|
89
89
|
|
|
90
90
|
### この順番の理由(依存)
|
|
91
91
|
|
|
@@ -120,10 +120,6 @@
|
|
|
120
120
|
|
|
121
121
|
### P1: Vim 運用でよく触る基盤(あると詰まりにくい)
|
|
122
122
|
|
|
123
|
-
- arglist(複数ファイル通常起動 + 操作)
|
|
124
|
-
- 複数ファイル引数(通常起動)
|
|
125
|
-
- `:args`, `:next`, `:prev`, `:first`, `:last`
|
|
126
|
-
- `alternate buffer (#)` との整合
|
|
127
123
|
- `Ctrl-w` window 操作の拡張
|
|
128
124
|
- `Ctrl-w c`(window close)
|
|
129
125
|
- `Ctrl-w o`(only / 他 window を閉じる)
|
data/docs/vim_diff.md
CHANGED
|
@@ -1,180 +1,102 @@
|
|
|
1
|
-
# RuVim と Vim
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
|
|
43
|
-
- `Ctrl-v` blockwise は矩形選択 + `y/d` の最小対応
|
|
44
|
-
- blockwise text object / paste の Vim 互換挙動は未実装
|
|
45
|
-
- Vim の細かい選択挙動や text object は一部未実装
|
|
46
|
-
- operator-pending は `d`, `y`, `c` の一部を実装
|
|
47
|
-
- text object は `iw/aw`, `ip/ap`, `i"/a"`, ``i`/a` ``, `i)/a)`, `i]/a]`, `i}/a}` を実装(簡易)
|
|
48
|
-
- Vim の text object 群全体は未実装
|
|
49
|
-
- word motion(`w`, `b`, `e`)は簡易定義
|
|
50
|
-
- Vim の厳密な単語境界とは一致しない場合がある
|
|
51
|
-
- undo 粒度は簡略化
|
|
52
|
-
- Insert mode は「入ってから出るまで」を 1 undo 単位
|
|
53
|
-
- `.` repeat は拡張済みだが完全互換ではない
|
|
54
|
-
- `x`, `dd`, `d{motion}`, `p/P`, `r<char>`, `i/a/A/I/o/O`, `cc`, `c{motion}` を対象
|
|
1
|
+
# RuVim と Vim の違い
|
|
2
|
+
|
|
3
|
+
RuVim は「Vim ライクな Ruby 製ターミナルエディタ」です。Vim 完全互換ではなく、Vim の操作感を優先しつつ一部を独自拡張・簡略化しています。
|
|
4
|
+
|
|
5
|
+
## RuVim の独自機能・強み
|
|
6
|
+
|
|
7
|
+
### Ruby ネイティブな拡張性
|
|
8
|
+
|
|
9
|
+
- 設定ファイルは Ruby DSL(`~/.config/ruvim/init.rb`)
|
|
10
|
+
- `nmap`, `imap`, `map_global`, `command`, `ex_command`, `ex_command_call`
|
|
11
|
+
- Vim script 不要で Ruby の全機能を利用可能
|
|
12
|
+
- `:ruby` / `:rb` で実行中に Ruby eval が可能(Vim の `:ruby` とは別物)
|
|
13
|
+
- plugin 向け `ctx.editor / ctx.buffer / ctx.window` API
|
|
14
|
+
|
|
15
|
+
### ネストしたウィンドウ分割(Layout Tree)
|
|
16
|
+
|
|
17
|
+
- `:vsplit` 後に `:split` すると、対象カラムだけが上下分割される(Vim と同様のツリー構造)
|
|
18
|
+
- 同方向の連続分割は自動的にフラット化(例: hsplit の中で hsplit → 1 レベルに統合)
|
|
19
|
+
- `Shift+Arrow` キーによるスマート分割
|
|
20
|
+
- 同軸方向に既存ウィンドウがあればフォーカス移動
|
|
21
|
+
- なければ新規分割(cross-direction split にも対応)
|
|
22
|
+
- ツリーパスベースの判定で、別領域のウィンドウに影響されない
|
|
23
|
+
|
|
24
|
+
### Rich View モード
|
|
25
|
+
|
|
26
|
+
- TSV / CSV / Markdown をフォーマットして閲覧できる構造化データ表示モード
|
|
27
|
+
- CJK 文字幅を考慮したカラム整列
|
|
28
|
+
|
|
29
|
+
### 検索は Ruby 正規表現
|
|
30
|
+
|
|
31
|
+
- `/`, `?`, `:s` はすべて Ruby の `Regexp` を使用
|
|
32
|
+
- Vim regex と異なる点はあるが、Ruby 利用者には馴染みやすい
|
|
33
|
+
- `:help regex` でヘルプ表示
|
|
34
|
+
|
|
35
|
+
## Vim と同等に実装済みの機能
|
|
36
|
+
|
|
37
|
+
### モード・編集操作
|
|
38
|
+
|
|
39
|
+
- Normal / Insert / Command-line / Visual(charwise, linewise, blockwise)
|
|
40
|
+
- operator-pending: `d`, `y`, `c` + motion / text object
|
|
41
|
+
- text object: `iw/aw`, `ip/ap`, `i"/a"`, `` i`/a` ``, `i)/a)`, `i]/a]`, `i}/a}`
|
|
42
|
+
- `.` repeat: `x`, `dd`, `d{motion}`, `p/P`, `r<char>`, `i/a/A/I/o/O`, `cc`, `c{motion}`
|
|
55
43
|
- macro 記録中の `.` は内部再生キーを macro に混ぜない
|
|
56
|
-
|
|
44
|
+
- word motion: `w`, `b`, `e`(`iskeyword` 対応)
|
|
45
|
+
- macros: `q{reg}`, `@{reg}`, `@@`
|
|
46
|
+
- marks / jumps: `m`, `'`, `` ` ``, `''`, ` `` `, `<C-o>`, `<C-i>`
|
|
47
|
+
|
|
48
|
+
### レジスタ
|
|
49
|
+
|
|
50
|
+
- unnamed(`"`), named(`"a`〜`"z`, `"A` append), black hole(`"_`)
|
|
51
|
+
- yank `"0`, numbered delete `"1`〜`"9`
|
|
52
|
+
- system clipboard `"+`, `"*`(`pbcopy/pbpaste`, `wl-copy/wl-paste`, `xclip`, `xsel`)
|
|
53
|
+
|
|
54
|
+
### Ex コマンド
|
|
55
|
+
|
|
56
|
+
- `:w`, `:q`, `:wq`, `:e`, `:buffer`, `:bnext`, `:bprev`, `:ls`, `:split`, `:vsplit`
|
|
57
|
+
- `:qa`, `:qa!`, `:wqa`
|
|
58
|
+
- quickfix / location list: `:vimgrep`, `:lvimgrep`, `:copen`, `:cnext`, `:lopen`, `:lnext`
|
|
59
|
+
- tabpage: `:tabnew`, `:tabnext`, `:tabprev`
|
|
60
|
+
|
|
61
|
+
### option system
|
|
57
62
|
|
|
58
|
-
|
|
63
|
+
- `:set`, `:setlocal`, `:setglobal`(global / buffer-local / window-local)
|
|
64
|
+
- 表示系: `number`, `relativenumber`, `cursorline`, `wrap`, `linebreak`, `breakindent`, `showbreak`, `list`, `listchars`, `colorcolumn`, `signcolumn`, `numberwidth`, `scrolloff`, `sidescrolloff`, `termguicolors`
|
|
65
|
+
- インデント: `shiftwidth`, `softtabstop`, `expandtab`, `autoindent`, `smartindent`, `tabstop`
|
|
66
|
+
- 検索: `ignorecase`, `smartcase`, `hlsearch`, `incsearch`
|
|
67
|
+
- 分割: `splitbelow`, `splitright`
|
|
68
|
+
- その他: `hidden`, `autowrite`, `clipboard`, `timeoutlen`, `ttimeoutlen`, `backspace`, `whichwrap`, `iskeyword`, `filetype`, `path`, `suffixesadd`, `grepprg`, `grepformat`, 補完系(`completeopt`, `pumheight`, `wildmode`, `wildmenu`, `wildignore`, `wildignorecase`)
|
|
59
69
|
|
|
60
|
-
|
|
61
|
-
- black hole(`"_`)、yank `0`、numbered delete `1-9`(簡易)を実装
|
|
62
|
-
- `"+`, `"*` は環境依存の system clipboard と連携(`pbcopy/pbpaste`, `wl-copy/wl-paste`, `xclip`, `xsel` のいずれか)
|
|
63
|
-
- small delete register `-` など Vim の全 register 種別は未実装
|
|
64
|
-
- paste の挙動は基本的な `charwise` / `linewise` 対応まで
|
|
65
|
-
- Vim の細かいカーソル位置ルールとは差がある可能性がある
|
|
70
|
+
### その他
|
|
66
71
|
|
|
67
|
-
|
|
72
|
+
- filetype 検出(拡張子 + shebang)/ ftplugin
|
|
73
|
+
- syntax highlight: Ruby(Prism lexer), JSON, Markdown, Scheme, TSV/CSV
|
|
74
|
+
- 補完: Ex コマンド名 + 引数補完, Insert mode buffer words(`Ctrl-n` / `Ctrl-p`)
|
|
75
|
+
- CLI: `--help`, `--version`, `--clean`, `-u`, `-R`, `-M`, `-Z`, `-o/-O/-p`, `-c`, `+{cmd}`, `-V`, `--startuptime`, `--cmd`
|
|
68
76
|
|
|
69
|
-
|
|
70
|
-
|
|
77
|
+
## 動作の微細な差分
|
|
78
|
+
|
|
79
|
+
- undo 粒度は簡略化(Insert mode は「入ってから出るまで」が 1 undo 単位)
|
|
80
|
+
- `.` repeat のカウント互換は完全ではない
|
|
81
|
+
- word motion の単語境界定義が Vim と一致しない場合がある
|
|
82
|
+
- paste のカーソル位置ルールに Vim との差がある可能性がある
|
|
83
|
+
- 文字幅対応は近似(CJK / emoji 幅2 / grapheme cluster は対応するが、East Asian Width 完全互換ではない)
|
|
84
|
+
- ANSI + raw mode の自前描画(行キャッシュによる簡易差分描画で Vim の描画最適化とは別実装)
|
|
71
85
|
- `SIGWINCH + self-pipe + IO.select` でリサイズ追従
|
|
72
|
-
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
## スクリプト / 設定の違い
|
|
79
|
-
|
|
80
|
-
- XDG 設定ファイル(`$XDG_CONFIG_HOME/ruvim/init.rb` または `~/.config/ruvim/init.rb`)を Ruby DSL(`ConfigDSL`)で読む
|
|
81
|
-
- Vim script 互換設定ファイルではない
|
|
82
|
-
- CLI の `-u {path|NONE}` / `--clean` は一部実装済み(Vim 互換の全オプションは未実装)
|
|
83
|
-
- 現状の DSL 例:
|
|
84
|
-
- `nmap`, `imap`, `map_global`
|
|
85
|
-
- `command`
|
|
86
|
-
- `ex_command`
|
|
87
|
-
- `ex_command_call`
|
|
88
|
-
|
|
89
|
-
## CLI オプションの違い
|
|
90
|
-
|
|
91
|
-
- 実装済み(現状)
|
|
92
|
-
- `--help`, `--version`
|
|
93
|
-
- `--clean`
|
|
94
|
-
- `-u {path|NONE}`
|
|
95
|
-
- `-R`, `-M`, `-Z`, `-n`(`-n` は現状 no-op)
|
|
96
|
-
- `-d`(placeholder: 未実装メッセージ)
|
|
97
|
-
- `-q {errorfile}`(placeholder: 未実装メッセージ)
|
|
98
|
-
- `-S [session]`(placeholder: 未実装メッセージ)
|
|
99
|
-
- `-o[N]`, `-O[N]`, `-p[N]`(基礎)
|
|
100
|
-
- `-V[N]`, `--verbose[=N]`(簡易)
|
|
101
|
-
- `--startuptime FILE`(簡易)
|
|
102
|
-
- `--cmd {cmd}`(pre-config Ex 実行)
|
|
103
|
-
- `-c {cmd}`
|
|
104
|
-
- `+{cmd}`, `+{line}`, `+`
|
|
105
|
-
- 未実装(Vim で定番だが RuVim は未対応)
|
|
106
|
-
- 実処理としては `-S`, `-q`, `-d` など(現状は placeholder のみ)
|
|
107
|
-
- 複数ファイル引数は `-o/-O/-p` 時のみ対応(通常起動の arglist 相当は未実装)
|
|
108
|
-
|
|
109
|
-
## option(設定)の違い
|
|
110
|
-
|
|
111
|
-
- 現状の実装済み option は少数(`number`, `relativenumber`, `ignorecase`, `smartcase`, `hlsearch`, `tabstop`, `filetype`)
|
|
112
|
-
- Vim の option 名短縮(例: `nu`, `ts`)は未対応
|
|
113
|
-
- `:set` の高度な構文(`+=`, `-=`, `^=`, `&`, `<` など)は未対応
|
|
114
|
-
- `:set all` や詳細な一覧表示は未対応(簡易表示のみ)
|
|
115
|
-
|
|
116
|
-
### Vim にあるが未実装の代表例(RuVim 現状)
|
|
117
|
-
|
|
118
|
-
- 表示系
|
|
119
|
-
- `relativenumber`
|
|
120
|
-
- `cursorline`
|
|
121
|
-
- `wrap`
|
|
122
|
-
- `list`, `listchars`
|
|
123
|
-
- `colorcolumn`
|
|
124
|
-
- `signcolumn`
|
|
125
|
-
- `numberwidth`
|
|
126
|
-
- `scrolloff`, `sidescrolloff`
|
|
127
|
-
- インデント/編集系
|
|
128
|
-
- `shiftwidth`
|
|
129
|
-
- `softtabstop`
|
|
130
|
-
- `expandtab`
|
|
131
|
-
- `autoindent`
|
|
132
|
-
- `smartindent`
|
|
133
|
-
- 検索系
|
|
134
|
-
- `ignorecase`
|
|
135
|
-
- `smartcase`
|
|
136
|
-
- `hlsearch`
|
|
137
|
-
- `incsearch`
|
|
138
|
-
- split / window 系
|
|
139
|
-
- `splitbelow`
|
|
140
|
-
- `splitright`
|
|
141
|
-
- `winfixheight`
|
|
142
|
-
- `winfixwidth`
|
|
143
|
-
- ファイル / 永続化系
|
|
144
|
-
- `swapfile`
|
|
145
|
-
- `backup`
|
|
146
|
-
- `writebackup`
|
|
147
|
-
- `undofile`
|
|
148
|
-
- `undodir`
|
|
149
|
-
- UI / 端末 / パフォーマンス系
|
|
150
|
-
- `termguicolors`
|
|
151
|
-
- `timeoutlen`
|
|
152
|
-
- `ttimeoutlen`
|
|
153
|
-
- `updatetime`
|
|
154
|
-
|
|
155
|
-
注記:
|
|
156
|
-
- これは網羅一覧ではなく、よく使われるものの代表例です。
|
|
157
|
-
- 実装済み option の一覧は `docs/config.md` を参照。
|
|
158
|
-
|
|
159
|
-
## 未実装(Vim との差分として大きいもの)
|
|
160
|
-
|
|
161
|
-
- text objects は一部のみ(`iw/aw`, `ip/ap`, `i"/a"`, ``i`/a` ``, `i)/a)`, `i]/a]`, `i}/a}`)
|
|
162
|
-
- change operator(`c` 系)は基礎のみ
|
|
163
|
-
- macros / replay は基礎のみ(`q{reg}`, `@{reg}`, `@@`)
|
|
164
|
-
- marks / jumps は基礎のみ(`m`, `'`, `` ` ``, `''`, `````, `<C-o>`, `<C-i>`)
|
|
165
|
-
- search regex 互換(現状は Ruby 正規表現)
|
|
166
|
-
- search は Ruby 正規表現ベース(Vim regex と非互換な点あり)
|
|
167
|
-
- substitute は最小実装(`:%s/.../.../g` のみ、Vim の置換フラグ群は未対応)
|
|
168
|
-
- folds
|
|
169
|
-
- syntax highlight は最小実装(regex ベース / `ruby`, `json` のみ)
|
|
170
|
-
- 補完は基礎のみ
|
|
171
|
-
- Ex 補完(コマンド名 + 一部引数)
|
|
172
|
-
- Insert mode buffer words 補完(`Ctrl-n` / `Ctrl-p`)
|
|
173
|
-
- LSP / diagnostics
|
|
174
|
-
- job/channel/terminal 連携
|
|
86
|
+
- `:w!` は現状 `:w` とほぼ同じ(権限昇格や readonly 強制保存は未実装)
|
|
87
|
+
- `:command` は Ex 文字列エイリアス展開の簡易実装
|
|
88
|
+
- Visual blockwise は矩形選択 + `y/d` の最小対応(blockwise text object / paste の Vim 互換挙動は未実装)
|
|
89
|
+
- option 名短縮(`nu`, `ts` 等)は未対応
|
|
90
|
+
- `:set` の高度な構文(`+=`, `-=`, `^=` 等)は未対応
|
|
91
|
+
- small delete register `"-` は未実装
|
|
175
92
|
|
|
176
|
-
##
|
|
93
|
+
## 未実装の主要機能
|
|
177
94
|
|
|
178
|
-
- Vim
|
|
179
|
-
-
|
|
180
|
-
-
|
|
95
|
+
- Vim script 互換 / プラグイン互換
|
|
96
|
+
- folds
|
|
97
|
+
- LSP / diagnostics
|
|
98
|
+
- job / channel / terminal 連携
|
|
99
|
+
- `:grep`, `:make`, `:cfile`, `:lgrep`
|
|
100
|
+
- substitute の高度なフラグ群(現状は `:%s/.../.../g` のみ)
|
|
101
|
+
- swap / backup / undofile(永続 undo)
|
|
102
|
+
- `-d`(diff mode), `-q`(quickfix mode), `-S`(session)は placeholder のみ
|