diff options
Diffstat (limited to 'readline/bind.c')
-rw-r--r-- | readline/bind.c | 283 |
1 files changed, 198 insertions, 85 deletions
diff --git a/readline/bind.c b/readline/bind.c index 1ba28b4..a939528 100644 --- a/readline/bind.c +++ b/readline/bind.c @@ -1,24 +1,23 @@ /* bind.c -- key binding and startup file support for the readline library. */ -/* Copyright (C) 1987-2005 Free Software Foundation, Inc. +/* Copyright (C) 1987-2010 Free Software Foundation, Inc. - This file is part of the GNU Readline Library, a library for - reading lines of text with interactive input and history editing. + This file is part of the GNU Readline Library (Readline), a library + for reading lines of text with interactive input and history editing. - The GNU Readline Library 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 2, or + Readline 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. - The GNU Readline Library 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 + Readline 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. - The GNU General Public License is often shipped with GNU software, and - is generally kept in a file called COPYING or LICENSE. If you do not - have a copy of the license, write to the Free Software Foundation, - 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + You should have received a copy of the GNU General Public License + along with Readline. If not, see <http://www.gnu.org/licenses/>. +*/ #define READLINE_LIBRARY @@ -80,7 +79,7 @@ static int glean_key_from_name PARAMS((char *)); static int find_boolean_var PARAMS((const char *)); static char *_rl_get_string_variable_value PARAMS((const char *)); -static int substring_member_of_array PARAMS((char *, const char **)); +static int substring_member_of_array PARAMS((const char *, const char * const *)); static int currently_reading_init_file; @@ -317,7 +316,7 @@ rl_macro_bind (keyseq, macro, map) if (rl_translate_keyseq (macro, macro_keys, ¯o_keys_len)) { - free (macro_keys); + xfree (macro_keys); return -1; } rl_generic_bind (ISMACR, keyseq, macro_keys, map); @@ -347,7 +346,7 @@ rl_generic_bind (type, keyseq, data, map) if (keyseq == 0 || *keyseq == 0) { if (type == ISMACR) - free (data); + xfree (data); return -1; } @@ -358,7 +357,7 @@ rl_generic_bind (type, keyseq, data, map) KEYS into KEYS_LEN. */ if (rl_translate_keyseq (keyseq, keys, &keys_len)) { - free (keys); + xfree (keys); return -1; } @@ -370,7 +369,10 @@ rl_generic_bind (type, keyseq, data, map) ic = uc; if (ic < 0 || ic >= KEYMAP_SIZE) - return -1; + { + xfree (keys); + return -1; + } if (META_CHAR (ic) && _rl_convert_meta_chars_to_ascii) { @@ -411,11 +413,18 @@ rl_generic_bind (type, keyseq, data, map) else { if (map[ic].type == ISMACR) - free ((char *)map[ic].function); + xfree ((char *)map[ic].function); else if (map[ic].type == ISKMAP) { map = FUNCTION_TO_KEYMAP (map, ic); ic = ANYOTHERKEY; + /* If we're trying to override a keymap with a null function + (e.g., trying to unbind it), we can't use a null pointer + here because that's indistinguishable from having not been + overridden. We use a special bindable function that does + nothing. */ + if (type == ISFUNC && data == 0) + data = (char *)_rl_null_function; } map[ic].function = KEYMAP_TO_FUNCTION (data); @@ -424,7 +433,7 @@ rl_generic_bind (type, keyseq, data, map) rl_binding_keymap = map; } - free (keys); + xfree (keys); return 0; } @@ -462,12 +471,21 @@ rl_translate_keyseq (seq, array, len) } else if (c == 'M') { - i++; - /* XXX - should obey convert-meta setting? */ + i++; /* seq[i] == '-' */ + /* XXX - obey convert-meta setting */ if (_rl_convert_meta_chars_to_ascii && _rl_keymap[ESC].type == ISKMAP) array[l++] = ESC; /* ESC is meta-prefix */ + else if (seq[i+1] == '\\' && seq[i+2] == 'C' && seq[i+3] == '-') + { + i += 4; + temp = (seq[i] == '?') ? RUBOUT : CTRL (_rl_to_upper (seq[i])); + array[l++] = META (temp); + } else { + /* This doesn't yet handle things like \M-\a, which may + or may not have any reasonable meaning. You're + probably better off using straight octal or hex. */ i++; array[l++] = META (seq[i]); } @@ -565,6 +583,11 @@ rl_untranslate_keyseq (seq) kseq[i++] = '-'; c = UNMETA (c); } + else if (c == ESC) + { + kseq[i++] = '\\'; + c = 'e'; + } else if (CTRL_CHAR (c)) { kseq[i++] = '\\'; @@ -613,7 +636,12 @@ _rl_untranslate_macro_value (seq) *r++ = '-'; c = UNMETA (c); } - else if (CTRL_CHAR (c) && c != ESC) + else if (c == ESC) + { + *r++ = '\\'; + c = 'e'; + } + else if (CTRL_CHAR (c)) { *r++ = '\\'; *r++ = 'C'; @@ -672,7 +700,7 @@ rl_function_of_keyseq (keyseq, map, type) { register int i; - if (!map) + if (map == 0) map = _rl_keymap; for (i = 0; keyseq && keyseq[i]; i++) @@ -681,25 +709,27 @@ rl_function_of_keyseq (keyseq, map, type) if (META_CHAR (ic) && _rl_convert_meta_chars_to_ascii) { - if (map[ESC].type != ISKMAP) + if (map[ESC].type == ISKMAP) + { + map = FUNCTION_TO_KEYMAP (map, ESC); + ic = UNMETA (ic); + } + /* XXX - should we just return NULL here, since this obviously + doesn't match? */ + else { if (type) *type = map[ESC].type; return (map[ESC].function); } - else - { - map = FUNCTION_TO_KEYMAP (map, ESC); - ic = UNMETA (ic); - } } if (map[ic].type == ISKMAP) { /* If this is the last key in the key sequence, return the map. */ - if (!keyseq[i + 1]) + if (keyseq[i + 1] == '\0') { if (type) *type = ISKMAP; @@ -709,7 +739,12 @@ rl_function_of_keyseq (keyseq, map, type) else map = FUNCTION_TO_KEYMAP (map, ic); } - else + /* If we're not at the end of the key sequence, and the current key + is bound to something other than a keymap, then the entire key + sequence is not bound. */ + else if (map[ic].type != ISKMAP && keyseq[i+1]) + return ((rl_command_func_t *)NULL); + else /* map[ic].type != ISKMAP && keyseq[i+1] == 0 */ { if (type) *type = map[ic].type; @@ -764,10 +799,12 @@ _rl_read_file (filename, sizep) if (i < 0) { - free (buffer); + xfree (buffer); return ((char *)NULL); } + RL_CHECK_SIGNALS (); + buffer[i] = '\0'; if (sizep) *sizep = i; @@ -791,6 +828,7 @@ rl_re_read_init_file (count, ignore) 1. the filename used for the previous call 2. the value of the shell variable `INPUTRC' 3. ~/.inputrc + 4. /etc/inputrc If the file existed and could be opened and read, 0 is returned, otherwise errno is returned. */ int @@ -799,17 +837,18 @@ rl_read_init_file (filename) { /* Default the filename. */ if (filename == 0) + filename = last_readline_init_file; + if (filename == 0) + filename = sh_get_env_value ("INPUTRC"); + if (filename == 0 || *filename == 0) { - filename = last_readline_init_file; - if (filename == 0) - filename = sh_get_env_value ("INPUTRC"); - if (filename == 0) - filename = DEFAULT_INPUTRC; + filename = DEFAULT_INPUTRC; + /* Try to read DEFAULT_INPUTRC; fall back to SYS_INPUTRC on failure */ + if (_rl_read_init_file (filename, 0) == 0) + return 0; + filename = SYS_INPUTRC; } - if (*filename == 0) - filename = DEFAULT_INPUTRC; - #if defined (__MSDOS__) if (_rl_read_init_file (filename, 0) == 0) return 0; @@ -832,8 +871,9 @@ _rl_read_init_file (filename, include_level) openname = tilde_expand (filename); buffer = _rl_read_file (openname, &file_size); - free (openname); + xfree (openname); + RL_CHECK_SIGNALS (); if (buffer == 0) return (errno); @@ -880,7 +920,7 @@ _rl_read_init_file (filename, include_level) current_readline_init_lineno++; } - free (buffer); + xfree (buffer); currently_reading_init_file = 0; return (0); } @@ -890,10 +930,10 @@ _rl_init_file_error (msg) const char *msg; { if (currently_reading_init_file) - fprintf (stderr, "readline: %s: line %d: %s\n", current_readline_init_file, + _rl_errmsg ("%s: line %d: %s\n", current_readline_init_file, current_readline_init_lineno, msg); else - fprintf (stderr, "readline: %s\n", msg); + _rl_errmsg ("%s", msg); } /* **************************************************************** */ @@ -905,11 +945,11 @@ _rl_init_file_error (msg) typedef int _rl_parser_func_t PARAMS((char *)); /* Things that mean `Control'. */ -const char *_rl_possible_control_prefixes[] = { +const char * const _rl_possible_control_prefixes[] = { "Control-", "C-", "CTRL-", (const char *)NULL }; -const char *_rl_possible_meta_prefixes[] = { +const char * const _rl_possible_meta_prefixes[] = { "Meta", "M-", (const char *)NULL }; @@ -971,7 +1011,7 @@ parser_if (args) `$if term=sun-cmd' into their .inputrc. */ _rl_parsing_conditionalized_out = _rl_stricmp (args + 5, tname) && _rl_stricmp (args + 5, rl_terminal_name); - free (tname); + xfree (tname); } #if defined (VI_MODE) else if (_rl_strnicmp (args, "mode=", 5) == 0) @@ -1068,8 +1108,8 @@ parser_include (args) } /* Associate textual names with actual functions. */ -static struct { - const char *name; +static const struct { + const char * const name; _rl_parser_func_t *function; } parser_directives [] = { { "if", parser_if }, @@ -1321,7 +1361,7 @@ rl_parse_and_bind (string) else rl_bind_keyseq (seq, rl_named_function (funname)); - free (seq); + xfree (seq); return 0; } @@ -1375,8 +1415,8 @@ rl_parse_and_bind (string) #define V_SPECIAL 0x1 -static struct { - const char *name; +static const struct { + const char * const name; int *value; int flags; } boolean_varlist [] = { @@ -1384,9 +1424,12 @@ static struct { { "blink-matching-paren", &rl_blink_matching_paren, V_SPECIAL }, { "byte-oriented", &rl_byte_oriented, 0 }, { "completion-ignore-case", &_rl_completion_case_fold, 0 }, + { "completion-map-case", &_rl_completion_case_map, 0 }, { "convert-meta", &_rl_convert_meta_chars_to_ascii, 0 }, { "disable-completion", &rl_inhibit_completion, 0 }, + { "echo-control-characters", &_rl_echo_control_chars, 0 }, { "enable-keypad", &_rl_enable_keypad, 0 }, + { "enable-meta-key", &_rl_enable_meta, 0 }, { "expand-tilde", &rl_complete_with_tilde_expansion, 0 }, { "history-preserve-point", &_rl_history_preserve_point, 0 }, { "horizontal-scroll-mode", &_rl_horizontal_scroll_mode, 0 }, @@ -1395,17 +1438,20 @@ static struct { { "mark-modified-lines", &_rl_mark_modified_lines, 0 }, { "mark-symlinked-directories", &_rl_complete_mark_symlink_dirs, 0 }, { "match-hidden-files", &_rl_match_hidden_files, 0 }, + { "menu-complete-display-prefix", &_rl_menu_complete_prefix_first, 0 }, { "meta-flag", &_rl_meta_flag, 0 }, { "output-meta", &_rl_output_meta_chars, 0 }, { "page-completions", &_rl_page_completions, 0 }, { "prefer-visible-bell", &_rl_prefer_visible_bell, V_SPECIAL }, { "print-completions-horizontally", &_rl_print_completions_horizontally, 0 }, + { "revert-all-at-newline", &_rl_revert_all_at_newline, 0 }, { "show-all-if-ambiguous", &_rl_complete_show_all, 0 }, { "show-all-if-unmodified", &_rl_complete_show_unmodified, 0 }, + { "skip-completed-text", &_rl_skip_completed_text, 0 }, #if defined (VISIBLE_STATS) { "visible-stats", &rl_visible_stats, 0 }, #endif /* VISIBLE_STATS */ - { (char *)NULL, (int *)NULL } + { (char *)NULL, (int *)NULL, 0 } }; static int @@ -1458,23 +1504,29 @@ typedef int _rl_sv_func_t PARAMS((const char *)); /* Forward declarations */ static int sv_bell_style PARAMS((const char *)); static int sv_combegin PARAMS((const char *)); +static int sv_dispprefix PARAMS((const char *)); static int sv_compquery PARAMS((const char *)); +static int sv_compwidth PARAMS((const char *)); static int sv_editmode PARAMS((const char *)); +static int sv_histsize PARAMS((const char *)); static int sv_isrchterm PARAMS((const char *)); static int sv_keymap PARAMS((const char *)); -static struct { - const char *name; +static const struct { + const char * const name; int flags; _rl_sv_func_t *set_func; } string_varlist[] = { { "bell-style", V_STRING, sv_bell_style }, { "comment-begin", V_STRING, sv_combegin }, + { "completion-display-width", V_INT, sv_compwidth }, + { "completion-prefix-display-length", V_INT, sv_dispprefix }, { "completion-query-items", V_INT, sv_compquery }, { "editing-mode", V_STRING, sv_editmode }, + { "history-size", V_INT, sv_histsize }, { "isearch-terminators", V_STRING, sv_isrchterm }, { "keymap", V_STRING, sv_keymap }, - { (char *)NULL, 0 } + { (char *)NULL, 0, (_rl_sv_func_t *)0 } }; static int @@ -1506,8 +1558,6 @@ rl_variable_value (name) const char *name; { register int i; - int v; - char *ret; /* Check for simple variables first. */ i = find_boolean_var (name); @@ -1585,6 +1635,22 @@ sv_combegin (value) } static int +sv_dispprefix (value) + const char *value; +{ + int nval = 0; + + if (value && *value) + { + nval = atoi (value); + if (nval < 0) + nval = 0; + } + _rl_completion_prefix_display_length = nval; + return 0; +} + +static int sv_compquery (value) const char *value; { @@ -1601,6 +1667,35 @@ sv_compquery (value) } static int +sv_compwidth (value) + const char *value; +{ + int nval = -1; + + if (value && *value) + nval = atoi (value); + + _rl_completion_columns = nval; + return 0; +} + +static int +sv_histsize (value) + const char *value; +{ + int nval = 500; + + if (value && *value) + { + nval = atoi (value); + if (nval < 0) + return 1; + } + stifle_history (nval); + return 0; +} + +static int sv_keymap (value) const char *value; { @@ -1664,7 +1759,7 @@ sv_isrchterm (value) rl_translate_keyseq (v + beg, _rl_isearch_terminators, &end); _rl_isearch_terminators[end] = '\0'; - free (v); + xfree (v); return 0; } @@ -1672,11 +1767,11 @@ sv_isrchterm (value) For example, `Space' returns ' '. */ typedef struct { - const char *name; + const char * const name; int value; } assoc_list; -static assoc_list name_key_alist[] = { +static const assoc_list name_key_alist[] = { { "DEL", 0x7f }, { "ESC", '\033' }, { "Escape", '\033' }, @@ -1705,8 +1800,8 @@ glean_key_from_name (name) } /* Auxiliary functions to manage keymaps. */ -static struct { - const char *name; +static const struct { + const char * const name; Keymap map; } keymap_names[] = { { "emacs", emacs_standard_keymap }, @@ -1809,7 +1904,7 @@ rl_list_funmap_names () for (i = 0; funmap_names[i]; i++) fprintf (rl_outstream, "%s\n", funmap_names[i]); - free (funmap_names); + xfree (funmap_names); } static char * @@ -1948,12 +2043,16 @@ rl_invoking_keyseqs_in_map (function, map) char *keyname = (char *)xmalloc (6 + strlen (seqs[i])); if (key == ESC) -#if 0 - sprintf (keyname, "\\e"); -#else - /* XXX - experimental */ - sprintf (keyname, "\\M-"); -#endif + { + /* If ESC is the meta prefix and we're converting chars + with the eighth bit set to ESC-prefixed sequences, then + we can use \M-. Otherwise we need to use the sequence + for ESC. */ + if (_rl_convert_meta_chars_to_ascii && map[ESC].type == ISKMAP) + sprintf (keyname, "\\M-"); + else + sprintf (keyname, "\\e"); + } else if (CTRL_CHAR (key)) sprintf (keyname, "\\C-%c", _rl_to_lower (UNCTRL (key))); else if (key == RUBOUT) @@ -1971,7 +2070,7 @@ rl_invoking_keyseqs_in_map (function, map) } strcat (keyname, seqs[i]); - free (seqs[i]); + xfree (seqs[i]); if (result_index + 2 > result_size) { @@ -1983,7 +2082,7 @@ rl_invoking_keyseqs_in_map (function, map) result[result_index] = (char *)NULL; } - free (seqs); + xfree (seqs); } break; } @@ -2035,10 +2134,10 @@ rl_function_dumper (print_readably) { fprintf (rl_outstream, "\"%s\": %s\n", invokers[j], name); - free (invokers[j]); + xfree (invokers[j]); } - free (invokers); + xfree (invokers); } } else @@ -2062,9 +2161,9 @@ rl_function_dumper (print_readably) fprintf (rl_outstream, "...\n"); for (j = 0; invokers[j]; j++) - free (invokers[j]); + xfree (invokers[j]); - free (invokers); + xfree (invokers); } } } @@ -2111,8 +2210,8 @@ _rl_macro_dumper_internal (print_readably, map, prefix) fprintf (rl_outstream, "%s%s outputs %s\n", prefix ? prefix : "", keyname, out ? out : ""); - free (keyname); - free (out); + xfree (keyname); + xfree (out); break; case ISFUNC: break; @@ -2135,13 +2234,13 @@ _rl_macro_dumper_internal (print_readably, map, prefix) out = (char *)xmalloc (strlen (keyname) + prefix_len + 1); strcpy (out, prefix); strcpy (out + prefix_len, keyname); - free (keyname); + xfree (keyname); keyname = out; } } _rl_macro_dumper_internal (print_readably, FUNCTION_TO_KEYMAP (map, key), keyname); - free (keyname); + xfree (keyname); break; } } @@ -2171,7 +2270,6 @@ _rl_get_string_variable_value (name) { static char numbuf[32]; char *ret; - int n; if (_rl_stricmp (name, "bell-style") == 0) { @@ -2188,6 +2286,16 @@ _rl_get_string_variable_value (name) } else if (_rl_stricmp (name, "comment-begin") == 0) return (_rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT); + else if (_rl_stricmp (name, "completion-display-width") == 0) + { + sprintf (numbuf, "%d", _rl_completion_columns); + return (numbuf); + } + else if (_rl_stricmp (name, "completion-prefix-display-length") == 0) + { + sprintf (numbuf, "%d", _rl_completion_prefix_display_length); + return (numbuf); + } else if (_rl_stricmp (name, "completion-query-items") == 0) { sprintf (numbuf, "%d", rl_completion_query_items); @@ -2195,6 +2303,11 @@ _rl_get_string_variable_value (name) } else if (_rl_stricmp (name, "editing-mode") == 0) return (rl_get_keymap_name_from_edit_mode ()); + else if (_rl_stricmp (name, "history-size") == 0) + { + sprintf (numbuf, "%d", history_is_stifled() ? history_max_entries : 0); + return (numbuf); + } else if (_rl_stricmp (name, "isearch-terminators") == 0) { if (_rl_isearch_terminators == 0) @@ -2203,7 +2316,7 @@ _rl_get_string_variable_value (name) if (ret) { strncpy (numbuf, ret, sizeof (numbuf) - 1); - free (ret); + xfree (ret); numbuf[sizeof(numbuf) - 1] = '\0'; } else @@ -2267,8 +2380,8 @@ rl_dump_variables (count, key) /* Return non-zero if any members of ARRAY are a substring in STRING. */ static int substring_member_of_array (string, array) - char *string; - const char **array; + const char *string; + const char * const *array; { while (*array) { |