forked from mttaggart/shell-setup
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathsetup.sh
More file actions
executable file
·316 lines (258 loc) · 9.53 KB
/
setup.sh
File metadata and controls
executable file
·316 lines (258 loc) · 9.53 KB
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
#!/usr/bin/env bash
set -euo pipefail
if [[ $EUID -eq 0 ]]; then
echo "[!] Do NOT run this script with sudo."
echo " Just execute ./setup.sh as your normal user; it will prompt for your sudo password when needed."
exit 1
fi
TMPDIR="$(mktemp -d)"
cleanup() { rm -rf "$TMPDIR"; }
trap cleanup EXIT
install_apt_packages() {
echo "[+] Installing apt packages"
sudo apt-get update -qq
sudo apt-get install -y --no-install-recommends \
ca-certificates curl wget gnupg git \
cmake gcc pkg-config fish fontconfig libfontconfig1-dev \
unzip p7zip-full neofetch tmux plocate libnotify4 libsecret-1-0 >/dev/null
}
install_obsidian() {
echo "[+] Checking for Obsidian…"
if command -v obsidian >/dev/null 2>&1; then
echo "[+] Obsidian is already installed – skipping"
return 0
fi
echo "[+] Installing Obsidian…"
local DEB="$TMPDIR/obsidian_1.4.13_amd64.deb"
wget -q "https://github.com/obsidianmd/obsidian-releases/releases/download/v1.4.13/obsidian_1.4.13_amd64.deb" -O "$DEB"
sudo dpkg -i "$DEB" >/dev/null || sudo apt-get -f install -y >/dev/null
echo "[+] Verifying installation..."
if ! command -v obsidian >/dev/null 2>&1; then
echo "[!] Obsidian installation failed."
return 1
fi
}
install_docker() {
echo "[+] Checking for Docker…"
if command -v docker >/dev/null 2>&1 && docker compose version >/dev/null 2>&1; then
echo "[+] Docker & Compose already installed – skipping"
return 0
fi
echo "[+] Installing Docker via get.docker.com"
local INSTALLER="$TMPDIR/get-docker.sh"
curl -fsSL https://get.docker.com -o "$INSTALLER" >/dev/null
sudo sh "$INSTALLER" >/dev/null
if ! groups "$USER" | grep -q '\bdocker\b'; then
echo "[+] Adding $USER to docker group"
sudo usermod -aG docker "$USER"
ADDED_GROUP=true
fi
docker --version >/dev/null 2>&1 || true
docker compose version >/dev/null 2>&1 || true
if [[ "${ADDED_GROUP:-}" == true ]]; then
echo "[i] You’re now in the ‘docker’ group."
echo " Log out & back in (or: newgrp docker ) to activate it."
fi
}
install_vscode() {
echo "[+] Checking for VS Code…"
if command -v code >/dev/null 2>&1; then
echo "[+] VS Code is already installed – skipping"
return 0
fi
echo "[+] Installing VS Code…"
local DEB="$TMPDIR/vscode.deb"
wget -q "https://code.visualstudio.com/sha/download?build=stable&os=linux-deb-x64" -O "$DEB"
sudo dpkg -i "$DEB" >/dev/null || sudo apt-get -f install -y >/dev/null
echo "[+] Verifying installation..."
if ! command -v code >/dev/null 2>&1; then
echo "[!] VS Code installation failed."
return 1
fi
echo "[+] VS Code installed successfully!"
code --version || true
}
install_nerdfont() {
echo "[+] Installing NerdFont"
if compgen -G "/usr/share/fonts/saucecode-pro/*.ttf" >/dev/null; then
echo "[+] NerdFont already installed – skipping"
return 0
fi
local ZIP="$TMPDIR/scp.zip"
local OUT="$TMPDIR/scp"
wget -qO "$ZIP" "https://github.com/ryanoasis/nerd-fonts/releases/download/v3.0.2/SourceCodePro.zip"
mkdir -p "$OUT"
unzip -qq "$ZIP" -d "$OUT" '*.ttf'
sudo mkdir -p /usr/share/fonts/saucecode-pro
sudo mv "$OUT"/*.ttf /usr/share/fonts/saucecode-pro
sudo fc-cache -s -f >/dev/null
}
install_starship() {
local VERSION="v1.24.0"
local ARCH="x86_64-unknown-linux-gnu"
echo "[+] Checking for Starship (${VERSION})…"
if command -v starship >/dev/null 2>&1; then
if starship --version 2>/dev/null | grep -q "starship ${VERSION}"; then
echo "[+] Starship already at ${VERSION} – skipping"
return 0
fi
fi
echo "[+] Installing Starship (pinned ${VERSION})"
local TGZ="$TMPDIR/starship.tar.gz"
curl -fsSL "https://github.com/starship/starship/releases/download/${VERSION}/starship-${ARCH}.tar.gz" -o "$TGZ"
tar -xzf "$TGZ" -C "$TMPDIR" starship
sudo install -m 0755 "$TMPDIR/starship" /usr/local/bin/starship
starship --version >/dev/null
}
install_poetry() {
echo "[+] Checking for Poetry…"
if command -v poetry >/dev/null 2>&1; then
echo "[+] Poetry already installed – skipping"
return 0
fi
echo "[+] Installing Poetry via install.python-poetry.org"
curl -sSL https://install.python-poetry.org | python3 - >/dev/null
local POETRY_BIN="$HOME/.local/bin/poetry"
if [[ ! -x $POETRY_BIN ]]; then
echo "[!] Poetry installation failed (binary not found)"; exit 1
fi
echo "[+] Poetry installed to $POETRY_BIN"
if ! grep -qx 'export PATH="$HOME/.local/bin:$PATH"' ~/.bashrc 2>/dev/null; then
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
echo "[i] Added ~/.local/bin to PATH in ~/.bashrc"
fi
if command -v fish >/dev/null 2>&1; then
mkdir -p ~/.config/fish/conf.d
local FISH_PATH_SNIPPET=~/.config/fish/conf.d/poetry_path.fish
if ! grep -q 'fish_user_paths.*\.local/bin' "$FISH_PATH_SNIPPET" 2>/dev/null; then
echo 'set -Ua fish_user_paths $HOME/.local/bin' > "$FISH_PATH_SNIPPET"
echo "[i] Added ~/.local/bin to Fish user paths (conf.d/poetry_path.fish)"
fi
mkdir -p ~/.config/fish/completions
poetry completions fish > ~/.config/fish/completions/poetry.fish
echo "[i] Installed Poetry tab-completion for Fish"
fi
}
install_uv() {
echo "[+] Checking for uv…"
if command -v uv >/dev/null 2>&1; then
echo "[+] uv already installed – skipping"
return 0
fi
echo "[+] Installing uv via astral.sh"
curl -LsSf https://astral.sh/uv/install.sh | UV_NO_MODIFY_PATH=1 sh >/dev/null
local UV_BIN="$HOME/.local/bin/uv"
echo "[+] uv installed to $UV_BIN"
if command -v fish >/dev/null 2>&1; then
mkdir -p ~/.config/fish/completions
"$UV_BIN" generate-shell-completion fish > ~/.config/fish/completions/uv.fish
"$HOME/.local/bin/uvx" --generate-shell-completion fish > ~/.config/fish/completions/uvx.fish
echo "[i] Installed uv/uvx tab‑completion for Fish"
fi
}
configure_tmux() {
echo "[+] Configuring tmux"
git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm 2>/dev/null || true
cp ./tmux/.tmux.conf ~/.tmux.conf
echo "[+] Remember: exit all sessions then press Ctrl-B I to install plugins"
}
configure_starship() {
echo "[+] Configuring Starship prompt"
mkdir -p ~/.config
cp ./Starship/starship.toml ~/.config/starship.toml
grep -qxF 'eval "$(starship init bash)"' ~/.bashrc || \
echo 'eval "$(starship init bash)"' >> ~/.bashrc
}
configure_fish() {
echo "[+] Configuring Fish"
mkdir -p ~/.config/fish/conf.d ~/.config/fish/completions
cp ./fish/config.fish ~/.config/fish/config.fish
cp ./fish/dracula.fish ~/.config/fish/conf.d/
cp ./fish/starship.fish ~/.config/fish/conf.d/starship.fish
cp ./fish/poetry.fish ~/.config/fish/completions/poetry.fish
}
configure_bashrc() {
echo "[+] Configuring bashrc"
cp ./bashrc/.bashrc ~/.bashrc
echo "[i] bashrc updated. Restart your shell to load changes."
}
configure_neofetch() {
echo "[+] Configuring neofetch"
mkdir -p ~/.config/neofetch
cp ./neofetch/config.conf ~/.config/neofetch/config.conf
cp ./neofetch/snake.txt ~/.config/neofetch/snake.txt
}
configure_vscode() {
echo "[+] Configuring VS Code"
if ! command -v code >/dev/null 2>&1; then
echo "[i] VS Code not installed; skipping VS Code config"
return 0
fi
local VSC_USER_DIR="$HOME/.config/Code/User"
mkdir -p "$VSC_USER_DIR"
mkdir -p "$VSC_USER_DIR/snippets"
if [[ -f ./vscode/settings.json ]]; then
cp ./vscode/settings.json "$VSC_USER_DIR/settings.json"
fi
if [[ -f ./vscode/keybindings.json ]]; then
cp ./vscode/keybindings.json "$VSC_USER_DIR/keybindings.json"
fi
if [[ -d ./vscode/snippets ]]; then
cp -r ./vscode/snippets/. "$VSC_USER_DIR/snippets/"
fi
if [[ -f ./vscode/extensions.txt ]]; then
echo "[+] Installing VS Code extensions (from vscode/extensions.txt)"
while IFS= read -r ext; do
[[ -z "$ext" ]] && continue
code --install-extension "$ext" --force >/dev/null 2>&1 || {
echo "[i] Failed to install extension: $ext (continuing)"
}
done < ./vscode/extensions.txt
fi
}
ensure_fish_shell() {
local FISH_BIN
FISH_BIN="$(command -v fish)"
if [[ -z "${FISH_BIN:-}" ]]; then
echo "[!] fish not found"
return 1
fi
if ! grep -qxF "$FISH_BIN" /etc/shells; then
echo "[+] Adding fish to /etc/shells"
echo "$FISH_BIN" | sudo tee -a /etc/shells >/dev/null
fi
}
welcome() {
echo "[+] Done! Welcome to mattlab!"
# For CI/Automation
if [[ "${CI:-}" == "true" || "${MATT_SKIP_WELCOME:-}" == "1" ]]; then
echo "[i] CI mode: skipping chsh + exec fish"
return 0
fi
ensure_fish_shell
sudo chsh -s "$(command -v fish)" "$USER"
if [[ -t 0 ]]; then
exec fish
else
echo "[i] Shell changed to fish. Start a new session to use it."
fi
}
main() {
echo "[+] Bootstrap starting…"
install_apt_packages
install_docker
install_obsidian
install_vscode
install_starship
configure_fish
install_nerdfont
# install_poetry
install_uv
configure_tmux
configure_vscode
configure_starship
configure_neofetch
configure_bashrc
welcome
}
main "$@"