489 lines
		
	
	
	
		
			17 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			489 lines
		
	
	
	
		
			17 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
| @ignore
 | |
| This file documents the user interface to the GNU History library.
 | |
| 
 | |
| Copyright (C) 1988, 1991 Free Software Foundation, Inc.
 | |
| 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
 | |
| 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 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}.
 | |
| 
 | |
| @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 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 @dfn{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 @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 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;
 | |
|   char *data;
 | |
| @} 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.
 | |
| 
 | |
| @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
 | |
| 
 | |
| @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 deftypefun
 | |
| 
 | |
| @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 deftypefun
 | |
| 
 | |
| @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
 | |
| 
 | |
| @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.  The value is positive if the history was
 | |
| stifled, negative if it wasn't.
 | |
| @end deftypefun
 | |
| 
 | |
| @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 deftypefun
 | |
| 
 | |
| @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 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 deftypefun
 | |
| 
 | |
| @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 deftypefun
 | |
| 
 | |
| @deftypefun int append_history (int nelements, char *filename)
 | |
| Append the last @var{nelements} of the history list to @var{filename}.
 | |
| @end deftypefun
 | |
| 
 | |
| @deftypefun int history_truncate_file (char *filename, int nlines)
 | |
| Truncate the history file @var{filename}, leaving only the last
 | |
| @var{nlines} lines.
 | |
| @end deftypefun
 | |
| 
 | |
| @node History Expansion
 | |
| @subsection History Expansion
 | |
| 
 | |
| These functions implement @code{csh}-like history expansion.
 | |
| 
 | |
| @deftypefun int history_expand (char *string, char **output)
 | |
| Expand @var{string}, placing the result into @var{output}, a pointer
 | |
| 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);
 | |
| @item 1
 | |
| if expansions did take place;
 | |
| @item -1
 | |
| 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 deftypefun
 | |
| 
 | |
| @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 Bash.
 | |
| @end deftypefun
 | |
| 
 | |
| @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 externally visible variables exported by
 | |
| the GNU History Library.
 | |
| 
 | |
| @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 program demonstrates simple use of the GNU History Library.
 | |
| 
 | |
| @smallexample
 | |
| 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");
 | |
|             @}
 | |
|         @}
 | |
|     @}
 | |
| @}
 | |
| @end smallexample
 | 
