Add autoenv command to manage autoenv's
usage: autoenv [-h] {init,edit,deinit}
options:
        -h, --help  show this help message and exit
commands:
        init        add .enter and .exit scripts in current directory
        edit        edit .enter and .exit scripts in current directory
        deinit      remove .enter and .exit scripts in current directory
Fixes #9.
			
			
This commit is contained in:
		
							parent
							
								
									40c2395f43
								
							
						
					
					
						commit
						36c4247e60
					
				
							
								
								
									
										24
									
								
								autoenv/_autoenv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								autoenv/_autoenv
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
			
		||||
#compdef autoenv
 | 
			
		||||
 | 
			
		||||
# Completion for the autoenv command.
 | 
			
		||||
_autoenv() {
 | 
			
		||||
  local ret=1 context curcontext="$curcontext" state line
 | 
			
		||||
  typeset -A opt_args
 | 
			
		||||
 | 
			
		||||
  _arguments -C -w -s \
 | 
			
		||||
    '(-h --help)'{-h,--help}'[show this help message and exit]' \
 | 
			
		||||
    '1: :->command'
 | 
			
		||||
 | 
			
		||||
  case $state in
 | 
			
		||||
    (command)
 | 
			
		||||
      declare -a commands
 | 
			
		||||
      local commands=(
 | 
			
		||||
        init:'add .enter and .exit scripts in current directory'
 | 
			
		||||
        edit:'edit .enter and .exit scripts in current directory'
 | 
			
		||||
        deinit:'remove .enter and .exit scripts in current directory'
 | 
			
		||||
      )
 | 
			
		||||
      _describe -t commands command commands && ret=0 ;;
 | 
			
		||||
  esac
 | 
			
		||||
 | 
			
		||||
  return ret
 | 
			
		||||
}
 | 
			
		||||
@ -1,108 +1,4 @@
 | 
			
		||||
# 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 bare essentials.
 | 
			
		||||
#
 | 
			
		||||
# The secret sauce can be found at the bottom of this file, where the `chpwd`
 | 
			
		||||
# hook function `_autoenv_chpwd` is added.
 | 
			
		||||
 | 
			
		||||
# Global entered directories array.
 | 
			
		||||
_autoenv_entered=()
 | 
			
		||||
 | 
			
		||||
# Check if the given file is authorized, if not prompt the user to authorize,
 | 
			
		||||
# ignore, or view the file. Authorized files and their modified times are
 | 
			
		||||
# stored in the ~/.cache/autoenv/authorized file to make authorization
 | 
			
		||||
# persistent.
 | 
			
		||||
_autoenv_authorized() {
 | 
			
		||||
  local file=$1
 | 
			
		||||
  # If autoenv cache directory does not exist, create it.
 | 
			
		||||
  local cache_dir=~/.cache/autoenv
 | 
			
		||||
  ! [ -d $cache_dir ] && mkdir -p $cache_dir
 | 
			
		||||
  local authorized_file=$cache_dir/authorized
 | 
			
		||||
  # Define a map to hold authorized key value pairs.
 | 
			
		||||
  typeset -A authorized=()
 | 
			
		||||
  # If the authorized file exists, load it into the map.
 | 
			
		||||
  [ -f $authorized_file ] && typeset -A authorized=(`cat $authorized_file`)
 | 
			
		||||
  # If the given file has been authorized, i.e. the modified time matches that
 | 
			
		||||
  # held in the authorized file, return.
 | 
			
		||||
  local modified_time=`zstat +mtime $file`
 | 
			
		||||
  [ "$authorized[$file]" = "$modified_time" ] && return
 | 
			
		||||
  # Prompt to authorize file.
 | 
			
		||||
  while true; do
 | 
			
		||||
    read "answer?Authorize $file [Y/n/v]? "
 | 
			
		||||
    case "$answer" in
 | 
			
		||||
      y|Y|yes|'')             # Authorize the file.
 | 
			
		||||
        authorized[$file]=$modified_time; break ;;
 | 
			
		||||
      n|N|no) return 1 ;;     # Do not authorize the file.
 | 
			
		||||
      v|V|view) cat $file ;;  # View the file.
 | 
			
		||||
    esac
 | 
			
		||||
  done
 | 
			
		||||
  # Store authorized associative array in authorized file.
 | 
			
		||||
  echo ${(kv)authorized} > $authorized_file
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Source an enter script and add its directory to the global entered
 | 
			
		||||
