14

I have a problem with NCurses... i need to handle all keys like Esc, Alt+F etc. Problem is that the codes are similar... i.e:


Esc - 27


Alt+A - 27 65


As an example there is double code for Alt+[key] combination what similar to Esc key... Any ideas how handle that?

Marcin Petrów
  • 1,447
  • 5
  • 24
  • 39

4 Answers4

17

Here is an example for python:

key = self.screen.getch()
if key == ord('q'): # quit
    go = False
elif key == 27: # Esc or Alt
    # Don't wait for another key
    # If it was Alt then curses has already sent the other key
    # otherwise -1 is sent (Escape)
    self.screen.nodelay(True)
    n = self.screen.getch()
    if n == -1:
        # Escape was pressed
        go = False
    # Return to delay
    self.screen.nodelay(False)
sjohnson.pi
  • 366
  • 3
  • 4
  • after days of searching how to capture the alt key combos, this one finally got it done. i assume the esc and alt having the same ascii code is an old terminal thing. Thank you sjohnson_pi – Alan Ennis Mar 02 '23 at 11:29
10

Resolved by:

  1. Use noecho or timeout mode
  2. Check for 27(ALT or ESC) code... if pass:
  3. try to read another code
  4. if another code is ERR then.. you have ESC key in other way you have ALT+another code
L Y E S - C H I O U K H
  • 4,765
  • 8
  • 40
  • 57
Marcin Petrów
  • 1,447
  • 5
  • 24
  • 39
  • 1
    What if the user hit `ESC` and then another key like `[` for example, really fast one after another, couldn't our code see both keys coming through and then it _would not exactly look like an `ESC`_? Because I don't really see how the terminal would know that on my second call to gather the next character that I'm trying to determine whether just `ESC` was hit?! – Alexis Wilke Jan 16 '18 at 05:24
  • 1
    @AlexisWilke That's correct. You have no way to determine if they actually hit Escape, then `[` _really fast_. However, you can often use such a short timeout that no human could reasonably hit it, and most escape sequences are long enough that it'd be very hard to hit every key perfectly within e.g. 25ms of each other. Terminals, on the other hand, will probably do it faster than that. – Nic Jul 16 '18 at 01:57
3

if you don't care to support users who hit escape and then another key (a holdover from old terminals vt100 era terminals I think), and just want to respond to the physical keys on the pc 101 key-board, you can set this at the start of your (c) code:

ESCDELAY = 10;

the man page explains what's going on in more detail: https://man7.org/linux/man-pages/man3/curs_variables.3x.html

then use keyname() to get an easily strcmp'ed human readable name for what was pressed such as ^c for control+c. See How to get Ctrl, Shift or Alt with getch() ncurses?

Al Ro
  • 466
  • 2
  • 11