From 8fbb496b0d7f4a3809f6449ef603f3cccb362636 Mon Sep 17 00:00:00 2001 From: "Kenneth Benzie (Benie)" Date: Sun, 22 Apr 2018 11:04:12 +0100 Subject: [PATCH] Add autoenv, automatic environment setup Using a hook, automatically detect when `.enter` and `.exit` scripts and source them when changing the shells current directory. --- autoenv/autoenv.plugin.zsh | 73 ++++++++++++++++++++++++++++++++++++++ zshrc | 1 + 2 files changed, 74 insertions(+) create mode 100644 autoenv/autoenv.plugin.zsh diff --git a/autoenv/autoenv.plugin.zsh b/autoenv/autoenv.plugin.zsh new file mode 100644 index 0000000..31c65bc --- /dev/null +++ b/autoenv/autoenv.plugin.zsh @@ -0,0 +1,73 @@ +# Automatically update the environment when the current working directory +# changes, this is a reimplementation of the ideas found in the repository +# https://github.com/Tarrasch/zsh-autoenv stripped down to suit my specific +# needs. + +# Global entered directories array. +_autoenv_entered=() + +# Source an enter script and add its directory to the global entered +# directories array. +_autoenv_enter() { + local entered=$1 + # If entered has already been sourced, return. + (( ${+_autoenv_entered[${_autoenv_entered[(i)$entered]}]} )) && return + # If the enter script is not authorized, return. + # TODO: _autoenv_authorized $entered/.enter || return + # Source the enter script. + source $entered/.enter + # Add the entered directory to the global entered array. + _autoenv_entered+=$entered +} + +# Source an exit script and remove its directory from the global entered +# directories array. +_autoenv_exit() { + local entered=$1 + # If the exit script is not authorized, return. + # TODO: _autoenv_authorized $entered/.exit || return + # Source the exit script. + source $entered/.exit + # Remove the entered directory from the global entered array. + _autoenv_entered[${_autoenv_entered[(i)$entered]}]=() +} + +# Find a directory containing a .enter file by searching up the directory tree +# starting in the current directory. +_autoenv_find_enter() { + local current=$PWD + # If an enter script is found in the current directory, return it. + [ -f "$current/.enter" ] && echo $current + # Loop until an enter script or the root directory is found. + while true; do + # Walk up one directory and make the path absolute. + local next=$current/..; local next=${next:A} + # If the current directory equals the next directory, return. + [[ $current == $next ]] && return || local current=$next + # If an enter script is found in the current directory, return it. + [ -f $current/.enter ] && echo $current + done +} + +# A chpwd hook function which automatically sources enter and exit scripts to +# setup local environments for directory and its subdirectories. +_autoenv_chpwd() { + local entered + # Loop over the entered directory stack. + for entered in $_autoenv_entered; do + # If the the current directory was previously entered then exit. + # TODO: Verify what this condition expression actually does. + ! [[ $PWD/ == $entered/* ]] && _autoenv_exit $entered + done + # Find the nearest enter script directory. + local enter=`_autoenv_find_enter` + # If the enter directory exists, enter it. + [ -d "$enter" ] && _autoenv_enter $enter +} + +# Register the autoenv chpwd hook. +autoload -U add-zsh-hook +add-zsh-hook chpwd _autoenv_chpwd + +# Ensure autoenv is activated in the current directory on first load. +_autoenv_chpwd diff --git a/zshrc b/zshrc index 357e130..95194d6 100644 --- a/zshrc +++ b/zshrc @@ -10,6 +10,7 @@ source-plugin() { source-plugin zsh-autosuggestions source-plugin zsh-history-substring-search source-plugin zsh-syntax-highlighting +source-plugin autoenv # Disable non end-of-line autosuggest accept widgets ZSH_AUTOSUGGEST_ACCEPT_WIDGETS=(end-of-line vi-end-of-line)