multishell hooks

This commit is contained in:
kepler155c@gmail.com 2017-10-14 03:41:54 -04:00
parent 153b0b86ff
commit 8b187f2813
8 changed files with 135 additions and 67 deletions

View File

@ -6,7 +6,6 @@ local Util = require('util')
local _rep = string.rep local _rep = string.rep
local _sub = string.sub local _sub = string.sub
local clipboard = _G.clipboard
local colors = _G.colors local colors = _G.colors
local device = _G.device local device = _G.device
local fs = _G.fs local fs = _G.fs
@ -1672,7 +1671,7 @@ function UI.Grid:eventHandler(event)
end end
elseif event.type == 'copy' then elseif event.type == 'copy' then
if self.selected then if self.selected then
clipboard.setData(Util.tostring(self.selected)) os.queueEvent('clipboard_copy', Util.tostring(self.selected))
end end
else else
return false return false
@ -2689,7 +2688,7 @@ function UI.TextEntry:eventHandler(event)
return true return true
elseif event.type == 'copy' then elseif event.type == 'copy' then
clipboard.setData(self.value) os.queueEvent('clipboard_copy', self.value)
elseif event.type == 'paste' then elseif event.type == 'paste' then
local input = tostring(self.value) local input = tostring(self.value)

View File

@ -7,13 +7,14 @@ local Peripheral = require('peripheral')
local UI = require('ui') local UI = require('ui')
local Util = require('util') local Util = require('util')
local clipboard = _G.clipboard local colors = _G.colors
local multishell = _ENV.multishell local multishell = _ENV.multishell
local os = _G.os
local textutils = _G.textutils local textutils = _G.textutils
local sandboxEnv = setmetatable(Util.shallowCopy(_ENV), { __index = _G }) local sandboxEnv = setmetatable(Util.shallowCopy(_ENV), { __index = _G })
sandboxEnv.exit = function() Event.exitPullEvents() end sandboxEnv.exit = function() Event.exitPullEvents() end
sandboxEnv._echo = function( ... ) return ... end sandboxEnv._echo = function( ... ) return { ... } end
injector(sandboxEnv) injector(sandboxEnv)
multishell.setTitle(multishell.getCurrent(), 'Lua') multishell.setTitle(multishell.getCurrent(), 'Lua')
@ -21,6 +22,7 @@ UI:configure('Lua', ...)
local command = '' local command = ''
local history = History.load('usr/.lua_history', 25) local history = History.load('usr/.lua_history', 25)
local extChars = Util.getVersion() > 1.76
local page = UI.Page { local page = UI.Page {
menuBar = UI.MenuBar { menuBar = UI.MenuBar {
@ -42,6 +44,10 @@ local page = UI.Page {
[ 'control-space' ] = 'autocomplete', [ 'control-space' ] = 'autocomplete',
}, },
}, },
indicator = UI.Text {
backgroundColor = colors.black,
y = 2, x = -1, width = 1,
},
grid = UI.ScrollingGrid { grid = UI.ScrollingGrid {
y = 3, y = 3,
columns = { columns = {
@ -54,6 +60,17 @@ local page = UI.Page {
notification = UI.Notification(), notification = UI.Notification(),
} }
function page.indicator:showResult(s)
local values = {
[ true ] = { c = colors.green, i = (extChars and '\003') or '+' },
[ false ] = { c = colors.red, i = 'x' }
}
self.textColor = values[s].c
self.value = values[s].i
self:draw()
end
function page:setPrompt(value, focus) function page:setPrompt(value, focus)
self.prompt:setValue(value) self.prompt:setValue(value)
self.prompt.scroll = 0 self.prompt.scroll = 0
@ -76,7 +93,6 @@ function page:enable()
end end
local function autocomplete(env, oLine, x) local function autocomplete(env, oLine, x)
local sLine = oLine:sub(1, x) local sLine = oLine:sub(1, x)
local nStartPos = sLine:find("[a-zA-Z0-9_%.]+$") local nStartPos = sLine:find("[a-zA-Z0-9_%.]+$")
if nStartPos then if nStartPos then
@ -109,7 +125,6 @@ local function autocomplete(env, oLine, x)
end end
function page:eventHandler(event) function page:eventHandler(event)
if event.type == 'global' then if event.type == 'global' then
self:setPrompt('', true) self:setPrompt('', true)
self:executeStatement('_G') self:executeStatement('_G')
@ -220,7 +235,6 @@ function page:setResult(result)
end end
function page.grid:eventHandler(event) function page.grid:eventHandler(event)
local entry = self:getSelected() local entry = self:getSelected()
local function commandAppend() local function commandAppend()
@ -255,8 +269,8 @@ function page.grid:eventHandler(event)
page:setPrompt(commandAppend(), true) page:setPrompt(commandAppend(), true)
page:executeStatement(commandAppend()) page:executeStatement(commandAppend())
elseif event.type == 'copy' then elseif event.type == 'copy' then
if entry and clipboard then if entry then
clipboard.setData(entry.rawValue) os.queueEvent('clipboard_copy', entry.rawValue)
end end
else else
return UI.ScrollingGrid.eventHandler(self, event) return UI.ScrollingGrid.eventHandler(self, event)
@ -265,10 +279,16 @@ function page.grid:eventHandler(event)
end end
function page:rawExecute(s) function page:rawExecute(s)
local fn, m = load('return _echo(' ..s.. ');', 'lua', nil, sandboxEnv) local fn, m
fn = load('return (' ..s.. ')', 'lua', nil, sandboxEnv)
if fn then if fn then
m = { pcall(fn) } fn = load('return {' ..s.. '}', 'lua', nil, sandboxEnv)
fn = table.remove(m, 1) end
if fn then
fn, m = pcall(fn)
if #m == 1 then if #m == 1 then
m = m[1] m = m[1]
end end
@ -284,7 +304,6 @@ function page:rawExecute(s)
end end
function page:executeStatement(statement) function page:executeStatement(statement)
command = statement command = statement
local s, m = self:rawExecute(command) local s, m = self:rawExecute(command)
@ -298,6 +317,7 @@ function page:executeStatement(statement)
self.notification:error(m, 5) self.notification:error(m, 5)
end end
end end
self.indicator:showResult(not not s)
end end
local args = { ... } local args = { ... }

View File

@ -27,6 +27,8 @@ local overviewTab
local runningTab local runningTab
local tabsDirty = false local tabsDirty = false
local closeInd = '*' local closeInd = '*'
local redrawTimer
local hooks = { }
multishell.term = term.current() multishell.term = term.current()
@ -417,16 +419,38 @@ function multishell.getCount()
return Util.size(tabs) return Util.size(tabs)
end end
function multishell.showMessage(text)
parentTerm.setCursorPos(3, 1)
parentTerm.setTextColor(_colors.textColor)
parentTerm.setBackgroundColor(_colors.backgroundColor)
if #text + 3 < w then
text = text .. string.rep(' ', w - #text - 3)
end
parentTerm.write(text)
redrawTimer = os.startTimer(2)
if currentTab then
currentTab.window.restoreCursor()
end
end
function multishell.hook(event, fn)
if type(event) == table then
for _,v in pairs(event) do
multishell.hook(v, fn)
end
else
if not hooks[event] then
hooks[event] = { }
end
table.insert(hooks[event], 1, fn)
end
end
-- control-o - overview -- control-o - overview
multishell.addHotkey(24, function() multishell.addHotkey(24, function()
multishell.setFocus(overviewTab.tabId) multishell.setFocus(overviewTab.tabId)
end) end)
-- control-t - toggle clipboard mode
multishell.addHotkey(20, function()
_G.clipboard.useInternal(not _G.clipboard.isInternal())
end)
-- control-backspace -- control-backspace
multishell.addHotkey(14, function() multishell.addHotkey(14, function()
local tabId = multishell.getFocus() local tabId = multishell.getFocus()
@ -512,11 +536,23 @@ while true do
-- Get the event -- Get the event
local tEventData = { os.pullEventRaw() } local tEventData = { os.pullEventRaw() }
local sEvent = table.remove(tEventData, 1) local sEvent = table.remove(tEventData, 1)
local passthrough = true
if sEvent == 'key_up' then if sEvent == 'key_up' then
processKeyEvent(sEvent, tEventData[1]) processKeyEvent(sEvent, tEventData[1])
end end
if sEvent == 'timer' and tEventData[1] == redrawTimer then
redrawMenu()
end
local hk = hooks[sEvent]
if hk then
for _,fn in pairs(hk) do
fn(sEvent, tEventData)
end
end
if sEvent == "term_resize" then if sEvent == "term_resize" then
-- Resize event -- Resize event
w,h = parentTerm.getSize() w,h = parentTerm.getSize()
@ -535,11 +571,7 @@ while true do
end end
elseif sEvent == "paste" then elseif sEvent == "paste" then
if _G.clipboard.isInternal() then resumeTab(currentTab, sEvent, tEventData)
resumeTab(currentTab, sEvent, { _G.clipboard.getText() or '' })
else
resumeTab(currentTab, sEvent, tEventData)
end
elseif sEvent == "char" or elseif sEvent == "char" or
sEvent == "key" or sEvent == "key" or
@ -599,7 +631,7 @@ while true do
end end
end end
else elseif passthrough then
-- Other event -- Other event
-- Passthrough to all processes -- Passthrough to all processes
for _,key in pairs(Util.keys(tabs)) do for _,key in pairs(Util.keys(tabs)) do

View File

@ -44,28 +44,21 @@ local function tokenise( ... )
return tWords return tWords
end end
local function run(env, command, ...) local function run(env, ...)
if not command then local args = tokenise(...)
error('No such program') local command = table.remove(args, 1) or error('No such program')
end local isUrl = not not command:match("^(https?:)")
local isUrl = not not command:match("^(https?:)//(([^/:]+):?([0-9]*))(/?.*)$")
local path, runFn
local path, loadFn
if isUrl then if isUrl then
path = command path = command
runFn = Util.loadUrl loadFn = Util.loadUrl
else else
path = shell.resolveProgram(command) path = shell.resolveProgram(command) or error('No such program')
runFn = loadfile loadFn = loadfile
end end
if not path then local fn, err = loadFn(path, env)
error('No such program')
end
local fn, err = runFn(path, env)
if not fn then if not fn then
error(err) error(err)
end end
@ -80,7 +73,7 @@ local function run(env, command, ...)
tProgramStack[#tProgramStack + 1] = path tProgramStack[#tProgramStack + 1] = path
end end
local r = { fn(table.unpack(tokenise(...))) } local r = { fn(table.unpack(args)) }
tProgramStack[#tProgramStack] = nil tProgramStack[#tProgramStack] = nil
@ -124,7 +117,6 @@ function shell.resolve( _sPath )
end end
function shell.resolveProgram( _sCommand ) function shell.resolveProgram( _sCommand )
if tAliases[_sCommand] ~= nil then if tAliases[_sCommand] ~= nil then
_sCommand = tAliases[_sCommand] _sCommand = tAliases[_sCommand]
end end
@ -299,13 +291,15 @@ function shell.aliases()
return tCopy return tCopy
end end
function shell.newTab(tabInfo, path, ...) function shell.newTab(tabInfo, ...)
local args = tokenise(...)
local path = table.remove(args, 1)
path = shell.resolveProgram(path) path = shell.resolveProgram(path)
if path then if path then
tabInfo.path = path tabInfo.path = path
tabInfo.env = sandboxEnv tabInfo.env = sandboxEnv
tabInfo.args = tokenise(...) tabInfo.args = args
tabInfo.title = fs.getName(path) tabInfo.title = fs.getName(path)
if path ~= 'sys/apps/shell' then if path ~= 'sys/apps/shell' then
@ -661,10 +655,9 @@ while not bExit do
end end
term.setTextColour(_colors.textColor) term.setTextColour(_colors.textColor)
if #sLine > 0 then if #sLine > 0 then
local args = tokenise(sLine) local result, err = shell.run(sLine)
local result, err = shell.run(table.remove(args, 1), table.unpack(args))
if not result and err then if not result and err then
_G.printError(err) _G.printError(err)
end end
end end
end end

View File

@ -1,10 +1,9 @@
if _G.clipboard then
return
end
_G.requireInjector() _G.requireInjector()
local Util = require('util') local Util = require('util')
local os = _G.os
local multishell = _ENV.multishell
local os = _G.os
local clipboard = { } local clipboard = { }
@ -32,8 +31,23 @@ end
function clipboard.useInternal(mode) function clipboard.useInternal(mode)
if mode ~= clipboard.internal then if mode ~= clipboard.internal then
clipboard.internal = mode clipboard.internal = mode
local text = 'Clipboard (^m): ' .. ((mode and 'internal') or 'normal')
multishell.showMessage(text)
os.queueEvent('clipboard_mode', mode) os.queueEvent('clipboard_mode', mode)
end end
end end
_G.clipboard = clipboard multishell.hook('clipboard_copy', function(_, args)
clipboard.setData(args[1])
end)
multishell.hook('paste', function(_, args)
if clipboard.isInternal() then
args[1] = clipboard.getText() or ''
end
end)
-- control-m - clipboard mode
multishell.addHotkey(50, function()
clipboard.useInternal(not clipboard.isInternal())
end)

View File

@ -1,4 +1,9 @@
-- Loads the Opus environment regardless if the file system is local or not -- Loads the Opus environment regardless if the file system is local or not
local colors = _G.colors
local fs = _G.fs
local http = _G.http
local shell = _ENV.shell
local term = _G.term
local w, h = term.getSize() local w, h = term.getSize()
term.setTextColor(colors.white) term.setTextColor(colors.white)
@ -34,7 +39,7 @@ local BASE = 'https://raw.githubusercontent.com/' .. GIT_REPO
local function makeEnv() local function makeEnv()
local env = setmetatable({ }, { __index = _G }) local env = setmetatable({ }, { __index = _G })
for k,v in pairs(_ENV) do for k,v in pairs(_ENV) do
env[k] = v env[k] = v
end end
return env return env
end end
@ -51,10 +56,10 @@ end
local function runUrl(file, ...) local function runUrl(file, ...)
local url = BASE .. '/' .. file local url = BASE .. '/' .. file
local h = http.get(url) local u = http.get(url)
if h then if u then
local fn = load(h.readAll(), url, nil, makeEnv()) local fn = load(u.readAll(), url, nil, makeEnv())
h.close() u.close()
if fn then if fn then
return fn(...) return fn(...)
end end
@ -108,7 +113,7 @@ if config.aliases then
end end
end end
shell.setPath(config.path) shell.setPath(config.path)
LUA_PATH = config.lua_path _ENV.LUA_PATH = config.lua_path
-- extensions -- extensions
local dir = 'sys/extensions' local dir = 'sys/extensions'

View File

@ -3,6 +3,12 @@ local GPS = require('gps')
local Socket = require('socket') local Socket = require('socket')
local Util = require('util') local Util = require('util')
local device = _G.device
local multishell = _ENV.multishell
local network = _G.network
local os = _G.os
local turtle = _G.turtle
-- move this into gps api -- move this into gps api
local gpsRequested local gpsRequested
local gpsLastPoint local gpsLastPoint
@ -17,7 +23,7 @@ local function snmpConnection(socket)
end end
if msg.type == 'reboot' then if msg.type == 'reboot' then
os.reboot() os.reboot()
elseif msg.type == 'shutdown' then elseif msg.type == 'shutdown' then
os.shutdown() os.shutdown()
@ -26,20 +32,19 @@ local function snmpConnection(socket)
socket:write('pong') socket:write('pong')
elseif msg.type == 'script' then elseif msg.type == 'script' then
local fn, msg = loadstring(msg.args, 'script') local fn, err = loadstring(msg.args, 'script')
if fn then if fn then
multishell.openTab({ multishell.openTab({
fn = fn, fn = fn,
env = getfenv(1),
title = 'script', title = 'script',
}) })
else else
printError(msg) _G.printError(err)
end end
elseif msg.type == 'scriptEx' then elseif msg.type == 'scriptEx' then
local s, m = pcall(function() local s, m = pcall(function()
local env = setmetatable(Util.shallowCopy(getfenv(1)), { __index = _G }) local env = setmetatable(Util.shallowCopy(_ENV), { __index = _G })
local fn, m = load(msg.args, 'script', nil, env) local fn, m = load(msg.args, 'script', nil, env)
if not fn then if not fn then
error(m) error(m)
@ -110,7 +115,7 @@ end)
device.wireless_modem.open(999) device.wireless_modem.open(999)
print('discovery: listening on port 999') print('discovery: listening on port 999')
Event.on('modem_message', function(e, s, sport, id, info, distance) Event.on('modem_message', function(_, _, sport, id, info, distance)
if sport == 999 and tonumber(id) and type(info) == 'table' then if sport == 999 and tonumber(id) and type(info) == 'table' then
if not network[id] then if not network[id] then
network[id] = { } network[id] = { }

View File

@ -2,7 +2,7 @@ local device = _G.device
local multishell = _ENV.multishell local multishell = _ENV.multishell
local os = _G.os local os = _G.os
if device.wireless_modem then if device.wireless_modem and false then
multishell.setTitle(multishell.getCurrent(), 'Chat') multishell.setTitle(multishell.getCurrent(), 'Chat')