From 470acd8956c3411780b8c4df1ea97461718d1472 Mon Sep 17 00:00:00 2001 From: Ismo Vuorinen Date: Wed, 30 Jul 2025 18:08:34 +0300 Subject: [PATCH] chore(config): fish: add ivuorinen/phpenv.fish Signed-off-by: Ismo Vuorinen --- config/fish/completions/phpenv.fish | 123 +++ config/fish/conf.d/phpenv.fish | 38 + config/fish/fish_plugins | 1 + config/fish/functions/phpenv.fish | 1078 +++++++++++++++++++++++++++ 4 files changed, 1240 insertions(+) create mode 100644 config/fish/completions/phpenv.fish create mode 100644 config/fish/conf.d/phpenv.fish create mode 100644 config/fish/functions/phpenv.fish diff --git a/config/fish/completions/phpenv.fish b/config/fish/completions/phpenv.fish new file mode 100644 index 0000000..8b627e8 --- /dev/null +++ b/config/fish/completions/phpenv.fish @@ -0,0 +1,123 @@ +# Completions for phpenv command +# Place in ~/.config/fish/completions/phpenv.fish + +# Complete main commands +complete -c phpenv -f -n "__fish_use_subcommand" -a "install" -d "Install a PHP version" +complete -c phpenv -f -n "__fish_use_subcommand" -a "uninstall" -d "Uninstall a PHP version" +complete -c phpenv -f -n "__fish_use_subcommand" -a "use" -d "Use PHP version for current shell" +complete -c phpenv -f -n "__fish_use_subcommand" -a "local" -d "Set PHP version for current project" +complete -c phpenv -f -n "__fish_use_subcommand" -a "global" -d "Set global PHP version" +complete -c phpenv -f -n "__fish_use_subcommand" -a "list" -d "List installed PHP versions" +complete -c phpenv -f -n "__fish_use_subcommand" -a "ls" -d "List installed PHP versions" +complete -c phpenv -f -n "__fish_use_subcommand" -a "current" -d "Show current PHP version" +complete -c phpenv -f -n "__fish_use_subcommand" -a "which" -d "Show path to PHP binary" +complete -c phpenv -f -n "__fish_use_subcommand" -a "versions" -d "Show all available versions" +complete -c phpenv -f -n "__fish_use_subcommand" -a "doctor" -d "Check phpenv installation" +complete -c phpenv -f -n "__fish_use_subcommand" -a "config" -d "Manage configuration" +complete -c phpenv -f -n "__fish_use_subcommand" -a "extensions" -d "Manage PHP extensions" +complete -c phpenv -f -n "__fish_use_subcommand" -a "ext" -d "Manage PHP extensions" +complete -c phpenv -f -n "__fish_use_subcommand" -a "help" -d "Show help" + +# Helper functions for completions +function __phpenv_complete_installed_versions + phpenv list 2>/dev/null | sed 's/^[* ]*//' +end + +function __phpenv_complete_available_versions + # Try to get dynamic versions first + if command -q curl -a command -q jq; and functions -q __phpenv_parse_version_field + echo "latest" + echo "nightly" + echo "5.x" + echo "7.x" + echo "8.x" + __phpenv_parse_version_field "latest" "8.4" + __phpenv_parse_version_field "nightly" "8.5" + __phpenv_parse_version_field "5.x" "5.6" + __phpenv_parse_version_field "7.x" "7.4" + __phpenv_parse_version_field "8.x" "8.4" + end + + # Fallback to common versions + printf "5.6\n7.0\n7.1\n7.2\n7.3\n7.4\n8.0\n8.1\n8.2\n8.3\n8.4\n8.5\n" +end + +function __phpenv_complete_config_keys + printf "global-version\nauto-install\nauto-install-extensions\nauto-switch\ndefault-extensions\n" +end + +function __phpenv_complete_extensions + printf "xdebug\nredis\nimagick\nmongodb\nmemcached\npcov\nast\ngrpc\n" + printf "protobuf\nyaml\nzip\ncurl\ngd\nintl\nmbstring\nmysql\nopcache\npdo\nsockets\nxml\n" +end + +function __phpenv_complete_binaries + printf "php\nphp-config\nphpize\ncomposer\npecl\npear\n" +end + +# Complete versions for install command +complete -c phpenv -f -n "__fish_seen_subcommand_from install" \ + -a "(__phpenv_complete_available_versions)" -d "PHP version" + +# Complete installed versions for uninstall, use commands +complete -c phpenv -f -n "__fish_seen_subcommand_from uninstall use local global" \ + -a "(__phpenv_complete_installed_versions)" -d "Installed PHP version" + +# Add system option for use command +complete -c phpenv -f -n "__fish_seen_subcommand_from use" -a "system" -d "Use system PHP" + +# Complete binaries for which command +complete -c phpenv -f -n "__fish_seen_subcommand_from which" -a "(__phpenv_complete_binaries)" -d "PHP binary" + +# Complete config subcommands +complete -c phpenv -f -n "__fish_seen_subcommand_from config; and not __fish_seen_subcommand_from get set list" \ + -a "get" -d "Get configuration value" +complete -c phpenv -f -n "__fish_seen_subcommand_from config; and not __fish_seen_subcommand_from get set list" \ + -a "set" -d "Set configuration value" +complete -c phpenv -f -n "__fish_seen_subcommand_from config; and not __fish_seen_subcommand_from get set list" \ + -a "list" -d "List all configuration" + +# Complete config keys +complete -c phpenv -f -n "__fish_seen_subcommand_from config; and __fish_seen_subcommand_from get set" \ + -a "(__phpenv_complete_config_keys)" -d "Configuration key" + +# Complete config values for boolean settings +complete -c phpenv -f \ + -n "__fish_seen_subcommand_from config; and __fish_seen_subcommand_from set" \ + -n "contains -- (commandline -opc)[-1] auto-install auto-install-extensions auto-switch" \ + -a "true false" -d "Boolean value" + +# Complete extensions subcommands +complete -c phpenv -f \ + -n "__fish_seen_subcommand_from extensions ext" \ + -n "not __fish_seen_subcommand_from install uninstall remove list ls available" \ + -a "install" -d "Install PHP extension" +complete -c phpenv -f \ + -n "__fish_seen_subcommand_from extensions ext" \ + -n "not __fish_seen_subcommand_from install uninstall remove list ls available" \ + -a "uninstall" -d "Uninstall PHP extension" +complete -c phpenv -f \ + -n "__fish_seen_subcommand_from extensions ext" \ + -n "not __fish_seen_subcommand_from install uninstall remove list ls available" \ + -a "remove" -d "Remove PHP extension" +complete -c phpenv -f \ + -n "__fish_seen_subcommand_from extensions ext" \ + -n "not __fish_seen_subcommand_from install uninstall remove list ls available" \ + -a "list" -d "List installed extensions" +complete -c phpenv -f \ + -n "__fish_seen_subcommand_from extensions ext" \ + -n "not __fish_seen_subcommand_from install uninstall remove list ls available" \ + -a "ls" -d "List installed extensions" +complete -c phpenv -f \ + -n "__fish_seen_subcommand_from extensions ext" \ + -n "not __fish_seen_subcommand_from install uninstall remove list ls available" \ + -a "available" -d "Show available extensions" + +# Complete extension names +complete -c phpenv -f \ + -n "__fish_seen_subcommand_from extensions ext; and __fish_seen_subcommand_from install" \ + -a "(__phpenv_complete_extensions)" -d "PHP extension" + +# Complete help options +complete -c phpenv -f -s h -l help -d "Show help" + diff --git a/config/fish/conf.d/phpenv.fish b/config/fish/conf.d/phpenv.fish new file mode 100644 index 0000000..1b93ca9 --- /dev/null +++ b/config/fish/conf.d/phpenv.fish @@ -0,0 +1,38 @@ +# phpenv configuration file +# Place in ~/.config/fish/conf.d/phpenv.fish + +# Set default configuration using session variables for most settings +# Only PHPENV_GLOBAL_VERSION needs to persist across shells +if not set -q PHPENV_AUTO_INSTALL + set -g PHPENV_AUTO_INSTALL false +end + +if not set -q PHPENV_AUTO_INSTALL_EXTENSIONS + set -g PHPENV_AUTO_INSTALL_EXTENSIONS false +end + +if not set -q PHPENV_AUTO_SWITCH + set -g PHPENV_AUTO_SWITCH true +end + +if not set -q PHPENV_DEFAULT_EXTENSIONS + set -g PHPENV_DEFAULT_EXTENSIONS "opcache" +end + +# Initialize PATH on shell startup if global version is set (less aggressive) +if test -n "$PHPENV_GLOBAL_VERSION"; and not set -q PHPENV_INITIALIZED + if functions -q __phpenv_is_version_installed __phpenv_set_php_path + if __phpenv_is_version_installed "$PHPENV_GLOBAL_VERSION" 2>/dev/null + # Only set PATH if no project-specific version is detected + if not __phpenv_find_version_file .php-version >/dev/null 2>&1 + if not __phpenv_find_version_file .tool-version >/dev/null 2>&1 + if not test -f composer.json + __phpenv_set_php_path "$PHPENV_GLOBAL_VERSION" 2>/dev/null + end + end + end + end + end + set -g PHPENV_INITIALIZED true +end + diff --git a/config/fish/fish_plugins b/config/fish/fish_plugins index c9d927b..0f02dce 100644 --- a/config/fish/fish_plugins +++ b/config/fish/fish_plugins @@ -9,3 +9,4 @@ meaningful-ooo/sponge nickeb96/puffer-fish jgusta/paths patrickf1/fzf.fish +ivuorinen/phpenv.fish diff --git a/config/fish/functions/phpenv.fish b/config/fish/functions/phpenv.fish new file mode 100644 index 0000000..40a5d2f --- /dev/null +++ b/config/fish/functions/phpenv.fish @@ -0,0 +1,1078 @@ +# phpenv - PHP Version Manager for Fish Shell +# Repository: https://github.com/ivuorinen/phpenv.fish + +function phpenv -d "PHP version manager for Fish Shell" + if not command -q jq + echo "Error: jq is required but not installed. Install with: brew install jq" >&2 + return 1 + end + + set -l phpenv_cmd $argv[1] + set -l phpenv_args $argv[2..] + + switch $phpenv_cmd + case install + __phpenv_install $phpenv_args + case uninstall + __phpenv_uninstall $phpenv_args + case use + __phpenv_use $phpenv_args + case local + __phpenv_local $phpenv_args + case global + __phpenv_global $phpenv_args + case list ls + __phpenv_list $phpenv_args + case current + __phpenv_current + case which + __phpenv_which $phpenv_args + case versions + __phpenv_versions + case doctor + __phpenv_doctor + case config + __phpenv_config $phpenv_args + case extensions ext + __phpenv_extensions $phpenv_args + case help -h --help "" + __phpenv_help + case '*' + echo "phpenv: unknown command '$phpenv_cmd'" + echo "Run 'phpenv help' for available commands." + return 1 + end +end + +function __phpenv_current + set -l phpenv_version (__phpenv_detect_version) + if test -n "$phpenv_version" + echo "$phpenv_version" + else + echo "No PHP version set" + return 1 + end +end + +function __phpenv_detect_version + set -l phpenv_version_file (__phpenv_find_version_file .php-version) + if test -n "$phpenv_version_file" + set -l phpenv_version (string trim < $phpenv_version_file) + if test -n "$phpenv_version" + echo $phpenv_version + return + end + end + + set -l phpenv_tool_version_file (__phpenv_find_version_file .tool-version) + if test -n "$phpenv_tool_version_file" + set -l phpenv_version (__phpenv_parse_tool_version $phpenv_tool_version_file) + if test -n "$phpenv_version" + echo $phpenv_version + return + end + end + + if test -f composer.json + set -l phpenv_version (__phpenv_parse_composer_version) + if test -n "$phpenv_version" + echo $phpenv_version + return + end + end + + if test -n "$PHPENV_GLOBAL_VERSION" + echo $PHPENV_GLOBAL_VERSION + return + end + + set -l phpenv_global_version (__phpenv_config_get global-version) + if test -n "$phpenv_global_version" + echo $phpenv_global_version + return + end + + if command -q php + php -r "echo PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION;" 2>/dev/null + end +end + +function __phpenv_find_version_file -a phpenv_filename + set -l phpenv_dir (pwd) + while test "$phpenv_dir" != "/" + if test -f "$phpenv_dir/$phpenv_filename" + echo "$phpenv_dir/$phpenv_filename" + return + end + set phpenv_dir (dirname $phpenv_dir) + end +end + +function __phpenv_parse_tool_version -a phpenv_file + if test -f $phpenv_file + set -l phpenv_line (grep "^php " $phpenv_file) + if test -n "$phpenv_line" + set -l phpenv_parts (string split ' ' $phpenv_line) + if test (count $phpenv_parts) -ge 2 + echo $phpenv_parts[2] | sed 's/^v//' + end + end + end +end + +function __phpenv_parse_composer_version + if not test -f composer.json + return + end + + set -l phpenv_platform_php (jq -r '.config.platform.php // empty' composer.json 2>/dev/null) + if test $status -eq 0 -a -n "$phpenv_platform_php" -a "$phpenv_platform_php" != "null" + echo $phpenv_platform_php + return + end + + set -l phpenv_require_php (jq -r '.require.php // empty' composer.json 2>/dev/null) + if test $status -eq 0 -a -n "$phpenv_require_php" -a "$phpenv_require_php" != "null" + __phpenv_parse_semver_constraint $phpenv_require_php + return + end +end + +function __phpenv_parse_semver_constraint -a phpenv_constraint + set phpenv_constraint (echo $phpenv_constraint | tr -d ' "') + + set -l phpenv_latest_8x (__phpenv_parse_version_field "8.x" "8.4") + set -l phpenv_latest_7x (__phpenv_parse_version_field "7.x" "7.4") + set -l phpenv_latest (__phpenv_parse_version_field "latest" "8.4") + + switch $phpenv_constraint + case '^8.*' + echo $phpenv_latest_8x + case '^7.*' + echo $phpenv_latest_7x + case '~8.4*' + echo "8.4" + case '~8.3*' + echo "8.3" + case '~8.2*' + echo "8.2" + case '~8.1*' + echo "8.1" + case '~8.0*' + echo "8.0" + case '~7.4*' + echo "7.4" + case '>=8.1' + echo $phpenv_latest_8x + case '>=8.0' + echo $phpenv_latest_8x + case '>=7.4' + echo $phpenv_latest_8x + case '8.*' '8.x.*' + echo $phpenv_latest_8x + case '7.*' '7.x.*' + echo $phpenv_latest_7x + case '5.*' '5.x.*' + echo "5.6" + case '*' + if echo $phpenv_constraint | grep -q '[0-9]\+\.[0-9]\+' + echo $phpenv_constraint | sed 's/[^0-9\.]//g' | cut -d. -f1,2 + else + echo $phpenv_latest + end + end +end + +# Cache version info to avoid repeated API calls +set -g __phpenv_version_cache +set -g __phpenv_version_cache_time 0 + +function __phpenv_get_version_info + set -l current_time (date +%s) + set -l cache_duration 300 # 5 minutes + + # Return cached version if still valid + if test -n "$__phpenv_version_cache" + set -l cache_age (math $current_time - $__phpenv_version_cache_time) + if test $cache_age -lt $cache_duration + echo $__phpenv_version_cache + return + end + end + + if command -q curl + set -l url https://raw.githubusercontent.com/shivammathur/setup-php/refs/heads/main + set -l version_data (curl -s "$url/src/configs/php-versions.json" 2>/dev/null) + if test -n "$version_data" + set -g __phpenv_version_cache $version_data + set -g __phpenv_version_cache_time $current_time + echo $version_data + end + end +end + +# Cache cellar path as it doesn't change +set -g __phpenv_cellar_cache + +function __phpenv_get_cellar_path + if test -n "$__phpenv_cellar_cache" + echo $__phpenv_cellar_cache + return + end + + if test -d /opt/homebrew/Cellar + set -g __phpenv_cellar_cache /opt/homebrew/Cellar + else if test -d /usr/local/Cellar + set -g __phpenv_cellar_cache /usr/local/Cellar + else + set -g __phpenv_cellar_cache "" + end + + echo $__phpenv_cellar_cache +end + +function __phpenv_ensure_taps + if not command -q brew + return 1 + end + + # Add taps if not already added + if not brew tap | grep -q shivammathur/php 2>/dev/null + brew tap shivammathur/php 2>/dev/null + end + if not brew tap | grep -q shivammathur/extensions 2>/dev/null + brew tap shivammathur/extensions 2>/dev/null + end +end + +function __phpenv_parse_version_field -a field fallback + set -l version_info (__phpenv_get_version_info) + if test -n "$version_info" + echo $version_info | jq -r ".$field // \"$fallback\"" 2>/dev/null + else + echo $fallback + end +end + +function __phpenv_list_installed + set -l phpenv_versions + set -l phpenv_cellar_path (__phpenv_get_cellar_path) + + if test -d $phpenv_cellar_path + for phpenv_dir in $phpenv_cellar_path/php@* $phpenv_cellar_path/php + if test -d $phpenv_dir + set -l phpenv_basename (basename $phpenv_dir) + + if echo $phpenv_basename | grep -qE '(debug|zts)' + continue + end + + if test "$phpenv_basename" = "php" + set -l phpenv_latest (__phpenv_parse_version_field "latest" "8.4") + set -a phpenv_versions $phpenv_latest + else if echo $phpenv_basename | grep -qE '^php@[0-9]+\.[0-9]+$' + set -l phpenv_version (echo $phpenv_basename | sed 's/php@//') + set -a phpenv_versions $phpenv_version + end + end + end + end + + printf '%s\n' $phpenv_versions | sort -V | uniq +end + +function __phpenv_resolve_version_alias -a phpenv_version + switch $phpenv_version + case latest + __phpenv_parse_version_field "latest" "8.4" + case nightly + __phpenv_parse_version_field "nightly" "8.5" + case '8.x' + __phpenv_parse_version_field "8.x" "8.4" + case '7.x' + __phpenv_parse_version_field "7.x" "7.4" + case '5.x' + __phpenv_parse_version_field "5.x" "5.6" + case '*' + echo $phpenv_version + end +end + +function __phpenv_get_formula_name -a phpenv_version + set -l phpenv_latest_version (__phpenv_parse_version_field "latest" "8.4") + + if test "$phpenv_version" = "$phpenv_latest_version" + echo "shivammathur/php/php" + else + echo "shivammathur/php/php@$phpenv_version" + end +end + +function __phpenv_is_version_installed -a phpenv_version + set -l phpenv_cellar_path (__phpenv_get_cellar_path) + set -l phpenv_latest_version (__phpenv_parse_version_field "latest" "8.4") + + if test "$phpenv_version" = "$phpenv_latest_version" + test -d "$phpenv_cellar_path/php" -o -d "$phpenv_cellar_path/php@$phpenv_version" + else + test -d "$phpenv_cellar_path/php@$phpenv_version" + end +end + +function __phpenv_get_php_path -a phpenv_version + set -l phpenv_cellar_path (__phpenv_get_cellar_path) + set -l phpenv_latest_version (__phpenv_parse_version_field "latest" "8.4") + + set -l phpenv_target_dir + if test "$phpenv_version" = "$phpenv_latest_version" + if test -d "$phpenv_cellar_path/php" + set phpenv_target_dir "$phpenv_cellar_path/php" + else if test -d "$phpenv_cellar_path/php@$phpenv_version" + set phpenv_target_dir "$phpenv_cellar_path/php@$phpenv_version" + end + else + if test -d "$phpenv_cellar_path/php@$phpenv_version" + set phpenv_target_dir "$phpenv_cellar_path/php@$phpenv_version" + end + end + + if test -n "$phpenv_target_dir" + # Find the latest version directory by sorting + set -l phpenv_versions + for phpenv_dir in $phpenv_target_dir/* + if test -d "$phpenv_dir" + set -a phpenv_versions (basename "$phpenv_dir") + end + end + + if test (count $phpenv_versions) -gt 0 + set -l phpenv_latest_dir (printf '%s\n' $phpenv_versions | sort -V | tail -1) + if test -n "$phpenv_latest_dir" + echo "$phpenv_target_dir/$phpenv_latest_dir" + end + end + end +end + +function __phpenv_set_php_path -a phpenv_version + set -l phpenv_php_path (__phpenv_get_php_path $phpenv_version) + if test -z "$phpenv_php_path" + echo "Failed to locate PHP $phpenv_version installation path" >&2 + return 1 + end + + if not test -x "$phpenv_php_path/bin/php" + echo "PHP binary not found at $phpenv_php_path/bin/php" >&2 + return 1 + end + + # Store original PATH if not already stored + if not set -q PHPENV_ORIGINAL_PATH + set -g PHPENV_ORIGINAL_PATH $PATH + end + + # Check if we're already using this version + if set -q PHPENV_CURRENT_VERSION; and test "$PHPENV_CURRENT_VERSION" = "$phpenv_version" + return 0 + end + + # Build clean PATH without any PHP paths + set -l phpenv_clean_path + for phpenv_path_entry in $PHPENV_ORIGINAL_PATH + if not echo $phpenv_path_entry | grep -qE "/(Cellar|opt/homebrew)/(php|php@)" + set -a phpenv_clean_path $phpenv_path_entry + end + end + + # Set new PATH with PHP version at front + set -gx PATH "$phpenv_php_path/bin" $phpenv_clean_path + set -g PHPENV_CURRENT_VERSION $phpenv_version + set -g PHPENV_CURRENT_PATH "$phpenv_php_path/bin" + + # Verify the change worked + if command -q php + set -l phpenv_active_version (php -r "echo PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION;" 2>/dev/null) + if test "$phpenv_active_version" != "$phpenv_version" + echo "Warning: PHP $phpenv_version set in PATH but php command shows $phpenv_active_version" >&2 + echo "PATH may have conflicting PHP installations" >&2 + end + end +end + +function __phpenv_restore_system_path + if set -q PHPENV_ORIGINAL_PATH + set -gx PATH $PHPENV_ORIGINAL_PATH + set -e PHPENV_CURRENT_VERSION + set -e PHPENV_CURRENT_PATH + set -e PHPENV_ORIGINAL_PATH + return 0 + else + echo "No original PATH stored to restore" + return 1 + end +end + +function __phpenv_install -a phpenv_version + if test -z "$phpenv_version" + echo "Usage: phpenv install " + return 1 + end + + set phpenv_version (__phpenv_resolve_version_alias $phpenv_version) + + if __phpenv_is_version_installed $phpenv_version + echo "PHP $phpenv_version is already installed" + return 0 + end + + echo "Installing PHP $phpenv_version..." + + if not __phpenv_ensure_taps + echo "Error: Homebrew is required but not available" + return 1 + end + + set -l phpenv_formula (__phpenv_get_formula_name $phpenv_version) + if test -z "$phpenv_formula" + echo "Unknown PHP version: $phpenv_version" + echo "Run 'phpenv versions' to see available versions" + return 1 + end + + if brew install $phpenv_formula + echo "PHP $phpenv_version installed successfully" + + if __phpenv_config_get auto-install-extensions | grep -q true + __phpenv_install_default_extensions $phpenv_version + end + else + echo "Failed to install PHP $phpenv_version" + return 1 + end +end + +function __phpenv_uninstall -a phpenv_version + if test -z "$phpenv_version" + echo "Usage: phpenv uninstall " + return 1 + end + + if not __phpenv_is_version_installed $phpenv_version + echo "PHP $phpenv_version is not installed" + return 1 + end + + set -l phpenv_formula (__phpenv_get_formula_name $phpenv_version) + if brew uninstall $phpenv_formula + echo "PHP $phpenv_version uninstalled successfully" + else + echo "Failed to uninstall PHP $phpenv_version" + return 1 + end +end + +function __phpenv_use + set -l phpenv_version $argv[1] + + # Handle special case: restore system PHP + if test "$phpenv_version" = "system" + __phpenv_restore_system_path + echo "Restored system PHP" + return 0 + end + + if test -z "$phpenv_version" + set phpenv_version (__phpenv_detect_version) + if test -z "$phpenv_version" + echo "No PHP version found for this project" + echo "Usage: phpenv use " + return 1 + end + echo "Detected PHP $phpenv_version for this project" + end + + if not __phpenv_is_version_installed $phpenv_version + if test "$(__phpenv_config_get auto-install)" = "true" + __phpenv_install $phpenv_version + else + echo "PHP $phpenv_version is not installed. Install with: phpenv install $phpenv_version" + return 1 + end + end + + if __phpenv_set_php_path $phpenv_version + echo "Using PHP $phpenv_version" + else + echo "Failed to switch to PHP $phpenv_version" + return 1 + end +end + +function __phpenv_local -a phpenv_version + if test -z "$phpenv_version" + echo "Usage: phpenv local " + return 1 + end + + echo $phpenv_version > .php-version + echo "Set local PHP version to $phpenv_version" +end + +function __phpenv_global -a phpenv_version + if test -z "$phpenv_version" + echo "Usage: phpenv global " + return 1 + end + + set -U PHPENV_GLOBAL_VERSION $phpenv_version + echo "Set global PHP version to $phpenv_version" +end + +function __phpenv_list + set -l phpenv_versions (__phpenv_list_installed) + set -l phpenv_current (__phpenv_detect_version) + + for phpenv_version in $phpenv_versions + if test "$phpenv_version" = "$phpenv_current" + echo "* $phpenv_version" + else + echo " $phpenv_version" + end + end +end + +function __phpenv_versions + echo "Available versions from shivammathur/homebrew-php:" + + set -l phpenv_tap_versions (__phpenv_get_tap_versions) + if test -n "$phpenv_tap_versions" + echo $phpenv_tap_versions + return + end + + # Use cached version info + set -l phpenv_latest (__phpenv_parse_version_field "latest" "8.4") + set -l phpenv_nightly (__phpenv_parse_version_field "nightly" "8.5") + set -l phpenv_version_8x (__phpenv_parse_version_field "8.x" "8.4") + set -l phpenv_version_7x (__phpenv_parse_version_field "7.x" "7.4") + set -l phpenv_version_5x (__phpenv_parse_version_field "5.x" "5.6") + + echo "Stable versions:" + echo " $phpenv_version_5x (5.x latest) $phpenv_version_7x (7.x latest) $phpenv_latest (latest stable)" + echo " $phpenv_nightly (nightly)" + echo " 5.6 7.0 7.1 7.2 7.3 7.4" + echo " 8.0 8.1 8.2 8.3 8.4 8.5" +end + +function __phpenv_get_tap_versions + if not command -q brew + return + end + + set -l phpenv_formulas (brew tap-info shivammathur/php --json 2>/dev/null | \ + jq -r '.[]|(.formula_names[]?)' 2>/dev/null) + + if test -z "$phpenv_formulas" + return + end + + set -l phpenv_versions + set -l phpenv_version_info (__phpenv_get_version_info) + set -l phpenv_latest_version (echo $phpenv_version_info | jq -r '.latest // "8.4"' 2>/dev/null) + + for phpenv_formula in $phpenv_formulas + set -l phpenv_clean_name (echo $phpenv_formula | sed 's|shivammathur/php/||') + + if echo $phpenv_clean_name | grep -qE '(debug|zts|autoconf|bison)' + continue + end + + if test "$phpenv_clean_name" = "php" + set -a phpenv_versions "$phpenv_latest_version (latest)" + else if echo $phpenv_clean_name | grep -qE '^php@[0-9]+\.[0-9]+$' + set -l phpenv_version (echo $phpenv_clean_name | sed 's/php@//') + set -a phpenv_versions $phpenv_version + end + end + + if test (count $phpenv_versions) -gt 0 + printf '%s\n' $phpenv_versions | sort -V | tr '\n' ' ' | sed 's/ $//' + echo "" + end +end + +function __phpenv_which -a phpenv_binary + set -l phpenv_binary (test -n "$phpenv_binary"; and echo $phpenv_binary; or echo "php") + set -l phpenv_version (__phpenv_detect_version) + + if test -n "$phpenv_version" + set -l phpenv_php_path (__phpenv_get_php_path $phpenv_version) + if test -x "$phpenv_php_path/bin/$phpenv_binary" + echo "$phpenv_php_path/bin/$phpenv_binary" + else + echo "$phpenv_binary not found for PHP $phpenv_version" + return 1 + end + else + which $phpenv_binary + end +end + +function __phpenv_doctor + echo "phpenv doctor" + echo "=============" + + if command -q jq + echo "✓ jq is installed" + else + echo "✗ jq is not installed (required)" + end + + if command -q brew + echo "✓ Homebrew is installed" + else + echo "✗ Homebrew is not installed" + return 1 + end + + # Check taps using unified function + set -l tap_status (__phpenv_ensure_taps 2>/dev/null; echo $status) + if test $tap_status -eq 0 + echo "✓ Required Homebrew taps are available" + else + echo "! Some Homebrew taps may need to be added automatically" + end + + set -l phpenv_versions (__phpenv_list_installed) + if test (count $phpenv_versions) -gt 0 + echo "✓ PHP versions installed: "(string join ", " $phpenv_versions) + else + echo "! No PHP versions installed" + end + + set -l phpenv_current (__phpenv_detect_version) + if test -n "$phpenv_current" + echo "✓ Current PHP version: $phpenv_current" + else + echo "! No PHP version detected" + end +end + +function __phpenv_config -a phpenv_action phpenv_key phpenv_value + switch $phpenv_action + case get + __phpenv_config_get $phpenv_key + case set + __phpenv_config_set $phpenv_key $phpenv_value + case list + __phpenv_config_list + case '*' + echo "Usage: phpenv config {get|set|list} [key] [value]" + return 1 + end +end + +function __phpenv_config_get -a phpenv_key + set -l phpenv_value + set -l phpenv_source + + switch $phpenv_key + case global-version + if test -n "$PHPENV_GLOBAL_VERSION" + set phpenv_value $PHPENV_GLOBAL_VERSION + set phpenv_source "fish universal variable" + end + case auto-install + if test -n "$PHPENV_AUTO_INSTALL" + set phpenv_value $PHPENV_AUTO_INSTALL + set phpenv_source "fish universal variable" + end + case auto-install-extensions + if test -n "$PHPENV_AUTO_INSTALL_EXTENSIONS" + set phpenv_value $PHPENV_AUTO_INSTALL_EXTENSIONS + set phpenv_source "fish universal variable" + end + case auto-switch + if test -n "$PHPENV_AUTO_SWITCH" + set phpenv_value $PHPENV_AUTO_SWITCH + set phpenv_source "fish universal variable" + end + case default-extensions + if test -n "$PHPENV_DEFAULT_EXTENSIONS" + set phpenv_value $PHPENV_DEFAULT_EXTENSIONS + set phpenv_source "fish universal variable" + end + end + + if test -z "$phpenv_value" + for phpenv_config_file in ~/.config/fish/conf.d/phpenv.fish ~/.config/phpenv/config ~/.phpenv.fish + if test -f $phpenv_config_file + set -l phpenv_file_value (grep "^$phpenv_key=" $phpenv_config_file | cut -d= -f2- | head -1) + if test -n "$phpenv_file_value" + set phpenv_value $phpenv_file_value + set phpenv_source $phpenv_config_file + break + end + end + end + end + + if test "$argv[2]" = "--verbose" + if test -n "$phpenv_value" + echo "$phpenv_key = $phpenv_value (from $phpenv_source)" + else + echo "$phpenv_key = (not set)" + end + else + echo $phpenv_value + end +end + +function __phpenv_config_set -a phpenv_key phpenv_value + if test -z "$phpenv_value" + echo "Usage: phpenv config set " + return 1 + end + + switch $phpenv_key + case global-version + if __phpenv_validate_version $phpenv_value + set -U PHPENV_GLOBAL_VERSION $phpenv_value + else + echo "Invalid PHP version: $phpenv_value" + echo "Run 'phpenv versions' to see available versions" + return 1 + end + case auto-install + if __phpenv_validate_boolean $phpenv_value + set -g PHPENV_AUTO_INSTALL $phpenv_value + else + echo "Invalid value for auto-install. Use 'true' or 'false'" + return 1 + end + case auto-install-extensions + if __phpenv_validate_boolean $phpenv_value + set -g PHPENV_AUTO_INSTALL_EXTENSIONS $phpenv_value + else + echo "Invalid value for auto-install-extensions. Use 'true' or 'false'" + return 1 + end + case auto-switch + if __phpenv_validate_boolean $phpenv_value + set -g PHPENV_AUTO_SWITCH $phpenv_value + else + echo "Invalid value for auto-switch. Use 'true' or 'false'" + return 1 + end + case default-extensions + if __phpenv_validate_extensions $phpenv_value + set -g PHPENV_DEFAULT_EXTENSIONS $phpenv_value + else + echo "Warning: Some extensions may not be available for all PHP versions" + set -g PHPENV_DEFAULT_EXTENSIONS $phpenv_value + end + case '*' + echo "Unknown config key: $phpenv_key" + echo "Available keys: global-version, auto-install, auto-install-extensions, auto-switch," + echo " default-extensions" + return 1 + end + echo "Set $phpenv_key = $phpenv_value" +end + +function __phpenv_config_list + echo "Configuration (showing sources):" + __phpenv_config_get global-version --verbose + __phpenv_config_get auto-install --verbose + __phpenv_config_get auto-install-extensions --verbose + __phpenv_config_get auto-switch --verbose + __phpenv_config_get default-extensions --verbose +end + +function __phpenv_extensions -a phpenv_action phpenv_extension + switch $phpenv_action + case install + __phpenv_extensions_install $phpenv_extension + case uninstall remove + __phpenv_extensions_uninstall $phpenv_extension + case list ls + __phpenv_extensions_list + case available + __phpenv_extensions_available + case '*' + echo "Usage: phpenv extensions {install|uninstall|list|available} [extension]" + return 1 + end +end + +function __phpenv_extensions_install -a phpenv_extension + if test -z "$phpenv_extension" + echo "Usage: phpenv extensions install " + return 1 + end + + # Check for version override first (from environment, not global variable) + set -l phpenv_version + if test -n "$PHPENV_VERSION_OVERRIDE" + set phpenv_version $PHPENV_VERSION_OVERRIDE + else + set phpenv_version (__phpenv_detect_version) + end + if test -z "$phpenv_version" + echo "No PHP version detected" + return 1 + end + + if not __phpenv_extension_available $phpenv_extension $phpenv_version + echo "Extension $phpenv_extension may not be available for PHP $phpenv_version" + echo "Attempting installation anyway..." + end + + echo "Installing $phpenv_extension for PHP $phpenv_version..." + + if not __phpenv_ensure_taps + echo "Error: Homebrew is required but not available" + return 1 + end + + set -l phpenv_formula "shivammathur/extensions/$phpenv_extension@$phpenv_version" + if brew install $phpenv_formula + echo "$phpenv_extension@$phpenv_version installed successfully" + else + echo "Failed to install $phpenv_extension@$phpenv_version" + echo "Extension may not be available for PHP $phpenv_version" + echo "Run 'phpenv extensions available' to see available extensions" + return 1 + end +end + +function __phpenv_extensions_uninstall -a phpenv_extension + if test -z "$phpenv_extension" + echo "Usage: phpenv extensions uninstall " + return 1 + end + + set -l phpenv_version (__phpenv_detect_version) + if test -z "$phpenv_version" + echo "No PHP version detected" + return 1 + end + + set -l phpenv_formula "shivammathur/extensions/$phpenv_extension@$phpenv_version" + if brew uninstall $phpenv_formula + echo "$phpenv_extension@$phpenv_version uninstalled successfully" + else + echo "Failed to uninstall $phpenv_extension@$phpenv_version" + return 1 + end +end + +function __phpenv_get_available_extensions + if not command -q brew + return 1 + end + + brew tap-info shivammathur/extensions --json 2>/dev/null | \ + jq -r '.[]|(.formula_names[]?)' 2>/dev/null +end + +function __phpenv_extension_available -a phpenv_extension phpenv_version + set -l phpenv_available_extensions (__phpenv_get_available_extensions) + + if test -z "$phpenv_available_extensions" + return 0 # Assume available if can't check + end + + for phpenv_ext_formula in $phpenv_available_extensions + if test "$phpenv_ext_formula" = "shivammathur/extensions/$phpenv_extension@$phpenv_version" + return 0 + end + end + + return 1 +end + +function __phpenv_extensions_available + set -l phpenv_version (__phpenv_detect_version) + if test -z "$phpenv_version" + set phpenv_version "8.3" + end + + echo "Available extensions for PHP $phpenv_version:" + + set -l phpenv_available_extensions (__phpenv_get_available_extensions) + + if test -n "$phpenv_available_extensions" + set -l phpenv_version_extensions + for phpenv_ext_formula in $phpenv_available_extensions + if echo $phpenv_ext_formula | grep -q "@$phpenv_version\$" + set -l phpenv_ext_name (echo $phpenv_ext_formula | \ + sed "s|shivammathur/extensions/||" | sed "s|@$phpenv_version||") + set -a phpenv_version_extensions $phpenv_ext_name + end + end + + if test (count $phpenv_version_extensions) -gt 0 + printf ' %s\n' $phpenv_version_extensions | sort + else + echo " No extensions found for PHP $phpenv_version" + end + else + echo " Unable to fetch extension list or Homebrew not available" + end +end + +function __phpenv_extensions_list + set -l phpenv_version (__phpenv_detect_version) + if test -z "$phpenv_version" + echo "No PHP version detected" + return 1 + end + + set -l phpenv_cellar_path (__phpenv_get_cellar_path) + echo "Extensions for PHP $phpenv_version:" + + if test -d $phpenv_cellar_path + for phpenv_ext_dir in $phpenv_cellar_path/*@$phpenv_version + if test -d $phpenv_ext_dir + set -l phpenv_ext_name (basename $phpenv_ext_dir | sed "s/@$phpenv_version//") + if test "$phpenv_ext_name" != "php" + echo " $phpenv_ext_name" + end + end + end + end +end + +function __phpenv_install_default_extensions -a phpenv_version + set -l phpenv_extensions (__phpenv_config_get default-extensions) + if test -n "$phpenv_extensions" + echo "Installing default extensions for PHP $phpenv_version..." + set -l phpenv_failed_extensions + + for phpenv_ext in (echo $phpenv_extensions | tr ' ' '\n') + if test -n "$phpenv_ext" + echo "Installing $phpenv_ext..." + # Temporarily switch context using local variable + set -l phpenv_saved_version (__phpenv_detect_version) + set -l PHPENV_VERSION_OVERRIDE $phpenv_version + if not env PHPENV_VERSION_OVERRIDE=$phpenv_version __phpenv_extensions_install $phpenv_ext + set -a phpenv_failed_extensions $phpenv_ext + echo "Warning: Failed to install $phpenv_ext for PHP $phpenv_version" + end + end + end + + if test (count $phpenv_failed_extensions) -gt 0 + echo "Some extensions failed to install: "(string join ", " $phpenv_failed_extensions) + echo "You can install them manually later with: phpenv extensions install " + else + echo "All default extensions installed successfully" + end + end +end + +function __phpenv_auto_switch --on-variable PWD + # Debouncing: skip if we just switched directories recently + set -l phpenv_current_time (date +%s) + if set -q PHPENV_LAST_SWITCH_TIME + set -l phpenv_time_diff (math $phpenv_current_time - $PHPENV_LAST_SWITCH_TIME) + if test $phpenv_time_diff -lt 1 + return 0 + end + end + + set -l phpenv_auto_switch (__phpenv_config_get auto-switch) + if test "$phpenv_auto_switch" = "false" + return 0 + end + + if not functions -q __phpenv_detect_version __phpenv_set_php_path + return 0 + end + + set -l phpenv_new_version (__phpenv_detect_version 2>/dev/null) + if test -z "$phpenv_new_version" + return 0 + end + + # Check if we're already using the correct version + if set -q PHPENV_CURRENT_VERSION; and test "$PHPENV_CURRENT_VERSION" = "$phpenv_new_version" + return 0 + end + + if __phpenv_is_version_installed "$phpenv_new_version" 2>/dev/null + __phpenv_set_php_path "$phpenv_new_version" 2>/dev/null + set -g PHPENV_LAST_SWITCH_TIME $phpenv_current_time + else + set -l phpenv_auto_install (__phpenv_config_get auto-install) + if test "$phpenv_auto_install" = "true" + echo "Auto-installing PHP $phpenv_new_version..." + if phpenv install "$phpenv_new_version" + set -g PHPENV_LAST_SWITCH_TIME $phpenv_current_time + end + end + end +end + +function __phpenv_help + echo "phpenv - PHP Version Manager for Fish Shell" + echo "" + echo "Usage: phpenv [args]" + echo "" + echo "Commands:" + echo " install Install a PHP version" + echo " uninstall Uninstall a PHP version" + echo " use [version|system] Use PHP version for current shell (auto-detects if no version)" + echo " 'system' restores original PATH" + echo " local Set PHP version for current project" + echo " global Set global PHP version" + echo " list List installed PHP versions" + echo " current Show current PHP version" + echo " which [binary] Show path to PHP binary" + echo " versions Show all available versions" + echo " doctor Check phpenv installation" + echo " config Manage configuration" + echo " extensions Manage PHP extensions" + echo " help Show this help" + echo "" + echo "Version sources (in order of priority):" + echo " 1. .php-version file" + echo " 2. .tool-version file" + echo " 3. composer.json" + echo " 4. Global version" + echo " 5. System PHP" + echo "" + echo "Configuration:" + echo " auto-switch: Enable automatic PHP version switching (default: true)" + echo " auto-install: Auto-install missing versions (default: false)" + echo "" + echo "For more information, visit:" + echo " https://github.com/ivuorinen/phpenv.fish" +end + +function __phpenv_validate_boolean -a phpenv_value + test "$phpenv_value" = "true" -o "$phpenv_value" = "false" +end + +function __phpenv_validate_version -a phpenv_version + if echo $phpenv_version | grep -qE '^[0-9]+\.[0-9]+$' + return 0 + end + + switch $phpenv_version + case latest nightly '5.x' '7.x' '8.x' + return 0 + case '*' + return 1 + end +end + +function __phpenv_validate_extensions -a phpenv_extensions_string + if echo $phpenv_extensions_string | grep -qE '^[a-zA-Z0-9_-]+( +[a-zA-Z0-9_-]+)*$' + return 0 + else + return 1 + end +end +