v0.10.0 - Added text editor (which took me way too long) and too many other tweaks to name.

This commit is contained in:
TheWahlolly
2025-05-04 15:16:54 +03:00
parent 6b8bee249a
commit 673a0b4a75
19 changed files with 997 additions and 384 deletions
+1 -1
View File
@@ -24,6 +24,6 @@ else
if fs.exists(directory) and fs.isDirectory(directory) or fs.exists(shell.workingDirectory .. directory) and fs.isDirectory(shell.workingDirectory .. directory) then
shell.workingDirectory = directory
else
print("error: no such directory")
print("\27[91mNo such directory.")
end
end
+321
View File
@@ -0,0 +1,321 @@
local args = {...}
local file = args[1]
args = nil
local fs = import("filesystem")
local event = import("event")
local gpu = component.proxy(component.list("gpu")())
local width, height = gpu.getResolution()
local scrollPosX, scrollPosY = 1, 1
local cursorPosX, cursorPosY = 1, 1
local cursorWhite = true
local changesMade = false
local renderBuffer = gpu.allocateBuffer()
local scrollSpeed = 5
--local ocelot = component.proxy(component.list("ocelot")())
local function rawset(x, y, text)
termlib.cursorPosX = x
termlib.cursorPosY = y
print(text, false, false)
end
local filestring, filepath, handle, data, tmpdata
if file then
if file:sub(1, 1) == "/" then
filepath = file
else
filepath = shell.workingDirectory .. file
end
handle, data, tmpdata = fs.open(filepath, "r"), "", nil
if fs.exists(filepath) then
filestring = filepath
repeat
tmpdata = handle:read(math.huge)
data = data .. (tmpdata or "")
until not tmpdata
tmpdata = {}
if data:gmatch("(.-)\n")() then
for line in data:gmatch("(.-)\n") do
local newLine = line:gsub("\r", "") -- this took me SO LONG TO FIGURE OUT AAAAAAAA I HATE CRLF I HATE CRLF I HATE CRLF
table.insert(tmpdata, newLine)
end
else
tmpdata = {data}
end
else
filepath = shell.workingDirectory .. file
filestring = "[NEW FILE]"
tmpdata = {""}
end
else
filepath = ""
filestring = "[NEW FILE]"
tmpdata = {""}
end
local function render()
gpu.setActiveBuffer(renderBuffer)
clear()
local realCursorX = math.min(cursorPosX, unicode.wlen(tmpdata[cursorPosY]) - scrollPosX + 2)
if realCursorX < 1 then
scrollPosX = scrollPosX + realCursorX - 1
cursorPosX = 1
realCursorX = math.min(cursorPosX, unicode.wlen(tmpdata[cursorPosY]) - scrollPosX + 2)
end
for i = scrollPosY, height + scrollPosY - 3 do
rawset(1, i - scrollPosY + 1, (tmpdata[i] or ""):sub(scrollPosX))
end
rawset(1, height - 1, "\27[107m\27[30m" .. filestring .. string.rep(" ", width))
rawset(1, height, "\27[107m\27[30m^X\27[0m Exit \27[107m\27[30m^S\27[0m Save" .. string.rep(" ", width))
local char = gpu.get(realCursorX, cursorPosY)
if cursorWhite then
rawset(realCursorX, cursorPosY, "\27[107m\27[30m" .. char .. "\27[0m")
else
rawset(realCursorX, cursorPosY, char)
end
gpu.bitblt()
gpu.setActiveBuffer(0)
end
local renderFlag, cursorRenderFlag = false, false
local function scrollUp()
cursorPosY = cursorPosY - 1
cursorRenderFlag = true
cursorWhite = true
if cursorPosY < 1 then
renderFlag = true
scrollPosY = scrollPosY - 1
cursorPosY = 1
end
if scrollPosY < 1 then
renderFlag = false
scrollPosY = 1
end
if math.min(cursorPosX, unicode.wlen(tmpdata[cursorPosY]) - scrollPosX + 2) < 1 then
renderFlag = true
end
end
local function scrollDown()
cursorPosY = cursorPosY + 1
cursorRenderFlag = true
cursorWhite = true
if cursorPosY + scrollPosY - 1 > #tmpdata then
renderFlag = false
cursorPosY = #tmpdata - scrollPosY + 1
end
if cursorPosY > height - 2 then
renderFlag = true
scrollPosY = scrollPosY + 1
cursorPosY = height - 2
end
if math.min(cursorPosX, unicode.wlen(tmpdata[cursorPosY]) - scrollPosX + 2) < 1 then
renderFlag = true
end
end
local function scrollLeft()
cursorRenderFlag = true
cursorWhite = true
if cursorPosX > 1 then
if cursorPosX <= unicode.wlen(tmpdata[cursorPosY]) - scrollPosX + 2 then
cursorPosX = cursorPosX - 1
elseif unicode.wlen(tmpdata[cursorPosY]) - scrollPosX + 1 > 1 then
cursorPosX = unicode.wlen(tmpdata[cursorPosY]) - scrollPosX + 1
end
elseif scrollPosX > 1 then
scrollPosX = scrollPosX - 1
renderFlag = true
end
if math.min(cursorPosX, unicode.wlen(tmpdata[cursorPosY]) - scrollPosX + 2) < 1 then
renderFlag = true
end
end
local function scrollRight()
cursorRenderFlag = true
cursorWhite = true
if cursorPosX <= unicode.wlen(tmpdata[cursorPosY]) - scrollPosX + 1 then
cursorPosX = cursorPosX + 1
end
if cursorPosX > width then
cursorPosX = width
scrollPosX = scrollPosX + 1
renderFlag = true
end
end
local function processEvent(args)
renderFlag, cursorRenderFlag = false, false
if args[1] == "key_down" then
local keycode = args[4]
local key = keyboard.keys[keycode]
if keyboard.ctrlDown then
return false, false, key
end
if key == "down" and cursorPosY < #tmpdata then
scrollDown()
end
if key == "up" then
scrollUp()
end
if key == "left" then
scrollLeft()
end
if key == "right" then
scrollRight()
end
if key == "enter" then
changesMade = true
renderFlag = true
cursorWhite = true
table.insert(tmpdata, cursorPosY + 1, tmpdata[cursorPosY]:sub(cursorPosX))
tmpdata[cursorPosY] = tmpdata[cursorPosY]:sub(1, cursorPosX - 1)
cursorPosX = 1
cursorPosY = cursorPosY + 1
scrollPosX = 1
if cursorPosY > height - 2 then
scrollPosY = scrollPosY + 1
cursorPosY = height - 2
end
end
if key == "back" then
changesMade = true
cursorRenderFlag = true
cursorWhite = true
if cursorPosY + scrollPosY - 1 > 1 then
cursorPosY = cursorPosY - 1
if cursorPosY < 1 then
scrollPosY = scrollPosY - 1
cursorPosY = 1
end
if scrollPosY < 1 then
scrollPosY = 1
end
cursorPosX = unicode.wlen(tmpdata[cursorPosY]) - scrollPosX + 2
if cursorPosX > width then
scrollPosX = cursorPosX - width + 1
cursorPosX = width
end
tmpdata[cursorPosY] = tmpdata[cursorPosY] .. tmpdata[cursorPosY + 1]
table.remove(tmpdata, cursorPosY + 1)
renderFlag = true
else
tmpdata[cursorPosY] = tmpdata[cursorPosY]:sub(1, cursorPosX + scrollPosX - 3) .. tmpdata[cursorPosY]:sub(cursorPosX + scrollPosX - 1)
cursorPosX = math.min(cursorPosX - 1, unicode.wlen(tmpdata[cursorPosY]) + 1)
if cursorPosX < 1 then
cursorPosX = 1
scrollPosX = scrollPosX - 1
renderFlag = true
else
rawset(1, cursorPosY - scrollPosY + 1, tmpdata[cursorPosY]:sub(scrollPosX) .. " ")
end
end
end
if args[3] >= 32 and args[3] <= 126 then
changesMade = true
cursorRenderFlag = true
cursorWhite = true
tmpdata[cursorPosY] = tmpdata[cursorPosY]:sub(1, cursorPosX + scrollPosX - 2) .. unicode.char(args[3]) .. tmpdata[cursorPosY]:sub(cursorPosX + scrollPosX - 1)
cursorPosX = math.min(cursorPosX, unicode.wlen(tmpdata[cursorPosY])) + 1
--ocelot.log(tostring(cursorPosX))
if cursorPosX > width then
cursorPosX = width
scrollPosX = scrollPosX + 1
renderFlag = true
else
rawset(1, cursorPosY - scrollPosY + 1, tmpdata[cursorPosY]:sub(scrollPosX))
end
end
elseif args[1] == "scroll" then
if args[5] == 1 then
for i = 1, scrollSpeed do
scrollUp()
end
elseif args[5] == -1 and cursorPosY < #tmpdata then
for i = 1, scrollSpeed do
scrollDown()
end
end
end
return renderFlag, cursorRenderFlag
end
local function save()
rawset(1, height - 1, "\27[107m\27[30m" .. string.rep(" ", width))
termlib.cursorPosX = 1
termlib.cursorPosY = height - 1
local savepath = read(nil, "\27[107m\27[30mSave location: ", filepath)
if fs.exists(savepath) then
rawset(1, height - 1, "\27[107m\27[30m" .. string.rep(" ", width))
local answer = read(nil, "\27[107m\27[30mFile already exists. Overwrite it? [Y/n] ")
if answer:lower() == "n" then
rawset(1, height - 1, "\27[107m\27[30m" .. filestring .. string.rep(" ", width))
return
end
end
local handle, errorMessage = fs.open(savepath, "w")
if handle then
handle:write(table.concat(tmpdata, "\n"))
handle:close()
rawset(1, height - 1, "\27[107m\27[30m" .. filestring .. string.rep(" ", width))
else
rawset(1, height - 1, "\27[107m\27[30mERROR: " .. errorMessage:gsub("\n", "") .. string.rep(" ", width))
end
changesMade = false
end
render()
while true do
local args = {event.pull(0.5)}
local renderFlag, cursorRenderFlag, specialKey = false, false, nil
local previousCursorX, previousCursorY = math.min(cursorPosX, unicode.wlen(tmpdata[cursorPosY]) - scrollPosX + 2), cursorPosY
if args and args[1] then
cursorWhite = true
renderFlag, cursorRenderFlag, specialKey = processEvent(args)
if specialKey == "x" then
if changesMade then
termlib.cursorPosX = 1
termlib.cursorPosY = height - 1
local response = read(nil, "\27[107m\27[30mWould you like to save changes? [Y/n] ")
if response:lower() ~= "n" then
save()
end
end
gpu.freeAllBuffers()
clear()
return
end
if specialKey == "s" then
save()
end
repeat
args = {event.pull("key_down", 0)}
if args and args[1] then
processEvent(args)
end
until not args or not args[1]
else
cursorWhite = not cursorWhite
cursorRenderFlag = true
end
if cursorRenderFlag then
local char = gpu.get(previousCursorX, previousCursorY)
rawset(previousCursorX, previousCursorY, char)
local realCursorX = math.min(cursorPosX, unicode.wlen(tmpdata[cursorPosY]) - scrollPosX + 2)
if realCursorX < 1 then
scrollPosX = scrollPosX + realCursorX - 1
cursorPosX = 1
realCursorX = math.min(cursorPosX, unicode.wlen(tmpdata[cursorPosY]) - scrollPosX + 2)
end
local char = gpu.get(realCursorX, cursorPosY)
if cursorWhite then
rawset(realCursorX, cursorPosY, "\27[107m\27[30m" .. char .. "\27[0m")
else
rawset(realCursorX, cursorPosY, char)
end
end
if renderFlag then
render()
end
end
+12
View File
@@ -21,6 +21,18 @@ if fs.exists("/halyde/apps/helpdb/" .. command .. ".txt") then
data = data .. (tmpdata or "")
until not tmpdata
print(data)
local aliases = table.copy(shell.aliases)
if table.find(aliases, command) then
local aliasIndex = table.find(aliases, command)
local aliasString = "Aliases:\n " .. aliasIndex
aliases[aliasIndex] = nil
while table.find(aliases, command) do
aliasIndex = table.find(aliases, command)
aliasString = aliasString .. ", " .. aliasIndex
aliases[aliasIndex] = nil
end
print(aliasString)
end
else
print("Could not find help file for: " .. command .. ".")
end
+3
View File
@@ -13,3 +13,6 @@ All current Halyde shell commands:
You can get additional information on any app or command by running:
help [COMMAND]
In the help documentation, an asterisk (*) next to an argument means it is optional.
This is excluding flags, which are all optional.
+1 -1
View File
@@ -1,7 +1,7 @@
Usage: help [COMMAND]
Displays info on the command specified, or a list of commands if one is not specified.
COMMAND Command to display information on.
COMMAND* Command to display information on.
Examples:
help Displays a list of all default commands available.
+1 -1
View File
@@ -2,7 +2,7 @@ Usage: ls [PATH]
Lists all files and directories in the specified path, or in the shell working directory if the path isn't specified.
Directories are shown in yellow, executable files are shown in green, and other files are shown in white.
PATH Path to the folder to list files and directories from.
PATH* Path to the folder to list files and directories from.
Examples:
ls Lists all files and directories from the current shell working directory.
+1 -1
View File
@@ -7,4 +7,4 @@ Removes files and directories.
Examples:
rm a.txt Removes a.txt in the current shell working directory.
rm -r -f /halyde/core/ Removes everything in /halyde/core forcedly and recursively. Note that trying this on a real machine will remove critical Halyde system files and cause it to stop working.
rm -r -f /halyde/core/ Removes everything in /halyde/core/ forcedly and recursively.
+137
View File
@@ -0,0 +1,137 @@
local raster = import("raster")
local event = import("event")
-- Initialize the 3D renderer for a spinning cube
-- Using the raster library for drawing
-- Screen dimensions
local SCREEN_WIDTH, SCREEN_HEIGHT = component.invoke(component.list("gpu")(), "getResolution")
SCREEN_WIDTH, SCREEN_HEIGHT = SCREEN_WIDTH * 2, SCREEN_HEIGHT * 4
local CENTER_X = SCREEN_WIDTH / 2
local CENTER_Y = SCREEN_HEIGHT / 2
-- Cube properties
local CUBE_SIZE = 10
local increment = 0
local WHITE = 0xFFFFFF
local ROTATION_SPEED = 0.1
-- 3D cube vertices (centered at origin)
local vertices = {
{-CUBE_SIZE, -CUBE_SIZE, -CUBE_SIZE}, -- 0: left bottom back
{CUBE_SIZE, -CUBE_SIZE, -CUBE_SIZE}, -- 1: right bottom back
{CUBE_SIZE, CUBE_SIZE, -CUBE_SIZE}, -- 2: right top back
{-CUBE_SIZE, CUBE_SIZE, -CUBE_SIZE}, -- 3: left top back
{-CUBE_SIZE, -CUBE_SIZE, CUBE_SIZE}, -- 4: left bottom front
{CUBE_SIZE, -CUBE_SIZE, CUBE_SIZE}, -- 5: right bottom front
{CUBE_SIZE, CUBE_SIZE, CUBE_SIZE}, -- 6: right top front
{-CUBE_SIZE, CUBE_SIZE, CUBE_SIZE} -- 7: left top front
}
-- Cube edges defined by vertex indices
local edges = {
{0, 1}, {1, 2}, {2, 3}, {3, 0}, -- back face
{4, 5}, {5, 6}, {6, 7}, {7, 4}, -- front face
{0, 4}, {1, 5}, {2, 6}, {3, 7} -- connecting edges
}
-- Projection parameters
local FOV = 256 -- Field of view (distance from camera to screen)
local Z_OFFSET = 300 -- Distance from camera to cube center
-- Initialize rotation angles
local angleX, angleY, angleZ = 0, 0, 0
-- Matrix multiplication function (apply rotation to a 3D point)
local function rotatePoint(x, y, z)
-- Rotation around X axis
local cosX, sinX = math.cos(angleX), math.sin(angleX)
local y1 = y * cosX - z * sinX
local z1 = y * sinX + z * cosX
-- Rotation around Y axis
local cosY, sinY = math.cos(angleY), math.sin(angleY)
local x1 = x * cosY + z1 * sinY
local z2 = -x * sinY + z1 * cosY
-- Rotation around Z axis
local cosZ, sinZ = math.cos(angleZ), math.sin(angleZ)
local x2 = x1 * cosZ - y1 * sinZ
local y2 = x1 * sinZ + y1 * cosZ
return x2, y2, z2
end
-- Perspective projection function (3D to 2D)
local function projectPoint(x, y, z)
-- Apply perspective projection
local scale = FOV / (z + Z_OFFSET)
local x2d = x * scale + CENTER_X
local y2d = y * scale + CENTER_Y
return x2d, y2d
end
-- Render a single frame
local function renderFrame()
increment = increment + 0.05
CUBE_SIZE = (math.sin(increment) + 1) * 25
vertices = {
{-CUBE_SIZE, -CUBE_SIZE, -CUBE_SIZE}, -- 0: left bottom back
{CUBE_SIZE, -CUBE_SIZE, -CUBE_SIZE}, -- 1: right bottom back
{CUBE_SIZE, CUBE_SIZE, -CUBE_SIZE}, -- 2: right top back
{-CUBE_SIZE, CUBE_SIZE, -CUBE_SIZE}, -- 3: left top back
{-CUBE_SIZE, -CUBE_SIZE, CUBE_SIZE}, -- 4: left bottom front
{CUBE_SIZE, -CUBE_SIZE, CUBE_SIZE}, -- 5: right bottom front
{CUBE_SIZE, CUBE_SIZE, CUBE_SIZE}, -- 6: right top front
{-CUBE_SIZE, CUBE_SIZE, CUBE_SIZE} -- 7: left top front
}
-- Update rotation angles
raster.clear()
angleX = angleX + ROTATION_SPEED
angleY = angleY + ROTATION_SPEED * 0.7
angleZ = angleZ + ROTATION_SPEED * 0.5
-- Project all vertices
local projectedPoints = {}
for i, vertex in ipairs(vertices) do
-- Rotate the point
local x, y, z = rotatePoint(vertex[1], vertex[2], vertex[3])
-- Project the point to 2D
local x2d, y2d = projectPoint(x, y, z)
projectedPoints[i] = {x2d, y2d}
end
-- Draw all edges
for _, edge in ipairs(edges) do
local p1 = projectedPoints[edge[1] + 1] -- +1 because Lua indices start at 1
local p2 = projectedPoints[edge[2] + 1]
-- Draw the line
raster.drawLine(p1[1], p1[2], p2[1], p2[2], WHITE)
end
-- Render the frame
raster.update()
end
-- Main program
function main()
-- Initialize raster engine
raster.init()
-- Main loop (assume this is called repeatedly by the host environment)
while true do
renderFrame()
if event.pull("key_down", 0) then
raster.free()
break
end
end
-- Return a reference to renderFrame so it can be called for animation
return renderFrame
end
-- Start the program
return main()
+3
View File
@@ -9,8 +9,11 @@ local shellcfg = {
["rename"] = "mv",
["ren"] = "mv",
["dir"] = "ls",
["list"] = "ls",
["man"] = "help",
["del"] = "rm",
["delete"] = "rm",
["remove"] = "rm",
[".."] = "cd .."
}, ["defaultWorkingDirectory"] = "/home/" -- the working directory that gets set when halyde starts
}
+1 -1
View File
@@ -1,7 +1,7 @@
local loadfile = ...
local filesystem = loadfile("/halyde/lib/filesystem.lua")(loadfile)
_G._OSVERSION = "Halyde 0.9.0"
_G._OSVERSION = "Halyde 0.10.0"
function _G.import(module, ...)
local args = table.pack(...)
+24 -5
View File
@@ -4,10 +4,25 @@ _G.cormgr.corList = {}
--local ocelot = component.proxy(component.list("ocelot")())
local filesystem = import("filesystem")
local gpu = component.proxy(component.list("gpu")())
function _G.cormgr.loadCoroutine(path)
function _G.cormgr.loadCoroutine(path, ...)
local args = {...}
local cor = coroutine.create(function()
import(path)
local result, errorMessage = xpcall(function(...)
import(...)
end, function(errorMessage)
return errorMessage .. "\n \n" .. debug.traceback()
end, path, table.unpack(args))
if not result then
if print then
gpu.freeAllBuffers()
print("\n\27[91m" .. errorMessage)
else
error(errorMessage)
end
end
--import(path, table.unpack(args))
end)
table.insert(_G.cormgr.corList, cor)
end
@@ -22,17 +37,21 @@ end
local function runCoroutines()
for i = 1, #_G.cormgr.corList do
local result, errorMessage = coroutine.resume(_G.cormgr.corList[i])
if cormgr.corList[i] then
local result, errorMessage = coroutine.resume(cormgr.corList[i])
if cormgr.corList[i] then
if not result then
handleError(errorMessage)
end
if coroutine.status(_G.cormgr.corList[i]) == "dead" then
table.remove(_G.cormgr.corList, i)
if coroutine.status(cormgr.corList[i]) == "dead" then
table.remove(cormgr.corList, i)
i = i - 1
end
--computer.pullSignal(0)
--coroutine.yield()
end
end
end
end
local handle = filesystem.open("/halyde/config/startupapps.cfg", "r")
+27
View File
@@ -2,6 +2,9 @@ _G.evmgr = {}
_G.evmgr.eventQueue = {}
local maxEventQueueLength = 10 -- increase if events start getting dropped
keyboard.ctrlDown = false
keyboard.altDown = false
--local ocelot = component.proxy(component.list("ocelot")())
while true do
@@ -11,6 +14,30 @@ while true do
if args and args[1] then
--ocelot.log("Sending signal "..args..","..computer.uptime())
table.insert(evmgr.eventQueue, args)
if keyboard then
if args[1] == "key_down" then
local keycode = args[4]
local key = keyboard.keys[keycode]
if key == "lcontrol" then
keyboard.ctrlDown = true
elseif key == "lmenu" then
keyboard.altDown = true
elseif key == "c" and keyboard.ctrlDown and keyboard.altDown then
if print then
print("\n\27[91mCoroutine "..tostring(#cormgr.corList).." killed.")
end
cormgr.corList[#cormgr.corList] = nil
end
elseif args[1] == "key_up" then
local keycode = args[4]
local key = keyboard.keys[keycode]
if key == "lcontrol" then
keyboard.ctrlDown = false
elseif key == "lmenu" then
keyboard.altDown = false
end
end
end
while #evmgr.eventQueue > maxEventQueueLength do
--ocelot.log("Queue length breach, removing first signal")
table.remove(evmgr.eventQueue, 1)
+1 -2
View File
@@ -1,5 +1,4 @@
_G.keyboard = {pressedChars = {}, pressedCodes = {}}
_G.keyboard.keys = {}
_G.keyboard = {["keys"] = {}}
keyboard.keys["1"] = 0x02
keyboard.keys["2"] = 0x03
+17 -13
View File
@@ -3,11 +3,22 @@ import("/halyde/core/termlib.lua")
local event = import("event")
--local ocelot = component.proxy(component.list("ocelot")())
local filesystem = import("filesystem")
local gpu = component.proxy(component.list("gpu")())
_G.shell = {}
_G.shell.workingDirectory = shellcfg["defaultWorkingDirectory"]
_G.shell.aliases = shellcfg["aliases"]
local function runAsCoroutine(path, ...)
--ocelot.log("running " .. path .. " as coroutine")
cormgr.loadCoroutine(path, ...)
local corIndex = #cormgr.corList
local cor = cormgr.corList[#cormgr.corList]
repeat
coroutine.yield()
until cormgr.corList[corIndex] ~= cor
end
function _G.shell.run(command)
checkArg(1, command, "string")
if shell.aliases[command:match("[^ ]+")] then
@@ -48,14 +59,14 @@ function _G.shell.run(command)
foundfile = true
local path = args[1]
table.remove(args, 1)
import(path, table.unpack(args))
runAsCoroutine(path, table.unpack(args))
else
for _, item in pairs(shellcfg["path"]) do
if filesystem.exists(item..args[1]) then
foundfile = true
local path = item..args[1]
table.remove(args, 1)
import(path, table.unpack(args))
runAsCoroutine(path, table.unpack(args))
break
else -- try to look for it without the file extension
local files = filesystem.list(item)
@@ -63,15 +74,7 @@ function _G.shell.run(command)
if args[1] == file:match("(.+)%.[^%.]+$") then
foundfile = true
table.remove(args, 1)
local function runCommand()
import(item..file, table.unpack(args))
end
local result, reason = xpcall(runCommand, function(errMsg)
return errMsg .. "\n\n" .. debug.traceback()
end)
if not result then
print("\27[91m" .. reason)
end
runAsCoroutine(item..file, table.unpack(args))
break
end
end
@@ -87,9 +90,10 @@ print(shellcfg["startupMessage"])
while true do
coroutine.yield()
-- print(shell.workingDirectory .. " >")
print(shellcfg["prompt"]:format(shell.workingDirectory),false)
--print(shellcfg["prompt"]:format(shell.workingDirectory),false)
-- termlib.cursorPosX = #(shell.workingDirectory .. " > ")
-- termlib.cursorPosY = termlib.cursorPosY - 1
local shellCommand = read("shell")
local shellCommand = read("shell", shellcfg["prompt"]:format(shell.workingDirectory))
shell.run(shellCommand)
gpu.freeAllBuffers()
end
+37 -26
View File
@@ -1,6 +1,7 @@
local event = import("event")
--local keyboard = import("keyboard")
--local ocelot = component.proxy(component.list("ocelot")())
local gpu = component.proxy(component.list("gpu")()) -- replace with component.gpu once implemented
_G.termlib = {}
termlib.cursorPosX = 1
@@ -41,7 +42,7 @@ gpu.setForeground(defaultForegroundColor)
gpu.setBackground(defaultBackgroundColor)
local function scrollDown()
if gpu.copy(0,1,width,height,0,-1) then
if gpu.copy(1,1,width,height,0,-1) then
local prevForeground = gpu.getForeground()
local prevBackground = gpu.getBackground()
gpu.setForeground(defaultForegroundColor)
@@ -61,7 +62,7 @@ local function newLine()
end
end
function parseCodeNumbers(code)
local function parseCodeNumbers(code)
o = {}
for num in code:sub(3,-2):gmatch("[^;]+") do
table.insert(o,tonumber(num))
@@ -69,13 +70,16 @@ function parseCodeNumbers(code)
return o
end
function _G.print(text,endNewLine)
function _G.print(text, endNewLine, wordWrap)
-- you don't know how tiring this was just for ANSI escape code support
if endNewLine==nil then
if endNewLine == nil then
endNewLine = true
end
if wordWrap == nil then
wordWrap = true
end
if not text or not tostring(text) then
return
@@ -93,7 +97,7 @@ function _G.print(text,endNewLine)
end
gpu.set(termlib.cursorPosX,termlib.cursorPosY,section)
termlib.cursorPosX = termlib.cursorPosX+unicode.wlen(section)
if termlib.cursorPosX>width then
if termlib.cursorPosX>width and wordWrap then
newLine()
end
section=""
@@ -162,13 +166,18 @@ end
function _G.clear()
local xRes, yRes = gpu.getResolution()
gpu.setForeground(defaultForegroundColor)
gpu.setBackground(defaultBackgroundColor)
gpu.fill(1,1,xRes,yRes," ")
termlib.cursorPosX, termlib.cursorPosY = 1, 1
end
function _G.read(readHistoryType)
function _G.read(readHistoryType, prefix, defaultText)
checkArg(1, readHistoryType, "string", "nil")
local curtext = ""
checkArg(2, prefix, "string", "nil")
checkArg(3, defaultText, "string", "nil")
local curtext = defaultText or ""
local prefix = prefix or ""
local RHIndex
if readHistoryType then
if not termlib.readHistory[readHistoryType] then
@@ -179,13 +188,10 @@ function _G.read(readHistoryType)
RHIndex = #termlib.readHistory[readHistoryType] -- read history index
end
local cursorPosX, cursorPosY = termlib.cursorPosX, termlib.cursorPosY
print(prefix .. curtext .. "\27[107m ", false)
local cursorWhite = true
while true do
if cursorWhite then
print("\27[107m ", false)
else
print(" ", false)
end
--ocelot.log(curtext)
termlib.cursorPosX = termlib.cursorPosX - 1
local args = {event.pull("key_down", 0.5)}
if args[4] then
@@ -194,39 +200,34 @@ function _G.read(readHistoryType)
local key = keyboard.keys[keycode]
if key == "up" and readHistoryType then
termlib.cursorPosX, termlib.cursorPosY = cursorPosX, cursorPosY
print(curtext .. " ", false)
print(prefix .. curtext .. " ", false)
RHIndex = RHIndex - 1
if RHIndex <= 0 then
RHIndex = 1
end
termlib.cursorPosX, termlib.cursorPosY = cursorPosX, cursorPosY
print(termlib.readHistory[readHistoryType][RHIndex] .. string.rep(" ", unicode.wlen(curtext) - unicode.wlen(termlib.readHistory[readHistoryType][RHIndex])), false)
print(prefix .. termlib.readHistory[readHistoryType][RHIndex] .. string.rep(" ", unicode.wlen(curtext) - unicode.wlen(termlib.readHistory[readHistoryType][RHIndex])), false)
curtext = termlib.readHistory[readHistoryType][RHIndex]
end
if key == "down" and readHistoryType then
termlib.cursorPosX, termlib.cursorPosY = cursorPosX, cursorPosY
print(curtext .. " ", false)
print(prefix .. curtext .. " ", false)
RHIndex = RHIndex + 1
if RHIndex > #termlib.readHistory[readHistoryType] then
RHIndex = #termlib.readHistory[readHistoryType]
end
termlib.cursorPosX, termlib.cursorPosY = cursorPosX, cursorPosY
print(termlib.readHistory[readHistoryType][RHIndex] .. string.rep(" ", unicode.wlen(curtext) - unicode.wlen(termlib.readHistory[readHistoryType][RHIndex])), false)
print(prefix .. termlib.readHistory[readHistoryType][RHIndex] .. string.rep(" ", unicode.wlen(curtext) - unicode.wlen(termlib.readHistory[readHistoryType][RHIndex])), false)
curtext = termlib.readHistory[readHistoryType][RHIndex]
end
if args[3] >= 32 and args[3] <= 126 then
curtext = curtext .. (unicode.char(args[3]) or "")
if readHistoryType then
termlib.readHistory[readHistoryType][RHIndex] = curtext
end
else
if key == "back" then
curtext = curtext:sub(1, #curtext-1)
termlib.cursorPosX, termlib.cursorPosY = cursorPosX, cursorPosY
print(curtext.." ", false)
elseif key == "enter" then
print(prefix .. curtext.." ", false)
end
if key == "enter" then
termlib.cursorPosX, termlib.cursorPosY = cursorPosX, cursorPosY
print(curtext .. " ")
print(prefix .. curtext .. " ")
if readHistoryType then
while #termlib.readHistory[readHistoryType] > 50 do
table.remove(termlib.readHistory[readHistoryType], 1)
@@ -234,11 +235,21 @@ function _G.read(readHistoryType)
end
return curtext
end
if args[3] >= 32 and args[3] <= 126 then
curtext = curtext .. (unicode.char(args[3]) or "")
if readHistoryType then
termlib.readHistory[readHistoryType][RHIndex] = curtext
end
end
termlib.cursorPosX, termlib.cursorPosY = cursorPosX, cursorPosY
print(curtext, false)
print(prefix .. curtext, false)
else
cursorWhite = not cursorWhite
end
if cursorWhite then
print("\27[107m ", false)
else
print(" ", false)
end
end
end
+6 -1
View File
@@ -48,7 +48,12 @@ function filesystem.open(path, mode) -- opens a file and returns its handle
return nil, "invalid handle type"
end
local address, absPath = filesystem.processPath(path)
local handle = component.invoke(address, "open", absPath, mode)
local handleArgs = {component.invoke(address, "open", absPath, mode)}
local handle = handleArgs[1]
if not handle then
return table.unpack(handleArgs)
end
handleArgs = nil
local properHandle = {}
properHandle.handle = handle
properHandle.address = address
+10 -5
View File
@@ -41,11 +41,8 @@ function raster.init(width, height, bgcolor)
width, height = raster.units.charToBraille(width, height)
bgcolor = bgcolor or raster.defaultBackgroundColor;
bgcolor = bgcolor or raster.defaultBackgroundColor
for i = 1, width*height do
display[i] = bgcolor
end
raster.displayWidth = width
raster.displayHeight = height
@@ -145,10 +142,10 @@ function raster.update()
raster.get(x,y),
raster.get(x,y+1),
raster.get(x,y+2),
raster.get(x,y+3),
raster.get(x+1,y),
raster.get(x+1,y+1),
raster.get(x+1,y+2),
raster.get(x,y+3),
raster.get(x+1,y+3)
}
local colorA = nil
@@ -170,6 +167,14 @@ function raster.update()
end
end
function raster.clear()
if renderBuffer~=nil then
gpu.setActiveBuffer(renderBuffer)
end
clear()
display = {}
end
function raster.free()
if renderBuffer==nil then
return true
+67
View File
@@ -0,0 +1,67 @@
This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file!
This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file!
This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file!
This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file!
This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file!
This is a long line! This is a long line! This is a long line! This is a long line! This is a long line! This is a long line! This is a long line! This is a long line! This is a long line!
This is a longer line! This is a longer line! This is a longer line! This is a longer line! This is a longer line! This is a longer line! This is a longer line! This is a longer line! This is a longer line! This is a longer line! This is a longer line! This is a longer line! This is a longer line! This is a longer line!
This is a short line!
This is a short line!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This has a lot of lines!
This is the last line!