-
Notifications
You must be signed in to change notification settings - Fork 138
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Provide keyboard input #22
Comments
Probably model it as a context manager, so we're sure to restore the terminal flags. |
Conway would even be a good place to demo it. Have a keystroke seed stable patterns or something. Or make it fully interactive, a la After Dark. ;-) |
I've been using getch from pager with blessings, might want to have a look at that code. |
I added a generator that given an input bytestring yields special curses KEY_LEFT & etc constants, or the bytestring/unicode as-is. https://github.com/jquast/blessings |
I tried to get both the original snippet and pager code working on os x. Os x is apparently unable to recognize when a read call should block (to read the first byte, for instance) and consequently getch() always returns immediately, even if no data is available in stdin. Is there not a way to provide a wrapper to curses.initscr().getch()? That seems to work fine on os x. Is there no way to avoid having it hijack the terminal? Adding this feature gets my vote, by the way. |
I don't like using curses.initscr().getch() at all. Hate it, in fact. I wanted some curses features in blessings that required calling initscr() first, but calling initscr() has nasty consequences on the type of environments blessings can run in. I especially like the idea of force_styling=True ... I've been able to emulate other kinds of terminals and see their sequences, I'd also like to translate terminal sequence not of my own process... I'm currently decoding keycodes for telnet clients, for instance. Placing the terminal in cooked isn't too bad.. I can help fix that. Erik: if you could propose the interface, the names of the methods and their behaviors, I think I can propose a patch. I can help with decoding multibyte sequences to numeric constants such as KEY_LEFT, which isn't mentioned here but I think the real issue, right? I've got code working for that. I propose an enable_keycodes=True to getch(), true by default? where getch() can return integer values that are compared to term.KEY_LEFT, etc.. Here's my proposal .. any comments welcomed. This is pseudo. term = blessings.Terminal()
with term.cooked(enable_keycodes=True):
print "your term is cooked"
inp = None
while inp != 'q':
inp = term.getch()
if inp in (term.KEY_LEFT, term.KEY_RIGHT, term.KEY_UP, term.KEY_DOWN):
print "move: %s" % (term.keyname(inp), )
else:
print "Pressed: %s" % (inp,) but hey, if you wanted to read until carriage return, (default / linemode) you'd use sys.stdin.readline() ... which is why i propose this additional method -- a generator which I'm using now and rather like: for inp in term.trans_input(sys.stdin.readline().strip()):
if type(inp) is int:
print "detected multibyte keystroke: %s" % (term.keyname(inp))
else:
print "input character: %s" % (inp,)) |
This version supplies trans_input and keyname: https://github.com/jquast/x84/blob/master/x84/blessings.py no cooked mode in it, though. |
Is there an ETA for this? |
I'm afraid I don't have an ETA, but it's the next thing I'm likely to add. |
This would be great! |
I've created a pull request to implement a _resolve_mulitbyte method, which is a generator for iterating over unicode strings that contain multibyte input sequences, such as \x1b[A translated to KEY_UP. This does not implement the character-at-a-time cooked mode proposed in this issue. I guess you could say its half-way there.. #27 |
I've added win32 and posix termios magic bits for character-at-a-time processing in my tree. With any luck we can close this issue in the next few days. I think the interface i've outlined fits in line with the rest of the styling of blessings, that is, should be very easy to use. with term.cbreak():
inp = term.inkey(timeout=5.0)
if inp is None:
print 'timeout'
elif inp.is_sequence:
print 'This is a detected input sequence: %r' % (inp,)
if inp.code == term.KEY_HOME:
print 'no place like it!'
else:
print 'Pressed', repr(inp)
else:
print "%s? doesn't impress me." % (inp,) edit: codefix per ms |
sounds awesome! I'll give it a spin right now! |
I think in the code above, do you mean: |
I'll go learn what cooked mode is and take a look at your PR. :-) Thanks for your hard work! |
I've completed the implementation in the attached pull request (which also includes sequence formatting) with a human test case so far, test_keyboard.py. I'll add automated tests for the parsers. |
This is too fun, I suppose we'll all be making games soon! |
What a hoot! :-D Ended up spending tonight getting Parsimonious running on Python 3 again, but I'll catch up with this soon. |
Hey, so great to see this feature finally getting added. And I love the demo! Thanks, jquast! I think I'll need to re-visit my project for which I had hoped to use blessings. |
I found this gem on the python-tulip ML for windows keyboard input, "Example of non-blocking asyncronous console input using Windows API calls in Python." |
I haven't forgotten about this. I'm just buying a house at the moment and so am a little distracted. :-) |
@erikrose: do you have an update on this? |
I think Erik got his house. Now i'm the busy one, looking for a place myself. I've been piecemealing 1 large pull request as individual pulls, working towards keyboard again. Currently stuck on why the Travis CI system is failing, I don't think Travis offers pseudo terminals. It's hard because the only way to fix it is to try random things, push it into a branch, and see what Travis has to say about it -- rather annoying since all of these tests pass fine locally. |
From #travis:
|
I'll take another look soon... its not that travis runs in a pty, but that another pty can be spawned using pty.fork and behave the way I expect it to. I'm getting an I/O error when reading from the master_fd. This is regarding pull #42 where you can find it failed, in blessings/tests.py decorator @as_subprocess I tried re-ordering some things with another branch but give up for the time being. |
I've resolved the pty issue, pull #42 is fully resolved. Once Erik reviews & merges this I'll be able to build upon the fixes and improved test infrastructure and submit a request for my 'sequence-aware' branch, providing term.center, rjust, ljust and wrap() helpers. The one following will be for keyboard support, I promise. |
keyboard support is implemented in my fork, https://github.com/jquast/blessed/ -- appreciate any feedback before it goes to pypi. |
This is resolved in 'blessed-integration' branch. |
The fork |
It's really freaking hard to read the state of the keyboard without calling
curses.initscr().getch()
. Let's make it easier on people; I've had 2 requests about it. Here's one implementation, from http://love-python.blogspot.com/2010/03/getch-in-python-get-single-character.html:As you can deduce from the above, you can do it with echo or without, async or blocking (see curses docs for that latter bit).
The text was updated successfully, but these errors were encountered: