├── .coveragerc ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE.md └── workflows │ └── ci.yml ├── .gitignore ├── .gitmodules ├── .travis.yml ├── AUTHORS.txt ├── CONTRIBUTING.md ├── LICENSE.txt ├── Makefile ├── README.rst ├── after ├── ftplugin │ └── python │ │ └── jedi.vim └── syntax │ └── python.vim ├── autoload ├── health │ └── jedi.vim └── jedi.vim ├── codecov.yml ├── doc ├── jedi-vim.txt └── logotype-a.svg ├── ftplugin └── python │ └── jedi.vim ├── plugin └── jedi.vim ├── pythonx ├── jedi_vim.py └── jedi_vim_debug.py ├── setup.cfg └── test ├── _utils.vim ├── test_integration.py ├── vimrc └── vspec ├── choose-venv.vim ├── completions.vim ├── completions_disabled.vim ├── documentation.vim ├── goto.vim ├── jedi_debug_info.vim ├── pyimport.vim └── signatures.vim /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | branch = 1 3 | # Used by/for neovim-python-client. 4 | concurrency = greenlet 5 | 6 | [report] 7 | include = pythonx/jedi_*.py,test/* 8 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [davidhalter] 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Issue 2 | 3 | 9 | 10 | ### Steps to reproduce 11 | 12 | 37 | 38 | ### Output of “:verbose JediDebugInfo” 39 | 40 | 45 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | on: [push, pull_request] 3 | 4 | jobs: 5 | tests: 6 | runs-on: ubuntu-20.04 7 | steps: 8 | - name: Checkout code 9 | uses: actions/checkout@v4 10 | with: 11 | submodules: recursive 12 | 13 | - name: Setup 14 | run: | 15 | sudo pip install pytest 16 | vim --version 17 | 18 | #- name: Setup tmate session 19 | # uses: mxschmitt/action-tmate@v3 20 | 21 | - name: Run tests 22 | run: 'make test' 23 | 24 | code-quality: 25 | runs-on: ubuntu-20.04 26 | steps: 27 | - name: Checkout code 28 | uses: actions/checkout@v4 29 | with: 30 | submodules: recursive 31 | 32 | - name: Run tests 33 | run: | 34 | vim --version 35 | make check 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.sw? 3 | *.py[cod] 4 | .ropeproject 5 | doc/tags 6 | .pytest-cache 7 | build 8 | .coverage* 9 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "jedi"] 2 | path = pythonx/jedi 3 | url = https://github.com/davidhalter/jedi.git 4 | [submodule "pythonx/parso"] 5 | path = pythonx/parso 6 | url = https://github.com/davidhalter/parso.git 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: bionic 2 | language: python 3 | python: 3.8 4 | env: 5 | - ENV=test 6 | - ENV=check 7 | - ENV=test_coverage 8 | install: 9 | - | 10 | if [ "$ENV" = "test" ]; then 11 | pip install pytest 12 | elif [ "$ENV" = "test_coverage" ]; then 13 | sudo add-apt-repository ppa:neovim-ppa/stable -y 14 | sudo apt-get update -q 15 | sudo apt-get install neovim -y 16 | 17 | pip install pynvim pytest-cov 18 | pip list 19 | nvim --version 20 | else 21 | vim --version 22 | fi 23 | script: 24 | - make --keep-going "$ENV" BUILD_VIRTUAL_ENV=$VIRTUAL_ENV 25 | 26 | after_script: 27 | - | 28 | if [ "$ENV" = "test_coverage" ]; then 29 | coverage xml 30 | travis_retry bash <(curl -s https://codecov.io/bash) -X fix -f coverage.xml -F py${TRAVIS_PYTHON_VERSION//./} 31 | fi 32 | -------------------------------------------------------------------------------- /AUTHORS.txt: -------------------------------------------------------------------------------- 1 | Main Authors 2 | ============ 3 | 4 | David Halter (@davidhalter) 5 | 6 | 7 | Contributors (in order of contributions) 8 | ======================================== 9 | 10 | Patrice Peterson (@runiq) 11 | tek (@tek) 12 | heavenshell (@heavenshell) 13 | Danilo Bargen (@dbrgn) 14 | mattn (@mattn) 15 | Enrico Batista da Luz (@ricobl) 16 | coot (@coot) 17 | Artur Dryomov (@ming13) 18 | andviro (@andviro) 19 | Jean-Louis Fuchs (@ganwell) 20 | Mathieu Comandon (@strycore) 21 | Nick Hurley (@todesschaf) 22 | gpoulin (@gpoulin) 23 | Akinori Hattori (@hattya) 24 | Luper Rouch (@flupke) 25 | Matthew Moses (@mlmoses) 26 | Tyler Wymer (@twymer) 27 | Artem Nezvigin (@artnez) 28 | rogererens (@rogererens) 29 | Emily Strickland (@emilyst) 30 | Tin Tvrtković (@Tinche) 31 | Zekeriya Koc (@zekzekus) 32 | ethinx (@ethinx) 33 | Wouter Overmeire (@lodagro) 34 | Stephen J. Fuhry (@fuhrysteve) 35 | Sheng Yun (@ShengYun) 36 | Yann Thomas-Gérard (@inside) 37 | Colin Su (@littleq0903) 38 | Arthur Jaron (@eyetracker) 39 | Justin M. Keyes (@justinmk) 40 | nagev (@np1) 41 | Chris Lasher (@gotgenes) 42 | Doan Thanh Nam (@tndoan) 43 | Markus Koller (@toupeira) 44 | Justin Cheevers @justincheevers 45 | Talha Ahmed (@talha81) 46 | Matthew Tylee Atkinson (@matatk) 47 | Pedro Ferrari (@petobens) 48 | Daniel Hahler (@blueyed) 49 | Dave Honneffer (@pearofducks) 50 | Bagrat Aznauryan (@n9code) 51 | Tomoyuki Kashiro (@kashiro) 52 | Tommy Allen (@tweekmonster) 53 | Mingliang (@Aulddays) 54 | Brian Mego (@brianmego) 55 | Stevan Milic (@stevanmilic) 56 | Konstantin Glukhov (@Konstantin-Glukhov) 57 | Seungchan An (@SeungChan92) 58 | Thomas Blauth (@ThomasBlauth) 59 | James Cherti (@jamescherti) 60 | 61 | @something are github user names. 62 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # We <3 pull requests! 2 | 3 | 1. Fork the Repo on github. 4 | 2. Add yourself to AUTHORS.txt 5 | 3. Add a test if possible. 6 | 4. Push to your fork and submit a pull request. 7 | 8 | Please use PEP8 as a Python code style. For VIM, just try to style your 9 | code similar to the jedi-vim code that is already there. 10 | 11 | # Bug reports 12 | Please include the output of `:version` and `:JediDebugInfo`. 13 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) <2013> 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | BUILD_VIRTUAL_ENV:=build/venv 2 | 3 | test: 4 | pytest 5 | 6 | test_nvim: 7 | VSPEC_VIM=nvim pytest 8 | 9 | test_coverage: export PYTEST_ADDOPTS:=--cov pythonx --cov test --cov-report=term-missing:skip-covered 10 | test_coverage: test_nvim 11 | 12 | $(dir $(BUILD_VIRTUAL_ENV)): 13 | mkdir -p $@ 14 | 15 | $(BUILD_VIRTUAL_ENV): | $(dir $(BUILD_VIRTUAL_ENV)) 16 | python -m venv $@ 17 | 18 | $(BUILD_VIRTUAL_ENV)/bin/vint: | $(BUILD_VIRTUAL_ENV) 19 | $|/bin/python -m pip install vim-vint==0.3.21 20 | 21 | $(BUILD_VIRTUAL_ENV)/bin/flake8: | $(BUILD_VIRTUAL_ENV) 22 | $|/bin/python -m pip install -q flake8==3.7.8 23 | 24 | vint: $(BUILD_VIRTUAL_ENV)/bin/vint 25 | $(BUILD_VIRTUAL_ENV)/bin/vint after autoload ftplugin plugin 26 | 27 | flake8: $(BUILD_VIRTUAL_ENV)/bin/flake8 28 | $(BUILD_VIRTUAL_ENV)/bin/flake8 pythonx/jedi_*.py 29 | 30 | check: vint flake8 31 | 32 | clean: 33 | rm -rf build 34 | 35 | .PHONY: test check clean vint flake8 36 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | .. image:: https://github.com/davidhalter/jedi-vim/blob/master/doc/logotype-a.svg 2 | 3 | ################################################# 4 | jedi-vim - awesome Python autocompletion with VIM 5 | ################################################# 6 | 7 | .. image:: https://travis-ci.org/davidhalter/jedi-vim.svg?branch=master 8 | :target: https://travis-ci.org/davidhalter/jedi-vim 9 | :alt: Travis-CI build status 10 | 11 | jedi-vim is a VIM binding to the autocompletion library 12 | `Jedi `_. 13 | 14 | Here are some pictures: 15 | 16 | .. image:: https://github.com/davidhalter/jedi/raw/master/docs/_screenshots/screenshot_complete.png 17 | 18 | Completion for almost anything (Ctrl+Space). 19 | 20 | .. image:: https://github.com/davidhalter/jedi/raw/master/docs/_screenshots/screenshot_function.png 21 | 22 | Display of function/class bodies, docstrings. 23 | 24 | .. image:: https://github.com/davidhalter/jedi/raw/master/docs/_screenshots/screenshot_pydoc.png 25 | 26 | Documentation (Pydoc) support (with highlighting, Shift+k). 27 | 28 | There is also support for goto and renaming. 29 | 30 | 31 | Get the latest from `github `_. 32 | 33 | Documentation 34 | ============= 35 | 36 | Documentation is available in your vim: ``:help jedi-vim``. You can also look 37 | it up `on github `_. 38 | 39 | You can read the Jedi library documentation `here `_. 40 | 41 | If you want to report issues, just use the github issue tracker. In case of 42 | questions about the software, please use `stackoverflow 43 | `_ and tag your question with ``jedi-vim``. 44 | 45 | 46 | Contributing 47 | ============ 48 | 49 | We love Pull Requests! Read the instructions in ``CONTRIBUTING.md``. 50 | 51 | 52 | Features 53 | ======== 54 | 55 | The Jedi library understands most of Python's core features. From decorators to 56 | generators, there is broad support. 57 | 58 | Apart from that, jedi-vim supports the following commands 59 | 60 | - Completion ```` 61 | - Goto assignment ``g`` (typical goto function) 62 | - Goto definition ``d`` (follow identifier as far as possible, 63 | includes imports and statements) 64 | - Goto (typing) stub ``s`` 65 | - Show Documentation/Pydoc ``K`` (shows a popup with assignments) 66 | - Renaming ``r`` 67 | - Usages ``n`` (shows all the usages of a name) 68 | - Open module, e.g. ``:Pyimport os`` (opens the ``os`` module) 69 | 70 | 71 | Installation 72 | ============ 73 | 74 | Requirements 75 | ------------ 76 | - **Vim**: You need a VIM version that was compiled with Python 3 or later 77 | (``+python3``). You can check this from within VIM using 78 | ``:python3 import sys; print(sys.version)``. 79 | 80 | - **Neovim**: You need a python environment with ``pynvim`` installed: 81 | ``pip install pynvim`` 82 | 83 | then check your environment is correctly setup from within Neovim using 84 | ``:checkhealth provider.python`` 85 | 86 | Manual installation 87 | ------------------- 88 | 89 | You might want to use `pathogen `_ or 90 | `Vundle `_ to install jedi-vim. 91 | 92 | The first thing you need after that is an up-to-date version of Jedi. Install 93 | ``git submodule update --init --recursive`` in your jedi-vim repository. 94 | 95 | Example installation command using Pathogen: 96 | 97 | .. code-block:: sh 98 | 99 | git clone --recursive https://github.com/davidhalter/jedi-vim.git ~/.vim/bundle/jedi-vim 100 | 101 | Example installation using Vundle: 102 | 103 | Add the following line in your `~/.vimrc` 104 | 105 | .. code-block:: vim 106 | 107 | Plugin 'davidhalter/jedi-vim' 108 | 109 | For installing Jedi, ``pip install jedi`` will also work, but you might run 110 | into issues when working in virtual environments. Please use git submodules. 111 | 112 | 113 | Installation with your distribution 114 | ----------------------------------- 115 | 116 | On Arch Linux, you can also install jedi-vim from official repositories as 117 | `vim-jedi `__. 118 | It is also available on 119 | `Debian (≥8) `__ and 120 | `Ubuntu (≥14.04) `__ as 121 | vim-python-jedi. 122 | On Fedora Linux, it is available as 123 | `vim-jedi `__. 124 | 125 | Please note that this version might be quite old compared to using jedi-vim 126 | from Git. 127 | 128 | Caveats 129 | ------- 130 | 131 | Note that the `python-mode `_ VIM plugin seems 132 | to conflict with jedi-vim, therefore you should disable it before enabling 133 | jedi-vim. 134 | 135 | To enjoy the full features of jedi-vim, you should have VIM >= 7.3, compiled with 136 | ``+conceal`` (which is not the case on some platforms, including OS X). If your VIM 137 | does not meet these requirements, the parameter recommendation list may not appear 138 | when you type an open bracket after a function name. Please read 139 | `the documentation `_ 140 | for details. 141 | 142 | 143 | Settings 144 | ======== 145 | 146 | Jedi is by default automatically initialized. If you don't want that I suggest 147 | you disable the auto-initialization in your ``.vimrc``: 148 | 149 | .. code-block:: vim 150 | 151 | let g:jedi#auto_initialization = 0 152 | 153 | There are also some VIM options (like ``completeopt`` and key defaults) which 154 | are automatically initialized, but you can skip this: 155 | 156 | .. code-block:: vim 157 | 158 | let g:jedi#auto_vim_configuration = 0 159 | 160 | 161 | You can make jedi-vim use tabs when going to a definition etc: 162 | 163 | .. code-block:: vim 164 | 165 | let g:jedi#use_tabs_not_buffers = 1 166 | 167 | If you are a person who likes to use VIM-splits, you might want to put this in your ``.vimrc``: 168 | 169 | .. code-block:: vim 170 | 171 | let g:jedi#use_splits_not_buffers = "left" 172 | 173 | This options could be "left", "right", "top", "bottom" or "winwidth". It will decide the direction where the split open. 174 | 175 | Jedi automatically starts the completion, if you type a dot, e.g. ``str.``, if 176 | you don't want this: 177 | 178 | .. code-block:: vim 179 | 180 | let g:jedi#popup_on_dot = 0 181 | 182 | Jedi selects the first line of the completion menu: for a better typing-flow 183 | and usually saves one keypress. 184 | 185 | .. code-block:: vim 186 | 187 | let g:jedi#popup_select_first = 0 188 | 189 | Jedi displays function call signatures in insert mode in real-time, highlighting 190 | the current argument. The call signatures can be displayed as a pop-up in the 191 | buffer (set to 1 by default (with the conceal feature), 2 otherwise), 192 | which has the advantage of being easier to refer to (but is a hack with 193 | many drawbacks since it changes the buffer's contents), 194 | or in Vim's command line aligned with the function call (set to 2), which 195 | can improve the integrity of Vim's undo history. 196 | 197 | .. code-block:: vim 198 | 199 | let g:jedi#show_call_signatures = "1" 200 | 201 | Here are a few more defaults for actions, read the docs (``:help jedi-vim``) to 202 | get more information. If you set them to ``""``, they are not assigned. 203 | 204 | .. code-block:: vim 205 | 206 | NOTE: subject to change! 207 | 208 | let g:jedi#goto_command = "d" 209 | let g:jedi#goto_assignments_command = "g" 210 | let g:jedi#goto_stubs_command = "s" 211 | let g:jedi#goto_definitions_command = "" 212 | let g:jedi#documentation_command = "K" 213 | let g:jedi#usages_command = "n" 214 | let g:jedi#completions_command = "" 215 | let g:jedi#rename_command = "r" 216 | let g:jedi#rename_command_keep_name = "R" 217 | 218 | An example for setting up your project: 219 | 220 | .. code-block:: vim 221 | 222 | let g:jedi#environment_path = "/usr/bin/python3.9" 223 | 224 | jedi-vim tries its best to guess your virtual env. If you want to work with a 225 | specific virtual environment however, you can point jedi-vim towards it: 226 | 227 | .. code-block:: vim 228 | 229 | let g:jedi#environment_path = "venv" 230 | 231 | Finally, if you don't want completion, but all the other features, use: 232 | 233 | .. code-block:: vim 234 | 235 | let g:jedi#completions_enabled = 0 236 | 237 | FAQ 238 | === 239 | 240 | I want to use Jedi with a Python 2 Environment, but it's not listed under "Known environments" 241 | ---------------------------------------------------------------------------------------------- 242 | 243 | Starting with version 0.18.0 Jedi dropped support for Python 2. 244 | 245 | 246 | I don't want the docstring window to popup during completion 247 | ------------------------------------------------------------ 248 | 249 | This depends on the ``completeopt`` option. Jedi initializes it in its 250 | ``ftplugin``. Add the following line to your ``.vimrc`` to disable it: 251 | 252 | .. code-block:: vim 253 | 254 | autocmd FileType python setlocal completeopt-=preview 255 | 256 | 257 | I want to do autocompletion 258 | --------------------------------- 259 | 260 | Don't even think about changing the Jedi command to ````, 261 | use `supertab `_! 262 | 263 | 264 | The completion is too slow! 265 | --------------------------- 266 | 267 | 1. Completion of complex libraries (like Numpy) should only be slow the first 268 | time you complete them. After that the results should be cached and very fast. 269 | 270 | 2. If it is still slow after the initial completion and you have installed the 271 | python-mode Vim plugin, try disabling its rope mode: 272 | 273 | .. code-block:: vim 274 | 275 | let g:pymode_rope = 0 276 | 277 | See issue `#163 `__. 278 | 279 | 3. You can also use `deoplete-jedi `__ 280 | for completions, which uses Jedi, but does completions asynchronously 281 | (requires Neovim). 282 | It makes sense to use both jedi-vim and deoplete-jedi, but you should disable 283 | jedi-vim's completions then: 284 | 285 | .. code-block:: vim 286 | 287 | let g:jedi#completions_enabled = 0 288 | 289 | Testing 290 | ======= 291 | 292 | jedi-vim is being tested with a combination of `vspec 293 | `_ and `py.test `_. 294 | 295 | The tests are in the ``test`` subdirectory, you can run them calling:: 296 | 297 | py.test 298 | 299 | The tests are automatically run with `travis 300 | `_. 301 | -------------------------------------------------------------------------------- /after/ftplugin/python/jedi.vim: -------------------------------------------------------------------------------- 1 | if jedi#init_python() && g:jedi#auto_initialization && g:jedi#completions_enabled 2 | call jedi#setup_completion() 3 | endif 4 | -------------------------------------------------------------------------------- /after/syntax/python.vim: -------------------------------------------------------------------------------- 1 | if !jedi#init_python() 2 | finish 3 | endif 4 | 5 | if g:jedi#show_call_signatures > 0 && has('conceal') 6 | " +conceal is the default for vim >= 7.3 7 | 8 | let s:e = g:jedi#call_signature_escape 9 | let s:full = s:e.'jedi=.\{-}'.s:e.'.\{-}'.s:e.'jedi'.s:e 10 | let s:ignore = s:e.'jedi.\{-}'.s:e 11 | exe 'syn match jediIgnore "'.s:ignore.'" contained conceal' 12 | setlocal conceallevel=2 13 | syn match jediFatSymbol "\*_\*" contained conceal 14 | syn match jediFat "\*_\*.\{-}\*_\*" contained contains=jediFatSymbol 15 | syn match jediSpace "\v[ ]+( )@=" contained 16 | exe 'syn match jediFunction "'.s:full.'" keepend extend ' 17 | \ .' contains=jediIgnore,jediFat,jediSpace' 18 | \ .' containedin=pythonComment,pythonString,pythonRawString' 19 | unlet! s:e s:full s:ignore 20 | 21 | hi def link jediIgnore Ignore 22 | hi def link jediFatSymbol Ignore 23 | hi def link jediSpace Normal 24 | 25 | if exists('g:colors_name') 26 | hi def link jediFunction CursorLine 27 | hi def link jediFat TabLine 28 | else 29 | hi def jediFunction term=NONE cterm=NONE ctermfg=6 guifg=Black gui=NONE ctermbg=0 guibg=Grey 30 | hi def jediFat term=bold,underline cterm=bold,underline gui=bold,underline ctermbg=0 guibg=#555555 31 | endif 32 | endif 33 | 34 | hi def jediUsage cterm=reverse gui=standout 35 | -------------------------------------------------------------------------------- /autoload/health/jedi.vim: -------------------------------------------------------------------------------- 1 | function! health#jedi#check() abort 2 | call v:lua.vim.health.start('jedi') 3 | silent call jedi#debug_info() 4 | endfunction 5 | -------------------------------------------------------------------------------- /autoload/jedi.vim: -------------------------------------------------------------------------------- 1 | scriptencoding utf-8 2 | 3 | " ------------------------------------------------------------------------ 4 | " Settings initialization 5 | " ------------------------------------------------------------------------ 6 | let s:deprecations = { 7 | \ 'get_definition_command': 'goto_definitions_command', 8 | \ 'pydoc': 'documentation_command', 9 | \ 'related_names_command': 'usages_command', 10 | \ 'autocompletion_command': 'completions_command', 11 | \ 'show_function_definition': 'show_call_signatures', 12 | \ } 13 | 14 | let s:default_settings = { 15 | \ 'use_tabs_not_buffers': 0, 16 | \ 'use_splits_not_buffers': 1, 17 | \ 'auto_initialization': 1, 18 | \ 'auto_vim_configuration': 1, 19 | \ 'goto_command': "'d'", 20 | \ 'goto_assignments_command': "'g'", 21 | \ 'goto_definitions_command': "''", 22 | \ 'goto_stubs_command': "'s'", 23 | \ 'completions_command': "''", 24 | \ 'call_signatures_command': "'n'", 25 | \ 'usages_command': "'n'", 26 | \ 'rename_command': "'r'", 27 | \ 'rename_command_keep_name': "'R'", 28 | \ 'completions_enabled': 1, 29 | \ 'popup_on_dot': 'g:jedi#completions_enabled', 30 | \ 'documentation_command': "'K'", 31 | \ 'show_call_signatures': has('conceal') ? 1 : 2, 32 | \ 'show_call_signatures_delay': 500, 33 | \ 'call_signature_escape': "'?!?'", 34 | \ 'auto_close_doc': 1, 35 | \ 'max_doc_height': 30, 36 | \ 'popup_select_first': 1, 37 | \ 'quickfix_window_height': 10, 38 | \ 'force_py_version': "'auto'", 39 | \ 'environment_path': "'auto'", 40 | \ 'added_sys_path': '[]', 41 | \ 'project_path': "'auto'", 42 | \ 'smart_auto_mappings': 0, 43 | \ 'case_insensitive_completion': 1, 44 | \ 'use_tag_stack': 1 45 | \ } 46 | 47 | for [s:key, s:val] in items(s:deprecations) 48 | if exists('g:jedi#'.s:key) 49 | echom "'g:jedi#".s:key."' is deprecated. Please use 'g:jedi#".s:val."' instead. Sorry for the inconvenience." 50 | exe 'let g:jedi#'.s:val.' = g:jedi#'.s:key 51 | endif 52 | endfor 53 | 54 | for [s:key, s:val] in items(s:default_settings) 55 | if !exists('g:jedi#'.s:key) 56 | exe 'let g:jedi#'.s:key.' = '.s:val 57 | endif 58 | endfor 59 | 60 | let s:supports_buffer_usages = has('nvim') || exists('*prop_add') 61 | 62 | 63 | " ------------------------------------------------------------------------ 64 | " Python initialization 65 | " ------------------------------------------------------------------------ 66 | let s:script_path = expand(':p:h:h') 67 | 68 | function! s:init_python() abort 69 | " Use g:jedi#force_py_version for loading Jedi, or fall back to using 70 | " `has()` - preferring Python 3. 71 | if !has('python3') 72 | throw 'jedi-vim requires Vim with support for Python 3.' 73 | endif 74 | call jedi#setup_python_imports() 75 | return 1 76 | endfunction 77 | 78 | 79 | function! jedi#reinit_python() abort 80 | let s:_init_python = -1 81 | call jedi#init_python() 82 | endfunction 83 | 84 | 85 | " This is meant to be called with `:unsilent` (for &shortmess+=F). 86 | function! s:display_exception() abort 87 | let error_lines = split(v:exception, '\n') 88 | let msg = 'Error: jedi-vim failed to initialize Python: ' 89 | \ .error_lines[0].' (in '.v:throwpoint.')' 90 | if len(error_lines) > 1 91 | echohl ErrorMsg 92 | echom 'jedi-vim error: '.error_lines[0] 93 | for line in error_lines[1:] 94 | echom line 95 | endfor 96 | echohl None 97 | let help_cmd = ':JediDebugInfo' 98 | if exists(':checkhealth') == 2 99 | let help_cmd .= ' / :checkhealth' 100 | endif 101 | let msg .= printf('. See :messages and/or %s for more information.', 102 | \ help_cmd) 103 | endif 104 | redraw " Redraw to only have the main message by default. 105 | echoerr msg 106 | endfunction 107 | 108 | 109 | let s:_init_python = -1 110 | function! jedi#init_python() abort 111 | if s:_init_python == -1 112 | let s:_init_python = 0 113 | try 114 | let s:_init_python = s:init_python() 115 | let s:_init_python = 1 116 | catch /^jedi/ 117 | " Only catch errors from jedi-vim itself here, so that for 118 | " unexpected Python exceptions the traceback will be shown 119 | " (e.g. with NameError in jedi#setup_python_imports's code). 120 | if !exists('g:jedi#squelch_py_warning') 121 | unsilent call s:display_exception() 122 | endif 123 | endtry 124 | endif 125 | return s:_init_python 126 | endfunction 127 | 128 | 129 | function! jedi#setup_python_imports() abort 130 | let g:_jedi_init_error = 0 131 | let init_lines = [ 132 | \ 'import vim', 133 | \ 'def _jedi_handle_exc(exc_info):', 134 | \ ' try:', 135 | \ ' from jedi_vim_debug import format_exc_info', 136 | \ ' vim.vars["_jedi_init_error"] = format_exc_info(exc_info)', 137 | \ ' except Exception:', 138 | \ ' import traceback', 139 | \ ' vim.vars["_jedi_init_error"] = "\\n".join(traceback.format_exception(*exc_info))', 140 | \ 'try:', 141 | \ ' import jedi_vim', 142 | \ ' if hasattr(jedi_vim, "jedi_import_error"):', 143 | \ ' _jedi_handle_exc(jedi_vim.jedi_import_error)', 144 | \ 'except Exception as exc:', 145 | \ ' _jedi_handle_exc(sys.exc_info())', 146 | \ ] 147 | exe 'python3 exec('''.escape(join(init_lines, '\n'), "'").''')' 148 | if g:_jedi_init_error isnot 0 149 | throw printf('jedi#setup_python_imports: %s', g:_jedi_init_error) 150 | endif 151 | return 1 152 | endfunction 153 | 154 | 155 | function! jedi#debug_info() abort 156 | if &verbose 157 | if &filetype !=# 'python' 158 | echohl WarningMsg | echo 'You should run this in a buffer with filetype "python".' | echohl None 159 | endif 160 | endif 161 | let spath = shellescape(s:script_path) 162 | echo '#### Jedi-vim debug information' 163 | echo "\n" 164 | echo '##### jedi-vim version' 165 | echo "\n" 166 | echo ' - jedi-vim git version: ' 167 | echon substitute(system('git -C '.spath.' describe --tags --always --dirty'), '\v\n$', '', '') 168 | echo ' - jedi git submodule status: ' 169 | echon substitute(system('git -C '.spath.' submodule status pythonx/jedi'), '\v\n$', '', '') 170 | echo ' - parso git submodule status: ' 171 | echon substitute(system('git -C '.spath.' submodule status pythonx/parso'), '\v\n$', '', '') 172 | echo "\n" 173 | echo '##### Global Python' 174 | echo "\n" 175 | echo 'Using Python version 3 to access Jedi.' 176 | let s:pythonjedi_called = 0 177 | try 178 | python3 import vim; vim.command('let s:pythonjedi_called = 1') 179 | catch 180 | echo 'Error when trying to import vim: '.v:exception 181 | endtry 182 | if !s:pythonjedi_called 183 | echohl WarningMsg 184 | echom 'python3 failed to run, likely a Python config issue.' 185 | if exists(':checkhealth') == 2 186 | echom 'Try :checkhealth for more information.' 187 | endif 188 | echohl None 189 | else 190 | try 191 | python3 from jedi_vim_debug import display_debug_info 192 | python3 display_debug_info() 193 | catch 194 | echohl WarningMsg 195 | echo 'Error when running display_debug_info: '.v:exception 196 | echohl None 197 | endtry 198 | endif 199 | echo "\n" 200 | echo '##### Settings' 201 | echo "\n" 202 | echo '```' 203 | let jedi_settings = items(filter(copy(g:), "v:key =~# '\\v^jedi#'")) 204 | let has_nondefault_settings = 0 205 | for [k, V] in jedi_settings 206 | exe 'let default = '.get(s:default_settings, 207 | \ substitute(k, '\v^jedi#', '', ''), "'-'") 208 | " vint: -ProhibitUsingUndeclaredVariable 209 | if default !=# V 210 | echo printf('g:%s = %s (default: %s)', k, string(V), string(default)) 211 | unlet! V " Fix variable type mismatch with Vim 7.3. 212 | let has_nondefault_settings = 1 213 | endif 214 | " vint: +ProhibitUsingUndeclaredVariable 215 | endfor 216 | if has_nondefault_settings 217 | echo "\n" 218 | endif 219 | verb set omnifunc? completeopt? 220 | echo '```' 221 | 222 | if &verbose 223 | echo "\n" 224 | echo '#### :version' 225 | echo '```' 226 | version 227 | echo '```' 228 | echo "\n" 229 | echo '#### :messages' 230 | echo '```' 231 | messages 232 | echo '```' 233 | echo "\n" 234 | echo '
:scriptnames' 235 | echo "\n" 236 | echo '```' 237 | scriptnames 238 | echo '```' 239 | echo '
' 240 | endif 241 | endfunction 242 | 243 | " Helper function instead of `python vim.eval()`, and `.command()` because 244 | " these also return error definitions. 245 | function! jedi#_vim_exceptions(str, is_eval) abort 246 | let l:result = {} 247 | try 248 | if a:is_eval 249 | let l:result.result = eval(a:str) 250 | else 251 | execute a:str 252 | let l:result.result = '' 253 | endif 254 | catch 255 | let l:result.exception = v:exception 256 | let l:result.throwpoint = v:throwpoint 257 | endtry 258 | return l:result 259 | endfunction 260 | 261 | call jedi#init_python() " Might throw an error. 262 | 263 | " ------------------------------------------------------------------------ 264 | " functions that call python code 265 | " ------------------------------------------------------------------------ 266 | function! jedi#goto() abort 267 | python3 jedi_vim.goto(mode="goto") 268 | endfunction 269 | 270 | function! jedi#goto_assignments() abort 271 | python3 jedi_vim.goto(mode="assignment") 272 | endfunction 273 | 274 | function! jedi#goto_definitions() abort 275 | python3 jedi_vim.goto(mode="definition") 276 | endfunction 277 | 278 | function! jedi#goto_stubs() abort 279 | python3 jedi_vim.goto(mode="stubs") 280 | endfunction 281 | 282 | function! jedi#usages() abort 283 | if exists('#jedi_usages#BufWinEnter') 284 | call jedi#clear_usages() 285 | endif 286 | python3 jedi_vim.usages() 287 | endfunction 288 | 289 | if !s:supports_buffer_usages 290 | " Hide usages in the current window. 291 | " Only handles the current window due to matchdelete() restrictions. 292 | function! jedi#_hide_usages_in_win() abort 293 | let winnr = winnr() 294 | let matchids = getwinvar(winnr, '_jedi_usages_vim_matchids', []) 295 | 296 | for matchid in matchids[1:] 297 | call matchdelete(matchid) 298 | endfor 299 | call setwinvar(winnr, '_jedi_usages_vim_matchids', []) 300 | 301 | " Remove the autocommands that might have triggered this function. 302 | augroup jedi_usages 303 | exe 'autocmd! * ' 304 | augroup END 305 | unlet! b:_jedi_usages_needs_clear 306 | endfunction 307 | 308 | " Show usages for current window (Vim without textprops only). 309 | function! jedi#_show_usages_in_win() abort 310 | python3 jedi_vim.highlight_usages_for_vim_win() 311 | 312 | if !exists('#jedi_usages#TextChanged#') 313 | augroup jedi_usages 314 | " Unset highlights on any changes to this buffer. 315 | " NOTE: Neovim's API handles movement of highlights, but would only 316 | " need to clear highlights that are changed inline. 317 | autocmd TextChanged call jedi#_clear_buffer_usages() 318 | 319 | " Hide usages when the buffer is removed from the window, or when 320 | " entering insert mode (but keep them for later). 321 | autocmd BufWinLeave,InsertEnter call jedi#_hide_usages_in_win() 322 | augroup END 323 | endif 324 | endfunction 325 | 326 | " Remove usages for the current buffer (and all its windows). 327 | function! jedi#_clear_buffer_usages() abort 328 | let bufnr = bufnr('%') 329 | let nvim_src_ids = getbufvar(bufnr, '_jedi_usages_src_ids', []) 330 | if !empty(nvim_src_ids) 331 | for src_id in nvim_src_ids 332 | " TODO: could only clear highlights below/after changed line?! 333 | call nvim_buf_clear_highlight(bufnr, src_id, 0, -1) 334 | endfor 335 | else 336 | call jedi#_hide_usages_in_win() 337 | endif 338 | endfunction 339 | endif 340 | 341 | " Remove/unset global usages. 342 | function! jedi#clear_usages() abort 343 | augroup jedi_usages 344 | autocmd! BufWinEnter 345 | autocmd! WinEnter 346 | augroup END 347 | 348 | if !s:supports_buffer_usages 349 | " Vim without textprops: clear current window, 350 | " autocommands will clean others on demand. 351 | call jedi#_hide_usages_in_win() 352 | 353 | " Setup autocommands to clear remaining highlights on WinEnter. 354 | augroup jedi_usages 355 | for b in range(1, bufnr('$')) 356 | if getbufvar(b, '_jedi_usages_needs_clear') 357 | exe 'autocmd WinEnter call jedi#_hide_usages_in_win()' 358 | endif 359 | endfor 360 | augroup END 361 | endif 362 | 363 | python3 jedi_vim.clear_usages() 364 | endfunction 365 | 366 | function! jedi#rename(...) abort 367 | python3 jedi_vim.rename() 368 | endfunction 369 | 370 | function! jedi#rename_visual(...) abort 371 | python3 jedi_vim.rename_visual() 372 | endfunction 373 | 374 | function! jedi#rename_keep_name(...) abort 375 | python3 jedi_vim.rename(delete_word=False) 376 | endfunction 377 | 378 | function! jedi#rename_visual_keep_name(...) abort 379 | python3 jedi_vim.rename_visual(use_selected_text_as_prompt_answer=True) 380 | endfunction 381 | 382 | function! jedi#completions(findstart, base) abort 383 | python3 jedi_vim.completions() 384 | endfunction 385 | 386 | function! jedi#enable_speed_debugging() abort 387 | python3 jedi_vim.jedi.set_debug_function(jedi_vim.print_to_stdout, speed=True, warnings=False, notices=False) 388 | endfunction 389 | 390 | function! jedi#enable_debugging() abort 391 | python3 jedi_vim.jedi.set_debug_function(jedi_vim.print_to_stdout) 392 | endfunction 393 | 394 | function! jedi#disable_debugging() abort 395 | python3 jedi_vim.jedi.set_debug_function(None) 396 | endfunction 397 | 398 | function! jedi#py_import(args) abort 399 | python3 jedi_vim.py_import() 400 | endfun 401 | 402 | function! jedi#choose_environment(args) abort 403 | python3 jedi_vim.choose_environment() 404 | endfun 405 | 406 | function! jedi#load_project(args) abort 407 | python3 jedi_vim.load_project() 408 | endfun 409 | 410 | function! jedi#py_import_completions(argl, cmdl, pos) abort 411 | python3 jedi_vim.py_import_completions() 412 | endfun 413 | 414 | function! jedi#clear_cache(bang) abort 415 | if a:bang 416 | python3 jedi_vim.jedi.cache.clear_time_caches(True) 417 | else 418 | python3 jedi_vim.jedi.cache.clear_time_caches(False) 419 | endif 420 | endfunction 421 | 422 | 423 | " ------------------------------------------------------------------------ 424 | " show_documentation 425 | " ------------------------------------------------------------------------ 426 | function! jedi#show_documentation() abort 427 | python3 if jedi_vim.show_documentation() is None: vim.command('return') 428 | 429 | let bn = bufnr('__doc__') 430 | if bn > 0 431 | let wi=index(tabpagebuflist(tabpagenr()), bn) 432 | if wi >= 0 433 | " If the __doc__ buffer is open in the current tab, jump to it 434 | silent execute (wi+1).'wincmd w' 435 | else 436 | silent execute 'sbuffer '.bn 437 | endif 438 | else 439 | split __doc__ 440 | endif 441 | 442 | setlocal modifiable 443 | setlocal noswapfile 444 | setlocal buftype=nofile 445 | silent normal! ggdG 446 | silent $put=l:doc 447 | silent normal! 1Gdd 448 | setlocal nomodifiable 449 | setlocal nomodified 450 | setlocal filetype=rst 451 | setlocal foldlevel=200 " do not fold in __doc__ 452 | 453 | if l:doc_lines > g:jedi#max_doc_height " max lines for plugin 454 | let l:doc_lines = g:jedi#max_doc_height 455 | endif 456 | execute 'resize '.l:doc_lines 457 | 458 | " quit comands 459 | nnoremap q ZQ 460 | if len(g:jedi#documentation_command) 461 | execute 'nnoremap '.g:jedi#documentation_command.' ZQ' 462 | endif 463 | endfunction 464 | 465 | " ------------------------------------------------------------------------ 466 | " helper functions 467 | " ------------------------------------------------------------------------ 468 | 469 | function! jedi#add_goto_window(for_usages, len) abort 470 | let height = min([a:len, g:jedi#quickfix_window_height]) 471 | 472 | " Use :copen to go to the window always - the user should select an entry. 473 | execute 'belowright copen '.height 474 | 475 | if &filetype !=# 'qf' 476 | echoerr printf('jedi-vim: unexpected ft with current window (%s), please report!', &filetype) 477 | endif 478 | if g:jedi#use_tabs_not_buffers == 1 479 | noremap :call jedi#goto_window_on_enter() 480 | endif 481 | 482 | augroup jedi_goto_window 483 | if a:for_usages 484 | autocmd BufWinLeave call jedi#clear_usages() 485 | else 486 | autocmd WinLeave q " automatically leave, if an option is chosen 487 | endif 488 | augroup END 489 | 490 | if a:for_usages && !has('nvim') 491 | if s:supports_buffer_usages 492 | " Setup autocommand for pending highlights with Vim's textprops. 493 | " (cannot be added to unlisted buffers) 494 | augroup jedi_usages 495 | autocmd! BufWinEnter * call s:usages_for_pending_buffers() 496 | augroup END 497 | else 498 | " Setup global autocommand to display any usages for a window. 499 | " Gets removed when closing the quickfix window that displays them, or 500 | " when clearing them (e.g. on TextChanged). 501 | augroup jedi_usages 502 | autocmd! BufWinEnter,WinEnter * call jedi#_show_usages_in_win() 503 | augroup END 504 | endif 505 | endif 506 | endfunction 507 | 508 | " Highlight usages for a buffer if not done so yet (Neovim only). 509 | function! s:usages_for_pending_buffers() abort 510 | python3 jedi_vim._handle_pending_usages_for_buf() 511 | endfunction 512 | 513 | 514 | function! jedi#goto_window_on_enter() abort 515 | let l:list = getqflist() 516 | let l:data = l:list[line('.') - 1] 517 | if l:data.bufnr 518 | " close goto_window buffer 519 | normal! ZQ 520 | python3 jedi_vim.set_buffer(vim.eval('bufname(l:data.bufnr)')) 521 | call cursor(l:data.lnum, l:data.col) 522 | else 523 | echohl WarningMsg | echo 'Builtin module cannot be opened.' | echohl None 524 | endif 525 | endfunction 526 | 527 | 528 | function! s:syn_stack() abort 529 | if !exists('*synstack') 530 | return [] 531 | endif 532 | return map(synstack(line('.'), col('.') - 1), "synIDattr(v:val, 'name')") 533 | endfunc 534 | 535 | 536 | function! jedi#do_popup_on_dot_in_highlight() abort 537 | let highlight_groups = s:syn_stack() 538 | for a in highlight_groups 539 | if a ==# 'pythonDoctest' 540 | return 1 541 | endif 542 | endfor 543 | 544 | for a in highlight_groups 545 | for b in ['pythonString', 'pythonComment', 'pythonNumber'] 546 | if a == b 547 | return 0 548 | endif 549 | endfor 550 | endfor 551 | return 1 552 | endfunc 553 | 554 | 555 | let s:show_call_signatures_last = [0, 0, ''] 556 | function! jedi#show_call_signatures() abort 557 | if s:_init_python == 0 558 | return 1 559 | endif 560 | let [line, col] = [line('.'), col('.')] 561 | let curline = getline(line) 562 | let reload_signatures = 1 563 | 564 | " Caching. On the same line only. 565 | if line == s:show_call_signatures_last[0] 566 | " Check if the number of special signs before or after the 567 | " cursor has not changed since the last call, which means that the 568 | " argument position was not changed and we can skip repainting. 569 | let prevcol = s:show_call_signatures_last[1] 570 | let prevline = s:show_call_signatures_last[2] 571 | let no_special = '[^,()=]' 572 | if substitute(curline[:col-2], no_special, '', 'g') 573 | \ == substitute(prevline[:prevcol-2], no_special, '', 'g') 574 | \ && substitute(curline[(col-2):], no_special, '', 'g') 575 | \ == substitute(prevline[(prevcol-2):], no_special, '', 'g') 576 | let reload_signatures = 0 577 | endif 578 | endif 579 | let s:show_call_signatures_last = [line, col, curline] 580 | 581 | if reload_signatures 582 | python3 jedi_vim.show_call_signatures() 583 | endif 584 | endfunction 585 | 586 | 587 | function! jedi#clear_call_signatures() abort 588 | if s:_init_python == 0 589 | return 1 590 | endif 591 | 592 | let s:show_call_signatures_last = [0, 0, ''] 593 | python3 jedi_vim.clear_call_signatures() 594 | endfunction 595 | 596 | 597 | function! jedi#configure_call_signatures() abort 598 | augroup jedi_call_signatures 599 | autocmd! * 600 | if g:jedi#show_call_signatures == 2 " Command line call signatures 601 | autocmd InsertEnter let g:jedi#first_col = s:save_first_col() 602 | endif 603 | autocmd InsertEnter let s:show_call_signatures_last = [0, 0, ''] 604 | autocmd InsertLeave call jedi#clear_call_signatures() 605 | if g:jedi#show_call_signatures_delay > 0 606 | autocmd InsertEnter let b:_jedi_orig_updatetime = &updatetime 607 | \ | let &updatetime = g:jedi#show_call_signatures_delay 608 | autocmd InsertLeave if exists('b:_jedi_orig_updatetime') 609 | \ | let &updatetime = b:_jedi_orig_updatetime 610 | \ | unlet b:_jedi_orig_updatetime 611 | \ | endif 612 | autocmd CursorHoldI call jedi#show_call_signatures() 613 | else 614 | autocmd CursorMovedI call jedi#show_call_signatures() 615 | endif 616 | augroup END 617 | endfunction 618 | 619 | 620 | " Determine where the current window is on the screen for displaying call 621 | " signatures in the correct column. 622 | function! s:save_first_col() abort 623 | if bufname('%') ==# '[Command Line]' || winnr('$') == 1 624 | return 0 625 | endif 626 | 627 | let startwin = winnr() 628 | let winwidth = winwidth(0) 629 | if winwidth == &columns 630 | return 0 631 | elseif winnr('$') == 2 632 | return startwin == 1 ? 0 : (winwidth(1) + 1) 633 | elseif winnr('$') == 3 634 | if startwin == 1 635 | return 0 636 | endif 637 | let ww1 = winwidth(1) 638 | let ww2 = winwidth(2) 639 | let ww3 = winwidth(3) 640 | if ww1 + ww2 + ww3 + 2 == &columns 641 | if startwin == 2 642 | return ww1 + 1 643 | else 644 | return ww1 + ww2 + 2 645 | endif 646 | elseif startwin == 2 647 | if ww2 + ww3 + 1 == &columns 648 | return 0 649 | else 650 | return ww1 + 1 651 | endif 652 | else " startwin == 3 653 | if ww2 + ww3 + 1 == &columns 654 | return ww2 + 1 655 | else 656 | return ww1 + 1 657 | endif 658 | endif 659 | endif 660 | return 0 661 | endfunction 662 | 663 | 664 | function! jedi#complete_string(autocomplete) abort 665 | if a:autocomplete 666 | if !(g:jedi#popup_on_dot && jedi#do_popup_on_dot_in_highlight()) 667 | return '' 668 | endif 669 | 670 | let s:saved_completeopt = &completeopt 671 | set completeopt-=longest 672 | set completeopt+=menuone 673 | set completeopt-=menu 674 | if &completeopt !~# 'noinsert\|noselect' 675 | " Patch 775 introduced noinsert and noselect, previously these 676 | " options didn't exist. Setting them in earlier versions results in 677 | " errors (E474). 678 | if has('patch-7.4-775') 679 | if g:jedi#popup_select_first 680 | set completeopt+=noinsert 681 | else 682 | set completeopt+=noselect 683 | endif 684 | else 685 | " To pass the tests we use this, it seems to get the closest to 686 | " the other options. I'm really not sure if this properly 687 | " works, but VIM 7.4-775 is already pretty old, so it might not 688 | " be a problem anymore in a few years. 689 | set completeopt+=longest 690 | endif 691 | endif 692 | elseif pumvisible() 693 | return "\" 694 | endif 695 | return "\\\=jedi#complete_opened(".a:autocomplete.")\" 696 | endfunction 697 | 698 | 699 | function! jedi#complete_opened(autocomplete) abort 700 | if a:autocomplete 701 | let &completeopt = s:saved_completeopt 702 | unlet s:saved_completeopt 703 | elseif pumvisible() && g:jedi#popup_select_first && stridx(&completeopt, 'longest') > -1 704 | return "\" 705 | endif 706 | return '' 707 | endfunction 708 | 709 | 710 | function! jedi#smart_auto_mappings() abort 711 | " Auto put import statement after from module.name and complete 712 | if search('\m^\s*from\s\+[A-Za-z0-9._]\{1,50}\%#\s*$', 'bcn', line('.')) 713 | " Enter character and start completion. 714 | return "\import \=jedi#complete_string(1)\" 715 | endif 716 | return "\" 717 | endfunction 718 | 719 | 720 | function! jedi#setup_completion() abort 721 | " We need our own omnifunc, so this overrides the omnifunc set by 722 | " $VIMRUNTIME/ftplugin/python.vim. 723 | setlocal omnifunc=jedi#completions 724 | 725 | " map ctrl+space for autocompletion 726 | if g:jedi#completions_command ==# '' 727 | " In terminals, sometimes equals . 728 | imap 729 | smap 730 | endif 731 | if len(g:jedi#completions_command) 732 | execute 'inoremap '.g:jedi#completions_command.' jedi#complete_string(0)' 733 | " A separate mapping for select mode: deletes and completes. 734 | execute 'snoremap '.g:jedi#completions_command." '\c'.jedi#complete_string(0)" 735 | endif 736 | endfunction 737 | 738 | "python3 jedi_vim.jedi.set_debug_function(jedi_vim.print_to_stdout, speed=True, warnings=False, notices=False) 739 | "python3 jedi_vim.jedi.set_debug_function(jedi_vim.print_to_stdout) 740 | 741 | " vim: set et ts=4: 742 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | status: 3 | project: true 4 | patch: true 5 | changes: true 6 | 7 | comment: off 8 | -------------------------------------------------------------------------------- /doc/jedi-vim.txt: -------------------------------------------------------------------------------- 1 | *jedi-vim.txt* - For Vim version 7.3 - Last change: 2014/07/29 2 | __ _______ _______ __ ____ ____ __ .___ ___.~ 3 | | | | ____|| \ | | \ \ / / | | | \/ |~ 4 | | | | |__ | .--. || | _____\ \/ / | | | \ / |~ 5 | .--. | | | __| | | | || | |______\ / | | | |\/| |~ 6 | | `--' | | |____ | '--' || | \ / | | | | | |~ 7 | \______/ |_______||_______/ |__| \__/ |__| |__| |__|~ 8 | 9 | jedi-vim - awesome Python autocompletion with Vim 10 | 11 | ============================================================================== 12 | Contents *jedi-vim-contents* 13 | 14 | 1. Introduction |jedi-vim-introduction| 15 | 2. Installation |jedi-vim-installation| 16 | 2.0. Requirements |jedi-vim-installation-requirements| 17 | 2.1. Manually |jedi-vim-installation-manually| 18 | 2.2. Using Pathogen |jedi-vim-installation-pathogen| 19 | 2.3. Using Vundle |jedi-vim-installation-vundle| 20 | 2.4. Installing from Repositories |jedi-vim-installation-repos| 21 | 3. Supported Python features |jedi-vim-support| 22 | 4. Usage |jedi-vim-usage| 23 | 5. Mappings |jedi-vim-keybindings| 24 | 5.1. Start completion |g:jedi#completions_command| 25 | 5.2. Go to definition |g:jedi#goto_command| 26 | 5.3. Go to assignment |g:jedi#goto_assignments_command| 27 | 5.4 Go to stub |g:jedi#goto_stubs_command| 28 | 5.5. Show documentation |g:jedi#documentation_command| 29 | 5.6. Rename variables |g:jedi#rename_command| 30 | 5.7. Rename variables (Reuse name) |g:jedi#rename_command_keep_name| 31 | 5.8. Show name usages |g:jedi#usages_command| 32 | 5.9. Open module by name |:Pyimport| 33 | 6. Configuration |jedi-vim-configuration| 34 | 6.1. auto_initialization |g:jedi#auto_initialization| 35 | 6.2. auto_vim_configuration |g:jedi#auto_vim_configuration| 36 | 6.3. popup_on_dot |g:jedi#popup_on_dot| 37 | 6.4. popup_select_first |g:jedi#popup_select_first| 38 | 6.5. auto_close_doc |g:jedi#auto_close_doc| 39 | 6.6. show_call_signatures |g:jedi#show_call_signatures| 40 | 6.7. show_call_signatures_delay |g:jedi#show_call_signatures_delay| 41 | 6.8. use_tabs_not_buffers |g:jedi#use_tabs_not_buffers| 42 | 6.9. squelch_py_warning |g:jedi#squelch_py_warning| 43 | 6.10. completions_enabled |g:jedi#completions_enabled| 44 | 6.11. use_splits_not_buffers |g:jedi#use_splits_not_buffers| 45 | 6.12. force_py_version |g:jedi#force_py_version| 46 | 6.13. smart_auto_mappings |g:jedi#smart_auto_mappings| 47 | 6.14. use_tag_stack |g:jedi#use_tag_stack| 48 | 6.15. environment_path |g:jedi#environment_path| 49 | |b:jedi_environment_path| 50 | 6.16. added_sys_path |g:jedi#added_sys_path| 51 | |b:jedi_added_sys_path| 52 | 6.17. case_insensitive_completion |g:jedi#case_insensitive_completion| 53 | |b:jedi_case_insensitive_completion| 54 | 7. Testing |jedi-vim-testing| 55 | 8. Contributing |jedi-vim-contributing| 56 | 9. License |jedi-vim-license| 57 | 58 | ============================================================================== 59 | 1. Introduction *jedi-vim-introduction* 60 | 61 | Jedi-vim is a Vim binding to the awesome Python autocompletion library 62 | `jedi`. Among jedi's (and, therefore, jedi-vim's) features are: 63 | 64 | - Completion for a wide array of Python features (see |jedi-vim-support|) 65 | - Robust in dealing with syntax errors and wrong indentation 66 | - Parses complex module/function/class structures 67 | - Infers function arguments from Sphinx/Epydoc strings 68 | - Doesn't execute Python code 69 | - Supports Virtualenv 70 | - Supports Python 2.7 and 3.4+ 71 | 72 | By leveraging this library, jedi-vim adds the following capabilities to Vim: 73 | 74 | - Displaying function/class bodies 75 | - "Go to definition" command 76 | - Displaying docstrings 77 | - Renaming and refactoring 78 | - Looking up related names 79 | 80 | ============================================================================== 81 | 2. Installation *jedi-vim-installation* 82 | 83 | ------------------------------------------------------------------------------ 84 | 2.0. Requirements *jedi-vim-installation-requirements* 85 | 86 | First of all, jedi-vim requires Vim to be compiled with the `+python` option. 87 | 88 | It is best if you have VIM >= 7.3, compiled with the `+conceal` option. With 89 | older versions, you will probably not see the parameter recommendation list 90 | for functions after typing the open bracket. Some platforms (including OS X 91 | releases) do not ship a VIM with `+conceal`. You can check if your VIM has the 92 | feature with > 93 | 94 | :ver 95 | 96 | and look for "`+conceal`" (as opposed to "`-conceal`") or > 97 | 98 | :echo has('conceal') 99 | 100 | which will report 0 (not included) or 1 (included). If your VIM lacks this 101 | feature and you would like function parameter completion, you will need to 102 | build your own VIM, or use a package for your operating system that has this 103 | feature (such as MacVim on OS X, which also contains a console binary). 104 | 105 | ------------------------------------------------------------------------------ 106 | 2.1. Installing manually *jedi-vim-installation-manually* 107 | 108 | 1. If you want to install jedi as a submodule instead, issue this command: > 109 | 110 | git clone --recursive http://github.com/davidhalter/jedi-vim 111 | 112 | 2. Put the plugin files into their respective folders in your vim runtime 113 | directory (usually ~/.vim). Be sure to pay attention to the directory 114 | structure! 115 | 3. Update the Vim help tags with > 116 | 117 | :helptags /doc 118 | 119 | ------------------------------------------------------------------------------ 120 | 2.2. Installing using Pathogen *jedi-vim-installation-pathogen* 121 | 122 | Pathogen simplifies installation considerably. 123 | 124 | 1.a Clone the git repository into your bundles directory: > 125 | 126 | git clone http://github.com/davidhalter/jedi-vim path/to/bundles/jedi-vim 127 | 128 | 1b. Again, if you want to install jedi as a submodule, use this command 129 | instead: > 130 | 131 | git clone --recursive http://github.com/davidhalter/jedi-vim 132 | 133 | ------------------------------------------------------------------------------ 134 | 2.3. Installing using Vundle *jedi-vim-installation-vundle* 135 | 136 | 1. Vundle automatically downloads subrepositories as git submodules, so you 137 | will automatically get the jedi library with the jedi-vim plugin. Add the 138 | following to the Bundles section in your .vimrc file: > 139 | 140 | Plugin 'davidhalter/jedi-vim' 141 | 142 | 2. Issue the following command in Vim: > 143 | 144 | :PluginInstall 145 | 146 | Help tags are generated automatically, so you should be good to go. 147 | 148 | ------------------------------------------------------------------------------ 149 | 2.4. Installing from Repositories *jedi-vim-installation-repos* 150 | 151 | Some Linux distributions have jedi-vim packages in their official 152 | repositories. On Arch Linux, install vim-jedi. On Debian (8+) or Ubuntu 153 | (14.04+) install vim-python-jedi. 154 | 155 | ============================================================================== 156 | 3. Supported Python features *jedi-vim-support* 157 | 158 | The Jedi library does all the hard work behind the scenes. It understands most 159 | Python features, among them: 160 | 161 | - Builtins 162 | - Multiple `return`s or `yield`s 163 | - Tuple assignments/array indexing/dictionary indexing 164 | - `with`-statement/exception handling 165 | - `*args` and `**kwargs` 166 | - Decorators, lambdas, closures 167 | - Generators, iterators 168 | - Some descriptors: `property`/`staticmethod`/`classmethod` 169 | - Some magic methods: `__call__`, `__iter__`, `__next__`, `__get__`, 170 | `__getitem__`, `__init__` 171 | - `list.append()`, `set.add()`, `list.extend()`, etc. 172 | - (Nested) list comprehensions and ternary expressions 173 | - Relative `import`s 174 | - `getattr()`/`__getattr__`/`__getattribute__` 175 | - Function annotations (py3k feature, are being ignored at the moment, but are 176 | parsed) 177 | - Class decorators (py3k feature, are being ignored at the moment, but are 178 | parsed) 179 | - Simple/usual `sys.path` modifications 180 | - `isinstance` checks for `if`/`while`/`assert` case, that doesn't work with 181 | Jedi 182 | - Stubs 183 | - And more... 184 | 185 | Note: This list is not necessarily up to date. For a complete list of 186 | features, please refer to the Jedi documentation at 187 | http://jedi.readthedocs.io. 188 | 189 | ============================================================================== 190 | 4. Usage *jedi-vim-usage* 191 | 192 | With the default settings, autocompletion can be triggered by typing 193 | . The first entry will automatically be selected, so you can press 194 | to insert it into your code or keep typing and narrow down your 195 | completion options. The usual and / keybindings work as 196 | well. Autocompletion is also triggered by typing a period in insert mode. 197 | Since periods rarely occur in Python code outside of method/import lookups, 198 | this is handy to have (but can be disabled). 199 | 200 | When it encounters a new module, jedi might take a few seconds to parse that 201 | module's contents. Afterwards, the contents are cached and completion will be 202 | almost instantaneous. 203 | 204 | ============================================================================== 205 | 5. Key Bindings *jedi-vim-keybindings* 206 | 207 | All keybindings can be mapped by setting the appropriate global option. For 208 | example, to set the keybinding for starting omnicompletion to instead of 209 | , add the following setting to your .vimrc file: > 210 | 211 | let g:jedi#completions_command = "" 212 | 213 | Note: If you have |g:jedi#auto_initialization| set to 0, you have to create 214 | a mapping yourself by calling a function: > 215 | 216 | " Using for omnicompletion 217 | inoremap 218 | " Use r (by default <\-r>) for renaming 219 | nnoremap r :call jedi#rename() 220 | " etc. 221 | 222 | Note: You can set commands to '', which means that they are empty and not 223 | assigned. It's an easy way to "disable" functionality of jedi-vim. 224 | 225 | ------------------------------------------------------------------------------ 226 | 5.1. `g:jedi#completions_command` *g:jedi#completions_command* 227 | Function: n/a; see above 228 | Default: Start completion 229 | 230 | Performs autocompletion (or omnicompletion, to be precise). 231 | 232 | Note: If you want to use for completion, please install Supertab: 233 | https://github.com/ervandew/supertab. 234 | 235 | ------------------------------------------------------------------------------ 236 | 5.2. `g:jedi#goto_command` *g:jedi#goto_command* 237 | Function: `jedi#goto()` 238 | Default: d Go to definition (or assignment) 239 | 240 | This function first tries |jedi#goto_definitions|, and falls back to 241 | |jedi#goto_assignments| for builtin modules. It produces an error if nothing 242 | could be found. 243 | NOTE: this implementation is subject to change. 244 | Ref: https://github.com/davidhalter/jedi/issues/570 245 | 246 | This command tries to find the original definition of the function/class under 247 | the cursor. Just like the `jedi#goto_assignments()` function, it does not work 248 | if the definition isn't in a Python source file. 249 | 250 | The difference between `jedi#goto_assignments()` and `jedi#goto_definitions()` 251 | is that the latter performs recursive lookups. Take, for example, the 252 | following module structure: > 253 | 254 | # file1.py: 255 | from file2 import foo 256 | 257 | # file2.py: 258 | from file3 import bar as foo 259 | 260 | # file3.py 261 | def bar(): 262 | pass 263 | 264 | The `jedi#goto_assignments()` function will take you to the > 265 | 266 | from file2 import foo 267 | 268 | statement in file1.py, while the `jedi#goto_definitions()` function will take 269 | you all the way to the > 270 | 271 | def bar(): 272 | 273 | line in file3.py. 274 | 275 | ------------------------------------------------------------------------------ 276 | 5.3. `g:jedi#goto_assignments_command` *g:jedi#goto_assignments_command* 277 | Function: `jedi#goto_assignments()` 278 | Default: g Go to assignment 279 | 280 | This function finds the first definition of the function/class under the 281 | cursor. It produces an error if the definition is not in a Python file. 282 | 283 | ------------------------------------------------------------------------------ 284 | 5.4. `g:jedi#goto_stubs_command` *g:jedi#goto_stubs_command* 285 | Function: `jedi#goto_stubs()` 286 | Default: s Go to stub 287 | 288 | Finds the stub of the function/class under the cursor. 289 | 290 | ------------------------------------------------------------------------------ 291 | 5.5. `g:jedi#documentation_command` *g:jedi#documentation_command* 292 | Function: `jedi#show_documentation()` 293 | Default: Show pydoc documentation 294 | 295 | This shows the pydoc documentation for the item currently under the cursor. 296 | The documentation is opened in a horizontally split buffer. The height of this 297 | buffer is controlled by `g:jedi#max_doc_height` (set by default to 30). 298 | 299 | ------------------------------------------------------------------------------ 300 | 5.6. `g:jedi#rename_command` *g:jedi#rename_command* 301 | Function: `jedi#rename()` 302 | Default: r Rename variables 303 | 304 | Jedi-vim deletes the word currently under the cursor and puts Vim in insert 305 | mode, where the user is expected to enter the new variable name. Upon leaving 306 | insert mode, jedi-vim then renames all occurrences of the old variable name 307 | with the new one. The number of performed renames is displayed in the command 308 | line. 309 | 310 | ------------------------------------------------------------------------------ 311 | 5.7. `g:jedi#rename_command_keep_name` *g:jedi#rename_command_keep_name* 312 | Function: `jedi#rename()` 313 | Default: R Rename variables 314 | (This key mapping does not delete the word under the cursor) 315 | 316 | Jedi-vim keeps the word currently under the cursor, moves the cursor to the end 317 | of the word, and puts Vim in insert mode, where the user is expected to enter 318 | the new variable name. Upon leaving insert mode, Jedi-vim then renames all 319 | occurrences of the old variable name with the new one. The number of performed 320 | renames is displayed in the command line. 321 | 322 | ------------------------------------------------------------------------------ 323 | 5.8. `g:jedi#usages_command` *g:jedi#usages_command* 324 | Function: `jedi#usages()` 325 | Default: n Show usages of a name. 326 | 327 | The quickfix window is populated with a list of all names which point to the 328 | definition of the name under the cursor. 329 | 330 | ------------------------------------------------------------------------------ 331 | 5.9. Open module by name *:Pyimport* 332 | Function: `jedi#py_import(args)` 333 | Default: :Pyimport e.g. `:Pyimport os` shows os.py in VIM. 334 | 335 | Simulate an import and open that module in VIM. 336 | 337 | ============================================================================== 338 | 6. Configuration *jedi-vim-configuration* 339 | 340 | Note: You currently have to set these options in your .vimrc. Setting them in 341 | an ftplugin (e.g. ~/.vim/ftplugin/python/jedi-vim-settings.vim) will not work 342 | because jedi-vim is not set up as an filetype plugin, but as a "regular" 343 | plugin. 344 | 345 | ------------------------------------------------------------------------------ 346 | 6.1. `g:jedi#auto_initialization` *g:jedi#auto_initialization* 347 | 348 | Upon initialization, jedi-vim performs the following steps: 349 | 350 | 1. Set the current buffers 'omnifunc' to its own completion function 351 | `jedi#completions` 352 | 2. Create mappings to commands specified in |jedi-vim-keybindings| 353 | 3. Call `jedi#configure_call_signatures()` if 354 | `g:jedi#show_call_signatures` is set 355 | 356 | You can disable the default initialization routine by setting this option to 357 | 0. Beware that you have to perform the above steps yourself, though. 358 | 359 | Options: 0 or 1 360 | Default: 1 (Perform automatic initialization) 361 | 362 | ------------------------------------------------------------------------------ 363 | 6.2. `g:jedi#auto_vim_configuration` *g:jedi#auto_vim_configuration* 364 | 365 | Jedi-vim sets 'completeopt' to `menuone,longest` and `popup` (for Vim version 366 | numbers higher than 8.1.1882) respectively `preview` by default, if 367 | 'completeopt' is not changed from Vim's default. 368 | It also remaps to in insert mode. 369 | 370 | If you want to keep your own configuration, disable this setting. 371 | 372 | Options: 0 or 1 373 | Default: 1 (Set 'completeopt' and mapping as described above) 374 | 375 | ------------------------------------------------------------------------------ 376 | 6.3. `g:jedi#popup_on_dot` *g:jedi#popup_on_dot* 377 | 378 | Jedi-vim automatically starts completion upon typing a period in insert mode. 379 | 380 | However, when working with large modules, this can slow down your typing flow 381 | since you have to wait for jedi to parse the module and show the completion 382 | menu. By disabling this setting, completion is only started when you manually 383 | press the completion key. 384 | You need to also have `g:jedi#completions_enabled` enabled for this. 385 | 386 | Options: 0 or 1 387 | Default: 1 (Start completion on typing a period) 388 | 389 | ------------------------------------------------------------------------------ 390 | 6.4. `g:jedi#popup_select_first` *g:jedi#popup_select_first* 391 | 392 | Upon starting completion, jedi-vim can automatically select the first entry 393 | that pops up (without actually inserting it). 394 | 395 | This leads to a better typing flow: As you type more characters, the entries 396 | in the completion menu are narrowed down. If they are narrowed down enough, 397 | you can just press to insert the first match. 398 | 399 | Options: 0 or 1 400 | Default: 1 (Automatically select first completion entry) 401 | 402 | ------------------------------------------------------------------------------ 403 | 6.5. `g:jedi#auto_close_doc` *g:jedi#auto_close_doc* 404 | 405 | When doing completion and jedi-vim shows the docstring of the currently selected 406 | item in a preview (not a popup) window, this window is being closed after 407 | insertion of a completion item. 408 | 409 | Set this to 0 to leave the preview window open even after leaving insert mode. 410 | This could be useful if you want to browse longer docstrings. 411 | 412 | This setting is ignored if a popup instead of a preview window is used. 413 | 414 | Options: 0 or 1 415 | Default: 1 (Automatically close preview window upon leaving insert mode) 416 | 417 | ------------------------------------------------------------------------------ 418 | 6.6. `g:jedi#show_call_signatures` *g:jedi#show_call_signatures* 419 | 420 | Jedi-vim can display a small window detailing the arguments of the currently 421 | completed function and highlighting the currently selected argument. This can 422 | be disabled by setting this option to 0. Setting this option to 2 shows call 423 | signatures in the command line instead of a popup window. 424 | 425 | Options: 0, 1, or 2 426 | Default: 1 (Show call signatures window) 427 | 428 | Note: 'showmode' must be disabled for command line call signatures to be 429 | visible. 430 | 431 | Note: This setting is ignored if |g:jedi#auto_initialization| is set to 0. In 432 | that case, if you want to see call signatures, you have to set it up 433 | manually by calling a function in your configuration file: > 434 | 435 | call jedi#configure_call_signatures() 436 | 437 | ------------------------------------------------------------------------------ 438 | 6.7. `g:jedi#show_call_signatures_delay` *g:jedi#show_call_signatures_delay* 439 | 440 | The delay to be used with |g:jedi#show_call_signatures|. If it is greater 441 | than 0 it will use Vim's |CursorHoldI| event instead of |CursorMovedI|. 442 | It will temporarily set Vim's |'updatetime'| option during insert mode. 443 | 444 | Options: delay in milliseconds 445 | Default: 500 446 | 447 | ------------------------------------------------------------------------------ 448 | 6.8. `g:jedi#use_tabs_not_buffers` *g:jedi#use_tabs_not_buffers* 449 | 450 | You can make jedi-vim open a new tab if you use the "go to", "show 451 | definition", or "related names" commands. When you leave this at the default 452 | (0), they open in the current window instead. 453 | 454 | Options: 0 or 1 455 | Default: 0 (Command output reuses current window) 456 | 457 | ------------------------------------------------------------------------------ 458 | 6.9. `g:jedi#squelch_py_warning` *g:jedi#squelch_py_warning* 459 | 460 | When Vim has not been compiled with +python, jedi-vim shows a warning to that 461 | effect and aborts loading itself. Set this to 1 to suppress that warning. 462 | 463 | Options: 0 or 1 464 | Default: 0 (Warning is shown) 465 | 466 | ------------------------------------------------------------------------------ 467 | 6.10. `g:jedi#completions_enabled` *g:jedi#completions_enabled* 468 | 469 | If you don't want Jedi completion, but all the other features, you can disable 470 | it in favor of another completion engine (that probably also uses Jedi, like 471 | YCM). 472 | 473 | Options: 0 or 1 474 | Default: 1 475 | 476 | ------------------------------------------------------------------------------ 477 | 6.11. `g:jedi#use_splits_not_buffers` *g:jedi#use_splits_not_buffers* 478 | 479 | If you want to open new split for "go to", you could set this option to the 480 | direction which you want to open a split with. 481 | 482 | Options: top, left, right, bottom or winwidth 483 | Default: "" (not enabled by default) 484 | 485 | Note: with the 'winwidth' option the window is split vertically or horizontally 486 | depending on the width of the window relative to 'textwidth'. This essentially 487 | means that if the window is big enough it will be split vertically but if it is 488 | small a horizontal split happens. 489 | 490 | ------------------------------------------------------------------------------ 491 | 6.12. `g:jedi#force_py_version` *g:jedi#force_py_version* 492 | 493 | If you have installed multiple Python versions, you can force the Python 494 | version that is going to be used. 495 | You don't have to compile VIM with multiple Python versions. 496 | The variable can be set in the .vimrc like this to force python 2: 497 | 498 | let g:jedi#force_py_version = 2 499 | 500 | By default jedi loads the latest Python version installed on your system that 501 | can be found. 502 | 503 | This variable can be changed during runtime. 504 | 505 | Options: 2, 2.7, 3, 3.5, 3.6, ... 506 | Default: "auto" 507 | ------------------------------------------------------------------------------ 508 | 6.13. `g:jedi#smart_auto_mappings` *g:jedi#smart_auto_mappings* 509 | 510 | When you start typing `from module.name` jedi-vim automatically 511 | can add the "import" statement and trigger the autocompletion popup. 512 | 513 | You can enable this using: > 514 | 515 | let g:jedi#smart_auto_mappings = 1 516 | < 517 | Options: 0 or 1 518 | Default: 0 (disabled by default) 519 | 520 | ------------------------------------------------------------------------------ 521 | 6.14. `g:jedi#use_tag_stack` *g:jedi#use_tag_stack* 522 | 523 | Write results of |jedi#goto| to a temporary file and use the |:tjump| command 524 | to enable full |tagstack| functionality. Use of the tag stack allows 525 | returning to the usage of a function with CTRL-T after exploring the 526 | definition with arbitrary changes to the |jumplist|. 527 | 528 | Options: 0 or 1 529 | Default: 1 (enabled by default) 530 | 531 | ------------------------------------------------------------------------------ 532 | 6.15. `g:jedi#environment_path` *g:jedi#environment_path* 533 | *b:jedi_environment_path* 534 | 535 | To use a specific virtualenv or a specific Python version it is possible to 536 | set an interpreter. 537 | 538 | Both setting the directory and setting a project is working. 539 | 540 | Examples: "/usr/bin/python3.9", "venv", "../venv", "../venv/bin/python" 541 | 542 | The buffer-local variable `b:jedi_environment_path` can be used to override the 543 | global variable `g:jedi#environment_path`. 544 | 545 | Default: "auto" 546 | 547 | ------------------------------------------------------------------------------ 548 | 6.16. `g:jedi#added_sys_path` *g:jedi#added_sys_path* 549 | *b:jedi_added_sys_path* 550 | 551 | To add extra sys_path. 552 | 553 | The buffer-local variable `b:jedi_added_sys_path` can be used to add 554 | additional extra sys_path. 555 | 556 | Examples: ["../site-packages"] 557 | Default: [] 558 | 559 | ------------------------------------------------------------------------------ 560 | 6.17. `g:jedi#case_insensitive_completion` *g:jedi#case_insensitive_completion* 561 | *b:jedi_case_insensitive_completion* 562 | 563 | 0 to disable case insensitive completion. 564 | 1 to enable case insensitive completion (default). 565 | 566 | The buffer-local variable `b:jedi_case_insensitive_completion` can be used to 567 | override the global variable `g:jedi#case_insensitive_completion`. 568 | 569 | Default: 1 570 | 571 | ============================================================================== 572 | 7. Testing *jedi-vim-testing* 573 | 574 | jedi-vim is being tested with a combination of vspec 575 | https://github.com/kana/vim-vspec and py.test http://pytest.org/. 576 | 577 | The tests are in the test subdirectory, you can run them calling:: 578 | 579 | py.test 580 | 581 | The tests are automatically run with `travis 582 | `_. 583 | 584 | ============================================================================== 585 | 8. Contributing *jedi-vim-contributing* 586 | 587 | We love Pull Requests! Read the instructions in `CONTRIBUTING.md`. 588 | 589 | ============================================================================== 590 | 9. License *jedi-vim-license* 591 | 592 | Jedi-vim is licensed with the MIT license. 593 | 594 | vim: textwidth=78 et filetype=help:norightleft: 595 | -------------------------------------------------------------------------------- /doc/logotype-a.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 | 28 | 30 | 31 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 130 | 132 | 133 | 134 | 135 | 136 | 138 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /ftplugin/python/jedi.vim: -------------------------------------------------------------------------------- 1 | if !jedi#init_python() 2 | finish 3 | endif 4 | " ------------------------------------------------------------------------ 5 | " Initialization of jedi-vim 6 | " ------------------------------------------------------------------------ 7 | 8 | if g:jedi#auto_initialization 9 | " goto / get_definition / usages 10 | if len(g:jedi#goto_command) 11 | execute 'nnoremap '.g:jedi#goto_command.' :call jedi#goto()' 12 | endif 13 | if len(g:jedi#goto_assignments_command) 14 | execute 'nnoremap '.g:jedi#goto_assignments_command.' :call jedi#goto_assignments()' 15 | endif 16 | if len(g:jedi#goto_definitions_command) 17 | execute 'nnoremap '.g:jedi#goto_definitions_command.' :call jedi#goto_definitions()' 18 | endif 19 | if len(g:jedi#goto_stubs_command) 20 | execute 'nnoremap '.g:jedi#goto_stubs_command.' :call jedi#goto_stubs()' 21 | endif 22 | if len(g:jedi#usages_command) 23 | execute 'nnoremap '.g:jedi#usages_command.' :call jedi#usages()' 24 | endif 25 | " rename 26 | if len(g:jedi#rename_command) 27 | execute 'nnoremap '.g:jedi#rename_command.' :call jedi#rename()' 28 | execute 'vnoremap '.g:jedi#rename_command.' :call jedi#rename_visual()' 29 | endif 30 | if len(g:jedi#rename_command_keep_name) 31 | execute 'nnoremap '.g:jedi#rename_command_keep_name.' :call jedi#rename_keep_name()' 32 | execute 'vnoremap '.g:jedi#rename_command_keep_name.' :call jedi#rename_visual_keep_name()' 33 | endif 34 | " documentation/pydoc 35 | if len(g:jedi#documentation_command) 36 | execute 'nnoremap '.g:jedi#documentation_command.' :call jedi#show_documentation()' 37 | endif 38 | 39 | if g:jedi#show_call_signatures > 0 40 | call jedi#configure_call_signatures() 41 | endif 42 | 43 | if g:jedi#completions_enabled == 1 44 | inoremap . .=jedi#complete_string(1) 45 | endif 46 | 47 | if g:jedi#smart_auto_mappings == 1 48 | inoremap =jedi#smart_auto_mappings() 49 | end 50 | 51 | if g:jedi#auto_close_doc && (&g:completeopt =~# '\' && &g:completeopt !~# '\') 52 | " close preview if its still open after insert 53 | augroup jedi_preview 54 | if v:version > 704 55 | autocmd CompleteDone pclose 56 | else 57 | autocmd InsertLeave if pumvisible() == 0|pclose|endif 58 | autocmd CursorMovedI if pumvisible() == 0|pclose|endif 59 | endif 60 | augroup END 61 | endif 62 | endif 63 | -------------------------------------------------------------------------------- /plugin/jedi.vim: -------------------------------------------------------------------------------- 1 | "jedi-vim - Omni Completion for python in vim 2 | " Maintainer: David Halter 3 | " 4 | " This part of the software is just the vim interface. The really big deal is 5 | " the Jedi Python library. 6 | 7 | if get(g:, 'jedi#auto_vim_configuration', 1) 8 | " jedi-vim doesn't work in compatible mode (vim script syntax problems) 9 | if &compatible 10 | " vint: -ProhibitSetNoCompatible 11 | set nocompatible 12 | " vint: +ProhibitSetNoCompatible 13 | endif 14 | 15 | " jedi-vim really needs, otherwise jedi-vim cannot start. 16 | filetype plugin on 17 | 18 | augroup jedi_pyi 19 | au! 20 | autocmd BufNewFile,BufRead *.pyi set filetype=python 21 | augroup END 22 | 23 | " Change completeopt, but only if it was not set already. 24 | " This gets done on VimEnter, since otherwise Vim fails to restore the 25 | " screen. Neovim is not affected, this is likely caused by using 26 | " :redir/execute() before the (alternate) terminal is configured. 27 | function! s:setup_completeopt() 28 | if exists('*execute') 29 | let completeopt = execute('silent verb set completeopt?') 30 | else 31 | redir => completeopt 32 | silent verb set completeopt? 33 | redir END 34 | endif 35 | if len(split(completeopt, '\n')) == 1 36 | set completeopt=menuone,longest 37 | if v:version > 801 || (v:version == 801 && has('patch-8.1.1882')) 38 | set completeopt+=popup 39 | else 40 | set completeopt+=preview 41 | endif 42 | endif 43 | endfunction 44 | if has('nvim') 45 | call s:setup_completeopt() 46 | else 47 | augroup jedi_startup 48 | au! 49 | autocmd VimEnter * call s:setup_completeopt() 50 | augroup END 51 | endif 52 | 53 | if len(mapcheck('', 'i')) == 0 54 | inoremap 55 | endif 56 | endif 57 | 58 | " Pyimport command 59 | command! -nargs=1 -complete=custom,jedi#py_import_completions Pyimport :call jedi#py_import() 60 | 61 | command! -nargs=? -complete=file JediChooseEnvironment :call jedi#choose_environment() 62 | command! -nargs=? -complete=file JediLoadProject :call jedi#load_project() 63 | 64 | 65 | function! s:jedi_debug_info() 66 | " Ensure the autoload file has been loaded (and ignore any errors, which 67 | " will be displayed with the debug info). 68 | let unset = {} 69 | let saved_squelch_py_warning = get(g:, 'jedi#squelch_py_warning', unset) 70 | let g:jedi#squelch_py_warning = 1 71 | call jedi#init_python() 72 | if saved_squelch_py_warning is unset 73 | unlet g:jedi#squelch_py_warning 74 | else 75 | let g:jedi#squelch_py_warning = saved_squelch_py_warning 76 | endif 77 | call jedi#debug_info() 78 | endfunction 79 | command! -nargs=0 -bar JediDebugInfo call s:jedi_debug_info() 80 | command! -nargs=0 -bang JediClearCache call jedi#clear_cache(0) 81 | 82 | " vim: set et ts=4: 83 | -------------------------------------------------------------------------------- /pythonx/jedi_vim.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | The Python parts of the Jedi library for VIM. It is mostly about communicating 4 | with VIM. 5 | """ 6 | 7 | from typing import Optional 8 | import traceback # for exception output 9 | import re 10 | import os 11 | import sys 12 | from shlex import split as shsplit 13 | from contextlib import contextmanager 14 | from pathlib import Path 15 | try: 16 | from itertools import zip_longest 17 | except ImportError: 18 | from itertools import izip_longest as zip_longest # Python 2 19 | 20 | import vim 21 | 22 | is_py3 = sys.version_info[0] >= 3 23 | if is_py3: 24 | ELLIPSIS = "…" 25 | unicode = str 26 | else: 27 | ELLIPSIS = u"…" 28 | 29 | 30 | try: 31 | # Somehow sys.prefix is set in combination with VIM and virtualenvs. 32 | # However the sys path is not affected. Just reset it to the normal value. 33 | sys.prefix = sys.base_prefix 34 | sys.exec_prefix = sys.base_exec_prefix 35 | except AttributeError: 36 | # If we're not in a virtualenv we don't care. Everything is fine. 37 | pass 38 | 39 | 40 | class PythonToVimStr(unicode): 41 | """ Vim has a different string implementation of single quotes """ 42 | __slots__ = [] 43 | 44 | def __new__(cls, obj, encoding='UTF-8'): 45 | if not (is_py3 or isinstance(obj, unicode)): 46 | obj = unicode.__new__(cls, obj, encoding) 47 | 48 | # Vim cannot deal with zero bytes: 49 | obj = obj.replace('\0', '\\0') 50 | return unicode.__new__(cls, obj) 51 | 52 | def __repr__(self): 53 | # this is totally stupid and makes no sense but vim/python unicode 54 | # support is pretty bad. don't ask how I came up with this... It just 55 | # works... 56 | # It seems to be related to that bug: http://bugs.python.org/issue5876 57 | if unicode is str: 58 | s = self 59 | else: 60 | s = self.encode('UTF-8') 61 | return '"%s"' % s.replace('\\', '\\\\').replace('"', r'\"') 62 | 63 | 64 | class VimError(Exception): 65 | def __init__(self, message, throwpoint, executing): 66 | super(type(self), self).__init__(message) 67 | self.message = message 68 | self.throwpoint = throwpoint 69 | self.executing = executing 70 | 71 | def __str__(self): 72 | return "{}; created by {!r} (in {})".format( 73 | self.message, self.executing, self.throwpoint 74 | ) 75 | 76 | 77 | def _catch_exception(string, is_eval): 78 | """ 79 | Interface between vim and python calls back to it. 80 | Necessary, because the exact error message is not given by `vim.error`. 81 | """ 82 | result = vim.eval('jedi#_vim_exceptions({0}, {1})'.format( 83 | repr(PythonToVimStr(string, 'UTF-8')), int(is_eval))) 84 | if 'exception' in result: 85 | raise VimError(result['exception'], result['throwpoint'], string) 86 | return result['result'] 87 | 88 | 89 | def vim_command(string): 90 | _catch_exception(string, is_eval=False) 91 | 92 | 93 | def vim_eval(string): 94 | return _catch_exception(string, is_eval=True) 95 | 96 | 97 | def no_jedi_warning(error=None): 98 | vim.command('echohl WarningMsg') 99 | vim.command('echom "Please install Jedi if you want to use jedi-vim."') 100 | if error: 101 | vim.command('echom "The error was: {0}"'.format(error)) 102 | vim.command('echohl None') 103 | 104 | 105 | def echo_highlight(msg): 106 | vim_command('echohl WarningMsg | echom "jedi-vim: {0}" | echohl None'.format( 107 | str(msg).replace('"', '\\"'))) 108 | 109 | 110 | jedi_path = os.path.join(os.path.dirname(__file__), 'jedi') 111 | sys.path.insert(0, jedi_path) 112 | parso_path = os.path.join(os.path.dirname(__file__), 'parso') 113 | sys.path.insert(0, parso_path) 114 | 115 | try: 116 | import jedi 117 | except ImportError: 118 | jedi = None 119 | jedi_import_error = sys.exc_info() 120 | else: 121 | try: 122 | version = jedi.__version__ 123 | except Exception as e: # e.g. AttributeError 124 | echo_highlight( 125 | "Error when loading the jedi python module ({0}). " 126 | "Please ensure that Jedi is installed correctly (see Installation " 127 | "in the README.".format(e)) 128 | jedi = None 129 | else: 130 | if isinstance(version, str): 131 | # the normal use case, now. 132 | from jedi import utils 133 | version = utils.version_info() 134 | if version < (0, 7): 135 | echo_highlight('Please update your Jedi version, it is too old.') 136 | finally: 137 | sys.path.remove(jedi_path) 138 | sys.path.remove(parso_path) 139 | 140 | 141 | class VimCompat: 142 | _eval_cache = {} 143 | _func_cache = {} 144 | 145 | @classmethod 146 | def has(cls, what): 147 | try: 148 | return cls._eval_cache[what] 149 | except KeyError: 150 | ret = cls._eval_cache[what] = cls.call('has', what) 151 | return ret 152 | 153 | @classmethod 154 | def call(cls, func, *args): 155 | try: 156 | f = cls._func_cache[func] 157 | except KeyError: 158 | if IS_NVIM: 159 | f = cls._func_cache[func] = getattr(vim.funcs, func) 160 | else: 161 | f = cls._func_cache[func] = vim.Function(func) 162 | return f(*args) 163 | 164 | @classmethod 165 | def setqflist(cls, items, title, context): 166 | if cls.has('patch-7.4.2200'): # can set qf title. 167 | what = {'title': title} 168 | if cls.has('patch-8.0.0590'): # can set qf context 169 | what['context'] = {'jedi_usages': context} 170 | if cls.has('patch-8.0.0657'): # can set items via "what". 171 | what['items'] = items 172 | cls.call('setqflist', [], ' ', what) 173 | else: 174 | # Can set title (and maybe context), but needs two calls. 175 | cls.call('setqflist', items) 176 | cls.call('setqflist', items, 'a', what) 177 | else: 178 | cls.call('setqflist', items) 179 | 180 | @classmethod 181 | def setqflist_title(cls, title): 182 | if cls.has('patch-7.4.2200'): 183 | cls.call('setqflist', [], 'a', {'title': title}) 184 | 185 | @classmethod 186 | def can_update_current_qflist_for_context(cls, context): 187 | if cls.has('patch-8.0.0590'): # can set qf context 188 | return cls.call('getqflist', {'context': 1})['context'] == { 189 | 'jedi_usages': context, 190 | } 191 | 192 | 193 | def catch_and_print_exceptions(func): 194 | def wrapper(*args, **kwargs): 195 | try: 196 | return func(*args, **kwargs) 197 | except (Exception, vim.error): 198 | print(traceback.format_exc()) 199 | return None 200 | return wrapper 201 | 202 | 203 | def _check_jedi_availability(show_error=False): 204 | def func_receiver(func): 205 | def wrapper(*args, **kwargs): 206 | if jedi is None: 207 | if show_error: 208 | no_jedi_warning() 209 | return 210 | else: 211 | return func(*args, **kwargs) 212 | return wrapper 213 | return func_receiver 214 | 215 | 216 | # Tuple of cache key / project 217 | _current_project_cache = None, None 218 | 219 | 220 | def get_project(): 221 | vim_environment_path = vim_eval( 222 | "get(b:, 'jedi_environment_path', g:jedi#environment_path)" 223 | ) 224 | vim_project_path = vim_eval("g:jedi#project_path") 225 | 226 | vim_added_sys_path = vim_eval("get(g:, 'jedi#added_sys_path', [])") 227 | vim_added_sys_path += vim_eval("get(b:, 'jedi_added_sys_path', [])") 228 | 229 | global _current_project_cache 230 | cache_key = dict(project_path=vim_project_path, 231 | environment_path=vim_environment_path, 232 | added_sys_path=vim_added_sys_path) 233 | if cache_key == _current_project_cache[0]: 234 | return _current_project_cache[1] 235 | 236 | if vim_environment_path in ("auto", "", None): 237 | environment_path = None 238 | else: 239 | environment_path = vim_environment_path 240 | 241 | if vim_project_path in ("auto", "", None): 242 | project_path = jedi.get_default_project().path 243 | else: 244 | project_path = vim_project_path 245 | 246 | project = jedi.Project(project_path, 247 | environment_path=environment_path, 248 | added_sys_path=vim_added_sys_path) 249 | 250 | _current_project_cache = cache_key, project 251 | return project 252 | 253 | 254 | @catch_and_print_exceptions 255 | def choose_environment(): 256 | args = shsplit(vim.eval('a:args')) 257 | 258 | envs = list(jedi.find_system_environments()) 259 | envs.extend(jedi.find_virtualenvs(paths=args or None)) 260 | 261 | env_paths = [env.executable for env in envs] 262 | 263 | vim_command('belowright new') 264 | vim.current.buffer[:] = env_paths 265 | vim.current.buffer.name = "Hit Enter to Choose an Environment" 266 | vim_command( 267 | 'setlocal buftype=nofile bufhidden=wipe noswapfile nobuflisted readonly nomodifiable') 268 | vim_command('noremap :bw') 269 | vim_command('noremap :python3 jedi_vim.choose_environment_hit_enter()') 270 | 271 | 272 | @catch_and_print_exceptions 273 | def choose_environment_hit_enter(): 274 | vim.vars['jedi#environment_path'] = vim.current.line 275 | vim_command('bd') 276 | 277 | 278 | @catch_and_print_exceptions 279 | def load_project(): 280 | path = vim.eval('a:args') 281 | vim.vars['jedi#project_path'] = path 282 | env_path = vim_eval("g:jedi#environment_path") 283 | if env_path == 'auto': 284 | env_path = None 285 | if path: 286 | try: 287 | project = jedi.Project.load(path) 288 | except FileNotFoundError: 289 | project = jedi.Project(path, environment_path=env_path) 290 | project.save() 291 | else: 292 | project = jedi.get_default_project() 293 | path = project.path 294 | project.save() 295 | 296 | global _current_project_cache 297 | cache_key = dict(project_path=path, 298 | environment_path=env_path, 299 | added_sys_path=[]) 300 | _current_project_cache = cache_key, project 301 | 302 | 303 | @catch_and_print_exceptions 304 | def get_script(source=None): 305 | jedi.settings.additional_dynamic_modules = [ 306 | b.name for b in vim.buffers if ( 307 | b.name is not None and 308 | b.name.endswith('.py') and 309 | b.options['buflisted'])] 310 | if source is None: 311 | source = '\n'.join(vim.current.buffer) 312 | buf_path = vim.current.buffer.name 313 | if not buf_path: 314 | # If a buffer has no name its name is an empty string. 315 | buf_path = None 316 | 317 | return jedi.Script(source, path=buf_path, project=get_project()) 318 | 319 | 320 | def get_pos(column=None): 321 | row = vim.current.window.cursor[0] 322 | if column is None: 323 | column = vim.current.window.cursor[1] 324 | return row, column 325 | 326 | 327 | @_check_jedi_availability(show_error=False) 328 | @catch_and_print_exceptions 329 | def completions(): 330 | jedi.settings.case_insensitive_completion = \ 331 | bool(int(vim_eval("get(b:, 'jedi_case_insensitive_completion', " 332 | "g:jedi#case_insensitive_completion)"))) 333 | 334 | row, column = vim.current.window.cursor 335 | # Clear call signatures in the buffer so they aren't seen by the completer. 336 | # Call signatures in the command line can stay. 337 | if int(vim_eval("g:jedi#show_call_signatures")) == 1: 338 | clear_call_signatures() 339 | if vim.eval('a:findstart') == '1': 340 | count = 0 341 | for char in reversed(vim.current.line[:column]): 342 | if not re.match(r'[\w\d]', char): 343 | break 344 | count += 1 345 | vim.command('return %i' % (column - count)) 346 | else: 347 | base = vim.eval('a:base') 348 | source = '' 349 | for i, line in enumerate(vim.current.buffer): 350 | # enter this path again, otherwise source would be incomplete 351 | if i == row - 1: 352 | source += line[:column] + base + line[column:] 353 | else: 354 | source += line 355 | source += '\n' 356 | # here again hacks, because jedi has a different interface than vim 357 | column += len(base) 358 | try: 359 | script = get_script(source=source) 360 | completions = script.complete(*get_pos(column)) 361 | signatures = script.get_signatures(*get_pos(column)) 362 | 363 | add_info = \ 364 | any(option in vim.eval("&completeopt").split(",") 365 | for option in ("preview", "popup")) 366 | out = [] 367 | for c in completions: 368 | d = dict(word=PythonToVimStr(c.name[:len(base)] + c.complete), 369 | abbr=PythonToVimStr(c.name_with_symbols), 370 | # stuff directly behind the completion 371 | menu=PythonToVimStr(c.description), 372 | icase=1, # case insensitive 373 | dup=1 # allow duplicates (maybe later remove this) 374 | ) 375 | if add_info: 376 | try: 377 | d["info"] = PythonToVimStr(c.docstring()) 378 | except Exception: 379 | print("jedi-vim: error with docstring for %r: %s" % ( 380 | c, traceback.format_exc())) 381 | out.append(d) 382 | 383 | strout = str(out) 384 | except Exception: 385 | # print to stdout, will be in :messages 386 | print(traceback.format_exc()) 387 | strout = '' 388 | completions = [] 389 | signatures = [] 390 | 391 | show_call_signatures(signatures) 392 | vim.command('return ' + strout) 393 | 394 | 395 | @contextmanager 396 | def tempfile(content): 397 | # Using this instead of the tempfile module because Windows won't read 398 | # from a file not yet written to disk 399 | with open(vim_eval('tempname()'), 'w') as f: 400 | f.write(content) 401 | try: 402 | yield f 403 | finally: 404 | os.unlink(f.name) 405 | 406 | 407 | @_check_jedi_availability(show_error=True) 408 | @catch_and_print_exceptions 409 | def goto(mode="goto"): 410 | """ 411 | :param str mode: "definition", "assignment", "goto" 412 | :rtype: list of jedi.api.classes.Name 413 | """ 414 | script = get_script() 415 | pos = get_pos() 416 | if mode == "goto": 417 | names = script.goto(*pos, follow_imports=True) 418 | elif mode == "definition": 419 | names = script.infer(*pos) 420 | elif mode == "assignment": 421 | names = script.goto(*pos) 422 | elif mode == "stubs": 423 | names = script.goto(*pos, follow_imports=True, only_stubs=True) 424 | 425 | if not names: 426 | echo_highlight("Couldn't find any definitions for this.") 427 | elif len(names) == 1 and mode != "related_name": 428 | n = list(names)[0] 429 | _goto_specific_name(n) 430 | else: 431 | show_goto_multi_results(names, mode) 432 | return names 433 | 434 | 435 | def _goto_specific_name(n, options=''): 436 | if n.column is None: 437 | if n.is_keyword: 438 | echo_highlight("Cannot get the definition of Python keywords.") 439 | else: 440 | name = 'Namespaces' if n.type == 'namespace' else 'Builtin modules' 441 | echo_highlight( 442 | "%s cannot be displayed (%s)." 443 | % (name, n.full_name or n.name) 444 | ) 445 | else: 446 | using_tagstack = int(vim_eval('g:jedi#use_tag_stack')) == 1 447 | result = set_buffer(n.module_path, options=options, 448 | using_tagstack=using_tagstack) 449 | if not result: 450 | return [] 451 | if (using_tagstack and n.module_path and 452 | n.module_path.exists()): 453 | tagname = n.name 454 | with tempfile('{0}\t{1}\t{2}'.format( 455 | tagname, n.module_path, 'call cursor({0}, {1})'.format( 456 | n.line, n.column + 1))) as f: 457 | old_tags = vim.eval('&tags') 458 | old_wildignore = vim.eval('&wildignore') 459 | try: 460 | # Clear wildignore to ensure tag file isn't ignored 461 | vim.command('set wildignore=') 462 | vim.command('let &tags = %s' % 463 | repr(PythonToVimStr(f.name))) 464 | vim.command('tjump %s' % tagname) 465 | finally: 466 | vim.command('let &tags = %s' % 467 | repr(PythonToVimStr(old_tags))) 468 | vim.command('let &wildignore = %s' % 469 | repr(PythonToVimStr(old_wildignore))) 470 | vim.current.window.cursor = n.line, n.column 471 | 472 | 473 | def relpath(path): 474 | """Make path relative to cwd if it is below.""" 475 | abspath = os.path.abspath(path) 476 | if abspath.startswith(os.getcwd()): 477 | return os.path.relpath(path) 478 | return path 479 | 480 | 481 | def annotate_description(n): 482 | code = n.get_line_code().strip() 483 | if n.type == 'statement': 484 | return code 485 | if n.type == 'function': 486 | if code.startswith('def'): 487 | return code 488 | typ = 'def' 489 | else: 490 | typ = n.type 491 | return '[%s] %s' % (typ, code) 492 | 493 | 494 | def show_goto_multi_results(names, mode): 495 | """Create (or reuse) a quickfix list for multiple names.""" 496 | global _current_names 497 | 498 | lst = [] 499 | (row, col) = vim.current.window.cursor 500 | current_idx = None 501 | current_def = None 502 | for n in names: 503 | if n.column is None: 504 | # Typically a namespace, in the future maybe other things as 505 | # well. 506 | lst.append(dict(text=PythonToVimStr(n.description))) 507 | else: 508 | text = annotate_description(n) 509 | lst.append(dict(filename=PythonToVimStr(relpath(str(n.module_path))), 510 | lnum=n.line, col=n.column + 1, 511 | text=PythonToVimStr(text))) 512 | 513 | # Select current/nearest entry via :cc later. 514 | if n.line == row and n.column <= col: 515 | if (current_idx is None 516 | or (abs(lst[current_idx]["col"] - col) 517 | > abs(n.column - col))): 518 | current_idx = len(lst) 519 | current_def = n 520 | 521 | # Build qflist title. 522 | qf_title = mode 523 | if current_def is not None: 524 | if current_def.full_name: 525 | qf_title += ": " + current_def.full_name 526 | else: 527 | qf_title += ": " + str(current_def) 528 | select_entry = current_idx 529 | else: 530 | select_entry = 0 531 | 532 | qf_context = id(names) 533 | if (_current_names 534 | and VimCompat.can_update_current_qflist_for_context(qf_context)): 535 | # Same list, only adjust title/selected entry. 536 | VimCompat.setqflist_title(qf_title) 537 | vim_command('%dcc' % select_entry) 538 | else: 539 | VimCompat.setqflist(lst, title=qf_title, context=qf_context) 540 | for_usages = mode == "usages" 541 | vim_eval('jedi#add_goto_window(%d, %d)' % (for_usages, len(lst))) 542 | vim_command('%d' % select_entry) 543 | 544 | 545 | def _same_names(a, b): 546 | """Compare without _inference_state. 547 | 548 | Ref: https://github.com/davidhalter/jedi-vim/issues/952) 549 | """ 550 | return all( 551 | x._name.start_pos == y._name.start_pos 552 | and x.module_path == y.module_path 553 | and x.name == y.name 554 | for x, y in zip(a, b) 555 | ) 556 | 557 | 558 | @catch_and_print_exceptions 559 | def usages(visuals=True): 560 | script = get_script() 561 | names = script.get_references(*get_pos()) 562 | if not names: 563 | echo_highlight("No usages found here.") 564 | return names 565 | 566 | if visuals: 567 | global _current_names 568 | 569 | if _current_names: 570 | if _same_names(_current_names, names): 571 | names = _current_names 572 | else: 573 | clear_usages() 574 | assert not _current_names 575 | 576 | show_goto_multi_results(names, "usages") 577 | if not _current_names: 578 | _current_names = names 579 | highlight_usages() 580 | else: 581 | assert names is _current_names # updated above 582 | return names 583 | 584 | 585 | _current_names = None 586 | """Current definitions to use for highlighting.""" 587 | _pending_names = {} 588 | """Pending definitions for unloaded buffers.""" 589 | _placed_names_in_buffers = set() 590 | """Set of buffers for faster cleanup.""" 591 | 592 | 593 | IS_NVIM = hasattr(vim, 'from_nvim') 594 | if IS_NVIM: 595 | vim_prop_add = None 596 | else: 597 | vim_prop_type_added = False 598 | try: 599 | vim_prop_add = vim.Function("prop_add") 600 | except ValueError: 601 | vim_prop_add = None 602 | else: 603 | vim_prop_remove = vim.Function("prop_remove") 604 | 605 | 606 | def clear_usages(): 607 | """Clear existing highlights.""" 608 | global _current_names 609 | if _current_names is None: 610 | return 611 | _current_names = None 612 | 613 | if IS_NVIM: 614 | for buf in _placed_names_in_buffers: 615 | src_ids = buf.vars.get('_jedi_usages_src_ids') 616 | if src_ids is not None: 617 | for src_id in src_ids: 618 | buf.clear_highlight(src_id) 619 | elif vim_prop_add: 620 | for buf in _placed_names_in_buffers: 621 | vim_prop_remove({ 622 | 'type': 'jediUsage', 623 | 'all': 1, 624 | 'bufnr': buf.number, 625 | }) 626 | else: 627 | # Unset current window only. 628 | assert _current_names is None 629 | highlight_usages_for_vim_win() 630 | 631 | _placed_names_in_buffers.clear() 632 | 633 | 634 | def highlight_usages(): 635 | """Set usage names to be highlighted. 636 | 637 | With Neovim it will use the nvim_buf_add_highlight API to highlight all 638 | buffers already. 639 | 640 | With Vim without support for text-properties only the current window is 641 | highlighted via matchaddpos, and autocommands are setup to highlight other 642 | windows on demand. Otherwise Vim's text-properties are used. 643 | """ 644 | global _current_names, _pending_names 645 | 646 | names = _current_names 647 | _pending_names = {} 648 | 649 | if IS_NVIM or vim_prop_add: 650 | bufs = {x.name: x for x in vim.buffers} 651 | defs_per_buf = {} 652 | for name in names: 653 | try: 654 | buf = bufs[str(name.module_path)] 655 | except KeyError: 656 | continue 657 | defs_per_buf.setdefault(buf, []).append(name) 658 | 659 | if IS_NVIM: 660 | # We need to remember highlight ids with Neovim's API. 661 | buf_src_ids = {} 662 | for buf, names in defs_per_buf.items(): 663 | buf_src_ids[buf] = [] 664 | for name in names: 665 | src_id = _add_highlighted_name(buf, name) 666 | buf_src_ids[buf].append(src_id) 667 | for buf, src_ids in buf_src_ids.items(): 668 | buf.vars['_jedi_usages_src_ids'] = src_ids 669 | else: 670 | for buf, names in defs_per_buf.items(): 671 | try: 672 | for name in names: 673 | _add_highlighted_name(buf, name) 674 | except vim.error as exc: 675 | if exc.args[0].startswith('Vim:E275:'): 676 | # "Cannot add text property to unloaded buffer" 677 | _pending_names.setdefault(buf.name, []).extend( 678 | names) 679 | else: 680 | highlight_usages_for_vim_win() 681 | 682 | 683 | def _handle_pending_usages_for_buf(): 684 | """Add (pending) highlights for the current buffer (Vim with textprops).""" 685 | buf = vim.current.buffer 686 | bufname = buf.name 687 | try: 688 | buf_names = _pending_names[bufname] 689 | except KeyError: 690 | return 691 | for name in buf_names: 692 | _add_highlighted_name(buf, name) 693 | del _pending_names[bufname] 694 | 695 | 696 | def _add_highlighted_name(buf, name): 697 | lnum = name.line 698 | start_col = name.column 699 | 700 | # Skip highlighting of module definitions that point to the start 701 | # of the file. 702 | if name.type == 'module' and lnum == 1 and start_col == 0: 703 | return 704 | 705 | _placed_names_in_buffers.add(buf) 706 | 707 | # TODO: validate that name.name is at this position? 708 | # Would skip the module definitions from above already. 709 | 710 | length = len(name.name) 711 | if vim_prop_add: 712 | # XXX: needs jediUsage highlight (via after/syntax/python.vim). 713 | global vim_prop_type_added 714 | if not vim_prop_type_added: 715 | vim.eval("prop_type_add('jediUsage', {'highlight': 'jediUsage'})") 716 | vim_prop_type_added = True 717 | vim_prop_add(lnum, start_col+1, { 718 | 'type': 'jediUsage', 719 | 'bufnr': buf.number, 720 | 'length': length, 721 | }) 722 | return 723 | 724 | assert IS_NVIM 725 | end_col = name.column + length 726 | src_id = buf.add_highlight('jediUsage', lnum-1, start_col, end_col, 727 | src_id=0) 728 | return src_id 729 | 730 | 731 | def highlight_usages_for_vim_win(): 732 | """Highlight usages in the current window. 733 | 734 | It stores the matchids in a window-local variable. 735 | 736 | (matchaddpos() only works for the current window.) 737 | """ 738 | win = vim.current.window 739 | 740 | cur_matchids = win.vars.get('_jedi_usages_vim_matchids') 741 | if cur_matchids: 742 | if cur_matchids[0] == vim.current.buffer.number: 743 | return 744 | 745 | # Need to clear non-matching highlights. 746 | for matchid in cur_matchids[1:]: 747 | expr = 'matchdelete(%d)' % int(matchid) 748 | vim.eval(expr) 749 | 750 | matchids = [] 751 | if _current_names: 752 | buffer_path = vim.current.buffer.name 753 | for name in _current_names: 754 | if (str(name.module_path) or '') == buffer_path: 755 | positions = [ 756 | [name.line, 757 | name.column + 1, 758 | len(name.name)] 759 | ] 760 | expr = "matchaddpos('jediUsage', %s)" % repr(positions) 761 | matchids.append(int(vim_eval(expr))) 762 | 763 | if matchids: 764 | vim.current.window.vars['_jedi_usages_vim_matchids'] = [ 765 | vim.current.buffer.number] + matchids 766 | elif cur_matchids is not None: 767 | # Always set it (uses an empty list for "unset", which is not possible 768 | # using del). 769 | vim.current.window.vars['_jedi_usages_vim_matchids'] = [] 770 | 771 | # Remember if clearing is needed for later buffer autocommands. 772 | vim.current.buffer.vars['_jedi_usages_needs_clear'] = bool(matchids) 773 | 774 | 775 | @_check_jedi_availability(show_error=True) 776 | @catch_and_print_exceptions 777 | def show_documentation(): 778 | script = get_script() 779 | try: 780 | names = script.help(*get_pos()) 781 | except Exception: 782 | # print to stdout, will be in :messages 783 | names = [] 784 | print("Exception, this shouldn't happen.") 785 | print(traceback.format_exc()) 786 | 787 | if not names: 788 | echo_highlight('No documentation found for that.') 789 | vim.command('return') 790 | return 791 | 792 | docs = [] 793 | for n in names: 794 | doc = n.docstring() 795 | if doc: 796 | title = 'Docstring for %s %s' % (n.type, n.full_name or n.name) 797 | underline = '=' * len(title) 798 | docs.append('%s\n%s\n%s' % (title, underline, doc)) 799 | else: 800 | docs.append('|No Docstring for %s|' % n) 801 | text = ('\n' + '-' * 79 + '\n').join(docs) 802 | vim.command('let l:doc = %s' % repr(PythonToVimStr(text))) 803 | vim.command('let l:doc_lines = %s' % len(text.split('\n'))) 804 | return True 805 | 806 | 807 | @catch_and_print_exceptions 808 | def clear_call_signatures(): 809 | # Check if using command line call signatures 810 | if int(vim_eval("g:jedi#show_call_signatures")) == 2: 811 | vim_command('echo ""') 812 | return 813 | cursor = vim.current.window.cursor 814 | e = vim_eval('g:jedi#call_signature_escape') 815 | # We need two turns here to search and replace certain lines: 816 | # 1. Search for a line with a call signature and save the appended 817 | # characters 818 | # 2. Actually replace the line and redo the status quo. 819 | py_regex = r'%sjedi=([0-9]+), (.*?)%s.*?%sjedi%s'.replace( 820 | '%s', re.escape(e)) 821 | for i, line in enumerate(vim.current.buffer): 822 | match = re.search(py_regex, line) 823 | if match is not None: 824 | # Some signs were added to minimize syntax changes due to call 825 | # signatures. We have to remove them again. The number of them is 826 | # specified in `match.group(1)`. 827 | after = line[match.end() + int(match.group(1)):] 828 | line = line[:match.start()] + match.group(2) + after 829 | vim.current.buffer[i] = line 830 | vim.current.window.cursor = cursor 831 | 832 | 833 | @_check_jedi_availability(show_error=False) 834 | @catch_and_print_exceptions 835 | def show_call_signatures(signatures=()): 836 | if int(vim_eval("has('conceal') && g:jedi#show_call_signatures")) == 0: 837 | return 838 | 839 | # We need to clear the signatures before we calculate them again. The 840 | # reason for this is that call signatures are unfortunately written to the 841 | # buffer. 842 | clear_call_signatures() 843 | if signatures == (): 844 | signatures = get_script().get_signatures(*get_pos()) 845 | 846 | if not signatures: 847 | return 848 | 849 | if int(vim_eval("g:jedi#show_call_signatures")) == 2: 850 | return cmdline_call_signatures(signatures) 851 | 852 | seen_sigs = [] 853 | for i, signature in enumerate(signatures): 854 | line, column = signature.bracket_start 855 | # signatures are listed above each other 856 | line_to_replace = line - i - 1 857 | # because there's a space before the bracket 858 | insert_column = column - 1 859 | if insert_column < 0 or line_to_replace <= 0: 860 | # Edge cases, when the call signature has no space on the screen. 861 | break 862 | 863 | # TODO check if completion menu is above or below 864 | line = vim_eval("getline(%s)" % line_to_replace) 865 | 866 | # Descriptions are usually looking like `param name`, remove the param. 867 | params = [p.description.replace('\n', '').replace('param ', '', 1) 868 | for p in signature.params] 869 | try: 870 | # *_*PLACEHOLDER*_* makes something fat. See after/syntax file. 871 | params[signature.index] = '*_*%s*_*' % params[signature.index] 872 | except (IndexError, TypeError): 873 | pass 874 | 875 | # Skip duplicates. 876 | if params in seen_sigs: 877 | continue 878 | seen_sigs.append(params) 879 | 880 | # This stuff is reaaaaally a hack! I cannot stress enough, that 881 | # this is a stupid solution. But there is really no other yet. 882 | # There is no possibility in VIM to draw on the screen, but there 883 | # will be one (see :help todo Patch to access screen under Python. 884 | # (Marko Mahni, 2010 Jul 18)) 885 | text = " (%s) " % ', '.join(params) 886 | text = ' ' * (insert_column - len(line)) + text 887 | end_column = insert_column + len(text) - 2 # -2 due to bold symbols 888 | 889 | # Need to decode it with utf8, because vim returns always a python 2 890 | # string even if it is unicode. 891 | e = vim_eval('g:jedi#call_signature_escape') 892 | if hasattr(e, 'decode'): 893 | e = e.decode('UTF-8') 894 | # replace line before with cursor 895 | regex = "xjedi=%sx%sxjedix".replace('x', e) 896 | 897 | prefix, replace = line[:insert_column], line[insert_column:end_column] 898 | 899 | # Check the replace stuff for strings, to append them 900 | # (don't want to break the syntax) 901 | regex_quotes = r'''\\*["']+''' 902 | # `add` are all the quotation marks. 903 | # join them with a space to avoid producing ''' 904 | add = ' '.join(re.findall(regex_quotes, replace)) 905 | # search backwards 906 | if add and replace[0] in ['"', "'"]: 907 | a = re.search(regex_quotes + '$', prefix) 908 | add = ('' if a is None else a.group(0)) + add 909 | 910 | tup = '%s, %s' % (len(add), replace) 911 | repl = prefix + (regex % (tup, text)) + add + line[end_column:] 912 | 913 | vim_eval('setline(%s, %s)' % (line_to_replace, repr(PythonToVimStr(repl)))) 914 | 915 | 916 | @catch_and_print_exceptions 917 | def cmdline_call_signatures(signatures): 918 | def get_params(s): 919 | return [p.description.replace('\n', '').replace('param ', '', 1) for p in s.params] 920 | 921 | def escape(string): 922 | return string.replace('"', '\\"').replace(r'\n', r'\\n') 923 | 924 | def join(): 925 | return ', '.join(filter(None, (left, center, right))) 926 | 927 | def too_long(): 928 | return len(join()) > max_msg_len 929 | 930 | if len(signatures) > 1: 931 | params = zip_longest(*map(get_params, signatures), fillvalue='_') 932 | params = ['(' + ', '.join(p) + ')' for p in params] 933 | else: 934 | params = get_params(signatures[0]) 935 | 936 | index = next(iter(s.index for s in signatures if s.index is not None), None) 937 | 938 | # Allow 12 characters for showcmd plus 18 for ruler - setting 939 | # noruler/noshowcmd here causes incorrect undo history 940 | max_msg_len = int(vim_eval('&columns')) - 12 941 | if int(vim_eval('&ruler')): 942 | max_msg_len -= 18 943 | max_msg_len -= len(signatures[0].name) + 2 # call name + parentheses 944 | 945 | if max_msg_len < (1 if params else 0): 946 | return 947 | elif index is None: 948 | text = escape(', '.join(params)) 949 | if params and len(text) > max_msg_len: 950 | text = ELLIPSIS 951 | elif max_msg_len < len(ELLIPSIS): 952 | return 953 | else: 954 | left = escape(', '.join(params[:index])) 955 | center = escape(params[index]) 956 | right = escape(', '.join(params[index + 1:])) 957 | while too_long(): 958 | if left and left != ELLIPSIS: 959 | left = ELLIPSIS 960 | continue 961 | if right and right != ELLIPSIS: 962 | right = ELLIPSIS 963 | continue 964 | if (left or right) and center != ELLIPSIS: 965 | left = right = None 966 | center = ELLIPSIS 967 | continue 968 | if too_long(): 969 | # Should never reach here 970 | return 971 | 972 | max_num_spaces = max_msg_len 973 | if index is not None: 974 | max_num_spaces -= len(join()) 975 | _, column = signatures[0].bracket_start 976 | spaces = min(int(vim_eval('g:jedi#first_col +' 977 | 'wincol() - col(".")')) + 978 | column - len(signatures[0].name), 979 | max_num_spaces) * ' ' 980 | 981 | if index is not None: 982 | vim_command(' echon "%s" | ' 983 | 'echohl Function | echon "%s" | ' 984 | 'echohl None | echon "(" | ' 985 | 'echohl jediFunction | echon "%s" | ' 986 | 'echohl jediFat | echon "%s" | ' 987 | 'echohl jediFunction | echon "%s" | ' 988 | 'echohl None | echon ")"' 989 | % (spaces, signatures[0].name, 990 | left + ', ' if left else '', 991 | center, ', ' + right if right else '')) 992 | else: 993 | vim_command(' echon "%s" | ' 994 | 'echohl Function | echon "%s" | ' 995 | 'echohl None | echon "(%s)"' 996 | % (spaces, signatures[0].name, text)) 997 | 998 | 999 | @_check_jedi_availability(show_error=True) 1000 | @catch_and_print_exceptions 1001 | def rename(delete_word=True): 1002 | if not int(vim.eval('a:0')): 1003 | # Need to save the cursor position before insert mode 1004 | cursor = vim.current.window.cursor 1005 | changenr = vim.eval('changenr()') # track undo tree 1006 | vim_command('augroup jedi_rename') 1007 | vim_command('autocmd InsertLeave call jedi#rename' 1008 | '({}, {}, {})'.format(cursor[0], cursor[1], changenr)) 1009 | vim_command('augroup END') 1010 | 1011 | vim_command("let s:jedi_replace_orig = expand('')") 1012 | line = vim_eval('getline(".")') 1013 | 1014 | if delete_word: 1015 | vim_command('normal! diw') 1016 | else: 1017 | vim_command('normal! yiwel') 1018 | 1019 | if re.match(r'\w+$', line[cursor[1]:]): 1020 | # In case the deleted word is at the end of the line we need to 1021 | # move the cursor to the end. 1022 | vim_command('startinsert!') 1023 | else: 1024 | vim_command('startinsert') 1025 | 1026 | else: 1027 | # Remove autocommand. 1028 | vim_command('autocmd! jedi_rename InsertLeave') 1029 | 1030 | args = vim.eval('a:000') 1031 | cursor = tuple(int(x) for x in args[:2]) 1032 | changenr = args[2] 1033 | 1034 | # Get replacement, if there is something on the cursor. 1035 | # This won't be the case when the user ends insert mode right away, 1036 | # and `` would pick up the nearest word instead. 1037 | if vim_eval('getline(".")[getpos(".")[2]-1]') != ' ': 1038 | replace = vim_eval("expand('')") 1039 | else: 1040 | replace = None 1041 | 1042 | vim_command('undo {}'.format(changenr)) 1043 | 1044 | vim.current.window.cursor = cursor 1045 | 1046 | if replace: 1047 | return do_rename(replace) 1048 | 1049 | 1050 | def rename_visual(use_selected_text_as_prompt_answer=False): 1051 | orig = vim.eval('getline(".")[(getpos("\'<")[2]-1):getpos("\'>")[2]' 1052 | '-((&selection ==# "exclusive") ? 2 : 1)]') 1053 | 1054 | input_text = "" 1055 | if use_selected_text_as_prompt_answer: 1056 | input_text = orig 1057 | 1058 | replace = vim.eval( 1059 | 'input("Rename to:", "{}")'.format(PythonToVimStr(input_text)) 1060 | ) 1061 | do_rename(replace, orig) 1062 | 1063 | 1064 | def do_rename(replace, orig=None): 1065 | if not len(replace): 1066 | echo_highlight('No rename possible without name.') 1067 | return 1068 | 1069 | if orig is None: 1070 | orig = vim_eval('s:jedi_replace_orig') 1071 | 1072 | if orig == replace: 1073 | echo_highlight('Jedi did 0 renames.') 1074 | return 1075 | 1076 | # Save original window / tab. 1077 | saved_tab = int(vim_eval('tabpagenr()')) 1078 | saved_win = int(vim_eval('winnr()')) 1079 | 1080 | temp_rename = usages(visuals=False) 1081 | # Sort the whole thing reverse (positions at the end of the line 1082 | # must be first, because they move the stuff before the position). 1083 | temp_rename = sorted(temp_rename, reverse=True, 1084 | key=lambda x: (str(x.module_path), x.line, x.column)) 1085 | buffers = set() 1086 | for r in temp_rename: 1087 | if r.in_builtin_module(): 1088 | continue 1089 | 1090 | result = set_buffer(r.module_path) 1091 | if not result: 1092 | echo_highlight('Failed to create buffer window for %s!' % (r.module_path)) 1093 | continue 1094 | 1095 | buffers.add(vim.current.buffer.name) 1096 | 1097 | # Replace original word. 1098 | r_line = vim.current.buffer[r.line - 1] 1099 | vim.current.buffer[r.line - 1] = (r_line[:r.column] + replace + 1100 | r_line[r.column + len(orig):]) 1101 | 1102 | # Restore previous tab and window. 1103 | vim_command('tabnext {0:d}'.format(saved_tab)) 1104 | vim_command('{0:d}wincmd w'.format(saved_win)) 1105 | 1106 | if len(buffers) > 1: 1107 | echo_highlight('Jedi did {0:d} renames in {1:d} buffers!'.format( 1108 | len(temp_rename), len(buffers))) 1109 | else: 1110 | echo_highlight('Jedi did {0:d} renames!'.format(len(temp_rename))) 1111 | 1112 | 1113 | @_check_jedi_availability(show_error=True) 1114 | @catch_and_print_exceptions 1115 | def py_import(): 1116 | args = shsplit(vim.eval('a:args')) 1117 | import_path = args.pop() 1118 | name = next(get_project().search(import_path), None) 1119 | if name is None: 1120 | echo_highlight('Cannot find %s in your project or on sys.path!' % import_path) 1121 | else: 1122 | cmd_args = ' '.join([a.replace(' ', '\\ ') for a in args]) 1123 | _goto_specific_name(name, options=cmd_args) 1124 | 1125 | 1126 | @catch_and_print_exceptions 1127 | def py_import_completions(): 1128 | argl = vim.eval('a:argl') 1129 | if jedi is None: 1130 | print('Pyimport completion requires jedi module: https://github.com/davidhalter/jedi') 1131 | comps = [] 1132 | else: 1133 | names = get_project().complete_search(argl) 1134 | comps = [argl + n for n in sorted(set(c.complete for c in names))] 1135 | vim.command("return '%s'" % '\n'.join(comps)) 1136 | 1137 | 1138 | @catch_and_print_exceptions 1139 | def set_buffer(path: Optional[Path], options='', using_tagstack=False): 1140 | """ 1141 | Opens a new buffer if we have to or does nothing. Returns True in case of 1142 | success. 1143 | """ 1144 | path = str(path or '') 1145 | # Check both, because it might be an empty string 1146 | if path in (vim.current.buffer.name, os.path.abspath(vim.current.buffer.name)): 1147 | return True 1148 | 1149 | path = relpath(path) 1150 | # options are what you can to edit the edit options 1151 | if int(vim_eval('g:jedi#use_tabs_not_buffers')) == 1: 1152 | _tabnew(path, options) 1153 | elif not vim_eval('g:jedi#use_splits_not_buffers') in [1, '1']: 1154 | user_split_option = vim_eval('g:jedi#use_splits_not_buffers') 1155 | split_options = { 1156 | 'top': 'topleft split', 1157 | 'left': 'topleft vsplit', 1158 | 'right': 'botright vsplit', 1159 | 'bottom': 'botright split', 1160 | 'winwidth': 'vs' 1161 | } 1162 | if (user_split_option == 'winwidth' and 1163 | vim.current.window.width <= 2 * int(vim_eval( 1164 | "&textwidth ? &textwidth : 80"))): 1165 | split_options['winwidth'] = 'sp' 1166 | if user_split_option not in split_options: 1167 | print('Unsupported value for g:jedi#use_splits_not_buffers: {0}. ' 1168 | 'Valid options are: {1}.'.format( 1169 | user_split_option, ', '.join(split_options.keys()))) 1170 | else: 1171 | vim_command(split_options[user_split_option] + " %s" % escape_file_path(path)) 1172 | else: 1173 | if int(vim_eval("!&hidden && &modified")) == 1: 1174 | if not vim_eval("bufname('%')"): 1175 | echo_highlight('Cannot open a new buffer, use `:set hidden` or save your buffer') 1176 | return False 1177 | else: 1178 | vim_command('w') 1179 | if using_tagstack: 1180 | return True 1181 | vim_command('edit %s %s' % (options, escape_file_path(path))) 1182 | # sometimes syntax is being disabled and the filetype not set. 1183 | if int(vim_eval('!exists("g:syntax_on")')) == 1: 1184 | vim_command('syntax enable') 1185 | if int(vim_eval("&filetype != 'python'")) == 1: 1186 | vim_command('set filetype=python') 1187 | return True 1188 | 1189 | 1190 | @catch_and_print_exceptions 1191 | def _tabnew(path, options=''): 1192 | """ 1193 | Open a file in a new tab or switch to an existing one. 1194 | 1195 | :param options: `:tabnew` options, read vim help. 1196 | """ 1197 | if int(vim_eval('has("gui")')) == 1: 1198 | vim_command('tab drop %s %s' % (options, escape_file_path(path))) 1199 | return 1200 | 1201 | for tab_nr in range(int(vim_eval("tabpagenr('$')"))): 1202 | for buf_nr in vim_eval("tabpagebuflist(%i + 1)" % tab_nr): 1203 | buf_nr = int(buf_nr) - 1 1204 | try: 1205 | buf_path = vim.buffers[buf_nr].name 1206 | except (LookupError, ValueError): 1207 | # Just do good old asking for forgiveness. 1208 | # don't know why this happens :-) 1209 | pass 1210 | else: 1211 | if os.path.abspath(buf_path) == os.path.abspath(path): 1212 | # tab exists, just switch to that tab 1213 | vim_command('tabfirst | tabnext %i' % (tab_nr + 1)) 1214 | # Goto the buffer's window. 1215 | vim_command('exec bufwinnr(%i) . " wincmd w"' % (buf_nr + 1)) 1216 | break 1217 | else: 1218 | continue 1219 | break 1220 | else: 1221 | # tab doesn't exist, add a new one. 1222 | vim_command('tabnew %s' % escape_file_path(path)) 1223 | 1224 | 1225 | def escape_file_path(path): 1226 | return path.replace(' ', r'\ ') 1227 | 1228 | 1229 | def print_to_stdout(level, str_out): 1230 | print(str_out) 1231 | -------------------------------------------------------------------------------- /pythonx/jedi_vim_debug.py: -------------------------------------------------------------------------------- 1 | """Used in jedi-vim's jedi#debug_info()""" 2 | import sys 3 | 4 | import vim 5 | from jedi_vim import PythonToVimStr, jedi 6 | 7 | 8 | def echo(msg): 9 | vim.command('echo %r' % PythonToVimStr(msg)) 10 | 11 | 12 | def echo_error(msg): 13 | vim.command('echohl ErrorMsg') 14 | echo(msg) 15 | vim.command('echohl None') 16 | 17 | 18 | def format_exc_info(exc_info=None, tb_indent=2): 19 | import traceback 20 | 21 | if exc_info is None: 22 | exc_info = sys.exc_info() 23 | 24 | exc_msg = traceback.format_exception_only(exc_info[0], exc_info[1]) 25 | lines = ''.join(exc_msg).rstrip('\n').split('\n') 26 | 27 | lines.append('Traceback (most recent call last):') 28 | tb = traceback.format_tb(exc_info[2]) 29 | lines.extend(''.join(tb).rstrip('\n').split('\n')) 30 | 31 | indent = ' ' * tb_indent 32 | return '{0}'.format(('\n' + indent).join(lines)) 33 | 34 | 35 | def get_known_environments(): 36 | """Get known Jedi environments.""" 37 | envs = list(jedi.find_virtualenvs()) 38 | envs.extend(jedi.find_system_environments()) 39 | return envs 40 | 41 | 42 | def display_debug_info(): 43 | echo(' - global sys.executable: `{0}`'.format(sys.executable)) 44 | echo(' - global sys.version: `{0}`'.format( 45 | ', '.join([x.strip() 46 | for x in sys.version.split('\n')]))) 47 | echo(' - global site module: `{0}`'.format(__import__('site').__file__)) 48 | 49 | try: 50 | import jedi_vim 51 | except Exception: 52 | echo_error('ERROR: could not import jedi_vim: {0}'.format( 53 | format_exc_info())) 54 | return 55 | 56 | if jedi_vim.jedi is None: 57 | if hasattr(jedi_vim, 'jedi_import_error'): 58 | error_msg = format_exc_info(jedi_vim.jedi_import_error) 59 | else: 60 | error_msg = 'unknown error' 61 | echo_error('ERROR: could not import the "jedi" Python module: {0}'.format( 62 | error_msg)) 63 | else: 64 | echo('\n##### Jedi\n\n - path: `{0}`'.format(jedi_vim.jedi.__file__)) 65 | echo(' - version: {0}'.format(jedi_vim.jedi.__version__)) 66 | 67 | try: 68 | project = jedi_vim.get_project() 69 | environment = project.get_environment() 70 | except AttributeError: 71 | script_evaluator = jedi_vim.jedi.Script('')._evaluator 72 | try: 73 | sys_path = script_evaluator.project.sys_path 74 | except AttributeError: 75 | sys_path = script_evaluator.sys_path 76 | else: 77 | echo('\n##### Jedi environment: {0}\n\n'.format(environment)) 78 | echo(' - executable: {0}'.format(environment.executable)) 79 | try: 80 | sys_path = environment.get_sys_path() 81 | except Exception: 82 | echo_error('ERROR: failed to get sys path from environment: {0}'.format( 83 | format_exc_info())) 84 | return 85 | 86 | echo(' - sys_path:') 87 | for p in sys_path: 88 | echo(' - `{0}`'.format(p)) 89 | 90 | if environment: 91 | echo('\n##### Known environments\n\n') 92 | for environment in get_known_environments(): 93 | echo(' - {0} ({1})\n'.format( 94 | environment, 95 | environment.executable, 96 | )) 97 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [tool:pytest] 2 | testpaths = test 3 | 4 | [flake8] 5 | max-line-length = 100 6 | -------------------------------------------------------------------------------- /test/_utils.vim: -------------------------------------------------------------------------------- 1 | function! CurrentBufferIsModule(module_name) 2 | return EndsWith(bufname('%'), a:module_name.'.py') 3 | endfunction 4 | 5 | 6 | function EndsWith(string, end) 7 | let l:should = len(a:string) - strlen(a:end) 8 | return l:should == stridx(a:string, a:end, should) 9 | endfunction 10 | 11 | " vim: et:ts=4:sw=4 12 | -------------------------------------------------------------------------------- /test/test_integration.py: -------------------------------------------------------------------------------- 1 | """Runs tests from ./vspec in vim-vspec.""" 2 | import os 3 | import subprocess 4 | try: 5 | from urllib.request import urlretrieve 6 | except ImportError: 7 | from urllib import urlretrieve 8 | import zipfile 9 | 10 | import pytest 11 | 12 | vspec_version = '1.9.0' 13 | 14 | VSPEC_URL = 'https://github.com/kana/vim-vspec/archive/%s.zip' % vspec_version 15 | root = os.path.dirname(os.path.dirname(__file__)) 16 | CACHE_FOLDER = os.path.join(root, 'build') 17 | VSPEC_FOLDER = os.path.join(CACHE_FOLDER, 'vim-vspec-%s' % vspec_version) 18 | VSPEC_RUNNER = os.path.join(VSPEC_FOLDER, 'bin/vspec') 19 | TEST_DIR = os.path.join(root, 'test', 'vspec') 20 | 21 | 22 | @pytest.fixture(scope='session') 23 | def install_vspec(): 24 | if not os.path.isdir(CACHE_FOLDER): 25 | os.mkdir(CACHE_FOLDER) 26 | 27 | if not os.path.exists(VSPEC_FOLDER): 28 | name, hdrs = urlretrieve(VSPEC_URL) 29 | z = zipfile.ZipFile(name) 30 | for n in z.namelist(): 31 | dest = os.path.join(CACHE_FOLDER, n) 32 | destdir = os.path.dirname(dest) 33 | if not os.path.isdir(destdir): 34 | os.makedirs(destdir) 35 | data = z.read(n) 36 | if not os.path.isdir(dest): 37 | with open(dest, 'wb') as f: 38 | f.write(data) 39 | z.close() 40 | os.chmod(VSPEC_RUNNER, 0o777) 41 | 42 | 43 | def get_vspec_tests(): 44 | for f in os.listdir(TEST_DIR): 45 | yield os.path.relpath(os.path.join(TEST_DIR, f)) 46 | 47 | 48 | @pytest.mark.parametrize('path', get_vspec_tests()) 49 | def test_integration(install_vspec, path): 50 | output = subprocess.check_output( 51 | [VSPEC_RUNNER, '.', VSPEC_FOLDER, os.path.relpath(path, root)], 52 | cwd=root, 53 | ) 54 | had_ok = False 55 | for line in output.splitlines(): 56 | if (line.startswith(b'not ok') or 57 | line.startswith(b'Error') or 58 | line.startswith(b'Bail out!')): 59 | pytest.fail(u"{0} failed:\n{1}".format( 60 | path, output.decode('utf-8')), pytrace=False) 61 | if not had_ok and line.startswith(b'ok'): 62 | had_ok = True 63 | if not had_ok: 64 | pytest.fail(u"{0} failed: no 'ok' found:\n{1}".format( 65 | path, output.decode('utf-8')), pytrace=False) 66 | -------------------------------------------------------------------------------- /test/vimrc: -------------------------------------------------------------------------------- 1 | " Minimal vimrc to use jedi-vim. 2 | " 3 | " Not used anywhere yet, but allows for easy testing. 4 | let script_dir = fnamemodify(expand(''), ':h:h') 5 | let &runtimepath = script_dir.','.&runtimepath.','.script_dir.'/after' 6 | 7 | syntax on 8 | filetype plugin indent on 9 | -------------------------------------------------------------------------------- /test/vspec/choose-venv.vim: -------------------------------------------------------------------------------- 1 | source plugin/jedi.vim 2 | source test/_utils.vim 3 | 4 | describe 'simple:' 5 | before 6 | new 7 | normal! ifoo 8 | end 9 | 10 | after 11 | bd! 12 | end 13 | 14 | it 'choose' 15 | Expect g:jedi#environment_path == 'auto' 16 | Expect bufname('%') == '' 17 | 18 | JediChooseEnvironment 19 | " A Python executable needs to be a few letters 20 | Expect len(getline('.')) > 5 21 | Expect bufname('%') == 'Hit Enter to Choose an Environment' 22 | 23 | execute "normal \" 24 | Expect g:jedi#environment_path != 'auto' 25 | bd " TODO why is this necessary? There seems to be a random buffer. 26 | Expect bufname('%') == '' 27 | Expect getline('.') == 'foo' 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /test/vspec/completions.vim: -------------------------------------------------------------------------------- 1 | let g:jedi#completions_command = 'X' 2 | source plugin/jedi.vim 3 | 4 | describe 'completions' 5 | before 6 | new 7 | set filetype=python 8 | end 9 | 10 | after 11 | " default 12 | let g:jedi#popup_select_first = 1 13 | bd! 14 | end 15 | 16 | it 'longest in completeopt' 17 | " This gets set up with Vim only on VimEnter. 18 | if has('nvim') 19 | Expect stridx(&completeopt, 'longest') > -1 20 | else 21 | Expect stridx(&completeopt, 'longest') == -1 22 | doautocmd VimEnter 23 | Expect stridx(&completeopt, 'longest') > -1 24 | endif 25 | 26 | " Do not use it for following tests. 27 | set completeopt-=longest 28 | end 29 | 30 | it 'no smart import by default' 31 | exec "normal ifrom os " 32 | Expect getline('.') == 'from os ' 33 | end 34 | 35 | it 'import' 36 | " X is the completion command 37 | normal oimporX 38 | Expect getline('.') == 'import' 39 | normal a subproX 40 | Expect getline('.') == 'import subprocess' 41 | end 42 | 43 | it 'exception' 44 | normal oIndentationErrX 45 | Expect getline('.') == 'IndentationError' 46 | 47 | " Do not remap keys (".") here, otherwise this triggers completion in 48 | " Neovim already. 49 | normal! a().filena 50 | 51 | normal aX 52 | Expect getline('.') == 'IndentationError().filename' 53 | end 54 | 55 | it 'cycling through entries popup_select_first=0' 56 | set completeopt+=longest 57 | let g:jedi#popup_select_first = 0 58 | execute "normal oraise impX\" 59 | 60 | Expect getline('.') == 'raise ImportError' 61 | set completeopt-=longest 62 | end 63 | 64 | it 'cycling through entries popup_select_first=1' 65 | execute "normal oraise impX\" 66 | Expect getline('.') == 'raise ImportWarning' 67 | end 68 | 69 | it 'cycling through entries popup_select_first=1 and longest' 70 | set completeopt+=longest 71 | execute "normal oraise impX" 72 | Expect getline('.') == 'raise Import' 73 | 74 | " With Neovim pumvisible() is 1 in jedi#complete_opened, which then 75 | " triggers the . This is not the case with Vim. 76 | if has('nvim') 77 | execute "normal oraise impX\" 78 | Expect getline('.') == 'raise ImportWarning' 79 | 80 | execute "normal oraise impX\\" 81 | Expect getline('.') == 'raise imp' 82 | else 83 | execute "normal oraise impX\" 84 | Expect getline('.') == 'raise ImportError' 85 | 86 | execute "normal oraise impX\\" 87 | Expect getline('.') == 'raise ImportWarning' 88 | endif 89 | set completeopt-=longest 90 | end 91 | end 92 | 93 | describe 'smart completions' 94 | before 95 | new 96 | let g:jedi#smart_auto_mappings = 1 97 | set filetype=python 98 | end 99 | 100 | after 101 | " default 102 | let g:jedi#smart_auto_mappings = 0 103 | bd! 104 | end 105 | 106 | it 'smart import' 107 | exec "normal ifrom os " 108 | Expect getline('.') == 'from os import ' 109 | end 110 | 111 | it 'no smart import after space' 112 | exec "normal! ifrom os " 113 | exec "normal a " 114 | Expect getline('.') == 'from os ' 115 | end 116 | end 117 | 118 | " vim: et:ts=4:sw=4 119 | -------------------------------------------------------------------------------- /test/vspec/completions_disabled.vim: -------------------------------------------------------------------------------- 1 | let g:jedi#completions_command = 'X' 2 | let g:jedi#completions_enabled = 0 3 | source plugin/jedi.vim 4 | 5 | describe 'completions_disabled' 6 | before 7 | set filetype=python 8 | end 9 | 10 | after 11 | try | %bwipeout! | catch | endtry 12 | end 13 | 14 | it 'typing' 15 | normal oraise ImportErrX 16 | Expect getline('.') == 'raise ImportErrX' 17 | end 18 | end 19 | 20 | " vim: et:ts=4:sw=4 21 | -------------------------------------------------------------------------------- /test/vspec/documentation.vim: -------------------------------------------------------------------------------- 1 | source plugin/jedi.vim 2 | 3 | describe 'documentation docstrings' 4 | before 5 | set filetype=python 6 | end 7 | 8 | after 9 | try | %bwipeout! | catch | endtry 10 | end 11 | 12 | it 'simple' 13 | Expect maparg('K') == ':call jedi#show_documentation()' 14 | put = 'ImportError' 15 | normal GK 16 | Expect bufname('%') == "__doc__" 17 | Expect &filetype == 'rst' 18 | let header = getline(1, 2) 19 | Expect header[0] == "Docstring for class builtins.ImportError" 20 | Expect header[1] == "========================================" 21 | let content = join(getline(3, '$'), "\n") 22 | Expect stridx(content, "Import can't find module") > 0 23 | normal K 24 | Expect bufname('%') == '' 25 | end 26 | 27 | it 'no documentation' 28 | put = 'x = 2' 29 | normal oGK 30 | Expect bufname('%') == '' 31 | end 32 | end 33 | 34 | " vim: et:ts=4:sw=4 35 | -------------------------------------------------------------------------------- /test/vspec/goto.vim: -------------------------------------------------------------------------------- 1 | let mapleader = '\' 2 | source plugin/jedi.vim 3 | source test/_utils.vim 4 | 5 | describe 'goto simple:' 6 | before 7 | new 8 | set filetype=python 9 | put =[ 10 | \ 'def a(): pass', 11 | \ 'b = a', 12 | \ 'c = b', 13 | \ ] 14 | normal! ggdd 15 | normal! G$ 16 | Expect line('.') == 3 17 | end 18 | 19 | after 20 | bd! 21 | end 22 | 23 | it 'goto definitions' 24 | normal \d 25 | Expect line('.') == 2 26 | Expect col('.') == 1 27 | end 28 | 29 | it 'goto assignments' 30 | normal \g 31 | Expect line('.') == 2 32 | Expect col('.') == 1 33 | 34 | " cursor before `=` means that it stays there. 35 | normal \g 36 | Expect line('.') == 2 37 | Expect col('.') == 1 38 | 39 | " going to the last line changes it. 40 | normal! $ 41 | normal \g 42 | Expect line('.') == 1 43 | Expect col('.') == 5 44 | end 45 | end 46 | 47 | 48 | describe 'goto with tabs:' 49 | before 50 | set filetype=python 51 | let g:jedi#use_tabs_not_buffers = 1 52 | end 53 | 54 | after 55 | try | %bwipeout! | catch | endtry 56 | end 57 | 58 | it 'follow import' 59 | put = ['import subprocess', 'subprocess'] 60 | normal G\g 61 | Expect getline('.') == 'import subprocess' 62 | Expect line('.') == 2 63 | Expect col('.') == 8 64 | 65 | normal G\d 66 | Expect CurrentBufferIsModule('subprocess') == 1 67 | Expect line('.') == 1 68 | Expect col('.') == 1 69 | Expect tabpagenr('$') == 2 70 | Expect winnr('$') == 1 71 | bwipe 72 | 73 | Expect tabpagenr('$') == 1 74 | Expect bufname('%') == '' 75 | end 76 | end 77 | 78 | 79 | describe 'goto with buffers' 80 | before 81 | set filetype=python 82 | let g:jedi#use_tabs_not_buffers = 0 83 | end 84 | 85 | after 86 | try | %bwipeout! | catch | endtry 87 | set nohidden 88 | end 89 | 90 | it 'no new tabs' 91 | put = ['import os'] 92 | normal G$ 93 | call jedi#goto_assignments() 94 | python3 jedi_vim.goto() 95 | Expect CurrentBufferIsModule('os') == 0 96 | " Without hidden, it's not possible to open a new buffer, when the old 97 | " one is not saved. 98 | set hidden 99 | call jedi#goto_assignments() 100 | Expect CurrentBufferIsModule('os') == 1 101 | Expect winnr('$') == 1 102 | Expect tabpagenr('$') == 1 103 | Expect line('.') == 1 104 | Expect col('.') == 1 105 | end 106 | end 107 | 108 | 109 | 110 | describe 'goto with splits' 111 | before 112 | enew! 113 | set filetype=python 114 | let g:jedi#use_splits_not_buffers = 'left' 115 | end 116 | 117 | after 118 | try | %bwipeout! | catch | endtry 119 | end 120 | 121 | it 'follow import' 122 | put = ['import subprocess', 'subprocess'] 123 | normal G\g 124 | Expect getline('.') == 'import subprocess' 125 | Expect line('.') == 2 126 | Expect col('.') == 8 127 | 128 | normal G\d 129 | Expect CurrentBufferIsModule('subprocess') == 1 130 | Expect line('.') == 1 131 | Expect col('.') == 1 132 | Expect winnr('$') == 2 133 | wincmd l 134 | Expect bufname('%') == '' 135 | end 136 | 137 | end 138 | 139 | 140 | describe 'goto wildignore' 141 | before 142 | enew! 143 | set filetype=python 144 | set wildignore=*,with\ spaces,*.pyc 145 | set hidden 146 | let g:jedi#use_tag_stack = 1 147 | let g:jedi#use_tabs_not_buffers = 0 148 | " Need to use splits for code coverage in new_buffer() 149 | let g:jedi#use_splits_not_buffers = 1 150 | 151 | put = ['from subprocess import Popen', 'Popen'] 152 | Expect CurrentBufferIsModule('subprocess') == 0 153 | normal G 154 | end 155 | 156 | after 157 | try | %bwipeout! | catch | endtry 158 | set wildignore&vim 159 | end 160 | 161 | it 'restores wildignore' 162 | let before = &wildignore 163 | call jedi#goto() 164 | Expect getline('.') =~ 'Popen' 165 | Expect &wildignore == before 166 | end 167 | 168 | it 'not using tagstack' 169 | let g:jedi#use_tag_stack = 0 170 | call jedi#goto() 171 | Expect CurrentBufferIsModule('subprocess') == 1 172 | Expect getline('.') =~ 'Popen' 173 | end 174 | end 175 | 176 | 177 | " vim: et:ts=4:sw=4 178 | -------------------------------------------------------------------------------- /test/vspec/jedi_debug_info.vim: -------------------------------------------------------------------------------- 1 | source plugin/jedi.vim 2 | 3 | describe 'JediDebugInfo' 4 | it 'works' 5 | redir @a | JediDebugInfo | redir END 6 | let output = split(@a, '\n') 7 | Expect output[0] == 'You should run this in a buffer with filetype "python".' 8 | Expect output[1] == '#### Jedi-vim debug information' 9 | Expect output[-1] == '' 10 | end 11 | end 12 | 13 | " vim: et:ts=4:sw=4 14 | -------------------------------------------------------------------------------- /test/vspec/pyimport.vim: -------------------------------------------------------------------------------- 1 | source plugin/jedi.vim 2 | source test/_utils.vim 3 | 4 | describe 'pyimport' 5 | before 6 | let g:jedi#use_tabs_not_buffers = 1 7 | let g:jedi#project_path = 'autoload' 8 | end 9 | 10 | after 11 | try | %bwipeout! | catch | endtry 12 | unlet g:jedi#project_path 13 | end 14 | 15 | it 'open_tab' 16 | Pyimport os 17 | Expect CurrentBufferIsModule('os') == 1 18 | Pyimport subprocess 19 | Expect CurrentBufferIsModule('subprocess') == 1 20 | " the empty tab is sometimes also a tab 21 | Expect tabpagenr('$') >= 2 22 | end 23 | 24 | it 'completion' 25 | " don't know how to test this directly 26 | "execute "Pyimport subproc\" 27 | "Expect CurrentBufferIsModule('subprocess') == 1 28 | 29 | Expect jedi#py_import_completions('subproc', 0, 0) == 'subprocess' 30 | Expect jedi#py_import_completions('subprocess', 0, 0) == 'subprocess' 31 | let g:comp = jedi#py_import_completions('sre_', 0, 0) 32 | Expect g:comp == "sre_compile\nsre_constants\nsre_parse" 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /test/vspec/signatures.vim: -------------------------------------------------------------------------------- 1 | source plugin/jedi.vim 2 | 3 | describe 'signatures' 4 | before 5 | enew 6 | set filetype=python 7 | end 8 | 9 | after 10 | try | %bwipeout! | catch | endtry 11 | end 12 | 13 | it 'simple' 14 | normal odef xyz(number): return 15 | normal o 16 | normal oxyz() 17 | doautocmd CursorHoldI 18 | Expect getline(3) == '?!?jedi=0, ?!? (*_*number*_*) ?!?jedi?!?' 19 | 20 | doautocmd InsertLeave 21 | Expect getline(3) == '' 22 | end 23 | 24 | it 'multiple buffers' 25 | set hidden 26 | new 27 | setfiletype python 28 | redir => autocmds 29 | autocmd jedi_call_signatures * 30 | redir END 31 | Expect autocmds =~# 'jedi_call_signatures' 32 | buffer # 33 | redir => autocmds 34 | autocmd jedi_call_signatures * 35 | redir END 36 | Expect autocmds =~# 'jedi_call_signatures' 37 | end 38 | 39 | it 'simple after CursorHoldI with only parenthesis' 40 | noautocmd normal o 41 | doautocmd CursorHoldI 42 | noautocmd normal istaticmethod() 43 | doautocmd CursorHoldI 44 | Expect getline(1) == '?!?jedi=0, ?!? (*_*f: Callable[..., Any]*_*) ?!?jedi?!?' 45 | end 46 | 47 | it 'highlights correct argument' 48 | noautocmd normal o 49 | doautocmd CursorHoldI 50 | noautocmd normal iformat(42, "x") 51 | " Move to x - highlights "x". 52 | noautocmd normal 2h 53 | doautocmd CursorHoldI 54 | Expect getline(1) == '?!?jedi=0, ?!? (value: object, *_*format_spec: str=...*_*) ?!?jedi?!?' 55 | " Move left to 42 - hightlights first argument ("value"). 56 | noautocmd normal 4h 57 | doautocmd CursorHoldI 58 | Expect getline(1) == '?!?jedi=0, ?!? (*_*value: object*_*, format_spec: str=...) ?!?jedi?!?' 59 | end 60 | 61 | it 'no signature' 62 | exe 'normal ostr ' 63 | python3 jedi_vim.show_call_signatures() 64 | Expect getline(1, '$') == ['', 'str '] 65 | end 66 | 67 | it 'signatures disabled' 68 | let g:jedi#show_call_signatures = 0 69 | 70 | exe 'normal ostr( ' 71 | python3 jedi_vim.show_call_signatures() 72 | Expect getline(1, '$') == ['', 'str( '] 73 | 74 | let g:jedi#show_call_signatures = 1 75 | end 76 | 77 | it 'command line simple' 78 | let g:jedi#show_call_signatures = 2 79 | call jedi#configure_call_signatures() 80 | 81 | exe 'normal ostaticmethod( ' 82 | redir => msg 83 | python3 jedi_vim.show_call_signatures() 84 | redir END 85 | Expect msg == "\nstaticmethod(f: Callable[..., Any])" 86 | 87 | redir => msg 88 | doautocmd InsertLeave 89 | redir END 90 | Expect msg == "\n" 91 | 92 | normal Sdef foo(a, b): pass 93 | exe 'normal ofoo(a, b, c, ' 94 | redir => msg 95 | python3 jedi_vim.show_call_signatures() 96 | redir END 97 | Expect msg == "\nfoo(a, b)" 98 | end 99 | 100 | it 'command line truncation' 101 | let g:jedi#show_call_signatures = 2 102 | call jedi#configure_call_signatures() 103 | 104 | function! Signature() 105 | redir => msg 106 | python3 jedi_vim.show_call_signatures() 107 | redir END 108 | return msg 109 | endfunction 110 | 111 | let funcname = repeat('a', &columns - (30 + (&ruler ? 18 : 0))) 112 | put = 'def '.funcname.'(arg1, arg2, arg3, a, b, c):' 113 | put = ' pass' 114 | execute "normal o\".funcname."( " 115 | Expect Signature() == "\n".funcname."(arg1, …)" 116 | 117 | exe 'normal sarg1, ' 118 | Expect Signature() == "\n".funcname."(…, arg2, …)" 119 | 120 | exe 'normal sarg2, arg3, ' 121 | Expect Signature() == "\n".funcname."(…, a, b, c)" 122 | 123 | exe 'normal sa, b, ' 124 | Expect Signature() == "\n".funcname."(…, c)" 125 | 126 | g/^/d 127 | put = 'def '.funcname.'('.repeat('b', 20).', arg2):' 128 | put = ' pass' 129 | execute "normal o\".funcname."( " 130 | Expect Signature() == "\n".funcname."(…)" 131 | end 132 | 133 | it 'command line no signature' 134 | let g:jedi#show_call_signatures = 2 135 | call jedi#configure_call_signatures() 136 | 137 | exe 'normal ostr ' 138 | redir => msg 139 | python3 jedi_vim.show_call_signatures() 140 | redir END 141 | Expect msg == "\n" 142 | end 143 | end 144 | --------------------------------------------------------------------------------