diff options
Diffstat (limited to 'bashhist.c')
-rw-r--r-- | bashhist.c | 92 |
1 files changed, 68 insertions, 24 deletions
@@ -1,6 +1,6 @@ /* bashhist.c -- bash interface to the GNU history library. */ -/* Copyright (C) 1993 Free Software Foundation, Inc. +/* Copyright (C) 1993-2004 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -36,6 +36,8 @@ #include "posixstat.h" #include "filecntl.h" +#include "bashintl.h" + #include "shell.h" #include "flags.h" #include "input.h" @@ -50,6 +52,7 @@ #if defined (READLINE) # include "bashline.h" +extern int rl_done, rl_dispatching; /* should really include readline.h */ #endif #if !defined (errno) @@ -58,6 +61,7 @@ extern int errno; static int histignore_item_func __P((struct ign *)); static int check_history_control __P((char *)); +static void hc_erasedups __P((char *)); static void really_add_history __P((char *)); static struct ignorevar histignore = @@ -77,7 +81,10 @@ static struct ignorevar histignore = becomes zero when we read lines from a file, for example. */ int remember_on_history = 1; -/* The number of lines that Bash has added to this history session. */ +/* The number of lines that Bash has added to this history session. The + difference between the number of the top element in the history list + (offset from history_base) and the number of lines in the history file. + Appending this session's history to the history file resets this to 0. */ int history_lines_this_session; /* The number of lines that Bash has read from the history file. */ @@ -134,10 +141,14 @@ int literal_history; exit, even if the history has been stifled. */ int force_append_history; -/* A nit for picking at history saving. - Value of 0 means save all lines parsed by the shell on the history. - Value of 1 means save all lines that do not start with a space. - Value of 2 means save all lines that do not match the last line saved. */ +/* A nit for picking at history saving. Flags have the following values: + + Value == 0 means save all lines parsed by the shell on the history. + Value & HC_IGNSPACE means save all lines that do not start with a space. + Value & HC_IGNDUPS means save all lines that do not match the last + line saved. + Value & HC_ERASEDUPS means to remove all other matching lines from the + history list before saving the latest line. */ int history_control; /* Set to 1 if the last command was added to the history list successfully @@ -206,6 +217,7 @@ bash_initialize_history () history_quotes_inhibit_expansion = 1; history_search_delimiter_chars = ";&()|<>"; history_inhibit_expansion_function = bash_history_inhibit_expansion; + sv_histchars ("histchars"); } void @@ -307,7 +319,7 @@ maybe_append_history (filename) fd = open (filename, O_WRONLY|O_CREAT, 0600); if (fd < 0) { - builtin_error ("%s: cannot create: %s", filename, strerror (errno)); + builtin_error (_("%s: cannot create: %s"), filename, strerror (errno)); return (EXECUTION_FAILURE); } close (fd); @@ -433,12 +445,19 @@ pre_process_line (line, print_changes, addit) /* If there was an error, return NULL. */ if (expanded < 0 || expanded == 2) /* 2 == print only */ { +# if defined (READLINE) + if (expanded == 2 && rl_dispatching == 0 && *history_value) +# else + if (expanded == 2 && *history_value) +# endif /* !READLINE */ + maybe_add_history (history_value); + free (history_value); # if defined (READLINE) /* New hack. We can allow the user to edit the failed history expansion. */ - if (history_reediting && expanded < 0) + if (history_reediting && expanded < 0 && rl_done) re_edit (line); # endif /* READLINE */ return ((char *)NULL); @@ -511,27 +530,49 @@ check_history_control (line) HIST_ENTRY *temp; int r; - switch (history_control) + if (history_control == 0) + return 1; + + /* ignorespace or ignoreboth */ + if ((history_control & HC_IGNSPACE) && *line == ' ') + return 0; + + /* ignoredups or ignoreboth */ + if (history_control & HC_IGNDUPS) { - case 0: /* nothing */ - return 1; - case 1: /* ignorespace */ - return (*line != ' '); - case 3: /* ignoreboth */ - if (*line == ' ') - return 0; - /* FALLTHROUGH if case == 3 (`ignoreboth') */ - case 2: /* ignoredups */ using_history (); temp = previous_history (); r = (temp == 0 || STREQ (temp->line, line) == 0); using_history (); - return r; + + if (r == 0) + return r; } - return 0; + return 1; +} + +/* Remove all entries matching LINE from the history list. Triggered when + HISTCONTROL includes `erasedups'. */ +static void +hc_erasedups (line) + char *line; +{ + HIST_ENTRY *temp; + int r; + + using_history (); + while (temp = previous_history ()) + { + if (STREQ (temp->line, line)) + { + r = where_history (); + remove_history (r); + } + } + using_history (); } /* Add LINE to the history list, handling possibly multi-line compound @@ -577,6 +618,11 @@ check_add_history (line, force) { if (check_history_control (line) && history_should_ignore (line) == 0) { + /* We're committed to saving the line. If the user has requested it, + remove other matching lines from the history. */ + if (history_control & HC_ERASEDUPS) + hc_erasedups (line); + if (force) { really_add_history (line); @@ -635,10 +681,8 @@ bash_add_history (line) free (new_line); if (old) - { - FREE (old->line); - free (old); - } + free_history_entry (old); + add_it = 0; } } |