no, that's not right

Bugfix: we want selections to persist even when we lift up the shift
key.

This requires hoisting some code inside every case inside the whole
keypress hierarchy, to ensure we never clear selections before
textinput events can handle them.

Current cross-cutting concerns we're explicitly scattering code for.
  - autosave
  - undo
  - selection management
This commit is contained in:
Kartik K. Agaram 2022-06-20 11:25:00 -07:00
parent 3be413602a
commit 3986e99fe0
3 changed files with 40 additions and 3 deletions

View File

@ -407,6 +407,9 @@ function App.textinput(t)
Text.textinput(t) Text.textinput(t)
end end
schedule_save() schedule_save()
if not App.shift_down() then
Selection1 = {}
end
end end
function App.keychord_pressed(chord) function App.keychord_pressed(chord)
@ -438,15 +441,19 @@ function App.keychord_pressed(chord)
Search_term = '' Search_term = ''
Search_backup = {cursor={line=Cursor1.line, pos=Cursor1.pos}, screen_top={line=Screen_top1.line, pos=Screen_top1.pos}} Search_backup = {cursor={line=Cursor1.line, pos=Cursor1.pos}, screen_top={line=Screen_top1.line, pos=Screen_top1.pos}}
assert(Search_text == nil) assert(Search_text == nil)
Selection1 = {}
elseif chord == 'C-=' then elseif chord == 'C-=' then
initialize_font_settings(Font_height+2) initialize_font_settings(Font_height+2)
Text.redraw_all() Text.redraw_all()
Selection1 = {}
elseif chord == 'C--' then elseif chord == 'C--' then
initialize_font_settings(Font_height-2) initialize_font_settings(Font_height-2)
Text.redraw_all() Text.redraw_all()
Selection1 = {}
elseif chord == 'C-0' then elseif chord == 'C-0' then
initialize_font_settings(20) initialize_font_settings(20)
Text.redraw_all() Text.redraw_all()
Selection1 = {}
elseif chord == 'C-z' then elseif chord == 'C-z' then
for _,line in ipairs(Lines) do line.y = nil end -- just in case we scroll for _,line in ipairs(Lines) do line.y = nil end -- just in case we scroll
local event = undo_event() local event = undo_event()
@ -459,6 +466,7 @@ function App.keychord_pressed(chord)
Text.redraw_all() -- if we're scrolling, reclaim all fragments to avoid memory leaks Text.redraw_all() -- if we're scrolling, reclaim all fragments to avoid memory leaks
schedule_save() schedule_save()
end end
Selection1 = {}
elseif chord == 'C-y' then elseif chord == 'C-y' then
for _,line in ipairs(Lines) do line.y = nil end -- just in case we scroll for _,line in ipairs(Lines) do line.y = nil end -- just in case we scroll
local event = redo_event() local event = redo_event()
@ -471,6 +479,7 @@ function App.keychord_pressed(chord)
Text.redraw_all() -- if we're scrolling, reclaim all fragments to avoid memory leaks Text.redraw_all() -- if we're scrolling, reclaim all fragments to avoid memory leaks
schedule_save() schedule_save()
end end
Selection1 = {}
-- clipboard -- clipboard
elseif chord == 'C-c' then elseif chord == 'C-c' then
for _,line in ipairs(Lines) do line.y = nil end -- just in case we scroll for _,line in ipairs(Lines) do line.y = nil end -- just in case we scroll
@ -478,6 +487,7 @@ function App.keychord_pressed(chord)
if s then if s then
App.setClipboardText(s) App.setClipboardText(s)
end end
Selection1 = {}
elseif chord == 'C-x' then elseif chord == 'C-x' then
for _,line in ipairs(Lines) do line.y = nil end -- just in case we scroll for _,line in ipairs(Lines) do line.y = nil end -- just in case we scroll
local s = Text.cut_selection() local s = Text.cut_selection()
@ -485,6 +495,7 @@ function App.keychord_pressed(chord)
App.setClipboardText(s) App.setClipboardText(s)
end end
schedule_save() schedule_save()
Selection1 = {}
elseif chord == 'C-v' then elseif chord == 'C-v' then
for _,line in ipairs(Lines) do line.y = nil end -- just in case we scroll for _,line in ipairs(Lines) do line.y = nil end -- just in case we scroll
-- We don't have a good sense of when to scroll, so we'll be conservative -- We don't have a good sense of when to scroll, so we'll be conservative
@ -506,6 +517,7 @@ function App.keychord_pressed(chord)
end end
schedule_save() schedule_save()
record_undo_event({before=before, after=snapshot(before_line, Cursor1.line)}) record_undo_event({before=before, after=snapshot(before_line, Cursor1.line)})
Selection1 = {}
-- dispatch to drawing or text -- dispatch to drawing or text
elseif App.mouse_down(1) or chord:sub(1,2) == 'C-' then elseif App.mouse_down(1) or chord:sub(1,2) == 'C-' then
-- DON'T reset line.y here -- DON'T reset line.y here
@ -553,7 +565,4 @@ function App.keychord_pressed(chord)
end end
function App.keyreleased(key, scancode) function App.keyreleased(key, scancode)
if not App.shift_down() then
Selection1 = {}
end
end end

