Skip to content

Commit

Permalink
Merge pull request #35 from jacquindev/main
Browse files Browse the repository at this point in the history
Add ability to customize pyenv-win-venv installation location
  • Loading branch information
arzkar authored Jan 2, 2025
2 parents ae57baf + 6217a0f commit bccbd42
Show file tree
Hide file tree
Showing 7 changed files with 199 additions and 17 deletions.
53 changes: 47 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ This script depends on the [pyenv-win](https://github.com/pyenv-win/pyenv-win) s

## Power Shell

```
```pwsh
Invoke-WebRequest -UseBasicParsing -Uri "https://raw.githubusercontent.com/pyenv-win/pyenv-win-venv/main/bin/install-pyenv-win-venv.ps1" -OutFile "$HOME\install-pyenv-win-venv.ps1";
&"$HOME\install-pyenv-win-venv.ps1"
```
Expand All @@ -22,7 +22,7 @@ Invoke-WebRequest -UseBasicParsing -Uri "https://raw.githubusercontent.com/pyenv

## Git

```
```pwsh
git clone https://github.com/pyenv-win/pyenv-win-venv "$HOME\.pyenv-win-venv"
```

Expand All @@ -36,6 +36,14 @@ Adding the following paths to your USER PATH variable in order to access the pye
[System.Environment]::SetEnvironmentVariable('path', $env:USERPROFILE + "\.pyenv-win-venv\bin;" + [System.Environment]::GetEnvironmentVariable('path', "User"),"User")
```

- **NOTES**: If you use another path other than `$HOME`, then add the project's `bin` folder to your corresponding USER PATH variable.

- For example, your `pyenv-win-venv` folder located in `D:\Applications\pyenv-win-venv`

```pwsh
[System.Environment]::SetEnvironmentVariable('path', "D:\Applications\pyenv-win-venv\bin;" + [System.Environment]::GetEnvironmentVariable('path', "User"), "User")
```

# Update

Automatically using `pyenv-venv update self` (Recommended)
Expand All @@ -48,7 +56,7 @@ Go to `%USERPROFILE%\.pyenv-win-venv` (which is your installed path) and run `gi

## Power Shell (If the CLI was installed using the PowerScript Installation Script)

```
```pwsh
Invoke-WebRequest -UseBasicParsing -Uri "https://raw.githubusercontent.com/pyenv-win/pyenv-win-venv/main/bin/install-pyenv-win-venv.ps1" -OutFile "$HOME\install-pyenv-win-venv.ps1"; &"$HOME\install-pyenv-win-venv.ps1"
```

Expand All @@ -62,7 +70,7 @@ pyenv-venv uninstall self

## Power Shell

```
```pwsh
Invoke-WebRequest -UseBasicParsing -Uri "https://raw.githubusercontent.com/pyenv-win/pyenv-win-venv/main/bin/install-pyenv-win-venv.ps1" -OutFile "$HOME\install-pyenv-win-venv.ps1";
&"$HOME\install-pyenv-win-venv.ps1" -Uninstall
```
Expand All @@ -83,12 +91,14 @@ Invoke-WebRequest -UseBasicParsing -Uri "https://raw.githubusercontent.com/pyenv
current directory and activate the env
activate activate an env
deactivate deactivate an env
completion autocomplete script for powershell
install install an env
uninstall uninstall an env
uninstall self uninstall the CLI and its envs
list <command> list all installed envs/python versions
local set the given env in .python-version file
config show the app directory
update self update the CLI to the latest version
which <command> show the full path to an executable
help <command> show the CLI/<command> menu
Expand Down Expand Up @@ -167,6 +177,37 @@ pyenv-venv which <exec_name>
pyenv-venv help install
```

## PowerShell Completion

- To load completion code into current shell:

```pwsh
pyenv-venv completion | Out-String | Invoke-Expression
```

- To add completion code directly to the `$PROFILE`

```pwsh
pyenv-venv completion >> $PROFILE
```

- One-time execution of `pyenv-venv` completion code to the `$PROFILE`

```pwsh
Add-Content $PROFILE "if (Get-Command pyenv-venv -ErrorAction SilentlyContinue) {
pyenv-venv completion | Out-String | Invoke-Expression
}"
```

- You can also save the completion script and execute it in the `$PROFILE`, for example:

```pwsh
# Create completion script
pyenv-venv completion > "$HOME\pyenv-venv-completion.ps1"
# Add to the `$PROFILE`
Add-Content $PROFILE "$HOME\pyenv-venv-completion.ps1"
```

# Note

## Env automatic activation using `.python-version` file
Expand All @@ -184,15 +225,15 @@ pyenv-venv help install

- First check if you already have a powershell profile.

```
```pwsh
Test-Path $profile
```
If its `False`, then you need to create a new profile.
- Create a new profile using:
```
```pwsh
New-Item -path $profile -type file –force
```
Expand Down
16 changes: 12 additions & 4 deletions bin/install-pyenv-win-venv.ps1
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# cSpell: disable
<#
.SYNOPSIS
Installs pyenv-win-venv
Expand Down Expand Up @@ -25,8 +26,15 @@
param (
[Switch] $Uninstall = $False
)

$PyEnvWinVenvDir = "${env:USERPROFILE}\.pyenv-win-venv"

$chooseLocation = $(Write-Host "Install 'pyenv-win-venv' to default (y) or custom (n) location?" -NoNewLine; Read-Host)
if ($chooseLocation.ToUpper() -eq 'Y') {
$PyEnvWinVenvDir = "${env:USERPROFILE}\.pyenv-win-venv"
}
else {
$PyEnvWinVenvDir = Read-Host "Input your desired location for pyenv-win-venv installation"
}

$BinPath = "${PyEnvWinVenvDir}\bin"

Function Remove-PyEnvVenvVars() {
Expand Down Expand Up @@ -75,7 +83,7 @@ Function Get-LatestVersion() {
}

Function Main() {
Remove-Item "$HOME\install-pyenv-win-venv.ps1"
Remove-Item "$HOME\install-pyenv-win-venv.ps1" -ErrorAction SilentlyContinue
If ($Uninstall) {
Remove-PyEnvWinVenv
If ($LastExitCode -eq 0) {
Expand Down Expand Up @@ -121,7 +129,7 @@ Function Main() {
else {
# First installation,
# Add the \bin path to the User's Environment Variables
[System.Environment]::SetEnvironmentVariable('path', $env:USERPROFILE + "\.pyenv-win-venv\bin;" + [System.Environment]::GetEnvironmentVariable('path', "User"), "User")
[System.Environment]::SetEnvironmentVariable('path', "$PyEnvWinVenvDir\bin;" + [System.Environment]::GetEnvironmentVariable('path', "User"), "User")
}

(New-Item -Path $PyEnvWinVenvDir -ItemType Directory) *> $null
Expand Down
7 changes: 6 additions & 1 deletion bin/pyenv-venv.bat
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
@ECHO OFF
@REM Alias for pyenv-win-venv.bat
"%USERPROFILE%\.pyenv-win-venv\bin\pyenv-win-venv.bat" %*

@REM "%USERPROFILE%\.pyenv-win-venv\bin\pyenv-win-venv.bat" %*

SET ScriptDir=%~dp0
SET ScriptDir=%ScriptDir:~0,-1%
"%ScriptDir%\pyenv-win-venv.bat" %*
2 changes: 1 addition & 1 deletion bin/pyenv-venv.ps1
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# Alias for pyenv-win-venv.ps1
&"$HOME\.pyenv-win-venv\bin\pyenv-win-venv.ps1" @args
&"$PSScriptRoot\pyenv-win-venv.ps1" @args
8 changes: 7 additions & 1 deletion bin/pyenv-win-venv.bat
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
@ECHO OFF
powershell -File "%USERPROFILE%\.pyenv-win-venv\bin\pyenv-win-venv.ps1" %*
@REM Determine script location for Windows Batch File

@REM Get current folder with no trailing slash
SET ScriptDir=%~dp0
SET ScriptDir=%ScriptDir:~0,-1%

powershell -File "%ScriptDir%\pyenv-win-venv.ps1" %*
39 changes: 35 additions & 4 deletions bin/pyenv-win-venv.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ Param(
# Auto-detect the shell
if ($MyInvocation.MyCommand.CommandType -eq "ExternalScript") {
$invokedShell = "bat"
} else {
}
else {
$invokedShell = "ps1"
}

$app_dir = "$HOME\.pyenv-win-venv"
$app_dir = Resolve-Path "$PSScriptRoot" | Split-Path
$app_env_dir = "$app_dir\envs"
$cli_version = Get-Content "$app_dir\.version"

Expand Down Expand Up @@ -222,6 +223,9 @@ function main {
pyenv which $subcommand2
}
}
elseif ($subcommand1 -eq 'completion') {
Get-Content "$app_dir\completions\pyenv-win-venv.ps1"
}
elseif ($subcommand1 -eq "help" -Or !$subcommand1) {
if (!$subcommand2) {
# Show the help menu if help command used or no commands are used
Expand All @@ -233,6 +237,9 @@ function main {
elseif ($subcommand2 -eq "activate") {
HelpActivate
}
elseif ($subcommand2 -eq "completion") {
HelpCompletion
}
elseif ($subcommand2 -eq "install") {
HelpInstall
}
Expand All @@ -247,7 +254,8 @@ function main {
}
}
else {
Write-Host "Command is not valid. Run `"pyenv-win-venv help`" for the HelpMenu" }
Write-Host "Command is not valid. Run `"pyenv-win-venv help`" for the HelpMenu"
}
}


Expand All @@ -264,6 +272,7 @@ init search for .python-version file in the
current directory and activate the env
activate activate an env
deactivate deactivate an env
completion autocomplete script for powershell
install install an env
uninstall uninstall an env
uninstall self uninstall the CLI and its envs
Expand Down Expand Up @@ -328,7 +337,7 @@ Function Remove-PyEnvVenvVars() {
Function Remove-PyEnvVenvProfile() {
$CurrentProfile = Get-Content $Profile
$UpdatedProfile = $CurrentProfile.Replace("pyenv-venv init", "")
Set-Content -Path $Profile -Value $UpdatedProfile
Set-Content -Path $Profile -Value $UpdatedProfile
}

# Function to write debug log
Expand Down Expand Up @@ -407,4 +416,26 @@ Example: `pyenv-venv which python`
"
}

Function HelpCompletion() {
Write-Host 'Usage: pyenv-venv completion
Generate autocompletion script for powershell.
- Load completion code into current shell:
pyenv-venv completion | Out-String | Invoke-Expression
- Add completion code directly to $PROFILE:
pyenv-venv completion >> $PROFILE
- Execute completion code in the $PROFILE:
Add-Content $PROFILE "if (Get-Command pyenv-venv -ErrorAction SilentlyContinue) {
pyenv-venv completion | Out-String | Invoke-Expression
}"
- Save completion script and execute in the $PROFILE:
pyenv-venv completion > "$HOME\pyenv-venv-completion.ps1"
Add-Content $PROFILE "$HOME\pyenv-venv-completion.ps1"
'
}

main
91 changes: 91 additions & 0 deletions completions/pyenv-win-venv.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# cSpell: disable
# This script is based on https://github.com/Moeologist/scoop-completion

# powershell completion for pyenv-win-venv

###-start-pyenv-venv-completion-###
$script:PyenvVenvCommands = @(
'activate',
'deactivate',
'init',
'install',
'config',
'completion',
'list'
'local',
'uninstall',
'update self',
'which',
'help'
)

$script:PyenvVenvSubCommands = @{
init = 'root'
list = 'envs python'
which = 'python python3 pip pip3'
help = 'activate completion init install list uninstall which'
}

function script:PyenvVenvExpandCmd($filter) {
$cmdList = @()
$cmdList += $PyenvVenvCommands
$cmdList -like "$filter*"
}

function script:PyenvVenvEnvNames($filter, $activate) {
if ($activate) {
@( pyenv-venv list envs | Where-Object { $_ -like "$filter*" })
} else {
@( pyenv-venv list envs | Where-Object { $_ -like "$filter*" }) + "self"
}
}

function script:PyenvVenvPythonVersions($filter) {
@(& Get-ChildItem -Path "$env:PYENV_HOME\versions" -Name | Where-Object { $_ -like "$filter*" })
}

function script:PyenvVenvExpandCmdParams($commands, $command, $filter) {
$commands.$command -split ' ' | Where-Object { $_ -like "$filter*" }
}

function script:PyenvVenvTabExpansion($lastBlock) {
switch -regex ($lastBlock) {
# pyenv-venv uninstall <env_name>|self
"^uninstall\s+(?:.+\s+)?(?<env_name>[\w][\-\.\w]*)?$" {
return PyenvVenvEnvNames $matches['env_name'] $false
}

# pyenv-venv activate <env_name>
"^activate\s+(?:.+\s+)?(?<env_name>[\w][\-\.\w]*)?$" {
return PyenvVenvEnvNames $matches['env_name'] $true
}

# pyenv-venv install <python_version> <env_name>
"^install\s+(?:.+\s+)?(?<python_version>[\w][\-\.\w]*)?$" {
return PyenvVenvPythonVersions $matches['python_version']
}

# pyenv-venv <cmd>
"^(?<cmd>\S*)$" {
return PyenvVenvExpandCmd $matches['cmd'] $true
}

# pyenv-venv <cmd> <subcmd>
"^(?<cmd>$($PyenvVenvSubCommands.Keys -join '|'))\s+(?<op>\S*)$" {
return PyenvVenvExpandCmdParams $PyenvVenvSubCommands $matches['cmd'] $matches['op']
}
}
}

$scriptBlock = {
param($wordToComplete, $commandAst, $cursorPosition)
$rest = $commandAst.CommandElements[1..$commandAst.CommandElements.Count] -join ' '
if ($rest -ne "" -and $wordToComplete -eq "") {
$rest += " "
}
PyenvVenvTabExpansion $rest
}

Register-ArgumentCompleter -Native -CommandName @('pyenv-venv', 'pyenv-win-venv') -ScriptBlock $scriptBlock

###-end-pyenv-venv-completion-###

0 comments on commit bccbd42

Please sign in to comment.