selecting text and deleting selections
[?]
May 29, 2022, 3:12 PM
DHI6IJCNSTHGED67T6H5X6Y636C7PIDGIJD32HBEKLT5WIMRS5MACDependencies
- [2]
2ZRC7FUL. - [3]
KOYAJWE4extract a couple more methods - [4]
AYE2VEGJextract a couple of methods - [5]
H2DPLWMVsnapshot: wrapping long lines at word boundaries - [6]
XNFTJHC4split keyboard handling between Text and Drawing - [7]
5DOC2CBMextract a function - [8]
3TFEAQSWstart using some globals - [9]
KECEMMMRextract couple of functions - [10]
2RXZ3PGObeginning of a new approach to scroll+wrap - [11]
ZPUQSPQPextract a few methods - [12]
WLHI7KD3new globals: draw partial screen line up top - [*]
BULPIBEGbeginnings of a module for the text editor - [*]
QYIFOHW3first test! - [*]
OYXDYPGSget rid of debug variables - [*]
HMODUNJEscroll on backspace - [*]
WY3JD6W6bugfix - [*]
PFT5Y2ZYmove - [*]
CG3264MMmove - [*]
AMSESRTHmove some code - [*]
AVTNUQYRbasic test-enabled framework - [*]
OTIBCAUJlove2d scaffold - [*]
OIB2QPRCstart remembering where the cursor is drawn in px - [*]
HYEAFRZ2split mouse_pressed events between Text and Drawing - [*]
BOFNXP5Gclicking now moves the cursor even on long, wrapped lines
Change contents
- edit in text.lua at line 28
local frag_len = utf8.len(frag) - edit in text.lua at line 48
if Selection1.line thenlocal lo, hi = Text.clip_selection(line_index, pos, pos+frag_len)if lo thenlocal lo_offset = utf8.offset(line.data, lo)local hi_offset = utf8.offset(line.data, hi)local pos_offset = utf8.offset(line.data, pos)local lo_pxif pos == lo thenlo_px = 0elselocal before = line.data:sub(pos_offset, lo_offset-1)local before_text = App.newText(love.graphics.getFont(), before)lo_px = App.width(before_text)*Zoomend--? print(lo,pos,hi, '--', lo_offset,pos_offset,hi_offset, '--', lo_px)local s = line.data:sub(lo_offset, hi_offset-1)local text = App.newText(love.graphics.getFont(), s)local text_width = App.width(text)*Zoomlove.graphics.setColor(0.7,0.7,0.9)love.graphics.rectangle('fill', x+lo_px,y, text_width,math.floor(15*Zoom))love.graphics.setColor(0,0,0)endend - edit in text.lua at line 75
local frag_len = utf8.len(frag) - replacement in text.lua at line 90
-- short words break on spaces-- long words break when they must-- Return any intersection of the region from Selection1 to Cursor1 with the-- region between {line=line_index, pos=apos} and {line=line_index, pos=bpos}.-- apos must be less than bpos. However Selection1 and Cursor1 can be in any order.-- Result: positions spos,epos between apos,bpos.function Text.clip_selection(line_index, apos, bpos)if Selection1.line == nil then return nil,nil end-- min,max = sorted(Selection1,Cursor1)local minl,minp = Selection1.line,Selection1.poslocal maxl,maxp = Cursor1.line,Cursor1.posif minl > maxl thenminl,maxl = maxl,minlminp,maxp = maxp,minpelseif minl == maxl thenif minp > maxp thenminp,maxp = maxp,minpendend-- check if intervals are disjointif line_index < minl then return nil,nil endif line_index > maxl then return nil,nil endif line_index == minl and bpos <= minp then return nil,nil endif line_index == maxl and apos >= maxp then return nil,nil end-- compare bounds more carefully (start inclusive, end exclusive)local a_ge = Text.le1({line=minl, pos=minp}, {line=line_index, pos=apos})local b_lt = Text.lt1({line=line_index, pos=bpos}, {line=maxl, pos=maxp})--? print(minl,line_index,maxl, '--', minp,apos,bpos,maxp, '--', a_ge,b_lt)if a_ge and b_lt then-- fully containedreturn apos,bposelseif a_ge thenassert(maxl == line_index)return apos,maxpelseif b_lt thenassert(minl == line_index)return minp,bposelseassert(minl == maxl and minl == line_index)return minp,maxpendendfunction Text.delete_selection()if Selection1.line == nil then return end-- min,max = sorted(Selection1,Cursor1)local minl,minp = Selection1.line,Selection1.poslocal maxl,maxp = Cursor1.line,Cursor1.posif minl > maxl thenminl,maxl = maxl,minlminp,maxp = maxp,minpelseif minl == maxl thenif minp > maxp thenminp,maxp = maxp,minpendend-- update Cursor1 and Selection1Cursor1.line = minlCursor1.pos = minpSelection1 = {}-- delete everything between min (inclusive) and max (exclusive)Lines[minl].fragments = nilLines[minl].screen_line_starting_pos = nillocal min_offset = utf8.offset(Lines[minl].data, minp)local max_offset = utf8.offset(Lines[maxl].data, maxp)if minl == maxl then--? print('minl == maxl')Lines[minl].data = Lines[minl].data:sub(1, min_offset-1)..Lines[minl].data:sub(max_offset)returnendassert(minl < maxl)local rhs = Lines[maxl].data:sub(max_offset)for i=maxl,minl+1,-1 dotable.remove(Lines, i)endLines[minl].data = Lines[minl].data:sub(1, min_offset-1)..rhsend - edit in text.lua at line 930
end-- some tests for operating over selections created using Shift- chords-- we're just testing delete_selection, and it works the same for all keysfunction test_backspace_over_selection()io.write('\ntest_backspace_over_selection')-- select just one character within a line with cursor before selectionApp.screen.init{width=25+30, height=60}Lines = load_array{'abc', 'def', 'ghi', 'jkl', 'mno'}Line_width = App.screen.widthCursor1 = {line=1, pos=1}Selection1 = {line=1, pos=2}Zoom = 1-- backspace deletes the selected character, even though it's after the cursorApp.run_after_keychord('backspace')check_eq(Lines[1].data, 'bc', "F - test_backspace_over_selection/data")-- cursor (remains) at start of selectioncheck_eq(Cursor1.line, 1, "F - test_backspace_over_selection/cursor:line")check_eq(Cursor1.pos, 1, "F - test_backspace_over_selection/cursor:pos")-- selection is clearedcheck_nil(Selection1.line, "F - test_backspace_over_selection/selection") - edit in text.lua at line 954
function test_backspace_over_selection_reverse()io.write('\ntest_backspace_over_selection')-- select just one character within a line with cursor after selectionApp.screen.init{width=25+30, height=60}Lines = load_array{'abc', 'def', 'ghi', 'jkl', 'mno'}Line_width = App.screen.widthCursor1 = {line=1, pos=2}Selection1 = {line=1, pos=1}Zoom = 1-- backspace deletes the selected characterApp.run_after_keychord('backspace')check_eq(Lines[1].data, 'bc', "F - test_backspace_over_selection_reverse/data")-- cursor moves to start of selectioncheck_eq(Cursor1.line, 1, "F - test_backspace_over_selection_reverse/cursor:line")check_eq(Cursor1.pos, 1, "F - test_backspace_over_selection_reverse/cursor:pos")-- selection is clearedcheck_nil(Selection1.line, "F - test_backspace_over_selection_reverse/selection")endfunction test_backspace_over_multiple_lines()io.write('\ntest_backspace_over_selection')-- select just one character within a line with cursor after selectionApp.screen.init{width=25+30, height=60}Lines = load_array{'abc', 'def', 'ghi', 'jkl', 'mno'}Line_width = App.screen.widthCursor1 = {line=1, pos=2}Selection1 = {line=4, pos=2}Zoom = 1-- backspace deletes the region and joins the remaining portions of lines on either sideApp.run_after_keychord('backspace')check_eq(Lines[1].data, 'akl', "F - test_backspace_over_multiple_lines/data:1")check_eq(Lines[2].data, 'mno', "F - test_backspace_over_multiple_lines/data:2")-- cursor remains at start of selectioncheck_eq(Cursor1.line, 1, "F - test_backspace_over_multiple_lines/cursor:line")check_eq(Cursor1.pos, 2, "F - test_backspace_over_multiple_lines/cursor:pos")-- selection is clearedcheck_nil(Selection1.line, "F - test_backspace_over_multiple_lines/selection")endfunction test_backspace_to_end_of_line()io.write('\ntest_backspace_over_selection')-- select region from cursor to end of lineApp.screen.init{width=25+30, height=60}Lines = load_array{'abc', 'def', 'ghi', 'jkl', 'mno'}Line_width = App.screen.widthCursor1 = {line=1, pos=2}Selection1 = {line=1, pos=4}Zoom = 1-- backspace deletes rest of line without joining to any other lineApp.run_after_keychord('backspace')check_eq(Lines[1].data, 'a', "F - test_backspace_to_start_of_line/data:1")check_eq(Lines[2].data, 'def', "F - test_backspace_to_start_of_line/data:2")-- cursor remains at start of selectioncheck_eq(Cursor1.line, 1, "F - test_backspace_to_start_of_line/cursor:line")check_eq(Cursor1.pos, 2, "F - test_backspace_to_start_of_line/cursor:pos")-- selection is clearedcheck_nil(Selection1.line, "F - test_backspace_to_start_of_line/selection")endfunction test_backspace_to_start_of_line()io.write('\ntest_backspace_over_selection')-- select region from cursor to start of lineApp.screen.init{width=25+30, height=60}Lines = load_array{'abc', 'def', 'ghi', 'jkl', 'mno'}Line_width = App.screen.widthCursor1 = {line=2, pos=1}Selection1 = {line=2, pos=3}Zoom = 1-- backspace deletes beginning of line without joining to any other lineApp.run_after_keychord('backspace')check_eq(Lines[1].data, 'abc', "F - test_backspace_to_start_of_line/data:1")check_eq(Lines[2].data, 'f', "F - test_backspace_to_start_of_line/data:2")-- cursor remains at start of selectioncheck_eq(Cursor1.line, 2, "F - test_backspace_to_start_of_line/cursor:line")check_eq(Cursor1.pos, 1, "F - test_backspace_to_start_of_line/cursor:pos")-- selection is clearedcheck_nil(Selection1.line, "F - test_backspace_to_start_of_line/selection")end - edit in text.lua at line 1098
--? print(chord) - edit in text.lua at line 1116
if Selection1.line thenText.delete_selection()returnend - edit in text.lua at line 1152
if Selection1.line thenText.delete_selection()returnend - edit in text.lua at line 1187
if Selection1.line thenSelection1 = {}end - edit in text.lua at line 1192
if Selection1.line thenSelection1 = {}end - edit in text.lua at line 1196
elseif chord == 'S-left' thenif Selection1.line == nil thenSelection1 = {line=Cursor1.line, pos=Cursor1.pos}endText.left()elseif chord == 'S-right' thenif Selection1.line == nil thenSelection1 = {line=Cursor1.line, pos=Cursor1.pos}endText.right() - edit in text.lua at line 1208
if Selection1.line thenSelection1 = {}end - edit in text.lua at line 1213
if Selection1.line thenSelection1 = {}end - edit in text.lua at line 1217
elseif chord == 'M-S-left' thenif Selection1.line == nil thenSelection1 = {line=Cursor1.line, pos=Cursor1.pos}endText.word_left()elseif chord == 'M-S-right' thenif Selection1.line == nil thenSelection1 = {line=Cursor1.line, pos=Cursor1.pos}endText.word_right() - edit in text.lua at line 1228
if Selection1.line thenSelection1 = {}end - edit in text.lua at line 1233
if Selection1.line thenSelection1 = {}end - edit in text.lua at line 1237
elseif chord == 'S-home' thenif Selection1.line == nil thenSelection1 = {line=Cursor1.line, pos=Cursor1.pos}endCursor1.pos = 1elseif chord == 'S-end' thenif Selection1.line == nil thenSelection1 = {line=Cursor1.line, pos=Cursor1.pos}endCursor1.pos = utf8.len(Lines[Cursor1.line].data) + 1 - edit in text.lua at line 1248
if Selection1.line thenSelection1 = {}end - edit in text.lua at line 1253
if Selection1.line thenSelection1 = {}endText.down()elseif chord == 'S-up' thenif Selection1.line == nil thenSelection1 = {line=Cursor1.line, pos=Cursor1.pos}endText.up()elseif chord == 'S-down' thenif Selection1.line == nil thenSelection1 = {line=Cursor1.line, pos=Cursor1.pos}end - edit in text.lua at line 1268
if Selection1.line thenSelection1 = {}end - edit in text.lua at line 1273
if Selection1.line thenSelection1 = {}endText.pagedown()elseif chord == 'S-pageup' thenif Selection1.line == nil thenSelection1 = {line=Cursor1.line, pos=Cursor1.pos}endText.pageup()elseif chord == 'S-pagedown' thenif Selection1.line == nil thenSelection1 = {line=Cursor1.line, pos=Cursor1.pos}end - replacement in text.lua at line 1439
if Lines[Cursor1.line].data:sub(offset,offset) == ' ' thenif Lines[Cursor1.line].data:sub(offset,offset) == ' ' then -- TODO: other space characters - edit in test.lua at line 11
endendfunction check_nil(x, msg)if x == nil thenio.write('.')elseerror(msg..'; should be nil but got "'..x..'"') - edit in main.lua at line 62
Selection1 = {} - edit in main.lua at line 183[25.492][26.1788]
if love.keyboard.isDown('lshift') or love.keyboard.isDown('rshift') thenif Selection1.line == nil thenSelection1 = {line=Cursor1.line, pos=Cursor1.pos}endelseif Selection1.line thenSelection1 = {}endend