How do I listen to STDIN input without pausing my script?
Not sure where are the commands you want to "continue running" in your example. Try this small script:
Thread.new do
loop do
s = gets.chomp
puts "You entered #{s}"
exit if s == 'end'
end
end
i = 0
loop do
puts "And the script is still running (#{i})..."
i += 1
sleep 1
end
Reading from STDIN is done in a separate thread, while the main script continues to work.
Input without stopping program
Here's a function that will timeout if no input is given:
import select
import sys
def timeout_input(timeout, prompt="", timeout_value=None):
sys.stdout.write(prompt)
sys.stdout.flush()
ready, _, _ = select.select([sys.stdin], [], [], timeout)
if ready:
return sys.stdin.readline().rstrip('\n')
else:
sys.stdout.write('\n')
sys.stdout.flush()
return timeout_value
You can easily modify it so it shows the remaining time by changing the timeout value on select.select
to 1
, and looping timeout
times.
Bash input without pausing the script?
read -t0
can be used to probe for input if your process is structured as a loop
#!/bin/bash
a='\|/-'
spin()
{
sleep 0.3
a="${a:1}${a:0:1}"
echo -n $'\e'7$'\r'"${a:1:1}"$'\e'8
}
echo 'try these /|\- , dbpq , |)>)|(<( , =>-<'
echo -n " enter a pattern to spin:"
while true
do
spin
if read -t0
then
read a
echo -n " using $a enter a new pattern:"
fi
done
else you could run one command in the background while promptiong for input in the foreground. etc...
Capture characters from standard input without waiting for enter to be pressed
That's not possible in a portable manner in pure C++, because it depends too much on the terminal used that may be connected with stdin
(they are usually line buffered). You can, however use a library for that:
conio available with Windows compilers. Use the
_getch()
function to give you a character without waiting for the Enter key. I'm not a frequent Windows developer, but I've seen my classmates just include<conio.h>
and use it. Seeconio.h
at Wikipedia. It listsgetch()
, which is declared deprecated in Visual C++.curses available for Linux. Compatible curses implementations are available for Windows too. It has also a
getch()
function. (tryman getch
to view its manpage). See Curses at Wikipedia.
I would recommend you to use curses if you aim for cross platform compatibility. That said, I'm sure there are functions that you can use to switch off line buffering (I believe that's called "raw mode", as opposed to "cooked mode" - look into man stty
). Curses would handle that for you in a portable manner, if I'm not mistaken.
Get user input without assuming there is a question
If you don't want to use an empty string for rl.question
, you could simply listen on the line
event as you don't even have to prompt the user with a question at all:
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.on('line', (line) => {
console.log(`You typed ${line}`);
});
From the docs:
The 'line' event is emitted whenever the input stream receives an
end-of-line input (\n, \r, or \r\n). This usually occurs when the user
presses Enter or Return.The listener function is called with a string containing the single
line of received input.
Non-blocking console input?
For Windows, console only, use the msvcrt
module:
import msvcrt
num = 0
done = False
while not done:
print(num)
num += 1
if msvcrt.kbhit():
print "you pressed",msvcrt.getch(),"so now i will quit"
done = True
For Linux, this article describes the following solution, it requires the termios
module:
import sys
import select
import tty
import termios
def isData():
return select.select([sys.stdin], [], [], 0) == ([sys.stdin], [], [])
old_settings = termios.tcgetattr(sys.stdin)
try:
tty.setcbreak(sys.stdin.fileno())
i = 0
while 1:
print(i)
i += 1
if isData():
c = sys.stdin.read(1)
if c == '\x1b': # x1b is ESC
break
finally:
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_settings)
For cross platform, or in case you want a GUI as well, you can use Pygame:
import pygame
from pygame.locals import *
def display(str):
text = font.render(str, True, (255, 255, 255), (159, 182, 205))
textRect = text.get_rect()
textRect.centerx = screen.get_rect().centerx
textRect.centery = screen.get_rect().centery
screen.blit(text, textRect)
pygame.display.update()
pygame.init()
screen = pygame.display.set_mode( (640,480) )
pygame.display.set_caption('Python numbers')
screen.fill((159, 182, 205))
font = pygame.font.Font(None, 17)
num = 0
done = False
while not done:
display( str(num) )
num += 1
pygame.event.pump()
keys = pygame.key.get_pressed()
if keys[K_ESCAPE]:
done = True
Ruby get input only if input exists
This works but only because self.reload! is not called while my console window is selected
Thread.new do
loop do
script_temp = gets
@script = @script + script_temp
end
end
def self.reload!
begin
eval @script
$stdout.flush()
rescue Exception
end
@script = ''
end
Based on this
Pause script until user presses enter in Node.JS
You can simply take input from stdin
Sample function :
function waitForKey(keyCode) {
return new Promise(resolve => {
process.stdin.on('data',function (chunk) {
if (chunk[0] === keyCode) {
resolve();
process.stdin.pause();
}
});
});
}
Now if you want to wait for enter key :
await waitForKey(10);
How can I test whether stdin has input available in julia?
bytesavailable(stdin)
Here is a sample usage. Note that if you capture the keyboard you also need to handle Ctrl+C yourself (in this example only the first byte of chunk is checked).
If you want to run it fully asynchronously put @async
in front of the while
loop. However if there will be no more code in this case this program will just exit.
import REPL
term = REPL.Terminals.TTYTerminal("xterm",stdin,stdout,stderr)
REPL.Terminals.raw!(term,true)
Base.start_reading(stdin)
while (true)
sleep(1)
bb = bytesavailable(stdin)
if bb > 0
data = read(stdin, bb)
if data[1] == UInt(3)
println("Ctrl+C - exiting")
exit()
end
println("Got $bb bytes: $(string(data))")
end
end
Related Topics
What Orm to Use in One Process Multiple Db Connections Sinatra Application
How to Refactor Openssl Pkcs5_Keyivgen in Ruby
How to Change Environment Variables When Running Rspec for Ruby
Ruby Equivalent of C#'s 'Yield' Keyword, Or, Creating Sequences Without Preallocating Memory
Dynamically Create a Class Inherited from Activerecord
Error Installing "Kgio-2.9.2" Gem on Windows
Ruby: Mass Initializing Instance Variables
Accessing the Child Instance in a Rabl Template
Does Anyone Have Parsing Rules for the Notepad++ Function List Plugin for Ruby and Rake
How to Replace the Characters in a String
Remove All Data from Active Storage
Why Does the Break Statement in Ruby Behave Differently When Using Proc.New V. the Ampersand Sign