diff --git a/bash/.bashrc b/bash/.bashrc index 5a45cac..f4f7eb2 100644 --- a/bash/.bashrc +++ b/bash/.bashrc @@ -5,6 +5,14 @@ # If not running interactively, don't do anything [[ $- != *i* ]] && return +# Export our directory to Termite for opening new terminals +if [[ $TERM == xterm-termite ]]; then + . /etc/profile.d/vte.sh + __vte_prompt_command +fi + +[ -f ~/.fzf.bash ] && source ~/.fzf.bash + # Make colorcoding available for everyone Black='\e[0;30m' # Black @@ -54,11 +62,3 @@ source ~/.profile # Import my prompt source ~/.bash_prompt - -# Export our directory to Termite for opening new terminals -if [[ $TERM == xterm-termite ]]; then - . /etc/profile.d/vte.sh - __vte_prompt_command -fi - -[ -f ~/.fzf.bash ] && source ~/.fzf.bash diff --git a/scripts/localrc b/scripts/localrc new file mode 100755 index 0000000..cc5b0ef --- /dev/null +++ b/scripts/localrc @@ -0,0 +1,117 @@ +# This script applies local configuration changes from the start of your +# file hierarchy tree down to your current working directory. +# +# When you change dirctories it automatically undoes those changes by using +# the command contained in the associative array `__undo_commands` starting by +# the ones furthest down until the common ancestor with your current +# +# The '.localrc' files should add an undo command to __undo_commands which is +# keyed with the '__UNDO_DIR' variable (i.e: __undo_commands[$__UNDO_DIR]='...') +# This variable will be eval-ed to undo your local changes. +# +# Example 1: a project that needs to have the PATH pre-pended +# +# # Taking advantage of PATH being expanded when sourcing the file +# __undo_commands[$__UNDO_DIR]="export PATH='$PATH'" +# export PATH="$__UNDO_DIR/bin:$PATH" +# +# Example 2: a project that needs to activate a virtualenv +# +# __undo_commands[$__UNDO_DIR]='deactivate' +# source env/bin/activate + +# Contains the commands to undo the changes made in a directory +declare -A __undo_commands +# Contains the PWD of the previous command (and not $OLDPWD) +__LAST_PWD='/' +# Declare this variable to print some debug information +#DEBUG_LOCALRC=toto + +# Source localrc files from "$1" and its parents unless we find "$2" and stop +function __source_localrc_files_rec() { + # "$1" and "$2" should not have any trailing slashes unless they are '/' + if [ "$1" != "$2" ]; then + # FIXME: condition should be unnecessary, but is there to avoid loops + [ "$1" != '/' ] && __source_localrc_files_rec "$(dirname "$1")" "$2" + + # Export the special '__UNDO_DIR' variable to key into '__undo_commands' + export __UNDO_DIR="$1" + local localrc="$1/.localrc" + # The post-fix traversal sourced the parent before the child + if [ -r "$localrc" ]; then + source "$localrc" + + if [ -n "${DEBUG_LOCALRC+set}" ]; then + echo "sourced $localrc with __UNDO_DIR as '$__UNDO_DIR'" + fi + fi + unset -v __UNDO_DIR + fi +} + +# Undo the changes made by "$1" and its parents unless we find "$2" and stop +function __undo_localrc_changes() { + # Undo the changes for our parent directory if we aren't at the common root + if [ "$1" != "$2" ]; then + # If there is a command to undo the changes for that directory, do it + [ -n "${DEBUG_LOCALRC+set}" ] && echo "Looking at undoing $1" + if [ -n "${__undo_commands[$1]+set}" ]; then + eval "${__undo_commands[$1]}" + + [ -n "${DEBUG_LOCALRC+set}" ] && echo "undid $1/.localrc" + fi + + # FIXME: condition should be unnecessary, but is there to avoid loops + [ "$1" != '/' ] && __undo_localrc_changes "$(dirname "$1")" "$2" + fi +} + +# Return the closest common parent directory of "$1" and "$2" +function common_parent() { + local directories=("$1") + + while [ "${directories[-1]}" != '/' ]; do + directories+=("$(dirname "${directories[-1]}")") + done + + for candidate in "${directories[@]}"; do + case "$2" in + "$candidate"*) printf "%s" "$candidate"; break;; + esac + done +} + +function __source_localrc_files() { + # Only do it if we changed our directory since the last command + if [ "$__LAST_PWD" = "$PWD" ]; then + return 0 + fi + + # Find the closest common parent directory + local parent='/' + if [ -n "$__LAST_PWD" ]; then + parent=$(common_parent "$__LAST_PWD" "$PWD") + fi + + if [ -n "${DEBUG_LOCALRC+set}" ]; then + echo "DEBUG" + echo "LAST: $__LAST_PWD" + echo "CUR: $PWD" + echo "PARENT: $parent" + fi + + __undo_localrc_changes "$__LAST_PWD" "$parent" + __source_localrc_files_rec "$PWD" "$parent" + + # Update our last seen working directory + __LAST_PWD="$PWD" +} + +# Execute this command every time +if [ -n "$BASH_VERSION" ]; then + [ -n "${DEBUG_LOCALRC+set}" ] && echo "Loaded Bash" + PROMPT_COMMAND="__source_localrc_files; $PROMPT_COMMAND" +elif [ -n "$ZSH_VERSION" ]; then + [ -n "${DEBUG_LOCALRC+set}" ] && echo "Loaded Zsh" + precmd_functions+=( __source_localrc_files) +fi diff --git a/shell/.profile b/shell/.profile index 2996f25..0ac5a7b 100644 --- a/shell/.profile +++ b/shell/.profile @@ -48,4 +48,7 @@ if { [ -n "$BASH_VERSION" ] && shopt -q login_shell; } || fi # Use keychain to handle ssh-agent, in interactive shell too -eval "$(keychain --eval id_rsa --quiet)" +eval "$(keychain --eval id_rsa --eval id_ed25519 --quiet)" + +# Use my localrc script to automatically source/unsource local configurations +source ~/.scripts/localrc diff --git a/zsh/.zshrc b/zsh/.zshrc index 905f973..4112a0c 100755 --- a/zsh/.zshrc +++ b/zsh/.zshrc @@ -1,3 +1,11 @@ +# Export our directory to Termite for opening new terminals +if [[ $TERM == xterm-termite ]]; then + . /etc/profile.d/vte.sh + __vte_osc7 +fi + +[ -f ~/.fzf.zsh ] && source ~/.fzf.zsh + # History configuration HISTFILE=~/.zhistory HISTSIZE=10000 @@ -97,11 +105,3 @@ source /usr/share/zsh/plugins/fast-syntax-highlighting/fast-syntax-highlighting. # import my prompt source ~/.zsh_prompt - -# Export our directory to Termite for opening new terminals -if [[ $TERM == xterm-termite ]]; then - . /etc/profile.d/vte.sh - __vte_osc7 -fi - -[ -f ~/.fzf.zsh ] && source ~/.fzf.zsh