HISTORY(3)

✨ HISTORY ✨

Okay bestie, this is history(3) from the Library Functions Manual πŸŽ€ Let's get into it πŸ’…

🌸 NAME 🌸

history β€” GNU History Library πŸ“š

The GNU History Library is Copyright (C) 1989-2025 by the Free Software Foundation, Inc. 🫢

πŸ¦‹ DESCRIPTION πŸ¦‹

Okay so lots of programs ask you for input one line at a time πŸ’­ The GNU History library is the one that keeps track of those lines, can attach arbitrary data to each line, and can pull info from earlier lines when you're writing new ones. Iconic ✨

The History library gives applications functions for managing their history, which is the list of lines you've already typed πŸ“œ Apps can pick which lines get saved, how many commands to keep, save the list to a file, read the list back from a file, and show lines from the history in different formats. The main character of your terminal, honestly πŸ‘‘

πŸ”₯ HISTORY EXPANSION πŸ”₯

The history library has a history expansion feature that is identical to the history expansion in bash πŸ’– This section explains which syntax features you get.

History expansions drop words from the history list right into your input, so repeating commands, grabbing the arguments from a previous command, or fixing a mistake in an old command is super quick πŸƒβ€β™€οΈπŸ’¨

History expansion usually happens right after a complete line is read 🧠 It happens in two parts. First, you figure out which history list entry to use for the substitution. Second, you pick out the bits of that entry you want to add to the current one.

The entry you grab from history is the event, and the parts of that entry you act on are words πŸŽ€ You've got a bunch of modifiers to play with the words you've selected. The entry gets split into words the same way bash does when it reads input, so several words that would normally be separated count as one word if they're wrapped in quotes (check out the description of history_tokenize() below πŸ‘€). The event designator picks the event, the optional word designator picks words out of the event, and the optional modifiers do the editing.

History expansions start whenever the history expansion character shows up, which is ! by default πŸ’œ They can show up anywhere in your input, but they don't nest, so no matryoshka situations πŸͺ†

Only backslash (\) and single quotes can quote the history expansion character πŸ™…β€β™€οΈ

There's a special shortcut for substitution that only works when the quick substitution character (default ^) is the very first character on the line ✨ It grabs the previous history entry, using an event designator equivalent to !!, and swaps one string for another inside it. It's covered below under Event Designators. This is the only history expansion that doesn't start with the history expansion character, so it's kind of the rebel of the group πŸ¦Ήβ€β™€οΈ

🧚 Event Designators 🧚

An event designator is how you point at an entry in the history list πŸ“ It starts at the history expansion character and runs until the word designator if there is one, or the end of the word if there isn't. Unless the reference is absolute, events are counted relative to where you currently are in the history list.

  • ! β€” Starts a history substitution, EXCEPT when it's followed by a blank, newline, carriage return, =, or (. So it's not a substitution in those cases πŸ™ˆ
  • !n β€” Goes to history list entry n πŸ”’
  • !-n β€” Goes back n entries from the current one πŸ”™
  • !! β€” Goes to the previous entry. This is a synonym for β€œ!-1” πŸ’…
  • !string β€” Goes to the most recent command before your current position in the history list that starts with string πŸ”
  • !?string[?] β€” Goes to the most recent command before your current position in the history list that contains string πŸ•΅οΈβ€β™€οΈ The trailing ? can be left out if string is followed right away by a newline. If string is missing, it uses the string from the most recent search instead. And if there was no previous search string, that's an error, so be careful 🚨
  • ^string1^string2^ β€” Quick substitution! It repeats the previous command and swaps string1 for string2. This is equivalent to β€œ!!:s^string1^string2^” (see Modifiers below) ✨
  • !# β€” The entire command line you've typed so far 🧾

🎯 Word Designators 🎯

