This commit is contained in:
2026-04-06 19:40:42 -07:00
commit da480fd7a4
7 changed files with 798 additions and 0 deletions

408
orderedit.lua Normal file
View File

@@ -0,0 +1,408 @@
-- SPDX-FileCopyrightText: 2017 Daniel Ratcliffe
--
-- SPDX-License-Identifier: LicenseRef-CCPL
-- Get file to edit
local x, y = 1, 1
local w, h = term.getSize()
local scrollX, scrollY = 0, 0
local tLines = {""}
local bRunning = true
local returnvalue = nil
-- Colours
local highlightColour, keywordColour, textColour, bgColour, errorColour
bgColour = colours.black
textColour = colours.white
highlightColour = colours.white
keywordColour = colours.white
errorColour = colours.white
-- Menus
local menu = require "cc.internal.menu"
local current_menu
local menu_items = {}
table.insert(menu_items, "Done")
local status_ok, status_text
local tCompletions
local nCompletion
local function redrawLines(line, endLine)
if not endLine then endLine = line end
local colour = term.getTextColour()
-- Highlight all lines between line and endLine, highlighting further lines if their
-- lexer state has changed and aborting at the end of the screen.
local changed = false
while (changed or line <= endLine) and line - scrollY < h do
term.setCursorPos(1 - scrollX, line - scrollY)
term.clearLine()
local contents = tLines[line]
if not contents then break end
print(contents)
line = line + 1
end
term.setTextColor(colours.white)
term.setCursorPos(x - scrollX, y - scrollY)
end
local function redrawText()
redrawLines(scrollY + 1, scrollY + h - 1)
end
local function redrawMenu()
-- Clear line
term.setCursorPos(1, h)
term.clearLine()
-- Draw line numbers
term.setCursorPos(w - #("Ln " .. y) + 1, h)
term.setTextColour(highlightColour)
term.write("Ln ")
term.setTextColour(textColour)
term.write(y)
term.setCursorPos(1, h)
if current_menu then
-- Draw menu
menu.draw(current_menu)
else
-- Draw status
term.setTextColour(colors.yellow)
term.write("Press ctrl to view options")
term.setTextColour(textColour)
end
-- Reset cursor
term.setCursorPos(x - scrollX, y - scrollY)
term.setCursorBlink(not current_menu)
end
local tMenuFuncs = {
Done = function()
local order = table.concat(tLines,"\n")
term.clear()
returnvalue = order
end
}
local function setCursor(newX, newY)
local _, oldY = x, y
x, y = newX, newY
local screenX = x - scrollX
local screenY = y - scrollY
local bRedraw = false
if screenX < 1 then
scrollX = x - 1
screenX = 1
bRedraw = true
elseif screenX > w then
scrollX = x - w
screenX = w
bRedraw = true
end
if screenY < 1 then
scrollY = y - 1
screenY = 1
bRedraw = true
elseif screenY > h - 1 then
scrollY = y - (h - 1)
screenY = h - 1
bRedraw = true
end
if bRedraw then
redrawText()
elseif y ~= oldY then
redrawLines(math.min(y, oldY), math.max(y, oldY))
else
redrawLines(y)
end
redrawMenu()
end
-- Actual program functionality begins
term.setBackgroundColour(bgColour)
term.clear()
term.setCursorPos(x, y)
term.setCursorBlink(true)
redrawText()
redrawMenu()
local function acceptCompletion()
if nCompletion then
-- Append the completion
local sCompletion = tCompletions[nCompletion]
tLines[y] = tLines[y] .. sCompletion
setCursor(x + #sCompletion, y)
end
end
local function handleMenuEvent(event)
assert(current_menu)
local result = menu.handle_event(current_menu, table.unpack(event, 1, event.n))
if result == false then
current_menu = nil
redrawMenu()
elseif result ~= nil then
tMenuFuncs[result]()
current_menu = nil
redrawMenu()
end
end
-- Handle input
while bRunning do
local event = table.pack(os.pullEvent())
if event[1] == "key" then
if current_menu then
handleMenuEvent(event)
if returnvalue then
return returnvalue
end
else
local key = event[2]
if key == keys.up then
if nCompletion then
-- Cycle completions
nCompletion = nCompletion - 1
if nCompletion < 1 then
nCompletion = #tCompletions
end
redrawLines(y)
elseif y > 1 then
-- Move cursor up
setCursor(
math.min(x, #tLines[y - 1] + 1),
y - 1
)
end
elseif key == keys.down then
if nCompletion then
-- Cycle completions
nCompletion = nCompletion + 1
if nCompletion > #tCompletions then
nCompletion = 1
end
redrawLines(y)
elseif y < #tLines then
-- Move cursor down
setCursor(
math.min(x, #tLines[y + 1] + 1),
y + 1
)
end
elseif key == keys.tab then
if nCompletion and x == #tLines[y] + 1 then
-- Accept autocomplete
acceptCompletion()
else
-- Indent line
local sLine = tLines[y]
tLines[y] = string.sub(sLine, 1, x - 1) .. " " .. string.sub(sLine, x)
setCursor(x + 4, y)
end
elseif key == keys.pageUp then
-- Move up a page
local newY
if y - (h - 1) >= 1 then
newY = y - (h - 1)
else
newY = 1
end
setCursor(
math.min(x, #tLines[newY] + 1),
newY
)
elseif key == keys.pageDown then
-- Move down a page
local newY
if y + (h - 1) <= #tLines then
newY = y + (h - 1)
else
newY = #tLines
end
local newX = math.min(x, #tLines[newY] + 1)
setCursor(newX, newY)
elseif key == keys.home then
-- Move cursor to the beginning
if x > 1 then
setCursor(1, y)
end
elseif key == keys["end"] then
-- Move cursor to the end
local nLimit = #tLines[y] + 1
if x < nLimit then
setCursor(nLimit, y)
end
elseif key == keys.left then
if x > 1 then
-- Move cursor left
setCursor(x - 1, y)
elseif x == 1 and y > 1 then
setCursor(#tLines[y - 1] + 1, y - 1)
end
elseif key == keys.right then
local nLimit = #tLines[y] + 1
if x < nLimit then
-- Move cursor right
setCursor(x + 1, y)
elseif nCompletion and x == #tLines[y] + 1 then
-- Accept autocomplete
acceptCompletion()
elseif x == nLimit and y < #tLines then
-- Go to next line
setCursor(1, y + 1)
end
elseif key == keys.delete then
local nLimit = #tLines[y] + 1
if x < nLimit then
local sLine = tLines[y]
tLines[y] = string.sub(sLine, 1, x - 1) .. string.sub(sLine, x + 1)
redrawLines(y)
elseif y < #tLines then
tLines[y] = tLines[y] .. tLines[y + 1]
table.remove(tLines, y + 1)
redrawText()
end
elseif key == keys.backspace then
if x > 1 then
-- Remove character
local sLine = tLines[y]
if x > 4 and string.sub(sLine, x - 4, x - 1) == " " and not string.sub(sLine, 1, x - 1):find("%S") then
tLines[y] = string.sub(sLine, 1, x - 5) .. string.sub(sLine, x)
setCursor(x - 4, y)
else
tLines[y] = string.sub(sLine, 1, x - 2) .. string.sub(sLine, x)
setCursor(x - 1, y)
end
elseif y > 1 then
-- Remove newline
local sPrevLen = #tLines[y - 1]
tLines[y - 1] = tLines[y - 1] .. tLines[y]
table.remove(tLines, y)
setCursor(sPrevLen + 1, y - 1)
redrawText()
end
elseif (key == keys.enter or key == keys.numPadEnter) then
-- Newline
local sLine = tLines[y]
local _, spaces = string.find(sLine, "^[ ]+")
if not spaces then
spaces = 0
end
tLines[y] = string.sub(sLine, 1, x - 1)
table.insert(tLines, y + 1, string.rep(' ', spaces) .. string.sub(sLine, x))
setCursor(spaces + 1, y + 1)
redrawText()
elseif key == keys.leftCtrl or key == keys.rightCtrl then
current_menu = menu.create(menu_items)
redrawMenu()
end
end
elseif event[1] == "char" then
if current_menu then
handleMenuEvent(event)
else
-- Input text
local sLine = tLines[y]
tLines[y] = string.sub(sLine, 1, x - 1) .. event[2] .. string.sub(sLine, x)
setCursor(x + 1, y)
end
elseif event[1] == "paste" then
-- Close menu if open
if current_menu then
current_menu = nil
redrawMenu()
end
-- Input text
local text = event[2]
local sLine = tLines[y]
tLines[y] = string.sub(sLine, 1, x - 1) .. text .. string.sub(sLine, x)
setCursor(x + #text, y)
elseif event[1] == "mouse_click" then
local button, cx, cy = event[2], event[3], event[4]
if current_menu then
handleMenuEvent(event)
else
if button == 1 then
-- Left click
if cy < h then
local newY = math.min(math.max(scrollY + cy, 1), #tLines)
local newX = math.min(math.max(scrollX + cx, 1), #tLines[newY] + 1)
setCursor(newX, newY)
else
current_menu = menu.create(menu_items)
redrawMenu()
end
end
end
elseif event[1] == "mouse_scroll" then
if not current_menu then
local direction = event[2]
if direction == -1 then
-- Scroll up
if scrollY > 0 then
-- Move cursor up
scrollY = scrollY - 1
redrawText()
end
elseif direction == 1 then
-- Scroll down
local nMaxScroll = #tLines - (h - 1)
if scrollY < nMaxScroll then
-- Move cursor down
scrollY = scrollY + 1
redrawText()
end
end
end
elseif event[1] == "term_resize" then
w, h = term.getSize()
setCursor(x, y)
redrawMenu()
redrawText()
end
end
-- Cleanup
term.clear()
term.setCursorBlink(false)
term.setCursorPos(1, 1)