Upgrade to version 2.0

This commit is contained in:
Andrey A. Chernov 1994-12-06 03:16:45 +00:00
parent ad12efc944
commit 1d4039c723
43 changed files with 7338 additions and 1025 deletions

View File

@ -1,16 +1,15 @@
# $Id: Makefile,v 1.15 1994/11/01 09:13:02 pst Exp $
# $Id: Makefile,v 1.16 1994/11/01 17:32:46 ache Exp $
CFLAGS+= -I${.CURDIR} -DVOID_SIGHANDLER \
-DHAVE_UNISTD_H -DHAVE_STRING_H -DHAVE_STDLIB_H -DHAVE_VARARGS_H \
-DFreeBSD
CFLAGS+= -I${.CURDIR} -DVOID_SIGHANDLER -DHAVE_CONFIG_H
LIB= readline
SRCS+= readline.c funmap.c keymaps.c vi_mode.c parens.c \
rltty.c complete.c bind.c isearch.c display.c signals.c \
history.c search.c tilde.c xmalloc.c
HEADERS= history.h readline.h keymaps.h chardefs.h tilde.h
NOMAN= noman
MAN3= readline.3
DPADD+= $(LIBTERMCAP)
LDADD+= -ltermcap
beforeinstall:
@ -19,7 +18,7 @@ beforeinstall:
chown ${BINOWN}.${BINGRP} ${DESTDIR}/usr/include/readline; \
chmod 755 ${DESTDIR}/usr/include/readline; \
fi
cd ${.CURDIR}/readline; \
cd ${.CURDIR}; \
for m in ${HEADERS} ; do \
cmp -s $$m ${DESTDIR}/usr/include/readline || \
install -c -o ${BINOWN} -g ${BINGRP} -m 444 \

View File

@ -0,0 +1,6 @@
If you want 8-bit clean version, put
set convert-meta off
set output-meta on
in your ~/.inputrc file
ache@astral.msk.su

View File

@ -5,7 +5,6 @@ directory.
NO_SYS_FILE <sys/file.h> is not present
HAVE_UNISTD_H <unistd.h> exists
HAVE_STDLIB_H <stdlib.h> exists
HAVE_GETPW_DECLS declarations for the getpw functions are in <pwd.h>
HAVE_VARARGS_H <varargs.h> exists and is usable
HAVE_STRING_H <string.h> exists
HAVE_ALLOCA_H <alloca.h> exists and is needed for alloca()
@ -19,14 +18,14 @@ HAVE_SYS_STREAM_H <sys/stream.h> exists
System-specific options:
OSF1 A machine running OSF/1
BSD386 BSDI's BSD/386 version 1.0 or 1.1
NetBSD NetBSD
FreeBSD FreeBSD version 1.1
_386BSD Old FreeBSD or NetBSD or ancient Jolitz 386bsd
AIX AIX 3.x
GWINSZ_IN_SYS_IOCTL need to include <sys/ioctl.h> for TIOCGWINSZ
HAVE_GETPW_DECLS the getpw* functions are declared in <pwd.h> and cannot
be redeclared without compiler errors
HAVE_STRCASECMP the strcasecmp and strncasecmp functions are available
USG Running a variant of System V
USGr3 Running System V.3
XENIX_22 Xenix 2.2
Linux Linux
CRAY running a recent version of Cray UNICOS
SunOS4 Running SunOS 4.x

View File

@ -19,6 +19,7 @@
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. */
#define READLINE_LIBRARY
#include <stdio.h>
#include <sys/types.h>
@ -50,8 +51,8 @@ extern int errno;
#include "rldefs.h"
/* Some standard library routines. */
#include <readline/readline.h>
#include <readline/history.h>
#include "readline.h"
#include "history.h"
#if !defined (strchr) && !defined (__STDC__)
extern char *strchr (), *strrchr ();
@ -61,10 +62,12 @@ extern int _rl_horizontal_scroll_mode;
extern int _rl_mark_modified_lines;
extern int _rl_bell_preference;
extern int _rl_meta_flag;
extern int rl_blink_matching_paren;
extern int _rl_convert_meta_chars_to_ascii;
extern int _rl_output_meta_chars;
extern int _rl_complete_show_all;
#if defined (PAREN_MATCHING)
extern int rl_blink_matching_paren;
#endif /* PAREN_MATCHING */
#if defined (VISIBLE_STATS)
extern int rl_visible_stats;
#endif /* VISIBLE_STATS */
@ -87,12 +90,12 @@ extern char **rl_funmap_names ();
void rl_set_keymap_from_edit_mode ();
static int glean_key_from_name ();
#if !defined (BSD386) && !defined (NetBSD) && \
!defined (FreeBSD) && !defined (_386BSD)
static int stricmp (), strnicmp ();
#else
#if defined (HAVE_STRCASECMP)
#define stricmp strcasecmp
#define strnicmp strncasecmp
#else
static int stricmp (), strnicmp ();
#endif
#if defined (STATIC_MALLOC)
@ -468,6 +471,9 @@ rl_read_init_file (filename)
filename = DEFAULT_INPUTRC;
}
if (!*filename)
filename = DEFAULT_INPUTRC;
openname = tilde_expand (filename);
if ((stat (openname, &finfo) < 0) ||
@ -509,7 +515,10 @@ rl_read_init_file (filename)
/* Skip leading whitespace. */
while (*line && whitespace (*line))
line++;
{
line++;
i--;
}
/* If the line is not a comment, then parse it. */
if (*line && *line != '#')
@ -950,7 +959,9 @@ static struct {
{ "horizontal-scroll-mode", &_rl_horizontal_scroll_mode },
{ "mark-modified-lines", &_rl_mark_modified_lines },
{ "meta-flag", &_rl_meta_flag },
#if defined (PAREN_MATCHING)
{ "blink-matching-paren", &rl_blink_matching_paren },
#endif
{ "convert-meta", &_rl_convert_meta_chars_to_ascii },
{ "show-all-if-ambiguous", &_rl_complete_show_all },
{ "output-meta", &_rl_output_meta_chars },
@ -1163,8 +1174,8 @@ rl_set_keymap_from_edit_mode ()
/* Print the names of functions known to Readline. */
void
rl_list_funmap_names (ignore)
int ignore;
rl_list_funmap_names (count, ignore)
int count, ignore;
{
register int i;
char **funmap_names;
@ -1208,7 +1219,7 @@ rl_invoking_keyseqs_in_map (function, map)
{
char *keyname = (char *)xmalloc (5);
if (CTRL_P (key))
if (CTRL_CHAR (key))
sprintf (keyname, "\\C-%c", to_lower (UNCTRL (key)));
else if (key == RUBOUT)
sprintf (keyname, "\\C-?");
@ -1253,7 +1264,7 @@ rl_invoking_keyseqs_in_map (function, map)
if (key == ESC)
sprintf (keyname, "\\e");
else if (CTRL_P (key))
else if (CTRL_CHAR (key))
sprintf (keyname, "\\C-%c", to_lower (UNCTRL (key)));
else if (key == RUBOUT)
sprintf (keyname, "\\C-?");
@ -1418,8 +1429,7 @@ substring_member_of_array (string, array)
return (0);
}
#if !defined (BSD386) && !defined (NetBSD) && \
!defined (FreeBSD) && !defined (_386BSD)
#if !defined (HAVE_STRCASECMP)
/* Whoops, Unix doesn't have strnicmp. */
/* Compare at most COUNT characters from string1 to string2. Case
@ -1437,7 +1447,8 @@ strnicmp (string1, string2, count)
ch2 = *string2++;
if (to_upper(ch1) == to_upper(ch2))
count--;
else break;
else
break;
}
return (count);
}
@ -1456,9 +1467,9 @@ stricmp (string1, string2)
if (to_upper(ch1) != to_upper(ch2))
return (1);
}
return (*string1 | *string2);
return (*string1 - *string2);
}
#endif
#endif /* !HAVE_STRCASECMP */
/* Determine if s2 occurs in s1. If so, return a pointer to the
match in s1. The compare is case insensitive. */
@ -1470,7 +1481,7 @@ strindex (s1, s2)
register int len = strlen (s1);
for (i = 0; (len - i) >= l; i++)
if (strnicmp (&s1[i], s2, l) == 0)
if (strnicmp (s1 + i, s2, l) == 0)
return (s1 + i);
return ((char *)NULL);
}

View File

@ -0,0 +1,122 @@
/* chardefs.h -- Character definitions for readline. */
/* Copyright (C) 1994 Free Software Foundation, Inc.
This file is part of the GNU Readline Library, a library for
reading lines of text with interactive input and history editing.
The GNU Readline Library is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 1, or
(at your option) any later version.
The GNU Readline Library is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
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. */
#ifndef _CHARDEFS_H
#define _CHARDEFS_H
#include <ctype.h>
#if defined (HAVE_STRING_H)
# include <string.h>
#else
# include <strings.h>
#endif /* HAVE_STRING_H */
#ifndef whitespace
#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
#endif
#ifdef CTRL
#undef CTRL
#endif
/* Some character stuff. */
#define control_character_threshold 0x020 /* Smaller than this is control. */
#define control_character_mask 0x1f /* 0x20 - 1 */
#define meta_character_threshold 0x07f /* Larger than this is Meta. */
#define control_character_bit 0x40 /* 0x000000, must be off. */
#define meta_character_bit 0x080 /* x0000000, must be on. */
#define largest_char 255 /* Largest character value. */
#define CTRL_CHAR(c) ((c) < control_character_threshold)
#define META_CHAR(c) ((c) > meta_character_threshold && (c) <= largest_char)
#define CTRL(c) ((c) & control_character_mask)
#define META(c) ((c) | meta_character_bit)
#define UNMETA(c) ((c) & (~meta_character_bit))
#define UNCTRL(c) to_upper(((c)|control_character_bit))
/* Old versions
#define lowercase_p(c) (((c) > ('a' - 1) && (c) < ('z' + 1)))
#define uppercase_p(c) (((c) > ('A' - 1) && (c) < ('Z' + 1)))
#define digit_p(c) ((c) >= '0' && (c) <= '9')
*/
#define lowercase_p(c) (islower(c))
#define uppercase_p(c) (isupper(c))
#define digit_p(x) (isdigit (x))
#define pure_alphabetic(c) (lowercase_p(c) || uppercase_p(c))
/* Old versions
# define to_upper(c) (lowercase_p(c) ? ((c) - 32) : (c))
# define to_lower(c) (uppercase_p(c) ? ((c) + 32) : (c))
*/
#ifndef to_upper
# define to_upper(c) (islower(c) ? toupper(c) : (c))
# define to_lower(c) (isupper(c) ? tolower(c) : (c))
#endif
#ifndef digit_value
#define digit_value(x) ((x) - '0')
#endif
#ifndef NEWLINE
#define NEWLINE '\n'
#endif
#ifndef RETURN
#define RETURN CTRL('M')
#endif
#ifndef RUBOUT
#define RUBOUT 0x7f
#endif
#ifndef TAB
#define TAB '\t'
#endif
#ifdef ABORT_CHAR
#undef ABORT_CHAR
#endif
#define ABORT_CHAR CTRL('G')
#ifdef PAGE
#undef PAGE
#endif
#define PAGE CTRL('L')
#ifdef SPACE
#undef SPACE
#endif
#define SPACE ' ' /* XXX - was 0x20 */
#ifdef ESC
#undef ESC
#endif
#define ESC CTRL('[')
#endif /* _CHARDEFS_H */

View File

@ -19,6 +19,7 @@
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. */
#define READLINE_LIBRARY
#include <stdio.h>
#include <sys/types.h>
@ -63,7 +64,7 @@ extern struct passwd *getpwent ();
#include "rldefs.h"
/* Some standard library routines. */
#include <readline/readline.h>
#include "readline.h"
/* Possible values for do_replace in rl_complete_internal. */
#define NO_MATCH 0
@ -225,6 +226,13 @@ int rl_ignore_completion_duplicates = 1;
within a completion entry finder function. */
int rl_filename_completion_desired = 0;
/* Non-zero means that the results of the matches are to be quoted using
double quotes (or an application-specific quoting mechanism) if the
filename contains any characters in rl_word_break_chars. This is
ALWAYS non-zero on entry, and can only be changed within a completion
entry finder function. */
int rl_filename_quoting_desired = 1;
/* This function, if defined, is called by the completer when real
filename completion is done, after all the matching names have been
generated. It is passed a (char**) known as matches in the code below.
@ -367,9 +375,7 @@ rl_complete_internal (what_to_do)
char *text, *saved_line_buffer;
char *replacement;
char quote_char = '\0';
#if defined (SHELL)
int found_quote = 0;
#endif
if (rl_line_buffer)
saved_line_buffer = savestring (rl_line_buffer);
@ -381,8 +387,9 @@ rl_complete_internal (what_to_do)
else
our_func = (Function *)filename_completion_function;
/* Only the completion entry function can change this. */
/* Only the completion entry function can change these. */
rl_filename_completion_desired = 0;
rl_filename_quoting_desired = 1;
/* We now look backwards for the start of a filename/variable word. */
end = rl_point;
@ -406,6 +413,7 @@ rl_complete_internal (what_to_do)
if (rl_line_buffer[scan] == '\\')
{
pass_next = 1;
found_quote |= 4;
continue;
}
@ -424,12 +432,11 @@ rl_complete_internal (what_to_do)
/* Found start of a quoted substring. */
quote_char = rl_line_buffer[scan];
rl_point = scan + 1;
#if defined (SHELL)
/* Shell-like quoting conventions. */
if (quote_char == '\'')
found_quote |= 1;
else if (quote_char == '"')
found_quote |= 2;
#endif
}
}
}
@ -437,34 +444,37 @@ rl_complete_internal (what_to_do)
if (rl_point == end)
{
int quoted = 0;
/* We didn't find an unclosed quoted substring up which to do
/* We didn't find an unclosed quoted substring upon which to do
completion, so use the word break characters to find the
substring on which to complete. */
while (--rl_point)
{
scan = rl_line_buffer[rl_point];
if (strchr (rl_completer_word_break_characters, scan) == 0)
continue;
#if defined (SHELL)
/* Don't let word break characters in quoted substrings break
words for the completer. */
if (found_quote)
{
if (strchr (rl_completer_quote_characters, scan))
{
quoted = !quoted;
continue;
}
if (quoted)
continue;
}
if (found_quote && char_is_quoted (rl_line_buffer, rl_point))
continue;
#endif /* SHELL */
if (strchr (rl_completer_word_break_characters, scan))
break;
/* Convoluted code, but it avoids an n^2 algorithm with calls
to char_is_quoted. */
break;
}
}
/* If we are at a word break, then advance past it. */
/* If we are at an unquoted word break, then advance past it. */
scan = rl_line_buffer[rl_point];
#if defined (SHELL)
if ((found_quote == 0 || char_is_quoted (rl_line_buffer, rl_point) == 0) &&
strchr (rl_completer_word_break_characters, scan))
#else
if (strchr (rl_completer_word_break_characters, scan))
#endif
{
/* If the character that caused the word break was a quoting
character, then remember it as the delimiter. */
@ -521,6 +531,7 @@ rl_complete_internal (what_to_do)
else
{
register int i;
int should_quote;
/* It seems to me that in all the cases we handle we would like
to ignore duplicate possiblilities. Scan for the text to
@ -603,8 +614,18 @@ rl_complete_internal (what_to_do)
matches don't require a quoted substring. */
replacement = matches[0];
if (matches[0] && rl_completer_quote_characters && !quote_char &&
rl_filename_completion_desired)
should_quote = matches[0] && rl_completer_quote_characters &&
rl_filename_completion_desired &&
rl_filename_quoting_desired;
if (should_quote)
#if defined (SHELL)
should_quote = should_quote && (!quote_char || quote_char == '"');
#else
should_quote = should_quote && !quote_char;
#endif
if (should_quote)
{
int do_replace;
@ -614,17 +635,17 @@ rl_complete_internal (what_to_do)
This also checks whether the common prefix of several
matches needs to be quoted. If the common prefix should
not be checked, add !matches[1] to the if clause. */
if (rl_strpbrk (matches[0], rl_completer_word_break_characters)
should_quote = rl_strpbrk (matches[0], rl_completer_word_break_characters) != 0;
#if defined (SHELL)
|| rl_strpbrk (matches[0], "$`")
should_quote = should_quote || rl_strpbrk (matches[0], "#$`") != 0;
#endif
)
if (should_quote)
do_replace = matches[1] ? MULT_MATCH : SINGLE_MATCH;
if (do_replace != NO_MATCH)
{
#if defined (SHELL)
/* XXX - experimental */
/* Quote the replacement, since we found an
embedded word break character in a potential
match. */
@ -648,7 +669,18 @@ rl_complete_internal (what_to_do)
rlen = strlen (rtext);
replacement = xmalloc (rlen + 1);
strcpy (replacement, rtext);
/* If we're completing on a quoted string where the user
has already supplied the opening quote, we don't want
the quote in the replacement text, and we reset
QUOTE_CHAR to 0 to avoid an extra closing quote. */
if (quote_char == '"')
{
strcpy (replacement, rtext + 1);
rlen--;
quote_char = 0;
}
else
strcpy (replacement, rtext);
if (do_replace == MULT_MATCH)
replacement[rlen - 1] = '\0';
free (rtext);
@ -927,7 +959,13 @@ static int
compare_strings (s1, s2)
char **s1, **s2;
{
return (strcmp (*s1, *s2));
int result;
result = **s1 - **s2;
if (result == 0)
result = strcmp (*s1, *s2);
return result;
}
/* A completion function for usernames.
@ -976,7 +1014,7 @@ username_completion_function (text, state)
}
else
{
char *value = (char *)xmalloc (2 + strlen (entry->pw_name));
char *value = xmalloc (2 + strlen (entry->pw_name));
*value = *text;
@ -1083,7 +1121,7 @@ completion_matches (text, entry_function)
if (low > si) low = si;
i++;
}
match_list[0] = (char *)xmalloc (low + 1);
match_list[0] = xmalloc (low + 1);
strncpy (match_list[0], match_list[1], low);
match_list[0][low] = '\0';
}
@ -1111,7 +1149,7 @@ filename_completion_function (text, state)
static char *users_dirname = (char *)NULL;
static int filename_len;
struct direct *entry = (struct direct *)NULL;
struct dirent *entry = (struct dirent *)NULL;
/* If we don't have any state, then do some initialization. */
if (!state)
@ -1185,8 +1223,8 @@ filename_completion_function (text, state)
{
/* Otherwise, if these match up to the length of filename, then
it is a match. */
if (((int)D_NAMLEN (entry)) >= filename_len &&
(entry->d_name[0] == filename[0]) &&
if ((entry->d_name[0] == filename[0]) &&
(((int)D_NAMLEN (entry)) >= filename_len) &&
(strncmp (filename, entry->d_name, filename_len) == 0))
break;
}
@ -1199,7 +1237,6 @@ filename_completion_function (text, state)
closedir (directory);
directory = (DIR *)NULL;
}
if (dirname)
{
free (dirname);
@ -1228,7 +1265,7 @@ filename_completion_function (text, state)
if (rl_complete_with_tilde_expansion && *users_dirname == '~')
{
int dirlen = strlen (dirname);
temp = (char *)xmalloc (2 + dirlen + D_NAMLEN (entry));
temp = xmalloc (2 + dirlen + D_NAMLEN (entry));
strcpy (temp, dirname);
/* Canonicalization cuts off any final slash present. We need
to add it back. */
@ -1240,8 +1277,7 @@ filename_completion_function (text, state)
}
else
{
temp = (char *)
xmalloc (1 + strlen (users_dirname) + D_NAMLEN (entry));
temp = xmalloc (1 + strlen (users_dirname) + D_NAMLEN (entry));
strcpy (temp, users_dirname);
}

View File

@ -0,0 +1,71 @@
/* config.h. Generated automatically by configure. */
/* config.h.in. Generated automatically from configure.in by autoheader. */
#ifndef _RL_CONFIG_H
#define _RL_CONFIG_H
/* Define if using alloca.c. */
/* #undef C_ALLOCA */
/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
This function is required for alloca.c support on those systems. */
/* #undef CRAY_STACKSEG_END */
/* Define if you have alloca.h and it should be used (not Ultrix). */
/* #undef HAVE_ALLOCA_H */
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown
*/
/* #undef STACK_DIRECTION */
/* Define if you do not have strings.h, index, bzero, etc.. */
/* #undef USG */
/* Define if your system defines TIOCGWINSZ in sys/ioctl.h. */
#define GWINSZ_IN_SYS_IOCTL 1
/* #undef HAVE_GETPW_DECLS */
/* #undef NO_SYS_FILE */
/* Define if you have strcasecmp. */
#define HAVE_STRCASECMP 1
/* Define if you have the <alloca.h> header file. */
/* #undef HAVE_ALLOCA_H */
/* Define if you have the <dirent.h> header file. */
#define HAVE_DIRENT_H 1
/* Define if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define if you have the <sys/pte.h> header file. */
/* #undef HAVE_SYS_PTE_H */
/* Define if you have the <sys/ptem.h> header file. */
/* #undef HAVE_SYS_PTEM_H */
/* Define if you have the <sys/stream.h> header file. */
/* #undef HAVE_SYS_STREAM_H */
/* Define if you have the <termcap.h> header file. */
#define HAVE_TERMCAP_H 1
/* Define if you have the <termio.h> header file. */
/* #undef HAVE_TERMIO_H */
/* Define if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define if you have the <varargs.h> header file. */
#define HAVE_VARARGS_H 1
#endif

View File

@ -19,6 +19,7 @@
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. */
#define READLINE_LIBRARY
#include <stdio.h>
#include <sys/types.h>
@ -39,8 +40,8 @@
#include "rldefs.h"
/* Some standard library routines. */
#include <readline/readline.h>
#include <readline/history.h>
#include "readline.h"
#include "history.h"
#if !defined (strchr) && !defined (__STDC__)
extern char *strchr (), *strrchr ();
@ -54,7 +55,7 @@ extern char *term_clreol, *term_im, *term_ic, *term_ei, *term_DC;
/* Termcap variables. */
extern char *term_up, *term_dc, *term_cr, *term_IC;
extern int screenheight, screenwidth, screenchars;
extern int terminal_can_insert;
extern int terminal_can_insert, term_xn;
extern void _rl_output_some_chars ();
extern int _rl_output_character_function ();
@ -69,11 +70,15 @@ extern int _rl_prefer_visible_bell;
void _rl_move_cursor_relative (), _rl_output_some_chars ();
void _rl_move_vert ();
static void update_line (), clear_to_eol ();
static void update_line (), clear_to_eol (), space_to_eol ();
static void delete_chars (), insert_some_chars ();
extern char *xmalloc (), *xrealloc ();
/* Heuristic used to decide whether it is faster to move from CUR to NEW
by backing up or outputting a carriage return and moving forward. */
#define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new)))
/* **************************************************************** */
/* */
/* Display stuff */
@ -87,12 +92,8 @@ extern char *xmalloc (), *xrealloc ();
the problems of input lines longer than the screen width.
update_line and the code that calls it makes a multiple line,
automatically wrapping line update. Carefull attention needs
to be paid to the vertical position variables.
handling of terminals with autowrap on (incl. DEC braindamage)
could be improved a bit. Right now I just cheat and decrement
screenwidth by one. */
automatically wrapping line update. Careful attention needs
to be paid to the vertical position variables. */
/* Keep two buffers; one which reflects the current contents of the
screen, and the other to draw what we think the new contents should
@ -281,8 +282,8 @@ rl_redisplay ()
if (!invisible_line)
{
visible_line = (char *)xmalloc (line_size);
invisible_line = (char *)xmalloc (line_size);
visible_line = xmalloc (line_size);
invisible_line = xmalloc (line_size);
line = invisible_line;
for (in = 0; in < line_size; in++)
{
@ -316,13 +317,13 @@ rl_redisplay ()
number of non-visible characters in the prompt string. */
if (rl_display_prompt == rl_prompt)
{
int local_len = strlen (local_prompt);
int local_len = local_prompt ? strlen (local_prompt) : 0;
if (local_prompt_prefix && forced_display)
_rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix));
if (local_prompt)
strncpy (line + out, local_prompt, local_len);
out += local_len;
if (local_len > 0)
strncpy (line + out, local_prompt, local_len);
out += local_len;
line[out] = '\0';
wrap_offset = local_len - visible_length;
}
@ -353,8 +354,8 @@ rl_redisplay ()
if (out + 8 >= line_size) /* XXX - 8 for \t */
{
line_size *= 2;
visible_line = (char *)xrealloc (visible_line, line_size);
invisible_line = (char *)xrealloc (invisible_line, line_size);
visible_line = xrealloc (visible_line, line_size);
invisible_line = xrealloc (invisible_line, line_size);
line = invisible_line;
}
@ -410,7 +411,7 @@ rl_redisplay ()
if (!_rl_horizontal_scroll_mode && term_up && *term_up)
{
int total_screen_chars = screenchars;
int nleft, cursor_linenum, pos;
int nleft, cursor_linenum, pos, changed_screen_line;
if (!rl_display_fixed || forced_display)
{
@ -425,17 +426,15 @@ rl_redisplay ()
/* Number of screen lines to display. The first line wraps at
(screenwidth + wrap_offset) chars, the rest of the lines have
screenwidth chars. */
nleft = out - screenwidth - wrap_offset;
if (nleft > 0)
inv_botlin = 1 + nleft / screenwidth;
else
inv_botlin = 0;
nleft = out - wrap_offset + term_xn - 1;
inv_botlin = (nleft > 0) ? nleft / screenwidth : 0;
/* The first line is at character position 0 in the buffer. The
second and subsequent lines start at N * screenwidth, offset by
OFFSET. OFFSET is wrap_offset for the invisible line and
visible_wrap_offset for the line currently displayed. */
#define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
#define L_OFFSET(n, offset) ((n) > 0 ? ((n) * screenwidth) + (offset) : 0)
#define VIS_CHARS(line) &visible_line[L_OFFSET((line), visible_wrap_offset)]
#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
@ -444,7 +443,10 @@ rl_redisplay ()
/* For each line in the buffer, do the updating display. */
for (linenum = 0; linenum <= inv_botlin; linenum++)
{
update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum);
update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum,
screenwidth + W_OFFSET(linenum, visible_wrap_offset),
screenwidth + W_OFFSET(linenum, wrap_offset),
inv_botlin);
/* If this is the line with the prompt, we might need to
compensate for invisible characters in the new line. Do
@ -462,7 +464,7 @@ rl_redisplay ()
/* Since the new first line is now visible, save its length. */
if (linenum == 0)
visible_first_line_len = _rl_last_c_pos;
visible_first_line_len = (inv_botlin > 0) ? screenwidth : out - wrap_offset;
}
/* We may have deleted some lines. If so, clear the left over
@ -483,50 +485,141 @@ rl_redisplay ()
/* Move the cursor where it should be. */
/* Which line? */
nleft = c_pos - screenwidth - wrap_offset;
if (nleft > 0)
cursor_linenum = 1 + nleft / screenwidth;
else
cursor_linenum = 0;
_rl_move_vert (cursor_linenum);
nleft = c_pos - wrap_offset - term_xn + 1;
cursor_linenum = (nleft > 0) ? nleft / screenwidth : 0;
/* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
different screen line during this redisplay. */
changed_screen_line = _rl_last_v_pos != cursor_linenum;
if (changed_screen_line)
{
_rl_move_vert (cursor_linenum);
/* If we moved up to the line with the prompt using term_up,
the physical cursor position on the screen stays the same,
but the buffer position needs to be adjusted to account
for invisible characters. */
if (cursor_linenum == 0 && wrap_offset)
_rl_last_c_pos += wrap_offset;
}
/* We have to reprint the prompt if it contains invisible
characters, since it's not generally OK to just reprint
the characters from the current cursor position. */
nleft = visible_length + wrap_offset;
if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
_rl_last_c_pos <= nleft && local_prompt)
{
if (term_cr)
tputs (term_cr, 1, _rl_output_character_function);
_rl_output_some_chars (local_prompt, nleft);
_rl_last_c_pos = nleft;
}
/* Where on that line? And where does that line start
in the buffer? */
pos = L_OFFSET(cursor_linenum, wrap_offset);
/* nleft == number of characters in the line buffer between the
start of the line and the cursor position. */
nleft = c_pos - pos;
_rl_move_cursor_relative (nleft, &invisible_line[pos]);
/* Since backspace() doesn't know about invisible characters in the
prompt, and there's no good way to tell it, we compensate for
those characters here and call backspace() directly. */
if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
{
backspace (_rl_last_c_pos - nleft);
_rl_last_c_pos = nleft;
}
if (nleft != _rl_last_c_pos)
_rl_move_cursor_relative (nleft, &invisible_line[pos]);
}
}
else /* Do horizontal scrolling. */
{
int lmargin;
#define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0)
int lmargin, ndisp, nleft, phys_c_pos, t;
/* Always at top line. */
_rl_last_v_pos = 0;
/* If the display position of the cursor would be off the edge
of the screen, start the display of this line at an offset that
leaves the cursor on the screen. */
if (c_pos - last_lmargin > screenwidth - 2)
lmargin = (c_pos / (screenwidth / 3) - 2) * (screenwidth / 3);
else if (c_pos - last_lmargin < 1)
lmargin = ((c_pos - 1) / (screenwidth / 3)) * (screenwidth / 3);
/* Compute where in the buffer the displayed line should start. This
will be LMARGIN. */
/* The number of characters that will be displayed before the cursor. */
ndisp = c_pos - wrap_offset;
nleft = visible_length + wrap_offset;
/* Where the new cursor position will be on the screen. This can be
longer than SCREENWIDTH; if it is, lmargin will be adjusted. */
phys_c_pos = c_pos - (last_lmargin ? last_lmargin : wrap_offset);
t = screenwidth / 3;
/* If the number of characters had already exceeded the screenwidth,
last_lmargin will be > 0. */
/* If the number of characters to be displayed is more than the screen
width, compute the starting offset so that the cursor is about
two-thirds of the way across the screen. */
if (phys_c_pos > screenwidth - 2)
{
lmargin = c_pos - (2 * t);
if (lmargin < 0)
lmargin = 0;
/* If the left margin would be in the middle of a prompt with
invisible characters, don't display the prompt at all. */
if (wrap_offset && lmargin > 0 && lmargin < nleft)
lmargin = nleft;
}
else if (ndisp < screenwidth - 2) /* XXX - was -1 */
lmargin = 0;
else if (phys_c_pos < 1)
{
/* If we are moving back towards the beginning of the line and
the last margin is no longer correct, compute a new one. */
lmargin = ((c_pos - 1) / t) * t; /* XXX */
if (wrap_offset && lmargin > 0 && lmargin < nleft)
lmargin = nleft;
}
else
lmargin = last_lmargin;
lmargin = last_lmargin;
/* If the first character on the screen isn't the first character
in the display line, indicate this with a special character. */
if (lmargin > 0)
line[lmargin] = '<';
if (lmargin + screenwidth < out)
line[lmargin + screenwidth - 1] = '>';
/* If SCREENWIDTH characters starting at LMARGIN do not encompass
the whole line, indicate that with a special characters at the
right edge of the screen. If LMARGIN is 0, we need to take the
wrap offset into account. */
t = lmargin + M_OFFSET (lmargin, wrap_offset) + screenwidth;
if (t < out)
line[t - 1] = '>';
if (!rl_display_fixed || forced_display || lmargin != last_lmargin)
{
forced_display = 0;
update_line (&visible_line[last_lmargin],
&invisible_line[lmargin], 0);
&invisible_line[lmargin],
0,
screenwidth + visible_wrap_offset,
screenwidth + (lmargin ? 0 : wrap_offset),
0);
/* If the visible new line is shorter than the old, but the number
of invisible characters is greater, and we are at the end of
the new line, we need to clear to eol. */
t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
(_rl_last_c_pos == out) &&
t < visible_first_line_len)
{
nleft = screenwidth - t;
clear_to_eol (nleft);
}
visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
if (visible_first_line_len > screenwidth)
visible_first_line_len = screenwidth;
_rl_move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]);
last_lmargin = lmargin;
@ -540,7 +633,13 @@ rl_redisplay ()
visible_line = invisible_line;
invisible_line = temp;
rl_display_fixed = 0;
visible_wrap_offset = wrap_offset;
/* If we are displaying on a single line, and last_lmargin is > 0, we
are not displaying any invisible characters, so set visible_wrap_offset
to 0. */
if (_rl_horizontal_scroll_mode && last_lmargin)
visible_wrap_offset = 0;
else
visible_wrap_offset = wrap_offset;
}
}
@ -561,22 +660,43 @@ new: eddie> Oh, my little buggy says to me, as lurgid as
Could be made even smarter, but this works well enough */
static void
update_line (old, new, current_line)
update_line (old, new, current_line, omax, nmax, inv_botlin)
register char *old, *new;
int current_line;
int current_line, omax, nmax;
{
register char *ofd, *ols, *oe, *nfd, *nls, *ne;
int lendiff, wsatend;
int temp, lendiff, wsatend, od, nd;
/* If we're at the right edge of a terminal that supports xn, we're
ready to wrap around, so do so. This fixes problems with knowing
the exact cursor position and cut-and-paste with certain terminal
emulators. In this calculation, TEMP is the physical screen
position of the cursor. */
temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
if (temp == screenwidth && term_xn && !_rl_horizontal_scroll_mode
&& _rl_last_v_pos == current_line - 1)
{
if (new[0])
putc (new[0], rl_outstream);
else
putc (' ', rl_outstream);
_rl_last_c_pos = 1; /* XXX */
_rl_last_v_pos++;
if (old[0])
old[0] = new[0];
}
/* Find first difference. */
for (ofd = old, nfd = new;
(ofd - old < screenwidth) && *ofd && (*ofd == *nfd);
(ofd - old < omax) && *ofd && (*ofd == *nfd);
ofd++, nfd++)
;
/* Move to the end of the screen line. */
for (oe = ofd; ((oe - old) < screenwidth) && *oe; oe++);
for (ne = nfd; ((ne - new) < screenwidth) && *ne; ne++);
/* Move to the end of the screen line. ND and OD are used to keep track
of the distance between ne and new and oe and old, respectively, to
move a subtraction out of each loop. */
for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++);
for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
/* If no difference, continue to next line. */
if (ofd == oe && nfd == ne)
@ -607,72 +727,112 @@ update_line (old, new, current_line)
}
_rl_move_vert (current_line);
/* If this is the first line and there are invisible characters in the
prompt string, and the prompt string has not changed, then redraw
the entire prompt string. We can only do this reliably if the
terminal supports a `cr' capability.
This is more than just an efficiency hack -- there is a problem with
redrawing portions of the prompt string if they contain terminal
escape sequences (like drawing the `unbold' sequence without a
corresponding `bold') that manifests itself on certain terminals. */
lendiff = strlen (local_prompt);
if (current_line == 0 && !_rl_horizontal_scroll_mode &&
lendiff > visible_length &&
_rl_last_c_pos > 0 && (ofd - old) >= lendiff && term_cr)
{
tputs (term_cr, 1, _rl_output_character_function);
_rl_output_some_chars (local_prompt, lendiff);
_rl_last_c_pos = lendiff;
}
_rl_move_cursor_relative (ofd - old, old);
/* if (len (new) > len (old)) */
lendiff = (nls - nfd) - (ols - ofd);
/* Insert (diff (len (old), len (new)) ch. */
temp = ne - nfd;
if (lendiff > 0)
{
if (terminal_can_insert)
/* Non-zero if we're increasing the number of lines. */
int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
/* Sometimes it is cheaper to print the characters rather than
use the terminal's capabilities. If we're growing the number
of lines, make sure we actually cause the new line to wrap
around on auto-wrapping terminals. */
if (terminal_can_insert && ((2 * temp) >= lendiff || term_IC) && (!term_xn || !gl))
{
/* Sometimes it is cheaper to print the characters rather than
use the terminal's capabilities. */
if ((2 * (ne - nfd)) < lendiff && !term_IC)
/* If lendiff > visible_length and _rl_last_c_pos == 0 and
_rl_horizontal_scroll_mode == 1, inserting the characters with
term_IC or term_ic will screw up the screen because of the
invisible characters. We need to just draw them. */
if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 ||
lendiff <= visible_length))
{
_rl_output_some_chars (nfd, (ne - nfd));
_rl_last_c_pos += (ne - nfd);
insert_some_chars (nfd, lendiff);
_rl_last_c_pos += lendiff;
}
else
{
if (*ols)
{
insert_some_chars (nfd, lendiff);
_rl_last_c_pos += lendiff;
}
else
{
/* At the end of a line the characters do not have to
be "inserted". They can just be placed on the screen. */
_rl_output_some_chars (nfd, lendiff);
_rl_last_c_pos += lendiff;
}
/* Copy (new) chars to screen from first diff to last match. */
if (((nls - nfd) - lendiff) > 0)
{
_rl_output_some_chars (&nfd[lendiff], ((nls - nfd) - lendiff));
_rl_last_c_pos += ((nls - nfd) - lendiff);
}
/* At the end of a line the characters do not have to
be "inserted". They can just be placed on the screen. */
_rl_output_some_chars (nfd, lendiff);
_rl_last_c_pos += lendiff;
}
/* Copy (new) chars to screen from first diff to last match. */
temp = nls - nfd;
if ((temp - lendiff) > 0)
{
_rl_output_some_chars (nfd + lendiff, temp - lendiff);
_rl_last_c_pos += temp - lendiff;
}
}
else
{ /* cannot insert chars, write to EOL */
_rl_output_some_chars (nfd, (ne - nfd));
_rl_last_c_pos += (ne - nfd);
{
/* cannot insert chars, write to EOL */
_rl_output_some_chars (nfd, temp);
_rl_last_c_pos += temp;
}
}
else /* Delete characters from line. */
{
/* If possible and inexpensive to use terminal deletion, then do so. */
if (term_dc && (2 * (ne - nfd)) >= (-lendiff))
if (term_dc && (2 * temp) >= -lendiff)
{
/* If all we're doing is erasing the invisible characters in the
prompt string, don't bother. It screws up the assumptions
about what's on the screen. */
if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
-lendiff == visible_wrap_offset)
lendiff = 0;
if (lendiff)
delete_chars (-lendiff); /* delete (diff) characters */
/* Copy (new) chars to screen from first diff to last match */
if ((nls - nfd) > 0)
temp = nls - nfd;
if (temp > 0)
{
_rl_output_some_chars (nfd, (nls - nfd));
_rl_last_c_pos += (nls - nfd);
_rl_output_some_chars (nfd, temp);
_rl_last_c_pos += temp;
}
}
/* Otherwise, print over the existing material. */
else
{
_rl_output_some_chars (nfd, (ne - nfd));
_rl_last_c_pos += (ne - nfd);
clear_to_eol ((oe - old) - (ne - new));
if (temp > 0)
{
_rl_output_some_chars (nfd, temp);
_rl_last_c_pos += temp;
}
lendiff = (oe - old) - (ne - new);
if (term_xn && current_line < inv_botlin)
space_to_eol (lendiff);
else
clear_to_eol (lendiff);
}
}
}
@ -713,16 +873,23 @@ _rl_move_cursor_relative (new, data)
{
register int i;
/* If we don't have to do anything, then return. */
if (_rl_last_c_pos == new) return;
/* It may be faster to output a CR, and then move forwards instead
of moving backwards. */
if (new + 1 < _rl_last_c_pos - new)
/* i == current physical cursor position. */
i = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
if (CR_FASTER (new, _rl_last_c_pos) || (term_xn && i == screenwidth))
{
#if defined (__MSDOS__)
putc ('\r', rl_outstream);
#else
tputs (term_cr, 1, _rl_output_character_function);
#endif /* !__MSDOS__ */
_rl_last_c_pos = 0;
}
if (_rl_last_c_pos == new) return;
if (_rl_last_c_pos < new)
{
/* Move the cursor forward. We do it by printing the command
@ -748,7 +915,7 @@ _rl_move_cursor_relative (new, data)
putc (data[i], rl_outstream);
#endif /* HACK_TERMCAP_MOTION */
}
else
else if (_rl_last_c_pos != new)
backspace (_rl_last_c_pos - new);
_rl_last_c_pos = new;
}
@ -822,19 +989,23 @@ int
rl_character_len (c, pos)
register int c, pos;
{
if (META_CHAR (c))
unsigned char uc;
uc = (unsigned char)c;
if (META_CHAR (uc))
return ((_rl_output_meta_chars == 0) ? 4 : 1);
if (c == '\t')
if (uc == '\t')
{
#if defined (DISPLAY_TABS)
return (((pos | (int)7) + 1) - pos);
return (((pos | 7) + 1) - pos);
#else
return (2);
#endif /* !DISPLAY_TABS */
}
return ((isprint (c)) ? 1 : 2);
return ((isprint (uc)) ? 1 : 2);
}
/* How to print things in the "echo-area". The prompt is treated as a
@ -913,17 +1084,21 @@ clear_to_eol (count)
}
else
#endif /* !__GO32__ */
{
register int i;
space_to_eol (count);
}
/* Do one more character space. */
count++;
/* Clear to the end of the line using spaces. COUNT is the minimum
number of character spaces to clear, */
static void
space_to_eol (count)
int count;
{
register int i;
for (i = 0; i < count; i++)
putc (' ', rl_outstream);
for (i = 0; i < count; i++)
putc (' ', rl_outstream);
backspace (count);
}
_rl_last_c_pos += count;
}
/* Insert COUNT characters from STRING to the output stream. */
@ -998,7 +1173,7 @@ delete_chars (count)
memset (row_start + width - count, 0, count * 2);
#else /* !_GO32 */
if (count > screenwidth)
if (count > screenwidth) /* XXX */
return;
if (term_DC && *term_DC)
@ -1015,3 +1190,30 @@ delete_chars (count)
}
#endif /* !__GO32__ */
}
void
_rl_update_final ()
{
int full_lines;
full_lines = 0;
if (_rl_vis_botlin && visible_line[screenwidth * _rl_vis_botlin] == 0)
{
_rl_vis_botlin--;
full_lines = 1;
}
_rl_move_vert (_rl_vis_botlin);
if (full_lines && term_xn)
{
/* Remove final line-wrap flag in xterm. */
char *last_line;
last_line = &visible_line[screenwidth * _rl_vis_botlin];
_rl_move_cursor_relative (screenwidth - 1, last_line);
clear_to_eol (0);
putc (last_line[screenwidth - 1], rl_outstream);
}
_rl_vis_botlin = 0;
crlf ();
fflush (rl_outstream);
rl_display_fixed++;
}

