mirror of
https://github.com/Ale32bit/Capy64.git
synced 2025-01-18 18:46:43 +00:00
Added reboot, OS improvements
This commit is contained in:
parent
84cba789a3
commit
29c55500bd
13 changed files with 444 additions and 451 deletions
1
Capy64/Assets/Lua/boot/00_common.lua
Normal file
1
Capy64/Assets/Lua/boot/00_common.lua
Normal file
|
@ -0,0 +1 @@
|
||||||
|
os.print = print
|
1
Capy64/Assets/Lua/boot/01_package.lua
Normal file
1
Capy64/Assets/Lua/boot/01_package.lua
Normal file
|
@ -0,0 +1 @@
|
||||||
|
package.path = "/lib/?.lua;/lib/?/init.lua;" .. package.path
|
79
Capy64/Assets/Lua/boot/02_stdio.lua
Normal file
79
Capy64/Assets/Lua/boot/02_stdio.lua
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
local term = require("term")
|
||||||
|
local expect = require("expect").expect
|
||||||
|
|
||||||
|
function write(sText)
|
||||||
|
expect(1, sText, "string", "number")
|
||||||
|
|
||||||
|
local w, h = term.getSize()
|
||||||
|
local x, y = term.getPos()
|
||||||
|
|
||||||
|
local nLinesPrinted = 0
|
||||||
|
local function newLine()
|
||||||
|
if y + 1 <= h then
|
||||||
|
term.setPos(1, y + 1)
|
||||||
|
else
|
||||||
|
term.setPos(1, h)
|
||||||
|
term.scroll(1)
|
||||||
|
end
|
||||||
|
x, y = term.getPos()
|
||||||
|
nLinesPrinted = nLinesPrinted + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Print the line with proper word wrapping
|
||||||
|
sText = tostring(sText)
|
||||||
|
while #sText > 0 do
|
||||||
|
local whitespace = string.match(sText, "^[ \t]+")
|
||||||
|
if whitespace then
|
||||||
|
-- Print whitespace
|
||||||
|
term.write(whitespace)
|
||||||
|
x, y = term.getPos()
|
||||||
|
sText = string.sub(sText, #whitespace + 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
local newline = string.match(sText, "^\n")
|
||||||
|
if newline then
|
||||||
|
-- Print newlines
|
||||||
|
newLine()
|
||||||
|
sText = string.sub(sText, 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
local text = string.match(sText, "^[^ \t\n]+")
|
||||||
|
if text then
|
||||||
|
sText = string.sub(sText, #text + 1)
|
||||||
|
if #text > w then
|
||||||
|
-- Print a multiline word
|
||||||
|
while #text > 0 do
|
||||||
|
if x > w then
|
||||||
|
newLine()
|
||||||
|
end
|
||||||
|
term.write(text)
|
||||||
|
text = string.sub(text, w - x + 2)
|
||||||
|
x, y = term.getPos()
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- Print a word normally
|
||||||
|
if x + #text - 1 > w then
|
||||||
|
newLine()
|
||||||
|
end
|
||||||
|
term.write(text)
|
||||||
|
x, y = term.getPos()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return nLinesPrinted
|
||||||
|
end
|
||||||
|
|
||||||
|
function print(...)
|
||||||
|
local nLinesPrinted = 0
|
||||||
|
local nLimit = select("#", ...)
|
||||||
|
for n = 1, nLimit do
|
||||||
|
local s = tostring(select(n, ...))
|
||||||
|
if n < nLimit then
|
||||||
|
s = s .. "\t"
|
||||||
|
end
|
||||||
|
nLinesPrinted = nLinesPrinted + write(s)
|
||||||
|
end
|
||||||
|
nLinesPrinted = nLinesPrinted + write("\n")
|
||||||
|
return nLinesPrinted
|
||||||
|
end
|
8
Capy64/Assets/Lua/boot/03_timer.lua
Normal file
8
Capy64/Assets/Lua/boot/03_timer.lua
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
local timer = require("timer")
|
||||||
|
|
||||||
|
function timer.sleep(n)
|
||||||
|
local timerId = timer.start(n)
|
||||||
|
repeat
|
||||||
|
local _, par = coroutine.yield("timer")
|
||||||
|
until par == timerId
|
||||||
|
end
|
13
Capy64/Assets/Lua/boot/99_shell.lua
Normal file
13
Capy64/Assets/Lua/boot/99_shell.lua
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
local term = require("term")
|
||||||
|
local colors = require("colors")
|
||||||
|
|
||||||
|
term.setSize(51, 19)
|
||||||
|
|
||||||
|
term.setForeground(0x59c9ff)
|
||||||
|
term.setBackground(colors.black)
|
||||||
|
term.clear()
|
||||||
|
term.setPos(1,1)
|
||||||
|
|
||||||
|
print(os.version())
|
||||||
|
|
||||||
|
dofile("/bin/shell.lua")
|
|
@ -1,446 +1,6 @@
|
||||||
local term = require("term")
|
local fs = require("fs")
|
||||||
local timer = require("timer")
|
|
||||||
os.print = print
|
|
||||||
|
|
||||||
package.path = "/lib/?.lua;/lib/?/init.lua;" .. package.path
|
|
||||||
|
|
||||||
local event = require("event")
|
|
||||||
local colors = require("colors")
|
|
||||||
local expect = require("expect").expect
|
|
||||||
|
|
||||||
function timer.sleep(n)
|
|
||||||
local timerId = timer.start(n)
|
|
||||||
repeat
|
|
||||||
local _, par = coroutine.yield("timer")
|
|
||||||
until par == timerId
|
|
||||||
end
|
|
||||||
|
|
||||||
function write(sText)
|
|
||||||
expect(1, sText, "string", "number")
|
|
||||||
|
|
||||||
local w, h = term.getSize()
|
|
||||||
local x, y = term.getPos()
|
|
||||||
|
|
||||||
local nLinesPrinted = 0
|
|
||||||
local function newLine()
|
|
||||||
if y + 1 <= h then
|
|
||||||
term.setPos(1, y + 1)
|
|
||||||
else
|
|
||||||
term.setPos(1, h)
|
|
||||||
term.scroll(1)
|
|
||||||
end
|
|
||||||
x, y = term.getPos()
|
|
||||||
nLinesPrinted = nLinesPrinted + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Print the line with proper word wrapping
|
|
||||||
sText = tostring(sText)
|
|
||||||
while #sText > 0 do
|
|
||||||
local whitespace = string.match(sText, "^[ \t]+")
|
|
||||||
if whitespace then
|
|
||||||
-- Print whitespace
|
|
||||||
term.write(whitespace)
|
|
||||||
x, y = term.getPos()
|
|
||||||
sText = string.sub(sText, #whitespace + 1)
|
|
||||||
end
|
|
||||||
|
|
||||||
local newline = string.match(sText, "^\n")
|
|
||||||
if newline then
|
|
||||||
-- Print newlines
|
|
||||||
newLine()
|
|
||||||
sText = string.sub(sText, 2)
|
|
||||||
end
|
|
||||||
|
|
||||||
local text = string.match(sText, "^[^ \t\n]+")
|
|
||||||
if text then
|
|
||||||
sText = string.sub(sText, #text + 1)
|
|
||||||
if #text > w then
|
|
||||||
-- Print a multiline word
|
|
||||||
while #text > 0 do
|
|
||||||
if x > w then
|
|
||||||
newLine()
|
|
||||||
end
|
|
||||||
term.write(text)
|
|
||||||
text = string.sub(text, w - x + 2)
|
|
||||||
x, y = term.getPos()
|
|
||||||
end
|
|
||||||
else
|
|
||||||
-- Print a word normally
|
|
||||||
if x + #text - 1 > w then
|
|
||||||
newLine()
|
|
||||||
end
|
|
||||||
term.write(text)
|
|
||||||
x, y = term.getPos()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return nLinesPrinted
|
|
||||||
end
|
|
||||||
|
|
||||||
function print(...)
|
|
||||||
local nLinesPrinted = 0
|
|
||||||
local nLimit = select("#", ...)
|
|
||||||
for n = 1, nLimit do
|
|
||||||
local s = tostring(select(n, ...))
|
|
||||||
if n < nLimit then
|
|
||||||
s = s .. "\t"
|
|
||||||
end
|
|
||||||
nLinesPrinted = nLinesPrinted + write(s)
|
|
||||||
end
|
|
||||||
nLinesPrinted = nLinesPrinted + write("\n")
|
|
||||||
return nLinesPrinted
|
|
||||||
end
|
|
||||||
|
|
||||||
function read(_sReplaceChar, _tHistory, _fnComplete, _sDefault)
|
|
||||||
expect(1, _sReplaceChar, "string", "nil")
|
|
||||||
expect(2, _tHistory, "table", "nil")
|
|
||||||
expect(3, _fnComplete, "function", "nil")
|
|
||||||
expect(4, _sDefault, "string", "nil")
|
|
||||||
|
|
||||||
term.setBlink(true)
|
|
||||||
|
|
||||||
local sLine
|
|
||||||
if type(_sDefault) == "string" then
|
|
||||||
sLine = _sDefault
|
|
||||||
else
|
|
||||||
sLine = ""
|
|
||||||
end
|
|
||||||
local nHistoryPos
|
|
||||||
local nPos, nScroll = #sLine, 0
|
|
||||||
if _sReplaceChar then
|
|
||||||
_sReplaceChar = string.sub(_sReplaceChar, 1, 1)
|
|
||||||
end
|
|
||||||
|
|
||||||
local tCompletions
|
|
||||||
local nCompletion
|
|
||||||
local function recomplete()
|
|
||||||
if _fnComplete and nPos == #sLine then
|
|
||||||
tCompletions = _fnComplete(sLine)
|
|
||||||
if tCompletions and #tCompletions > 0 then
|
|
||||||
nCompletion = 1
|
|
||||||
else
|
|
||||||
nCompletion = nil
|
|
||||||
end
|
|
||||||
else
|
|
||||||
tCompletions = nil
|
|
||||||
nCompletion = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function uncomplete()
|
|
||||||
tCompletions = nil
|
|
||||||
nCompletion = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local w = term.getSize()
|
|
||||||
local sx = term.getPos()
|
|
||||||
|
|
||||||
local function redraw(_bClear)
|
|
||||||
local cursor_pos = nPos - nScroll
|
|
||||||
if sx + cursor_pos >= w then
|
|
||||||
-- We've moved beyond the RHS, ensure we're on the edge.
|
|
||||||
nScroll = sx + nPos - w
|
|
||||||
elseif cursor_pos < 0 then
|
|
||||||
-- We've moved beyond the LHS, ensure we're on the edge.
|
|
||||||
nScroll = nPos
|
|
||||||
end
|
|
||||||
|
|
||||||
local _, cy = term.getPos()
|
|
||||||
term.setPos(sx, cy)
|
|
||||||
local sReplace = _bClear and " " or _sReplaceChar
|
|
||||||
if sReplace then
|
|
||||||
term.write(string.rep(sReplace, math.max(#sLine - nScroll, 0)))
|
|
||||||
else
|
|
||||||
term.write(string.sub(sLine, nScroll + 1))
|
|
||||||
end
|
|
||||||
|
|
||||||
if nCompletion then
|
|
||||||
local sCompletion = tCompletions[nCompletion]
|
|
||||||
local oldText, oldBg
|
|
||||||
if not _bClear then
|
|
||||||
oldText = term.getForeground()
|
|
||||||
oldBg = term.getBackground()
|
|
||||||
term.setForeground(colors.white)
|
|
||||||
term.setBackground(colors.gray)
|
|
||||||
end
|
|
||||||
if sReplace then
|
|
||||||
term.write(string.rep(sReplace, #sCompletion))
|
|
||||||
else
|
|
||||||
term.write(sCompletion)
|
|
||||||
end
|
|
||||||
if not _bClear then
|
|
||||||
term.setForeground(oldText)
|
|
||||||
term.setBackground(oldBg)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
term.setPos(sx + nPos - nScroll, cy)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function clear()
|
|
||||||
redraw(true)
|
|
||||||
end
|
|
||||||
|
|
||||||
recomplete()
|
|
||||||
redraw()
|
|
||||||
|
|
||||||
local function acceptCompletion()
|
|
||||||
if nCompletion then
|
|
||||||
-- Clear
|
|
||||||
clear()
|
|
||||||
|
|
||||||
-- Find the common prefix of all the other suggestions which start with the same letter as the current one
|
|
||||||
local sCompletion = tCompletions[nCompletion]
|
|
||||||
sLine = sLine .. sCompletion
|
|
||||||
nPos = #sLine
|
|
||||||
|
|
||||||
-- Redraw
|
|
||||||
recomplete()
|
|
||||||
redraw()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
while true do
|
|
||||||
local sEvent, param, param1, param2 = event.pull()
|
|
||||||
if sEvent == "char" then
|
|
||||||
-- Typed key
|
|
||||||
clear()
|
|
||||||
sLine = string.sub(sLine, 1, nPos) .. param .. string.sub(sLine, nPos + 1)
|
|
||||||
nPos = nPos + 1
|
|
||||||
recomplete()
|
|
||||||
redraw()
|
|
||||||
|
|
||||||
elseif sEvent == "paste" then
|
|
||||||
-- Pasted text
|
|
||||||
clear()
|
|
||||||
sLine = string.sub(sLine, 1, nPos) .. param .. string.sub(sLine, nPos + 1)
|
|
||||||
nPos = nPos + #param
|
|
||||||
recomplete()
|
|
||||||
redraw()
|
|
||||||
|
|
||||||
elseif sEvent == "key_down" then
|
|
||||||
if param1 == "enter" then
|
|
||||||
-- Enter/Numpad Enter
|
|
||||||
if nCompletion then
|
|
||||||
clear()
|
|
||||||
uncomplete()
|
|
||||||
redraw()
|
|
||||||
end
|
|
||||||
break
|
|
||||||
|
|
||||||
elseif param1 == "left" then
|
|
||||||
-- Left
|
|
||||||
if nPos > 0 then
|
|
||||||
clear()
|
|
||||||
nPos = nPos - 1
|
|
||||||
recomplete()
|
|
||||||
redraw()
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif param1 == "right" then
|
|
||||||
-- Right
|
|
||||||
if nPos < #sLine then
|
|
||||||
-- Move right
|
|
||||||
clear()
|
|
||||||
nPos = nPos + 1
|
|
||||||
recomplete()
|
|
||||||
redraw()
|
|
||||||
else
|
|
||||||
-- Accept autocomplete
|
|
||||||
acceptCompletion()
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif param1 == "up" or param1 == "down" then
|
|
||||||
-- Up or down
|
|
||||||
if nCompletion then
|
|
||||||
-- Cycle completions
|
|
||||||
clear()
|
|
||||||
if param == "up" then
|
|
||||||
nCompletion = nCompletion - 1
|
|
||||||
if nCompletion < 1 then
|
|
||||||
nCompletion = #tCompletions
|
|
||||||
end
|
|
||||||
elseif param == "down" then
|
|
||||||
nCompletion = nCompletion + 1
|
|
||||||
if nCompletion > #tCompletions then
|
|
||||||
nCompletion = 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
redraw()
|
|
||||||
|
|
||||||
elseif _tHistory then
|
|
||||||
-- Cycle history
|
|
||||||
clear()
|
|
||||||
if param1 == "up" then
|
|
||||||
-- Up
|
|
||||||
if nHistoryPos == nil then
|
|
||||||
if #_tHistory > 0 then
|
|
||||||
nHistoryPos = #_tHistory
|
|
||||||
end
|
|
||||||
elseif nHistoryPos > 1 then
|
|
||||||
nHistoryPos = nHistoryPos - 1
|
|
||||||
end
|
|
||||||
else
|
|
||||||
-- Down
|
|
||||||
if nHistoryPos == #_tHistory then
|
|
||||||
nHistoryPos = nil
|
|
||||||
elseif nHistoryPos ~= nil then
|
|
||||||
nHistoryPos = nHistoryPos + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if nHistoryPos then
|
|
||||||
sLine = _tHistory[nHistoryPos]
|
|
||||||
nPos, nScroll = #sLine, 0
|
|
||||||
else
|
|
||||||
sLine = ""
|
|
||||||
nPos, nScroll = 0, 0
|
|
||||||
end
|
|
||||||
uncomplete()
|
|
||||||
redraw()
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif param1 == "back" then
|
|
||||||
-- Backspace
|
|
||||||
if nPos > 0 then
|
|
||||||
clear()
|
|
||||||
sLine = string.sub(sLine, 1, nPos - 1) .. string.sub(sLine, nPos + 1)
|
|
||||||
nPos = nPos - 1
|
|
||||||
if nScroll > 0 then nScroll = nScroll - 1 end
|
|
||||||
recomplete()
|
|
||||||
redraw()
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif param1 == "home" then
|
|
||||||
-- Home
|
|
||||||
if nPos > 0 then
|
|
||||||
clear()
|
|
||||||
nPos = 0
|
|
||||||
recomplete()
|
|
||||||
redraw()
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif param1 == "delete" then
|
|
||||||
-- Delete
|
|
||||||
if nPos < #sLine then
|
|
||||||
clear()
|
|
||||||
sLine = string.sub(sLine, 1, nPos) .. string.sub(sLine, nPos + 2)
|
|
||||||
recomplete()
|
|
||||||
redraw()
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif param1 == "end" then
|
|
||||||
-- End
|
|
||||||
if nPos < #sLine then
|
|
||||||
clear()
|
|
||||||
nPos = #sLine
|
|
||||||
recomplete()
|
|
||||||
redraw()
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif param1 == "tab" then
|
|
||||||
-- Tab (accept autocomplete)
|
|
||||||
acceptCompletion()
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif sEvent == "mouse_down" or sEvent == "mouse_drag" and param == 1 then
|
|
||||||
local _, cy = term.getPos()
|
|
||||||
if param1 >= sx and param1 <= w and param2 == cy then
|
|
||||||
-- Ensure we don't scroll beyond the current line
|
|
||||||
nPos = math.min(math.max(nScroll + param1 - sx, 0), #sLine)
|
|
||||||
redraw()
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif sEvent == "term_resize" then
|
|
||||||
-- Terminal resized
|
|
||||||
w = term.getSize()
|
|
||||||
redraw()
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local _, cy = term.getPos()
|
|
||||||
term.setBlink(false)
|
|
||||||
term.setPos(w + 1, cy)
|
|
||||||
print()
|
|
||||||
|
|
||||||
return sLine
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function printError(...)
|
|
||||||
local r, g, b = term.getForeground()
|
|
||||||
term.setForeground(colors.red)
|
|
||||||
print(...)
|
|
||||||
term.setForeground(r, g, b)
|
|
||||||
end
|
|
||||||
|
|
||||||
local tEnv = {
|
|
||||||
["_echo"] = function(...)
|
|
||||||
return ...
|
|
||||||
end,
|
|
||||||
p = function(t, sv)
|
|
||||||
for k, v in pairs(t) do
|
|
||||||
if sv then
|
|
||||||
print(k, v)
|
|
||||||
else
|
|
||||||
print(k, type(v))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
fs = require("fs"),
|
|
||||||
}
|
|
||||||
setmetatable(tEnv, { __index = _ENV })
|
|
||||||
|
|
||||||
local tCommandHistory = {}
|
|
||||||
|
|
||||||
term.setSize(51, 19)
|
|
||||||
|
|
||||||
term.setForeground(colors.yellow)
|
|
||||||
term.setBackground(colors.black)
|
|
||||||
term.clear()
|
|
||||||
term.setPos(1,1)
|
|
||||||
print("Lua prompt")
|
|
||||||
while true do
|
|
||||||
term.setForeground(colors.yellow)
|
|
||||||
write("> ")
|
|
||||||
term.setForeground(colors.white)
|
|
||||||
local s = read(nil, tCommandHistory)
|
|
||||||
if s:match("%S") and tCommandHistory[#tCommandHistory] ~= s then
|
|
||||||
table.insert(tCommandHistory, s)
|
|
||||||
end
|
|
||||||
|
|
||||||
local nForcePrint = 0
|
|
||||||
local func, e = load(s, "=lua", "t", tEnv)
|
|
||||||
local func2 = load("return _echo(" .. s .. ");", "=lua", "t", tEnv)
|
|
||||||
|
|
||||||
if not func then
|
|
||||||
if func2 then
|
|
||||||
func = func2
|
|
||||||
e = nil
|
|
||||||
nForcePrint = 1
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if func2 then
|
|
||||||
func = func2
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if func then
|
|
||||||
local tResults = table.pack(pcall(func))
|
|
||||||
if tResults[1] then
|
|
||||||
local n = 1
|
|
||||||
while n < tResults.n or n <= nForcePrint do
|
|
||||||
local value = tResults[n + 1]
|
|
||||||
print(tostring(value))
|
|
||||||
n = n + 1
|
|
||||||
end
|
|
||||||
else
|
|
||||||
printError(tResults[2])
|
|
||||||
end
|
|
||||||
else
|
|
||||||
printError(e)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
local files = fs.list("/boot")
|
||||||
|
for k, v in ipairs(files) do
|
||||||
|
dofile("/boot/" .. v)
|
||||||
end
|
end
|
283
Capy64/Assets/Lua/lib/io.lua
Normal file
283
Capy64/Assets/Lua/lib/io.lua
Normal file
|
@ -0,0 +1,283 @@
|
||||||
|
local expect = require("expect").expect
|
||||||
|
local event = require("event")
|
||||||
|
local term = require("term")
|
||||||
|
|
||||||
|
local io = {}
|
||||||
|
|
||||||
|
function io.read(_sReplaceChar, _tHistory, _fnComplete, _sDefault)
|
||||||
|
expect(1, _sReplaceChar, "string", "nil")
|
||||||
|
expect(2, _tHistory, "table", "nil")
|
||||||
|
expect(3, _fnComplete, "function", "nil")
|
||||||
|
expect(4, _sDefault, "string", "nil")
|
||||||
|
|
||||||
|
term.setBlink(true)
|
||||||
|
|
||||||
|
local sLine
|
||||||
|
if type(_sDefault) == "string" then
|
||||||
|
sLine = _sDefault
|
||||||
|
else
|
||||||
|
sLine = ""
|
||||||
|
end
|
||||||
|
local nHistoryPos
|
||||||
|
local nPos, nScroll = #sLine, 0
|
||||||
|
if _sReplaceChar then
|
||||||
|
_sReplaceChar = string.sub(_sReplaceChar, 1, 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
local tCompletions
|
||||||
|
local nCompletion
|
||||||
|
local function recomplete()
|
||||||
|
if _fnComplete and nPos == #sLine then
|
||||||
|
tCompletions = _fnComplete(sLine)
|
||||||
|
if tCompletions and #tCompletions > 0 then
|
||||||
|
nCompletion = 1
|
||||||
|
else
|
||||||
|
nCompletion = nil
|
||||||
|
end
|
||||||
|
else
|
||||||
|
tCompletions = nil
|
||||||
|
nCompletion = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function uncomplete()
|
||||||
|
tCompletions = nil
|
||||||
|
nCompletion = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local w = term.getSize()
|
||||||
|
local sx = term.getPos()
|
||||||
|
|
||||||
|
local function redraw(_bClear)
|
||||||
|
local cursor_pos = nPos - nScroll
|
||||||
|
if sx + cursor_pos >= w then
|
||||||
|
-- We've moved beyond the RHS, ensure we're on the edge.
|
||||||
|
nScroll = sx + nPos - w
|
||||||
|
elseif cursor_pos < 0 then
|
||||||
|
-- We've moved beyond the LHS, ensure we're on the edge.
|
||||||
|
nScroll = nPos
|
||||||
|
end
|
||||||
|
|
||||||
|
local _, cy = term.getPos()
|
||||||
|
term.setPos(sx, cy)
|
||||||
|
local sReplace = _bClear and " " or _sReplaceChar
|
||||||
|
if sReplace then
|
||||||
|
term.write(string.rep(sReplace, math.max(#sLine - nScroll, 0)))
|
||||||
|
else
|
||||||
|
term.write(string.sub(sLine, nScroll + 1))
|
||||||
|
end
|
||||||
|
|
||||||
|
if nCompletion then
|
||||||
|
local sCompletion = tCompletions[nCompletion]
|
||||||
|
local oldText, oldBg
|
||||||
|
if not _bClear then
|
||||||
|
oldText = term.getForeground()
|
||||||
|
oldBg = term.getBackground()
|
||||||
|
term.setForeground(colors.white)
|
||||||
|
term.setBackground(colors.gray)
|
||||||
|
end
|
||||||
|
if sReplace then
|
||||||
|
term.write(string.rep(sReplace, #sCompletion))
|
||||||
|
else
|
||||||
|
term.write(sCompletion)
|
||||||
|
end
|
||||||
|
if not _bClear then
|
||||||
|
term.setForeground(oldText)
|
||||||
|
term.setBackground(oldBg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
term.setPos(sx + nPos - nScroll, cy)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function clear()
|
||||||
|
redraw(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
recomplete()
|
||||||
|
redraw()
|
||||||
|
|
||||||
|
local function acceptCompletion()
|
||||||
|
if nCompletion then
|
||||||
|
-- Clear
|
||||||
|
clear()
|
||||||
|
|
||||||
|
-- Find the common prefix of all the other suggestions which start with the same letter as the current one
|
||||||
|
local sCompletion = tCompletions[nCompletion]
|
||||||
|
sLine = sLine .. sCompletion
|
||||||
|
nPos = #sLine
|
||||||
|
|
||||||
|
-- Redraw
|
||||||
|
recomplete()
|
||||||
|
redraw()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
while true do
|
||||||
|
local sEvent, param, param1, param2 = event.pull()
|
||||||
|
if sEvent == "char" then
|
||||||
|
-- Typed key
|
||||||
|
clear()
|
||||||
|
sLine = string.sub(sLine, 1, nPos) .. param .. string.sub(sLine, nPos + 1)
|
||||||
|
nPos = nPos + 1
|
||||||
|
recomplete()
|
||||||
|
redraw()
|
||||||
|
|
||||||
|
elseif sEvent == "paste" then
|
||||||
|
-- Pasted text
|
||||||
|
clear()
|
||||||
|
sLine = string.sub(sLine, 1, nPos) .. param .. string.sub(sLine, nPos + 1)
|
||||||
|
nPos = nPos + #param
|
||||||
|
recomplete()
|
||||||
|
redraw()
|
||||||
|
|
||||||
|
elseif sEvent == "key_down" then
|
||||||
|
if param1 == "enter" then
|
||||||
|
-- Enter/Numpad Enter
|
||||||
|
if nCompletion then
|
||||||
|
clear()
|
||||||
|
uncomplete()
|
||||||
|
redraw()
|
||||||
|
end
|
||||||
|
break
|
||||||
|
|
||||||
|
elseif param1 == "left" then
|
||||||
|
-- Left
|
||||||
|
if nPos > 0 then
|
||||||
|
clear()
|
||||||
|
nPos = nPos - 1
|
||||||
|
recomplete()
|
||||||
|
redraw()
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif param1 == "right" then
|
||||||
|
-- Right
|
||||||
|
if nPos < #sLine then
|
||||||
|
-- Move right
|
||||||
|
clear()
|
||||||
|
nPos = nPos + 1
|
||||||
|
recomplete()
|
||||||
|
redraw()
|
||||||
|
else
|
||||||
|
-- Accept autocomplete
|
||||||
|
acceptCompletion()
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif param1 == "up" or param1 == "down" then
|
||||||
|
-- Up or down
|
||||||
|
if nCompletion then
|
||||||
|
-- Cycle completions
|
||||||
|
clear()
|
||||||
|
if param == "up" then
|
||||||
|
nCompletion = nCompletion - 1
|
||||||
|
if nCompletion < 1 then
|
||||||
|
nCompletion = #tCompletions
|
||||||
|
end
|
||||||
|
elseif param == "down" then
|
||||||
|
nCompletion = nCompletion + 1
|
||||||
|
if nCompletion > #tCompletions then
|
||||||
|
nCompletion = 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
redraw()
|
||||||
|
|
||||||
|
elseif _tHistory then
|
||||||
|
-- Cycle history
|
||||||
|
clear()
|
||||||
|
if param1 == "up" then
|
||||||
|
-- Up
|
||||||
|
if nHistoryPos == nil then
|
||||||
|
if #_tHistory > 0 then
|
||||||
|
nHistoryPos = #_tHistory
|
||||||
|
end
|
||||||
|
elseif nHistoryPos > 1 then
|
||||||
|
nHistoryPos = nHistoryPos - 1
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- Down
|
||||||
|
if nHistoryPos == #_tHistory then
|
||||||
|
nHistoryPos = nil
|
||||||
|
elseif nHistoryPos ~= nil then
|
||||||
|
nHistoryPos = nHistoryPos + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if nHistoryPos then
|
||||||
|
sLine = _tHistory[nHistoryPos]
|
||||||
|
nPos, nScroll = #sLine, 0
|
||||||
|
else
|
||||||
|
sLine = ""
|
||||||
|
nPos, nScroll = 0, 0
|
||||||
|
end
|
||||||
|
uncomplete()
|
||||||
|
redraw()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif param1 == "back" then
|
||||||
|
-- Backspace
|
||||||
|
if nPos > 0 then
|
||||||
|
clear()
|
||||||
|
sLine = string.sub(sLine, 1, nPos - 1) .. string.sub(sLine, nPos + 1)
|
||||||
|
nPos = nPos - 1
|
||||||
|
if nScroll > 0 then nScroll = nScroll - 1 end
|
||||||
|
recomplete()
|
||||||
|
redraw()
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif param1 == "home" then
|
||||||
|
-- Home
|
||||||
|
if nPos > 0 then
|
||||||
|
clear()
|
||||||
|
nPos = 0
|
||||||
|
recomplete()
|
||||||
|
redraw()
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif param1 == "delete" then
|
||||||
|
-- Delete
|
||||||
|
if nPos < #sLine then
|
||||||
|
clear()
|
||||||
|
sLine = string.sub(sLine, 1, nPos) .. string.sub(sLine, nPos + 2)
|
||||||
|
recomplete()
|
||||||
|
redraw()
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif param1 == "end" then
|
||||||
|
-- End
|
||||||
|
if nPos < #sLine then
|
||||||
|
clear()
|
||||||
|
nPos = #sLine
|
||||||
|
recomplete()
|
||||||
|
redraw()
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif param1 == "tab" then
|
||||||
|
-- Tab (accept autocomplete)
|
||||||
|
acceptCompletion()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif sEvent == "mouse_down" or sEvent == "mouse_move" and param == 1 then
|
||||||
|
local _, cy = term.getPos()
|
||||||
|
if param1 >= sx and param1 <= w and param2 == cy then
|
||||||
|
-- Ensure we don't scroll beyond the current line
|
||||||
|
nPos = math.min(math.max(nScroll + param1 - sx, 0), #sLine)
|
||||||
|
redraw()
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif sEvent == "term_resize" then
|
||||||
|
-- Terminal resized
|
||||||
|
w = term.getSize()
|
||||||
|
redraw()
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local _, cy = term.getPos()
|
||||||
|
term.setBlink(false)
|
||||||
|
term.setPos(w + 1, cy)
|
||||||
|
print()
|
||||||
|
|
||||||
|
return sLine
|
||||||
|
end
|
||||||
|
|
||||||
|
return io
|
|
@ -5,6 +5,10 @@ local bootSleep = 2000
|
||||||
local bg = 0x0
|
local bg = 0x0
|
||||||
local fg = 0xffffff
|
local fg = 0xffffff
|
||||||
|
|
||||||
|
term.setForeground(fg)
|
||||||
|
term.setBackground(bg)
|
||||||
|
term.clear()
|
||||||
|
|
||||||
local function sleep(n)
|
local function sleep(n)
|
||||||
local timerId = timer.start(n)
|
local timerId = timer.start(n)
|
||||||
repeat
|
repeat
|
||||||
|
|
|
@ -26,7 +26,8 @@ public class Bios : IPlugin
|
||||||
private EventEmitter _eventEmitter;
|
private EventEmitter _eventEmitter;
|
||||||
private RuntimeInputEvents _runtimeInputEvents;
|
private RuntimeInputEvents _runtimeInputEvents;
|
||||||
private Drawing _drawing;
|
private Drawing _drawing;
|
||||||
private bool CloseRuntime = false;
|
private static bool CloseRuntime = false;
|
||||||
|
private static bool OpenBios = false;
|
||||||
|
|
||||||
public Bios(IGame game)
|
public Bios(IGame game)
|
||||||
{
|
{
|
||||||
|
@ -47,12 +48,18 @@ public class Bios : IPlugin
|
||||||
if (CloseRuntime)
|
if (CloseRuntime)
|
||||||
{
|
{
|
||||||
_runtimeInputEvents.Unregister();
|
_runtimeInputEvents.Unregister();
|
||||||
|
|
||||||
_game.LuaRuntime.Close();
|
_game.LuaRuntime.Close();
|
||||||
|
|
||||||
CloseRuntime = false;
|
CloseRuntime = false;
|
||||||
|
|
||||||
StartLuaOS();
|
if (OpenBios)
|
||||||
|
{
|
||||||
|
OpenBios = false;
|
||||||
|
RunBIOS();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StartLuaOS();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Resume();
|
Resume();
|
||||||
|
@ -150,6 +157,12 @@ public class Bios : IPlugin
|
||||||
_game.Exit();
|
_game.Exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Reboot()
|
||||||
|
{
|
||||||
|
CloseRuntime = true;
|
||||||
|
OpenBios = true;
|
||||||
|
}
|
||||||
|
|
||||||
private int L_OpenDataFolder(IntPtr state)
|
private int L_OpenDataFolder(IntPtr state)
|
||||||
{
|
{
|
||||||
var path = FileSystem.DataPath;
|
var path = FileSystem.DataPath;
|
||||||
|
|
|
@ -20,8 +20,8 @@ namespace Capy64;
|
||||||
|
|
||||||
public class Capy64 : Game, IGame
|
public class Capy64 : Game, IGame
|
||||||
{
|
{
|
||||||
|
public const string Version = "Capy64 a0.0.1";
|
||||||
public Game Game => this;
|
public Game Game => this;
|
||||||
public string Version => "Capy64 a0.0.1";
|
|
||||||
public IList<IPlugin> NativePlugins { get; private set; }
|
public IList<IPlugin> NativePlugins { get; private set; }
|
||||||
public IList<IPlugin> Plugins { get; private set; }
|
public IList<IPlugin> Plugins { get; private set; }
|
||||||
public int Width { get; set; } = 400;
|
public int Width { get; set; } = 400;
|
||||||
|
@ -102,6 +102,8 @@ public class Capy64 : Game, IGame
|
||||||
|
|
||||||
protected override void Initialize()
|
protected override void Initialize()
|
||||||
{
|
{
|
||||||
|
Window.Title = Version;
|
||||||
|
|
||||||
UpdateSize();
|
UpdateSize();
|
||||||
|
|
||||||
Window.AllowUserResizing = false;
|
Window.AllowUserResizing = false;
|
||||||
|
|
|
@ -11,7 +11,6 @@ namespace Capy64;
|
||||||
public interface IGame
|
public interface IGame
|
||||||
{
|
{
|
||||||
Game Game { get; }
|
Game Game { get; }
|
||||||
public string Version { get; }
|
|
||||||
IList<IPlugin> NativePlugins { get; }
|
IList<IPlugin> NativePlugins { get; }
|
||||||
IList<IPlugin> Plugins { get; }
|
IList<IPlugin> Plugins { get; }
|
||||||
GameWindow Window { get; }
|
GameWindow Window { get; }
|
||||||
|
|
|
@ -20,14 +20,43 @@ public class OS : IPlugin
|
||||||
public void LuaInit(Lua state)
|
public void LuaInit(Lua state)
|
||||||
{
|
{
|
||||||
state.GetGlobal("os");
|
state.GetGlobal("os");
|
||||||
|
|
||||||
|
state.PushString("version");
|
||||||
|
state.PushCFunction(L_Version);
|
||||||
|
state.SetTable(-3);
|
||||||
|
|
||||||
state.PushString("shutdown");
|
state.PushString("shutdown");
|
||||||
state.PushCFunction(L_Shutdown);
|
state.PushCFunction(L_Shutdown);
|
||||||
state.SetTable(-3);
|
state.SetTable(-3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int L_Version(IntPtr state)
|
||||||
|
{
|
||||||
|
var L = Lua.FromIntPtr(state);
|
||||||
|
|
||||||
|
L.PushString(Capy64.Version);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
private static int L_Shutdown(IntPtr state)
|
private static int L_Shutdown(IntPtr state)
|
||||||
{
|
{
|
||||||
BIOS.Bios.Shutdown();
|
var L = Lua.FromIntPtr(state);
|
||||||
|
|
||||||
|
var doReboot = false;
|
||||||
|
if (L.IsBoolean(1))
|
||||||
|
{
|
||||||
|
doReboot = L.ToBoolean(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doReboot)
|
||||||
|
{
|
||||||
|
BIOS.Bios.Reboot();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BIOS.Bios.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ public class Runtime
|
||||||
|
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
|
Parent.SetTop(0);
|
||||||
var initContent = File.ReadAllText(Path.Combine(FileSystem.DataPath, "init.lua"));
|
var initContent = File.ReadAllText(Path.Combine(FileSystem.DataPath, "init.lua"));
|
||||||
var status = Thread.LoadString(initContent, "=init.lua");
|
var status = Thread.LoadString(initContent, "=init.lua");
|
||||||
if (status != LuaStatus.OK)
|
if (status != LuaStatus.OK)
|
||||||
|
|
Loading…
Reference in a new issue