-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathextended_cd.bashrc
executable file
·334 lines (269 loc) · 11.3 KB
/
extended_cd.bashrc
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
#################################################################################
## File: extended_cd.bashrc
## Des: Define a function to wrap the cd-builtin command, with extra features.
## Author: Darin Kelkhoff
## Notes:
## Todo:
## Modified: Fri Aug 10 2007
##################################################################################
################################################
## define the max size of the CD_HISTORY file ##
################################################
CD_HISTORY_SIZE=250
########################################################
## define the location of the CD_HISTORY file (and a ##
## location for a tmp copy of it while rebuilding it) ##
########################################################
CD_HISTORY=~/.cd_history
CD_HISTORY_NEW=~/.cd_history.new
##########################################################################
## Function: cd
## Desc: customzed cd command, that looks for specific patterns to help
## navigate the file system faster.
## Args: the first argument is checked for the patterns as described
## in usage block below
## Input:
## Output:
## Notes: Future ideas:
##########################################################################
function cd
{
arg="$1";
######################################
## make sure CD_HISTORY file exists ##
######################################
if [ ! -e $CD_HISTORY ]; then
touch $CD_HISTORY
fi
###############################
## check for a help argument ##
###############################
if [ "$arg" = "-h" -o "$arg" = "-help" -o "$arg" = "--help" ]; then
builtin cd -help 2>&1 | grep -v "invalid option"
############
## usage: ##
############
echo
echo "For extended features, use the following for [dir] (not compatible with [-L|-P] flags):"
echo " ?pattern - Pick directory from cd_history matching <pattern>."
echo " .?pattern - Pick directory from cd_history matching <pattern>, under cwd."
echo " _ - Go to last entry in cd_history."
echo " _number - Go to <number>'th last entry in cd_history."
echo " ...pattern - Go up (multiple ../'s) to directory matching <pattern>."
echo " ^old^new - Go to pwd, with pattern <old> replaced with <new>"
echo " _? - List cd_history, prompt to select directory."
echo " _?number - List last <number> cd_history entries, prompt to select directory."
return;
fi
####################################################
## sometimes one accidentally says "cd cd foo" -- ##
## if so, strip off the accidental cd argument ##
####################################################
if [ "$arg" = "cd" -a \! -z "$2" ]; then
arg="$2";
fi
#################################################################
## check if invoked with an argument starting with a ? or a .? ##
#################################################################
if [ $(echo "$arg" | grep "^\.\??") ]; then
############################################
## if the argument started with dot, set ##
## pwd.* as the start of the grep pattern ##
############################################
patternPrefix=""
if [ $(echo "$arg" | grep "^\.") ]; then
patternPrefix="$(pwd).*"
fi
#################################################################
## look for a pattern after the ?, to filter the cd_history by ##
#################################################################
pattern=${patternPrefix}$(echo "$arg" | sed "s/^\.//" | sed "s/^?//");
##########################################################
## if pattern not given, default it to . (to match all) ##
##########################################################
if [ -z "$pattern" ]; then
pattern="."
fi
#####################################################################
## read the the cd history, sorted -u, and filtered by the pattern ##
#####################################################################
history=$(sort -u $CD_HISTORY | grep -e "$pattern")
if [ -z "$history" ]; then
echo "Sorry, no applicable cd history.";
return;
fi
#################################
## prompt user for where to go ##
#################################
_cd_prompt "$history" "cat"
######################################################
## check for special argument "_" -- go to nth-last ##
## dir switched to, as recorded in history file ##
######################################################
elif [ $(echo "$arg" | grep "^_?\?[0-9]*$") ]; then
########################################################
## check for _? - to do prompting from end of history ##
########################################################
doPrompt=""
if [ $(echo "$arg" | grep "^_?") ]; then
doPrompt="1"
fi
############################
## check for number given ##
############################
number=$(echo "$arg" | sed "s/^_//" | sed "s/^?//");
if [ -z "$number" ]; then
if [ -z "$doPrompt" ]; then
###########################################
## if not prompting, default number to 1 ##
###########################################
number="1"
else
################################################
## if prompting, default to full history size ##
################################################
number="$CD_HISTORY_SIZE"
fi
fi
##################################################################
## if not doing prompt, just get line from history and go there ##
##################################################################
if [ -z "$doPrompt" ]; then
dir=$(tail -n $number $CD_HISTORY | head -1);
builtin cd "$dir";
else
##########################
## otherwise, do prompt ##
##########################
## _cd_prompt "$(tail -n ${number} $CD_HISTORY)" "tac"
_cd_prompt "$(tail -n ${number} $CD_HISTORY)" "reverse"
fi
############################################################################
## return here without letting this entry be re-added to the history file ##
############################################################################
return;
######################################################
## check for special argument "...pattern" -- go up ##
## (ie, ..) until arrive in dir named by pattern. ##
######################################################
elif [ $(echo "$arg" | grep "^\.\.\..*$") ]; then
pattern=$(echo "$arg" | sed "s/^\.\.\.//");
target=$(pwd)
while [ -z "$(echo $target | grep $pattern[^/]*$)" ]; do
target=$(dirname $target)
if [ -z "$target" ]; then
echo "cd: ${pattern}: No such matching ancestor directory";
return;
fi
done
builtin cd $target;
####################################################################
## check for special argument "^old^new" - go to pwd after regexp ##
####################################################################
elif [ $(echo "$arg" | grep "^\^.\+\^.\+") ]; then
pattern=$(echo "$arg" | sed "s/\^$//")
old=$(echo "$pattern" | sed "s/^\^//;s/\^.*//");
new=$(echo "$pattern" | sed "s/^\^//;s/.*\^//");
##############################################
## couldn't this sed just use the orignial ##
## arg as in: s${arg}^ ? Consider changing. ##
##############################################
target=$(pwd | sed "s/$old/$new/")
builtin cd $target;
##################################
## else default to normal usage ##
##################################
else
builtin cd "$@";
fi
########################################################################
## remove the new cwd from .cd_history, then re-add it at the end (so ##
## it won't be duplicated, and it will be at the bottom of the file) ##
########################################################################
grep -v "^$(pwd)\$" $CD_HISTORY > $CD_HISTORY_NEW;
pwd >> $CD_HISTORY_NEW;
###############################################################
## chomp the .cd_history file down to only its last $n lines ##
###############################################################
tail -n $CD_HISTORY_SIZE $CD_HISTORY_NEW > $CD_HISTORY;
rm $CD_HISTORY_NEW;
}
##########################################################################
## Function: _cd_prompt
## Desc: display a list of options for a cd destination and prompt user
## Args: history - list of dirs to display as options
## Args: sort - useful as "cat" or "tac" - lets list be sorted
## & numbered forward or backward (tac -> backward)
## Input:
## Output:
## Notes:
##########################################################################
function _cd_prompt
{
history="$1"
sort="$2"
############
## prompt ##
############
echo "$history" | $sort | cat -n | $sort | awk '{ print $0, $1; }' | sed "s/\( \+\w\+\)\(.\+\) \(\w\+$\)/${YELLOW}\1${RESET} \2 ${YELLOW}\3${RESET}/"
echo -n "${YELLOW}cd${RESET}> ";
read answer;
########################################
## if no answer given, take no action ##
########################################
if [ -z "$answer" ]; then
return;
fi
####################################
## check if answer is all numbers ##
####################################
nonums="$(echo $answer | sed 's/[0-9]//g')"
if [ ! -z "$nonums" ] ; then
#######################################################################
## if line isn't all numbers, take it to mean the directory to cd to ##
#######################################################################
dir="$answer";
else
################################################################################
## if line is all numbers, use it to mean a line from the list of files above ##
################################################################################
dir="$(echo "$history" | $sort | head -${answer} | tail -n 1)"
fi
builtin cd "$dir";
}
##########################################################################
## Function: cd-clean
## Desc: clean no longer existing entries from the CD_HISTORY file
## Args:
## Input:
## Output: A note about how many lines were kept
## Notes:
##########################################################################
function cd-clean
{
for i in $(cat $CD_HISTORY); do
if [ -d $i ]; then
echo $i >> $CD_HISTORY_NEW;
fi
done
mv $CD_HISTORY_NEW $CD_HISTORY
lines=$(cat $CD_HISTORY | wc -l)
echo "Keeping $lines lines of cd_history."
}
##########################################################################
## Function: reverse
## Desc: for systems without a 'tac' command, use this to 'tac' a file.
## Args:
## Input:
## Output:
## Notes:
##########################################################################
function reverse
{
local line
if IFS= read -r line
then
reverse
printf '%s\n' "$line"
fi
}