-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathij.bash
135 lines (124 loc) · 5.37 KB
/
ij.bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# IJ bash environment
# $Revision: 1.4 $
# See http://mbreen.com/ij.html
# This is free software with NO WARRANTY of any kind.
# License: GNU GPL v3 - see http://www.gnu.org/licenses
# Apart from the following aliases (which can be unaliased),
# a namespace prefix of 'ij' is used in this file so that
# it should be safe to source it globally by default:
# any adjustments - for example, a redefinition of PS1 -
# can be done after the 'source ij.bash'.
alias d=ij_rd
alias h=ij_hist
alias fts=ij_fts
# Prompt as null command transparent to bash on copy/paste.
# (This is not truly transparent since it resets the
# exit status of the last executed command to 0 - so avoid copying
# the prompt where the command following it tests '$?')
PS1=": \W \!; "
# For PS2, this function tries to generate a string of spaces
# of the same visible width as PS1.
# As this is only for aesthetics, it doesn't try very hard.
# If changes to PS1 cause it to fail, it is best to change
# it to simply echo a fixed width string of, say, 3 spaces.
_ij_ps2() {
local dirfull=$(dirs +0)
local dirbase=$(basename $dirfull)
local histnum=$(history 1|sed 's/ *//;s/ .*//;q')
echo $PS1|perl -pe's/\\\[.*?\\\]//g;
s#\\w#'$dirfull'#; s/\\W/'$dirbase'/; s/\\!/'$histnum'/;
s/./ /g;'
}
# _ij_ps2() { echo " "; }
# Now add colour and other non-printing characters...
XF_PROMPT_BACKGROUND="\[\e[37;44;1m\]"
# (use red for root)
((UID == 0)) && XF_PROMPT_BACKGROUND="\[\e[37;41;1m\]"
XF_RESET_BACKGROUND="\[\e[0m\]"
# (extra space after background colour border for readability)
PS1="${XF_PROMPT_BACKGROUND}${PS1}${XF_RESET_BACKGROUND} "
# \r turns the prompt into a mere background colour splash
PS2="${XF_PROMPT_BACKGROUND}\$(_ij_ps2)${XF_RESET_BACKGROUND} \r"
# Keep prompts short by putting anything else, such as the full
# path to the working directory (\w), in the window titlebar.
case $TERM in
xterm*|rxvt|Eterm) PS1="\[\033]0;\A \h \w \007\]$PS1" ;;
esac
# HISTTIMEFORMAT assumed unset (if it is set then there is little
# we can do to cope with the fact, since (1) unsetting it will not
# change the output of previous history lines, and (2), it may
# have been changed - i.e., its current value does not allow us to
# derive a filter for previous commands.
# Annotate directory changes in history: this highlights all
# directory changes and may be especially helpful where the new
# working directory is not obvious from the command, e.g., where
# $CDPATH is used or where 'popd' or an alias effects the cd.
_ij_fixhist() {
# First strip off the history number to retrieve the command.
# Also strip any leading transparent prompts (null commands)
# included with a command line copied from a terminal session.
local cmd=$(history 1|
perl -pe '$. > 1 or s/^ *\d* ( *: .*?; )*// or exit')
local hdir=`dirs +0` # or `pwd -P` (no symlinks) or $PWD (no ~)
[ "$ij_hfirst" ] || ij_hfirst=$hdir
if [ "$hdir" != "$ij_hlast" ]; then
ij_hlast=$hdir
if [ "$cmd" ]; then
cmd=$(echo "$cmd"|sed "s/ *## cd [^\"']\+$//")
local annote=" ## cd $hdir"
let local width=20-${#cmd}+${#annote}
printf -v cmd "%s%${width}s" "$cmd" "$annote"
fi
fi
local hnum=`history 1|sed 's/ *//;s/ .*//;q'`
# Set the history only if a prior command exists.
[ "$cmd" ] && history -s "$cmd"
# In certain circumstances, 'history -s' adds a new entry to
# the history rather than modifying the most recent one.
# Correct for this if necessary.
local hnew=`history 1|sed 's/ *//;s/ .*//;q'`
((hnew==hnum)) || history -d $hnum
}
# bash executes this prior to displaying each primary (PS1) prompt
PROMPT_COMMAND=_ij_fixhist
# Embed the numbers labelling the history output in null commands
# so commands can be line- (triple-click-) copied from it.
# A leading space distinguishes history output from actual prompts.
# One optional argument: the number of commands to be listed.
ij_hist() { history $1|
perl -pe 's/^ *(\d+)(\*?) / / && printf " : %3s%s;",$1,$2'; }
# Filter a Terminal Session copied from an xterm window by turning
# lines not beginning with a transparent prompt into line comments.
# This provides a record which can be fed back into bash to
# repeat the commands. The prompts are stripped from the commands
# unless an argument (conventionally '-p') is passed.
ij_fts() { perl -pe '$p=": .*?;";
if (/^$p/) { '$#' || s/( *$p)*// } else { s/^/# / }'; }
# return to a directory logged in the working directory history
ij_rd() {
local item
unset item
while read; do item[${#item[*]}]="cd $REPLY"; done < \
<(ij_dirhist|head -n -1)
if ((${#item[*]} > 0)); then
local cmd
cmd=$(ijmenu -1 0 -1 "${item[@]}")
if (($? == 0)); then echo $cmd; eval $cmd; fi
else
echo "No directory changes logged." >&2 && false
fi
}
# Outputs the working directory history, most recent last,
# and showing only the most recent visit to each directory
# (so each visited directory is listed only once).
ij_dirhist() {
[ "$ij_hfirst" ] && (echo "## cd $ij_hfirst"; history)|
sed -n "s/.*## cd \([^\"' #]\+\)$/\1/p"|
tac|awk '!x[$0]++{print}'|tac;
}
# Restore a saved directory history for easy navigation via
# ij_rd. Use like this:
# ij_dirhist > ~/dirlog
# ... in a new terminal session:
# ij_restore < ~/dirlog
ij_restore() { while read; do history -s "## cd $REPLY"; done }