-
-
Save elliottminns/09a598082d77f795c88e93f7f73dba61 to your computer and use it in GitHub Desktop.
| # =========================================== | |
| # ZSH Hacks - Dreams of Code | |
| # =========================================== | |
| # Add these to your .zshrc file | |
| # =========================================== | |
| # ------------------------------------------- | |
| # 1. Edit Command Buffer | |
| # ------------------------------------------- | |
| # Open the current command in your $EDITOR (e.g., neovim) | |
| # Press Ctrl+X followed by Ctrl+E to trigger | |
| autoload -Uz edit-command-line | |
| zle -N edit-command-line | |
| bindkey '^X^E' edit-command-line | |
| # For Vi mode users: | |
| # bindkey -M vicmd 'v' edit-command-line | |
| # ------------------------------------------- | |
| # 2. Undo in ZSH | |
| # ------------------------------------------- | |
| # Press Ctrl+_ (Ctrl+Underscore) to undo | |
| # This is built-in, no configuration needed! | |
| # Redo widget exists but has no default binding: | |
| # bindkey '^Y' redo # Example binding if you want it | |
| # ------------------------------------------- | |
| # 3. Magic Space - Expand History | |
| # ------------------------------------------- | |
| # Expands history expressions like !! or !$ when you press space | |
| bindkey ' ' magic-space | |
| # ------------------------------------------- | |
| # 4. chpwd Hook - Run Commands on Directory Change | |
| # ------------------------------------------- | |
| # NOTE: Only one chpwd hook can be defined at once | |
| # To merge them, use add-zsh-hook which is mentioned below | |
| # Example: List directory contents on cd | |
| chpwd() { | |
| ls | |
| } | |
| # Example: Auto-activate Python virtual environments | |
| chpwd() { | |
| if [[ -d .venv ]]; then | |
| source .venv/bin/activate | |
| fi | |
| } | |
| # Example: Auto-load Nix development shells | |
| chpwd() { | |
| if [[ -f flake.nix ]] && [[ -z "$IN_NIX_SHELL" ]]; then | |
| nix develop | |
| fi | |
| } | |
| # Example: Auto-use correct Node version with nvm | |
| chpwd() { | |
| if [[ -f .nvmrc ]]; then | |
| nvm use | |
| fi | |
| } | |
| # ------------------------------------------- | |
| # 4.1. Bonus: Merging Hooks | |
| # ------------------------------------------- | |
| # To merge hooks, use add-zsh-hook | |
| autoload -Uz add-zsh-hook | |
| # Then Define separate functions | |
| function auto_venv() { | |
| # If already in a virtualenv, do nothing | |
| if [[ -n "$VIRTUAL_ENV" && "$PWD" != *"${VIRTUAL_ENV:h}"* ]]; then | |
| deactivate | |
| return | |
| fi | |
| [[ -n "$VIRTUAL_ENV" ]] && return | |
| local dir="$PWD" | |
| while [[ "$dir" != "/" ]]; do | |
| if [[ -f "$dir/.venv/bin/activate" ]]; then | |
| source "$dir/.venv/bin/activate" | |
| return | |
| fi | |
| dir="${dir:h}" | |
| done | |
| } | |
| function auto_nix() { | |
| # If we're already in a nix develop shell, do nothing | |
| [[ -n "$IN_NIX_SHELL" ]] && return | |
| # Walk up to find a flake | |
| local dir="$PWD" | |
| while [[ "$dir" != "/" ]]; do | |
| if [[ -f "$dir/flake.nix" ]]; then | |
| # If this project already has .envrc, just allow it (you can remove this if you prefer) | |
| if [[ ! -f "$dir/.envrc" ]]; then | |
| # Create .envrc that loads the dev env (fast, no interactive shell) | |
| cat > "$dir/.envrc" <<'EOF' | |
| # autogenerated: load flake dev environment | |
| eval "$(nix print-dev-env)" | |
| EOF | |
| command direnv allow "$dir" >/dev/null 2>&1 | |
| fi | |
| command direnv reload >/dev/null 2>&1 | |
| return | |
| fi | |
| dir="${dir:h}" | |
| done | |
| } | |
| function auto_nvm() { | |
| [[ -f .nvmrc ]] && nvm use | |
| } | |
| # Register them all | |
| add-zsh-hook chpwd auto_venv | |
| add-zsh-hook chpwd auto_nix | |
| add-zsh-hook chpwd auto_nvm | |
| # ------------------------------------------- | |
| # 5. Suffix Aliases - Open Files by Extension | |
| # ------------------------------------------- | |
| # Just type the filename to open it with the associated program | |
| alias -s json=jless | |
| alias -s md=bat | |
| alias -s go='$EDITOR' | |
| alias -s rs='$EDITOR' | |
| alias -s txt=bat | |
| alias -s log=bat | |
| alias -s py='$EDITOR' | |
| alias -s js='$EDITOR' | |
| alias -s ts='$EDITOR' | |
| alias -s html=open # macOS: open in default browser | |
| # ------------------------------------------- | |
| # 6. Global Aliases - Use Anywhere in Commands | |
| # ------------------------------------------- | |
| # Redirect stderr to /dev/null | |
| alias -g NE='2>/dev/null' | |
| # Redirect stdout to /dev/null | |
| alias -g NO='>/dev/null' | |
| # Redirect both stdout and stderr to /dev/null | |
| alias -g NUL='>/dev/null 2>&1' | |
| # Pipe to jq | |
| alias -g J='| jq' | |
| # Copy output to clipboard (macOS) | |
| alias -g C='| pbcopy' | |
| # Copy output to clipboard (Linux with xclip) | |
| # alias -g C='| xclip -selection clipboard' | |
| # ------------------------------------------- | |
| # 7. zmv - Advanced Batch Rename/Move | |
| # ------------------------------------------- | |
| # Enable zmv | |
| autoload -Uz zmv | |
| # Usage examples: | |
| # zmv '(*).log' '$1.txt' # Rename .log to .txt | |
| # zmv -w '*.log' '*.txt' # Same thing, simpler syntax | |
| # zmv -n '(*).log' '$1.txt' # Dry run (preview changes) | |
| # zmv -i '(*).log' '$1.txt' # Interactive mode (confirm each) | |
| # Helpful aliases for zmv | |
| alias zcp='zmv -C' # Copy with patterns | |
| alias zln='zmv -L' # Link with patterns | |
| # ------------------------------------------- | |
| # 8. Named Directories - Bookmark Folders | |
| # ------------------------------------------- | |
| # Access with ~name syntax, e.g., cd ~yt or ls ~yt | |
| hash -d yt=~/projects/youtube | |
| hash -d dot=~/.dotfiles | |
| hash -d dl=~/Downloads | |
| # Add your own commonly used directories here | |
| # ------------------------------------------- | |
| # 9. Custom Widgets | |
| # ------------------------------------------- | |
| # Clear screen but keep current command buffer | |
| function clear-screen-and-scrollback() { | |
| echoti civis >"$TTY" | |
| printf '%b' '\e[H\e[2J\e[3J' >"$TTY" | |
| echoti cnorm >"$TTY" | |
| zle redisplay | |
| } | |
| zle -N clear-screen-and-scrollback | |
| bindkey '^Xl' clear-screen-and-scrollback | |
| # Copy current command buffer to clipboard (macOS) | |
| function copy-buffer-to-clipboard() { | |
| echo -n "$BUFFER" | pbcopy | |
| zle -M "Copied to clipboard" | |
| } | |
| zle -N copy-buffer-to-clipboard | |
| bindkey '^Xc' copy-buffer-to-clipboard | |
| # For Linux with wl-copy: | |
| # function copy-buffer-to-clipboard() { | |
| # echo -n "$BUFFER" | wl-copy | |
| # zle -M "Copied to clipboard" | |
| # } | |
| # ------------------------------------------- | |
| # 10. Hotkey Insertions - Text Snippets | |
| # ------------------------------------------- | |
| # Insert git commit template (Ctrl+X, G, C) | |
| # \C-b moves cursor back one position | |
| bindkey -s '^Xgc' 'git commit -m ""\C-b' | |
| # More examples: | |
| bindkey -s '^Xgp' 'git push origin ' | |
| bindkey -s '^Xgs' 'git status\n' | |
| bindkey -s '^Xgl' 'git log --oneline -n 10\n' |
@seanPruss I also had this issue. I changed the check to:
if [[ -n "$VIRTUAL_ENV" && "$PWD" != *"${VIRTUAL_ENV:h}"* ]]; then
deactivate
return
fi
The second part checks whether the parent folder of $VIRTUAL_ENV (this should be your project folder) appears in the $PWD string. If not, this suggests you are outside the project folder, and thus deactivates the venv.
Neither clear-screen-and-scrollback nor copy-buffer-to-clipboard work for me ๐
Those commands were the ones I most wanted... I'm on a Mac using Ghostty+tmux, not sure how to test why it's not working for me.
@mzaveiro Try them again! I had them bound to their Ctrl counterparts (ctrl+x ctrl+c) but they might be conflicting.
Now they're Ctrl+X c and Ctrl+X l
@seanPruss I also had this issue. I changed the check to:
if [[ -n "$VIRTUAL_ENV" && "$PWD" != *"${VIRTUAL_ENV:h}"* ]]; then deactivate return fiThe second part checks whether the parent folder of $VIRTUAL_ENV (this should be your project folder) appears in the $PWD string. If not, this suggests you are outside the project folder, and thus deactivates the venv.
Thanks for this snippet! I've gone ahead and modified my code :)
@mzaveiro Try them again! I had them bound to their Ctrl counterparts (
ctrl+x ctrl+c) but they might be conflicting.Now they're
Ctrl+X candCtrl+X l
Nice! Both work now ๐ Thanks for the quick reply!
idk if it was the same for you but $VIRTUAL_ENV was an absolute path for me so the auto_venv function didn't deactivate when I cd'd out of a directory with a venv