mirror of
https://github.com/LDDestroier/CC/
synced 2024-11-05 01:26:20 +00:00
Create eldit.lua
To do: + file saving + syntax formatting + other text functions + yadda
This commit is contained in:
parent
9e7475e684
commit
2e289f23bc
449
eldit.lua
Normal file
449
eldit.lua
Normal file
@ -0,0 +1,449 @@
|
||||
-- eldit
|
||||
-- by lddestroier
|
||||
-- wget https://raw.githubusercontent.com/LDDestroier/CC/master/eldit.lua
|
||||
|
||||
local scr_x, scr_y = term.getSize()
|
||||
|
||||
local eldit = {}
|
||||
eldit.buffer = {{}}
|
||||
eldit.scrollX = 0
|
||||
eldit.scrollY = 0
|
||||
eldit.cursors = {
|
||||
{x = 1, y = 1, lastX = 1}
|
||||
}
|
||||
eldit.selections = {}
|
||||
eldit.size = {
|
||||
x = 1,
|
||||
y = 1,
|
||||
width = scr_x,
|
||||
height = scr_y
|
||||
}
|
||||
|
||||
local eClearLine = function(y)
|
||||
local cx, cy = term.getCursorPos()
|
||||
term.setCursorPos(eldit.size.x, y or cy)
|
||||
term.write((" "):rep(eldit.size.width))
|
||||
term.setCursorPos(cx, cy)
|
||||
end
|
||||
|
||||
local eClear = function()
|
||||
local cx, cy = term.getCursorPos()
|
||||
for y = eldit.size.y, eldit.size.y + eldit.size.height - 1 do
|
||||
term.setCursorPos(eldit.size.x, y)
|
||||
term.write((" "):rep(eldit.size.width))
|
||||
end
|
||||
term.setCursorPos(cx, cy)
|
||||
end
|
||||
|
||||
local explode = function(div, str, replstr, includeDiv)
|
||||
if (div == '') then
|
||||
return false
|
||||
end
|
||||
local pos, arr = 0, {}
|
||||
for st, sp in function() return string.find(str, div, pos, false) end do
|
||||
table.insert(arr, string.sub(replstr or str, pos, st - 1 + (includeDiv and #div or 0)))
|
||||
pos = sp + 1
|
||||
end
|
||||
table.insert(arr, string.sub(replstr or str, pos))
|
||||
return arr
|
||||
end
|
||||
|
||||
prompt = function(prebuffer)
|
||||
local keysDown = {}
|
||||
local miceDown = {}
|
||||
if type(prebuffer) == "string" then
|
||||
for i = 1, #prebuffer do
|
||||
if prebuffer:sub(i,i) == "\n" then
|
||||
eldit.buffer[#eldit.buffer + 1] = {}
|
||||
else
|
||||
eldit.buffer[#eldit.buffer] = prebuffer:sub(i,i)
|
||||
end
|
||||
end
|
||||
elseif type(prebuffer) == "table" then
|
||||
eldit.buffer = prebuffer
|
||||
end
|
||||
local isCursorBlink = false
|
||||
local isInsert = false
|
||||
|
||||
local checkIfSelected = function(x, y)
|
||||
for id, sel in pairs(eldit.selections) do
|
||||
if (x >= sel[1].x or y >= sel[1].y) and (x <= sel[2].x or y <= sel[2].y) then
|
||||
return id
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local checkIfCursor = function(x, y)
|
||||
for id, cur in pairs(eldit.cursors) do
|
||||
if x == cur.x and y == cur.y then
|
||||
return id
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local getChar = function(x, y)
|
||||
if eldit.buffer[y] then
|
||||
return eldit.buffer[y][x]
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
local render = function()
|
||||
local cx, cy
|
||||
for y = 1, eldit.size.height - 1 do -- minus one because it reserves space for the bar
|
||||
for x = 1, eldit.size.width do
|
||||
term.setCursorPos(eldit.size.x + x - 1, eldit.size.y + y - 1)
|
||||
cx = x + eldit.scrollX
|
||||
cy = y + eldit.scrollY
|
||||
|
||||
if checkIfSelected(cx, cy) then
|
||||
term.setBackgroundColor(colors.blue)
|
||||
else
|
||||
term.setBackgroundColor(colors.black)
|
||||
end
|
||||
|
||||
if checkIfCursor(cx, cy) and isCursorBlink then
|
||||
if isInsert then
|
||||
term.setTextColor(colors.black)
|
||||
term.setBackgroundColor(colors.white)
|
||||
else
|
||||
term.setTextColor(colors.black)
|
||||
term.setBackgroundColor(colors.lightGray)
|
||||
end
|
||||
else
|
||||
term.setTextColor(colors.white)
|
||||
end
|
||||
term.write(getChar(cx, cy) or " ")
|
||||
end
|
||||
end
|
||||
term.setCursorPos(eldit.size.x, eldit.size.y + eldit.size.height - 1)
|
||||
term.setBackgroundColor(colors.gray)
|
||||
eClearLine()
|
||||
for id,cur in pairs(eldit.cursors) do
|
||||
term.write("(" .. cur.x .. "," .. cur.y .. ") ")
|
||||
end
|
||||
end
|
||||
|
||||
local scrollToCursor = function()
|
||||
local lowCur, highCur = eldit.cursors[1], eldit.cursors[1]
|
||||
local leftCur, rightCur = eldit.cursors[1], eldit.cursors[1]
|
||||
for id,cur in pairs(eldit.cursors) do
|
||||
if cur.y < lowCur.y then
|
||||
lowCur = cur
|
||||
elseif cur.y > highCur.y then
|
||||
highCur = cur
|
||||
end
|
||||
if cur.x < leftCur.x then
|
||||
leftCur = cur
|
||||
elseif cur.y > rightCur.x then
|
||||
rightCur = cur
|
||||
end
|
||||
end
|
||||
if lowCur.y - eldit.scrollY < 1 then
|
||||
eldit.scrollY = highCur.y - 1
|
||||
elseif highCur.y - eldit.scrollY > eldit.size.height - 1 then
|
||||
eldit.scrollY = lowCur.y - eldit.size.height + 1
|
||||
end
|
||||
if leftCur.x - eldit.scrollX < 1 then
|
||||
eldit.scrollX = rightCur.x - 1
|
||||
elseif rightCur.x - eldit.scrollX > eldit.size.width then
|
||||
eldit.scrollX = leftCur.x - eldit.size.width
|
||||
end
|
||||
end
|
||||
|
||||
local adjustScroll = function(amount)
|
||||
eldit.scrollY = math.min(
|
||||
math.max(
|
||||
0,
|
||||
eldit.scrollY + amount
|
||||
),
|
||||
math.max(
|
||||
0,
|
||||
#eldit.buffer - eldit.size.height + 1
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
local removeRedundantCursors = function()
|
||||
local xes = {}
|
||||
for i = #eldit.cursors, 1, -1 do
|
||||
if xes[eldit.cursors[i].x] == eldit.cursors[i].y then
|
||||
table.remove(eldit.cursors, i)
|
||||
else
|
||||
xes[eldit.cursors[i].x] = eldit.cursors[i].y
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local deleteText = function(mode, direction)
|
||||
for id,cur in pairs(eldit.cursors) do
|
||||
|
||||
if mode == "single" then
|
||||
if direction == "forward" then
|
||||
|
||||
elseif direction == "backward" then
|
||||
if cur.x > 1 then
|
||||
cur.x = cur.x - 1
|
||||
table.remove(eldit.buffer[cur.y], cur.x)
|
||||
elseif cur.y > 1 then
|
||||
for i = 1, #eldit.buffer[cur.y] do
|
||||
table.insert(eldit.buffer[cur.y - 1], eldit.buffer[cur.y][i])
|
||||
end
|
||||
table.remove(eldit.buffer, cur.y)
|
||||
cur.y = cur.y - 1
|
||||
cur.x = #eldit.buffer[cur.y] + 1
|
||||
end
|
||||
else
|
||||
if cur.x >= 1 and cur.x <= #eldit.buffer[cur.y] then
|
||||
table.remove(eldit.buffer[cur.y], cur.x)
|
||||
elseif cur.x == #eldit.buffer[cur.y] + 1 and cur.y < #eldit.buffer then
|
||||
for i = 1, #eldit.buffer[cur.y + 1] do
|
||||
table.insert(eldit.buffer[cur.y], eldit.buffer[cur.y + 1][i])
|
||||
end
|
||||
table.remove(eldit.buffer, cur.y + 1)
|
||||
end
|
||||
end
|
||||
elseif mode == "word" then
|
||||
local pos = cur.x
|
||||
local interruptable = {
|
||||
[" "] = true,
|
||||
["["] = true, ["]"] = true,
|
||||
["{"] = true, ["}"] = true,
|
||||
["("] = true, [")"] = true,
|
||||
["|"] = true,
|
||||
["/"] = true,
|
||||
["\\"] = true,
|
||||
["+"] = true,
|
||||
["-"] = true,
|
||||
["*"] = true,
|
||||
["="] = true,
|
||||
}
|
||||
if direction == "forward" then
|
||||
repeat
|
||||
pos = pos + 1
|
||||
until interruptable[eldit.buffer[cur.y][pos]] or pos >= #eldit.buffer[cur.y]
|
||||
for i = pos, cur.x, -1 do
|
||||
table.remove(eldit.buffer[cur.y], i)
|
||||
end
|
||||
else
|
||||
repeat
|
||||
pos = pos - 1
|
||||
until interruptable[eldit.buffer[cur.y][pos]] or pos <= 1
|
||||
for i = cur.x - 1, pos, -1 do
|
||||
table.remove(eldit.buffer[cur.y], i)
|
||||
end
|
||||
cur.x = pos
|
||||
end
|
||||
elseif mode == "line" then
|
||||
if direction == "forward" then
|
||||
for i = cur.x, #eldit.buffer[cur.y] do
|
||||
eldit.buffer[cur.y][i] = nil
|
||||
end
|
||||
else
|
||||
for i = cur.x, 1, -1 do
|
||||
table.remove(eldit.buffer[cur.y], i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
cur.lastX = cur.x
|
||||
scrollToCursor()
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
local placeText = function(text)
|
||||
for id,sel in pairs(eldit.selections) do
|
||||
for y = sel[2].y, sel[1].y, -1 do
|
||||
for x = #eldit.buffer[y], 1, -1 do
|
||||
if (y > sel[1].y and y < sel[2].y) or (x >= sel[1].x and x <= sel[2].x) then
|
||||
table.remove(eldit.buffer[y], x)
|
||||
end
|
||||
end
|
||||
end
|
||||
eldit.cursors[#eldit.cursors + 1] = {x = sel[1].x, y = sel[1].y}
|
||||
end
|
||||
removeRedundantCursors()
|
||||
for id,cur in pairs(eldit.cursors) do
|
||||
for i = 1, #text do
|
||||
if isInsert then
|
||||
eldit.buffer[cur.y][cur.x + i - 1] = text:sub(i,i)
|
||||
else
|
||||
table.insert(eldit.buffer[cur.y], cur.x, text:sub(i,i))
|
||||
end
|
||||
cur.x = cur.x + 1
|
||||
end
|
||||
cur.lastX = cur.x
|
||||
end
|
||||
scrollToCursor()
|
||||
end
|
||||
|
||||
local adjustCursor = function(xmod, ymod, setLastX)
|
||||
for id,cur in pairs(eldit.cursors) do
|
||||
cur.x = cur.x + xmod
|
||||
cur.y = cur.y + ymod
|
||||
cur.y = math.max(1, math.min(cur.y, #eldit.buffer + 1))
|
||||
if xmod ~= 0 then
|
||||
repeat
|
||||
if cur.x < 1 and cur.y > 1 then
|
||||
cur.y = cur.y - 1
|
||||
cur.x = cur.x + #eldit.buffer[cur.y] + 1
|
||||
elseif cur.x > #eldit.buffer[cur.y] + 1 and cur.y < #eldit.buffer then
|
||||
cur.x = cur.x - #eldit.buffer[cur.y] - 1
|
||||
cur.y = cur.y + 1
|
||||
end
|
||||
until (cur.x >= 1 and cur.x <= #eldit.buffer[cur.y] + 1) or ((cur.y == 1 and xmod < 0) or (cur.y == #eldit.buffer and xmod > 0))
|
||||
end
|
||||
if setLastX then
|
||||
cur.lastX = cur.x
|
||||
else
|
||||
cur.x = cur.lastX
|
||||
end
|
||||
if cur.y < 1 then
|
||||
cur.y = math.max(1, math.min(cur.y, #eldit.buffer))
|
||||
cur.x = 1
|
||||
elseif cur.y > #eldit.buffer then
|
||||
cur.y = math.max(1, math.min(cur.y, #eldit.buffer))
|
||||
cur.x = #eldit.buffer[cur.y] + 1
|
||||
else
|
||||
cur.y = math.max(1, math.min(cur.y, #eldit.buffer))
|
||||
cur.x = math.max(1, math.min(cur.x, #eldit.buffer[cur.y] + 1))
|
||||
end
|
||||
end
|
||||
removeRedundantCursors()
|
||||
scrollToCursor()
|
||||
end
|
||||
|
||||
local makeNewLine = function()
|
||||
for id,cur in pairs(eldit.cursors) do
|
||||
table.insert(eldit.buffer, cur.y + 1, {})
|
||||
for i = cur.x, #eldit.buffer[cur.y] do
|
||||
if i > cur.x or not isInsert then
|
||||
table.insert(eldit.buffer[cur.y + 1], eldit.buffer[cur.y][i])
|
||||
end
|
||||
eldit.buffer[cur.y][i] = nil
|
||||
end
|
||||
cur.x = 1
|
||||
cur.y = cur.y + 1
|
||||
end
|
||||
scrollToCursor()
|
||||
end
|
||||
|
||||
local evt
|
||||
local tID = os.startTimer(0.5)
|
||||
local doRender = true
|
||||
|
||||
while true do
|
||||
evt = {os.pullEvent()}
|
||||
if evt[1] == "timer" then
|
||||
if evt[2] == tID then
|
||||
if isCursorBlink then
|
||||
tID = os.startTimer(0.4)
|
||||
else
|
||||
tID = os.startTimer(0.3)
|
||||
end
|
||||
isCursorBlink = not isCursorBlink
|
||||
doRender = true
|
||||
end
|
||||
elseif evt[1] == "char" or evt[1] == "paste" then
|
||||
placeText(evt[2])
|
||||
doRender = true
|
||||
elseif evt[1] == "key" then
|
||||
keysDown[evt[2]] = true
|
||||
if evt[2] == keys.insert then
|
||||
isInsert = not isInsert
|
||||
doRender, isCursorBlink = true, true
|
||||
|
||||
elseif evt[2] == keys.enter then
|
||||
makeNewLine()
|
||||
doRender, isCursorBlink = true, false
|
||||
|
||||
elseif evt[2] == keys.home then
|
||||
eldit.cursors = {{
|
||||
x = 1,
|
||||
y = eldit.cursors[1].y,
|
||||
lastX = 1
|
||||
}}
|
||||
doRender = true
|
||||
|
||||
elseif evt[2] == keys["end"] then
|
||||
eldit.cursors = {{
|
||||
x = #eldit.buffer[eldit.cursors[1].y] + 1,
|
||||
y = eldit.cursors[1].y,
|
||||
lastX = #eldit.buffer[eldit.cursors[1].y] + 1
|
||||
}}
|
||||
doRender = true
|
||||
|
||||
elseif evt[2] == keys.pageUp then
|
||||
adjustScroll(-eldit.size.height)
|
||||
doRender = true
|
||||
|
||||
elseif evt[2] == keys.pageDown then
|
||||
adjustScroll(eldit.size.height)
|
||||
doRender = true
|
||||
|
||||
elseif evt[2] == keys.backspace then
|
||||
deleteText(keysDown[keys.leftCtrl] and "word" or "single", "backward")
|
||||
doRender, isCursorBlink = true, false
|
||||
|
||||
elseif evt[2] == keys.delete then
|
||||
deleteText(keysDown[keys.leftCtrl] and "word" or "single", keysDown[keys.leftCtrl] and "forward")
|
||||
doRender, isCursorBlink = true, false
|
||||
|
||||
elseif evt[2] == keys.left then
|
||||
adjustCursor(-1, 0, true)
|
||||
doRender, isCursorBlink = true, true
|
||||
|
||||
elseif evt[2] == keys.right then
|
||||
adjustCursor(1, 0, true)
|
||||
doRender, isCursorBlink = true, true
|
||||
|
||||
elseif evt[2] == keys.up then
|
||||
adjustCursor(0, -1, false)
|
||||
doRender, isCursorBlink = true, true
|
||||
|
||||
elseif evt[2] == keys.down then
|
||||
adjustCursor(0, 1, false)
|
||||
doRender, isCursorBlink = true, true
|
||||
|
||||
end
|
||||
elseif evt[1] == "key_up" then
|
||||
keysDown[evt[2]] = nil
|
||||
elseif evt[1] == "mouse_click" then
|
||||
miceDown[evt[2]] = {x = evt[3], y = evt[4]}
|
||||
if keysDown[keys.leftCtrl] then
|
||||
table.insert(eldit.cursors, {
|
||||
x = evt[3] + eldit.scrollX,
|
||||
y = evt[4] + eldit.scrollY,
|
||||
lastX = evt[3] + eldit.scrollX
|
||||
})
|
||||
else
|
||||
eldit.cursors = {{
|
||||
x = evt[3] + eldit.scrollX,
|
||||
y = evt[4] + eldit.scrollY,
|
||||
lastX = evt[3] + eldit.scrollX
|
||||
}}
|
||||
end
|
||||
adjustCursor(0, 0, true)
|
||||
doRender = true
|
||||
elseif evt[1] == "mouse_drag" then
|
||||
miceDown[evt[2]] = {x = evt[3], y = evt[4]}
|
||||
doRender = true
|
||||
elseif evt[1] == "mouse_up" then
|
||||
miceDown[evt[2]] = nil
|
||||
elseif evt[1] == "mouse_scroll" then
|
||||
local amount = (keysDown[keys.leftCtrl] and eldit.size.height or 1) * evt[2]
|
||||
adjustScroll(amount)
|
||||
doRender = true
|
||||
end
|
||||
if doRender then
|
||||
render()
|
||||
doRender = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
prompt()
|
Loading…
Reference in New Issue
Block a user