From e2734cd572a8578ee07637f9c5471c0ccce119cc Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Wed, 20 Jul 2022 09:11:29 -0700 Subject: bugfix: where cursor is drawn The published version of lines.love was broken for almost an hour. The cursor would render one position to the right of where it really is. To fix it, this commit rolls back 26ba6e4e5a71. There doesn't seem a good way to test it. --- Manual_tests.md | 4 ++++ text.lua | 15 +++++++++++---- text_tests.lua | 20 ++++++++++---------- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/Manual_tests.md b/Manual_tests.md index 767d0fc..8d121d9 100644 --- a/Manual_tests.md +++ b/Manual_tests.md @@ -9,6 +9,10 @@ record those here. - Filename as relative path - from defaults +* How the screen looks. Our tests use a level of indirection to check text and + graphics printed to screen, but not the precise pixels they translate to. + - where exactly the cursor is drawn to highlight a given character + ### Other compromises Lua is dynamically typed. Tests can't patch over lack of type-checking. diff --git a/text.lua b/text.lua index 5a9896f..db0c3b7 100644 --- a/text.lua +++ b/text.lua @@ -803,15 +803,15 @@ end function Text.nearest_pos_less_than(line, x) --? print('', '-- nearest_pos_less_than', line, x) local len = utf8.len(line) - local max_x = Text.x(line, len) + local max_x = Text.x_after(line, len) if x > max_x then return len+1 end local left, right = 0, len+1 while true do local curr = math.floor((left+right)/2) - local currxmin = Text.x(line, curr+1) - local currxmax = Text.x(line, curr+2) + local currxmin = Text.x_after(line, curr+1) + local currxmax = Text.x_after(line, curr+2) --? print('', x, left, right, curr, currxmin, currxmax) if currxmin <= x and x < currxmax then return curr @@ -828,7 +828,7 @@ function Text.nearest_pos_less_than(line, x) assert(false) end -function Text.x(s, pos) +function Text.x_after(s, pos) local offset = Text.offset(s, math.min(pos+1, #s+1)) local s_before = s:sub(1, offset-1) --? print('^'..s_before..'$') @@ -836,6 +836,13 @@ function Text.x(s, pos) return App.width(text_before) end +function Text.x(s, pos) + local offset = Text.offset(s, pos) + local s_before = s:sub(1, offset-1) + local text_before = App.newText(love.graphics.getFont(), s_before) + return App.width(text_before) +end + function Text.to2(State, pos1) if State.lines[pos1.line].mode == 'drawing' then return {line=pos1.line, screen_line=1, screen_pos=1} diff --git a/text_tests.lua b/text_tests.lua index 4de3759..4e3cd2c 100644 --- a/text_tests.lua +++ b/text_tests.lua @@ -285,7 +285,7 @@ function test_click_with_mouse_takes_margins_into_account() edit.run_after_mouse_click(Editor_state, Editor_state.left+8,Editor_state.top+5, 1) -- cursor moves check_eq(Editor_state.cursor1.line, 1, 'F - test_click_with_mouse_takes_margins_into_account/cursor:line') - check_eq(Editor_state.cursor1.pos, 1, 'F - test_click_with_mouse_takes_margins_into_account/cursor:pos') + check_eq(Editor_state.cursor1.pos, 2, 'F - test_click_with_mouse_takes_margins_into_account/cursor:pos') check_nil(Editor_state.selection1.line, 'F - test_click_with_mouse_takes_margins_into_account/selection is empty to avoid perturbing future edits') end @@ -375,7 +375,7 @@ function test_click_with_mouse_on_wrapping_line() edit.run_after_mouse_click(Editor_state, Editor_state.left+8,Editor_state.top+5, 1) -- cursor moves check_eq(Editor_state.cursor1.line, 1, 'F - test_click_with_mouse_on_wrapping_line/cursor:line') - check_eq(Editor_state.cursor1.pos, 1, 'F - test_click_with_mouse_on_wrapping_line/cursor:pos') + check_eq(Editor_state.cursor1.pos, 2, 'F - test_click_with_mouse_on_wrapping_line/cursor:pos') check_nil(Editor_state.selection1.line, 'F - test_click_with_mouse_on_wrapping_line/selection is empty to avoid perturbing future edits') end @@ -395,7 +395,7 @@ function test_click_with_mouse_on_wrapping_line_takes_margins_into_account() edit.run_after_mouse_click(Editor_state, Editor_state.left+8,Editor_state.top+5, 1) -- cursor moves check_eq(Editor_state.cursor1.line, 1, 'F - test_click_with_mouse_on_wrapping_line_takes_margins_into_account/cursor:line') - check_eq(Editor_state.cursor1.pos, 1, 'F - test_click_with_mouse_on_wrapping_line_takes_margins_into_account/cursor:pos') + check_eq(Editor_state.cursor1.pos, 2, 'F - test_click_with_mouse_on_wrapping_line_takes_margins_into_account/cursor:pos') check_nil(Editor_state.selection1.line, 'F - test_click_with_mouse_on_wrapping_line_takes_margins_into_account/selection is empty to avoid perturbing future edits') end @@ -834,7 +834,7 @@ function test_move_cursor_using_mouse() edit.draw(Editor_state) -- populate line.y for each line in Editor_state.lines edit.run_after_mouse_release(Editor_state, Editor_state.left+8,Editor_state.top+5, 1) check_eq(Editor_state.cursor1.line, 1, 'F - test_move_cursor_using_mouse/cursor:line') - check_eq(Editor_state.cursor1.pos, 1, 'F - test_move_cursor_using_mouse/cursor:pos') + check_eq(Editor_state.cursor1.pos, 2, 'F - test_move_cursor_using_mouse/cursor:pos') check_nil(Editor_state.selection1.line, 'F - test_move_cursor_using_mouse/selection:line') check_nil(Editor_state.selection1.pos, 'F - test_move_cursor_using_mouse/selection:pos') end @@ -855,7 +855,7 @@ function test_select_text_using_mouse() -- drag and release somewhere else edit.run_after_mouse_release(Editor_state, Editor_state.left+20,Editor_state.top+Editor_state.line_height+5, 1) check_eq(Editor_state.selection1.line, 1, 'F - test_select_text_using_mouse/selection:line') - check_eq(Editor_state.selection1.pos, 1, 'F - test_select_text_using_mouse/selection:pos') + check_eq(Editor_state.selection1.pos, 2, 'F - test_select_text_using_mouse/selection:pos') check_eq(Editor_state.cursor1.line, 2, 'F - test_select_text_using_mouse/cursor:line') check_eq(Editor_state.cursor1.pos, 4, 'F - test_select_text_using_mouse/cursor:pos') end @@ -880,7 +880,7 @@ function test_select_text_using_mouse_and_shift() edit.run_after_mouse_release(Editor_state, Editor_state.left+20,Editor_state.top+Editor_state.line_height+5, 1) App.fake_key_release('lshift') check_eq(Editor_state.selection1.line, 1, 'F - test_select_text_using_mouse_and_shift/selection:line') - check_eq(Editor_state.selection1.pos, 1, 'F - test_select_text_using_mouse_and_shift/selection:pos') + check_eq(Editor_state.selection1.pos, 2, 'F - test_select_text_using_mouse_and_shift/selection:pos') check_eq(Editor_state.cursor1.line, 2, 'F - test_select_text_using_mouse_and_shift/cursor:line') check_eq(Editor_state.cursor1.pos, 4, 'F - test_select_text_using_mouse_and_shift/cursor:pos') end @@ -911,9 +911,9 @@ function test_select_text_repeatedly_using_mouse_and_shift() App.fake_key_release('lshift') -- selection is between first and third location. forget the second location, not the first. check_eq(Editor_state.selection1.line, 1, 'F - test_select_text_repeatedly_using_mouse_and_shift/selection:line') - check_eq(Editor_state.selection1.pos, 1, 'F - test_select_text_repeatedly_using_mouse_and_shift/selection:pos') + check_eq(Editor_state.selection1.pos, 2, 'F - test_select_text_repeatedly_using_mouse_and_shift/selection:pos') check_eq(Editor_state.cursor1.line, 2, 'F - test_select_text_repeatedly_using_mouse_and_shift/cursor:line') - check_eq(Editor_state.cursor1.pos, 1, 'F - test_select_text_repeatedly_using_mouse_and_shift/cursor:pos') + check_eq(Editor_state.cursor1.pos, 2, 'F - test_select_text_repeatedly_using_mouse_and_shift/cursor:pos') end function test_cut_without_selection() @@ -1129,7 +1129,7 @@ function test_down_arrow_scrolls_down_by_one_screen_line() edit.run_after_keychord(Editor_state, 'down') check_eq(Editor_state.screen_top1.line, 2, 'F - test_down_arrow_scrolls_down_by_one_screen_line/screen_top') check_eq(Editor_state.cursor1.line, 3, 'F - test_down_arrow_scrolls_down_by_one_screen_line/cursor:line') - check_eq(Editor_state.cursor1.pos, 6, 'F - test_down_arrow_scrolls_down_by_one_screen_line/cursor:pos') + check_eq(Editor_state.cursor1.pos, 5, 'F - test_down_arrow_scrolls_down_by_one_screen_line/cursor:pos') y = Editor_state.top App.screen.check(y, 'def', 'F - test_down_arrow_scrolls_down_by_one_screen_line/screen:1') y = y + Editor_state.line_height @@ -1693,7 +1693,7 @@ function test_position_cursor_on_recently_edited_wrapping_line() edit.run_after_mouse_release(Editor_state, Editor_state.left+8,Editor_state.top+Editor_state.line_height*2+5, 1) -- cursor should move check_eq(Editor_state.cursor1.line, 1, 'F - test_position_cursor_on_recently_edited_wrapping_line/cursor:line') - check_eq(Editor_state.cursor1.pos, 25, 'F - test_position_cursor_on_recently_edited_wrapping_line/cursor:pos') + check_eq(Editor_state.cursor1.pos, 26, 'F - test_position_cursor_on_recently_edited_wrapping_line/cursor:pos') end function test_backspace_can_scroll_up() -- cgit 1.4.1-2-gfad0