[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Check for a keypress
- From: Sean Conner <sean@...>
- Date: Sat, 30 Nov 2013 16:14:23 -0500
It was thus said that the Great John Hind once stated:
> > On Fri, 29 Nov 2013, Jose Torre-Bueno wrote:
> > Is there a way from inside Lua to check whether any key has been
> > pressed? io.read() will get a line from the console but if there
> > is no input it pends waiting for input. I would like to be able
> > to write a test that gets input if any is ready but would continue
> > if there is none. It is not obvious to me if this can be done at
> > all.
>
> Not a solution, but some background. Here is a a Lua C function to do it
> extracted from one of my libraries, complete with comment:
>
> /* R1: Boolean, true if there is outstanding data in the keyboard buffer.
> ** This is a helper to allow a demonstration terminal program implemented on the command line.
> ** Need a solution for Linux, although _kbhit is POSIX there seem to be theological reasons for not
> ** having it in Linux and it is not in baseline C.
> */
> static int luakbhit(lua_State* L) {
> #if defined(LUA_WIN)
> lua_pushboolean(L, _kbhit());
> #else
> lua_pushboolean(L, FALSE);
> #endif
> return 1;
> }
>
> Search online for "_kbhit" for more background on the theology!
If you *really* want to do this for Unix, the code is quite involved. You
first need to get the "keyboard" [1] into raw mode:
#include <errno.h>
#include <termios.h>
#include <unistd.h>
struct termios init_term;
struct termios curr_term;
int set_raw(void)
{
if (!isatty(STDIN_FILENO))
return ENOTTY;
if (tcgetattr(STDIN_FILENO,&init_term) < 0)
return errno;
curr_term = init_term;
#if HAVE_CFMAKERAW
cfmakeraw(&curr_term);
#else
curr_term.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
curr_term.c_oflag &= ~OPOST;
curr_term.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
curr_term.c_cflag &= ~(CSIZE|PARENB);
curr_term.c_cflag |= CS8;
#endif
if (tcsetattr(STDIN_FILENO,TCSANOW,&curr_term) < 0)
return errno;
return 0;
}
And now that you have the "keyboard" [1] in raw mode, you can now write
_kbhit() [2]
#include <sys/poll.h>
#include <unistd.h>
int _kbhit(void)
{
struct poll fds;
fds.fd = STDIN_FILENO;
fds.events = POLLIN;
if (poll(&fds,1,0) == 0)
return 1;
else
return 0;
}
Now, just make sure to call tcsetattr(STDIN_FILENO,TCSANOW,&init_term)
before the program ends, to restore the "keyboard" mode.
-spc (If your Unix system doesn't have poll(), you can use select(), but
that's an exercise for the reader ... )
[1] It's really the input stream.
[2] Technically, this violates the C standard for naming---any
identifier starting with a single _ is reserved for the C
implementation and *NOT* user code. You have been warned.