]>
Commit | Line | Data |
---|---|---|
726f6388 JA |
1 | This file is bind.def, from which is created bind.c. |
2 | It implements the builtin "bind" in Bash. | |
3 | ||
8868edaf | 4 | Copyright (C) 1987-2020 Free Software Foundation, Inc. |
726f6388 JA |
5 | |
6 | This file is part of GNU Bash, the Bourne Again SHell. | |
7 | ||
3185942a JA |
8 | Bash is free software: you can redistribute it and/or modify |
9 | it under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation, either version 3 of the License, or | |
11 | (at your option) any later version. | |
726f6388 | 12 | |
3185942a JA |
13 | Bash is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
726f6388 | 17 | |
3185942a JA |
18 | You should have received a copy of the GNU General Public License |
19 | along with Bash. If not, see <http://www.gnu.org/licenses/>. | |
726f6388 JA |
20 | |
21 | $PRODUCES bind.c | |
22 | ||
ccc6cda3 JA |
23 | #include <config.h> |
24 | ||
726f6388 JA |
25 | $BUILTIN bind |
26 | $DEPENDS_ON READLINE | |
27 | $FUNCTION bind_builtin | |
ac50fbac | 28 | $SHORT_DOC bind [-lpsvPSVX] [-m keymap] [-f filename] [-q name] [-u name] [-r keyseq] [-x keyseq:shell-command] [keyseq:readline-function or readline-command] |
3185942a JA |
29 | Set Readline key bindings and variables. |
30 | ||
31 | Bind a key sequence to a Readline function or a macro, or set a | |
32 | Readline variable. The non-option argument syntax is equivalent to | |
33 | that found in ~/.inputrc, but must be passed as a single argument: | |
34 | e.g., bind '"\C-x\C-r": re-read-init-file'. | |
35 | ||
36 | Options: | |
37 | -m keymap Use KEYMAP as the keymap for the duration of this | |
726f6388 JA |
38 | command. Acceptable keymap names are emacs, |
39 | emacs-standard, emacs-meta, emacs-ctlx, vi, vi-move, | |
40 | vi-command, and vi-insert. | |
41 | -l List names of functions. | |
ccc6cda3 JA |
42 | -P List function names and bindings. |
43 | -p List functions and bindings in a form that can be | |
44 | reused as input. | |
ccc6cda3 | 45 | -S List key sequences that invoke macros and their values |
7117c2d2 JA |
46 | -s List key sequences that invoke macros and their values |
47 | in a form that can be reused as input. | |
3185942a JA |
48 | -V List variable names and values |
49 | -v List variable names and values in a form that can | |
50 | be reused as input. | |
51 | -q function-name Query about which keys invoke the named function. | |
52 | -u function-name Unbind all keys which are bound to the named function. | |
53 | -r keyseq Remove the binding for KEYSEQ. | |
54 | -f filename Read key bindings from FILENAME. | |
55 | -x keyseq:shell-command Cause SHELL-COMMAND to be executed when | |
56 | KEYSEQ is entered. | |
a0c0a00f | 57 | -X List key sequences bound with -x and associated commands |
ac50fbac | 58 | in a form that can be reused as input. |
3185942a JA |
59 | |
60 | Exit Status: | |
61 | bind returns 0 unless an unrecognized option is given or an error occurs. | |
726f6388 JA |
62 | $END |
63 | ||
726f6388 | 64 | #if defined (READLINE) |
ccc6cda3 JA |
65 | |
66 | #if defined (HAVE_UNISTD_H) | |
cce855bc JA |
67 | # ifdef _MINIX |
68 | # include <sys/types.h> | |
69 | # endif | |
ccc6cda3 JA |
70 | # include <unistd.h> |
71 | #endif | |
72 | ||
73 | #include <stdio.h> | |
726f6388 JA |
74 | #include <errno.h> |
75 | #if !defined (errno) | |
76 | extern int errno; | |
77 | #endif /* !errno */ | |
ccc6cda3 | 78 | |
726f6388 JA |
79 | #include <readline/readline.h> |
80 | #include <readline/history.h> | |
ccc6cda3 | 81 | |
b80f6443 JA |
82 | #include "../bashintl.h" |
83 | ||
ccc6cda3 JA |
84 | #include "../shell.h" |
85 | #include "../bashline.h" | |
726f6388 | 86 | #include "bashgetopt.h" |
ccc6cda3 | 87 | #include "common.h" |
726f6388 | 88 | |
8868edaf CR |
89 | static int query_bindings PARAMS((char *)); |
90 | static int unbind_command PARAMS((char *)); | |
91 | static int unbind_keyseq PARAMS((char *)); | |
726f6388 JA |
92 | |
93 | #define BIND_RETURN(x) do { return_code = x; goto bind_exit; } while (0) | |
94 | ||
cce855bc JA |
95 | #define LFLAG 0x0001 |
96 | #define PFLAG 0x0002 | |
97 | #define FFLAG 0x0004 | |
98 | #define VFLAG 0x0008 | |
99 | #define QFLAG 0x0010 | |
100 | #define MFLAG 0x0020 | |
101 | #define RFLAG 0x0040 | |
102 | #define PPFLAG 0x0080 | |
103 | #define VVFLAG 0x0100 | |
104 | #define SFLAG 0x0200 | |
105 | #define SSFLAG 0x0400 | |
106 | #define UFLAG 0x0800 | |
bb70624e | 107 | #define XFLAG 0x1000 |
ac50fbac | 108 | #define XXFLAG 0x2000 |
726f6388 JA |
109 | |
110 | int | |
111 | bind_builtin (list) | |
112 | WORD_LIST *list; | |
113 | { | |
ccc6cda3 | 114 | int return_code; |
726f6388 | 115 | Keymap kmap, saved_keymap; |
ccc6cda3 | 116 | int flags, opt; |
a0c0a00f | 117 | char *initfile, *map_name, *fun_name, *unbind_name, *remove_seq, *cmd_seq, *t; |
726f6388 JA |
118 | |
119 | if (no_line_editing) | |
3185942a JA |
120 | { |
121 | #if 0 | |
122 | builtin_error (_("line editing not enabled")); | |
123 | return (EXECUTION_FAILURE); | |
124 | #else | |
125 | builtin_warning (_("line editing not enabled")); | |
126 | #endif | |
127 | } | |
726f6388 JA |
128 | |
129 | kmap = saved_keymap = (Keymap) NULL; | |
ccc6cda3 | 130 | flags = 0; |
a0c0a00f | 131 | initfile = map_name = fun_name = unbind_name = remove_seq = cmd_seq = (char *)NULL; |
ccc6cda3 | 132 | return_code = EXECUTION_SUCCESS; |
726f6388 | 133 | |
3185942a | 134 | if (bash_readline_initialized == 0) |
726f6388 JA |
135 | initialize_readline (); |
136 | ||
f73dda09 JA |
137 | begin_unwind_frame ("bind_builtin"); |
138 | unwind_protect_var (rl_outstream); | |
139 | ||
726f6388 JA |
140 | rl_outstream = stdout; |
141 | ||
142 | reset_internal_getopt (); | |
a0c0a00f | 143 | while ((opt = internal_getopt (list, "lvpVPsSXf:q:u:m:r:x:")) != -1) |
726f6388 JA |
144 | { |
145 | switch (opt) | |
146 | { | |
147 | case 'l': | |
ccc6cda3 | 148 | flags |= LFLAG; |
726f6388 | 149 | break; |
726f6388 | 150 | case 'v': |
ccc6cda3 | 151 | flags |= VFLAG; |
726f6388 | 152 | break; |
ccc6cda3 JA |
153 | case 'p': |
154 | flags |= PFLAG; | |
726f6388 | 155 | break; |
726f6388 | 156 | case 'f': |
ccc6cda3 | 157 | flags |= FFLAG; |
726f6388 JA |
158 | initfile = list_optarg; |
159 | break; | |
726f6388 | 160 | case 'm': |
ccc6cda3 | 161 | flags |= MFLAG; |
726f6388 JA |
162 | map_name = list_optarg; |
163 | break; | |
726f6388 | 164 | case 'q': |
ccc6cda3 | 165 | flags |= QFLAG; |
726f6388 JA |
166 | fun_name = list_optarg; |
167 | break; | |
cce855bc JA |
168 | case 'u': |
169 | flags |= UFLAG; | |
170 | unbind_name = list_optarg; | |
171 | break; | |
ccc6cda3 JA |
172 | case 'r': |
173 | flags |= RFLAG; | |
174 | remove_seq = list_optarg; | |
175 | break; | |
176 | case 'V': | |
177 | flags |= VVFLAG; | |
178 | break; | |
179 | case 'P': | |
180 | flags |= PPFLAG; | |
181 | break; | |
182 | case 's': | |
183 | flags |= SFLAG; | |
184 | break; | |
185 | case 'S': | |
186 | flags |= SSFLAG; | |
187 | break; | |
bb70624e JA |
188 | case 'x': |
189 | flags |= XFLAG; | |
190 | cmd_seq = list_optarg; | |
191 | break; | |
ac50fbac CR |
192 | case 'X': |
193 | flags |= XXFLAG; | |
194 | break; | |
8868edaf | 195 | case GETOPT_HELP: |
726f6388 | 196 | default: |
ccc6cda3 | 197 | builtin_usage (); |
726f6388 JA |
198 | BIND_RETURN (EX_USAGE); |
199 | } | |
200 | } | |
201 | ||
202 | list = loptend; | |
203 | ||
204 | /* First, see if we need to install a special keymap for this | |
205 | command. Then start on the arguments. */ | |
206 | ||
ccc6cda3 | 207 | if ((flags & MFLAG) && map_name) |
726f6388 JA |
208 | { |
209 | kmap = rl_get_keymap_by_name (map_name); | |
ac50fbac | 210 | if (kmap == 0) |
28ef6c31 | 211 | { |
b80f6443 | 212 | builtin_error (_("`%s': invalid keymap name"), map_name); |
726f6388 | 213 | BIND_RETURN (EXECUTION_FAILURE); |
28ef6c31 | 214 | } |
726f6388 JA |
215 | } |
216 | ||
217 | if (kmap) | |
218 | { | |
219 | saved_keymap = rl_get_keymap (); | |
220 | rl_set_keymap (kmap); | |
221 | } | |
222 | ||
223 | /* XXX - we need to add exclusive use tests here. It doesn't make sense | |
224 | to use some of these options together. */ | |
225 | /* Now hack the option arguments */ | |
ccc6cda3 JA |
226 | if (flags & LFLAG) |
227 | rl_list_funmap_names (); | |
726f6388 | 228 | |
ccc6cda3 JA |
229 | if (flags & PFLAG) |
230 | rl_function_dumper (1); | |
231 | ||
232 | if (flags & PPFLAG) | |
726f6388 JA |
233 | rl_function_dumper (0); |
234 | ||
ccc6cda3 JA |
235 | if (flags & SFLAG) |
236 | rl_macro_dumper (1); | |
237 | ||
238 | if (flags & SSFLAG) | |
239 | rl_macro_dumper (0); | |
726f6388 | 240 | |
ccc6cda3 JA |
241 | if (flags & VFLAG) |
242 | rl_variable_dumper (1); | |
243 | ||
244 | if (flags & VVFLAG) | |
245 | rl_variable_dumper (0); | |
246 | ||
247 | if ((flags & FFLAG) && initfile) | |
726f6388 JA |
248 | { |
249 | if (rl_read_init_file (initfile) != 0) | |
250 | { | |
a0c0a00f CR |
251 | t = printable_filename (initfile, 0); |
252 | builtin_error (_("%s: cannot read: %s"), t, strerror (errno)); | |
253 | if (t != initfile) | |
254 | free (t); | |
726f6388 JA |
255 | BIND_RETURN (EXECUTION_FAILURE); |
256 | } | |
257 | } | |
258 | ||
ccc6cda3 | 259 | if ((flags & QFLAG) && fun_name) |
726f6388 JA |
260 | return_code = query_bindings (fun_name); |
261 | ||
cce855bc JA |
262 | if ((flags & UFLAG) && unbind_name) |
263 | return_code = unbind_command (unbind_name); | |
264 | ||
ccc6cda3 JA |
265 | if ((flags & RFLAG) && remove_seq) |
266 | { | |
d233b485 CR |
267 | opt = unbind_keyseq (remove_seq); |
268 | BIND_RETURN (opt); | |
ccc6cda3 JA |
269 | } |
270 | ||
bb70624e JA |
271 | if (flags & XFLAG) |
272 | return_code = bind_keyseq_to_unix_command (cmd_seq); | |
273 | ||
ac50fbac CR |
274 | if (flags & XXFLAG) |
275 | return_code = print_unix_command_map (); | |
276 | ||
726f6388 JA |
277 | /* Process the rest of the arguments as binding specifications. */ |
278 | while (list) | |
279 | { | |
8868edaf CR |
280 | int olen, nlen, d, i; |
281 | char **obindings, **nbindings; | |
282 | ||
283 | obindings = rl_invoking_keyseqs (bash_execute_unix_command); | |
284 | olen = obindings ? strvec_len (obindings) : 0; | |
285 | ||
726f6388 | 286 | rl_parse_and_bind (list->word->word); |
8868edaf CR |
287 | |
288 | nbindings = rl_invoking_keyseqs (bash_execute_unix_command); | |
289 | nlen = nbindings ? strvec_len (nbindings) : 0; | |
290 | ||
291 | if (nlen < olen) /* fewer bind -x bindings */ | |
292 | for (d = olen - nlen, i = 0; i < olen && d > 0; i++) | |
293 | if (nlen == 0 || strvec_search (nbindings, obindings[i]) >= 0) | |
294 | { | |
295 | unbind_unix_command (obindings[i]); | |
296 | d--; | |
297 | } | |
298 | ||
299 | strvec_dispose (obindings); | |
300 | strvec_dispose (nbindings); | |
301 | ||
726f6388 JA |
302 | list = list->next; |
303 | } | |
304 | ||
305 | bind_exit: | |
306 | if (saved_keymap) | |
307 | rl_set_keymap (saved_keymap); | |
308 | ||
f73dda09 JA |
309 | run_unwind_frame ("bind_builtin"); |
310 | ||
8868edaf CR |
311 | if (return_code < 0) |
312 | return_code = EXECUTION_FAILURE; | |
313 | ||
3185942a | 314 | return (sh_chkwrite (return_code)); |
726f6388 JA |
315 | } |
316 | ||
317 | static int | |
318 | query_bindings (name) | |
319 | char *name; | |
320 | { | |
f73dda09 | 321 | rl_command_func_t *function; |
726f6388 JA |
322 | char **keyseqs; |
323 | int j; | |
324 | ||
325 | function = rl_named_function (name); | |
cce855bc | 326 | if (function == 0) |
726f6388 | 327 | { |
b80f6443 | 328 | builtin_error (_("`%s': unknown function name"), name); |
726f6388 JA |
329 | return EXECUTION_FAILURE; |
330 | } | |
331 | ||
332 | keyseqs = rl_invoking_keyseqs (function); | |
333 | ||
334 | if (!keyseqs) | |
335 | { | |
b80f6443 | 336 | printf (_("%s is not bound to any keys.\n"), name); |
726f6388 JA |
337 | return EXECUTION_FAILURE; |
338 | } | |
339 | ||
b80f6443 | 340 | printf (_("%s can be invoked via "), name); |
726f6388 JA |
341 | for (j = 0; j < 5 && keyseqs[j]; j++) |
342 | printf ("\"%s\"%s", keyseqs[j], keyseqs[j + 1] ? ", " : ".\n"); | |
343 | if (keyseqs[j]) | |
344 | printf ("...\n"); | |
7117c2d2 | 345 | strvec_dispose (keyseqs); |
726f6388 JA |
346 | return EXECUTION_SUCCESS; |
347 | } | |
cce855bc JA |
348 | |
349 | static int | |
350 | unbind_command (name) | |
351 | char *name; | |
352 | { | |
f73dda09 | 353 | rl_command_func_t *function; |
cce855bc JA |
354 | |
355 | function = rl_named_function (name); | |
356 | if (function == 0) | |
357 | { | |
3185942a | 358 | builtin_error (_("`%s': unknown function name"), name); |
cce855bc JA |
359 | return EXECUTION_FAILURE; |
360 | } | |
361 | ||
362 | rl_unbind_function_in_map (function, rl_get_keymap ()); | |
363 | return EXECUTION_SUCCESS; | |
364 | } | |
d233b485 CR |
365 | |
366 | static int | |
367 | unbind_keyseq (seq) | |
368 | char *seq; | |
369 | { | |
370 | char *kseq; | |
8868edaf CR |
371 | int kslen, type; |
372 | rl_command_func_t *f; | |
d233b485 CR |
373 | |
374 | kseq = (char *)xmalloc ((2 * strlen (seq)) + 1); | |
375 | if (rl_translate_keyseq (seq, kseq, &kslen)) | |
376 | { | |
377 | free (kseq); | |
378 | builtin_error (_("`%s': cannot unbind"), seq); | |
379 | return EXECUTION_FAILURE; | |
380 | } | |
8868edaf | 381 | if ((f = rl_function_of_keyseq_len (kseq, kslen, (Keymap)0, &type)) == 0) |
d233b485 CR |
382 | { |
383 | free (kseq); | |
384 | return (EXECUTION_SUCCESS); | |
385 | } | |
8868edaf CR |
386 | if (type == ISKMAP) |
387 | f = ((Keymap) f)[ANYOTHERKEY].function; | |
d233b485 CR |
388 | |
389 | /* I wish this didn't have to translate the key sequence again, but readline | |
390 | doesn't have a binding function that takes a translated key sequence as | |
391 | an argument. */ | |
392 | if (rl_bind_keyseq (seq, (rl_command_func_t *)NULL) != 0) | |
393 | { | |
394 | free (kseq); | |
395 | builtin_error (_("`%s': cannot unbind"), seq); | |
396 | return (EXECUTION_FAILURE); | |
397 | } | |
398 | ||
8868edaf CR |
399 | if (f == bash_execute_unix_command) |
400 | unbind_unix_command (seq); | |
401 | ||
d233b485 CR |
402 | free (kseq); |
403 | return (EXECUTION_SUCCESS); | |
404 | } | |
726f6388 | 405 | #endif /* READLINE */ |