Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect Caps Lock in Python curses

For such a basic question, I'm surprised I couldn't find anything by searching...

Anyways, I made a curses app in Python that assists in solving puzzles of a certain DSiWare game. With it, you can take a puzzle and inspect the components of it individually. The keys qweasdzx are used to paint tiles (the keys are arranged in some sort of palette). Pressing one of these keys while holding Shift highlights tiles with that color. I couldn't ask for a more natural control scheme.

So it's a shame that, once again, Shift is giving me issues (last time I had issues with Shift, I earned a Tumbleweed badge). Though this time, the problem is more or less Caps Lock, which completely screws up my program by reversing the functions.

How can I detect the state of Caps Lock in Python with curses?

EDIT: If you're going to suggest using a separate module, I probably should remind you that curses - and therefore my program - is in UNIX territory.

like image 217
Exp HP Avatar asked Dec 28 '22 11:12

Exp HP


2 Answers

I found a solution on my own:

Since curses is completely unaware of the Caps Lock setting according to ΤΖΩΤΖΙΟΥ, I tried an alternative solution. Specifically, I looked up how to check Caps Lock in a BASH script. What I found was this:

Linux only. Requires X Window System.

$ xset q | grep LED
>  auto repeat:  on    key click percent:  0    LED mask:  00000000

The last 0 in that output (the 66th character in the string) is the Caps Lock flag. 1 if it's on, 0 if it's off.

Python can run UNIX system commands with the Linux-only commands module. commands does not appear to interfere with curses.

>>> import commands
>>> # Caps Lock is off.
>>> commands.getoutput("xset q | grep LED")[65]
'0'
>>> # Setting Caps Lock on now.
>>> commands.getoutput("xset q | grep LED")[65]
'1'

This works fine for me; this is a personal-use script, and it's not like my program wasn't already Linux-exclusive. But I do hope somebody has another, more Windows-compatible solution.

I'm going to accept this self-answer for now, but if somebody else can come up with a better working solution, I'd like to see it.

like image 86
Exp HP Avatar answered Jan 18 '23 23:01

Exp HP


The short answer: you can't.

A longer answer:

curses was created as a terminfo-based library to ease the creation of character-based UIs independent of the terminal used (for terminal in 'vt220', 'wyse100', …).

These terminals connected through a serial line and the communication to-and-fro the host were through either plain text (input by the user or output by the host) or special sequences ("escape" sequences; input by the user if special keys were pressed, like or Prev, or output by the host if special operations like cursor positioning or screen clearing was requested).

I have no knowledge of any dumb terminal sending a special sequence whenever the Caps Lock key was depressed, or the host querying for the Caps Lock status; locking capitals was part of the job of the terminal, and the host had no need for any knowledge. This is similar to the reason you can't have a curses program act when the Control key is depressed on its own.

Everything about curses relates to terminfo capabilities; there isn't any related capability for what you ask.

like image 31
tzot Avatar answered Jan 18 '23 22:01

tzot