├── .gitignore ├── README.md ├── autoload ├── pyenv.vim ├── pyenv │ ├── info.vim │ ├── pyenv.vim │ ├── python.vim │ └── utils.vim ├── vital.vim └── vital │ ├── _vim_pyenv.vim │ ├── _vim_pyenv │ ├── Prelude.vim │ ├── Process.vim │ └── System │ │ ├── Cache │ │ ├── Base.vim │ │ └── Memory.vim │ │ └── Filepath.vim │ └── vim_pyenv.vital ├── doc └── vim-pyenv.txt ├── initialize.py ├── plugin └── pyenv.vim ├── pyenv_vim.py └── statics ├── _screenshot01.png └── _screenshot02.png /.gitignore: -------------------------------------------------------------------------------- 1 | .local.vimrc 2 | .python-version 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | vim-pyenv 2 | =============================================================================== 3 | vim-pyenv allows you to activate and deactivate the pyenv Python correctly 4 | in a live Vim session. 5 | 6 | [pyenv](https://github.com/yyuu/pyenv) is a simple Python version management 7 | system and users can change the Python versions in a simple way. 8 | However, if you use pyenv to switch the Python version or virtualenv, the 9 | omni-completion would not work correctly. 10 | This is because Vim refers to the system Python and does not know anything 11 | about the pyenv Python, especially the packages you installed on the pyenv 12 | Python. 13 | 14 | vim-pyenv activates the pyenv Python and adds the external Python library 15 | search path (PYTHONPATH) to Vim's internal Python PYTHONPATH. 16 | Thus, with vim-pyenv, your [jedi-vim](https://github.com/davidhalter/jedi-vim) 17 | or any kind of Python omni-completion system returns a correct completion list. 18 | 19 | ![vim-pyenv allows you to select pyenv Python within a live Vim 20 | session](./statics/_screenshot01.png) 21 | 22 | Additionally, vim-pyenv supports Vim's dual Python 2 and 3 system. 23 | If your Vim is compiled with +python and +python3, vim-pyenv automatically 24 | synchronizes the Python version to the external Python version. 25 | 26 | ![jedi-vim omni completion works correctly](./statics/_screenshot02.png) 27 | 28 | 29 | Documentation 30 | =============================================================================== 31 | See `:help vim-pyenv` in Vim. 32 | 33 | 34 | Installation 35 | =============================================================================== 36 | Installing vim-pyenv by using [Neobundle](https://github.com/Shougo/neobundle.vim) 37 | is strongly recommended, because with Neobundle you can specify the 38 | dependencies of the plugins via `depends` options. 39 | The following is an example of Neobundle entry which specifies jedi-vim as a 40 | dependency. 41 | 42 | ```vim 43 | NeoBundle 'davidhalter/jedi-vim' 44 | 45 | " Do not load vim-pyenv until *.py is opened and 46 | " make sure that it is loaded after jedi-vim is loaded. 47 | NeoBundleLazy 'lambdalisue/vim-pyenv', { 48 | \ 'depends': ['davidhalter/jedi-vim'], 49 | \ 'autoload': { 50 | \ 'filetypes': ['python', 'python3'], 51 | \ }} 52 | ``` 53 | 54 | You can use [vundle](https://github.com/gmarik/vundle) or 55 | [pathogen](http://www.vim.org/scripts/script.php?script_id=2332), but make sure 56 | that vim-pyenv is loaded after jedi-vim. 57 | 58 | 59 | Using vim-pyenv with jedi-vim 60 | ============================================================================== 61 | 62 | `vim-pyenv-activate-post` and `vim-pyenv-deactivate-post` autocmd can be used 63 | to change the major version of jedi like 64 | 65 | ```vim 66 | if jedi#init_python() 67 | function! s:jedi_auto_force_py_version() abort 68 | let g:jedi#force_py_version = pyenv#python#get_internal_major_version() 69 | endfunction 70 | augroup vim-pyenv-custom-augroup 71 | autocmd! * 72 | autocmd User vim-pyenv-activate-post call s:jedi_auto_force_py_version() 73 | autocmd User vim-pyenv-deactivate-post call s:jedi_auto_force_py_version() 74 | augroup END 75 | endif 76 | ``` 77 | 78 | The code above automatically call `jedi#force_py_version` every after user change a python version of pyenv via `:PyenvActivate` or `:PyenvDeactivate` command. 79 | -------------------------------------------------------------------------------- /autoload/pyenv.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | 5 | function! s:activate(...) abort " {{{ 6 | if pyenv#pyenv#is_activated() 7 | call s:deactivate({'quiet': 1}) 8 | endif 9 | let envs = pyenv#pyenv#get_selected_envs() 10 | let env = get(a:000, 0, '') 11 | let env = empty(env) ? get(envs, 0, 'system') : env 12 | let opts = extend({ 13 | \ 'quiet': 0, 14 | \}, get(a:000, 1, {})) 15 | " activate pyenv and select correct python 16 | if pyenv#pyenv#activate(env) 17 | " automatically select a correct python major version 18 | " and regulate sys.path 19 | call pyenv#python#auto_internal_major_version() 20 | call pyenv#python#exec_code( 21 | \ 'pyenv_vim.activate(vim.vars["pyenv#python_exec"])') 22 | call pyenv#utils#doautocmd('activate-post') 23 | if !opts.quiet 24 | redraw | call pyenv#utils#info(printf( 25 | \'vim-pyenv: "%s" is activated.', env, 26 | \)) 27 | endif 28 | else 29 | redraw | call pyenv#utils#error(printf( 30 | \ 'vim-pyenv: Failed to activate "%s". Python version of the env is not supported in this Vim.', 31 | \ env, 32 | \)) 33 | endif 34 | endfunction " }}} 35 | function! s:deactivate(...) abort " {{{ 36 | let opts = extend({ 37 | \ 'quiet': 0, 38 | \}, get(a:000, 0, {})) 39 | if pyenv#pyenv#is_activated() 40 | let env = pyenv#pyenv#get_activated_env() 41 | " reset 'sys.path' of internal python 42 | call pyenv#python#exec_code('pyenv_vim.deactivate()') 43 | " deactivate pyenv and select correct python 44 | call pyenv#pyenv#deactivate() 45 | call pyenv#python#auto_internal_major_version() 46 | call pyenv#utils#doautocmd('deactivate-post') 47 | if !opts.quiet 48 | redraw! | call pyenv#utils#info(printf( 49 | \'vim-pyenv: "%s" is deactivated.', env, 50 | \)) 51 | endif 52 | endif 53 | endfunction " }}} 54 | function! s:validate() abort " {{{ 55 | if !pyenv#pyenv#is_enabled() 56 | call pyenv#utils#error( 57 | \ '"pyenv" is not found in $PATH.', 58 | \ 'Specify g:pyenv#pyenv_exec', 59 | \) 60 | return 0 61 | elseif !pyenv#python#is_enabled() 62 | call pyenv#utils#error( 63 | \ 'vim-pyenv requires Python and/or Python3 interpreter (+python, +python3).', 64 | \) 65 | return 0 66 | endif 67 | return 1 68 | endfunction " }}} 69 | 70 | 71 | function! pyenv#activate(...) abort " {{{ 72 | if s:validate() 73 | return call('s:activate', a:000) 74 | endif 75 | endfunction " }}} 76 | function! pyenv#deactivate(...) abort " {{{ 77 | if s:validate() 78 | return call('s:deactivate', a:000) 79 | endif 80 | endfunction " }}} 81 | 82 | 83 | let &cpo = s:save_cpo 84 | unlet! s:save_cpo 85 | -------------------------------------------------------------------------------- /autoload/pyenv/info.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | 5 | let s:C = pyenv#utils#import('System.Cache.Memory') 6 | let s:cache = s:C.new() 7 | 8 | 9 | function! s:get_info() abort " {{{ 10 | if !pyenv#python#is_enabled() || !pyenv#pyenv#is_enabled() 11 | return {} 12 | endif 13 | let info = s:cache.get('info', {}) 14 | if empty(info) 15 | let info = { 16 | \ 'internal_version': pyenv#python#get_internal_version(), 17 | \ 'internal_major_version': pyenv#python#get_internal_major_version(), 18 | \ 'external_version': pyenv#python#get_external_version(), 19 | \ 'external_major_version': pyenv#python#get_external_major_version(), 20 | \ 'selected_versions': pyenv#pyenv#get_selected_envs(), 21 | \ 'activated_version': pyenv#pyenv#get_activated_env(), 22 | \} 23 | let info.selected_version = get(info.selected_versions, 0, 'system') 24 | let info.selected_versions = join(info.selected_versions, ', ') 25 | call s:cache.set('info', info) 26 | endif 27 | return info 28 | endfunction " }}} 29 | function! s:format_string(format, info) abort " {{{ 30 | let format_map = { 31 | \ 'iv': 'internal_version', 32 | \ 'im': 'internal_major_version', 33 | \ 'ev': 'external_version', 34 | \ 'em': 'external_major_version', 35 | \ 'sv': 'selected_version', 36 | \ 'ss': 'selected_versions', 37 | \ 'av': 'activated_version', 38 | \} 39 | return pyenv#utils#format_string(a:format, format_map, a:info) 40 | endfunction " }}} 41 | function! s:format_string_by_preset(name, info) abort " {{{ 42 | let preset = { 43 | \ 'long': '%{#}av%{ (|)}ev', 44 | \ 'short': '%{#}av', 45 | \} 46 | return s:format_string(get(preset, a:name, ''), a:info) 47 | endfunction " }}} 48 | function! s:clear() abort " {{{ 49 | call s:cache.remove('info') 50 | endfunction " }}} 51 | 52 | function! pyenv#info#get(...) abort " {{{ 53 | return call('s:get_info', a:000) 54 | endfunction " }}} 55 | function! pyenv#info#format(format, ...) abort " {{{ 56 | if a:0 > 0 57 | let info = expr 58 | else 59 | let info = s:get_info() 60 | endif 61 | return s:format_string(a:format, info) 62 | endfunction " }}} 63 | function! pyenv#info#preset(preset_name, ...) abort " {{{ 64 | if a:0 > 0 65 | let info = expr 66 | else 67 | let info = s:get_info() 68 | endif 69 | return s:format_string_by_preset(a:preset_name, info) 70 | endfunction " }}} 71 | 72 | " Autocmd 73 | augroup vim-pyenv-info " {{{ 74 | autocmd! * 75 | " clear cache when user activate/deactivate pyenv 76 | autocmd User vim-pyenv-activate-post call s:clear() 77 | autocmd User vim-pyenv-deactivate-post call s:clear() 78 | augroup END " }}} 79 | 80 | let &cpo = s:save_cpo 81 | "vim: foldlevel=0 sts=2 sw=2 smarttab et ai textwidth=0 fdm=marker 82 | -------------------------------------------------------------------------------- /autoload/pyenv/pyenv.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | 5 | let s:R = pyenv#utils#import('Process') 6 | let s:P = pyenv#utils#import('System.Filepath') 7 | let s:activated_name = '' 8 | 9 | 10 | " Private 11 | function! s:is_enabled() abort " {{{ 12 | return executable(g:pyenv#pyenv_exec) 13 | endfunction " }}} 14 | function! s:parse_envs(rows) abort " {{{ 15 | let envs = map( 16 | \ deepcopy(a:rows), 17 | \ 'split(substitute(v:val, "\*", "", "g"))[0]', 18 | \) 19 | return envs 20 | endfunction " }}} 21 | function! s:get_installable_envs() abort " {{{ 22 | if !s:is_enabled() 23 | return [] 24 | endif 25 | let result = pyenv#utils#system(join([ 26 | \ g:pyenv#pyenv_exec, 27 | \ 'install', 28 | \ '--list', 29 | \])) 30 | if result.status == 0 31 | let candidates = split(result.stdout, "\n")[1:] 32 | return map(candidates, 'substitute(v:val, "^\\s\\+", "", "")') 33 | endif 34 | return [] 35 | endfunction " }}} 36 | function! s:get_available_envs() abort " {{{ 37 | if !s:is_enabled() 38 | return [] 39 | endif 40 | let result = pyenv#utils#system(join([ 41 | \ g:pyenv#pyenv_exec, 42 | \ 'versions', 43 | \])) 44 | if result.status == 0 45 | return s:parse_envs(split(result.stdout, "\n")) 46 | endif 47 | return [] 48 | endfunction " }}} 49 | function! s:get_selected_envs() abort " {{{ 50 | if !s:is_enabled() 51 | return [] 52 | endif 53 | let result = pyenv#utils#system(join([ 54 | \ g:pyenv#pyenv_exec, 55 | \ 'version', 56 | \])) 57 | if result.status == 0 58 | return s:parse_envs(split(result.stdout, "\n")) 59 | endif 60 | return [] 61 | endfunction " }}} 62 | function! s:get_activated_env() abort " {{{ 63 | return empty(s:activated_name) ? 'builtin' : s:activated_name 64 | endfunction " }}} 65 | function! s:get_prefixes() abort " {{{ 66 | if !s:is_enabled() 67 | return [] 68 | endif 69 | let result = pyenv#utils#system(join([ 70 | \ g:pyenv#pyenv_exec, 71 | \ 'prefix', 72 | \])) 73 | if result.status == 0 74 | return split(result.stdout, '\v\r?\n') 75 | endif 76 | return [] 77 | endfunction " }}} 78 | 79 | 80 | function! s:is_activated() abort " {{{ 81 | return !empty(s:activated_name) 82 | endfunction " }}} 83 | function! s:activate(name) abort " {{{ 84 | if !s:is_enabled() 85 | return 0 86 | endif 87 | let previous_PYENV_VERSION = $PYENV_VERSION 88 | let $PYENV_VERSION = a:name 89 | let external_python_major_version = pyenv#python#get_external_major_version() 90 | if external_python_major_version == 2 && !has('python') 91 | " cannot activate this python 92 | let $PYENV_VERSION = previous_PYENV_VERSION 93 | return 0 94 | elseif external_python_major_version == 3 && !has('python3') 95 | " cannot activate this python 96 | let $PYENV_VERSION = previous_PYENV_VERSION 97 | return 0 98 | endif 99 | let s:activated_name = a:name 100 | if g:pyenv#auto_create_ctags 101 | call s:create_ctags() 102 | endif 103 | if g:pyenv#auto_assign_ctags 104 | call s:assign_ctags() 105 | endif 106 | return 1 107 | endfunction " }}} 108 | function! s:deactivate() abort " {{{ 109 | if !s:is_enabled() 110 | return 0 111 | endif 112 | let is_activated = s:is_activated() 113 | let $PYENV_VERSION = '' 114 | let s:activated_name = '' 115 | if g:pyenv#auto_assign_ctags 116 | call s:assign_ctags() 117 | endif 118 | return 1 119 | endfunction " }}} 120 | function! s:create_ctags(...) abort " {{{ 121 | let verbose = get(a:000, 0, 0) 122 | if !s:is_enabled() || empty(g:pyenv#ctags_exec) 123 | return 0 124 | endif 125 | let prefixes = s:get_prefixes() 126 | for prefix in prefixes 127 | let result = pyenv#utils#system(join([ 128 | \ g:pyenv#ctags_exec, 129 | \ '-o', s:P.join(prefix, 'tags'), 130 | \ '-R', prefix, 131 | \])) 132 | if verbose && result.status 133 | echoerr result.stdout 134 | echo result.args 135 | endif 136 | endfor 137 | return 1 138 | endfunction " }}} 139 | function! s:assign_ctags() abort " {{{ 140 | if !s:is_enabled() 141 | return 0 142 | endif 143 | let prefixes = s:get_prefixes() 144 | for prefix in prefixes 145 | let tagfile = s:P.join(prefix, 'tags') 146 | let taglist = split(&l:tags, ',') 147 | if filereadable(tagfile) && index(taglist, tagfile) == -1 148 | silent execute printf('setlocal tags+=%s', fnameescape(tagfile)) 149 | endif 150 | endfor 151 | endfunction " }}} 152 | function! s:withdraw_ctags() abort " {{{ 153 | if !s:is_enabled() 154 | return 0 155 | endif 156 | let prefixes = s:get_prefixes() 157 | for prefix in prefixes 158 | let tagfile = s:P.join(prefix, 'tags') 159 | let &l:tags = substitute(&l:tags, 160 | \ printf(',\?%s', tagfile), 161 | \ '', '', 162 | \) 163 | endfor 164 | endfunction " }}} 165 | 166 | 167 | " External API 168 | function! pyenv#pyenv#is_enabled(...) abort " {{{ 169 | return call('s:is_enabled', a:000) 170 | endfunction " }}} 171 | function! pyenv#pyenv#get_installable_envs(...) abort " {{{ 172 | return call('s:get_installable_envs', a:000) 173 | endfunction " }}} 174 | function! pyenv#pyenv#get_available_envs(...) abort " {{{ 175 | return call('s:get_available_envs', a:000) 176 | endfunction " }}} 177 | function! pyenv#pyenv#get_selected_envs(...) abort " {{{ 178 | return call('s:get_selected_envs', a:000) 179 | endfunction " }}} 180 | function! pyenv#pyenv#get_activated_env(...) abort " {{{ 181 | return call('s:get_activated_env', a:000) 182 | endfunction " }}} 183 | function! pyenv#pyenv#is_activated(...) abort " {{{ 184 | return call('s:is_activated', a:000) 185 | endfunction " }}} 186 | function! pyenv#pyenv#activate(...) abort " {{{ 187 | return call('s:activate', a:000) 188 | endfunction " }}} 189 | function! pyenv#pyenv#deactivate(...) abort " {{{ 190 | return call('s:deactivate', a:000) 191 | endfunction " }}} 192 | function! pyenv#pyenv#create_ctags(...) abort " {{{ 193 | return call('s:create_ctags', a:000) 194 | endfunction " }}} 195 | function! pyenv#pyenv#assign_ctags(...) abort " {{{ 196 | return call('s:assign_ctags', a:000) 197 | endfunction " }}} 198 | function! pyenv#pyenv#withdraw_ctags(...) abort " {{{ 199 | return call('s:withdraw_ctags', a:000) 200 | endfunction " }}} 201 | 202 | 203 | function! s:init() abort " {{{ 204 | if empty(get(g:, 'pyenv#pyenv_exec', '')) 205 | let candidates = [ 206 | \ expand('~/.pyenv/bin/pyenv'), 207 | \ expand('~/.anyenv/envs/pyenv/bin/pyenv'), 208 | \ expand('/usr/local/bin/pyenv'), 209 | \ 'pyenv', 210 | \] 211 | let g:pyenv#pyenv_exec = get( 212 | \ filter(candidates, 'executable(v:val)'), 213 | \ 0, '') 214 | endif 215 | if empty(get(g:, 'pyenv#ctags_exec', '')) 216 | if executable('ctags') 217 | let g:pyenv#ctags_exec = 'ctags' 218 | endif 219 | endif 220 | let g:pyenv#auto_create_ctags = get(g:, 'pyenv#auto_create_ctags', 0) 221 | let g:pyenv#auto_assign_ctags = get(g:, 'pyenv#auto_assign_ctags', 1) 222 | endfunction " }}} 223 | call s:init() 224 | 225 | let &cpo = s:save_cpo 226 | " vim:set et ts=2 sts=2 sw=2 tw=0 fdm=marker: 227 | -------------------------------------------------------------------------------- /autoload/pyenv/python.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | 5 | let s:P = pyenv#utils#import('System.Filepath') 6 | let s:repository_root = fnameescape(expand(':p:h:h:h')) 7 | let s:selected_major_version = 0 8 | 9 | 10 | " Private 11 | function! s:is_enabled() abort " {{{ 12 | return has('pythonx') || has('python') || has('python3') 13 | endfunction " }}} 14 | 15 | function! s:get_external_version() abort " {{{ 16 | if !executable(g:pyenv#python_exec) 17 | return '' 18 | endif 19 | let result = pyenv#utils#system(join([ 20 | \ g:pyenv#python_exec, 21 | \ '--version', 22 | \])) 23 | if result.status == 0 24 | return split(result.stdout)[1] 25 | endif 26 | return '' 27 | endfunction " }}} 28 | function! s:get_external_major_version() abort " {{{ 29 | let external_version = s:get_external_version() 30 | if empty(external_version) 31 | return 0 32 | endif 33 | return get(split(external_version, '\.'), 0, '0') 34 | endfunction " }}} 35 | function! s:get_internal_version() abort " {{{ 36 | return s:exec_code('pyenv_vim.py_version()') 37 | endfunction " }}} 38 | function! s:get_internal_major_version() abort " {{{ 39 | if s:selected_major_version == 0 40 | if has('python') && has('python3') 41 | return get(g:, 'pyenv#default_major_version', 2) 42 | elseif has('python') 43 | return 2 44 | elseif has('python3') 45 | return 3 46 | endif 47 | endif 48 | return s:selected_major_version 49 | endfunction " }}} 50 | function! s:set_internal_major_version(major) abort " {{{ 51 | if a:major == 2 && has('python') 52 | let s:selected_major_version = 2 53 | return 1 54 | elseif a:major == 3 && has('python3') 55 | let s:selected_major_version = 3 56 | return 1 57 | endif 58 | return 0 59 | endfunction " }}} 60 | function! s:auto_internal_major_version() abort " {{{ 61 | let external_major = s:get_external_major_version() 62 | call s:set_internal_major_version(external_major) 63 | endfunction " }}} 64 | 65 | function! s:exec_file(file, ...) abort " {{{ 66 | let major = get(a:000, 0, s:get_internal_major_version()) 67 | if major == 2 && has('python') 68 | execute printf('pyfile %s', fnameescape(a:file)) 69 | elseif major == 3 && has('python3') 70 | execute printf('py3file %s', fnameescape(a:file)) 71 | endif 72 | endfunction " }}} 73 | function! s:exec_code(code, ...) abort " {{{ 74 | let major = get(a:000, 0, s:get_internal_major_version()) 75 | let return_value = 0 76 | if major == 2 && has('python') 77 | execute printf('python %s', a:code) 78 | elseif major == 3 && has('python3') 79 | execute printf('python3 %s', a:code) 80 | endif 81 | return return_value 82 | endfunction " }}} 83 | 84 | 85 | " External API 86 | function! pyenv#python#is_enabled(...) abort " {{{ 87 | return call('s:is_enabled', a:000) 88 | endfunction " }}} 89 | function! pyenv#python#get_external_version(...) abort " {{{ 90 | return call('s:get_external_version', a:000) 91 | endfunction " }}} 92 | function! pyenv#python#get_external_major_version(...) abort " {{{ 93 | return call('s:get_external_major_version', a:000) 94 | endfunction " }}} 95 | function! pyenv#python#get_internal_version(...) abort " {{{ 96 | return call('s:get_internal_version', a:000) 97 | endfunction " }}} 98 | function! pyenv#python#get_internal_major_version(...) abort " {{{ 99 | return call('s:get_internal_major_version', a:000) 100 | endfunction " }}} 101 | function! pyenv#python#set_internal_major_version(...) abort " {{{ 102 | return call('s:get_internal_major_version', a:000) 103 | endfunction " }}} 104 | function! pyenv#python#auto_internal_major_version(...) abort " {{{ 105 | return call('s:auto_internal_major_version', a:000) 106 | endfunction " }}} 107 | function! pyenv#python#exec_file(...) abort " {{{ 108 | return call('s:exec_file', a:000) 109 | endfunction " }}} 110 | function! pyenv#python#exec_code(...) abort " {{{ 111 | return call('s:exec_code', a:000) 112 | endfunction " }}} 113 | 114 | 115 | function! s:init() abort " {{{ 116 | if empty(get(g:, 'pyenv#python_exec', '')) 117 | let candidates = [ 118 | \ expand('~/.pyenv/shims/python'), 119 | \ expand('~/.anyenv/envs/pyenv/shims/python'), 120 | \ expand('/usr/local/bin/python'), 121 | \ 'python', 122 | \] 123 | let g:pyenv#python_exec = get( 124 | \ filter(candidates, 'executable(v:val)'), 125 | \ 0, '') 126 | endif 127 | " initialize internal python (invalid version will be ignored silently) 128 | let filename = s:P.join(s:repository_root, 'initialize.py') 129 | call s:auto_internal_major_version() 130 | call s:exec_file(filename, 2) 131 | call s:exec_file(filename, 3) 132 | endfunction " }}} 133 | call s:init() 134 | 135 | 136 | let &cpo = s:save_cpo 137 | " vim:set et ts=2 sts=2 sw=2 tw=0 fdm=marker: 138 | -------------------------------------------------------------------------------- /autoload/pyenv/utils.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | 5 | let s:V = vital#of('vim_pyenv') 6 | 7 | function! pyenv#utils#import(name) abort " {{{ 8 | let cache_name = printf( 9 | \ '_vital_module_%s', 10 | \ substitute(a:name, '\.', '_', 'g'), 11 | \) 12 | if !has_key(s:, cache_name) 13 | let s:[cache_name] = s:V.import(a:name) 14 | endif 15 | return s:[cache_name] 16 | endfunction " }}} 17 | function! pyenv#utils#system(...) abort " {{{ 18 | let P = pyenv#utils#import('Process') 19 | silent let stdout = call(P.system, a:000, P) 20 | let status = P.get_last_status() 21 | return { 22 | \ 'stdout': stdout, 23 | \ 'status': status, 24 | \ 'args': a:000, 25 | \} 26 | endfunction " }}} 27 | 28 | " echo 29 | function! pyenv#utils#echo(hl, msg) abort " {{{ 30 | execute 'echohl' a:hl 31 | try 32 | for m in split(a:msg, '\v\r?\n') 33 | echo m 34 | endfor 35 | finally 36 | echohl None 37 | endtry 38 | endfunction " }}} 39 | function! pyenv#utils#debug(...) abort " {{{ 40 | if !get(g:, 'pyenv#debug', 0) 41 | return 42 | endif 43 | let args = map(deepcopy(a:000), 'pyenv#utils#ensure_string(v:val)') 44 | call pyenv#utils#echo('Comment', 'DEBUG: vim-pyenv: ' . join(args)) 45 | endfunction " }}} 46 | function! pyenv#utils#info(...) abort " {{{ 47 | let args = map(deepcopy(a:000), 'pyenv#utils#ensure_string(v:val)') 48 | call pyenv#utils#echo('Title', join(args)) 49 | endfunction " }}} 50 | function! pyenv#utils#warn(...) abort " {{{ 51 | let args = map(deepcopy(a:000), 'pyenv#utils#ensure_string(v:val)') 52 | call pyenv#utils#echo('WarningMsg', join(args)) 53 | endfunction " }}} 54 | function! pyenv#utils#error(...) abort " {{{ 55 | let args = map(deepcopy(a:000), 'pyenv#utils#ensure_string(v:val)') 56 | call pyenv#utils#echo('Error', join(args)) 57 | endfunction " }}} 58 | 59 | " echomsg 60 | function! pyenv#utils#echomsg(hl, msg) abort " {{{ 61 | execute 'echohl' a:hl 62 | try 63 | for m in split(a:msg, '\v\r?\n') 64 | echomsg m 65 | endfor 66 | finally 67 | echohl None 68 | endtry 69 | endfunction " }}} 70 | function! pyenv#utils#debugmsg(...) abort " {{{ 71 | if !get(g:, 'pyenv#debug', 0) 72 | return 73 | endif 74 | let args = map(deepcopy(a:000), 'pyenv#utils#ensure_string(v:val)') 75 | call pyenv#utils#echomsg('Comment', 'DEBUG: vim-pyenv: ' . join(args)) 76 | endfunction " }}} 77 | function! pyenv#utils#infomsg(...) abort " {{{ 78 | let args = map(deepcopy(a:000), 'pyenv#utils#ensure_string(v:val)') 79 | call pyenv#utils#echomsg('Title', join(args)) 80 | endfunction " }}} 81 | function! pyenv#utils#warnmsg(...) abort " {{{ 82 | let args = map(deepcopy(a:000), 'pyenv#utils#ensure_string(v:val)') 83 | call pyenv#utils#echomsg('WarningMsg', join(args)) 84 | endfunction " }}} 85 | function! pyenv#utils#errormsg(...) abort " {{{ 86 | let args = map(deepcopy(a:000), 'pyenv#utils#ensure_string(v:val)') 87 | call pyenv#utils#echomsg('Error', join(args)) 88 | endfunction " }}} 89 | 90 | " string 91 | function! pyenv#utils#ensure_string(x) abort " {{{ 92 | let P = pyenv#utils#import('Prelude') 93 | return P.is_string(a:x) ? a:x : [a:x] 94 | endfunction " }}} 95 | function! pyenv#utils#smart_string(value) abort " {{{ 96 | let P = pyenv#utils#import('Prelude') 97 | if P.is_string(a:value) 98 | return a:value 99 | elseif P.is_numeric(a:value) 100 | return a:value ? string(a:value) : '' 101 | elseif P.is_list(a:value) || P.is_dict(a:value) 102 | return !empty(a:value) ? string(a:value) : '' 103 | else 104 | return string(a:value) 105 | endif 106 | endfunction " }}} 107 | function! pyenv#utils#format_string(format, format_map, data) abort " {{{ 108 | " format rule: 109 | " %{|} 110 | " '' if != '' 111 | " '' if == '' 112 | " %{} 113 | " '' if != '' 114 | " '' if == '' 115 | " %{|} 116 | " '' if != '' 117 | " '' if == '' 118 | if empty(a:data) 119 | return '' 120 | endif 121 | let pattern_base = '\v\%%%%(\{([^\}\|]*)%%(\|([^\}\|]*)|)\}|)%s' 122 | let str = copy(a:format) 123 | for [key, value] in items(a:format_map) 124 | let result = pyenv#utils#smart_string(get(a:data, value, '')) 125 | let pattern = printf(pattern_base, key) 126 | let repl = strlen(result) ? printf('\1%s\2', result) : '' 127 | let str = substitute(str, pattern, repl, 'g') 128 | endfor 129 | return substitute(str, '\v^\s+|\s+$', '', 'g') 130 | endfunction " }}} 131 | 132 | function! pyenv#utils#doautocmd(name) abort " {{{ 133 | let name = printf('vim-pyenv-%s', a:name) 134 | if 703 < v:version || (v:version == 703 && has('patch438')) 135 | silent execute 'doautocmd User ' . name 136 | else 137 | silent execute 'doautocmd User ' . name 138 | endif 139 | endfunction " }}} 140 | 141 | let &cpo = s:save_cpo 142 | " vim:set et ts=2 sts=2 sw=2 tw=0 fdm=marker: 143 | -------------------------------------------------------------------------------- /autoload/vital.vim: -------------------------------------------------------------------------------- 1 | function! vital#of(name) abort 2 | let files = globpath(&runtimepath, 'autoload/vital/' . a:name . '.vital') 3 | let file = split(files, "\n") 4 | if empty(file) 5 | throw 'vital: version file not found: ' . a:name 6 | endif 7 | let ver = readfile(file[0], 'b') 8 | if empty(ver) 9 | throw 'vital: invalid version file: ' . a:name 10 | endif 11 | return vital#_{substitute(ver[0], '\W', '', 'g')}#new() 12 | endfunction 13 | -------------------------------------------------------------------------------- /autoload/vital/_vim_pyenv.vim: -------------------------------------------------------------------------------- 1 | let s:self_version = expand(':t:r') 2 | let s:self_file = expand('') 3 | 4 | " Note: The extra argument to globpath() was added in Patch 7.2.051. 5 | let s:globpath_third_arg = v:version > 702 || v:version == 702 && has('patch51') 6 | 7 | let s:loaded = {} 8 | let s:cache_module_path = {} 9 | let s:cache_sid = {} 10 | 11 | let s:_vital_files_cache_runtimepath = '' 12 | let s:_vital_files_cache = [] 13 | let s:_unify_path_cache = {} 14 | 15 | function! s:import(name, ...) abort 16 | let target = {} 17 | let functions = [] 18 | for a in a:000 19 | if type(a) == type({}) 20 | let target = a 21 | elseif type(a) == type([]) 22 | let functions = a 23 | endif 24 | unlet a 25 | endfor 26 | let module = s:_import(a:name) 27 | if empty(functions) 28 | call extend(target, module, 'keep') 29 | else 30 | for f in functions 31 | if has_key(module, f) && !has_key(target, f) 32 | let target[f] = module[f] 33 | endif 34 | endfor 35 | endif 36 | return target 37 | endfunction 38 | 39 | function! s:load(...) dict abort 40 | for arg in a:000 41 | let [name; as] = type(arg) == type([]) ? arg[: 1] : [arg, arg] 42 | let target = split(join(as, ''), '\W\+') 43 | let dict = self 44 | let dict_type = type({}) 45 | while !empty(target) 46 | let ns = remove(target, 0) 47 | if !has_key(dict, ns) 48 | let dict[ns] = {} 49 | endif 50 | if type(dict[ns]) == dict_type 51 | let dict = dict[ns] 52 | else 53 | unlet dict 54 | break 55 | endif 56 | endwhile 57 | 58 | if exists('dict') 59 | call extend(dict, s:_import(name)) 60 | endif 61 | unlet arg 62 | endfor 63 | return self 64 | endfunction 65 | 66 | function! s:unload() abort 67 | let s:loaded = {} 68 | let s:cache_sid = {} 69 | let s:cache_module_path = {} 70 | endfunction 71 | 72 | function! s:exists(name) abort 73 | return s:_get_module_path(a:name) !=# '' 74 | endfunction 75 | 76 | function! s:search(pattern) abort 77 | let paths = s:_vital_files(a:pattern) 78 | let modules = sort(map(paths, 's:_file2module(v:val)')) 79 | return s:_uniq(modules) 80 | endfunction 81 | 82 | function! s:expand_modules(entry, all) abort 83 | if type(a:entry) == type([]) 84 | let candidates = s:_concat(map(copy(a:entry), 's:search(v:val)')) 85 | if empty(candidates) 86 | throw printf('vital: Any of module %s is not found', string(a:entry)) 87 | endif 88 | if eval(join(map(copy(candidates), 'has_key(a:all, v:val)'), '+')) 89 | let modules = [] 90 | else 91 | let modules = [candidates[0]] 92 | endif 93 | else 94 | let modules = s:search(a:entry) 95 | if empty(modules) 96 | throw printf('vital: Module %s is not found', a:entry) 97 | endif 98 | endif 99 | call filter(modules, '!has_key(a:all, v:val)') 100 | for module in modules 101 | let a:all[module] = 1 102 | endfor 103 | return modules 104 | endfunction 105 | 106 | function! s:_import(name) abort 107 | if type(a:name) == type(0) 108 | return s:_build_module(a:name) 109 | endif 110 | let path = s:_get_module_path(a:name) 111 | if path ==# '' 112 | throw 'vital: module not found: ' . a:name 113 | endif 114 | let sid = s:_get_sid_by_script(path) 115 | if !sid 116 | try 117 | execute 'source' fnameescape(path) 118 | catch /^Vim\%((\a\+)\)\?:E484/ 119 | throw 'vital: module not found: ' . a:name 120 | catch /^Vim\%((\a\+)\)\?:E127/ 121 | " Ignore. 122 | endtry 123 | 124 | let sid = s:_get_sid_by_script(path) 125 | endif 126 | return s:_build_module(sid) 127 | endfunction 128 | 129 | function! s:_get_module_path(name) abort 130 | let key = a:name . '_' 131 | if has_key(s:cache_module_path, key) 132 | return s:cache_module_path[key] 133 | endif 134 | if s:_is_absolute_path(a:name) && filereadable(a:name) 135 | return a:name 136 | endif 137 | if a:name ==# '' 138 | let paths = [s:self_file] 139 | elseif a:name =~# '\v^\u\w*%(\.\u\w*)*$' 140 | let paths = s:_vital_files(a:name) 141 | else 142 | throw 'vital: Invalid module name: ' . a:name 143 | endif 144 | 145 | call filter(paths, 'filereadable(expand(v:val, 1))') 146 | let path = get(paths, 0, '') 147 | let s:cache_module_path[key] = path 148 | return path 149 | endfunction 150 | 151 | function! s:_get_sid_by_script(path) abort 152 | if has_key(s:cache_sid, a:path) 153 | return s:cache_sid[a:path] 154 | endif 155 | 156 | let path = s:_unify_path(a:path) 157 | for line in filter(split(s:_redir('scriptnames'), "\n"), 158 | \ 'stridx(v:val, s:self_version) > 0') 159 | let list = matchlist(line, '^\s*\(\d\+\):\s\+\(.\+\)\s*$') 160 | if !empty(list) && s:_unify_path(list[2]) ==# path 161 | let s:cache_sid[a:path] = list[1] - 0 162 | return s:cache_sid[a:path] 163 | endif 164 | endfor 165 | return 0 166 | endfunction 167 | 168 | function! s:_file2module(file) abort 169 | let filename = fnamemodify(a:file, ':p:gs?[\\/]?/?') 170 | let tail = matchstr(filename, 'autoload/vital/_\w\+/\zs.*\ze\.vim$') 171 | return join(split(tail, '[\\/]\+'), '.') 172 | endfunction 173 | 174 | if filereadable(expand(':r') . '.VIM') 175 | " resolve() is slow, so we cache results. 176 | " Note: On windows, vim can't expand path names from 8.3 formats. 177 | " So if getting full path via and $HOME was set as 8.3 format, 178 | " vital load duplicated scripts. Below's :~ avoid this issue. 179 | function! s:_unify_path(path) abort 180 | if has_key(s:_unify_path_cache, a:path) 181 | return s:_unify_path_cache[a:path] 182 | endif 183 | let value = tolower(fnamemodify(resolve(fnamemodify( 184 | \ a:path, ':p')), ':~:gs?[\\/]?/?')) 185 | let s:_unify_path_cache[a:path] = value 186 | return value 187 | endfunction 188 | else 189 | function! s:_unify_path(path) abort 190 | return resolve(fnamemodify(a:path, ':p:gs?[\\/]?/?')) 191 | endfunction 192 | endif 193 | 194 | if s:globpath_third_arg 195 | function! s:_runtime_files(path) abort 196 | return split(globpath(&runtimepath, a:path, 1), "\n") 197 | endfunction 198 | else 199 | function! s:_runtime_files(path) abort 200 | return split(globpath(&runtimepath, a:path), "\n") 201 | endfunction 202 | endif 203 | 204 | function! s:_vital_files(pattern) abort 205 | if s:_vital_files_cache_runtimepath !=# &runtimepath 206 | let path = printf('autoload/vital/%s/**/*.vim', s:self_version) 207 | let s:_vital_files_cache = s:_runtime_files(path) 208 | let mod = ':p:gs?[\\/]\+?/?' 209 | call map(s:_vital_files_cache, 'fnamemodify(v:val, mod)') 210 | let s:_vital_files_cache_runtimepath = &runtimepath 211 | endif 212 | let target = substitute(a:pattern, '\.', '/', 'g') 213 | let target = substitute(target, '\*', '[^/]*', 'g') 214 | let regexp = printf('autoload/vital/%s/%s.vim', s:self_version, target) 215 | return filter(copy(s:_vital_files_cache), 'v:val =~# regexp') 216 | endfunction 217 | 218 | " Copy from System.Filepath 219 | if has('win16') || has('win32') || has('win64') 220 | function! s:_is_absolute_path(path) abort 221 | return a:path =~? '^[a-z]:[/\\]' 222 | endfunction 223 | else 224 | function! s:_is_absolute_path(path) abort 225 | return a:path[0] ==# '/' 226 | endfunction 227 | endif 228 | 229 | function! s:_build_module(sid) abort 230 | if has_key(s:loaded, a:sid) 231 | return copy(s:loaded[a:sid]) 232 | endif 233 | let functions = s:_get_functions(a:sid) 234 | 235 | let prefix = '' . a:sid . '_' 236 | let module = {} 237 | for func in functions 238 | let module[func] = function(prefix . func) 239 | endfor 240 | if has_key(module, '_vital_loaded') 241 | let V = vital#{s:self_version}#new() 242 | if has_key(module, '_vital_depends') 243 | let all = {} 244 | let modules = 245 | \ s:_concat(map(module._vital_depends(), 246 | \ 's:expand_modules(v:val, all)')) 247 | call call(V.load, modules, V) 248 | endif 249 | try 250 | call module._vital_loaded(V) 251 | catch 252 | " FIXME: Show an error message for debug. 253 | endtry 254 | endif 255 | if !get(g:, 'vital_debug', 0) 256 | call filter(module, 'v:key =~# "^\\a"') 257 | endif 258 | let s:loaded[a:sid] = module 259 | return copy(module) 260 | endfunction 261 | 262 | if exists('+regexpengine') 263 | function! s:_get_functions(sid) abort 264 | let funcs = s:_redir(printf("function /\\%%#=2^\%d_", a:sid)) 265 | let map_pat = '' . a:sid . '_\zs\w\+' 266 | return map(split(funcs, "\n"), 'matchstr(v:val, map_pat)') 267 | endfunction 268 | else 269 | function! s:_get_functions(sid) abort 270 | let prefix = '' . a:sid . '_' 271 | let funcs = s:_redir('function') 272 | let filter_pat = '^\s*function ' . prefix 273 | let map_pat = prefix . '\zs\w\+' 274 | return map(filter(split(funcs, "\n"), 275 | \ 'stridx(v:val, prefix) > 0 && v:val =~# filter_pat'), 276 | \ 'matchstr(v:val, map_pat)') 277 | endfunction 278 | endif 279 | 280 | if exists('*uniq') 281 | function! s:_uniq(list) abort 282 | return uniq(a:list) 283 | endfunction 284 | else 285 | function! s:_uniq(list) abort 286 | let i = len(a:list) - 1 287 | while 0 < i 288 | if a:list[i] ==# a:list[i - 1] 289 | call remove(a:list, i) 290 | let i -= 2 291 | else 292 | let i -= 1 293 | endif 294 | endwhile 295 | return a:list 296 | endfunction 297 | endif 298 | 299 | function! s:_concat(lists) abort 300 | let result_list = [] 301 | for list in a:lists 302 | let result_list += list 303 | endfor 304 | return result_list 305 | endfunction 306 | 307 | function! s:_redir(cmd) abort 308 | let [save_verbose, save_verbosefile] = [&verbose, &verbosefile] 309 | set verbose=0 verbosefile= 310 | redir => res 311 | silent! execute a:cmd 312 | redir END 313 | let [&verbose, &verbosefile] = [save_verbose, save_verbosefile] 314 | return res 315 | endfunction 316 | 317 | function! vital#{s:self_version}#new() abort 318 | return s:_import('') 319 | endfunction 320 | -------------------------------------------------------------------------------- /autoload/vital/_vim_pyenv/Prelude.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | if v:version ># 703 || 5 | \ (v:version is 703 && has('patch465')) 6 | function! s:glob(expr) abort 7 | return glob(a:expr, 1, 1) 8 | endfunction 9 | else 10 | function! s:glob(expr) abort 11 | let R = glob(a:expr, 1) 12 | return split(R, '\n') 13 | endfunction 14 | endif 15 | 16 | function! s:globpath(path, expr) abort 17 | let R = globpath(a:path, a:expr, 1) 18 | return split(R, '\n') 19 | endfunction 20 | 21 | " Wrapper functions for type(). 22 | let [ 23 | \ s:__TYPE_NUMBER, 24 | \ s:__TYPE_STRING, 25 | \ s:__TYPE_FUNCREF, 26 | \ s:__TYPE_LIST, 27 | \ s:__TYPE_DICT, 28 | \ s:__TYPE_FLOAT] = [ 29 | \ type(3), 30 | \ type(""), 31 | \ type(function('tr')), 32 | \ type([]), 33 | \ type({}), 34 | \ has('float') ? type(str2float('0')) : -1] 35 | " __TYPE_FLOAT = -1 when -float 36 | " This doesn't match to anything. 37 | 38 | " Number or Float 39 | function! s:is_numeric(Value) abort 40 | let _ = type(a:Value) 41 | return _ ==# s:__TYPE_NUMBER 42 | \ || _ ==# s:__TYPE_FLOAT 43 | endfunction 44 | 45 | " Number 46 | function! s:is_number(Value) abort 47 | return type(a:Value) ==# s:__TYPE_NUMBER 48 | endfunction 49 | 50 | " Float 51 | function! s:is_float(Value) abort 52 | return type(a:Value) ==# s:__TYPE_FLOAT 53 | endfunction 54 | " String 55 | function! s:is_string(Value) abort 56 | return type(a:Value) ==# s:__TYPE_STRING 57 | endfunction 58 | " Funcref 59 | function! s:is_funcref(Value) abort 60 | return type(a:Value) ==# s:__TYPE_FUNCREF 61 | endfunction 62 | " List 63 | function! s:is_list(Value) abort 64 | return type(a:Value) ==# s:__TYPE_LIST 65 | endfunction 66 | " Dictionary 67 | function! s:is_dict(Value) abort 68 | return type(a:Value) ==# s:__TYPE_DICT 69 | endfunction 70 | 71 | function! s:truncate_skipping(str, max, footer_width, separator) abort 72 | call s:_warn_deprecated("truncate_skipping", "Data.String.truncate_skipping") 73 | 74 | let width = s:wcswidth(a:str) 75 | if width <= a:max 76 | let ret = a:str 77 | else 78 | let header_width = a:max - s:wcswidth(a:separator) - a:footer_width 79 | let ret = s:strwidthpart(a:str, header_width) . a:separator 80 | \ . s:strwidthpart_reverse(a:str, a:footer_width) 81 | endif 82 | 83 | return s:truncate(ret, a:max) 84 | endfunction 85 | 86 | function! s:truncate(str, width) abort 87 | " Original function is from mattn. 88 | " http://github.com/mattn/googlereader-vim/tree/master 89 | 90 | call s:_warn_deprecated("truncate", "Data.String.truncate") 91 | 92 | if a:str =~# '^[\x00-\x7f]*$' 93 | return len(a:str) < a:width ? 94 | \ printf('%-'.a:width.'s', a:str) : strpart(a:str, 0, a:width) 95 | endif 96 | 97 | let ret = a:str 98 | let width = s:wcswidth(a:str) 99 | if width > a:width 100 | let ret = s:strwidthpart(ret, a:width) 101 | let width = s:wcswidth(ret) 102 | endif 103 | 104 | if width < a:width 105 | let ret .= repeat(' ', a:width - width) 106 | endif 107 | 108 | return ret 109 | endfunction 110 | 111 | function! s:strwidthpart(str, width) abort 112 | call s:_warn_deprecated("strwidthpart", "Data.String.strwidthpart") 113 | 114 | if a:width <= 0 115 | return '' 116 | endif 117 | let ret = a:str 118 | let width = s:wcswidth(a:str) 119 | while width > a:width 120 | let char = matchstr(ret, '.$') 121 | let ret = ret[: -1 - len(char)] 122 | let width -= s:wcswidth(char) 123 | endwhile 124 | 125 | return ret 126 | endfunction 127 | function! s:strwidthpart_reverse(str, width) abort 128 | call s:_warn_deprecated("strwidthpart_reverse", "Data.String.strwidthpart_reverse") 129 | 130 | if a:width <= 0 131 | return '' 132 | endif 133 | let ret = a:str 134 | let width = s:wcswidth(a:str) 135 | while width > a:width 136 | let char = matchstr(ret, '^.') 137 | let ret = ret[len(char) :] 138 | let width -= s:wcswidth(char) 139 | endwhile 140 | 141 | return ret 142 | endfunction 143 | 144 | if v:version >= 703 145 | " Use builtin function. 146 | function! s:wcswidth(str) abort 147 | call s:_warn_deprecated("wcswidth", "Data.String.wcswidth") 148 | return strwidth(a:str) 149 | endfunction 150 | else 151 | function! s:wcswidth(str) abort 152 | call s:_warn_deprecated("wcswidth", "Data.String.wcswidth") 153 | 154 | if a:str =~# '^[\x00-\x7f]*$' 155 | return strlen(a:str) 156 | end 157 | 158 | let mx_first = '^\(.\)' 159 | let str = a:str 160 | let width = 0 161 | while 1 162 | let ucs = char2nr(substitute(str, mx_first, '\1', '')) 163 | if ucs == 0 164 | break 165 | endif 166 | let width += s:_wcwidth(ucs) 167 | let str = substitute(str, mx_first, '', '') 168 | endwhile 169 | return width 170 | endfunction 171 | 172 | " UTF-8 only. 173 | function! s:_wcwidth(ucs) abort 174 | let ucs = a:ucs 175 | if (ucs >= 0x1100 176 | \ && (ucs <= 0x115f 177 | \ || ucs == 0x2329 178 | \ || ucs == 0x232a 179 | \ || (ucs >= 0x2e80 && ucs <= 0xa4cf 180 | \ && ucs != 0x303f) 181 | \ || (ucs >= 0xac00 && ucs <= 0xd7a3) 182 | \ || (ucs >= 0xf900 && ucs <= 0xfaff) 183 | \ || (ucs >= 0xfe30 && ucs <= 0xfe6f) 184 | \ || (ucs >= 0xff00 && ucs <= 0xff60) 185 | \ || (ucs >= 0xffe0 && ucs <= 0xffe6) 186 | \ || (ucs >= 0x20000 && ucs <= 0x2fffd) 187 | \ || (ucs >= 0x30000 && ucs <= 0x3fffd) 188 | \ )) 189 | return 2 190 | endif 191 | return 1 192 | endfunction 193 | endif 194 | 195 | let s:is_windows = has('win16') || has('win32') || has('win64') || has('win95') 196 | let s:is_cygwin = has('win32unix') 197 | let s:is_mac = !s:is_windows && !s:is_cygwin 198 | \ && (has('mac') || has('macunix') || has('gui_macvim') || 199 | \ (!isdirectory('/proc') && executable('sw_vers'))) 200 | let s:is_unix = has('unix') 201 | 202 | function! s:is_windows() abort 203 | return s:is_windows 204 | endfunction 205 | 206 | function! s:is_cygwin() abort 207 | return s:is_cygwin 208 | endfunction 209 | 210 | function! s:is_mac() abort 211 | return s:is_mac 212 | endfunction 213 | 214 | function! s:is_unix() abort 215 | return s:is_unix 216 | endfunction 217 | 218 | function! s:_warn_deprecated(name, alternative) abort 219 | try 220 | echohl Error 221 | echomsg "Prelude." . a:name . " is deprecated! Please use " . a:alternative . " instead." 222 | finally 223 | echohl None 224 | endtry 225 | endfunction 226 | 227 | function! s:smart_execute_command(action, word) abort 228 | execute a:action . ' ' . (a:word == '' ? '' : '`=a:word`') 229 | endfunction 230 | 231 | function! s:escape_file_searching(buffer_name) abort 232 | return escape(a:buffer_name, '*[]?{}, ') 233 | endfunction 234 | 235 | function! s:escape_pattern(str) abort 236 | return escape(a:str, '~"\.^$[]*') 237 | endfunction 238 | 239 | function! s:getchar(...) abort 240 | let c = call('getchar', a:000) 241 | return type(c) == type(0) ? nr2char(c) : c 242 | endfunction 243 | 244 | function! s:getchar_safe(...) abort 245 | let c = s:input_helper('getchar', a:000) 246 | return type(c) == type("") ? c : nr2char(c) 247 | endfunction 248 | 249 | function! s:input_safe(...) abort 250 | return s:input_helper('input', a:000) 251 | endfunction 252 | 253 | function! s:input_helper(funcname, args) abort 254 | let success = 0 255 | if inputsave() !=# success 256 | throw 'inputsave() failed' 257 | endif 258 | try 259 | return call(a:funcname, a:args) 260 | finally 261 | if inputrestore() !=# success 262 | throw 'inputrestore() failed' 263 | endif 264 | endtry 265 | endfunction 266 | 267 | function! s:set_default(var, val) abort 268 | if !exists(a:var) || type({a:var}) != type(a:val) 269 | let {a:var} = a:val 270 | endif 271 | endfunction 272 | 273 | function! s:substitute_path_separator(path) abort 274 | return s:is_windows ? substitute(a:path, '\\', '/', 'g') : a:path 275 | endfunction 276 | 277 | function! s:path2directory(path) abort 278 | return s:substitute_path_separator(isdirectory(a:path) ? a:path : fnamemodify(a:path, ':p:h')) 279 | endfunction 280 | 281 | function! s:_path2project_directory_git(path) abort 282 | let parent = a:path 283 | 284 | while 1 285 | let path = parent . '/.git' 286 | if isdirectory(path) || filereadable(path) 287 | return parent 288 | endif 289 | let next = fnamemodify(parent, ':h') 290 | if next == parent 291 | return '' 292 | endif 293 | let parent = next 294 | endwhile 295 | endfunction 296 | 297 | function! s:_path2project_directory_svn(path) abort 298 | let search_directory = a:path 299 | let directory = '' 300 | 301 | let find_directory = s:escape_file_searching(search_directory) 302 | let d = finddir('.svn', find_directory . ';') 303 | if d == '' 304 | return '' 305 | endif 306 | 307 | let directory = fnamemodify(d, ':p:h:h') 308 | 309 | " Search parent directories. 310 | let parent_directory = s:path2directory( 311 | \ fnamemodify(directory, ':h')) 312 | 313 | if parent_directory != '' 314 | let d = finddir('.svn', parent_directory . ';') 315 | if d != '' 316 | let directory = s:_path2project_directory_svn(parent_directory) 317 | endif 318 | endif 319 | return directory 320 | endfunction 321 | 322 | function! s:_path2project_directory_others(vcs, path) abort 323 | let vcs = a:vcs 324 | let search_directory = a:path 325 | 326 | let find_directory = s:escape_file_searching(search_directory) 327 | let d = finddir(vcs, find_directory . ';') 328 | if d == '' 329 | return '' 330 | endif 331 | return fnamemodify(d, ':p:h:h') 332 | endfunction 333 | 334 | function! s:path2project_directory(path, ...) abort 335 | let is_allow_empty = get(a:000, 0, 0) 336 | let search_directory = s:path2directory(a:path) 337 | let directory = '' 338 | 339 | " Search VCS directory. 340 | for vcs in ['.git', '.bzr', '.hg', '.svn'] 341 | if vcs ==# '.git' 342 | let directory = s:_path2project_directory_git(search_directory) 343 | elseif vcs ==# '.svn' 344 | let directory = s:_path2project_directory_svn(search_directory) 345 | else 346 | let directory = s:_path2project_directory_others(vcs, search_directory) 347 | endif 348 | if directory != '' 349 | break 350 | endif 351 | endfor 352 | 353 | " Search project file. 354 | if directory == '' 355 | for d in ['build.xml', 'prj.el', '.project', 'pom.xml', 'package.json', 356 | \ 'Makefile', 'configure', 'Rakefile', 'NAnt.build', 357 | \ 'P4CONFIG', 'tags', 'gtags'] 358 | let d = findfile(d, s:escape_file_searching(search_directory) . ';') 359 | if d != '' 360 | let directory = fnamemodify(d, ':p:h') 361 | break 362 | endif 363 | endfor 364 | endif 365 | 366 | if directory == '' 367 | " Search /src/ directory. 368 | let base = s:substitute_path_separator(search_directory) 369 | if base =~# '/src/' 370 | let directory = base[: strridx(base, '/src/') + 3] 371 | endif 372 | endif 373 | 374 | if directory == '' && !is_allow_empty 375 | " Use original path. 376 | let directory = search_directory 377 | endif 378 | 379 | return s:substitute_path_separator(directory) 380 | endfunction 381 | 382 | let &cpo = s:save_cpo 383 | unlet s:save_cpo 384 | 385 | " vim:set et ts=2 sts=2 sw=2 tw=0: 386 | -------------------------------------------------------------------------------- /autoload/vital/_vim_pyenv/Process.vim: -------------------------------------------------------------------------------- 1 | " TODO: move all comments to doc file. 2 | " 3 | " 4 | " FIXME: This module name should be Vital.System ? 5 | " But the name has been already taken. 6 | 7 | let s:save_cpo = &cpo 8 | set cpo&vim 9 | 10 | 11 | " FIXME: Unfortunately, can't use s:_vital_loaded() for this purpose. 12 | " Because these variables are used when this script file is loaded. 13 | let s:is_windows = has('win16') || has('win32') || has('win64') || has('win95') 14 | let s:is_unix = has('unix') 15 | " As of 7.4.122, the system()'s 1st argument is converted internally by Vim. 16 | " Note that Patch 7.4.122 does not convert system()'s 2nd argument and 17 | " return-value. We must convert them manually. 18 | let s:need_trans = v:version < 704 || (v:version == 704 && !has('patch122')) 19 | 20 | let s:TYPE_DICT = type({}) 21 | let s:TYPE_LIST = type([]) 22 | let s:TYPE_STRING = type("") 23 | 24 | 25 | " Execute program in the background from Vim. 26 | " Return an empty string always. 27 | " 28 | " If a:expr is a List, shellescape() each argument. 29 | " If a:expr is a String, the arguments are passed as-is. 30 | " 31 | " Windows: 32 | " Using :!start , execute program without via cmd.exe. 33 | " Spawning 'expr' with 'noshellslash' 34 | " keep special characters from unwanted expansion. 35 | " (see :help shellescape()) 36 | " 37 | " Unix: 38 | " using :! , execute program in the background by shell. 39 | function! s:spawn(expr, ...) abort 40 | let shellslash = 0 41 | if s:is_windows 42 | let shellslash = &l:shellslash 43 | setlocal noshellslash 44 | endif 45 | try 46 | if type(a:expr) is s:TYPE_LIST 47 | let special = 1 48 | let cmdline = join(map(a:expr, 'shellescape(v:val, special)'), ' ') 49 | elseif type(a:expr) is s:TYPE_STRING 50 | let cmdline = a:expr 51 | if a:0 && a:1 52 | " for :! command 53 | let cmdline = substitute(cmdline, '\([!%#]\|<[^<>]\+>\)', '\\\1', 'g') 54 | endif 55 | else 56 | throw 'Process.spawn(): invalid argument (value type:'.type(a:expr).')' 57 | endif 58 | if s:is_windows 59 | silent execute '!start' cmdline 60 | else 61 | silent execute '!' cmdline '&' 62 | endif 63 | finally 64 | if s:is_windows 65 | let &l:shellslash = shellslash 66 | endif 67 | endtry 68 | return '' 69 | endfunction 70 | 71 | " iconv() wrapper for safety. 72 | function! s:iconv(expr, from, to) abort 73 | if a:from == '' || a:to == '' || a:from ==? a:to 74 | return a:expr 75 | endif 76 | let result = iconv(a:expr, a:from, a:to) 77 | return result != '' ? result : a:expr 78 | endfunction 79 | 80 | " Check vimproc. 81 | function! s:has_vimproc() abort 82 | if !exists('s:exists_vimproc') 83 | try 84 | call vimproc#version() 85 | let s:exists_vimproc = 1 86 | catch 87 | let s:exists_vimproc = 0 88 | endtry 89 | endif 90 | return s:exists_vimproc 91 | endfunction 92 | 93 | " * {command} [, {input} [, {timeout}]] 94 | " * {command} [, {dict}] 95 | " {dict} = { 96 | " use_vimproc: bool, 97 | " input: string, 98 | " timeout: bool, 99 | " background: bool, 100 | " } 101 | function! s:system(str, ...) abort 102 | " Process optional arguments at first 103 | " because use_vimproc is required later 104 | " for a:str argument. 105 | let input = '' 106 | let use_vimproc = s:has_vimproc() 107 | let background = 0 108 | let args = [] 109 | if a:0 ==# 1 110 | " {command} [, {dict}] 111 | " a:1 = {dict} 112 | if type(a:1) is s:TYPE_DICT 113 | if has_key(a:1, 'use_vimproc') 114 | let use_vimproc = a:1.use_vimproc 115 | endif 116 | if has_key(a:1, 'input') 117 | let args += [s:iconv(a:1.input, &encoding, 'char')] 118 | endif 119 | if use_vimproc && has_key(a:1, 'timeout') 120 | " ignores timeout unless you have vimproc. 121 | let args += [a:1.timeout] 122 | endif 123 | if has_key(a:1, 'background') 124 | let background = a:1.background 125 | endif 126 | elseif type(a:1) is s:TYPE_STRING 127 | let args += [s:iconv(a:1, &encoding, 'char')] 128 | else 129 | throw 'Process.system(): invalid argument (value type:'.type(a:1).')' 130 | endif 131 | elseif a:0 >= 2 132 | " {command} [, {input} [, {timeout}]] 133 | " a:000 = [{input} [, {timeout}]] 134 | let [input; rest] = a:000 135 | let input = s:iconv(input, &encoding, 'char') 136 | let args += [input] + rest 137 | endif 138 | 139 | " Process a:str argument. 140 | if type(a:str) is s:TYPE_LIST 141 | let expr = use_vimproc ? '"''" . v:val . "''"' : 's:shellescape(v:val)' 142 | let command = join(map(copy(a:str), expr), ' ') 143 | elseif type(a:str) is s:TYPE_STRING 144 | let command = a:str 145 | else 146 | throw 'Process.system(): invalid argument (value type:'.type(a:str).')' 147 | endif 148 | if s:need_trans 149 | let command = s:iconv(command, &encoding, 'char') 150 | endif 151 | let args = [command] + args 152 | if background && (use_vimproc || !s:is_windows) 153 | let args[0] = args[0] . ' &' 154 | endif 155 | 156 | let funcname = use_vimproc ? 'vimproc#system' : 'system' 157 | let output = call(funcname, args) 158 | let output = s:iconv(output, 'char', &encoding) 159 | return output 160 | endfunction 161 | 162 | function! s:get_last_status() abort 163 | return s:has_vimproc() ? 164 | \ vimproc#get_last_status() : v:shell_error 165 | endfunction 166 | 167 | if s:is_windows 168 | function! s:shellescape(command) abort 169 | return substitute(a:command, '[&()[\]{}^=;!''+,`~]', '^\0', 'g') 170 | endfunction 171 | else 172 | function! s:shellescape(...) abort 173 | return call('shellescape', a:000) 174 | endfunction 175 | endif 176 | 177 | 178 | let &cpo = s:save_cpo 179 | unlet s:save_cpo 180 | 181 | " vim:set et ts=2 sts=2 sw=2 tw=0: 182 | -------------------------------------------------------------------------------- /autoload/vital/_vim_pyenv/System/Cache/Base.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | function! s:_vital_loaded(V) dict abort 5 | let s:Prelude = a:V.import('Prelude') 6 | endfunction 7 | function! s:_vital_depends() abort 8 | return ['Prelude'] 9 | endfunction 10 | 11 | let s:cache = { 12 | \ '__name__': 'base', 13 | \} 14 | function! s:new(...) abort 15 | return deepcopy(s:cache) 16 | endfunction 17 | function! s:cache.cache_key(obj) abort 18 | let cache_key = s:Prelude.is_string(a:obj) ? a:obj : string(a:obj) 19 | return cache_key 20 | endfunction 21 | function! s:cache.has(name) abort 22 | throw "vital: System.Cache.Base: has({name}) is not implemented" 23 | endfunction 24 | function! s:cache.get(name, ...) abort 25 | throw "vital: System.Cache.Base: get({name}[, {default}]) is not implemented" 26 | endfunction 27 | function! s:cache.set(name, value) abort 28 | throw "vital: System.Cache.Base: set({name}, {value}[, {default}]) is not implemented" 29 | endfunction 30 | function! s:cache.keys() abort 31 | throw "vital: System.Cache.Base: keys() is not implemented" 32 | endfunction 33 | function! s:cache.remove(name) abort 34 | throw "vital: System.Cache.Base: remove({name}) is not implemented" 35 | endfunction 36 | function! s:cache.clear() abort 37 | throw "vital: System.Cache.Base: clear() is not implemented" 38 | endfunction 39 | 40 | let &cpo = s:save_cpo 41 | unlet s:save_cpo 42 | "vim: sts=2 sw=2 smarttab et ai textwidth=0 fdm=marker 43 | -------------------------------------------------------------------------------- /autoload/vital/_vim_pyenv/System/Cache/Memory.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | function! s:_vital_loaded(V) dict abort 5 | let s:Base = a:V.import('System.Cache.Base') 6 | endfunction 7 | function! s:_vital_depends() abort 8 | return ['System.Cache.Base'] 9 | endfunction 10 | 11 | let s:cache = { 12 | \ '_cached': {}, 13 | \ '__name__': 'memory', 14 | \} 15 | function! s:new(...) abort 16 | return extend( 17 | \ call(s:Base.new, a:000, s:Base), 18 | \ deepcopy(s:cache) 19 | \) 20 | endfunction 21 | 22 | function! s:cache.has(name) abort 23 | let cache_key = self.cache_key(a:name) 24 | return has_key(self._cached, cache_key) 25 | endfunction 26 | function! s:cache.get(name, ...) abort 27 | let default = get(a:000, 0, '') 28 | let cache_key = self.cache_key(a:name) 29 | if has_key(self._cached, cache_key) 30 | return self._cached[cache_key] 31 | else 32 | return default 33 | endif 34 | endfunction 35 | function! s:cache.set(name, value) abort 36 | let cache_key = self.cache_key(a:name) 37 | let self._cached[cache_key] = a:value 38 | endfunction 39 | function! s:cache.remove(name) abort 40 | let cache_key = self.cache_key(a:name) 41 | if has_key(self._cached, cache_key) 42 | unlet self._cached[cache_key] 43 | endif 44 | endfunction 45 | function! s:cache.keys() abort 46 | return keys(self._cached) 47 | endfunction 48 | function! s:cache.clear() abort 49 | let self._cached = {} 50 | endfunction 51 | 52 | let &cpo = s:save_cpo 53 | unlet s:save_cpo 54 | "vim: sts=2 sw=2 smarttab et ai textwidth=0 fdm=marker 55 | -------------------------------------------------------------------------------- /autoload/vital/_vim_pyenv/System/Filepath.vim: -------------------------------------------------------------------------------- 1 | " You should check the following related builtin functions. 2 | " fnamemodify() 3 | " resolve() 4 | " simplify() 5 | 6 | let s:save_cpo = &cpo 7 | set cpo&vim 8 | 9 | let s:path_sep_pattern = (exists('+shellslash') ? '[\\/]' : '/') . '\+' 10 | let s:is_windows = has('win16') || has('win32') || has('win64') || has('win95') 11 | let s:is_cygwin = has('win32unix') 12 | let s:is_mac = !s:is_windows && !s:is_cygwin 13 | \ && (has('mac') || has('macunix') || has('gui_macvim') || 14 | \ (!isdirectory('/proc') && executable('sw_vers'))) 15 | 16 | " Get the directory separator. 17 | function! s:separator() abort 18 | return fnamemodify('.', ':p')[-1 :] 19 | endfunction 20 | 21 | " Get the path separator. 22 | let s:path_separator = s:is_windows ? ';' : ':' 23 | function! s:path_separator() abort 24 | return s:path_separator 25 | endfunction 26 | 27 | " Get the path extensions 28 | function! s:path_extensions() abort 29 | if !exists('s:path_extensions') 30 | if s:is_windows 31 | if exists('$PATHEXT') 32 | let pathext = $PATHEXT 33 | else 34 | " get default PATHEXT 35 | let pathext = matchstr(system('set pathext'), '^pathext=\zs.*\ze\n', 'i') 36 | endif 37 | let s:path_extensions = map(split(pathext, s:path_separator), 'tolower(v:val)') 38 | elseif s:is_cygwin 39 | " cygwin is not use $PATHEXT 40 | let s:path_extensions = ['', '.exe'] 41 | else 42 | let s:path_extensions = [''] 43 | endif 44 | endif 45 | return s:path_extensions 46 | endfunction 47 | 48 | " Convert all directory separators to "/". 49 | function! s:unify_separator(path) abort 50 | return substitute(a:path, s:path_sep_pattern, '/', 'g') 51 | endfunction 52 | 53 | " Get the full path of command. 54 | if exists('*exepath') 55 | function! s:which(str) abort 56 | return exepath(a:str) 57 | endfunction 58 | else 59 | function! s:which(command, ...) abort 60 | let pathlist = a:command =~# s:path_sep_pattern ? [''] : 61 | \ !a:0 ? split($PATH, s:path_separator) : 62 | \ type(a:1) == type([]) ? copy(a:1) : 63 | \ split(a:1, s:path_separator) 64 | 65 | let pathext = s:path_extensions() 66 | if index(pathext, '.' . tolower(fnamemodify(a:command, ':e'))) != -1 67 | let pathext = [''] 68 | endif 69 | 70 | let dirsep = s:separator() 71 | for dir in pathlist 72 | let head = dir ==# '' ? '' : dir . dirsep 73 | for ext in pathext 74 | let full = fnamemodify(head . a:command . ext, ':p') 75 | if filereadable(full) 76 | if s:is_case_tolerant() 77 | let full = glob(substitute( 78 | \ toupper(full), '\u:\@!', '[\0\L\0]', 'g'), 1) 79 | endif 80 | if full != '' 81 | return full 82 | endif 83 | endif 84 | endfor 85 | endfor 86 | 87 | return '' 88 | endfunction 89 | endif 90 | 91 | " Split the path with directory separator. 92 | " Note that this includes the drive letter of MS Windows. 93 | function! s:split(path) abort 94 | return split(a:path, s:path_sep_pattern) 95 | endfunction 96 | 97 | " Join the paths. 98 | " join('foo', 'bar') => 'foo/bar' 99 | " join('foo/', 'bar') => 'foo/bar' 100 | " join('/foo/', ['bar', 'buz/']) => '/foo/bar/buz/' 101 | function! s:join(...) abort 102 | let sep = s:separator() 103 | let path = '' 104 | for part in a:000 105 | let path .= sep . 106 | \ (type(part) is type([]) ? call('s:join', part) : 107 | \ part) 108 | unlet part 109 | endfor 110 | return substitute(path[1 :], s:path_sep_pattern, sep, 'g') 111 | endfunction 112 | 113 | " Check if the path is absolute path. 114 | if s:is_windows 115 | function! s:is_absolute(path) abort 116 | return a:path =~? '^[a-z]:[/\\]' 117 | endfunction 118 | else 119 | function! s:is_absolute(path) abort 120 | return a:path[0] ==# '/' 121 | endfunction 122 | endif 123 | 124 | function! s:is_relative(path) abort 125 | return !s:is_absolute(a:path) 126 | endfunction 127 | 128 | " Return the parent directory of the path. 129 | " NOTE: fnamemodify(path, ':h') does not return the parent directory 130 | " when path[-1] is the separator. 131 | function! s:dirname(path) abort 132 | let path = a:path 133 | let orig = a:path 134 | 135 | let path = s:remove_last_separator(path) 136 | if path == '' 137 | return orig " root directory 138 | endif 139 | 140 | let path = fnamemodify(path, ':h') 141 | return path 142 | endfunction 143 | 144 | " Return the basename of the path. 145 | " NOTE: fnamemodify(path, ':h') does not return basename 146 | " when path[-1] is the separator. 147 | function! s:basename(path) abort 148 | let path = a:path 149 | let orig = a:path 150 | 151 | let path = s:remove_last_separator(path) 152 | if path == '' 153 | return orig " root directory 154 | endif 155 | 156 | let path = fnamemodify(path, ':t') 157 | return path 158 | endfunction 159 | 160 | " Remove the separator at the end of a:path. 161 | function! s:remove_last_separator(path) abort 162 | let sep = s:separator() 163 | let pat = (sep == '\' ? '\\' : '/') . '\+$' 164 | return substitute(a:path, pat, '', '') 165 | endfunction 166 | 167 | 168 | " Return true if filesystem ignores alphabetic case of a filename. 169 | " Return false otherwise. 170 | let s:is_case_tolerant = filereadable(expand(':r') . '.VIM') 171 | function! s:is_case_tolerant() abort 172 | return s:is_case_tolerant 173 | endfunction 174 | 175 | 176 | let &cpo = s:save_cpo 177 | unlet s:save_cpo 178 | 179 | " vim:set et ts=2 sts=2 sw=2 tw=0: 180 | -------------------------------------------------------------------------------- /autoload/vital/vim_pyenv.vital: -------------------------------------------------------------------------------- 1 | vim_pyenv 2 | 386a15e 3 | 4 | System.Filepath 5 | System.Cache.Memory 6 | Process 7 | Prelude 8 | -------------------------------------------------------------------------------- /doc/vim-pyenv.txt: -------------------------------------------------------------------------------- 1 | *vim-pyenv.txt* Activate a pyenv Python within Vim 2 | 3 | Version: 2.0 4 | Author: Alisue *vim-pyenv-author* 5 | License: MIT license {{{ 6 | Copyright (c) 2014 Alisue, hashnote.net 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | THE SOFTWARE. 25 | }}} 26 | 27 | 28 | CONTENTS *vim-pyenv-contents* 29 | 30 | Introduction |vim-pyenv-introduction| 31 | Usage |vim-pyenv-usage| 32 | Requirements |vim-pyenv-requirements| 33 | Interface |vim-pyenv-interface| 34 | Commands |vim-pyenv-commands| 35 | Functions |vim-pyenv-functions| 36 | Configurations |vim-pyenv-configurations| 37 | Autocmd |vim-pyenv-autocmd| 38 | FAQ |vim-pyenv-faq| 39 | 40 | 41 | =============================================================================== 42 | INTRODUCTION *vim-pyenv-introduction* 43 | 44 | *vim-pyenv* allows you to activate and deactivate the pyenv Python correctly 45 | in a live Vim session. 46 | 47 | pyenv (https://github.com/yyuu/pyenv) is a simple Python version management 48 | system and users can change the Python versions in a simple way. 49 | However, if you use pyenv to switch the Python version or virtualenv, the 50 | omni-completion would not work correctly. 51 | This is because Vim refers to the system Python and does not know anything 52 | about the pyenv Python, especially the packages you installed on the pyenv 53 | Python. 54 | 55 | vim-pyenv activates the pyenv Python and adds the external Python library 56 | search path (PYTHONPATH) to Vim's internal Python PYTHONPATH. 57 | Thus, with vim-pyenv, your jedi-vim(https://github.com/davidhalter/jedi-vim) 58 | or any kind of Python omni-completion system returns a correct completion list. 59 | 60 | Additionally, vim-pyenv supports Vim's dual Python 2 and 3 system. 61 | If your Vim is compiled with +python and +python3, vim-pyenv automatically 62 | synchronizes the Python version to the external Python version. 63 | 64 | 65 | =============================================================================== 66 | USAGE *vim-pyenv-usage* 67 | 68 | Assuming that you have three pyenv-virtualenv environments (simply called 69 | virtualenvs) and you are now in one of them, called A. 70 | If you open Vim from a terminal, vim-pyenv automatically detects the 71 | current virtualenv and activates it in the Vim session. 72 | 73 | If you want to change the virtualenv from A to B then do: 74 | > 75 | :PyenvActivate B 76 | < 77 | To deactivate the virtualenv: 78 | > 79 | :PyenvDeactivate 80 | < 81 | 82 | If your Vim is compiled with +python and +python3, the internal Python version 83 | is automatically synchronized to the external Python version. 84 | 85 | 86 | =============================================================================== 87 | Requirements *vim-pyenv-requirements* 88 | 89 | Requirements: 90 | * Vim compiled with +python and/or +python3 91 | * pyenv command in your terminal 92 | 93 | Recommended: 94 | * jedi-vim for omni-completion 95 | 96 | =============================================================================== 97 | INTERFACE *vim-pyenv-interface* 98 | 99 | ------------------------------------------------------------------------------- 100 | COMMANDS *vim-pyenv-commands* 101 | 102 | 103 | :PyenvActivate [{name}] *:PyenvActivate* 104 | Activate a pyenv Python. The name of the pyenv Python can be completed 105 | with at the command line. 106 | 107 | If the name is not specified, the name will be guessed based on pyenv's 108 | current settings. 109 | 110 | :PyenvDeactivate *:PyenvDeactivate* 111 | Deactivate the current pyenv Python. 112 | 113 | :PyenvCreateCtags *:PyenvCreateCtags* 114 | Create 'ctags' of current activated pyenv in $(pyenv prefix)/ctags. 115 | It requires |g:pyenv#ctags_exec| to be correctly specified. 116 | 117 | :PyenvAssignCtags *:PyenvAssignCtags* 118 | Assign 'ctags' of current activated pyenv at $(pyenv prefix)/ctags to 119 | |tags-option| if the file is not listed in |&l:tags|. 120 | 121 | :PyenvWithdrawCtags *:PyenvWithdrawCtags* 122 | Withdraw 'ctags' of current activated pyenv at $(pyenv prefix)/ctags from 123 | |tags-option| if the file is listed in |&l:tags|. 124 | 125 | 126 | ------------------------------------------------------------------------------- 127 | FUNCTIONS *vim-pyenv-functions* 128 | 129 | pyenv#info#format({format}) *pyenv#info#format()* 130 | 131 | Return a current pyenv status in a specified {format}. The following 132 | format strings are available to use in the {format}. 133 | 134 | 'iv' A version of the internal python 135 | 'im' A major version of the internal python 136 | 'ev' A version of the external python 137 | 'em' A major version of the external python 138 | 'sv' A selected version name 139 | 'ss' A selected version names 140 | 'av' An activated version name 141 | 142 | And the following rules are applied to the {format}. 143 | 144 | 1. If a format string is leaded by %, the '%' and the format string 145 | will be translated into a corresponding informations. 146 | E.g: '%iv' -> '2.7.9' or '' 147 | 2. If a format string is leaded by %{left|}, the '%{left|}' and the 148 | format string will be translated into a corresponding informations 149 | and 'left' will be inserted at left side of the translation if the 150 | translation is not an empty string. 151 | E.g: '%{#}iv' -> '#2.7.9' or '' 152 | 3. If a format string is leaded by %{|right}, the '%{|right}' and the 153 | format string will be translated into a corresponding informations 154 | and 'right' will be inserted at right side of the translation if the 155 | translation is not an empty string. 156 | E.g: '%{|$}iv' -> '2.7.9$' or '' 157 | 4. If a format string is leaded by %{left|right}, the '%{left|right}' 158 | and the format string will be translated into a corresponding 159 | informations and 'left' and 'right' will be inserted at left and 160 | right side of the translation respectively if the translation is not 161 | an empty string. 162 | E.g: '%{#|$}iv' -> '#2.7.9$' or '' 163 | 164 | pyenv#info#preset({name}) *pyenv#info#preset()* 165 | 166 | Return a formatted string of following presets, specified by {name}. 167 | 168 | 'long' 169 | Show an activated version name and a version of the internal python 170 | E.g.: #system (2.7.9) 171 | 172 | 'short' 173 | Show an activated version name 174 | E.g.: #system 175 | 176 | 177 | ------------------------------------------------------------------------------- 178 | CONFIGURATION *vim-pyenv-configuration* 179 | 180 | g:pyenv#auto_activate *g:pyenv#auto_activate* 181 | 182 | If it is 1, vim-pyenv automatically activates the current pyenv Python 183 | when vim-pyenv is loaded. 184 | Default to 1. 185 | 186 | g:pyenv#pyenv_exec *g:pyenv#pyenv_exec* 187 | 188 | The path of pyenv executable. 189 | 190 | g:pyenv#python_exec *g:pyenv#python_exec* 191 | 192 | The path of Python executable. 193 | 194 | g:pyenv#ctags_exec *g:pyenv#ctags_exec* 195 | 196 | The path of ctags executable. 197 | 198 | g:pyenv#auto_create_ctags *g:pyenv#auto_create_ctags* 199 | 200 | If it is 1, vim-pyenv automatically call |:PyenvCreateCtags| everytime 201 | when user activate. It is very slow. 202 | Default to 0. 203 | 204 | g:pyenv#auto_assign_ctags *g:pyenv#auto_assign_ctags* 205 | 206 | If it is 1, vim-pyenv automatically assign/withdraw tags everytime 207 | when user activate. 208 | Default to 1. 209 | 210 | 211 | ------------------------------------------------------------------------------- 212 | AUTOCMD *vim-pyenv-autocmd* 213 | 214 | vim-pyenv-activate-post *vim-pyenv-activate-post* 215 | 216 | Called after activation 217 | 218 | vim-pyenv-deactivate-post *vim-pyenv-deactivate-post* 219 | 220 | Called after deactivation 221 | 222 | =============================================================================== 223 | FAQ *vim-pyenv-faq* 224 | 225 | Q. It say '"pyenv" is not found in $PATH' but I can use it in my terminal. 226 | 227 | A. Make sure that correct path is existing in $PATH of Vim. You may need to 228 | add a corresponding path manually like 229 | > 230 | let sep = has('win32') || has('win64') ? ';' : ':' 231 | let $PATH = join([ 232 | \ expand('~/.pyenv/bin'), 233 | \ $PATH, 234 | \], sep) 235 | < 236 | Or specify an absolute path to |g:pyenv#pyenv_exec|. 237 | 238 | 239 | Q. I would like to switch between python and python3 even in jedi-vim 240 | 241 | A. To do that, your vim required to be compiled with +python/+python3 so first 242 | make sure that your vim has both python interpreter. 243 | Then you can switch a major version of python of jedi with the following code 244 | > 245 | function! s:jedi_auto_force_py_version() abort 246 | let major_version = pyenv#python#get_internal_major_version() 247 | call jedi#force_py_version(major_version) 248 | endfunction 249 | augroup vim-pyenv-custom-augroup 250 | autocmd! * 251 | autocmd User vim-pyenv-activate-post call s:jedi_auto_force_py_version() 252 | autocmd User vim-pyenv-deactivate-post call s:jedi_auto_force_py_version() 253 | augroup END 254 | < 255 | vim:tw=78:fo=tcq2mM:ts=8:ft=help:norl 256 | -------------------------------------------------------------------------------- /initialize.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | import vim 3 | import os 4 | import sys 5 | 6 | # update the sys path to include the pyenv_vim script 7 | repository_root = vim.eval("expand(s:repository_root)") 8 | if repository_root not in sys.path: 9 | sys.path.insert(0, repository_root) 10 | 11 | # import pyenv_vim so the vimscript can use it 12 | import pyenv_vim 13 | -------------------------------------------------------------------------------- /plugin/pyenv.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | 5 | command! -bar -nargs=? -complete=customlist,s:PyenvActivateComplete 6 | \ PyenvActivate :call pyenv#activate() 7 | command! -bar PyenvDeactivate :call pyenv#deactivate() 8 | command! -bar PyenvCreateCtags :call pyenv#pyenv#create_ctags() 9 | command! -bar PyenvAssignCtags :call pyenv#pyenv#assign_ctags() 10 | command! -bar PyenvWithdrawCtags :call pyenv#pyenv#withdraw_ctags() 11 | 12 | 13 | function! s:PyenvActivateComplete(arglead, cmdline, cursorpos) abort " {{{ 14 | let candidates = pyenv#pyenv#get_available_envs() 15 | let prefix = get(split(a:arglead, ','), -1, '') 16 | return filter(candidates, 'v:val =~# "^" . prefix') 17 | endfunction " }}} 18 | 19 | 20 | " Automatically activate 21 | if get(g:, 'pyenv#auto_activate', 1) 22 | if has('vim_starting') 23 | augroup vim-pyenv-vim-start 24 | autocmd! * 25 | autocmd VimEnter * call pyenv#activate('', {'quiet': 1}) 26 | augroup END 27 | else 28 | call pyenv#activate('', {'quiet': 1}) 29 | endif 30 | endif 31 | 32 | let &cpo = s:save_cpo 33 | "vim: foldlevel=0 sts=2 sw=2 smarttab et ai textwidth=0 fdm=marker 34 | -------------------------------------------------------------------------------- /pyenv_vim.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | import vim 3 | import sys 4 | import subprocess 5 | 6 | 7 | # None in Python 2 and Python 3 is a bit different. 8 | # The variable which set as `None` in python 2 would be 9 | # detected as an object which is not None in python 3. 10 | # Thus None like object is required for compatibility. 11 | NONE = 0 12 | 13 | 14 | # The original sys.path 15 | _original_sys_path = NONE 16 | 17 | 18 | def py_version(): 19 | """ 20 | Return the version of the executing python to the Vim 21 | The vimscript can get the value from a `return_value` variable. 22 | """ 23 | py_version = sys.version.split()[0] 24 | vim.command('let return_value = "{}"'.format(py_version)) 25 | 26 | 27 | def get_external_sys_path(python_exec=None): 28 | """ 29 | Get the sys.path value of the external python (system python) 30 | """ 31 | python_exec = python_exec or 'python' 32 | # execute the external python and get the sys.path value 33 | args = [python_exec, '-c', 'import sys; print("\\n".join(sys.path))'] 34 | p = subprocess.Popen(args, stdout=subprocess.PIPE) 35 | stdout, stderr = p.communicate() 36 | return stdout.splitlines() 37 | 38 | 39 | def activate(python_exec=None): 40 | """ 41 | Update the executing python's sys.path with the external python's sys.path 42 | """ 43 | global _original_sys_path 44 | # get current external python's sys.path 45 | external_sys_path = get_external_sys_path(python_exec) 46 | # convert it into string (it required in python3) 47 | if sys.version_info >= (3, 0): 48 | external_sys_path = [x.decode('utf-8') for x in external_sys_path] 49 | # save original sys.path 50 | if _original_sys_path == NONE: 51 | _original_sys_path = sys.path[:] 52 | # update sys.path with the origianl sys.path and external sys.path 53 | sys.path[:] = _original_sys_path 54 | for path in reversed(external_sys_path): 55 | # if the path is already specified in original sys.path 56 | # remove and insert to re-order the appearance 57 | if path in sys.path: 58 | sys.path.remove(path) 59 | sys.path.insert(0, path) 60 | 61 | 62 | def deactivate(): 63 | """ 64 | Restore the executing python's sys.path 65 | """ 66 | global _original_sys_path 67 | # restore original sys path if the original is stored 68 | if _original_sys_path != NONE: 69 | sys.path[:] = _original_sys_path 70 | _original_sys_path = NONE 71 | -------------------------------------------------------------------------------- /statics/_screenshot01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambdalisue/vim-pyenv/ce9e88535e8625da85cc6b113d2920f3230996cc/statics/_screenshot01.png -------------------------------------------------------------------------------- /statics/_screenshot02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambdalisue/vim-pyenv/ce9e88535e8625da85cc6b113d2920f3230996cc/statics/_screenshot02.png --------------------------------------------------------------------------------