View File

@ -1,34 +1,25 @@
# This makefile for History library documentation is in -*- text -*- mode.
# Emacs likes it that way.
DOC_SUPPORT = ../../doc-support/
TEXINDEX = $(DOC_SUPPORT)/texindex
INFOBJ = readline.info history.info
TEX = tex
DVIOBJ = history.dvi
INFOBJ = history.info
all: info
all: $(DVIOBJ) $(INFOBJ)
history.dvi: hist.texinfo hsuser.texinfo hstech.texinfo
$(TEX) hist.texinfo
$(TEXINDEX) hist.??
$(TEX) hist.texinfo
mv hist.dvi history.dvi
readline.info: rlman.texinfo rluser.texinfo rltech.texinfo
makeinfo rlman.texinfo
history.info: hist.texinfo hsuser.texinfo hstech.texinfo
makeinfo hist.texinfo
./texinfo.tex: $(DOC_SUPPORT)texinfo.tex
ln -s $(DOC_SUPPORT)texinfo.tex .
$(TEXINDEX):
(cd $(DOC_SUPPORT); $(MAKE) $(MFLAGS) CFLAGS='$(CFLAGS)' texindex)
info: $(INFOOBJ)
clean:
rm -f *.aux *.cp *.fn *.ky *.log *.pg *.toc *.tp *.vr *.cps *.pgs \
*.fns *.kys *.tps *.vrs *.o core texinfo.tex
*.fns *.kys *.tps *.vrs *.o core
squeaky-clean:
rm -f *.aux *.cp *.fn *.ky *.log *.pg *.toc *.tp *.vr *.cps *.pgs \
*.dvi *.info *.info-* *.fns *.kys *.tps *.vrs *.o core
*.info *.info-* *.fns *.kys *.tps *.vrs *.o core
distclean: clean
realclean: clean

View File

@ -1,11 +1,20 @@
\input texinfo @c -*-texinfo-*-
@comment %**start of header (This is for running Texinfo on a region.)
@c %**start of header (This is for running Texinfo on a region.)
@setfilename history.info
@settitle GNU Readline Library
@comment %**end of header (This is for running Texinfo on a region.)
@synindex vr fn
@settitle GNU History Library
@c %**end of header (This is for running Texinfo on a region.)
@setchapternewpage odd
@ignore
last change: Wed Jul 20 09:57:17 EDT 1994
@end ignore
@set EDITION 2.0
@set VERSION 2.0
@set UPDATED 20 July 1994
@set UPDATE-MONTH July 1994
@ifinfo
This document describes the GNU History library, a programming tool that
provides a consistent user interface for recalling lines of previously
@ -37,17 +46,13 @@ by the Foundation.
@titlepage
@sp 10
@center @titlefont{GNU History Library}
@center Brian Fox
@center Free Software Foundation
@center Version 1.1
@center April 1991
@c Include the Distribution inside the titlepage environment so
@c that headings are turned off.
@title GNU History Library
@subtitle Edition @value{EDITION}, for @code{History Library} Version @value{VERSION}.
@subtitle @value{UPDATE-MONTH}
@author Brian Fox, Free Software Foundation
@author Chet Ramey, Case Western Reserve University
@page
This document describes the GNU History library, a programming tool that
provides a consistent user interface for recalling lines of previously
typed input.
@ -91,6 +96,8 @@ typed input.
@end menu
@end ifinfo
@syncodeindex fn vr
@include hsuser.texinfo
@include hstech.texinfo
@ -101,6 +108,6 @@ typed input.
@node Function and Variable Index
@appendix Function and Variable Index
@printindex vr
@contents
@contents
@bye

View File

@ -0,0 +1,744 @@
This is Info file history.info, produced by Makeinfo-1.55 from the
input file hist.texinfo.
This document describes the GNU History library, a programming tool
that provides a consistent user interface for recalling lines of
previously typed input.
Copyright (C) 1988, 1991 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice pare
preserved on all copies.
Permission is granted to copy and distribute modified versions of
this manual under the conditions for verbatim copying, provided that
the entire resulting derived work is distributed under the terms of a
permission notice identical to this one.
Permission is granted to copy and distribute translations of this
manual into another language, under the above conditions for modified
versions, except that this permission notice may be stated in a
translation approved by the Foundation.

File: history.info, Node: Top, Next: Using History Interactively, Prev: (DIR), Up: (DIR)
GNU History Library
*******************
This document describes the GNU History library, a programming tool
that provides a consistent user interface for recalling lines of
previously typed input.
* Menu:
* Using History Interactively:: GNU History User's Manual.
* Programming with GNU History:: GNU History Programmer's Manual.
* Concept Index:: Index of concepts described in this manual.
* Function and Variable Index:: Index of externally visible functions
and variables.

File: history.info, Node: Using History Interactively, Next: Programming with GNU History, Prev: Top, Up: Top
Using History Interactively
***************************
This chapter describes how to use the GNU History Library
interactively, from a user's standpoint. It should be considered a
user's guide. For information on using the GNU History Library in your
own programs, *note Programming with GNU History::..
* Menu:
* History Interaction:: What it feels like using History as a user.

File: history.info, Node: History Interaction, Up: Using History Interactively
History Interaction
===================
The History library provides a history expansion feature that is
similar to the history expansion provided by `csh'. The following text
describes the syntax used to manipulate the history information.
History expansion takes place in two parts. The first is to
determine which line from the previous history should be used during
substitution. The second is to select portions of that line for
inclusion into the current one. The line selected from the previous
history is called the "event", and the portions of that line that are
acted upon are called "words". The line is broken into words in the
same fashion that Bash does, so that several English (or Unix) words
surrounded by quotes are considered as one word.
* Menu:
* Event Designators:: How to specify which history line to use.
* Word Designators:: Specifying which words are of interest.
* Modifiers:: Modifying the results of substitution.

File: history.info, Node: Event Designators, Next: Word Designators, Up: History Interaction
Event Designators
-----------------
An event designator is a reference to a command line entry in the
history list.
`!'
Start a history substitution, except when followed by a space, tab,
the end of the line, = or (.
`!!'
Refer to the previous command. This is a synonym for `!-1'.
`!n'
Refer to command line N.
`!-n'
Refer to the command N lines back.
`!string'
Refer to the most recent command starting with STRING.
`!?string'[`?']
Refer to the most recent command containing STRING.
`!#'
The entire command line typed so far.
`^string1^string2^'
Quick Substitution. Repeat the last command, replacing STRING1
with STRING2. Equivalent to `!!:s/string1/string2/'.

File: history.info, Node: Word Designators, Next: Modifiers, Prev: Event Designators, Up: History Interaction
Word Designators
----------------
A : separates the event specification from the word designator. It
can be omitted if the word designator begins with a ^, $, * or %.
Words are numbered from the beginning of the line, with the first word
being denoted by a 0 (zero).
`0 (zero)'
The `0'th word. For many applications, this is the command word.
`n'
The Nth word.
`^'
The first argument; that is, word 1.
`$'
The last argument.
`%'
The word matched by the most recent `?string?' search.
`x-y'
A range of words; `-Y' abbreviates `0-Y'.
`*'
All of the words, except the `0'th. This is a synonym for `1-$'.
It is not an error to use * if there is just one word in the event;
the empty string is returned in that case.
`x*'
Abbreviates `x-$'
`x-'
Abbreviates `x-$' like `x*', but omits the last word.

