summaryrefslogtreecommitdiff
path: root/readline/bind.c
diff options
context:
space:
mode:
Diffstat (limited to 'readline/bind.c')
-rw-r--r--readline/bind.c283
1 files changed, 198 insertions, 85 deletions
diff --git a/readline/bind.c b/readline/bind.c
index 1ba28b4b673..a939528862f 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, &macro_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)
{