OILS / spec / stateful / bind.py View on Github | oilshell.org

150 lines, 90 significant
1#!/usr/bin/env python3
2"""
3spec/stateful/bind.py
4"""
5from __future__ import print_function
6
7import sys
8import time
9
10import harness
11from harness import register, expect_prompt
12from test.spec_lib import log
13
14
15def add_foo_fn(sh):
16 sh.sendline('function foo() { echo "FOO"; }')
17 time.sleep(0.1)
18
19
20def send_bind(sh, opts, keymap=None):
21 "Helper method to send a bind command and sleep for a moment. W/ optional keymap."
22
23 if keymap:
24 sh.sendline(f"bind -m {keymap} {opts}")
25 else:
26 sh.sendline(f"bind {opts}")
27 time.sleep(0.1)
28
29
30@register(not_impl_shells=['dash', 'mksh'])
31def bind_plain(sh):
32 "test bind (w/out flags) for adding bindings to readline fns"
33 expect_prompt(sh)
34
35 # There aren't many readline fns that will work nicely with pexpect (e.g., cursor-based fns)
36 # Editing input seems like a reasonable choice
37 send_bind(sh, ''' '"\C-x\C-h": backward-delete-char' ''')
38 expect_prompt(sh)
39
40 sh.send("echo FOOM")
41 sh.sendcontrol('x')
42 sh.sendcontrol('h')
43 sh.sendline("P")
44 time.sleep(0.1)
45
46 sh.expect("FOOP")
47
48
49@register(not_impl_shells=['dash', 'mksh'])
50def bind_r(sh):
51 "test bind -r for removing bindings"
52 expect_prompt(sh)
53
54 add_foo_fn(sh)
55 expect_prompt(sh)
56
57 send_bind(sh, """-x '"\C-x\C-f": foo' """)
58 expect_prompt(sh)
59
60 sh.sendcontrol('x')
61 sh.sendcontrol('f')
62 time.sleep(0.1)
63 sh.expect("FOO")
64
65 send_bind(sh, '-r "\C-x\C-f" ')
66
67 sh.sendcontrol('x')
68 sh.sendcontrol('f')
69 time.sleep(0.1)
70
71 expect_prompt(sh)
72
73
74@register(not_impl_shells=['dash', 'mksh'])
75def bind_x(sh):
76 "test bind -x for setting bindings to custom shell functions"
77 expect_prompt(sh)
78
79 add_foo_fn(sh)
80 expect_prompt(sh)
81
82 send_bind(sh, """-x '"\C-x\C-f": foo' """)
83 expect_prompt(sh)
84
85 sh.sendcontrol('x')
86 sh.sendcontrol('f')
87 time.sleep(0.1)
88
89 sh.expect("FOO")
90
91
92@register(not_impl_shells=['dash', 'mksh'])
93def bind_u(sh):
94 "test bind -u for unsetting all bindings to a fn"
95 expect_prompt(sh)
96
97 send_bind(sh, "'\C-p: yank'")
98 expect_prompt(sh)
99
100 send_bind(sh, "-u yank")
101 expect_prompt(sh)
102
103 send_bind(sh, "-q yank")
104 sh.expect("yank is not bound to any keys")
105
106
107@register(not_impl_shells=['dash', 'mksh'])
108def bind_q(sh):
109 "test bind -q for querying bindings to a fn"
110 expect_prompt(sh)
111
112 # Probably bound, but we're not testing that precisely
113 send_bind(sh, "-q yank")
114 sh.expect(["yank can be invoked via", "yank is not bound to any keys"])
115
116 expect_prompt(sh)
117
118 # Probably NOT bound, but we're not testing that precisely
119 send_bind(sh, "-q dump-functions")
120 sh.expect([
121 "dump-functions can be invoked via",
122 "dump-functions is not bound to any keys"
123 ])
124
125
126@register(not_impl_shells=['dash', 'mksh'])
127def bind_m(sh):
128 "test bind -m for setting bindings in specific keymaps"
129 expect_prompt(sh)
130
131 send_bind(sh, "-u yank", "vi")
132 expect_prompt(sh)
133
134 send_bind(sh, "'\C-p: yank'", "emacs")
135 expect_prompt(sh)
136
137 send_bind(sh, "-q yank", "vi")
138 sh.expect("yank is not bound to any keys")
139 expect_prompt(sh)
140
141 send_bind(sh, "-q yank", "emacs")
142 sh.expect("yank can be invoked via")
143
144
145if __name__ == '__main__':
146 try:
147 sys.exit(harness.main(sys.argv))
148 except RuntimeError as e:
149 print('FATAL: %s' % e, file=sys.stderr)
150 sys.exit(1)