File: history.info, Node: Modifiers, Prev: Word Designators, Up: History Interaction
Modifiers
---------
After the optional word designator, you can add a sequence of one or
more of the following modifiers, each preceded by a :.
`h'
Remove a trailing pathname component, leaving only the head.
`r'
Remove a trailing suffix of the form `.'SUFFIX, leaving the
basename.
`e'
Remove all but the trailing suffix.
`t'
Remove all leading pathname components, leaving the tail.
`p'
Print the new command but do not execute it.
`s/old/new/'
Substitute NEW for the first occurrence of OLD in the event line.
Any delimiter may be used in place of /. The delimiter may be
quoted in OLD and NEW with a single backslash. If & appears in
NEW, it is replaced by OLD. A single backslash will quote the &.
The final delimiter is optional if it is the last character on the
input line.
`&'
Repeat the previous substitution.
`g'
Cause changes to be applied over the entire event line. Used in
conjunction with `s', as in `gs/old/new/', or with `&'.

File: history.info, Node: Programming with GNU History, Next: Concept Index, Prev: Using History Interactively, Up: Top
Programming with GNU History
****************************
This chapter describes how to interface programs that you write with
the GNU History Library. It should be considered a technical guide.
For information on the interactive use of GNU History, *note Using
History Interactively::..
* Menu:
* Introduction to History:: What is the GNU History library for?
* History Storage:: How information is stored.
* History Functions:: Functions that you can use.
* History Variables:: Variables that control behaviour.
* History Programming Example:: Example of using the GNU History Library.

File: history.info, Node: Introduction to History, Next: History Storage, Up: Programming with GNU History
Introduction to History
=======================
Many programs read input from the user a line at a time. The GNU
History library is able to keep track of those lines, associate
arbitrary data with each line, and utilize information from previous
lines in composing new ones.
The programmer using the History library has available functions for
remembering lines on a history list, associating arbitrary data with a
line, removing lines from the list, searching through the list for a
line containing an arbitrary text string, and referencing any line in
the list directly. In addition, a history "expansion" function is
available which provides for a consistent user interface across
different programs.
The user using programs written with the History library has the
benefit of a consistent user interface with a set of well-known
commands for manipulating the text of previous lines and using that text
in new commands. The basic history manipulation commands are similar to
the history substitution provided by `csh'.
If the programmer desires, he can use the Readline library, which
includes some history manipulation by default, and has the added
advantage of command line editing.

File: history.info, Node: History Storage, Next: History Functions, Prev: Introduction to History, Up: Programming with GNU History
History Storage
===============
The history list is an array of history entries. A history entry is
declared as follows:
typedef struct _hist_entry {
char *line;
char *data;
} HIST_ENTRY;
The history list itself might therefore be declared as
HIST_ENTRY **the_history_list;
The state of the History library is encapsulated into a single
structure:
/* A structure used to pass the current state of the history stuff around. */
typedef struct _hist_state {
HIST_ENTRY **entries; /* Pointer to the entries themselves. */
int offset; /* The location pointer within this array. */
int length; /* Number of elements within this array. */
int size; /* Number of slots allocated to this array. */
int flags;
} HISTORY_STATE;
If the flags member includes `HS_STIFLED', the history has been
stifled.

File: history.info, Node: History Functions, Next: History Variables, Prev: History Storage, Up: Programming with GNU History
History Functions
=================
This section describes the calling sequence for the various functions
present in GNU History.
* Menu:
* Initializing History and State Management:: Functions to call when you
want to use history in a
program.
* History List Management:: Functions used to manage the list
of history entries.
* Information About the History List:: Functions returning information about
the history list.
* Moving Around the History List:: Functions used to change the position
in the history list.
* Searching the History List:: Functions to search the history list
for entries containing a string.
* Managing the History File:: Functions that read and write a file
containing the history list.
* History Expansion:: Functions to perform csh-like history
expansion.

File: history.info, Node: Initializing History and State Management, Next: History List Management, Up: History Functions
Initializing History and State Management
-----------------------------------------
This section describes functions used to initialize and manage the
state of the History library when you want to use the history functions
in your program.
- Function: void using_history ()
Begin a session in which the history functions might be used. This
initializes the interactive variables.
- Function: HISTORY_STATE * history_get_history_state ()
Return a structure describing the current state of the input
history.
- Function: void history_set_history_state (HISTORY_STATE *state)
Set the state of the history list according to STATE.

File: history.info, Node: History List Management, Next: Information About the History List, Prev: Initializing History and State Management, Up: History Functions
History List Management
-----------------------
These functions manage individual entries on the history list, or set
parameters managing the list itself.
- Function: void add_history (char *string)
Place STRING at the end of the history list. The associated data
field (if any) is set to `NULL'.
- Function: HIST_ENTRY * remove_history (int which)
Remove history entry at offset WHICH from the history. The
removed element is returned so you can free the line, data, and
containing structure.
- Function: HIST_ENTRY * replace_history_entry (int which, char *line,
char *data)
Make the history entry at offset WHICH have LINE and DATA. This
returns the old entry so you can dispose of the data. In the case
of an invalid WHICH, a `NULL' pointer is returned.
- Function: void stifle_history (int max)
Stifle the history list, remembering only the last MAX entries.
- Function: int unstifle_history ()
Stop stifling the history. This returns the previous amount the
history was stifled. The value is positive if the history was
stifled, negative if it wasn't.
- Function: int history_is_stifled ()
Returns non-zero if the history is stifled, zero if it is not.

File: history.info, Node: Information About the History List, Next: Moving Around the History List, Prev: History List Management, Up: History Functions
Information About the History List
----------------------------------
These functions return information about the entire history list or
individual list entries.
- Function: HIST_ENTRY ** history_list ()
Return a `NULL' terminated array of `HIST_ENTRY' which is the
current input history. Element 0 of this list is the beginning of
time. If there is no history, return `NULL'.
- Function: int where_history ()
Returns the offset of the current history element.
- Function: HIST_ENTRY * current_history ()
Return the history entry at the current position, as determined by
`where_history ()'. If there is no entry there, return a `NULL'
pointer.
- Function: HIST_ENTRY * history_get (int offset)
Return the history entry at position OFFSET, starting from
`history_base'. If there is no entry there, or if OFFSET is
greater than the history length, return a `NULL' pointer.
- Function: int history_total_bytes ()
Return the number of bytes that the primary history entries are
using. This function returns the sum of the lengths of all the
lines in the history.

File: history.info, Node: Moving Around the History List, Next: Searching the History List, Prev: Information About the History List, Up: History Functions
Moving Around the History List
------------------------------
These functions allow the current index into the history list to be
set or changed.
- Function: int history_set_pos (int pos)
Set the position in the history list to POS, an absolute index
into the list.
- Function: HIST_ENTRY * previous_history ()
Back up the current history offset to the previous history entry,
and return a pointer to that entry. If there is no previous
entry, return a `NULL' pointer.
- Function: HIST_ENTRY * next_history ()
Move the current history offset forward to the next history entry,
and return the a pointer to that entry. If there is no next
entry, return a `NULL' pointer.

File: history.info, Node: Searching the History List, Next: Managing the History File, Prev: Moving Around the History List, Up: History Functions
Searching the History List
--------------------------
These functions allow searching of the history list for entries
containing a specific string. Searching may be performed both forward
and backward from the current history position. The search may be
"anchored", meaning that the string must match at the beginning of the
history entry.
- Function: int history_search (char *string, int direction)
Search the history for STRING, starting at the current history
offset. If DIRECTION < 0, then the search is through previous
entries, else through subsequent. If STRING is found, then the
current history index is set to that history entry, and the value
returned is the offset in the line of the entry where STRING was
found. Otherwise, nothing is changed, and a -1 is returned.
- Function: int history_search_prefix (char *string, int direction)
Search the history for STRING, starting at the current history
offset. The search is anchored: matching lines must begin with
STRING. If DIRECTION < 0, then the search is through previous
entries, else through subsequent. If STRING is found, then the
current history index is set to that entry, and the return value
is 0. Otherwise, nothing is changed, and a -1 is returned.
- Function: int history_search_pos (char *string, int direction, int
pos)
Search for STRING in the history list, starting at POS, an
absolute index into the list. If DIRECTION is negative, the search
proceeds backward from POS, otherwise forward. Returns the
absolute index of the history element where STRING was found, or
-1 otherwise.

File: history.info, Node: Managing the History File, Next: History Expansion, Prev: Searching the History List, Up: History Functions
Managing the History File
-------------------------
The History library can read the history from and write it to a file.
This section documents the functions for managing a history file.
- Function: int read_history (char *filename)
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.
- Function: int read_history_range (char *filename, int from, int to)
Read a range of lines from FILENAME, adding them to the history
list. Start reading at line FROM and end at TO. If FROM is zero,
start at the beginning. If TO is less than FROM, then read until
the end of the file. If FILENAME is `NULL', then read from
`~/.history'. Returns 0 if successful, or `errno' if not.
- Function: int write_history (char *filename)
Write the current history to FILENAME, overwriting FILENAME if
necessary. If FILENAME is `NULL', then write the history list to
`~/.history'. Values returned are as in `read_history ()'.
- Function: int append_history (int nelements, char *filename)
Append the last NELEMENTS of the history list to FILENAME.
- Function: int history_truncate_file (char *filename, int nlines)
Truncate the history file FILENAME, leaving only the last NLINES
lines.

File: history.info, Node: History Expansion, Prev: Managing the History File, Up: History Functions
History Expansion
-----------------
These functions implement `csh'-like history expansion.
- Function: int history_expand (char *string, char **output)
Expand STRING, placing the result into OUTPUT, a pointer to a
string (*note History Interaction::.). Returns:
`0'
If no expansions took place (or, if the only change in the
text was the de-slashifying of the history expansion
character);
`1'
if expansions did take place;
`-1'
if there was an error in expansion;
`2'
if the returned line should only be displayed, but not
executed, as with the `:p' modifier (*note Modifiers::.).
If an error ocurred in expansion, then OUTPUT contains a
descriptive error message.
- Function: char * history_arg_extract (int first, int last, char
*string)
Extract a string segment consisting of the FIRST through LAST
arguments present in STRING. Arguments are broken up as in Bash.
- Function: char * get_history_event (char *string, int *cindex, int
qchar)
Returns the text of the history event beginning at STRING +
*CINDEX. *CINDEX is modified to point to after the event
specifier. At function entry, CINDEX points to the index into
STRING where the history event specification begins. QCHAR is a
character that is allowed to end the event specification in
addition to the "normal" terminating characters.
- Function: char ** history_tokenize (char *string)
Return an array of tokens parsed out of STRING, much as the shell
might. The tokens are split on white space and on the characters
`()<>;&|$', and shell quoting conventions are obeyed.

File: history.info, Node: History Variables, Next: History Programming Example, Prev: History Functions, Up: Programming with GNU History
History Variables
=================
This section describes the externally visible variables exported by
the GNU History Library.
- Variable: int history_base
The logical offset of the first entry in the history list.
- Variable: int history_length
The number of entries currently stored in the history list.
- Variable: int max_input_history
The maximum number of history entries. This must be changed using
`stifle_history ()'.
- Variable: char history_expansion_char
The character that starts a history event. The default is `!'.
- Variable: char history_subst_char
The character that invokes word substitution if found at the start
of a line. The default is `^'.
- Variable: char history_comment_char
During tokenization, if this character is seen as the first
character of a word, then it and all subsequent characters up to a
newline are ignored, suppressing history expansion for the
remainder of the line. This is disabled by default.
- Variable: char * history_no_expand_chars
The list of characters which inhibit history expansion if found
immediately following HISTORY_EXPANSION_CHAR. The default is
whitespace and `='.

File: history.info, Node: History Programming Example, Prev: History Variables, Up: Programming with GNU History
History Programming Example
===========================
The following program demonstrates simple use of the GNU History
Library.
main ()
{
char line[1024], *t;
int len, done = 0;
line[0] = 0;
using_history ();
while (!done)
{
printf ("history$ ");
fflush (stdout);
t = fgets (line, sizeof (line) - 1, stdin);
if (t && *t)
{
len = strlen (t);
if (t[len - 1] == '\n')
t[len - 1] = '\0';
}
if (!t)
strcpy (line, "quit");
if (line[0])
{
char *expansion;
int result;
result = history_expand (line, &expansion);
if (result)
fprintf (stderr, "%s\n", expansion);
if (result < 0 || result == 2)
{
free (expansion);
continue;
}
add_history (expansion);
strncpy (line, expansion, sizeof (line) - 1);
free (expansion);
}
if (strcmp (line, "quit") == 0)
done = 1;
else if (strcmp (line, "save") == 0)
write_history ("history_file");
else if (strcmp (line, "read") == 0)
read_history ("history_file");
else if (strcmp (line, "list") == 0)
{
register HIST_ENTRY **the_list;
register int i;
the_list = history_list ();
if (the_list)
for (i = 0; the_list[i]; i++)
printf ("%d: %s\n", i + history_base, the_list[i]->line);
}
else if (strncmp (line, "delete", 6) == 0)
{
int which;
if ((sscanf (line + 6, "%d", &which)) == 1)
{
HIST_ENTRY *entry = remove_history (which);
if (!entry)
fprintf (stderr, "No such entry %d\n", which);
else
{
free (entry->line);
free (entry);
}
}
else
{
fprintf (stderr, "non-numeric arg given to `delete'\n");
}
}
}
}

File: history.info, Node: Concept Index, Next: Function and Variable Index, Prev: Programming with GNU History, Up: Top
Concept Index
*************
* Menu:
* anchored search: Searching the History List.
* event designators: Event Designators.
* expansion: History Interaction.
* history events: Event Designators.
* History Searching: Searching the History List.

File: history.info, Node: Function and Variable Index, Prev: Concept Index, Up: Top
Function and Variable Index
***************************
* Menu:
* add_history: History List Management.
* append_history: Managing the History File.
* current_history: Information About the History List.
* get_history_event: History Expansion.
* history_arg_extract: History Expansion.
* history_base: History Variables.
* history_comment_char: History Variables.
* history_expand: History Expansion.
* history_expansion_char: History Variables.
* history_get: Information About the History List.
* history_get_history_state: Initializing History and State Management.
* history_is_stifled: History List Management.
* history_length: History Variables.
* history_list: Information About the History List.
* history_no_expand_chars: History Variables.
* history_search: Searching the History List.
* history_search_pos: Searching the History List.
* history_search_prefix: Searching the History List.
* history_set_history_state: Initializing History and State Management.
* history_set_pos: Moving Around the History List.
* history_subst_char: History Variables.
* history_tokenize: History Expansion.
* history_total_bytes: Information About the History List.
* history_truncate_file: Managing the History File.
* max_input_history: History Variables.
* next_history: Moving Around the History List.
* previous_history: Moving Around the History List.
* read_history: Managing the History File.
* read_history_range: Managing the History File.
* remove_history: History List Management.
* replace_history_entry: History List Management.
* stifle_history: History List Management.
* unstifle_history: History List Management.
* using_history: Initializing History and State Management.
* where_history: Information About the History List.
* write_history: Managing the History File.

Tag Table:
Node: Top975
Node: Using History Interactively1569
Node: History Interaction2077
Node: Event Designators3122
Node: Word Designators3952
Node: Modifiers4936
Node: Programming with GNU History6065
Node: Introduction to History6791
Node: History Storage8112
Node: History Functions9205
Node: Initializing History and State Management10176
Node: History List Management10968
Node: Information About the History List12396
Node: Moving Around the History List13702
Node: Searching the History List14587
Node: Managing the History File16419
Node: History Expansion17925
Node: History Variables19769
Node: History Programming Example21138
Node: Concept Index23742
Node: Function and Variable Index24223

End Tag Table

View File

