Skip to content

Instantly share code, notes, and snippets.

@laggardkernel
Created July 4, 2019 04:42
Show Gist options
  • Save laggardkernel/607877fde3b821d1fbc560410c75e847 to your computer and use it in GitHub Desktop.
Save laggardkernel/607877fde3b821d1fbc560410c75e847 to your computer and use it in GitHub Desktop.
Cash First #zsh
_env_init() {
  # init version manager without rehash on startup
  local SHELL_NAME="zsh"
  local init_args=(- --no-rehash zsh)
  local zshrc="$HOME/.zshrc"
  
  # For security on Linux
  [[ -n $XDG_RUNTIME_DIR ]] && local TMPDIR="$XDG_RUNTIME_DIR"

  for i in nodenv rbenv; do
    cache_file="${TMPDIR:-/tmp}/${i}-cache.$UID.${SHELL_NAME}"
    if [[ "${commands[$i]}" -nt "$cache_file" \
      || "$zshrc" -nt "$cache_file" \
      || ! -s "$cache_file"  ]]; then

      # Cache init code.
      $i init "${init_args[@]}" >| "$cache_file" 2>/dev/null
    fi

    source "$cache_file"
    unset cache_file
  done

  # pyenv: skip init if a venv is activated by poetry or pipenv
  if [[ -z $POETRY_ACTIVE ]] && [[ -z $PIPENV_ACTIVE ]]; then
    cache_file="${TMPDIR:-/tmp}/pyenv-cache.$UID.${SHELL_NAME}"
    if [[ "${commands[pyenv]}" -nt "$cache_file" \
      || "$zshrc" -nt "$cache_file" \
      || ! -s "$cache_file"  ]]; then

      # Cache init code.
      pyenv init "${init_args[@]}" >| "$cache_file" 2>/dev/null
    fi

    source "$cache_file"
    unset cache_file

    # pyenv-virtualenv init
    init_args=(- zsh)

    cache_file="${TMPDIR:-/tmp}/pyenv-virtualenv-cache.$UID.${SHELL_NAME}"
    if [[ "${commands[pyenv-virtualenv]}" -nt "$cache_file" \
      || "$zshrc" -nt "$cache_file" \
      || ! -s "$cache_file"  ]]; then

      pyenv virtualenv-init "${init_args[@]}" >| "$cache_file" 2>/dev/null
    fi

    source "$cache_file"
    
    # remove _pyenv_virtualenv_hook, cause
    # 1. it's heavy, slow down command execution dramatically
    # 2. `pyenv local <venv-name>` is enough, no need to use
    #    `pyenv activate <venv-name>` to mimic the behavior of `source venv/bin/activate`
    autoload -Uz add-zsh-hook
    add-zsh-hook -D precmd _pyenv_virtualenv_hook

    unset cache_file
  fi

  unset init_args
  
  # optional: rehash manually
  # for i in rbenv pyenv nodenv; do
  #   (( $+commands[i] )) && $i rehash
  # done
}

# created a dummy plugin with `zplugin create _local/init0`, then press Enter twice.
# or create the dummy plugin manually with following codes,

# if ! [[ -d "${ZPLGM[HOME_DIR]}/plugins/_local---init1" ]]; then
#   mkdir -p "${ZPLGM[HOME_DIR]}/plugins/_local---init1" 2>/dev/null
#   touch "${ZPLGM[HOME_DIR]}/plugins/_local---init1/init.plugin.zsh" 2>/dev/null
# fi

zplugin ice wait'0' atload'_env_init' lucid
zplugin light _local/init0

rbenv and its forks support auto rehash after installation of a new pkg. You may still need to do rehash manually after you uninstall a pkg, or after installation of a new version of ruby/python/node.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment