Integrate new readline from Brian Fox.

This commit is contained in:
Stu Grossman
1991-11-19 05:59:18 +00:00
parent c5bbc6ea41
commit 870ca25340
9 changed files with 2488 additions and 1018 deletions

View File

@@ -3,22 +3,30 @@
Version 1, February 1989
Copyright (C) 1989 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
The Free Software Foundation has exempted Bash from the requirement of
Paragraph 2c of the General Public License. This is to say, there is
no requirement for Bash to print a notice when it is started
interactively in the usual way. We made this exception because users
and standards expect shells not to print such messages. This
exception applies to any program that serves as a shell and that is
based primarily on Bash as opposed to other GNU software.
Preamble
The license agreements of most software companies try to keep users
at the mercy of those companies. By contrast, our General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. The
software--to make sure the software is free for all its users. The
General Public License applies to the Free Software Foundation's
software and to any other program whose authors commit to using it.
You can use it for your programs, too.
When we speak of free software, we are referring to freedom, not
price. Specifically, the General Public License is designed to make
price. Specifically, the General Public License is designed to make
sure that you have the freedom to give away or sell copies of free
software, that you receive source code or can get it if you want it,
that you can change the software or use pieces of it in new free
@@ -65,7 +73,7 @@ appropriately publish on each copy an appropriate copyright notice and
disclaimer of warranty; keep intact all the notices that refer to this
General Public License and to the absence of any warranty; and give any
other recipients of the Program a copy of this General Public License
along with the Program. You may charge a fee for the physical act of
along with the Program. You may charge a fee for the physical act of
transferring a copy.
2. You may modify your copy or copies of the Program or any portion of
@@ -114,7 +122,7 @@ Paragraphs 1 and 2 above provided that you also do one of the following:
Paragraphs 1 and 2 above; or,
c) accompany it with the information you received as to where the
corresponding source code may be obtained. (This alternative is
corresponding source code may be obtained. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form alone.)
@@ -130,7 +138,7 @@ accompany that operating system.
Program except as expressly provided under this General Public License.
Any attempt otherwise to copy, modify, sublicense, distribute or transfer
the Program is void, and will automatically terminate your rights to use
the Program under this License. However, parties who have received
the Program under this License. However, parties who have received
copies, or rights to use copies, from you under this General Public
License will not have their licenses terminated so long as such parties
remain in full compliance.
@@ -150,7 +158,7 @@ of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
Each version is given a distinguishing version number. If the Program
specifies a version number of the license which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
@@ -160,7 +168,7 @@ Foundation.
8. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
@@ -203,7 +211,7 @@ the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,40 +1,96 @@
Mon Nov 11 20:50:29 1991 Steve Chamberlain (sac at cygnus.com)
Fri Nov 1 07:02:13 1991 Brian Fox (bfox at gnuwest.fsf.org)
* Makefile.in: Use the MINUS_G no-debug convention
* readline.c: (many_places) move all the declarations of rindex to
only one place, to reduce the number of warnings it makes.
* readline.c (rl_translate_keyseq) Make C-? translate to RUBOUT
unconditionally.
Sat Nov 9 03:19:40 1991 John Gilmore (gnu at cygnus.com)
Mon Oct 28 11:34:52 1991 Brian Fox (bfox at gnuwest.fsf.org)
* configure.in: Make a link for sysdep.h. Specify commontargets.
* sysdep-norm.h: The usual alloca declarations.
* sysdep-aix.h: What AIX 3.1 on RS/6000 needs for alloca.
* history.c, readline.c: Use sysdep.h.
* readline.c; Use Posix directory routines and macros.
Thu Oct 24 21:58:46 1991 John Gilmore (gnu at cygnus.com)
* funmap.c; Add entry for call-last-kbd-macro.
* configure.in: aix is a Sys V as far as we're concerned.
Switch to new config/hm-* scheme.
* readline.c (rl_prep_term); Use system EOF character on POSIX
systems also.
Thu Oct 24 02:08:50 1991 Fred Fish (fnf at cygnus.com)
Thu Oct 3 16:19:53 1991 Brian Fox (bfox at gnuwest.fsf.org)
* config/hmake-sysv: Send RANLIB (echo) output to /dev/null.
* readline.c; Make a distinction between having a TERMIOS tty
driver, and having POSIX signal handling. You might one without
the other. New defines used HAVE_POSIX_SIGNALS, and
TERMIOS_TTY_DRIVER.
Tue Sep 17 17:44:22 1991 Stu Grossman (grossman at cygnus.com)
Tue Jul 30 22:37:26 1991 Brian Fox (bfox at gnuwest.fsf.org)
* config/hmake-sysv: sgi/irix support.
* readline.c: rl_getc () If a call to read () returns without an
error, but with zero characters, the file is empty, so return EOF.
Sun May 19 07:49:34 1991 John Gilmore and Rich Pixley (at cygnus.com)
Thu Jul 11 20:58:38 1991 Brian Fox (bfox at gnuwest.fsf.org)
Make readline independent of the applications that use it.
* readline.c: (rl_get_next_history, rl_get_previous_history)
Reallocate the buffer space if the line being moved to is longer
the the current space allocated. Amazing that no one has found
this bug until now.
* readline.h, keymaps.h: include other include files with "foo.h"
rather than <readline/foo.h>. This works here, and works when
included from other applications.
Sun Jul 7 02:37:05 1991 Brian Fox (bfox at gnuwest.fsf.org)
* Makefile.in: Create template for configurable Makefile.
This version is not ready for prime time, so we have left
Makefile itself (the original version) too.
* readline.c:(rl_parse_and_bind) Allow leading whitespace.
Make sure TERMIO and TERMIOS systems treat CR and NL
disctinctly.
Tue Jun 25 04:09:27 1991 Brian Fox (bfox at gnuwest.fsf.org)
* readline.c: Rework parsing conditionals to pay attention to the
prior states of the conditional stack. This makes $if statements
work correctly.
Mon Jun 24 20:45:59 1991 Brian Fox (bfox at gnuwest.fsf.org)
* readline.c: support for displaying key binding information
includes the functions rl_list_funmap_names (),
invoking_keyseqs_in_map (), rl_invoking_keyseqs (),
rl_dump_functions (), and rl_function_dumper ().
funmap.c: support for same includes rl_funmap_names ().
readline.c, funmap.c: no longer define STATIC_MALLOC. However,
update both version of xrealloc () to handle a null pointer.
Thu Apr 25 12:03:49 1991 Brian Fox (bfox at gnuwest.fsf.org)
* vi_mode.c (rl_vi_fword, fWord, etc. All functions use
the macro `isident()'. Fixed movement bug which prevents
continious movement through the text.
Fri Jul 27 16:47:01 1990 Brian Fox (bfox at gnuwest.fsf.org)
* readline.c (parser_if) Allow "$if term=foo" construct.
Wed May 23 16:10:33 1990 Brian Fox (bfox at gnuwest.fsf.org)
* readline.c (rl_dispatch) Correctly remember the last command
executed. Fixed typo in username_completion_function ().
Mon Apr 9 19:55:48 1990 Brian Fox (bfox at gnuwest.fsf.org)
* readline.c: username_completion_function (); For text passed in
with a leading `~', remember that this could be a filename (after
it is completed).
Thu Apr 5 13:44:24 1990 Brian Fox (bfox at gnuwest.fsf.org)
* readline.c: rl_search_history (): Correctly handle case of an
unfound search string, but a graceful exit (as with ESC).
* readline.c: rl_restart_output (); The Apollo passes the address
of the file descriptor to TIOCSTART, not the descriptor itself.
Tue Mar 20 05:38:55 1990 Brian Fox (bfox at gnuwest.fsf.org)
* readline.c: rl_complete (); second call in a row causes possible
completions to be listed.
* readline.c: rl_redisplay (), added prompt_this_line variable
which is the first character character following \n in prompt.
Sun Mar 11 04:32:03 1990 Brian Fox (bfox at gnuwest.fsf.org)
@@ -47,8 +103,10 @@ Wed Jan 17 19:24:09 1990 Brian Fox (bfox at sbphy.ucsb.edu)
Thu Jan 11 10:54:04 1990 Brian Fox (bfox at sbphy.ucsb.edu)
* readline.c, readline.h: added rl_show_star to control the
display of an asterisk on modified history lines.
* readline.c: added mark_modified_lines to control the
display of an asterisk on modified history lines. Also
added a user variable called mark-modified-lines to the
`set' command.
Thu Jan 4 10:38:05 1990 Brian Fox (bfox at sbphy.ucsb.edu)
@@ -117,4 +175,3 @@ Wed Jun 28 20:20:51 1989 Brian Fox (bfox at aurel)
* Made readline and history into independent libraries.

View File

@@ -40,7 +40,7 @@ KEYMAP_ENTRY_ARRAY emacs_standard_keymap = {
{ ISFUNC, rl_end_of_line }, /* Control-e */
{ ISFUNC, rl_forward }, /* Control-f */
{ ISFUNC, rl_abort }, /* Control-g */
{ ISFUNC, rl_backward }, /* Control-h */
{ ISFUNC, rl_rubout }, /* Control-h */
{ ISFUNC, rl_complete }, /* Control-i */
{ ISFUNC, rl_newline }, /* Control-j */
{ ISFUNC, rl_kill_line }, /* Control-k */
@@ -188,7 +188,7 @@ KEYMAP_ENTRY_ARRAY emacs_meta_keymap = {
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-f */
{ ISFUNC, rl_abort }, /* Meta-Control-g */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-h */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-i */
{ ISFUNC, rl_tab_insert }, /* Meta-Control-i */
{ ISFUNC, rl_vi_editing_mode }, /* Meta-Control-j */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-k */
{ ISFUNC, (Function *)0x0 }, /* Meta-Control-l */
@@ -281,7 +281,7 @@ KEYMAP_ENTRY_ARRAY emacs_meta_keymap = {
{ ISFUNC, rl_do_lowercase_version }, /* Meta-Z */
/* Some more punctuation. */
{ ISFUNC, (Function *)0x0 }, /* Meta-[ */
{ ISFUNC, rl_arrow_keys }, /* Meta-[ */
{ ISFUNC, (Function *)0x0 }, /* Meta-\ */
{ ISFUNC, (Function *)0x0 }, /* Meta-] */
{ ISFUNC, (Function *)0x0 }, /* Meta-^ */
@@ -303,7 +303,7 @@ KEYMAP_ENTRY_ARRAY emacs_meta_keymap = {
{ ISFUNC, rl_downcase_word }, /* Meta-l */
{ ISFUNC, (Function *)0x0 }, /* Meta-m */
{ ISFUNC, (Function *)0x0 }, /* Meta-n */
{ ISFUNC, (Function *)0x0 }, /* Meta-o */
{ ISFUNC, rl_arrow_keys }, /* Meta-o */
{ ISFUNC, (Function *)0x0 }, /* Meta-p */
{ ISFUNC, (Function *)0x0 }, /* Meta-q */
{ ISFUNC, rl_revert_line }, /* Meta-r */

View File

@@ -19,16 +19,16 @@
along with Readline; see the file COPYING. If not, write to the Free
Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define STATIC_MALLOC
#ifndef STATIC_MALLOC
/* #define STATIC_MALLOC */
#if !defined (STATIC_MALLOC)
extern char *xmalloc (), *xrealloc ();
#else
static char *xmalloc (), *xrealloc ();
#endif
#endif /* STATIC_MALLOC */
#ifndef FILE
#if !defined (BUFSIZ)
#include <stdio.h>
#endif /* FILE */
#endif /* BUFSIZ */
#include "readline.h"
@@ -36,92 +36,103 @@ FUNMAP **funmap = (FUNMAP **)NULL;
static int funmap_size = 0;
static int funmap_entry = 0;
/* After initializing the function map, this is the index of the first
program specific function. */
int funmap_program_specific_entry_start;
static FUNMAP default_funmap[] = {
{ "beginning-of-line", rl_beg_of_line },
{ "abort", rl_abort },
{ "accept-line", rl_newline },
{ "arrow-key-prefix", rl_arrow_keys },
{ "backward-char", rl_backward },
{ "backward-delete-char", rl_rubout },
{ "backward-kill-line", rl_backward_kill_line },
{ "backward-kill-word", rl_backward_kill_word },
{ "backward-word", rl_backward_word },
{ "beginning-of-history", rl_beginning_of_history },
{ "beginning-of-line", rl_beg_of_line },
{ "call-last-kbd-macro", rl_call_last_kbd_macro },
{ "capitalize-word", rl_capitalize_word },
{ "clear-screen", rl_clear_screen },
{ "complete", rl_complete },
{ "delete-char", rl_delete },
{ "digit-argument", rl_digit_argument },
{ "do-lowercase-version", rl_do_lowercase_version },
{ "downcase-word", rl_downcase_word },
{ "dump-functions", rl_dump_functions },
{ "end-kbd-macro", rl_end_kbd_macro },
{ "end-of-history", rl_end_of_history },
{ "end-of-line", rl_end_of_line },
{ "forward-char", rl_forward },
{ "accept-line", rl_newline },
{ "forward-search-history", rl_forward_search_history },
{ "forward-word", rl_forward_word },
{ "kill-line", rl_kill_line },
{ "clear-screen", rl_clear_screen },
{ "kill-word", rl_kill_word },
{ "next-history", rl_get_next_history },
{ "possible-completions", rl_possible_completions },
{ "previous-history", rl_get_previous_history },
{ "quoted-insert", rl_quoted_insert },
{ "re-read-init-file", rl_re_read_init_file },
{ "redraw-current-line", rl_refresh_line},
{ "reverse-search-history", rl_reverse_search_history },
{ "forward-search-history", rl_forward_search_history },
{ "transpose-chars", rl_transpose_chars },
{ "unix-line-discard", rl_unix_line_discard },
{ "unix-word-rubout", rl_unix_word_rubout },
{ "yank", rl_yank },
{ "yank-pop", rl_yank_pop },
{ "yank-nth-arg", rl_yank_nth_arg },
{ "backward-delete-char", rl_rubout },
{ "backward-word", rl_backward_word },
{ "kill-word", rl_kill_word },
{ "forward-word", rl_forward_word },
{ "tab-insert", rl_tab_insert },
{ "backward-kill-word", rl_backward_kill_word },
{ "backward-kill-line", rl_backward_kill_line },
{ "transpose-words", rl_transpose_words },
{ "digit-argument", rl_digit_argument },
{ "complete", rl_complete },
{ "possible-completions", rl_possible_completions },
{ "do-lowercase-version", rl_do_lowercase_version },
{ "digit-argument", rl_digit_argument },
{ "universal-argument", rl_universal_argument },
{ "abort", rl_abort },
{ "undo", rl_undo_command },
{ "upcase-word", rl_upcase_word },
{ "downcase-word", rl_downcase_word },
{ "capitalize-word", rl_capitalize_word },
{ "revert-line", rl_revert_line },
{ "beginning-of-history", rl_beginning_of_history },
{ "end-of-history", rl_end_of_history },
{ "self-insert", rl_insert },
{ "start-kbd-macro", rl_start_kbd_macro },
{ "end-kbd-macro", rl_end_kbd_macro },
{ "re-read-init-file", rl_re_read_init_file },
#ifdef VI_MODE
{ "vi-movement-mode", rl_vi_movement_mode },
{ "vi-insertion-mode", rl_vi_insertion_mode },
{ "vi-arg-digit", rl_vi_arg_digit },
{ "vi-prev-word", rl_vi_prev_word },
{ "vi-next-word", rl_vi_next_word },
{ "vi-char-search", rl_vi_char_search },
{ "vi-editing-mode", rl_vi_editing_mode },
{ "vi-eof-maybe", rl_vi_eof_maybe },
{ "vi-append-mode", rl_vi_append_mode },
{ "vi-put", rl_vi_put },
{ "tab-insert", rl_tab_insert },
{ "transpose-chars", rl_transpose_chars },
{ "transpose-words", rl_transpose_words },
{ "undo", rl_undo_command },
{ "universal-argument", rl_universal_argument },
{ "unix-line-discard", rl_unix_line_discard },
{ "unix-word-rubout", rl_unix_word_rubout },
{ "upcase-word", rl_upcase_word },
{ "yank", rl_yank },
{ "yank-nth-arg", rl_yank_nth_arg },
{ "yank-pop", rl_yank_pop },
#if defined (VI_MODE)
{ "vi-append-eol", rl_vi_append_eol },
{ "vi-insert-beg", rl_vi_insert_beg },
{ "vi-delete", rl_vi_delete },
{ "vi-append-mode", rl_vi_append_mode },
{ "vi-arg-digit", rl_vi_arg_digit },
{ "vi-bWord", rl_vi_bWord },
{ "vi-bracktype", rl_vi_bracktype },
{ "vi-bword", rl_vi_bword },
{ "vi-change-case", rl_vi_change_case },
{ "vi-change-char", rl_vi_change_char },
{ "vi-change-to", rl_vi_change_to },
{ "vi-char-search", rl_vi_char_search },
{ "vi-column", rl_vi_column },
{ "vi-comment", rl_vi_comment },
{ "vi-complete", rl_vi_complete },
{ "vi-delete", rl_vi_delete },
{ "vi-delete-to", rl_vi_delete_to },
{ "vi-dosearch", rl_vi_dosearch },
{ "vi-eWord", rl_vi_eWord },
{ "vi-editing-mode", rl_vi_editing_mode },
{ "vi-end-word", rl_vi_end_word },
{ "vi-eof-maybe", rl_vi_eof_maybe },
{ "vi-eword", rl_vi_eword },
{ "vi-fWord", rl_vi_fWord },
{ "vi-first-print", rl_vi_first_print },
{ "vi-fword", rl_vi_fword },
{ "vi-fWord", rl_vi_fWord },
{ "vi-bword", rl_vi_bword },
{ "vi-bWord", rl_vi_bWord },
{ "vi-eword", rl_vi_eword },
{ "vi-eWord", rl_vi_eWord },
{ "vi-end-word", rl_vi_end_word },
{ "vi-change-case", rl_vi_change_case },
{ "vi-insert-beg", rl_vi_insert_beg },
{ "vi-insertion-mode", rl_vi_insertion_mode },
{ "vi-match", rl_vi_match },
{ "vi-bracktype", rl_vi_bracktype },
{ "vi-change-char", rl_vi_change_char },
{ "vi-yank-arg", rl_vi_yank_arg },
{ "vi-search", rl_vi_search },
{ "vi-search-again", rl_vi_search_again },
{ "vi-dosearch", rl_vi_dosearch },
{ "vi-subst", rl_vi_subst },
{ "vi-movement-mode", rl_vi_movement_mode },
{ "vi-next-word", rl_vi_next_word },
{ "vi-overstrike", rl_vi_overstrike },
{ "vi-overstrike-delete", rl_vi_overstrike_delete },
{ "vi-prev-word", rl_vi_prev_word },
{ "vi-put", rl_vi_put },
{ "vi-replace, ", rl_vi_replace },
{ "vi-column", rl_vi_column },
{ "vi-delete-to", rl_vi_delete_to },
{ "vi-change-to", rl_vi_change_to },
{ "vi-search", rl_vi_search },
{ "vi-search-again", rl_vi_search_again },
{ "vi-subst", rl_vi_subst },
{ "vi-yank-arg", rl_vi_yank_arg },
{ "vi-yank-to", rl_vi_yank_to },
{ "vi-complete", rl_vi_complete },
#endif /* VI_MODE */
{(char *)NULL, (Function *)NULL }
@@ -159,6 +170,48 @@ rl_initialize_funmap ()
rl_add_funmap_entry (default_funmap[i].name, default_funmap[i].function);
funmap_initialized = 1;
funmap_program_specific_entry_start = i;
}
/* Stupid comparison routine for qsort () ing strings. */
static int
qsort_string_compare (s1, s2)
register char **s1, **s2;
{
return (strcmp (*s1, *s2));
}
/* Produce a NULL terminated array of known function names. The array
is sorted. The array itself is allocated, but not the strings inside.
You should free () the array when you done, but not the pointrs. */
char **
rl_funmap_names ()
{
char **result = (char **)NULL;
int result_size, result_index;
result_size = result_index = 0;
/* Make sure that the function map has been initialized. */
rl_initialize_funmap ();
for (result_index = 0; funmap[result_index]; result_index++)
{
if (result_index + 2 > result_size)
{
if (!result)
result = (char **)xmalloc ((result_size = 20) * sizeof (char *));
else
result = (char **)
xrealloc (result, (result_size += 20) * sizeof (char *));
}
result[result_index] = funmap[result_index]->name;
result[result_index + 1] = (char *)NULL;
}
qsort (result, result_index, sizeof (char *), qsort_string_compare);
return (result);
}
/* Things that mean `Control'. */
@@ -170,7 +223,7 @@ char *possible_meta_prefixes[] = {
"Meta", "M-", (char *)NULL
};
#ifdef STATIC_MALLOC
#if defined (STATIC_MALLOC)
/* **************************************************************** */
/* */
@@ -196,7 +249,12 @@ xrealloc (pointer, bytes)
char *pointer;
int bytes;
{
char *temp = (char *)realloc (pointer, bytes);
char *temp;
if (!pointer)
temp = (char *)malloc (bytes);
else
temp = (char *)realloc (pointer, bytes);
if (!temp)
memory_error_and_abort ();

View File

@@ -25,24 +25,27 @@
you can call. I think I have done that. */
/* Remove these declarations when we have a complete libgnu.a. */
#define STATIC_MALLOC
#ifndef STATIC_MALLOC
#if !defined (STATIC_MALLOC)
extern char *xmalloc (), *xrealloc ();
#else
static char *xmalloc (), *xrealloc ();
#endif
#include <stdio.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifdef __GNUC__
#define alloca __builtin_alloca
#else
#if defined (sparc) && defined (sun)
#include <alloca.h>
#if defined (__GNUC__)
# define alloca __builtin_alloca
#else
# if defined (sparc) || defined (HAVE_ALLOCA_H)
# include <alloca.h>
# else
extern char *alloca ();
#endif
#endif
# endif /* sparc || HAVE_ALLOCA_H */
#endif /* !__GNU_C__ */
#include "history.h"
@@ -64,7 +67,7 @@ extern char *alloca ();
/* **************************************************************** */
/* */
/* History functions */
/* History Functions */
/* */
/* **************************************************************** */
@@ -73,18 +76,18 @@ static HIST_ENTRY **the_history = (HIST_ENTRY **)NULL;
/* Non-zero means that we have enforced a limit on the amount of
history that we save. */
static int history_stifled = 0;
int history_stifled = 0;
/* If HISTORY_STIFLED is non-zero, then this is the maximum number of
entries to remember. */
static int max_input_history;
int max_input_history;
/* The current location of the interactive history pointer. Just makes
life easier for outside callers. */
static int history_offset = 0;
/* The number of strings currently stored in the input_history list. */
static int history_length = 0;
int history_length = 0;
/* The current number of slots allocated to the input_history. */
static int history_size = 0;
@@ -121,6 +124,21 @@ using_history ()
history_offset = history_length;
}
/* Return the number of bytes that the primary history entries are using.
This just adds up the lengths of the_history->lines. */
int
history_total_bytes ()
{
register int i, result;
result = 0;
for (i = 0; the_history && the_history[i]; i++)
result += strlen (the_history[i]->line);
return (result);
}
/* Place STRING at the end of the history list. The data field
is set to NULL. */
void
@@ -129,43 +147,50 @@ add_history (string)
{
HIST_ENTRY *temp;
if (history_stifled && (history_length == max_input_history)) {
register int i;
if (history_stifled && (history_length == max_input_history))
{
register int i;
/* If the history is stifled, and history_length is zero,
and it equals max_input_history, we don't save items. */
if (!history_length)
return;
/* If the history is stifled, and history_length is zero,
and it equals max_input_history, we don't save items. */
if (!history_length)
return;
/* If there is something in the slot, then remove it. */
if (the_history[0])
{
free (the_history[0]->line);
free (the_history[0]);
}
for (i = 0; i < history_length; i++)
the_history[i] = the_history[i + 1];
history_base++;
/* If there is something in the slot, then remove it. */
if (the_history[0]) {
free (the_history[0]->line);
free (the_history[0]);
}
else
{
if (!history_size)
{
the_history = (HIST_ENTRY **)
xmalloc ((history_size = DEFAULT_HISTORY_GROW_SIZE)
* sizeof (HIST_ENTRY *));
history_length = 1;
for (i = 0; i < history_length; i++)
the_history[i] = the_history[i + 1];
history_base++;
} else {
if (!history_size) {
the_history =
(HIST_ENTRY **)xmalloc ((history_size = DEFAULT_HISTORY_GROW_SIZE)
* sizeof (HIST_ENTRY *));
history_length = 1;
} else {
if (history_length == (history_size - 1)) {
the_history =
(HIST_ENTRY **)xrealloc (the_history,
((history_size += DEFAULT_HISTORY_GROW_SIZE)
* sizeof (HIST_ENTRY *)));
}
history_length++;
}
else
{
if (history_length == (history_size - 1))
{
the_history = (HIST_ENTRY **)
xrealloc (the_history,
((history_size += DEFAULT_HISTORY_GROW_SIZE)
* sizeof (HIST_ENTRY *)));
}
history_length++;
}
}
}
temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
temp->line = savestring (string);
@@ -208,15 +233,22 @@ where_history ()
}
/* Search the history for STRING, starting at history_offset.
If DIRECTION < 0, then the search is through previous entries,
else through subsequent. If the string is found, then
current_history () is the history entry, and the value of this function
is the offset in the line of that history entry that the string was
found in. Otherwise, nothing is changed, and a -1 is returned. */
int
history_search (string, direction)
If DIRECTION < 0, then the search is through previous entries, else
through subsequent. If ANCHORED is non-zero, the string must
appear at the beginning of a history line, otherwise, the string
may appear anywhere in the line. If the string is found, then
current_history () is the history entry, and the value of this
function is the offset in the line of that history entry that the
string was found in. Otherwise, nothing is changed, and a -1 is
returned. */
#define ANCHORED_SEARCH 1
#define NON_ANCHORED_SEARCH 0
static int
history_search_internal (string, direction, anchored)
char *string;
int direction;
int direction, anchored;
{
register int i = history_offset;
register int reverse = (direction < 0);
@@ -248,7 +280,19 @@ history_search (string, direction)
if (string_len > index)
goto next_line;
/* Do the actual search. */
/* Handle anchored searches first. */
if (anchored == ANCHORED_SEARCH)
{
if (strncmp (string, line, string_len) == 0)
{
history_offset = i;
return (0);
}
goto next_line;
}
/* Do substring search. */
if (reverse)
{
index -= string_len;
@@ -265,7 +309,7 @@ history_search (string, direction)
}
else
{
register int limit = (string_len - index) + 1;
register int limit = index - string_len + 1;
index = 0;
while (index < limit)
@@ -286,6 +330,24 @@ history_search (string, direction)
}
}
/* Do a non-anchored search for STRING through the history in DIRECTION. */
int
history_search (string, direction)
char *string;
int direction;
{
return (history_search_internal (string, direction, NON_ANCHORED_SEARCH));
}
/* Do an anchored search for string through the history in DIRECTION. */
int
history_search_prefix (string, direction)
char *string;
int direction;
{
return (history_search_internal (string, direction, ANCHORED_SEARCH));
}
/* Remove history element WHICH from the history. The removed
element is returned to you so you can free the line, data,
and containing structure. */
@@ -307,6 +369,7 @@ remove_history (which)
history_length--;
}
return (return_value);
}
@@ -364,16 +427,11 @@ history_filename (filename)
char *home = (char *)getenv ("HOME");
if (!home) home = ".";
return_val = (char *)xmalloc (2 + strlen (home) + strlen (".history"));
strcpy (return_val, home);
strcat (return_val, "/");
strcat (return_val, ".history");
sprintf (return_val, "%s/.history", home);
}
return (return_val);
}
/* What to use until the line gets too big. */
#define TYPICAL_LINE_SIZE 2048
/* Add the contents of FILENAME to the history list, a line at a time.
If FILENAME is NULL, then read from ~/.history. Returns 0 if
successful, or errno if not. */
@@ -381,43 +439,197 @@ int
read_history (filename)
char *filename;
{
char *input = history_filename (filename);
FILE *file = fopen (input, "r");
char *line = (char *)xmalloc (TYPICAL_LINE_SIZE);
int line_size = TYPICAL_LINE_SIZE;
int done = 0;
return (read_history_range (filename, 0, -1));
}
if (!file)
/* Read a range of lines from FILENAME, adding them to the history list.
Start reading at the FROM'th line and end at the TO'th. If FROM
is zero, start at the beginning. If TO is less than FROM, read
until the end of the file. If FILENAME is NULL, then read from
~/.history. Returns 0 if successful, or errno if not. */
int
read_history_range (filename, from, to)
char *filename;
int from, to;
{
register int line_start, line_end;
char *input, *buffer = (char *)NULL;
int file, current_line;
struct stat finfo;
extern int errno;
input = history_filename (filename);
file = open (input, O_RDONLY, 0666);
if ((file < 0) ||
(stat (input, &finfo) == -1))
goto error_and_exit;
buffer = (char *)xmalloc (finfo.st_size + 1);
if (read (file, buffer, finfo.st_size) != finfo.st_size)
error_and_exit:
{
extern int errno;
free (line);
if (file >= 0)
close (file);
if (buffer)
free (buffer);
return (errno);
}
while (!done)
close (file);
/* Set TO to larger than end of file if negative. */
if (to < 0)
to = finfo.st_size;
/* Start at beginning of file, work to end. */
line_start = line_end = current_line = 0;
/* Skip lines until we are at FROM. */
while (line_start < finfo.st_size && current_line < from)
{
int c;
int i;
i = 0;
while (!(done = ((c = getc (file)) == EOF)))
{
if (c == '\n')
break;
line [i++] = c;
if (i == line_size)
line = (char *)xrealloc (line, line_size += TYPICAL_LINE_SIZE);
}
line[i] = '\0';
if (line[0])
add_history (line);
for (line_end = line_start; line_end < finfo.st_size; line_end++)
if (buffer[line_end] == '\n')
{
current_line++;
line_start = line_end + 1;
if (current_line == from)
break;
}
}
free (line);
fclose (file);
/* If there are lines left to gobble, then gobble them now. */
for (line_end = line_start; line_end < finfo.st_size; line_end++)
if (buffer[line_end] == '\n')
{
buffer[line_end] = '\0';
if (buffer[line_start])
add_history (buffer + line_start);
current_line++;
if (current_line >= to)
break;
line_start = line_end + 1;
}
return (0);
}
/* Truncate the history file FNAME, leaving only LINES trailing lines.
If FNAME is NULL, then use ~/.history. */
history_truncate_file (fname, lines)
char *fname;
register int lines;
{
register int i;
int file;
char *buffer = (char *)NULL, *filename;
struct stat finfo;
filename = history_filename (fname);
if (stat (filename, &finfo) == -1)
goto truncate_exit;
file = open (filename, O_RDONLY, 0666);
if (file == -1)
goto truncate_exit;
buffer = (char *)xmalloc (finfo.st_size + 1);
read (file, buffer, finfo.st_size);
close (file);
/* Count backwards from the end of buffer until we have passed
LINES lines. */
for (i = finfo.st_size; lines && i; i--)
{
if (buffer[i] == '\n')
lines--;
}
/* If there are fewer lines in the file than we want to truncate to,
then we are all done. */
if (!i)
goto truncate_exit;
/* Otherwise, write from the start of this line until the end of the
buffer. */
for (--i; i; i--)
if (buffer[i] == '\n')
{
i++;
break;
}
file = open (filename, O_WRONLY | O_TRUNC | O_CREAT, 0666);
if (file == -1)
goto truncate_exit;
write (file, buffer + i, finfo.st_size - i);
close (file);
truncate_exit:
if (buffer)
free (buffer);
free (filename);
}
#define HISTORY_APPEND 0
#define HISTORY_OVERWRITE 1
/* Workhorse function for writing history. Writes NELEMENT entries
from the history list to FILENAME. OVERWRITE is non-zero if you
wish to replace FILENAME with the entries. */
static int
history_do_write (filename, nelements, overwrite)
char *filename;
int nelements, overwrite;
{
extern int errno;
register int i;
char *output = history_filename (filename);
int file, mode;
char cr = '\n';
if (overwrite)
mode = O_WRONLY | O_CREAT | O_TRUNC;
else
mode = O_WRONLY | O_APPEND;
if ((file = open (output, mode, 0666)) == -1)
return (errno);
if (nelements > history_length)
nelements = history_length;
for (i = history_length - nelements; i < history_length; i++)
{
if (write (file, the_history[i]->line, strlen (the_history[i]->line)) < 0)
break;
if (write (file, &cr, 1) < 0)
break;
}
close (file);
return (0);
}
/* Append NELEMENT entries to FILENAME. The entries appended are from
the end of the list minus NELEMENTs up to the end of the list. */
int
append_history (nelements, filename)
int nelements;
char *filename;
{
return (history_do_write (filename, nelements, HISTORY_APPEND));
}
/* Overwrite FILENAME with the current history. If FILENAME is NULL,
then write the history list to ~/.history. Values returned
are as in read_history ().*/
@@ -425,19 +637,7 @@ int
write_history (filename)
char *filename;
{
extern int errno;
char *output = history_filename (filename);
FILE *file = fopen (output, "w");
register int i;
if (!file) return (errno);
if (!history_length) return (0);
for (i = 0; i < history_length; i++)
fprintf (file, "%s\n", the_history[i]->line);
fclose (file);
return (0);
return (history_do_write (filename, history_length, HISTORY_OVERWRITE));
}
/* Return the history entry at the current position, as determined by
@@ -653,7 +853,8 @@ get_history_event (string, caller_index, delimiting_quote)
search_again:
index = history_search (temp, -1);
index = history_search_internal
(temp, -1, substring_okay ? NON_ANCHORED_SEARCH : ANCHORED_SEARCH);
if (index < 0)
search_lost:
@@ -662,9 +863,7 @@ get_history_event (string, caller_index, delimiting_quote)
return ((char *)NULL);
}
if (index == 0 || substring_okay ||
(strncmp (temp, the_history[history_offset]->line,
strlen (temp)) == 0))
if (index == 0)
{
search_won:
entry = current_history ();
@@ -1174,7 +1373,7 @@ get_history_word_specifier (spec, from, caller_index)
/* Extract the args specified, starting at FIRST, and ending at LAST.
The args are taken from STRING. If either FIRST or LAST is < 0,
then make that arg count from the right (subtract from the number of
tokens, so that FIRST = -1 means the next to last token on the line. */
tokens, so that FIRST = -1 means the next to last token on the line). */
char *
history_arg_extract (first, last, string)
int first, last;
@@ -1205,7 +1404,7 @@ history_arg_extract (first, last, string)
last++;
if (first > len || last > len)
if (first > len || last > len || first < 0 || last < 0)
result = ((char *)NULL);
else
{
@@ -1353,7 +1552,7 @@ history_tokenize (string)
return (result);
}
#ifdef STATIC_MALLOC
#if defined (STATIC_MALLOC)
/* **************************************************************** */
/* */
@@ -1379,10 +1578,16 @@ xrealloc (pointer, bytes)
char *pointer;
int bytes;
{
char *temp = (char *)realloc (pointer, bytes);
char *temp;
if (!pointer)
temp = (char *)xmalloc (bytes);
else
temp = (char *)realloc (pointer, bytes);
if (!temp)
memory_error_and_abort ();
return (temp);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,55 +1,59 @@
/* Readline.h -- the names of functions callable from within readline. */
#ifndef _READLINE_H_
#if !defined (_READLINE_H_)
#define _READLINE_H_
#include <readline/keymaps.h>
#include "keymaps.h"
#ifndef __FUNCTION_DEF
#if !defined (__FUNCTION_DEF)
typedef int Function ();
#define __FUNCTION_DEF
#endif
#endif /* __FUNCTION_DEF */
/* The functions for manipulating the text of the line within readline.
Most of these functions are bound to keys by default. */
extern int
rl_beg_of_line (), rl_backward (), rl_delete (), rl_end_of_line (),
rl_forward (), ding (), rl_backward (), rl_newline (), rl_kill_line (),
rl_clear_screen (), rl_get_next_history (), rl_get_previous_history (),
rl_quoted_insert (), rl_reverse_search_history (), rl_transpose_chars
(), rl_unix_line_discard (), rl_quoted_insert (), rl_unix_word_rubout
(), rl_yank (), rl_rubout (), rl_backward_word (), rl_kill_word (),
rl_forward_word (), rl_tab_insert (), rl_yank_pop (), rl_yank_nth_arg (),
rl_backward_kill_word (), rl_backward_kill_line (), rl_transpose_words
(), rl_complete (), rl_possible_completions (), rl_do_lowercase_version
(), rl_digit_argument (), rl_universal_argument (), rl_abort (),
rl_undo_command (), rl_revert_line (), rl_beginning_of_history (),
rl_end_of_history (), rl_forward_search_history (), rl_insert (),
rl_upcase_word (), rl_downcase_word (), rl_capitalize_word (),
rl_restart_output (), rl_re_read_init_file ();
rl_beg_of_line (), rl_backward (), rl_delete (), rl_end_of_line (),
rl_forward (), ding (), rl_backward (), rl_newline (), rl_kill_line (),
rl_clear_screen (), rl_get_next_history (), rl_get_previous_history (),
rl_quoted_insert (), rl_reverse_search_history (), rl_transpose_chars (),
rl_unix_line_discard (), rl_quoted_insert (), rl_unix_word_rubout (),
rl_yank (), rl_rubout (), rl_backward_word (), rl_kill_word (),
rl_forward_word (), rl_tab_insert (), rl_yank_pop (), rl_yank_nth_arg (),
rl_backward_kill_word (), rl_backward_kill_line (), rl_transpose_words (),
rl_complete (), rl_possible_completions (), rl_do_lowercase_version (),
rl_digit_argument (), rl_universal_argument (), rl_abort (),
rl_undo_command (), rl_revert_line (), rl_beginning_of_history (),
rl_end_of_history (), rl_forward_search_history (), rl_insert (),
rl_upcase_word (), rl_downcase_word (), rl_capitalize_word (),
rl_restart_output (), rl_re_read_init_file (), rl_dump_functions ();
/* These are *both* defined even when VI_MODE is not. */
extern int rl_vi_editing_mode (), rl_emacs_editing_mode ();
#ifdef VI_MODE
#if defined (VI_MODE)
/* Things for vi mode. */
extern int rl_vi_movement_mode (), rl_vi_insertion_mode (), rl_vi_arg_digit (),
rl_vi_prev_word (), rl_vi_next_word (), rl_vi_char_search (),
rl_vi_eof_maybe (), rl_vi_append_mode (), rl_vi_put (),
rl_vi_append_eol (), rl_vi_insert_beg (), rl_vi_delete (), rl_vi_comment (),
rl_vi_first_print (), rl_vi_fword (), rl_vi_fWord (), rl_vi_bword (),
rl_vi_bWord (), rl_vi_eword (), rl_vi_eWord (), rl_vi_end_word (),
rl_vi_change_case (), rl_vi_match (), rl_vi_bracktype (), rl_vi_change_char (),
rl_vi_yank_arg (), rl_vi_search (), rl_vi_search_again (),
rl_vi_dosearch (), rl_vi_subst (), rl_vi_overstrike (),
rl_vi_overstrike_delete (), rl_vi_replace(), rl_vi_column (),
rl_vi_delete_to (), rl_vi_change_to (), rl_vi_yank_to (), rl_vi_complete ();
extern int
rl_vi_movement_mode (), rl_vi_insertion_mode (), rl_vi_arg_digit (),
rl_vi_prev_word (), rl_vi_next_word (), rl_vi_char_search (),
rl_vi_eof_maybe (), rl_vi_append_mode (), rl_vi_put (),
rl_vi_append_eol (), rl_vi_insert_beg (), rl_vi_delete (), rl_vi_comment (),
rl_vi_first_print (), rl_vi_fword (), rl_vi_fWord (), rl_vi_bword (),
rl_vi_bWord (), rl_vi_eword (), rl_vi_eWord (), rl_vi_end_word (),
rl_vi_change_case (), rl_vi_match (), rl_vi_bracktype (),
rl_vi_change_char (), rl_vi_yank_arg (), rl_vi_search (),
rl_vi_search_again (), rl_vi_dosearch (), rl_vi_subst (),
rl_vi_overstrike (), rl_vi_overstrike_delete (), rl_vi_replace(),
rl_vi_column (), rl_vi_delete_to (), rl_vi_change_to (), rl_vi_yank_to (),
rl_vi_complete (), rl_vi_fetch_history ();
#endif /* VI_MODE */
/* Keyboard macro commands. */
extern int
rl_start_kbd_macro (), rl_end_kbd_macro (), rl_call_last_kbd_macro ();
extern int rl_arrow_keys(), rl_refresh_line ();
/* Maintaining the state of undo. We remember individual deletes and inserts
on a chain of things to do. */
@@ -100,8 +104,8 @@ extern char *rl_terminal_name;
extern FILE *rl_instream, *rl_outstream;
/* The basic list of characters that signal a break between words for the
completer routine. The contents of this variable is what breaks words
in the shell, i.e. "n\"\\'`@$>". */
completer routine. The initial contents of this variable is what
breaks words in the shell, i.e. "n\"\\'`@$>". */
extern char *rl_basic_word_break_characters;
/* The list of characters that signal a break between words for
@@ -119,6 +123,14 @@ extern char *rl_special_prefixes;
completer. */
extern Function *rl_completion_entry_function;
/* If rl_ignore_some_completions_function is non-NULL it is the address
of a function to call after all of the possible matches have been
generated, but before the actual completion is done to the input line.
The function is called with one argument; a NULL terminated array
of (char *). If your function removes any of the elements, they
must be free()'ed. */
extern Function *rl_ignore_some_completions_function;
/* Pointer to alternative function to create matches.
Function is called with TEXT, START, and END.
START and END are indices in RL_LINE_BUFFER saying what the boundaries
@@ -128,12 +140,6 @@ extern Function *rl_completion_entry_function;
array of strings returned. */
extern Function *rl_attempted_completion_function;
/* If non-null, this contains the address of a function to call if the
standard meaning for expanding a tilde fails. The function is called
with the text (sans tilde, as in "foo"), and returns a malloc()'ed string
which is the expansion, or a NULL pointer if there is no expansion. */
extern Function *rl_tilde_expander;
/* If non-zero, then this is the address of a function to call just
before readline_internal () prints the first prompt. */
extern Function *rl_startup_hook;
@@ -147,6 +153,29 @@ extern Function *rl_symbolic_link_hook;
with an asterisk. */
extern int rl_show_star;
/* **************************************************************** */
/* */
/* Tilde Variables That Can be Externally Set */
/* */
/* **************************************************************** */
/* If non-null, this contains the address of a function to call if the
standard meaning for expanding a tilde fails. The function is called
with the text (sans tilde, as in "foo"), and returns a malloc()'ed string
which is the expansion, or a NULL pointer if there is no expansion. */
extern Function *tilde_expansion_failure_hook;
/* When non-null, this is a NULL terminated array of strings which
are duplicates for a tilde prefix. Bash uses this to expand
`=~' and `:~'. */
extern char **tilde_additional_prefixes;
/* When non-null, this is a NULL terminated array of strings which match
the end of a username, instead of just "/". Bash sets this to
`/' and `:'. */
extern char **tilde_additional_suffixes;
/* **************************************************************** */
/* */
/* Well Published Functions */
@@ -167,4 +196,3 @@ extern char **completion_matches ();
extern int rl_add_defun ();
#endif /* _READLINE_H_ */

View File

@@ -19,9 +19,9 @@
along with Readline; see the file COPYING. If not, write to the Free
Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef FILE
#ifndef BUFSIZ
#include <stdio.h>
#endif /* FILE */
#endif /* BUFSIZ */
#include "readline.h"
@@ -39,7 +39,7 @@ KEYMAP_ENTRY_ARRAY vi_movement_keymap = {
{ ISFUNC, rl_emacs_editing_mode }, /* Control-e */
{ ISFUNC, (Function *)0x0 }, /* Control-f */
{ ISFUNC, rl_abort }, /* Control-g */
{ ISFUNC, rl_backward }, /* Control-h */
{ ISFUNC, rl_rubout }, /* Control-h */
{ ISFUNC, (Function *)0x0 }, /* Control-i */
{ ISFUNC, rl_newline }, /* Control-j */
{ ISFUNC, rl_kill_line }, /* Control-k */
@@ -99,7 +99,7 @@ KEYMAP_ENTRY_ARRAY vi_movement_keymap = {
{ ISFUNC, (Function *)0x0 }, /* : */
{ ISFUNC, rl_vi_char_search }, /* ; */
{ ISFUNC, (Function *)0x0 }, /* < */
{ ISFUNC, (Function *)0x0 }, /* = */
{ ISFUNC, rl_vi_complete }, /* = */
{ ISFUNC, (Function *)0x0 }, /* > */
{ ISFUNC, rl_vi_search }, /* ? */
{ ISFUNC, (Function *)0x0 }, /* @ */
@@ -111,7 +111,7 @@ KEYMAP_ENTRY_ARRAY vi_movement_keymap = {
{ ISFUNC, rl_vi_delete_to }, /* D */
{ ISFUNC, rl_vi_end_word }, /* E */
{ ISFUNC, rl_vi_char_search }, /* F */
{ ISFUNC, (Function *)0x0 }, /* G */
{ ISFUNC, rl_vi_fetch_history }, /* G */
{ ISFUNC, (Function *)0x0 }, /* H */
{ ISFUNC, rl_vi_insert_beg }, /* I */
{ ISFUNC, (Function *)0x0 }, /* J */
@@ -134,7 +134,7 @@ KEYMAP_ENTRY_ARRAY vi_movement_keymap = {
/* Some more punctuation. */
{ ISFUNC, (Function *)0x0 }, /* [ */
{ ISFUNC, (Function *)0x0 }, /* \ */
{ ISFUNC, rl_vi_complete }, /* \ */
{ ISFUNC, (Function *)0x0 }, /* ] */
{ ISFUNC, rl_vi_first_print }, /* ^ */
{ ISFUNC, rl_vi_yank_arg }, /* _ */

View File

@@ -1,14 +1,83 @@
/* vi_mode.c -- A vi emulation mode for Bash.
Derived from code written by Jeff Sparkes (jsparkes@bnr.ca). */
Derived from code written by Jeff Sparkes (jeff1@????).
*/
/* Copyright (C) 1988, 1991 Free Software Foundation, Inc.
This file is part of the GNU Readline Library (the Library), a set of
routines for providing Emacs style line input to programs that ask
for it.
The 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 1, or (at your option)
any later version.
The 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 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,
675 Mass Ave, Cambridge, MA 02139, USA. */
/* **************************************************************** */
/* */
/* VI Emulation Mode */
/* */
/* **************************************************************** */
#if defined (VI_MODE)
#include <stdio.h>
#if defined (__GNUC__)
# define alloca __builtin_alloca
#else
# if defined (sparc) || defined (HAVE_ALLOCA_H)
# include <alloca.h>
# endif
#endif
/* Some standard library routines. */
#include "readline.h"
#include "history.h"
#ifndef digit
#define digit(c) ((c) >= '0' && (c) <= '9')
#endif
#ifndef isletter
#define isletter(c) (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z'))
#endif
#ifndef digit_value
#define digit_value(c) ((c) - '0')
#endif
#ifndef member
#define member(c, s) ((c) ? index ((s), (c)) : 0)
#endif
#ifndef isident
#define isident(c) ((isletter(c) || digit(c) || c == '_'))
#endif
#ifndef exchange
#define exchange(x, y) {int temp = x; x = y; y = temp;}
#endif
/* Variables imported from readline.c */
extern int rl_point, rl_end, rl_mark, rl_done;
extern FILE *rl_instream;
extern int rl_line_buffer_len, rl_explicit_arg, rl_numeric_arg;
extern Keymap keymap;
extern char *rl_prompt;
extern char *rl_line_buffer;
extern int rl_arg_sign;
extern char *xmalloc (), *xrealloc ();
extern void rl_extend_line_buffer ();
/* Last string searched for from `/' or `?'. */
static char *vi_last_search = (char *)NULL;
@@ -17,6 +86,9 @@ static int vi_histpos;
/* Non-zero means enter insertion mode. */
int vi_doing_insert = 0;
/* String inserted into the line by rl_vi_comment (). */
char *rl_vi_comment_begin = (char *)NULL;
/* *** UNCLEAN *** */
/* Command keys which do movement for xxx_to commands. */
static char *vi_motion = " hl^$0ftFt;,%wbeWBE|";
@@ -26,13 +98,43 @@ static char *vi_motion = " hl^$0ftFt;,%wbeWBE|";
static Keymap vi_replace_map = (Keymap)NULL;
/* The number of characters inserted in the last replace operation. */
static vi_replace_count = 0;
static int vi_replace_count = 0;
/* Yank the nth arg from the previous line into this line at point. */
rl_vi_yank_arg (count)
int count;
{
rl_yank_nth_arg (count, 0);
/* Readline thinks that the first word on a line is the 0th, while vi
thinks the first word on a line is the 1st. Compensate. */
if (rl_explicit_arg)
rl_yank_nth_arg (count - 1, 0);
else
rl_yank_nth_arg ('$', 0);
}
/* With an argument, move back that many history lines, else move to the
beginning of history. */
rl_vi_fetch_history (count, c)
int count, c;
{
extern int rl_explicit_arg;
int current = where_history ();
/* Giving an argument of n means we want the nth command in the history
file. The command number is interpreted the same way that the bash
`history' command does it -- that is, giving an argument count of 450
to this command would get the command listed as number 450 in the
output of `history'. */
if (rl_explicit_arg)
{
int wanted = history_base + current - count;
if (wanted <= 0)
rl_beginning_of_history (0, 0);
else
rl_get_previous_history (wanted);
}
else
rl_beginning_of_history (count, 0);
}
/* Search again for the last thing searched for. */
@@ -78,7 +180,7 @@ rl_vi_search (count, key)
save_pos = rl_point;
/* Reuse the line input buffer to read the search string. */
the_line[0] = 0;
rl_line_buffer[0] = 0;
rl_end = rl_point = 0;
p = (char *)alloca (2 + (rl_prompt ? strlen (rl_prompt) : 0));
@@ -128,8 +230,38 @@ rl_vi_search (count, key)
if (vi_last_search)
free (vi_last_search);
vi_last_search = savestring (the_line);
rl_vi_dosearch (the_line, dir);
vi_last_search = savestring (rl_line_buffer);
rl_vi_dosearch (rl_line_buffer, dir);
}
/* Search for STRING in the history list. DIR is < 0 for searching
backwards. POS is an absolute index into the history list at
which point to begin searching. If the first character of STRING
is `^', the string must match a prefix of a history line, otherwise
a full substring match is performed. */
static int
vi_history_search_pos (string, dir, pos)
char *string;
int dir, pos;
{
int ret, old = where_history ();
history_set_pos (pos);
if (*string == '^')
ret = history_search_prefix (string + 1, dir);
else
ret = history_search (string, dir);
if (ret == -1)
{
history_set_pos (old);
return (-1);
}
ret = where_history ();
history_set_pos (old);
return ret;
}
rl_vi_dosearch (string, dir)
@@ -145,7 +277,7 @@ rl_vi_dosearch (string, dir)
return;
}
if ((save = history_search_pos (string, dir, vi_histpos + dir)) == -1)
if ((save = vi_history_search_pos (string, dir, vi_histpos + dir)) == -1)
{
maybe_unsave_line ();
rl_clear_message ();
@@ -161,9 +293,16 @@ rl_vi_dosearch (string, dir)
h = current_history ();
history_set_pos (old);
strcpy (the_line, h->line);
{
int line_len = strlen (h->line);
if (line_len >= rl_line_buffer_len)
rl_extend_line_buffer (line_len);
strcpy (rl_line_buffer, h->line);
}
rl_undo_list = (UNDO_LIST *)h->data;
rl_end = strlen (the_line);
rl_end = strlen (rl_line_buffer);
rl_point = 0;
rl_clear_message ();
}
@@ -172,19 +311,21 @@ rl_vi_dosearch (string, dir)
rl_vi_complete (ignore, key)
int ignore, key;
{
if (!whitespace (the_line[rl_point]))
if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])))
{
if (!whitespace (the_line[rl_point + 1]))
if (!whitespace (rl_line_buffer[rl_point + 1]))
rl_vi_end_word (1, 'E');
rl_point++;
}
if (key == '*')
rl_complete_internal ('*');
rl_complete_internal ('*'); /* Expansion and replacement. */
else if (key == '=')
rl_complete_internal ('?'); /* List possible completions. */
else if (key == '\\')
rl_complete_internal (TAB); /* Standard Readline completion. */
else
rl_complete (0, key);
rl_vi_insertion_mode ();
}
/* Previous word in vi mode. */
@@ -197,6 +338,12 @@ rl_vi_prev_word (count, key)
return;
}
if (rl_point == 0)
{
ding ();
return;
}
if (uppercase_p (key))
rl_vi_bWord (count);
else
@@ -213,6 +360,12 @@ rl_vi_next_word (count, key)
return;
}
if (rl_point >= (rl_end - 1))
{
ding ();
return;
}
if (uppercase_p (key))
rl_vi_fWord (count);
else
@@ -242,11 +395,11 @@ rl_vi_fWord (count)
while (count-- && rl_point < (rl_end - 1))
{
/* Skip until whitespace. */
while (!whitespace (the_line[rl_point]) && rl_point < rl_end)
while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
rl_point++;
/* Now skip whitespace. */
while (whitespace (the_line[rl_point]) && rl_point < rl_end)
while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
rl_point++;
}
}
@@ -256,42 +409,71 @@ rl_vi_bWord (count)
{
while (count-- && rl_point > 0)
{
while (rl_point-- >= 0 && whitespace (the_line[rl_point]));
while (rl_point >= 0 && !whitespace (the_line[rl_point]))
/* If we are at the start of a word, move back to whitespace so
we will go back to the start of the previous word. */
if (!whitespace (rl_line_buffer[rl_point]) &&
whitespace (rl_line_buffer[rl_point - 1]))
rl_point--;
rl_point++;
while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
rl_point--;
if (rl_point > 0)
{
while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point]));
rl_point++;
}
}
}
rl_vi_eWord (count)
int count;
{
while (count -- && rl_point < (rl_end - 1))
while (count-- && rl_point < (rl_end - 1))
{
while (rl_point++ < rl_end && whitespace (the_line[rl_point]));
while (rl_point++ < rl_end && !whitespace (the_line[rl_point]));
rl_point--;
if (!whitespace (rl_line_buffer[rl_point]))
rl_point++;
/* Move to the next non-whitespace character (to the start of the
next word). */
while (++rl_point < rl_end && whitespace (rl_line_buffer[rl_point]));
if (rl_point && rl_point < rl_end)
{
/* Skip whitespace. */
while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
rl_point++;
/* Skip until whitespace. */
while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point]))
rl_point++;
/* Move back to the last character of the word. */
rl_point--;
}
}
}
rl_vi_fword (count)
int count;
{
while (count -- && rl_point < (rl_end - 1))
while (count-- && rl_point < (rl_end - 1))
{
if (isident (the_line[rl_point]))
/* Move to white space (really non-identifer). */
if (isident (rl_line_buffer[rl_point]))
{
while (isident (the_line[rl_point]) && rl_point < rl_end)
rl_point += 1;
while (isident (rl_line_buffer[rl_point]) && rl_point < rl_end)
rl_point++;
}
else if (!whitespace (the_line[rl_point]))
else /* if (!whitespace (rl_line_buffer[rl_point])) */
{
while (!isident (the_line[rl_point]) &&
!whitespace (the_line[rl_point]) && rl_point < rl_end)
rl_point += 1;
while (!isident (rl_line_buffer[rl_point]) &&
!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
rl_point++;
}
while (whitespace (the_line[rl_point]) && rl_point < rl_end)
/* Move past whitespace. */
while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
rl_point++;
}
}
@@ -299,16 +481,35 @@ rl_vi_fword (count)
rl_vi_bword (count)
int count;
{
while (count -- && rl_point > 0)
while (count-- && rl_point > 0)
{
while (--rl_point > 0 && whitespace (the_line[rl_point]));
int last_is_ident;
/* If we are at the start of a word, move back to whitespace
so we will go back to the start of the previous word. */
if (!whitespace (rl_line_buffer[rl_point]) &&
whitespace (rl_line_buffer[rl_point - 1]))
rl_point--;
/* If this character and the previous character are `opposite', move
back so we don't get messed up by the rl_point++ down there in
the while loop. Without this code, words like `l;' screw up the
function. */
last_is_ident = isident (rl_line_buffer[rl_point - 1]);
if ((isident (rl_line_buffer[rl_point]) && !last_is_ident) ||
(!isident (rl_line_buffer[rl_point]) && last_is_ident))
rl_point--;
while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
rl_point--;
if (rl_point > 0)
{
if (isident (the_line[rl_point]))
while (--rl_point >= 0 && isident (the_line[rl_point]));
if (isident (rl_line_buffer[rl_point]))
while (--rl_point >= 0 && isident (rl_line_buffer[rl_point]));
else
while (--rl_point >= 0 && !isident (the_line[rl_point]) &&
!whitespace (the_line[rl_point]));
while (--rl_point >= 0 && !isident (rl_line_buffer[rl_point]) &&
!whitespace (rl_line_buffer[rl_point]));
rl_point++;
}
}
@@ -317,19 +518,23 @@ rl_vi_bword (count)
rl_vi_eword (count)
int count;
{
while (count -- && rl_point < rl_end - 1)
while (count-- && rl_point < rl_end - 1)
{
while (++rl_point < rl_end && whitespace (the_line[rl_point]));
if (!whitespace (rl_line_buffer[rl_point]))
rl_point++;
while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
rl_point++;
if (rl_point < rl_end)
{
if (isident (the_line[rl_point]))
while (++rl_point < rl_end && isident (the_line[rl_point]));
if (isident (rl_line_buffer[rl_point]))
while (++rl_point < rl_end && isident (rl_line_buffer[rl_point]));
else
while (++rl_point < rl_end && !isident (the_line[rl_point])
&& !whitespace (the_line[rl_point]));
rl_point--;
while (++rl_point < rl_end && !isident (rl_line_buffer[rl_point])
&& !whitespace (rl_line_buffer[rl_point]));
}
rl_point--;
}
}
@@ -398,35 +603,41 @@ rl_vi_arg_digit (count, c)
rl_digit_argument (count, c);
}
/* Doesn't take an arg count in vi */
rl_vi_change_case (ignore1, ignore2)
int ignore1, ignore2;
rl_vi_change_case (count, ignore)
int count, ignore;
{
char c = 0;
if (uppercase_p (the_line[rl_point]))
c = to_lower (the_line[rl_point]);
else if (lowercase_p (the_line[rl_point]))
c = to_upper (the_line[rl_point]);
/* Don't try this on an empty line. */
if (rl_point >= rl_end)
return;
/* Vi is kind of strange here. */
if (c)
while (count-- && rl_point < rl_end)
{
rl_begin_undo_group ();
rl_delete (1, c);
rl_insert (1, c);
rl_end_undo_group ();
rl_vi_check ();
if (uppercase_p (rl_line_buffer[rl_point]))
c = to_lower (rl_line_buffer[rl_point]);
else if (lowercase_p (rl_line_buffer[rl_point]))
c = to_upper (rl_line_buffer[rl_point]);
/* Vi is kind of strange here. */
if (c)
{
rl_begin_undo_group ();
rl_delete (1, c);
rl_insert (1, c);
rl_end_undo_group ();
rl_vi_check ();
}
else
rl_forward (1);
}
else
rl_forward (1);
}
rl_vi_put (count, key)
int count, key;
{
if (!uppercase_p (key))
rl_forward (1);
if (!uppercase_p (key) && (rl_point + 1 <= rl_end))
rl_point++;
rl_yank ();
rl_backward (1);
@@ -451,6 +662,9 @@ rl_vi_domove (key, nextkey)
int key, *nextkey;
{
int c, save;
int old_end, added_blank;
added_blank = 0;
rl_mark = rl_point;
c = rl_read_key ();
@@ -461,10 +675,14 @@ rl_vi_domove (key, nextkey)
if (digit (c))
{
save = rl_numeric_arg;
rl_numeric_arg = digit_value (c);
rl_digit_loop1 ();
rl_numeric_arg *= save;
c = rl_read_key (); /* real command */
*nextkey = c;
}
else if ((key == 'd' && c == 'd') ||
(key == 'y' && c == 'y') ||
(key == 'c' && c == 'c'))
{
rl_mark = rl_end;
@@ -475,15 +693,41 @@ rl_vi_domove (key, nextkey)
return (-1);
}
/* Append a blank character temporarily so that the motion routines
work right at the end of the line. */
old_end = rl_end;
rl_line_buffer[rl_end++] = ' '; /* This looks pretty bogus to me??? */
rl_line_buffer[rl_end] = '\0';
added_blank++;
rl_dispatch (c, keymap);
/* Remove the blank that we added. */
rl_end = old_end;
rl_line_buffer[rl_end] = '\0';
if (rl_point > rl_end)
rl_point = rl_end - 1;
/* No change in position means the command failed. */
if (rl_mark == rl_point)
return (-1);
if ((c == 'w' || c == 'W') && rl_point < rl_end)
/* rl_vi_f[wW]ord () leaves the cursor on the first character of the next
word. If we are not at the end of the line, and we are on a
non-whitespace character, move back one (presumably to whitespace). */
if ((c == 'w' || c == 'W') && (rl_point < rl_end) &&
!whitespace (rl_line_buffer[rl_point]))
rl_point--;
/* If cw or cW, back up to the end of a word, so the behaviour of ce
or cE is the actual result. Brute-force, no subtlety. Do the same
thing for dw or dW. */
if (key == 'c' && (to_upper (c) == 'W'))
{
while (rl_point && whitespace (rl_line_buffer[rl_point]))
rl_point--;
}
if (rl_mark < rl_point)
exchange (rl_point, rl_mark);
@@ -498,7 +742,7 @@ rl_digit_loop1 ()
while (1)
{
rl_message ("(arg: %d) ", arg_sign * rl_numeric_arg, 0);
rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg, 0);
key = c = rl_read_key ();
if (keymap[c].type == ISFUNC &&
@@ -507,19 +751,21 @@ rl_digit_loop1 ()
rl_numeric_arg *= 4;
continue;
}
c = UNMETA (c);
if (numeric (c))
{
if (rl_explicit_arg)
rl_numeric_arg = (rl_numeric_arg * 10) + (c - '0');
rl_numeric_arg = (rl_numeric_arg * 10) + digit_value (c);
else
rl_numeric_arg = (c - '0');
rl_numeric_arg = digit_value (c);
rl_explicit_arg = 1;
}
else
{
rl_clear_message ();
rl_stuff_char (key);
break;
}
}
}
@@ -538,7 +784,7 @@ rl_vi_delete_to (count, key)
return;
}
if ((c != '|') && (c != 'h') && rl_mark < rl_end)
if ((c != 'l') && (c != '|') && (c != 'h') && rl_mark < rl_end)
rl_mark++;
rl_kill_text (rl_point, rl_mark);
@@ -558,7 +804,7 @@ rl_vi_change_to (count, key)
return;
}
if ((c != '|') && (c != 'h') && rl_mark < rl_end)
if ((c != 'l') && (c != '|') && (c != 'h') && rl_mark < rl_end)
rl_mark++;
rl_begin_undo_group ();
@@ -581,6 +827,9 @@ rl_vi_yank_to (count, key)
return;
}
if ((c != 'l') && (c != '|') && (c != 'h') && rl_mark < rl_end)
rl_mark++;
rl_begin_undo_group ();
rl_kill_text (rl_point, rl_mark);
rl_end_undo_group ();
@@ -590,21 +839,36 @@ rl_vi_yank_to (count, key)
rl_vi_delete (count)
{
if (rl_point >= rl_end - 1)
int end;
if (rl_end == 0)
{
rl_delete (count, 0);
if (rl_point > 0)
rl_backward (1);
ding ();
return;
}
else
rl_delete (count, 0);
end = rl_point + count;
if (end >= rl_end)
end = rl_end;
rl_kill_text (rl_point, end);
if (rl_point > 0 && rl_point == rl_end)
rl_backward (1);
}
/* Turn the current line into a comment in shell history. A ksh function */
/* Turn the current line into a comment in shell history.
A K*rn shell style function. */
rl_vi_comment ()
{
rl_beg_of_line ();
rl_insert_text (": "); /* # doesn't work in interactive mode */
if (rl_vi_comment_begin != (char *)NULL)
rl_insert_text (rl_vi_comment_begin);
else
rl_insert_text (": "); /* Default. */
rl_redisplay ();
rl_newline (1, '\010');
}
@@ -618,7 +882,7 @@ rl_back_to_indent (ignore1, ignore2)
int ignore1, ignore2;
{
rl_beg_of_line ();
while (rl_point < rl_end && whitespace (the_line[rl_point]))
while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
rl_point++;
}
@@ -639,70 +903,88 @@ rl_vi_char_search (count, key)
dir = (key == ';' ? orig_dir : -orig_dir);
else
{
target = rl_getc (in_stream);
target = rl_getc (rl_instream);
switch (key)
{
case 't':
orig_dir = dir = FTO;
break;
{
case 't':
orig_dir = dir = FTO;
break;
case 'T':
orig_dir = dir = BTO;
break;
case 'T':
orig_dir = dir = BTO;
break;
case 'f':
orig_dir = dir = FFIND;
break;
case 'f':
orig_dir = dir = FFIND;
break;
case 'F':
orig_dir = dir = BFIND;
break;
}
case 'F':
orig_dir = dir = BFIND;
break;
}
}
pos = rl_point;
if (dir < 0)
while (count--)
{
pos--;
do
if (dir < 0)
{
if (the_line[pos] == target)
if (pos == 0)
{
if (dir == BTO)
rl_point = pos + 1;
else
rl_point = pos;
ding ();
return;
}
pos--;
do
{
if (rl_line_buffer[pos] == target)
{
if (dir == BTO)
rl_point = pos + 1;
else
rl_point = pos;
break;
}
}
while (pos--);
if (pos < 0)
{
ding ();
return;
}
}
while (pos--);
if (pos < 0)
{
ding ();
return;
}
}
else
{ /* dir > 0 */
pos++;
do
{
if (the_line[pos] == target)
else
{ /* dir > 0 */
if (pos >= rl_end)
{
if (dir == FTO)
rl_point = pos - 1;
else
rl_point = pos;
ding ();
return;
}
pos++;
do
{
if (rl_line_buffer[pos] == target)
{
if (dir == FTO)
rl_point = pos - 1;
else
rl_point = pos;
break;
}
}
while (++pos < rl_end);
if (pos >= (rl_end - 1))
{
ding ();
return;
}
}
while (++pos < rl_end);
if (pos >= (rl_end - 1))
ding ();
}
}
@@ -712,9 +994,9 @@ rl_vi_match ()
int count = 1, brack, pos;
pos = rl_point;
if ((brack = rl_vi_bracktype (the_line[rl_point])) == 0)
if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
{
while ((brack = rl_vi_bracktype (the_line[rl_point])) == 0 &&
while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 &&
rl_point < rl_end - 1)
rl_forward (1);
@@ -734,7 +1016,7 @@ rl_vi_match ()
{
if (--pos >= 0)
{
int b = rl_vi_bracktype (the_line[pos]);
int b = rl_vi_bracktype (rl_line_buffer[pos]);
if (b == -brack)
count--;
else if (b == brack)
@@ -753,7 +1035,7 @@ rl_vi_match ()
{
if (++pos < rl_end)
{
int b = rl_vi_bracktype (the_line[pos]);
int b = rl_vi_bracktype (rl_line_buffer[pos]);
if (b == -brack)
count--;
else if (b == brack)
@@ -785,24 +1067,26 @@ rl_vi_bracktype (c)
}
}
rl_vi_change_char ()
rl_vi_change_char (count, key)
int count, key;
{
int c;
c = rl_getc (in_stream);
c = rl_getc (rl_instream);
switch (c)
if (c == '\033' || c == CTRL ('C'))
return;
while (count-- && rl_point < rl_end)
{
case '\033':
case CTRL('C'):
return;
default:
rl_begin_undo_group ();
rl_delete (1, c);
rl_insert (1, c);
if (count == 0)
rl_backward (1);
rl_end_undo_group ();
break;
}
}
@@ -818,7 +1102,7 @@ rl_vi_subst (count, key)
rl_kill_line (1);
}
else
rl_delete (1, key);
rl_delete (count, key);
rl_vi_insertion_mode ();
}
@@ -880,21 +1164,33 @@ rl_vi_overstrike_delete (count)
}
}
rl_vi_replace ()
rl_vi_replace (count, key)
int count, key;
{
int i;
vi_replace_count = 0;
vi_replace_map = rl_make_bare_keymap ();
if (!vi_replace_map)
{
vi_replace_map = rl_make_bare_keymap ();
for (i = ' '; i < 127; i++)
vi_replace_map[i].function = rl_vi_overstrike;
for (i = ' '; i < 127; i++)
vi_replace_map[i].function = rl_vi_overstrike;
vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
vi_replace_map[ESC].function = rl_vi_movement_mode;
vi_replace_map[RETURN].function = rl_newline;
vi_replace_map[NEWLINE].function = rl_newline;
vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
vi_replace_map[ESC].function = rl_vi_movement_mode;
vi_replace_map[RETURN].function = rl_newline;
vi_replace_map[NEWLINE].function = rl_newline;
/* If the normal vi insertion keymap has ^H bound to erase, do the
same here. Probably should remove the assignment to RUBOUT up
there, but I don't think it will make a difference in real life. */
if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC &&
vi_insertion_keymap[CTRL ('H')].function == rl_rubout)
vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete;
}
keymap = vi_replace_map;
}
@@ -907,12 +1203,12 @@ rl_vi_possible_completions()
{
int save_pos = rl_point;
if (!index (" ;", the_line[rl_point]))
if (!index (" ;", rl_line_buffer[rl_point]))
{
while (!index(" ;", the_line[++rl_point]))
while (!index(" ;", rl_line_buffer[++rl_point]))
;
}
else if (the_line[rl_point-1] == ';')
else if (rl_line_buffer[rl_point-1] == ';')
{
ding ();
return (0);
@@ -923,3 +1219,5 @@ rl_vi_possible_completions()
return (0);
}
#endif /* VI_MODE */