@ -2,7 +2,7 @@
This file documents the user interface to the GNU History library.
Copyright (C) 1988, 1991 Free Software Foundation, Inc.
Authored by Brian Fox.
Authored by Brian Fox and Chet Ramey.
Permission is granted to make and distribute verbatim copies of this manual
provided the copyright notice and this permission notice are preserved on
@ -26,8 +26,9 @@ into another language, under the above conditions for modified versions.
@node Programming with GNU History
@chapter Programming with GNU History
This chapter describes how to interface the GNU History Library with
programs that you write. It should be considered a technical guide.
This chapter describes how to interface programs that you write
with the GNU History Library.
It should be considered a technical guide.
For information on the interactive use of GNU History, @pxref{Using
History Interactively}.
@ -42,32 +43,35 @@ History Interactively}.
@node Introduction to History
@section Introduction to History
Many programs read input from the user a line at a time. The GNU history
Many programs read input from the user a line at a time. The GNU History
library is able to keep track of those lines, associate arbitrary data with
each line, and utilize information from previous lines in making up new
each line, and utilize information from previous lines in composing new
ones.
The programmer using the History library has available to him functions
for remembering lines on a history stack, associating arbitrary data
with a line, removing lines from the stack, searching through the stack
The programmer using the History library has available functions
for remembering lines on a history list, associating arbitrary data
with a line, removing lines from the list, searching through the list
for a line containing an arbitrary text string, and referencing any line
on the stack directly. In addition, a history @dfn{expansion} function
is available which provides for a consistent user interface across many
in the list directly. In addition, a history @dfn{expansion} function
is available which provides for a consistent user interface across
different programs.
The end-user using programs written with the History library has the
benifit of a consistent user interface, with a set of well-known
The user using programs written with the History library has the
benefit of a consistent user interface with a set of well-known
commands for manipulating the text of previous lines and using that text
in new commands. The basic history manipulation commands are similar to
the history substitution used by @code{Csh}.
the history substitution provided by @code{csh}.
If the programmer desires, he can use the Readline library, which
includes some history manipulation by default, and has the added
advantage of Emacs style command line editing.
advantage of command line editing.
@node History Storage
@section History Storage
The history list is an array of history entries. A history entry is
declared as follows:
@example
typedef struct _hist_entry @{
char *line;
@ -75,179 +79,352 @@ typedef struct _hist_entry @{
@} HIST_ENTRY;
@end example
The history list itself might therefore be declared as
@example
HIST_ENTRY **the_history_list;
@end example
The state of the History library is encapsulated into a single structure:
@example
/* A structure used to pass the current state of the history stuff around. */
typedef struct _hist_state @{
HIST_ENTRY **entries; /* Pointer to the entries themselves. */
int offset; /* The location pointer within this array. */
int length; /* Number of elements within this array. */
int size; /* Number of slots allocated to this array. */
int flags;
@} HISTORY_STATE;
@end example
If the flags member includes @code{HS_STIFLED}, the history has been
stifled.
@node History Functions
@section History Functions
This section describes the calling sequence for the various functions
present in GNU History.
@defun {void using_history} ()
Begin a session in which the history functions might be used. This
just initializes the interactive variables.
@end defun
@menu
* Initializing History and State Management:: Functions to call when you
want to use history in a
program.
* History List Management:: Functions used to manage the list
of history entries.
* Information About the History List:: Functions returning information about
the history list.
* Moving Around the History List:: Functions used to change the position
in the history list.
* Searching the History List:: Functions to search the history list
for entries containing a string.
* Managing the History File:: Functions that read and write a file
containing the history list.
* History Expansion:: Functions to perform csh-like history
expansion.
@end menu
@defun {void add_history} (char *string)
@node Initializing History and State Management
@subsection Initializing History and State Management
This section describes functions used to initialize and manage
the state of the History library when you want to use the history
functions in your program.
@deftypefun void using_history ()
Begin a session in which the history functions might be used. This
initializes the interactive variables.
@end deftypefun
@deftypefun {HISTORY_STATE *} history_get_history_state ()
Return a structure describing the current state of the input history.
@end deftypefun
@deftypefun void history_set_history_state (HISTORY_STATE *state)
Set the state of the history list according to @var{state}.
@end deftypefun
@node History List Management
@subsection History List Management
These functions manage individual entries on the history list, or set
parameters managing the list itself.
@deftypefun void add_history (char *string)
Place @var{string} at the end of the history list. The associated data
field (if any) is set to @code{NULL}.
@end defun
@end deftypefun
@defun {int where_history} ()
Returns the number which says what history element we are now looking
at.
@end defun
@defun {int history_set_pos} (int pos)
Set the position in the history list to @var{pos}.
@end defun
@defun {int history_search_pos} (char *string, int direction, int pos)
Search for @var{string} in the history list, starting at @var{pos}, an
absolute index into the list. @var{direction}, if negative, says to search
backwards from @var{pos}, else forwards. Returns the absolute index of
the history element where @var{string} was found, or -1 otherwise.
@end defun
@defun {HIST_ENTRY *remove_history} ();
Remove history element @var{which} from the history. The removed
element is returned to you so you can free the line, data,
@deftypefun {HIST_ENTRY *} remove_history (int which)
Remove history entry at offset @var{which} from the history. The
removed element is returned so you can free the line, data,
and containing structure.
@end defun
@end deftypefun
@defun {void stifle_history} (int max)
Stifle the history list, remembering only @var{max} number of entries.
@end defun
@deftypefun {HIST_ENTRY *} replace_history_entry (int which, char *line, char *data)
Make the history entry at offset @var{which} have @var{line} and @var{data}.
This returns the old entry so you can dispose of the data. In the case
of an invalid @var{which}, a @code{NULL} pointer is returned.
@end deftypefun
@defun {int unstifle_history} ();
@deftypefun void stifle_history (int max)
Stifle the history list, remembering only the last @var{max} entries.
@end deftypefun
@deftypefun int unstifle_history ()
Stop stifling the history. This returns the previous amount the
history was stifled by. The value is positive if the history was
history was stifled. The value is positive if the history was
stifled, negative if it wasn't.
@end defun
@end deftypefun
@defun {int read_history} (char *filename)
@deftypefun int history_is_stifled ()
Returns non-zero if the history is stifled, zero if it is not.
@end deftypefun
@node Information About the History List
@subsection Information About the History List
These functions return information about the entire history list or
individual list entries.
@deftypefun {HIST_ENTRY **} history_list ()
Return a @code{NULL} terminated array of @code{HIST_ENTRY} which is the
current input history. Element 0 of this list is the beginning of time.
If there is no history, return @code{NULL}.
@end deftypefun
@deftypefun int where_history ()
Returns the offset of the current history element.
@end deftypefun
@deftypefun {HIST_ENTRY *} current_history ()
Return the history entry at the current position, as determined by
@code{where_history ()}. If there is no entry there, return a @code{NULL}
pointer.
@end deftypefun
@deftypefun {HIST_ENTRY *} history_get (int offset)
Return the history entry at position @var{offset}, starting from
@code{history_base}. If there is no entry there, or if @var{offset}
is greater than the history length, return a @code{NULL} pointer.
@end deftypefun
@deftypefun int history_total_bytes ()
Return the number of bytes that the primary history entries are using.
This function returns the sum of the lengths of all the lines in the
history.
@end deftypefun
@node Moving Around the History List
@subsection Moving Around the History List
These functions allow the current index into the history list to be
set or changed.
@deftypefun int history_set_pos (int pos)
Set the position in the history list to @var{pos}, an absolute index
into the list.
@end deftypefun
@deftypefun {HIST_ENTRY *} previous_history ()
Back up the current history offset to the previous history entry, and
return a pointer to that entry. If there is no previous entry, return
a @code{NULL} pointer.
@end deftypefun
@deftypefun {HIST_ENTRY *} next_history ()
Move the current history offset forward to the next history entry, and
return the a pointer to that entry. If there is no next entry, return
a @code{NULL} pointer.
@end deftypefun
@node Searching the History List
@subsection Searching the History List
@cindex History Searching
These functions allow searching of the history list for entries containing
a specific string. Searching may be performed both forward and backward
from the current history position. The search may be @dfn{anchored},
meaning that the string must match at the beginning of the history entry.
@cindex anchored search
@deftypefun int history_search (char *string, int direction)
Search the history for @var{string}, starting at the current history
offset. If @var{direction} < 0, then the search is through previous entries,
else through subsequent. If @var{string} is found, then
the current history index is set to that history entry, and the value
returned is the offset in the line of the entry where
@var{string} was found. Otherwise, nothing is changed, and a -1 is
returned.
@end deftypefun
@deftypefun int history_search_prefix (char *string, int direction)
Search the history for @var{string}, starting at the current history
offset. The search is anchored: matching lines must begin with
@var{string}. If @var{direction} < 0, then the search is through previous
entries, else through subsequent. If @var{string} is found, then the
current history index is set to that entry, and the return value is 0.
Otherwise, nothing is changed, and a -1 is returned.
@end deftypefun
@deftypefun int history_search_pos (char *string, int direction, int pos)
Search for @var{string} in the history list, starting at @var{pos}, an
absolute index into the list. If @var{direction} is negative, the search
proceeds backward from @var{pos}, otherwise forward. Returns the absolute
index of the history element where @var{string} was found, or -1 otherwise.
@end deftypefun
@node Managing the History File
@subsection Managing the History File
The History library can read the history from and write it to a file.
This section documents the functions for managing a history file.
@deftypefun int read_history (char *filename)
Add the contents of @var{filename} to the history list, a line at a
time. If @var{filename} is @code{NULL}, then read from
@file{~/.history}. Returns 0 if successful, or errno if not.
@end defun
@end deftypefun
@defun {int read_history_range} (char *filename, int from, int to)
@deftypefun int read_history_range (char *filename, int from, int to)
Read a range of lines from @var{filename}, adding them to the history list.
Start reading at the @var{from}'th line and end at the @var{to}'th. If
Start reading at line @var{from} and end at @var{to}. If
@var{from} is zero, start at the beginning. If @var{to} is less than
@var{from}, then read until the end of the file. If @var{filename} is
@code{NULL}, then read from @file{~/.history}. Returns 0 if successful,
or @code{errno} if not.
@end defun
@end deftypefun
@defun {int write_history} (char *filename)
Append the current history to @var{filename}. If @var{filename} is
@code{NULL}, then append the history list to @file{~/.history}. Values
@deftypefun int write_history (char *filename)
Write the current history to @var{filename}, overwriting @var{filename}
if necessary. If @var{filename} is
@code{NULL}, then write the history list to @file{~/.history}. Values
returned are as in @code{read_history ()}.
@end defun
@end deftypefun
@defun {int append_history} (int nelements, char *filename)
Append @var{nelement} entries to @var{filename}. The entries appended
are from the end of the list minus @var{nelements} up to the end of the
list.
@end defun
@deftypefun int append_history (int nelements, char *filename)
Append the last @var{nelements} of the history list to @var{filename}.
@end deftypefun
@defun {HIST_ENTRY *replace_history_entry} ()
Make the history entry at @var{which} have @var{line} and @var{data}.
This returns the old entry so you can dispose of the data. In the case
of an invalid @var{which}, a @code{NULL} pointer is returned.
@end defun
@deftypefun int history_truncate_file (char *filename, int nlines)
Truncate the history file @var{filename}, leaving only the last
@var{nlines} lines.
@end deftypefun
@defun {HIST_ENTRY *current_history} ()
Return the history entry at the current position, as determined by
@code{history_offset}. If there is no entry there, return a @code{NULL}
pointer.
@end defun
@node History Expansion
@subsection History Expansion
@defun {HIST_ENTRY *previous_history} ()
Back up @var{history_offset} to the previous history entry, and return a
pointer to that entry. If there is no previous entry, return a
@code{NULL} pointer.
@end defun
These functions implement @code{csh}-like history expansion.
@defun {HIST_ENTRY *next_history} ()
Move @code{history_offset} forward to the next history entry, and return
the a pointer to that entry. If there is no next entry, return a
@code{NULL} pointer.
@end defun
@defun {HIST_ENTRY **history_list} ()
Return a @code{NULL} terminated array of @code{HIST_ENTRY} which is the
current input history. Element 0 of this list is the beginning of time.
If there is no history, return @code{NULL}.
@end defun
@defun {int history_search} (char *string, int direction)
Search the history for @var{string}, starting at @code{history_offset}.
If @var{direction} < 0, then the search is through previous entries,
else through subsequent. If @var{string} is found, then
@code{current_history ()} is the history entry, and the value of this
function is the offset in the line of that history entry that the
@var{string} was found in. Otherwise, nothing is changed, and a -1 is
returned.
@end defun
@defun {int history_expand} (char *string, char **output)
@deftypefun int history_expand (char *string, char **output)
Expand @var{string}, placing the result into @var{output}, a pointer
to a string. Returns:
to a string (@pxref{History Interaction}). Returns:
@table @code
@item 0
If no expansions took place (or, if the only change in
the text was the de-slashifying of the history expansion
character),
character);
@item 1
if expansions did take place, or
if expansions did take place;
@item -1
if there was an error in expansion.
if there was an error in expansion;
@item 2
if the returned line should only be displayed, but not executed,
as with the @code{:p} modifier (@pxref{Modifiers}).
@end table
If an error ocurred in expansion, then @var{output} contains a descriptive
error message.
@end defun
@end deftypefun
@defun {char *history_arg_extract} (int first, int last, char *string)
@deftypefun {char *} history_arg_extract (int first, int last, char *string)
Extract a string segment consisting of the @var{first} through @var{last}
arguments present in @var{string}. Arguments are broken up as in
the GNU Bash shell.
@end defun
arguments present in @var{string}. Arguments are broken up as in Bash.
@end deftypefun
@defun {int history_total_bytes} ();
Return the number of bytes that the primary history entries are using.
This just adds up the lengths of @code{the_history->lines}.
@end defun
@deftypefun {char *} get_history_event (char *string, int *cindex, int qchar)
Returns the text of the history event beginning at @var{string} +
@var{*cindex}. @var{*cindex} is modified to point to after the event
specifier. At function entry, @var{cindex} points to the index into
@var{string} where the history event specification begins. @var{qchar}
is a character that is allowed to end the event specification in addition
to the ``normal'' terminating characters.
@end deftypefun
@deftypefun {char **} history_tokenize (char *string)
Return an array of tokens parsed out of @var{string}, much as the
shell might. The tokens are split on white space and on the
characters @code{()<>;&|$}, and shell quoting conventions are
obeyed.
@end deftypefun
@node History Variables
@section History Variables
This section describes the variables in GNU History that are externally
visible.
This section describes the externally visible variables exported by
the GNU History Library.
@defvar {int history_base}
For convenience only. You set this when interpreting history commands.
It is the logical offset of the first history element.
@end defvar
@deftypevar int history_base
The logical offset of the first entry in the history list.
@end deftypevar
@deftypevar int history_length
The number of entries currently stored in the history list.
@end deftypevar
@deftypevar int max_input_history
The maximum number of history entries. This must be changed using
@code{stifle_history ()}.
@end deftypevar
@deftypevar char history_expansion_char
The character that starts a history event. The default is @samp{!}.
@end deftypevar
@deftypevar char history_subst_char
The character that invokes word substitution if found at the start of
a line. The default is @samp{^}.
@end deftypevar
@deftypevar char history_comment_char
During tokenization, if this character is seen as the first character
of a word, then it and all subsequent characters up to a newline are
ignored, suppressing history expansion for the remainder of the line.
This is disabled by default.
@end deftypevar
@deftypevar {char *} history_no_expand_chars
The list of characters which inhibit history expansion if found immediately
following @var{history_expansion_char}. The default is whitespace and
@samp{=}.
@end deftypevar
@node History Programming Example
@section History Programming Example
The following snippet of code demonstrates simple use of the GNU History
Library.
The following program demonstrates simple use of the GNU History Library.
@smallexample
main ()
@{
char line[1024], *t;
int done = 0;
int len, done = 0;
line[0] = 0;
using_history ();
while (!done)
@{
fprintf (stdout, "history%% ");
t = gets (line);
printf ("history$ ");
fflush (stdout);
t = fgets (line, sizeof (line) - 1, stdin);
if (t && *t)
@{
len = strlen (t);
if (t[len - 1] == '\n')
t[len - 1] = '\0';
@}
if (!t)
strcpy (line, "quit");
@ -257,37 +434,41 @@ main ()
char *expansion;
int result;
using_history ();
result = history_expand (line, &expansion);
strcpy (line, expansion);
free (expansion);
if (result)
fprintf (stderr, "%s\n", line);
fprintf (stderr, "%s\n", expansion);
if (result < 0)
continue;
if (result < 0 || result == 2)
@{
free (expansion);
continue;
@}
add_history (line);
add_history (expansion);
strncpy (line, expansion, sizeof (line) - 1);
free (expansion);
@}
if (strcmp (line, "quit") == 0) done = 1;
if (strcmp (line, "save") == 0) write_history (0);
if (strcmp (line, "read") == 0) read_history (0);
if (strcmp (line, "list") == 0)
if (strcmp (line, "quit") == 0)
done = 1;
else if (strcmp (line, "save") == 0)
write_history ("history_file");
else if (strcmp (line, "read") == 0)
read_history ("history_file");
else if (strcmp (line, "list") == 0)
@{
register HIST_ENTRY **the_list = history_list ();
register HIST_ENTRY **the_list;
register int i;
the_list = history_list ();
if (the_list)
for (i = 0; the_list[i]; i++)
fprintf (stdout, "%d: %s\n",
i + history_base, the_list[i]->line);
printf ("%d: %s\n", i + history_base, the_list[i]->line);
@}
if (strncmp (line, "delete", strlen ("delete")) == 0)
else if (strncmp (line, "delete", 6) == 0)
@{
int which;
if ((sscanf (line + strlen ("delete"), "%d", &which)) == 1)
if ((sscanf (line + 6, "%d", &which)) == 1)
@{
HIST_ENTRY *entry = remove_history (which);
if (!entry)

View File

@ -48,8 +48,8 @@ information on using the GNU History Library in your own programs,
@cindex expansion
The History library provides a history expansion feature that is similar
to the history expansion in @code{csh}. The following text describes
the syntax used to manipulate the history information.
to the history expansion provided by @code{csh}. The following text
describes the syntax used to manipulate the history information.
History expansion takes place in two parts. The first is to determine
which line from the previous history should be used during substitution.
@ -72,6 +72,7 @@ surrounded by quotes are considered as one word.
An event designator is a reference to a command line entry in the
history list.
@cindex history events
@table @asis
@ -86,7 +87,7 @@ Refer to the previous command. This is a synonym for @code{!-1}.
Refer to command line @var{n}.
@item @code{!-n}
Refer to the command line @var{n} lines back.
Refer to the command @var{n} lines back.
@item @code{!string}
Refer to the most recent command starting with @var{string}.

View File

@ -0,0 +1,74 @@
This is Info file readline.info, produced by Makeinfo-1.55 from the
input file rlman.texinfo.
This document describes the GNU Readline Library, a utility which
aids in the consistency of user interface across discrete programs that
need to provide a command line interface.
Copyright (C) 1988, 1991 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice pare
preserved on all copies.
Permission is granted to copy and distribute modified versions of
this manual under the conditions for verbatim copying, provided that
the entire resulting derived work is distributed under the terms of a
permission notice identical to this one.
Permission is granted to copy and distribute translations of this
manual into another language, under the above conditions for modified
versions, except that this permission notice may be stated in a
translation approved by the Foundation.

Indirect:
readline.info-1: 1000
readline.info-2: 50467

Tag Table:
(Indirect)
Node: Top1000
Node: Command Line Editing1613
Node: Introduction and Notation2264
Node: Readline Interaction3284
Node: Readline Bare Essentials4423
Node: Readline Movement Commands5953
Node: Readline Killing Commands6844
Node: Readline Arguments8547
Node: Readline Init File9498
Node: Readline Init Syntax10502
Node: Conditional Init Constructs17435
Node: Bindable Readline Commands19681
Node: Commands For Moving20351
Node: Commands For History21199
Node: Commands For Text23783
Node: Commands For Killing25522
Node: Numeric Arguments26971
Node: Commands For Completion27598
Node: Keyboard Macros28525
Node: Miscellaneous Commands29084
Node: Readline vi Mode30372
Node: Programming with GNU Readline32122
Node: Basic Behavior32919
Node: Custom Functions36232
Node: The Function Type36845
Node: Function Writing37690
Node: Readline Convenience Functions40453
Node: Function Naming41118
Node: Keymaps42345
Node: Binding Keys43856
Node: Associating Function Names and Bindings45650
Node: Allowing Undoing46812
Node: Redisplay49397
Node: Modifying Text50467
Node: Utility Functions51378
Node: Custom Completers54444
Node: How Completing Works55165
Node: Completion Functions58156
Node: Completion Variables61171
Node: A Short Completion Example64996
Node: Concept Index77230
Node: Function and Variable Index77717

End Tag Table

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,978 @@
This is Info file readline.info, produced by Makeinfo-1.55 from the
input file rlman.texinfo.
This document describes the GNU Readline Library, a utility which
aids in the consistency of user interface across discrete programs that
need to provide a command line interface.
Copyright (C) 1988, 1991 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice pare
preserved on all copies.
Permission is granted to copy and distribute modified versions of
this manual under the conditions for verbatim copying, provided that
the entire resulting derived work is distributed under the terms of a
permission notice identical to this one.
Permission is granted to copy and distribute translations of this
manual into another language, under the above conditions for modified
versions, except that this permission notice may be stated in a
translation approved by the Foundation.

File: readline.info, Node: Modifying Text, Next: Utility Functions, Prev: Redisplay, Up: Readline Convenience Functions
Modifying Text
--------------
- Function: int rl_insert_text (char *text)
Insert TEXT into the line at the current cursor position.
- Function: int rl_delete_text (int start, int end)
Delete the text between START and END in the current line.
- Function: char * rl_copy_text (int start, int end)
Return a copy of the text between START and END in the current
line.
- Function: int rl_kill_text (int start, int end)
Copy the text between START and END in the current line to the
kill ring, appending or prepending to the last kill if the last
command was a kill command. The text is deleted. If START is
less than END, the text is appended, otherwise prepended. If the
last command was not a kill, a new kill ring slot is used.

File: readline.info, Node: Utility Functions, Prev: Modifying Text, Up: Readline Convenience Functions
Utility Functions
-----------------
- Function: int rl_reset_terminal (char *terminal_name)
Reinitialize Readline's idea of the terminal settings using
TERMINAL_NAME as the terminal type (e.g., `vt100').
- Function: int alphabetic (int c)
Return 1 if C is an alphabetic character.
- Function: int numeric (int c)
Return 1 if C is a numeric character.
- Function: int ding ()
Ring the terminal bell, obeying the setting of `bell-style'.
The following are implemented as macros, defined in `chartypes.h'.
- Function: int uppercase_p (int c)
Return 1 if C is an uppercase alphabetic character.
- Function: int lowercase_p (int c)
Return 1 if C is a lowercase alphabetic character.
- Function: int digit_p (int c)
Return 1 if C is a numeric character.
- Function: int to_upper (int c)
If C is a lowercase alphabetic character, return the corresponding
uppercase character.
- Function: int to_lower (int c)
If C is an uppercase alphabetic character, return the corresponding
lowercase character.
- Function: int digit_value (int c)
If C is a number, return the value it represents.
An Example
----------
Here is a function which changes lowercase characters to their
uppercase equivalents, and uppercase characters to lowercase. If this
function was bound to `M-c', then typing `M-c' would change the case of
the character under point. Typing `M-1 0 M-c' would change the case of
the following 10 characters, leaving the cursor on the last character
changed.
/* Invert the case of the COUNT following characters. */
int
invert_case_line (count, key)
int count, key;
{
register int start, end, i;
start = rl_point;
if (rl_point >= rl_end)
return (0);
if (count < 0)
{
direction = -1;
count = -count;
}
else
direction = 1;
/* Find the end of the range to modify. */
end = start + (count * direction);
/* Force it to be within range. */
if (end > rl_end)
end = rl_end;
else if (end < 0)
end = 0;
if (start == end)
return (0);
if (start > end)
{
int temp = start;
start = end;
end = temp;
}
/* Tell readline that we are modifying the line, so it will save
the undo information. */
rl_modifying (start, end);
for (i = start; i != end; i++)
{
if (uppercase_p (rl_line_buffer[i]))
rl_line_buffer[i] = to_lower (rl_line_buffer[i]);
else if (lowercase_p (rl_line_buffer[i]))
rl_line_buffer[i] = to_upper (rl_line_buffer[i]);
}
/* Move point to on top of the last character changed. */
rl_point = (direction == 1) ? end - 1 : start;
return (0);
}

File: readline.info, Node: Custom Completers, Prev: Readline Convenience Functions, Up: Programming with GNU Readline
Custom Completers
=================
Typically, a program that reads commands from the user has a way of
disambiguating commands and data. If your program is one of these, then
it can provide completion for commands, data, or both. The following
sections describe how your program and Readline cooperate to provide
this service.
* Menu:
* How Completing Works:: The logic used to do completion.
* Completion Functions:: Functions provided by Readline.
* Completion Variables:: Variables which control completion.
* A Short Completion Example:: An example of writing completer subroutines.

File: readline.info, Node: How Completing Works, Next: Completion Functions, Up: Custom Completers
How Completing Works
--------------------
In order to complete some text, the full list of possible completions
must be available. That is, it is not possible to accurately expand a
partial word without knowing all of the possible words which make sense
in that context. The Readline library provides the user interface to
completion, and two of the most common completion functions: filename
and username. For completing other types of text, you must write your
own completion function. This section describes exactly what such
functions must do, and provides an example.
There are three major functions used to perform completion:
1. The user-interface function `rl_complete ()'. This function is
called with the same arguments as other Readline functions
intended for interactive use: COUNT and INVOKING_KEY. It
isolates the word to be completed and calls `completion_matches
()' to generate a list of possible completions. It then either
lists the possible completions, inserts the possible completions,
or actually performs the completion, depending on which behavior
is desired.
2. The internal function `completion_matches ()' uses your
"generator" function to generate the list of possible matches, and
then returns the array of these matches. You should place the
address of your generator function in
`rl_completion_entry_function'.
3. The generator function is called repeatedly from
`completion_matches ()', returning a string each time. The
arguments to the generator function are TEXT and STATE. TEXT is
the partial word to be completed. STATE is zero the first time
the function is called, allowing the generator to perform any
necessary initialization, and a positive non-zero integer for each
subsequent call. When the generator function returns `(char
*)NULL' this signals `completion_matches ()' that there are no
more possibilities left. Usually the generator function computes
the list of possible completions when STATE is zero, and returns
them one at a time on subsequent calls. Each string the generator
function returns as a match must be allocated with `malloc()';
Readline frees the strings when it has finished with them.
- Function: int rl_complete (int ignore, int invoking_key)
Complete the word at or before point. You have supplied the
function that does the initial simple matching selection algorithm
(see `completion_matches ()'). The default is to do filename
completion.
- Variable: Function * rl_completion_entry_function
This is a pointer to the generator function for `completion_matches
()'. If the value of `rl_completion_entry_function' is `(Function
*)NULL' then the default filename generator function,
`filename_entry_function ()', is used.

File: readline.info, Node: Completion Functions, Next: Completion Variables, Prev: How Completing Works, Up: Custom Completers
Completion Functions
--------------------
Here is the complete list of callable completion functions present in
Readline.
- Function: int rl_complete_internal (int what_to_do)
Complete the word at or before point. WHAT_TO_DO says what to do
with the completion. A value of `?' means list the possible
completions. `TAB' means do standard completion. `*' means
insert all of the possible completions. `!' means to display all
of the possible completions, if there is more than one, as well as
performing partial completion.
- Function: int rl_complete (int ignore, int invoking_key)
Complete the word at or before point. You have supplied the
function that does the initial simple matching selection algorithm
(see `completion_matches ()' and `rl_completion_entry_function').
The default is to do filename completion. This calls
`rl_complete_internal ()' with an argument depending on
INVOKING_KEY.
- Function: int rl_possible_completions (int count, int invoking_key))
List the possible completions. See description of `rl_complete
()'. This calls `rl_complete_internal ()' with an argument of `?'.
- Function: int rl_insert_completions (int count, int invoking_key))
Insert the list of possible completions into the line, deleting the
partially-completed word. See description of `rl_complete ()'.
This calls `rl_complete_internal ()' with an argument of `*'.
- Function: char ** completion_matches (char *text, CPFunction
*entry_func)
Returns an array of `(char *)' which is a list of completions for
TEXT. If there are no completions, returns `(char **)NULL'. The
first entry in the returned array is the substitution for TEXT.
The remaining entries are the possible completions. The array is
terminated with a `NULL' pointer.
ENTRY_FUNC is a function of two args, and returns a `(char *)'.
The first argument is TEXT. The second is a state argument; it is
zero on the first call, and non-zero on subsequent calls.
eNTRY_FUNC returns a `NULL' pointer to the caller when there are
no more matches.
- Function: char * filename_completion_function (char *text, int state)
A generator function for filename completion in the general case.
Note that completion in Bash is a little different because of all
the pathnames that must be followed when looking up completions
for a command. The Bash source is a useful reference for writing
custom completion functions.
- Function: char * username_completion_function (char *text, int state)
A completion generator for usernames. TEXT contains a partial
username preceded by a random character (usually `~'). As with all
completion generators, STATE is zero on the first call and non-zero
for subsequent calls.

File: readline.info, Node: Completion Variables, Next: A Short Completion Example, Prev: Completion Functions, Up: Custom Completers
Completion Variables
--------------------
- Variable: Function * rl_completion_entry_function
A pointer to the generator function for `completion_matches ()'.
`NULL' means to use `filename_entry_function ()', the default
filename completer.
- Variable: CPPFunction * rl_attempted_completion_function
A pointer to an alternative function to create matches. The
function is called with TEXT, START, and END. START and END are
indices in `rl_line_buffer' saying what the boundaries of TEXT
are. If this function exists and returns `NULL', or if this
variable is set to `NULL', then `rl_complete ()' will call the
value of `rl_completion_entry_function' to generate matches,
otherwise the array of strings returned will be used.
- Variable: int rl_completion_query_items
Up to this many items will be displayed in response to a
possible-completions call. After that, we ask the user if she is
sure she wants to see them all. The default value is 100.
- Variable: char * rl_basic_word_break_characters
The basic list of characters that signal a break between words for
the completer routine. The default value of this variable is the
characters which break words for completion in Bash, i.e., `"
\t\n\"\\'`@$><=;|&{("'.
- Variable: char * rl_completer_word_break_characters
The list of characters that signal a break between words for
`rl_complete_internal ()'. The default list is the value of
`rl_basic_word_break_characters'.
- Variable: char * rl_special_prefixes
The list of characters that are word break characters, but should
be left in TEXT when it is passed to the completion function.
Programs can use this to help determine what kind of completing to
do. For instance, Bash sets this variable to "$@" so that it can
complete shell variables and hostnames.
- Variable: int rl_ignore_completion_duplicates
If non-zero, then disallow duplicates in the matches. Default is
1.
- Variable: int rl_filename_completion_desired
Non-zero means that the results of the matches are to be treated as
filenames. This is *always* zero on entry, and can only be changed
within a completion entry generator function. If it is set to a
non-zero value, directory names have a slash appended and Readline
attempts to quote completed filenames if they contain any embedded
word break characters.
- Variable: int rl_filename_quoting_desired
Non-zero means that the results of the matches are to be quoted
using double quotes (or an application-specific quoting mechanism)
if the completed filename contains any characters in
`rl_completer_word_break_chars'. This is *always* non-zero on
entry, and can only be changed within a completion entry generator
function.
- Variable: Function * rl_ignore_some_completions_function
This function, if defined, is called by the completer when real
filename completion is done, after all the matching names have
been generated. It is passed a `NULL' terminated array of matches.
The first element (`matches[0]') is the maximal substring common
to all matches. This function can re-arrange the list of matches
as required, but each element deleted from the array must be freed.
- Variable: char * rl_completer_quote_characters
List of characters which can be used to quote a substring of the
line. Completion occurs on the entire substring, and within the
substring `rl_completer_word_break_characters' are treated as any
other character, unless they also appear within this list.

File: readline.info, Node: A Short Completion Example, Prev: Completion Variables, Up: Custom Completers
A Short Completion Example
--------------------------
Here is a small application demonstrating the use of the GNU Readline
library. It is called `fileman', and the source code resides in
`examples/fileman.c'. This sample application provides completion of
command names, line editing features, and access to the history list.
/* fileman.c -- A tiny application which demonstrates how to use the
GNU Readline library. This application interactively allows users
to manipulate files and their modes. */
#include <stdio.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/errno.h>
#include <readline/readline.h>
#include <readline/history.h>
extern char *getwd ();
extern char *xmalloc ();
/* The names of functions that actually do the manipulation. */
int com_list (), com_view (), com_rename (), com_stat (), com_pwd ();
int com_delete (), com_help (), com_cd (), com_quit ();
/* A structure which contains information on the commands this program
can understand. */
typedef struct {
char *name; /* User printable name of the function. */
Function *func; /* Function to call to do the job. */
char *doc; /* Documentation for this function. */
} COMMAND;
COMMAND commands[] = {
{ "cd", com_cd, "Change to directory DIR" },
{ "delete", com_delete, "Delete FILE" },
{ "help", com_help, "Display this text" },
{ "?", com_help, "Synonym for `help'" },
{ "list", com_list, "List files in DIR" },
{ "ls", com_list, "Synonym for `list'" },
{ "pwd", com_pwd, "Print the current working directory" },
{ "quit", com_quit, "Quit using Fileman" },
{ "rename", com_rename, "Rename FILE to NEWNAME" },
{ "stat", com_stat, "Print out statistics on FILE" },
{ "view", com_view, "View the contents of FILE" },
{ (char *)NULL, (Function *)NULL, (char *)NULL }
};
/* Forward declarations. */
char *stripwhite ();
COMMAND *find_command ();
/* The name of this program, as taken from argv[0]. */
char *progname;
/* When non-zero, this global means the user is done using this program. */
int done;
char *
dupstr (s)
int s;
{
char *r;
r = xmalloc (strlen (s) + 1);
strcpy (r, s);
return (r);
}
main (argc, argv)
int argc;
char **argv;
{
char *line, *s;
progname = argv[0];
initialize_readline (); /* Bind our completer. */
/* Loop reading and executing lines until the user quits. */
for ( ; done == 0; )
{
line = readline ("FileMan: ");
if (!line)
break;
/* Remove leading and trailing whitespace from the line.
Then, if there is anything left, add it to the history list
and execute it. */
s = stripwhite (line);
if (*s)
{
add_history (s);
execute_line (s);
}
free (line);
}
exit (0);
}
/* Execute a command line. */
int
execute_line (line)
char *line;
{
register int i;
COMMAND *command;
char *word;
/* Isolate the command word. */
i = 0;
while (line[i] && whitespace (line[i]))
i++;
word = line + i;
while (line[i] && !whitespace (line[i]))
i++;
if (line[i])
line[i++] = '\0';
command = find_command (word);
if (!command)
{
fprintf (stderr, "%s: No such command for FileMan.\n", word);
return (-1);
}
/* Get argument to command, if any. */
while (whitespace (line[i]))
i++;
word = line + i;
/* Call the function. */
return ((*(command->func)) (word));
}
/* Look up NAME as the name of a command, and return a pointer to that
command. Return a NULL pointer if NAME isn't a command name. */
COMMAND *
find_command (name)
char *name;
{
register int i;
for (i = 0; commands[i].name; i++)
if (strcmp (name, commands[i].name) == 0)
return (&commands[i]);
return ((COMMAND *)NULL);
}
/* Strip whitespace from the start and end of STRING. Return a pointer
into STRING. */
char *
stripwhite (string)
char *string;
{
register char *s, *t;
for (s = string; whitespace (*s); s++)
;
if (*s == 0)
return (s);
t = s + strlen (s) - 1;
while (t > s && whitespace (*t))
t--;
*++t = '\0';
return s;
}
/* **************************************************************** */
/* */
/* Interface to Readline Completion */
/* */
/* **************************************************************** */
char *command_generator ();
char **fileman_completion ();
/* Tell the GNU Readline library how to complete. We want to try to complete
on command names if this is the first word in the line, or on filenames
if not. */
initialize_readline ()
{
/* Allow conditional parsing of the ~/.inputrc file. */
rl_readline_name = "FileMan";
/* Tell the completer that we want a crack first. */
rl_attempted_completion_function = (CPPFunction *)fileman_completion;
}
/* Attempt to complete on the contents of TEXT. START and END show the
region of TEXT that contains the word to complete. We can use the
entire line in case we want to do some simple parsing. Return the
array of matches, or NULL if there aren't any. */
char **
fileman_completion (text, start, end)
char *text;
int start, end;
{
char **matches;
matches = (char **)NULL;
/* If this word is at the start of the line, then it is a command
to complete. Otherwise it is the name of a file in the current
directory. */
if (start == 0)
matches = completion_matches (text, command_generator);
return (matches);
}
/* Generator function for command completion. STATE lets us know whether
to start from scratch; without any state (i.e. STATE == 0), then we
start at the top of the list. */
char *
command_generator (text, state)
char *text;
int state;
{
static int list_index, len;
char *name;
/* If this is a new word to complete, initialize now. This includes
saving the length of TEXT for efficiency, and initializing the index
variable to 0. */
if (!state)
{
list_index = 0;
len = strlen (text);
}
/* Return the next name which partially matches from the command list. */
while (name = commands[list_index].name)
{
list_index++;
if (strncmp (name, text, len) == 0)
return (dupstr(name));
}
/* If no names matched, then return NULL. */
return ((char *)NULL);
}
/* **************************************************************** */
/* */
/* FileMan Commands */
/* */
/* **************************************************************** */
/* String to pass to system (). This is for the LIST, VIEW and RENAME
commands. */
static char syscom[1024];
/* List the file(s) named in arg. */
com_list (arg)
char *arg;
{
if (!arg)
arg = "";
sprintf (syscom, "ls -FClg %s", arg);
return (system (syscom));
}
com_view (arg)
char *arg;
{
if (!valid_argument ("view", arg))
return 1;
sprintf (syscom, "more %s", arg);
return (system (syscom));
}
com_rename (arg)
char *arg;
{
too_dangerous ("rename");
return (1);
}
com_stat (arg)
char *arg;
{
struct stat finfo;
if (!valid_argument ("stat", arg))
return (1);
if (stat (arg, &finfo) == -1)
{
perror (arg);
return (1);
}
printf ("Statistics for `%s':\n", arg);
printf ("%s has %d link%s, and is %d byte%s in length.\n", arg,
finfo.st_nlink,
(finfo.st_nlink == 1) ? "" : "s",
finfo.st_size,
(finfo.st_size == 1) ? "" : "s");
printf ("Inode Last Change at: %s", ctime (&finfo.st_ctime));
printf (" Last access at: %s", ctime (&finfo.st_atime));
printf (" Last modified at: %s", ctime (&finfo.st_mtime));
return (0);
}
com_delete (arg)
char *arg;
{
too_dangerous ("delete");
return (1);
}
/* Print out help for ARG, or for all of the commands if ARG is
not present. */
com_help (arg)
char *arg;
{
register int i;
int printed = 0;
for (i = 0; commands[i].name; i++)
{
if (!*arg || (strcmp (arg, commands[i].name) == 0))
{
printf ("%s\t\t%s.\n", commands[i].name, commands[i].doc);
printed++;
}
}
if (!printed)
{
printf ("No commands match `%s'. Possibilties are:\n", arg);
for (i = 0; commands[i].name; i++)
{
/* Print in six columns. */
if (printed == 6)
{
printed = 0;
printf ("\n");
}
printf ("%s\t", commands[i].name);
printed++;
}
if (printed)
printf ("\n");
}
return (0);
}
/* Change to the directory ARG. */
com_cd (arg)
char *arg;
{
if (chdir (arg) == -1)
{
perror (arg);
return 1;
}
com_pwd ("");
return (0);
}
/* Print out the current working directory. */
com_pwd (ignore)
char *ignore;
{
char dir[1024], *s;
s = getwd (dir);
if (s == 0)
{
printf ("Error getting pwd: %s\n", dir);
return 1;
}
printf ("Current directory is %s\n", dir);
return 0;
}
/* The user wishes to quit using this program. Just set DONE non-zero. */
com_quit (arg)
char *arg;
{
done = 1;
return (0);
}
/* Function which tells you that you can't do this. */
too_dangerous (caller)
char *caller;
{
fprintf (stderr,
"%s: Too dangerous for me to distribute. Write it yourself.\n",
caller);
}
/* Return non-zero if ARG is a valid argument for CALLER, else print
an error message and return zero. */
int
valid_argument (caller, arg)
char *caller, *arg;
{
if (!arg || !*arg)
{
fprintf (stderr, "%s: Argument required.\n", caller);
return (0);
}
return (1);
}

File: readline.info, Node: Concept Index, Next: Function and Variable Index, Prev: Programming with GNU Readline, Up: Top
Concept Index
*************
* Menu:
* interaction, readline: Readline Interaction.
* Kill ring: Readline Killing Commands.
* Killing text: Readline Killing Commands.
* readline, function: Basic Behavior.
* Yanking text: Readline Killing Commands.

File: readline.info, Node: Function and Variable Index, Prev: Concept Index, Up: Top
Function and Variable Index
***************************
* Menu:
* $else: Conditional Init Constructs.
* $endif: Conditional Init Constructs.
* $if: Conditional Init Constructs.
* abort (C-g): Miscellaneous Commands.
* accept-line (Newline, Return): Commands For History.
* alphabetic: Utility Functions.
* backward-char (C-b): Commands For Moving.
* backward-delete-char (Rubout): Commands For Text.
* backward-kill-line (C-x Rubout): Commands For Killing.
* backward-kill-word (M-DEL): Commands For Killing.
* backward-word (M-b): Commands For Moving.
* beginning-of-history (M-<): Commands For History.
* beginning-of-line (C-a): Commands For Moving.
* bell-style: Readline Init Syntax.
* call-last-kbd-macro (C-x e): Keyboard Macros.
* capitalize-word (M-c): Commands For Text.
* clear-screen (C-l): Commands For Moving.
* comment-begin: Readline Init Syntax.
* complete (TAB): Commands For Completion.
* completion-query-items: Readline Init Syntax.
* completion_matches: Completion Functions.
* convert-meta: Readline Init Syntax.
* delete-char (C-d): Commands For Text.
* delete-horizontal-space (): Commands For Killing.
* digit-argument (M-0, M-1, ... M-): Numeric Arguments.
* digit_p: Utility Functions.
* digit_value: Utility Functions.
* ding: Utility Functions.
* do-uppercase-version (M-a, M-b, ...): Miscellaneous Commands.
* downcase-word (M-l): Commands For Text.
* dump-functions (): Miscellaneous Commands.
* editing-mode: Readline Init Syntax.
* end-kbd-macro (C-x )): Keyboard Macros.
* end-of-history (M->): Commands For History.
* end-of-line (C-e): Commands For Moving.
* expand-tilde: Readline Init Syntax.
* filename_completion_function: Completion Functions.
* forward-char (C-f): Commands For Moving.
* forward-search-history (C-s): Commands For History.
* forward-word (M-f): Commands For Moving.
* free_undo_list: Allowing Undoing.
* history-search-backward (): Commands For History.
* history-search-forward (): Commands For History.
* horizontal-scroll-mode: Readline Init Syntax.
* insert-completions (): Commands For Completion.
* keymap: Readline Init Syntax.
* kill-line (C-k): Commands For Killing.
* kill-whole-line (): Commands For Killing.
* kill-word (M-d): Commands For Killing.
* lowercase_p: Utility Functions.
* mark-modified-lines: Readline Init Syntax.
* meta-flag: Readline Init Syntax.
* next-history (C-n): Commands For History.
* non-incremental-forward-search-history (M-n): Commands For History.
* non-incremental-reverse-search-history (M-p): Commands For History.
* numeric: Utility Functions.
* output-meta: Readline Init Syntax.
* possible-completions (M-?): Commands For Completion.
* prefix-meta (ESC): Miscellaneous Commands.
* previous-history (C-p): Commands For History.
* quoted-insert (C-q, C-v): Commands For Text.
* re-read-init-file (C-x C-r): Miscellaneous Commands.
* readline: Basic Behavior.
* redraw-current-line (): Commands For Moving.
* reverse-search-history (C-r): Commands For History.
* revert-line (M-r): Miscellaneous Commands.
* rl_add_defun: Function Naming.
* rl_add_undo: Allowing Undoing.
* rl_attempted_completion_function: Completion Variables.
* rl_basic_word_break_characters: Completion Variables.
* rl_begin_undo_group: Allowing Undoing.
* rl_bind_key: Binding Keys.
* rl_bind_key_in_map: Binding Keys.
* rl_clear_message: Redisplay.
* rl_complete: How Completing Works.
* rl_complete: Completion Functions.
* rl_completer_quote_characters: Completion Variables.
* rl_completer_word_break_characters: Completion Variables.
* rl_complete_internal: Completion Functions.
* rl_completion_entry_function: Completion Variables.
* rl_completion_entry_function: How Completing Works.
* rl_completion_query_items: Completion Variables.
* rl_copy_keymap: Keymaps.
* rl_copy_text: Modifying Text.
* rl_delete_text: Modifying Text.
* rl_discard_keymap: Keymaps.
* rl_done: Function Writing.
* rl_do_undo: Allowing Undoing.
* rl_end: Function Writing.
* rl_end_undo_group: Allowing Undoing.
* rl_filename_completion_desired: Completion Variables.
* rl_filename_quoting_desired: Completion Variables.
* rl_forced_update_display: Redisplay.
* rl_function_of_keyseq: Associating Function Names and Bindings.
* rl_generic_bind: Binding Keys.
* rl_get_keymap: Keymaps.
* rl_get_keymap_by_name: Keymaps.
* rl_ignore_completion_duplicates: Completion Variables.
* rl_ignore_some_completions_function: Completion Variables.
* rl_insert_completions: Completion Functions.
* rl_insert_text: Modifying Text.
* rl_instream: Function Writing.
* rl_invoking_keyseqs: Associating Function Names and Bindings.
* rl_invoking_keyseqs_in_map: Associating Function Names and Bindings.
* rl_kill_text: Modifying Text.
* rl_line_buffer: Function Writing.
* rl_make_bare_keymap: Keymaps.
* rl_make_keymap: Keymaps.
* rl_mark: Function Writing.
* rl_message: Redisplay.
* rl_modifying: Allowing Undoing.
* rl_named_function: Associating Function Names and Bindings.
* rl_on_new_line: Redisplay.
* rl_outstream: Function Writing.
* rl_parse_and_bind: Binding Keys.
* rl_pending_input: Function Writing.
* rl_point: Function Writing.
* rl_possible_completions: Completion Functions.
* rl_prompt: Function Writing.
* rl_readline_name: Function Writing.
* rl_redisplay: Redisplay.
* rl_reset_line_state: Redisplay.
* rl_reset_terminal: Utility Functions.
* rl_set_keymap: Keymaps.
* rl_special_prefixes: Completion Variables.
* rl_startup_hook: Function Writing.
* rl_terminal_name: Function Writing.
* rl_unbind_key: Binding Keys.
* rl_unbind_key_in_map: Binding Keys.
* self-insert (a, b, A, 1, !, ...): Commands For Text.
* show-all-if-ambiguous: Readline Init Syntax.
* start-kbd-macro (C-x (): Keyboard Macros.
* tab-insert (M-TAB): Commands For Text.
* tilde-expand (M-~): Miscellaneous Commands.
* to_lower: Utility Functions.
* to_upper: Utility Functions.
* transpose-chars (C-t): Commands For Text.
* transpose-words (M-t): Commands For Text.
* undo (C-_, C-x C-u): Miscellaneous Commands.
* universal-argument (): Numeric Arguments.
* unix-line-discard (C-u): Commands For Killing.
* unix-word-rubout (C-w): Commands For Killing.
* upcase-word (M-u): Commands For Text.
* uppercase_p: Utility Functions.
* username_completion_function: Completion Functions.
* yank (C-y): Commands For Killing.
* yank-last-arg (M-., M-_): Commands For History.
* yank-nth-arg (M-C-y): Commands For History.
* yank-pop (M-y): Commands For Killing.

View File

@ -6,6 +6,15 @@
@synindex vr fn
@setchapternewpage odd
@ignore
last change: Thu Jul 21 16:02:40 EDT 1994
@end ignore
@set EDITION 2.0
@set VERSION 2.0
@set UPDATED 21 July 1994
@set UPDATE-MONTH July 1994
@ifinfo
This document describes the GNU Readline Library, a utility which aids
in the consistency of user interface across discrete programs that need
@ -35,13 +44,13 @@ except that this permission notice may be stated in a translation approved
by the Foundation.
@end ifinfo
@titlepage
@titlepage
@sp 10
@center @titlefont{GNU Readline Library}
@center Brian Fox
@center Free Software Foundation
@center Version 1.1
@center April 1991
@title GNU Readline Library
@subtitle Edition @value{EDITION}, for @code{Readline Library} Version @value{VERSION}.
@subtitle @value{UPDATE-MONTH}
@author Brian Fox, Free Software Foundation
@author Chet Ramey, Case Western Reserve University
@page
This document describes the GNU Readline Library, a utility which aids
@ -100,4 +109,3 @@ to provide a command line interface.
@contents
@bye

File diff suppressed because it is too large Load Diff

View File

@ -49,7 +49,7 @@ command line editing interface.
* Bindable Readline Commands:: A description of most of the Readline commands
available for binding
* Readline vi Mode:: A short description of how to make Readline
behave line the vi editor.
behave like the vi editor.
@end menu
@node Introduction and Notation
@ -164,6 +164,9 @@ operate on characters while meta keystrokes operate on words.
@node Readline Killing Commands
@subsection Readline Killing Commands
@cindex Killing text
@cindex Yanking text
@dfn{Killing} text means to delete the text from the line, but to save
it away for later use, usually by @dfn{yanking} (re-inserting)
it back into the line.
@ -177,6 +180,7 @@ that when you yank it back, you get it all. The kill
ring is not line specific; the text that you killed on a previously
typed line is available to be yanked back later, when you are typing
another line.
@cindex Kill ring
Here is the list of commands for killing text.
@ -236,7 +240,12 @@ keybindings installed by default,
it is possible that you would like to use a different set
of keybindings. You can customize programs that use Readline by putting
commands in an @dfn{init} file in your home directory. The name of this
@ifset BashFeatures
file is taken from the value of the shell variable @code{INPUTRC}. If
@end ifset
@ifclear BashFeatures
file is taken from the value of the environment variable @code{INPUTRC}. If
@end ifclear
that variable is unset, the default is @file{~/.inputrc}.
When a program which uses the Readline library starts up, the
@ -614,6 +623,11 @@ insert the @var{n}th word from the previous command (the words
in the previous command begin with word 0). A negative argument
inserts the @var{n}th word from the end of the previous command.
@item yank-last-arg (M-., M-_)
Insert last argument to the previous command (the last word on the
previous line). With an
argument, behave exactly like @code{yank-nth-arg}.
@end ftable
@node Commands For Text
@ -730,7 +744,7 @@ bound to a key.
@ftable @code
@item complete (TAB)
Attempt to do completion on the text before the cursor. This is
implementation defined. Generally, if you are typing a filename
application-specific. Generally, if you are typing a filename
argument, you can do filename completion; if you are typing a command,
you can do command completion, if you are typing in a symbol to GDB, you
can do symbol name completion, if you are typing in a variable to Bash,
@ -818,11 +832,7 @@ word expansions.
Perform history expansion on the current line.
@item insert-last-argument (M-., M-_)
Insert the last argument to the previous command (the last word on
the previous line). With an argument @var{n},
insert the @var{n}th word from the previous command (the words
in the previous command begin with word 0). A negative argument
inserts the @var{n}th word from the end of the previous command.
A synonym for @code{yank-last-arg}.
@item operate-and-get-next (C-o)
Accept the current line for execution and fetch the next line

View File

@ -24,7 +24,7 @@
#include <stdio.h>
#endif /* !BUFSIZ */
#include <readline/readline.h>
#include "readline.h"
/* An array of function pointers, one for each possible key.
If the type byte is ISKMAP, then the pointer is the address of
@ -377,7 +377,7 @@ KEYMAP_ENTRY_ARRAY emacs_meta_keymap = {
{ ISFUNC, (Function *)0x0 }, /* Meta-+ */
{ ISFUNC, (Function *)0x0 }, /* Meta-, */
{ ISFUNC, rl_digit_argument }, /* Meta-- */
{ ISFUNC, (Function *)0x0 }, /* Meta-. */
{ ISFUNC, rl_yank_last_arg}, /* Meta-. */
{ ISFUNC, (Function *)0x0 }, /* Meta-/ */
/* Regular digits. */
@ -430,12 +430,12 @@ KEYMAP_ENTRY_ARRAY emacs_meta_keymap = {
{ ISFUNC, rl_do_lowercase_version }, /* Meta-Z */
/* Some more punctuation. */
{ ISFUNC, rl_arrow_keys }, /* Meta-[ */
{ ISFUNC, (Function *)0x0 }, /* Meta-[ */ /* was rl_arrow_keys */
{ ISFUNC, rl_delete_horizontal_space }, /* Meta-\ */
{ ISFUNC, (Function *)0x0 }, /* Meta-] */
{ ISFUNC, (Function *)0x0 }, /* Meta-^ */
{ ISFUNC, (Function *)0x0 }, /* Meta-_ */
{ ISFUNC, (Function *)0x0 }, /* Meta-` */
{ ISFUNC, (Function *)0x0 }, /* Meta-] */
{ ISFUNC, (Function *)0x0 }, /* Meta-^ */
{ ISFUNC, rl_yank_last_arg }, /* Meta-_ */
{ ISFUNC, (Function *)0x0 }, /* Meta-` */
/* Lowercase alphabet. */
{ ISFUNC, (Function *)0x0 }, /* Meta-a */
@ -452,7 +452,7 @@ KEYMAP_ENTRY_ARRAY emacs_meta_keymap = {
{ ISFUNC, rl_downcase_word }, /* Meta-l */
{ ISFUNC, (Function *)0x0 }, /* Meta-m */
{ ISFUNC, rl_noninc_forward_search }, /* Meta-n */
{ ISFUNC, rl_arrow_keys }, /* Meta-o */
{ ISFUNC, (Function *)0x0 }, /* Meta-o */ /* was rl_arrow_keys */
{ ISFUNC, rl_noninc_reverse_search }, /* Meta-p */
{ ISFUNC, (Function *)0x0 }, /* Meta-q */
{ ISFUNC, rl_revert_line }, /* Meta-r */

View File

@ -19,6 +19,12 @@ $if TERM=xterm
"\e[C": forward-char
"\e[D": backward-char
# alternate arrow key prefix
"\eOA": previous-history
"\eOB": next-history
"\eOC": forward-char
"\eOD": backward-char
# Under Xterm in Bash, we bind local Function keys to do something useful.
$if Bash
"\e[11~": "Function Key 1"
@ -53,6 +59,7 @@ $endif
$if Ftp
"\C-xg": "get \M-?"
"\C-xt": "put \M-?"
"\M-.": yank-last-arg
$endif
" ": self-insert

View File

@ -2,7 +2,7 @@
#
EXECUTABLES = fileman
CFLAGS = -g -I../..
CFLAGS = -g -I..
LDFLAGS = -g -L..
fileman: fileman.o

View File

@ -3,13 +3,17 @@
to manipulate files and their modes. */
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/errno.h>
#include <readline/readline.h>
#include <readline/history.h>
extern char *getwd ();
extern char *xmalloc ();
/* The names of functions that actually do the manipulation. */
int com_list (), com_view (), com_rename (), com_stat (), com_pwd ();
int com_delete (), com_help (), com_cd (), com_quit ();
@ -38,66 +42,79 @@ COMMAND commands[] = {
{ (char *)NULL, (Function *)NULL, (char *)NULL }
};
/* Forward declarations. */
char *stripwhite ();
COMMAND *find_command ();
/* The name of this program, as taken from argv[0]. */
char *progname;
/* When non-zero, this global means the user is done using this program. */
int done = 0;
int done;
char *
dupstr (s)
int s;
{
char *r;
r = xmalloc (strlen (s) + 1);
strcpy (r, s);
return (r);
}
main (argc, argv)
int argc;
char **argv;
{
char *line, *s;
progname = argv[0];
initialize_readline (); /* Bind our completer. */
/* Loop reading and executing lines until the user quits. */
while (!done)
for ( ; done == 0; )
{
char *line;
line = readline ("FileMan: ");
if (!line)
{
done = 1; /* Encountered EOF at top level. */
}
else
{
/* Remove leading and trailing whitespace from the line.
Then, if there is anything left, add it to the history list
and execute it. */
stripwhite (line);
break;
if (*line)
{
add_history (line);
execute_line (line);
}
}
/* Remove leading and trailing whitespace from the line.
Then, if there is anything left, add it to the history list
and execute it. */
s = stripwhite (line);
if (line)
free (line);
if (*s)
{
add_history (s);
execute_line (s);
}
free (line);
}
exit (0);
}
/* Execute a command line. */
int
execute_line (line)
char *line;
{
register int i;
COMMAND *find_command (), *command;
COMMAND *command;
char *word;
/* Isolate the command word. */
i = 0;
while (line[i] && whitespace (line[i]))
i++;
word = line + i;
while (line[i] && !whitespace (line[i]))
i++;
word = line;
if (line[i])
line[i++] = '\0';
@ -106,7 +123,7 @@ execute_line (line)
if (!command)
{
fprintf (stderr, "%s: No such command for FileMan.\n", word);
return;
return (-1);
}
/* Get argument to command, if any. */
@ -116,7 +133,7 @@ execute_line (line)
word = line + i;
/* Call the function. */
(*(command->func)) (word);
return ((*(command->func)) (word));
}
/* Look up NAME as the name of a command, and return a pointer to that
@ -134,24 +151,26 @@ find_command (name)
return ((COMMAND *)NULL);
}
/* Strip whitespace from the start and end of STRING. */
/* Strip whitespace from the start and end of STRING. Return a pointer
into STRING. */
char *
stripwhite (string)
char *string;
{
register int i = 0;
register char *s, *t;
while (whitespace (string[i]))
i++;
for (s = string; whitespace (*s); s++)
;
if (*s == 0)
return (s);
if (i)
strcpy (string, string + i);
t = s + strlen (s) - 1;
while (t > s && whitespace (*t))
t--;
*++t = '\0';
i = strlen (string) - 1;
while (i > 0 && whitespace (string[i]))
i--;
string[++i] = '\0';
return s;
}
/* **************************************************************** */
@ -160,18 +179,19 @@ stripwhite (string)
/* */
/* **************************************************************** */
char *command_generator ();
char **fileman_completion ();
/* Tell the GNU Readline library how to complete. We want to try to complete
on command names if this is the first word in the line, or on filenames
if not. */
initialize_readline ()
{
char **fileman_completion ();
/* Allow conditional parsing of the ~/.inputrc file. */
rl_readline_name = "FileMan";
/* Tell the completer that we want a crack first. */
rl_attempted_completion_function = (Function *)fileman_completion;
rl_attempted_completion_function = (CPPFunction *)fileman_completion;
}
/* Attempt to complete on the contents of TEXT. START and END show the
@ -184,7 +204,6 @@ fileman_completion (text, start, end)
int start, end;
{
char **matches;
char *command_generator ();
matches = (char **)NULL;
@ -223,7 +242,7 @@ command_generator (text, state)
list_index++;
if (strncmp (name, text, len) == 0)
return (name);
return (dupstr(name));
}
/* If no names matched, then return NULL. */
@ -245,26 +264,27 @@ com_list (arg)
char *arg;
{
if (!arg)
arg = "*";
arg = "";
sprintf (syscom, "ls -FClg %s", arg);
system (syscom);
return (system (syscom));
}
com_view (arg)
char *arg;
{
if (!valid_argument ("view", arg))
return;
return 1;
sprintf (syscom, "cat %s | more", arg);
system (syscom);
sprintf (syscom, "more %s", arg);
return (system (syscom));
}
com_rename (arg)
char *arg;
{
too_dangerous ("rename");
return (1);
}
com_stat (arg)
@ -273,27 +293,32 @@ com_stat (arg)
struct stat finfo;
if (!valid_argument ("stat", arg))
return;
return (1);
if (stat (arg, &finfo) == -1)
{
perror (arg);
return;
return (1);
}
printf ("Statistics for `%s':\n", arg);
printf ("%s has %d link%s, and is %d bytes in length.\n", arg,
finfo.st_nlink, (finfo.st_nlink == 1) ? "" : "s", finfo.st_size);
printf (" Created on: %s", ctime (&finfo.st_ctime));
printf (" Last access at: %s", ctime (&finfo.st_atime));
printf ("Last modified at: %s", ctime (&finfo.st_mtime));
printf ("%s has %d link%s, and is %d byte%s in length.\n", arg,
finfo.st_nlink,
(finfo.st_nlink == 1) ? "" : "s",
finfo.st_size,
(finfo.st_size == 1) ? "" : "s");
printf ("Inode Last Change at: %s", ctime (&finfo.st_ctime));
printf (" Last access at: %s", ctime (&finfo.st_atime));
printf (" Last modified at: %s", ctime (&finfo.st_mtime));
return (0);
}
com_delete (arg)
char *arg;
{
too_dangerous ("delete");
return (1);
}
/* Print out help for ARG, or for all of the commands if ARG is
@ -307,10 +332,10 @@ com_help (arg)
for (i = 0; commands[i].name; i++)
{
if (!*arg || (strcmp (arg, commands[i].name) == 0))
{
printf ("%s\t\t%s.\n", commands[i].name, commands[i].doc);
printed++;
}
{
printf ("%s\t\t%s.\n", commands[i].name, commands[i].doc);
printed++;
}
}
if (!printed)
@ -318,21 +343,22 @@ com_help (arg)
printf ("No commands match `%s'. Possibilties are:\n", arg);
for (i = 0; commands[i].name; i++)
{
/* Print in six columns. */
if (printed == 6)
{
printed = 0;
printf ("\n");
}
{
/* Print in six columns. */
if (printed == 6)
{
printed = 0;
printf ("\n");
}
printf ("%s\t", commands[i].name);
printed++;
}
printf ("%s\t", commands[i].name);
printed++;
}
if (printed)
printf ("\n");
printf ("\n");
}
return (0);
}
/* Change to the directory ARG. */
@ -340,20 +366,30 @@ com_cd (arg)
char *arg;
{
if (chdir (arg) == -1)
perror (arg);
{
perror (arg);
return 1;
}
com_pwd ("");
return (0);
}
/* Print out the current working directory. */
com_pwd (ignore)
char *ignore;
{
char dir[1024];
char dir[1024], *s;
(void) getwd (dir);
s = getwd (dir);
if (s == 0)
{
printf ("Error getting pwd: %s\n", dir);
return 1;
}
printf ("Current directory is %s\n", dir);
return 0;
}
/* The user wishes to quit using this program. Just set DONE non-zero. */
@ -361,6 +397,7 @@ com_quit (arg)
char *arg;
{
done = 1;
return (0);
}
/* Function which tells you that you can't do this. */
@ -368,8 +405,8 @@ too_dangerous (caller)
char *caller;
{
fprintf (stderr,
"%s: Too dangerous for me to distribute. Write it yourself.\n",
caller);
"%s: Too dangerous for me to distribute. Write it yourself.\n",
caller);
}
/* Return non-zero if ARG is a valid argument for CALLER, else print
@ -386,10 +423,3 @@ valid_argument (caller, arg)
return (1);
}
/*
* Local variables:
* compile-command: "cc -g -I../.. -L.. -o fileman fileman.c -lreadline -ltermcap"
* end:
*/

