-
Notifications
You must be signed in to change notification settings - Fork 0
/
input.py
152 lines (120 loc) · 4.17 KB
/
input.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# -*- coding: utf-8 -*-
#
# Copyright (C) 2015 Rodrigo Silva (MestreLion) <linux@rodrigosilva.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. See <http://www.gnu.org/licenses/gpl.html>
'''
Abstraction layer to deal with terminal keyboard input
and related curses methods and constants
'''
import os
import sys
import curses.ascii
import locale
# enum from stdlib doesn't allow re-assignments, so we use our custom one
from . import enum2 as enum
if sys.version < '3':
def b2s(b):
return b
else:
def b2s(b):
return str(b, encoding=locale.getpreferredencoding())
class MOVE(enum.Enum):
UP = (curses.KEY_UP, ord('k'))
DOWN = (curses.KEY_DOWN, ord('j'))
LEFT = (curses.KEY_LEFT, ord('h'))
RIGHT = (curses.KEY_RIGHT, ord('l'))
UP_RIGHT = (curses.KEY_PPAGE, ord('u'), curses.KEY_A3)
DOWN_RIGHT = (curses.KEY_NPAGE, ord('n'), curses.KEY_C3)
UP_LEFT = (curses.KEY_HOME, ord('y'), curses.KEY_A1, curses.KEY_FIND)
DOWN_LEFT = (curses.KEY_END, ord('b'), curses.KEY_C1, curses.KEY_SELECT)
class KEY(enum.Enum):
RESIZE = curses.KEY_RESIZE
F1 = curses.KEY_F1
F2 = curses.KEY_F2
F3 = curses.KEY_F3
F4 = curses.KEY_F4
F5 = curses.KEY_F5
F6 = curses.KEY_F6
F7 = curses.KEY_F7
F8 = curses.KEY_F8
F9 = curses.KEY_F9
F10 = curses.KEY_F10
F11 = curses.KEY_F11
F12 = curses.KEY_F12
# Some aliases
INSERT = curses.KEY_IC
DELETE = curses.KEY_DC
NUM_5 = curses.KEY_B2
ALT_F9 = curses.KEY_F57
ESC = curses.ascii.ESC
# The above make static analyzers like Pylint and Pydev happy
# Now generate all other KEY constants
for __ in dir(curses):
if __.startswith("KEY_"):
setattr(KEY, __[4:], getattr(curses, __))
def ctrl(c):
return curses.ascii.ctrl(ord(c))
def getch(window):
'''Get a character from user. Blocks until input.
Wrapper for curses.window.getch()
'''
return window.window.getch()
def unctrl(ch):
'''Return a a printable representation of character ch.
Control characters are displayed with a caret, for example ^C.
Printing characters are left as they are.
Wrapper for curses.unctrl()
'''
return b2s(curses.unctrl(ch))
if os.environ.get('DISPLAY') is None:
is_console = True
def keyboard_leds():
import struct
import fcntl
DEVICE = '/dev/tty'
KDGETLED = 0x4B31
SCRLOCK = 0x01
NUMLOCK = 0x02
CAPLOCK = 0x04
leds = 0
try:
fd = os.open(DEVICE, os.O_RDONLY | os.O_NOCTTY)
retbytes = fcntl.ioctl(fd, KDGETLED, struct.pack('I', 0))
[leds] = struct.unpack('I', retbytes)
except IOError: # not a true tty console, but an X11 terminal emulator
pass
return (("NUM LOCK", bool(leds & NUMLOCK)),
("CAP LOCK", bool(leds & CAPLOCK)),
("SCR LOCK", bool(leds & SCRLOCK)))
else:
is_console = False
def keyboard_leds():
import subprocess
SCRLOCK = 0x04
NUMLOCK = 0x02
CAPLOCK = 0x01
leds = 0
try:
for line in (subprocess.check_output(["xset", "-q"]).
decode(locale.getpreferredencoding()).
split('\n')):
if 'LED mask' in line:
leds = int(line.split(' ')[-1])
break
except subprocess.CalledProcessError:
pass
return (("NUM LOCK", bool(leds & NUMLOCK)),
("CAP LOCK", bool(leds & CAPLOCK)),
("SCR LOCK", bool(leds & SCRLOCK)))