Word designators let you select the exact words you want from the event πŸ’– They're optional. If you don't include one, the history expansion uses the entire event. A : separates the event specification from the word designator, and it can be left out if the word designator starts with a ^, $, *, -, or %. Words are numbered from the beginning of the line, and the first word is numbered 0 (zero) πŸ”’ When words get inserted into the current line, they're separated by single spaces.

  • 0 (zero) β€” The zeroth word. For the shell, and lots of other apps, that's the command word πŸš€
  • n β€” The *n*th word 🎯
  • ^ β€” The first argument, which is word 1 πŸ₯‡
  • $ β€” The last word. This is usually the last argument, but if the line only has one word, it expands to the zeroth word instead 🫠
  • % β€” The first word matched by the most recent β€œ?string?” search, but only if the search string starts with a character that's part of a word πŸ”Ž By default, searches start at the end of each line and go toward the beginning, so the first match is the one closest to the end of the line 🏁
  • x-y β€” A range of words. β€œ-y” is short for β€œ0-y” πŸ“
  • * β€” All of the words except the zeroth. This is a synonym for β€œ1-$” 🌈 It's not an error to use * when the event only has one word; in that case it just expands to the empty string 🫧
  • x* β€” Short for x-$ πŸ’«
  • x- β€” Short for x-$ like x*, but it leaves out the last word πŸ‘‹ If x is missing, it defaults to 0.

If you give a word designator without an event specification, the previous command gets used as the event, which is the same as !! 🧁

πŸ› οΈ Modifiers πŸ› οΈ

After the optional word designator, the expansion can have a bunch of the following modifiers, one or more in a row, and each one has to start with a β€œ:” πŸ’… They edit the word or words you picked out of the history event, kind of like a glow-up for your command πŸ’„

  • h β€” Removes a trailing filename component and leaves only the head πŸ—‚οΈ
  • t β€” Removes all the leading filename components and leaves only the tail πŸͺΆ
  • r β€” Removes a trailing suffix of the form .xxx and leaves the basename βœ‚οΈ
  • e β€” Removes everything except the trailing suffix πŸ§ƒ
  • p β€” Prints the new command but does NOT run it πŸ‘€ Good for checking before committing 🫢
  • q β€” Quotes the substituted words, which also stops any further substitutions from happening πŸ”’
  • x β€” Quotes the substituted words like q does, but also breaks them into words at blanks and newlines πŸ’₯ The q and x modifiers are mutually exclusive, so the expansion uses whichever one you typed last πŸ™ƒ
  • s/old/new/ β€” Swaps new in for the first occurrence of old in the event line πŸ”„ Any character can be the delimiter instead of /. The final delimiter is optional if it's the last character of the event line. A single backslash quotes the delimiter inside old and new. If & shows up in new, it gets replaced with old, and a single backslash quotes the & too 🧷 If old is null, it gets set to the last old that was substituted or, if no previous history substitutions happened, the last string from a !?string[?] search πŸ” If new is null, every matching old gets deleted πŸ—‘οΈ
  • & β€” Repeats the previous substitution πŸ”
  • g β€” Applies the changes across the entire event line 🌍 This gets used with β€œ:s” (like β€œ:gs/old/new/”) or β€œ:&”. If you use it with β€œ:s”, any delimiter works in place of /, and the final delimiter is optional if it's the last character of the event line. An a can be used as a synonym for g πŸ’•
  • G β€” Applies the following s or & modifier once to each word in the event line 🫧

πŸŽ€ PROGRAMMING WITH HISTORY FUNCTIONS πŸŽ€

This section is for when you're writing your own programs with the History library πŸ’»βœ¨

🌷 Introduction to History 🌷

A programmer using the History library gets functions for remembering lines on a history list, attaching arbitrary data to a line, removing lines from the list, searching the list for a line that contains an arbitrary text string, and referencing any line in the list directly πŸ” There's also a history expansion function, which gives different programs a consistent user interface 🫢

Users of programs built with the History library get a consistent interface too, 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 identical to the history substitution provided by bash πŸ’–

Programmers can also use the readline library, which already includes some history manipulation by default and has the extra perk of command line editing πŸ–ŠοΈβœ¨

Before you declare any functions that use the History library's functionality in your code, include the file <readline/history.h> in every file that uses the History library's features πŸ“ It supplies extern declarations for all of the library's public functions and variables, and it declares all of the public data structures 🧚

πŸ“¦ History Storage πŸ“¦

The history list is an array of history entries πŸ“š A history entry is declared like this:

typedef void * histdata_t;

