ruvim 0.4.0 → 0.6.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.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/AGENTS.md +53 -4
  3. data/README.md +15 -6
  4. data/Rakefile +7 -0
  5. data/benchmark/cext_compare.rb +165 -0
  6. data/benchmark/chunked_load.rb +256 -0
  7. data/benchmark/file_load.rb +140 -0
  8. data/benchmark/hotspots.rb +178 -0
  9. data/docs/binding.md +3 -2
  10. data/docs/command.md +81 -9
  11. data/docs/done.md +23 -0
  12. data/docs/spec.md +105 -19
  13. data/docs/todo.md +9 -0
  14. data/docs/tutorial.md +9 -1
  15. data/docs/vim_diff.md +13 -0
  16. data/ext/ruvim/extconf.rb +5 -0
  17. data/ext/ruvim/ruvim_ext.c +519 -0
  18. data/lib/ruvim/app.rb +217 -2778
  19. data/lib/ruvim/browser.rb +104 -0
  20. data/lib/ruvim/buffer.rb +39 -28
  21. data/lib/ruvim/command_invocation.rb +2 -2
  22. data/lib/ruvim/completion_manager.rb +708 -0
  23. data/lib/ruvim/dispatcher.rb +14 -8
  24. data/lib/ruvim/display_width.rb +91 -45
  25. data/lib/ruvim/editor.rb +64 -81
  26. data/lib/ruvim/ex_command_registry.rb +3 -1
  27. data/lib/ruvim/gh/link.rb +207 -0
  28. data/lib/ruvim/git/blame.rb +16 -6
  29. data/lib/ruvim/git/branch.rb +20 -5
  30. data/lib/ruvim/git/grep.rb +107 -0
  31. data/lib/ruvim/git/handler.rb +42 -1
  32. data/lib/ruvim/global_commands.rb +175 -35
  33. data/lib/ruvim/highlighter.rb +4 -13
  34. data/lib/ruvim/key_handler.rb +1510 -0
  35. data/lib/ruvim/keymap_manager.rb +7 -7
  36. data/lib/ruvim/lang/base.rb +5 -0
  37. data/lib/ruvim/lang/c.rb +116 -0
  38. data/lib/ruvim/lang/cpp.rb +107 -0
  39. data/lib/ruvim/lang/csv.rb +4 -1
  40. data/lib/ruvim/lang/diff.rb +2 -0
  41. data/lib/ruvim/lang/dockerfile.rb +36 -0
  42. data/lib/ruvim/lang/elixir.rb +85 -0
  43. data/lib/ruvim/lang/erb.rb +30 -0
  44. data/lib/ruvim/lang/go.rb +83 -0
  45. data/lib/ruvim/lang/html.rb +34 -0
  46. data/lib/ruvim/lang/javascript.rb +83 -0
  47. data/lib/ruvim/lang/json.rb +6 -0
  48. data/lib/ruvim/lang/lua.rb +76 -0
  49. data/lib/ruvim/lang/makefile.rb +36 -0
  50. data/lib/ruvim/lang/markdown.rb +3 -4
  51. data/lib/ruvim/lang/ocaml.rb +77 -0
  52. data/lib/ruvim/lang/perl.rb +91 -0
  53. data/lib/ruvim/lang/python.rb +85 -0
  54. data/lib/ruvim/lang/registry.rb +102 -0
  55. data/lib/ruvim/lang/ruby.rb +7 -0
  56. data/lib/ruvim/lang/rust.rb +95 -0
  57. data/lib/ruvim/lang/scheme.rb +5 -0
  58. data/lib/ruvim/lang/sh.rb +76 -0
  59. data/lib/ruvim/lang/sql.rb +52 -0
  60. data/lib/ruvim/lang/toml.rb +36 -0
  61. data/lib/ruvim/lang/tsv.rb +4 -1
  62. data/lib/ruvim/lang/typescript.rb +53 -0
  63. data/lib/ruvim/lang/yaml.rb +62 -0
  64. data/lib/ruvim/rich_view/table_renderer.rb +3 -3
  65. data/lib/ruvim/rich_view.rb +14 -7
  66. data/lib/ruvim/screen.rb +126 -72
  67. data/lib/ruvim/stream/file_load.rb +85 -0
  68. data/lib/ruvim/stream/follow.rb +40 -0
  69. data/lib/ruvim/stream/git.rb +43 -0
  70. data/lib/ruvim/stream/run.rb +74 -0
  71. data/lib/ruvim/stream/stdin.rb +55 -0
  72. data/lib/ruvim/stream.rb +35 -0
  73. data/lib/ruvim/stream_mixer.rb +394 -0
  74. data/lib/ruvim/terminal.rb +18 -4
  75. data/lib/ruvim/text_metrics.rb +84 -65
  76. data/lib/ruvim/version.rb +1 -1
  77. data/lib/ruvim/window.rb +5 -5
  78. data/lib/ruvim.rb +23 -6
  79. data/test/app_command_test.rb +382 -0
  80. data/test/app_completion_test.rb +43 -19
  81. data/test/app_dot_repeat_test.rb +27 -3
  82. data/test/app_ex_command_test.rb +154 -0
  83. data/test/app_motion_test.rb +13 -12
  84. data/test/app_register_test.rb +2 -1
  85. data/test/app_scenario_test.rb +15 -10
  86. data/test/app_startup_test.rb +70 -27
  87. data/test/app_text_object_test.rb +2 -1
  88. data/test/app_unicode_behavior_test.rb +3 -2
  89. data/test/browser_test.rb +88 -0
  90. data/test/buffer_test.rb +24 -0
  91. data/test/cli_test.rb +63 -0
  92. data/test/command_invocation_test.rb +33 -0
  93. data/test/config_dsl_test.rb +47 -0
  94. data/test/dispatcher_test.rb +74 -4
  95. data/test/ex_command_registry_test.rb +106 -0
  96. data/test/follow_test.rb +20 -21
  97. data/test/gh_link_test.rb +141 -0
  98. data/test/git_blame_test.rb +96 -17
  99. data/test/git_grep_test.rb +64 -0
  100. data/test/highlighter_test.rb +125 -0
  101. data/test/indent_test.rb +137 -0
  102. data/test/input_screen_integration_test.rb +1 -1
  103. data/test/keyword_chars_test.rb +85 -0
  104. data/test/lang_test.rb +634 -0
  105. data/test/markdown_renderer_test.rb +5 -5
  106. data/test/on_save_hook_test.rb +12 -8
  107. data/test/render_snapshot_test.rb +78 -0
  108. data/test/rich_view_test.rb +42 -42
  109. data/test/run_command_test.rb +307 -0
  110. data/test/screen_test.rb +68 -5
  111. data/test/stream_test.rb +165 -0
  112. data/test/window_test.rb +59 -0
  113. metadata +52 -2
