-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 8e2f2af
Showing
2 changed files
with
263 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
HISTORY RECALL PROJECT | ||
|
||
Manage bash history from multiple terminal windows in a sane and | ||
rational way. | ||
|
||
For a quick start, scroll down for installation and usage. | ||
|
||
|
||
INTRODUCTION | ||
|
||
---------------------------------------------------- | ||
> Those who forget the past are doomed to retype it. | ||
> - [George Santayana][1] (paraphrased) | ||
---------------------------------------------------- | ||
|
||
The history recall project helps organize your bash history. | ||
If you have ever been in the position where you are trying | ||
to find the one terminal window that you used to enter an | ||
obscure command so that you can use your bash history to | ||
recall it, then you may be looking for a better way to manage | ||
your history. | ||
|
||
Aside: Note that if you would like to share a single | ||
bash history across *all* of your terminal windows, there | ||
is a simple solution: | ||
|
||
$ unset HISTFILESIZE | ||
$ export PROMPT_COMMAND="history -a" | ||
$ shopt -s histappend | ||
|
||
For more information on this, see [The Definitive Guide to | ||
Bash Command Line History][2]. If, however, you are accustomed | ||
to doing different tasks in different terminals, and in general | ||
*like* the fact that your history is segregated by terminal window, | ||
then a more complicated solution may meet your needs better. | ||
History Recall is just such a solution. | ||
|
||
|
||
USAGE | ||
|
||
Docs to-be-written. See the script itself. | ||
|
||
|
||
INSTALLATION | ||
|
||
The History Recall commands are all implemented as bash functions | ||
defined in a single historyrc file. To install, all that you need | ||
to do is source this file. First, clone the project from github: | ||
|
||
cd ~/local | ||
git clone https://github.com/greg-1-anderson/history-recall | ||
|
||
Then source the file when your bash shell starts up. | ||
|
||
*In ~/.bashrc | ||
source ~/local/history-recall/historyrc | ||
|
||
Once you have installed History Recall, you must either re-source | ||
your .bashrc file or close and re-open your terminal windows. | ||
Once you do this, your bash history will be saved in a separate file | ||
for each terminal window, and your history will persist across reboots. | ||
|
||
Nifty. | ||
|
||
|
||
[1]: http://en.wikipedia.org/wiki/George_Santayana | ||
[2]: http://www.catonmat.net/blog/the-definitive-guide-to-bash-command-line-history/ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
# History configuration | ||
# c.f. http://www.catonmat.net/blog/the-definitive-guide-to-bash-command-line-history/ | ||
shopt -s histappend | ||
shopt -s histreedit | ||
mkdir -p $HOME/.history | ||
# If $HISTFILE is in the home directory, then make a new history file unique to this tty | ||
if [ $(dirname "$HISTFILE") == "$HOME" ] | ||
then | ||
TTY=$(tty | tr / _) | ||
HOSTNAME=$(hostname -s) | ||
export HISTFILE="$HOME/.history/bash_${HOSTNAME}${TTY}" | ||
if [ -f "$HISTFILE" ] | ||
then | ||
history -r | ||
fi | ||
fi | ||
export HISTIGNORE="&:[ ]*:ls:hist.*:exit" | ||
export PROMPT_COMMAND="$PROMPT_COMMAND"'; HISTTIMEFORMAT="[%m/%d@%H:%M:%S] " history -a' | ||
|
||
# Print command history including execution times, for this run of 'history' only | ||
alias histt='HISTTIMEFORMAT="[%m/%d@%H:%M:%S] " history' | ||
|
||
# Make a note in command history | ||
# Usage: | ||
# $ note COMMAND // comment | ||
# command output | ||
# $ recall comment | ||
# command output | ||
# The 'note' command embeds the output of the supplied command | ||
# into the bash history file. This command output may be printed | ||
# out again verbatim later with the 'recall' command. | ||
function note { | ||
t=$(date "+%s") | ||
p=(); | ||
c=false | ||
for a in "$@"; | ||
do | ||
if $c || [ "x$a" == "x//" ] | ||
then | ||
c=true | ||
else | ||
p[${#p[@]}]="$a"; | ||
fi | ||
done | ||
echo "#$t >>" $* >> $HISTFILE | ||
COLUMNS=$((COLUMNS-5-${#t})) "${p[@]}" | sed -e "s/^/#$t :: /" | tee -a $HISTFILE | sed -e 's/^#[^:]*:: //' | ||
} | ||
|
||
# Begin a new task: switch to a new command history | ||
# file, and make a note in it. We'll copy existing | ||
# history over, just in case we did some stuff relevant | ||
# to the current task before declaring it. | ||
# Usage: | ||
# $ task Install whizzy-fu pro | ||
# begin task: Install whizzy-fu pro | ||
# $ sudu apt-get install whizzyfu libwhizzyfu-dev | ||
# $ ... lots of other stuff | ||
# $ finished | ||
# finished task: Install whizzy-fu pro | ||
# | ||
# ... a few days later, in a different terminal: | ||
# $ recall whizzy | ||
# # Fri Oct 12 11:06:43 PDT 2012 | ||
# recalled task: Install whizzy-fu pro | ||
# $ ^Rapt-get | ||
# (reverse-i-search)`sudo apt-get': sudo apt-get install whizzyfu libwhizzyfu-dev | ||
function task { | ||
t=$(date "+%s") | ||
task=$(echo $* | tr A-Z a-z | sed -e 's/ /_/g' -e 's/[^a-z0-9_]//g') | ||
taskfile="$HOME/.history/task_$task" | ||
history -a | ||
histpush "$taskfile" | ||
note echo "begin task: $*" // $HISTFILE | ||
echo "HISTFILE is now $HISTFILE" | ||
} | ||
|
||
# Complete a task and go back to previous HISTFILE. Optional. | ||
function finished { | ||
l=$(grep "^#[0-9]\+ :: begin task:" $HISTFILE | tail -n 1) | ||
if [ -z "$l" ] | ||
then | ||
echo "finished: no task in progress" | ||
else | ||
m=$(echo $l | sed -e 's/^#[^>]*:: begin/finished/') | ||
echo $m | ||
histpop | ||
fi | ||
} | ||
|
||
# Show all active nested tasks in this terminal | ||
function tasks { | ||
for f in $HISTFILE $(echo $HISTFILES | tr : ' ') ; do | ||
if [ ${f:0:1} != '/' ] | ||
then | ||
f="$HOME/.history/$f" | ||
fi | ||
l=$(grep -Hm 1 "^#[0-9]\+ >>.*$*" $f) | ||
t=$(echo $l | sed -e 's/^[^#]*#\([0-9]\+\).*/\1/') | ||
c=$(echo $l | sed -e 's/^[^>]*>> *//') | ||
d=$(date --date="@$t") | ||
n=${c#*:} | ||
sn=${n%% //*} | ||
echo "$(basename $f):$sn // $d" | ||
done | ||
} | ||
|
||
# grep all history files for a command pattern | ||
function hgrep { | ||
( | ||
cd $HOME/.history | ||
grep $* $HISTFILE $(ls -t | grep -v $(basename $HISTFILE)) | grep -v '^[^:]*:#' | ||
) | ||
} | ||
|
||
# Show the output of a command passed to 'note', or switch back to a | ||
# task (and corresponding history file) from the past. | ||
function recall { | ||
l=$(cd $HOME/.history && grep "^#[0-9]\+ >>.*$*" $HISTFILE $(ls -t) | tail -n 1) | ||
if [ -z "$l" ] | ||
then | ||
echo "recall: cannot find $*: No such note or task" | ||
else | ||
f=$(echo $l | sed -e 's/^\([^:]*\):#.*/\1/') | ||
if [ ${f:0:1} != '/' ] | ||
then | ||
f="$HOME/.history/$f" | ||
fi | ||
t=$(echo $l | sed -e 's/^[^#]*#\([0-9]\+\).*/\1/') | ||
c=$(echo $l | sed -e 's/^[^>]*>> *//') | ||
d=$(date --date="@$t") | ||
if [ "${c%%:*}" == "echo begin task" ] | ||
then | ||
n=${c#*:} | ||
if [ "$HISTFILE" == "$f" ] | ||
then | ||
echo "# $d" | ||
echo "${c#* }" | ||
else | ||
echo "# $d" | ||
echo "resume task: $n" | ||
histpush "$f" | ||
echo "HISTFILE is now $HISTFILE" | ||
fi | ||
else | ||
if [ "$HISTFILE" != "$f" ] | ||
then | ||
echo "recall: found note in $f" | ||
fi | ||
if [ "${c%% *}" == "echo" ] | ||
then | ||
echo "# $d" | ||
echo "${c#* }" | ||
else | ||
echo "# $d" | ||
echo "\$ $c" | ||
grep "#$t :: " $HISTFILE | sed -e 's/^#[0-9]* :: //' | ||
fi | ||
fi | ||
fi | ||
} | ||
|
||
# Start using a new history file. Keep a stack of previous | ||
# history files so they may be returned to at a later time. | ||
function histpush { | ||
if [ -n "$1" ] | ||
then | ||
if [ -n "$HISTFILES" ] | ||
then | ||
export HISTFILES="$HISTFILE" | ||
else | ||
export HISTFILES="$HISTFILES:$HISTFILE" | ||
fi | ||
export HISTFILE="$1" | ||
history -r | ||
fi | ||
} | ||
|
||
# Resume using a history file that was in use in the past. | ||
function histpop { | ||
if [ -n "$HISTFILES" ] | ||
then | ||
export HISTFILE="${HISTFILES%%:*}" | ||
history -r | ||
if [ "${HISTFILES/:/}" == "$HISTFILES" ] | ||
then | ||
export HISTFILES= | ||
else | ||
export HISTFILES="${HISTFILES#*:}" | ||
fi | ||
else | ||
echo "histpop: HISTFILES is empty" | ||
fi | ||
echo "HISTFILE restored to $HISTFILE" | ||
} | ||
|