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