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/test/lang_test.rb ADDED
@@ -0,0 +1,634 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "test_helper"
4
+
5
+ class LangTest < Minitest::Test
6
+ # --- YAML ---
7
+
8
+ def test_yaml_key_highlighted
9
+ cols = RuVim::Highlighter.color_columns("yaml", "name: value")
10
+ assert_equal "\e[36m", cols[0] # "name" as key
11
+ end
12
+
13
+ def test_yaml_string_highlighted
14
+ cols = RuVim::Highlighter.color_columns("yaml", 'key: "hello"')
15
+ assert_equal "\e[32m", cols[5] # opening quote
16
+ end
17
+
18
+ def test_yaml_boolean_highlighted
19
+ cols = RuVim::Highlighter.color_columns("yaml", "enabled: true")
20
+ assert_equal "\e[35m", cols[9] # "true"
21
+ end
22
+
23
+ def test_yaml_comment_overrides
24
+ cols = RuVim::Highlighter.color_columns("yaml", "# comment")
25
+ assert_equal "\e[90m", cols[0]
26
+ assert_equal "\e[90m", cols[8]
27
+ end
28
+
29
+ def test_yaml_anchor
30
+ cols = RuVim::Highlighter.color_columns("yaml", "base: &default")
31
+ assert_equal "\e[93m", cols[6] # "&default"
32
+ end
33
+
34
+ def test_yaml_empty
35
+ cols = RuVim::Highlighter.color_columns("yaml", "")
36
+ assert_empty cols
37
+ end
38
+
39
+ # --- Shell ---
40
+
41
+ def test_sh_keyword_if
42
+ cols = RuVim::Highlighter.color_columns("sh", "if [ -f foo ]; then")
43
+ assert_equal "\e[36m", cols[0] # "if"
44
+ end
45
+
46
+ def test_sh_variable
47
+ cols = RuVim::Highlighter.color_columns("sh", 'echo $HOME')
48
+ assert_equal "\e[93m", cols[5] # "$HOME"
49
+ end
50
+
51
+ def test_sh_string
52
+ cols = RuVim::Highlighter.color_columns("sh", 'x="hello"')
53
+ assert_equal "\e[32m", cols[2] # opening quote
54
+ end
55
+
56
+ def test_sh_comment
57
+ cols = RuVim::Highlighter.color_columns("sh", "# comment here")
58
+ assert_equal "\e[90m", cols[0]
59
+ end
60
+
61
+ def test_sh_empty
62
+ cols = RuVim::Highlighter.color_columns("sh", "")
63
+ assert_empty cols
64
+ end
65
+
66
+ # --- Python ---
67
+
68
+ def test_python_keyword_def
69
+ cols = RuVim::Highlighter.color_columns("python", "def foo():")
70
+ assert_equal "\e[36m", cols[0] # "def"
71
+ end
72
+
73
+ def test_python_decorator
74
+ cols = RuVim::Highlighter.color_columns("python", "@staticmethod")
75
+ assert_equal "\e[35m", cols[0] # "@"
76
+ end
77
+
78
+ def test_python_string
79
+ cols = RuVim::Highlighter.color_columns("python", 'x = "hello"')
80
+ assert_equal "\e[32m", cols[4] # opening quote
81
+ end
82
+
83
+ def test_python_builtin
84
+ cols = RuVim::Highlighter.color_columns("python", "print(len(x))")
85
+ assert_equal "\e[35m", cols[0] # "print"
86
+ end
87
+
88
+ def test_python_comment
89
+ cols = RuVim::Highlighter.color_columns("python", "x = 1 # comment")
90
+ assert_equal "\e[90m", cols[7]
91
+ end
92
+
93
+ def test_python_empty
94
+ cols = RuVim::Highlighter.color_columns("python", "")
95
+ assert_empty cols
96
+ end
97
+
98
+ # --- JavaScript ---
99
+
100
+ def test_javascript_keyword_const
101
+ cols = RuVim::Highlighter.color_columns("javascript", "const x = 42;")
102
+ assert_equal "\e[36m", cols[0] # "const"
103
+ end
104
+
105
+ def test_javascript_string
106
+ cols = RuVim::Highlighter.color_columns("javascript", "let s = 'hello';")
107
+ assert_equal "\e[32m", cols[8] # opening quote
108
+ end
109
+
110
+ def test_javascript_template_string
111
+ cols = RuVim::Highlighter.color_columns("javascript", "let s = `hello`;")
112
+ assert_equal "\e[32m", cols[8] # opening backtick
113
+ end
114
+
115
+ def test_javascript_number
116
+ cols = RuVim::Highlighter.color_columns("javascript", "let x = 42;")
117
+ assert_equal "\e[33m", cols[8]
118
+ end
119
+
120
+ def test_javascript_line_comment
121
+ cols = RuVim::Highlighter.color_columns("javascript", "x = 1; // comment")
122
+ assert_equal "\e[90m", cols[7]
123
+ end
124
+
125
+ def test_javascript_empty
126
+ cols = RuVim::Highlighter.color_columns("javascript", "")
127
+ assert_empty cols
128
+ end
129
+
130
+ # --- TypeScript ---
131
+
132
+ def test_typescript_keyword_interface
133
+ cols = RuVim::Highlighter.color_columns("typescript", "interface Foo {}")
134
+ assert_equal "\e[36m", cols[0] # "interface"
135
+ end
136
+
137
+ def test_typescript_inherits_js_string
138
+ cols = RuVim::Highlighter.color_columns("typescript", 'let s = "hello";')
139
+ assert_equal "\e[32m", cols[8]
140
+ end
141
+
142
+ def test_typescript_empty
143
+ cols = RuVim::Highlighter.color_columns("typescript", "")
144
+ assert_empty cols
145
+ end
146
+
147
+ # --- HTML ---
148
+
149
+ def test_html_tag
150
+ cols = RuVim::Highlighter.color_columns("html", "<div>hello</div>")
151
+ assert_equal "\e[36m", cols[0] # "<div"
152
+ end
153
+
154
+ def test_html_attribute_string
155
+ cols = RuVim::Highlighter.color_columns("html", '<a href="url">')
156
+ assert_equal "\e[32m", cols[8] # opening quote
157
+ end
158
+
159
+ def test_html_comment
160
+ cols = RuVim::Highlighter.color_columns("html", "<!-- comment -->")
161
+ assert_equal "\e[90m", cols[0]
162
+ end
163
+
164
+ def test_html_empty
165
+ cols = RuVim::Highlighter.color_columns("html", "")
166
+ assert_empty cols
167
+ end
168
+
169
+ # --- TOML ---
170
+
171
+ def test_toml_table_header
172
+ cols = RuVim::Highlighter.color_columns("toml", "[package]")
173
+ assert_equal "\e[1;36m", cols[0]
174
+ end
175
+
176
+ def test_toml_key
177
+ cols = RuVim::Highlighter.color_columns("toml", "name = \"test\"")
178
+ assert_equal "\e[36m", cols[0] # "name"
179
+ end
180
+
181
+ def test_toml_string
182
+ cols = RuVim::Highlighter.color_columns("toml", 'name = "test"')
183
+ assert_equal "\e[32m", cols[7] # opening quote
184
+ end
185
+
186
+ def test_toml_comment
187
+ cols = RuVim::Highlighter.color_columns("toml", "# comment")
188
+ assert_equal "\e[90m", cols[0]
189
+ end
190
+
191
+ def test_toml_empty
192
+ cols = RuVim::Highlighter.color_columns("toml", "")
193
+ assert_empty cols
194
+ end
195
+
196
+ # --- Go ---
197
+
198
+ def test_go_keyword_func
199
+ cols = RuVim::Highlighter.color_columns("go", "func main() {")
200
+ assert_equal "\e[36m", cols[0] # "func"
201
+ end
202
+
203
+ def test_go_type
204
+ cols = RuVim::Highlighter.color_columns("go", "var x int = 42")
205
+ assert_equal "\e[36m", cols[6] # "int"
206
+ end
207
+
208
+ def test_go_string
209
+ cols = RuVim::Highlighter.color_columns("go", 'fmt.Println("hello")')
210
+ assert_equal "\e[32m", cols[12] # opening quote
211
+ end
212
+
213
+ def test_go_line_comment
214
+ cols = RuVim::Highlighter.color_columns("go", "x := 1 // comment")
215
+ assert_equal "\e[90m", cols[7]
216
+ end
217
+
218
+ def test_go_empty
219
+ cols = RuVim::Highlighter.color_columns("go", "")
220
+ assert_empty cols
221
+ end
222
+
223
+ # --- Rust ---
224
+
225
+ def test_rust_keyword_fn
226
+ cols = RuVim::Highlighter.color_columns("rust", "fn main() {")
227
+ assert_equal "\e[36m", cols[0] # "fn"
228
+ end
229
+
230
+ def test_rust_keyword_let
231
+ cols = RuVim::Highlighter.color_columns("rust", "let mut x = 42;")
232
+ assert_equal "\e[36m", cols[0] # "let"
233
+ assert_equal "\e[36m", cols[4] # "mut"
234
+ end
235
+
236
+ def test_rust_string
237
+ cols = RuVim::Highlighter.color_columns("rust", 'println!("hello");')
238
+ assert_equal "\e[32m", cols[9] # opening quote
239
+ end
240
+
241
+ def test_rust_lifetime
242
+ cols = RuVim::Highlighter.color_columns("rust", "fn foo<'a>(x: &'a str)")
243
+ assert_equal "\e[35m", cols[7] # "'a"
244
+ end
245
+
246
+ def test_rust_line_comment
247
+ cols = RuVim::Highlighter.color_columns("rust", "x = 1; // comment")
248
+ assert_equal "\e[90m", cols[7]
249
+ end
250
+
251
+ def test_rust_empty
252
+ cols = RuVim::Highlighter.color_columns("rust", "")
253
+ assert_empty cols
254
+ end
255
+
256
+ # --- Makefile ---
257
+
258
+ def test_makefile_target
259
+ cols = RuVim::Highlighter.color_columns("make", "all:")
260
+ assert_equal "\e[1;33m", cols[0]
261
+ end
262
+
263
+ def test_makefile_variable_ref
264
+ cols = RuVim::Highlighter.color_columns("make", "\t$(CC) -o $@ $<")
265
+ assert_equal "\e[93m", cols[1] # "$(CC)"
266
+ end
267
+
268
+ def test_makefile_comment
269
+ cols = RuVim::Highlighter.color_columns("make", "# comment")
270
+ assert_equal "\e[90m", cols[0]
271
+ end
272
+
273
+ def test_makefile_empty
274
+ cols = RuVim::Highlighter.color_columns("make", "")
275
+ assert_empty cols
276
+ end
277
+
278
+ # --- Dockerfile ---
279
+
280
+ def test_dockerfile_instruction
281
+ cols = RuVim::Highlighter.color_columns("dockerfile", "FROM ubuntu:22.04")
282
+ assert_equal "\e[36m", cols[0] # "FROM"
283
+ end
284
+
285
+ def test_dockerfile_variable
286
+ cols = RuVim::Highlighter.color_columns("dockerfile", "ENV PATH=$PATH:/app")
287
+ assert_equal "\e[93m", cols[9] # "$PATH"
288
+ end
289
+
290
+ def test_dockerfile_comment
291
+ cols = RuVim::Highlighter.color_columns("dockerfile", "# comment")
292
+ assert_equal "\e[90m", cols[0]
293
+ end
294
+
295
+ def test_dockerfile_empty
296
+ cols = RuVim::Highlighter.color_columns("dockerfile", "")
297
+ assert_empty cols
298
+ end
299
+
300
+ # --- SQL ---
301
+
302
+ def test_sql_keyword_select
303
+ cols = RuVim::Highlighter.color_columns("sql", "SELECT * FROM users;")
304
+ assert_equal "\e[36m", cols[0] # "SELECT"
305
+ end
306
+
307
+ def test_sql_string
308
+ cols = RuVim::Highlighter.color_columns("sql", "WHERE name = 'foo'")
309
+ assert_equal "\e[32m", cols[13] # opening quote
310
+ end
311
+
312
+ def test_sql_line_comment
313
+ cols = RuVim::Highlighter.color_columns("sql", "-- comment")
314
+ assert_equal "\e[90m", cols[0]
315
+ end
316
+
317
+ def test_sql_empty
318
+ cols = RuVim::Highlighter.color_columns("sql", "")
319
+ assert_empty cols
320
+ end
321
+
322
+ # --- Elixir ---
323
+
324
+ def test_elixir_keyword_def
325
+ cols = RuVim::Highlighter.color_columns("elixir", "def hello do")
326
+ assert_equal "\e[36m", cols[0] # "def"
327
+ end
328
+
329
+ def test_elixir_atom
330
+ cols = RuVim::Highlighter.color_columns("elixir", ":ok")
331
+ assert_equal "\e[96m", cols[0] # ":ok"
332
+ end
333
+
334
+ def test_elixir_module_attribute
335
+ cols = RuVim::Highlighter.color_columns("elixir", "@moduledoc false")
336
+ assert_equal "\e[93m", cols[0] # "@moduledoc"
337
+ end
338
+
339
+ def test_elixir_string
340
+ cols = RuVim::Highlighter.color_columns("elixir", 'IO.puts("hello")')
341
+ assert_equal "\e[32m", cols[8] # opening quote
342
+ end
343
+
344
+ def test_elixir_comment
345
+ cols = RuVim::Highlighter.color_columns("elixir", "# comment")
346
+ assert_equal "\e[90m", cols[0]
347
+ end
348
+
349
+ def test_elixir_empty
350
+ cols = RuVim::Highlighter.color_columns("elixir", "")
351
+ assert_empty cols
352
+ end
353
+
354
+ # --- Perl ---
355
+
356
+ def test_perl_keyword_my
357
+ cols = RuVim::Highlighter.color_columns("perl", "my $x = 42;")
358
+ assert_equal "\e[36m", cols[0] # "my"
359
+ end
360
+
361
+ def test_perl_scalar_variable
362
+ cols = RuVim::Highlighter.color_columns("perl", "my $name = 1;")
363
+ assert_equal "\e[93m", cols[3] # "$name"
364
+ end
365
+
366
+ def test_perl_array_variable
367
+ cols = RuVim::Highlighter.color_columns("perl", "my @list = (1,2);")
368
+ assert_equal "\e[35m", cols[3] # "@list"
369
+ end
370
+
371
+ def test_perl_hash_variable
372
+ cols = RuVim::Highlighter.color_columns("perl", 'my %hash = (a => 1);')
373
+ assert_equal "\e[96m", cols[3] # "%hash"
374
+ end
375
+
376
+ def test_perl_string
377
+ cols = RuVim::Highlighter.color_columns("perl", 'print "hello";')
378
+ assert_equal "\e[32m", cols[6] # opening quote
379
+ end
380
+
381
+ def test_perl_comment
382
+ cols = RuVim::Highlighter.color_columns("perl", "# comment")
383
+ assert_equal "\e[90m", cols[0]
384
+ end
385
+
386
+ def test_perl_pod_line
387
+ cols = RuVim::Highlighter.color_columns("perl", "=head1 NAME")
388
+ assert_equal "\e[90m", cols[0]
389
+ assert_equal "\e[90m", cols[10]
390
+ end
391
+
392
+ def test_perl_empty
393
+ cols = RuVim::Highlighter.color_columns("perl", "")
394
+ assert_empty cols
395
+ end
396
+
397
+ # --- Lua ---
398
+
399
+ def test_lua_keyword_function
400
+ cols = RuVim::Highlighter.color_columns("lua", "function hello()")
401
+ assert_equal "\e[36m", cols[0] # "function"
402
+ end
403
+
404
+ def test_lua_keyword_local
405
+ cols = RuVim::Highlighter.color_columns("lua", "local x = 42")
406
+ assert_equal "\e[36m", cols[0] # "local"
407
+ end
408
+
409
+ def test_lua_string
410
+ cols = RuVim::Highlighter.color_columns("lua", 'print("hello")')
411
+ assert_equal "\e[32m", cols[6] # opening quote
412
+ end
413
+
414
+ def test_lua_builtin
415
+ cols = RuVim::Highlighter.color_columns("lua", "print(type(x))")
416
+ assert_equal "\e[35m", cols[0] # "print"
417
+ end
418
+
419
+ def test_lua_line_comment
420
+ cols = RuVim::Highlighter.color_columns("lua", "-- comment")
421
+ assert_equal "\e[90m", cols[0]
422
+ end
423
+
424
+ def test_lua_number
425
+ cols = RuVim::Highlighter.color_columns("lua", "local x = 42")
426
+ assert_equal "\e[33m", cols[10] # "4"
427
+ end
428
+
429
+ def test_lua_empty
430
+ cols = RuVim::Highlighter.color_columns("lua", "")
431
+ assert_empty cols
432
+ end
433
+
434
+ # --- OCaml ---
435
+
436
+ def test_ocaml_keyword_let
437
+ cols = RuVim::Highlighter.color_columns("ocaml", "let x = 42")
438
+ assert_equal "\e[36m", cols[0] # "let"
439
+ end
440
+
441
+ def test_ocaml_keyword_match
442
+ cols = RuVim::Highlighter.color_columns("ocaml", "match x with")
443
+ assert_equal "\e[36m", cols[0] # "match"
444
+ end
445
+
446
+ def test_ocaml_string
447
+ cols = RuVim::Highlighter.color_columns("ocaml", 'let s = "hello"')
448
+ assert_equal "\e[32m", cols[8] # opening quote
449
+ end
450
+
451
+ def test_ocaml_block_comment
452
+ cols = RuVim::Highlighter.color_columns("ocaml", "(* comment *)")
453
+ assert_equal "\e[90m", cols[0]
454
+ assert_equal "\e[90m", cols[12]
455
+ end
456
+
457
+ def test_ocaml_type_variable
458
+ cols = RuVim::Highlighter.color_columns("ocaml", "type 'a list")
459
+ assert_equal "\e[93m", cols[5] # "'a"
460
+ end
461
+
462
+ def test_ocaml_number
463
+ cols = RuVim::Highlighter.color_columns("ocaml", "let x = 42")
464
+ assert_equal "\e[33m", cols[8] # "4"
465
+ end
466
+
467
+ def test_ocaml_empty
468
+ cols = RuVim::Highlighter.color_columns("ocaml", "")
469
+ assert_empty cols
470
+ end
471
+
472
+ # --- Filetype detection ---
473
+
474
+ def test_detect_filetype_yaml
475
+ editor = fresh_editor
476
+ assert_equal "yaml", editor.detect_filetype("config.yml")
477
+ assert_equal "yaml", editor.detect_filetype("config.yaml")
478
+ end
479
+
480
+ def test_detect_filetype_sh
481
+ editor = fresh_editor
482
+ assert_equal "sh", editor.detect_filetype("script.sh")
483
+ assert_equal "sh", editor.detect_filetype("script.bash")
484
+ assert_equal "sh", editor.detect_filetype("script.zsh")
485
+ end
486
+
487
+ def test_detect_filetype_python
488
+ editor = fresh_editor
489
+ assert_equal "python", editor.detect_filetype("app.py")
490
+ end
491
+
492
+ def test_detect_filetype_javascript
493
+ editor = fresh_editor
494
+ assert_equal "javascript", editor.detect_filetype("app.js")
495
+ assert_equal "javascript", editor.detect_filetype("app.mjs")
496
+ end
497
+
498
+ def test_detect_filetype_typescript
499
+ editor = fresh_editor
500
+ assert_equal "typescript", editor.detect_filetype("app.ts")
501
+ assert_equal "typescriptreact", editor.detect_filetype("app.tsx")
502
+ end
503
+
504
+ def test_detect_filetype_html
505
+ editor = fresh_editor
506
+ assert_equal "html", editor.detect_filetype("index.html")
507
+ assert_equal "html", editor.detect_filetype("index.htm")
508
+ end
509
+
510
+ def test_detect_filetype_toml
511
+ editor = fresh_editor
512
+ assert_equal "toml", editor.detect_filetype("Cargo.toml")
513
+ end
514
+
515
+ def test_detect_filetype_go
516
+ editor = fresh_editor
517
+ assert_equal "go", editor.detect_filetype("main.go")
518
+ end
519
+
520
+ def test_detect_filetype_rust
521
+ editor = fresh_editor
522
+ assert_equal "rust", editor.detect_filetype("main.rs")
523
+ end
524
+
525
+ def test_detect_filetype_makefile
526
+ editor = fresh_editor
527
+ assert_equal "make", editor.detect_filetype("Makefile")
528
+ assert_equal "make", editor.detect_filetype("GNUmakefile")
529
+ end
530
+
531
+ def test_detect_filetype_dockerfile
532
+ editor = fresh_editor
533
+ assert_equal "dockerfile", editor.detect_filetype("Dockerfile")
534
+ assert_equal "dockerfile", editor.detect_filetype("Dockerfile.prod")
535
+ end
536
+
537
+ def test_detect_filetype_sql
538
+ editor = fresh_editor
539
+ assert_equal "sql", editor.detect_filetype("schema.sql")
540
+ end
541
+
542
+ def test_detect_filetype_elixir
543
+ editor = fresh_editor
544
+ assert_equal "elixir", editor.detect_filetype("app.ex")
545
+ assert_equal "elixir", editor.detect_filetype("app.exs")
546
+ end
547
+
548
+ def test_detect_filetype_perl
549
+ editor = fresh_editor
550
+ assert_equal "perl", editor.detect_filetype("script.pl")
551
+ assert_equal "perl", editor.detect_filetype("Module.pm")
552
+ end
553
+
554
+ def test_detect_filetype_lua
555
+ editor = fresh_editor
556
+ assert_equal "lua", editor.detect_filetype("init.lua")
557
+ end
558
+
559
+ def test_detect_filetype_ocaml
560
+ editor = fresh_editor
561
+ assert_equal "ocaml", editor.detect_filetype("main.ml")
562
+ assert_equal "ocaml", editor.detect_filetype("main.mli")
563
+ end
564
+
565
+ # --- Indent support ---
566
+
567
+ def test_python_indent_after_colon
568
+ assert RuVim::Lang::Python.indent_trigger?("def foo():")
569
+ assert RuVim::Lang::Python.indent_trigger?("if x > 0:")
570
+ end
571
+
572
+ def test_javascript_indent_after_brace
573
+ assert RuVim::Lang::Javascript.indent_trigger?("function foo() {")
574
+ end
575
+
576
+ def test_go_indent_after_brace
577
+ assert RuVim::Lang::Go.indent_trigger?("func main() {")
578
+ end
579
+
580
+ def test_rust_indent_after_brace
581
+ assert RuVim::Lang::Rust.indent_trigger?("fn main() {")
582
+ end
583
+
584
+ def test_elixir_indent_after_do
585
+ assert RuVim::Lang::Elixir.indent_trigger?("def hello do")
586
+ end
587
+
588
+ def test_lua_indent_after_function
589
+ assert RuVim::Lang::Lua.indent_trigger?("function hello()")
590
+ end
591
+
592
+ def test_sh_indent_after_then
593
+ assert RuVim::Lang::Sh.indent_trigger?("if [ -f foo ]; then")
594
+ end
595
+
596
+ def test_yaml_indent_after_key_colon
597
+ assert RuVim::Lang::Yaml.indent_trigger?("services:")
598
+ end
599
+
600
+ # --- ERB ---
601
+
602
+ def test_erb_html_tag_highlighted
603
+ cols = RuVim::Highlighter.color_columns("erb", "<div>hello</div>")
604
+ assert_equal "\e[36m", cols[0] # "<div"
605
+ end
606
+
607
+ def test_erb_ruby_tag_highlighted
608
+ cols = RuVim::Highlighter.color_columns("erb", '<%= link_to "home", root_path %>')
609
+ # <%= and %> delimiters should be highlighted
610
+ assert_equal "\e[35m", cols[0] # "<%="
611
+ end
612
+
613
+ def test_erb_ruby_comment_tag
614
+ cols = RuVim::Highlighter.color_columns("erb", "<%# this is a comment %>")
615
+ assert_equal "\e[90m", cols[0]
616
+ end
617
+
618
+ def test_erb_mixed_html_and_ruby
619
+ cols = RuVim::Highlighter.color_columns("erb", '<p><%= "hi" %></p>')
620
+ assert_equal "\e[36m", cols[0] # "<p"
621
+ assert_equal "\e[35m", cols[3] # "<%="
622
+ end
623
+
624
+ def test_erb_empty
625
+ cols = RuVim::Highlighter.color_columns("erb", "")
626
+ assert_empty cols
627
+ end
628
+
629
+ def test_detect_filetype_erb
630
+ editor = fresh_editor
631
+ assert_equal "erb", editor.detect_filetype("index.html.erb")
632
+ assert_equal "erb", editor.detect_filetype("show.erb")
633
+ end
634
+ end
@@ -8,11 +8,11 @@ class MarkdownRendererTest < Minitest::Test
8
8
  # --- Registration ---
