2 * Copyright 2004-2006 Timo Hirvonen
4 * keys.[ch] by Frank Terbeck <frank.terbeck@rwth-aachen.de>
5 * heavily modified by Timo Hirvonen
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
24 #include <ui_curses.h>
25 #include <command_mode.h>
34 const char * const key_context_names
[NR_CTXS
+ 1] = {
44 struct binding
*key_bindings
[NR_CTXS
] = { NULL
, };
46 static const enum key_context view_to_context
[] = {
55 #define KEY_IS_CHAR -255
59 * key: KEY_IS_CHAR, not a key
62 const struct key key_table
[] = {
63 { "!", KEY_IS_CHAR
, 33 },
64 { "\"", KEY_IS_CHAR
, 34 },
65 { "#", KEY_IS_CHAR
, 35 },
66 { "$", KEY_IS_CHAR
, 36 },
67 { "%", KEY_IS_CHAR
, 37 },
68 { "&", KEY_IS_CHAR
, 38 },
69 { "'", KEY_IS_CHAR
, 39 },
70 { "(", KEY_IS_CHAR
, 40 },
71 { ")", KEY_IS_CHAR
, 41 },
72 { "*", KEY_IS_CHAR
, 42 },
73 { "+", KEY_IS_CHAR
, 43 },
74 { ",", KEY_IS_CHAR
, 44 },
75 { "-", KEY_IS_CHAR
, 45 },
76 { ".", KEY_IS_CHAR
, 46 },
77 { "0", KEY_IS_CHAR
, 48 },
78 { "1", KEY_IS_CHAR
, 49 },
79 { "2", KEY_IS_CHAR
, 50 },
80 { "3", KEY_IS_CHAR
, 51 },
81 { "4", KEY_IS_CHAR
, 52 },
82 { "5", KEY_IS_CHAR
, 53 },
83 { "6", KEY_IS_CHAR
, 54 },
84 { "7", KEY_IS_CHAR
, 55 },
85 { "8", KEY_IS_CHAR
, 56 },
86 { "9", KEY_IS_CHAR
, 57 },
87 { ";", KEY_IS_CHAR
, 59 },
88 { "<", KEY_IS_CHAR
, 60 },
89 { "=", KEY_IS_CHAR
, 61 },
90 { ">", KEY_IS_CHAR
, 62 },
91 { "@", KEY_IS_CHAR
, 64 },
92 { "A", KEY_IS_CHAR
, 65 },
93 { "B", KEY_IS_CHAR
, 66 },
94 { "C", KEY_IS_CHAR
, 67 },
95 { "D", KEY_IS_CHAR
, 68 },
96 { "E", KEY_IS_CHAR
, 69 },
97 { "F", KEY_IS_CHAR
, 70 },
98 { "F1", KEY_F(1), 0 },
99 { "F10", KEY_F(10), 0 },
100 { "F11", KEY_F(11), 0 },
101 { "F12", KEY_F(12), 0 },
102 { "F2", KEY_F(2), 0 },
103 { "F3", KEY_F(3), 0 },
104 { "F4", KEY_F(4), 0 },
105 { "F5", KEY_F(5), 0 },
106 { "F6", KEY_F(6), 0 },
107 { "F7", KEY_F(7), 0 },
108 { "F8", KEY_F(8), 0 },
109 { "F9", KEY_F(9), 0 },
110 { "G", KEY_IS_CHAR
, 71 },
111 { "H", KEY_IS_CHAR
, 72 },
112 { "I", KEY_IS_CHAR
, 73 },
113 { "J", KEY_IS_CHAR
, 74 },
114 { "K", KEY_IS_CHAR
, 75 },
115 { "KP_center", KEY_B2
, 0 },
116 { "KP_lower_left", KEY_C1
, 0 },
117 { "KP_lower_right", KEY_C3
, 0 },
118 { "KP_upper_left", KEY_A1
, 0 },
119 { "KP_upper_right", KEY_A3
, 0 },
120 { "L", KEY_IS_CHAR
, 76 },
121 { "M", KEY_IS_CHAR
, 77 },
122 { "M-!", KEY_IS_CHAR
, 161 },
123 { "M-\"", KEY_IS_CHAR
, 162 },
124 { "M-#", KEY_IS_CHAR
, 163 },
125 { "M-$", KEY_IS_CHAR
, 164 },
126 { "M-%", KEY_IS_CHAR
, 165 },
127 { "M-&", KEY_IS_CHAR
, 166 },
128 { "M-'", KEY_IS_CHAR
, 167 },
129 { "M-(", KEY_IS_CHAR
, 168 },
130 { "M-)", KEY_IS_CHAR
, 169 },
131 { "M-*", KEY_IS_CHAR
, 170 },
132 { "M-+", KEY_IS_CHAR
, 171 },
133 { "M-,", KEY_IS_CHAR
, 172 },
134 { "M--", KEY_IS_CHAR
, 173 },
135 { "M-.", KEY_IS_CHAR
, 174 },
136 { "M-/", KEY_IS_CHAR
, 175 },
137 { "M-0", KEY_IS_CHAR
, 176 },
138 { "M-1", KEY_IS_CHAR
, 177 },
139 { "M-2", KEY_IS_CHAR
, 178 },
140 { "M-3", KEY_IS_CHAR
, 179 },
141 { "M-4", KEY_IS_CHAR
, 180 },
142 { "M-5", KEY_IS_CHAR
, 181 },
143 { "M-6", KEY_IS_CHAR
, 182 },
144 { "M-7", KEY_IS_CHAR
, 183 },
145 { "M-8", KEY_IS_CHAR
, 184 },
146 { "M-9", KEY_IS_CHAR
, 185 },
147 { "M-:", KEY_IS_CHAR
, 186 },
148 { "M-;", KEY_IS_CHAR
, 187 },
149 { "M-<", KEY_IS_CHAR
, 188 },
150 { "M-=", KEY_IS_CHAR
, 189 },
151 { "M->", KEY_IS_CHAR
, 190 },
152 { "M-?", KEY_IS_CHAR
, 191 },
153 { "M-@", KEY_IS_CHAR
, 192 },
154 { "M-A", KEY_IS_CHAR
, 193 },
155 { "M-B", KEY_IS_CHAR
, 194 },
156 { "M-C", KEY_IS_CHAR
, 195 },
157 { "M-D", KEY_IS_CHAR
, 196 },
158 { "M-E", KEY_IS_CHAR
, 197 },
159 { "M-F", KEY_IS_CHAR
, 198 },
160 { "M-G", KEY_IS_CHAR
, 199 },
161 { "M-H", KEY_IS_CHAR
, 200 },
162 { "M-I", KEY_IS_CHAR
, 201 },
163 { "M-J", KEY_IS_CHAR
, 202 },
164 { "M-K", KEY_IS_CHAR
, 203 },
165 { "M-L", KEY_IS_CHAR
, 204 },
166 { "M-M", KEY_IS_CHAR
, 205 },
167 { "M-N", KEY_IS_CHAR
, 206 },
168 { "M-O", KEY_IS_CHAR
, 207 },
169 { "M-P", KEY_IS_CHAR
, 208 },
170 { "M-Q", KEY_IS_CHAR
, 209 },
171 { "M-R", KEY_IS_CHAR
, 210 },
172 { "M-S", KEY_IS_CHAR
, 211 },
173 { "M-T", KEY_IS_CHAR
, 212 },
174 { "M-U", KEY_IS_CHAR
, 213 },
175 { "M-V", KEY_IS_CHAR
, 214 },
176 { "M-W", KEY_IS_CHAR
, 215 },
177 { "M-X", KEY_IS_CHAR
, 216 },
178 { "M-Y", KEY_IS_CHAR
, 217 },
179 { "M-Z", KEY_IS_CHAR
, 218 },
180 { "M-[", KEY_IS_CHAR
, 219 },
181 { "M-\\", KEY_IS_CHAR
, 220 },
182 { "M-]", KEY_IS_CHAR
, 221 },
183 { "M-^", KEY_IS_CHAR
, 222 },
184 { "M-^?", KEY_IS_CHAR
, 255 },
185 { "M-^@", KEY_IS_CHAR
, 128 },
186 { "M-^A", KEY_IS_CHAR
, 129 },
187 { "M-^B", KEY_IS_CHAR
, 130 },
188 { "M-^C", KEY_IS_CHAR
, 131 },
189 { "M-^D", KEY_IS_CHAR
, 132 },
190 { "M-^E", KEY_IS_CHAR
, 133 },
191 { "M-^F", KEY_IS_CHAR
, 134 },
192 { "M-^G", KEY_IS_CHAR
, 135 },
193 { "M-^H", KEY_IS_CHAR
, 136 },
194 { "M-^I", KEY_IS_CHAR
, 137 },
195 { "M-^J", KEY_IS_CHAR
, 138 },
196 { "M-^K", KEY_IS_CHAR
, 139 },
197 { "M-^L", KEY_IS_CHAR
, 140 },
198 { "M-^M", KEY_IS_CHAR
, 141 },
199 { "M-^N", KEY_IS_CHAR
, 142 },
200 { "M-^O", KEY_IS_CHAR
, 143 },
201 { "M-^P", KEY_IS_CHAR
, 144 },
202 { "M-^Q", KEY_IS_CHAR
, 145 },
203 { "M-^R", KEY_IS_CHAR
, 146 },
204 { "M-^S", KEY_IS_CHAR
, 147 },
205 { "M-^T", KEY_IS_CHAR
, 148 },
206 { "M-^U", KEY_IS_CHAR
, 149 },
207 { "M-^V", KEY_IS_CHAR
, 150 },
208 { "M-^W", KEY_IS_CHAR
, 151 },
209 { "M-^X", KEY_IS_CHAR
, 152 },
210 { "M-^Y", KEY_IS_CHAR
, 153 },
211 { "M-^Z", KEY_IS_CHAR
, 154 },
212 { "M-^[", KEY_IS_CHAR
, 155 },
213 { "M-^\\", KEY_IS_CHAR
, 156 },
214 { "M-^]", KEY_IS_CHAR
, 157 },
215 { "M-^^", KEY_IS_CHAR
, 158 },
216 { "M-^_", KEY_IS_CHAR
, 159 },
217 { "M-_", KEY_IS_CHAR
, 223 },
218 { "M-`", KEY_IS_CHAR
, 224 },
219 { "M-a", KEY_IS_CHAR
, 225 },
220 { "M-b", KEY_IS_CHAR
, 226 },
221 { "M-c", KEY_IS_CHAR
, 227 },
222 { "M-d", KEY_IS_CHAR
, 228 },
223 { "M-e", KEY_IS_CHAR
, 229 },
224 { "M-f", KEY_IS_CHAR
, 230 },
225 { "M-g", KEY_IS_CHAR
, 231 },
226 { "M-h", KEY_IS_CHAR
, 232 },
227 { "M-i", KEY_IS_CHAR
, 233 },
228 { "M-j", KEY_IS_CHAR
, 234 },
229 { "M-k", KEY_IS_CHAR
, 235 },
230 { "M-l", KEY_IS_CHAR
, 236 },
231 { "M-m", KEY_IS_CHAR
, 237 },
232 { "M-n", KEY_IS_CHAR
, 238 },
233 { "M-o", KEY_IS_CHAR
, 239 },
234 { "M-p", KEY_IS_CHAR
, 240 },
235 { "M-q", KEY_IS_CHAR
, 241 },
236 { "M-r", KEY_IS_CHAR
, 242 },
237 { "M-s", KEY_IS_CHAR
, 243 },
238 { "M-space", KEY_IS_CHAR
, 160 },
239 { "M-t", KEY_IS_CHAR
, 244 },
240 { "M-u", KEY_IS_CHAR
, 245 },
241 { "M-v", KEY_IS_CHAR
, 246 },
242 { "M-w", KEY_IS_CHAR
, 247 },
243 { "M-x", KEY_IS_CHAR
, 248 },
244 { "M-y", KEY_IS_CHAR
, 249 },
245 { "M-z", KEY_IS_CHAR
, 250 },
246 { "M-{", KEY_IS_CHAR
, 251 },
247 { "M-|", KEY_IS_CHAR
, 252 },
248 { "M-}", KEY_IS_CHAR
, 253 },
249 { "M-~", KEY_IS_CHAR
, 254 },
250 { "N", KEY_IS_CHAR
, 78 },
251 { "O", KEY_IS_CHAR
, 79 },
252 { "P", KEY_IS_CHAR
, 80 },
253 { "Q", KEY_IS_CHAR
, 81 },
254 { "R", KEY_IS_CHAR
, 82 },
255 { "S", KEY_IS_CHAR
, 83 },
256 { "S-begin", KEY_SBEG
, 0 },
257 { "S-cancel", KEY_SCANCEL
, 0 },
258 { "S-command", KEY_SCOMMAND
, 0 },
259 { "S-copy", KEY_SCOPY
, 0 },
260 { "S-create", KEY_SCREATE
, 0 },
261 { "S-del_line", KEY_SDL
, 0 },
262 { "S-delete", KEY_SDC
, 0 },
263 { "S-eol", KEY_SEOL
, 0 },
264 { "S-exit", KEY_SEXIT
, 0 },
265 { "S-find", KEY_SFIND
, 0 },
266 { "S-help", KEY_SHELP
, 0 },
267 { "S-home", KEY_SHOME
, 0 },
268 { "S-insert", KEY_SIC
, 0 },
269 { "S-left", KEY_SLEFT
, 0 },
270 { "S-message", KEY_SMESSAGE
, 0 },
271 { "S-move", KEY_SMOVE
, 0 },
272 { "S-next", KEY_SNEXT
, 0 },
273 { "S-options", KEY_SOPTIONS
, 0 },
274 { "S-previous", KEY_SPREVIOUS
, 0 },
275 { "S-print", KEY_SPRINT
, 0 },
276 { "S-redo", KEY_SREDO
, 0 },
277 { "S-replace", KEY_SREPLACE
, 0 },
278 { "S-resume", KEY_SRSUME
, 0 },
279 { "S-right", KEY_SRIGHT
, 0 },
280 { "S-save", KEY_SSAVE
, 0 },
281 { "S-suspend", KEY_SSUSPEND
, 0 },
282 { "S-undo", KEY_SUNDO
, 0 },
283 { "T", KEY_IS_CHAR
, 84 },
284 { "U", KEY_IS_CHAR
, 85 },
285 { "V", KEY_IS_CHAR
, 86 },
286 { "W", KEY_IS_CHAR
, 87 },
287 { "X", KEY_IS_CHAR
, 88 },
288 { "Y", KEY_IS_CHAR
, 89 },
289 { "Z", KEY_IS_CHAR
, 90 },
290 { "[", KEY_IS_CHAR
, 91 },
291 { "\\", KEY_IS_CHAR
, 92 },
292 { "]", KEY_IS_CHAR
, 93 },
293 { "^", KEY_IS_CHAR
, 94 },
294 { "^A", KEY_IS_CHAR
, 1 },
295 { "^B", KEY_IS_CHAR
, 2 },
296 { "^C", KEY_IS_CHAR
, 3 },
297 { "^D", KEY_IS_CHAR
, 4 },
298 { "^E", KEY_IS_CHAR
, 5 },
299 { "^F", KEY_IS_CHAR
, 6 },
300 { "^G", KEY_IS_CHAR
, 7 },
301 { "^H", KEY_IS_CHAR
, 8 },
302 { "^K", KEY_IS_CHAR
, 11 },
303 { "^L", KEY_IS_CHAR
, 12 },
304 { "^M", KEY_IS_CHAR
, 13 },
305 { "^N", KEY_IS_CHAR
, 14 },
306 { "^O", KEY_IS_CHAR
, 15 },
307 { "^P", KEY_IS_CHAR
, 16 },
308 { "^Q", KEY_IS_CHAR
, 17 },
309 { "^R", KEY_IS_CHAR
, 18 },
310 { "^S", KEY_IS_CHAR
, 19 },
311 { "^T", KEY_IS_CHAR
, 20 },
312 { "^U", KEY_IS_CHAR
, 21 },
313 { "^V", KEY_IS_CHAR
, 22 },
314 { "^W", KEY_IS_CHAR
, 23 },
315 { "^X", KEY_IS_CHAR
, 24 },
316 { "^Y", KEY_IS_CHAR
, 25 },
317 { "^Z", KEY_IS_CHAR
, 26 },
318 { "^\\", KEY_IS_CHAR
, 28 },
319 { "^]", KEY_IS_CHAR
, 29 },
320 { "^^", KEY_IS_CHAR
, 30 },
321 { "^_", KEY_IS_CHAR
, 31 },
322 { "_", KEY_IS_CHAR
, 95 },
323 { "`", KEY_IS_CHAR
, 96 },
324 { "a", KEY_IS_CHAR
, 97 },
325 { "b", KEY_IS_CHAR
, 98 },
326 { "back_tab", KEY_BTAB
, 0 },
327 { "backspace", KEY_BACKSPACE
, 127 }, /* NOTE: both key and ch */
328 { "begin", KEY_BEG
, 0 },
329 { "c", KEY_IS_CHAR
, 99 },
330 { "cancel", KEY_CANCEL
, 0 },
331 { "clear", KEY_CLEAR
, 0 },
332 { "clear_all_tabs", KEY_CATAB
, 0 },
333 { "clear_tab", KEY_CTAB
, 0 },
334 { "close", KEY_CLOSE
, 0 },
335 { "command", KEY_COMMAND
, 0 },
336 { "copy", KEY_COPY
, 0 },
337 { "create", KEY_CREATE
, 0 },
338 { "d", KEY_IS_CHAR
, 100 },
339 { "del_line", KEY_DL
, 0 },
340 { "delete", KEY_DC
, 0 },
341 { "down", KEY_DOWN
, 0 },
342 { "e", KEY_IS_CHAR
, 101 },
343 { "eic", KEY_EIC
, 0 },
344 { "end", KEY_END
, 0 },
345 { "enter", KEY_IS_CHAR
, 10 },
346 { "eol", KEY_EOL
, 0 },
347 { "eos", KEY_EOS
, 0 },
348 { "exit", KEY_EXIT
, 0 },
349 { "f", KEY_IS_CHAR
, 102 },
350 { "find", KEY_FIND
, 0 },
351 { "g", KEY_IS_CHAR
, 103 },
352 { "h", KEY_IS_CHAR
, 104 },
353 { "help", KEY_HELP
, 0 },
354 { "home", KEY_HOME
, 0 },
355 { "i", KEY_IS_CHAR
, 105 },
356 { "ins_line", KEY_IL
, 0 },
357 { "insert", KEY_IC
, 0 },
358 { "j", KEY_IS_CHAR
, 106 },
359 { "k", KEY_IS_CHAR
, 107 },
360 { "l", KEY_IS_CHAR
, 108 },
361 { "left", KEY_LEFT
, 0 },
362 { "lower_left", KEY_LL
, 0 },
363 { "m", KEY_IS_CHAR
, 109 },
364 { "mark", KEY_MARK
, 0 },
365 { "message", KEY_MESSAGE
, 0 },
366 { "move", KEY_MOVE
, 0 },
367 { "n", KEY_IS_CHAR
, 110 },
368 { "next", KEY_NEXT
, 0 },
369 { "o", KEY_IS_CHAR
, 111 },
370 { "open", KEY_OPEN
, 0 },
371 { "options", KEY_OPTIONS
, 0 },
372 { "p", KEY_IS_CHAR
, 112 },
373 { "page_down", KEY_NPAGE
, 0 },
374 { "page_up", KEY_PPAGE
, 0 },
375 { "previous", KEY_PREVIOUS
, 0 },
376 { "print", KEY_PRINT
, 0 },
377 { "q", KEY_IS_CHAR
, 113 },
378 { "r", KEY_IS_CHAR
, 114 },
379 { "redo", KEY_REDO
, 0 },
380 { "reference", KEY_REFERENCE
, 0 },
381 { "refresh", KEY_REFRESH
, 0 },
382 { "replace", KEY_REPLACE
, 0 },
383 { "restart", KEY_RESTART
, 0 },
384 { "resume", KEY_RESUME
, 0 },
385 { "right", KEY_RIGHT
, 0 },
386 { "s", KEY_IS_CHAR
, 115 },
387 { "save", KEY_SAVE
, 0 },
388 { "scroll_b", KEY_SR
, 0 },
389 { "scroll_f", KEY_SF
, 0 },
390 { "select", KEY_SELECT
, 0 },
391 { "send", KEY_SEND
, 0 },
392 { "set_tab", KEY_STAB
, 0 },
393 { "space", KEY_IS_CHAR
, 32 },
394 { "suspend", KEY_SUSPEND
, 0 },
395 { "t", KEY_IS_CHAR
, 116 },
396 { "tab", KEY_IS_CHAR
, 9 },
397 { "u", KEY_IS_CHAR
, 117 },
398 { "undo", KEY_UNDO
, 0 },
400 { "v", KEY_IS_CHAR
, 118 },
401 { "w", KEY_IS_CHAR
, 119 },
402 { "x", KEY_IS_CHAR
, 120 },
403 { "y", KEY_IS_CHAR
, 121 },
404 { "z", KEY_IS_CHAR
, 122 },
405 { "{", KEY_IS_CHAR
, 123 },
406 { "|", KEY_IS_CHAR
, 124 },
407 { "}", KEY_IS_CHAR
, 125 },
408 { "~", KEY_IS_CHAR
, 126 },
413 static int find_context(const char *name
)
417 for (i
= 0; i
< NR_CTXS
; i
++) {
418 if (strcmp(name
, key_context_names
[i
]) == 0)
421 error_msg("invalid context '%s'", name
);
425 static const struct key
*find_key(const char *name
)
429 for (i
= 0; key_table
[i
].name
; i
++) {
430 if (strcmp(name
, key_table
[i
].name
) == 0)
431 return &key_table
[i
];
433 error_msg("invalid key '%s'", name
);
437 static struct binding
*find_binding(enum key_context c
, const struct key
*k
)
439 struct binding
*b
= key_bindings
[c
];
449 void show_binding(const char *context
, const char *key
)
452 const struct binding
*b
;
455 c
= find_context(context
);
463 b
= find_binding(c
, k
);
465 info_msg("No such binding");
467 info_msg("bind %s %s %s", context
, key
, b
->cmd
);
471 int key_bind(const char *context
, const char *key
, const char *cmd
, int force
)
474 struct binding
*b
, *ptr
, *prev
;
477 c
= find_context(context
);
485 /* check if already bound */
486 b
= find_binding(c
, k
);
490 key_unbind(context
, key
, 0);
495 size
= strlen(cmd
) + 1;
497 b
= xmalloc(sizeof(struct binding
) + size
);
499 memcpy(b
->cmd
, cmd
, size
);
501 /* insert keeping sorted by key */
503 ptr
= key_bindings
[c
];
505 if (strcmp(b
->key
->name
, ptr
->key
->name
) < 0)
518 error_msg("key %s already bound in context %s", key
, key_context_names
[c
]);
522 int key_unbind(const char *context
, const char *key
, int force
)
526 struct binding
*b
, *prev
;
528 c
= find_context(context
);
541 prev
->next
= b
->next
;
543 key_bindings
[c
] = b
->next
;
552 error_msg("key %s not bound in context %s", key
, context
);
558 static int handle_key(const struct binding
*b
, const struct key
*k
)
570 static const struct key
*ch_to_key(uchar ch
)
574 for (i
= 0; key_table
[i
].name
; i
++) {
575 if (key_table
[i
].ch
== ch
)
576 return &key_table
[i
];
581 static const struct key
*keycode_to_key(int key
)
585 for (i
= 0; key_table
[i
].name
; i
++) {
586 if (key_table
[i
].key
!= KEY_IS_CHAR
&& key_table
[i
].key
== key
)
587 return &key_table
[i
];
592 void normal_mode_ch(uchar ch
)
597 /* you can't redefine these keys */
600 enter_command_mode();
606 enter_search_backward_mode();
610 c
= view_to_context
[cur_view
];
617 /* view-specific ch */
618 if (handle_key(key_bindings
[c
], k
))
622 handle_key(key_bindings
[CTX_COMMON
], k
);
625 void normal_mode_key(int key
)
627 enum key_context c
= view_to_context
[cur_view
];
628 const struct key
*k
= keycode_to_key(key
);
634 /* view-specific key */
635 if (handle_key(key_bindings
[c
], k
))
639 handle_key(key_bindings
[CTX_COMMON
], k
);