v1.14.0 - Added the download command (Halyde equivalent of wget) and clipboard pasting support.

This commit is contained in:
TheWahlolly
2025-07-02 12:34:14 +03:00
parent 97f411180d
commit fb4c80f3a0
6 changed files with 241 additions and 164 deletions
+3 -1
View File
@@ -1,7 +1,7 @@
local agcfg = { local agcfg = {
["halyde"] = { ["halyde"] = {
["maindir"] = "", ["maindir"] = "",
["version"] = "1.13.0", ["version"] = "1.14.0",
["description"] = "A universal, customizable and feature-packed operating system for OpenComputers.", ["description"] = "A universal, customizable and feature-packed operating system for OpenComputers.",
["directories"] = { ["directories"] = {
"halyde/apps", "halyde/apps",
@@ -20,6 +20,7 @@ local agcfg = {
"halyde/apps/helpdb/clear.txt", "halyde/apps/helpdb/clear.txt",
"halyde/apps/helpdb/cp.txt", "halyde/apps/helpdb/cp.txt",
"halyde/apps/helpdb/default.txt", "halyde/apps/helpdb/default.txt",
"halyde/apps/helpdb/download.txt",
"halyde/apps/helpdb/echo.txt", "halyde/apps/helpdb/echo.txt",
"halyde/apps/helpdb/fetch.txt", "halyde/apps/helpdb/fetch.txt",
"halyde/apps/helpdb/help.txt", "halyde/apps/helpdb/help.txt",
@@ -34,6 +35,7 @@ local agcfg = {
"halyde/apps/cd.lua", "halyde/apps/cd.lua",
"halyde/apps/clear.lua", "halyde/apps/clear.lua",
"halyde/apps/cp.lua", "halyde/apps/cp.lua",
"halyde/apps/download.lua",
"halyde/apps/echo.lua", "halyde/apps/echo.lua",
"halyde/apps/fetch.lua", "halyde/apps/fetch.lua",
"halyde/apps/help.lua", "halyde/apps/help.lua",
+57
View File
@@ -0,0 +1,57 @@
local url = ...
local component = import("component")
local fs = import("filesystem")
if not component.list("internet")() then
print("\27[91mThis program requires an internet card to run.")
return
end
if not url then
print("Please enter a URL to download from.")
shell.run("help download")
return
end
if url:sub(-1, -1) == "/" then
url = url:sub(1, -2)
end
local internet = component.internet
local request, data, tmpdata = nil, "", nil
local status, errorMessage = pcall(function()
request = internet.request(url)
request:finishConnect()
end)
if not status then
print("\27[91mDownload failed: " .. errorMessage)
end
local responseCode = request:response()
if responseCode and responseCode ~= 200 then
print("\27[91mDownload failed: " .. tostring(responseCode))
end
repeat
tmpdata = request.read(math.huge)
data = data .. (tmpdata or "")
until not tmpdata
local saveLocation
local saveLocationOK = false
repeat
saveLocation = read(nil, "File save location: ", fs.concat(shell.workingDirectory, url:match("/([^/]+)$")))
if fs.isDirectory(saveLocation) then
print("\27[91mThe specified location is a directory.")
elseif fs.exists(saveLocation) then
local answer = read(nil, "\27[91mThere is already a file at the specified directory. Overwrite it? [Y/n]")
if answer:lower() ~= "n" then
saveLocationOK = true
end
else
saveLocationOK = true
end
until saveLocationOK
local handle = fs.open(saveLocation, "w")
handle:write(data)
handle:close()
print("File downloaded successfully.")
+1
View File
@@ -4,6 +4,7 @@ All default Halyde shell commands:
cd Changes directory. cd Changes directory.
clear Clears the screen. clear Clears the screen.
cp Copies a file. cp Copies a file.
download Downloads a file from the internet.
echo Prints a message. echo Prints a message.
edit Opens the text editor. edit Opens the text editor.
fetch Displays system information. fetch Displays system information.
+7
View File
@@ -0,0 +1,7 @@
Usage: download [URL]
Downloads a file from the internet.
URL Specifies the URL from which to download the file from.
Examples:
download https://github.com/ Downloads github.com.
+1 -1
View File
@@ -1,7 +1,7 @@
local loadfile = ... local loadfile = ...
local filesystem = loadfile("/halyde/lib/filesystem.lua")(loadfile) local filesystem = loadfile("/halyde/lib/filesystem.lua")(loadfile)
_G._OSVERSION = "Halyde 1.13.0" _G._OSVERSION = "Halyde 1.14.0"
_G._OSLOGO = "" _G._OSLOGO = ""
local handle, tmpdata = filesystem.open("/halyde/config/oslogo.ans", "r"), nil local handle, tmpdata = filesystem.open("/halyde/config/oslogo.ans", "r"), nil
repeat repeat
+172 -162
View File
@@ -188,192 +188,202 @@ function _G.clear()
end end
-- god i hope this silly claude code works first try -- god i hope this silly claude code works first try
-- Fluxdrive caught vibe coding???
function _G.read(readHistoryType, prefix, defaultText) function _G.read(readHistoryType, prefix, defaultText)
checkArg(1, readHistoryType, "string", "nil") checkArg(1, readHistoryType, "string", "nil")
checkArg(2, prefix, "string", "nil") checkArg(2, prefix, "string", "nil")
checkArg(3, defaultText, "string", "nil") checkArg(3, defaultText, "string", "nil")
local curtext = defaultText or "" local curtext = defaultText or ""
local prefix = prefix or "" local prefix = prefix or ""
local textCursorPos = unicode.wlen(curtext) + 1 -- Position within the text (1-based) local textCursorPos = unicode.wlen(curtext) + 1 -- Position within the text (1-based)
local RHIndex local RHIndex
if readHistoryType then if readHistoryType then
if not termlib.readHistory[readHistoryType] then if not termlib.readHistory[readHistoryType] then
termlib.readHistory[readHistoryType] = {curtext} termlib.readHistory[readHistoryType] = {curtext}
elseif termlib.readHistory[readHistoryType][#termlib.readHistory[readHistoryType]] ~= "" then elseif termlib.readHistory[readHistoryType][#termlib.readHistory[readHistoryType]] ~= "" then
table.insert(termlib.readHistory[readHistoryType], curtext) table.insert(termlib.readHistory[readHistoryType], curtext)
end end
RHIndex = #termlib.readHistory[readHistoryType] RHIndex = #termlib.readHistory[readHistoryType]
end
local cursorPosX, cursorPosY = termlib.cursorPosX, termlib.cursorPosY
-- Track maximum text length to ensure proper clearing across wrapped lines
local maxTextLength = unicode.wlen(prefix .. curtext)
-- Function to calculate how many lines text will occupy
local function calculateLines(text)
local totalWidth = unicode.wlen(prefix .. text)
local width = gpu.getResolution()
return math.ceil(totalWidth / width)
end
-- Track maximum lines used
local maxLinesUsed = calculateLines(curtext)
-- Function to redraw the input line with cursor
local function redrawLine()
local startX, startY = cursorPosX, cursorPosY
-- Calculate current and max lines needed
local currentLines = calculateLines(curtext)
local linesToClear = math.max(maxLinesUsed, currentLines)
-- Clear all potentially used lines
for i = 0, linesToClear - 1 do
termlib.cursorPosX, termlib.cursorPosY = 1, startY + i
if startY + i <= height then
local width = gpu.getResolution()
termlib.write(string.rep(" ", width))
end end
end
local cursorPosX, cursorPosY = termlib.cursorPosX, termlib.cursorPosY -- Reset cursor to start position
termlib.cursorPosX, termlib.cursorPosY = startX, startY
-- Track maximum text length to ensure proper clearing across wrapped lines -- Update tracking variables
local maxTextLength = unicode.wlen(prefix .. curtext) maxTextLength = math.max(maxTextLength, unicode.wlen(prefix .. curtext))
maxLinesUsed = math.max(maxLinesUsed, currentLines)
-- Function to calculate how many lines text will occupy -- Draw text with cursor positioned correctly
local function calculateLines(text) local beforeCursor = curtext:sub(1, utf8.offset(curtext, textCursorPos) - 1 or 0)
local totalWidth = unicode.wlen(prefix .. text) local afterCursor = curtext:sub(utf8.offset(curtext, textCursorPos) or (#curtext + 1))
local width = gpu.getResolution()
return math.ceil(totalWidth / width)
end
-- Track maximum lines used termlib.write(prefix .. beforeCursor)
local maxLinesUsed = calculateLines(curtext) termlib.write("\27[30m\27[107m" .. (afterCursor:sub(1, 1) ~= "" and afterCursor:sub(1, 1) or " ") .. "\27[0m") -- HUGE SHOUTOUT TO WAH FOR MAKING THE ESCAPE CODES WORK YEAAAAAAA
termlib.write(afterCursor:sub(2))
end
-- Function to redraw the input line with cursor redrawLine()
local function redrawLine() local cursorWhite = true
local startX, startY = cursorPosX, cursorPosY
-- Calculate current and max lines needed while true do
local currentLines = calculateLines(curtext) local args = {event.pull("key_down", "clipboard", 0.5)}
local linesToClear = math.max(maxLinesUsed, currentLines)
-- Clear all potentially used lines if args[1] == "key_down" and args[4] then
for i = 0, linesToClear - 1 do cursorWhite = true
termlib.cursorPosX, termlib.cursorPosY = 1, startY + i local keycode = args[4]
if startY + i <= height then local key = keyboard.keys[keycode]
local width = gpu.getResolution()
termlib.write(string.rep(" ", width)) -- Handle arrow keys
if key == "up" and readHistoryType then
RHIndex = RHIndex - 1
if RHIndex <= 0 then
RHIndex = 1
end end
curtext = termlib.readHistory[readHistoryType][RHIndex]
textCursorPos = unicode.wlen(curtext) + 1
redrawLine()
elseif key == "down" and readHistoryType then
RHIndex = RHIndex + 1
if RHIndex > #termlib.readHistory[readHistoryType] then
RHIndex = #termlib.readHistory[readHistoryType]
end
curtext = termlib.readHistory[readHistoryType][RHIndex]
textCursorPos = unicode.wlen(curtext) + 1
redrawLine()
elseif key == "left" then
-- Move cursor left
if textCursorPos > 1 then
textCursorPos = textCursorPos - 1
redrawLine()
end end
-- Reset cursor to start position elseif key == "right" then
termlib.cursorPosX, termlib.cursorPosY = startX, startY -- Move cursor right
if textCursorPos <= unicode.wlen(curtext) then
textCursorPos = textCursorPos + 1
redrawLine()
end
-- Update tracking variables elseif key == "home" then
maxTextLength = math.max(maxTextLength, unicode.wlen(prefix .. curtext)) -- Move to beginning of line
maxLinesUsed = math.max(maxLinesUsed, currentLines) textCursorPos = 1
redrawLine()
-- Draw text with cursor positioned correctly elseif key == "end" then
-- Move to end of line
textCursorPos = unicode.wlen(curtext) + 1
redrawLine()
elseif key == "back" then
-- Backspace - delete character before cursor
if textCursorPos > 1 then
local beforeCursor = curtext:sub(1, utf8.offset(curtext, textCursorPos - 1) - 1 or 0)
local afterCursor = curtext:sub(utf8.offset(curtext, textCursorPos) or (#curtext + 1))
curtext = beforeCursor .. afterCursor
textCursorPos = textCursorPos - 1
if readHistoryType then
termlib.readHistory[readHistoryType][RHIndex] = curtext
end
redrawLine()
end
elseif key == "delete" then
-- Delete - delete character at cursor
if textCursorPos <= unicode.wlen(curtext) then
local beforeCursor = curtext:sub(1, utf8.offset(curtext, textCursorPos) - 1 or 0)
local afterCursor = curtext:sub(utf8.offset(curtext, textCursorPos + 1) or (#curtext + 1))
curtext = beforeCursor .. afterCursor
if readHistoryType then
termlib.readHistory[readHistoryType][RHIndex] = curtext
end
redrawLine()
end
elseif key == "enter" then
termlib.cursorPosX, termlib.cursorPosY = cursorPosX, cursorPosY
print(prefix .. curtext .. " ")
if readHistoryType then
while #termlib.readHistory[readHistoryType] > 50 do
table.remove(termlib.readHistory[readHistoryType], 1)
end
end
return curtext
elseif args[3] >= 32 and args[3] <= 126 then
-- Insert character at cursor position
local char = unicode.char(args[3]) or ""
local beforeCursor = curtext:sub(1, utf8.offset(curtext, textCursorPos) - 1 or 0) local beforeCursor = curtext:sub(1, utf8.offset(curtext, textCursorPos) - 1 or 0)
local afterCursor = curtext:sub(utf8.offset(curtext, textCursorPos) or (#curtext + 1)) local afterCursor = curtext:sub(utf8.offset(curtext, textCursorPos) or (#curtext + 1))
curtext = beforeCursor .. char .. afterCursor
termlib.write(prefix .. beforeCursor) textCursorPos = textCursorPos + 1
termlib.write("\27[30m\27[107m" .. (afterCursor:sub(1, 1) ~= "" and afterCursor:sub(1, 1) or " ") .. "\27[0m") -- HUGE SHOUTOUT TO WAH FOR MAKING THE ESCAPE CODES WORK YEAAAAAAA if readHistoryType then
termlib.write(afterCursor:sub(2)) termlib.readHistory[readHistoryType][RHIndex] = curtext
end end
redrawLine() redrawLine()
local cursorWhite = true end
while true do elseif args[1] == "clipboard" then
local args = {event.pull("key_down", "clipboard", 0.5)} -- Handle clipboard paste
local text = args[3] or ""
local beforeCursor = curtext:sub(1, utf8.offset(curtext, textCursorPos) - 1 or 0)
local afterCursor = curtext:sub(utf8.offset(curtext, textCursorPos) or (#curtext + 1))
curtext = beforeCursor .. text .. afterCursor
textCursorPos = textCursorPos + #text
if readHistoryType then
termlib.readHistory[readHistoryType][RHIndex] = curtext
end
redrawLine()
if args[1] == "key_down" and args[4] then else
cursorWhite = true -- Cursor blink timing
local keycode = args[4] cursorWhite = not cursorWhite
local key = keyboard.keys[keycode] if cursorWhite then
redrawLine()
-- Handle arrow keys else
if key == "up" and readHistoryType then -- Show cursor as normal character or space
RHIndex = RHIndex - 1 termlib.cursorPosX, termlib.cursorPosY = cursorPosX, cursorPosY
if RHIndex <= 0 then local beforeCursor = curtext:sub(1, utf8.offset(curtext, textCursorPos) - 1 or 0)
RHIndex = 1 local afterCursor = curtext:sub(utf8.offset(curtext, textCursorPos) or (#curtext + 1))
end termlib.write(prefix .. beforeCursor)
curtext = termlib.readHistory[readHistoryType][RHIndex] termlib.write(afterCursor:sub(1, 1) ~= "" and afterCursor:sub(1, 1) or " ")
textCursorPos = unicode.wlen(curtext) + 1 termlib.write(afterCursor:sub(2))
redrawLine() end
end
elseif key == "down" and readHistoryType then
RHIndex = RHIndex + 1
if RHIndex > #termlib.readHistory[readHistoryType] then
RHIndex = #termlib.readHistory[readHistoryType]
end
curtext = termlib.readHistory[readHistoryType][RHIndex]
textCursorPos = unicode.wlen(curtext) + 1
redrawLine()
elseif key == "left" then
-- Move cursor left
if textCursorPos > 1 then
textCursorPos = textCursorPos - 1
redrawLine()
end
elseif key == "right" then
-- Move cursor right
if textCursorPos <= unicode.wlen(curtext) then
textCursorPos = textCursorPos + 1
redrawLine()
end
elseif key == "home" then
-- Move to beginning of line
textCursorPos = 1
redrawLine()
elseif key == "end" then
-- Move to end of line
textCursorPos = unicode.wlen(curtext) + 1
redrawLine()
elseif key == "back" then
-- Backspace - delete character before cursor
if textCursorPos > 1 then
local beforeCursor = curtext:sub(1, utf8.offset(curtext, textCursorPos - 1) - 1 or 0)
local afterCursor = curtext:sub(utf8.offset(curtext, textCursorPos) or (#curtext + 1))
curtext = beforeCursor .. afterCursor
textCursorPos = textCursorPos - 1
if readHistoryType then
termlib.readHistory[readHistoryType][RHIndex] = curtext
end
redrawLine()
end
elseif key == "delete" then
-- Delete - delete character at cursor
if textCursorPos <= unicode.wlen(curtext) then
local beforeCursor = curtext:sub(1, utf8.offset(curtext, textCursorPos) - 1 or 0)
local afterCursor = curtext:sub(utf8.offset(curtext, textCursorPos + 1) or (#curtext + 1))
curtext = beforeCursor .. afterCursor
if readHistoryType then
termlib.readHistory[readHistoryType][RHIndex] = curtext
end
redrawLine()
end
elseif key == "enter" then
termlib.cursorPosX, termlib.cursorPosY = cursorPosX, cursorPosY
print(prefix .. curtext .. " ")
if readHistoryType then
while #termlib.readHistory[readHistoryType] > 50 do
table.remove(termlib.readHistory[readHistoryType], 1)
end
end
return curtext
elseif args[3] >= 32 and args[3] <= 126 then
-- Insert character at cursor position
local char = unicode.char(args[3]) or ""
local beforeCursor = curtext:sub(1, utf8.offset(curtext, textCursorPos) - 1 or 0)
local afterCursor = curtext:sub(utf8.offset(curtext, textCursorPos) or (#curtext + 1))
curtext = beforeCursor .. char .. afterCursor
textCursorPos = textCursorPos + 1
if readHistoryType then
termlib.readHistory[readHistoryType][RHIndex] = curtext
end
redrawLine()
end
elseif args[1] == "clipboard" then
-- Handle clipboard paste here if needed
else
-- Cursor blink timing
cursorWhite = not cursorWhite
if cursorWhite then
redrawLine()
else
-- Show cursor as normal character or space
termlib.cursorPosX, termlib.cursorPosY = cursorPosX, cursorPosY
local beforeCursor = curtext:sub(1, utf8.offset(curtext, textCursorPos) - 1 or 0)
local afterCursor = curtext:sub(utf8.offset(curtext, textCursorPos) or (#curtext + 1))
termlib.write(prefix .. beforeCursor)
termlib.write(afterCursor:sub(1, 1) ~= "" and afterCursor:sub(1, 1) or " ")
termlib.write(afterCursor:sub(2))
end
end
end end
end end