View File

@ -0,0 +1,82 @@
main ()
{
char line[1024], *t;
int len, done = 0;
line[0] = 0;
using_history ();
while (!done)
{
printf ("history$ ");
fflush (stdout);
t = fgets (line, sizeof (line) - 1, stdin);
if (t && *t)
{
len = strlen (t);
if (t[len - 1] == '\n')
t[len - 1] = '\0';
}
if (!t)
strcpy (line, "quit");
if (line[0])
{
char *expansion;
int result;
using_history ();
result = history_expand (line, &expansion);
if (result)
fprintf (stderr, "%s\n", expansion);
if (result < 0 || result == 2)
{
free (expansion);
continue;
}
add_history (expansion);
strncpy (line, expansion, sizeof (line) - 1);
free (expansion);
}
if (strcmp (line, "quit") == 0)
done = 1;
else if (strcmp (line, "save") == 0)
write_history ("history_file");
else if (strcmp (line, "read") == 0)
read_history ("history_file");
else if (strcmp (line, "list") == 0)
{
register HIST_ENTRY **the_list;
register int i;
the_list = history_list ();
if (the_list)
for (i = 0; the_list[i]; i++)
printf ("%d: %s\n", i + history_base, the_list[i]->line);
}
else if (strncmp (line, "delete", 6) == 0)
{
int which;
if ((sscanf (line + 6, "%d", &which)) == 1)
{
HIST_ENTRY *entry = remove_history (which);
if (!entry)
fprintf (stderr, "No such entry %d\n", which);
else
{
free (entry->line);
free (entry);
}
}
else
{
fprintf (stderr, "non-numeric arg given to `delete'\n");
}
}
}
}