typedef struct _hist_entry {
  char *line;
  char *timestamp;
  histdata_t data;
} HIST_ENTRY;

The history list itself might therefore be declared as

HIST_ENTRY ** the_history_list;

The whole state of the History library is wrapped up in a single structure 🎁

/*
 * A structure used to pass around the current state of the history.
 */
typedef struct _hist_state {
  HIST_ENTRY **entries; /* Pointer to entry records. */
  int offset;           /* The current record. */
  int length;           /* Number of records in list. */
  int size;             /* Number of records allocated. */
  int flags;
} HISTORY_STATE;

If the flags member includes HS_STIFLED, the history has been stifled πŸ™Š

πŸ’« History Functions πŸ’«

This section explains the calling sequence for the various functions exported by the GNU History library πŸ“ž

πŸŒ™ Initializing History and State Management πŸŒ™

This section covers the functions you use to initialize and manage the state of the History library when you want to use the history functions in your program πŸ› οΈ

void using_history (void)

Starts a session in which the history functions might be used. This initializes the interactive variables 🌱

HISTORY_STATE * history_get_history_state (void)

Returns a structure describing the current state of the input history πŸ“Έ

void history_set_history_state (HISTORY_STATE *state)

Sets the state of the history list according to state πŸ”§

✨ History List Management ✨

okay so these functions handle individual entries on the history list, or tweak the settings for the list itself πŸ’…

void add_history (const char *string)

slide string onto the very end of the history list πŸ’–. The associated data field (if there is one) gets set to NULL. If you've already set a cap with stifle_history() and this new entry would push you over it, the oldest entry gets removed πŸ—‘οΈ

void add_history_time (const char *string)

this one changes the time stamp on the most recent history entry so it now says string πŸ•°οΈ

HIST_ENTRY * remove_history (int which)

removes the history entry at offset which 🫢 the removed element is handed back to you so you can free the line, the data, and the containing structure. don't forget to clean up after yourself bestie 🧹

histdata_t free_history_entry (HIST_ENTRY *histent)

frees the history entry histent along with any private data the history library attached to it. it returns the application-specific data so you can dispose of it however you like ✨

HIST_ENTRY * replace_history_entry (int which, const char *line, histdata_t data)

this swaps the entry at offset which so it now has line and data πŸ”„ you get the old entry back so you can deal with any application-specific data it was carrying. if which is invalid, you get a NULL pointer back πŸ™ˆ

void clear_history (void)

wipes the entire history list by deleting every single entry. fresh start era 🧼

void stifle_history (int max)

stifles the history list so it only remembers the last max entries 🀏 the list will hold only max entries at any one time.

int unstifle_history (void)

stops stifling the history πŸ›‘ it returns the previously-set maximum number of history entries (as set by stifle_history()). history was stifled. the value is positive if the history was stifled, and negative if it wasn't.

int history_is_stifled (void)

returns non-zero if the history is stifled, and zero if it isn't πŸ’œ

✨ Information About the History List ✨

these functions give you info about the whole history list or about individual entries πŸ”

HIST_ENTRY ** history_list (void)

returns a NULL terminated array of HIST_ENTRY * containing the current input history πŸ“œ element 0 of this list is the beginning of time 🌌. if there's no history at all, you get NULL back.

int where_history (void)

returns the offset of the current history element πŸ“

HIST_ENTRY * current_history (void)

returns the history entry at the current position, as decided by where_history(). if nothing lives there, you get a NULL pointer πŸ«₯

HIST_ENTRY * history_get (int offset)

returns the history entry at position offset 🎯 valid values of offset start at history_base and go up to history_length - 1. if there's no entry there, or if offset is outside that valid range, you get a NULL pointer back ❌

time_t history_get_time (HIST_ENTRY *)

returns the time stamp attached to the history entry you pass in as the argument ⏰

int history_total_bytes (void)

returns the number of bytes the primary history entries are using πŸ’Ύ this is the sum of the lengths of all the lines in the history.

✨ Moving Around the History List ✨

these functions let you set or change the current index into the history list 🧭

int history_set_pos (int pos)

sets the current history offset to pos, which is an absolute index into the list πŸ“Œ returns 1 on success, and 0 if pos is less than zero or greater than the number of history entries.