# directories array.
 | 
			
		||||
_autoenv_enter() {
 | 
			
		||||
  local entered=$1
 | 
			
		||||
  # If entered exists in the entered directories array, return.
 | 
			
		||||
  (( ${+_autoenv_entered[${_autoenv_entered[(i)$entered]}]} )) && return
 | 
			
		||||
  # If the enter script is not authorized, return.
 | 
			
		||||
  _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.
 | 
			
		||||
  _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 all directories containing a .enter file by searching up the directory
 | 
			
		||||
# tree starting in the current directory.
 | 
			
		||||
_autoenv_find_enter_directories() {
 | 
			
		||||
  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
 | 
			
		||||
    # Go up one directory and make the path absolute.
 | 
			
		||||
    local next=$current/..; local next=${next:A}
 | 
			
		||||
    # If an enter script is found in the current directory, return it.
 | 
			
		||||
    [ -f $next/.enter ] && echo $next
 | 
			
		||||
    # If the current directory equals the next directory we are done, otherwise
 | 
			
		||||
    # update the current directory.
 | 
			
		||||
    [[ $current == $next ]] && return || local current=$next
 | 
			
		||||
  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 reversed entered directory array.
 | 
			
		||||
  for entered in ${(aO)_autoenv_entered}; do
 | 
			
		||||
    # If the the current directory was previously entered then exit.
 | 
			
		||||
    ! [[ $PWD/ == $entered/* ]] && _autoenv_exit $entered
 | 
			
		||||
  done
 | 
			
		||||
  # Find all enter script directories, store them in an array.
 | 
			
		||||
  local enter_dirs=(`_autoenv_find_enter_directories`)
 | 
			
		||||
  # Loop over reversed enter script directories array, so enter scripts found
 | 
			
		||||
  # last are sourced first, then source all enter scripts.
 | 
			
		||||
  for enter in ${(aO)enter_dirs}; do _autoenv_enter $enter; done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# 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
 | 
			
		||||
# Source the autoenv implementation script.
 | 
			
		||||
source ${0:a:h}/autoenv.zsh
 | 
			
		||||
# Add the autoenv directory to fpath for completion.
 | 
			
		||||
fpath+=${0:a:h}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										179
									
								
								autoenv/autoenv.zsh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								autoenv/autoenv.zsh
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,179 @@
 | 
			
		||||
# 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 bare essentials.
 | 
			
		||||
#
 | 
			
		||||
# The secret sauce can be found at the bottom of this file, where the chpwd
 | 
			
		||||
# hook function _autoenv_chpwd is added.
 | 
			
		||||
 | 
			
		||||
# The autoenv command provides a convenient way to create, edit, and remove
 | 
			
		||||
# enter and exit scripts in the current directory.
 | 
			
		||||
autoenv() {
 | 
			
		||||
  local cmd=$1
 | 
			
		||||
  case "$cmd" in
 | 
			
		||||
    -h|--help)  # Display help.
 | 
			
		||||
      echo "\
 | 
			
		||||
usage: autoenv [-h] {init,edit,deinit}
 | 
			
		||||
 | 
			
		||||
options:
 | 
			
		||||
        -h, --help  show this help message and exit
 | 
			
		||||
 | 
			
		||||
commands:
 | 
			
		||||
        init        add .enter and .exit scripts in current directory
 | 
			
		||||
        edit        edit .enter and .exit scripts in current directory
 | 
			
		||||
        deinit      remove .enter and .exit scripts in current directory"
 | 
			
		||||
      ;;
 | 
			
		||||
 | 
			
		||||
    init)  # Create enter and exit scripts in current directory.
 | 
			
		||||
      if [ -f $PWD/.enter ] || [ -f $PWD/.exit ]; then
 | 
			
		||||
        echo '.enter or .exit already exists'; return 1
 | 
			
		||||
      fi
 | 
			
		||||
      # Create then edit enter and exit scripts.
 | 
			
		||||
      touch .enter .exit && autoenv edit
 | 
			
		||||
      # If enter script exists, authorize it.
 | 
			
		||||
      [ -f $PWD/.enter ] && _autoenv_authorized $PWD/.enter yes
 | 
			
		||||
      # If exit script exists, authorize it.
 | 
			
		||||
      [ -f $PWD/.exit ] && _autoenv_authorized $PWD/.exit yes
 | 
			
		||||
      # Enter the new autoenv.
 | 
			
		||||
      _autoenv_enter $PWD ;;
 | 
			
		||||
 | 
			
		||||
    edit)  # Edit enter and exit scripts in current directory.
 | 
			
		||||
      if ! [ -f $PWD/.enter ] || ! [ -f $PWD/.exit ]; then
 | 
			
		||||
        echo '.enter or .exit not found'; return 1
 | 
			
		||||
      fi
 | 
			
		||||
      # If vim exists, edit enter and exit scripts.
 | 
			
		||||
      if which vim &> /dev/null; then
 | 
			
		||||
        vim -p .enter .exit
 | 
			
		||||
      else
 | 
			
		||||
        echo 'vim not found'; return 1
 | 
			
		||||
      fi ;;
 | 
			
		||||
 | 
			
		||||
    deinit)  # Remove enter and exit scripts in current directory.
 | 
			
		||||
      if [ -f $PWD/.enter ] || [ -f $PWD/.exit ]; then
 | 
			
		||||
        # Prompt user to confirm removal of enter and exit scripts.
 | 
			
		||||
        while true; do
 | 
			
		||||
          read "answer?Are you sure [y/N]? "
 | 
			
		||||
          case "$answer" in
 | 
			
		||||
            y|Y|yes)
 | 
			
		||||
              # Remove enter and exit scripts if they exist.
 | 
			
		||||
              [ -f $PWD/.enter ] && rm $PWD/.enter
 | 
			
		||||
              [ -f $PWD/.exit ] && rm $PWD/.exit
 | 
			
		||||
              break ;;
 | 
			
		||||
            *) break ;;
 | 
			
		||||
          esac
 | 
			
		||||
        done
 | 
			
		||||
      else
 | 
			
		||||
        echo '.enter and .exit not found'; return 1
 | 
			
		||||
      fi ;;
 | 
			
		||||
 | 
			
		||||
    *)  # Invalid arguments, show help then error.
 | 
			
		||||
      echo "invalid arguments: $@"
 | 
			
		||||
      autoenv --help
 | 
			
		||||
      return 1 ;;
 | 
			
		||||
  esac
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Global entered directories array.
 | 
			
		||||
_autoenv_entered=()
 | 
			
		||||
 | 
			
		||||
# Check if the given file is authorized, if not prompt the user to authorize,
 | 
			
		||||
# ignore, or view the file. Authorized files and their modified times are
 | 
			
		||||
# stored in the ~/.cache/autoenv/authorized file to make authorization
 | 
			
		||||
# persistent.
 | 
			
		||||
_autoenv_authorized() {
 | 
			
		||||
  local file=$1 yes=$2
 | 
			
		||||
  # If autoenv cache directory does not exist, create it.
 | 
			
		||||
  ! [ -d ~/.cache/autoenv ] && mkdir -p ~/.cache/autoenv
 | 
			
		||||
  # If the authorized file does not exist, create it.
 | 
			
		||||
  ! [ -f ~/.cache/autoenv/authorized ] && touch ~/.cache/autoenv/authorized
 | 
			
		||||
  # Load the authorized file into a map of authorized key value pairs.
 | 
			
		||||
  typeset -A authorized=(`cat ~/.cache/autoenv/authorized`)
 | 
			
		||||
  # If the file has been removed, return.
 | 
			
		||||
  ! [ -f $file ] && return 1
 | 
			
		||||
  # If the given file has been authorized, i.e. the modified time matches that
 | 
			
		||||
  # held in the authorized file, return.
 | 
			
		||||
  local modified_time=`zstat +mtime $file`
 | 
			
		||||
  [ "$authorized[$file]" = "$modified_time" ] && return
 | 
			
		||||
  # If yes, don't prompt for user confirmation.
 | 
			
		||||
  if [ "$yes" != "yes" ]; then
 | 
			
		||||
    # Prompt to authorize file.
 | 
			
		||||
    while true; do
 | 
			
		||||
      read "answer?Authorize $file [Y/n/v]? "
 | 
			
		||||
      case "$answer" in
 | 
			
		||||
        y|Y|yes|'') break ;;    # Authorize the file.
 | 
			
		||||
        n|N|no) return 1 ;;     # Do not authorize the file.
 | 
			
		||||
        v|V|view) cat $file ;;  # View the file.
 | 
			
		||||
      esac
 | 
			
		||||
    done
 | 
			
		||||
  fi
 | 
			
		||||
  # Add file to the authorized map.
 | 
			
		||||
  authorized[$file]=$modified_time
 | 
			
		||||
  # Store authorized map in authorized file.
 | 
			
		||||
  echo ${(kv)authorized} > ~/.cache/autoenv/authorized
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Source an enter script and add its directory to the global entered
 | 
			
		||||
# directories array.
 | 
			
		||||
_autoenv_enter() {
 | 
			
		||||
  local entered=$1
 | 
			
		||||
  # If entered exists in the entered directories array, return.
 | 
			
		||||
  (( ${+_autoenv_entered[${_autoenv_entered[(i)$entered]}]} )) && return
 | 
			
		||||
  # If the enter script is not authorized, return.
 | 
			
		||||
  _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.
 | 
			
		||||
  _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 all directories containing a .enter file by searching up the directory
 | 
			
		||||
# tree starting in the current directory.
 | 
			
		||||
_autoenv_find_enter_directories() {
 | 
			
		||||
  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
 | 
			
		||||
    # Go up one directory and make the path absolute.
 | 
			
		||||
    local next=$current/..; local next=${next:A}
 | 
			
		||||
    # If an enter script is found in the current directory, return it.
 | 
			
		||||
    [ -f $next/.enter ] && echo $next
 | 
			
		||||
    # If the current directory equals the next directory we are done, otherwise
 | 
			
		||||
    # update the current directory.
 | 
			
		||||
    [[ $current == $next ]] && return || local current=$next
 | 
			
		||||
  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 reversed entered directory array.
 | 
			
		||||
  for entered in ${(aO)_autoenv_entered}; do
 | 
			
		||||
    # If the the current directory was previously entered then exit.
 | 
			
		||||
    ! [[ $PWD/ == $entered/* ]] && _autoenv_exit $entered
 | 
			
		||||
  done
 | 
			
		||||
  # Find all enter script directories, store them in an array.
 | 
			
		||||
  local enter_dirs=(`_autoenv_find_enter_directories`)
 | 
			
		||||
  # Loop over reversed enter script directories array, so enter scripts found
 | 
			
		||||
  # last are sourced first, then source all enter scripts.
 | 
			
		||||
  for enter in ${(aO)enter_dirs}; do _autoenv_enter $enter; done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# 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
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user