View File

@ -15,11 +15,11 @@ static char *line_read = (char *)NULL;
/* Read a string, and return a pointer to it. Returns NULL on EOF. */
char *
do_gets ()
rl_gets ()
{
/* If the buffer has already been allocated, return the memory
to the free pool. */
if (line_read != (char *)NULL)
if (line_read)
{
free (line_read);
line_read = (char *)NULL;
@ -35,7 +35,6 @@ do_gets ()
return (line_read);
}
/* **************************************************************** */
/* */
/* Writing a Function to be Called by Readline. */
@ -93,4 +92,3 @@ invert_case_line (count, key)
rl_point = end - direction;
}

View File

@ -19,6 +19,7 @@
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. */
#define READLINE_LIBRARY
#if defined (STATIC_MALLOC)
static char *xmalloc (), *xrealloc ();
@ -37,7 +38,9 @@ extern char *xmalloc (), *xrealloc ();
#endif /* HAVE_STDLIB_H */
#include "rlconf.h"
#include <readline/readline.h>
#include "readline.h"
static int qsort_string_compare ();
FUNMAP **funmap = (FUNMAP **)NULL;
static int funmap_size = 0;
@ -100,12 +103,14 @@ static FUNMAP default_funmap[] = {
{ "tilde-expand", rl_tilde_expand },
{ "transpose-chars", rl_transpose_chars },
{ "transpose-words", rl_transpose_words },
{ "tty-status", rl_tty_status },
{ "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-last-arg", rl_yank_last_arg },
{ "yank-nth-arg", rl_yank_nth_arg },
{ "yank-pop", rl_yank_pop },
@ -150,7 +155,6 @@ static FUNMAP default_funmap[] = {
{ "vi-tilde-expand", rl_vi_tilde_expand },
{ "vi-yank-arg", rl_vi_yank_arg },
{ "vi-yank-to", rl_vi_yank_to },
#endif /* VI_MODE */
{(char *)NULL, (Function *)NULL }
@ -193,19 +197,6 @@ rl_initialize_funmap ()
funmap_program_specific_entry_start = i;
}
/* Stupid comparison routine for qsort () ing strings. */
static int
qsort_string_compare (s1, s2)
register char **s1, **s2;
{
int r;
r = **s1 - **s2;
if (r == 0)
r = strcmp (*s1, *s2);
return r;
}
/* 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. */
@ -239,6 +230,19 @@ rl_funmap_names ()
return (result);
}
/* Stupid comparison routine for qsort () ing strings. */
static int
qsort_string_compare (s1, s2)
register char **s1, **s2;
{
int r;
r = **s1 - **s2;
if (r == 0)
r = strcmp (*s1, *s2);
return r;
}
/* Things that mean `Control'. */
char *possible_control_prefixes[] = {
"Control-", "C-", "CTRL-", (char *)NULL

View File

@ -23,6 +23,11 @@
/* The goal is to make the implementation transparent, so that you
don't have to know what data types are used, just what functions
you can call. I think I have done that. */
#define READLINE_LIBRARY
#if defined (HAVE_CONFIG_H)
# include "config.h"
#endif
#include <stdio.h>
#include <sys/types.h>
@ -50,7 +55,7 @@ extern int errno;
#endif /* !errno */
#include "memalloc.h"
#include <readline/history.h>
#include "history.h"
#if defined (STATIC_MALLOC)
static char *xmalloc (), *xrealloc ();
@ -72,8 +77,8 @@ extern char *strcpy ();
#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
#endif
#ifndef digit
#define digit(c) ((c) >= '0' && (c) <= '9')
#ifndef digit_p
#define digit_p(c) ((c) >= '0' && (c) <= '9')
#endif
#ifndef digit_value
@ -117,7 +122,7 @@ 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. */
int history_stifled = 0;
static int history_stifled = 0;
/* If HISTORY_STIFLED is non-zero, then this is the maximum number of
entries to remember. */
@ -168,6 +173,9 @@ history_get_history_state ()
state->offset = history_offset;
state->length = history_length;
state->size = history_size;
state->flags = 0;
if (history_stifled)
state->flags |= HS_STIFLED;
return (state);
}
@ -181,6 +189,8 @@ history_set_history_state (state)
history_offset = state->offset;
history_length = state->length;
history_size = state->size;
if (state->flags & HS_STIFLED)
history_stifled = 1;
}
/* Begin a session in which the history functions might be used. This
@ -490,6 +500,12 @@ unstifle_history ()
return (result);
}
int
history_is_stifled ()
{
return (history_stifled);
}
/* Return the string that should be used in the place of this
filename. This only matters when you don't specify the
filename to read_history (), or write_history (). */
@ -664,7 +680,7 @@ history_truncate_file (fname, lines)
/* Write only if there are more lines in the file than we want to
truncate to. */
if (i && ((file = open (filename, O_WRONLY, 0666)) != -1))
if (i && ((file = open (filename, O_WRONLY|O_TRUNC, 0666)) != -1))
{
write (file, buffer + i, finfo.st_size - i);
close (file);
@ -922,10 +938,10 @@ get_history_event (string, caller_index, delimiting_quote)
i++;
}
if (digit (string[i]))
if (digit_p (string[i]))
{
/* Get the extent of the digits and compute the value. */
for (which = 0; digit (string[i]); i++)
for (which = 0; digit_p (string[i]); i++)
which = (which * 10) + digit_value (string[i]);
*caller_index = i;
@ -1067,40 +1083,45 @@ quote_breaks (s)
#endif /* SHELL */
static char *
hist_error (ret, s, start, current, errtype)
char *ret, *s;
hist_error(s, start, current, errtype)
char *s;
int start, current, errtype;
{
char *temp, *emsg;
int ll;
int ll, elen;
ll = 1 + (current - start);
temp = xmalloc (1 + ll);
strncpy (temp, s + start, ll);
temp[ll] = 0;
ll = current - start;
switch (errtype)
{
case EVENT_NOT_FOUND:
emsg = "event not found";
elen = 15;
break;
case BAD_WORD_SPEC:
emsg = "bad word specifier";
elen = 18;
break;
case SUBST_FAILED:
emsg = "substitution failed";
elen = 19;
break;
case BAD_MODIFIER:
emsg = "unrecognized history modifier";
elen = 29;
break;
default:
emsg = "unknown expansion error";
elen = 23;
break;
}
sprintf (ret, "%s: %s", temp, emsg);
free (temp);
return ret;
temp = xmalloc (ll + elen + 3);
strncpy (temp, s + start, ll);
temp[ll] = ':';
temp[ll + 1] = ' ';
strcpy (temp + ll + 2, emsg);
return (temp);
}
/* Get a history substitution string from STR starting at *IPTR
@ -1237,8 +1258,8 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
if (!event)
{
hist_error (result, string, start, i, EVENT_NOT_FOUND);
*ret_string = result;
*ret_string = hist_error (string, start, i, EVENT_NOT_FOUND);
free (result);
return (-1);
}
@ -1251,8 +1272,8 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
we complain. */
if (word_spec == (char *)&error_pointer)
{
hist_error (result, string, starting_index, i, BAD_WORD_SPEC);
*ret_string = result;
*ret_string = hist_error (string, starting_index, i, BAD_WORD_SPEC);
free (result);
return (-1);
}
@ -1283,8 +1304,8 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
switch (c)
{
default:
hist_error (result, string, i+1, i+2, BAD_MODIFIER);
*ret_string = result;
*ret_string = hist_error (string, i+1, i+2, BAD_MODIFIER);
free (result);
free (temp);
return -1;
@ -1389,8 +1410,8 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
/* If there is no lhs, the substitution can't succeed. */
if (subst_lhs_len == 0)
{
hist_error (result, string, starting_index, i, SUBST_FAILED);
*ret_string = result;
*ret_string = hist_error (string, starting_index, i, SUBST_FAILED);
free (result);
free (temp);
return -1;
}
@ -1411,8 +1432,8 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
/* Ignore impossible cases. */
if (subst_lhs_len > l_temp)
{
hist_error (result, string, starting_index, i, SUBST_FAILED);
*ret_string = result;
*ret_string = hist_error (string, starting_index, i, SUBST_FAILED);
free (result);
free (temp);
return (-1);
}
@ -1455,8 +1476,8 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
if (failed == 0)
continue; /* don't want to increment i */
hist_error (result, string, starting_index, i, SUBST_FAILED);
*ret_string = result;
*ret_string = hist_error (string, starting_index, i, SUBST_FAILED);
free (result);
free (temp);
return (-1);
}
@ -1486,7 +1507,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
n = strlen (temp);
if (n > result_len)
result = xrealloc (result, n + 1);
result = xrealloc (result, n + 2);
strcpy (result, temp);
free (temp);
@ -1513,8 +1534,12 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
{ \
int sl = strlen (s); \
j += sl; \
while (j >= result_len) \
result = xrealloc (result, result_len += 128); \
if (j >= result_len) \
{ \
while (j >= result_len) \
result_len += 128; \
result = xrealloc (result, result_len); \
} \
strcpy (result + j - sl, s); \
} \
while (0)
@ -1522,7 +1547,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
#define ADD_CHAR(c) \
do \
{ \
if (j >= result_len) \
if (j >= result_len - 1) \
result = xrealloc (result, result_len += 64); \
result[j++] = c; \
result[j] = '\0'; \
@ -1545,6 +1570,14 @@ history_expand (hstring, output)
/* Used when adding the string. */
char *temp;
/* Setting the history expansion character to 0 inhibits all
history expansion. */
if (history_expansion_char == 0)
{
*output = savestring (hstring);
return (0);
}
/* Prepare the buffer for printing error messages. */
result = xmalloc (result_len = 256);
result[0] = '\0';
@ -1679,7 +1712,7 @@ history_expand (hstring, output)
break;
}
#ifdef NO_BANG_HASH_MODIFIERS
#if defined (NO_BANG_HASH_MODIFIERS)
/* There is something that is listed as a `word specifier' in csh
documentation which means `the expanded text to this point'.
That is not a word specifier, it is an event specifier. If we
@ -1790,11 +1823,13 @@ get_history_word_specifier (spec, from, caller_index)
/* Try to get FIRST and LAST figured out. */
if (spec[i] == '-' || spec[i] == '^')
if (spec[i] == '-')
first = 0;
else if (spec[i] == '^')
first = 1;
else if (digit (spec[i]) && expecting_word_spec)
else if (digit_p (spec[i]) && expecting_word_spec)
{
for (first = 0; digit (spec[i]); i++)
for (first = 0; digit_p (spec[i]); i++)
first = (first * 10) + digit_value (spec[i]);
}
else
@ -1811,9 +1846,9 @@ get_history_word_specifier (spec, from, caller_index)
{
i++;
if (digit (spec[i]))
if (digit_p (spec[i]))
{
for (last = 0; digit (spec[i]); i++)
for (last = 0; digit_p (spec[i]); i++)
last = (last * 10) + digit_value (spec[i]);
}
else if (spec[i] == '$')

View File

@ -0,0 +1,180 @@
/* History.h -- the names of functions that you can call in history. */
/* The structure used to store a history entry. */
typedef struct _hist_entry {
char *line;
char *data;
} HIST_ENTRY;
/* A structure used to pass the current state of the history stuff around. */
typedef struct _hist_state {
HIST_ENTRY **entries; /* Pointer to the entries themselves. */
int offset; /* The location pointer within this array. */
int length; /* Number of elements within this array. */
int size; /* Number of slots allocated to this array. */
int flags;
} HISTORY_STATE;
/* Flag values for the `flags' member of HISTORY_STATE. */
#define HS_STIFLED 0x01
/* Initialization and state management. */
/* Begin a session in which the history functions might be used. This
just initializes the interactive variables. */
extern void using_history ();
/* Return the current HISTORY_STATE of the history. */
extern HISTORY_STATE *history_get_history_state ();
/* Set the state of the current history array to STATE. */
extern void history_set_history_state ();
/* Manage the history list. */
/* Place STRING at the end of the history list.
The associated data field (if any) is set to NULL. */
extern void add_history ();
/* A reasonably useless function, only here for completeness. WHICH
is the magic number that tells us which element to delete. The
elements are numbered from 0. */
extern HIST_ENTRY *remove_history ();
/* Make the history entry at WHICH have LINE and DATA. This returns
the old entry so you can dispose of the data. In the case of an
invalid WHICH, a NULL pointer is returned. */
extern HIST_ENTRY *replace_history_entry ();
/* Stifle the history list, remembering only MAX number of entries. */
extern void stifle_history ();
/* Stop stifling the history. This returns the previous amount the
history was stifled by. The value is positive if the history was
stifled, negative if it wasn't. */
extern int unstifle_history ();
/* Return 1 if the history is stifled, 0 if it is not. */
extern int history_is_stifled ();
/* Information about the history list. */
/* Return a NULL terminated array of HIST_ENTRY which is the current input
history. Element 0 of this list is the beginning of time. If there
is no history, return NULL. */
extern HIST_ENTRY **history_list ();
/* Returns the number which says what history element we are now
looking at. */
extern int where_history ();
/* Return the history entry at the current position, as determined by
history_offset. If there is no entry there, return a NULL pointer. */
HIST_ENTRY *current_history ();
/* Return the history entry which is logically at OFFSET in the history
array. OFFSET is relative to history_base. */
extern HIST_ENTRY *history_get ();
/* Return the number of bytes that the primary history entries are using.
This just adds up the lengths of the_history->lines. */
extern int history_total_bytes ();
/* Moving around the history list. */
/* Set the position in the history list to POS. */
int history_set_pos ();
/* Back up history_offset to the previous history entry, and return
a pointer to that entry. If there is no previous entry, return
a NULL pointer. */
extern HIST_ENTRY *previous_history ();
/* Move history_offset forward to the next item in the input_history,
and return the a pointer to that entry. If there is no next entry,
return a NULL pointer. */
extern HIST_ENTRY *next_history ();
/* Searching the history list. */
/* 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. */
extern int history_search ();
extern int history_search_prefix ();
/* Search the history for @var{string}, starting at history_offset.
The search is anchored: matching lines must begin with string. */
/* Search for STRING in the history list, starting at POS, an
absolute index into the list. DIR, if negative, says to search
backwards from POS, else forwards.
Returns the absolute index of the history element where STRING
was found, or -1 otherwise. */
extern int history_search_pos ();
/* Managing the history file. */
/* 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. */
extern int read_history ();
/* 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. */
extern int read_history_range ();
/* Write the current history to FILENAME. If FILENAME is NULL,
then write the history list to ~/.history. Values returned
are as in read_history (). */
extern int write_history ();
/* 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 ();
/* Truncate the history file, leaving only the last NLINES lines. */
extern int history_truncate_file ();
/* History expansion. */
/* Expand the string STRING, placing the result into OUTPUT, a pointer
to a string. Returns:
0) If no expansions took place (or, if the only change in
the text was the de-slashifying of the history expansion
character)
1) If expansions did take place
-1) If there was an error in expansion.
2) If the returned line should just be printed.
If an error ocurred in expansion, then OUTPUT contains a descriptive
error message. */
extern int history_expand ();
/* Extract a string segment consisting of the FIRST through LAST
arguments present in STRING. Arguments are broken up as in
the shell. */
extern char *history_arg_extract ();
/* Return the text of the history event beginning at the current
offset into STRING. */
extern char *get_history_event ();
/* Return an array of tokens, much as the shell might. The tokens are
parsed out of STRING. */
extern char **history_tokenize ();
/* Exported history variables. */
extern int history_base;
extern int history_length;
extern int max_input_history;
extern char history_expansion_char;
extern char history_subst_char;
extern char history_comment_char;
extern char *history_no_expand_chars;

View File

@ -24,12 +24,17 @@
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. */
#define READLINE_LIBRARY
#include <stdio.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "memalloc.h"
#include <readline/readline.h>
#include <readline/history.h>
#include "readline.h"
#include "history.h"
#define STREQ(a, b) (((a)[0] == (b)[0]) && (strcmp ((a), (b)) == 0))
#define STREQN(a, b, n) (((a)[0] == (b)[0]) && (strncmp ((a), (b), (n)) == 0))
@ -175,6 +180,7 @@ rl_search_history (direction, invoking_key)
search_string = xmalloc (search_string_size = 128);
*search_string = '\0';
search_string_index = 0;
prev_line_found = (char *)0; /* XXX */
/* Normalize DIRECTION into 1 or -1. */
direction = (direction >= 0) ? 1 : -1;
@ -240,10 +246,10 @@ rl_search_history (direction, invoking_key)
rl_clear_message ();
free (allocated_line);
free (lines);
return;
return 0;
default:
if (c < 32 || c > 126)
if (CTRL_CHAR (c) || META_CHAR (c) || c == RUBOUT)
{
rl_execute_next (c);
done = 1;
@ -277,7 +283,7 @@ rl_search_history (direction, invoking_key)
break;
}
else
line_index += reverse ? -1 : 1;
line_index += direction;
}
if (found)
break;
@ -291,7 +297,7 @@ rl_search_history (direction, invoking_key)
i += direction;
/* At limit for direction? */
if ((reverse && i < 0) || (!reverse && i == hlen))
if (reverse ? (i < 0) : (i == hlen))
{
failed++;
break;
@ -319,7 +325,7 @@ rl_search_history (direction, invoking_key)
/* We cannot find the search string. Ding the bell. */
ding ();
i = last_found_line;
break;
continue; /* XXX - was break */
}
/* We have found the search string. Just display it. But don't

View File

@ -18,6 +18,7 @@
You should have received a copy of the GNU General Public License
along with Readline; see the file COPYING. If not, write to the Free
Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define READLINE_LIBRARY
#if defined (HAVE_STDLIB_H)
# include <stdlib.h>
@ -26,10 +27,10 @@
#endif /* HAVE_STDLIB_H */
#include "rlconf.h"
#include <readline/keymaps.h>
#include "keymaps.h"
#include "emacs_keymap.c"
#ifdef VI_MODE
#if defined (VI_MODE)
#include "vi_keymap.c"
#endif

View File

@ -0,0 +1,95 @@
/* keymaps.h -- Manipulation of readline keymaps. */
/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
This file is part of the GNU Readline Library, a library for
reading lines of text with interactive input and history editing.
The GNU Readline Library is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 1, or
(at your option) any later version.
The GNU Readline Library is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
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. */
#ifndef _KEYMAPS_H_
#define _KEYMAPS_H_
#if defined (READLINE_LIBRARY)
# include "chardefs.h"
#else
# include <readline/chardefs.h>
#endif
#if !defined (__FUNCTION_DEF)
# define __FUNCTION_DEF
typedef int Function ();
typedef void VFunction ();
typedef char *CPFunction ();
typedef char **CPPFunction ();
#endif
/* A keymap contains one entry for each key in the ASCII set.
Each entry consists of a type and a pointer.
POINTER is the address of a function to run, or the
address of a keymap to indirect through.
TYPE says which kind of thing POINTER is. */
typedef struct _keymap_entry {
char type;
Function *function;
} KEYMAP_ENTRY;
/* This must be large enough to hold bindings for all of the characters
in a desired character set (e.g, 128 for ASCII, 256 for ISO Latin-x,
and so on). */
#define KEYMAP_SIZE 256
/* I wanted to make the above structure contain a union of:
union { Function *function; struct _keymap_entry *keymap; } value;
but this made it impossible for me to create a static array.
Maybe I need C lessons. */
typedef KEYMAP_ENTRY KEYMAP_ENTRY_ARRAY[KEYMAP_SIZE];
typedef KEYMAP_ENTRY *Keymap;
/* The values that TYPE can have in a keymap entry. */
#define ISFUNC 0
#define ISKMAP 1
#define ISMACR 2
extern KEYMAP_ENTRY_ARRAY emacs_standard_keymap, emacs_meta_keymap, emacs_ctlx_keymap;
extern KEYMAP_ENTRY_ARRAY vi_insertion_keymap, vi_movement_keymap;
/* Return a new, empty keymap.
Free it with free() when you are done. */
extern Keymap rl_make_bare_keymap ();
/* Return a new keymap which is a copy of MAP. */
extern Keymap rl_copy_keymap ();
/* Return a new keymap with the printing characters bound to rl_insert,
the lowercase Meta characters bound to run their equivalents, and
the Meta digits bound to produce numeric arguments. */
extern Keymap rl_make_keymap ();
extern void rl_discard_keymap ();
/* Return the keymap corresponding to a given name. Names look like
`emacs' or `emacs-meta' or `vi-insert'. */
extern Keymap rl_get_keymap_by_name ();
/* Return the current keymap. */
extern Keymap rl_get_keymap ();
/* Set the current keymap to MAP. */
extern void rl_set_keymap ();
#endif /* _KEYMAPS_H_ */

View File

@ -19,13 +19,26 @@
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. */
#define READLINE_LIBRARY
#include "rlconf.h"
#if !defined (PAREN_MATCHING)
rl_insert_close (count, invoking_key)
int count, invoking_key;
{
return (rl_insert (count, invoking_key));
}
#else /* PAREN_MATCHING */
#include <stdio.h>
#include <sys/types.h>
#if defined (FD_SET)
#include <sys/time.h>
#endif
#include <readline/readline.h>
# include <sys/time.h>
#endif /* FD_SET */
#include "readline.h"
extern int rl_explicit_arg;
@ -114,5 +127,4 @@ find_matching_open (string, from, closer)
return (i);
}
#endif /* PAREN_MATCHING */