HIST_ENTRY * previous_history (void)

backs the current history offset up to the previous history entry and gives you a pointer to that entry ⬅️ if there's no previous entry, you get a NULL pointer.

HIST_ENTRY * next_history (void)

if the current history offset points at a valid history entry, it gets incremented ➑️ then, if the possibly-incremented offset points at a valid entry, you get a pointer to that entry. otherwise you get a NULL pointer.

✨ Searching the History List ✨

these functions let you hunt through the history list for entries containing a specific string πŸ”Ž you can search forward and backward from the current history position. the search can also be anchored, which means the string has to match right at the beginning of the history entry 🎯

int history_search (const char *string, int direction)

searches the history for string, starting at the current history offset πŸ•΅οΈ if direction is less than 0, the search goes through previous entries, otherwise it goes through subsequent entries. if string is found, the current history index gets set to that entry, and the value returned is the offset in the line of the entry where string was found. otherwise nothing changes and the function returns -1.

int history_search_prefix (const char *string, int direction)

searches the history for string, starting at the current history offset πŸ”€ this search is anchored, so matching lines must begin with string. if direction is less than 0, the search goes through previous entries, otherwise through subsequent ones. if string is found, the current history index is set to that entry and the return value is 0. otherwise nothing changes and the function returns -1.

int history_search_pos (const char *string, int direction, int pos)

searches for string in the history list, starting at pos, an absolute index into the list πŸ“ if direction is negative, the search moves backward from pos, otherwise it moves forward. it returns the absolute index of the history element where string was found, or -1 if it wasn't found.

✨ Managing the History File ✨

the History library can read the history from a file and write it back out again πŸ“ this section covers the functions for handling a history file.

int read_history (const char *filename)

adds the contents of filename to the history list, one line at a time πŸ“– if filename is NULL, it reads from ~/.history. returns 0 if it works, or errno if it doesn't.

int read_history_range (const char *filename, int from, int to)

reads a range of lines from filename and adds them to the history list βœ‚οΈ it starts reading at line from and ends at to. if from is zero, it starts at the beginning. if to is less than from, it reads until the end of the file. if filename is NULL, it reads from ~/.history. returns 0 if successful, or errno if not.

int write_history (const char *filename)

writes the current history to filename, overwriting filename if necessary ✍️ if filename is NULL, the history list gets written to ~/.history. returns 0 on success, or errno on a read or write error.

int append_history (int nelements, const char *filename)

appends the last nelements of the history list to filename βž• if filename is NULL, it appends to ~/.history. returns 0 on success, or errno on a read or write error.

int history_truncate_file (const char *filename, int nlines)

truncates the history file filename, leaving only the last nlines lines βœ‚οΈ if filename is NULL, then ~/.history gets truncated. returns 0 on success, or errno on failure.

✨ History Expansion ✨

these functions handle history expansion πŸͺ„

int history_expand (const char *string, char **output)

expands string and places the result into output, which is a pointer to a string πŸŽ€ it returns:

  • 0 β€” if no expansions took place (or, if the only change in the text was the removal of escape characters preceding the history expansion character);
  • 1 β€” if expansions did take place;
  • -1 β€” if there was an error in expansion;
  • 2 β€” if the returned line should be displayed but not executed, as with the :p modifier.

if an error occurred in expansion, then output contains a descriptive error message 🚨

char * get_history_event (const char *string, int *cindex, int qchar)

returns the text of the history event beginning at string + *cindex 🧾 *cindex gets modified so it points to just after the event specifier. when the function is entered, cindex points to the index into string where the history event specification begins. qchar is a character that's allowed to end the event specification, on top of the "normal" terminating characters ✨

char ** history_tokenize (const char *string)

returns an array of tokens parsed out of string, kind of like how the shell would do it 🐚 the tokens are split on the characters in the history_word_delimiters variable, and shell quoting conventions are obeyed.

char * history_arg_extract (int first, int last, const char *string)

extracts a string segment made up of the first through last arguments present in string βœ‚οΈ arguments are split using history_tokenize().

✨ History Variables ✨