View File

@ -175,6 +175,7 @@ function Text.keychord_pressed(chord)
end end
schedule_save() schedule_save()
record_undo_event({before=before, after=snapshot(before_line, Cursor1.line)}) record_undo_event({before=before, after=snapshot(before_line, Cursor1.line)})
Selection1 = {}
elseif chord == 'tab' then elseif chord == 'tab' then
local before = snapshot(Cursor1.line) local before = snapshot(Cursor1.line)
--? print(Screen_top1.line, Screen_top1.pos, Cursor1.line, Cursor1.pos, Screen_bottom1.line, Screen_bottom1.pos) --? print(Screen_top1.line, Screen_top1.pos, Cursor1.line, Cursor1.pos, Screen_bottom1.line, Screen_bottom1.pos)
@ -186,10 +187,12 @@ function Text.keychord_pressed(chord)
end end
schedule_save() schedule_save()
record_undo_event({before=before, after=snapshot(Cursor1.line)}) record_undo_event({before=before, after=snapshot(Cursor1.line)})
Selection1 = {}
elseif chord == 'backspace' then elseif chord == 'backspace' then
if Selection1.line then if Selection1.line then
Text.delete_selection() Text.delete_selection()
schedule_save() schedule_save()
Selection1 = {}
return return
end end
local before local before
@ -228,10 +231,12 @@ function Text.keychord_pressed(chord)
assert(Text.le1(Screen_top1, Cursor1)) assert(Text.le1(Screen_top1, Cursor1))
schedule_save() schedule_save()
record_undo_event({before=before, after=snapshot(Cursor1.line)}) record_undo_event({before=before, after=snapshot(Cursor1.line)})
Selection1 = {}
elseif chord == 'delete' then elseif chord == 'delete' then
if Selection1.line then if Selection1.line then
Text.delete_selection() Text.delete_selection()
schedule_save() schedule_save()
Selection1 = {}
return return
end end
local before local before
@ -264,6 +269,7 @@ function Text.keychord_pressed(chord)
end end
schedule_save() schedule_save()
record_undo_event({before=before, after=snapshot(Cursor1.line)}) record_undo_event({before=before, after=snapshot(Cursor1.line)})
Selection1 = {}
--== shortcuts that move the cursor --== shortcuts that move the cursor
elseif chord == 'left' then elseif chord == 'left' then
if Selection1.line then if Selection1.line then

View File

@ -186,6 +186,28 @@ function test_click_on_wrapping_line_containing_non_ascii()
check_eq(Cursor1.pos, 15, 'F - test_click_on_wrapping_line_containing_non_ascii/cursor') -- one more than the number of UTF-8 code-points check_eq(Cursor1.pos, 15, 'F - test_click_on_wrapping_line_containing_non_ascii/cursor') -- one more than the number of UTF-8 code-points
end end
function test_select_text()
io.write('\ntest_select_text')
-- display a line of text
App.screen.init{width=80, height=80}
Lines = load_array{'abc def'}
Line_width = 75
Cursor1 = {line=1, pos=1}
Screen_top1 = {line=1, pos=1}
Screen_bottom1 = {}
App.draw()
-- select a letter
App.fake_key_press('lshift')
App.run_after_keychord('S-right')
App.fake_key_release('lshift')
App.keyreleased('lshift')
-- selection persists even after shift is released
check_eq(Selection1.line, 1, 'F - test_select_text/selection:line')
check_eq(Selection1.pos, 1, 'F - test_select_text/selection:pos')
check_eq(Cursor1.line, 1, 'F - test_select_text/cursor:line')
check_eq(Cursor1.pos, 2, 'F - test_select_text/cursor:pos')
end
function test_edit_after_click_resets_selection() function test_edit_after_click_resets_selection()
io.write('\ntest_edit_after_click_resets_selection') io.write('\ntest_edit_after_click_resets_selection')
-- display a line of text -- display a line of text