1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-04-13 14:59:10 +08:00

feat(python): add virtualenv support

close https://github.com/SpaceVim/SpaceVim/issues/4269
This commit is contained in:
Wang Shidong 2022-04-08 00:53:52 +08:00 committed by GitHub
parent d061ce7f46
commit 17ff71f45c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 365 additions and 0 deletions

View File

@ -116,6 +116,8 @@ function! SpaceVim#layers#lang#python#plugins() abort
\ { 'on_ft' : 'python'}])
call add(plugins, ['alfredodeza/coveragepy.vim',
\ { 'merged' : 0}])
call add(plugins, [g:_spacevim_root_dir . 'bundle/vim-virtualenv',
\ { 'merged' : 0}])
return plugins
endfunction
@ -249,6 +251,13 @@ function! s:language_specified_mappings() abort
\ })
endif
let g:_spacevim_mappings_space.l.v = {'name' : '+Virtualenv'}
call SpaceVim#mapping#space#langSPC('nnoremap', ['l', 'v', 'l'],
\ 'VirtualEnvList', 'list-all-virtualenvs', 1)
call SpaceVim#mapping#space#langSPC('nnoremap', ['l', 'v', 'd'],
\ 'VirtualEnvDeactivate', 'deactivate-current-virtualenv', 1)
endfunction

View File

