For example, catching every "key" event and changing any time that the "tab" key is pressed to queue as pressing the "enter" key?
This is a read-only snapshot of the ComputerCraft forums,
taken in April 2020.
Intercepting Events
Started by Selim, 19 November 2015 - 10:25 PMPosted 19 November 2015 - 11:25 PM
Is it possible to intercept an event before it can be caught and change its parameters before re-queueing it?
For example, catching every "key" event and changing any time that the "tab" key is pressed to queue as pressing the "enter" key?
For example, catching every "key" event and changing any time that the "tab" key is pressed to queue as pressing the "enter" key?
Posted 20 November 2015 - 12:15 AM
Sure, just overwrite coroutine.yeild.
Posted 20 November 2015 - 12:29 AM
Also, I made a utility for that.
http://www.computercraft.info/forums2/index.php?/topic/23974-h4x0rz-stuff-newest-randomutils/
http://www.computercraft.info/forums2/index.php?/topic/23974-h4x0rz-stuff-newest-randomutils/
Posted 20 November 2015 - 12:34 AM
Sure, just overwrite coroutine.yeild.
That would break any program that uses coroutines and doesn't just pass events through.
Posted 20 November 2015 - 12:36 AM
Umm… no it wouldn't.
Every program uses coroutines.
Every program uses coroutines.
Edited on 19 November 2015 - 11:36 PM
Posted 20 November 2015 - 12:53 AM
As KingOfGamesYami stated, every program uses coroutines, that's because the event system uses coroutine.yield.That would break any program that uses coroutines and doesn't just pass events through.
The os.pullEventRaw function looks something like this I believe
os.pullEventRaw = function( ... )
return coroutine.yield( ... )
end
So that's why it wouldn't break anythingEdit: But still, I'd recommend to modify os.pullEventRaw or os.pullEvent instead, and incercept the events there
os.pullEventRaw = function( ... )
local e = { coroutine.yield( ... ) } --# Call coroutine.yield, which is what os.pullEventRaw usually is using( so no need to backup the function )
--# Handle the events here
if e[1] == "key" then
if e[2] == keys.enter then
print( "The enter key was pressed" )
elseif e[2] == keys.tab then --# The tab key was pressed
e[2] = keys.enter --# Change it to the enter key instead
end
end
return unpack( e ) --# Return the event
end
Edited on 20 November 2015 - 12:07 AM
Posted 20 November 2015 - 01:14 AM
and doesn't just pass events through.
function test()
local co = coroutine.create(function()
print(coroutine.yield('world'))
end)
local ok, res = coroutine.resume(co)
local ok = coroutine.resume(co, 'hello ' .. res)
end
--# try it before the override
test()
--# says 'hello world'
local oldYield = coroutine.yield
function coroutine.yield(...)
local res = {oldYield(...)}
if res[1] == 'hello world' then
return 'broken'
else
return unpack(res)
end
end
--# try it after the override
test()
--# says 'broken'
Posted 20 November 2015 - 01:47 AM
That appears to be the desired behaviour.
Posted 20 November 2015 - 01:55 AM
No, you only want to change the events (the 'hello world' isn't an event).
Thus that program is broken by the modification.
Thus that program is broken by the modification.
Posted 20 November 2015 - 02:20 AM
'hello world' is an event
An event is just data given to coroutine.resume
An event is just data given to coroutine.resume
Edited on 20 November 2015 - 01:24 AM
Posted 20 November 2015 - 02:27 AM
Not in that case.
Here's another example.
Here's another example.
function test()
local co = coroutine.create(function()
print(coroutine.yield())
end)
local ok, res = coroutine.resume(co)
local ok = coroutine.resume(co, io.read('*l'))
end
--# type in 'key'
--# it says 'key'
test()
local oldYield = coroutine.yield
function coroutine.yield(...)
local res = {oldYield(...)}
if res[1] == 'key' then
return 'broken'
else
return unpack(res)
end
end
--# type in 'key'
--# it says 'broken'
test()
Posted 20 November 2015 - 02:31 AM
Again, the definition of an event is data passed to coroutine.yield.
In addition, unless he overwrites the 'key' event to return 'broken' specifically (as you did), it won't break anything. And if he does overwrite it like that, obviously it was his intention to break it.
In addition, unless he overwrites the 'key' event to return 'broken' specifically (as you did), it won't break anything. And if he does overwrite it like that, obviously it was his intention to break it.
Posted 20 November 2015 - 02:44 AM
No, the definition of an event is an arg-list of event_name,event_data…
You can resume coroutines with stuff other than events, it's just the environment that programs run in in CraftOS is being resumed with events.
Coroutines are also helpful for parsers if you don't have all the input for it available they can yield and wait for more input.
You can resume coroutines with stuff other than events, it's just the environment that programs run in in CraftOS is being resumed with events.
Coroutines are also helpful for parsers if you don't have all the input for it available they can yield and wait for more input.
Edited on 20 November 2015 - 01:44 AM
Posted 20 November 2015 - 02:57 AM
Again, the definition of an event is data passed to coroutine.yield.
Well, really that's an "all mammals are dolphins" type-statement - only the reverse is true, in that all events come from coroutine.yield! Really you can pass whatever sort of data you like back and forth between coroutines. ComputerCraft primarily has us sending event data, but that's because of the manner in which Dan designed CraftOS, the framework within which all our scripts run.
But, CoderPuppy, the entire point is to carry out the sort of translation your demonstrations are performing. Eg:
local oldYield = coroutine.yield
function coroutine.yield(...)
local res = {oldYield(...)}
if res[1] == "key" and res[2] == keys.tab then
return "key", keys.enter
else
return unpack(res)
end
end
Odds of another script using that specific set of values for "res" for something other than keyboard input? Slim. To say the least.
Yes, this would act as a system-wide translation, and that could be potentially unwanted… but who knows, as Selim hasn't said.
Posted 20 November 2015 - 03:01 AM
snip
No the whole point is to change the events, not anything using coroutines.
So basically wrap it in a coroutine (and modify the events before resuming it) or override os.pullRawEvent (or os.pullEvent).
Posted 20 November 2015 - 05:33 AM
I get what you're saying, but to say that the suggested override will "break" anything is pushing it.
Odds are a custom coroutine manager would indeed be the "neatest" way to handle things (possibly with a TLCO in front of it, depending on whether you're going for a system-wide translation or not). By all means provide Selim with an example, if you like.
Odds are a custom coroutine manager would indeed be the "neatest" way to handle things (possibly with a TLCO in front of it, depending on whether you're going for a system-wide translation or not). By all means provide Selim with an example, if you like.
Posted 20 November 2015 - 01:09 PM
Thanks, somehow I didn't think of just overriding os.pullEventRaw().