/
smartcd_config
271 lines (242 loc) · 11.6 KB
/
smartcd_config
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
function smartcd_config() {
local smartcd_file="$(_smartcd_file)"
local varstash_file=${smartcd_file/%smartcd/varstash}
local arrays_file=${smartcd_file/%smartcd/arrays}
function setup_file() {
local file="$1"; shift
local config="$1"; shift
if ! command grep "smartcd" "$file" >/dev/null 2>&1; then
echo "Configuring $file"
echo -e "$config" >> $file
else
echo "$file already appears to be configured, please check it for correctness"
echo "This is what you configured:"
echo -e "$config"
fi
}
function generate_config() {
function _setup_conditionally() {
local cond=$1; shift
if [[ ! $cond =~ $yes ]]; then
local comment="# "
fi
config="$config\n${comment}$*"
}
local config="# Load and configure smartcd\nsource $arrays_file\nsource $varstash_file\nsource $smartcd_file"
_setup_conditionally "$enable_chpwd_hook" "smartcd setup chpwd-hook"
_setup_conditionally "$setup_cd" "smartcd setup cd"
_setup_conditionally "$setup_pushd" "smartcd setup pushd"
_setup_conditionally "$setup_pushd" "smartcd setup popd"
_setup_conditionally "$enable_prompt_hook" "smartcd setup prompt-hook"
_setup_conditionally "$enable_exit_hook" "smartcd setup exit-hook"
_setup_conditionally "$enable_completion" "smartcd setup completion"
_setup_conditionally "$autoconfigure" "VARSTASH_AUTOCONFIGURE=1"
_setup_conditionally "$autoedit" "VARSTASH_AUTOEDIT=1"
_setup_conditionally "$noinode" "SMARTCD_NO_INODE=1"
_setup_conditionally "$automigrate" "SMARTCD_AUTOMIGRATE=1"
_setup_conditionally "$legacy" "SMARTCD_LEGACY=1"
# Add commented-out quiet settings so the user can enable them later
_setup_conditionally "" "SMARTCD_QUIET=1"
_setup_conditionally "" "VARSTASH_QUIET=1"
unset -f _setup_conditionally
echo -e "$config"
}
local yes="^y"
function read_yesno() {
local yesno
builtin read yesno < /dev/tty
yesno=$(echo $yesno | command tr 'A-Z' 'a-z')
: ${yesno:=$1}
echo $yesno
}
function ask() {
echo >/dev/tty
echo "[ $1 ]" >/dev/tty
echo -ne "$2" >/dev/tty
case $3 in
y) echo -n " [Y/n] " >/dev/tty;;
n) echo -n " [y/N] " >/dev/tty;;
esac
read_yesno $3
}
if [[ -n "$BASH_VERSION" ]]; then
local possible_files=".bashrc .bash_profile .profile"
local possible_dirs="$HOME"
elif [[ -n "$ZSH_VERSION" ]]; then
local -a possible_files
possible_files=(".zshrc" ".zprofile" ".zlogin")
local -a possible_dirs
possible_dirs=("$ZDOTDIR" "$HOME")
else
echo "Unknown shell, sorry! Only bash and zsh are supported at this time"
exit 1
fi
if [[ -f "$HOME/.smartcd_config" ]]; then
local use_defs=n
local chpwd_def=n cd_def=n pushd_def=n prompt_def=n exit_def=n
local comp_def=n autocon_def=n autoed_def=n
local inode_def=n automig_def=n legacy_def=n line=
while builtin read -r line; do
case $line in
"smartcd setup chpwd-hook") chpwd_def=y;;
"smartcd setup cd") cd_def=y;;
"smartcd setup pushd") pushd_def=y;;
"smartcd setup prompt-hook") prompt_def=y;;
"smartcd setup exit-hook") exit_def=y;;
"smartcd setup completion") comp_def=y;;
"VARSTASH_AUTOCONFIGURE=1") autocon_def=y;;
"VARSTASH_AUTOEDIT=1") autoed_def=y;;
"SMARTCD_NO_INODE=1") inode_def=y;;
"SMARTCD_AUTOMIGRATE=1") automig_def=y;;
"SMARTCD_LEGACY=1") legacy_def=y;;
esac
done < "$HOME/.smartcd_config"
else
local use_defs=$(ask "use defaults" "Use all default settings?" y)
# In case the answer is 'no', set the actual defaults.
# Use chpwd hook for zsh by default.
if [[ -n "$ZSH_VERSION" ]]; then
local chpwd_def=y cd_def=n pushd_def=n
else
local chpwd_def=n cd_def=y pushd_def=y
fi
local prompt_def=n exit_def=n comp_def=y autocon_def=n autoed_def=n
local inode_def=n automig_def=n legacy_def=n
fi
if [[ ! $use_defs =~ $yes ]]; then
if [[ -n "$ZSH_VERSION" ]]; then
local enable_chpwd_hook=$(ask "smartcd setup chpwd-hook" "Would you like to plug into Zsh's chpwd hook? (recommended)" $chpwd_def)
fi
# Ask for chpwd related settings only if not on zsh, or if not using chpwd hook.
if [[ -z "$ZSH_VERSION" ]] || [[ $enable_chpwd_hook == "n" ]]; then
local setup_cd=$(ask "smartcd setup cd" "Would you like to wrap cd with smartcd? (recommended)" y)
local setup_pushd=$(ask "smartcd setup pushd" "Would you like to wrap pushd and popd?" y)
local enable_prompt_hook=$(ask "smartcd setup prompt-hook" "Would you like to enable prompt-command hooks? (This is only recommended\nif you are an \"autocd\" user, say no if you are unsure)" n)
else
local setup_cd=n setup_pushd=n enable_prompt_hook=n
fi
local enable_exit_hook=$(ask "smartcd setup exit-hook" "Would you like to enable the shell exit hook? This will cause bash_leave\nscripts to run when exiting your shell" $exit_def)
local enable_completion=$(ask "smartcd setup completion" "Would you like to enable smartcd tab completion?" $comp_def)
local autoconfigure=$(ask "VARSTASH_AUTOCONFIGURE=1" "Would you like smartcd to automatically add stash commands to your enter scripts\nwhen you run (auto)stash interactively?" $autocon_def)
if [[ $autoconfigure =~ $yes ]]; then
local autoedit=$(ask "VARSTASH_AUTOEDIT=1" "Would you also like to edit the smartcd config after it is automatically configured?" $autoed_def)
fi
local advanced=$(ask "advanced options" "Do you want to configure advanced settings?" n)
if [[ $advanced =~ $yes ]]; then
echo
echo "[ADVANCED USAGE]"
local noinode=$(ask "SMARTCD_NO_INODE=1" "Would you like to skip validation that scripts are not stale from a previously\ndeleted or renamed directory? (DISCOURAGED)" $inode_def)
local automigrate=$(ask "SMARTCD_AUTOMIGRATE=1" "Would you like to automatically migrate legacy .bash_enter and .bash_leave\nscripts to ~/.smartcd?" $automig_def)
local legacy=$(ask "SMARTCD_LEGACY=1" "Would you like to allow legacy .bash_enter and .bash_leave scripts to run\nin-place? (DISCOURAGED)" $legacy_def)
else
local noinode=$inode_def
local automigrate=$automig_def
local legacy=$legacy_def
fi
else
# Use chpwd hook for zsh by default.
if [[ -n "$ZSH_VERSION" ]]; then
local enable_chpwd_hook=y setup_cd=n setup_pushd=n
else
local enable_chpwd_hook=n setup_cd=y setup_pushd=y
fi
local enable_prompt_hook=n enable_exit_hook=n enable_completion=y
local autoconfigure=n autoedit=n noinode=n automigrate=n legacy=n
fi
local config="$(generate_config)"
echo
# Temporarily disable noclobber for zsh users
[[ -n $ZSH_VERSION ]] && setopt localoptions && setopt clobber
if [[ -f "$HOME/.smartcd_config" ]]; then
local config_file_exists=1
echo -n "$HOME/.smartcd_config already exists, do you want to overwrite it? [y/N] "
local overwrite_config_file=$(read_yesno n)
if [[ $overwrite_config_file =~ $yes ]]; then
echo -e "$config" > "$HOME/.smartcd_config"
else
echo "Ok, here is the configuration that you generated, please update as necessary:"
echo "$config"
fi
else
echo -n "Would you like to configure smartcd in $HOME/.smartcd_config? (recommended) [Y/n] "
local create_config_file=$(read_yesno y)
if [[ $create_config_file =~ $yes ]]; then
echo -e "$config" > "$HOME/.smartcd_config"
local config_file_exists=1
fi
fi
if [[ -n $config_file_exists ]]; then
if [[ $SMARTCD_LOADNOW == "1" ]]; then
local loadnow=yes
elif [[ $SMARTCD_LOADNOW != "0" ]]; then
echo -n "Would you like to load your config file now? [Y/n] "
local loadnow=$(read_yesno y)
fi
if [[ $loadnow =~ $yes ]]; then
source $HOME/.smartcd_config
fi
for pdir in $possible_dirs; do
for file in $possible_files; do
if [[ -f "$pdir/$file" ]]; then
if command grep "\.smartcd_config" "$pdir/$file" >/dev/null 2>&1; then
local setup=1
else
echo -n "I see you have a $pdir/$file, would you like to load your config file from there? [Y/n] "
local answer=$(read_yesno y)
if [[ $answer =~ $yes ]]; then
echo -e "\n[ -r \"\$HOME/.smartcd_config\" ] && ( [ -n "\$BASH_VERSION" ] || [ -n "\$ZSH_VERSION" ] ) && source ~/.smartcd_config" >> "$pdir/$file"
local setup=1
fi
fi
fi
done
done
if [[ -z $setup ]]; then
echo -n "You did not load your config anywhere, which file would you like to load it from? "
builtin read filename < /dev/tty
if [[ -n "$filename" ]]; then
# eval here to expand ~
local real_filename=$(readlink -f $(eval echo $filename))
if [[ -f "$real_filename" ]]; then
echo -e "\nsource ~/.smartcd_config" >> "$real_filename"
else
echo "Sorry, I can't find $filename"
fi
else
echo
echo "WARNING"
echo "You apparently did not configure your shell to load your smartcd configuration."
echo "Make sure you add \"source ~/.smartcd_config\" to the appropriate location."
fi
fi
else
for file in $possible_files; do
if [[ -f "$HOME/$file" ]]; then
echo -n "I see you have a $file, would you like to write your config to it? [Y/n] "
local answer=$(read_yesno y)
if [[ $answer =~ $yes ]]; then
setup_file "$HOME/$file" "$config"
local setup=1
fi
fi
done
if [[ -z $setup ]]; then
echo -n "You did not configure any files, which file would you like to set up? "
builtin read filename < /dev/tty
if [[ -n "$filename" ]]; then
# eval here to expand ~
local real_filename=$(readlink -f $(eval echo $filename))
if [[ -f "$real_filename" ]]; then
setup_file "$real_filename" "$config"
else
echo "Sorry, I can't find $filename"
fi
else
echo "Ok, here is your configuration, please set it up in an appropriate location:"
echo "$config"
fi
fi
fi
unset -f setup_file generate_config read_yesno ask
}
# vim: filetype=sh autoindent expandtab shiftwidth=4 softtabstop=4