Skip to content

Instantly share code, notes, and snippets.

@KeyAmam
Last active October 20, 2023 07:34
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save KeyAmam/a6afcabc3a724fc4a541aca7629c3ff6 to your computer and use it in GitHub Desktop.
Save KeyAmam/a6afcabc3a724fc4a541aca7629c3ff6 to your computer and use it in GitHub Desktop.
A script which defines actions before and after each command execution
#!/bin/bash
# NOTES
# To activate hooks, run:
# . ./.bash_hooks
# To clear hooks, run:
# trap '' DEBUG
# PROMPT_COMMAND=
# To add a new action to the preceding hook
# define a function
# add it into __hooks__before_each_command
# To add a new action to the subsequent hook
# define a function
# add it into __hooks__after_each_command
filename="$(basename "$BASH_SOURCE")"
# deactivate hooks to initialize (activate at the end)
unset __HOOKS__ACTIVATED
########## START OF PRECEDING HOOK ##########
# define functions and add them into __hooks__before_each_command
function __hooks__set_git_clone_flag() {
if [ 'git' = "$1" ] && [ 'clone' = "$2" ]; then
echo "Setting __HOOKS__ON_GIT_CLONE=true in $filename"
export __HOOKS__ON_GIT_CLONE=true
fi
}
function __hooks__before_each_command() {
local last_command=( $BASH_COMMAND )
if [ -z "$__HOOKS__ACTIVATED" ]; then
return
fi
# before each command
__hooks__set_git_clone_flag "${last_command[@]}";
if [ -z "$__HOOKS__EXECUTING_LINE" ]; then
return
fi
unset __HOOKS__EXECUTING_LINE
# before each first command of a comamnd line
}
########## END OF PRECEDING HOOK ##########
########## START OF SUBSEQUENT HOOK ##########
# define functions and add them into __hooks__after_each_command
function __hooks__prevent_duplicate_actions() {
export __HOOKS__EXECUTING_LINE=true
}
function __hooks__unset_git_clone_flag() {
unset __HOOKS__ON_GIT_CLONE
}
function __hooks__after_each_command() {
if [ -z "$__HOOKS__ACTIVATED" ]; then
return
fi
# after each command
__hooks__prevent_duplicate_actions
__hooks__unset_git_clone_flag
if [ "$PREVPWD" != "$PWD" ]; then
# after changing directories
# do something here
export PREVPWD="$PWD"
fi
}
########## END OF SUBSEQUENT HOOK ##########
########## START REGISTERING HOOKS ##
function __hooks__register_function() {
local f="$1"; shift
local regex="^ *$f *$"
# filter the given function name out of PROMPT_COMMAND to avoid invalid format and duplicate execution
# awk splits PROMPT_COMMAND by ";", extract elements that UNMATCH to the given regex and join with ";"
# avoided using ORS to skip appending ";" to the last record
PROMPT_COMMAND="$(
echo "$PROMPT_COMMAND" |
awk -v regex="$regex" 'BEGIN { RS=";" } length($1) > 0 && $1 !~ regex { printf "%s%s", delim, $1; delim=";" }'
)"
# append the function name
export PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND;}$f"
}
# register the preceding hook
echo 'registering the preceding hook..'
trap '__hooks__before_each_command' DEBUG
# register the subsequent hook
echo 'registering the subsequent hook..'
__hooks__register_function '__hooks__after_each_command'
unset __hooks__register_function
# initialize PREVPWD
echo 'initializing $PREVPWD..'
export PREVPWD="$PWD"
unset filename
# activate hooks
echo 'activating hooks..'
export __HOOKS__ACTIVATED=true
########## FINISH REGISTERING HOOKS ##########
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment