100 lines
3.6 KiB
Lua
100 lines
3.6 KiB
Lua
-- 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
|