data/docs/spec.md CHANGED
@@ -93,8 +93,8 @@ RuVim は Vim と同様に、用途ごとに座標系を分けています。
93
93
  - tabpages 管理(タブごとに layout tree / current window を保持)
94
94
  - current window の管理
95
95
  - mode 管理(`:normal`, `:insert`, `:command_line`, `:rich`)
96
- - ステータスメッセージ
97
- - コマンドライン状態
96
+ - message line のメッセージ管理
97
+ - command-line 状態
98
98
 
99
99
  ## コマンドモデル
100
100
 
@@ -192,6 +192,9 @@ RuVim::ExCommandRegistry.instance.register(
192
192
  - user config / ftplugin を読み込まない
193
193
  - `:ruby` / `:rb` を禁止する
194
194
  - `:!` を禁止する
195
+ - `:grep` / `:lgrep` を禁止する
196
+ - `:git` / `:gh` を禁止する
197
+ - Ruby 構文チェック(`on_save`)を無効化する
195
198
  - `-n`
196
199
  - 現状は no-op(将来の swap / 永続 undo / session 互換の先行予約)
197
200
  - `-o[N]`, `-O[N]`, `-p[N]`
@@ -216,7 +219,7 @@ RuVim::ExCommandRegistry.instance.register(
216
219
 
217
220
  - `stdin` が non-TTY で、起動引数ファイルがない場合は `stdin` を follow stream として開く
218
221
  - バッファ名は `[stdin]`
219
- - status line に `[stdin/live]`, `[stdin/closed]`, `[stdin/error]` を表示
222
+ - statusline に `[stdin]`(完了時 `[stdin/EOF]`、失敗時 `[stdin/error]`)を表示
220
223
  - Normal mode の `Ctrl-c` はデフォルトバインドで `stdin` stream stop(上流 PID へ直接 signal は送らない)
221
224
  - `Ctrl-z` は全モード共通で suspend
222
225
  - suspend 前に terminal を cooked + main screen に戻す
@@ -309,7 +312,7 @@ RuVim::ExCommandRegistry.instance.register(
309
312
  - Normal mode とほぼ同じキーバインドが使える(移動・検索・yank 等)
310
313
  - バッファを変更する操作(insert/delete/change/paste/replace)はブロック
311
314
  - `Esc` / `Ctrl-C` で Normal mode に戻る
312
- - ステータスラインに `-- RICH --` を表示
315
+ - statusline `-- RICH --` を表示
313
316
  - 描画時に表示行をテーブル整形(`TableRenderer` を利用)
314
317
  - wrap は強制 OFF
315
318
 
@@ -332,7 +335,7 @@ RuVim::ExCommandRegistry.instance.register(
332
335
 
333
336
  - 画面下部にメッセージ行をオーバーレイ描画
334
337
  - 最下行に「Press ENTER or type command to continue」を反転表示
335
- - ステータスラインは非表示(Vim と同様)
338
+ - statusline は非表示(Vim と同様)
336
339
  - 対象コマンド: `:ls` / `:buffers`, `:args`, `:set`(引数なし), `:command`(引数なし)
337
340
  - 1行以下の出力時は通常の `echo` を使用
338
341
 
@@ -371,6 +374,11 @@ RuVim::ExCommandRegistry.instance.register(
371
374
  - `:copen`, `:cclose`, `:cnext` / `:cn`, `:cprev` / `:cp`
372
375
  - `:lopen`, `:lclose`, `:lnext` / `:ln`, `:lprev` / `:lp`
373
376
  - `:grep /pattern/ [path...]`, `:lgrep /pattern/ [path...]`
377
+ - `grepprg` を argv 配列として実行(シェル経由ではない)
378
+ - ファイル引数の glob パターンは Ruby 側で展開
379
+ - restricted mode(`-Z`)では禁止
380
+ - `:git checkout <branch>` でブランチ切り替え
381
+ - ブランチ一覧(`:git branch`)で Enter を押すとコマンドラインにプリフィル、明示的に Enter で確定
374
382
  - `:filter [/pattern/]` : 検索マッチ行のみのフィルタバッファを作成(`g/` キーバインド)
375
383
  - `:rich [format]`
376
384
  - `:d [count]` / `:delete`
@@ -410,11 +418,12 @@ RuVim::ExCommandRegistry.instance.register(
410
418
  - `:bindings` は current buffer 文脈の有効 key binding を layer 別(`buffer`, `filetype`, `app`)に一覧表示
411
419
  - 任意で mode filter を受ける(例 `:bindings normal`)
412
420
  - 大きいファイルを開くときは、閾値以上で段階読み込みになる場合がある
413
- - status line に `[load/live]`(失敗時 `[load/error]`)
414
- - デフォルト実装は先頭 `8MB` を先に表示し、残りをバックグラウンド読み込み後に反映
421
+ - statusline に `[load]`(失敗時 `[load/error]`)
422
+ - デフォルト実装は先頭 `8MB` を先に表示し、残りをチャンク単位でバックグラウンド読み込み
415
423
  - 環境変数:
416
424
  - `RUVIM_ASYNC_FILE_THRESHOLD_BYTES`
417
425
  - `RUVIM_ASYNC_FILE_PREFIX_BYTES`
426
+ - ファイルを開く際、FIFO・デバイス・ソケット等の特殊ファイルは拒否する(`File.file?` チェック)
418
427
 
419
428
  ### `:command`(現状仕様)
420
429
 
@@ -433,13 +442,26 @@ RuVim::ExCommandRegistry.instance.register(
433
442
  - `buffer`
434
443
  - `window`
435
444
  - `stdout` / `stderr` に出力があれば `[Ruby Output]` 仮想バッファに表示(返り値も表示)
436
- - 出力がない場合、返り値をステータスラインに表示(`inspect`)
445
+ - 出力がない場合、返り値を message line に表示(`inspect`)
446
+
447
+ ### `:r` / `:read`(ファイル・コマンド出力の挿入)
448
+
449
+ - `:r <file>` でファイルの内容をカーソル行の下に挿入
450
+ - `:r !<command>` でシェルコマンドの stdout を挿入
451
+ - 行番号指定可: `:3r file.txt`(3行目の下に挿入)
452
+ - stderr が出た場合、最初の行をエラーメッセージとして表示
453
+
454
+ ### `:w !`(バッファ内容をコマンドへパイプ)
455
+
456
+ - `:w !<command>` でバッファ全体をシェルコマンドの stdin に渡す
457
+ - 範囲指定可: `:'<,'>w !sort`(選択範囲のみ渡す)
437
458
 
438
459
  ### `:!`(shell 実行, 最小)
439
460
 
440
461
  - `:!<command>` で shell コマンドを同期実行
441
- - `stdout` / `stderr` があれば `[Shell Output]` 仮想バッファに表示(終了ステータスを含む)
442
- - 出力がない場合は `shell exit N` をステータス表示
462
+ - alternate screen を一時的に抜けて main screen 上でコマンドを実行(Vim 互換)
463
+ - 実行後 "Press ENTER or type command to continue" を表示し、入力待ち後にエディタに復帰
464
+ - 完了後は `shell exit N` をステータス表示
443
465
  - restricted mode(`-Z`)では禁止
444
466
 
445
467
  ### バッファ管理 Ex コマンド(現状仕様)
@@ -477,11 +499,15 @@ ANSI エスケープシーケンスによる再描画です。
477
499
  - カーソル非表示/表示 (`?25l / ?25h`)
478
500
  - 行キャッシュによる簡易差分描画(同サイズ時)
479
501
  - フッターは 2 行固定:
480
- - 最下段: command line / error message
481
- - 1つ上: status line
482
- - Command-line mode 時も status line は維持し、最下段だけを入力行として使う
502
+ - 最下段: 用途に応じて command-line(`:` `/` `?` 入力時)または message line(メッセージ表示時)として使用。複数行メッセージ時は hit-enter prompt で表示
503
+ - 1つ上: statusline(モード・ファイル名・カーソル位置)
504
+ - command-line mode 時も statusline は維持し、最下段だけを入力行として使う
483
505
  - ファイル未指定起動時は Vim 風 intro screen を表示(RuVim では intro 用の read-only 特殊バッファ)
484
506
  - カーソル位置の文字を反転表示(見やすさ向上)
507
+ - カーソル形状の制御(DECSCUSR)
508
+ - Normal / Visual mode: ターミナルカーソルを非表示にし、セル描画(反転)でカーソルを表現
509
+ - Insert / Command-line mode: ターミナルのバーカーソル(`\e[6 q`)を表示
510
+ - UI 開始時に非点滅ブロック(`\e[2 q`)を設定、終了時にデフォルト(`\e[0 q`)に復元
485
511
 
486
512
  ### split UI
487
513
 
@@ -500,7 +526,7 @@ ANSI エスケープシーケンスによる再描画です。
500
526
  - `:tabnew [path]` で新しいタブを作成
501
527
  - `:tabnext`, `:tabprev` で移動
502
528
  - `:tabs` で全タブ一覧を表示(各タブのウィンドウとバッファ名)
503
- - ステータスラインに `tab:n/m` を表示(タブが2つ以上のとき)
529
+ - statusline `tab:n/m` を表示(タブが2つ以上のとき)
504
530
  - 各タブは以下を独立に保持
505
531
  - window list(表示中 window 群)
506
532
  - current window
@@ -711,9 +737,30 @@ Vim 完全互換ではなく、まずは扱いやすい粒度を優先した仕
711
737
 
712
738
  - 描画時に filetype ごとの regex ベース highlighter を適用
713
739
  - 現状の対応 filetype:
714
- - `ruby`
715
- - `json` / `jsonl`
740
+ - `ruby`(Prism lexer ベース。スマートインデント・保存時 ruby -wc チェック)
741
+ - `json` / `jsonl`(キー・値・真偽値・数値。スマートインデント)
716
742
  - `markdown`(見出し・フェンス・HR・ブロック引用・インライン装飾)
743
+ - `scheme`(キーワード・文字列・数値・真偽値・文字リテラル・コメント)
744
+ - `diff`(追加/削除/ハンク/ヘッダ/メタの行単位カラー)
745
+ - `c`(キーワード・型名・文字列・数値・コメント・プリプロセッサ・定数マクロ。スマートインデント・保存時 gcc チェック)
746
+ - `cpp`(C 拡張: `class`, `namespace`, `template`, `auto`, `nullptr` 等。アクセス指定子インデント・保存時 g++ チェック)
747
+ - `yaml`(キー・文字列・真偽値・アンカー・タグ・ブロックスカラー・コメント。インデント)
748
+ - `sh`(キーワード・変数・文字列・数値・コメント。インデント)
749
+ - `python`(キーワード・組み込み関数・デコレータ・文字列・数値・定数・コメント。インデント)
750
+ - `javascript` / `javascriptreact`(キーワード・テンプレートリテラル・文字列・数値・定数・コメント。インデント)
751
+ - `typescript` / `typescriptreact`(JS 拡張: `interface`, `type`, `enum`, `readonly` 等。インデント)
752
+ - `html`(タグ・属性・文字列・エンティティ・DOCTYPE・コメント)
753
+ - `toml`(テーブルヘッダ・キー・文字列・真偽値・日時・数値・コメント)
754
+ - `go`(キーワード・型名・文字列・raw 文字列・数値・定数・コメント。インデント)
755
+ - `rust`(キーワード・ライフタイム・マクロ・属性・文字列・数値・定数・コメント。インデント)
756
+ - `make`(ターゲット・変数定義・変数参照・ディレクティブ・関数・自動変数・コメント)
757
+ - `dockerfile`(命令キーワード・フラグ・変数・文字列・コメント)
758
+ - `sql`(キーワード(大文字小文字不問)・文字列・数値・パラメータ・コメント)
759
+ - `elixir`(キーワード・アトム・モジュール・属性・シジル・文字列・数値・コメント。インデント)
760
+ - `perl`(キーワード・スカラー/配列/ハッシュ変数・文字列・数値・POD・コメント。インデント)
761
+ - `lua`(キーワード・組み込み関数・長文字列・文字列・数値・コメント。インデント)
762
+ - `ocaml`(キーワード・型変数・モジュール名・文字列・数値・ブロックコメント。インデント)
763
+ - `erb`(HTML ベース + ERB デリミタ・ERB コメント)
717
764
  - 優先度(高 -> 低):
718
765
  - cursor / visual
719
766
  - search highlight
@@ -742,13 +789,14 @@ Visual mode と同様に Normal mode の上に乗るモードとして設計さ
742
789
  - Normal mode とほぼ同じキーバインドが使える(移動・検索・yank 等)
743
790
  - バッファを変更する操作(insert/delete/change/paste/replace)はブロック
744
791
  - `Esc` / `Ctrl-C` で Normal mode に戻る
745
- - ステータスラインに `-- RICH --` を表示
792
+ - statusline `-- RICH --` を表示
746
793
  - wrap は強制 OFF
747
794
  - **レンダリング**:
748
795
  - `Screen` の `plain_window_render_rows` で `editor.rich_mode?` を判定
749
796
  - Rich mode の場合、表示行だけを `RichView.render_visible_lines` で整形
750
797
  - バッファ内容は変更せず、描画パイプラインでの変換のみ
751
798
  - `render_rich_view_line_sc` は ANSI エスケープシーケンスを幅ゼロとして扱い、横スクロール時もスタイルを正しく維持
799
+ - Rich view に渡す前にバッファ行の制御文字(ESC 含む)をサニタイズし、terminal escape injection を防止
752
800
  - **横スクロール**:
753
801
  - 表示カラム(display column)ベースでスクロール量を管理(`@rich_col_offset_sc`)
754
802
  - `renderer.cursor_display_col` で raw バッファの `cursor_x` を整形後の表示カラムに変換し、スクロールオフセットを決定
@@ -812,6 +860,7 @@ Visual mode と同様に Normal mode の上に乗るモードとして設計さ
812
860
  ### Git Blame
813
861
 
814
862
  `<C-g>` で `:git ` プリセットのコマンドラインモードに入る。`:git <subcommand>` で実行。
863
+ 未知のサブコマンドは `:!` と同様に alternate screen を抜けてシェルで直接実行する(例: `:git stash`)。`:gh` も同様(例: `:gh issue list`)。
815
864
 
816
865
  ### GitStatus
817
866
 
@@ -827,7 +876,11 @@ Visual mode と同様に Normal mode の上に乗るモードとして設計さ
827
876
 
828
877
  ### GitBranch
829
878
 
830
- `:git branch` で `git branch -a` の結果を `kind: :git_branch` の読み取り専用バッファで表示。コミット日時の新しい順にソート。各行にブランチ名、日付、最新コミットのサブジェクトを表示。Enter でカーソル行のブランチをチェックアウト。
879
+ `:git branch` で `git branch -a` の結果を `kind: :git_branch` の読み取り専用バッファで表示。コミット日時の新しい順にソート。各行にブランチ名、日付、最新コミットのサブジェクトを表示。Enter でカーソル行のブランチ名を `:git checkout <branch>` としてコマンドラインにプリフィル(確認ステップあり、即時実行ではない)。
880
+
881
+ ### GitGrep
882
+
883
+ `:git grep <pattern> [<args>...]` で `git grep -n` を実行し、結果を `kind: :git_grep` の読み取り専用バッファで表示。追加引数をそのまま渡せる(例: `:git grep -i pattern`)。マッチがない場合はメッセージ表示のみ。Enter で該当ファイルの該当行にジャンプ。Esc / Ctrl-C でバッファを閉じる。
831
884
 
832
885
  ### GitCommit
833
886
 
@@ -836,7 +889,8 @@ Visual mode と同様に Normal mode の上に乗るモードとして設計さ
836
889
  ### GitBlame
837
890
 
838
891
  - **Blame バッファ**: `kind: :blame`、readonly、modifiable=false
839
- - 表示形式: `短縮ハッシュ 著者名 日付 コード行`
892
+ - 表示形式: ガター(行番号エリア)にメタ情報(短縮ハッシュ・著者名・日付)を暗灰色で表示、本文はコードのみで元ファイルの filetype に基づく syntax highlight が適用される
893
+ - `gutter_labels` オプション: バッファに行ごとのガターラベルを設定する汎用機能。設定されると行番号の代わりにラベルを表示
840
894
  - 内部で `git blame --porcelain` を使用して構造化パース
841
895
  - ソースファイルのカーソル行位置を引き継ぐ
842
896
 
@@ -848,6 +902,38 @@ Blame バッファ内のバッファローカルバインディング:
848
902
 
849
903
  実装: `lib/ruvim/git/blame.rb`(blame パース・実行)、`lib/ruvim/git/commands.rb`(status/diff/log 実行)、`lib/ruvim/global_commands.rb`(コマンドハンドラ)
850
904
 
905
+ ## GitHub 連携
906
+
907
+ ### gh link
908
+
909
+ `:gh link` で現在のファイル・カーソル行の GitHub URL を生成し、message line に表示する。同時に OSC 52 エスケープシーケンスでクリップボードにコピーする。
910
+
911
+ - ビジュアル選択範囲(`:'<,'>gh link`)を指定すると `#L5-L10` 形式の行範囲リンクを生成
912
+ - GitHub リモートを自動検出(全リモートを走査し、`origin` → `upstream` → その他の優先順位)
913
+ - SSH / HTTPS 両対応
914
+ - `:gh link <remote>` でリモート名を明示指定可能
915
+ - 現在のブランチ名を使用
916
+ - ファイルがリモートと異なる場合、URL の後に `(remote may differ)` を注記
917
+ - GitHub リモートが見つからない場合はエラー
918
+
919
+ ### gh browse
920
+
921
+ `:gh browse` で現在のファイル・カーソル行の GitHub URL をブラウザで開く。
922
+
923
+ - `:gh link` と同じ URL 解決ロジック(行範囲、リモート自動検出、リモート指定)
924
+ - ブラウザ起動は `Browser` モジュールを使用(macOS: `open`, Linux: `xdg-open`, WSL: `wslview` / PowerShell)
925
+ - 開いた URL を message line に表示
926
+ - ファイルがリモートと異なる場合、`(remote may differ)` を注記
927
+
928
+ ### gh pr
929
+
930
+ `:gh pr` で現在のブランチの PR ページをブラウザで開く。
931
+
932
+ - `https://github.com/user/repo/pulls?q=head:<branch>` を生成して開く
933
+ - ファイルパスがなくても動作(カレントディレクトリから git リポジトリを検出)
934
+
935
+ 実装: `lib/ruvim/gh/link.rb`, `lib/ruvim/browser.rb`
936
+
851
937
  ## テスト(現状)
852
938
 
853
939
  - `Minitest` を利用
data/docs/todo.md CHANGED
@@ -229,6 +229,15 @@
229
229
  - `spelllang`(スペルチェック言語)
230
230
  - `[PARTIAL]` `termguicolors`(検索/`cursorline`/`colorcolumn` 背景色の最小 truecolor 対応)
231
231
 
232
+ ## 大きいファイルの非同期ロード
233
+
234
+ - `-c` で渡したコマンドが非同期ロード中の不完全なバッファに対して実行される
235
+ - startup actions をロード完了後に遅延実行するコールバックを `finish_async_file_load!` に追加する
236
+ - ユーザーの対話操作は制限しない(`-c` 起動コマンドのみ遅延)
237
+ - 非同期ロードの性能改善(現状は同期パスの約3倍遅い)
238
+ - `Array<String>` ベースのバッファ構造が根本原因(split + GC 負荷)
239
+ - rope / lazy split 等のデータ構造変更が必要(大きな変更)
240
+
232
241
  ## メモ(実装方針)
233
242
 
234
243
  - Vim 完全互換の CLI を目指すより、よく使うフラグから互換寄りに実装する
data/docs/tutorial.md CHANGED
@@ -27,7 +27,7 @@ ruvim path/to/file.txt
27
27
  - `-S Session.vim`(session startup placeholder。現状は未実装メッセージのみ)
28
28
  - `-R`(readonly で開く。現在バッファの `:w` を拒否)
29
29
  - `-M`(modifiable off 相当。編集操作を拒否し、あわせて readonly)
30
- - `-Z`(restricted mode。config/ftplugin を読まず、`:ruby` と `:!` を無効化)
30
+ - `-Z`(restricted mode。config/ftplugin を読まず、`:ruby`、`:!`、`:grep`、`:lgrep`、`:git`、`:gh` を無効化)
31
31
  - `-f`(follow mode: `tail -f` 相当。ファイルの追記をリアルタイムに追従)
32
32
  - `-n`(現状 no-op。将来の swap/永続機能向け互換フラグ)
33
33
  - `-o[N]` / `-O[N]` / `-p[N]`(複数ファイルを split / vsplit / tab で開く)
@@ -146,6 +146,14 @@ ruvim -p a.rb b.rb
146
146
  - `:copen`, `:cnext`, `:cprev`, `:cclose`
147
147
  - `:lvimgrep /foo/`
148
148
  - `:lopen`, `:lnext`, `:lprev`, `:lclose`
149
+ - `:grep pattern [files...]`(外部 grep → quickfix)
150
+ - `:lgrep pattern [files...]`(外部 grep → location list)
151
+ - `:git blame` / `:git status` / `:git diff` / `:git log` / `:git branch` / `:git commit` / `:git grep`
152
+ - `:gh link` / `:gh browse` / `:gh pr`
153
+ - `:r file.txt`(ファイルの内容をカーソル行の下に挿入)
154
+ - `:r !ls`(コマンドの出力をカーソル行の下に挿入)
155
+ - `:w !wc -l`(バッファの内容をコマンドの stdin にパイプ)
156
+ - `:!ls`(alternate screen でシェルコマンドを実行)
149
157
 
150
158
  ## Follow mode(`tail -f` 相当)
151
159
 
data/docs/vim_diff.md CHANGED
@@ -84,6 +84,19 @@ RuVim は「Vim ライクな Ruby 製ターミナルエディタ」です。Vim
84
84
  - 補完: Ex コマンド名 + 引数補完, Insert mode buffer words(`Ctrl-n` / `Ctrl-p`)
85
85
  - CLI: `--help`, `--version`, `--clean`, `-u`, `-R`, `-M`, `-Z`, `-f`, `-o/-O/-p`, `-c`, `+{cmd}`, `-V`, `--startuptime`, `--cmd`
86
86
 
87
+ ## セキュリティ / Restricted mode (`-Z`)
88
+
89
+ - Vim と同様に `-Z` で restricted mode を有効化
90
+ - RuVim では以下のコマンドが無効化される:
91
+ - `:!`(シェル実行)
92
+ - `:ruby` / `:rb`(Ruby eval)
93
+ - `:grep` / `:lgrep`(外部 grep 実行)
94
+ - `:git`(Git 操作全般)
95
+ - `:gh`(GitHub 操作全般)
96
+ - `:grep` / `:lgrep` はシェル経由ではなく argv 配列で安全に実行(シェルインジェクション対策済み)
97
+ - Rich view レンダリング時にバッファ内容の制御文字を無害化(ターミナルエスケープインジェクション対策)
98
+ - 特殊ファイル(FIFO/デバイス/ソケット)の読み込みを拒否(DoS 対策)
99
+
87
100
  ## 動作の微細な差分
88
101
 
89
102
  - undo 粒度は簡略化(Insert mode は「入ってから出るまで」が 1 undo 単位)
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "mkmf"
4
+
5
+ create_makefile("ruvim/ruvim_ext")