9
9
 
10
10
  def test_renderer_registered_for_markdown
11
- assert_equal renderer, RuVim::RichView.renderer_for("markdown")
11
+ assert_equal renderer, RuVim::RichView.renderer_for(:markdown)
12
12
  end
13
13
 
14
14
  def test_delimiter_for_markdown
15
- assert_nil renderer.delimiter_for("markdown")
15
+ assert_nil renderer.delimiter_for(:markdown)
16
16
  end
17
17
 
18
18
  # --- Headings ---
@@ -240,10 +240,10 @@ class MarkdownRendererTest < Minitest::Test
240
240
  buf.replace_all_lines!(["# Title", "", "Some **bold** text"])
241
241
  buf.options["filetype"] = "markdown"
242
242
 
243
- RuVim::RichView.open!(editor, format: "markdown")
243
+ RuVim::RichView.open!(editor, format: :markdown)
244
244
  assert_equal :rich, editor.mode
245
245
  state = editor.rich_state
246
- assert_equal "markdown", state[:format]
246
+ assert_equal :markdown, state[:format]
247
247
 
248
248
  # Render visible lines
249
249
  lines = (0...buf.line_count).map { |i| buf.line_at(i) }
@@ -260,7 +260,7 @@ class MarkdownRendererTest < Minitest::Test
260
260
  editor = fresh_editor
261
261
  buf = editor.current_buffer
262
262
  buf.options["filetype"] = "markdown"
263
- assert_equal "markdown", RuVim::RichView.detect_format(buf)
263
+ assert_equal :markdown, RuVim::RichView.detect_format(buf)
264
264
  end
265
265
 
266
266
  private