-
Notifications
You must be signed in to change notification settings - Fork 0
/
gofi.sh
executable file
·367 lines (296 loc) · 10.3 KB
/
gofi.sh
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
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
#!/bin/sh
#=======================================================================
# PRELIMINARIES
#=======================================================================
#-----------------------------------------------------------------------
# Configuration
#-----------------------------------------------------------------------
# exit immediately if an error is encountered
set -e
export PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin
# where to put programs not installed from .deb packages
prefix=/usr/local
mandir="$prefix/share/man/man1"
bindir="$prefix/bin"
if [ -z "$GOFISH_CONF_DIR" ]; then
GOFISH_CONF_DIR="$HOME/.config/fish"
fi
fonts_confd=/etc/fonts/conf.d
fontconfig_overrides="$fonts_confd/00-overrides.conf"
uid=$( id -u )
#-----------------------------------------------------------------------
# Functions
#-----------------------------------------------------------------------
# NOTE: when used in an assignment, command substitution doesn't require
# quoting; elsewhere (e.g. in a for-loop), it does
width=$( seq 1 72 )
log() {
local msg="$1"
local color="$2"
local sep="$3"
if [ -n "$color" ]; then
reset='\e[0m'
fi
if [ -n "$sep" ]; then
sep=$( printf "$sep%.s" $width )
before="$sep\n\n"
after="\n\n$sep"
fi
>&2 printf "$color$before$msg$after$reset\n"
}
info() {
local msg="$1"
local sep="$2"
log "$msg" '\e[32m' "$sep"
}
warning() {
local msg="$1"
local sep="$2"
log "$msg" '\e[33m' "$sep"
}
error() {
local msg="$1"
local sep="$2"
log "$msg" '\e[31m' "$sep"
}
# Fetch installation archive if cmd is not available, else return 10.
maybe_fetch_archive() {
local cmd="$1"
local repo="$2"
local archive_regex="$3"
if ! command -v "$cmd" >/dev/null || [ -n "$GOFISH_FORCE" ]; then
release_link=https://github.com$(
curl -sL "https://github.com/$repo/releases" |
grep -oPm1 '/[^"]+/'"$archive_regex"
)
curl -sLO "$release_link"
basename "$release_link"
else
return 10
fi
}
maybe_install_deb() {
# NOTE: declare deb as local in a separate statement first, otherwise
# local would override the exit status of the subshell, which would
# make && always succeed; cf.
# https://wiki.ubuntu.com/DashAsBinSh#local,
# https://www.tldp.org/LDP/abs/html/localvar.html
local deb
local status
deb=$( maybe_fetch_archive "$@" ) &&
sudo dpkg --force-overwrite -i "$deb"
# NOTE: we have to explicitly set the return code here or else $? is
# used, which means 10 if the command is already installed and
# maybe_fetch_archive didn't fetch anything
status=$?
[ $status -eq 10 ] && return 0 || return $status
}
#-----------------------------------------------------------------------
# Check that we're not running as root
#-----------------------------------------------------------------------
if [ "$uid" -eq 0 ]; then
error "\
This script should be run as a regular user, it will request sudo
privileges where appropriate.\
"
exit 1
fi
#-----------------------------------------------------------------------
# Check for required commands which might not be present
#-----------------------------------------------------------------------
cmds='curl git dpkg apt-add-repository apt-get mandb unzip'
for cmd in $cmds; do
if ! command -v $cmd >/dev/null; then
error "This script needs the command '$cmd' to run but it wasn't found."
abort=1
fi
done
if [ -n "$abort" ]; then
error 'Some required commands are missing, please install them first.'
exit 1
fi
#=======================================================================
# INSTALLATION
#=======================================================================
# trace the execution of the script to pinpoint problem in case of
# failure
set -x
sudo mkdir -p "$mandir" "$bindir"
#-----------------------------------------------------------------------
# Add fish PPA and install it:
#-----------------------------------------------------------------------
if ! command -v fish >/dev/null || [ -n "$GOFISH_FORCE" ]; then
sudo apt-add-repository -y ppa:fish-shell/release-3
sudo apt-get update
sudo apt-get install -o Dpkg::Options::=--force-overwrite -y fish
fi
#-----------------------------------------------------------------------
# Clone fish config
#-----------------------------------------------------------------------
conf_dir_parent="$GOFISH_CONF_DIR"
while [ ! -d "$conf_dir_parent" ]; do
conf_dir_parent=$( dirname "$conf_dir_parent" )
done
if [ -w "$conf_dir_parent" ]; then
run_as="#$uid"
else
run_as='#0'
fi
if [ -d "$GOFISH_CONF_DIR" ]; then
disabled="$GOFISH_CONF_DIR:disabled:$(date +%s)"
set +x
warning "\
Moving existing fish configuration directory:
$GOFISH_CONF_DIR
to:
$disabled\
" =
set -x
sudo -u $run_as mv "$GOFISH_CONF_DIR" "$disabled"
fi
sudo -u $run_as mkdir -p "$GOFISH_CONF_DIR"
cd "$GOFISH_CONF_DIR"
sudo -u $run_as git clone https://github.com/dlukes/go-fish .
#-----------------------------------------------------------------------
# Perform all custom downloads in a temporary working directory
#-----------------------------------------------------------------------
workdir=$( mktemp -d )
cd "$workdir"
set +x
info "\
Temporary working directory is:
$workdir
All downloaded and extracted files will be placed there, so that's where
you should check if anything goes wrong.\
" =
set -x
#-----------------------------------------------------------------------
# Install fzf (for fuzzy-searching all the things™):
#-----------------------------------------------------------------------
# additional resources are only in the source release, so it has to be
# fetched separately and *first*, because once the fzf binary is
# available, the command -v check in maybe_fetch_archive will succeed
# and the conditional block will be skipped
fzf_source_archive=$( maybe_fetch_archive fzf junegunn/fzf 'archive/refs/tags/.*?\.tar\.gz' ) && {
tar xzf "$fzf_source_archive"
sudo mv fzf-*/man/man1/fzf.1 "$mandir"
fzf_share="$prefix/share/fzf"
sudo rm -rf "$fzf_share"
sudo mkdir -p "$fzf_share"
sudo mv fzf-*/shell "$fzf_share"
update_man_db=1
}
fzf_binary_archive=$( maybe_fetch_archive fzf junegunn/fzf-bin 'fzf-.*?-linux_amd64.tar.gz' ) && {
tar xzf "$fzf_binary_archive"
sudo mv fzf "$bindir"
}
#-----------------------------------------------------------------------
# Install fasd (for quick cd based on frecency of history entries)
#-----------------------------------------------------------------------
fasd_archive=$( maybe_fetch_archive fasd clvv/fasd '.*?\.tar\.gz' ) && {
tar xzf "$fasd_archive"
sudo mv fasd-*/fasd.1 "$mandir"
sudo mv fasd-*/fasd "$bindir"
update_man_db=1
}
#-----------------------------------------------------------------------
# Install exa (a modern replacement for ls, with git support & more):
#-----------------------------------------------------------------------
repo=ogham/exa
exa_binary_archive=$( maybe_fetch_archive exa "$repo" 'exa-linux-x86_64-.*?\.zip' ) && {
mkdir exa
mv "$exa_binary_archive" exa
cd exa
unzip "$exa_binary_archive"
sudo mv man/* "$mandir"
sudo mv bin/* "$bindir"
sudo mv completions/exa.fish /usr/share/fish/completions/
cd -
update_man_db=1
}
#-----------------------------------------------------------------------
# Install bat (a cat(1) clone with wings):
#-----------------------------------------------------------------------
maybe_install_deb bat sharkdp/bat 'bat_.*?amd64.deb'
#-----------------------------------------------------------------------
# Install rg (a faster grep clone with better defaults):
#-----------------------------------------------------------------------
maybe_install_deb rg BurntSushi/ripgrep 'ripgrep_.*?_amd64.deb'
#-----------------------------------------------------------------------
# Install fd (a faster & simpler find clone with better defaults):
#-----------------------------------------------------------------------
maybe_install_deb fd sharkdp/fd 'fd_.*?_amd64.deb'
#-----------------------------------------------------------------------
# Fix Ubuntu Mono fontconfig substitution rules (prompt uses Unicode)
#-----------------------------------------------------------------------
if [ ! -d "$fonts_confd" ]; then
set +x
warning "\
The directory
$fonts_confd
does not exist, will not attempt to fix Ubuntu Mono font substitution
rules.\
" =
set -x
elif [ -e "$fontconfig_overrides" ]; then
set +x
warning "\
A file named
$fontconfig_overrides
already exists; refusing to overwrite it to fix Ubuntu Mono font
substitution rules.\
" =
set -x
else
set +x
info "\
Installing fontconfig substitution overrides for Ubuntu Mono. This is
because the default prompt uses Unicode characters which don't exist in
Ubuntu Mono and get substituted by a sans-serif font by default because
of improper configuration.
If you're using a different font, you may have to tweak this override
file:
$fontconfig_overrides
If you're installing this on a server which you'll be connecting to via
ssh, you may have to configure these overrides on your local machine
instead. Cf.:
https://github.com/dlukes/go-fish#troubleshooting-unicode-glyphs-in-prompt
NOTE: You may need to run 'fc-cache -fv' to update your fontconfig cache
and/or open a new terminal window for these changes to take effect.\
" =
set -x
cat <<'END' | sudo tee "$fontconfig_overrides"
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<!--
Added by https://github.com/dlukes/go-fish because the default prompt
uses Unicode characters which don't exist in Ubuntu Mono and get
substituted by a sans-serif font by default because of improper
configuration.
-->
<fontconfig>
<alias>
<family>Ubuntu Mono</family>
<default>
<family>monospace</family>
</default>
</alias>
</fontconfig>
END
fi
#-----------------------------------------------------------------------
# Update man db for good measure if some man pages were manually added
#-----------------------------------------------------------------------
if [ -n "$update_man_db" ]; then
sudo mandb >/dev/null
fi
set +x
info "\
All done. Invoke the 'fish' command to try the fish shell out and see if
you like it. Check out the README for tips on what's available and
configured:
https://github.com/dlukes/go-fish
And the fish shell website for a tutorial and extensive documentation:
https://fishshell.com/
Have fun using the Friendly Interactive SHell!\
" =