File diff suppressed because it is too large Load Diff

View File

@ -20,6 +20,7 @@
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. */
#define READLINE_LIBRARY
#include <stdio.h>
#include <sys/types.h>
@ -29,12 +30,6 @@
#endif /* !NO_SYS_FILE */
#include <signal.h>
/* This is needed to include support for TIOCGWINSZ and window resizing. */
#if defined (OSF1) || defined (BSD386) || defined (NetBSD) || \
defined (FreeBSD) || defined (_386BSD) || defined (AIX)
# include <sys/ioctl.h>
#endif /* OSF1 || BSD386 */
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
@ -58,9 +53,13 @@ extern int errno;
/* System-specific feature definitions and include files. */
#include "rldefs.h"
#if defined (GWINSZ_IN_SYS_IOCTL) || (defined (VSTATUS) && !defined (SunOS4))
# include <sys/ioctl.h>
#endif /* GWINSZ_IN_SYS_IOCTL || VSTATUS */
/* Some standard library routines. */
#include <readline/readline.h>
#include <readline/history.h>
#include "readline.h"
#include "history.h"
/* NOTE: Functions and variables prefixed with `_rl_' are
pseudo-global: they are global so they can be shared
@ -75,12 +74,14 @@ extern void _rl_bind_if_unbound ();
/* External redisplay functions and variables from display.c */
extern void _rl_move_vert ();
extern void _rl_update_final ();
extern void _rl_erase_at_end_of_line ();
extern void _rl_move_cursor_relative ();
extern int _rl_vis_botlin;
extern int _rl_last_c_pos;
extern int _rl_horizontal_scroll_mode;
extern int rl_display_fixed;
extern char *rl_display_prompt;
@ -107,6 +108,7 @@ static char *readline_internal ();
static void readline_initialize_everything ();
static int init_terminal_io ();
static void start_using_history ();
static void bind_arrow_keys ();
#if !defined (__GO32__)
static void readline_default_bindings ();
@ -155,7 +157,7 @@ int rl_arg_sign = 1;
static int rl_initialized = 0;
/* If non-zero, this program is running in an EMACS buffer. */
static char *running_in_emacs = (char *)NULL;
static int running_in_emacs = 0;
/* The current offset in the current input line. */
int rl_point;
@ -225,6 +227,10 @@ char *rl_line_buffer = (char *)NULL;
int rl_line_buffer_len = 0;
#define DEFAULT_BUFFER_SIZE 256
/* Forward declarations used by the display and termcap code. */
int term_xn;
int screenwidth, screenheight, screenchars;
/* **************************************************************** */
/* */
@ -278,7 +284,7 @@ readline (prompt)
return ((char *)NULL);
}
rl_visible_prompt_length = rl_prompt ? rl_expand_prompt (rl_prompt) : 0;
rl_visible_prompt_length = rl_expand_prompt (rl_prompt);
rl_initialize ();
rl_prep_terminal (_rl_meta_flag);
@ -810,10 +816,9 @@ add_macro_char (c)
if (current_macro_index + 1 >= current_macro_size)
{
if (!current_macro)
current_macro = (char *)xmalloc (current_macro_size = 25);
current_macro = xmalloc (current_macro_size = 25);
else
current_macro =
(char *)xrealloc (current_macro, current_macro_size += 25);
current_macro = xrealloc (current_macro, current_macro_size += 25);
}
current_macro[current_macro_index++] = c;
@ -916,6 +921,8 @@ _rl_kill_kbd_macro ()
/* Initliaze readline (and terminal if not already). */
rl_initialize ()
{
char *t;
/* If we have never been called before, initialize the
terminal and data structures. */
if (!rl_initialized)
@ -932,6 +939,16 @@ rl_initialize ()
/* We aren't done yet. We haven't even gotten started yet! */
rl_done = 0;
/* Check for LC_CTYPE and use its value to decide the defaults for
8-bit character input and output. */
t = getenv ("LC_CTYPE");
if (t && (strcmp (t, "iso-8859-1") == 0 || strcmp (t, "iso_8859_1") == 0))
{
_rl_meta_flag = 1;
_rl_convert_meta_chars_to_ascii = 0;
_rl_output_meta_chars = 1;
}
/* Tell the history routines what is going on. */
start_using_history ();
@ -952,7 +969,7 @@ static void
readline_initialize_everything ()
{
/* Find out if we are running in Emacs. */
running_in_emacs = getenv ("EMACS");
running_in_emacs = getenv ("EMACS") != (char *)0;
/* Set up input and output if they are not already set up. */
if (!rl_instream)
@ -968,8 +985,7 @@ readline_initialize_everything ()
/* Allocate data structures. */
if (!rl_line_buffer)
rl_line_buffer =
(char *)xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE);
rl_line_buffer = xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE);
/* Initialize the terminal interface. */
init_terminal_io ((char *)NULL);
@ -985,10 +1001,20 @@ readline_initialize_everything ()
/* Read in the init file. */
rl_read_init_file ((char *)NULL);
/* XXX */
if (_rl_horizontal_scroll_mode && term_xn)
{
screenwidth--;
screenchars -= screenheight;
}
/* Override the effect of any `set keymap' assignments in the
inputrc file. */
rl_set_keymap_from_edit_mode ();
/* Try to bind a common arrow key prefix, if not already bound. */
bind_arrow_keys ();
/* If the completion parser's default word break characters haven't
been set yet, then do so now. */
if (rl_completer_word_break_characters == (char *)NULL)
@ -1004,6 +1030,51 @@ readline_default_bindings ()
rltty_set_default_bindings (_rl_keymap);
}
static void
bind_arrow_keys_internal ()
{
Function *f;
f = rl_function_of_keyseq ("\033[A", _rl_keymap, (int *)NULL);
if (!f || f == rl_do_lowercase_version)
{
_rl_bind_if_unbound ("\033[A", rl_get_previous_history);
_rl_bind_if_unbound ("\033[B", rl_get_next_history);
_rl_bind_if_unbound ("\033[C", rl_forward);
_rl_bind_if_unbound ("\033[D", rl_backward);
}
f = rl_function_of_keyseq ("\033OA", _rl_keymap, (int *)NULL);
if (!f || f == rl_do_lowercase_version)
{
_rl_bind_if_unbound ("\033OA", rl_get_previous_history);
_rl_bind_if_unbound ("\033OB", rl_get_next_history);
_rl_bind_if_unbound ("\033OC", rl_forward);
_rl_bind_if_unbound ("\033OD", rl_backward);
}
}
/* Try and bind the common arrow key prefix after giving termcap and
the inputrc file a chance to bind them and create `real' keymaps
for the arrow key prefix. */
static void
bind_arrow_keys ()
{
Keymap xkeymap;
xkeymap = _rl_keymap;
_rl_keymap = emacs_standard_keymap;
bind_arrow_keys_internal ();
#if defined (VI_MODE)
_rl_keymap = vi_movement_keymap;
bind_arrow_keys_internal ();
#endif
_rl_keymap = xkeymap;
}
/* **************************************************************** */
/* */
@ -1029,7 +1100,7 @@ rl_digit_loop ()
continue;
}
c = UNMETA (c);
if (numeric (c))
if (digit_p (c))
{
if (rl_explicit_arg)
rl_numeric_arg = (rl_numeric_arg * 10) + (c - '0');
@ -1106,16 +1177,14 @@ int dumb_term = 0;
#undef PC
#if !defined (__linux__)
char PC;
char *BC, *UP;
/* If this causes problems, remove the `extern'. */
extern char PC, *BC, *UP;
#endif /* __linux__ */
/* Some strings to control terminal actions. These are output by tputs (). */
char *term_goto, *term_clreol, *term_cr, *term_clrpag, *term_backspace;
char *term_pc;
int screenwidth, screenheight, screenchars;
/* Non-zero if we determine that the terminal can do character insertion. */
int terminal_can_insert = 0;
@ -1218,7 +1287,8 @@ _rl_set_screen_size (tty, ignore_env)
set_lines_and_columns (screenheight, screenwidth);
#endif
screenwidth--;
if (!term_xn)
screenwidth--;
screenchars = screenwidth * screenheight;
}
@ -1295,20 +1365,21 @@ init_terminal_io (terminal_name)
#if defined (HACK_TERMCAP_MOTION)
term_forward_char = (char *)NULL;
#endif /* HACK_TERMCAP_MOTION */
terminal_can_insert = 0;
terminal_can_insert = term_xn = 0;
return;
#else /* !__GO32__ */
char *term, *buffer;
int tty;
Keymap xkeymap;
term = terminal_name ? terminal_name : getenv ("TERM");
if (!term_string_buffer)
term_string_buffer = (char *)xmalloc (2048);
term_string_buffer = xmalloc (2048);
if (!term_buffer)
term_buffer = (char *)xmalloc (2048);
term_buffer = xmalloc (2048);
buffer = term_string_buffer;
@ -1352,6 +1423,8 @@ init_terminal_io (terminal_name)
screenwidth = screenheight = 0;
term_xn = tgetflag ("am") && tgetflag ("xn");
_rl_set_screen_size (tty, 0);
/* "An application program can assume that the terminal can do
@ -1371,11 +1444,24 @@ init_terminal_io (terminal_name)
/* Attempt to find and bind the arrow keys. Do not override already
bound keys in an overzealous attempt, however. */
xkeymap = _rl_keymap;
_rl_keymap = emacs_standard_keymap;
_rl_bind_if_unbound (term_ku, rl_get_previous_history);
_rl_bind_if_unbound (term_kd, rl_get_next_history);
_rl_bind_if_unbound (term_kr, rl_forward);
_rl_bind_if_unbound (term_kl, rl_backward);
#if defined (VI_MODE)
_rl_keymap = vi_movement_keymap;
_rl_bind_if_unbound (term_ku, rl_get_previous_history);
_rl_bind_if_unbound (term_kd, rl_get_next_history);
_rl_bind_if_unbound (term_kr, rl_forward);
_rl_bind_if_unbound (term_kl, rl_backward);
#endif /* VI_MODE */
_rl_keymap = xkeymap;
#endif /* !__GO32__ */
return 0;
}
@ -1440,6 +1526,18 @@ crlf ()
return 0;
}
rl_tty_status (count, key)
int count, key;
{
#if defined (TIOCSTAT)
ioctl (1, TIOCSTAT, (char *)0);
rl_refresh_line ();
#else
ding ();
#endif
return 0;
}
/* **************************************************************** */
/* */
@ -1457,7 +1555,7 @@ int
alphabetic (c)
int c;
{
if (pure_alphabetic (c) || (numeric (c)))
if (pure_alphabetic (c) || (digit_p (c)))
return (1);
if (allow_pathname_alphabetic_chars)
@ -1466,14 +1564,6 @@ alphabetic (c)
return (0);
}
/* Return non-zero if C is a numeric character. */
int
numeric (c)
int c;
{
return (c >= '0' && c <= '9');
}
/* Ring the terminal bell. */
int
ding ()
@ -1508,7 +1598,8 @@ ding ()
}
/* How to abort things. */
rl_abort ()
rl_abort (count, key)
int count, key;
{
ding ();
rl_clear_message ();
@ -1541,7 +1632,7 @@ rl_copy_text (from, to)
}
length = to - from;
copy = (char *)xmalloc (1 + length);
copy = xmalloc (1 + length);
strncpy (copy, the_line + from, length);
copy[length] = '\0';
return (copy);
@ -1554,9 +1645,10 @@ rl_extend_line_buffer (len)
int len;
{
while (len >= rl_line_buffer_len)
rl_line_buffer =
(char *)xrealloc
(rl_line_buffer, rl_line_buffer_len += DEFAULT_BUFFER_SIZE);
{
rl_line_buffer_len += DEFAULT_BUFFER_SIZE;
rl_line_buffer = xrealloc (rl_line_buffer, rl_line_buffer_len);
}
the_line = rl_line_buffer;
}
@ -1671,8 +1763,8 @@ rl_delete_text (from, to)
might as well let rl_redisplay do that job. */
/* Move forward COUNT characters. */
rl_forward (count)
int count;
rl_forward (count, key)
int count, key;
{
if (count < 0)
rl_backward (-count);
@ -1697,8 +1789,8 @@ rl_forward (count)
}
/* Move backward COUNT characters. */
rl_backward (count)
int count;
rl_backward (count, key)
int count, key;
{
if (count < 0)
rl_forward (-count);
@ -1716,22 +1808,24 @@ rl_backward (count)
}
/* Move to the beginning of the line. */
rl_beg_of_line ()
rl_beg_of_line (count, key)
int count, key;
{
rl_point = 0;
return 0;
}
/* Move to the end of the line. */
rl_end_of_line ()
rl_end_of_line (count, key)
int count, key;
{
rl_point = rl_end;
return 0;
}
/* Move forward a word. We do what Emacs does. */
rl_forward_word (count)
int count;
rl_forward_word (count, key)
int count, key;
{
int c;
@ -1772,8 +1866,8 @@ rl_forward_word (count)
}
/* Move backward a word. We do what Emacs does. */
rl_backward_word (count)
int count;
rl_backward_word (count, key)
int count, key;
{
int c;
@ -1858,7 +1952,8 @@ rl_refresh_line ()
/* C-l typed to a line without quoting clears the screen, and then reprints
the prompt and the current input line. Given a numeric arg, redraw only
the current line. */
rl_clear_screen ()
rl_clear_screen (count, key)
int count, key;
{
if (rl_explicit_arg)
{
@ -1999,19 +2094,18 @@ rl_insert (count, c)
}
/* Insert the next typed character verbatim. */
rl_quoted_insert (count)
int count;
rl_quoted_insert (count, key)
int count, key;
{
int c;
c = rl_read_key ();
return (rl_insert (count, c));
return (rl_insert (count, c));
}
/* Insert a tab character. */
rl_tab_insert (count)
int count;
rl_tab_insert (count, key)
int count, key;
{
return (rl_insert (count, '\t'));
}
@ -2031,13 +2125,7 @@ rl_newline (count, key)
#endif /* VI_MODE */
if (readline_echoing_p)
{
_rl_move_vert (_rl_vis_botlin);
_rl_vis_botlin = 0;
crlf ();
fflush (out_stream);
rl_display_fixed++;
}
_rl_update_final ();
return 0;
}
@ -2064,8 +2152,8 @@ rl_do_lowercase_version (ignore1, ignore2)
}
/* Rubout the character behind point. */
rl_rubout (count)
int count;
rl_rubout (count, key)
int count, key;
{
if (count < 0)
{
@ -2164,7 +2252,8 @@ rl_delete_horizontal_space (count, ignore)
/* This does what C-w does in Unix. We can't prevent people from
using behaviour that they expect. */
rl_unix_word_rubout ()
rl_unix_word_rubout (count, key)
int count, key;
{
if (!rl_point)
ding ();
@ -2189,7 +2278,8 @@ rl_unix_word_rubout ()
latter, because if you are a Unix weenie, then you haven't backspaced
into the line at all, and if you aren't, then you know what you are
doing. */
rl_unix_line_discard ()
rl_unix_line_discard (count, key)
int count, key;
{
if (!rl_point)
ding ();
@ -2224,22 +2314,22 @@ rl_unix_line_discard ()
static int rl_change_case ();
/* Uppercase the word at point. */
rl_upcase_word (count)
int count;
rl_upcase_word (count, key)
int count, key;
{
return (rl_change_case (count, UpCase));
}
/* Lowercase the word at point. */
rl_downcase_word (count)
int count;
rl_downcase_word (count, key)
int count, key;
{
return (rl_change_case (count, DownCase));
}
/* Upcase the first letter, downcase the rest. */
rl_capitalize_word (count)
int count;
rl_capitalize_word (count, key)
int count, key;
{
return (rl_change_case (count, CapCase));
}
@ -2311,8 +2401,8 @@ rl_change_case (count, op)
/* **************************************************************** */
/* Transpose the words at point. */
rl_transpose_words (count)
int count;
rl_transpose_words (count, key)
int count, key;
{
char *word1, *word2;
int w1_beg, w1_end, w2_beg, w2_end;
@ -2371,8 +2461,8 @@ rl_transpose_words (count)
/* Transpose the characters at point. If point is at the end of the line,
then transpose the characters before point. */
rl_transpose_chars (count)
int count;
rl_transpose_chars (count, key)
int count, key;
{
char dummy[2];
@ -2510,6 +2600,7 @@ undo_thing:
}
/* Begin a group. Subsequent undos are undone as an atomic operation. */
int
rl_begin_undo_group ()
{
rl_add_undo (UNDO_BEGIN, 0, 0, 0);
@ -2517,6 +2608,7 @@ rl_begin_undo_group ()
}
/* End an undo group started with rl_begin_undo_group (). */
int
rl_end_undo_group ()
{
rl_add_undo (UNDO_END, 0, 0, 0);
@ -2546,7 +2638,9 @@ rl_modifying (start, end)
}
/* Revert the current line to its previous state. */
rl_revert_line ()
int
rl_revert_line (count, key)
int count, key;
{
if (!rl_undo_list)
ding ();
@ -2559,8 +2653,9 @@ rl_revert_line ()
}
/* Do some undoing of things that were done. */
rl_undo_command (count)
int count;
int
rl_undo_command (count, key)
int count, key;
{
if (count < 0)
return 0; /* Nothing to do. */
@ -2672,13 +2767,15 @@ maybe_save_line ()
/* **************************************************************** */
/* Meta-< goes to the start of the history. */
rl_beginning_of_history ()
rl_beginning_of_history (count, key)
int count, key;
{
return (rl_get_previous_history (1 + where_history ()));
}
/* Meta-> goes to the end of the history. (The current line). */
rl_end_of_history ()
rl_end_of_history (count, key)
int count, key;
{
maybe_replace_line ();
using_history ();
@ -2687,8 +2784,8 @@ rl_end_of_history ()
}
/* Move down to the next history line. */
rl_get_next_history (count)
int count;
rl_get_next_history (count, key)
int count, key;
{
HIST_ENTRY *temp = (HIST_ENTRY *)NULL;
@ -2732,8 +2829,8 @@ rl_get_next_history (count)
/* Get the previous item out of our interactive history, making it the current
line. If there is no previous history, just ding. */
rl_get_previous_history (count)
int count;
rl_get_previous_history (count, key)
int count, key;
{
HIST_ENTRY *old_temp = (HIST_ENTRY *)NULL;
HIST_ENTRY *temp = (HIST_ENTRY *)NULL;
@ -2814,7 +2911,8 @@ rl_set_mark (position)
}
/* Exchange the position of mark and point. */
rl_exchange_mark_and_point ()
rl_exchange_mark_and_point (count, key)
int count, key;
{
if (rl_mark > rl_end)
rl_mark = -1;
@ -2845,7 +2943,7 @@ rl_exchange_mark_and_point ()
#define DEFAULT_MAX_KILLS 10
/* The real variable to look at to find out when to flush kills. */
int rl_max_kills = DEFAULT_MAX_KILLS;
int rl_max_kills = DEFAULT_MAX_KILLS;
/* Where to store killed text. */
char **rl_kill_ring = (char **)NULL;
@ -2873,16 +2971,17 @@ rl_kill_text (from, to)
int from, to;
{
int slot;
char *text = rl_copy_text (from, to);
char *text;
/* Is there anything to kill? */
if (from == to)
{
free (text);
last_command_was_kill++;
return 0;
}
text = rl_copy_text (from, to);
/* Delete the copied text from the line. */
rl_delete_text (from, to);
@ -2895,7 +2994,7 @@ rl_kill_text (from, to)
/* If we don't have any defined, then make one. */
rl_kill_ring = (char **)
xmalloc (((rl_kill_ring_length = 1) + 1) * sizeof (char *));
slot = 1;
rl_kill_ring[slot = 0] = (char *)NULL;
}
else
{
@ -2911,25 +3010,20 @@ rl_kill_text (from, to)
}
else
{
rl_kill_ring =
(char **)
xrealloc (rl_kill_ring,
((slot = (rl_kill_ring_length += 1)) + 1)
* sizeof (char *));
slot = rl_kill_ring_length += 1;
rl_kill_ring = (char **)xrealloc (rl_kill_ring, slot * sizeof (char *));
}
rl_kill_ring[--slot] = (char *)NULL;
}
slot--;
}
else
{
slot = rl_kill_ring_length - 1;
}
slot = rl_kill_ring_length - 1;
/* If the last command was a kill, prepend or append. */
if (last_command_was_kill && rl_editing_mode != vi_mode)
{
char *old = rl_kill_ring[slot];
char *new = (char *)xmalloc (1 + strlen (old) + strlen (text));
char *new = xmalloc (1 + strlen (old) + strlen (text));
if (from < to)
{
@ -2965,8 +3059,8 @@ rl_kill_text (from, to)
/* **************************************************************** */
/* Delete the word at point, saving the text in the kill ring. */
rl_kill_word (count)
int count;
rl_kill_word (count, key)
int count, key;
{
int orig_point = rl_point;
@ -3004,8 +3098,8 @@ rl_backward_kill_word (count, ignore)
/* Kill from here to the end of the line. If DIRECTION is negative, kill
back to the line start instead. */
rl_kill_line (direction)
int direction;
rl_kill_line (direction, ignore)
int direction, ignore;
{
int orig_point = rl_point;
@ -3023,8 +3117,8 @@ rl_kill_line (direction)
/* Kill backwards to the start of the line. If DIRECTION is negative, kill
forwards to the line end instead. */
rl_backward_kill_line (direction)
int direction;
rl_backward_kill_line (direction, ignore)
int direction, ignore;
{
int orig_point = rl_point;
@ -3146,6 +3240,19 @@ rl_yank_nth_arg (count, ignore)
return 0;
}
/* Yank the last argument from the previous history line. This `knows'
how rl_yank_nth_arg treats a count of `$'. With an argument, this
behaves the same as rl_yank_nth_arg. */
int
rl_yank_last_arg (count, key)
int count, key;
{
if (rl_explicit_arg)
return (rl_yank_nth_arg (count, key));
else
return (rl_yank_nth_arg ('$', key));
}
/* How to toggle back and forth between editing modes. */
rl_vi_editing_mode (count, key)
int count, key;
@ -3181,7 +3288,7 @@ rl_getc (stream)
#if defined (__GO32__)
if (isatty (0))
return (getkey ());
return (getkey () & 0x7F);
#endif /* __GO32__ */
while (1)
@ -3239,6 +3346,77 @@ rl_getc (stream)
}
}
#if !defined (SHELL)
#ifdef savestring
#undef savestring
#endif
/* Backwards compatibilty, now that savestring has been removed from
all `public' readline header files. */
char *
savestring (s)
char *s;
{
return ((char *)strcpy (xmalloc (1 + (int)strlen (s)), (s)));
}
#endif
/* Function equivalents for the macros defined in chartypes.h. */
#undef uppercase_p
int
uppercase_p (c)
int c;
{
return (isupper (c));
}
#undef lowercase_p
int
lowercase_p (c)
int c;
{
return (islower (c));
}
#undef pure_alphabetic
int
pure_alphabetic (c)
int c;
{
return (isupper (c) || islower (c));
}
#undef digit_p
int
digit_p (c)
int c;
{
return (isdigit (c));
}
#undef to_lower
int
to_lower (c)
int c;
{
return (isupper (c) ? tolower (c) : c);
}
#undef to_upper
int
to_upper (c)
int c;
{
return (islower (c) ? toupper (c) : c);
}
#undef digit_value
int
digit_value (c)
int c;
{
return (isdigit (c) ? c - '0' : c);
}
#if defined (STATIC_MALLOC)
/* **************************************************************** */

View File

@ -0,0 +1,289 @@
/* Readline.h -- the names of functions callable from within readline. */
/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
This file is part of the GNU Readline Library, a library for
reading lines of text with interactive input and history editing.
The GNU Readline Library is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 1, or
(at your option) any later version.
The GNU Readline Library is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
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. */
#if !defined (_READLINE_H_)
#define _READLINE_H_
#if defined (READLINE_LIBRARY)
# include "keymaps.h"
# include "tilde.h"
#else
# include <readline/keymaps.h>
# include <readline/tilde.h>
#endif
/* The functions for manipulating the text of the line within readline.
Most of these functions are bound to keys by default. */
extern int
rl_tilde_expand (),
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_insert_completions (),
rl_do_lowercase_version (), rl_kill_full_line (),
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 (),
rl_delete_horizontal_space (), rl_history_search_forward (),
rl_history_search_backward (), rl_tty_status (), rl_yank_last_arg ();
/* `Public' utility functions. */
extern int rl_insert_text (), rl_delete_text (), rl_kill_text ();
extern int rl_complete_internal ();
extern int rl_expand_prompt ();
extern int rl_initialize ();
extern int rl_set_signals (), rl_clear_signals ();
extern int rl_init_argument (), rl_digit_argument ();
extern int rl_read_key (), rl_getc (), rl_stuff_char ();
extern int maybe_save_line (), maybe_unsave_line (), maybe_replace_line ();
extern int rl_modifying ();
extern int rl_begin_undo_group (), rl_end_undo_group ();
extern void rl_add_undo (), free_undo_list ();
extern int rl_do_undo ();
/* Not available unless readline is compiled -DPAREN_MATCHING. */
extern int rl_insert_close ();
/* These are *both* defined even when VI_MODE is not. */
extern int rl_vi_editing_mode (), rl_emacs_editing_mode ();
/* Non incremental history searching. */
extern int
rl_noninc_forward_search (), rl_noninc_reverse_search (),
rl_noninc_forward_search_again (), rl_noninc_reverse_search_again ();
/* Things for vi mode. Not available unless readline is compiled -DVI_MODE. */
extern int rl_vi_check (), rl_vi_textmod_command ();
extern int
rl_vi_redo (), rl_vi_tilde_expand (),
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_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 ();
/* Keyboard macro commands. */
extern int rl_start_kbd_macro (), rl_end_kbd_macro ();
extern int 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. */
/* The actions that undo knows how to undo. Notice that UNDO_DELETE means
to insert some text, and UNDO_INSERT means to delete some text. I.e.,
the code tells undo what to undo, not how to undo it. */
enum undo_code { UNDO_DELETE, UNDO_INSERT, UNDO_BEGIN, UNDO_END };
/* What an element of THE_UNDO_LIST looks like. */
typedef struct undo_list {
struct undo_list *next;
int start, end; /* Where the change took place. */
char *text; /* The text to insert, if undoing a delete. */
enum undo_code what; /* Delete, Insert, Begin, End. */
} UNDO_LIST;
/* The current undo list for RL_LINE_BUFFER. */
extern UNDO_LIST *rl_undo_list;
/* The data structure for mapping textual names to code addresses. */
typedef struct {
char *name;
Function *function;
} FUNMAP;
extern FUNMAP **funmap;
/* **************************************************************** */
/* */
/* Well Published Variables */
/* */
/* **************************************************************** */
/* The name of the calling program. You should initialize this to
whatever was in argv[0]. It is used when parsing conditionals. */
extern char *rl_readline_name;
/* The line buffer that is in use. */
extern char *rl_line_buffer;
/* The location of point, and end. */
extern int rl_point, rl_end;
/* The name of the terminal to use. */
extern char *rl_terminal_name;
/* The input and output streams. */
extern FILE *rl_instream, *rl_outstream;
/* The basic list of characters that signal a break between words for the
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
rl_complete_internal. The default list is the contents of
rl_basic_word_break_characters. */
extern char *rl_completer_word_break_characters;
/* List of characters which can be used to quote a substring of the line.
Completion occurs on the entire substring, and within the substring
rl_completer_word_break_characters are treated as any other character,
unless they also appear within this list. */
extern char *rl_completer_quote_characters;
/* List of characters that are word break characters, but should be left
in TEXT when it is passed to the completion function. The shell uses
this to help determine what kind of completing to do. */
extern char *rl_special_prefixes;
/* Pointer to the generator function for completion_matches ().
NULL means to use filename_entry_function (), the default filename
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
of TEXT are.
If this function exists and returns NULL then call the value of
rl_completion_entry_function to try to match, otherwise use the
array of strings returned. */
extern CPPFunction *rl_attempted_completion_function;
/* 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;
/* If non-zero, then this is the address of a function to call when
completing on a directory name. The function is called with
the address of a string (the current directory name) as an arg. */
extern Function *rl_directory_completion_hook;
/* Backwards compatibility with previous versions of readline. */
#define rl_symbolic_link_hook rl_directory_completion_hook
/* The address of a function to call periodically while Readline is
awaiting character input, or NULL, for no event handling. */
extern Function *rl_event_hook;
/* Non-zero means that modified history lines are preceded
with an asterisk. */
extern int rl_show_star;
/* Non-zero means that the results of the matches are to be treated
as filenames. This is ALWAYS zero on entry, and can only be changed
within a completion entry finder function. */
extern int rl_filename_completion_desired;
/* Non-zero means that the results of the matches are to be quoted using
double quotes (or an application-specific quoting mechanism) if the
filename contains any characters in rl_word_break_chars. This is
ALWAYS non-zero on entry, and can only be changed within a completion
entry finder function. */
extern int rl_filename_quoting_desired;
/* Non-zero means to suppress normal filename completion after the
user-specified completion function has been called. */
extern int rl_attempted_completion_over;
/* **************************************************************** */
/* */
/* Well Published Functions */
/* */
/* **************************************************************** */
/* Read a line of input. Prompt with PROMPT. A NULL PROMPT means none. */
extern char *readline ();
/* These functions are from complete.c. */
/* Return an array of strings which are the result of repeatadly calling
FUNC with TEXT. */
extern char **completion_matches ();
extern char *username_completion_function ();
extern char *filename_completion_function ();
/* These functions are from bind.c. */
/* rl_add_defun (char *name, Function *function, int key)
Add NAME to the list of named functions. Make FUNCTION
be the function that gets called.
If KEY is not -1, then bind it. */
extern int rl_add_defun ();
extern int rl_bind_key (), rl_bind_key_in_map ();
extern int rl_unbind_key (), rl_unbind_key_in_map ();
extern int rl_set_key ();
extern int rl_macro_bind (), rl_generic_bind (), rl_variable_bind ();
extern int rl_translate_keyseq ();
extern Function *rl_named_function (), *rl_function_of_keyseq ();
extern int rl_parse_and_bind ();
extern Keymap rl_get_keymap (), rl_get_keymap_by_name ();
extern void rl_set_keymap ();
extern char **rl_invoking_keyseqs (), **rl_invoking_keyseqs_in_map ();
extern void rl_function_dumper ();
extern int rl_read_init_file ();
/* Functions in funmap.c */
extern void rl_list_funmap_names ();
extern void rl_initialize_funmap ();
/* Functions in display.c */
extern void rl_redisplay ();
extern int rl_message (), rl_clear_message ();
extern int rl_reset_line_state ();
extern int rl_character_len ();
extern int rl_show_char ();
extern int crlf (), rl_on_new_line ();
extern int rl_forced_update_display ();
/* Definitions available for use by readline clients. */
#define RL_PROMPT_START_IGNORE '\001'
#define RL_PROMPT_END_IGNORE '\002'
#if !defined (savestring)
extern char *savestring (); /* XXX backwards compatibility */
#endif
#endif /* _READLINE_H_ */

View File

@ -26,6 +26,14 @@
#if !defined (_RLDEFS_H)
#define _RLDEFS_H
#if defined (HAVE_CONFIG_H)
# include "config.h"
#endif
#if defined (HAVE_UNISTD_H)
# include <unistd.h> /* for _POSIX_VERSION */
#endif /* HAVE_UNISTD_H */
#if !defined (PRAGMA_ALLOCA)
# include "memalloc.h"
#endif
@ -34,9 +42,9 @@
#define HAVE_BSD_SIGNALS
/* #define USE_XON_XOFF */
#if defined (__linux__)
#if defined (__linux__) || defined (HAVE_TERMCAP_H)
# include <termcap.h>
#endif /* __linux__ */
#endif /* __linux__ || HAVE_TERMCAP_H */
/* Some USG machines have BSD signal handling (sigblock, sigsetmask, etc.) */
#if defined (USG) && !defined (hpux)
@ -45,14 +53,15 @@
/* System V machines use termio. */
#if !defined (_POSIX_VERSION)
# if defined (USG) || defined (hpux) || defined (Xenix) || defined (sgi) || defined (DGUX)
# if defined (USG) || defined (hpux) || defined (Xenix) || defined (sgi) || \
defined (DGUX) || defined (HAVE_TERMIO_H)
# undef NEW_TTY_DRIVER
# define TERMIO_TTY_DRIVER
# include <termio.h>
# if !defined (TCOON)
# define TCOON 1
# endif
# endif /* USG || hpux || Xenix || sgi || DUGX */
# endif /* USG || hpux || Xenix || sgi || DUGX || HAVE_TERMIO_H */
#endif /* !_POSIX_VERSION */
/* Posix systems use termios and the Posix signal functions. */
@ -102,9 +111,6 @@
#if defined (HAVE_DIRENT_H)
# include <dirent.h>
# if !defined (direct)
# define direct dirent
# endif /* !direct */
# define D_NAMLEN(d) strlen ((d)->d_name)
#else /* !HAVE_DIRENT_H */
# define D_NAMLEN(d) ((d)->d_namlen)
@ -117,6 +123,9 @@
# else /* !USG */
# include <sys/dir.h>
# endif /* !USG */
# if !defined (dirent)
# define dirent direct
# endif /* !dirent */
#endif /* !HAVE_DIRENT_H */
#if defined (USG) && defined (TIOCGWINSZ) && !defined (Linux)
@ -160,6 +169,13 @@ extern char *strchr (), *strrchr ();
# include <varargs.h>
#endif /* HAVE_VARARGS_H */
/* This is needed to include support for TIOCGWINSZ and window resizing. */
#if defined (OSF1) || defined (BSD386) || defined (NetBSD) || \
defined (__BSD_4_4__) || defined (FreeBSD) || defined (_386BSD) || \
defined (AIX)
# define GWINSZ_IN_SYS_IOCTL
#endif
#if !defined (emacs_mode)
# define no_mode -1
# define vi_mode 0
@ -179,6 +195,11 @@ extern char *strchr (), *strrchr ();
# define KEYMAP_TO_FUNCTION(data) (Function *)(data)
#endif
#ifndef savestring
extern char *xmalloc ();
#define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x))
#endif
/* Possible values for _rl_bell_preference. */
#define NO_BELL 0
#define AUDIBLE_BELL 1

View File

@ -20,6 +20,8 @@
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. */
#define READLINE_LIBRARY
#include <sys/types.h>
#include <signal.h>
#include <errno.h>
@ -29,14 +31,8 @@
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
/* This is needed to include support for TIOCGWINSZ and window resizing. */
#if defined (OSF1) || defined (BSD386) || defined (NetBSD) || \
defined (FreeBSD) || defined (_386BSD) || defined (AIX)
# include <sys/ioctl.h>
#endif /* OSF1 || BSD386 */
#include "rldefs.h"
#include <readline/readline.h>
#include "readline.h"
#if !defined (errno)
extern int errno;
@ -50,6 +46,8 @@ extern int _rl_eof_char;
# undef HANDLE_SIGNALS
#endif /* __GO32__ */
static int output_was_flushed;
/* **************************************************************** */
/* */
/* Signal Management */
@ -125,6 +123,7 @@ extern char *term_mo;
extern char *term_ks;
extern char *term_ke;
static int
outchar (c)
int c;
@ -201,6 +200,13 @@ get_tty_settings (tty, tiop)
int tty;
TIOTYPE *tiop;
{
#if !defined (SHELL) && defined (TIOCGWINSZ)
struct winsize w;
if (ioctl (tty, TIOCGWINSZ, &w) == 0)
(void) ioctl (tty, TIOCSWINSZ, &w);
#endif
tiop->flags = tiop->lflag = 0;
ioctl (tty, TIOCGETP, &(tiop->sgttyb));
@ -360,21 +366,30 @@ prepare_terminal_settings (meta_flag, otio, tiop)
static TIOTYPE otio;
#if defined (FLUSHO)
# define OUTPUT_BEING_FLUSHED(tp) (tp->c_lflag & FLUSHO)
#else
# define OUTPUT_BEING_FLUSHED(tp) 0
#endif
static int
get_tty_settings (tty, tiop)
int tty;
TIOTYPE *tiop;
{
#ifdef TIOCGWINSZ
/* XXX this prevents to got editing mode from tcsh. Ache */
#if !defined (SHELL) && defined (TIOCGWINSZ)
struct winsize w;
if (ioctl (tty, TIOCGWINSZ, &w) == 0)
(void) ioctl (tty, TIOCSWINSZ, &w);
#endif
while (GETATTR (tty, tiop) < 0)
/* Keep looping if output is being flushed after a ^O (or whatever
the flush character is). */
while (GETATTR (tty, tiop) < 0 || OUTPUT_BEING_FLUSHED (tiop))
{
if (OUTPUT_BEING_FLUSHED (tiop))
continue;
if (errno != EINTR)
return -1;
errno = 0;
@ -452,6 +467,13 @@ prepare_terminal_settings (meta_flag, otio, tiop)
tiop->c_cc[VMIN] = 1;
tiop->c_cc[VTIME] = 0;
if (tiop->c_lflag & FLUSHO)
{
output_was_flushed = 1;
tiop->c_lflag &= ~FLUSHO;
otio.c_lflag &= ~FLUSHO;
}
/* Turn off characters that we need on Posix systems with job control,
just to be sure. This includes ^Y and ^V. This should not really
be necessary. */
@ -500,8 +522,12 @@ rl_prep_terminal (meta_flag)
return;
}
if (output_was_flushed)
output_was_flushed = 0;
control_meta_key (1);
control_keypad (1);
fflush (rl_outstream);
terminal_prepped = 1;
release_sigint ();
@ -529,6 +555,7 @@ rl_deprep_terminal ()
control_meta_key (0);
control_keypad (0);
fflush (rl_outstream);
terminal_prepped = 0;
release_sigint ();
@ -614,79 +641,56 @@ rltty_set_default_bindings (kmap)
#if defined (NEW_TTY_DRIVER)
#define SET_SPECIAL(sc, func) \
do \
{ \
int ic; \
ic = sc; \
if (ic != -1 && kmap[ic].type == ISFUNC) \
kmap[ic].function = func; \
} \
while (0)
if (get_tty_settings (tty, &ttybuff) == 0)
{
if (ttybuff.flags & SGTTY_SET)
{
int erase, kill;
erase = ttybuff.sgttyb.sg_erase;
kill = ttybuff.sgttyb.sg_kill;
if (erase != -1 && kmap[erase].type == ISFUNC)
kmap[erase].function = rl_rubout;
if (kill != -1 && kmap[kill].type == ISFUNC)
kmap[kill].function = rl_unix_line_discard;
SET_SPECIAL (ttybuff.sgttyb.sg_erase, rl_rubout);
SET_SPECIAL (ttybuff.sgttyb.sg_kill, rl_unix_line_discard);
}
# if defined (TIOCGLTC)
if (ttybuff.flags & LTCHARS_SET)
{
int werase, nextc;
werase = ttybuff.ltchars.t_werasc;
nextc = ttybuff.ltchars.t_lnextc;
if (werase != -1 && kmap[werase].type == ISFUNC)
kmap[werase].function = rl_unix_word_rubout;
if (nextc != -1 && kmap[nextc].type == ISFUNC)
kmap[nextc].function = rl_quoted_insert;
SET_SPECIAL (ttybuff.ltchars.t_werasc, rl_unix_word_rubout);
SET_SPECIAL (ttybuff.ltchars.t_lnextc, rl_quoted_insert);
}
}
# endif /* TIOCGLTC */
}
#else /* !NEW_TTY_DRIVER */
#define SET_SPECIAL(sc, func) \
do \
{ \
unsigned char uc; \
uc = ttybuff.c_cc[sc]; \
if (uc != (unsigned char)_POSIX_VDISABLE && kmap[uc].type == ISFUNC) \
kmap[uc].function = func; \
} \
while (0)
if (get_tty_settings (tty, &ttybuff) == 0)
{
unsigned char erase, kill;
erase = ttybuff.c_cc[VERASE];
kill = ttybuff.c_cc[VKILL];
if (erase != (unsigned char)_POSIX_VDISABLE &&
kmap[erase].type == ISFUNC)
kmap[erase].function = rl_rubout;
if (kill != (unsigned char)_POSIX_VDISABLE &&
kmap[kill].type == ISFUNC)
kmap[kill].function = rl_unix_line_discard;
SET_SPECIAL (VERASE, rl_rubout);
SET_SPECIAL (VKILL, rl_unix_line_discard);
# if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER)
{
unsigned char nextc;
nextc = ttybuff.c_cc[VLNEXT];
if (nextc != (unsigned char)_POSIX_VDISABLE &&
kmap[nextc].type == ISFUNC)
kmap[nextc].function = rl_quoted_insert;
}
SET_SPECIAL (VLNEXT, rl_quoted_insert);
# endif /* VLNEXT && TERMIOS_TTY_DRIVER */
# if defined (VWERASE) && defined (TERMIOS_TTY_DRIVER)
{
unsigned char werase;
werase = ttybuff.c_cc[VWERASE];
if (werase != (unsigned char)_POSIX_VDISABLE &&
kmap[werase].type == ISFUNC)
kmap[werase].function = rl_unix_word_rubout;
}
SET_SPECIAL (VWERASE, rl_unix_word_rubout);
# endif /* VWERASE && TERMIOS_TTY_DRIVER */
}
#endif /* !NEW_TTY_DRIVER */

View File

@ -20,12 +20,19 @@
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. */
#define READLINE_LIBRARY
#include <sys/types.h>
#include <stdio.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "memalloc.h"
#include <readline/readline.h>
#include <readline/history.h>
#include "rldefs.h"
#include "readline.h"
#include "history.h"
#define STREQ(a, b) (((a)[0] == (b)[0]) && (strcmp ((a), (b)) == 0))
#define STREQN(a, b, n) (((a)[0] == (b)[0]) && (strncmp ((a), (b), (n)) == 0))

View File

@ -19,6 +19,7 @@
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. */
#define READLINE_LIBRARY
#include <stdio.h>
#include <sys/types.h>
@ -28,11 +29,6 @@
#endif /* !NO_SYS_FILE */
#include <signal.h>
/* This is needed to include support for TIOCGWINSZ and window resizing. */
#if defined (OSF1) || defined (BSD386) || defined (_386BSD) || defined (__BSD_4_4__) || defined (AIX)
# include <sys/ioctl.h>
#endif /* OSF1 || BSD386 || _386BSD || __BSD_4_4__ || AIX */
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
@ -54,9 +50,13 @@ extern int errno;
/* System-specific feature definitions and include files. */
#include "rldefs.h"
#if defined (GWINSZ_IN_SYS_IOCTL)
# include <sys/ioctl.h>
#endif /* GWINSZ_IN_SYS_IOCTL */
/* Some standard library routines. */
#include <readline/readline.h>
#include <readline/history.h>
#include "readline.h"
#include "history.h"
static void cr ();

View File

@ -33,7 +33,7 @@
# include "ansi_stdlib.h"
#endif /* HAVE_STDLIB_H */
#include <readline/tilde.h>
#include "tilde.h"
#include <pwd.h>
#if defined (USG) && !defined (HAVE_GETPW_DECLS)

View File

@ -0,0 +1,38 @@
/* tilde.h: Externally available variables and function in libtilde.a. */
#if !defined (__TILDE_H__)
# define __TILDE_H__
/* Function pointers can be declared as (Function *)foo. */
#if !defined (__FUNCTION_DEF)
# define __FUNCTION_DEF
typedef int Function ();
typedef void VFunction ();
typedef char *CPFunction ();
typedef char **CPPFunction ();
#endif /* _FUNCTION_DEF */
/* 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 CPFunction *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;
/* Return a new string which is the result of tilde expanding STRING. */
extern char *tilde_expand ();
/* Do the work of tilde expansion on FILENAME. FILENAME starts with a
tilde. If there is no expansion, call tilde_expansion_failure_hook. */
extern char *tilde_expand_word ();
#endif /* __TILDE_H__ */

View File

@ -24,7 +24,7 @@
#include <stdio.h>
#endif /* !BUFSIZ */
#include <readline/readline.h>
#include "readline.h"
#if 0
extern KEYMAP_ENTRY_ARRAY vi_escape_keymap;
@ -61,7 +61,7 @@ KEYMAP_ENTRY_ARRAY vi_movement_keymap = {
{ ISFUNC, rl_yank }, /* Control-y */
{ ISFUNC, (Function *)0x0 }, /* Control-z */
{ ISFUNC, rl_abort }, /* Control-[ */ /* vi_escape_keymap */
{ ISFUNC, (Function *)0x0 }, /* Control-[ */ /* vi_escape_keymap */
{ ISFUNC, (Function *)0x0 }, /* Control-\ */
{ ISFUNC, (Function *)0x0 }, /* Control-] */
{ ISFUNC, (Function *)0x0 }, /* Control-^ */

View File

@ -20,6 +20,7 @@
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. */
#define READLINE_LIBRARY
/* **************************************************************** */
/* */
@ -38,19 +39,19 @@
# include "ansi_stdlib.h"
#endif /* HAVE_STDLIB_H */
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <stdio.h>
/* Some standard library routines. */
#include "rldefs.h"
#include <readline/readline.h>
#include <readline/history.h>
#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'))
#ifndef digit_p
#define digit_p(c) ((c) >= '0' && (c) <= '9')
#endif
#ifndef digit_value
@ -58,15 +59,15 @@
#endif
#ifndef member
#define member(c, s) ((c) ? (char *)strchr ((s), (c)) : 0)
#define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0)
#endif
#ifndef isident
#define isident(c) ((isletter(c) || digit(c) || c == '_'))
#define isident(c) ((pure_alphabetic (c) || digit_p (c) || c == '_'))
#endif
#ifndef exchange
#define exchange(x, y) {int temp = x; x = y; y = temp;}
#define exchange(x, y) do {int temp = x; x = y; y = temp;} while (0)
#endif
#ifndef VI_COMMENT_BEGIN_DEFAULT
@ -152,7 +153,7 @@ int
rl_vi_textmod_command (c)
int c;
{
return (member (c, vi_textmod) != (char *)NULL);
return (member (c, vi_textmod));
}
/* Bound to `.'. Called from command mode, so we know that we have to
@ -175,8 +176,8 @@ rl_vi_redo (count, c)
}
/* Yank the nth arg from the previous line into this line at point. */
rl_vi_yank_arg (count)
int count;
rl_vi_yank_arg (count, key)
int count, key;
{
/* 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. */
@ -503,14 +504,16 @@ rl_vi_eword (count)
return (0);
}
rl_vi_insert_beg ()
rl_vi_insert_beg (count, key)
int count, key;
{
rl_beg_of_line ();
rl_vi_insertion_mode ();
return (0);
}
rl_vi_append_mode ()
rl_vi_append_mode (count, key)
int count, key;
{
if (rl_point < rl_end)
rl_point++;
@ -518,7 +521,8 @@ rl_vi_append_mode ()
return (0);
}
rl_vi_append_eol ()
rl_vi_append_eol (count, key)
int count, key;
{
rl_end_of_line ();
rl_vi_append_mode ();
@ -536,7 +540,8 @@ rl_vi_eof_maybe (count, c)
/* Switching from one mode to the other really just involves
switching keymaps. */
rl_vi_insertion_mode ()
rl_vi_insertion_mode (count, key)
int count, key;
{
_rl_keymap = vi_insertion_keymap;
return (0);
@ -558,7 +563,8 @@ _rl_vi_done_inserting ()
vi_continued_command = 0;
}
rl_vi_movement_mode ()
rl_vi_movement_mode (count, key)
int count, key;
{
if (rl_point > 0)
rl_backward (1);
@ -636,7 +642,8 @@ rl_vi_check ()
return (0);
}
rl_vi_column (count)
rl_vi_column (count, key)
int count, key;
{
if (count > rl_end)
rl_end_of_line ();
@ -658,7 +665,7 @@ rl_vi_domove (key, nextkey)
if (!member (c, vi_motion))
{
if (digit (c))
if (digit_p (c))
{
save = rl_numeric_arg;
rl_numeric_arg = digit_value (c);
@ -753,7 +760,7 @@ rl_digit_loop1 ()
}
c = UNMETA (c);
if (numeric (c))
if (digit_p (c))
{
if (rl_explicit_arg)
rl_numeric_arg = (rl_numeric_arg * 10) + digit_value (c);
@ -862,8 +869,8 @@ rl_vi_yank_to (count, key)
return (0);
}
rl_vi_delete (count)
int count;
rl_vi_delete (count, key)
int count, key;
{
int end;
@ -887,7 +894,8 @@ rl_vi_delete (count)
/* Turn the current line into a comment in shell history.
A K*rn shell style function. */
rl_vi_comment ()
rl_vi_comment (count, key)
int count, key;
{
rl_beg_of_line ();
@ -901,7 +909,8 @@ rl_vi_comment ()
return (0);
}
rl_vi_first_print ()
rl_vi_first_print (count, key)
int count, key;
{
return (rl_back_to_indent ());
}
@ -1022,7 +1031,8 @@ rl_vi_char_search (count, key)
}
/* Match brackets */
rl_vi_match ()
rl_vi_match (ignore, key)
int ignore, key;
{
int count = 1, brack, pos;