ruvim 0.1.0 → 0.2.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/docs/binding.md +6 -0
- data/docs/command.md +16 -0
- data/docs/config.md +203 -84
- data/docs/lib_cleanup_report.md +79 -0
- data/docs/plugin.md +13 -15
- data/docs/spec.md +39 -22
- data/docs/todo.md +187 -10
- data/docs/tutorial.md +1 -1
- data/docs/vim_diff.md +2 -1
- data/lib/ruvim/app.rb +681 -123
- data/lib/ruvim/config_loader.rb +19 -5
- data/lib/ruvim/context.rb +0 -7
- data/lib/ruvim/dispatcher.rb +10 -0
- data/lib/ruvim/display_width.rb +25 -2
- data/lib/ruvim/editor.rb +173 -4
- data/lib/ruvim/global_commands.rb +500 -55
- data/lib/ruvim/input.rb +22 -10
- data/lib/ruvim/keyword_chars.rb +46 -0
- data/lib/ruvim/screen.rb +388 -53
- data/lib/ruvim/text_metrics.rb +26 -0
- data/lib/ruvim/version.rb +2 -2
- data/lib/ruvim/window.rb +35 -10
- data/lib/ruvim.rb +1 -0
- data/test/app_completion_test.rb +101 -0
- data/test/app_motion_test.rb +97 -2
- data/test/app_scenario_test.rb +270 -0
- data/test/app_startup_test.rb +10 -0
- data/test/config_loader_test.rb +37 -0
- data/test/dispatcher_test.rb +116 -0
- data/test/display_width_test.rb +18 -0
- data/test/fixtures/render_basic_snapshot.txt +7 -8
- data/test/fixtures/render_basic_snapshot_nonumber.txt +1 -2
- data/test/fixtures/render_unicode_scrolled_snapshot.txt +6 -7
- data/test/input_screen_integration_test.rb +26 -13
- data/test/screen_test.rb +166 -0
- data/test/window_test.rb +26 -0
- metadata +5 -1
data/test/dispatcher_test.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require_relative "test_helper"
|
|
2
|
+
require "tmpdir"
|
|
2
3
|
|
|
3
4
|
class DispatcherTest < Minitest::Test
|
|
4
5
|
def setup
|
|
@@ -43,6 +44,35 @@ class DispatcherTest < Minitest::Test
|
|
|
43
44
|
assert_equal "ruby: 3", @editor.message
|
|
44
45
|
end
|
|
45
46
|
|
|
47
|
+
def test_dispatch_ex_ruby_captures_stdout_and_stderr_into_virtual_buffer
|
|
48
|
+
@dispatcher.dispatch_ex(@editor, "ruby STDOUT.puts(%q[out]); STDERR.puts(%q[err]); 42")
|
|
49
|
+
|
|
50
|
+
assert_equal "[Ruby Output]", @editor.message
|
|
51
|
+
assert_equal :help, @editor.current_buffer.kind
|
|
52
|
+
body = @editor.current_buffer.lines.join("\n")
|
|
53
|
+
assert_includes body, "[stdout]"
|
|
54
|
+
assert_includes body, "out"
|
|
55
|
+
assert_includes body, "[stderr]"
|
|
56
|
+
assert_includes body, "err"
|
|
57
|
+
assert_includes body, "[result]"
|
|
58
|
+
assert_includes body, "42"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def test_dispatch_ex_shell_captures_stdout_and_stderr_into_virtual_buffer
|
|
62
|
+
@dispatcher.dispatch_ex(@editor, "!echo out; echo err 1>&2")
|
|
63
|
+
|
|
64
|
+
assert_equal "[Shell Output]", @editor.message
|
|
65
|
+
assert_equal :help, @editor.current_buffer.kind
|
|
66
|
+
body = @editor.current_buffer.lines.join("\n")
|
|
67
|
+
assert_includes body, "[command]"
|
|
68
|
+
assert_includes body, "echo out; echo err 1>&2"
|
|
69
|
+
assert_includes body, "[stdout]"
|
|
70
|
+
assert_includes body, "out"
|
|
71
|
+
assert_includes body, "[stderr]"
|
|
72
|
+
assert_includes body, "err"
|
|
73
|
+
assert_includes body, "[status]"
|
|
74
|
+
end
|
|
75
|
+
|
|
46
76
|
def test_dispatch_ex_set_commands
|
|
47
77
|
@dispatcher.dispatch_ex(@editor, "set number")
|
|
48
78
|
assert_equal true, @editor.current_window.options["number"]
|
|
@@ -121,4 +151,90 @@ class DispatcherTest < Minitest::Test
|
|
|
121
151
|
@dispatcher.dispatch_ex(@editor, "lnext")
|
|
122
152
|
assert_equal 1, @editor.current_window.cursor_y
|
|
123
153
|
end
|
|
154
|
+
|
|
155
|
+
def test_hidden_option_allows_buffer_switch_without_bang
|
|
156
|
+
@editor.materialize_intro_buffer!
|
|
157
|
+
@editor.current_buffer.replace_all_lines!(["x"])
|
|
158
|
+
@editor.current_buffer.modified = true
|
|
159
|
+
other = @editor.add_empty_buffer(path: "other.txt")
|
|
160
|
+
@editor.set_option("hidden", true, scope: :global)
|
|
161
|
+
|
|
162
|
+
@dispatcher.dispatch_ex(@editor, "buffer #{other.id}")
|
|
163
|
+
|
|
164
|
+
assert_equal other.id, @editor.current_buffer.id
|
|
165
|
+
refute @editor.message_error?
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def test_autowrite_saves_current_buffer_before_buffer_switch
|
|
169
|
+
Dir.mktmpdir("ruvim-autowrite") do |dir|
|
|
170
|
+
path = File.join(dir, "a.txt")
|
|
171
|
+
File.write(path, "old\n")
|
|
172
|
+
@editor.materialize_intro_buffer!
|
|
173
|
+
@editor.current_buffer.path = path
|
|
174
|
+
@editor.current_buffer.replace_all_lines!(["new"])
|
|
175
|
+
@editor.current_buffer.modified = true
|
|
176
|
+
other = @editor.add_empty_buffer(path: "other.txt")
|
|
177
|
+
@editor.set_option("autowrite", true, scope: :global)
|
|
178
|
+
|
|
179
|
+
@dispatcher.dispatch_ex(@editor, "buffer #{other.id}")
|
|
180
|
+
|
|
181
|
+
assert_equal other.id, @editor.current_buffer.id
|
|
182
|
+
assert_equal "new", File.read(path).strip
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def test_bdelete_deletes_current_buffer_and_switches_to_another
|
|
187
|
+
@editor.materialize_intro_buffer!
|
|
188
|
+
first = @editor.current_buffer
|
|
189
|
+
other = @editor.add_empty_buffer(path: "other.txt")
|
|
190
|
+
@dispatcher.dispatch_ex(@editor, "buffer #{other.id}")
|
|
191
|
+
assert_equal other.id, @editor.current_buffer.id
|
|
192
|
+
|
|
193
|
+
@dispatcher.dispatch_ex(@editor, "bd")
|
|
194
|
+
|
|
195
|
+
assert_equal first.id, @editor.current_buffer.id
|
|
196
|
+
refute @editor.buffers.key?(other.id)
|
|
197
|
+
assert_equal "buffer #{other.id} deleted", @editor.message
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def test_bdelete_rejects_modified_buffer_without_bang
|
|
201
|
+
@editor.materialize_intro_buffer!
|
|
202
|
+
@editor.current_buffer.replace_all_lines!(["x"])
|
|
203
|
+
@editor.current_buffer.modified = true
|
|
204
|
+
|
|
205
|
+
@dispatcher.dispatch_ex(@editor, "bd")
|
|
206
|
+
|
|
207
|
+
assert_equal true, @editor.message_error?
|
|
208
|
+
assert_match(/No write since last change/, @editor.message)
|
|
209
|
+
assert @editor.buffers.key?(@editor.current_buffer.id)
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def test_bdelete_bang_deletes_modified_buffer
|
|
213
|
+
@editor.materialize_intro_buffer!
|
|
214
|
+
first = @editor.current_buffer
|
|
215
|
+
other = @editor.add_empty_buffer(path: "other.txt")
|
|
216
|
+
@dispatcher.dispatch_ex(@editor, "buffer #{other.id}")
|
|
217
|
+
@editor.current_buffer.replace_all_lines!(["dirty"])
|
|
218
|
+
@editor.current_buffer.modified = true
|
|
219
|
+
|
|
220
|
+
@dispatcher.dispatch_ex(@editor, "bd!")
|
|
221
|
+
|
|
222
|
+
assert_equal first.id, @editor.current_buffer.id
|
|
223
|
+
refute @editor.buffers.key?(other.id)
|
|
224
|
+
refute @editor.message_error?
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def test_splitbelow_and_splitright_change_insertion_side
|
|
228
|
+
@editor.set_option("splitbelow", false, scope: :global)
|
|
229
|
+
first = @editor.current_window_id
|
|
230
|
+
@dispatcher.dispatch_ex(@editor, "split")
|
|
231
|
+
assert_equal @editor.window_order[0], @editor.current_window_id
|
|
232
|
+
assert_equal first, @editor.window_order[1]
|
|
233
|
+
|
|
234
|
+
@editor.set_option("splitright", false, scope: :global)
|
|
235
|
+
@editor.current_window_id = first
|
|
236
|
+
@dispatcher.dispatch_ex(@editor, "vsplit")
|
|
237
|
+
idx = @editor.window_order.index(@editor.current_window_id)
|
|
238
|
+
assert_equal 1, idx
|
|
239
|
+
end
|
|
124
240
|
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require_relative "test_helper"
|
|
2
|
+
|
|
3
|
+
class DisplayWidthTest < Minitest::Test
|
|
4
|
+
def test_ambiguous_width_cache_tracks_env_changes
|
|
5
|
+
prev = ENV["RUVIM_AMBIGUOUS_WIDTH"]
|
|
6
|
+
ENV["RUVIM_AMBIGUOUS_WIDTH"] = nil
|
|
7
|
+
assert_equal 1, RuVim::DisplayWidth.cell_width("Ω")
|
|
8
|
+
|
|
9
|
+
ENV["RUVIM_AMBIGUOUS_WIDTH"] = "2"
|
|
10
|
+
assert_equal 2, RuVim::DisplayWidth.cell_width("Ω")
|
|
11
|
+
ensure
|
|
12
|
+
if prev.nil?
|
|
13
|
+
ENV.delete("RUVIM_AMBIGUOUS_WIDTH")
|
|
14
|
+
else
|
|
15
|
+
ENV["RUVIM_AMBIGUOUS_WIDTH"] = prev
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
1 # title
|
|
2
|
-
2
|
|
3
|
-
3 foo
|
|
4
|
-
4 bar 日本語 編集
|
|
5
|
-
5 baz
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
-- NORMAL -- t1/1 w 1:1
|
|
1
|
+
1 # title
|
|
2
|
+
2
|
|
3
|
+
3 foo
|
|
4
|
+
4 bar 日本語 編集
|
|
5
|
+
5 baz
|
|
6
|
+
~
|
|
7
|
+
-- NORMAL -- [No Na 1:1
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
1 # title
|
|
2
|
-
2
|
|
3
|
-
3 foo
|
|
4
|
-
4 bar 日本語 編集
|
|
5
|
-
5 baz
|
|
6
|
-
|
|
7
|
-
-- NORMAL -- t1 4:5
|
|
1
|
+
1 # title
|
|
2
|
+
2
|
|
3
|
+
3 foo
|
|
4
|
+
4 bar 日本語 編集
|
|
5
|
+
5 baz
|
|
6
|
+
-- NORMAL -- [N 4:5
|
|
@@ -30,6 +30,21 @@ class InputScreenIntegrationTest < Minitest::Test
|
|
|
30
30
|
end
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
+
def with_fake_select
|
|
34
|
+
io_sc = IO.singleton_class
|
|
35
|
+
verbose, $VERBOSE = $VERBOSE, nil
|
|
36
|
+
io_sc.alias_method(:__orig_select_for_input_screen_test, :select)
|
|
37
|
+
io_sc.define_method(:select) do |readers, *_rest|
|
|
38
|
+
ready = Array(readers).select { |io| io.respond_to?(:ready?) && io.ready? }
|
|
39
|
+
ready.empty? ? nil : [ready, [], []]
|
|
40
|
+
end
|
|
41
|
+
yield
|
|
42
|
+
ensure
|
|
43
|
+
io_sc.alias_method(:select, :__orig_select_for_input_screen_test)
|
|
44
|
+
io_sc.remove_method(:__orig_select_for_input_screen_test) rescue nil
|
|
45
|
+
$VERBOSE = verbose
|
|
46
|
+
end
|
|
47
|
+
|
|
33
48
|
def test_input_pagedown_to_app_and_screen_render
|
|
34
49
|
app = RuVim::App.new(clean: true)
|
|
35
50
|
editor = app.instance_variable_get(:@editor)
|
|
@@ -43,15 +58,7 @@ class InputScreenIntegrationTest < Minitest::Test
|
|
|
43
58
|
stdin = FakeTTY.new("\e[6~")
|
|
44
59
|
input = RuVim::Input.new(stdin: stdin)
|
|
45
60
|
|
|
46
|
-
|
|
47
|
-
verbose, $VERBOSE = $VERBOSE, nil
|
|
48
|
-
io_sc.alias_method(:__orig_select_for_input_screen_test, :select)
|
|
49
|
-
io_sc.define_method(:select) do |readers, *_rest|
|
|
50
|
-
ready = Array(readers).select { |io| io.respond_to?(:ready?) && io.ready? }
|
|
51
|
-
ready.empty? ? nil : [ready, [], []]
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
begin
|
|
61
|
+
with_fake_select do
|
|
55
62
|
key = input.read_key(timeout: 0.2)
|
|
56
63
|
assert_equal :pagedown, key
|
|
57
64
|
|
|
@@ -60,10 +67,16 @@ class InputScreenIntegrationTest < Minitest::Test
|
|
|
60
67
|
|
|
61
68
|
assert_operator editor.current_window.cursor_y, :>, 0
|
|
62
69
|
assert_includes term.writes.last, "line "
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def test_input_keeps_repeated_arrow_sequences_separate
|
|
74
|
+
stdin = FakeTTY.new("\e[A\e[A")
|
|
75
|
+
input = RuVim::Input.new(stdin: stdin)
|
|
76
|
+
|
|
77
|
+
with_fake_select do
|
|
78
|
+
assert_equal :up, input.read_key(timeout: 0.2)
|
|
79
|
+
assert_equal :up, input.read_key(timeout: 0.2)
|
|
67
80
|
end
|
|
68
81
|
end
|
|
69
82
|
end
|
data/test/screen_test.rb
CHANGED
|
@@ -55,6 +55,38 @@ class ScreenTest < Minitest::Test
|
|
|
55
55
|
assert_equal " 3 ", screen.send(:line_number_prefix, editor, win, buf, 2, 3) # current line is absolute when both enabled
|
|
56
56
|
end
|
|
57
57
|
|
|
58
|
+
def test_signcolumn_yes_reserves_one_column_in_gutter
|
|
59
|
+
editor = RuVim::Editor.new
|
|
60
|
+
buf = editor.add_empty_buffer
|
|
61
|
+
win = editor.add_window(buffer_id: buf.id)
|
|
62
|
+
editor.set_option("number", true, scope: :window, window: win, buffer: buf)
|
|
63
|
+
editor.set_option("signcolumn", "yes", scope: :window, window: win, buffer: buf)
|
|
64
|
+
term = TerminalStub.new([8, 20])
|
|
65
|
+
screen = RuVim::Screen.new(terminal: term)
|
|
66
|
+
|
|
67
|
+
w = screen.send(:number_column_width, editor, win, buf)
|
|
68
|
+
prefix = screen.send(:line_number_prefix, editor, win, buf, 0, w)
|
|
69
|
+
|
|
70
|
+
assert_equal 6, w # sign(1) + default numberwidth(4) + trailing space
|
|
71
|
+
assert_equal " 1 ", prefix
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def test_signcolumn_yes_with_width_reserves_multiple_columns
|
|
75
|
+
editor = RuVim::Editor.new
|
|
76
|
+
buf = editor.add_empty_buffer
|
|
77
|
+
win = editor.add_window(buffer_id: buf.id)
|
|
78
|
+
editor.set_option("number", true, scope: :window, window: win, buffer: buf)
|
|
79
|
+
editor.set_option("signcolumn", "yes:2", scope: :window, window: win, buffer: buf)
|
|
80
|
+
term = TerminalStub.new([8, 20])
|
|
81
|
+
screen = RuVim::Screen.new(terminal: term)
|
|
82
|
+
|
|
83
|
+
w = screen.send(:number_column_width, editor, win, buf)
|
|
84
|
+
prefix = screen.send(:line_number_prefix, editor, win, buf, 0, w)
|
|
85
|
+
|
|
86
|
+
assert_equal 7, w # sign(2) + default numberwidth(4) + trailing space
|
|
87
|
+
assert_equal " 1 ", prefix
|
|
88
|
+
end
|
|
89
|
+
|
|
58
90
|
def test_render_shows_error_message_on_command_line_row_with_highlight
|
|
59
91
|
editor = RuVim::Editor.new
|
|
60
92
|
buf = editor.add_empty_buffer
|
|
@@ -120,4 +152,138 @@ class ScreenTest < Minitest::Test
|
|
|
120
152
|
assert_equal 10, RuVim::DisplayWidth.display_width(visible, tabstop: 2)
|
|
121
153
|
refute_includes out, "\n"
|
|
122
154
|
end
|
|
155
|
+
|
|
156
|
+
def test_termguicolors_uses_truecolor_sequences_for_search_highlight
|
|
157
|
+
editor = RuVim::Editor.new
|
|
158
|
+
buf = editor.add_empty_buffer
|
|
159
|
+
win = editor.add_window(buffer_id: buf.id)
|
|
160
|
+
buf.replace_all_lines!(["foo"])
|
|
161
|
+
editor.set_last_search(pattern: "foo", direction: :forward)
|
|
162
|
+
editor.set_option("termguicolors", true, scope: :global)
|
|
163
|
+
|
|
164
|
+
term = TerminalStub.new([6, 20])
|
|
165
|
+
screen = RuVim::Screen.new(terminal: term)
|
|
166
|
+
out = screen.send(:render_text_line, buf.line_at(0), editor, buffer_row: 0, window: win, buffer: buf, width: 6)
|
|
167
|
+
|
|
168
|
+
assert_includes out, "\e[48;2;255;215;0m"
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def test_render_text_line_respects_list_and_listchars_for_tab_trail_and_nbsp
|
|
172
|
+
editor = RuVim::Editor.new
|
|
173
|
+
buf = editor.add_empty_buffer
|
|
174
|
+
win = editor.add_window(buffer_id: buf.id)
|
|
175
|
+
buf.replace_all_lines!(["\tA \u00A0 "])
|
|
176
|
+
editor.set_option("list", true, scope: :window, window: win, buffer: buf)
|
|
177
|
+
editor.set_option("listchars", "tab:>.,trail:~,nbsp:*", scope: :window, window: win, buffer: buf)
|
|
178
|
+
|
|
179
|
+
term = TerminalStub.new([6, 20])
|
|
180
|
+
screen = RuVim::Screen.new(terminal: term)
|
|
181
|
+
out = screen.send(:render_text_line, buf.line_at(0), editor, buffer_row: 0, window: win, buffer: buf, width: 12)
|
|
182
|
+
visible = out.gsub(/\e\[[0-9;?]*[A-Za-z]/, "")
|
|
183
|
+
|
|
184
|
+
assert_includes visible, ">."
|
|
185
|
+
assert_includes visible, "*"
|
|
186
|
+
assert_includes visible, "~"
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def test_render_text_line_sanitizes_terminal_escape_controls
|
|
190
|
+
editor = RuVim::Editor.new
|
|
191
|
+
buf = editor.add_empty_buffer
|
|
192
|
+
win = editor.add_window(buffer_id: buf.id)
|
|
193
|
+
buf.replace_all_lines!(["A\e]52;c;owned\aB"])
|
|
194
|
+
win.cursor_y = 1 # avoid cursor highlight on the tested row
|
|
195
|
+
|
|
196
|
+
term = TerminalStub.new([6, 40])
|
|
197
|
+
screen = RuVim::Screen.new(terminal: term)
|
|
198
|
+
out = screen.send(:render_text_line, buf.line_at(0), editor, buffer_row: 0, window: win, buffer: buf, width: 20)
|
|
199
|
+
|
|
200
|
+
refute_includes out, "\e]52"
|
|
201
|
+
visible = out.gsub(/\e\[[0-9;?]*[A-Za-z]/, "")
|
|
202
|
+
assert_includes visible, "A"
|
|
203
|
+
assert_includes visible, "B"
|
|
204
|
+
assert_includes visible, "?"
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def test_wrap_and_showbreak_render_continuation_rows
|
|
208
|
+
editor = RuVim::Editor.new
|
|
209
|
+
buf = editor.add_empty_buffer
|
|
210
|
+
win = editor.add_window(buffer_id: buf.id)
|
|
211
|
+
buf.replace_all_lines!(["abcdef ghijkl"])
|
|
212
|
+
editor.set_option("wrap", true, scope: :window, window: win, buffer: buf)
|
|
213
|
+
editor.set_option("showbreak", ">>", scope: :window, window: win, buffer: buf)
|
|
214
|
+
|
|
215
|
+
term = TerminalStub.new([6, 8])
|
|
216
|
+
screen = RuVim::Screen.new(terminal: term)
|
|
217
|
+
rows, cols = term.winsize
|
|
218
|
+
text_rows, text_cols = editor.text_viewport_size(rows:, cols:)
|
|
219
|
+
rects = screen.send(:window_rects, editor, text_rows:, text_cols:)
|
|
220
|
+
frame = screen.send(:build_frame, editor, rows:, cols:, text_rows:, text_cols:, rects:)
|
|
221
|
+
|
|
222
|
+
row1 = frame[:lines][1].to_s.gsub(/\e\[[0-9;?]*[A-Za-z]/, "")
|
|
223
|
+
row2 = frame[:lines][2].to_s.gsub(/\e\[[0-9;?]*[A-Za-z]/, "")
|
|
224
|
+
assert_includes row1, "abcdef"
|
|
225
|
+
assert_includes row2, ">>"
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def test_cursor_screen_position_supports_virtualedit_past_eol
|
|
229
|
+
editor = RuVim::Editor.new
|
|
230
|
+
buf = editor.add_empty_buffer
|
|
231
|
+
win = editor.add_window(buffer_id: buf.id)
|
|
232
|
+
buf.replace_all_lines!(["abc"])
|
|
233
|
+
editor.set_option("virtualedit", "onemore", scope: :global)
|
|
234
|
+
win.cursor_y = 0
|
|
235
|
+
win.cursor_x = 4
|
|
236
|
+
|
|
237
|
+
term = TerminalStub.new([6, 20])
|
|
238
|
+
screen = RuVim::Screen.new(terminal: term)
|
|
239
|
+
rows, cols = term.winsize
|
|
240
|
+
text_rows, text_cols = editor.text_viewport_size(rows:, cols:)
|
|
241
|
+
rects = screen.send(:window_rects, editor, text_rows:, text_cols:)
|
|
242
|
+
pos = screen.send(:cursor_screen_position, editor, text_rows, rects)
|
|
243
|
+
|
|
244
|
+
# col 1-based; "abc" places cursor at 4, one-past-eol should be 5
|
|
245
|
+
assert_equal [1, 5], pos
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def test_cursor_screen_position_is_clamped_to_text_area_under_wrap
|
|
249
|
+
editor = RuVim::Editor.new
|
|
250
|
+
buf = editor.add_empty_buffer
|
|
251
|
+
win = editor.add_window(buffer_id: buf.id)
|
|
252
|
+
buf.replace_all_lines!(["x" * 40, "tail"])
|
|
253
|
+
editor.set_option("wrap", true, scope: :window, window: win, buffer: buf)
|
|
254
|
+
win.row_offset = 0
|
|
255
|
+
win.cursor_y = 1
|
|
256
|
+
win.cursor_x = 0
|
|
257
|
+
|
|
258
|
+
term = TerminalStub.new([6, 8]) # text_rows = 4 (footer 2 rows)
|
|
259
|
+
screen = RuVim::Screen.new(terminal: term)
|
|
260
|
+
rows, cols = term.winsize
|
|
261
|
+
text_rows, text_cols = editor.text_viewport_size(rows:, cols:)
|
|
262
|
+
rects = screen.send(:window_rects, editor, text_rows:, text_cols:)
|
|
263
|
+
row, _col = screen.send(:cursor_screen_position, editor, text_rows, rects)
|
|
264
|
+
|
|
265
|
+
assert_operator row, :<=, text_rows
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
def test_linebreak_and_breakindent_prefer_space_wrap
|
|
269
|
+
editor = RuVim::Editor.new
|
|
270
|
+
buf = editor.add_empty_buffer
|
|
271
|
+
win = editor.add_window(buffer_id: buf.id)
|
|
272
|
+
buf.replace_all_lines!([" foo bar baz"])
|
|
273
|
+
editor.set_option("wrap", true, scope: :window, window: win, buffer: buf)
|
|
274
|
+
editor.set_option("linebreak", true, scope: :window, window: win, buffer: buf)
|
|
275
|
+
editor.set_option("breakindent", true, scope: :window, window: win, buffer: buf)
|
|
276
|
+
editor.set_option("showbreak", ">", scope: :window, window: win, buffer: buf)
|
|
277
|
+
|
|
278
|
+
term = TerminalStub.new([6, 10])
|
|
279
|
+
screen = RuVim::Screen.new(terminal: term)
|
|
280
|
+
rows, cols = term.winsize
|
|
281
|
+
text_rows, text_cols = editor.text_viewport_size(rows:, cols:)
|
|
282
|
+
rects = screen.send(:window_rects, editor, text_rows:, text_cols:)
|
|
283
|
+
frame = screen.send(:build_frame, editor, rows:, cols:, text_rows:, text_cols:, rects:)
|
|
284
|
+
|
|
285
|
+
row2 = frame[:lines][2].to_s.gsub(/\e\[[0-9;?]*[A-Za-z]/, "")
|
|
286
|
+
assert_includes row2, ">"
|
|
287
|
+
assert_match(/\s>|\>\s/, row2)
|
|
288
|
+
end
|
|
123
289
|
end
|
data/test/window_test.rb
CHANGED
|
@@ -18,4 +18,30 @@ class WindowTest < Minitest::Test
|
|
|
18
18
|
assert_operator cursor_col, :<, offset_col + 4
|
|
19
19
|
assert_equal 3, win.col_offset
|
|
20
20
|
end
|
|
21
|
+
|
|
22
|
+
def test_ensure_visible_respects_scrolloff_and_sidescrolloff
|
|
23
|
+
buffer = RuVim::Buffer.new(id: 1, lines: ["0123456789", "aaaaa", "bbbbb", "ccccc", "0123456789", "eeeee"])
|
|
24
|
+
win = RuVim::Window.new(id: 1, buffer_id: 1)
|
|
25
|
+
win.cursor_y = 4
|
|
26
|
+
win.cursor_x = 8
|
|
27
|
+
|
|
28
|
+
win.ensure_visible(buffer, height: 3, width: 5, tabstop: 2, scrolloff: 1, sidescrolloff: 1)
|
|
29
|
+
|
|
30
|
+
assert_equal 3, win.row_offset
|
|
31
|
+
assert_operator win.col_offset, :>, 0
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def test_move_down_preserves_preferred_column_across_empty_line
|
|
35
|
+
long = "x" * 80
|
|
36
|
+
buffer = RuVim::Buffer.new(id: 1, lines: [long, "", long])
|
|
37
|
+
win = RuVim::Window.new(id: 1, buffer_id: 1)
|
|
38
|
+
win.cursor_y = 0
|
|
39
|
+
win.cursor_x = 50
|
|
40
|
+
|
|
41
|
+
win.move_down(buffer)
|
|
42
|
+
assert_equal [1, 0], [win.cursor_y, win.cursor_x]
|
|
43
|
+
|
|
44
|
+
win.move_down(buffer)
|
|
45
|
+
assert_equal [2, 50], [win.cursor_y, win.cursor_x]
|
|
46
|
+
end
|
|
21
47
|
end
|
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.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Koichi Sasada
|
|
@@ -24,6 +24,7 @@ files:
|
|
|
24
24
|
- docs/command.md
|
|
25
25
|
- docs/config.md
|
|
26
26
|
- docs/done.md
|
|
27
|
+
- docs/lib_cleanup_report.md
|
|
27
28
|
- docs/plugin.md
|
|
28
29
|
- docs/spec.md
|
|
29
30
|
- docs/todo.md
|
|
@@ -49,6 +50,7 @@ files:
|
|
|
49
50
|
- lib/ruvim/highlighter.rb
|
|
50
51
|
- lib/ruvim/input.rb
|
|
51
52
|
- lib/ruvim/keymap_manager.rb
|
|
53
|
+
- lib/ruvim/keyword_chars.rb
|
|
52
54
|
- lib/ruvim/screen.rb
|
|
53
55
|
- lib/ruvim/terminal.rb
|
|
54
56
|
- lib/ruvim/text_metrics.rb
|
|
@@ -66,7 +68,9 @@ files:
|
|
|
66
68
|
- test/buffer_test.rb
|
|
67
69
|
- test/cli_test.rb
|
|
68
70
|
- test/config_dsl_test.rb
|
|
71
|
+
- test/config_loader_test.rb
|
|
69
72
|
- test/dispatcher_test.rb
|
|
73
|
+
- test/display_width_test.rb
|
|
70
74
|
- test/editor_mark_test.rb
|
|
71
75
|
- test/editor_register_test.rb
|
|
72
76
|
- test/fixtures/render_basic_snapshot.txt
|