This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
cmdpwnd's profile picture

Detect custom key combos on automated script?

Started by cmdpwnd, 20 March 2016 - 02:40 AM
cmdpwnd #1
Posted 20 March 2016 - 03:40 AM
OQIs there a way to detect a key combination for an interrupt similar to how CraftOS terminates a program with ctrl + T? This would be implemented in a program where the computer is left unattended and no events are being thrown while the program is running. (hence if yielding, the computer would hang)

I have a completely isolated computer. a user can interact with this computer. the computer is running a program. the program will detect if a user enters a key sequence such as CTRL+D. if this sequence is detected, the program will call another function within the same program which is a CLI [aka console or shell]. once the user is finished with the CLI they will 'exit' the CLI and the loop which was running to detect the key sequence will again be running, as the CLI returned because it is simply a function.

How can I do this?


function console()
  --console
end

function run()
  while true do
	if ([key sequence]) then
	  console()
	else
	  --run program normally
	end
  end
end

ANSWER

function other()
    print('Ctrl+D Detected!')
end

function run()
    local counter = 0
    while true do
        local event, key = os.pullEvent()
        if event == 'key' and key == keys.leftCtrl then
            counter = 1
        elseif event == 'key_up' and key == keys.leftCtrl then
            counter = 0
        end
        if event == 'key' and key == keys.d and counter == 1 then
            other()
        end
    end
end

run()
Credit: Bomb Bloke
Edited on 21 March 2016 - 09:01 PM
Bomb Bloke #2
Posted 20 March 2016 - 05:05 AM
You can't ever prevent events from being thrown - only from being caught. And if you're not catching events, then how would you catch Ctrl+T? That's putting aside that ComputerCraft will kill your script if it fails to yield regularly… the closest you could get would be to yield using an event filter set to something that can never occur.

Anyway, it's not so much CraftOS that handles Ctrl+T so much as it's os.pullEvent(). That function specifically looks out for "terminate" events in the queue and errors whenever it spots one. Compare os.pullEventRaw(), which is effectively the same other than the fact that it has no special handling for "terminate" events at all (meaning you can implement your own, or just ignore them entirely).

https://github.com/alekso56/ComputercraftLua/blob/master/bios.lua#L197
Dragon53535 #3
Posted 20 March 2016 - 08:00 AM
I'm assuming you want to basically hit a certain key, or any key to interrupt a running program? Depending on how your code is setup you could use just a normal while loop with a timer, or go for the parallel api.
cmdpwnd #4
Posted 20 March 2016 - 05:48 PM

Yes, basically im looking to do what dragon says, sorry for the wording, when i say no events, i mean that no player is there to trigger events and i don't have the computer hooked up to anything that triggers events externally. its simply a standalone computer running my program. I'm trying to make a available an interrupt sequence not to 'stop' the program but to run another function.



function console()
  --PROGRAM CONSOLE
end
function run()
  if (KEY SEQUENCE) then
    console()
  end
end
Bomb Bloke #5
Posted 20 March 2016 - 09:37 PM
You've lost me. You want to detect the user pressing a certain combo even when there's no user there to enter the combo and generate the associated events…?

Well, let's say there IS a user present, they're holding eg Ctrl + I, and you want to detect that. First up, you'll ideally be using CC 1.74 or later, as that's the build that introduced key_up events.

The idea is that every time someone presses one of the keys that's involved in your combo, you'll get a "key" event, and you should increment a counter. Whenever they let go, you get a "key_up" event, and you should decrement your counter. If the counter reaches two, then both relevant keys are held, and you should go off and run your other function.

Under older CC builds (if memory serves), if Ctrl is held while a character key is pressed, a "char" event for that character will not be generated. So, on receiving a "key" event for your character of interest, you queue a random event, and if that gets pulled before the expected "char" event you know your combo is being held.
Dragon53535 #6
Posted 20 March 2016 - 09:57 PM
BB, you've got the concept wrong. He wants a script like this:


local timer = os.startTimer(0.1)
while true do
  local event = {os.pullEvent()}
  if event[1] == "timer" and event[2] == timer then
    --#Normal code stuff
    timer = os.startTimer(0.1)
  elseif event[1] == "key" and event[2] == keys.w then
    --#Other stuff
  end
end
To be honest with you, the way he's describing it is that he wants basically the parallel api, however i think he also wants the normal program to pause while the other bit is executing. I believe a way to achieve that would be to override os.pullEvent to check if that key is pressed and then based on that run the appropriate function while also utilizing os.pullEventRaw or whatever.
cmdpwnd #7
Posted 20 March 2016 - 11:12 PM
The only interaction with the user that the computer will have is when the user presses an interrupt sequence such as ctrl+T. otherwise the computer is left alone to run the program. When the user does press said sequence the running code will execute another function within the same file synchronously (NOT async aka parallel aka 'simultaneous').
cmdpwnd #8
Posted 20 March 2016 - 11:24 PM
I'm obviously not making myself clear.

I have a completely isolated computer. a user can interact with this computer. the computer is running a program. the program will detect if a user enters a key sequence such as CTRL+D. if this sequence is detected, the program will call another function within the same program which is a CLI [aka console or shell]. once the user is finished with the CLI they will 'exit' the CLI and the loop which was running to detect the key sequence will again be running, as the CLI returned because it is simply a function.


function console()
  --console
end

function run()
  while true do
	if ([key sequence]) then
	  console()
	else
	  --run program normally
	end
  end
end
Edited on 20 March 2016 - 10:24 PM
Bomb Bloke #9
Posted 21 March 2016 - 06:54 AM
Ok, but… I assume you're already aware of how to detect standard keypresses, and I've explained above how pick up combinations.

So what's the problem?
cmdpwnd #10
Posted 21 March 2016 - 09:40 PM
None, I've got it working now! :)/> Just wanted to restate because I was so unclear about it. Sorry :)/> hahaha