diff --git a/miniOS/command.lua b/miniOS/command.lua index f95b34a..e400194 100644 --- a/miniOS/command.lua +++ b/miniOS/command.lua @@ -162,8 +162,7 @@ local function twoFileCommandHelper(run, parts) end local function runline(line) - --computer.beep() - checkArg(1, line, "string") + checkArg(1, line, "string", "nil") --print(line) line = text.trim(line) if line == "" then return true end @@ -174,27 +173,7 @@ local function runline(line) if command == nil then return true end --drive selector if #command == 2 then if string.sub(command, 2, 2) == ":" then filesystem.drive.setcurrent(string.sub(command, 1, 1)) return true end end - --external commands and programs - command = parts[1] - if filesystem.exists(command) then - if not filesystem.isDirectory(command) then - if text.endswith(command, ".lua") then runprog(command, parts) return true end - if text.endswith(command, ".bat") then runbat(command, parts) return true end - runprog(command, parts) return true - end - end - if filesystem.exists(command .. ".lua") then - if not filesystem.isDirectory(command .. ".lua") then - runprog(command .. ".lua", parts) - return true - end - end - if filesystem.exists(command .. ".bat") then - if not filesystem.isDirectory(command .. ".bat") then - runbat(command .. ".bat", parts) - return true - end - end + --internal commands if command == "exit" then history = {} return "exit" end if command == "cls" then term.clear(); term.gpu().setForeground(0xFFFFFF); term.gpu().setBackground(0x000000) return true end @@ -218,13 +197,14 @@ local function runline(line) if command == "rename" then return twoFileCommandHelper(moveFile, parts) end if command == "ren" then return twoFileCommandHelper(moveFile, parts) end if command == "move" then return twoFileCommandHelper(moveFile, parts) end + if command == "mkdir" then return filesystem.makeDirectory(fixPath(parts[2])) end if command == "cmds" then printPaged([[ Internal Commands: exit --- Exit the command interpreter, Usually restarts it. cls ---- Clears the screen. ver ---- Outputs version information. mem ---- Outputs memory information. -dir ---- Lists the files on the current disk. +dir ---- Lists the files on the current disk or a path. cmds --- Lists the commands. intro -- Outputs the introduction message. drives - Lists the drives and their addresses. @@ -238,7 +218,31 @@ touch -- Creates a file. del ---- Deletes a file. copy --- Copies a file. move --- Moves a file. -ren ---- Renames a file.]]) print() return true end +ren ---- Renames a file. +mkdir -- Creates a directory.]]) printPaged() return true end + + --external commands and programs + command = parts[1] + if filesystem.exists(command) then + if not filesystem.isDirectory(command) then + if text.endswith(command, ".lua") then runprog(command, parts) return true end + if text.endswith(command, ".bat") then runbat(command, parts) return true end + runprog(command, parts) return true + end + end + if filesystem.exists(command .. ".lua") then + if not filesystem.isDirectory(command .. ".lua") then + runprog(command .. ".lua", parts) + return true + end + end + if filesystem.exists(command .. ".bat") then + if not filesystem.isDirectory(command .. ".bat") then + runbat(command .. ".bat", parts) + return true + end + end + print("'" .. parts[1] .. "' is not an internal or external command, program or batch file.") return false end @@ -255,6 +259,8 @@ end if shell.runline(table.concat(tArgs, " ")) == "exit" then return end +local cmds = {"exit", "cls", "ver", "mem", "dir ", "cmds", "intro", "drives", "labels", "echo ", "type ", "more ", "touch", "del ", "copy ", "move ", "ren ", "mkdir "} + while true do if miniOS.cmdBat and #miniOS.cmdBat == 0 then miniOS.cmdBat = nil @@ -276,7 +282,42 @@ while true do end else term.write(filesystem.drive.getcurrent() ..">") - line = term.read(history) + line = term.read(history, nil, function(line, pos) + local filtered = {} + + local space = string.match(line, '^.*() ') + + if space == nil then + for _,option in ipairs(cmds) do + if string.sub(option, 1, #line) == line then + filtered[#filtered + 1] = option + end + end + end + + local preline + if space ~= nil then + preline = string.sub(line, 1, space) + line = string.sub(line, space + 1) + else + preline = "" + end + local path + local dirsep = string.match(line, '^.*()/') + if dirsep ~= nil then + path = string.sub(line, 1, dirsep) + else path = "" end + + for file in fs.list(path) do + file = path .. file + if string.sub(file, 1, #line) == line and string.sub(file, -1) == '/' then + filtered[#filtered + 1] = preline .. file + elseif string.sub(file, 1, #line) == line and (string.sub(file, -4) == '.lua' or string.sub(file, -4) == '.bat') then + filtered[#filtered + 1] = preline .. file .. ' ' + end + end + return filtered + end) while #history > 10 do table.remove(history, 1) end diff --git a/miniOS/miniOS.lua b/miniOS/miniOS.lua index c152ec0..70f65d0 100644 --- a/miniOS/miniOS.lua +++ b/miniOS/miniOS.lua @@ -1,5 +1,5 @@ _G._OSNAME = "miniOS classic" -_G._OSVER = "0.6.4.3" +_G._OSVER = "0.6.5" _G._OSVERSION = _OSNAME .. " " .. _OSVER _G._OSCREDIT = "miniOS classic by Skye, based off of OpenOS code from OpenComputers.\nminiOS code is under BSD 2-clause licence, OpenOS code is under the MIT licence." @@ -767,12 +767,15 @@ function terminal_code() end end - function term.read(history, dobreak) + function term.read(history, dobreak, hint) checkArg(1, history, "table", "nil") + checkArg(3, hint, "table", "function", "nil") history = history or {} table.insert(history, "") local offset = term.getCursor() - 1 local scrollX, scrollY = 0, #history - 1 + + local hints = { handler = hint } local function getCursor() local cx, cy = term.getCursor() @@ -783,7 +786,7 @@ function terminal_code() local cbx, cby = getCursor() return history[cby] end - + local function setCursor(nbx, nby) local w, h = component.gpu.getResolution() local cx, cy = term.getCursor() @@ -830,6 +833,13 @@ function terminal_code() str = text.padRight(str, l) component.gpu.set(1 + offset, cy, str) end + + local function setline(to) + local cbx, cby = getCursor() + history[cby] = to + redraw() + end + local function home() local cbx, cby = getCursor() @@ -911,8 +921,65 @@ function terminal_code() right(len) end + local function tab() + if not hints.handler then return end + local main_kb = term.keyboard() + -- term may not have a keyboard + -- in which case, we shouldn't be handling tab events + if not main_kb then + return + end + if not hints.cache then + local data = hints.handler + hints.handler = function(...) + if type(data) == "table" then + local args = {...} + local filtered = {} + for _,option in ipairs(data) do + if string.sub(option, 1, #args[1]) == args[1] then + filtered[#filtered + 1] = option + --print(option) + end + end + return filtered + else + return data(...) or {} + end + end + hints.cache = hints.handler(line(), #line() + 1) + hints.cache.i = -1 + end + + local cache = hints.cache + local cache_size = #cache + + if cache_size == 1 and cache.i == 0 then + -- there was only one solution, and the user is asking for the next + hints.cache = hints.handler(cache[1], #line() + 1) + hints.cache.i = -1 + cache = hints.cache + cache_size = #cache + end + + local change = keyboard.isShiftDown(main_kb) and -1 or 1 + cache.i = (cache.i + change) % math.max(#cache, 1) + local next = cache[cache.i + 1] + if next then + local tail = unicode.len(line()) - #line() + setline(next) + local cbx, cby = getCursor() + setCursor(cbx + #line(), cby) + end + end + local function onKeyDown(char, code) term.setCursorBlink(false) + + if code == keyboard.keys.tab then + tab() + else + hints.cache = nil + end if code == keyboard.keys.back then if left() then delete() end elseif code == keyboard.keys.delete then diff --git a/miniOSNT b/miniOSNT index dc1625b..47b6dcf 160000 --- a/miniOSNT +++ b/miniOSNT @@ -1 +1 @@ -Subproject commit dc1625b05540914f8fb9f3af8b499256458768d5 +Subproject commit 47b6dcfc8dce78486bc68ea33487b161ef95357a