mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-11 00:09:44 -04:00
OpenOS 1.6.3 update (#2414)
Why a version change? > This minor version change should not introduce breaking changes, but older code doing non standard things with process environments, `require` and the package library, shebang redirections, or direct calls to /bin/lua, may see some breakages. Also, `shell.resolve` has been fully reworked. This is a crucial and heavily used api. Thus, in case of any mistakes or bugs a version change will help pinpoint regressions. I've heavily tested the resolve code, but it is new code and deserves some bake time in the wild. Changelog: /bin/lua removes shebang line and calls load directly. Improves workflows that define custom environments, and loadfile no longer removes shebang lines load: loaded code chunks now inherit the parent _ENV naturally, having a real-lua behavior require: heavily optimized and made errors more natural and helpful, exposing more information about failure to require a library /lib/pipes: commented out pipes.create which is a future feature to create event-boxed threads process: more process crash text is dumped to the shell to help identify "out of memory" issues shell.resolve: reworked and optimized! possibly breaking change: specifying an extension (ext) to `shell.resolve(name, ext)` will no longer return results to directories, but only files (if they exist). However, it was never the intent of this method to return results to directories when specifying an extension various memory optimizations throughout. openos now allocates ~153k to boot to shell.
This commit is contained in:
parent
f297eefd7d
commit
06a0861597
@ -5,13 +5,23 @@ if #args == 0 then
|
|||||||
args = {"/opt/core/lua_shell.lua"}
|
args = {"/opt/core/lua_shell.lua"}
|
||||||
end
|
end
|
||||||
|
|
||||||
local script, reason = loadfile(args[1], nil, setmetatable({},{__index=_ENV}))
|
local filename = args[1]
|
||||||
|
local buffer, script, reason
|
||||||
|
buffer = io.lines(filename, "*a")()
|
||||||
|
if buffer then
|
||||||
|
buffer = buffer:gsub("^#![^\n]+", "") -- remove shebang if any
|
||||||
|
script, reason = load(buffer, "="..filename)
|
||||||
|
else
|
||||||
|
reason = string.format("could not open %s for reading", filename)
|
||||||
|
end
|
||||||
|
|
||||||
if not script then
|
if not script then
|
||||||
io.stderr:write(tostring(reason) .. "\n")
|
io.stderr:write(tostring(reason) .. "\n")
|
||||||
os.exit(false)
|
os.exit(false)
|
||||||
end
|
end
|
||||||
local result, reason = pcall(script, table.unpack(args, 2))
|
|
||||||
if not result then
|
buffer, reason = pcall(script, table.unpack(args, 2))
|
||||||
|
if not buffer then
|
||||||
io.stderr:write(reason, "\n")
|
io.stderr:write(reason, "\n")
|
||||||
os.exit(false)
|
os.exit(false)
|
||||||
end
|
end
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
function loadfile(filename, mode, env)
|
function loadfile(filename, ...)
|
||||||
if filename:sub(1,1) ~= "/" then
|
if filename:sub(1,1) ~= "/" then
|
||||||
filename = (os.getenv("PWD") or "/") .. "/" .. filename
|
filename = (os.getenv("PWD") or "/") .. "/" .. filename
|
||||||
end
|
end
|
||||||
@ -16,11 +16,9 @@ function loadfile(filename, mode, env)
|
|||||||
end
|
end
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
table.insert(buffer, data)
|
buffer[#buffer + 1] = data
|
||||||
end
|
end
|
||||||
buffer[1] = (buffer[1] or ""):gsub("^#![^\n]+", "") -- remove shebang if any
|
return load(table.concat(buffer), "=" .. filename, ...)
|
||||||
buffer = table.concat(buffer)
|
|
||||||
return load(buffer, "=" .. filename, mode, env)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function dofile(filename)
|
function dofile(filename)
|
||||||
@ -35,12 +33,10 @@ function print(...)
|
|||||||
local args = table.pack(...)
|
local args = table.pack(...)
|
||||||
local stdout = io.stdout
|
local stdout = io.stdout
|
||||||
stdout:setvbuf("line")
|
stdout:setvbuf("line")
|
||||||
|
local pre = ""
|
||||||
for i = 1, args.n do
|
for i = 1, args.n do
|
||||||
local arg = tostring(args[i])
|
stdout:write(pre, tostring(args[i]))
|
||||||
if i > 1 then
|
pre = "\t"
|
||||||
arg = "\t" .. arg
|
|
||||||
end
|
|
||||||
stdout:write(arg)
|
|
||||||
end
|
end
|
||||||
stdout:write("\n")
|
stdout:write("\n")
|
||||||
stdout:setvbuf("no")
|
stdout:setvbuf("no")
|
||||||
|
@ -27,10 +27,18 @@ local kernel_load = _G.load
|
|||||||
local intercept_load
|
local intercept_load
|
||||||
intercept_load = function(source, label, mode, env)
|
intercept_load = function(source, label, mode, env)
|
||||||
if env then
|
if env then
|
||||||
env.load = kernel_load([[
|
local loader = setmetatable(
|
||||||
local source, label, mode, env = ...
|
{
|
||||||
return load(source, label, mode, env or fenv)
|
env = env,
|
||||||
]], "=load", "t", {fenv=env, load=intercept_load})
|
load = intercept_load,
|
||||||
|
},
|
||||||
|
{__call = function(tbl, _source, _label, _mode, _env)
|
||||||
|
return tbl.load(_source, _label, _mode, _env or tbl.env)
|
||||||
|
end})
|
||||||
|
if env.load and (type(env.load) ~= "table" or env.load.load ~= intercept_load) then
|
||||||
|
loader.load = env.load
|
||||||
|
end
|
||||||
|
env.load = loader
|
||||||
end
|
end
|
||||||
return kernel_load(source, label, mode, env or process.info().env)
|
return kernel_load(source, label, mode, env or process.info().env)
|
||||||
end
|
end
|
||||||
|
@ -2,11 +2,7 @@ local computer = require("computer")
|
|||||||
local event = require("event")
|
local event = require("event")
|
||||||
local fs = require("filesystem")
|
local fs = require("filesystem")
|
||||||
local shell = require("shell")
|
local shell = require("shell")
|
||||||
local process = require("process")
|
local info = require("process").info
|
||||||
|
|
||||||
local function env()
|
|
||||||
return process.info().data.vars
|
|
||||||
end
|
|
||||||
|
|
||||||
os.execute = function(command)
|
os.execute = function(command)
|
||||||
if not command then
|
if not command then
|
||||||
@ -20,7 +16,7 @@ function os.exit(code)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function os.getenv(varname)
|
function os.getenv(varname)
|
||||||
local env = env()
|
local env = info().data.vars
|
||||||
if not varname then
|
if not varname then
|
||||||
return env
|
return env
|
||||||
elseif varname == '#' then
|
elseif varname == '#' then
|
||||||
@ -34,7 +30,7 @@ function os.setenv(varname, value)
|
|||||||
if value ~= nil then
|
if value ~= nil then
|
||||||
value = tostring(value)
|
value = tostring(value)
|
||||||
end
|
end
|
||||||
env()[varname] = value
|
info().data.vars[varname] = value
|
||||||
return value
|
return value
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,11 +1,6 @@
|
|||||||
local buffer = require("buffer")
|
local buffer = require("buffer")
|
||||||
local tty = require("tty")
|
local tty = require("tty")
|
||||||
|
|
||||||
local io_open = io.open
|
|
||||||
function io.open(path, mode)
|
|
||||||
return io_open(require("shell").resolve(path), mode)
|
|
||||||
end
|
|
||||||
|
|
||||||
local stdinStream = {handle="stdin"}
|
local stdinStream = {handle="stdin"}
|
||||||
local stdoutStream = {handle="stdout"}
|
local stdoutStream = {handle="stdout"}
|
||||||
local stderrStream = {handle="stderr"}
|
local stderrStream = {handle="stderr"}
|
||||||
@ -15,13 +10,13 @@ local function badFileDescriptor()
|
|||||||
return nil, "bad file descriptor"
|
return nil, "bad file descriptor"
|
||||||
end
|
end
|
||||||
|
|
||||||
function stdinStream:close()
|
function stdinStream.close()
|
||||||
return nil, "cannot close standard file"
|
return nil, "cannot close standard file"
|
||||||
end
|
end
|
||||||
stdoutStream.close = stdinStream.close
|
stdoutStream.close = stdinStream.close
|
||||||
stderrStream.close = stdinStream.close
|
stderrStream.close = stdinStream.close
|
||||||
|
|
||||||
function stdinStream:read()
|
function stdinStream.read()
|
||||||
return tty.read(stdinHistory)
|
return tty.read(stdinHistory)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
#!/bin/lua
|
|
||||||
|
|
||||||
local component = require("component")
|
local component = require("component")
|
||||||
local computer = require("computer")
|
local computer = require("computer")
|
||||||
local text = require("text")
|
local text = require("text")
|
||||||
|
@ -36,7 +36,8 @@ end
|
|||||||
|
|
||||||
function io.open(path, mode)
|
function io.open(path, mode)
|
||||||
-- These requires are not on top because this is a bootstrapped file.
|
-- These requires are not on top because this is a bootstrapped file.
|
||||||
local stream, result = require("filesystem").open(path, mode)
|
local resolved_path = require("shell").resolve(path)
|
||||||
|
local stream, result = require("filesystem").open(resolved_path, mode)
|
||||||
if stream then
|
if stream then
|
||||||
return require("buffer").new(mode, stream)
|
return require("buffer").new(mode, stream)
|
||||||
else
|
else
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
local component = require("component")
|
|
||||||
|
|
||||||
local keyboard = {pressedChars = {}, pressedCodes = {}}
|
local keyboard = {pressedChars = {}, pressedCodes = {}}
|
||||||
|
|
||||||
-- these key definitions are only a subset of all the defined keys
|
-- these key definitions are only a subset of all the defined keys
|
||||||
@ -32,16 +30,6 @@ keyboard.keys = {
|
|||||||
numpadenter = 0x9C,
|
numpadenter = 0x9C,
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Create inverse mapping for name lookup.
|
|
||||||
setmetatable(keyboard.keys,
|
|
||||||
{
|
|
||||||
__index = function(tbl, k)
|
|
||||||
getmetatable(keyboard.keys).__index = nil -- to be safe
|
|
||||||
loadfile(package.searchpath("tools/keyboard_full", package.path), "t", setmetatable({keyboard=keyboard},{__index=_G}))()
|
|
||||||
return tbl[k]
|
|
||||||
end
|
|
||||||
})
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
local function getKeyboardAddress(address)
|
local function getKeyboardAddress(address)
|
||||||
@ -94,4 +82,13 @@ end
|
|||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
setmetatable(keyboard.keys,
|
||||||
|
{
|
||||||
|
__index = function(tbl, key)
|
||||||
|
setmetatable(tbl, nil)
|
||||||
|
dofile("/opt/core/full_keyboard.lua")
|
||||||
|
return tbl[key] -- some keyboard keys are handled by __index by design
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
return keyboard
|
return keyboard
|
||||||
|
@ -16,11 +16,6 @@ local loaded = {
|
|||||||
}
|
}
|
||||||
package.loaded = loaded
|
package.loaded = loaded
|
||||||
|
|
||||||
local preload = {}
|
|
||||||
package.preload = preload
|
|
||||||
|
|
||||||
package.searchers = {}
|
|
||||||
|
|
||||||
function package.searchpath(name, path, sep, rep)
|
function package.searchpath(name, path, sep, rep)
|
||||||
checkArg(1, name, "string")
|
checkArg(1, name, "string")
|
||||||
checkArg(2, path, "string")
|
checkArg(2, path, "string")
|
||||||
@ -47,67 +42,28 @@ function package.searchpath(name, path, sep, rep)
|
|||||||
return nil, table.concat(errorFiles, "\n")
|
return nil, table.concat(errorFiles, "\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
local function preloadSearcher(module)
|
|
||||||
if preload[module] ~= nil then
|
|
||||||
return preload[module]
|
|
||||||
else
|
|
||||||
return "\tno field package.preload['" .. module .. "']"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function pathSearcher(module)
|
|
||||||
local filepath, reason = package.searchpath(module, package.path)
|
|
||||||
if filepath then
|
|
||||||
local loader, reason = loadfile(filepath, "bt", _G)
|
|
||||||
if loader then
|
|
||||||
return loader, filepath
|
|
||||||
else
|
|
||||||
return reason
|
|
||||||
end
|
|
||||||
else
|
|
||||||
return reason
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
table.insert(package.searchers, preloadSearcher)
|
|
||||||
table.insert(package.searchers, pathSearcher)
|
|
||||||
|
|
||||||
function require(module)
|
function require(module)
|
||||||
checkArg(1, module, "string")
|
checkArg(1, module, "string")
|
||||||
if loaded[module] ~= nil then
|
if loaded[module] ~= nil then
|
||||||
return loaded[module]
|
return loaded[module]
|
||||||
elseif not loading[module] then
|
elseif not loading[module] then
|
||||||
loading[module] = true
|
local library, status, step
|
||||||
local loader, value, errorMsg = nil, nil, {"module '" .. module .. "' not found:"}
|
|
||||||
for i = 1, #package.searchers do
|
step, library, status = "not found", package.searchpath(module, package.path)
|
||||||
-- the pcall is mostly for out of memory errors
|
|
||||||
local ok, f, extra = pcall(package.searchers[i], module)
|
if library then
|
||||||
if not ok then
|
step, library, status = "loadfile failed", loadfile(library)
|
||||||
table.insert(errorMsg, "\t" .. (f or "nil"))
|
|
||||||
elseif f and type(f) ~= "string" then
|
|
||||||
loader = f
|
|
||||||
value = extra
|
|
||||||
break
|
|
||||||
elseif f then
|
|
||||||
table.insert(errorMsg, f)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
if loader then
|
|
||||||
local success, result = pcall(loader, module, value)
|
if library then
|
||||||
|
loading[module] = true
|
||||||
|
step, library, status = "load failed", pcall(library, module)
|
||||||
loading[module] = false
|
loading[module] = false
|
||||||
if not success then
|
|
||||||
error(result, 2)
|
|
||||||
end
|
|
||||||
if result then
|
|
||||||
loaded[module] = result
|
|
||||||
elseif not loaded[module] then
|
|
||||||
loaded[module] = true
|
|
||||||
end
|
|
||||||
return loaded[module]
|
|
||||||
else
|
|
||||||
loading[module] = false
|
|
||||||
error(table.concat(errorMsg, "\n"), 2)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
assert(library, string.format("module '%s' %s:\n%s", module, step, status))
|
||||||
|
loaded[module] = status
|
||||||
|
return status
|
||||||
else
|
else
|
||||||
error("already loading: " .. module .. "\n" .. debug.traceback(), 2)
|
error("already loading: " .. module .. "\n" .. debug.traceback(), 2)
|
||||||
end
|
end
|
||||||
|
@ -371,11 +371,14 @@ function plib.popen(prog, mode, env)
|
|||||||
return pfd
|
return pfd
|
||||||
end
|
end
|
||||||
|
|
||||||
function plib.create(fp, name)
|
-- function plib.create(fp, name)
|
||||||
checkArg(1, fp, "function")
|
-- checkArg(1, fp, "function")
|
||||||
checkArg(2, name, "string", "nil")
|
-- checkArg(2, name, "string", "nil")
|
||||||
local pco = plib.internal.create(fp, nil, name)
|
|
||||||
return pco.stack[1]
|
-- local pco = plib.internal.create(fp, function()end, name)
|
||||||
end
|
-- -- process.info(pco.stack[1]).data.event = nil
|
||||||
|
|
||||||
|
-- return pco.stack[1]
|
||||||
|
-- end
|
||||||
|
|
||||||
return plib
|
return plib
|
||||||
|
@ -32,10 +32,10 @@ function process.load(path, env, init, name)
|
|||||||
local p = process.findProcess()
|
local p = process.findProcess()
|
||||||
env = env or p.env
|
env = env or p.env
|
||||||
local code
|
local code
|
||||||
if type(path) == 'string' then
|
if type(path) == "string" then
|
||||||
code = function(...)
|
code = function(...)
|
||||||
local fs, shell = require("filesystem"), require("shell")
|
local fs, shell = require("filesystem"), require("shell")
|
||||||
local program, reason = shell.resolve(path, 'lua')
|
local program, reason = shell.resolve(path, "lua")
|
||||||
if not program then
|
if not program then
|
||||||
if fs.isDirectory(shell.resolve(path)) then
|
if fs.isDirectory(shell.resolve(path)) then
|
||||||
io.stderr:write(path .. ": is a directory\n")
|
io.stderr:write(path .. ": is a directory\n")
|
||||||
@ -48,7 +48,7 @@ function process.load(path, env, init, name)
|
|||||||
os.setenv("_", program)
|
os.setenv("_", program)
|
||||||
local f = fs.open(program)
|
local f = fs.open(program)
|
||||||
if f then
|
if f then
|
||||||
local shebang = f:read(1024):match("^#!([^\n]+)")
|
local shebang = (f:read(1024) or ""):match("^#!([^\n]+)")
|
||||||
f:close()
|
f:close()
|
||||||
if shebang then
|
if shebang then
|
||||||
local result = table.pack(shell.execute(shebang:gsub("%s",""), env, program, ...))
|
local result = table.pack(shell.execute(shebang:gsub("%s",""), env, program, ...))
|
||||||
@ -59,7 +59,7 @@ function process.load(path, env, init, name)
|
|||||||
local command
|
local command
|
||||||
command, reason = loadfile(program, "bt", env)
|
command, reason = loadfile(program, "bt", env)
|
||||||
if not command then
|
if not command then
|
||||||
io.stderr:write(program..(reason or ""):gsub("^[^:]*", "").."\n")
|
io.stderr:write(program, " ", reason or "", "\n")
|
||||||
return 128
|
return 128
|
||||||
end
|
end
|
||||||
return command(...)
|
return command(...)
|
||||||
@ -80,14 +80,14 @@ function process.load(path, env, init, name)
|
|||||||
end,
|
end,
|
||||||
function(msg)
|
function(msg)
|
||||||
-- msg can be a custom error object
|
-- msg can be a custom error object
|
||||||
if type(msg) == 'table' then
|
if type(msg) == "table" then
|
||||||
if msg.reason ~= "terminated" then
|
if msg.reason ~= "terminated" then
|
||||||
io.stderr:write(msg.reason.."\n")
|
io.stderr:write(msg.reason.."\n")
|
||||||
end
|
end
|
||||||
return msg.code or 0
|
return msg.code or 0
|
||||||
end
|
end
|
||||||
local stack = debug.traceback():gsub('^([^\n]*\n)[^\n]*\n[^\n]*\n','%1')
|
local stack = debug.traceback():gsub("^([^\n]*\n)[^\n]*\n[^\n]*\n","%1")
|
||||||
io.stderr:write(string.format('%s:\n%s', msg or '', stack))
|
io.stderr:write(string.format("%s:\n%s", msg or "", stack))
|
||||||
return 128 -- syserr
|
return 128 -- syserr
|
||||||
end, ...)
|
end, ...)
|
||||||
}
|
}
|
||||||
@ -107,13 +107,11 @@ function process.load(path, env, init, name)
|
|||||||
{
|
{
|
||||||
handles = {},
|
handles = {},
|
||||||
io = {},
|
io = {},
|
||||||
coroutine_handler = {}
|
|
||||||
},
|
},
|
||||||
parent = p,
|
parent = p,
|
||||||
instances = setmetatable({}, {__mode="v"}),
|
instances = setmetatable({}, {__mode="v"}),
|
||||||
}
|
}
|
||||||
setmetatable(new_proc.data.io, {__index=p.data.io})
|
setmetatable(new_proc.data.io, {__index=p.data.io})
|
||||||
setmetatable(new_proc.data.coroutine_handler, {__index=p.data.coroutine_handler})
|
|
||||||
setmetatable(new_proc.data, {__index=p.data})
|
setmetatable(new_proc.data, {__index=p.data})
|
||||||
process.list[thread] = new_proc
|
process.list[thread] = new_proc
|
||||||
|
|
||||||
|
@ -246,12 +246,12 @@ function sh.internal.createThreads(commands, env, start_args)
|
|||||||
local thread_env = type(program) == "string" and env or nil
|
local thread_env = type(program) == "string" and env or nil
|
||||||
local thread, reason = process.load(program, thread_env, function(...)
|
local thread, reason = process.load(program, thread_env, function(...)
|
||||||
local cdata = process.info().data.command
|
local cdata = process.info().data.command
|
||||||
local args, has_tokens, start_args = cdata.args, cdata.has_tokens, cdata.start_args
|
local args, has_tokens, c_start_args = cdata.args, cdata.has_tokens, cdata.start_args
|
||||||
if has_tokens then
|
if has_tokens then
|
||||||
args = sh.internal.buildCommandRedirects(args)
|
args = sh.internal.buildCommandRedirects(args)
|
||||||
end
|
end
|
||||||
|
|
||||||
sh.internal.concatn(args, start_args)
|
sh.internal.concatn(args, c_start_args)
|
||||||
sh.internal.concatn(args, {...}, select('#', ...))
|
sh.internal.concatn(args, {...}, select('#', ...))
|
||||||
|
|
||||||
-- popen expects each process to first write an empty string
|
-- popen expects each process to first write an empty string
|
||||||
|
@ -18,60 +18,13 @@ function shell.getShell()
|
|||||||
if shells[shellName] then
|
if shells[shellName] then
|
||||||
return shells[shellName]
|
return shells[shellName]
|
||||||
end
|
end
|
||||||
local sh, reason = loadfile(shellName, "t")
|
local sh, reason = loadfile(shellName)
|
||||||
if sh then
|
if sh then
|
||||||
shells[shellName] = sh
|
shells[shellName] = sh
|
||||||
end
|
end
|
||||||
return sh, reason
|
return sh, reason
|
||||||
end
|
end
|
||||||
|
|
||||||
local function findFile(name, ext)
|
|
||||||
checkArg(1, name, "string")
|
|
||||||
local function findIn(dir)
|
|
||||||
if dir:sub(1, 1) ~= "/" then
|
|
||||||
dir = shell.resolve(dir)
|
|
||||||
end
|
|
||||||
dir = fs.concat(fs.concat(dir, name), "..")
|
|
||||||
local name = fs.name(name)
|
|
||||||
local list = fs.list(dir)
|
|
||||||
if list and name then
|
|
||||||
local files = {}
|
|
||||||
for file in list do
|
|
||||||
files[file] = true
|
|
||||||
end
|
|
||||||
if ext and name:sub(-(1 + ext:len())) == "." .. ext then
|
|
||||||
-- Name already contains extension, prioritize.
|
|
||||||
if files[name] then
|
|
||||||
return true, fs.concat(dir, name)
|
|
||||||
end
|
|
||||||
elseif files[name] then
|
|
||||||
-- Check exact name.
|
|
||||||
return true, fs.concat(dir, name)
|
|
||||||
elseif ext then
|
|
||||||
-- Check name with automatially added extension.
|
|
||||||
local name = name .. "." .. ext
|
|
||||||
if files[name] then
|
|
||||||
return true, fs.concat(dir, name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
if name:sub(1, 1) == "/" then
|
|
||||||
local found, where = findIn("/")
|
|
||||||
if found then return where end
|
|
||||||
elseif name:sub(1, 2) == "./" then
|
|
||||||
local found, where = findIn(shell.getWorkingDirectory())
|
|
||||||
if found then return where end
|
|
||||||
else
|
|
||||||
for path in string.gmatch(shell.getPath(), "[^:]+") do
|
|
||||||
local found, where = findIn(path)
|
|
||||||
if found then return where end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
function shell.prime()
|
function shell.prime()
|
||||||
@ -133,21 +86,37 @@ function shell.setPath(value)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function shell.resolve(path, ext)
|
function shell.resolve(path, ext)
|
||||||
if ext then
|
checkArg(1, path, "string")
|
||||||
|
|
||||||
|
local dir = path
|
||||||
|
if dir:find("/") ~= 1 then
|
||||||
|
dir = fs.concat(shell.getWorkingDirectory(), dir)
|
||||||
|
end
|
||||||
|
local name = fs.name(path)
|
||||||
|
dir = fs[name and "path" or "canonical"](dir)
|
||||||
|
local fullname = fs.concat(dir, name or "")
|
||||||
|
|
||||||
|
if not ext then
|
||||||
|
return fullname
|
||||||
|
elseif name then
|
||||||
checkArg(2, ext, "string")
|
checkArg(2, ext, "string")
|
||||||
local where = findFile(path, ext)
|
-- search for name in PATH if no dir was given
|
||||||
if where then
|
-- no dir was given if path has no /
|
||||||
return where
|
local search_in = path:find("/") and dir or shell.getPath()
|
||||||
else
|
for search_path in string.gmatch(search_in, "[^:]+") do
|
||||||
return nil, "file not found"
|
-- resolve search_path because they may be relative
|
||||||
end
|
local search_name = fs.concat(shell.resolve(search_path), name)
|
||||||
else
|
if not fs.exists(search_name) then
|
||||||
if path:sub(1, 1) == "/" then
|
search_name = search_name .. "." .. ext
|
||||||
return fs.canonical(path)
|
end
|
||||||
else
|
-- extensions are provided when the caller is looking for a file
|
||||||
return fs.concat(shell.getWorkingDirectory(), path)
|
if fs.exists(search_name) and not fs.isDirectory(search_name) then
|
||||||
|
return search_name
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return nil, "file not found"
|
||||||
end
|
end
|
||||||
|
|
||||||
function shell.execute(command, env, ...)
|
function shell.execute(command, env, ...)
|
||||||
@ -179,11 +148,11 @@ function shell.parse(...)
|
|||||||
if param == "--" then
|
if param == "--" then
|
||||||
doneWithOptions = true -- stop processing options at `--`
|
doneWithOptions = true -- stop processing options at `--`
|
||||||
elseif param:sub(1, 2) == "--" then
|
elseif param:sub(1, 2) == "--" then
|
||||||
if param:match("%-%-(.-)=") ~= nil then
|
local key, value = param:match("%-%-(.-)=(.*)")
|
||||||
options[param:match("%-%-(.-)=")] = param:match("=(.*)")
|
if not key then
|
||||||
else
|
key, value = param:sub(3), true
|
||||||
options[param:sub(3)] = true
|
|
||||||
end
|
end
|
||||||
|
options[key] = value
|
||||||
elseif param:sub(1, 1) == "-" and param ~= "-" then
|
elseif param:sub(1, 1) == "-" and param ~= "-" then
|
||||||
for j = 2, unicode.len(param) do
|
for j = 2, unicode.len(param) do
|
||||||
options[unicode.sub(param, j, j)] = true
|
options[unicode.sub(param, j, j)] = true
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
-- called from /init.lua
|
-- called from /init.lua
|
||||||
local raw_loadfile = ...
|
local raw_loadfile = ...
|
||||||
|
|
||||||
_G._OSVERSION = "OpenOS 1.6.2"
|
_G._OSVERSION = "OpenOS 1.6.3"
|
||||||
|
|
||||||
local component = component
|
local component = component
|
||||||
local computer = computer
|
local computer = computer
|
||||||
@ -96,11 +96,11 @@ do
|
|||||||
package.loaded.component = component
|
package.loaded.component = component
|
||||||
package.loaded.computer = computer
|
package.loaded.computer = computer
|
||||||
package.loaded.unicode = unicode
|
package.loaded.unicode = unicode
|
||||||
package.preload["buffer"] = loadfile("/lib/buffer.lua")
|
package.loaded.buffer = assert(loadfile("/lib/buffer.lua"))()
|
||||||
package.preload["filesystem"] = loadfile("/lib/filesystem.lua")
|
package.loaded.filesystem = assert(loadfile("/lib/filesystem.lua"))()
|
||||||
|
|
||||||
-- Inject the io modules
|
-- Inject the io modules
|
||||||
_G.io = loadfile("/lib/io.lua")()
|
_G.io = assert(loadfile("/lib/io.lua"))()
|
||||||
end
|
end
|
||||||
|
|
||||||
status("Initializing file system...")
|
status("Initializing file system...")
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
local keyboard = require("keyboard")
|
||||||
|
|
||||||
keyboard.keys["1"] = 0x02
|
keyboard.keys["1"] = 0x02
|
||||||
keyboard.keys["2"] = 0x03
|
keyboard.keys["2"] = 0x03
|
||||||
keyboard.keys["3"] = 0x04
|
keyboard.keys["3"] = 0x04
|
||||||
@ -132,7 +134,7 @@ setmetatable(keyboard.keys,
|
|||||||
{
|
{
|
||||||
__index = function(tbl, k)
|
__index = function(tbl, k)
|
||||||
if type(k) ~= "number" then return end
|
if type(k) ~= "number" then return end
|
||||||
for name,value in pairs(keyboard.keys) do
|
for name,value in pairs(tbl.keys) do
|
||||||
if value == k then
|
if value == k then
|
||||||
return name
|
return name
|
||||||
end
|
end
|
Loading…
x
Reference in New Issue
Block a user