mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-19 12:17:17 -04:00
This commit is contained in:
commit
e3a6a3a9b4
@ -148,6 +148,76 @@ end
|
|||||||
local args, options = shell.parse(...)
|
local args, options = shell.parse(...)
|
||||||
local history = {}
|
local history = {}
|
||||||
|
|
||||||
|
local lastSearch
|
||||||
|
|
||||||
|
local function drawPrompt()
|
||||||
|
local foreground = component.gpu.setForeground(0xFF0000)
|
||||||
|
term.write(expand(os.getenv("PS1") or "$ "))
|
||||||
|
component.gpu.setForeground(foreground)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getMatchingPrograms(pattern)
|
||||||
|
local res = {}
|
||||||
|
for dir in string.gmatch(os.getenv("PATH"), "[a-zA-Z0-9/.]+") do
|
||||||
|
for file in fs.list(dir) do
|
||||||
|
if string.match(file, "^" .. pattern .. "(.+)[.]lua") then
|
||||||
|
res[#res+1] = file:match("(.+).lua")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getMatchingFiles(pattern)
|
||||||
|
local res = {}
|
||||||
|
local dir = fs.isDirectory(pattern) and pattern or fs.path(pattern) or "/"
|
||||||
|
local name = (dir == pattern) and "" or fs.name(pattern) or ""
|
||||||
|
for file in fs.list(dir) do
|
||||||
|
if string.match(file, "^" .. name) then
|
||||||
|
res[#res+1] = file
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
|
||||||
|
local function hintHandler(line)
|
||||||
|
local base, space, after = string.match(line, "(.+)(%s)(.+)")
|
||||||
|
local searchProgram = not base
|
||||||
|
if not base then
|
||||||
|
base = ""
|
||||||
|
after = line or ""
|
||||||
|
end
|
||||||
|
if searchProgram then
|
||||||
|
local matches
|
||||||
|
if after:find("[/.]") == 1 then
|
||||||
|
matches = getMatchingFiles(after)
|
||||||
|
if #matches == 1 then
|
||||||
|
lastSearch = ""
|
||||||
|
local ret = base .. (space or "") .. after .. matches[1]:gsub(after:match("[/]*(%w+)$"),"",1)
|
||||||
|
return ret:gsub("[^/]$","%1 ")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
matches = getMatchingPrograms(after)
|
||||||
|
if #matches == 1 then
|
||||||
|
lastSearch = ""
|
||||||
|
return matches[1] .. " "
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if lastSearch == line then return matches end
|
||||||
|
else
|
||||||
|
local matches = getMatchingFiles(after)
|
||||||
|
|
||||||
|
for k in ipairs(matches)do
|
||||||
|
local ret = base .. space .. after .. (matches[k]):gsub(after:match("[/]*(%w+)$") or "","",1)
|
||||||
|
matches[k] = ret:gsub("[^/]$","%1 "):gsub("/$","")
|
||||||
|
end
|
||||||
|
|
||||||
|
return matches
|
||||||
|
end
|
||||||
|
lastSearch = line
|
||||||
|
end
|
||||||
|
|
||||||
if #args == 0 and (io.input() == io.stdin or options.i) and not options.c then
|
if #args == 0 and (io.input() == io.stdin or options.i) and not options.c then
|
||||||
-- interactive shell.
|
-- interactive shell.
|
||||||
while true do
|
while true do
|
||||||
@ -158,10 +228,8 @@ if #args == 0 and (io.input() == io.stdin or options.i) and not options.c then
|
|||||||
term.clear()
|
term.clear()
|
||||||
end
|
end
|
||||||
while term.isAvailable() do
|
while term.isAvailable() do
|
||||||
local foreground = component.gpu.setForeground(0xFF0000)
|
drawPrompt()
|
||||||
term.write(expand(os.getenv("PS1") or "$ "))
|
local command = term.read(history, nil, hintHandler)
|
||||||
component.gpu.setForeground(foreground)
|
|
||||||
local command = term.read(history)
|
|
||||||
if not command then
|
if not command then
|
||||||
term.write("exit\n")
|
term.write("exit\n")
|
||||||
return -- eof
|
return -- eof
|
||||||
|
@ -101,7 +101,7 @@ function term.isAvailable()
|
|||||||
return component.isAvailable("gpu") and component.isAvailable("screen")
|
return component.isAvailable("gpu") and component.isAvailable("screen")
|
||||||
end
|
end
|
||||||
|
|
||||||
function term.read(history, dobreak)
|
function term.read(history, dobreak, hint, prompt)
|
||||||
checkArg(1, history, "table", "nil")
|
checkArg(1, history, "table", "nil")
|
||||||
history = history or {}
|
history = history or {}
|
||||||
table.insert(history, "")
|
table.insert(history, "")
|
||||||
@ -109,6 +109,9 @@ function term.read(history, dobreak)
|
|||||||
local scrollX, scrollY = 0, #history - 1
|
local scrollX, scrollY = 0, #history - 1
|
||||||
local cursorX = 1
|
local cursorX = 1
|
||||||
|
|
||||||
|
local hintCache = (type(hint)=="table" and #hint > 1)and hint
|
||||||
|
local selectedHint = 0
|
||||||
|
|
||||||
local function getCursor()
|
local function getCursor()
|
||||||
return cursorX, 1 + scrollY
|
return cursorX, 1 + scrollY
|
||||||
end
|
end
|
||||||
@ -247,29 +250,61 @@ function term.read(history, dobreak)
|
|||||||
right(unicode.len(value))
|
right(unicode.len(value))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function tab()
|
||||||
|
if not hintCache then
|
||||||
|
if type(hint) == "function" then
|
||||||
|
local h = hint(line())
|
||||||
|
if type(h) == "string" then
|
||||||
|
local _, cby = getCursor()
|
||||||
|
history[cby] = after
|
||||||
|
elseif type(h) == "table" and #h > 0 then
|
||||||
|
hintCache = h
|
||||||
|
selectedHint = 1
|
||||||
|
local _, cby = getCursor()
|
||||||
|
history[cby] = hintCache[selectedHint] or ""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
selectedHint = (selectedHint+1)<=#hintCache and (selectedHint+1) or 1
|
||||||
|
local _, cby = getCursor()
|
||||||
|
history[cby] = hintCache[selectedHint] or ""
|
||||||
|
end
|
||||||
|
redraw()
|
||||||
|
ende()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function cleanHint()
|
||||||
|
if type(hint) ~= "table" then
|
||||||
|
hintCache = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local function onKeyDown(char, code)
|
local function onKeyDown(char, code)
|
||||||
term.setCursorBlink(false)
|
term.setCursorBlink(false)
|
||||||
if code == keyboard.keys.back then
|
if code == keyboard.keys.back then
|
||||||
if left() then delete() end
|
if left() then delete() end cleanHint()
|
||||||
elseif code == keyboard.keys.delete then
|
elseif code == keyboard.keys.delete then
|
||||||
delete()
|
delete()cleanHint()
|
||||||
elseif code == keyboard.keys.left then
|
elseif code == keyboard.keys.left then
|
||||||
left()
|
left()
|
||||||
elseif code == keyboard.keys.right then
|
elseif code == keyboard.keys.right then
|
||||||
right()
|
right()
|
||||||
elseif code == keyboard.keys.home then
|
elseif code == keyboard.keys.home then
|
||||||
home()
|
home()cleanHint()
|
||||||
elseif code == keyboard.keys["end"] then
|
elseif code == keyboard.keys["end"] then
|
||||||
ende()
|
ende()cleanHint()
|
||||||
elseif code == keyboard.keys.up then
|
elseif code == keyboard.keys.up then
|
||||||
up()
|
up()
|
||||||
elseif code == keyboard.keys.down then
|
elseif code == keyboard.keys.down then
|
||||||
down()
|
down()
|
||||||
|
elseif code == keyboard.keys.tab and hint then
|
||||||
|
tab()
|
||||||
elseif code == keyboard.keys.enter then
|
elseif code == keyboard.keys.enter then
|
||||||
local cbx, cby = getCursor()
|
local cbx, cby = getCursor()
|
||||||
if cby ~= #history then -- bring entry to front
|
if cby ~= #history then -- bring entry to front
|
||||||
history[#history] = line()
|
history[#history] = line()
|
||||||
table.remove(history, cby)
|
table.remove(history, cby)
|
||||||
|
cleanHint()
|
||||||
end
|
end
|
||||||
return true, history[#history] .. "\n"
|
return true, history[#history] .. "\n"
|
||||||
elseif keyboard.isControlDown() and code == keyboard.keys.d then
|
elseif keyboard.isControlDown() and code == keyboard.keys.d then
|
||||||
@ -282,6 +317,7 @@ function term.read(history, dobreak)
|
|||||||
return true, nil
|
return true, nil
|
||||||
elseif not keyboard.isControl(char) then
|
elseif not keyboard.isControl(char) then
|
||||||
insert(unicode.char(char))
|
insert(unicode.char(char))
|
||||||
|
cleanHint()
|
||||||
end
|
end
|
||||||
term.setCursorBlink(true)
|
term.setCursorBlink(true)
|
||||||
term.setCursorBlink(true) -- force toggle to caret
|
term.setCursorBlink(true) -- force toggle to caret
|
||||||
|
Loading…
x
Reference in New Issue
Block a user