spaces->tab, equipper improvements, supertreefarm rewrite, follow improvements, sensor cleanup, milo multiple items allowed in recipes, remote canvas access

This commit is contained in:
kepler155c@gmail.com
2019-06-18 15:23:20 -04:00
parent 3b9b509429
commit 045b32884f
162 changed files with 20448 additions and 20286 deletions

View File

@@ -1,13 +1,13 @@
{
[ "58ec8d6e36e346d9f42eb43935652e3e58e2c829" ] = {
title = "Mwm",
category = "Apps",
icon = "\030f\031f \0304 \
[ "58ec8d6e36e346d9f42eb43935652e3e58e2c829" ] = {
title = "Mwm",
category = "Apps",
icon = "\030f\031f \0304 \
\030f\031dshell]\0304\0314 \
\0304\031f ",
iconExt = "\030 \031f\0305\031f\155\030f\128\031d\152\140\030d\031f\151\030f\128\128\0304\0314\128\
iconExt = "\030 \031f\0305\031f\155\030f\128\031d\152\140\030d\031f\151\030f\128\128\0304\0314\128\
\030 \031f\030f\0315\152\129\030d\031f\141\030f\031d\153\030d\031f\149\030f\031d\131\148\0304\0314\128\
\030 \031f\0304\031f\131\131\131\131\131\131\131\030e\0314\131",
run = "mwm.lua usr/config/mwm",
},
run = "mwm.lua usr/config/mwm",
},
}

View File

@@ -8,76 +8,76 @@ local os = _G.os
local remoteId
local args = { ... }
if #args == 1 then
remoteId = tonumber(args[1])
remoteId = tonumber(args[1])
else
print('Enter host ID')
remoteId = tonumber(_G.read())
print('Enter host ID')
remoteId = tonumber(_G.read())
end
if not remoteId then
error('Syntax: mirrorClient <host ID>')
error('Syntax: mirrorClient <host ID>')
end
local function wrapTerm(socket)
local methods = { 'blit', 'clear', 'clearLine', 'setCursorPos', 'write',
'setTextColor', 'setTextColour', 'setBackgroundColor',
'setBackgroundColour', 'scroll', 'setCursorBlink', }
local methods = { 'blit', 'clear', 'clearLine', 'setCursorPos', 'write',
'setTextColor', 'setTextColour', 'setBackgroundColor',
'setBackgroundColour', 'scroll', 'setCursorBlink', }
socket.term = multishell.term
socket.oldTerm = Util.shallowCopy(socket.term)
socket.term = multishell.term
socket.oldTerm = Util.shallowCopy(socket.term)
for _,k in pairs(methods) do
socket.term[k] = function(...)
if not socket.queue then
socket.queue = { }
Event.onTimeout(0, function()
if socket.queue then
socket:write(socket.queue)
socket.queue = nil
end
end)
end
table.insert(socket.queue, {
f = k,
args = { ... },
})
socket.oldTerm[k](...)
end
end
for _,k in pairs(methods) do
socket.term[k] = function(...)
if not socket.queue then
socket.queue = { }
Event.onTimeout(0, function()
if socket.queue then
socket:write(socket.queue)
socket.queue = nil
end
end)
end
table.insert(socket.queue, {
f = k,
args = { ... },
})
socket.oldTerm[k](...)
end
end
end
while true do
print('connecting...')
local socket
print('connecting...')
local socket
while true do
socket = Socket.connect(remoteId, 5901)
if socket then
break
end
os.sleep(3)
end
while true do
socket = Socket.connect(remoteId, 5901)
if socket then
break
end
os.sleep(3)
end
print('connected')
print('connected')
wrapTerm(socket)
wrapTerm(socket)
os.queueEvent('term_resize')
os.queueEvent('term_resize')
while true do
local e = Event.pullEvent()
if e[1] == 'terminate' then
break
end
if not socket.connected then
break
end
end
while true do
local e = Event.pullEvent()
if e[1] == 'terminate' then
break
end
if not socket.connected then
break
end
end
for k,v in pairs(socket.oldTerm) do
socket.term[k] = v
end
for k,v in pairs(socket.oldTerm) do
socket.term[k] = v
end
socket:close()
socket:close()
end

View File

