Skip to content

Commit 33aac3f

Browse files
committed
add support for CTRL-left and CTRL-right, at least on some terminal emulators; tested with xterm, gnome-terminal and rxvt
1 parent a59f338 commit 33aac3f

File tree

4 files changed

+31
-10
lines changed

4 files changed

+31
-10
lines changed

pyrepl/input.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
from __future__ import print_function
3636
import unicodedata
3737
from collections import deque
38+
import pprint
39+
from trace import trace
3840

3941

4042
class InputTranslator(object):
@@ -59,26 +61,23 @@ def __init__(self, keymap, verbose=0,
5961
for keyspec, command in keymap:
6062
keyseq = tuple(parse_keys(keyspec))
6163
d[keyseq] = command
62-
if self.verbose:
63-
print(d)
64+
if verbose:
65+
trace('[input] keymap: {}', pprint.pformat(d))
6466
self.k = self.ck = compile_keymap(d, ())
6567
self.results = deque()
6668
self.stack = []
6769

6870
def push(self, evt):
69-
if self.verbose:
70-
print("pushed", evt.data, end='')
71+
trace("[input] pushed {!r}", evt.data)
7172
key = evt.data
7273
d = self.k.get(key)
7374
if isinstance(d, dict):
74-
if self.verbose:
75-
print("transition")
75+
trace("[input] transition")
7676
self.stack.append(key)
7777
self.k = d
7878
else:
7979
if d is None:
80-
if self.verbose:
81-
print("invalid")
80+
trace("[input] invalid")
8281
if self.stack or len(key) > 1 or unicodedata.category(key) == 'C':
8382
self.results.append(
8483
(self.invalid_cls, self.stack + [key]))
@@ -88,8 +87,7 @@ def push(self, evt):
8887
self.results.append(
8988
(self.character_cls, [key]))
9089
else:
91-
if self.verbose:
92-
print("matched", d)
90+
trace("[input] matched {}", d)
9391
self.results.append((d, self.stack + [key]))
9492
self.stack = []
9593
self.k = self.ck

pyrepl/keymap.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@
8989
'space': ' ',
9090
'tab': '\t',
9191
'up': 'up',
92+
'ctrl left': 'ctrl left',
93+
'ctrl right': 'ctrl right',
9294
}
9395

9496
class KeySpecError(Exception):

pyrepl/reader.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ def make_default_syntax_table():
162162
(r'\EOF', 'end'), # the entries in the terminfo database for xterms
163163
(r'\EOH', 'home'), # seem to be wrong. this is a less than ideal
164164
# workaround
165+
(r'\<ctrl left>', 'backward-word'),
166+
(r'\<ctrl right>', 'forward-word'),
165167
])
166168

167169
if 'c' in globals(): # only on python 2.x

pyrepl/unix_eventqueue.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,24 @@
5353
#function keys x in 1-20 -> fX: kfX
5454
_keynames.update(('f%d' % i, 'kf%d' % i) for i in range(1, 21))
5555

56+
# this is a bit of a hack: CTRL-left and CTRL-right are not standardized
57+
# termios sequences: each terminal emulator implements its own slightly
58+
# different incarnation, and as far as I know, there is no way to know
59+
# programmatically which sequences correspond to CTRL-left and
60+
# CTRL-right. In bash, these keys usually work because there are bindings
61+
# in ~/.inputrc, but pyrepl does not support it. The workaround is to
62+
# hard-code here a bunch of known sequences, which will be seen as "ctrl
63+
# left" and "ctrl right" keys, which can be finally be mapped to commands
64+
# by the reader's keymaps.
65+
#
66+
CTRL_ARROW_KEYCODE = {
67+
# for xterm, gnome-terminal, xfce terminal, etc.
68+
'\033[1;5D': 'ctrl left',
69+
'\033[1;5C': 'ctrl right',
70+
# for rxvt
71+
'\033Od': 'ctrl left',
72+
'\033Oc': 'ctrl right',
73+
}
5674

5775
def general_keycodes():
5876
keycodes = {}
@@ -61,6 +79,7 @@ def general_keycodes():
6179
trace('key {key} tiname {tiname} keycode {keycode!r}', **locals())
6280
if keycode:
6381
keycodes[keycode] = key
82+
keycodes.update(CTRL_ARROW_KEYCODE)
6483
return keycodes
6584

6685

0 commit comments

Comments
 (0)