-
Notifications
You must be signed in to change notification settings - Fork 0
/
.zshrc
executable file
·247 lines (207 loc) · 9.54 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
# Keep history for 50000 commands.
HISTFILE=~/.histfile
HISTSIZE=50000
SAVEHIST=50000
# Do not put duplicate entries in the history. What is the point of pressing the
# up arrow thirty times and nothing happens?
setopt hist_ignore_dups
# Do not record a command in the history if it is prefixed by a space.
setopt hist_ignore_space
# Write history immediately instead of at exit. This ensures that history is not
# lost even when the shell is not properly terminated.
setopt inc_append_history
# Change dir automatically without the cd command.
setopt autocd
# Use Emacs-style controls (even though I use Vim).
bindkey -e
# Make all keys work in GNOME terminal. To generate the ~/.zkbd/$TERM file, run
# `autoload zkbd` and `zkbd`.
source ~/.zkbd/$TERM
[[ -n ${key[Home]} ]] && bindkey "${key[Home]}" beginning-of-line
[[ -n ${key[End]} ]] && bindkey "${key[End]}" end-of-line
[[ -n ${key[Delete]} ]] && bindkey "${key[Delete]}" delete-char
# Use FZF for history search (Ctrl + R), and use Ctrl + T to insert a file name
# from the current directory.
source /usr/share/fzf/key-bindings.zsh
# For some reason FZF started not respecting the default chronological order in
# reverse-i-search, make it do that after all. Also make the color integrate a
# bit more nicely. Edit: remove the --no-sort again, I think it was working
# better without it after all ... not sure what changed there.
export FZF_DEFAULT_OPTS="--color=dark,bg+:0"
# Make Ctrl + Z discard the current input, and bring it up again after the next
# command has finished. Ctrl-Z on empty input will still background the process.
ctrl-z-stash() {
emulate -LR zsh
if [[ $#BUFFER -eq 0 ]]; then
bg
zle redisplay
else
zle push-input
fi
}
zle -N ctrl-z-stash
bindkey "^Z" ctrl-z-stash
# Use Vim-inspired navigation key bindings in Emacs mode. This helps navigating
# those really long commands when you need to fix the typo right in the middle.
bindkey "^E" vi-forward-blank-word-end
bindkey "^W" vi-forward-blank-word
bindkey "^B" backward-word
# Enable completion.
autoload -Uz compinit
compinit
# Set preferred tools.
export CC='clang'
export CPP='clang -E'
export CXX='clang++'
export EDITOR='vim'
# Add ~/.local/bin to the path.
export PATH="$PATH:$HOME/.local/bin:$HOME/.nix-profile/bin"
# Allow cd'ing into subdirectories of ~/repos and ~/profile from anywhere.
export CDPATH=".:$HOME/repos:$HOME/profile"
# I only use Nix with locally pinned files, there should not be any global Nix
# search path. Unset the one that came with the AUR "nix" package.
unset NIX_PATH
# Add a pinned version of Nix 2.3 to the path.
# Nix 2.4 broke the entire CLI and there is no easy way to avoid it,
# so instead stick with 2.3.
alias nix='/nix/store/9hkh1fx8z1frgbz2nawr0mnyvizrb8yk-nix-2.3.15/bin/nix'
# But I do want to use flakes some times too, so add a Nix with flakes as well.
alias nix210='/nix/store/l0iqmrkw6l78fsixm8l9j6w52372wkhm-nix-2.10.3/bin/nix --extra-experimental-features nix-command --extra-experimental-features flakes'
# Colour ls and grep output by default. Also prevent ls from quoting names with
# spaces. Furthermore, list directories before files.
alias ls='ls --color=auto --quoting-style=literal --group-directories-first'
alias grep='grep --color=auto'
alias egrep='egrep --color=auto'
# MPV with loudness normalization, for watching movies or series without having
# to turn up the volume if there’s a conversation and then having to turn it
# down when there’s an explosion. We add a compressor with 40ms attack and 3s
# release (quite long, otherwise the effect is very apparent and that destroys
# the content).
alias mpv-loudnorm='gnome-session-inhibit mpv --audio-channels=stereo --af="acompressor=ratio=6:attack=40:release=3000,loudnorm=I=-18"'
# Journalctl is quite verbose by default, and its timestamp does not include the
# year. Fix that by picking ISO 8601 timestamps and omitting the hostname.
# (I wish there were a mode that replaces the T in ISO 8601 with a normal space.
# It hurts readability and there is no ambiguity anyway. </rant>)
alias journalctl='journalctl --output=short-iso --no-hostname'
# Use Git's diff functionality instead of GNU Diff. Git's is far superior. Use a
# function instead of an alias so we can define a custom autocomplete that
# completes files, not Git stuff.
function diff() {
git diff --no-index "$@"
}
# Autocomplete the diff alias.
compdef '_path_files _path_files' diff
# Fuzzy cd with fzf,
# based on https://github.com/junegunn/fzf/wiki/Examples#changing-directory.
function fd() {
local dir
dir=$(find ${1:-.} -path '*/\.*' -prune -o -type d -print 2> /dev/null | fzf +m) &&
cd "$dir"
}
# Allow exit the Vim way.
alias :q='exit'
# Aliases to cd up multiple directories.
alias ...='cd ../..'
alias ....='cd ../../..'
alias .....='cd ../../../..'
# Enter a Nix development environment, and create an indirect GC root for it
# at .nix-devenv, to ensure that it does not get garbage collected during the
# next 'nix-store --gc'.
function nsh {
nix build --no-link
nix-store --add-root .nix-devenv --indirect --realize $(nix path-info) > /dev/null
nix run -c $SHELL
}
# Same but then for using flakes.
function fsh {
# Build the devShell itself, record its store path.
shell_storepath=$(nix210 build --no-link --print-out-paths .#devShells.x86_64-linux.default)
# Adding a GC root for just the shell is insufficient, because Nix needs the
# flake inputs to determine the store path of the shell. `flake archive` can
# give us the store paths for the flake inputs, then we pass all of those to
# nix-store --add-root along the the shell itself.
nix210 flake archive --dry-run --json \
| jq --raw-output '.. | .path? | select(. != null)' \
| xargs --max-procs=1 \
nix-store --add-root .nix-devenv --indirect --realise ${shell_storepath} \
> /dev/null
# Finally, enter the development shell itself.
nix210 develop --command $SHELL
}
# The Gnome keyring does not support ed25519 keys, and it is annoying to have to
# unlock the key every time. Therefore start an ssh-agent that is shared among
# all shells, but do not load a key immediately. A manual ssh-add is still
# required, but after that the key will remain loaded and accessible to new
# shells.
# Store information about the running SSH agent in ~/.ssh/environment.
SSH_ENV=$HOME/.ssh/environment
# To start an ssh agent, run the program, which prints shell script that sets
# the right environment variables. It also echoes the PID, suppress that by
# commenting it with sed. Then make the file executable and evaluate it.
function start_ssh_agent {
ssh-agent | sed 's/^echo/#echo/' > "${SSH_ENV}"
chmod 600 "${SSH_ENV}"
. "${SSH_ENV}" > /dev/null
}
# If an environment file exists, run it to pick up the correct environment
# variables. If it turns out that the agent is no longer running, start a new
# agent. This will update the environment file. If there was no environment
# file, also start a new agent (and write the environment file).
if [ -f "${SSH_ENV}" ]; then
. "${SSH_ENV}" > /dev/null
ps ${SSH_AGENT_PID} | grep ssh-agent$ > /dev/null || {
start_ssh_agent;
}
else
start_ssh_agent;
fi
# Set suffix aliases to open certain files with an editor by default.
alias -s cpp=gvim
alias -s h=gvim
alias -s md=gvim
alias -s rs=gvim
# Make R store local packages in a sane location.
export R_LIBS_USER="$HOME/.local/lib/R/library"
# Customise the prompt, first load the plugins to set the colour and get the Git
# status.
autoload -Uz colors
autoload -Uz vcs_info
colors
# If any Nix store paths are on the path, extract the package name part from the
# directory. These act as a kind of virtualenv indicator. We first locate all
# Nix store paths that occur in the path, printing the matches, one per line.
# Then with Awk we cut off the store path prefix, and print everything on a
# single line, by setting the output record separator (ORS) to the empty string.
# Truncate to 30 characters if there's a lot of store paths on the path.
nix_paths=$(
echo $PATH \
| grep -E '/nix/store/[a-z0-9]{32}-([^/]+)' --only-matching \
| awk 'ORS = ""; { print substr($1, 45, length($1)) " " }' \
| awk '{ if (length($0) > 30) { print substr($0, 0, 30) "… " } else { print $0 }}'
)
# Alternatively, for my newer workflow, we can tell the name from the GC root.
if [[ -v NIX_GCROOT ]]; then
nix_paths=$(echo $NIX_GCROOT | awk '{ print substr($0, 45) " " }')
fi
nix_info_msg="%{$fg[blue]%}${nix_paths}%{$reset_color%}"
# Retrieve source control status before printing the prompt.
precmd() { vcs_info }
# Enable info for Git and Subversion. Do detect changes in the working
# directory. Format source control info as the branch in red, optionally with an
# action in yellow. Staged and unstaged changes will show as a red star and
# green plus.
zstyle ':vcs_info:*' enable git svn
zstyle ':vcs_info:*' check-for-changes true
zstyle ':vcs_info:*' formats "%{$fg[red]%}%b%u%c%{$reset_color%} "
zstyle ':vcs_info:*' actionformats "%{$fg[red]%}%b%u%c %{$fg[yellow]%}%a%{$reset_color%} "
zstyle ':vcs_info:*' unstagedstr "%{$fg[red]%}*"
zstyle ':vcs_info:*' stagedstr "%{$fg[green]%}+"
# Normally, the PS1 variable is evaluated only once, but because the vcs info
# changes, we need to do it on every prompt.
setopt prompt_subst
# Start with a newline, then user@host in green, then three components of the
# working directory, then source control (vcs) info, then a dollar in white.
# (There is no different charater for a root prompt, as root does not use this
# .zshrc anyway.)
PS1='
%{$fg[green]%}%n@%m%{$reset_color%} %3~ ${nix_info_msg}${vcs_info_msg_0_}%{$fg[white]%}$%{$reset_color%} '