diff options
Diffstat (limited to 'readline/bind.c')
-rw-r--r-- | readline/bind.c | 342 |
1 files changed, 277 insertions, 65 deletions
diff --git a/readline/bind.c b/readline/bind.c index a939528..f88e5aa 100644 --- a/readline/bind.c +++ b/readline/bind.c @@ -1,6 +1,6 @@ /* bind.c -- key binding and startup file support for the readline library. */ -/* Copyright (C) 1987-2010 Free Software Foundation, Inc. +/* Copyright (C) 1987-2012 Free Software Foundation, Inc. This file is part of the GNU Readline Library (Readline), a library for reading lines of text with interactive input and history editing. @@ -72,11 +72,15 @@ extern char *strchr (), *strrchr (); /* Variables exported by this file. */ Keymap rl_binding_keymap; +static int _rl_skip_to_delim PARAMS((char *, int, int)); + static char *_rl_read_file PARAMS((char *, size_t *)); static void _rl_init_file_error PARAMS((const char *)); static int _rl_read_init_file PARAMS((const char *, int)); static int glean_key_from_name PARAMS((char *)); + static int find_boolean_var PARAMS((const char *)); +static int find_string_var PARAMS((const char *)); static char *_rl_get_string_variable_value PARAMS((const char *)); static int substring_member_of_array PARAMS((const char *, const char * const *)); @@ -113,6 +117,9 @@ rl_bind_key (key, function) int key; rl_command_func_t *function; { + char keyseq[3]; + int l; + if (key < 0) return (key); @@ -131,8 +138,24 @@ rl_bind_key (key, function) return (key); } - _rl_keymap[key].type = ISFUNC; - _rl_keymap[key].function = function; + /* If it's bound to a function or macro, just overwrite. Otherwise we have + to treat it as a key sequence so rl_generic_bind handles shadow keymaps + for us. If we are binding '\' make sure to escape it so it makes it + through the call to rl_translate_keyseq. */ + if (_rl_keymap[key].type != ISKMAP) + { + _rl_keymap[key].type = ISFUNC; + _rl_keymap[key].function = function; + } + else + { + l = 0; + if (key == '\\') + keyseq[l++] = '\\'; + keyseq[l++] = key; + keyseq[l] = '\0'; + rl_bind_keyseq (keyseq, function); + } rl_binding_keymap = _rl_keymap; return (0); } @@ -538,7 +561,7 @@ rl_translate_keyseq (seq, array, len) case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': i++; - for (temp = 2, c -= '0'; ISOCTAL (seq[i]) && temp--; i++) + for (temp = 2, c -= '0'; ISOCTAL ((unsigned char)seq[i]) && temp--; i++) c = (c * 8) + OCTVALUE (seq[i]); i--; /* auto-increment in for loop */ array[l++] = c & largest_char; @@ -567,6 +590,40 @@ rl_translate_keyseq (seq, array, len) return (0); } +static int +_rl_isescape (c) + int c; +{ + switch (c) + { + case '\007': + case '\b': + case '\f': + case '\n': + case '\r': + case TAB: + case 0x0b: return (1); + default: return (0); + } +} + +static int +_rl_escchar (c) + int c; +{ + switch (c) + { + case '\007': return ('a'); + case '\b': return ('b'); + case '\f': return ('f'); + case '\n': return ('n'); + case '\r': return ('r'); + case TAB: return ('t'); + case 0x0b: return ('v'); + default: return (c); + } +} + char * rl_untranslate_keyseq (seq) int seq; @@ -618,9 +675,10 @@ rl_untranslate_keyseq (seq) return kseq; } -static char * -_rl_untranslate_macro_value (seq) +char * +_rl_untranslate_macro_value (seq, use_escapes) char *seq; + int use_escapes; { char *ret, *r, *s; int c; @@ -644,9 +702,14 @@ _rl_untranslate_macro_value (seq) else if (CTRL_CHAR (c)) { *r++ = '\\'; - *r++ = 'C'; - *r++ = '-'; - c = _rl_to_lower (UNCTRL (c)); + if (use_escapes && _rl_isescape (c)) + c = _rl_escchar (c); + else + { + *r++ = 'C'; + *r++ = '-'; + c = _rl_to_lower (UNCTRL (c)); + } } else if (c == RUBOUT) { @@ -1157,6 +1220,38 @@ handle_parser_directive (statement) return (1); } +/* Start at STRING[START] and look for DELIM. Return I where STRING[I] == + DELIM or STRING[I] == 0. DELIM is usually a double quote. */ +static int +_rl_skip_to_delim (string, start, delim) + char *string; + int start, delim; +{ + int i, c, passc; + + for (i = start,passc = 0; c = string[i]; i++) + { + if (passc) + { + passc = 0; + if (c == 0) + break; + continue; + } + + if (c == '\\') + { + passc = 1; + continue; + } + + if (c == delim) + break; + } + + return i; +} + /* Read the binding command from STRING and perform it. A key binding command looks like: Keyname: function-name\0, a variable binding command looks like: set variable value. @@ -1172,7 +1267,7 @@ rl_parse_and_bind (string) while (string && whitespace (*string)) string++; - if (!string || !*string || *string == '#') + if (string == 0 || *string == 0 || *string == '#') return 0; /* If this is a parser directive, act on it. */ @@ -1192,31 +1287,16 @@ rl_parse_and_bind (string) backslash to quote characters in the key expression. */ if (*string == '"') { - int passc = 0; + i = _rl_skip_to_delim (string, 1, '"'); - for (i = 1; c = string[i]; i++) - { - if (passc) - { - passc = 0; - continue; - } - - if (c == '\\') - { - passc++; - continue; - } - - if (c == '"') - break; - } /* If we didn't find a closing quote, abort the line. */ if (string[i] == '\0') { _rl_init_file_error ("no closing `\"' in key binding"); return 1; } + else + i++; /* skip past closing double quote */ } /* Advance to the colon (:) or whitespace which separates the two objects. */ @@ -1236,6 +1316,7 @@ rl_parse_and_bind (string) if (_rl_stricmp (string, "set") == 0) { char *var, *value, *e; + int s; var = string + i; /* Make VAR point to start of variable name. */ @@ -1243,25 +1324,37 @@ rl_parse_and_bind (string) /* Make VALUE point to start of value string. */ value = var; - while (*value && !whitespace (*value)) value++; + while (*value && whitespace (*value) == 0) value++; if (*value) *value++ = '\0'; while (*value && whitespace (*value)) value++; - /* Strip trailing whitespace from values to boolean variables. Temp - fix until I get a real quoted-string parser here. */ - i = find_boolean_var (var); - if (i >= 0) + /* Strip trailing whitespace from values of boolean variables. */ + if (find_boolean_var (var) >= 0) { /* remove trailing whitespace */ +remove_trailing: e = value + strlen (value) - 1; while (e >= value && whitespace (*e)) e--; e++; /* skip back to whitespace or EOS */ + if (*e && e >= value) *e = '\0'; } - + else if ((i = find_string_var (var)) >= 0) + { + /* Allow quoted strings in variable values */ + if (*value == '"') + { + i = _rl_skip_to_delim (value, 1, *value); + value[i] = '\0'; + value++; /* skip past the quote */ + } + else + goto remove_trailing; + } + rl_variable_bind (var, value); return 0; } @@ -1282,32 +1375,13 @@ rl_parse_and_bind (string) the quoted string delimiter, like the shell. */ if (*funname == '\'' || *funname == '"') { - int delimiter, passc; - - delimiter = string[i++]; - for (passc = 0; c = string[i]; i++) - { - if (passc) - { - passc = 0; - continue; - } - - if (c == '\\') - { - passc = 1; - continue; - } - - if (c == delimiter) - break; - } - if (c) + i = _rl_skip_to_delim (string, i+1, *funname); + if (string[i]) i++; } /* Advance to the end of the string. */ - for (; string[i] && !whitespace (string[i]); i++); + for (; string[i] && whitespace (string[i]) == 0; i++); /* No extra whitespace at the end of the string. */ string[i] = '\0'; @@ -1367,7 +1441,7 @@ rl_parse_and_bind (string) /* Get the actual character we want to deal with. */ kname = strrchr (string, '-'); - if (!kname) + if (kname == 0) kname = string; else kname++; @@ -1423,11 +1497,16 @@ static const struct { { "bind-tty-special-chars", &_rl_bind_stty_chars, 0 }, { "blink-matching-paren", &rl_blink_matching_paren, V_SPECIAL }, { "byte-oriented", &rl_byte_oriented, 0 }, +#if defined (COLOR_SUPPORT) + { "colored-completion-prefix",&_rl_colored_completion_prefix, 0 }, + { "colored-stats", &_rl_colored_stats, 0 }, +#endif { "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-bracketed-paste", &_rl_enable_bracketed_paste, 0 }, { "enable-keypad", &_rl_enable_keypad, 0 }, { "enable-meta-key", &_rl_enable_meta, 0 }, { "expand-tilde", &rl_complete_with_tilde_expansion, 0 }, @@ -1447,6 +1526,7 @@ static const struct { { "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 }, + { "show-mode-in-prompt", &_rl_show_mode_in_prompt, 0 }, { "skip-completed-text", &_rl_skip_completed_text, 0 }, #if defined (VISIBLE_STATS) { "visible-stats", &rl_visible_stats, 0 }, @@ -1486,6 +1566,8 @@ hack_special_boolean_var (i) else _rl_bell_preference = AUDIBLE_BELL; } + else if (_rl_stricmp (name, "show-mode-in-prompt") == 0) + _rl_reset_prompt (); } typedef int _rl_sv_func_t PARAMS((const char *)); @@ -1508,9 +1590,13 @@ 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_emacs_modestr 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 int sv_seqtimeout PARAMS((const char *)); +static int sv_viins_modestr PARAMS((const char *)); +static int sv_vicmd_modestr PARAMS((const char *)); static const struct { const char * const name; @@ -1523,9 +1609,13 @@ static const struct { { "completion-prefix-display-length", V_INT, sv_dispprefix }, { "completion-query-items", V_INT, sv_compquery }, { "editing-mode", V_STRING, sv_editmode }, + { "emacs-mode-string", V_STRING, sv_emacs_modestr }, { "history-size", V_INT, sv_histsize }, { "isearch-terminators", V_STRING, sv_isrchterm }, { "keymap", V_STRING, sv_keymap }, + { "keyseq-timeout", V_INT, sv_seqtimeout }, + { "vi-cmd-mode-string", V_STRING, sv_vicmd_modestr }, + { "vi-ins-mode-string", V_STRING, sv_viins_modestr }, { (char *)NULL, 0, (_rl_sv_func_t *)0 } }; @@ -1542,7 +1632,7 @@ find_string_var (name) } /* A boolean value that can appear in a `set variable' command is true if - the value is null or empty, `on' (case-insenstive), or "1". Any other + the value is null or empty, `on' (case-insensitive), or "1". Any other values result in 0 (false). */ static int bool_to_int (value) @@ -1683,13 +1773,17 @@ static int sv_histsize (value) const char *value; { - int nval = 500; + int nval; + nval = 500; if (value && *value) { nval = atoi (value); if (nval < 0) - return 1; + { + unstifle_history (); + return 0; + } } stifle_history (nval); return 0; @@ -1711,6 +1805,23 @@ sv_keymap (value) } static int +sv_seqtimeout (value) + const char *value; +{ + int nval; + + nval = 0; + if (value && *value) + { + nval = atoi (value); + if (nval < 0) + nval = 0; + } + _rl_keyseq_timeout = nval; + return 0; +} + +static int sv_bell_style (value) const char *value; { @@ -1748,7 +1859,7 @@ sv_isrchterm (value) } else { - for (beg = end = 0; whitespace (v[end]) == 0; end++) + for (beg = end = 0; v[end] && whitespace (v[end]) == 0; end++) ; } @@ -1762,7 +1873,96 @@ sv_isrchterm (value) xfree (v); return 0; } - + +extern char *_rl_emacs_mode_str; + +static int +sv_emacs_modestr (value) + const char *value; +{ + if (value && *value) + { + FREE (_rl_emacs_mode_str); + _rl_emacs_mode_str = (char *)xmalloc (2 * strlen (value) + 1); + rl_translate_keyseq (value, _rl_emacs_mode_str, &_rl_emacs_modestr_len); + _rl_emacs_mode_str[_rl_emacs_modestr_len] = '\0'; + return 0; + } + else if (value) + { + FREE (_rl_emacs_mode_str); + _rl_emacs_mode_str = (char *)xmalloc (1); + _rl_emacs_mode_str[_rl_emacs_modestr_len = 0] = '\0'; + return 0; + } + else if (value == 0) + { + FREE (_rl_emacs_mode_str); + _rl_emacs_mode_str = 0; /* prompt_modestr does the right thing */ + _rl_emacs_modestr_len = 0; + return 0; + } + return 1; +} + +static int +sv_viins_modestr (value) + const char *value; +{ + if (value && *value) + { + FREE (_rl_vi_ins_mode_str); + _rl_vi_ins_mode_str = (char *)xmalloc (2 * strlen (value) + 1); + rl_translate_keyseq (value, _rl_vi_ins_mode_str, &_rl_vi_ins_modestr_len); + _rl_vi_ins_mode_str[_rl_vi_ins_modestr_len] = '\0'; + return 0; + } + else if (value) + { + FREE (_rl_vi_ins_mode_str); + _rl_vi_ins_mode_str = (char *)xmalloc (1); + _rl_vi_ins_mode_str[_rl_vi_ins_modestr_len = 0] = '\0'; + return 0; + } + else if (value == 0) + { + FREE (_rl_vi_ins_mode_str); + _rl_vi_ins_mode_str = 0; /* prompt_modestr does the right thing */ + _rl_vi_ins_modestr_len = 0; + return 0; + } + return 1; +} + +static int +sv_vicmd_modestr (value) + const char *value; +{ + if (value && *value) + { + FREE (_rl_vi_cmd_mode_str); + _rl_vi_cmd_mode_str = (char *)xmalloc (2 * strlen (value) + 1); + rl_translate_keyseq (value, _rl_vi_cmd_mode_str, &_rl_vi_cmd_modestr_len); + _rl_vi_cmd_mode_str[_rl_vi_cmd_modestr_len] = '\0'; + return 0; + } + else if (value) + { + FREE (_rl_vi_cmd_mode_str); + _rl_vi_cmd_mode_str = (char *)xmalloc (1); + _rl_vi_cmd_mode_str[_rl_vi_cmd_modestr_len = 0] = '\0'; + return 0; + } + else if (value == 0) + { + FREE (_rl_vi_cmd_mode_str); + _rl_vi_cmd_mode_str = 0; /* prompt_modestr does the right thing */ + _rl_vi_cmd_modestr_len = 0; + return 0; + } + return 1; +} + /* Return the character which matches NAME. For example, `Space' returns ' '. */ @@ -2167,7 +2367,8 @@ rl_function_dumper (print_readably) } } } - free (names); + + xfree (names); } /* Print all of the current functions and their bindings to @@ -2200,7 +2401,7 @@ _rl_macro_dumper_internal (print_readably, map, prefix) { case ISMACR: keyname = _rl_get_keyname (key); - out = _rl_untranslate_macro_value ((char *)map[key].function); + out = _rl_untranslate_macro_value ((char *)map[key].function, 0); if (print_readably) fprintf (rl_outstream, "\"%s%s\": \"%s\"\n", prefix ? prefix : "", @@ -2312,7 +2513,7 @@ _rl_get_string_variable_value (name) { if (_rl_isearch_terminators == 0) return 0; - ret = _rl_untranslate_macro_value (_rl_isearch_terminators); + ret = _rl_untranslate_macro_value (_rl_isearch_terminators, 0); if (ret) { strncpy (numbuf, ret, sizeof (numbuf) - 1); @@ -2330,6 +2531,17 @@ _rl_get_string_variable_value (name) ret = rl_get_keymap_name_from_edit_mode (); return (ret ? ret : "none"); } + else if (_rl_stricmp (name, "keyseq-timeout") == 0) + { + sprintf (numbuf, "%d", _rl_keyseq_timeout); + return (numbuf); + } + else if (_rl_stricmp (name, "emacs-mode-string") == 0) + return (_rl_emacs_mode_str ? _rl_emacs_mode_str : RL_EMACS_MODESTR_DEFAULT); + else if (_rl_stricmp (name, "vi-cmd-mode-string") == 0) + return (_rl_emacs_mode_str ? _rl_emacs_mode_str : RL_VI_CMD_MODESTR_DEFAULT); + else if (_rl_stricmp (name, "vi-ins-mode-string") == 0) + return (_rl_emacs_mode_str ? _rl_emacs_mode_str : RL_VI_INS_MODESTR_DEFAULT); else return (0); } |