This repository has no description
8.3 kB
263 lines
1{ self, ... }:
2{
3 perSystem =
4 { pkgs, ... }:
5 let
6 zshrc = ''
7 autoload -U compinit && compinit
8
9 # Setup custom interactive shell init stuff.
10 # Bind gpg-agent to this TTY if gpg commands are used.
11 export GPG_TTY=$(tty)
12
13 # show how long a command takes
14 ZSH_COMMAND_TIME_MIN_SECONDS=3
15 ZSH_COMMAND_TIME_EXCLUDE=(vim)
16 ZSH_COMMAND_TIME_MSG="took: %s sec"
17 source ${
18 pkgs.fetchFromGitHub {
19 owner = "popstas";
20 repo = "zsh-command-time";
21 rev = "803d26eef526bff1494d1a584e46a6e08d25d918";
22 hash = "sha256-ndHVFcz+XmUW0zwFq7pBXygdRKyPLjDZNmTelhd5bv8=";
23 }
24 }/command-time.plugin.zsh
25
26 unsetopt nomatch # no matches found urls
27 setopt autocd extendedglob
28 bindkey -e
29
30 #C-x C-e open line in editor
31 autoload -z edit-command-line
32 zle -N edit-command-line
33 bindkey "^X^E" edit-command-line
34
35 #fzf inclusion
36 source ${pkgs.fzf}/share/fzf/completion.zsh
37 source ${pkgs.fzf}/share/fzf/key-bindings.zsh
38
39 # atuin distributed shell history
40 if type -p atuin >/dev/null; then
41 export ATUIN_CONFIG_DIR=${pkgs.writeTextDir "/config.toml" ''
42 auto_sync = true
43 update_check = false
44 sync_address = "http://green.r:8888"
45 sync_frequency = 0
46 style = "compact"
47 ''};
48 export ATUIN_NOBIND="true" # disable all keybdinings of atuin
49 eval "$(${pkgs.atuin}/bin/atuin init zsh)" # TODO make this optional?
50 bindkey '^r' _atuin_search_widget # bind ctrl+r to atuin
51 # use zsh only session history
52 fc -p
53 fi
54
55 #completion magic
56 autoload -Uz compinit
57 compinit
58 zstyle ':completion:*' menu select
59
60 #enable automatic rehashing of $PATH
61 zstyle ':completion:*' rehash true
62
63 # fancy mv which interactively gets the second argument if not given
64 function mv() {
65 if [[ "$#" -ne 1 ]] || [[ ! -e "$1" ]]; then
66 command mv -v "$@"
67 return
68 fi
69
70 newfilename="$1"
71 vared newfilename
72 command mv -v -- "$1" "$newfilename"
73 }
74
75 #emacs bindings
76 bindkey "[7~" beginning-of-line
77 bindkey "[8~" end-of-line
78 bindkey "Oc" emacs-forward-word
79 bindkey "Od" emacs-backward-word
80
81 # direnv integration
82 eval "$(${pkgs.direnv}/bin/direnv hook zsh)"
83
84 # Use nvim as MANPAGER if available
85 if command -v nvim >/dev/null 2>&1; then
86 export MANPAGER="nvim +Man!"
87 fi
88
89 # This function is called whenever a command is not found.
90 command_not_found_handler() {
91 local p='${pkgs.nix-index}/etc/profile.d/command-not-found.sh'
92 if [ -x "$p" ] && [ -f '/nix/var/nix/profiles/per-user/root/channels/nixos/programs.sqlite' ]; then
93 # Run the helper program.
94 "$p" "$@"
95
96 # Retry the command if we just installed it.
97 if [ $? = 126 ]; then
98 "$@"
99 else
100 return 127
101 fi
102 else
103 # Indicate than there was an error so ZSH falls back to its default handler
104 echo "$1: command not found" >&2
105 return 127
106 fi
107 }
108
109 download_nixpkgs_cache_index () {
110 filename="index-$(uname -m | sed 's/^arm64$/aarch64/')-$(uname | tr A-Z a-z)"
111 mkdir -p ~/.cache/nix-index && cd ~/.cache/nix-index
112 # -N will only download a new version if there is an update.
113 wget -q -N https://github.com/nix-community/nix-index-database/releases/latest/download/$filename
114 ln -f $filename files
115 }
116
117 # Setup aliases.
118 alias -- grep='grep --color=auto'
119 alias -- ip='ip -color=auto'
120 alias -- l='ls -alh'
121 alias -- la='ls -la'
122 alias -- ll='ls -l'
123 alias -- ls='ls --color'
124 alias -- ns='nix-shell --command zsh'
125 alias -- nb='nix build --no-link --print-out-paths -L'
126 alias -- ne='nix eval --json'
127 alias -- nloc='nix-locate --top-level --whole-name'
128
129 # Setup prompt.
130 autoload -U promptinit
131 promptinit
132
133 p_error='%(?..%F{red}%?%f )'
134 t_error='%(?..%? )'
135
136 case $UID in
137 0)
138 p_username='%F{red}root%f'
139 t_username='root'
140 ;;
141 1337)
142 p_username=""
143 t_username=""
144 ;;
145 *)
146 p_username='%F{blue}%n%f'
147 t_username='%n'
148 ;;
149 esac
150
151 if test -n "$SSH_CLIENT"; then
152 p_hostname='@%F{magenta}%M%f '
153 t_hostname='@%M '
154 else
155 p_hostname=""
156 t_hostname=""
157 fi
158
159 #check if in nix shell
160 if test -n "$IN_NIX_SHELL"; then
161 p_nixshell='%F{green}[s]%f '
162 t_nixshell='[s] '
163 else
164 p_nixshell=""
165 t_nixshell=""
166 fi
167
168 PROMPT="$p_error$p_username$p_hostname$p_nixshell%~ "
169 TITLE="$t_error$t_username$t_hostname$t_nixshell%~"
170 case $TERM in
171 (*xterm* | *rxvt*)
172 function precmd {
173 PROMPT_EVALED=$(print -P "$TITLE")
174 echo -ne "\033]0;$$ $PROMPT_EVALED\007"
175 }
176 # This seems broken for some reason
177 # # This is seen while the shell waits for a command to complete.
178 # function preexec {
179 # PROMPT_EVALED=$(print -P "$TITLE")
180 # echo -ne "\033]0;$$ $PROMPT_EVALED $1\007"
181 # }
182 ;;
183 esac
184
185
186 # Auto-start tmux for new sessions
187 # Check if we're already in tmux (even through sudo)
188 if [[ "$TERM" != "linux" && -z "$TMUX" && "$TERM" != "dumb" ]]; then
189 # Check if we're inside tmux by looking for tmux in the process tree
190 in_tmux=false
191 pid=$$
192 while [[ $pid -ne 1 ]]; do
193 if ps -p $pid -o comm= 2>/dev/null | grep -q '^tmux'; then
194 in_tmux=true
195 break
196 fi
197 # Get parent PID
198 pid=$(ps -p $pid -o ppid= 2>/dev/null | tr -d ' ') || break
199 done
200
201 if [[ "$in_tmux" == "false" ]]; then
202 # Preserve SSH_AUTH_SOCK for tmux
203 if [[ -n "$SSH_AUTH_SOCK" ]]; then
204 tmux set-environment -g SSH_AUTH_SOCK "$SSH_AUTH_SOCK" 2>/dev/null
205 fi
206
207 # Generate a readable session name using name-generator
208 session_name=$(${self.packages.${pkgs.system}.name-generator}/bin/name-generator 2>/dev/null || echo "session-$$")
209 # Start tmux with the generated session name
210 exec tmux -u new-session -s "$session_name"
211 fi
212 fi
213
214 # Set tmux status bar color based on hostname for SSH sessions
215 if [[ -n "$TMUX" && "$__host__" != "$HOST" ]]; then
216 # Generate a color based on hostname hash
217 color=$(( $(echo -n "$HOST" | od -An -N4 -tu4) % 255 ))
218 tmux set -g status-bg "colour$color" 2>/dev/null || true
219 export __host__="$HOST"
220 fi
221
222 # Configure tmux for better mouse support
223 if [[ -n "$TMUX" ]]; then
224 # Enable mouse mode for scrolling
225 tmux set -g mouse on 2>/dev/null || true
226 fi
227
228 # Disable some features to support TRAMP.
229 if [ "$TERM" = dumb ]; then
230 unsetopt zle prompt_cr prompt_subst
231 unset RPS1 RPROMPT
232 PS1='$ '
233 PROMPT='$ '
234 fi
235 '';
236 in
237 {
238 packages.zsh = pkgs.symlinkJoin {
239 name = "zsh-with-config";
240 paths = [
241 (pkgs.writeShellApplication {
242 name = "zsh";
243 runtimeInputs = with pkgs; [
244 tmux
245 fzf
246 direnv
247 atuin
248 nix-index
249 self.packages.${pkgs.system}.name-generator
250 ];
251 text = ''
252 export ZDOTDIR=${pkgs.writeTextDir "/.zshrc" zshrc}
253 exec ${pkgs.zsh}/bin/zsh "$@"
254 '';
255 })
256 pkgs.zsh
257 ];
258 passthru = {
259 inherit zshrc;
260 };
261 };
262 };
263}