-- helpers for selecting portions of text function edit.mouse_loc(editor) local mx,my = love.mouse.getPosition() return edit.to_loc(editor, mx, my) end function Text.cut_selection_and_record_undo_event(editor) if editor.selection1.line == nil then return end local result = Text.selection(editor) Text.delete_selection_and_record_undo_event(editor) return result end function Text.delete_selection_and_record_undo_event(editor) if editor.selection1.line == nil then return end local minl,maxl = minmax(editor.selection1.line, editor.cursor.line) local before = snapshot(editor, minl, maxl) Text.delete_selection_without_undo(editor) record_undo_event(editor, {before=before, after=snapshot(editor, editor.cursor.line)}) end function Text.delete_selection_without_undo(editor) if editor.selection1.line == nil then return end -- min,max = sorted(editor.selection1,editor.cursor) local minl,minp = editor.selection1.line,editor.selection1.pos local maxl,maxp = editor.cursor.line,editor.cursor.pos if minl > maxl then minl,maxl = maxl,minl minp,maxp = maxp,minp elseif minl == maxl then if minp > maxp then minp,maxp = maxp,minp end end -- update editor.cursor and editor.selection1 editor.cursor.line = minl editor.cursor.pos = minp if edit.lt(editor.cursor, editor.screen_top) then editor.screen_top = edit.hor(editor, editor.cursor, editor.left) end editor.selection1 = {} -- delete everything between min (inclusive) and max (exclusive) local min_offset = Text.offset(editor.lines[minl].data, minp) local max_offset = Text.offset(editor.lines[maxl].data, maxp) if minl == maxl then editor.lines[minl].data = editor.lines[minl].data:sub(1, min_offset-1)..editor.lines[minl].data:sub(max_offset) return end assert(minl < maxl, ('minl %d not < maxl %d'):format(minl, maxl)) local rhs = editor.lines[maxl].data:sub(max_offset) for i=maxl,minl+1,-1 do table.remove(editor.lines, i) end editor.lines[minl].data = editor.lines[minl].data:sub(1, min_offset-1)..rhs end function Text.selection(editor) if editor.selection1.line == nil then return end -- min,max = sorted(editor.selection1,editor.cursor) local minl,minp = editor.selection1.line,editor.selection1.pos local maxl,maxp = editor.cursor.line,editor.cursor.pos if minl > maxl then minl,maxl = maxl,minl minp,maxp = maxp,minp elseif minl == maxl then if minp > maxp then minp,maxp = maxp,minp end end local min_offset = Text.offset(editor.lines[minl].data, minp) local max_offset = Text.offset(editor.lines[maxl].data, maxp) if minl == maxl then return editor.lines[minl].data:sub(min_offset, max_offset-1) end assert(minl < maxl, ('minl %d not < maxl %d'):format(minl, maxl)) local result = {editor.lines[minl].data:sub(min_offset)} for i=minl+1,maxl-1 do if editor.lines[i].mode == 'text' then table.insert(result, editor.lines[i].data) end end table.insert(result, editor.lines[maxl].data:sub(1, max_offset-1)) return table.concat(result, '\n') end function in_selection(editor, line_index, pos, cursor) if editor.selection1.line == nil then return false end assert(cursor.mode == 'text') assert(editor.lines[line_index].mode == 'text') local curr = {mode='text', line=line_index, pos=pos} if edit.eq(cursor, editor.selection1) then return false elseif edit.lt(cursor, editor.selection1) then return edit.le(cursor, curr) and edit.lt(curr, editor.selection1) elseif edit.lt(editor.selection1, cursor) then return edit.le(editor.selection1, curr) and edit.lt(curr, cursor) end end