├── LICENSE ├── README.md └── bin └── p /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 - 2019 Nimit Kalra 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `p` 2 | ## Python Version Management, Simplified. 3 | 4 | ![introduction](https://cloud.githubusercontent.com/assets/1139621/7488032/37f37308-f389-11e4-8995-89f7cba5ad8b.gif) 5 | 6 | `p` is **powerful** and **feature-packed**, yet **simple**; both in setup and use. There are no tricky settings, options, or crazy dependencies. `p` is just a helpful ~600 line Bash script that gets the job done. 7 | 8 | **`p` let's you quickly switch between Python versions whenever you need to, removing the barrier between Python 2.x.x and 3.x.x.** 9 | 10 | `p` was heavily inspired by [`n`, a version manager for Node.js](https://github.com/tj/n). 11 | 12 | `p` is also great for getting started using Python development versions. Use `p latest` to get up and running with the latest development version of Python! 13 | 14 | ## Getting Started 15 | After the [super painless drag-and-drop installation](#installation), you can [start using `p`](#usage) right away. 16 | 17 | ## Usage 18 | ``` 19 | Usage: p [COMMAND] [args] 20 | 21 | Commands: 22 | 23 | p Output versions installed 24 | p status Output current status 25 | p Activate to Python 26 | p latest Activate to the latest Python release 27 | p stable Activate to the latest stable Python release 28 | p use [args ...] Execute Python with [args ...] 29 | p bin Output bin path for 30 | p rm Remove the given version(s) 31 | p prev Revert to the previously activated version 32 | p ls Output the versions of Python available 33 | p ls latest Output the latest Python version available 34 | p ls stable Output the latest stable Python version available 35 | 36 | Options: 37 | 38 | -V, --version Output current version of p 39 | -h, --help Display help information 40 | ``` 41 | 42 | ## Installation 43 | After downloading the Bash script, simply copy it over to your `$PATH` and `p` will take care of the rest. 44 | ```sh 45 | $ wget https://github.com/qw3rtman/p/releases/download/v0.1.0/p 46 | $ chmod +x p 47 | $ mv p /usr/local/bin 48 | ``` 49 | 50 | If you don't have `wget` on your system, you can download the `p` binary from the [releases page](https://github.com/qw3rtman/p/releases) and follow the above steps from the second one onward. 51 | 52 | Alternatively, you can install `p` via `npm`: 53 | 54 | ```shell 55 | npm install -g pyvm 56 | ``` 57 | 58 | So far, `p` has only been tested in Bash. If you can make `p` work on another shell, please send in a pull request! 59 | 60 | ## Updating 61 | Simply follow the above steps and swap out the old Bash script with the new one! 62 | 63 | ## Contributing 64 | Contributions are always welcome. 65 | 66 | Find something interesting in the TODO below, fork our code, create a new branch, and send us a pull request. 67 | 68 | There are only two rules: avoid [code smells](http://blog.codinghorror.com/code-smells/) and abide by the syntax-formatting of the existing code. 69 | 70 | ## TODO 71 | * **greater abstraction between Python 2.x.x and 3.x.x** 72 | * also manage pip 73 | * per-directory/project Python version 74 | * **also manage PyPy** 75 | 76 | ## FAQs 77 | * How does `p` differ from [`pyenv`](https://github.com/yyuu/pyenv)? 78 | * `p` is designed for the average Python user. You can get up and running with the latest development build of Python with one simple command: `p latest`. No configuration is necessary; `p` manages everything for you. 79 | * On the other hand, `pyenv` is for the more advanced user who is comfortable configuring their Python environment to all their needs. `p` provides the basics in one easy to use aesthetically-pleasing command. 80 | * Additionally, `p` is easier to use. To switch your Python version, simply run `p` and you'll be presented with a list of installed Python versions to select from that you can scroll through with your arrow keys and select with the return key. 81 | * `p` is great at dealing with any version of Python. If it's not installed, running `p ` will download the source, configure it for your system, and compile it, all in one simple command. 82 | * How does `p` work? 83 | * `p` stores each Python version installed in `/usr/local/p/versions/python`. When a Python version is activated, `p` creates a symbolic link to the Python binary located at `/usr/local/p/versions/python/python`. Since `p` prefixes the $PATH with `/usr/local/p/versions/python`, this version of `python` is found first; hence, it is used over the default version of Python installed on your system. 84 | * How do I revert back to my default Python version? 85 | * Simply run `p default` and `p` will remove the symbolic link described above; therefore reverting back to your default Python version. 86 | * Does `p` download the source each time I activate or install a version? 87 | * Nope. `p` stores the source for each of the versions installed, allowing for quick activations between already-installed versions. 88 | * How do I get this working on Windows? 89 | * Unfortunately, `p` is not supported on Windows at the time. If you know of a workaround, send in a pull request! 90 | 91 | ## Core Team 92 | ### Nimit Kalra 93 | * / 94 | * 95 | * 96 | * 97 | 98 | ## License 99 | 100 | The below license was included in [`n`](https://github.com/tj/n) and is included below. `p`'s license (also MIT) can be found in [the LICENSE file](https://github.com/qw3rtman/p/blob/master/LICENSE). 101 | 102 | > (The MIT License) 103 | 104 | > Copyright (c) 2014 TJ Holowaychuk <tj@vision-media.ca> 105 | 106 | > Permission is hereby granted, free of charge, to any person obtaining 107 | a copy of this software and associated documentation files (the 108 | 'Software'), to deal in the Software without restriction, including 109 | without limitation the rights to use, copy, modify, merge, publish, 110 | distribute, sublicense, and/or sell copies of the Software, and to 111 | permit persons to whom the Software is furnished to do so, subject to 112 | the following conditions: 113 | 114 | > The above copyright notice and this permission notice shall be 115 | included in all copies or substantial portions of the Software. 116 | 117 | > THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 118 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 119 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 120 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 121 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 122 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 123 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 124 | -------------------------------------------------------------------------------- /bin/p: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # 4 | # Setup. 5 | # 6 | 7 | VERSION="0.1.0" 8 | UP=$'\033[A' 9 | DOWN=$'\033[B' 10 | P_PREFIX=${P_PREFIX-/usr/local} 11 | BASE_VERSIONS_DIR=$P_PREFIX/p/versions 12 | 13 | # 14 | # Add to PATH. 15 | # 16 | 17 | if ! grep -q "export PATH=$BASE_VERSIONS_DIR/python:\$PATH" ~/.bashrc; then 18 | echo -e "\nexport PATH=$BASE_VERSIONS_DIR/python:\$PATH" >> ~/.bashrc 19 | fi 20 | 21 | if ! grep -q "export PATH=\"$BASE_VERSIONS_DIR/python:\$PATH\"" ~/.zshrc; then 22 | echo -e "\nexport PATH=\"$BASE_VERSIONS_DIR/python:\$PATH\"" >> ~/.zshrc 23 | fi 24 | 25 | # 26 | # Python source. 27 | # 28 | 29 | MIRROR=(${PYTHON_MIRROR-https://www.python.org/ftp/python/}) 30 | 31 | test -d "$BASE_VERSIONS_DIR"/python || mkdir -p "$BASE_VERSIONS_DIR"/python 32 | 33 | # 34 | # Log 35 | # 36 | 37 | log() { 38 | printf " \033[36m%10s\033[0m : \033[90m%s\033[0m\n" "$1" "$2" 39 | } 40 | 41 | # 42 | # Exit with the given 43 | # 44 | 45 | abort() { 46 | printf "\n \033[31mError: %s\033[0m\n\n" "$@" && exit 1 47 | } 48 | 49 | # 50 | # Print a (differentiable from log) success message. 51 | # 52 | 53 | success() { 54 | printf "\n \033[32mSuccess: %s\033[0m\n\n" "$@" 55 | } 56 | 57 | # 58 | # Ensure we have curl or wget support. 59 | # 60 | 61 | GET= 62 | 63 | # wget support (Added --no-check-certificate for Github downloads) 64 | command -v wget > /dev/null && GET="wget --no-check-certificate -q -O-" 65 | 66 | command -v curl > /dev/null && GET="curl -# -L" 67 | 68 | test -z "$GET" && abort "curl or wget required" 69 | 70 | # 71 | # Functions used when showing versions installed 72 | # 73 | 74 | enter_fullscreen() { 75 | tput smcup 76 | stty -echo 77 | } 78 | 79 | leave_fullscreen() { 80 | tput rmcup 81 | stty echo 82 | } 83 | 84 | handle_sigint() { 85 | leave_fullscreen 86 | exit $? 87 | } 88 | 89 | handle_sigtstp() { 90 | leave_fullscreen 91 | kill -s SIGSTOP $$ 92 | } 93 | 94 | # 95 | # Output usage information. 96 | # 97 | 98 | display_help() { 99 | cat <<-EOF 100 | 101 | Usage: p [COMMAND] [args] 102 | 103 | Commands: 104 | 105 | p Output versions installed 106 | p status Output current status 107 | p Activate to Python 108 | p latest Activate to the latest Python release 109 | p stable Activate to the latest stable Python release 110 | p use [args ...] Execute Python with [args ...] 111 | p bin Output bin path for 112 | p rm Remove the given version(s) 113 | p prev Revert to the previously activated version 114 | p ls Output the versions of Python available 115 | p ls latest Output the latest Python version available 116 | p ls stable Output the latest stable Python version available 117 | 118 | Options: 119 | 120 | -V, --version Output current version of p 121 | -h, --help Display help information 122 | 123 | EOF 124 | exit 0 125 | } 126 | 127 | # 128 | # Output status. 129 | # 130 | 131 | display_status() { 132 | get_current_version 133 | 134 | log version "$current" 135 | log bin "$(display_bin_path_for_version)" 136 | log previous "$(get_previous_version)" 137 | log latest "$(is_latest_version)" 138 | log stable "$(is_latest_stable_version)" 139 | } 140 | 141 | # 142 | # Hide cursor. 143 | # 144 | 145 | hide_cursor() { 146 | printf "\e[?25l" 147 | } 148 | 149 | # 150 | # Show cursor. 151 | # 152 | 153 | show_cursor() { 154 | printf "\e[?25h" 155 | } 156 | 157 | # 158 | # Output version after selected. 159 | # 160 | 161 | next_version_installed() { 162 | list_versions_installed | grep "$selected" -A 1 | tail -n 1 163 | } 164 | 165 | # 166 | # Output version before selected. 167 | # 168 | 169 | prev_version_installed() { 170 | list_versions_installed | grep "$selected" -B 1 | head -n 1 171 | } 172 | 173 | # 174 | # Output previous version. 175 | # 176 | get_previous_version() { 177 | if [ ! -f "$BASE_VERSIONS_DIR"/.prev ]; then 178 | echo "none" 179 | else 180 | cat "$BASE_VERSIONS_DIR"/.prev 181 | fi 182 | } 183 | 184 | # 185 | # Output p version. 186 | # 187 | 188 | display_p_version() { 189 | echo $VERSION && exit 0 190 | } 191 | 192 | # 193 | # Gets current human-readable Python version. 194 | # 195 | get_current_version() { 196 | # current=$(python -c 'import sys; print(".".join(map(str, sys.version_info[:3])))') 197 | local version 198 | version=$(python -V 2>&1) 199 | current=${version#*Python } 200 | } 201 | 202 | # 203 | # Check for installed version, and populate $active 204 | # 205 | 206 | check_current_version() { 207 | command -v python &> /dev/null 208 | if test $? -eq 0; then 209 | get_current_version 210 | if diff &> /dev/null \ 211 | "$BASE_VERSIONS_DIR"/python/"$current"/python.exe \ 212 | "$(which python)" ; then 213 | active="python/$current" 214 | fi 215 | fi 216 | } 217 | 218 | # 219 | # Display sorted versions directories paths. 220 | # 221 | 222 | versions_paths() { 223 | find "$BASE_VERSIONS_DIR" -maxdepth 2 -type d \ 224 | | sed 's|'"$BASE_VERSIONS_DIR"'/||g' \ 225 | | egrep "[0-9]+\.[0-9]+\.[0-9]+([a|b]?)([0-9]?)+" \ 226 | | sort -k 1,1n -k 2,2n -k 3,3n -t . -k 4,4n -d -k 5,5n -r 227 | } 228 | 229 | # 230 | # Display installed versions with 231 | # 232 | 233 | display_versions_with_selected() { 234 | selected=$1 235 | echo 236 | for version in $(versions_paths); do 237 | version_minus_python=${version#*python\/} 238 | if test "$version" = "$selected"; then 239 | printf " \033[36mο\033[0m %s\033[0m\n" "$version_minus_python" 240 | else 241 | printf " \033[90m%s\033[0m\n" "$version_minus_python" 242 | fi 243 | done 244 | echo 245 | } 246 | 247 | # 248 | # List installed versions. 249 | # 250 | 251 | list_versions_installed() { 252 | for version in $(versions_paths); do 253 | echo "${version}" 254 | done 255 | } 256 | 257 | # 258 | # Display current python --version and others installed. 259 | # 260 | 261 | display_versions() { 262 | enter_fullscreen 263 | check_current_version 264 | display_versions_with_selected "$active" 265 | 266 | trap handle_sigint INT 267 | trap handle_sigtstp SIGTSTP 268 | 269 | while true; do 270 | read -r -n 3 c 271 | case "$c" in 272 | $UP) 273 | clear 274 | display_versions_with_selected "$(prev_version_installed)" 275 | ;; 276 | $DOWN) 277 | clear 278 | display_versions_with_selected "$(next_version_installed)" 279 | ;; 280 | *) 281 | activate "$selected" 282 | leave_fullscreen 283 | exit 284 | ;; 285 | esac 286 | done 287 | } 288 | 289 | # 290 | # Move up a line and erase. 291 | # 292 | 293 | erase_line() { 294 | printf "\033[1A\033[2K" 295 | } 296 | 297 | # 298 | # Check if the HEAD response of is 200. 299 | # 300 | 301 | is_ok() { 302 | curl -Is "$1" | head -n 1 | grep 200 > /dev/null 303 | } 304 | 305 | # 306 | # Determine tarball url for 307 | # 308 | 309 | tarball_url() { 310 | version_directory="${version%a*}" 311 | echo "${MIRROR[@]}${version_directory%b*}/Python-${version}.tgz" 312 | } 313 | 314 | # 315 | # Activate 316 | # 317 | 318 | activate() { 319 | local version=$1 320 | check_current_version 321 | if test "$version" != "$active"; then 322 | echo "$active" > "$BASE_VERSIONS_DIR"/.prev 323 | 324 | ln -sf "$BASE_VERSIONS_DIR"/"$version"/python.exe "$BASE_VERSIONS_DIR"/python/python 325 | fi 326 | } 327 | 328 | # 329 | # Activate previous Python. 330 | # 331 | 332 | activate_previous() { 333 | test -f "$BASE_VERSIONS_DIR"/.prev || abort "no previous versions activated" 334 | local prev 335 | prev=$(cat "$BASE_VERSIONS_DIR"/.prev) 336 | test -d "$BASE_VERSIONS_DIR"/"$prev" || abort "previous version $prev not installed" 337 | activate "$prev" 338 | echo 339 | get_current_version 340 | log activate "$current" 341 | echo 342 | 343 | success "Now using Python $current!" 344 | } 345 | 346 | # 347 | # Activate default (prior to p) Python. 348 | # 349 | activate_default() { 350 | log activate default 351 | 352 | rm -rf "$BASE_VERSIONS_DIR"/python/python 353 | 354 | get_current_version 355 | success "Now using Python $current!\n Use \`p \` to activate another version." 356 | } 357 | 358 | # 359 | # Install 360 | # 361 | 362 | install() { 363 | local version=${1#v} 364 | 365 | local dots 366 | dots=$(echo "$version" | sed 's/[^.]*//g') 367 | if test ${#dots} -eq 1; then 368 | version=$($GET 2> /dev/null "${MIRROR[@]}" \ 369 | | egrep -o '[0-9]+\.[0-9]+\.[0-9]+' \ 370 | | egrep -v '^0\.[0-7]\.' \ 371 | | egrep -v '^0\.8\.[0-5]$' \ 372 | | sort -u -k 1,1n -k 2,2n -k 3,3n -t . \ 373 | | egrep ^"$version" \ 374 | | tail -n1) 375 | 376 | test "$version" || abort "invalid version ${1#v}" 377 | fi 378 | 379 | local dir=$BASE_VERSIONS_DIR/python/$version 380 | local url 381 | url=$(tarball_url "$version") 382 | 383 | if test -d "$dir"; then 384 | if [[ ! -e "$dir"/n.lock ]] ; then 385 | activate python/"$version" 386 | 387 | log activate "$version" 388 | 389 | get_current_version 390 | success "Now using Python $current!" 391 | 392 | exit 393 | fi 394 | fi 395 | 396 | echo 397 | log install Python-"$version" 398 | 399 | is_ok "$url" || abort "invalid version $version" 400 | 401 | log create "$dir" 402 | mkdir -p "$dir" 403 | if [ $? -ne 0 ] ; then 404 | abort "sudo required" 405 | else 406 | touch "$dir"/p.lock 407 | fi 408 | 409 | cd "$dir" || exit 410 | 411 | log fetch "$url" 412 | 413 | curl -L# "$url" | tar -zx --strip 1 414 | 415 | erase_line 416 | rm -f "$dir"/p.lock 417 | 418 | log configure "$version" 419 | ./configure &> /dev/null 420 | 421 | log compile "$version" 422 | make &> /dev/null 423 | 424 | if [ ! -f "python.exe" ]; then 425 | abort "Unable to compile Python $version!" 426 | fi 427 | 428 | activate python/"$version" 429 | log activate "$version" 430 | 431 | source ~/.bashrc 432 | source ~/.zshrc 433 | export PATH=$BASE_VERSIONS_DIR/python:$PATH 434 | log refresh \$PATH 435 | 436 | get_current_version 437 | success "Now using Python $current!" 438 | } 439 | 440 | # 441 | # Remove 442 | # 443 | 444 | remove_versions() { 445 | test -z "$1" && abort "version(s) required" 446 | 447 | for version in "$@"; do 448 | if [[ "$version" = "latest" ]]; then 449 | version=$(display_latest_version) 450 | elif [[ "$version" = "stable" ]]; then 451 | version=$(display_latest_stable_version) 452 | fi 453 | 454 | rm -rf "$BASE_VERSIONS_DIR"/python/"${version#v}" 455 | log remove "$version" 456 | done 457 | 458 | versions=("$@") 459 | 460 | success "Removed Python ${versions// /, }!" 461 | } 462 | 463 | # 464 | # Output bin path for 465 | # 466 | 467 | display_bin_path_for_version() { 468 | get_current_version 469 | 470 | if [ ! -z "$1" ]; then 471 | local version=${1#v} 472 | else 473 | if [ ! -d "$BASE_VERSIONS_DIR"/python/"$current" ]; then 474 | abort "Version required!" 475 | else 476 | local version=$current; 477 | fi 478 | fi 479 | 480 | local bin=$BASE_VERSIONS_DIR/python/$version/python.exe 481 | if test -f "$bin"; then 482 | printf "%s \n" "$bin" 483 | else 484 | abort "Python $version is not installed" 485 | fi 486 | } 487 | 488 | # 489 | # Execute the given of Python with [args ...] 490 | # 491 | 492 | execute_with_version() { 493 | test -z "$1" && abort "version required" 494 | local version=${1#v} 495 | 496 | if [[ "$version" = "latest" ]]; then 497 | version=$(display_latest_version) 498 | elif [[ "$version" = "stable" ]]; then 499 | version=$(display_latest_stable_version) 500 | fi 501 | 502 | local bin=$BASE_VERSIONS_DIR/python/$version/python.exe 503 | 504 | shift # remove version 505 | 506 | if test -f "$bin"; then 507 | $bin "$@" 508 | else 509 | abort "Python $version is not installed" 510 | fi 511 | } 512 | 513 | # 514 | # Display the latest release version. 515 | # 516 | 517 | display_latest_version() { 518 | latest_directory=$($GET 2> /dev/null "${MIRROR[@]}" \ 519 | | egrep -o '[0-9]+\.[0-9]+\.[0-9]+' \ 520 | | sort -u -k 1,1n -k 2,2n -k 3,3n -t . \ 521 | | tail -n1) 522 | 523 | $GET 2> /dev/null "${MIRROR[@]}" "$latest_directory" \ 524 | | egrep -o '[0-9]+\.[0-9]+\.[0-9]+[a|b][0-9]+' \ 525 | | sort -k 1,1n -k 2,2n -k 3,3n -t . -k 4,4n -d -k 5,5n -d \ 526 | | tail -n1 527 | } 528 | 529 | # 530 | # Determine if current version is the latest version. 531 | # 532 | 533 | is_latest_version() { 534 | get_current_version 535 | if [[ $current == $(display_latest_version) ]]; then 536 | echo "yes" 537 | else 538 | echo "no" 539 | fi 540 | } 541 | 542 | # 543 | # Display the latest stable release version. 544 | # 545 | 546 | display_latest_stable_version() { 547 | $GET 2> /dev/null "${MIRROR[@]}" \ 548 | | egrep -o '[0-9]+\.[0-9]*[02468]\.[0-9]+' \ 549 | | sort -u -k 1,1n -k 2,2n -k 3,3n -t . \ 550 | | tail -n1 551 | } 552 | 553 | # 554 | # Determine if current version is the latest stable version. 555 | # 556 | 557 | is_latest_stable_version() { 558 | get_current_version 559 | if [[ $current == $(display_latest_stable_version) ]]; then 560 | echo "yes" 561 | else 562 | echo "no" 563 | fi 564 | } 565 | 566 | # 567 | # Display the versions available. 568 | # 569 | 570 | display_remote_versions() { 571 | check_current_version 572 | local versions="" 573 | versions=$($GET 2> /dev/null "${MIRROR[@]}" \ 574 | | egrep -o '[0-9]+\.[0-9]+\.[0-9]+' \ 575 | | egrep -v '^0\.[0-7]\.' \ 576 | | egrep -v '^0\.8\.[0-5]$' \ 577 | | sort -u -k 1,1n -k 2,2n -k 3,3n -t . \ 578 | | awk '{ print " " $1 }') 579 | 580 | echo 581 | 582 | for v in $versions; do 583 | if test "$active" = "python/$v"; then 584 | printf " \033[36mο\033[0m %s \033[0m\n" "$v" 585 | else 586 | if test -d "$BASE_VERSIONS_DIR"/python/"$v"; then 587 | printf " %s \033[0m\n" "$v" 588 | else 589 | printf " \033[90m%s\033[0m\n" "$v" 590 | fi 591 | fi 592 | done 593 | echo 594 | } 595 | 596 | # 597 | # Handle arguments. 598 | # 599 | 600 | if test $# -eq 0; then 601 | test -z "$(versions_paths)" && abort "no installed version" 602 | display_versions 603 | else 604 | while test $# -ne 0; do 605 | case $1 in 606 | -V|--version) display_p_version ;; 607 | -h|--help|help) display_help ;; 608 | status) display_status ;; 609 | bin|which) 610 | case $2 in 611 | latest) display_bin_path_for_version "$($0 ls latest)"; exit ;; 612 | stable) display_bin_path_for_version "$($0 ls stable)"; exit ;; 613 | *) display_bin_path_for_version "$2"; exit ;; 614 | esac 615 | exit ;; 616 | as|use) shift; execute_with_version "$@"; exit ;; 617 | rm|-) shift; remove_versions "$@"; exit ;; 618 | ls|list) 619 | case $2 in 620 | latest) display_latest_version; exit ;; 621 | stable) display_latest_stable_version; exit ;; 622 | *) display_remote_versions; exit ;; 623 | esac 624 | exit ;; 625 | prev|previous) activate_previous; exit ;; 626 | default) activate_default; exit ;; 627 | latest) install "$($0 ls latest)"; exit ;; 628 | stable) install "$($0 ls stable)"; exit ;; 629 | *) install "$1"; exit ;; 630 | esac 631 | shift 632 | done 633 | fi 634 | --------------------------------------------------------------------------------