lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Am 30.11.2013 13:03 schröbte John Hind:
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.

What made you think that `_kbhit` (or `kbhit`) was in POSIX? IIRC, it's an old DOS function (and it's not listed here[1]).

*/
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!

I did, but found nothing on theology. Could you share a link?


@OP: In case you are on a POSIX machine you could use luaposix[2]:

    local p = require( "posix" )

    local function table_copy( t )
      local copy = {}
      for k,v in pairs( t ) do
        if type( v ) == "table" then
          copy[ k ] = table_copy( v )
        else
          copy[ k ] = v
        end
      end
      return copy
    end

    assert( p.isatty( p.STDIN_FILENO ), "stdin not a terminal" )
    local saved_tcattr = assert( p.tcgetattr( p.STDIN_FILENO ) )
    local raw_tcattr = table_copy( saved_tcattr )
raw_tcattr.lflag = bit32.band( raw_tcattr.lflag, bit32.bnot( p.ICANON ) )

    local guard = setmetatable( {}, { __gc = function()
      p.tcsetattr( p.STDIN_FILENO, p.TCSANOW, saved_tcattr )
    end } )


    local function kbhit()
      assert( p.tcsetattr( p.STDIN_FILENO, p.TCSANOW, raw_tcattr ) )
      local r = assert( p.rpoll( p.STDIN_FILENO, 0 ) )
      assert( p.tcsetattr( p.STDIN_FILENO, p.TCSANOW, saved_tcattr ) )
      return r > 0
    end


    ---[[
    -- Test code
    repeat until kbhit()
    print( "key pressed!" )
    --]]

HTH,
Philipp


  [1]: http://pubs.opengroup.org/onlinepubs/9699919799/
  [2]: https://github.com/luaposix/luaposix