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
b85ae9b923
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
|
# Source the autoenv implementation script.
|
||||||
# changes, this is a reimplementation of the ideas found in the repository
|
source ${0:a:h}/autoenv.zsh
|
||||||
# https://github.com/Tarrasch/zsh-autoenv stripped down to bare essentials.
|
# Add the autoenv directory to fpath for completion.
|
||||||
#
|
fpath+=${0:a:h}
|
||||||
# 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
|
|
||||||
|
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