@@ -7,41 +7,41 @@ local term = _G.term
local mon = term.current()
local args = { ... }
if args[1] then
mon = _G.device[args[1]]
mon = _G.device[args[1]]
end
if not mon then
error('Invalid monitor')
error('Invalid monitor')
end
mon.setBackgroundColor(colors.black)
mon.clear()
while true do
local socket = Socket.server(5901)
local socket = Socket.server(5901)
print('mirror: connection from ' .. socket.dhost)
print('mirror: connection from ' .. socket.dhost)
Event.addRoutine(function()
while true do
local data = socket:read()
if not data then
break
end
for _,v in ipairs(data) do
mon[v.f](unpack(v.args))
end
end
end)
Event.addRoutine(function()
while true do
local data = socket:read()
if not data then
break
end
for _,v in ipairs(data) do
mon[v.f](unpack(v.args))
end
end
end)
while true do
Event.pullEvent()
if not socket.connected then
break
end
end
while true do
Event.pullEvent()
if not socket.connected then
break
end
end
print('connection lost')
print('connection lost')
socket:close()
socket:close()
end

View File

@@ -17,8 +17,8 @@ local term = _G.term
local window = _G.window
local function syntax()
printError('Syntax:')
error('mwm sessionName [monitor]')
printError('Syntax:')
error('mwm sessionName [monitor]')
end
local args = { ... }
@@ -33,9 +33,9 @@ local parentMon
local defaultEnv = Util.shallowCopy(_ENV)
defaultEnv.multishell = multishell
if args[2] then
parentMon = peripheral.wrap(args[2]) or syntax()
parentMon = peripheral.wrap(args[2]) or syntax()
else
parentMon = peripheral.find('monitor') or syntax()
parentMon = peripheral.find('monitor') or syntax()
end
parentMon.setTextScale(.5)
@@ -54,8 +54,8 @@ monitor.setBackgroundColor(colors.gray)
monitor.clear()
local function nextUID()
UID = UID + 1
return UID
UID = UID + 1
return UID
end
local function xprun(env, path, ...)
@@ -68,471 +68,471 @@ local function xprun(env, path, ...)
end
local function write(win, x, y, text)
win.setCursorPos(x, y)
win.write(text)
win.setCursorPos(x, y)
win.write(text)
end
local function redraw()
--monitor.clear()
monitor.canvas:dirty()
--monitor.setBackgroundColor(colors.gray)
monitor.canvas:clear(colors.gray)
for k, process in ipairs(processes) do
process.container.canvas:dirty()
process:focus(k == #processes)
end
--monitor.clear()
monitor.canvas:dirty()
--monitor.setBackgroundColor(colors.gray)
monitor.canvas:clear(colors.gray)
for k, process in ipairs(processes) do
process.container.canvas:dirty()
process:focus(k == #processes)
end
end
local function getProcessAt(x, y)
for k = #processes, 1, -1 do
local process = processes[k]
if x >= process.x and
y >= process.y and
x <= process.x + process.width - 1 and
y <= process.y + process.height - 1 then
return k, process
end
end
for k = #processes, 1, -1 do
local process = processes[k]
if x >= process.x and
y >= process.y and
x <= process.x + process.width - 1 and
y <= process.y + process.height - 1 then
return k, process
end
end
end
--[[ A runnable process ]]--
local Process = { }
function Process:new(args)
args.env = args.env or Util.shallowCopy(defaultEnv)
args.width = args.width or termDim.width
args.height = args.height or termDim.height
args.env = args.env or Util.shallowCopy(defaultEnv)
args.width = args.width or termDim.width
args.height = args.height or termDim.height
-- TODO: randomize start position
local self = setmetatable({
uid = nextUID(),
x = args.x or 1,
y = args.y or 1,
width = args.width + 2,
height = args.height + 3,
path = args.path,
args = args.args or { },
title = args.title or 'shell',
}, { __index = Process })
-- TODO: randomize start position
local self = setmetatable({
uid = nextUID(),
x = args.x or 1,
y = args.y or 1,
width = args.width + 2,
height = args.height + 3,
path = args.path,
args = args.args or { },
title = args.title or 'shell',
}, { __index = Process })
self:adjustDimensions()
if not args.x then
self.x = math.random(1, monDim.width - self.width + 1)
self.y = math.random(1, monDim.height - self.height + 1)
end
self:adjustDimensions()
if not args.x then
self.x = math.random(1, monDim.width - self.width + 1)
self.y = math.random(1, monDim.height - self.height + 1)
end
self.container = Terminal.window(monitor, self.x, self.y, self.width, self.height, true)
self.window = window.create(self.container, 2, 3, args.width, args.height, true)
self.terminal = self.window
self.container = Terminal.window(monitor, self.x, self.y, self.width, self.height, true)
self.window = window.create(self.container, 2, 3, args.width, args.height, true)
self.terminal = self.window
self.container.canvas.parent = monitor.canvas
table.insert(monitor.canvas.layers, 1, self.container.canvas)
self.container.canvas:setVisible(true)
self.container.canvas.parent = monitor.canvas
table.insert(monitor.canvas.layers, 1, self.container.canvas)
self.container.canvas:setVisible(true)
--self.container.getSize = self.window.getSize
--self.container.getSize = self.window.getSize
self.co = coroutine.create(function()
local result, err
self.co = coroutine.create(function()
local result, err
if args.fn then
result, err = Util.runFunction(args.env, args.fn, table.unpack(self.args))
elseif args.path then
result, err = xprun(args.env, args.path, table.unpack(self.args))
end
if args.fn then
result, err = Util.runFunction(args.env, args.fn, table.unpack(self.args))
elseif args.path then
result, err = xprun(args.env, args.path, table.unpack(self.args))
end
if not result and err and err ~= 'Terminated' then
printError('\n' .. tostring(err))
os.pullEventRaw('terminate')
end
multishell.removeProcess(self)
end)
if not result and err and err ~= 'Terminated' then
printError('\n' .. tostring(err))
os.pullEventRaw('terminate')
end
multishell.removeProcess(self)
end)
self:focus(false)
self:focus(false)
return self
return self
end
function Process:focus(focused)
if focused then
self.container.setBackgroundColor(colors.yellow)
else
self.container.setBackgroundColor(colors.gray)
end
self.container.setTextColor(colors.black)
write(self.container, 2, 2, string.rep(' ', self.width - 2))
write(self.container, 3, 2, self.title)
write(self.container, self.width - 2, 2, '*')
if focused then
self.container.setBackgroundColor(colors.yellow)
else
self.container.setBackgroundColor(colors.gray)
end
self.container.setTextColor(colors.black)
write(self.container, 2, 2, string.rep(' ', self.width - 2))
write(self.container, 3, 2, self.title)
write(self.container, self.width - 2, 2, '*')
if focused then
self.window.restoreCursor()
elseif self.showSizers then
self:drawSizers(false)
end
if focused then
self.window.restoreCursor()
elseif self.showSizers then
self:drawSizers(false)
end
end
function Process:drawSizers(showSizers)
local sizeChars = {
'\135', '\139', '\141', '\142'
}
local sizeChars = {
'\135', '\139', '\141', '\142'
}
if Util.getVersion() < 1.8 then
sizeChars = {
'#', '#', '#', '#'
}
end
if Util.getVersion() < 1.8 then
sizeChars = {
'#', '#', '#', '#'
}
end
self.showSizers = showSizers
self.showSizers = showSizers
self.container.setBackgroundColor(colors.black)
self.container.setTextColor(colors.white)
self.container.setBackgroundColor(colors.black)
self.container.setTextColor(colors.white)
if self.showSizers then
write(self.container, 1, 1, sizeChars[1])
write(self.container, self.width, 1, sizeChars[2])
write(self.container, 1, self.height, sizeChars[3])
write(self.container, self.width, self.height, sizeChars[4])
if self.showSizers then
write(self.container, 1, 1, sizeChars[1])
write(self.container, self.width, 1, sizeChars[2])
write(self.container, 1, self.height, sizeChars[3])
write(self.container, self.width, self.height, sizeChars[4])
self.container.setTextColor(colors.yellow)
write(self.container, 1, 3, '+')
write(self.container, 1, 5, '-')
write(self.container, 3, 1, '+')
write(self.container, 5, 1, '-')
self.container.setTextColor(colors.yellow)
write(self.container, 1, 3, '+')
write(self.container, 1, 5, '-')
write(self.container, 3, 1, '+')
write(self.container, 5, 1, '-')
local str = string.format('%d x %d', self.width - 2, self.height - 3)
write(self.container, (self.width - #str) / 2, 1, str)
local str = string.format('%d x %d', self.width - 2, self.height - 3)
write(self.container, (self.width - #str) / 2, 1, str)
else
write(self.container, 1, 1, string.rep(' ', self.width))
write(self.container, self.width, 1, ' ')
write(self.container, 1, self.height, ' ')
write(self.container, self.width, self.height, ' ')
write(self.container, 1, 3, ' ')
write(self.container, 1, 5, ' ')
end
else
write(self.container, 1, 1, string.rep(' ', self.width))
write(self.container, self.width, 1, ' ')
write(self.container, 1, self.height, ' ')
write(self.container, self.width, self.height, ' ')
write(self.container, 1, 3, ' ')
write(self.container, 1, 5, ' ')
end
end
function Process:adjustDimensions()
self.width = math.min(self.width, monDim.width)
self.height = math.min(self.height, monDim.height)
self.width = math.min(self.width, monDim.width)
self.height = math.min(self.height, monDim.height)
self.x = math.max(1, self.x)
self.y = math.max(1, self.y)
self.x = math.min(self.x, monDim.width - self.width + 1)
self.y = math.min(self.y, monDim.height - self.height + 1)
self.x = math.max(1, self.x)
self.y = math.max(1, self.y)
self.x = math.min(self.x, monDim.width - self.width + 1)
self.y = math.min(self.y, monDim.height - self.height + 1)
end
function Process:reposition()
self:adjustDimensions()
self.container.reposition(self.x, self.y, self.width, self.height)
self.container.setBackgroundColor(colors.black)
self.container.clear()
self.window.reposition(2, 3, self.width - 2, self.height - 3)
if self.window ~= self.terminal then
self.terminal.reposition(1, 1, self.width - 2, self.height - 3)
end
redraw()
self:adjustDimensions()
self.container.reposition(self.x, self.y, self.width, self.height)
self.container.setBackgroundColor(colors.black)
self.container.clear()
self.window.reposition(2, 3, self.width - 2, self.height - 3)
if self.window ~= self.terminal then
self.terminal.reposition(1, 1, self.width - 2, self.height - 3)
end
redraw()
end
function Process:click(x, y)
if y == 2 then -- title bar
if x == self.width - 2 then
self:resume('terminate')
else
self:drawSizers(not self.showSizers)
end
if y == 2 then -- title bar
if x == self.width - 2 then
self:resume('terminate')
else
self:drawSizers(not self.showSizers)
end
elseif x == 1 or y == 1 then -- sizers
self:resizeClick(x, y)
elseif x == 1 or y == 1 then -- sizers
self:resizeClick(x, y)
elseif x > 1 and x < self.width then
if self.showSizers then
self:drawSizers(false)
end
self:resume('mouse_click', 1, x - 1, y - 2)
self:resume('mouse_up', 1, x - 1, y - 2)
end
elseif x > 1 and x < self.width then
if self.showSizers then
self:drawSizers(false)
end
self:resume('mouse_click', 1, x - 1, y - 2)
self:resume('mouse_up', 1, x - 1, y - 2)
end
end
function Process:resizeClick(x, y)
if x == 1 and y == 3 then
self.height = self.height + 1
elseif x == 1 and y == 5 then
self.height = self.height - 1
elseif x == 3 and y == 1 then
self.width = self.width + 1
elseif x == 5 and y == 1 then
self.width = self.width - 1
else
return
end
self:reposition()
self:resume('term_resize')
self:drawSizers(true)
multishell.saveSession(sessionFile)
if x == 1 and y == 3 then
self.height = self.height + 1
elseif x == 1 and y == 5 then
self.height = self.height - 1
elseif x == 3 and y == 1 then
self.width = self.width + 1
elseif x == 5 and y == 1 then
self.width = self.width - 1
else
return
end
self:reposition()
self:resume('term_resize')
self:drawSizers(true)
multishell.saveSession(sessionFile)
end
function Process:resume(event, ...)
if coroutine.status(self.co) == 'dead' then
return
end
if coroutine.status(self.co) == 'dead' then
return
end
if not self.filter or self.filter == event or event == "terminate" then
--term.redirect(self.terminal)
local previousTerm = term.redirect(self.terminal)
if not self.filter or self.filter == event or event == "terminate" then
--term.redirect(self.terminal)
local previousTerm = term.redirect(self.terminal)
local previous = running
running = self -- stupid shell set title
local ok, result = coroutine.resume(self.co, event, ...)
running = previous
local previous = running
running = self -- stupid shell set title
local ok, result = coroutine.resume(self.co, event, ...)
running = previous
self.terminal = term.current()
term.redirect(previousTerm)
self.terminal = term.current()
term.redirect(previousTerm)
if ok then
self.filter = result
else
printError(result)
end
return ok, result
end
if ok then
self.filter = result
else
printError(result)
end
return ok, result
end
end
--[[ Install a multishell manager for the monitor ]]--
function multishell.getFocus()
return processes[#processes].uid
return processes[#processes].uid
end
function multishell.setFocus(uid)
local process = Util.find(processes, 'uid', uid)
local process = Util.find(processes, 'uid', uid)
if process then
local lastFocused = processes[#processes]
if lastFocused ~= process then
if process then
local lastFocused = processes[#processes]
if lastFocused ~= process then
if lastFocused then
lastFocused:focus(false)
end
if lastFocused then
lastFocused:focus(false)
end
Util.removeByValue(processes, process)
table.insert(processes, process)
Util.removeByValue(processes, process)
table.insert(processes, process)
process.container.canvas:raise()
process:focus(true)
process.container.canvas:dirty()
end
return true
end
return false
process.container.canvas:raise()
process:focus(true)
process.container.canvas:dirty()
end
return true
end
return false
end
function multishell.getTitle(uid)
local process = Util.find(processes, 'uid', uid)
if process then
return process.title
end
local process = Util.find(processes, 'uid', uid)
if process then
return process.title
end
end
function multishell.setTitle(uid, title)
local process = Util.find(processes, 'uid', uid)
if process then
process.title = title or ''
process:focus(process == processes[#processes])
end
local process = Util.find(processes, 'uid', uid)
if process then
process.title = title or ''
process:focus(process == processes[#processes])
end
end
function multishell.getCurrent()
if running then
return running.uid
end
if running then
return running.uid
end
end
function multishell.getCount()
return #processes
return #processes
end
function multishell.getTabs()
return processes
return processes
end
function multishell.launch(env, file, ...)
return multishell.openTab({
path = file,
env = env,
title = 'shell',
args = { ... },
})
return multishell.openTab({
path = file,
env = env,
title = 'shell',
args = { ... },
})
end
function multishell.openTab(tabInfo)
local process = Process:new(tabInfo)
local process = Process:new(tabInfo)
table.insert(processes, 1, process)
table.insert(processes, 1, process)
--local previousTerm = term.current()
process:resume()
--term.redirect(previousTerm)
--local previousTerm = term.current()
process:resume()
--term.redirect(previousTerm)
multishell.saveSession(sessionFile)
multishell.saveSession(sessionFile)
return process.uid
return process.uid
end
function multishell.removeProcess(process)
Util.removeByValue(processes, process)
process.container.canvas:removeLayer()
Util.removeByValue(processes, process)
process.container.canvas:removeLayer()
multishell.saveSession(sessionFile)
redraw()
multishell.saveSession(sessionFile)
redraw()
end
function multishell.saveSession(filename)
local t = { }
for _,process in ipairs(processes) do
if process.path and not process.isShell then
table.insert(t, {
x = process.x,
y = process.y,
width = process.width - 2,
height = process.height - 3,
path = process.path,
args = process.args,
})
end
end
Util.writeTable(filename, t)
local t = { }
for _,process in ipairs(processes) do
if process.path and not process.isShell then
table.insert(t, {
x = process.x,
y = process.y,
width = process.width - 2,
height = process.height - 3,
path = process.path,
args = process.args,
})
end
end
Util.writeTable(filename, t)
end
function multishell.loadSession(filename)
local config = Util.readTable(filename)
if config then
for k = #config, 1, -1 do
multishell.openTab(config[k])
end
end
local config = Util.readTable(filename)
if config then
for k = #config, 1, -1 do
multishell.openTab(config[k])
end
end
end
function multishell.stop()
multishell._stop = true
multishell._stop = true
end
function multishell.start()
while not multishell._stop do
while not multishell._stop do
local event = { os.pullEventRaw() }
local event = { os.pullEventRaw() }
if event[1] == 'terminate' then
local focused = processes[#processes]
if focused.isShell then
focused:resume('terminate')
else
break
end
if event[1] == 'terminate' then
local focused = processes[#processes]
if focused.isShell then
focused:resume('terminate')
else
break
end
elseif event[1] == 'monitor_touch' then
local x, y = event[3], event[4]
elseif event[1] == 'monitor_touch' then
local x, y = event[3], event[4]
local key, process = getProcessAt(x, y)
if process then
if key ~= #processes then
multishell.setFocus(process.uid)
multishell.saveSession(sessionFile)
end
process:click(x - process.x + 1, y - process.y + 1)
local key, process = getProcessAt(x, y)
if process then
if key ~= #processes then
multishell.setFocus(process.uid)
multishell.saveSession(sessionFile)
end
process:click(x - process.x + 1, y - process.y + 1)
else
process = processes[#processes]
if process and process.showSizers then
process.x = math.floor(x - (process.width) / 2)
process.y = y
process:reposition()
process:drawSizers(true)
multishell.saveSession(sessionFile)
end
end
else
process = processes[#processes]
if process and process.showSizers then
process.x = math.floor(x - (process.width) / 2)
process.y = y
process:reposition()
process:drawSizers(true)
multishell.saveSession(sessionFile)
end
end
elseif event[1] == 'mouse_click' or
event[1] == 'mouse_up' then
elseif event[1] == 'mouse_click' or
event[1] == 'mouse_up' then
local focused = processes[#processes]
if not focused.isShell then
multishell.setFocus(1) -- shell is always 1
else
focused:resume(unpack(event))
end
local focused = processes[#processes]
if not focused.isShell then
multishell.setFocus(1) -- shell is always 1
else
focused:resume(unpack(event))
end
elseif event[1] == 'char' or
event[1] == 'key' or
event[1] == 'key_up' or
event[1] == 'paste' then
elseif event[1] == 'char' or
event[1] == 'key' or
event[1] == 'key_up' or
event[1] == 'paste' then
local focused = processes[#processes]
if focused then
focused:resume(unpack(event))
end
local focused = processes[#processes]
if focused then
focused:resume(unpack(event))
end
else
for _,process in pairs(Util.shallowCopy(processes)) do
process:resume(unpack(event))
end
end
else
for _,process in pairs(Util.shallowCopy(processes)) do
process:resume(unpack(event))
end
end
monitor.canvas:render(parentMon)
monitor.canvas:render(parentMon)
local focused = processes[#processes]
if focused then
focused.window.restoreCursor()
end
end
local focused = processes[#processes]
if focused then
focused.window.restoreCursor()
end
end
end
--[[ Special shell process for launching programs ]]--
local function addShell()
local process = setmetatable({
x = monDim.width,
y = monDim.height,
width = 1,
height = 1,
isShell = true,
uid = nextUID(),
title = 'Terminal',
}, { __index = Process })
local process = setmetatable({
x = monDim.width,
y = monDim.height,
width = 1,
height = 1,
isShell = true,
uid = nextUID(),
title = 'Terminal',
}, { __index = Process })
function process:focus(focused)
self.window.setVisible(focused)
if focused then
self.window.restoreCursor()
else
parentTerm.clear()
parentTerm.setCursorBlink(false)
local str = 'Click screen for shell'
write(parentTerm,
math.floor((termDim.width - #str) / 2),
math.floor(termDim.height / 2),
str)
end
end
function process:focus(focused)
self.window.setVisible(focused)
if focused then
self.window.restoreCursor()
else
parentTerm.clear()
parentTerm.setCursorBlink(false)
local str = 'Click screen for shell'
write(parentTerm,
math.floor((termDim.width - #str) / 2),
math.floor(termDim.height / 2),
str)
end
end
function process:click()
end
function process:click()
end
process.container = Terminal.window(monitor, process.x, process.y+1, process.width, process.height, true)
process.window = window.create(parentTerm, 1, 1, termDim.width, termDim.height, true)
process.terminal = process.window
process.container = Terminal.window(monitor, process.x, process.y+1, process.width, process.height, true)
process.window = window.create(parentTerm, 1, 1, termDim.width, termDim.height, true)
process.terminal = process.window
process.co = coroutine.create(function()
print('To run a program on the monitor, type "fg <program>"')
print('To quit, type "exit"')
os.run(Util.shallowCopy(defaultEnv), shell.resolveProgram('shell'))
multishell.stop()
end)
process.co = coroutine.create(function()
print('To run a program on the monitor, type "fg <program>"')
print('To quit, type "exit"')
os.run(Util.shallowCopy(defaultEnv), shell.resolveProgram('shell'))
multishell.stop()
end)
table.insert(processes, process)
process:focus(true)
table.insert(processes, process)
process:focus(true)
local previousTerm = term.current()
process:resume()
term.redirect(previousTerm)
local previousTerm = term.current()
process:resume()
term.redirect(previousTerm)
end
addShell()