5set "pyenv=cscript //nologo "%~dp0..\libexec\pyenv.vbs""
7:: if 'pyenv' called alone, then run pyenv.vbs
14for /f "delims=␌" %%i in ('echo skip') do (call :incrementskip)
15if [%skip%]==[0] set "skip_arg="
16if not [%skip%]==[0] set "skip_arg=skip=%skip% "
18if /i [%1%2]==[version] call :check_path
20:: use pyenv.vbs to aid resolving absolute path of "active" version into 'bindir'
23for /f "%skip_arg%delims=" %%i in ('%pyenv% vname') do call :extrapath "%~dp0..\versions\%%i"
25:: Add %AppData% Python Scripts to %extrapaths%.
26for /F "tokens=1,2 delims=-" %%i in ('%pyenv% vname') do (
27 if /i "%%j" == "win32" (
28 for /F "tokens=1,2,3 delims=." %%a in ("%%i") do (
29 set "extrapaths=%extrapaths%%AppData%\Python\Python%%a%%b-32\Scripts;"
32 for /F "tokens=1,2,3 delims=." %%a in ("%%i") do (
33 set "extrapaths=%extrapaths%%AppData%\Python\Python%%a%%b\Scripts;"
38:: all help implemented as plugin
39if /i [%2]==[--help] goto :plugin
41 call :plugin %2 %1 || goto :error
45 if [%2]==[] call :plugin help --help || goto :error
46 if not [%2]==[] call :plugin %2 --help || goto :error
50:: let pyenv.vbs handle these
51set "commands=rehash global local version vname version-name versions commands shims which whence help --help"
52for %%a in (%commands%) do (
54 rem endlocal not really needed here since above commands do not set any variable
55 rem endlocal closed automatically with exit
56 rem no need to update PATH either
57 %pyenv% %* || goto :error
62:: jump to plugin or fall to exec
63if /i not [%1]==[exec] goto :plugin
64:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
67if not exist "%bindir%" (
68 echo No global/local python version has been set yet. Please set the global/local version by typing:
69 echo pyenv global 3.7.4
70 echo pyenv local 3.7.4
75set cmdline=%cmdline:~5%
77:: update PATH to active version and run command
78:: endlocal needed only if cmdline sets a variable: SET FOO=BAR
79call :remove_shims_from_path
80%cmdline% || goto :error
84:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
85:remove_shims_from_path
86set "python_shims=%~dp0..\shims"
87call :normalizepath "%python_shims%" python_shims
89set "path=%extrapaths%"
91:: arcane magic courtesy of StackOverflow question 5471556
92:: https://stackoverflow.com/a/7940444/381865
93setlocal DisableDelayedExpansion
94:: escape all special characters
95set "_path=%_path:"=""%"
96set "_path=%_path:^=^^%"
97set "_path=%_path:&=^&%"
98set "_path=%_path:|=^|%"
99set "_path=%_path:<=^<%"
100set "_path=%_path:>=^>%"
101set "_path=%_path:;=^;^;%"
102:: the 'missing' quotes below are intended
103set _path=%_path:""="%
104:: " => ""Q (like quote)
105set "_path=%_path:"=""Q%"
106:: ;; => "S"S (like semicolon)
107set "_path=%_path:;;="S"S%"
108set "_path=%_path:^;^;=;%"
109set "_path=%_path:""="%"
110setlocal EnableDelayedExpansion
113set "_path=!_path:"Q=!"
115for %%a in ("!_path:"S"S=";"!") do (
121 if /i not "%%~dpfa"=="%python_shims%" call :append_to_path %%~dpfa
126:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
130:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
132set "exe=%~dp0..\libexec\pyenv-%1"
134call :normalizepath %exe% exe
136if exist "%exe%.bat" (
137 set "exe=call "%exe%.bat""
139) else if exist "%exe%.cmd" (
140 set "exe=call "%exe%.cmd""
142) else if exist "%exe%.vbs" (
143 set "exe=cscript //nologo "%exe%.vbs""
145) else if exist "%exe%.lnk" (
146 set "exe=start '' "%exe%.bat""
148 echo pyenv: no such command '%1'
152:: replace first arg with %exe%
154set cmdline=%cmdline:^=^^%
155set cmdline=%cmdline:!=^!%
161if not [%arg1%]==[] goto :loop_len
163setlocal enabledelayedexpansion
164set cmdline=!exe! !cmdline:~%len%!
165:: run command (no need to update PATH for plugins)
166:: endlocal needed to ensure exit will not automatically close setlocal
167:: otherwise PYTHON_VERSION will be lost
168endlocal && endlocal && %cmdline% || goto :error
170:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
171:: convert path which may have relative nodes (.. or .)
172:: to its absolute value so can be used in PATH
176:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
177:: compute list of paths to add for all activated python versions
179call :normalizepath %1 bindir
180set "extrapaths=%extrapaths%%bindir%;%bindir%\Scripts;%bindir%\bin;"
182:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
183:: check pyenv python shim is first in PATH
185set "python_shim=%~dp0..\shims\python.bat"
186if not exist "%python_shim%" goto :eof
187call :normalizepath "%python_shim%" python_shim
189for /f "%skip_arg%delims=" %%a in ('where python') do (
190 if /i "%python_shim%"=="%%~dpfa" goto :eof
191 call :set_python_where %%~dpfa
193call :bad_path "%python_where%"
195:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
196:: set python_where variable if empty
198if "%python_where%"=="" set "python_where=%*"
200:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
201:: tell bad PATH and exit
205echo ␛[91mFATAL: Found ␛[95m%bad_python%␛[91m version before pyenv in PATH.␛[0m
206echo ␛[91mPlease remove ␛[95m%bad_dir%␛[91m from PATH for pyenv to work properly.␛[0m
208:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
209:: if AutoExec/AutoRun is configured for cmd it probably ends with the `cls` command
210:: meaning there will be a Form Feed (U+000C) included in the output.
211:: so we add it as a dilimiter so that we can skip x number of lines.
212:: we find out how many to skip and pass that tot the skip option of the for loop,
213:: EXCEPT skip=0 gives errors...
214:: so we prepend every command with `echo skip` to force skip being at least 1