@ -9,6 +9,7 @@ In `bundle/` directory, there are two kinds of plugins: forked plugins without c
- `vim-toml`: based on [cespare/vim-toml@717bd87ef9](https://github.com/cespare/vim-toml/tree/717bd87ef928293e0cc6cfc12ebf2e007cb25311)
- `neoformat`: based on [neoformat](https://github.com/sbdchd/neoformat/tree/f1b6cd506b72be0a2aaf529105320ec929683920)
- `github-issues.vim`: based on [github-issues.vim](https://github.com/jaxbot/github-issues.vim/tree/46f1922d3d225ed659f3dda1c95e35001c9f41f4)
- `vim-virtualenv`: based on [vim-virtualenv](https://github.com/jmcantrell/vim-virtualenv/tree/b1150223cd876f155ed7a3b2e285ed33f6f93873)
### No changed plugins

9
bundle/vim-virtualenv/.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
*.pyc
/doc/tags
### Template taken from github's gitignore repository
### Python template
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

View File

@ -0,0 +1,13 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

View File

@ -0,0 +1,49 @@
virtualenv.vim
==============
When using :python or :!python, it will only have access to the environment outside of any virtualenvs. If you're working with packages that are only installed in a virtualenv, they will not be available to Vim.
*__Until now!__* The virtualenv.vim plugin will modify python's sys.path and the $PATH environment variable so that anything done with :python or :!python will behave like you would expect for the chosen virtualenv.
If compiled with python support, Vim will have a :python command, but this will be tied to whatever version is the default on your system. If this is the version of python that you use, or you're using a Linux distribution with a sensible package manager (like Debian or Ubuntu), you likely will not have to do anything more than install the plugin. If not, then you will likely have to recompile vim with your version of python.
Usage examples
==============
Deactivate the current virtualenv
:VirtualEnvDeactivate
List all virtualenvs
:VirtualEnvList
Activate the 'spam' virtualenv
:VirtualEnvActivate spam
If you're unsure which one to activate, you could always use tab completion
:VirtualEnvActivate <tab>
![tab-completion](http://i.imgur.com/1ZGrM.png "Tab Completion")
If the shell that started vim had $VIRTUAL\_ENV set, omitting the name will
imply usage of this value.
If you're a virtualenvwrapper user and have $PROJECT\_HOME set, omitting the
name will try to guess which virtualenv to activate based on the current
filename.
You can even show the current virtualenv in the statusline with the included function
![statusline](http://i.imgur.com/oxE70.png "Statusline")
Or, for those with a properly configured Powerline (the virtualenv segment is not enabled by default), your virtualenv indicator will toggle on or off accordingly.
![powerline_indicator](http://i.imgur.com/t6pGg7w.png "Powerline Indicator Toggled")
For more detailed help
:help virtualenv

View File

@ -0,0 +1,57 @@
import vim, os, sys
prev_syspath = None
activate_content = """
try:
__file__
except NameError:
raise AssertionError(
"You must run this like execfile('path/to/activate_this.py', dict(__file__='path/to/activate_this.py'))")
import sys
import os
old_os_path = os.environ['PATH']
os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + os.pathsep + old_os_path
base = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if sys.platform == 'win32':
site_packages = os.path.join(base, 'Lib', 'site-packages')
else:
version = '%s.%s' % (sys.version_info.major, sys.version_info.minor)
site_packages = os.path.join(base, 'lib', 'python%s' % version, 'site-packages')
prev_sys_path = list(sys.path)
import site
site.addsitedir(site_packages)
sys.real_prefix = sys.prefix
sys.prefix = base
# Move the added items to the front of the path:
new_sys_path = []
for item in list(sys.path):
if item not in prev_sys_path:
new_sys_path.append(item)
sys.path.remove(item)
sys.path[:0] = new_sys_path
"""
def activate(env):
global prev_syspath
prev_syspath = list(sys.path)
activate = os.path.join(env, (sys.platform == 'win32') and 'Scripts' or 'bin', 'activate_this.py')
try:
fo = open(activate)
f = fo.read()
fo.close()
except:
f = activate_content
code = compile(f, activate, 'exec')
exec(code, dict(__file__=activate))
def deactivate():
global prev_syspath
try:
sys.path[:] = prev_syspath
prev_syspath = None
except:
pass

View File

@ -0,0 +1,116 @@
if has('python3')
python3 import sys, vim
python3 if vim.eval('expand("<sfile>:p:h")') not in sys.path: sys.path.append(vim.eval('expand("<sfile>:p:h")'))
python3 import pyvenv
endif
if has('python')
python import sys, vim
python if vim.eval('expand("<sfile>:p:h")') not in sys.path: sys.path.append(vim.eval('expand("<sfile>:p:h")'))
python import pyvenv
endif
function! virtualenv#activate(...)
let name = a:0 > 0 ? a:1 : ''
let silent = a:0 > 1 ? a:2 : 0
let env_dir = ''
if len(name) == 0 "Figure out the name based on current file
if isdirectory($VIRTUAL_ENV)
let name = fnamemodify($VIRTUAL_ENV, ':t')
let env_dir = $VIRTUAL_ENV
elseif isdirectory($PROJECT_HOME)
let fn = expand('%:p')
let pat = '^'.$PROJECT_HOME.'/'
if fn =~ pat
let name = fnamemodify(substitute(fn, pat, '', ''), ':h')
if name != '.' "No project directory
let env_dir = g:virtualenv_directory.'/'.name
endif
endif
endif
else
let env_dir = g:virtualenv_directory.'/'.name
endif
"Couldn't figure it out, so DIE
if !isdirectory(env_dir)
if !silent
echoerr "No virtualenv could be auto-detected and activated."
endif
return
endif
let bin = env_dir.(has('win32')? '/Scripts': '/bin')
call virtualenv#deactivate()
let s:prev_path = $PATH
" Prepend bin to PATH, but only if it's not there already
" (activate_this does this also, https://github.com/pypa/virtualenv/issues/14)
if $PATH[:len(bin)] != bin.':'
let $PATH = bin.':'.$PATH
endif
if has('python')
python pyvenv.activate(vim.eval('l:env_dir'))
endif
if has('python3')
python3 pyvenv.activate(vim.eval('l:env_dir'))
endif
let g:virtualenv_name = name
let $VIRTUAL_ENV = env_dir
if exists("*airline#extensions#virtualenv#update")
call airline#extensions#virtualenv#update()
endif
endfunction
function! virtualenv#deactivate()
if has('python')
python pyvenv.deactivate()
endif
if has('python3')
python3 pyvenv.deactivate()
endif
unlet! g:virtualenv_name
let $VIRTUAL_ENV = '' " can't delete parent variables
if exists('s:prev_path')
let $PATH = s:prev_path
endif
if exists("*airline#extensions#virtualenv#update")
call airline#extensions#virtualenv#update()
endif
endfunction
function! virtualenv#list()
for name in virtualenv#names('')
echo name
endfor
endfunction
function! virtualenv#statusline()
if exists('g:virtualenv_name')
return substitute(g:virtualenv_stl_format, '\C%n', g:virtualenv_name, 'g')
else
return ''
endif
endfunction
function! virtualenv#names(prefix)
let venvs = []
for dir in split(glob(g:virtualenv_directory.'/'.a:prefix.'*'), '\n')
if !isdirectory(dir)
continue
endif
let fn = dir.(has('win32')? '/Scripts': '/bin').'/activate'
if !filereadable(fn)
continue
endif
call add(venvs, fnamemodify(dir, ':t'))
endfor
return venvs
endfunction

View File

@ -0,0 +1,58 @@
*virtualenv.txt* Activate a python virtualenv within Vim
Author: Jeremy Cantrell <jmcantrell@gmail.com> *virtualenv-author*
License: Same terms as Vim itself (see |license|)
INTRODUCTION *virtualenv* *virtualenv.vim*
The virtualenv plugin allows you to activate and deactivate a virtualenv
within a live Vim session.
COMMANDS *virtualenv-commands*
:VirtualEnvList *:VirtualEnvList*
List all available virtualenvs.
:VirtualEnvDeactivate *:VirtualEnvDeactivate*
Deactivate the current virtualenv.
:VirtualEnvActivate [name] *:VirtualEnvActivate*
Activate a virtualenv. The name of the virtualenv can be completed with
<tab> at the command line.
If name is not specified, and you have $PROJECT_HOME set, the name will be
guessed based on the current filename.
CONFIGURATION *virtualenv-configuration*
g:virtualenv_loaded *g:virtualenv_loaded*
If set in your |vimrc|, virtualenv.vim is not loaded.
g:virtualenv_directory *g:virtualenv_directory*
The directory that contains the virtualenvs. If you're a virtualenvwrapper
user and you have $WORKON_HOME set, it will default to this. Otherwise it
will default to ~/.virtualenvs.
g:virtualenv_auto_activate *g:virtualenv_auto_activate*
If set, an attempt will be made to detect any active virtualenv, and
activate it.
Example: >
let g:virtualenv_directory = '/path/to/virtualenvs'
<
g:virtualenv_stl_format *g:virtualenv_stl_format*
Format string for the statusline function.
Example: >
let g:virtualenv_stl_format = '[%n]'
<
To use the statusline flag, this must appear in your |'statusline'| setting: >
%{virtualenv#statusline()}
<
The content is derived from the |g:virtualenv_stl_format| variable.
Powerline users can see their statuslines too. After configuring powerline
according to its documentation to support a virtualenv segment, Powerline will
read the value of $VIRTUAL_ENV and display it.
vim:tw=78:et:ft=help:norl:

View File

@ -0,0 +1,53 @@
if exists("g:virtualenv_loaded")
finish
endif
let g:virtualenv_loaded = 1
let s:save_cpo = &cpo
set cpo&vim
if !has('python3') && !has('python')
finish
endif
if !exists("g:virtualenv_auto_activate")
let g:virtualenv_auto_activate = 1
endif
if !exists("g:virtualenv_stl_format")
let g:virtualenv_stl_format = '%n'
endif
if !exists("g:virtualenv_directory")
if isdirectory($WORKON_HOME)
let g:virtualenv_directory = $WORKON_HOME
else
let g:virtualenv_directory = '~/.virtualenvs'
endif
endif
let g:virtualenv_directory = expand(g:virtualenv_directory)
command! -bar VirtualEnvList :call virtualenv#list()
command! -bar VirtualEnvDeactivate :call virtualenv#deactivate()
command! -bar -nargs=? -complete=customlist,s:CompleteVirtualEnv VirtualEnvActivate :call virtualenv#activate(<q-args>)
function! s:Error(message)
echohl ErrorMsg | echo a:message | echohl None
endfunction
function! s:CompleteVirtualEnv(arg_lead, cmd_line, cursor_pos)
return virtualenv#names(a:arg_lead)
endfunction
" DEPRECATED: Leaving in for compatibility
function! VirtualEnvStatusline()
return virtualenv#statusline()
endfunction
if g:virtualenv_auto_activate == 1
call virtualenv#activate('', 1)
endif
let &cpo = s:save_cpo