patchlevel f
shlib/Makefile.in f
support/config.guess f
-support/config.rpath f
+support/config.rpath f 755
support/config.sub f
-support/install.sh f
-support/mkdirs f
+support/install.sh f 755
+support/mkdirs f 755
support/mkdist f
-support/mkinstalldirs f
+support/mkinstalldirs f 755
support/shobj-conf f
-support/shlib-install f
+support/shlib-install f 755
support/wcwidth.c f
doc/Makefile.in f
doc/texinfo.tex f
elif test $bash_cv_termcap_lib = libncurses; then
TERMCAP_LIB=-lncurses
TERMCAP_DEP=
+elif test $bash_cv_termcap_lib = libcurses; then
+TERMCAP_LIB=-lcurses
+TERMCAP_DEP=
elif test $bash_cv_termcap_lib = libc; then
TERMCAP_LIB=
TERMCAP_DEP=
Modified by Chet Ramey for Readline.
- Copyright (C) 1985, 1988, 1990-1991, 1995-2021
+ Copyright (C) 1985, 1988, 1990-1991, 1995-2021, 2023
Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
static bool is_colored (enum indicator_no type);
static void restore_default_color (void);
-#define RL_COLOR_PREFIX_EXTENSION "readline-colored-completion-prefix"
+#define RL_COLOR_PREFIX_EXTENSION ".readline-colored-completion-prefix"
COLOR_EXT_TYPE *_rl_color_ext_list = 0;
either return its first argument (if no conversion takes place) or
newly-allocated memory. This can, for instance, convert filenames
between character sets for comparison against what's typed at the
- keyboard. The returned value is what is added to the list of
- matches. The second argument is the length of the filename to be
- converted. */
+ keyboard (after its potential modification by rl_completion_rewrite_hook).
+ The returned value is what is added to the list of matches.
+ The second argument is the length of the filename to be converted. */
rl_dequote_func_t *rl_filename_rewrite_hook = (rl_dequote_func_t *)NULL;
+/* If non-zero, this is the address of a function to call before
+ comparing the filename portion of a word to be completed with directory
+ entries from the filesystem. This takes the address of the partial word
+ to be completed, after any rl_filename_dequoting_function has been applied.
+ The function should either return its first argument (if no conversion
+ takes place) or newly-allocated memory. This can, for instance, convert
+ the filename portion of the completion word to a character set suitable
+ for comparison against directory entries read from the filesystem (after
+ their potential modification by rl_filename_rewrite_hook).
+ The returned value is what is added to the list of matches.
+ The second argument is the length of the filename to be converted. */
+rl_dequote_func_t *rl_completion_rewrite_hook = (rl_dequote_func_t *)NULL;
+
/* Non-zero means readline completion functions perform tilde expansion. */
int rl_complete_with_tilde_expansion = 0;
int
rl_possible_completions (int ignore, int invoking_key)
{
+ last_completion_failed = 0;
rl_completion_invoking_key = invoking_key;
return (rl_complete_internal ('?'));
}
append_to_match (matches[0], delimiter, quote_char, nontrivial_lcd);
break;
}
-
+ /*FALLTHROUGH*/
+
+ case '%':
do_display = 1;
break;
filename_len = strlen (filename);
/* Normalize the filename if the application has set a rewrite hook. */
- if (*filename && rl_filename_rewrite_hook)
+ if (*filename && rl_completion_rewrite_hook)
{
- temp = (*rl_filename_rewrite_hook) (filename, filename_len);
+ temp = (*rl_completion_rewrite_hook) (filename, filename_len);
if (temp != filename)
{
xfree (filename);
The line selected from the history is called the @dfn{event},
and the portions of that line that are acted upon are called @dfn{words}.
-The dfn{event designator} selects the event, the optional
+The line is broken into words in the same fashion
+that Bash does, so that several words
+surrounded by quotes are considered one word.
+The @dfn{event designator} selects the event, the optional
@dfn{word designator} selects words from the event, and
various optional @dfn{modifiers} are available to manipulate the
selected words.
-The line is broken into words in the same fashion
-that Bash does, so that several words
-surrounded by quotes are considered one word.
History expansions are introduced by the appearance of the
history expansion character, which is @samp{!} by default.
History expansions may appear anywhere in the input, but do not nest.
@code{rl_macro_dumper} calls it instead of printing anything.
If @var{readable} is greater than zero, the list is formatted in such a way
that it can be made part of an @code{inputrc} file and re-read.
-
@end deftypefun
@deftypefun int rl_variable_bind (const char *variable, const char *value)
values for only those capabilities Readline uses.
@end deftypefun
+@deftypefun {void} rl_reparse_colors (void)
+Read or re-read color definitions from @env{LS_COLORS}.
+@end deftypefun
+
@deftypefun {void} rl_clear_history (void)
Clear the history list by deleting all of the entries, in the same manner
as the History library's @code{clear_history()} function.
@deftypevar {rl_dequote_func_t *} rl_filename_rewrite_hook
If non-zero, this is the address of a function called when reading
directory entries from the filesystem for completion and comparing
-them to the partial word to be completed. The function should
+them to the filename portion of the partial word to be completed
+(after its potential modification by @code{rl_completion_rewrite_hook}).
+The function should
perform any necessary application or system-specific conversion on
the filename, such as converting between character sets or converting
from a filesystem format to a character input format.
allocated string.
@end deftypevar
+@deftypevar {rl_dequote_func_t *} rl_completion_rewrite_hook
+If non-zero, this is the address of a function to call before
+comparing the filename portion of a word to be completed with directory
+entries from the filesystem.
+The function takes two arguments: @var{fname}, the filename to be converted,
+after any @code{rl_filename_dequoting_function} has been applied,
+and @var{fnlen}, its length in bytes.
+It must either return its first argument (if no conversion takes place)
+or the converted filename in newly-allocated memory.
+The function should perform any necessary application or system-specific
+conversion on the filename, such as converting between character sets or
+converting from a character input format to some other format.
+Readline compares the converted form against directory entries, after
+their potential modification by @code{rl_filename_rewrite_hook}, and adds
+any matches to the list of matches.
+Readline will free the allocated string.
+@end deftypevar
+
@deftypevar {rl_compdisp_func_t *} rl_completion_display_matches_hook
If non-zero, then this is the address of a function to call when
completing a word would normally display the list of possible matches.
@end ifclear
+@item execute-named-command (M-x)
+Read a bindable readline command name from the input and execute the
+function to which it's bound, as if the key sequence to which it was
+bound appeared in the input.
+If this function is supplied with a numeric argument, it passes that
+argument to the function it executes.
+
@end ftable
@node Readline vi Mode
@set EDITION 8.3
@set VERSION 8.3
-@set UPDATED 31 July 2023
-@set UPDATED-MONTH July 2023
+@set UPDATED 3 November 2023
+@set UPDATED-MONTH November 2023
-@set LASTCHANGE Mon Jul 31 10:09:09 EDT 2023
+@set LASTCHANGE Fri Nov 3 12:04:26 EDT 2023
{ ISFUNC, rl_upcase_word }, /* Meta-u */
{ ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-v */
{ ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-w */
- { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-x */
+ { ISFUNC, rl_execute_named_command }, /* Meta-x */
{ ISFUNC, rl_yank_pop }, /* Meta-y */
{ ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-z */
SOURCES = excallback.c fileman.c histexamp.c manexamp.c rl-fgets.c rl.c \
rlbasic.c rlcat.c rlevent.c rlptytest.c rltest.c rlversion.c \
- rltest2.c rl-callbacktest.c hist_erasedups.c hist_purgecmd.c \
+ rl-callbacktest.c hist_erasedups.c hist_purgecmd.c \
rlkeymaps.c rl-timeout.c
EXECUTABLES = fileman$(EXEEXT) rltest$(EXEEXT) rl$(EXEEXT) rlcat$(EXEEXT) \
rlkeymaps$(EXEEXT) rl-timeout$(EXEEXT)
OBJECTS = fileman.o rltest.o rl.o rlevent.o rlcat.o rlversion.o histexamp.o \
- rltest2.o rl-callbacktest.o rlbasic.o hist_erasedups.o hist_purgecmd.o \
+ rl-callbacktest.o rlbasic.o hist_erasedups.o hist_purgecmd.o \
rlkeymaps.o rl-timeout.o
OTHEREXE = rlptytest$(EXEEXT)
elif test $bash_cv_termcap_lib = libncurses; then
TERMCAP_LIB=-lncurses
TERMCAP_DEP=
+elif test $bash_cv_termcap_lib = libcurses; then
+TERMCAP_LIB=-lcurses
+TERMCAP_DEP=
elif test $bash_cv_termcap_lib = libc; then
TERMCAP_LIB=
TERMCAP_DEP=
else
-TERMCAP_LIB=-lcurses
+TERMCAP_LIB=-lncurses
TERMCAP_DEP=
fi
])
{ "end-of-history", rl_end_of_history },
{ "end-of-line", rl_end_of_line },
{ "exchange-point-and-mark", rl_exchange_point_and_mark },
+ { "execute-named-command", rl_execute_named_command },
{ "fetch-history", rl_fetch_history },
{ "forward-backward-delete-char", rl_rubout_or_delete },
{ "forward-byte", rl_forward_byte },
if (_rl_digit_p (c))
{
+ _rl_add_executing_keyseq (key);
r = _rl_digit_value (c);
rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) + r : r;
rl_explicit_arg = 1;
}
else if (c == '-' && rl_explicit_arg == 0)
{
+ _rl_add_executing_keyseq (key);
rl_numeric_arg = 1;
_rl_argcxt |= NUM_SAWMINUS;
rl_arg_sign = -1;
_rl_set_cursor (im, force);
#endif
+ RL_UNSETSTATE (RL_STATE_OVERWRITE);
rl_insert_mode = im;
+ if (rl_insert_mode == RL_IM_OVERWRITE)
+ RL_SETSTATE (RL_STATE_OVERWRITE);
}
/* Toggle overwrite mode. A positive explicit argument selects overwrite
}
#endif /* COLOR_SUPPORT */
+static void
+free_color_ext_list (void)
+{
+ COLOR_EXT_TYPE *e;
+ COLOR_EXT_TYPE *e2;
+
+ for (e = _rl_color_ext_list; e != NULL; /* empty */)
+ {
+ e2 = e;
+ e = e->next;
+ free (e2);
+ }
+
+ _rl_color_ext_list = 0;
+}
+
void _rl_parse_colors(void)
{
#if defined (COLOR_SUPPORT)
if (state < 0)
{
- COLOR_EXT_TYPE *e;
- COLOR_EXT_TYPE *e2;
_rl_errmsg ("unparsable value for LS_COLORS environment variable");
free (color_buf);
- for (e = _rl_color_ext_list; e != NULL; /* empty */)
- {
- e2 = e;
- e = e->next;
- free (e2);
- }
- _rl_color_ext_list = NULL;
+ free_color_ext_list ();
+
_rl_colored_stats = 0; /* can't have colored stats without colors */
+ _rl_colored_completion_prefix = 0; /* or colored prefixes */
}
#else /* !COLOR_SUPPORT */
;
#endif /* !COLOR_SUPPORT */
}
+
+void
+rl_reparse_colors (void)
+{
+ char *v;
+
+ v = sh_get_env_value ("LS_COLORS");
+ if (v == 0 && color_buf == 0)
+ return; /* no change */
+ if (v && color_buf && STREQ (v, color_buf))
+ return; /* no change */
+
+ free (color_buf);
+ free_color_ext_list ();
+
+ _rl_parse_colors ();
+}
_rl_add_executing_keyseq (int key)
{
RESIZE_KEYSEQ_BUFFER ();
- rl_executing_keyseq[rl_key_sequence_length++] = key;
+ rl_executing_keyseq[rl_key_sequence_length++] = key;
}
/* `delete' the last character added to the executing key sequence. Use this
extern int rl_abort (int, int);
extern int rl_tty_status (int, int);
+extern int rl_execute_named_command (int, int);
+
/* Bindable commands for incremental and non-incremental history searching. */
extern int rl_history_search_forward (int, int);
extern int rl_history_search_backward (int, int);
extern void rl_reset_screen_size (void);
extern char *rl_get_termcap (const char *);
+extern void rl_reparse_colors (void);
/* Functions for character input. */
extern int rl_stuff_char (int);
converted. */
extern rl_dequote_func_t *rl_filename_rewrite_hook;
+/* If non-zero, this is the address of a function to call before
+ comparing the filename portion of a word to be completed with directory
+ entries from the filesystem. This takes the address of the partial word
+ to be completed, after any rl_filename_dequoting_function has been applied.
+ The function should either return its first argument (if no conversion
+ takes place) or newly-allocated memory. This can, for instance, convert
+ the filename portion of the completion word to a character set suitable
+ for comparison against directory entries read from the filesystem (after
+ their potential modification by rl_filename_rewrite_hook).
+ The returned value is what is added to the list of matches.
+ The second argument is the length of the filename to be converted. */
+extern rl_dequote_func_t *rl_completion_rewrite_hook;
+
/* Backwards compatibility with previous versions of readline. */
#define rl_symbolic_link_hook rl_directory_completion_hook
char *search_terminators;
} _rl_search_cxt;
+/* readstr flags */
+#define RL_READSTR_NOSPACE 0x01 /* don't insert space, use for completion */
+
+typedef struct __rl_readstr_context
+{
+ int flags;
+
+ int prevc;
+ int lastc;
+#if defined (HANDLE_MULTIBYTE)
+ char mb[MB_LEN_MAX];
+ char pmb[MB_LEN_MAX];
+#endif
+
+ int save_point;
+ int save_mark;
+ int save_line;
+
+ int (*compfunc) (struct __rl_readstr_context *, int);
+} _rl_readstr_cxt;
+
struct _rl_cmd {
Keymap map;
int count;
#endif
extern int _rl_set_mark_at_pos (int);
+extern _rl_readstr_cxt *_rl_rscxt_alloc (int);
+extern void _rl_rscxt_dispose (_rl_readstr_cxt *, int);
+extern void _rl_free_saved_readstr_line (void);
+extern void _rl_unsave_saved_readstr_line (void);
+extern _rl_readstr_cxt *_rl_readstr_init (int, int);
+extern int _rl_readstr_cleanup (_rl_readstr_cxt *, int);
+extern void _rl_readstr_restore (_rl_readstr_cxt *);
+extern int _rl_readstr_getchar (_rl_readstr_cxt *);
+extern int _rl_readstr_dispatch (_rl_readstr_cxt *, int);
+
/* undo.c */
extern UNDO_LIST *_rl_copy_undo_entry (UNDO_LIST *);
extern UNDO_LIST *_rl_copy_undo_list (UNDO_LIST *);
extern int _rl_optimize_typeahead;
extern int _rl_keep_mark_active;
+extern _rl_readstr_cxt *_rl_rscxt;
+
/* undo.c */
extern int _rl_doing_an_undo;
extern int _rl_undo_group_level;
extern int errno;
#endif /* !errno */
+int _rl_use_tty_xon_xoff = 1;
+
rl_vintfunc_t *rl_prep_term_function = rl_prep_terminal;
rl_voidfunc_t *rl_deprep_term_function = rl_deprep_terminal;
}
#if defined (TIOCGETC)
-# if defined (USE_XON_XOFF)
- /* Get rid of terminal output start and stop characters. */
- tiop->tchars.t_stopc = -1; /* C-s */
- tiop->tchars.t_startc = -1; /* C-q */
+ if (_rl_use_tty_xon_xoff == 0)
+ {
+ /* Get rid of terminal output start and stop characters. */
+ tiop->tchars.t_stopc = -1; /* C-s */
+ tiop->tchars.t_startc = -1; /* C-q */
- /* If there is an XON character, bind it to restart the output. */
- if (oldtio.tchars.t_startc != -1)
- rl_bind_key (oldtio.tchars.t_startc, rl_restart_output);
-# endif /* USE_XON_XOFF */
+ /* If there is an XON character, bind it to restart the output. */
+ if (oldtio.tchars.t_startc != -1)
+ rl_bind_key (oldtio.tchars.t_startc, rl_restart_output);
+ }
/* If there is an EOF char, bind _rl_eof_char to it. */
if (oldtio.tchars.t_eofc != -1)
if ((unsigned char) oldtio.c_cc[VEOF] != (unsigned char) _POSIX_VDISABLE)
_rl_eof_char = oldtio.c_cc[VEOF];
-#if defined (USE_XON_XOFF)
+ if (_rl_use_tty_xon_xoff == 0)
#if defined (IXANY)
- tiop->c_iflag &= ~(IXON | IXANY);
+ tiop->c_iflag &= ~(IXON | IXANY);
#else
- /* `strict' Posix systems do not define IXANY. */
- tiop->c_iflag &= ~IXON;
+ /* `strict' Posix systems do not define IXANY. */
+ tiop->c_iflag &= ~IXON;
#endif /* IXANY */
-#endif /* USE_XON_XOFF */
/* Only turn this off if we are using all 8 bits. */
if (((tiop->c_cflag & CSIZE) == CS8) || meta_flag)
{
return (mark_active);
}
+
+/* **************************************************************** */
+/* */
+/* Reading a string entered from the keyboard */
+/* */
+/* **************************************************************** */
+
+/* A very simple set of functions to read a string from the keyboard using
+ the line buffer as temporary storage. The caller can set a completion
+ function to perform completion on TAB and SPACE. */
+
+/* XXX - this is all very similar to the search stuff but with a different
+ CXT. */
+
+static HIST_ENTRY *_rl_saved_line_for_readstr;
+_rl_readstr_cxt *_rl_rscxt;
+
+_rl_readstr_cxt *
+_rl_rscxt_alloc (int flags)
+{
+ _rl_readstr_cxt *cxt;
+
+ cxt = (_rl_readstr_cxt *)xmalloc (sizeof (_rl_readstr_cxt));
+
+ cxt->flags = flags;
+
+ cxt->save_point = rl_point;
+ cxt->save_mark = rl_mark;
+ cxt->save_line = where_history ();
+
+ cxt->prevc = cxt->lastc = 0;
+
+ cxt->compfunc = NULL;
+
+ return cxt;
+}
+
+void
+_rl_rscxt_dispose (_rl_readstr_cxt *cxt, int flags)
+{
+ xfree (cxt);
+}
+
+void
+_rl_free_saved_readstr_line ()
+{
+ if (_rl_saved_line_for_readstr)
+ _rl_free_saved_line (_rl_saved_line_for_readstr);
+ _rl_saved_line_for_readstr = (HIST_ENTRY *)NULL;
+}
+
+void
+_rl_unsave_saved_readstr_line ()
+{
+ if (_rl_saved_line_for_readstr)
+ _rl_unsave_line (_rl_saved_line_for_readstr);
+ _rl_saved_line_for_readstr = (HIST_ENTRY *)NULL;
+}
+
+_rl_readstr_cxt *
+_rl_readstr_init (int pchar, int flags)
+{
+ _rl_readstr_cxt *cxt;
+ char *p;
+
+ cxt = _rl_rscxt_alloc (flags);
+
+ rl_maybe_replace_line ();
+ _rl_saved_line_for_readstr = _rl_alloc_saved_line ();
+
+ rl_undo_list = 0;
+
+ rl_line_buffer[0] = 0;
+ rl_end = rl_point = 0;
+
+ p = _rl_make_prompt_for_search (pchar ? pchar : '@');
+ rl_message ("%s", p);
+ xfree (p);
+
+ _rl_rscxt = cxt;
+
+ return cxt;
+}
+
+int
+_rl_readstr_cleanup (_rl_readstr_cxt *cxt, int r)
+{
+ _rl_rscxt_dispose (cxt, 0);
+ _rl_rscxt = 0;
+
+ return (r != 1);
+}
+
+void
+_rl_readstr_restore (_rl_readstr_cxt *cxt)
+{
+ _rl_unsave_saved_readstr_line (); /* restores rl_undo_list */
+ rl_point = cxt->save_point;
+ rl_mark = cxt->save_mark;
+ rl_restore_prompt (); /* _rl_make_prompt_for_search saved it */
+ rl_clear_message ();
+ _rl_fix_point (1);
+}
+
+int
+_rl_readstr_getchar (_rl_readstr_cxt *cxt)
+{
+ int c;
+
+ cxt->prevc = cxt->lastc;
+
+ /* Read a key and decide how to proceed. */
+ RL_SETSTATE(RL_STATE_MOREINPUT);
+ c = cxt->lastc = rl_read_key ();
+ RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+#if defined (HANDLE_MULTIBYTE)
+ /* This ends up with C (and LASTC) being set to the last byte of the
+ multibyte character. In most cases c == lastc == mb[0] */
+ if (c >= 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ c = cxt->lastc = _rl_read_mbstring (cxt->lastc, cxt->mb, MB_LEN_MAX);
+#endif
+
+ RL_CHECK_SIGNALS ();
+ return c;
+}
+
+/* Process just-read character C according to readstr context CXT. Return -1
+ if the caller should abort the read, 0 if we should break out of the
+ loop, and 1 if we should continue to read characters. This can perform
+ completion on the string read so far (stored in rl_line_buffer) if the
+ caller has set up a completion function. The completion function can
+ return -1 to indicate that we should abort the read. If we return -1
+ we will call _rl_readstr_restore to clean up the state, leaving the caller
+ to free the context. */
+int
+_rl_readstr_dispatch (_rl_readstr_cxt *cxt, int c)
+{
+ int n;
+
+ if (c < 0)
+ c = CTRL ('C');
+
+ switch (c)
+ {
+ case CTRL('W'):
+ rl_unix_word_rubout (1, c);
+ break;
+
+ case CTRL('U'):
+ rl_unix_line_discard (1, c);
+ break;
+
+ case CTRL('Q'):
+ case CTRL('V'):
+ n = rl_quoted_insert (1, c);
+ if (n < 0)
+ {
+ _rl_readstr_restore (cxt);
+ return -1;
+ }
+ cxt->lastc = rl_line_buffer[rl_point - 1]; /* preserve prevc */
+ break;
+
+ case RETURN:
+ case NEWLINE:
+ return 0;
+
+ case CTRL('H'):
+ case RUBOUT:
+ if (rl_point == 0)
+ {
+ _rl_readstr_restore (cxt);
+ return -1;
+ }
+ _rl_rubout_char (1, c);
+ break;
+
+ case CTRL('C'):
+ case CTRL('G'):
+ rl_ding ();
+ _rl_readstr_restore (cxt);
+ return -1;
+
+ case ESC:
+ /* Allow users to bracketed-paste text into the string.
+ Similar code is in search.c:_rl_nsearch_dispatch(). */
+ if (_rl_enable_bracketed_paste && ((n = _rl_nchars_available ()) >= (BRACK_PASTE_SLEN-1)))
+ {
+ if (_rl_read_bracketed_paste_prefix (c) == 1)
+ rl_bracketed_paste_begin (1, c);
+ else
+ {
+ c = rl_read_key (); /* get the ESC that got pushed back */
+ _rl_insert_char (1, c);
+ }
+ }
+ else
+ _rl_insert_char (1, c);
+ break;
+
+ case ' ':
+ if ((cxt->flags & RL_READSTR_NOSPACE) == 0)
+ {
+ _rl_insert_char (1, c);
+ break;
+ }
+ /* FALLTHROUGH */
+ case TAB:
+ /* Perform completion if the caller has set a completion function. */
+ n = (cxt->compfunc) ? (*cxt->compfunc) (cxt, c) : _rl_insert_char (1, c);
+ if (n < 0)
+ {
+ _rl_readstr_restore (cxt);
+ return -1;
+ }
+ break;
+
+ default:
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ rl_insert_text (cxt->mb);
+ else
+#endif
+ _rl_insert_char (1, c);
+ break;
+ }
+
+ (*rl_redisplay_function) ();
+ rl_deactivate_mark ();
+ return 1;
+}
+
+/* **************************************************************** */
+/* */
+/* Reading and Executing named commands */
+/* */
+/* **************************************************************** */
+
+/* A completion generator for bindable readline command names. */
+static char *
+readcmd_completion_function (const char *text, int state)
+{
+ static const char **cmdlist = NULL;
+ static size_t lind, nlen;
+ const char *cmdname;
+
+ if (state == 0)
+ {
+ if (cmdlist)
+ free (cmdlist);
+
+ cmdlist = rl_funmap_names ();
+ lind = 0;
+ nlen = RL_STRLEN (text);
+ }
+ if (cmdlist == 0 || cmdlist[lind] == 0)
+ return (char *)NULL;
+
+ while (cmdlist[lind])
+ {
+ cmdname = cmdlist[lind++];
+ if (STREQN (text, cmdname, nlen))
+ return (savestring (cmdname));
+ }
+ return ((char *)NULL);
+}
+
+static void
+_rl_display_cmdname_matches (char **matches)
+{
+ size_t len, max, i;
+ int old;
+
+ old = rl_filename_completion_desired;
+ rl_filename_completion_desired = 0;
+
+ /* There is more than one match. Find out how many there are,
+ and find the maximum printed length of a single entry. */
+ for (max = 0, i = 1; matches[i]; i++)
+ {
+ len = strlen (matches[i]);
+
+ if (len > max)
+ max = len;
+ }
+ len = i - 1;
+
+ rl_display_match_list (matches, len, max);
+ rl_filename_completion_desired = old;
+
+ rl_forced_update_display ();
+ rl_display_fixed = 1;
+}
+
+static int
+_rl_readcmd_complete (_rl_readstr_cxt *cxt, int c)
+{
+ char **matches;
+ char *prefix;
+ size_t plen;
+
+ matches = rl_completion_matches (rl_line_buffer, readcmd_completion_function);
+
+ if (RL_SIG_RECEIVED())
+ {
+ _rl_free_match_list (matches);
+ matches = 0;
+ RL_CHECK_SIGNALS ();
+ return -1;
+ }
+ else if (matches == 0)
+ rl_ding ();
+
+ /* Whether or not there are multiple matches, we just want to append the
+ new characters in matches[0]. We display possible matches if we didn't
+ append anything. */
+ if (matches)
+ {
+ prefix = matches[0];
+ plen = strlen (prefix);
+
+ if (plen > rl_end)
+ {
+ size_t n;
+ for (n = rl_end; n < plen && prefix[n]; n++)
+ _rl_insert_char (1, prefix[n]);
+ }
+ else if (matches[1])
+ _rl_display_cmdname_matches (matches);
+ _rl_free_match_list (matches);
+ }
+
+ return 0;
+}
+
+/* Use the readstr functions to read a bindable command name using the
+ line buffer, with completion. */
+static char *
+_rl_read_command_name ()
+{
+ _rl_readstr_cxt *cxt;
+ char *ret;
+ int c, r;
+
+ cxt = _rl_readstr_init ('!', RL_READSTR_NOSPACE);
+ cxt->compfunc = _rl_readcmd_complete;
+
+ /* skip callback stuff for now */
+ r = 0;
+ while (1)
+ {
+ c = _rl_readstr_getchar (cxt);
+
+ if (c < 0)
+ {
+ _rl_readstr_restore (cxt);
+ _rl_readstr_cleanup (cxt, r);
+ return NULL;
+ }
+
+ if (c == 0)
+ break;
+
+ r = _rl_readstr_dispatch (cxt, c);
+ if (r < 0)
+ {
+ _rl_readstr_cleanup (cxt, r);
+ return NULL; /* dispatch function cleans up */
+ }
+ else if (r == 0)
+ break;
+ }
+
+ ret = savestring (rl_line_buffer);
+
+ /* Now restore the original line and perform one final redisplay. */
+ _rl_readstr_restore (cxt);
+ (*rl_redisplay_function) ();
+
+ /* And free up the context. */
+ _rl_readstr_cleanup (cxt, r);
+ return ret;
+}
+
+/* Read a command name from the keyboard and execute it as if the bound key
+ sequence had been entered. */
+int
+rl_execute_named_command (int count, int key)
+{
+ char *command;
+ rl_command_func_t *func;
+ int r;
+
+ command = _rl_read_command_name ();
+ if (command == 0 || *command == '\0')
+ return 1;
+ if (func = rl_named_function (command))
+ {
+ int prev, ostate;
+
+ prev = rl_dispatching;
+ ostate = RL_ISSTATE (RL_STATE_DISPATCHING);
+ rl_dispatching = 1;
+ RL_SETSTATE (RL_STATE_DISPATCHING); /* make sure it's set */
+ r = (*func) (count, key);
+ if (ostate == 0)
+ RL_UNSETSTATE (RL_STATE_DISPATCHING); /* unset it if it wasn't set */
+ rl_dispatching = prev;
+ }
+ else
+ {
+ rl_ding ();
+ r = 1;
+ }
+
+ return r;
+}