this section covers the externally-visible variables exported by the GNU History Library πŸ‘‘

int history_base

the logical offset of the first entry in the history list πŸ₯‡

int history_length

the number of entries currently stored in the history list πŸ”’

int history_max_entries

the maximum number of history entries 🧒 this must be changed using stifle_history().

int history_write_timestamps

if non-zero, timestamps get written to the history file so they can be preserved between sessions ⏳ the default value is 0, meaning timestamps are not saved. the current timestamp format uses the value of history_comment_char to delimit timestamp entries in the history file. if that variable doesn't have a value (which is the default), the history library won't write timestamps πŸ™…β€β™€οΈ

char history_expansion_char

the character that introduces a history event 🎬 the default is !. setting this to 0 inhibits history expansion 🚫

char history_subst_char

the character that invokes word substitution if it's found at the start of a line πŸ” the default is ^.

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 πŸ™Š this suppresses history expansion for the rest of the line. it's disabled by default.

char * history_word_delimiters

the characters that separate tokens for history_tokenize() 🧩 the default value is " \t\n()<>;&|".

char * history_no_expand_chars

the list of characters that inhibit history expansion if they're found immediately following history_expansion_char πŸ›‘ the default is space, tab, newline, \r, and =.

char * history_search_delimiter_chars

the list of additional characters that can delimit a history search string, on top of space, tab, : and ? in the case of a substring search πŸ” the default is empty.

int history_quotes_inhibit_expansion

if non-zero, the history expansion code implements shell-like quoting 🐚 single-quoted words are not scanned for the history expansion character or the history comment character, and double-quoted words may have history expansion performed, since single quotes aren't special within double quotes. the default value is 0 πŸ’…

Okay bestie, let's pick up where we left off πŸ’…

✨ int history_quoting_state ✨

An application can set this variable to say the line it's currently expanding is already inside some quotes πŸŽ€ If it's set to ', history expansion assumes the line is single-quoted and skips expansion until it hits an unquoted closing single quote. If it's set to ", history expansion assumes the line is double-quoted until it hits an unquoted closing double quote. If it's set to zero (the default), history expansion assumes the line isn't quoted at all and treats quote characters in the line the way we just talked about. This only does anything if history_quotes_inhibit_expansion is set 🫢

✨ rl_linebuf_func_t * history_inhibit_expansion_function ✨

This one should be set to the address of a function that takes two arguments: a char * (a string) and an int index into that string (i) πŸ’œ It should return a non-zero value if the history expansion starting at string[i] should not happen, and zero if the expansion should go ahead. It's meant for apps like bash that use the history expansion character for extra stuff, so it's giving multi-purpose energy 🧚 By default, this variable is set to NULL.


✨ FILES ✨

~/.history : Default filename for reading and writing saved history πŸ“πŸŒΈ

✨ SEE ALSO ✨

  • The Gnu Readline Library, Brian Fox and Chet Ramey πŸ“š
  • The Gnu History Library, Brian Fox and Chet Ramey πŸ“š
  • bash(1) 🐚
  • readline(3) πŸ¦‹

✨ AUTHORS ✨

Brian Fox, Free Software Foundation πŸ‘‘ bfox@gnu.org

Chet Ramey, Case Western Reserve University πŸ‘‘ chet.ramey@case.edu

✨ BUG REPORTS ✨

If you find a bug in the history library, you should report it πŸ™ˆ But first, make sure it's really a bug, and that it shows up in the latest version of the history library you have. Literally double-check, bestie.

Once you've confirmed a bug actually exists, email a bug report to bug-readline@gnu.org πŸ’Œ If you have a fix, you're welcome to send that too, slay! Suggestions and β€œphilosophical” bug reports can go to bug-readline@gnu.org or get posted to the Usenet newsgroup gnu.bash.bug 🫢

Comments and bug reports about this manual page should go to chet.ramey@case.edu πŸ’–


That's the whole tea, bestie β˜•βœ¨ This page is from GNU History 8.3, last updated 2024 December 31, and it's filed under HISTORY(3) πŸŽ€ Stay iconic, stay curious, and I'll see you in the next chat πŸ¦‹πŸ’…

πŸ“¦ where this page comes from