How can I check for keyboard input without stopping execution? - ruby

What command/keyword is used to check for keyboard input without stopping execution? I want to build a loop that will run continuously, and at every iteration of the loop, I want to check for keyboard input. If the user presses the right key, my program will act on it; if not, it will continue to run.
EDIT
I want it to work with out pressing the enter key. Like when a game runs it checks if the user presses the arrow key then acts on the key press or continues if nothing is pressed.

From what I could find and some hacking around, I managed to put together something that will immediately echo the keys you press when running in command line.
require 'io/console'
loop do
p STDIN.getch
end
But as the referenced answer mentions, you'll want to capture SIGTERMs so you don't get trapped in the program: Signal.trap("INT") { exit }
So the meat of your program and all of its processing lives in that main loop, and each go around of that loop it will grab a character from the STDIN.

You cannot do that with a simple method. The most common way to do that is to use the curses gem.

Related

remove and replace the text when putting a string into the console $stdin ruby

I have a program that is a client, talking to a server with socket.
When the user is inputting a message, if another message comes in, it breaks up the text visually, making it hard to understand for the user.
the scenario can be thought up like this
c=0
p=Thread.new do
loop {
# this is the messages coming in
c+=1
puts c
sleep 1
}
end
g=Thread.new do
loop {
#this is the user input
puts $stdin.gets
}
end
p.join
g.join
in the case of some really slow typers, the output looked similar to this
1
h2
el3
l4
o5
hello
6
Is there any way to remove and replace the text when putting a string into the console?
edit
So, now if i can get each character separate, i can add it to a string, and in the thread p when it puts, it will put "\r" + c and then print the string.
this would allow the user to still see what they are typing, as well as not interrupting the p thread.
I dont know how to get each character individually.
this also brings up the problem of "how would backspace work?" and "would i need a switch statement for special characters like return and ctrl+c?"
If you are trying to implement a chat app in terminal, the "appropriate" tool is curses. A curses library essentially lets you write a GUI in the terminal. It lets you define separate regions of the screen that you can update separately and also lets you read input without echoing it to the terminal.
Your program is multithreaded, and both of your threads are fighting over the same resource: the terminal! The classic way to handle this is to protect the shared resource with a mutex.
The idea is simple: whenever a thread interacts with the shared resource (the terminal) synchronize that access with the shared mutex. That way they don't stomp on each other.
But your situation is tricky, it's easy to see when thread p wants to use the terminal, but it's not easy in thread g because that's just the user typing. What you probably would have to do is use IO#read_nonblock in a tight loop to get the user's input character-by-character. You could then use that to detect when the user pauses their input and take that moment to unlock the mutex, allowing the other thread to dump its output.
Note that this will also make thread p more complicated because it needs to be able to buffer its output while it's waiting for the terminal to become available.

how to interupt a program trying to open a file

We are making a program write to a file on my computer and there is basically just one part that I can't figure out how it works.
Before the program opens the file the program allows me to press the Return key to go ahead to open the file and thus erasing the content. Or I can press ctrl+C to interrupt my program. I'm thankful for any kind of input here since I really can't seem to find anything about this specific function.
filename = ARGV.first
puts "We're going to erase #{filename}"
# This is the part I can't find out how it works.
puts "If you dont want that press ctrl-c (^C)."
puts "If you do want that press RETURN."
$stdin.gets
Ruby gets reads a line of text. When called on a file - it reads a line of this file. When called on $stdin as in your case, it reads a line from the standard input (a console).
If you press Enter, the program will read an empty line and continue execution. If you press Ctrl+C a signal is sent to the program and this signal make program to stop execution. You can press Ctrl+C in any moment of program execution and it will be stopped (unless the signal is handled in the program, but it's not the case here).
See also:
gets docs
question about Ctrl-C

Read single key from console input

I want to resume script execution immediately after any key is pressed kind of like C's getch() but I can't find a way. I also need to know the input so I can either call the function or not.
I considered calling cmd.exe /c pause but that doesn't return the input and WScript.StdIn.Read(1) doesn't resume execution after pressing a key. Instead, you can type as much as you want and, when enter is pressed, it only reads the first character. Is this possible? Thank you!

How to Detect Keypress in Applescript

I have several nested loops in an Applescript, but I need a simple way for the user to stop executing the entire script. A (rather inefficient) idea I had was to check if keys were pressed within the quickest loop, and pass error number -128 in a keypress event, but I can't find a way to detect what keys were pressed.
I've seen recommendations for Jon's Commands, but I can't seem to install it properly even though it's in my ApplicationScripts -- (keys pressed) doesn't work.
Alternately, is there a better way to stop running the script across multiple loops?
Try using command . to stop the script

powershell bash loops are randomly stuck waiting for keyboard input

I have bash script I am running from powershell in windows that does a for loop. Every once in a while, one of the loop iteration hangs until I hit enter on the keyboard.
This doesn't happen all the time, in fact, it happens pretty rarely, but it still does.
The interesting thing is that my loop innards is basically time _command_ and so after I hit enter, it'll tell me how long the command took to run. The command actually takes way less time to execute than the loop iteration takes - because it's waiting for keyboard input for some odd reason.
It's pretty annoying to leave a script running overnight and come back in the morning to see that it didn't get very far.
Does someone knows WHY this happens and WHAT to do to get around it?
Thanks,
jbu
I have encountered the same problem several times. Now I guess I have found the reason!
If you ever press the mouse within the powershell, it might get stuck and need user to press "enter" to continue. So the get-around-way is to make sure that you didn't accidentally press your mouse within the shell window while you are already running some program...
Goto the powershell properties and unselect 'Quick Edit'/'Insert' check boxes. If these are selected, the console pauses output and resumes only when an Enter key is pressed ( You can identify this by monitoring the console title bar- it will switch from "Administrator:Windows PowerShell" to "Select Administrator:Windows Powershell"
Until you post the script, there's little we can do to help.
However, in general, one of your commands probably returns a null once in a while as input to stdin of another command which, upon seeing null looks to the terminal as stdin. Or something along those lines.

Resources