getting double/triple/etc events via Reader#on on subsequent Reader#read_keypress
pjvleeuwen opened this issue · 4 comments
It seems that after calling Reader#read_keypress
a new Reader
needs to be created, otherwise we get double events on second read_keypress
, triple events on third read_keypress
, etc. This does not seem intended to me. With events I mean events via the Reader#on
listeners.
So my question is: is this intentional? And: did I miss this part in the ReadMe.md?
Example where I ran into this (not cleaned up for this case specific, sorry, have to run and wanted to share what I saw anyway):
require 'tty-screen'
require 'tty-box'
require 'tty-reader'
class Test
def initialize
@reader = ::TTY::Reader.new
@x = 10
@y = 10
end
def redraw
print ::TTY::Box.frame(width: ::TTY::Screen.width, height: ::TTY::Screen.height, left: 0, top: 0)
print ::TTY::Box.frame("x = #{@x}\ny = #{@y}", width: 10, height: 10, left: @x, top: @y)
end
def draw
redraw
loop do
# @reader = ::TTY::Reader.new
@reader.on(:keyleft) { |event| @x -= 1 }
@reader.on(:keyright) { |event| @x += 1 }
@reader.on(:keyup) { |event| @y -= 1 }
@reader.on(:keydown) { |event| @y += 1 }
@reader.on(:keyescape) { |event| break }
@reader.read_keypress
@reader.cursor.clear_screen
redraw
end
end
end
Test.new.draw
Describe your environment
- OS version:
Ubuntu 18.04.3 LTS
- Ruby version:
ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-linux]
(in docker,FROM ruby:2.6.5
) - TTY version:
gem list tty
*** LOCAL GEMS ***
tty-box (0.5.0)
tty-color (0.5.0)
tty-cursor (0.7.0)
tty-pager (0.12.1)
tty-prompt (0.20.0)
tty-reader (0.7.0)
tty-screen (0.7.0)
tty-which (0.4.1)
The above described behavior can be seen here (screencast):
https://gofile.io/?c=h9yHhT
It was uploaded without account. We can remove it with this code:
lcFCbnjtgykQntXeOzok
I don't believe this is an issue with tty-reader
here.
The reason for your issue is that you register to listen for an event in an infinite loop. Each time you run through the loop, you yet another event to listen for and on and on. So, for example, the :keyleft
internal stores all registered listeners in an array, which in your case are { |event| @x -= 1 }
procs.
I'd suggest to change your code to register each key event listener only once:
class Test
def initialize
@reader = ::TTY::Reader.new
@reader.on(:keyleft) { |event| @x -= 1 }
@reader.on(:keyright) { |event| @x += 1 }
@reader.on(:keyup) { |event| @y -= 1 }
@reader.on(:keydown) { |event| @y += 1 }
@reader.on(:keyescape) { |event| break }
@x = 10
@y = 10
end
def draw
redraw
loop do
@reader.read_keypress
@reader.cursor.clear_screen
redraw
end
end
end
I should have seen that... doh (><)
Thanks, and lets pretend I never reported this...
Cheers