diff --git a/argentum.cfg b/argentum.cfg index ffb7dcb..1e22b85 100644 --- a/argentum.cfg +++ b/argentum.cfg @@ -1,7 +1,7 @@ local agcfg = { ["halyde"] = { ["maindir"] = "", - ["version"] = "1.15.0", + ["version"] = "2.0.0", ["description"] = "A universal, customizable and feature-packed operating system for OpenComputers.", ["directories"] = { "halyde/apps", @@ -82,7 +82,7 @@ local agcfg = { }, ["edit"] = { ["maindir"] = "", - ["version"] = "1.2.0", + ["version"] = "1.2.1", ["description"] = "The default text editor for Halyde.", ["files"] = { "halyde/apps/edit.lua", diff --git a/halyde/apps/edit.lua b/halyde/apps/edit.lua index f9f2cb9..1f84367 100644 --- a/halyde/apps/edit.lua +++ b/halyde/apps/edit.lua @@ -2,6 +2,7 @@ local file = ... local fs = import("filesystem") local event = import("event") local component = import("component") +local unicode = import("unicode") local gpu = component.gpu local width, height = gpu.getResolution() local scrollPosX, scrollPosY = 1, 1 diff --git a/halyde/apps/ls.lua b/halyde/apps/ls.lua index eafb80d..f7149b8 100644 --- a/halyde/apps/ls.lua +++ b/halyde/apps/ls.lua @@ -2,6 +2,7 @@ local args = {...} local target = args[1] args = nil local fs = import("filesystem") +local unicode = import("unicode") local maxLength = 0 local margin = 2 -- minimum space between filename and size local dirTable = {} diff --git a/halyde/core/boot.lua b/halyde/core/boot.lua index efd382f..c9044f7 100644 --- a/halyde/core/boot.lua +++ b/halyde/core/boot.lua @@ -1,7 +1,7 @@ local loadfile = ... local filesystem = loadfile("/halyde/lib/filesystem.lua")(loadfile) -_G._OSVERSION = "Halyde 1.15.0" +_G._OSVERSION = "Halyde 2.0.0" _G._OSLOGO = "" local handle, tmpdata = filesystem.open("/halyde/config/oslogo.ans", "r"), nil repeat diff --git a/halyde/core/termlib.lua b/halyde/core/termlib.lua index 052b339..238242c 100644 --- a/halyde/core/termlib.lua +++ b/halyde/core/termlib.lua @@ -1,3 +1,4 @@ +local unicode = import("unicode") local event = import("event") --local keyboard = import("keyboard") @@ -86,8 +87,8 @@ function termlib.write(text, textWrap) if text:find("\a") then computer.beep() end - text = "\27[0m" .. text:gsub("\t", " ") text = tostring(text) + text = "\27[0m" .. text:gsub("\t", " ") readBreak = 0 -- readBreak is for when, inside the for loop, there normally would have been an increase in the "i" variable because it has read more than one character. -- unfortunately, changing the "i" variable would have unpredictable effects, so to not risk anything, this workaround was done. @@ -187,203 +188,177 @@ function _G.clear() termlib.cursorPosX, termlib.cursorPosY = 1, 1 end --- 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, maxChars) checkArg(1, readHistoryType, "string", "nil") checkArg(2, prefix, "string", "nil") checkArg(3, defaultText, "string", "nil") - local curtext = defaultText or "" - local prefix = prefix or "" - local textCursorPos = unicode.wlen(curtext) + 1 -- Position within the text (1-based) + checkArg(4, maxChars, "number", "nil") + maxChars = maxChars or math.huge - local RHIndex + local text = defaultText or "" + + local historyIdx if readHistoryType then if not termlib.readHistory[readHistoryType] then - termlib.readHistory[readHistoryType] = {curtext} - elseif termlib.readHistory[readHistoryType][#termlib.readHistory[readHistoryType]] ~= "" then - table.insert(termlib.readHistory[readHistoryType], curtext) + termlib.readHistory[readHistoryType] = {text} + elseif termlib.readHistory[readHistoryType][#termlib.readHistory[readHistoryType] ] ~= "" then + table.insert(termlib.readHistory[readHistoryType], text) end - RHIndex = #termlib.readHistory[readHistoryType] + historyIdx = #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) + local cur = unicode.len(text)+1 + if prefix then termlib.write(prefix) end + local startX, startY = termlib.cursorPosX, termlib.cursorPosY + local fg, bg = gpu.getForeground(), gpu.getBackground() + local cursorBlink = true + local function get(idx) + idx=startX+idx-1 + return gpu.get(idx%width,startY+(idx//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)) + local function checkScroll(y) + for i=1,y-height do + scrollDown() + startY=startY-1 + end + return math.min(y,height) + end + local function set(idx,chr,rev) + if chr==nil or chr=="" then return end + if rev then + gpu.setForeground(bg) + gpu.setBackground(fg) + else + gpu.setForeground(fg) + gpu.setBackground(bg) + end + idx=startX+idx-1 + local setX, setY = (idx-1)%width+1, startY+((idx-1)//width+1)-1 + setY = checkScroll(setY) + gpu.set(setX,setY,unicode.sub(chr,1,width-setX+1)) + for i=1,math.ceil((#chr+setX-1)/width)+1 do + gpu.set(1,setY+i,unicode.sub(chr,2-setX+i*width,width+i*width-setX)) + setY = checkScroll(setY) end end - - -- Reset cursor to start position - termlib.cursorPosX, termlib.cursorPosY = startX, startY - - -- Update tracking variables - maxTextLength = math.max(maxTextLength, unicode.wlen(prefix .. curtext)) - maxLinesUsed = math.max(maxLinesUsed, currentLines) - - -- Draw text with cursor positioned correctly - 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("\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)) + local function strDef(a,b) + if #a==0 then return b end + return a end + local function curPos(cur) + -- component.ocelot.log(table.concat({cur,unicode.wlen(unicode.sub(text,1,cur)),unicode.len(text)}," ")) + return unicode.wlen(unicode.sub(text,1,cur-1))+1 + end + local function add(chr) + if type(chr)~="string" or #chr==0 then return end + if unicode.len(text)>=maxChars then return end + if maxChars1 then + text=unicode.sub(text,1,cur-2)..unicode.sub(text,cur) + cur=cur-1 + set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),true) + cursorBlink = true + set(curPos(cur)+1,unicode.sub(text,cur+1).." ",false) + updateHistory() + elseif key=="delete" then + text = unicode.sub(text,1,cur-1)..unicode.sub(text,cur+1) + set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),true) + cursorBlink = true + if cur<=unicode.len(text) then + set(curPos(cur+1),unicode.sub(text,cur+1).." ",false) 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 - - 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() + updateHistory() + elseif key=="enter" then + set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),false) + break + elseif not (args[3]<32 or (args[3]>0x7F and args[3]<=0x9F)) then + add(unicode.char(args[3]) or " ") + updateHistory() end - - elseif args[1] == "clipboard" then - -- 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() - + elseif args and args[1]=="clipboard" then + local clip = args[3] + if not args[3] then goto continue end + while isLine(unicode.sub(clip,1,1)) do clip=unicode.sub(clip,2) end + while isLine(unicode.sub(clip,-1)) do clip=unicode.sub(clip,1,-2) end + add(clip) + updateHistory() 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 + cursorBlink=not cursorBlink + set(curPos(cur),strDef(unicode.sub(text,cur,cur)," "),cursorBlink) + end + ::continue:: + end + + if readHistoryType then + if termlib.readHistory[readHistoryType][#termlib.readHistory[readHistoryType]]=="" then + table.remove(termlib.readHistory[readHistoryType],#termlib.readHistory[readHistoryType]) + end + if historyIdx<#termlib.readHistory[readHistoryType] then + table.remove(termlib.readHistory[readHistoryType],historyIdx) + table.insert(termlib.readHistory[readHistoryType],text) + end + while #termlib.readHistory[readHistoryType] > 50 do + table.remove(termlib.readHistory[readHistoryType], 1) end end + + termlib.cursorPosX=1 + termlib.cursorPosY=termlib.cursorPosY+math.ceil((unicode.wlen(text)+startX-1)/width) + if termlib.cursorPosY>height then scrollDown() end + + return text end diff --git a/halyde/lib/filesystem.lua b/halyde/lib/filesystem.lua index f904efa..a6abc45 100644 --- a/halyde/lib/filesystem.lua +++ b/halyde/lib/filesystem.lua @@ -2,9 +2,11 @@ local loadfile = ... -- raw loadfile from boot.lua local component, computer if loadfile then + unicode = loadfile("/halyde/lib/unicode.lua")(loadfile) component = loadfile("/halyde/lib/component.lua")(loadfile) computer = _G.computer elseif import then + unicode = import("unicode") component = import("component") computer = import("computer") end @@ -44,7 +46,10 @@ function filesystem.absolutePath(path) -- returns the address and absolute path checkArg(1, path, "string") path = filesystem.canonical(path) local address = nil - if path:find("^/mnt/...") then + if path:find("^/tmp") then + address = computer.tmpAddress() + path = path:sub(5) + elseif path:find("^/mnt/...") then address = component.get(path:sub(6,8)) if not address then address = computer.getBootAddress() @@ -69,48 +74,36 @@ function filesystem.exists(path) -- check if path exists return component.invoke(address, "exists", absPath) end -local function readUniChar(readByte) - local function inRange(min,max,...) - for _,v in ipairs({...}) do - if not (v and v>=min and v=min and v