1
0
mirror of https://github.com/kepler155c/opus synced 2024-06-14 01:16:52 +00:00

multishell hooks

This commit is contained in:
kepler155c@gmail.com 2017-10-15 02:36:54 -04:00
parent 8b187f2813
commit 9b8b5238b0
7 changed files with 279 additions and 254 deletions

View File

@ -1,7 +1,7 @@
local colors = _G.colors local colors = _G.colors
local fs = _G.fs local fs = _G.fs
local os = _G.os local os = _G.os
--local shell = _ENV.shell local shell = _ENV.shell
local term = _G.term local term = _G.term
local Opus = { } local Opus = { }

View File

@ -1671,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
os.queueEvent('clipboard_copy', Util.tostring(self.selected)) os.queueEvent('clipboard_copy', self.selected)
end end
else else
return false return false

View File

@ -268,6 +268,7 @@ function page.grid:eventHandler(event)
elseif event.type == 'grid_select' then elseif event.type == 'grid_select' then
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 then if entry then
os.queueEvent('clipboard_copy', entry.rawValue) os.queueEvent('clipboard_copy', entry.rawValue)

View File

@ -20,7 +20,7 @@ local window = _G.window
local parentTerm = term.current() local parentTerm = term.current()
local w,h = parentTerm.getSize() local w,h = parentTerm.getSize()
local tabs = {} local tabs = { }
local currentTab local currentTab
local _tabId = 0 local _tabId = 0
local overviewTab local overviewTab
@ -29,6 +29,9 @@ local tabsDirty = false
local closeInd = '*' local closeInd = '*'
local redrawTimer local redrawTimer
local hooks = { } local hooks = { }
local control
local hotkeys = { }
local downState = { }
multishell.term = term.current() multishell.term = term.current()
@ -77,65 +80,11 @@ end
local function redrawMenu() local function redrawMenu()
if not tabsDirty then if not tabsDirty then
os.queueEvent('multishell', 'draw') os.queueEvent('multishell_redraw')
tabsDirty = true tabsDirty = true
end end
end end
-- Draw menu
local function draw()
tabsDirty = false
parentTerm.setBackgroundColor( _colors.tabBarBackgroundColor )
if currentTab and currentTab.isOverview then
parentTerm.setTextColor( _colors.focusTextColor )
else
parentTerm.setTextColor( _colors.tabBarTextColor )
end
parentTerm.setCursorPos( 1, 1 )
parentTerm.clearLine()
parentTerm.write('+')
local tabX = 2
local function compareTab(a, b)
return a.tabId < b.tabId
end
for _,tab in Util.spairs(tabs, compareTab) do
if tab.hidden and tab ~= currentTab or tab.isOverview then
tab.sx = nil
tab.ex = nil
else
tab.sx = tabX + 1
tab.ex = tabX + #tab.title
tabX = tabX + #tab.title + 1
end
end
for _,tab in Util.spairs(tabs) do
if tab.sx then
if tab == currentTab then
parentTerm.setTextColor(_colors.focusTextColor)
parentTerm.setBackgroundColor(_colors.focusBackgroundColor)
else
parentTerm.setTextColor(_colors.textColor)
parentTerm.setBackgroundColor(_colors.backgroundColor)
end
parentTerm.setCursorPos(tab.sx, 1)
parentTerm.write(tab.title)
end
end
if currentTab and not currentTab.isOverview then
parentTerm.setTextColor(_colors.focusTextColor)
parentTerm.setBackgroundColor(_colors.backgroundColor)
parentTerm.setCursorPos( w, 1 )
parentTerm.write(closeInd)
end
if currentTab then
currentTab.window.restoreCursor()
end
end
local function selectTab(tab) local function selectTab(tab)
if not tab then if not tab then
for _,ftab in pairs(tabs) do for _,ftab in pairs(tabs) do
@ -222,7 +171,7 @@ local function launchProcess(tab)
local e, code = os.pullEventRaw('key') local e, code = os.pullEventRaw('key')
if e == 'terminate' or e == 'key' and code == keys.enter then if e == 'terminate' or e == 'key' and code == keys.enter then
if tab.isOverview then if tab.isOverview then
os.queueEvent('multishell', 'terminate') -- os.queueEvent('multishell', 'terminate')
end end
break break
end end
@ -249,49 +198,6 @@ local function launchProcess(tab)
return tab return tab
end end
local function resizeWindows()
local windowY = 2
local windowHeight = h-1
for _,key in pairs(Util.keys(tabs)) do
local tab = tabs[key]
local x,y = tab.window.getCursorPos()
if y > windowHeight then
tab.window.scroll( y - windowHeight )
tab.window.setCursorPos( x, windowHeight )
end
tab.window.reposition( 1, windowY, w, windowHeight )
end
-- Pass term_resize to all processes
for _,key in pairs(Util.keys(tabs)) do
resumeTab(tabs[key], "term_resize")
end
end
local control
local hotkeys = { }
local function processKeyEvent(event, code)
if event == 'key_up' then
if code == keys.leftCtrl or code == keys.rightCtrl then
control = false
end
elseif event == 'char' then
control = false
elseif event == 'key' then
if code == keys.leftCtrl or code == keys.rightCtrl then
control = true
elseif control then
local hotkey = hotkeys[code]
control = false
if hotkey then
hotkey()
end
end
end
end
function multishell.addHotkey(code, fn) function multishell.addHotkey(code, fn)
hotkeys[code] = fn hotkeys[code] = fn
end end
@ -340,10 +246,8 @@ function multishell.getTab(tabId)
end end
function multishell.terminate(tabId) function multishell.terminate(tabId)
local tab = tabs[tabId] os.queueEvent('multishell_terminate', tabId)
if tab and not tab.isOverview then --[[
if coroutine.status(tab.co) ~= 'dead' then
resumeTab(tab, "terminate")
else else
tabs[tabId] = nil tabs[tabId] = nil
if tab == currentTab then if tab == currentTab then
@ -356,6 +260,7 @@ function multishell.terminate(tabId)
redrawMenu() redrawMenu()
end end
end end
]]
end end
function multishell.getTabs() function multishell.getTabs()
@ -434,7 +339,7 @@ function multishell.showMessage(text)
end end
function multishell.hook(event, fn) function multishell.hook(event, fn)
if type(event) == table then if type(event) == 'table' then
for _,v in pairs(event) do for _,v in pairs(event) do
multishell.hook(v, fn) multishell.hook(v, fn)
end end
@ -446,46 +351,190 @@ function multishell.hook(event, fn)
end end
end end
-- control-o - overview multishell.hook('multishell_terminate', function(_, eventData)
multishell.addHotkey(24, function() local tabId = eventData[1] or -1
multishell.setFocus(overviewTab.tabId)
end)
-- control-backspace
multishell.addHotkey(14, function()
local tabId = multishell.getFocus()
local tab = tabs[tabId] local tab = tabs[tabId]
if not tab.isOverview then
os.queueEvent('multishell', 'terminateTab', tabId) if tab and not tab.isOverview then
tab = Util.shallowCopy(tab) if coroutine.status(tab.co) ~= 'dead' then
tab.isDead = false resumeTab(tab, "terminate")
tab.focused = true end
multishell.openTab(tab)
end end
return true
end) end)
-- control-tab - next tab multishell.hook('multishell_redraw', function()
multishell.addHotkey(15, function() tabsDirty = false
parentTerm.setBackgroundColor( _colors.tabBarBackgroundColor )
if currentTab and currentTab.isOverview then
parentTerm.setTextColor( _colors.focusTextColor )
else
parentTerm.setTextColor( _colors.tabBarTextColor )
end
parentTerm.setCursorPos( 1, 1 )
parentTerm.clearLine()
parentTerm.write('+')
local tabX = 2
local function compareTab(a, b) local function compareTab(a, b)
return a.tabId < b.tabId return a.tabId < b.tabId
end end
local visibleTabs = { }
for _,tab in Util.spairs(tabs, compareTab) do for _,tab in Util.spairs(tabs, compareTab) do
if not tab.hidden then
table.insert(visibleTabs, tab) if tab.hidden and tab ~= currentTab or tab.isOverview then
tab.sx = nil
tab.ex = nil
else
tab.sx = tabX + 1
tab.ex = tabX + #tab.title
tabX = tabX + #tab.title + 1
end end
end end
for k,tab in ipairs(visibleTabs) do for _,tab in Util.spairs(tabs) do
if tab.tabId == currentTab.tabId then if tab.sx then
if k < #visibleTabs then if tab == currentTab then
multishell.setFocus(visibleTabs[k + 1].tabId) parentTerm.setTextColor(_colors.focusTextColor)
return parentTerm.setBackgroundColor(_colors.focusBackgroundColor)
else
parentTerm.setTextColor(_colors.textColor)
parentTerm.setBackgroundColor(_colors.backgroundColor)
end
parentTerm.setCursorPos(tab.sx, 1)
parentTerm.write(tab.title)
end
end
if currentTab and not currentTab.isOverview then
parentTerm.setTextColor(_colors.focusTextColor)
parentTerm.setBackgroundColor(_colors.backgroundColor)
parentTerm.setCursorPos( w, 1 )
parentTerm.write(closeInd)
end
if currentTab then
currentTab.window.restoreCursor()
end
return true
end)
multishell.hook('term_resize', function(_, eventData)
if not eventData[1] then --- TEST
w,h = parentTerm.getSize()
local windowY = 2
local windowHeight = h-1
for _,key in pairs(Util.keys(tabs)) do
local tab = tabs[key]
local x,y = tab.window.getCursorPos()
if y > windowHeight then
tab.window.scroll( y - windowHeight )
tab.window.setCursorPos( x, windowHeight )
end
tab.window.reposition( 1, windowY, w, windowHeight )
end
redrawMenu()
end
end)
-- downstate should be stored in the tab
multishell.hook('key_up', function(_, eventData)
local code = eventData[1]
if code == keys.leftCtrl or code == keys.rightCtrl then
control = false
end
if downState[code] ~= currentTab then
downState[code] = nil
return true
end
downState[code] = nil
end)
multishell.hook('char', function()
control = false -- is this right ??
end)
multishell.hook('key', function(_, eventData)
local code = eventData[1]
local firstPress = not eventData[2]
if firstPress then
downState[code] = currentTab
if code == keys.leftCtrl or code == keys.rightCtrl then
control = true
elseif control then
local hotkey = hotkeys[code]
--control = false
if hotkey then
hotkey()
end end
end end
else
--key was pressed initially in a previous window
if downState[code] ~= currentTab then
return true
end
end end
if #visibleTabs > 0 then end)
multishell.setFocus(visibleTabs[1].tabId)
multishell.hook({ 'mouse_click' }, function(_, eventData)
local x, y = eventData[2], eventData[3]
if y == 1 then
if x == 1 then
multishell.setFocus(overviewTab.tabId)
elseif x == w then
if currentTab then
multishell.terminate(currentTab.tabId)
end
else
for _,tab in pairs(tabs) do
if not tab.hidden and tab.sx then
if x >= tab.sx and x <= tab.ex then
multishell.setFocus(tab.tabId)
break
end
end
end
end
downState.mouse = nil
return true
end end
downState.mouse = currentTab
eventData[3] = eventData[3] - 1
end)
multishell.hook({ 'mouse_up', 'mouse_drag' }, function(event, eventData)
if downState.mouse ~= currentTab then
-- don't send mouse up as the mouse click event was on another window
if event == 'mouse_up' then
downState.mouse = nil
end
return true -- stop propagation
end
eventData[3] = eventData[3] - 1
end)
multishell.hook({ 'mouse_scroll' }, function(_, eventData)
local dir, y = eventData[1], eventData[3]
if y == 1 then
return true
end
if currentTab.terminal.scrollUp then
if dir == -1 then
currentTab.terminal.scrollUp()
else
currentTab.terminal.scrollDown()
end
end
eventData[3] = y - 1
end) end)
local function startup() local function startup()
@ -513,9 +562,6 @@ local function startup()
end end
end end
-- Begin
--parentTerm.clear()
multishell.openTab({ multishell.openTab({
focused = true, focused = true,
fn = startup, fn = startup,
@ -527,115 +573,42 @@ if not currentTab then
multishell.setFocus(overviewTab.tabId) multishell.setFocus(overviewTab.tabId)
end end
draw() redrawMenu()
local lastClicked local currentTabEvents = Util.transpose {
'char', 'key', 'key_up',
'mouse_click', 'mouse_drag', 'mouse_scroll', 'mouse_up',
'paste', 'terminate',
}
while true do while true do
-- 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 local stopPropagation
if sEvent == 'key_up' then
processKeyEvent(sEvent, tEventData[1])
end
if sEvent == 'timer' and tEventData[1] == redrawTimer then if sEvent == 'timer' and tEventData[1] == redrawTimer then
redrawMenu() redrawMenu()
end end
local hk = hooks[sEvent] local eventHooks = hooks[sEvent]
if hk then if eventHooks then
for _,fn in pairs(hk) do for _,fn in pairs(eventHooks) do
fn(sEvent, tEventData) stopPropagation = fn(sEvent, tEventData)
if stopPropagation then
break
end
end end
end end
if sEvent == "term_resize" then if not stopPropagation then
-- Resize event if currentTabEvents[sEvent] then
w,h = parentTerm.getSize() resumeTab(currentTab, sEvent, tEventData)
resizeWindows()
redrawMenu()
elseif sEvent == 'multishell' then else
local action = tEventData[1] -- Passthrough to all processes
for _,key in pairs(Util.keys(tabs)) do
if action == 'terminate' then resumeTab(tabs[key], sEvent, tEventData)
break
elseif action == 'terminateTab' then
multishell.terminate(tEventData[2])
elseif action == 'draw' then
draw()
end
elseif sEvent == "paste" then
resumeTab(currentTab, sEvent, tEventData)
elseif sEvent == "char" or
sEvent == "key" or
sEvent == "terminate" then
processKeyEvent(sEvent, tEventData[1])
-- Keyboard event - Passthrough to current process
resumeTab(currentTab, sEvent, tEventData)
elseif sEvent == "mouse_click" then
local button, x, y = tEventData[1], tEventData[2], tEventData[3]
lastClicked = nil
if y == 1 then
-- Switch process
if x == 1 then
multishell.setFocus(overviewTab.tabId)
elseif x == w then
if currentTab then
multishell.terminate(currentTab.tabId)
end
else
for _,tab in pairs(tabs) do
if not tab.hidden and tab.sx then
if x >= tab.sx and x <= tab.ex then
multishell.setFocus(tab.tabId)
break
end
end
end
end end
elseif currentTab then
-- Passthrough to current process
lastClicked = currentTab
resumeTab(currentTab, sEvent, { button, x, y-1 })
end
elseif sEvent == "mouse_up" then
if currentTab and lastClicked == currentTab then
local button, x, y = tEventData[1], tEventData[2], tEventData[3]
resumeTab(currentTab, sEvent, { button, x, y-1 })
end
elseif sEvent == "mouse_drag" or sEvent == "mouse_scroll" then
-- Other mouse event
local p1, x, y = tEventData[1], tEventData[2], tEventData[3]
if currentTab and (y ~= 1) then
if currentTab.terminal.scrollUp then
if p1 == -1 then
currentTab.terminal.scrollUp()
else
currentTab.terminal.scrollDown()
end
else
-- Passthrough to current process
resumeTab(currentTab, sEvent, { p1, x, y-1 })
end
end
elseif passthrough then
-- Other event
-- Passthrough to all processes
for _,key in pairs(Util.keys(tabs)) do
resumeTab(tabs[key], sEvent, tEventData)
end end
end end
end end

View File

@ -2,52 +2,44 @@ _G.requireInjector()
local Util = require('util') local Util = require('util')
local keys = _G.keys
local multishell = _ENV.multishell local multishell = _ENV.multishell
local os = _G.os local textutils = _G.textutils
local clipboard = { } local clipboard = { }
function clipboard.getData()
return clipboard.data
end
function clipboard.setData(data)
clipboard.data = data
if data then
clipboard.useInternal(true)
end
end
function clipboard.getText() function clipboard.getText()
if clipboard.data then if clipboard.data then
if type(clipboard.data) == 'table' then
local s, m = pcall(textutils.serialize, clipboard.data)
clipboard.data = (s and m) or Util.tostring(clipboard.data)
end
return Util.tostring(clipboard.data) return Util.tostring(clipboard.data)
end end
end end
function clipboard.isInternal()
return clipboard.internal
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') local text = 'Clipboard (^m): ' .. ((mode and 'internal') or 'normal')
multishell.showMessage(text) multishell.showMessage(text)
os.queueEvent('clipboard_mode', mode)
end end
end end
multishell.hook('clipboard_copy', function(_, args) multishell.hook('clipboard_copy', function(_, args)
clipboard.setData(args[1]) clipboard.data = args[1]
if clipboard.data then
clipboard.useInternal(true)
end
end) end)
multishell.hook('paste', function(_, args) multishell.hook('paste', function(_, args)
if clipboard.isInternal() then if clipboard.internal then
args[1] = clipboard.getText() or '' args[1] = clipboard.getText() or ''
end end
end) end)
-- control-m - clipboard mode -- control-m - toggle clipboard mode
multishell.addHotkey(50, function() multishell.addHotkey(keys.m, function()
clipboard.useInternal(not clipboard.isInternal()) clipboard.useInternal(not clipboard.internal)
end) end)

58
sys/autorun/hotkeys.lua Normal file
View File

@ -0,0 +1,58 @@
_G.requireInjector()
local Util = require('util')
local keys = _G.keys
local multishell = _ENV.multishell
-- control-o - overview
multishell.addHotkey(keys.o, function()
for _,tab in pairs(multishell.getTabs()) do
if tab.isOverview then
multishell.setFocus(tab.tabId)
end
end
end)
-- control-backspace - restart tab
multishell.addHotkey(keys.backspace, function()
local tabs = multishell.getTabs()
local tabId = multishell.getFocus()
local tab = tabs[tabId]
if not tab.isOverview then
multishell.terminate(tabId)
tab = Util.shallowCopy(tab)
tab.isDead = false
tab.focused = true
multishell.openTab(tab)
end
end)
-- control-tab - next tab
multishell.addHotkey(keys.tab, function()
local tabs = multishell.getTabs()
local visibleTabs = { }
local currentTabId = multishell.getFocus()
local function compareTab(a, b)
return a.tabId < b.tabId
end
for _,tab in Util.spairs(tabs, compareTab) do
if not tab.hidden then
table.insert(visibleTabs, tab)
end
end
for k,tab in ipairs(visibleTabs) do
if tab.tabId == currentTabId then
if k < #visibleTabs then
multishell.setFocus(visibleTabs[k + 1].tabId)
return
end
end
end
if #visibleTabs > 0 then
multishell.setFocus(visibleTabs[1].tabId)
end
end)

View File

@ -3,6 +3,7 @@ _G.requireInjector()
local Terminal = require('terminal') local Terminal = require('terminal')
local Util = require('util') local Util = require('util')
local keys = _G.keys
local multishell = _ENV.multishell local multishell = _ENV.multishell
local os = _G.os local os = _G.os
local term = _G.term local term = _G.term
@ -25,7 +26,7 @@ end
print('Debug started') print('Debug started')
print('Press ^d to activate debug window') print('Press ^d to activate debug window')
multishell.addHotkey(32, function() multishell.addHotkey(keys.d, function()
local currentId = multishell.getFocus() local currentId = multishell.getFocus()
if currentId ~= tabId then if currentId ~= tabId then
previousId = currentId previousId = currentId
@ -40,4 +41,4 @@ os.pullEventRaw('terminate')
print('Debug stopped') print('Debug stopped')
_G.debug = function() end _G.debug = function() end
multishell.removeHotkey(32) multishell.removeHotkey(keys.d)