ruvim 0.3.0 → 0.4.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/AGENTS.md +18 -6
- data/README.md +15 -1
- data/docs/binding.md +16 -0
- data/docs/command.md +78 -4
- data/docs/config.md +10 -2
- data/docs/spec.md +60 -9
- data/docs/tutorial.md +24 -0
- data/docs/vim_diff.md +18 -8
- data/lib/ruvim/app.rb +290 -8
- data/lib/ruvim/buffer.rb +14 -2
- data/lib/ruvim/cli.rb +6 -0
- data/lib/ruvim/editor.rb +12 -1
- data/lib/ruvim/file_watcher.rb +243 -0
- data/lib/ruvim/git/blame.rb +245 -0
- data/lib/ruvim/git/branch.rb +97 -0
- data/lib/ruvim/git/commit.rb +102 -0
- data/lib/ruvim/git/diff.rb +129 -0
- data/lib/ruvim/git/handler.rb +84 -0
- data/lib/ruvim/git/log.rb +41 -0
- data/lib/ruvim/git/status.rb +103 -0
- data/lib/ruvim/global_commands.rb +176 -42
- data/lib/ruvim/highlighter.rb +3 -1
- data/lib/ruvim/input.rb +1 -0
- data/lib/ruvim/lang/diff.rb +41 -0
- data/lib/ruvim/lang/json.rb +34 -0
- data/lib/ruvim/rich_view/json_renderer.rb +131 -0
- data/lib/ruvim/rich_view/jsonl_renderer.rb +57 -0
- data/lib/ruvim/rich_view.rb +16 -0
- data/lib/ruvim/screen.rb +9 -12
- data/lib/ruvim/version.rb +1 -1
- data/lib/ruvim.rb +10 -0
- data/test/app_completion_test.rb +25 -0
- data/test/app_scenario_test.rb +169 -0
- data/test/cli_test.rb +14 -0
- data/test/clipboard_test.rb +67 -0
- data/test/command_line_test.rb +118 -0
- data/test/config_dsl_test.rb +87 -0
- data/test/display_width_test.rb +41 -0
- data/test/file_watcher_test.rb +197 -0
- data/test/follow_test.rb +199 -0
- data/test/git_blame_test.rb +713 -0
- data/test/highlighter_test.rb +44 -0
- data/test/indent_test.rb +86 -0
- data/test/rich_view_test.rb +256 -0
- data/test/search_option_test.rb +19 -0
- data/test/test_helper.rb +9 -0
- metadata +17 -1
data/test/highlighter_test.rb
CHANGED
|
@@ -14,6 +14,12 @@ class HighlighterTest < Minitest::Test
|
|
|
14
14
|
assert_equal "\e[33m", cols[6] # number start
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
+
def test_jsonl_highlighter_reuses_json_colors
|
|
18
|
+
cols = RuVim::Highlighter.color_columns("jsonl", '{"a": 10}')
|
|
19
|
+
assert_equal "\e[36m", cols[1] # key chars
|
|
20
|
+
assert_equal "\e[33m", cols[6] # number start
|
|
21
|
+
end
|
|
22
|
+
|
|
17
23
|
def test_ruby_highlighter_marks_instance_variables_and_constants
|
|
18
24
|
cols = RuVim::Highlighter.color_columns("ruby", "@x = Foo")
|
|
19
25
|
assert_equal "\e[93m", cols[0] # @x
|
|
@@ -134,4 +140,42 @@ class HighlighterTest < Minitest::Test
|
|
|
134
140
|
cols = RuVim::Highlighter.color_columns("scheme", "")
|
|
135
141
|
assert_empty cols
|
|
136
142
|
end
|
|
143
|
+
|
|
144
|
+
# --- Diff ---
|
|
145
|
+
|
|
146
|
+
def test_diff_add_line_green
|
|
147
|
+
cols = RuVim::Highlighter.color_columns("diff", "+added line")
|
|
148
|
+
refute_empty cols
|
|
149
|
+
assert_equal "\e[32m", cols[0]
|
|
150
|
+
assert_equal "\e[32m", cols[5]
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def test_diff_delete_line_red
|
|
154
|
+
cols = RuVim::Highlighter.color_columns("diff", "-removed line")
|
|
155
|
+
refute_empty cols
|
|
156
|
+
assert_equal "\e[31m", cols[0]
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def test_diff_hunk_header_cyan
|
|
160
|
+
cols = RuVim::Highlighter.color_columns("diff", "@@ -1,3 +1,4 @@ def foo")
|
|
161
|
+
refute_empty cols
|
|
162
|
+
assert_equal "\e[36m", cols[0]
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def test_diff_header_bold
|
|
166
|
+
cols = RuVim::Highlighter.color_columns("diff", "diff --git a/foo.rb b/foo.rb")
|
|
167
|
+
refute_empty cols
|
|
168
|
+
assert_equal "\e[1m", cols[0]
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def test_diff_context_line_no_color
|
|
172
|
+
cols = RuVim::Highlighter.color_columns("diff", " context line")
|
|
173
|
+
assert_empty cols
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def test_diff_meta_line_yellow
|
|
177
|
+
cols = RuVim::Highlighter.color_columns("diff", "index abc..def 100644")
|
|
178
|
+
refute_empty cols
|
|
179
|
+
assert_equal "\e[33m", cols[0]
|
|
180
|
+
end
|
|
137
181
|
end
|
data/test/indent_test.rb
CHANGED
|
@@ -1,5 +1,91 @@
|
|
|
1
1
|
require_relative "test_helper"
|
|
2
2
|
|
|
3
|
+
class JsonIndentTest < Minitest::Test
|
|
4
|
+
def calc(lines, target_row, sw = 2)
|
|
5
|
+
RuVim::Lang::Json.calculate_indent(lines, target_row, sw)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def test_first_line_is_zero
|
|
9
|
+
assert_equal 0, calc(["{"], 0)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def test_after_open_brace
|
|
13
|
+
lines = ["{", ' "key": "value"']
|
|
14
|
+
assert_equal 2, calc(lines, 1)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def test_close_brace
|
|
18
|
+
lines = ["{", ' "key": "value"', "}"]
|
|
19
|
+
assert_equal 0, calc(lines, 2)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def test_after_open_bracket
|
|
23
|
+
lines = ["[", " 1"]
|
|
24
|
+
assert_equal 2, calc(lines, 1)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def test_close_bracket
|
|
28
|
+
lines = ["[", " 1,", " 2", "]"]
|
|
29
|
+
assert_equal 0, calc(lines, 3)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def test_nested_objects
|
|
33
|
+
lines = [
|
|
34
|
+
"{",
|
|
35
|
+
' "a": {',
|
|
36
|
+
' "b": 1',
|
|
37
|
+
" }",
|
|
38
|
+
"}"
|
|
39
|
+
]
|
|
40
|
+
assert_equal 2, calc(lines, 1)
|
|
41
|
+
assert_equal 4, calc(lines, 2)
|
|
42
|
+
assert_equal 2, calc(lines, 3)
|
|
43
|
+
assert_equal 0, calc(lines, 4)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def test_array_in_object
|
|
47
|
+
lines = [
|
|
48
|
+
"{",
|
|
49
|
+
' "items": [',
|
|
50
|
+
" 1,",
|
|
51
|
+
" 2",
|
|
52
|
+
" ]",
|
|
53
|
+
"}"
|
|
54
|
+
]
|
|
55
|
+
assert_equal 2, calc(lines, 1)
|
|
56
|
+
assert_equal 4, calc(lines, 2)
|
|
57
|
+
assert_equal 4, calc(lines, 3)
|
|
58
|
+
assert_equal 2, calc(lines, 4)
|
|
59
|
+
assert_equal 0, calc(lines, 5)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def test_shiftwidth_4
|
|
63
|
+
lines = ["{", ' "key": 1', "}"]
|
|
64
|
+
assert_equal 4, calc(lines, 1, 4)
|
|
65
|
+
assert_equal 0, calc(lines, 2, 4)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def test_indent_trigger_open_brace
|
|
69
|
+
assert RuVim::Lang::Json.indent_trigger?("{")
|
|
70
|
+
assert RuVim::Lang::Json.indent_trigger?(' "key": {')
|
|
71
|
+
assert RuVim::Lang::Json.indent_trigger?(' "key": [')
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def test_indent_trigger_no_trigger
|
|
75
|
+
refute RuVim::Lang::Json.indent_trigger?(' "key": "value"')
|
|
76
|
+
refute RuVim::Lang::Json.indent_trigger?("}")
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def test_dedent_trigger_close_brace
|
|
80
|
+
assert_kind_of Regexp, RuVim::Lang::Json.dedent_trigger("}")
|
|
81
|
+
assert_kind_of Regexp, RuVim::Lang::Json.dedent_trigger("]")
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def test_dedent_trigger_no_trigger
|
|
85
|
+
assert_nil RuVim::Lang::Json.dedent_trigger("a")
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
3
89
|
class RubyIndentTest < Minitest::Test
|
|
4
90
|
def calc(lines, target_row, sw = 2)
|
|
5
91
|
RuVim::Lang::Ruby.calculate_indent(lines, target_row, sw)
|
data/test/rich_view_test.rb
CHANGED
|
@@ -459,6 +459,161 @@ class RichViewTest < Minitest::Test
|
|
|
459
459
|
assert_equal dc0, dc1, "Second field start should align across CJK and ASCII rows"
|
|
460
460
|
end
|
|
461
461
|
|
|
462
|
+
# --- JSON Rich View tests ---
|
|
463
|
+
|
|
464
|
+
def test_json_registered
|
|
465
|
+
assert RuVim::RichView.renderer_for("json")
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
def test_json_open_creates_virtual_buffer
|
|
469
|
+
editor = fresh_editor
|
|
470
|
+
buf = editor.current_buffer
|
|
471
|
+
buf.replace_all_lines!(['{"a":1,"b":[2,3]}'])
|
|
472
|
+
buf.options["filetype"] = "json"
|
|
473
|
+
count_before = editor.buffers.length
|
|
474
|
+
|
|
475
|
+
RuVim::RichView.open!(editor, format: "json")
|
|
476
|
+
assert_equal count_before + 1, editor.buffers.length
|
|
477
|
+
new_buf = editor.current_buffer
|
|
478
|
+
refute_equal buf.id, new_buf.id
|
|
479
|
+
assert_equal :json_formatted, new_buf.kind
|
|
480
|
+
assert new_buf.readonly?
|
|
481
|
+
end
|
|
482
|
+
|
|
483
|
+
def test_json_open_binds_close_keys
|
|
484
|
+
editor = fresh_editor
|
|
485
|
+
editor.keymap_manager = RuVim::KeymapManager.new
|
|
486
|
+
buf = editor.current_buffer
|
|
487
|
+
buf.replace_all_lines!(['{"a":1}'])
|
|
488
|
+
buf.options["filetype"] = "json"
|
|
489
|
+
|
|
490
|
+
RuVim::RichView.open!(editor, format: "json")
|
|
491
|
+
result = editor.keymap_manager.resolve_with_context(:normal, ["\e"], editor: editor)
|
|
492
|
+
assert_equal "rich.close_buffer", result.invocation.id
|
|
493
|
+
end
|
|
494
|
+
|
|
495
|
+
def test_json_open_pretty_prints
|
|
496
|
+
editor = fresh_editor
|
|
497
|
+
buf = editor.current_buffer
|
|
498
|
+
buf.replace_all_lines!(['{"a":1,"b":[2,3]}'])
|
|
499
|
+
buf.options["filetype"] = "json"
|
|
500
|
+
|
|
501
|
+
RuVim::RichView.open!(editor, format: "json")
|
|
502
|
+
new_buf = editor.current_buffer
|
|
503
|
+
lines = new_buf.lines
|
|
504
|
+
assert lines.length > 1, "Minified JSON should be expanded to multiple lines"
|
|
505
|
+
assert_equal "{", lines.first.strip
|
|
506
|
+
assert_equal "}", lines.last.strip
|
|
507
|
+
end
|
|
508
|
+
|
|
509
|
+
def test_json_open_multiline_buffer
|
|
510
|
+
editor = fresh_editor
|
|
511
|
+
buf = editor.current_buffer
|
|
512
|
+
buf.replace_all_lines!(['{', '"key": "value"', '}'])
|
|
513
|
+
buf.options["filetype"] = "json"
|
|
514
|
+
|
|
515
|
+
RuVim::RichView.open!(editor, format: "json")
|
|
516
|
+
new_buf = editor.current_buffer
|
|
517
|
+
lines = new_buf.lines
|
|
518
|
+
assert lines.length >= 3
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
def test_json_open_invalid_json_shows_error
|
|
522
|
+
editor = fresh_editor
|
|
523
|
+
buf = editor.current_buffer
|
|
524
|
+
buf.replace_all_lines!(['{"invalid json'])
|
|
525
|
+
buf.options["filetype"] = "json"
|
|
526
|
+
|
|
527
|
+
RuVim::RichView.open!(editor, format: "json")
|
|
528
|
+
# Should stay on original buffer
|
|
529
|
+
assert_equal buf.id, editor.current_buffer.id
|
|
530
|
+
assert_match(/JSON/, editor.message.to_s)
|
|
531
|
+
end
|
|
532
|
+
|
|
533
|
+
def test_json_open_does_not_enter_rich_mode
|
|
534
|
+
editor = fresh_editor
|
|
535
|
+
buf = editor.current_buffer
|
|
536
|
+
buf.replace_all_lines!(['{"a":1}'])
|
|
537
|
+
buf.options["filetype"] = "json"
|
|
538
|
+
|
|
539
|
+
RuVim::RichView.open!(editor, format: "json")
|
|
540
|
+
# Virtual buffer approach — no rich mode
|
|
541
|
+
assert_equal :normal, editor.mode
|
|
542
|
+
assert_nil editor.rich_state
|
|
543
|
+
end
|
|
544
|
+
|
|
545
|
+
def test_json_cursor_maps_to_formatted_line
|
|
546
|
+
editor = fresh_editor
|
|
547
|
+
buf = editor.current_buffer
|
|
548
|
+
# {"a":1,"b":{"c":2}}
|
|
549
|
+
buf.replace_all_lines!(['{"a":1,"b":{"c":2}}'])
|
|
550
|
+
buf.options["filetype"] = "json"
|
|
551
|
+
|
|
552
|
+
# Place cursor at "c" key — find its offset
|
|
553
|
+
line = buf.line_at(0)
|
|
554
|
+
idx = line.index('"c"')
|
|
555
|
+
editor.current_window.cursor_x = idx
|
|
556
|
+
|
|
557
|
+
RuVim::RichView.open!(editor, format: "json")
|
|
558
|
+
new_buf = editor.current_buffer
|
|
559
|
+
# Cursor should be on the line containing "c"
|
|
560
|
+
cursor_line = new_buf.line_at(editor.current_window.cursor_y)
|
|
561
|
+
assert_match(/"c"/, cursor_line, "Cursor should be on the line with \"c\" key")
|
|
562
|
+
end
|
|
563
|
+
|
|
564
|
+
def test_json_cursor_maps_multiline_source
|
|
565
|
+
editor = fresh_editor
|
|
566
|
+
buf = editor.current_buffer
|
|
567
|
+
buf.replace_all_lines!(['{', ' "x": [1, 2, 3]', '}'])
|
|
568
|
+
buf.options["filetype"] = "json"
|
|
569
|
+
|
|
570
|
+
# Place cursor on line 1 at the "x" key (col 2 = opening quote)
|
|
571
|
+
editor.current_window.cursor_y = 1
|
|
572
|
+
editor.current_window.cursor_x = 2
|
|
573
|
+
|
|
574
|
+
RuVim::RichView.open!(editor, format: "json")
|
|
575
|
+
new_buf = editor.current_buffer
|
|
576
|
+
cursor_line = new_buf.line_at(editor.current_window.cursor_y)
|
|
577
|
+
assert_match(/"x"/, cursor_line, "Cursor should be on the line with \"x\" key")
|
|
578
|
+
end
|
|
579
|
+
|
|
580
|
+
def test_json_cursor_at_start_stays_at_start
|
|
581
|
+
editor = fresh_editor
|
|
582
|
+
buf = editor.current_buffer
|
|
583
|
+
buf.replace_all_lines!(['{"a":1}'])
|
|
584
|
+
buf.options["filetype"] = "json"
|
|
585
|
+
editor.current_window.cursor_x = 0
|
|
586
|
+
|
|
587
|
+
RuVim::RichView.open!(editor, format: "json")
|
|
588
|
+
assert_equal 0, editor.current_window.cursor_y
|
|
589
|
+
end
|
|
590
|
+
|
|
591
|
+
def test_json_significant_offset
|
|
592
|
+
r = RuVim::RichView::JsonRenderer
|
|
593
|
+
# {"a" — 4 significant chars: { " a "
|
|
594
|
+
assert_equal 4, r.significant_char_count('{"a"', 4)
|
|
595
|
+
# { "a" — space outside string skipped, still 4 significant
|
|
596
|
+
assert_equal 4, r.significant_char_count('{ "a"', 5)
|
|
597
|
+
end
|
|
598
|
+
|
|
599
|
+
def test_json_line_for_significant_offset
|
|
600
|
+
formatted = "{\n \"a\": 1\n}"
|
|
601
|
+
r = RuVim::RichView::JsonRenderer
|
|
602
|
+
# count 0 → line 0 (before any char)
|
|
603
|
+
assert_equal 0, r.line_for_significant_count(formatted, 0)
|
|
604
|
+
# count 1 → line 0 ({ is the 1st significant char, on line 0)
|
|
605
|
+
assert_equal 0, r.line_for_significant_count(formatted, 1)
|
|
606
|
+
# count 2 → line 1 (" opening quote of "a" is on line 1)
|
|
607
|
+
assert_equal 1, r.line_for_significant_count(formatted, 2)
|
|
608
|
+
end
|
|
609
|
+
|
|
610
|
+
def test_json_filetype_detected
|
|
611
|
+
editor = fresh_editor
|
|
612
|
+
buf = editor.current_buffer
|
|
613
|
+
buf.options["filetype"] = "json"
|
|
614
|
+
assert_equal "json", RuVim::RichView.detect_format(buf)
|
|
615
|
+
end
|
|
616
|
+
|
|
462
617
|
# --- Filetype detection tests ---
|
|
463
618
|
|
|
464
619
|
def test_detect_filetype_tsv
|
|
@@ -475,4 +630,105 @@ class RichViewTest < Minitest::Test
|
|
|
475
630
|
editor = RuVim::Editor.new
|
|
476
631
|
assert_equal "tsv", editor.detect_filetype("DATA.TSV")
|
|
477
632
|
end
|
|
633
|
+
|
|
634
|
+
def test_detect_filetype_jsonl
|
|
635
|
+
editor = RuVim::Editor.new
|
|
636
|
+
assert_equal "jsonl", editor.detect_filetype("data.jsonl")
|
|
637
|
+
end
|
|
638
|
+
|
|
639
|
+
# --- JSONL Rich View tests ---
|
|
640
|
+
|
|
641
|
+
def test_jsonl_registered
|
|
642
|
+
assert RuVim::RichView.renderer_for("jsonl")
|
|
643
|
+
end
|
|
644
|
+
|
|
645
|
+
def test_jsonl_open_creates_virtual_buffer
|
|
646
|
+
editor = fresh_editor
|
|
647
|
+
buf = editor.current_buffer
|
|
648
|
+
buf.replace_all_lines!(['{"a":1}', '{"b":2}'])
|
|
649
|
+
buf.options["filetype"] = "jsonl"
|
|
650
|
+
count_before = editor.buffers.length
|
|
651
|
+
|
|
652
|
+
RuVim::RichView.open!(editor, format: "jsonl")
|
|
653
|
+
assert_equal count_before + 1, editor.buffers.length
|
|
654
|
+
new_buf = editor.current_buffer
|
|
655
|
+
refute_equal buf.id, new_buf.id
|
|
656
|
+
assert_equal :jsonl_formatted, new_buf.kind
|
|
657
|
+
assert new_buf.readonly?
|
|
658
|
+
end
|
|
659
|
+
|
|
660
|
+
def test_jsonl_open_binds_close_keys
|
|
661
|
+
editor = fresh_editor
|
|
662
|
+
editor.keymap_manager = RuVim::KeymapManager.new
|
|
663
|
+
buf = editor.current_buffer
|
|
664
|
+
buf.replace_all_lines!(['{"a":1}', '{"b":2}'])
|
|
665
|
+
buf.options["filetype"] = "jsonl"
|
|
666
|
+
|
|
667
|
+
RuVim::RichView.open!(editor, format: "jsonl")
|
|
668
|
+
result = editor.keymap_manager.resolve_with_context(:normal, ["\e"], editor: editor)
|
|
669
|
+
assert_equal "rich.close_buffer", result.invocation.id
|
|
670
|
+
end
|
|
671
|
+
|
|
672
|
+
def test_jsonl_open_pretty_prints_each_line
|
|
673
|
+
editor = fresh_editor
|
|
674
|
+
buf = editor.current_buffer
|
|
675
|
+
buf.replace_all_lines!(['{"a":1,"b":[2,3]}', '{"c":4}'])
|
|
676
|
+
buf.options["filetype"] = "jsonl"
|
|
677
|
+
|
|
678
|
+
RuVim::RichView.open!(editor, format: "jsonl")
|
|
679
|
+
new_buf = editor.current_buffer
|
|
680
|
+
lines = new_buf.lines
|
|
681
|
+
# Each JSON object should be expanded; separated by "---"
|
|
682
|
+
assert lines.length > 2, "JSONL should be expanded to multiple lines"
|
|
683
|
+
assert lines.any? { |l| l.include?("---") }, "Entries should be separated"
|
|
684
|
+
end
|
|
685
|
+
|
|
686
|
+
def test_jsonl_open_maps_cursor_to_correct_entry
|
|
687
|
+
editor = fresh_editor
|
|
688
|
+
buf = editor.current_buffer
|
|
689
|
+
buf.replace_all_lines!(['{"a":1}', '{"b":2}', '{"c":3}'])
|
|
690
|
+
buf.options["filetype"] = "jsonl"
|
|
691
|
+
editor.current_window.cursor_y = 1 # on second entry
|
|
692
|
+
|
|
693
|
+
RuVim::RichView.open!(editor, format: "jsonl")
|
|
694
|
+
new_buf = editor.current_buffer
|
|
695
|
+
cy = editor.current_window.cursor_y
|
|
696
|
+
# Cursor should be within the second entry's formatted block
|
|
697
|
+
nearby = (cy..[cy + 2, new_buf.lines.length - 1].min).map { |r| new_buf.line_at(r) }.join("\n")
|
|
698
|
+
assert_match(/"b"/, nearby, "Cursor should be near the entry with \"b\"")
|
|
699
|
+
end
|
|
700
|
+
|
|
701
|
+
def test_jsonl_open_skips_blank_lines
|
|
702
|
+
editor = fresh_editor
|
|
703
|
+
buf = editor.current_buffer
|
|
704
|
+
buf.replace_all_lines!(['{"a":1}', '', '{"b":2}'])
|
|
705
|
+
buf.options["filetype"] = "jsonl"
|
|
706
|
+
|
|
707
|
+
RuVim::RichView.open!(editor, format: "jsonl")
|
|
708
|
+
new_buf = editor.current_buffer
|
|
709
|
+
lines = new_buf.lines
|
|
710
|
+
# Should contain both entries
|
|
711
|
+
assert lines.any? { |l| l.include?('"a"') }
|
|
712
|
+
assert lines.any? { |l| l.include?('"b"') }
|
|
713
|
+
end
|
|
714
|
+
|
|
715
|
+
def test_jsonl_open_shows_parse_error_inline
|
|
716
|
+
editor = fresh_editor
|
|
717
|
+
buf = editor.current_buffer
|
|
718
|
+
buf.replace_all_lines!(['{"a":1}', 'bad json', '{"b":2}'])
|
|
719
|
+
buf.options["filetype"] = "jsonl"
|
|
720
|
+
|
|
721
|
+
RuVim::RichView.open!(editor, format: "jsonl")
|
|
722
|
+
new_buf = editor.current_buffer
|
|
723
|
+
lines = new_buf.lines
|
|
724
|
+
# Invalid line should show an error marker
|
|
725
|
+
assert lines.any? { |l| l.include?("PARSE ERROR") }, "Invalid JSON line should show error"
|
|
726
|
+
end
|
|
727
|
+
|
|
728
|
+
def test_jsonl_filetype_detected
|
|
729
|
+
editor = fresh_editor
|
|
730
|
+
buf = editor.current_buffer
|
|
731
|
+
buf.options["filetype"] = "jsonl"
|
|
732
|
+
assert_equal "jsonl", RuVim::RichView.detect_format(buf)
|
|
733
|
+
end
|
|
478
734
|
end
|
data/test/search_option_test.rb
CHANGED
|
@@ -36,4 +36,23 @@ class SearchOptionTest < Minitest::Test
|
|
|
36
36
|
cols = screen.send(:search_highlight_source_cols, @editor, "foo bar", source_col_offset: 0)
|
|
37
37
|
assert_equal({}, cols)
|
|
38
38
|
end
|
|
39
|
+
|
|
40
|
+
def test_nohlsearch_suppresses_highlight_until_next_search
|
|
41
|
+
screen = RuVim::Screen.new(terminal: TerminalStub.new([10, 40]))
|
|
42
|
+
@editor.set_last_search(pattern: "foo", direction: :forward)
|
|
43
|
+
|
|
44
|
+
# highlight is active
|
|
45
|
+
cols = screen.send(:search_highlight_source_cols, @editor, "foo bar", source_col_offset: 0)
|
|
46
|
+
assert_equal true, cols[0]
|
|
47
|
+
|
|
48
|
+
# suppress via nohlsearch
|
|
49
|
+
@editor.suppress_hlsearch!
|
|
50
|
+
cols = screen.send(:search_highlight_source_cols, @editor, "foo bar", source_col_offset: 0)
|
|
51
|
+
assert_equal({}, cols)
|
|
52
|
+
|
|
53
|
+
# next search restores highlight
|
|
54
|
+
@editor.set_last_search(pattern: "bar", direction: :forward)
|
|
55
|
+
cols = screen.send(:search_highlight_source_cols, @editor, "foo bar", source_col_offset: 0)
|
|
56
|
+
assert_equal true, cols[4]
|
|
57
|
+
end
|
|
39
58
|
end
|
data/test/test_helper.rb
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
# Suppress "system temporary path is not writable" warnings in sandboxed environments
|
|
2
|
+
unless ENV["TMPDIR"] && File.writable?(ENV["TMPDIR"])
|
|
3
|
+
candidates = ["/tmp", "/var/tmp"]
|
|
4
|
+
# Claude Code sandbox uses /tmp/claude-<uid>
|
|
5
|
+
candidates.unshift("/tmp/claude-#{Process.uid}") if Dir.exist?("/tmp/claude-#{Process.uid}")
|
|
6
|
+
found = candidates.find { |d| File.writable?(d) }
|
|
7
|
+
ENV["TMPDIR"] = found if found
|
|
8
|
+
end
|
|
9
|
+
|
|
1
10
|
$LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
|
|
2
11
|
require "minitest/autorun"
|
|
3
12
|
require "ruvim"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ruvim
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Koichi Sasada
|
|
@@ -62,6 +62,14 @@ files:
|
|
|
62
62
|
- lib/ruvim/display_width.rb
|
|
63
63
|
- lib/ruvim/editor.rb
|
|
64
64
|
- lib/ruvim/ex_command_registry.rb
|
|
65
|
+
- lib/ruvim/file_watcher.rb
|
|
66
|
+
- lib/ruvim/git/blame.rb
|
|
67
|
+
- lib/ruvim/git/branch.rb
|
|
68
|
+
- lib/ruvim/git/commit.rb
|
|
69
|
+
- lib/ruvim/git/diff.rb
|
|
70
|
+
- lib/ruvim/git/handler.rb
|
|
71
|
+
- lib/ruvim/git/log.rb
|
|
72
|
+
- lib/ruvim/git/status.rb
|
|
65
73
|
- lib/ruvim/global_commands.rb
|
|
66
74
|
- lib/ruvim/highlighter.rb
|
|
67
75
|
- lib/ruvim/input.rb
|
|
@@ -69,12 +77,15 @@ files:
|
|
|
69
77
|
- lib/ruvim/keyword_chars.rb
|
|
70
78
|
- lib/ruvim/lang/base.rb
|
|
71
79
|
- lib/ruvim/lang/csv.rb
|
|
80
|
+
- lib/ruvim/lang/diff.rb
|
|
72
81
|
- lib/ruvim/lang/json.rb
|
|
73
82
|
- lib/ruvim/lang/markdown.rb
|
|
74
83
|
- lib/ruvim/lang/ruby.rb
|
|
75
84
|
- lib/ruvim/lang/scheme.rb
|
|
76
85
|
- lib/ruvim/lang/tsv.rb
|
|
77
86
|
- lib/ruvim/rich_view.rb
|
|
87
|
+
- lib/ruvim/rich_view/json_renderer.rb
|
|
88
|
+
- lib/ruvim/rich_view/jsonl_renderer.rb
|
|
78
89
|
- lib/ruvim/rich_view/markdown_renderer.rb
|
|
79
90
|
- lib/ruvim/rich_view/table_renderer.rb
|
|
80
91
|
- lib/ruvim/screen.rb
|
|
@@ -94,15 +105,20 @@ files:
|
|
|
94
105
|
- test/arglist_test.rb
|
|
95
106
|
- test/buffer_test.rb
|
|
96
107
|
- test/cli_test.rb
|
|
108
|
+
- test/clipboard_test.rb
|
|
109
|
+
- test/command_line_test.rb
|
|
97
110
|
- test/config_dsl_test.rb
|
|
98
111
|
- test/config_loader_test.rb
|
|
99
112
|
- test/dispatcher_test.rb
|
|
100
113
|
- test/display_width_test.rb
|
|
101
114
|
- test/editor_mark_test.rb
|
|
102
115
|
- test/editor_register_test.rb
|
|
116
|
+
- test/file_watcher_test.rb
|
|
103
117
|
- test/fixtures/render_basic_snapshot.txt
|
|
104
118
|
- test/fixtures/render_basic_snapshot_nonumber.txt
|
|
105
119
|
- test/fixtures/render_unicode_scrolled_snapshot.txt
|
|
120
|
+
- test/follow_test.rb
|
|
121
|
+
- test/git_blame_test.rb
|
|
106
122
|
- test/highlighter_test.rb
|
|
107
123
|
- test/indent_test.rb
|
|
108
124
|
- test/input_screen_integration_test.rb
|