This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

superconfig / tools / zsh / flake-module.nix
11 kB 326 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 # Lazy load completions for commands based on their installation path 64 _lazy_completion_loader() { 65 local cmd="$words[1]" 66 [[ -n "$ZSH_COMP_DEBUG" ]] && echo "DEBUG: _lazy_completion_loader called for cmd: $cmd" >&2 67 68 if command -v "$cmd" >/dev/null 2>&1; then 69 local cmd_path="$(which "$cmd" 2>/dev/null)" 70 [[ -n "$ZSH_COMP_DEBUG" ]] && echo "DEBUG: initial cmd_path: $cmd_path" >&2 71 72 local found_zsh_completions=false 73 74 # Follow absolute symlinks and check each level 75 while [[ -n "$cmd_path" ]]; do 76 local share_dir="$(dirname "$cmd_path")/../share" 77 [[ -n "$ZSH_COMP_DEBUG" ]] && echo "DEBUG: checking share_dir: $share_dir" >&2 78 79 # Check zsh completion directories 80 for dir in "$share_dir/zsh/site-functions" "$share_dir/zsh/vendor-completions"; do 81 if [[ -d "$dir" ]]; then 82 [[ ! " ''${fpath[@]} " =~ " $dir " ]] && fpath=("$dir" $fpath) 83 if [[ -f "$dir/_$cmd" ]]; then 84 found_zsh_completions=true 85 [[ -n "$ZSH_COMP_DEBUG" ]] && echo "DEBUG: found zsh completion: $dir/_$cmd" >&2 86 fi 87 fi 88 done 89 90 # Follow absolute symlink or stop 91 if [[ -L "$cmd_path" ]]; then 92 cmd_path="$(readlink "$cmd_path" 2>/dev/null)" 93 [[ "$cmd_path" == /* ]] || cmd_path="" # Only follow absolute symlinks 94 [[ -n "$ZSH_COMP_DEBUG" ]] && echo "DEBUG: following symlink to: $cmd_path" >&2 95 else 96 break 97 fi 98 done 99 100 # Load completions if found 101 if [[ "$found_zsh_completions" == true ]]; then 102 [[ -n "$ZSH_COMP_DEBUG" ]] && echo "DEBUG: reinitializing completions" >&2 103 compinit &>/dev/null 104 fi 105 fi 106 107 # Save completion function before removing lazy loader 108 local completion_function="''${_comps[$cmd]:-}" 109 compdef -d "$cmd" 2>/dev/null 110 111 # Use loaded completion or fall back to normal 112 if [[ -n "$completion_function" ]]; then 113 $completion_function "$@" 114 else 115 _normal 116 fi 117 } 118 119 # Set as default completer for commands without completions 120 zstyle -e ':completion:*' completer ' 121 if [[ -z $_comps[$words[1]] ]]; then 122 reply=(_lazy_completion_loader _complete) 123 else 124 reply=(_complete) 125 fi 126 ' 127 128 # fancy mv which interactively gets the second argument if not given 129 function mv() { 130 if [[ "$#" -ne 1 ]] || [[ ! -e "$1" ]]; then 131 command mv -v "$@" 132 return 133 fi 134 135 newfilename="$1" 136 vared newfilename 137 command mv -v -- "$1" "$newfilename" 138 } 139 140 #emacs bindings 141 bindkey "[7~" beginning-of-line 142 bindkey "[8~" end-of-line 143 bindkey "Oc" emacs-forward-word 144 bindkey "Od" emacs-backward-word 145 146 # direnv integration 147 eval "$(${pkgs.direnv}/bin/direnv hook zsh)" 148 149 # Use nvim as MANPAGER if available and output is not piped 150 if command -v nvim >/dev/null 2>&1; then 151 export MANPAGER='sh -c "if [ -t 1 ]; then nvim +Man!; else cat; fi"' 152 fi 153 154 # This function is called whenever a command is not found. 155 command_not_found_handler() { 156 local p='${pkgs.nix-index}/etc/profile.d/command-not-found.sh' 157 if [ -x "$p" ] && [ -f '/nix/var/nix/profiles/per-user/root/channels/nixos/programs.sqlite' ]; then 158 # Run the helper program. 159 "$p" "$@" 160 161 # Retry the command if we just installed it. 162 if [ $? = 126 ]; then 163 "$@" 164 else 165 return 127 166 fi 167 else 168 # Indicate than there was an error so ZSH falls back to its default handler 169 echo "$1: command not found" >&2 170 return 127 171 fi 172 } 173 174 download_nixpkgs_cache_index () { 175 filename="index-$(uname -m | sed 's/^arm64$/aarch64/')-$(uname | tr A-Z a-z)" 176 mkdir -p ~/.cache/nix-index && cd ~/.cache/nix-index 177 # -N will only download a new version if there is an update. 178 wget -q -N https://github.com/nix-community/nix-index-database/releases/latest/download/$filename 179 ln -f $filename files 180 } 181 182 # Setup aliases. 183 alias -- grep='grep --color=auto' 184 alias -- ip='ip -color=auto' 185 alias -- l='ls -alh' 186 alias -- la='ls -la' 187 alias -- ll='ls -l' 188 alias -- ls='ls --color' 189 alias -- ns='nix-shell --command zsh' 190 alias -- nb='nix build --no-link --print-out-paths -L' 191 alias -- ne='nix eval --json' 192 alias -- nloc='nix-locate --top-level --whole-name' 193 194 # Setup prompt. 195 autoload -U promptinit 196 promptinit 197 198 p_error='%(?..%F{red}%?%f )' 199 t_error='%(?..%? )' 200 201 case $UID in 202 0) 203 p_username='%F{red}root%f' 204 t_username='root' 205 ;; 206 1337) 207 p_username="" 208 t_username="" 209 ;; 210 *) 211 p_username='%F{blue}%n%f' 212 t_username='%n' 213 ;; 214 esac 215 216 if test -n "$SSH_CLIENT"; then 217 p_hostname='@%F{magenta}%M%f ' 218 t_hostname='@%M ' 219 else 220 p_hostname="" 221 t_hostname="" 222 fi 223 224 #check if in nix shell 225 if test -n "$IN_NIX_SHELL"; then 226 p_nixshell='%F{green}[s]%f ' 227 t_nixshell='[s] ' 228 else 229 p_nixshell="" 230 t_nixshell="" 231 fi 232 233 PROMPT="$p_error$p_username$p_hostname$p_nixshell%~ " 234 TITLE="$t_error$t_username$t_hostname$t_nixshell%~" 235 case $TERM in 236 (*xterm* | *rxvt*) 237 function precmd { 238 PROMPT_EVALED=$(print -P "$TITLE") 239 echo -ne "\033]0;$$ $PROMPT_EVALED\007" 240 } 241 # This seems broken for some reason 242 # # This is seen while the shell waits for a command to complete. 243 # function preexec { 244 # PROMPT_EVALED=$(print -P "$TITLE") 245 # echo -ne "\033]0;$$ $PROMPT_EVALED $1\007" 246 # } 247 ;; 248 esac 249 250 251 # Auto-start tmux for new sessions 252 # Check if we're already in tmux (even through sudo) 253 if [[ "$TERM" != "linux" && -z "$TMUX" && "$TERM" != "dumb" ]]; then 254 # Check if we're inside tmux by looking for tmux in the process tree 255 in_tmux=false 256 pid=$$ 257 while [[ $pid -ne 1 ]]; do 258 if ps -p $pid -o comm= 2>/dev/null | grep -q '^tmux'; then 259 in_tmux=true 260 break 261 fi 262 # Get parent PID 263 pid=$(ps -p $pid -o ppid= 2>/dev/null | tr -d ' ') || break 264 done 265 266 if [[ "$in_tmux" == "false" ]]; then 267 # Preserve SSH_AUTH_SOCK for tmux 268 if [[ -n "$SSH_AUTH_SOCK" ]]; then 269 tmux set-environment -g SSH_AUTH_SOCK "$SSH_AUTH_SOCK" 2>/dev/null 270 fi 271 272 # Generate a readable session name using name-generator 273 session_name=$(${ 274 self.packages.${pkgs.system}.name-generator 275 }/bin/name-generator 2>/dev/null || echo "session-$$") 276 # Start tmux with the generated session name 277 exec tmux -u new-session -s "$session_name" 278 fi 279 fi 280 281 # Set tmux status bar color based on hostname for SSH sessions 282 if [[ -n "$TMUX" && "$__host__" != "$HOST" ]]; then 283 # Generate a color based on hostname hash 284 color=$(( $(echo -n "$HOST" | od -An -N4 -tu4) % 255 )) 285 tmux set -g status-bg "colour$color" 2>/dev/null || true 286 export __host__="$HOST" 287 fi 288 289 # Configure tmux for better mouse support 290 if [[ -n "$TMUX" ]]; then 291 # Enable mouse mode for scrolling 292 tmux set -g mouse on 2>/dev/null || true 293 fi 294 295 # Disable some features to support TRAMP. 296 if [ "$TERM" = dumb ]; then 297 unsetopt zle prompt_cr prompt_subst 298 unset RPS1 RPROMPT 299 PS1='$ ' 300 PROMPT='$ ' 301 fi 302 ''; 303 in 304 { 305 packages.zsh = 306 (self.libWithPkgs.${pkgs.system}.makeWrapper pkgs.zsh { 307 runtimeInputs = with pkgs; [ 308 gnugrep 309 tmux 310 fzf 311 direnv 312 atuin 313 nix-index 314 self.packages.${pkgs.system}.name-generator 315 ]; 316 env = { 317 ZDOTDIR = pkgs.writeTextDir "/.zshrc" zshrc; 318 }; 319 }).overrideAttrs 320 (old: { 321 passthru = (old.passthru or { }) // { 322 inherit zshrc; 323 }; 324 }); 325 }; 326}