-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path.zshrc
501 lines (444 loc) · 16.2 KB
/
.zshrc
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
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
# 2020-09-24, 2020-09-18, 2020-01-21, 2022-03-09, 2022-07-06, 2022-08-30, 2022-11-07, 2023-02-17, 2023-03-21
# Plugin selection mainly from:
# https://medium.com/@ahadsheriff/how-to-get-a-better-development-experience-on-your-mac-8478be58bba4
#
# Requirements
# pygments (for colorize): brew install pygments
# install homebrew if necessary (https://brew.sh)
which brew > /dev/null || /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# install pygments if necessary
which pygmentize > /dev/null || brew install pygments
# VARIABLES
export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8
export EDITOR='nova'
# Note: homebrew bins are linked from /usr/local/bin, which is already in the path
export PATH="/usr/local/sbin:$PATH"
export PATH="/usr/local/opt/python@3/libexec/bin:$PATH" # python3 unversioned symlinks (from homebrew)
# Setup pyenv (if installed)
which pyenv > /dev/null 2>&1
HAS_PYENV=$?
if [[ $HAS_PYENV ]]; then
export PYENV_ROOT="$(pyenv root)"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
fi
# PLUGINS
# Download Znap, if it's not there yet.
[[ -f ~/.znap/zsh-snap/znap.zsh ]] ||
git clone --depth 1 -- \
https://github.com/marlonrichert/zsh-snap.git ~/.znap/zsh-snap
source ~/.znap/zsh-snap/znap.zsh # Start Znap
# pure prompt
znap source sindresorhus/pure async.zsh pure.zsh
# znap prompt sindresorhus/pure # fast prompt (needs to be put after modt though)
# add exit code to prompt (if non-zero)
_PROMPT_NEWLINE=$'\n' # workaround to get newline within prompt
PROMPT='%(?.%F{magenta}.%F{red}%?${_PROMPT_NEWLINE})❯%f '
# plugins
znap source zsh-users/zsh-syntax-highlighting
znap source zsh-users/zsh-autosuggestions
# znap source MichaelAquilina/zsh-autoswitch-virtualenv
#export AUTOSWITCH_VIRTUAL_ENV_DIR="./venv" # store virtualenvs in each project folder
## export AUTOSWITCH_VIRTUAL_ENV_DIR="." # store virtualenvs in each project folder
## export AUTOSWITCH_VIRTUAL_ENV_NAME="venv"
# oh-my-zsh plugins
znap source ohmyzsh/ohmyzsh lib/theme-and-appearance # required libraries for the following plugins
znap source ohmyzsh/ohmyzsh plugins/colored-man-pages
znap source ohmyzsh/ohmyzsh plugins/colorize
znap source ohmyzsh/ohmyzsh plugins/common-aliases
# OPTIONS
setopt auto_cd # cd by just typing the folder name
# setopt auto_pushd pushd_ignore_dups setopt pushd_minus
# ALIASES
alias ls='ls -G' # colored ls
if type 'ccat' > /dev/null; then # colored cat (if available)
alias cat=ccat
fi
if type 'cless' > /dev/null; then # colored less (if available)
alias less=cless
fi
alias home='cd ~'
alias lanip="ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'" #https://stackoverflow.com/a/13322549
alias wanip='curl http://ipecho.net/plain; echo'
alias edit="$EDITOR"
# FUNCTIONS
CODE_FOLDER=~/code # don't quote so tilde gets expanded
function code () {
if (( $# == 0 )); then
# of args is empty (length zero?)
1=10
fi
cd $CODE_FOLDER; ls -t | head -n $1 | column;
}
AUTHOR_STRING='Martin Grödl <martin@process.studio> (https://process.studio)'
function new () {
mkdir $1
if [ $? -eq 0 ]; then
cd $1
npm init -y 1>/dev/null
sed -i '' 's/"main": "index.js"/"private": true/g' package.json
sed -i '' 's/1.0.0/0.1.0/g' package.json
sed -i '' "s#\"author\": \"\"#\"author\": \"$AUTHOR_STRING\"#g" package.json
sed -i '' 's/ISC"/AGPL-3.0"/g' package.json
sed -i '' 's/"description": ""/"description": "",/g' package.json
node=$(node -v); node="${node:1}" # remove first character ('v') from version string
# add engines field with current versions of node and npm (use caret ^ to allow minor and patch changes)
sed -i '' '$i\
\ \ "engines": {\
\ \ \ \ "node": "^'$node'",\
\ \ \ \ "npm": "^'$(npm -v)'"\
\ \ }\
' package.json
echo "node_modules\n.DS_Store\n__pycache__\nvenv\n.venv" > .gitignore
git init 1>/dev/null
sed -i '' 's/master/main/g' .git/HEAD # rename master to main
fi
}
function quote () {
emulate -L zsh
Q=$(curl -s --connect-timeout 1 "http://www.quotationspage.com/random.php" | iconv -c -f ISO-8859-1 -t UTF-8 | grep -m 1 "dt ")
TXT=$(echo "$Q" | sed -e 's/<\/dt>.*//g' -e 's/.*html//g' -e 's/^[^a-zA-Z]*//' -e 's/<\/a..*$//g')
WHO=$(echo "$Q" | sed -e 's/.*\/quotes\///g' -e 's/<.*//g' -e 's/.*">//g')
[[ -n "$WHO" && -n "$TXT" ]] && echo "\"${TXT}\"\n\t-${WHO}"
}
# https://gist.github.com/jaytaylor/6527607
function timeout() { perl -e 'alarm shift; exec @ARGV' "$@"; }
function motd () {
TD=$(date -r ~/.motd +%s 2>/dev/null || echo 0) # touch date in seconds (or 0 if date fails i.e. file doesn't exit)
MD=$(date -v 0H -v 0M -v 0S +%s) # midnight date in seconds
if [[ $TD < $MD || "$1" == "-f" ]]; then
# todo: handle timeout of quote
new_quote=$(quote) # get new quote
[[ -n $new_quote ]] && echo $new_quote > ~/.motd # save, if not empty
fi
/bin/cat ~/.motd
}
# Autoswitch python venv
# Looks in $VENV_DIR and one subdirectory deep for pyvenv.cfg
VENV_DIR='venv'
GRAY="\033[2;37m"
NC="\033[0m"
function mkvenv () {
if [[ -f "$PWD/$VENV_DIR/pyvenv.cfg" ]]; then
echo "venv already present: ${GRAY}$PWD/$VENV_DIR${NC}"
return
fi
if [[ $HAS_PYENV ]]; then
if [[ -n "$1" ]]; then
py_version="$1"
else
py_version=$(pyenv global)
fi
# check if requested version is installed
available_version=$(pyenv latest $py_version 2> /dev/null)
if [[ $? -ne 0 ]]; then
# not installed; check if version is available
install_version=$(pyenv latest --known $py_version 2> /dev/null)
if [[ $? -ne 0 ]]; then
echo "Python version not available: $py_version"
return 1
fi
echo "Installing python version: $install_version"
pyenv install $install_version
echo "Using python version: $install_version"
else
echo "Using python version: $available_version"
fi
pyenv local $py_version # set the version given, not the actual installed one
fi
echo "Creating venv: ${GRAY}$PWD/$VENV_DIR${NC}"
python -m venv $VENV_DIR
if [[ -f "$PWD/$VENV_DIR/pyvenv.cfg" ]]; then
echo "Activating venv: ${GRAY}$PWD/$VENV_DIR${NC}";
source $PWD/$VENV_DIR/bin/activate
fi
}
function rmvenv () {
for venv_dir in $VENV_DIR $VENV_DIR/*(N); do
if [[ -f "$PWD/$venv_dir/pyvenv.cfg" ]]; then
if [[ -n $VIRTUAL_ENV ]]; then
echo "Deactivating venv: ${GRAY}$VIRTUAL_ENV${NC}";
deactivate
fi
echo "Removing venv: ${GRAY}$PWD/$venv_dir${NC}"
rm -rf $PWD/$venv_dir
fi
done
}
function switchvenv () {
if [[ -n $VIRTUAL_ENV ]]; then
# a virtual env is already activated
local DIR=$(dirname $VIRTUAL_ENV) # parnt directory of the venv
# if we are in a subdirectory of $DIR do nothing; we are already activated
if [[ $PWD == $DIR || $PWD == $DIR/* ]]; then
# echo 'already activated'
return
fi
# we are not in a directory of the activated env; deactivate
echo "Deactivating venv: ${GRAY}$VIRTUAL_ENV${NC}";
deactivate
fi
for venv_dir in $VENV_DIR $VENV_DIR/*(N); do # the N supresses an error when no expansion can't be found (nullglob)
if [[ -f "$PWD/$venv_dir/pyvenv.cfg" ]]; then
echo "Activating venv: ${GRAY}$PWD/$venv_dir${NC}";
source $PWD/$venv_dir/bin/activate
break
fi
done;
}
function switchvenv_first() {
add-zsh-hook -D precmd switchvenv_first
add-zsh-hook chpwd switchvenv
switchvenv
}
function switchvenv_init() {
autoload -Uz add-zsh-hook
add-zsh-hook precmd switchvenv_first
}
# Check Node, Python and Homebrew for outdated versions
function outdated () {
FN_NAME=$0
## node
function out_node() {
echo "node"
echo "-------------------"
node_current=${"$(node -v)":1} # remove leading 'v'
node_latest=$(n lsr lts)
if [[ $node_current == $node_latest ]]; then
echo "✅ $node_current"
else
echo "Latest LTS: $node_latest"
echo "Current: $node_current"
export _outdated_update_node="n lts --preserve"
if [[ $1 != "noupcmd" ]]; then
echo "🔄 Update with \`$FN_NAME update node\` (or \`$_outdated_update_node\`)"
fi
fi
}
## python
function out_py() {
echo "\npython"
echo "-------------------"
python_current=$(pyenv global)
## latest (without characters other than digits and .) Note: xargs trims the string
python_latest=$(pyenv install --list | grep -E "^\s+[0-9.]+$" | tail -1 | xargs echo)
if [[ $python_current == $python_latest ]]; then
echo "✅ $python_current"
else
echo "Latest: $python_latest"
echo "Current: $python_current"
export _outdated_update_py="pyenv install $python_latest && pyenv global $python_latest"
if [[ $1 != "noupcmd" ]]; then
echo "🔄 Update with \`$FN_NAME update py\` (or \`$_outdated_update_py\`)"
fi
fi
}
## npm
function out_npm() {
echo "\nnpm"
echo "-------------------"
npm_out=$(npm out -g)
if [[ -z "$npm_out" ]]; then
echo "✅"
else
echo $npm_out
# echo "🔄 Update with \`npm i -g <package>\`"
npm_out=`echo "$npm_out" | tail -f -n +2` # remove header (1 line)
npm_out=`echo "$npm_out" | sed -e 's/[[:space:]].*$//'` # only keep first part of each line
npm_out=`echo "$npm_out" | xargs` # contract to arg list
export _outdated_update_npm="npm i -g $npm_out"
if [[ $1 != "noupcmd" ]]; then
echo "🔄 Update with \`$FN_NAME update npm\` (or \`$_outdated_update_npm\`)"
fi
fi
}
## pip
function out_pip() {
echo "\npip"
echo "-------------------"
pip_out=$(pyenv exec pip list --outdated)
if [[ -z "$pip_out" ]]; then
echo "✅"
else
echo $pip_out
# echo "🔄 Update with \`pip install --upgrade <package>\`"
pip_out=`echo "$pip_out" | tail -f -n +3` # remove header (2 lines)
pip_out=`echo "$pip_out" | sed -e 's/[[:space:]].*$//'` # only keep first part of each line
pip_out=`echo "$pip_out" | xargs` # contract to arg list
export _outdated_update_pip="pip install --upgrade $pip_out"
if [[ $1 != "noupcmd" ]]; then
echo "🔄 Update with \`$FN_NAME update pip\` (or \`$_outdated_update_pip\`)"
fi
fi
}
## homebrew
function out_brew() {
echo "\nbrew"
echo "-------------------"
brew update --quiet
brew_out=$(brew outdated)
if [[ -z "$brew_out" ]]; then
echo "✅"
else
echo $brew_out
export _outdated_update_brew="brew upgrade"
if [[ $1 != "noupcmd" ]]; then
echo "🔄 Update with \`$FN_NAME update brew\` (or \`$_outdated_update_brew\`)"
fi
fi
}
function out_all() {
out_node; out_py; out_npm; out_pip; out_brew
}
function up_node() {
[[ -z "$_outdated_update_node" ]] && out_node noupcmd
if [[ ! -z "$_outdated_update_node" ]]; then
echo "\n🆙 Updating node..."
echo "Running \`$_outdated_update_node\`"
eval "$_outdated_update_node"
export _outdated_update_node=''
fi
}
function up_py() {
[[ -z "$_outdated_update_py" ]] && out_py noupcmd
if [[ ! -z "$_outdated_update_py" ]]; then
echo "\n🆙 Updating python..."
echo "Running \`$_outdated_update_py\`"
eval "$_outdated_update_py"
export _outdated_update_py=''
fi
}
function up_npm() {
[[ -z "$_outdated_update_npm" ]] && out_npm noupcmd
if [[ ! -z "$_outdated_update_npm" ]]; then
echo "\n🆙 Updating npm packages..."
echo "Running \`$_outdated_update_npm\`"
eval "$_outdated_update_npm"
export _outdated_update_npm=''
fi
}
function up_pip() {
[[ -z "$_outdated_update_pip" ]] && out_pip noupcmd
if [[ ! -z "$_outdated_update_pip" ]]; then
echo "\n🆙 Updating pip packages..."
echo "Running \`$_outdated_update_pip\`"
eval "$_outdated_update_pip"
export _outdated_update_pip=''
fi
}
function up_brew() {
[[ -z "$_outdated_update_brew" ]] && out_brew noupcmd
if [[ ! -z "$_outdated_update_brew" ]]; then
echo "\n🆙 Updating brew packages..."
echo "Running \`$_outdated_update_brew\`"
eval "$_outdated_update_brew"
export _outdated_update_brew=''
fi
}
function up_all() {
up_node; up_py; up_npm; up_pip; up_brew
}
function usage() {
echo "Usage:"
echo " Check all: $FN_NAME"
echo " Check specific: $FN_NAME [node|python|py|npm|pip|homebrew|brew|all]"
echo " Update all: $FN_NAME update|up"
echo " Update specific: $FN_NAME update|up [node|python|py|npm|pip|homebrew|brew|all]"
}
if [[ $1 == "node" ]] ; then
out_node
elif [[ $1 == "python" || $1 == "py" ]]; then
out_py
elif [[ $1 == "npm" ]]; then
out_npm
elif [[ $1 == "pip" ]]; then
out_pip
elif [[ $1 == "homebrew" || $1 == "brew" ]]; then
out_brew
elif [[ $1 == "all" || -z "$1" ]]; then
out_all
elif [[ $1 == "update" || $1 == "up" ]]; then
if [[ $2 == "node" ]]; then
up_node
elif [[ $2 == "python" || $2 == "py" ]]; then
up_py
elif [[ $2 == "npm" ]]; then
up_npm
elif [[ $2 == "pip" ]]; then
up_pip
elif [[ $2 == "homebrew" || $2 == "brew" ]]; then
up_brew
elif [[ $2 == "all" || -z "$2" ]]; then
up_all
else
usage
fi
else
usage
fi
}
# Hexdump
function hexdump () {
if [[ -z "$1" ]]; then
echo "Usage:"
echo " $0 file [number-of-lines]"
return 1
fi
if [[ -t 1 ]]; then
# stdout is a terminal
local NUM_LINES=20
[[ -n "$2" ]] && NUM_LINES="$2"
# TODO check for pygmentize
if [[ $NUM_LINES -eq 0 ]]; then
xxd $1 | pygmentize -l hexdump
else
xxd $1 | head -n "$NUM_LINES" | pygmentize -l hexdump
fi
[[ -z "$2" ]] && echo "/*\n Output truncated to $NUM_LINES lines.\n Specify number of lines as 2nd argument (0 for unlimited).\n When redirecting to a file (with \'>\'), the whole file is dumped by default.\n*/"
else
# stdout isn't a terminal
local NUM_LINES=0
[[ -n "$2" ]] && NUM_LINES="$2"
if [[ $NUM_LINES -eq 0 ]]; then
xxd $1
else
xxd $1 | head -n "$NUM_LINES"
fi
fi
}
# Get path of c header file
function cheader () {
if [[ -z "$1" ]]; then
echo "Usage:"
echo " $0 header-filename ... Print path of C header file (.c can be omitted)"
return 1
fi
# add .c if omitted
if [[ "$1" != *.h ]]; then
1="$1.h"
fi
# list of paths
local paths=()
paths+=("/usr/include/$1")
if [[ $(uname) == 'Darwin' ]]; then
paths+=("$(xcode-select -p)/SDKs/MacOSX.sdk/usr/include/$1")
fi
paths+=("/usr/local/include/$1")
for p in $paths; do
# check if file exists
if [[ -f $p ]]; then
echo "$p"
return 0
fi
done
echo "Couldn't find header $1"
return 2
}
alias ch=cheader
# Show motd when logging in
echo; motd
switchvenv_init
# --------------------------------------
# AUTOMATICALLY UPDATED BELOW THIS POINT
# --------------------------------------