312 lines
10 KiB
Plaintext
312 lines
10 KiB
Plaintext
@ignore
|
|
This file documents the user interface to the GNU History library.
|
|
|
|
Copyright (C) 1988, 1991 Free Software Foundation, Inc.
|
|
Authored by Brian Fox.
|
|
|
|
Permission is granted to make and distribute verbatim copies of this manual
|
|
provided the copyright notice and this permission notice are preserved on
|
|
all copies.
|
|
|
|
Permission is granted to process this file through Tex and print the
|
|
results, provided the printed document carries copying permission notice
|
|
identical to this one except for the removal of this paragraph (this
|
|
paragraph not being relevant to the printed manual).
|
|
|
|
Permission is granted to copy and distribute modified versions of this
|
|
manual under the conditions for verbatim copying, provided also that the
|
|
GNU Copyright statement is available to the distributee, and 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.
|
|
@end ignore
|
|
|
|
@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.
|
|
For information on the interactive use of GNU History, @pxref{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.
|
|
@end menu
|
|
|
|
@node Introduction to History
|
|
@section 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 making up 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
|
|
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
|
|
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
|
|
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}.
|
|
|
|
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.
|
|
|
|
@node History Storage
|
|
@section History Storage
|
|
|
|
@example
|
|
typedef struct _hist_entry @{
|
|
char *line;
|
|
char *data;
|
|
@} HIST_ENTRY;
|
|
@end example
|
|
|
|
@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
|
|
|
|
@defun {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
|
|
|
|
@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,
|
|
and containing structure.
|
|
@end defun
|
|
|
|
@defun {void stifle_history} (int max)
|
|
Stifle the history list, remembering only @var{max} number of entries.
|
|
@end defun
|
|
|
|
@defun {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
|
|
stifled, negative if it wasn't.
|
|
@end defun
|
|
|
|
@defun {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
|
|
|
|
@defun {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
|
|
@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
|
|
|
|
@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
|
|
returned are as in @code{read_history ()}.
|
|
@end defun
|
|
|
|
@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
|
|
|
|
@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
|
|
|
|
@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
|
|
|
|
@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
|
|
|
|
@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)
|
|
Expand @var{string}, placing the result into @var{output}, a pointer
|
|
to a string. 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),
|
|
@item 1
|
|
if expansions did take place, or
|
|
@item -1
|
|
if there was an error in expansion.
|
|
@end table
|
|
|
|
If an error ocurred in expansion, then @var{output} contains a descriptive
|
|
error message.
|
|
@end defun
|
|
|
|
@defun {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
|
|
|
|
@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
|
|
|
|
@node History Variables
|
|
@section History Variables
|
|
|
|
This section describes the variables in GNU History that are externally
|
|
visible.
|
|
|
|
@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
|
|
|
|
@node History Programming Example
|
|
@section History Programming Example
|
|
|
|
The following snippet of code demonstrates simple use of the GNU History
|
|
Library.
|
|
|
|
@smallexample
|
|
main ()
|
|
@{
|
|
char line[1024], *t;
|
|
int done = 0;
|
|
|
|
line[0] = 0;
|
|
|
|
while (!done)
|
|
@{
|
|
fprintf (stdout, "history%% ");
|
|
t = gets (line);
|
|
|
|
if (!t)
|
|
strcpy (line, "quit");
|
|
|
|
if (line[0])
|
|
@{
|
|
char *expansion;
|
|
int result;
|
|
|
|
using_history ();
|
|
|
|
result = history_expand (line, &expansion);
|
|
strcpy (line, expansion);
|
|
free (expansion);
|
|
if (result)
|
|
fprintf (stderr, "%s\n", line);
|
|
|
|
if (result < 0)
|
|
continue;
|
|
|
|
add_history (line);
|
|
@}
|
|
|
|
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)
|
|
@{
|
|
register HIST_ENTRY **the_list = history_list ();
|
|
register int i;
|
|
|
|
if (the_list)
|
|
for (i = 0; the_list[i]; i++)
|
|
fprintf (stdout, "%d: %s\n",
|
|
i + history_base, the_list[i]->line);
|
|
@}
|
|
if (strncmp (line, "delete", strlen ("delete")) == 0)
|
|
@{
|
|
int which;
|
|
if ((sscanf (line + strlen ("delete"), "%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");
|
|
@}
|
|
@}
|
|
@}
|
|
@}
|
|
@end smallexample
|
|
|
|
|
|
|