Last active
April 5, 2024 15:16
-
-
Save 166MMX/10ab6d2840228d4308e8f78526c2b198 to your computer and use it in GitHub Desktop.
work in progress intelligent - currently not so much - wip PATH manager
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env sh | |
set -e -u | |
# https://peterlyons.com/problog/2012/09/managing-per-project-interpreters-and-the-path/ | |
# Function to append a directory to PATH if it exists | |
add_path() { | |
if [ -d "$1" ]; then | |
PATH="$PATH:$1" | |
fi | |
} | |
PROGRAM_FILES="$(cygpath --windows "$PROGRAMFILES")" | |
APP_DATA="$(cygpath --windows "$APPDATA")" | |
G_NODE_18="$APP_DATA/JetBrains/IntelliJIdea2022.3/node/node-v18.15.0-win-x64" | |
G_NODE_16="$APP_DATA/JetBrains/IntelliJIdea2022.3/node/node-v16.4.2-win-x64" | |
G_PYTHON_3_12="$PROGRAM_FILES/Python312/" | |
U_JAVA="$HOME/.jdks" | |
U_JAVA_21="$HOME/temurin-21.0.2" | |
U_JAVA_17="$HOME/temurin-17.0.10" | |
G_JAVA_8="$PROGRAM_FILES/Eclipse Adoptium/jdk-8.0.352.8-hotspot" | |
G_JAVA_17="$PROGRAM_FILES/Eclipse Adoptium/jdk-17.0.5.8-hotspot" | |
setup_homebrew() { | |
[ -d '/usr/local/bin' ] && PATH="/usr/local/bin:$PATH" | |
} | |
setup_java() { | |
PWD_JAVA_VERSION="$PWD/.java-version" | |
# Dynamically configure JAVA_HOME based on the project's Java version | |
# pom.xml - maven | |
# build.gradle - gradle | |
# .java-version - jenv | |
[ -f "$PWD_JAVA_VERSION" ] && { | |
read -r JAVA_VERSION < "$PWD_JAVA_VERSION" | |
} | |
[ -n "${JAVA_VERSION:}" ] && { | |
U_JAVA_VAR="U_JAVA_${JAVA_VERSION##.}" | |
G_JAVA_VAR="G_JAVA_${JAVA_VERSION##.}" | |
if [ -n "${!U_JAVA_VAR}" ]; then | |
JAVA_HOME="${!U_JAVA_VAR}" | |
elif [ -z "${!G_JAVA_VAR}" ]; then | |
JAVA_HOME="${!G_JAVA_VAR}" | |
elif [ -z "${G_JAVA:}" ]; then | |
JAVA_HOME="${G_JAVA:}" | |
else | |
JAVA_HOME='' | |
fi | |
export JAVA_HOME | |
add_path "$JAVA_HOME/bin" | |
} | |
} | |
setup_node() { | |
# package.json - node.js | |
# .node-version | |
# .nvmrc - nvm | |
# * https://github.com/nvm-sh/nvm?tab=readme-ov-file#nvmrc | |
# * https://github.com/tj/n?tab=readme-ov-file#specifying-nodejs-versions | |
# * https://github.com/shadowspawn/node-version-usage | |
# Project node_modules | |
## Node.js | |
add_path "$PWD/node_modules/.bin" | |
} | |
setup_python() { | |
## Global | |
G_PYTHON="$G_PYTHON_3_12" | |
add_path "$G_PYTHON" | |
add_path "$G_PYTHON/bin" # Unix | |
add_path "$G_PYTHON/Scripts" # Windows | |
## Project venv | |
# https://docs.python.org/3/library/venv.html#how-venvs-work | |
add_path "$PWD/.venv/bin" # POSIX | |
add_path "$PWD/.venv/Scripts" # Windows | |
# .python-version - pyenv | |
# requirements.txt | |
# Pipfile - pipenv | |
# pyproject.toml - poetry | |
: | |
} | |
setup_ruby() { | |
RBENV_ROOT="$HOME/.rbenv" | |
# Gemfile - rbenv | |
# https://github.com/rbenv/rbenv | |
# Initialize rbenv, if available | |
[ -d "$RBENV_ROOT/bin" ] && { | |
add_path "$RBENV_ROOT/bin" | |
export PATH | |
export RBENV_ROOT | |
eval "$(rbenv init -)" | |
} | |
} | |
setup_perl() { | |
#/usr/bin/core_perl # git for windows / msys2 | |
#/usr/bin/vendor_perl # git for windows / msys2 | |
PLENV_ROOT="$HOME/.plenv" | |
#PWD_PERL_VERSION="$PWD/.perl-version" | |
# https://github.com/tokuhirom/plenv | |
# Setup plenv if it exists | |
if [ -d "$PLENV_ROOT/bin" ]; then | |
add_path "$PLENV_ROOT/bin" | |
export PATH | |
export PLENV_ROOT | |
eval "$(plenv init -)" | |
fi | |
# Check for a project-specific .perl-version file | |
#if [ -f "$PWD_PERL_VERSION" ]; then | |
# read -r PERL_VERSION < "$PWD_PERL_VERSION" | |
# PLENV_VERSION="$PERL_VERSION" | |
# export PLENV_VERSION | |
#fi | |
# Only proceed if the specified Perl version is installed under plenv | |
#if [ -n "${PERL_VERSION:}" ] && [ -d "$PL_ENV/versions/$PERL_VERSION" ]; then | |
# add_path "$HOME/.plenv/versions/$PERL_VERSION/bin" | |
#fi | |
} | |
setup_dotnet() { | |
#/c/Program Files/dotnet | |
: | |
} | |
setup_winget() { | |
#/c/Program Files/WinGet/Links | |
: | |
} | |
setup_msys2() { | |
add_path '/bin' | |
if [ "$MSYSTEM" = "MINGW64" ]; then | |
add_path '/mingw64/bin' | |
elif [ "$MSYSTEM" = "MINGW32" ]; then | |
add_path '/mingw32/bin' | |
elif [ "$MSYSTEM" = "MSYS" ]; then | |
add_path '/usr/bin' | |
fi | |
add_path '/sbin' | |
add_path '/usr/sbin' | |
add_path '/usr/X11/bin' | |
} | |
setup_windows() { | |
#/c/Windows | |
#/c/Windows/System32/OpenSSH | |
#/c/Windows/System32/Wbem | |
#/c/Windows/System32/WindowsPowerShell/v1.0 | |
#/c/Windows/system32 | |
: | |
} | |
setup_apps() { | |
# Add directories for installed applications | |
add_path "$PROGRAM_FILES/7-Zip" | |
add_path "$PROGRAM_FILES/Amazon/AWSCLIV2" | |
add_path "$PROGRAM_FILES/JetBrains/IntelliJ IDEA 2022.3.1/bin" | |
add_path "$PROGRAM_FILES/Microsoft VS Code/bin" | |
add_path "$PROGRAM_FILES/Vagrant/bin" | |
add_path "$PROGRAM_FILES/gs/gs10.00.0/bin" | |
} | |
setup_path() { | |
# Normal system stuff comes first for security | |
# So others can't override basic commands like ls | |
# Reset PATH to a basic, secure set of directories | |
PATH='' | |
# Personal | |
add_path "$HOME/.local/bin" | |
add_path "$HOME/.bin" | |
add_path "$HOME/bin" | |
setup_msys2 | |
setup_windows | |
setup_homebrew | |
setup_winget | |
setup_java | |
setup_node | |
setup_perl | |
setup_python | |
setup_ruby | |
setup_dotnet | |
setup_apps | |
# Projects | |
add_path "$HOME/projects/dotfiles/bin" | |
export PATH | |
} | |
# Run setup_path during shell startup or manually as needed | |
setup_path | |
if [ -n "${ZSH_VERSION}" ]; then | |
chpwd() { | |
[ -d .git ] || \ | |
[ -d node_modules/.bin ] || \ | |
[ -d python/bin ] || \ | |
[ -d node/bin ] && setupPath | |
} | |
fi | |
# Adjust PATH automatically in some shells | |
case "$SHELL" in | |
*zsh) | |
autoload -U add-zsh-hook | |
add-zsh-hook chpwd | |
;; | |
*bash) | |
PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND ;}setup_path" | |
;; | |
esac | |
PROMPT_COMMAND="$PROMPT_COMMAND;setup_path" | |
# Function to wrap the Python command to use virtual environments, if available | |
python_exec_wrapper() { | |
# This holds the initial directory to start searching for .venv | |
search_dir="" | |
# Loop through all arguments to find a .py file and extract its directory | |
for arg in "$@"; do | |
case "$arg" in | |
*.py) | |
# Extract directory from the script's path | |
search_dir="$(dirname -- "$arg")" | |
# Break the loop once the first .py file is found | |
break | |
;; | |
esac | |
done | |
# If no .py file is found in arguments, use the current directory | |
[ -z "$search_dir" ] && search_dir="$(pwd)" | |
# Initialize a flag to indicate whether a .venv directory has been found | |
found_venv="" | |
# Search for .venv by moving up directories | |
while [ -n "$search_dir" ] && [ -z "$found_venv" ]; do | |
if [ -d "$search_dir/.venv" ] && [ -x "$search_dir/.venv/bin/python" ]; then | |
found_venv="$search_dir/.venv" | |
else | |
# Move up a directory | |
search_dir="$(cd "$search_dir/.." && pwd)" | |
# If we've reached the root directory, stop the loop | |
[ "$search_dir" = '/' ] && search_dir='' | |
fi | |
done | |
# Execute the Python script using the found .venv or the system Python interpreter | |
if [ -n "$found_venv" ]; then | |
echo "Using Python interpreter from .venv at $found_venv" | |
"$found_venv/bin/python" "$@" | |
else | |
echo "Using system Python interpreter" | |
command python "$@" | |
fi | |
} | |
# Alias the custom python function | |
alias python='python_exec_wrapper' | |
# To make this function available in your shell, you can source this script file | |
# or define the function directly in your shell's initialization files. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment