diff --git a/README.md b/README.md index 21e939a2..f4b2173e 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,7 @@ I recommend reading the docs of these plugins to understand them better. Each pl * [gist-vim](https://github.com/mattn/gist-vim) Easily create gists from Vim using the `:Gist` command * [vim-indent-guides](https://github.com/nathanaelkane/vim-indent-guides) Is a plugin for visually displaying indent levels in Vim * [editorconfig-vim](https://github.com/editorconfig/editorconfig-vim) EditorConfig helps maintain consistent coding styles for multiple developers working on the same project across various editors and IDEs. +* [jedi-vim](https://github.com/davidhalter/jedi-vim) A great Python autocompletion library for VIM. ## Included color schemes diff --git a/sources_non_forked/jedi-vim/.github/FUNDING.yml b/sources_non_forked/jedi-vim/.github/FUNDING.yml new file mode 100644 index 00000000..418e47a8 --- /dev/null +++ b/sources_non_forked/jedi-vim/.github/FUNDING.yml @@ -0,0 +1 @@ +github: [davidhalter] diff --git a/sources_non_forked/jedi-vim/.github/ISSUE_TEMPLATE.md b/sources_non_forked/jedi-vim/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000..582f51f5 --- /dev/null +++ b/sources_non_forked/jedi-vim/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,44 @@ +### Issue + + + +### Steps to reproduce + + + +### Output of “:verbose JediDebugInfo” + + diff --git a/sources_non_forked/jedi-vim/.github/workflows/ci.yml b/sources_non_forked/jedi-vim/.github/workflows/ci.yml new file mode 100644 index 00000000..235f429b --- /dev/null +++ b/sources_non_forked/jedi-vim/.github/workflows/ci.yml @@ -0,0 +1,63 @@ +name: ci +on: [push, pull_request] + +jobs: + tests: + runs-on: ubuntu-20.04 + steps: + - name: Checkout code + uses: actions/checkout@v2 + with: + submodules: recursive + + - name: Setup + run: | + sudo pip install pytest + vim --version + + #- name: Setup tmate session + # uses: mxschmitt/action-tmate@v3 + + - name: Run tests + run: 'make test' + + code-quality: + runs-on: ubuntu-20.04 + steps: + - name: Checkout code + uses: actions/checkout@v2 + with: + submodules: recursive + + - name: Run tests + run: | + vim --version + make check + + coverage: + runs-on: ubuntu-20.04 + + steps: + - name: Checkout code + uses: actions/checkout@v2 + with: + submodules: recursive + + - name: Install dependencies + run: | + sudo add-apt-repository ppa:neovim-ppa/stable -y + sudo apt-get update -q + sudo apt-get install neovim -y + + sudo pip install pynvim pytest-cov + sudo pip list + nvim --version + + - name: Run tests + run: | + make --keep-going test_coverage BUILD_VIRTUAL_ENV=$VIRTUAL_ENV + + - name: Upload coverage data + run: | + coverage xml + bash <(curl -s https://codecov.io/bash) -X fix -f coverage.xml -F py${TRAVIS_PYTHON_VERSION//./} diff --git a/sources_non_forked/jedi-vim/.gitignore b/sources_non_forked/jedi-vim/.gitignore new file mode 100644 index 00000000..ebe32309 --- /dev/null +++ b/sources_non_forked/jedi-vim/.gitignore @@ -0,0 +1,8 @@ +*~ +*.sw? +*.py[cod] +.ropeproject +doc/tags +.pytest-cache +build +.coverage* diff --git a/sources_non_forked/jedi-vim/.gitmodules b/sources_non_forked/jedi-vim/.gitmodules new file mode 100644 index 00000000..04d8fe61 --- /dev/null +++ b/sources_non_forked/jedi-vim/.gitmodules @@ -0,0 +1,6 @@ +[submodule "jedi"] + path = pythonx/jedi + url = https://github.com/davidhalter/jedi.git +[submodule "pythonx/parso"] + path = pythonx/parso + url = https://github.com/davidhalter/parso.git diff --git a/sources_non_forked/jedi-vim/.travis.yml b/sources_non_forked/jedi-vim/.travis.yml new file mode 100644 index 00000000..7c2db150 --- /dev/null +++ b/sources_non_forked/jedi-vim/.travis.yml @@ -0,0 +1,31 @@ +dist: bionic +language: python +python: 3.8 +env: + - ENV=test + - ENV=check + - ENV=test_coverage +install: + - | + if [ "$ENV" = "test" ]; then + pip install pytest + elif [ "$ENV" = "test_coverage" ]; then + sudo add-apt-repository ppa:neovim-ppa/stable -y + sudo apt-get update -q + sudo apt-get install neovim -y + + pip install pynvim pytest-cov + pip list + nvim --version + else + vim --version + fi +script: + - make --keep-going "$ENV" BUILD_VIRTUAL_ENV=$VIRTUAL_ENV + +after_script: + - | + if [ "$ENV" = "test_coverage" ]; then + coverage xml + travis_retry bash <(curl -s https://codecov.io/bash) -X fix -f coverage.xml -F py${TRAVIS_PYTHON_VERSION//./} + fi diff --git a/sources_non_forked/jedi-vim/AUTHORS.txt b/sources_non_forked/jedi-vim/AUTHORS.txt new file mode 100644 index 00000000..0dc43efe --- /dev/null +++ b/sources_non_forked/jedi-vim/AUTHORS.txt @@ -0,0 +1,61 @@ +Main Authors +============ + +David Halter (@davidhalter) + + +Contributors (in order of contributions) +======================================== + +Patrice Peterson (@runiq) +tek (@tek) +heavenshell (@heavenshell) +Danilo Bargen (@dbrgn) +mattn (@mattn) +Enrico Batista da Luz (@ricobl) +coot (@coot) +Artur Dryomov (@ming13) +andviro (@andviro) +Jean-Louis Fuchs (@ganwell) +Mathieu Comandon (@strycore) +Nick Hurley (@todesschaf) +gpoulin (@gpoulin) +Akinori Hattori (@hattya) +Luper Rouch (@flupke) +Matthew Moses (@mlmoses) +Tyler Wymer (@twymer) +Artem Nezvigin (@artnez) +rogererens (@rogererens) +Emily Strickland (@emilyst) +Tin Tvrtković (@Tinche) +Zekeriya Koc (@zekzekus) +ethinx (@ethinx) +Wouter Overmeire (@lodagro) +Stephen J. Fuhry (@fuhrysteve) +Sheng Yun (@ShengYun) +Yann Thomas-Gérard (@inside) +Colin Su (@littleq0903) +Arthur Jaron (@eyetracker) +Justin M. Keyes (@justinmk) +nagev (@np1) +Chris Lasher (@gotgenes) +Doan Thanh Nam (@tndoan) +Markus Koller (@toupeira) +Justin Cheevers @justincheevers +Talha Ahmed (@talha81) +Matthew Tylee Atkinson (@matatk) +Pedro Ferrari (@petobens) +Daniel Hahler (@blueyed) +Dave Honneffer (@pearofducks) +Bagrat Aznauryan (@n9code) +Tomoyuki Kashiro (@kashiro) +Tommy Allen (@tweekmonster) +Mingliang (@Aulddays) +Brian Mego (@brianmego) +Stevan Milic (@stevanmilic) +Konstantin Glukhov (@Konstantin-Glukhov) +Seungchan An (@SeungChan92) +Thomas Blauth (@ThomasBlauth) +James Cherti (@jamescherti) + +@something are github user names. diff --git a/sources_non_forked/jedi-vim/CONTRIBUTING.md b/sources_non_forked/jedi-vim/CONTRIBUTING.md new file mode 100644 index 00000000..285eb308 --- /dev/null +++ b/sources_non_forked/jedi-vim/CONTRIBUTING.md @@ -0,0 +1,12 @@ +# We <3 pull requests! + + 1. Fork the Repo on github. + 2. Add yourself to AUTHORS.txt + 3. Add a test if possible. + 4. Push to your fork and submit a pull request. + +Please use PEP8 as a Python code style. For VIM, just try to style your +code similar to the jedi-vim code that is already there. + +# Bug reports +Please include the output of `:version` and `:JediDebugInfo`. diff --git a/sources_non_forked/jedi-vim/LICENSE.txt b/sources_non_forked/jedi-vim/LICENSE.txt new file mode 100644 index 00000000..12f223fc --- /dev/null +++ b/sources_non_forked/jedi-vim/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) <2013> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/sources_non_forked/jedi-vim/Makefile b/sources_non_forked/jedi-vim/Makefile new file mode 100644 index 00000000..02a19917 --- /dev/null +++ b/sources_non_forked/jedi-vim/Makefile @@ -0,0 +1,35 @@ +BUILD_VIRTUAL_ENV:=build/venv + +test: + pytest + +test_nvim: + VSPEC_VIM=nvim pytest + +test_coverage: export PYTEST_ADDOPTS:=--cov pythonx --cov test --cov-report=term-missing:skip-covered +test_coverage: test_nvim + +$(dir $(BUILD_VIRTUAL_ENV)): + mkdir -p $@ + +$(BUILD_VIRTUAL_ENV): | $(dir $(BUILD_VIRTUAL_ENV)) + python -m venv $@ + +$(BUILD_VIRTUAL_ENV)/bin/vint: | $(BUILD_VIRTUAL_ENV) + $|/bin/python -m pip install vim-vint==0.3.21 + +$(BUILD_VIRTUAL_ENV)/bin/flake8: | $(BUILD_VIRTUAL_ENV) + $|/bin/python -m pip install -q flake8==3.7.8 + +vint: $(BUILD_VIRTUAL_ENV)/bin/vint + $(BUILD_VIRTUAL_ENV)/bin/vint after autoload ftplugin plugin + +flake8: $(BUILD_VIRTUAL_ENV)/bin/flake8 + $(BUILD_VIRTUAL_ENV)/bin/flake8 pythonx/jedi_*.py + +check: vint flake8 + +clean: + rm -rf build + +.PHONY: test check clean vint flake8 diff --git a/sources_non_forked/jedi-vim/README.rst b/sources_non_forked/jedi-vim/README.rst new file mode 100644 index 00000000..ac82362c --- /dev/null +++ b/sources_non_forked/jedi-vim/README.rst @@ -0,0 +1,293 @@ +.. image:: https://github.com/davidhalter/jedi-vim/blob/master/doc/logotype-a.svg + +################################################# +jedi-vim - awesome Python autocompletion with VIM +################################################# + +.. image:: https://travis-ci.org/davidhalter/jedi-vim.svg?branch=master + :target: https://travis-ci.org/davidhalter/jedi-vim + :alt: Travis-CI build status + +jedi-vim is a VIM binding to the autocompletion library +`Jedi `_. + +Here are some pictures: + +.. image:: https://github.com/davidhalter/jedi/raw/master/docs/_screenshots/screenshot_complete.png + +Completion for almost anything (Ctrl+Space). + +.. image:: https://github.com/davidhalter/jedi/raw/master/docs/_screenshots/screenshot_function.png + +Display of function/class bodies, docstrings. + +.. image:: https://github.com/davidhalter/jedi/raw/master/docs/_screenshots/screenshot_pydoc.png + +Documentation (Pydoc) support (with highlighting, Shift+k). + +There is also support for goto and renaming. + + +Get the latest from `github `_. + +Documentation +============= + +Documentation is available in your vim: ``:help jedi-vim``. You can also look +it up `on github `_. + +You can read the Jedi library documentation `here `_. + +If you want to report issues, just use the github issue tracker. In case of +questions about the software, please use `stackoverflow +`_ and tag your question with ``jedi-vim``. + + +Contributing +============ + +We love Pull Requests! Read the instructions in ``CONTRIBUTING.md``. + + +Features +======== + +The Jedi library understands most of Python's core features. From decorators to +generators, there is broad support. + +Apart from that, jedi-vim supports the following commands + +- Completion ```` +- Goto assignment ``g`` (typical goto function) +- Goto definition ``d`` (follow identifier as far as possible, + includes imports and statements) +- Goto (typing) stub ``s`` +- Show Documentation/Pydoc ``K`` (shows a popup with assignments) +- Renaming ``r`` +- Usages ``n`` (shows all the usages of a name) +- Open module, e.g. ``:Pyimport os`` (opens the ``os`` module) + + +Installation +============ + +Requirements +------------ +You need a VIM version that was compiled with Python 2.7 or later +(``+python`` or ``+python3``). You can check this from within VIM using +``:python3 import sys; print(sys.version)`` (use ``:python`` for Python 2). + +Manual installation +------------------- + +You might want to use `pathogen `_ or +`Vundle `_ to install jedi-vim. + +The first thing you need after that is an up-to-date version of Jedi. Install +``git submodule update --init --recursive`` in your jedi-vim repository. + +Example installation command using Pathogen: + +.. code-block:: sh + + git clone --recursive https://github.com/davidhalter/jedi-vim.git ~/.vim/bundle/jedi-vim + +Example installation using Vundle: + +Add the following line in your `~/.vimrc` + +.. code-block:: vim + + Plugin 'davidhalter/jedi-vim' + +For installing Jedi, ``pip install jedi`` will also work, but you might run +into issues when working in virtual environments. Please use git submodules. + + +Installation with your distribution +----------------------------------- + +On Arch Linux, you can also install jedi-vim from official repositories as +`vim-jedi `__. +It is also available on +`Debian (≥8) `__ and +`Ubuntu (≥14.04) `__ as +vim-python-jedi. +On Fedora Linux, it is available as +`vim-jedi `__. + +Please note that this version might be quite old compared to using jedi-vim +from Git. + +Caveats +------- + +Note that the `python-mode `_ VIM plugin seems +to conflict with jedi-vim, therefore you should disable it before enabling +jedi-vim. + +To enjoy the full features of jedi-vim, you should have VIM >= 7.3, compiled with +``+conceal`` (which is not the case on some platforms, including OS X). If your VIM +does not meet these requirements, the parameter recommendation list may not appear +when you type an open bracket after a function name. Please read +`the documentation `_ +for details. + + +Settings +======== + +Jedi is by default automatically initialized. If you don't want that I suggest +you disable the auto-initialization in your ``.vimrc``: + +.. code-block:: vim + + let g:jedi#auto_initialization = 0 + +There are also some VIM options (like ``completeopt`` and key defaults) which +are automatically initialized, but you can skip this: + +.. code-block:: vim + + let g:jedi#auto_vim_configuration = 0 + + +You can make jedi-vim use tabs when going to a definition etc: + +.. code-block:: vim + + let g:jedi#use_tabs_not_buffers = 1 + +If you are a person who likes to use VIM-splits, you might want to put this in your ``.vimrc``: + +.. code-block:: vim + + let g:jedi#use_splits_not_buffers = "left" + +This options could be "left", "right", "top", "bottom" or "winwidth". It will decide the direction where the split open. + +Jedi automatically starts the completion, if you type a dot, e.g. ``str.``, if +you don't want this: + +.. code-block:: vim + + let g:jedi#popup_on_dot = 0 + +Jedi selects the first line of the completion menu: for a better typing-flow +and usually saves one keypress. + +.. code-block:: vim + + let g:jedi#popup_select_first = 0 + +Jedi displays function call signatures in insert mode in real-time, highlighting +the current argument. The call signatures can be displayed as a pop-up in the +buffer (set to 1 by default (with the conceal feature), 2 otherwise), +which has the advantage of being easier to refer to (but is a hack with +many drawbacks since it changes the buffer's contents), +or in Vim's command line aligned with the function call (set to 2), which +can improve the integrity of Vim's undo history. + +.. code-block:: vim + + let g:jedi#show_call_signatures = "1" + +Here are a few more defaults for actions, read the docs (``:help jedi-vim``) to +get more information. If you set them to ``""``, they are not assigned. + +.. code-block:: vim + + NOTE: subject to change! + + let g:jedi#goto_command = "d" + let g:jedi#goto_assignments_command = "g" + let g:jedi#goto_stubs_command = "s" + let g:jedi#goto_definitions_command = "" + let g:jedi#documentation_command = "K" + let g:jedi#usages_command = "n" + let g:jedi#completions_command = "" + let g:jedi#rename_command = "r" + +An example for setting up your project: + +.. code-block:: vim + + let g:jedi#environment_path = "/usr/bin/python3.9" + +jedi-vim tries its best to guess your virtual env. If you want to work with a +specific virtual environment however, you can point jedi-vim towards it: + +.. code-block:: vim + + let g:jedi#environment_path = "venv" + +Finally, if you don't want completion, but all the other features, use: + +.. code-block:: vim + + let g:jedi#completions_enabled = 0 + +FAQ +=== + +I want to use Jedi with a Python 2 Environment, but it's not listed under "Known environments" +---------------------------------------------------------------------------------------------- + +Starting with version 0.18.0 Jedi dropped support for Python 2. + + +I don't want the docstring window to popup during completion +------------------------------------------------------------ + +This depends on the ``completeopt`` option. Jedi initializes it in its +``ftplugin``. Add the following line to your ``.vimrc`` to disable it: + +.. code-block:: vim + + autocmd FileType python setlocal completeopt-=preview + + +I want to do autocompletion +--------------------------------- + +Don't even think about changing the Jedi command to ````, +use `supertab `_! + + +The completion is too slow! +--------------------------- + +1. Completion of complex libraries (like Numpy) should only be slow the first + time you complete them. After that the results should be cached and very fast. + +2. If it is still slow after the initial completion and you have installed the + python-mode Vim plugin, try disabling its rope mode: + + .. code-block:: vim + + let g:pymode_rope = 0 + + See issue `#163 `__. + +3. You can also use `deoplete-jedi `__ + for completions, which uses Jedi, but does completions asynchronously + (requires Neovim). + It makes sense to use both jedi-vim and deoplete-jedi, but you should disable + jedi-vim's completions then: + + .. code-block:: vim + + let g:jedi#completions_enabled = 0 + +Testing +======= + +jedi-vim is being tested with a combination of `vspec +`_ and `py.test `_. + +The tests are in the ``test`` subdirectory, you can run them calling:: + + py.test + +The tests are automatically run with `travis +`_. diff --git a/sources_non_forked/jedi-vim/after/ftplugin/python/jedi.vim b/sources_non_forked/jedi-vim/after/ftplugin/python/jedi.vim new file mode 100644 index 00000000..f1983603 --- /dev/null +++ b/sources_non_forked/jedi-vim/after/ftplugin/python/jedi.vim @@ -0,0 +1,3 @@ +if jedi#init_python() && g:jedi#auto_initialization && g:jedi#completions_enabled + call jedi#setup_completion() +endif diff --git a/sources_non_forked/jedi-vim/after/syntax/python.vim b/sources_non_forked/jedi-vim/after/syntax/python.vim new file mode 100644 index 00000000..08d0d1e7 --- /dev/null +++ b/sources_non_forked/jedi-vim/after/syntax/python.vim @@ -0,0 +1,34 @@ +if !jedi#init_python() + finish +endif + +if g:jedi#show_call_signatures > 0 && has('conceal') + " +conceal is the default for vim >= 7.3 + + let s:e = g:jedi#call_signature_escape + let s:full = s:e.'jedi=.\{-}'.s:e.'.\{-}'.s:e.'jedi'.s:e + let s:ignore = s:e.'jedi.\{-}'.s:e + exe 'syn match jediIgnore "'.s:ignore.'" contained conceal' + setlocal conceallevel=2 + syn match jediFatSymbol "\*_\*" contained conceal + syn match jediFat "\*_\*.\{-}\*_\*" contained contains=jediFatSymbol + syn match jediSpace "\v[ ]+( )@=" contained + exe 'syn match jediFunction "'.s:full.'" keepend extend ' + \ .' contains=jediIgnore,jediFat,jediSpace' + \ .' containedin=pythonComment,pythonString,pythonRawString' + unlet! s:e s:full s:ignore + + hi def link jediIgnore Ignore + hi def link jediFatSymbol Ignore + hi def link jediSpace Normal + + if exists('g:colors_name') + hi def link jediFunction CursorLine + hi def link jediFat TabLine + else + hi def jediFunction term=NONE cterm=NONE ctermfg=6 guifg=Black gui=NONE ctermbg=0 guibg=Grey + hi def jediFat term=bold,underline cterm=bold,underline gui=bold,underline ctermbg=0 guibg=#555555 + endif +endif + +hi def jediUsage cterm=reverse gui=standout diff --git a/sources_non_forked/jedi-vim/autoload/health/jedi.vim b/sources_non_forked/jedi-vim/autoload/health/jedi.vim new file mode 100644 index 00000000..8c80e93f --- /dev/null +++ b/sources_non_forked/jedi-vim/autoload/health/jedi.vim @@ -0,0 +1,4 @@ +function! health#jedi#check() abort + call health#report_start('jedi') + silent call jedi#debug_info() +endfunction diff --git a/sources_non_forked/jedi-vim/autoload/jedi.vim b/sources_non_forked/jedi-vim/autoload/jedi.vim new file mode 100644 index 00000000..dcef9b6d --- /dev/null +++ b/sources_non_forked/jedi-vim/autoload/jedi.vim @@ -0,0 +1,732 @@ +scriptencoding utf-8 + +" ------------------------------------------------------------------------ +" Settings initialization +" ------------------------------------------------------------------------ +let s:deprecations = { + \ 'get_definition_command': 'goto_definitions_command', + \ 'pydoc': 'documentation_command', + \ 'related_names_command': 'usages_command', + \ 'autocompletion_command': 'completions_command', + \ 'show_function_definition': 'show_call_signatures', +\ } + +let s:default_settings = { + \ 'use_tabs_not_buffers': 0, + \ 'use_splits_not_buffers': 1, + \ 'auto_initialization': 1, + \ 'auto_vim_configuration': 1, + \ 'goto_command': "'d'", + \ 'goto_assignments_command': "'g'", + \ 'goto_definitions_command': "''", + \ 'goto_stubs_command': "'s'", + \ 'completions_command': "''", + \ 'call_signatures_command': "'n'", + \ 'usages_command': "'n'", + \ 'rename_command': "'r'", + \ 'completions_enabled': 1, + \ 'popup_on_dot': 'g:jedi#completions_enabled', + \ 'documentation_command': "'K'", + \ 'show_call_signatures': has('conceal') ? 1 : 2, + \ 'show_call_signatures_delay': 500, + \ 'call_signature_escape': "'?!?'", + \ 'auto_close_doc': 1, + \ 'max_doc_height': 30, + \ 'popup_select_first': 1, + \ 'quickfix_window_height': 10, + \ 'force_py_version': "'auto'", + \ 'environment_path': "'auto'", + \ 'added_sys_path': '[]', + \ 'project_path': "'auto'", + \ 'smart_auto_mappings': 0, + \ 'case_insensitive_completion': 1, + \ 'use_tag_stack': 1 +\ } + +for [s:key, s:val] in items(s:deprecations) + if exists('g:jedi#'.s:key) + echom "'g:jedi#".s:key."' is deprecated. Please use 'g:jedi#".s:val."' instead. Sorry for the inconvenience." + exe 'let g:jedi#'.s:val.' = g:jedi#'.s:key + endif +endfor + +for [s:key, s:val] in items(s:default_settings) + if !exists('g:jedi#'.s:key) + exe 'let g:jedi#'.s:key.' = '.s:val + endif +endfor + +let s:supports_buffer_usages = has('nvim') || exists('*prop_add') + + +" ------------------------------------------------------------------------ +" Python initialization +" ------------------------------------------------------------------------ +let s:script_path = expand(':p:h:h') + +function! s:init_python() abort + " Use g:jedi#force_py_version for loading Jedi, or fall back to using + " `has()` - preferring Python 3. + if !has('python3') + throw 'jedi-vim requires Vim with support for Python 3.' + endif + call jedi#setup_python_imports() + return 1 +endfunction + + +function! jedi#reinit_python() abort + let s:_init_python = -1 + call jedi#init_python() +endfunction + + +" This is meant to be called with `:unsilent` (for &shortmess+=F). +function! s:display_exception() abort + let error_lines = split(v:exception, '\n') + let msg = 'Error: jedi-vim failed to initialize Python: ' + \ .error_lines[0].' (in '.v:throwpoint.')' + if len(error_lines) > 1 + echohl ErrorMsg + echom 'jedi-vim error: '.error_lines[0] + for line in error_lines[1:] + echom line + endfor + echohl None + let help_cmd = ':JediDebugInfo' + if exists(':checkhealth') == 2 + let help_cmd .= ' / :checkhealth' + endif + let msg .= printf('. See :messages and/or %s for more information.', + \ help_cmd) + endif + redraw " Redraw to only have the main message by default. + echoerr msg +endfunction + + +let s:_init_python = -1 +function! jedi#init_python() abort + if s:_init_python == -1 + let s:_init_python = 0 + try + let s:_init_python = s:init_python() + let s:_init_python = 1 + catch /^jedi/ + " Only catch errors from jedi-vim itself here, so that for + " unexpected Python exceptions the traceback will be shown + " (e.g. with NameError in jedi#setup_python_imports's code). + if !exists('g:jedi#squelch_py_warning') + unsilent call s:display_exception() + endif + endtry + endif + return s:_init_python +endfunction + + +function! jedi#setup_python_imports() abort + let g:_jedi_init_error = 0 + let init_lines = [ + \ 'import vim', + \ 'def _jedi_handle_exc(exc_info):', + \ ' try:', + \ ' from jedi_vim_debug import format_exc_info', + \ ' vim.vars["_jedi_init_error"] = format_exc_info(exc_info)', + \ ' except Exception:', + \ ' import traceback', + \ ' vim.vars["_jedi_init_error"] = "\\n".join(traceback.format_exception(*exc_info))', + \ 'try:', + \ ' import jedi_vim', + \ ' if hasattr(jedi_vim, "jedi_import_error"):', + \ ' _jedi_handle_exc(jedi_vim.jedi_import_error)', + \ 'except Exception as exc:', + \ ' _jedi_handle_exc(sys.exc_info())', + \ ] + exe 'python3 exec('''.escape(join(init_lines, '\n'), "'").''')' + if g:_jedi_init_error isnot 0 + throw printf('jedi#setup_python_imports: %s', g:_jedi_init_error) + endif + return 1 +endfunction + + +function! jedi#debug_info() abort + if &verbose + if &filetype !=# 'python' + echohl WarningMsg | echo 'You should run this in a buffer with filetype "python".' | echohl None + endif + endif + let spath = shellescape(s:script_path) + echo '#### Jedi-vim debug information' + echo "\n" + echo '##### jedi-vim version' + echo "\n" + echo ' - jedi-vim git version: ' + echon substitute(system('git -C '.spath.' describe --tags --always --dirty'), '\v\n$', '', '') + echo ' - jedi git submodule status: ' + echon substitute(system('git -C '.spath.' submodule status pythonx/jedi'), '\v\n$', '', '') + echo ' - parso git submodule status: ' + echon substitute(system('git -C '.spath.' submodule status pythonx/parso'), '\v\n$', '', '') + echo "\n" + echo '##### Global Python' + echo "\n" + echo 'Using Python version 3 to access Jedi.' + let s:pythonjedi_called = 0 + try + python3 import vim; vim.command('let s:pythonjedi_called = 1') + catch + echo 'Error when trying to import vim: '.v:exception + endtry + if !s:pythonjedi_called + echohl WarningMsg + echom 'python3 failed to run, likely a Python config issue.' + if exists(':checkhealth') == 2 + echom 'Try :checkhealth for more information.' + endif + echohl None + else + try + python3 from jedi_vim_debug import display_debug_info + python3 display_debug_info() + catch + echohl WarningMsg + echo 'Error when running display_debug_info: '.v:exception + echohl None + endtry + endif + echo "\n" + echo '##### Settings' + echo "\n" + echo '```' + let jedi_settings = items(filter(copy(g:), "v:key =~# '\\v^jedi#'")) + let has_nondefault_settings = 0 + for [k, V] in jedi_settings + exe 'let default = '.get(s:default_settings, + \ substitute(k, '\v^jedi#', '', ''), "'-'") + " vint: -ProhibitUsingUndeclaredVariable + if default !=# V + echo printf('g:%s = %s (default: %s)', k, string(V), string(default)) + unlet! V " Fix variable type mismatch with Vim 7.3. + let has_nondefault_settings = 1 + endif + " vint: +ProhibitUsingUndeclaredVariable + endfor + if has_nondefault_settings + echo "\n" + endif + verb set omnifunc? completeopt? + echo '```' + + if &verbose + echo "\n" + echo '#### :version' + echo '```' + version + echo '```' + echo "\n" + echo '#### :messages' + echo '```' + messages + echo '```' + echo "\n" + echo '
:scriptnames' + echo "\n" + echo '```' + scriptnames + echo '```' + echo '
' + endif +endfunction + +" Helper function instead of `python vim.eval()`, and `.command()` because +" these also return error definitions. +function! jedi#_vim_exceptions(str, is_eval) abort + let l:result = {} + try + if a:is_eval + let l:result.result = eval(a:str) + else + execute a:str + let l:result.result = '' + endif + catch + let l:result.exception = v:exception + let l:result.throwpoint = v:throwpoint + endtry + return l:result +endfunction + +call jedi#init_python() " Might throw an error. + +" ------------------------------------------------------------------------ +" functions that call python code +" ------------------------------------------------------------------------ +function! jedi#goto() abort + python3 jedi_vim.goto(mode="goto") +endfunction + +function! jedi#goto_assignments() abort + python3 jedi_vim.goto(mode="assignment") +endfunction + +function! jedi#goto_definitions() abort + python3 jedi_vim.goto(mode="definition") +endfunction + +function! jedi#goto_stubs() abort + python3 jedi_vim.goto(mode="stubs") +endfunction + +function! jedi#usages() abort + if exists('#jedi_usages#BufWinEnter') + call jedi#clear_usages() + endif + python3 jedi_vim.usages() +endfunction + +if !s:supports_buffer_usages +" Hide usages in the current window. +" Only handles the current window due to matchdelete() restrictions. +function! jedi#_hide_usages_in_win() abort + let winnr = winnr() + let matchids = getwinvar(winnr, '_jedi_usages_vim_matchids', []) + + for matchid in matchids[1:] + call matchdelete(matchid) + endfor + call setwinvar(winnr, '_jedi_usages_vim_matchids', []) + + " Remove the autocommands that might have triggered this function. + augroup jedi_usages + exe 'autocmd! * ' + augroup END + unlet! b:_jedi_usages_needs_clear +endfunction + +" Show usages for current window (Vim without textprops only). +function! jedi#_show_usages_in_win() abort + python3 jedi_vim.highlight_usages_for_vim_win() + + if !exists('#jedi_usages#TextChanged#') + augroup jedi_usages + " Unset highlights on any changes to this buffer. + " NOTE: Neovim's API handles movement of highlights, but would only + " need to clear highlights that are changed inline. + autocmd TextChanged call jedi#_clear_buffer_usages() + + " Hide usages when the buffer is removed from the window, or when + " entering insert mode (but keep them for later). + autocmd BufWinLeave,InsertEnter call jedi#_hide_usages_in_win() + augroup END + endif +endfunction + +" Remove usages for the current buffer (and all its windows). +function! jedi#_clear_buffer_usages() abort + let bufnr = bufnr('%') + let nvim_src_ids = getbufvar(bufnr, '_jedi_usages_src_ids', []) + if !empty(nvim_src_ids) + for src_id in nvim_src_ids + " TODO: could only clear highlights below/after changed line?! + call nvim_buf_clear_highlight(bufnr, src_id, 0, -1) + endfor + else + call jedi#_hide_usages_in_win() + endif +endfunction +endif + +" Remove/unset global usages. +function! jedi#clear_usages() abort + augroup jedi_usages + autocmd! BufWinEnter + autocmd! WinEnter + augroup END + + if !s:supports_buffer_usages + " Vim without textprops: clear current window, + " autocommands will clean others on demand. + call jedi#_hide_usages_in_win() + + " Setup autocommands to clear remaining highlights on WinEnter. + augroup jedi_usages + for b in range(1, bufnr('$')) + if getbufvar(b, '_jedi_usages_needs_clear') + exe 'autocmd WinEnter call jedi#_hide_usages_in_win()' + endif + endfor + augroup END + endif + + python3 jedi_vim.clear_usages() +endfunction + +function! jedi#rename(...) abort + python3 jedi_vim.rename() +endfunction + +function! jedi#rename_visual(...) abort + python3 jedi_vim.rename_visual() +endfunction + +function! jedi#completions(findstart, base) abort + python3 jedi_vim.completions() +endfunction + +function! jedi#enable_speed_debugging() abort + python3 jedi_vim.jedi.set_debug_function(jedi_vim.print_to_stdout, speed=True, warnings=False, notices=False) +endfunction + +function! jedi#enable_debugging() abort + python3 jedi_vim.jedi.set_debug_function(jedi_vim.print_to_stdout) +endfunction + +function! jedi#disable_debugging() abort + python3 jedi_vim.jedi.set_debug_function(None) +endfunction + +function! jedi#py_import(args) abort + python3 jedi_vim.py_import() +endfun + +function! jedi#choose_environment(args) abort + python3 jedi_vim.choose_environment() +endfun + +function! jedi#load_project(args) abort + python3 jedi_vim.load_project() +endfun + +function! jedi#py_import_completions(argl, cmdl, pos) abort + python3 jedi_vim.py_import_completions() +endfun + +function! jedi#clear_cache(bang) abort + if a:bang + python3 jedi_vim.jedi.cache.clear_time_caches(True) + else + python3 jedi_vim.jedi.cache.clear_time_caches(False) + endif +endfunction + + +" ------------------------------------------------------------------------ +" show_documentation +" ------------------------------------------------------------------------ +function! jedi#show_documentation() abort + python3 if jedi_vim.show_documentation() is None: vim.command('return') + + let bn = bufnr('__doc__') + if bn > 0 + let wi=index(tabpagebuflist(tabpagenr()), bn) + if wi >= 0 + " If the __doc__ buffer is open in the current tab, jump to it + silent execute (wi+1).'wincmd w' + else + silent execute 'sbuffer '.bn + endif + else + split __doc__ + endif + + setlocal modifiable + setlocal noswapfile + setlocal buftype=nofile + silent normal! ggdG + silent $put=l:doc + silent normal! 1Gdd + setlocal nomodifiable + setlocal nomodified + setlocal filetype=rst + setlocal foldlevel=200 " do not fold in __doc__ + + if l:doc_lines > g:jedi#max_doc_height " max lines for plugin + let l:doc_lines = g:jedi#max_doc_height + endif + execute 'resize '.l:doc_lines + + " quit comands + nnoremap q ZQ + if len(g:jedi#documentation_command) + execute 'nnoremap '.g:jedi#documentation_command.' ZQ' + endif +endfunction + +" ------------------------------------------------------------------------ +" helper functions +" ------------------------------------------------------------------------ + +function! jedi#add_goto_window(for_usages, len) abort + let height = min([a:len, g:jedi#quickfix_window_height]) + + " Use :copen to go to the window always - the user should select an entry. + execute 'belowright copen '.height + + if &filetype !=# 'qf' + echoerr printf('jedi-vim: unexpected ft with current window (%s), please report!', &filetype) + endif + if g:jedi#use_tabs_not_buffers == 1 + noremap :call jedi#goto_window_on_enter() + endif + + augroup jedi_goto_window + if a:for_usages + autocmd BufWinLeave call jedi#clear_usages() + else + autocmd WinLeave q " automatically leave, if an option is chosen + endif + augroup END + + if a:for_usages && !has('nvim') + if s:supports_buffer_usages + " Setup autocommand for pending highlights with Vim's textprops. + " (cannot be added to unlisted buffers) + augroup jedi_usages + autocmd! BufWinEnter * call s:usages_for_pending_buffers() + augroup END + else + " Setup global autocommand to display any usages for a window. + " Gets removed when closing the quickfix window that displays them, or + " when clearing them (e.g. on TextChanged). + augroup jedi_usages + autocmd! BufWinEnter,WinEnter * call jedi#_show_usages_in_win() + augroup END + endif + endif +endfunction + +" Highlight usages for a buffer if not done so yet (Neovim only). +function! s:usages_for_pending_buffers() abort + python3 jedi_vim._handle_pending_usages_for_buf() +endfunction + + +function! jedi#goto_window_on_enter() abort + let l:list = getqflist() + let l:data = l:list[line('.') - 1] + if l:data.bufnr + " close goto_window buffer + normal! ZQ + python3 jedi_vim.set_buffer(vim.eval('bufname(l:data.bufnr)')) + call cursor(l:data.lnum, l:data.col) + else + echohl WarningMsg | echo 'Builtin module cannot be opened.' | echohl None + endif +endfunction + + +function! s:syn_stack() abort + if !exists('*synstack') + return [] + endif + return map(synstack(line('.'), col('.') - 1), "synIDattr(v:val, 'name')") +endfunc + + +function! jedi#do_popup_on_dot_in_highlight() abort + let highlight_groups = s:syn_stack() + for a in highlight_groups + if a ==# 'pythonDoctest' + return 1 + endif + endfor + + for a in highlight_groups + for b in ['pythonString', 'pythonComment', 'pythonNumber'] + if a == b + return 0 + endif + endfor + endfor + return 1 +endfunc + + +let s:show_call_signatures_last = [0, 0, ''] +function! jedi#show_call_signatures() abort + if s:_init_python == 0 + return 1 + endif + let [line, col] = [line('.'), col('.')] + let curline = getline(line) + let reload_signatures = 1 + + " Caching. On the same line only. + if line == s:show_call_signatures_last[0] + " Check if the number of special signs before or after the + " cursor has not changed since the last call, which means that the + " argument position was not changed and we can skip repainting. + let prevcol = s:show_call_signatures_last[1] + let prevline = s:show_call_signatures_last[2] + let no_special = '[^,()=]' + if substitute(curline[:col-2], no_special, '', 'g') + \ == substitute(prevline[:prevcol-2], no_special, '', 'g') + \ && substitute(curline[(col-2):], no_special, '', 'g') + \ == substitute(prevline[(prevcol-2):], no_special, '', 'g') + let reload_signatures = 0 + endif + endif + let s:show_call_signatures_last = [line, col, curline] + + if reload_signatures + python3 jedi_vim.show_call_signatures() + endif +endfunction + + +function! jedi#clear_call_signatures() abort + if s:_init_python == 0 + return 1 + endif + + let s:show_call_signatures_last = [0, 0, ''] + python3 jedi_vim.clear_call_signatures() +endfunction + + +function! jedi#configure_call_signatures() abort + augroup jedi_call_signatures + autocmd! * + if g:jedi#show_call_signatures == 2 " Command line call signatures + autocmd InsertEnter let g:jedi#first_col = s:save_first_col() + endif + autocmd InsertEnter let s:show_call_signatures_last = [0, 0, ''] + autocmd InsertLeave call jedi#clear_call_signatures() + if g:jedi#show_call_signatures_delay > 0 + autocmd InsertEnter let b:_jedi_orig_updatetime = &updatetime + \ | let &updatetime = g:jedi#show_call_signatures_delay + autocmd InsertLeave if exists('b:_jedi_orig_updatetime') + \ | let &updatetime = b:_jedi_orig_updatetime + \ | unlet b:_jedi_orig_updatetime + \ | endif + autocmd CursorHoldI call jedi#show_call_signatures() + else + autocmd CursorMovedI call jedi#show_call_signatures() + endif + augroup END +endfunction + + +" Determine where the current window is on the screen for displaying call +" signatures in the correct column. +function! s:save_first_col() abort + if bufname('%') ==# '[Command Line]' || winnr('$') == 1 + return 0 + endif + + let startwin = winnr() + let winwidth = winwidth(0) + if winwidth == &columns + return 0 + elseif winnr('$') == 2 + return startwin == 1 ? 0 : (winwidth(1) + 1) + elseif winnr('$') == 3 + if startwin == 1 + return 0 + endif + let ww1 = winwidth(1) + let ww2 = winwidth(2) + let ww3 = winwidth(3) + if ww1 + ww2 + ww3 + 2 == &columns + if startwin == 2 + return ww1 + 1 + else + return ww1 + ww2 + 2 + endif + elseif startwin == 2 + if ww2 + ww3 + 1 == &columns + return 0 + else + return ww1 + 1 + endif + else " startwin == 3 + if ww2 + ww3 + 1 == &columns + return ww2 + 1 + else + return ww1 + 1 + endif + endif + endif + return 0 +endfunction + + +function! jedi#complete_string(autocomplete) abort + if a:autocomplete + if !(g:jedi#popup_on_dot && jedi#do_popup_on_dot_in_highlight()) + return '' + endif + + let s:saved_completeopt = &completeopt + set completeopt-=longest + set completeopt+=menuone + set completeopt-=menu + if &completeopt !~# 'noinsert\|noselect' + " Patch 775 introduced noinsert and noselect, previously these + " options didn't exist. Setting them in earlier versions results in + " errors (E474). + if has('patch-7.4-775') + if g:jedi#popup_select_first + set completeopt+=noinsert + else + set completeopt+=noselect + endif + else + " To pass the tests we use this, it seems to get the closest to + " the other options. I'm really not sure if this properly + " works, but VIM 7.4-775 is already pretty old, so it might not + " be a problem anymore in a few years. + set completeopt+=longest + endif + endif + elseif pumvisible() + return "\" + endif + return "\\\=jedi#complete_opened(".a:autocomplete.")\" +endfunction + + +function! jedi#complete_opened(autocomplete) abort + if a:autocomplete + let &completeopt = s:saved_completeopt + unlet s:saved_completeopt + elseif pumvisible() && g:jedi#popup_select_first && stridx(&completeopt, 'longest') > -1 + return "\" + endif + return '' +endfunction + + +function! jedi#smart_auto_mappings() abort + " Auto put import statement after from module.name and complete + if search('\m^\s*from\s\+[A-Za-z0-9._]\{1,50}\%#\s*$', 'bcn', line('.')) + " Enter character and start completion. + return "\import \=jedi#complete_string(1)\" + endif + return "\" +endfunction + + +function! jedi#setup_completion() abort + " We need our own omnifunc, so this overrides the omnifunc set by + " $VIMRUNTIME/ftplugin/python.vim. + setlocal omnifunc=jedi#completions + + " map ctrl+space for autocompletion + if g:jedi#completions_command ==# '' + " In terminals, sometimes equals . + imap + smap + endif + if len(g:jedi#completions_command) + execute 'inoremap '.g:jedi#completions_command.' jedi#complete_string(0)' + " A separate mapping for select mode: deletes and completes. + execute 'snoremap '.g:jedi#completions_command." '\c'.jedi#complete_string(0)" + endif +endfunction + +"python3 jedi_vim.jedi.set_debug_function(jedi_vim.print_to_stdout, speed=True, warnings=False, notices=False) +"python3 jedi_vim.jedi.set_debug_function(jedi_vim.print_to_stdout) + +" vim: set et ts=4: diff --git a/sources_non_forked/jedi-vim/codecov.yml b/sources_non_forked/jedi-vim/codecov.yml new file mode 100644 index 00000000..a0a30858 --- /dev/null +++ b/sources_non_forked/jedi-vim/codecov.yml @@ -0,0 +1,7 @@ +coverage: + status: + project: true + patch: true + changes: true + +comment: off diff --git a/sources_non_forked/jedi-vim/doc/jedi-vim.txt b/sources_non_forked/jedi-vim/doc/jedi-vim.txt new file mode 100644 index 00000000..3b94a6d5 --- /dev/null +++ b/sources_non_forked/jedi-vim/doc/jedi-vim.txt @@ -0,0 +1,578 @@ +*jedi-vim.txt* - For Vim version 7.3 - Last change: 2014/07/29 + __ _______ _______ __ ____ ____ __ .___ ___.~ + | | | ____|| \ | | \ \ / / | | | \/ |~ + | | | |__ | .--. || | _____\ \/ / | | | \ / |~ +.--. | | | __| | | | || | |______\ / | | | |\/| |~ +| `--' | | |____ | '--' || | \ / | | | | | |~ + \______/ |_______||_______/ |__| \__/ |__| |__| |__|~ + + jedi-vim - awesome Python autocompletion with Vim + +============================================================================== +Contents *jedi-vim-contents* + +1. Introduction |jedi-vim-introduction| +2. Installation |jedi-vim-installation| + 2.0. Requirements |jedi-vim-installation-requirements| + 2.1. Manually |jedi-vim-installation-manually| + 2.2. Using Pathogen |jedi-vim-installation-pathogen| + 2.3. Using Vundle |jedi-vim-installation-vundle| + 2.4. Installing from Repositories |jedi-vim-installation-repos| +3. Supported Python features |jedi-vim-support| +4. Usage |jedi-vim-usage| +5. Mappings |jedi-vim-keybindings| + 5.1. Start completion |g:jedi#completions_command| + 5.2. Go to definition |g:jedi#goto_command| + 5.3. Go to assignment |g:jedi#goto_assignments_command| + 5.4 Go to stub |g:jedi#goto_stubs_command| + 5.5. Show documentation |g:jedi#documentation_command| + 5.6. Rename variables |g:jedi#rename_command| + 5.7. Show name usages |g:jedi#usages_command| + 5.8. Open module by name |:Pyimport| +6. Configuration |jedi-vim-configuration| + 6.1. auto_initialization |g:jedi#auto_initialization| + 6.2. auto_vim_configuration |g:jedi#auto_vim_configuration| + 6.3. popup_on_dot |g:jedi#popup_on_dot| + 6.4. popup_select_first |g:jedi#popup_select_first| + 6.5. auto_close_doc |g:jedi#auto_close_doc| + 6.6. show_call_signatures |g:jedi#show_call_signatures| + 6.7. show_call_signatures_delay |g:jedi#show_call_signatures_delay| + 6.8. use_tabs_not_buffers |g:jedi#use_tabs_not_buffers| + 6.9. squelch_py_warning |g:jedi#squelch_py_warning| + 6.10. completions_enabled |g:jedi#completions_enabled| + 6.11. use_splits_not_buffers |g:jedi#use_splits_not_buffers| + 6.12. force_py_version |g:jedi#force_py_version| + 6.13. smart_auto_mappings |g:jedi#smart_auto_mappings| + 6.14. use_tag_stack |g:jedi#use_tag_stack| + 6.15. environment_path |g:jedi#environment_path| + |b:jedi_environment_path| + 6.16. added_sys_path |g:jedi#added_sys_path| + |b:jedi_added_sys_path| + 6.17. case_insensitive_completion |g:jedi#case_insensitive_completion| + |b:jedi_case_insensitive_completion| +7. Testing |jedi-vim-testing| +8. Contributing |jedi-vim-contributing| +9. License |jedi-vim-license| + +============================================================================== +1. Introduction *jedi-vim-introduction* + +Jedi-vim is a Vim binding to the awesome Python autocompletion library +`jedi`. Among jedi's (and, therefore, jedi-vim's) features are: + +- Completion for a wide array of Python features (see |jedi-vim-support|) +- Robust in dealing with syntax errors and wrong indentation +- Parses complex module/function/class structures +- Infers function arguments from Sphinx/Epydoc strings +- Doesn't execute Python code +- Supports Virtualenv +- Supports Python 2.7 and 3.4+ + +By leveraging this library, jedi-vim adds the following capabilities to Vim: + +- Displaying function/class bodies +- "Go to definition" command +- Displaying docstrings +- Renaming and refactoring +- Looking up related names + +============================================================================== +2. Installation *jedi-vim-installation* + +------------------------------------------------------------------------------ +2.0. Requirements *jedi-vim-installation-requirements* + +First of all, jedi-vim requires Vim to be compiled with the `+python` option. + +It is best if you have VIM >= 7.3, compiled with the `+conceal` option. With +older versions, you will probably not see the parameter recommendation list +for functions after typing the open bracket. Some platforms (including OS X +releases) do not ship a VIM with `+conceal`. You can check if your VIM has the +feature with > + + :ver + +and look for "`+conceal`" (as opposed to "`-conceal`") or > + + :echo has('conceal') + +which will report 0 (not included) or 1 (included). If your VIM lacks this +feature and you would like function parameter completion, you will need to +build your own VIM, or use a package for your operating system that has this +feature (such as MacVim on OS X, which also contains a console binary). + +------------------------------------------------------------------------------ +2.1. Installing manually *jedi-vim-installation-manually* + +1. If you want to install jedi as a submodule instead, issue this command: > + + git clone --recursive http://github.com/davidhalter/jedi-vim + +2. Put the plugin files into their respective folders in your vim runtime + directory (usually ~/.vim). Be sure to pay attention to the directory + structure! +3. Update the Vim help tags with > + + :helptags /doc + +------------------------------------------------------------------------------ +2.2. Installing using Pathogen *jedi-vim-installation-pathogen* + +Pathogen simplifies installation considerably. + +1.a Clone the git repository into your bundles directory: > + + git clone http://github.com/davidhalter/jedi-vim path/to/bundles/jedi-vim + +1b. Again, if you want to install jedi as a submodule, use this command + instead: > + + git clone --recursive http://github.com/davidhalter/jedi-vim + +------------------------------------------------------------------------------ +2.3. Installing using Vundle *jedi-vim-installation-vundle* + +1. Vundle automatically downloads subrepositories as git submodules, so you + will automatically get the jedi library with the jedi-vim plugin. Add the + following to the Bundles section in your .vimrc file: > + + Plugin 'davidhalter/jedi-vim' + +2. Issue the following command in Vim: > + + :PluginInstall + +Help tags are generated automatically, so you should be good to go. + +------------------------------------------------------------------------------ +2.4. Installing from Repositories *jedi-vim-installation-repos* + +Some Linux distributions have jedi-vim packages in their official +repositories. On Arch Linux, install vim-jedi. On Debian (8+) or Ubuntu +(14.04+) install vim-python-jedi. + +============================================================================== +3. Supported Python features *jedi-vim-support* + +The Jedi library does all the hard work behind the scenes. It understands most +Python features, among them: + +- Builtins +- Multiple `return`s or `yield`s +- Tuple assignments/array indexing/dictionary indexing +- `with`-statement/exception handling +- `*args` and `**kwargs` +- Decorators, lambdas, closures +- Generators, iterators +- Some descriptors: `property`/`staticmethod`/`classmethod` +- Some magic methods: `__call__`, `__iter__`, `__next__`, `__get__`, + `__getitem__`, `__init__` +- `list.append()`, `set.add()`, `list.extend()`, etc. +- (Nested) list comprehensions and ternary expressions +- Relative `import`s +- `getattr()`/`__getattr__`/`__getattribute__` +- Function annotations (py3k feature, are being ignored at the moment, but are + parsed) +- Class decorators (py3k feature, are being ignored at the moment, but are + parsed) +- Simple/usual `sys.path` modifications +- `isinstance` checks for `if`/`while`/`assert` case, that doesn't work with + Jedi +- Stubs +- And more... + +Note: This list is not necessarily up to date. For a complete list of +features, please refer to the Jedi documentation at +http://jedi.readthedocs.io. + +============================================================================== +4. Usage *jedi-vim-usage* + +With the default settings, autocompletion can be triggered by typing +. The first entry will automatically be selected, so you can press + to insert it into your code or keep typing and narrow down your +completion options. The usual and / keybindings work as +well. Autocompletion is also triggered by typing a period in insert mode. +Since periods rarely occur in Python code outside of method/import lookups, +this is handy to have (but can be disabled). + +When it encounters a new module, jedi might take a few seconds to parse that +module's contents. Afterwards, the contents are cached and completion will be +almost instantaneous. + +============================================================================== +5. Key Bindings *jedi-vim-keybindings* + +All keybindings can be mapped by setting the appropriate global option. For +example, to set the keybinding for starting omnicompletion to instead of +, add the following setting to your .vimrc file: > + + let g:jedi#completions_command = "" + +Note: If you have |g:jedi#auto_initialization| set to 0, you have to create +a mapping yourself by calling a function: > + + " Using for omnicompletion + inoremap + " Use r (by default <\-r>) for renaming + nnoremap r :call jedi#rename() + " etc. + +Note: You can set commands to '', which means that they are empty and not +assigned. It's an easy way to "disable" functionality of jedi-vim. + +------------------------------------------------------------------------------ +5.1. `g:jedi#completions_command` *g:jedi#completions_command* +Function: n/a; see above +Default: Start completion + +Performs autocompletion (or omnicompletion, to be precise). + +Note: If you want to use for completion, please install Supertab: +https://github.com/ervandew/supertab. + +------------------------------------------------------------------------------ +5.2. `g:jedi#goto_command` *g:jedi#goto_command* +Function: `jedi#goto()` +Default: d Go to definition (or assignment) + +This function first tries |jedi#goto_definitions|, and falls back to +|jedi#goto_assignments| for builtin modules. It produces an error if nothing +could be found. +NOTE: this implementation is subject to change. +Ref: https://github.com/davidhalter/jedi/issues/570 + +This command tries to find the original definition of the function/class under +the cursor. Just like the `jedi#goto_assignments()` function, it does not work +if the definition isn't in a Python source file. + +The difference between `jedi#goto_assignments()` and `jedi#goto_definitions()` +is that the latter performs recursive lookups. Take, for example, the +following module structure: > + + # file1.py: + from file2 import foo + + # file2.py: + from file3 import bar as foo + + # file3.py + def bar(): + pass + +The `jedi#goto_assignments()` function will take you to the > + + from file2 import foo + +statement in file1.py, while the `jedi#goto_definitions()` function will take +you all the way to the > + + def bar(): + +line in file3.py. + +------------------------------------------------------------------------------ +5.3. `g:jedi#goto_assignments_command` *g:jedi#goto_assignments_command* +Function: `jedi#goto_assignments()` +Default: g Go to assignment + +This function finds the first definition of the function/class under the +cursor. It produces an error if the definition is not in a Python file. + +------------------------------------------------------------------------------ +5.4. `g:jedi#goto_stubs_command` *g:jedi#goto_stubs_command* +Function: `jedi#goto_stubs()` +Default: s Go to stub + +Finds the stub of the function/class under the cursor. + +------------------------------------------------------------------------------ +5.5. `g:jedi#documentation_command` *g:jedi#documentation_command* +Function: `jedi#show_documentation()` +Default: Show pydoc documentation + +This shows the pydoc documentation for the item currently under the cursor. +The documentation is opened in a horizontally split buffer. The height of this +buffer is controlled by `g:jedi#max_doc_height` (set by default to 30). + +------------------------------------------------------------------------------ +5.6. `g:jedi#rename_command` *g:jedi#rename_command* +Function: `jedi#rename()` +Default: r Rename variables + +Jedi-vim deletes the word currently under the cursor and puts Vim in insert +mode, where the user is expected to enter the new variable name. Upon leaving +insert mode, jedi-vim then renames all occurrences of the old variable name +with the new one. The number of performed renames is displayed in the command +line. + +------------------------------------------------------------------------------ +5.7. `g:jedi#usages_command` *g:jedi#usages_command* +Function: `jedi#usages()` +Default: n Show usages of a name. + +The quickfix window is populated with a list of all names which point to the +definition of the name under the cursor. + +------------------------------------------------------------------------------ +5.8. Open module by name *:Pyimport* +Function: `jedi#py_import(args)` +Default: :Pyimport e.g. `:Pyimport os` shows os.py in VIM. + +Simulate an import and open that module in VIM. + +============================================================================== +6. Configuration *jedi-vim-configuration* + +Note: You currently have to set these options in your .vimrc. Setting them in +an ftplugin (e.g. ~/.vim/ftplugin/python/jedi-vim-settings.vim) will not work +because jedi-vim is not set up as an filetype plugin, but as a "regular" +plugin. + +------------------------------------------------------------------------------ +6.1. `g:jedi#auto_initialization` *g:jedi#auto_initialization* + +Upon initialization, jedi-vim performs the following steps: + +1. Set the current buffers 'omnifunc' to its own completion function + `jedi#completions` +2. Create mappings to commands specified in |jedi-vim-keybindings| +3. Call `jedi#configure_call_signatures()` if + `g:jedi#show_call_signatures` is set + +You can disable the default initialization routine by setting this option to +0. Beware that you have to perform the above steps yourself, though. + +Options: 0 or 1 +Default: 1 (Perform automatic initialization) + +------------------------------------------------------------------------------ +6.2. `g:jedi#auto_vim_configuration` *g:jedi#auto_vim_configuration* + +Jedi-vim sets 'completeopt' to `menuone,longest,preview` by default, if +'completeopt' is not changed from Vim's default. +It also remaps to in insert mode. + +If you want to keep your own configuration, disable this setting. + +Options: 0 or 1 +Default: 1 (Set 'completeopt' and mapping as described above) + +------------------------------------------------------------------------------ +6.3. `g:jedi#popup_on_dot` *g:jedi#popup_on_dot* + +Jedi-vim automatically starts completion upon typing a period in insert mode. + +However, when working with large modules, this can slow down your typing flow +since you have to wait for jedi to parse the module and show the completion +menu. By disabling this setting, completion is only started when you manually +press the completion key. +You need to also have `g:jedi#completions_enabled` enabled for this. + +Options: 0 or 1 +Default: 1 (Start completion on typing a period) + +------------------------------------------------------------------------------ +6.4. `g:jedi#popup_select_first` *g:jedi#popup_select_first* + +Upon starting completion, jedi-vim can automatically select the first entry +that pops up (without actually inserting it). + +This leads to a better typing flow: As you type more characters, the entries +in the completion menu are narrowed down. If they are narrowed down enough, +you can just press to insert the first match. + +Options: 0 or 1 +Default: 1 (Automatically select first completion entry) + +------------------------------------------------------------------------------ +6.5. `g:jedi#auto_close_doc` *g:jedi#auto_close_doc* + +When doing completion, jedi-vim shows the docstring of the currently selected +item in a preview window. By default, this window is being closed after +insertion of a completion item. + +Set this to 0 to leave the preview window open even after leaving insert mode. +This could be useful if you want to browse longer docstrings. + +Options: 0 or 1 +Default: 1 (Automatically close preview window upon leaving insert mode) + +------------------------------------------------------------------------------ +6.6. `g:jedi#show_call_signatures` *g:jedi#show_call_signatures* + +Jedi-vim can display a small window detailing the arguments of the currently +completed function and highlighting the currently selected argument. This can +be disabled by setting this option to 0. Setting this option to 2 shows call +signatures in the command line instead of a popup window. + +Options: 0, 1, or 2 +Default: 1 (Show call signatures window) + +Note: 'showmode' must be disabled for command line call signatures to be +visible. + +Note: This setting is ignored if |g:jedi#auto_initialization| is set to 0. In +that case, if you want to see call signatures, you have to set it up +manually by calling a function in your configuration file: > + + call jedi#configure_call_signatures() + +------------------------------------------------------------------------------ +6.7. `g:jedi#show_call_signatures_delay` *g:jedi#show_call_signatures_delay* + +The delay to be used with |g:jedi#show_call_signatures|. If it is greater +than 0 it will use Vim's |CursorHoldI| event instead of |CursorMovedI|. +It will temporarily set Vim's |'updatetime'| option during insert mode. + +Options: delay in milliseconds +Default: 500 + +------------------------------------------------------------------------------ +6.8. `g:jedi#use_tabs_not_buffers` *g:jedi#use_tabs_not_buffers* + +You can make jedi-vim open a new tab if you use the "go to", "show +definition", or "related names" commands. When you leave this at the default +(0), they open in the current window instead. + +Options: 0 or 1 +Default: 0 (Command output reuses current window) + +------------------------------------------------------------------------------ +6.9. `g:jedi#squelch_py_warning` *g:jedi#squelch_py_warning* + +When Vim has not been compiled with +python, jedi-vim shows a warning to that +effect and aborts loading itself. Set this to 1 to suppress that warning. + +Options: 0 or 1 +Default: 0 (Warning is shown) + +------------------------------------------------------------------------------ +6.10. `g:jedi#completions_enabled` *g:jedi#completions_enabled* + +If you don't want Jedi completion, but all the other features, you can disable +it in favor of another completion engine (that probably also uses Jedi, like +YCM). + +Options: 0 or 1 +Default: 1 + +------------------------------------------------------------------------------ +6.11. `g:jedi#use_splits_not_buffers` *g:jedi#use_splits_not_buffers* + +If you want to open new split for "go to", you could set this option to the +direction which you want to open a split with. + +Options: top, left, right, bottom or winwidth +Default: "" (not enabled by default) + +Note: with the 'winwidth' option the window is split vertically or horizontally +depending on the width of the window relative to 'textwidth'. This essentially +means that if the window is big enough it will be split vertically but if it is +small a horizontal split happens. + +------------------------------------------------------------------------------ +6.12. `g:jedi#force_py_version` *g:jedi#force_py_version* + +If you have installed multiple Python versions, you can force the Python +version that is going to be used. +You don't have to compile VIM with multiple Python versions. +The variable can be set in the .vimrc like this to force python 2: + +let g:jedi#force_py_version = 2 + +By default jedi loads the latest Python version installed on your system that +can be found. + +This variable can be changed during runtime. + +Options: 2, 2.7, 3, 3.5, 3.6, ... +Default: "auto" +------------------------------------------------------------------------------ +6.13. `g:jedi#smart_auto_mappings` *g:jedi#smart_auto_mappings* + +When you start typing `from module.name` jedi-vim automatically +can add the "import" statement and trigger the autocompletion popup. + +You can enable this using: > + + let g:jedi#smart_auto_mappings = 1 +< +Options: 0 or 1 +Default: 0 (disabled by default) + +------------------------------------------------------------------------------ +6.14. `g:jedi#use_tag_stack` *g:jedi#use_tag_stack* + +Write results of |jedi#goto| to a temporary file and use the |:tjump| command +to enable full |tagstack| functionality. Use of the tag stack allows +returning to the usage of a function with CTRL-T after exploring the +definition with arbitrary changes to the |jumplist|. + +Options: 0 or 1 +Default: 1 (enabled by default) + +------------------------------------------------------------------------------ +6.15. `g:jedi#environment_path` *g:jedi#environment_path* + *b:jedi_environment_path* + +To use a specific virtualenv or a specific Python version it is possible to +set an interpreter. + +Both setting the directory and setting a project is working. + +Examples: "/usr/bin/python3.9", "venv", "../venv", "../venv/bin/python" + +The buffer-local variable `b:jedi_environment_path` can be used to override the +global variable `g:jedi#environment_path`. + +Default: "auto" + +------------------------------------------------------------------------------ +6.16. `g:jedi#added_sys_path` *g:jedi#added_sys_path* + *b:jedi_added_sys_path* + +To add extra sys_path. + +The buffer-local variable `b:jedi_added_sys_path` can be used to add +additional extra sys_path. + +Examples: ["../site-packages"] +Default: [] + +------------------------------------------------------------------------------ +6.17. `g:jedi#case_insensitive_completion` *g:jedi#case_insensitive_completion* + *b:jedi_case_insensitive_completion* + +0 to disable case insensitive completion. +1 to enable case insensitive completion (default). + +The buffer-local variable `b:jedi_case_insensitive_completion` can be used to +override the global variable `g:jedi#case_insensitive_completion`. + +Default: 1 + +============================================================================== +7. Testing *jedi-vim-testing* + +jedi-vim is being tested with a combination of vspec +https://github.com/kana/vim-vspec and py.test http://pytest.org/. + +The tests are in the test subdirectory, you can run them calling:: + + py.test + +The tests are automatically run with `travis +`_. + +============================================================================== +8. Contributing *jedi-vim-contributing* + +We love Pull Requests! Read the instructions in `CONTRIBUTING.md`. + +============================================================================== +9. License *jedi-vim-license* + +Jedi-vim is licensed with the MIT license. + + vim: textwidth=78 et filetype=help:norightleft: diff --git a/sources_non_forked/jedi-vim/doc/logotype-a.svg b/sources_non_forked/jedi-vim/doc/logotype-a.svg new file mode 100644 index 00000000..80380bdd --- /dev/null +++ b/sources_non_forked/jedi-vim/doc/logotype-a.svg @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sources_non_forked/jedi-vim/ftplugin/python/jedi.vim b/sources_non_forked/jedi-vim/ftplugin/python/jedi.vim new file mode 100644 index 00000000..5b97b9c2 --- /dev/null +++ b/sources_non_forked/jedi-vim/ftplugin/python/jedi.vim @@ -0,0 +1,53 @@ +if !jedi#init_python() + finish +endif +" ------------------------------------------------------------------------ +" Initialization of jedi-vim +" ------------------------------------------------------------------------ + +if g:jedi#auto_initialization + " goto / get_definition / usages + if len(g:jedi#goto_command) + execute 'nnoremap '.g:jedi#goto_command.' :call jedi#goto()' + endif + if len(g:jedi#goto_assignments_command) + execute 'nnoremap '.g:jedi#goto_assignments_command.' :call jedi#goto_assignments()' + endif + if len(g:jedi#goto_definitions_command) + execute 'nnoremap '.g:jedi#goto_definitions_command.' :call jedi#goto_definitions()' + endif + if len(g:jedi#goto_stubs_command) + execute 'nnoremap '.g:jedi#goto_stubs_command.' :call jedi#goto_stubs()' + endif + if len(g:jedi#usages_command) + execute 'nnoremap '.g:jedi#usages_command.' :call jedi#usages()' + endif + " rename + if len(g:jedi#rename_command) + execute 'nnoremap '.g:jedi#rename_command.' :call jedi#rename()' + execute 'vnoremap '.g:jedi#rename_command.' :call jedi#rename_visual()' + endif + " documentation/pydoc + if len(g:jedi#documentation_command) + execute 'nnoremap '.g:jedi#documentation_command.' :call jedi#show_documentation()' + endif + + if g:jedi#show_call_signatures > 0 + call jedi#configure_call_signatures() + endif + + if g:jedi#completions_enabled == 1 + inoremap . .=jedi#complete_string(1) + endif + + if g:jedi#smart_auto_mappings == 1 + inoremap =jedi#smart_auto_mappings() + end + + if g:jedi#auto_close_doc + " close preview if its still open after insert + augroup jedi_preview + autocmd! InsertLeave if pumvisible() == 0|pclose|endif + augroup END + endif +endif diff --git a/sources_non_forked/jedi-vim/plugin/jedi.vim b/sources_non_forked/jedi-vim/plugin/jedi.vim new file mode 100644 index 00000000..d409240c --- /dev/null +++ b/sources_non_forked/jedi-vim/plugin/jedi.vim @@ -0,0 +1,77 @@ +"jedi-vim - Omni Completion for python in vim +" Maintainer: David Halter +" +" This part of the software is just the vim interface. The really big deal is +" the Jedi Python library. + +if get(g:, 'jedi#auto_vim_configuration', 1) + " jedi-vim doesn't work in compatible mode (vim script syntax problems) + if &compatible + " vint: -ProhibitSetNoCompatible + set nocompatible + " vint: +ProhibitSetNoCompatible + endif + + " jedi-vim really needs, otherwise jedi-vim cannot start. + filetype plugin on + + augroup jedi_pyi + au! + autocmd BufNewFile,BufRead *.pyi set filetype=python + augroup END + + " Change completeopt, but only if it was not set already. + " This gets done on VimEnter, since otherwise Vim fails to restore the + " screen. Neovim is not affected, this is likely caused by using + " :redir/execute() before the (alternate) terminal is configured. + function! s:setup_completeopt() + if exists('*execute') + let completeopt = execute('silent verb set completeopt?') + else + redir => completeopt + silent verb set completeopt? + redir END + endif + if len(split(completeopt, '\n')) == 1 + set completeopt=menuone,longest,preview + endif + endfunction + if has('nvim') + call s:setup_completeopt() + else + augroup jedi_startup + au! + autocmd VimEnter * call s:setup_completeopt() + augroup END + endif + + if len(mapcheck('', 'i')) == 0 + inoremap + endif +endif + +" Pyimport command +command! -nargs=1 -complete=custom,jedi#py_import_completions Pyimport :call jedi#py_import() + +command! -nargs=? -complete=file JediChooseEnvironment :call jedi#choose_environment() +command! -nargs=? -complete=file JediLoadProject :call jedi#load_project() + + +function! s:jedi_debug_info() + " Ensure the autoload file has been loaded (and ignore any errors, which + " will be displayed with the debug info). + let unset = {} + let saved_squelch_py_warning = get(g:, 'jedi#squelch_py_warning', unset) + let g:jedi#squelch_py_warning = 1 + call jedi#init_python() + if saved_squelch_py_warning is unset + unlet g:jedi#squelch_py_warning + else + let g:jedi#squelch_py_warning = saved_squelch_py_warning + endif + call jedi#debug_info() +endfunction +command! -nargs=0 -bar JediDebugInfo call s:jedi_debug_info() +command! -nargs=0 -bang JediClearCache call jedi#clear_cache(0) + +" vim: set et ts=4: diff --git a/sources_non_forked/jedi-vim/pythonx/jedi_vim.py b/sources_non_forked/jedi-vim/pythonx/jedi_vim.py new file mode 100644 index 00000000..b140668a --- /dev/null +++ b/sources_non_forked/jedi-vim/pythonx/jedi_vim.py @@ -0,0 +1,1211 @@ +# -*- coding: utf-8 -*- +""" +The Python parts of the Jedi library for VIM. It is mostly about communicating +with VIM. +""" + +from typing import Optional +import traceback # for exception output +import re +import os +import sys +from shlex import split as shsplit +from contextlib import contextmanager +from pathlib import Path +try: + from itertools import zip_longest +except ImportError: + from itertools import izip_longest as zip_longest # Python 2 + +import vim + +is_py3 = sys.version_info[0] >= 3 +if is_py3: + ELLIPSIS = "…" + unicode = str +else: + ELLIPSIS = u"…" + + +try: + # Somehow sys.prefix is set in combination with VIM and virtualenvs. + # However the sys path is not affected. Just reset it to the normal value. + sys.prefix = sys.base_prefix + sys.exec_prefix = sys.base_exec_prefix +except AttributeError: + # If we're not in a virtualenv we don't care. Everything is fine. + pass + + +class PythonToVimStr(unicode): + """ Vim has a different string implementation of single quotes """ + __slots__ = [] + + def __new__(cls, obj, encoding='UTF-8'): + if not (is_py3 or isinstance(obj, unicode)): + obj = unicode.__new__(cls, obj, encoding) + + # Vim cannot deal with zero bytes: + obj = obj.replace('\0', '\\0') + return unicode.__new__(cls, obj) + + def __repr__(self): + # this is totally stupid and makes no sense but vim/python unicode + # support is pretty bad. don't ask how I came up with this... It just + # works... + # It seems to be related to that bug: http://bugs.python.org/issue5876 + if unicode is str: + s = self + else: + s = self.encode('UTF-8') + return '"%s"' % s.replace('\\', '\\\\').replace('"', r'\"') + + +class VimError(Exception): + def __init__(self, message, throwpoint, executing): + super(type(self), self).__init__(message) + self.message = message + self.throwpoint = throwpoint + self.executing = executing + + def __str__(self): + return "{}; created by {!r} (in {})".format( + self.message, self.executing, self.throwpoint + ) + + +def _catch_exception(string, is_eval): + """ + Interface between vim and python calls back to it. + Necessary, because the exact error message is not given by `vim.error`. + """ + result = vim.eval('jedi#_vim_exceptions({0}, {1})'.format( + repr(PythonToVimStr(string, 'UTF-8')), int(is_eval))) + if 'exception' in result: + raise VimError(result['exception'], result['throwpoint'], string) + return result['result'] + + +def vim_command(string): + _catch_exception(string, is_eval=False) + + +def vim_eval(string): + return _catch_exception(string, is_eval=True) + + +def no_jedi_warning(error=None): + vim.command('echohl WarningMsg') + vim.command('echom "Please install Jedi if you want to use jedi-vim."') + if error: + vim.command('echom "The error was: {0}"'.format(error)) + vim.command('echohl None') + + +def echo_highlight(msg): + vim_command('echohl WarningMsg | echom "jedi-vim: {0}" | echohl None'.format( + str(msg).replace('"', '\\"'))) + + +jedi_path = os.path.join(os.path.dirname(__file__), 'jedi') +sys.path.insert(0, jedi_path) +parso_path = os.path.join(os.path.dirname(__file__), 'parso') +sys.path.insert(0, parso_path) + +try: + import jedi +except ImportError: + jedi = None + jedi_import_error = sys.exc_info() +else: + try: + version = jedi.__version__ + except Exception as e: # e.g. AttributeError + echo_highlight( + "Error when loading the jedi python module ({0}). " + "Please ensure that Jedi is installed correctly (see Installation " + "in the README.".format(e)) + jedi = None + else: + if isinstance(version, str): + # the normal use case, now. + from jedi import utils + version = utils.version_info() + if version < (0, 7): + echo_highlight('Please update your Jedi version, it is too old.') +finally: + sys.path.remove(jedi_path) + sys.path.remove(parso_path) + + +class VimCompat: + _eval_cache = {} + _func_cache = {} + + @classmethod + def has(cls, what): + try: + return cls._eval_cache[what] + except KeyError: + ret = cls._eval_cache[what] = cls.call('has', what) + return ret + + @classmethod + def call(cls, func, *args): + try: + f = cls._func_cache[func] + except KeyError: + if IS_NVIM: + f = cls._func_cache[func] = getattr(vim.funcs, func) + else: + f = cls._func_cache[func] = vim.Function(func) + return f(*args) + + @classmethod + def setqflist(cls, items, title, context): + if cls.has('patch-7.4.2200'): # can set qf title. + what = {'title': title} + if cls.has('patch-8.0.0590'): # can set qf context + what['context'] = {'jedi_usages': context} + if cls.has('patch-8.0.0657'): # can set items via "what". + what['items'] = items + cls.call('setqflist', [], ' ', what) + else: + # Can set title (and maybe context), but needs two calls. + cls.call('setqflist', items) + cls.call('setqflist', items, 'a', what) + else: + cls.call('setqflist', items) + + @classmethod + def setqflist_title(cls, title): + if cls.has('patch-7.4.2200'): + cls.call('setqflist', [], 'a', {'title': title}) + + @classmethod + def can_update_current_qflist_for_context(cls, context): + if cls.has('patch-8.0.0590'): # can set qf context + return cls.call('getqflist', {'context': 1})['context'] == { + 'jedi_usages': context, + } + + +def catch_and_print_exceptions(func): + def wrapper(*args, **kwargs): + try: + return func(*args, **kwargs) + except (Exception, vim.error): + print(traceback.format_exc()) + return None + return wrapper + + +def _check_jedi_availability(show_error=False): + def func_receiver(func): + def wrapper(*args, **kwargs): + if jedi is None: + if show_error: + no_jedi_warning() + return + else: + return func(*args, **kwargs) + return wrapper + return func_receiver + + +# Tuple of cache key / project +_current_project_cache = None, None + + +def get_project(): + vim_environment_path = vim_eval( + "get(b:, 'jedi_environment_path', g:jedi#environment_path)" + ) + vim_project_path = vim_eval("g:jedi#project_path") + + vim_added_sys_path = vim_eval("get(g:, 'jedi#added_sys_path', [])") + vim_added_sys_path += vim_eval("get(b:, 'jedi_added_sys_path', [])") + + global _current_project_cache + cache_key = dict(project_path=vim_project_path, + environment_path=vim_environment_path, + added_sys_path=vim_added_sys_path) + if cache_key == _current_project_cache[0]: + return _current_project_cache[1] + + if vim_environment_path in ("auto", "", None): + environment_path = None + else: + environment_path = vim_environment_path + + if vim_project_path in ("auto", "", None): + project_path = jedi.get_default_project().path + else: + project_path = vim_project_path + + project = jedi.Project(project_path, + environment_path=environment_path, + added_sys_path=vim_added_sys_path) + + _current_project_cache = cache_key, project + return project + + +@catch_and_print_exceptions +def choose_environment(): + args = shsplit(vim.eval('a:args')) + + envs = list(jedi.find_system_environments()) + envs.extend(jedi.find_virtualenvs(paths=args or None)) + + env_paths = [env.executable for env in envs] + + vim_command('belowright new') + vim.current.buffer[:] = env_paths + vim.current.buffer.name = "Hit Enter to Choose an Environment" + vim_command( + 'setlocal buftype=nofile bufhidden=wipe noswapfile nobuflisted readonly nomodifiable') + vim_command('noremap :bw') + vim_command('noremap :python3 jedi_vim.choose_environment_hit_enter()') + + +@catch_and_print_exceptions +def choose_environment_hit_enter(): + vim.vars['jedi#environment_path'] = vim.current.line + vim_command('bd') + + +@catch_and_print_exceptions +def load_project(): + path = vim.eval('a:args') + vim.vars['jedi#project_path'] = path + env_path = vim_eval("g:jedi#environment_path") + if env_path == 'auto': + env_path = None + if path: + try: + project = jedi.Project.load(path) + except FileNotFoundError: + project = jedi.Project(path, environment_path=env_path) + project.save() + else: + project = jedi.get_default_project() + path = project.path + project.save() + + global _current_project_cache + cache_key = dict(project_path=path, + environment_path=env_path, + added_sys_path=[]) + _current_project_cache = cache_key, project + + +@catch_and_print_exceptions +def get_script(source=None): + jedi.settings.additional_dynamic_modules = [ + b.name for b in vim.buffers if ( + b.name is not None and + b.name.endswith('.py') and + b.options['buflisted'])] + if source is None: + source = '\n'.join(vim.current.buffer) + buf_path = vim.current.buffer.name + if not buf_path: + # If a buffer has no name its name is an empty string. + buf_path = None + + return jedi.Script(source, path=buf_path, project=get_project()) + + +def get_pos(column=None): + row = vim.current.window.cursor[0] + if column is None: + column = vim.current.window.cursor[1] + return row, column + + +@_check_jedi_availability(show_error=False) +@catch_and_print_exceptions +def completions(): + jedi.settings.case_insensitive_completion = \ + bool(int(vim_eval("get(b:, 'jedi_case_insensitive_completion', " + "g:jedi#case_insensitive_completion)"))) + + row, column = vim.current.window.cursor + # Clear call signatures in the buffer so they aren't seen by the completer. + # Call signatures in the command line can stay. + if int(vim_eval("g:jedi#show_call_signatures")) == 1: + clear_call_signatures() + if vim.eval('a:findstart') == '1': + count = 0 + for char in reversed(vim.current.line[:column]): + if not re.match(r'[\w\d]', char): + break + count += 1 + vim.command('return %i' % (column - count)) + else: + base = vim.eval('a:base') + source = '' + for i, line in enumerate(vim.current.buffer): + # enter this path again, otherwise source would be incomplete + if i == row - 1: + source += line[:column] + base + line[column:] + else: + source += line + source += '\n' + # here again hacks, because jedi has a different interface than vim + column += len(base) + try: + script = get_script(source=source) + completions = script.complete(*get_pos(column)) + signatures = script.get_signatures(*get_pos(column)) + + add_info = "preview" in vim.eval("&completeopt").split(",") + out = [] + for c in completions: + d = dict(word=PythonToVimStr(c.name[:len(base)] + c.complete), + abbr=PythonToVimStr(c.name_with_symbols), + # stuff directly behind the completion + menu=PythonToVimStr(c.description), + icase=1, # case insensitive + dup=1 # allow duplicates (maybe later remove this) + ) + if add_info: + try: + d["info"] = PythonToVimStr(c.docstring()) + except Exception: + print("jedi-vim: error with docstring for %r: %s" % ( + c, traceback.format_exc())) + out.append(d) + + strout = str(out) + except Exception: + # print to stdout, will be in :messages + print(traceback.format_exc()) + strout = '' + completions = [] + signatures = [] + + show_call_signatures(signatures) + vim.command('return ' + strout) + + +@contextmanager +def tempfile(content): + # Using this instead of the tempfile module because Windows won't read + # from a file not yet written to disk + with open(vim_eval('tempname()'), 'w') as f: + f.write(content) + try: + yield f + finally: + os.unlink(f.name) + + +@_check_jedi_availability(show_error=True) +@catch_and_print_exceptions +def goto(mode="goto"): + """ + :param str mode: "definition", "assignment", "goto" + :rtype: list of jedi.api.classes.Name + """ + script = get_script() + pos = get_pos() + if mode == "goto": + names = script.goto(*pos, follow_imports=True) + elif mode == "definition": + names = script.infer(*pos) + elif mode == "assignment": + names = script.goto(*pos) + elif mode == "stubs": + names = script.goto(*pos, follow_imports=True, only_stubs=True) + + if not names: + echo_highlight("Couldn't find any definitions for this.") + elif len(names) == 1 and mode != "related_name": + n = list(names)[0] + _goto_specific_name(n) + else: + show_goto_multi_results(names, mode) + return names + + +def _goto_specific_name(n, options=''): + if n.column is None: + if n.is_keyword: + echo_highlight("Cannot get the definition of Python keywords.") + else: + name = 'Namespaces' if n.type == 'namespace' else 'Builtin modules' + echo_highlight( + "%s cannot be displayed (%s)." + % (name, n.full_name or n.name) + ) + else: + using_tagstack = int(vim_eval('g:jedi#use_tag_stack')) == 1 + result = set_buffer(n.module_path, options=options, + using_tagstack=using_tagstack) + if not result: + return [] + if (using_tagstack and n.module_path and + n.module_path.exists()): + tagname = n.name + with tempfile('{0}\t{1}\t{2}'.format( + tagname, n.module_path, 'call cursor({0}, {1})'.format( + n.line, n.column + 1))) as f: + old_tags = vim.eval('&tags') + old_wildignore = vim.eval('&wildignore') + try: + # Clear wildignore to ensure tag file isn't ignored + vim.command('set wildignore=') + vim.command('let &tags = %s' % + repr(PythonToVimStr(f.name))) + vim.command('tjump %s' % tagname) + finally: + vim.command('let &tags = %s' % + repr(PythonToVimStr(old_tags))) + vim.command('let &wildignore = %s' % + repr(PythonToVimStr(old_wildignore))) + vim.current.window.cursor = n.line, n.column + + +def relpath(path): + """Make path relative to cwd if it is below.""" + abspath = os.path.abspath(path) + if abspath.startswith(os.getcwd()): + return os.path.relpath(path) + return path + + +def annotate_description(n): + code = n.get_line_code().strip() + if n.type == 'statement': + return code + if n.type == 'function': + if code.startswith('def'): + return code + typ = 'def' + else: + typ = n.type + return '[%s] %s' % (typ, code) + + +def show_goto_multi_results(names, mode): + """Create (or reuse) a quickfix list for multiple names.""" + global _current_names + + lst = [] + (row, col) = vim.current.window.cursor + current_idx = None + current_def = None + for n in names: + if n.column is None: + # Typically a namespace, in the future maybe other things as + # well. + lst.append(dict(text=PythonToVimStr(n.description))) + else: + text = annotate_description(n) + lst.append(dict(filename=PythonToVimStr(relpath(str(n.module_path))), + lnum=n.line, col=n.column + 1, + text=PythonToVimStr(text))) + + # Select current/nearest entry via :cc later. + if n.line == row and n.column <= col: + if (current_idx is None + or (abs(lst[current_idx]["col"] - col) + > abs(n.column - col))): + current_idx = len(lst) + current_def = n + + # Build qflist title. + qf_title = mode + if current_def is not None: + if current_def.full_name: + qf_title += ": " + current_def.full_name + else: + qf_title += ": " + str(current_def) + select_entry = current_idx + else: + select_entry = 0 + + qf_context = id(names) + if (_current_names + and VimCompat.can_update_current_qflist_for_context(qf_context)): + # Same list, only adjust title/selected entry. + VimCompat.setqflist_title(qf_title) + vim_command('%dcc' % select_entry) + else: + VimCompat.setqflist(lst, title=qf_title, context=qf_context) + for_usages = mode == "usages" + vim_eval('jedi#add_goto_window(%d, %d)' % (for_usages, len(lst))) + vim_command('%d' % select_entry) + + +def _same_names(a, b): + """Compare without _inference_state. + + Ref: https://github.com/davidhalter/jedi-vim/issues/952) + """ + return all( + x._name.start_pos == y._name.start_pos + and x.module_path == y.module_path + and x.name == y.name + for x, y in zip(a, b) + ) + + +@catch_and_print_exceptions +def usages(visuals=True): + script = get_script() + names = script.get_references(*get_pos()) + if not names: + echo_highlight("No usages found here.") + return names + + if visuals: + global _current_names + + if _current_names: + if _same_names(_current_names, names): + names = _current_names + else: + clear_usages() + assert not _current_names + + show_goto_multi_results(names, "usages") + if not _current_names: + _current_names = names + highlight_usages() + else: + assert names is _current_names # updated above + return names + + +_current_names = None +"""Current definitions to use for highlighting.""" +_pending_names = {} +"""Pending definitions for unloaded buffers.""" +_placed_names_in_buffers = set() +"""Set of buffers for faster cleanup.""" + + +IS_NVIM = hasattr(vim, 'from_nvim') +if IS_NVIM: + vim_prop_add = None +else: + vim_prop_type_added = False + try: + vim_prop_add = vim.Function("prop_add") + except ValueError: + vim_prop_add = None + else: + vim_prop_remove = vim.Function("prop_remove") + + +def clear_usages(): + """Clear existing highlights.""" + global _current_names + if _current_names is None: + return + _current_names = None + + if IS_NVIM: + for buf in _placed_names_in_buffers: + src_ids = buf.vars.get('_jedi_usages_src_ids') + if src_ids is not None: + for src_id in src_ids: + buf.clear_highlight(src_id) + elif vim_prop_add: + for buf in _placed_names_in_buffers: + vim_prop_remove({ + 'type': 'jediUsage', + 'all': 1, + 'bufnr': buf.number, + }) + else: + # Unset current window only. + assert _current_names is None + highlight_usages_for_vim_win() + + _placed_names_in_buffers.clear() + + +def highlight_usages(): + """Set usage names to be highlighted. + + With Neovim it will use the nvim_buf_add_highlight API to highlight all + buffers already. + + With Vim without support for text-properties only the current window is + highlighted via matchaddpos, and autocommands are setup to highlight other + windows on demand. Otherwise Vim's text-properties are used. + """ + global _current_names, _pending_names + + names = _current_names + _pending_names = {} + + if IS_NVIM or vim_prop_add: + bufs = {x.name: x for x in vim.buffers} + defs_per_buf = {} + for name in names: + try: + buf = bufs[str(name.module_path)] + except KeyError: + continue + defs_per_buf.setdefault(buf, []).append(name) + + if IS_NVIM: + # We need to remember highlight ids with Neovim's API. + buf_src_ids = {} + for buf, names in defs_per_buf.items(): + buf_src_ids[buf] = [] + for name in names: + src_id = _add_highlighted_name(buf, name) + buf_src_ids[buf].append(src_id) + for buf, src_ids in buf_src_ids.items(): + buf.vars['_jedi_usages_src_ids'] = src_ids + else: + for buf, names in defs_per_buf.items(): + try: + for name in names: + _add_highlighted_name(buf, name) + except vim.error as exc: + if exc.args[0].startswith('Vim:E275:'): + # "Cannot add text property to unloaded buffer" + _pending_names.setdefault(buf.name, []).extend( + names) + else: + highlight_usages_for_vim_win() + + +def _handle_pending_usages_for_buf(): + """Add (pending) highlights for the current buffer (Vim with textprops).""" + buf = vim.current.buffer + bufname = buf.name + try: + buf_names = _pending_names[bufname] + except KeyError: + return + for name in buf_names: + _add_highlighted_name(buf, name) + del _pending_names[bufname] + + +def _add_highlighted_name(buf, name): + lnum = name.line + start_col = name.column + + # Skip highlighting of module definitions that point to the start + # of the file. + if name.type == 'module' and lnum == 1 and start_col == 0: + return + + _placed_names_in_buffers.add(buf) + + # TODO: validate that name.name is at this position? + # Would skip the module definitions from above already. + + length = len(name.name) + if vim_prop_add: + # XXX: needs jediUsage highlight (via after/syntax/python.vim). + global vim_prop_type_added + if not vim_prop_type_added: + vim.eval("prop_type_add('jediUsage', {'highlight': 'jediUsage'})") + vim_prop_type_added = True + vim_prop_add(lnum, start_col+1, { + 'type': 'jediUsage', + 'bufnr': buf.number, + 'length': length, + }) + return + + assert IS_NVIM + end_col = name.column + length + src_id = buf.add_highlight('jediUsage', lnum-1, start_col, end_col, + src_id=0) + return src_id + + +def highlight_usages_for_vim_win(): + """Highlight usages in the current window. + + It stores the matchids in a window-local variable. + + (matchaddpos() only works for the current window.) + """ + win = vim.current.window + + cur_matchids = win.vars.get('_jedi_usages_vim_matchids') + if cur_matchids: + if cur_matchids[0] == vim.current.buffer.number: + return + + # Need to clear non-matching highlights. + for matchid in cur_matchids[1:]: + expr = 'matchdelete(%d)' % int(matchid) + vim.eval(expr) + + matchids = [] + if _current_names: + buffer_path = vim.current.buffer.name + for name in _current_names: + if (str(name.module_path) or '') == buffer_path: + positions = [ + [name.line, + name.column + 1, + len(name.name)] + ] + expr = "matchaddpos('jediUsage', %s)" % repr(positions) + matchids.append(int(vim_eval(expr))) + + if matchids: + vim.current.window.vars['_jedi_usages_vim_matchids'] = [ + vim.current.buffer.number] + matchids + elif cur_matchids is not None: + # Always set it (uses an empty list for "unset", which is not possible + # using del). + vim.current.window.vars['_jedi_usages_vim_matchids'] = [] + + # Remember if clearing is needed for later buffer autocommands. + vim.current.buffer.vars['_jedi_usages_needs_clear'] = bool(matchids) + + +@_check_jedi_availability(show_error=True) +@catch_and_print_exceptions +def show_documentation(): + script = get_script() + try: + names = script.help(*get_pos()) + except Exception: + # print to stdout, will be in :messages + names = [] + print("Exception, this shouldn't happen.") + print(traceback.format_exc()) + + if not names: + echo_highlight('No documentation found for that.') + vim.command('return') + return + + docs = [] + for n in names: + doc = n.docstring() + if doc: + title = 'Docstring for %s %s' % (n.type, n.full_name or n.name) + underline = '=' * len(title) + docs.append('%s\n%s\n%s' % (title, underline, doc)) + else: + docs.append('|No Docstring for %s|' % n) + text = ('\n' + '-' * 79 + '\n').join(docs) + vim.command('let l:doc = %s' % repr(PythonToVimStr(text))) + vim.command('let l:doc_lines = %s' % len(text.split('\n'))) + return True + + +@catch_and_print_exceptions +def clear_call_signatures(): + # Check if using command line call signatures + if int(vim_eval("g:jedi#show_call_signatures")) == 2: + vim_command('echo ""') + return + cursor = vim.current.window.cursor + e = vim_eval('g:jedi#call_signature_escape') + # We need two turns here to search and replace certain lines: + # 1. Search for a line with a call signature and save the appended + # characters + # 2. Actually replace the line and redo the status quo. + py_regex = r'%sjedi=([0-9]+), (.*?)%s.*?%sjedi%s'.replace( + '%s', re.escape(e)) + for i, line in enumerate(vim.current.buffer): + match = re.search(py_regex, line) + if match is not None: + # Some signs were added to minimize syntax changes due to call + # signatures. We have to remove them again. The number of them is + # specified in `match.group(1)`. + after = line[match.end() + int(match.group(1)):] + line = line[:match.start()] + match.group(2) + after + vim.current.buffer[i] = line + vim.current.window.cursor = cursor + + +@_check_jedi_availability(show_error=False) +@catch_and_print_exceptions +def show_call_signatures(signatures=()): + if int(vim_eval("has('conceal') && g:jedi#show_call_signatures")) == 0: + return + + # We need to clear the signatures before we calculate them again. The + # reason for this is that call signatures are unfortunately written to the + # buffer. + clear_call_signatures() + if signatures == (): + signatures = get_script().get_signatures(*get_pos()) + + if not signatures: + return + + if int(vim_eval("g:jedi#show_call_signatures")) == 2: + return cmdline_call_signatures(signatures) + + seen_sigs = [] + for i, signature in enumerate(signatures): + line, column = signature.bracket_start + # signatures are listed above each other + line_to_replace = line - i - 1 + # because there's a space before the bracket + insert_column = column - 1 + if insert_column < 0 or line_to_replace <= 0: + # Edge cases, when the call signature has no space on the screen. + break + + # TODO check if completion menu is above or below + line = vim_eval("getline(%s)" % line_to_replace) + + # Descriptions are usually looking like `param name`, remove the param. + params = [p.description.replace('\n', '').replace('param ', '', 1) + for p in signature.params] + try: + # *_*PLACEHOLDER*_* makes something fat. See after/syntax file. + params[signature.index] = '*_*%s*_*' % params[signature.index] + except (IndexError, TypeError): + pass + + # Skip duplicates. + if params in seen_sigs: + continue + seen_sigs.append(params) + + # This stuff is reaaaaally a hack! I cannot stress enough, that + # this is a stupid solution. But there is really no other yet. + # There is no possibility in VIM to draw on the screen, but there + # will be one (see :help todo Patch to access screen under Python. + # (Marko Mahni, 2010 Jul 18)) + text = " (%s) " % ', '.join(params) + text = ' ' * (insert_column - len(line)) + text + end_column = insert_column + len(text) - 2 # -2 due to bold symbols + + # Need to decode it with utf8, because vim returns always a python 2 + # string even if it is unicode. + e = vim_eval('g:jedi#call_signature_escape') + if hasattr(e, 'decode'): + e = e.decode('UTF-8') + # replace line before with cursor + regex = "xjedi=%sx%sxjedix".replace('x', e) + + prefix, replace = line[:insert_column], line[insert_column:end_column] + + # Check the replace stuff for strings, to append them + # (don't want to break the syntax) + regex_quotes = r'''\\*["']+''' + # `add` are all the quotation marks. + # join them with a space to avoid producing ''' + add = ' '.join(re.findall(regex_quotes, replace)) + # search backwards + if add and replace[0] in ['"', "'"]: + a = re.search(regex_quotes + '$', prefix) + add = ('' if a is None else a.group(0)) + add + + tup = '%s, %s' % (len(add), replace) + repl = prefix + (regex % (tup, text)) + add + line[end_column:] + + vim_eval('setline(%s, %s)' % (line_to_replace, repr(PythonToVimStr(repl)))) + + +@catch_and_print_exceptions +def cmdline_call_signatures(signatures): + def get_params(s): + return [p.description.replace('\n', '').replace('param ', '', 1) for p in s.params] + + def escape(string): + return string.replace('"', '\\"').replace(r'\n', r'\\n') + + def join(): + return ', '.join(filter(None, (left, center, right))) + + def too_long(): + return len(join()) > max_msg_len + + if len(signatures) > 1: + params = zip_longest(*map(get_params, signatures), fillvalue='_') + params = ['(' + ', '.join(p) + ')' for p in params] + else: + params = get_params(signatures[0]) + + index = next(iter(s.index for s in signatures if s.index is not None), None) + + # Allow 12 characters for showcmd plus 18 for ruler - setting + # noruler/noshowcmd here causes incorrect undo history + max_msg_len = int(vim_eval('&columns')) - 12 + if int(vim_eval('&ruler')): + max_msg_len -= 18 + max_msg_len -= len(signatures[0].name) + 2 # call name + parentheses + + if max_msg_len < (1 if params else 0): + return + elif index is None: + text = escape(', '.join(params)) + if params and len(text) > max_msg_len: + text = ELLIPSIS + elif max_msg_len < len(ELLIPSIS): + return + else: + left = escape(', '.join(params[:index])) + center = escape(params[index]) + right = escape(', '.join(params[index + 1:])) + while too_long(): + if left and left != ELLIPSIS: + left = ELLIPSIS + continue + if right and right != ELLIPSIS: + right = ELLIPSIS + continue + if (left or right) and center != ELLIPSIS: + left = right = None + center = ELLIPSIS + continue + if too_long(): + # Should never reach here + return + + max_num_spaces = max_msg_len + if index is not None: + max_num_spaces -= len(join()) + _, column = signatures[0].bracket_start + spaces = min(int(vim_eval('g:jedi#first_col +' + 'wincol() - col(".")')) + + column - len(signatures[0].name), + max_num_spaces) * ' ' + + if index is not None: + vim_command(' echon "%s" | ' + 'echohl Function | echon "%s" | ' + 'echohl None | echon "(" | ' + 'echohl jediFunction | echon "%s" | ' + 'echohl jediFat | echon "%s" | ' + 'echohl jediFunction | echon "%s" | ' + 'echohl None | echon ")"' + % (spaces, signatures[0].name, + left + ', ' if left else '', + center, ', ' + right if right else '')) + else: + vim_command(' echon "%s" | ' + 'echohl Function | echon "%s" | ' + 'echohl None | echon "(%s)"' + % (spaces, signatures[0].name, text)) + + +@_check_jedi_availability(show_error=True) +@catch_and_print_exceptions +def rename(): + if not int(vim.eval('a:0')): + # Need to save the cursor position before insert mode + cursor = vim.current.window.cursor + changenr = vim.eval('changenr()') # track undo tree + vim_command('augroup jedi_rename') + vim_command('autocmd InsertLeave call jedi#rename' + '({}, {}, {})'.format(cursor[0], cursor[1], changenr)) + vim_command('augroup END') + + vim_command("let s:jedi_replace_orig = expand('')") + line = vim_eval('getline(".")') + vim_command('normal! diw') + if re.match(r'\w+$', line[cursor[1]:]): + # In case the deleted word is at the end of the line we need to + # move the cursor to the end. + vim_command('startinsert!') + else: + vim_command('startinsert') + + else: + # Remove autocommand. + vim_command('autocmd! jedi_rename InsertLeave') + + args = vim.eval('a:000') + cursor = tuple(int(x) for x in args[:2]) + changenr = args[2] + + # Get replacement, if there is something on the cursor. + # This won't be the case when the user ends insert mode right away, + # and `` would pick up the nearest word instead. + if vim_eval('getline(".")[getpos(".")[2]-1]') != ' ': + replace = vim_eval("expand('')") + else: + replace = None + + vim_command('undo {}'.format(changenr)) + + vim.current.window.cursor = cursor + + if replace: + return do_rename(replace) + + +def rename_visual(): + replace = vim.eval('input("Rename to: ")') + orig = vim.eval('getline(".")[(getpos("\'<")[2]-1):getpos("\'>")[2]]') + do_rename(replace, orig) + + +def do_rename(replace, orig=None): + if not len(replace): + echo_highlight('No rename possible without name.') + return + + if orig is None: + orig = vim_eval('s:jedi_replace_orig') + + # Save original window / tab. + saved_tab = int(vim_eval('tabpagenr()')) + saved_win = int(vim_eval('winnr()')) + + temp_rename = usages(visuals=False) + # Sort the whole thing reverse (positions at the end of the line + # must be first, because they move the stuff before the position). + temp_rename = sorted(temp_rename, reverse=True, + key=lambda x: (str(x.module_path), x.line, x.column)) + buffers = set() + for r in temp_rename: + if r.in_builtin_module(): + continue + + result = set_buffer(r.module_path) + if not result: + echo_highlight('Failed to create buffer window for %s!' % (r.module_path)) + continue + + buffers.add(vim.current.buffer.name) + + # Replace original word. + r_line = vim.current.buffer[r.line - 1] + vim.current.buffer[r.line - 1] = (r_line[:r.column] + replace + + r_line[r.column + len(orig):]) + + # Restore previous tab and window. + vim_command('tabnext {0:d}'.format(saved_tab)) + vim_command('{0:d}wincmd w'.format(saved_win)) + + if len(buffers) > 1: + echo_highlight('Jedi did {0:d} renames in {1:d} buffers!'.format( + len(temp_rename), len(buffers))) + else: + echo_highlight('Jedi did {0:d} renames!'.format(len(temp_rename))) + + +@_check_jedi_availability(show_error=True) +@catch_and_print_exceptions +def py_import(): + args = shsplit(vim.eval('a:args')) + import_path = args.pop() + name = next(get_project().search(import_path), None) + if name is None: + echo_highlight('Cannot find %s in your project or on sys.path!' % import_path) + else: + cmd_args = ' '.join([a.replace(' ', '\\ ') for a in args]) + _goto_specific_name(name, options=cmd_args) + + +@catch_and_print_exceptions +def py_import_completions(): + argl = vim.eval('a:argl') + if jedi is None: + print('Pyimport completion requires jedi module: https://github.com/davidhalter/jedi') + comps = [] + else: + names = get_project().complete_search(argl) + comps = [argl + n for n in sorted(set(c.complete for c in names))] + vim.command("return '%s'" % '\n'.join(comps)) + + +@catch_and_print_exceptions +def set_buffer(path: Optional[Path], options='', using_tagstack=False): + """ + Opens a new buffer if we have to or does nothing. Returns True in case of + success. + """ + path = str(path or '') + # Check both, because it might be an empty string + if path in (vim.current.buffer.name, os.path.abspath(vim.current.buffer.name)): + return True + + path = relpath(path) + # options are what you can to edit the edit options + if int(vim_eval('g:jedi#use_tabs_not_buffers')) == 1: + _tabnew(path, options) + elif not vim_eval('g:jedi#use_splits_not_buffers') in [1, '1']: + user_split_option = vim_eval('g:jedi#use_splits_not_buffers') + split_options = { + 'top': 'topleft split', + 'left': 'topleft vsplit', + 'right': 'botright vsplit', + 'bottom': 'botright split', + 'winwidth': 'vs' + } + if (user_split_option == 'winwidth' and + vim.current.window.width <= 2 * int(vim_eval( + "&textwidth ? &textwidth : 80"))): + split_options['winwidth'] = 'sp' + if user_split_option not in split_options: + print('Unsupported value for g:jedi#use_splits_not_buffers: {0}. ' + 'Valid options are: {1}.'.format( + user_split_option, ', '.join(split_options.keys()))) + else: + vim_command(split_options[user_split_option] + " %s" % escape_file_path(path)) + else: + if int(vim_eval("!&hidden && &modified")) == 1: + if not vim_eval("bufname('%')"): + echo_highlight('Cannot open a new buffer, use `:set hidden` or save your buffer') + return False + else: + vim_command('w') + if using_tagstack: + return True + vim_command('edit %s %s' % (options, escape_file_path(path))) + # sometimes syntax is being disabled and the filetype not set. + if int(vim_eval('!exists("g:syntax_on")')) == 1: + vim_command('syntax enable') + if int(vim_eval("&filetype != 'python'")) == 1: + vim_command('set filetype=python') + return True + + +@catch_and_print_exceptions +def _tabnew(path, options=''): + """ + Open a file in a new tab or switch to an existing one. + + :param options: `:tabnew` options, read vim help. + """ + if int(vim_eval('has("gui")')) == 1: + vim_command('tab drop %s %s' % (options, escape_file_path(path))) + return + + for tab_nr in range(int(vim_eval("tabpagenr('$')"))): + for buf_nr in vim_eval("tabpagebuflist(%i + 1)" % tab_nr): + buf_nr = int(buf_nr) - 1 + try: + buf_path = vim.buffers[buf_nr].name + except (LookupError, ValueError): + # Just do good old asking for forgiveness. + # don't know why this happens :-) + pass + else: + if os.path.abspath(buf_path) == os.path.abspath(path): + # tab exists, just switch to that tab + vim_command('tabfirst | tabnext %i' % (tab_nr + 1)) + # Goto the buffer's window. + vim_command('exec bufwinnr(%i) . " wincmd w"' % (buf_nr + 1)) + break + else: + continue + break + else: + # tab doesn't exist, add a new one. + vim_command('tabnew %s' % escape_file_path(path)) + + +def escape_file_path(path): + return path.replace(' ', r'\ ') + + +def print_to_stdout(level, str_out): + print(str_out) diff --git a/sources_non_forked/jedi-vim/pythonx/jedi_vim_debug.py b/sources_non_forked/jedi-vim/pythonx/jedi_vim_debug.py new file mode 100644 index 00000000..2c673225 --- /dev/null +++ b/sources_non_forked/jedi-vim/pythonx/jedi_vim_debug.py @@ -0,0 +1,96 @@ +"""Used in jedi-vim's jedi#debug_info()""" +import sys + +import vim +from jedi_vim import PythonToVimStr, jedi + + +def echo(msg): + vim.command('echo %r' % PythonToVimStr(msg)) + + +def echo_error(msg): + vim.command('echohl ErrorMsg') + echo(msg) + vim.command('echohl None') + + +def format_exc_info(exc_info=None, tb_indent=2): + import traceback + + if exc_info is None: + exc_info = sys.exc_info() + + exc_msg = traceback.format_exception_only(exc_info[0], exc_info[1]) + lines = ''.join(exc_msg).rstrip('\n').split('\n') + + lines.append('Traceback (most recent call last):') + tb = traceback.format_tb(exc_info[2]) + lines.extend(''.join(tb).rstrip('\n').split('\n')) + + indent = ' ' * tb_indent + return '{0}'.format(('\n' + indent).join(lines)) + + +def get_known_environments(): + """Get known Jedi environments.""" + envs = list(jedi.find_virtualenvs()) + envs.extend(jedi.find_system_environments()) + return envs + + +def display_debug_info(): + echo(' - global sys.executable: `{0}`'.format(sys.executable)) + echo(' - global sys.version: `{0}`'.format( + ', '.join([x.strip() + for x in sys.version.split('\n')]))) + echo(' - global site module: `{0}`'.format(__import__('site').__file__)) + + try: + import jedi_vim + except Exception: + echo_error('ERROR: could not import jedi_vim: {0}'.format( + format_exc_info())) + return + + if jedi_vim.jedi is None: + if hasattr(jedi_vim, 'jedi_import_error'): + error_msg = format_exc_info(jedi_vim.jedi_import_error) + else: + error_msg = 'unknown error' + echo_error('ERROR: could not import the "jedi" Python module: {0}'.format( + error_msg)) + else: + echo('\n##### Jedi\n\n - path: `{0}`'.format(jedi_vim.jedi.__file__)) + echo(' - version: {0}'.format(jedi_vim.jedi.__version__)) + + try: + project = jedi_vim.get_project() + environment = project.get_environment() + except AttributeError: + script_evaluator = jedi_vim.jedi.Script('')._evaluator + try: + sys_path = script_evaluator.project.sys_path + except AttributeError: + sys_path = script_evaluator.sys_path + else: + echo('\n##### Jedi environment: {0}\n\n'.format(environment)) + echo(' - executable: {0}'.format(environment.executable)) + try: + sys_path = environment.get_sys_path() + except Exception: + echo_error('ERROR: failed to get sys path from environment: {0}'.format( + format_exc_info())) + return + + echo(' - sys_path:') + for p in sys_path: + echo(' - `{0}`'.format(p)) + + if environment: + echo('\n##### Known environments\n\n') + for environment in get_known_environments(): + echo(' - {0} ({1})\n'.format( + environment, + environment.executable, + )) diff --git a/sources_non_forked/jedi-vim/setup.cfg b/sources_non_forked/jedi-vim/setup.cfg new file mode 100644 index 00000000..93e190e5 --- /dev/null +++ b/sources_non_forked/jedi-vim/setup.cfg @@ -0,0 +1,5 @@ +[tool:pytest] +testpaths = test + +[flake8] +max-line-length = 100 diff --git a/sources_non_forked/jedi-vim/test/_utils.vim b/sources_non_forked/jedi-vim/test/_utils.vim new file mode 100644 index 00000000..5ad2a1d4 --- /dev/null +++ b/sources_non_forked/jedi-vim/test/_utils.vim @@ -0,0 +1,11 @@ +function! CurrentBufferIsModule(module_name) + return EndsWith(bufname('%'), a:module_name.'.py') +endfunction + + +function EndsWith(string, end) + let l:should = len(a:string) - strlen(a:end) + return l:should == stridx(a:string, a:end, should) +endfunction + +" vim: et:ts=4:sw=4 diff --git a/sources_non_forked/jedi-vim/test/test_integration.py b/sources_non_forked/jedi-vim/test/test_integration.py new file mode 100644 index 00000000..10a7b172 --- /dev/null +++ b/sources_non_forked/jedi-vim/test/test_integration.py @@ -0,0 +1,65 @@ +"""Runs tests from ./vspec in vim-vspec.""" +import os +import subprocess +try: + from urllib.request import urlretrieve +except ImportError: + from urllib import urlretrieve +import zipfile + +import pytest + +vspec_version = '1.9.0' + +VSPEC_URL = 'https://github.com/kana/vim-vspec/archive/%s.zip' % vspec_version +root = os.path.dirname(os.path.dirname(__file__)) +CACHE_FOLDER = os.path.join(root, 'build') +VSPEC_FOLDER = os.path.join(CACHE_FOLDER, 'vim-vspec-%s' % vspec_version) +VSPEC_RUNNER = os.path.join(VSPEC_FOLDER, 'bin/vspec') +TEST_DIR = os.path.join(root, 'test', 'vspec') + + +@pytest.fixture(scope='session') +def install_vspec(): + if not os.path.isdir(CACHE_FOLDER): + os.mkdir(CACHE_FOLDER) + + if not os.path.exists(VSPEC_FOLDER): + name, hdrs = urlretrieve(VSPEC_URL) + z = zipfile.ZipFile(name) + for n in z.namelist(): + dest = os.path.join(CACHE_FOLDER, n) + destdir = os.path.dirname(dest) + if not os.path.isdir(destdir): + os.makedirs(destdir) + data = z.read(n) + if not os.path.isdir(dest): + with open(dest, 'wb') as f: + f.write(data) + z.close() + os.chmod(VSPEC_RUNNER, 0o777) + + +def get_vspec_tests(): + for f in os.listdir(TEST_DIR): + yield os.path.relpath(os.path.join(TEST_DIR, f)) + + +@pytest.mark.parametrize('path', get_vspec_tests()) +def test_integration(install_vspec, path): + output = subprocess.check_output( + [VSPEC_RUNNER, '.', VSPEC_FOLDER, os.path.relpath(path, root)], + cwd=root, + ) + had_ok = False + for line in output.splitlines(): + if (line.startswith(b'not ok') or + line.startswith(b'Error') or + line.startswith(b'Bail out!')): + pytest.fail(u"{0} failed:\n{1}".format( + path, output.decode('utf-8')), pytrace=False) + if not had_ok and line.startswith(b'ok'): + had_ok = True + if not had_ok: + pytest.fail(u"{0} failed: no 'ok' found:\n{1}".format( + path, output.decode('utf-8')), pytrace=False) diff --git a/sources_non_forked/jedi-vim/test/vimrc b/sources_non_forked/jedi-vim/test/vimrc new file mode 100644 index 00000000..82111f3d --- /dev/null +++ b/sources_non_forked/jedi-vim/test/vimrc @@ -0,0 +1,8 @@ +" Minimal vimrc to use jedi-vim. +" +" Not used anywhere yet, but allows for easy testing. +let script_dir = fnamemodify(expand(''), ':h:h') +let &runtimepath = script_dir.','.&runtimepath.','.script_dir.'/after' + +syntax on +filetype plugin indent on diff --git a/sources_non_forked/jedi-vim/test/vspec/choose-venv.vim b/sources_non_forked/jedi-vim/test/vspec/choose-venv.vim new file mode 100644 index 00000000..d93ea075 --- /dev/null +++ b/sources_non_forked/jedi-vim/test/vspec/choose-venv.vim @@ -0,0 +1,29 @@ +source plugin/jedi.vim +source test/_utils.vim + +describe 'simple:' + before + new + normal! ifoo + end + + after + bd! + end + + it 'choose' + Expect g:jedi#environment_path == 'auto' + Expect bufname('%') == '' + + JediChooseEnvironment + " A Python executable needs to be a few letters + Expect len(getline('.')) > 5 + Expect bufname('%') == 'Hit Enter to Choose an Environment' + + execute "normal \" + Expect g:jedi#environment_path != 'auto' + bd " TODO why is this necessary? There seems to be a random buffer. + Expect bufname('%') == '' + Expect getline('.') == 'foo' + end +end diff --git a/sources_non_forked/jedi-vim/test/vspec/completions.vim b/sources_non_forked/jedi-vim/test/vspec/completions.vim new file mode 100644 index 00000000..068e5392 --- /dev/null +++ b/sources_non_forked/jedi-vim/test/vspec/completions.vim @@ -0,0 +1,131 @@ +let g:jedi#completions_command = 'X' +source plugin/jedi.vim + +describe 'completions' + before + new + set filetype=python + end + + after + " default + let g:jedi#popup_select_first = 1 + bd! + end + + it 'longest in completeopt' + " This gets set up with Vim only on VimEnter. + if has('nvim') + Expect stridx(&completeopt, 'longest') > -1 + else + Expect stridx(&completeopt, 'longest') == -1 + doautocmd VimEnter + Expect stridx(&completeopt, 'longest') > -1 + endif + + " Do not use it for following tests. + set completeopt-=longest + end + + it 'no smart import by default' + exec "normal ifrom os " + Expect getline('.') == 'from os ' + end + + it 'import' + " X is the completion command + normal oimporX + Expect getline('.') == 'import' + normal a subproX + Expect getline('.') == 'import subprocess' + end + + it 'exception' + normal oIndentationErrX + Expect getline('.') == 'IndentationError' + + " Do not remap keys (".") here, otherwise this triggers completion in + " Neovim already. + normal! a().filena + + normal aX + Expect getline('.') == 'IndentationError().filename' + end + + it 'multi complete' + " NOTE: nvim results in "importErr()" here with completeopt+=longest, + " but Vim is fine. + " This is due to `pumvisible()` in jedi#complete_opened being true + " with nvim still, but it is 0 with Vim, i.e. Vim appears to close + " the pum already (with the tests). + " + " This might be a misunderstanding though, since the test might not + " expect the "import" keyword to be offered for completion?! + normal oImpXErrX() + Expect getline('.') == 'ImportError()' + end + + it 'cycling through entries popup_select_first=0' + set completeopt+=longest + let g:jedi#popup_select_first = 0 + execute "normal oraise impX\" + + Expect getline('.') == 'raise ImportError' + set completeopt-=longest + end + + it 'cycling through entries popup_select_first=1' + execute "normal oraise impX\" + Expect getline('.') == 'raise ImportWarning' + end + + it 'cycling through entries popup_select_first=1 and longest' + set completeopt+=longest + execute "normal oraise impX" + Expect getline('.') == 'raise Import' + + " With Neovim pumvisible() is 1 in jedi#complete_opened, which then + " triggers the . This is not the case with Vim. + if has('nvim') + execute "normal oraise impX\" + Expect getline('.') == 'raise ImportWarning' + + execute "normal oraise impX\\" + Expect getline('.') == 'raise imp' + else + execute "normal oraise impX\" + Expect getline('.') == 'raise ImportError' + + execute "normal oraise impX\\" + Expect getline('.') == 'raise ImportWarning' + endif + set completeopt-=longest + end +end + +describe 'smart completions' + before + new + let g:jedi#smart_auto_mappings = 1 + set filetype=python + end + + after + " default + let g:jedi#smart_auto_mappings = 0 + bd! + end + + it 'smart import' + exec "normal ifrom os " + Expect getline('.') == 'from os import ' + end + + it 'no smart import after space' + exec "normal! ifrom os " + exec "normal a " + Expect getline('.') == 'from os ' + end +end + +" vim: et:ts=4:sw=4 diff --git a/sources_non_forked/jedi-vim/test/vspec/completions_disabled.vim b/sources_non_forked/jedi-vim/test/vspec/completions_disabled.vim new file mode 100644 index 00000000..03d17c5f --- /dev/null +++ b/sources_non_forked/jedi-vim/test/vspec/completions_disabled.vim @@ -0,0 +1,20 @@ +let g:jedi#completions_command = 'X' +let g:jedi#completions_enabled = 0 +source plugin/jedi.vim + +describe 'completions_disabled' + before + set filetype=python + end + + after + try | %bwipeout! | catch | endtry + end + + it 'typing' + normal oraise ImportErrX + Expect getline('.') == 'raise ImportErrX' + end +end + +" vim: et:ts=4:sw=4 diff --git a/sources_non_forked/jedi-vim/test/vspec/documentation.vim b/sources_non_forked/jedi-vim/test/vspec/documentation.vim new file mode 100644 index 00000000..c97c1a89 --- /dev/null +++ b/sources_non_forked/jedi-vim/test/vspec/documentation.vim @@ -0,0 +1,34 @@ +source plugin/jedi.vim + +describe 'documentation docstrings' + before + set filetype=python + end + + after + try | %bwipeout! | catch | endtry + end + + it 'simple' + Expect maparg('K') == ':call jedi#show_documentation()' + put = 'ImportError' + normal GK + Expect bufname('%') == "__doc__" + Expect &filetype == 'rst' + let header = getline(1, 2) + Expect header[0] == "Docstring for class builtins.ImportError" + Expect header[1] == "========================================" + let content = join(getline(3, '$'), "\n") + Expect stridx(content, "Import can't find module") > 0 + normal K + Expect bufname('%') == '' + end + + it 'no documentation' + put = 'x = 2' + normal oGK + Expect bufname('%') == '' + end +end + +" vim: et:ts=4:sw=4 diff --git a/sources_non_forked/jedi-vim/test/vspec/goto.vim b/sources_non_forked/jedi-vim/test/vspec/goto.vim new file mode 100644 index 00000000..f5116f22 --- /dev/null +++ b/sources_non_forked/jedi-vim/test/vspec/goto.vim @@ -0,0 +1,177 @@ +let mapleader = '\' +source plugin/jedi.vim +source test/_utils.vim + +describe 'goto simple:' + before + new + set filetype=python + put =[ + \ 'def a(): pass', + \ 'b = a', + \ 'c = b', + \ ] + normal! ggdd + normal! G$ + Expect line('.') == 3 + end + + after + bd! + end + + it 'goto definitions' + normal \d + Expect line('.') == 2 + Expect col('.') == 1 + end + + it 'goto assignments' + normal \g + Expect line('.') == 2 + Expect col('.') == 1 + + " cursor before `=` means that it stays there. + normal \g + Expect line('.') == 2 + Expect col('.') == 1 + + " going to the last line changes it. + normal! $ + normal \g + Expect line('.') == 1 + Expect col('.') == 5 + end +end + + +describe 'goto with tabs:' + before + set filetype=python + let g:jedi#use_tabs_not_buffers = 1 + end + + after + try | %bwipeout! | catch | endtry + end + + it 'follow import' + put = ['import subprocess', 'subprocess'] + normal G\g + Expect getline('.') == 'import subprocess' + Expect line('.') == 2 + Expect col('.') == 8 + + normal G\d + Expect CurrentBufferIsModule('subprocess') == 1 + Expect line('.') == 1 + Expect col('.') == 1 + Expect tabpagenr('$') == 2 + Expect winnr('$') == 1 + bwipe + + Expect tabpagenr('$') == 1 + Expect bufname('%') == '' + end +end + + +describe 'goto with buffers' + before + set filetype=python + let g:jedi#use_tabs_not_buffers = 0 + end + + after + try | %bwipeout! | catch | endtry + set nohidden + end + + it 'no new tabs' + put = ['import os'] + normal G$ + call jedi#goto_assignments() + python3 jedi_vim.goto() + Expect CurrentBufferIsModule('os') == 0 + " Without hidden, it's not possible to open a new buffer, when the old + " one is not saved. + set hidden + call jedi#goto_assignments() + Expect CurrentBufferIsModule('os') == 1 + Expect winnr('$') == 1 + Expect tabpagenr('$') == 1 + Expect line('.') == 1 + Expect col('.') == 1 + end +end + + + +describe 'goto with splits' + before + enew! + set filetype=python + let g:jedi#use_splits_not_buffers = 'left' + end + + after + try | %bwipeout! | catch | endtry + end + + it 'follow import' + put = ['import subprocess', 'subprocess'] + normal G\g + Expect getline('.') == 'import subprocess' + Expect line('.') == 2 + Expect col('.') == 8 + + normal G\d + Expect CurrentBufferIsModule('subprocess') == 1 + Expect line('.') == 1 + Expect col('.') == 1 + Expect winnr('$') == 2 + wincmd l + Expect bufname('%') == '' + end + +end + + +describe 'goto wildignore' + before + enew! + set filetype=python + set wildignore=*,with\ spaces,*.pyc + set hidden + let g:jedi#use_tag_stack = 1 + let g:jedi#use_tabs_not_buffers = 0 + " Need to use splits for code coverage in new_buffer() + let g:jedi#use_splits_not_buffers = 1 + + put = ['from subprocess import Popen', 'Popen'] + Expect CurrentBufferIsModule('subprocess') == 0 + normal G + end + + after + try | %bwipeout! | catch | endtry + set wildignore&vim + end + + it 'restores wildignore' + let before = &wildignore + call jedi#goto() + Expect getline('.') =~ 'Popen' + Expect &wildignore == before + end + + it 'not using tagstack' + let g:jedi#use_tag_stack = 0 + call jedi#goto() + Expect CurrentBufferIsModule('subprocess') == 1 + Expect getline('.') =~ 'Popen' + end +end + + +" vim: et:ts=4:sw=4 diff --git a/sources_non_forked/jedi-vim/test/vspec/jedi_debug_info.vim b/sources_non_forked/jedi-vim/test/vspec/jedi_debug_info.vim new file mode 100644 index 00000000..a7b9b014 --- /dev/null +++ b/sources_non_forked/jedi-vim/test/vspec/jedi_debug_info.vim @@ -0,0 +1,13 @@ +source plugin/jedi.vim + +describe 'JediDebugInfo' + it 'works' + redir @a | JediDebugInfo | redir END + let output = split(@a, '\n') + Expect output[0] == 'You should run this in a buffer with filetype "python".' + Expect output[1] == '#### Jedi-vim debug information' + Expect output[-1] == '' + end +end + +" vim: et:ts=4:sw=4 diff --git a/sources_non_forked/jedi-vim/test/vspec/pyimport.vim b/sources_non_forked/jedi-vim/test/vspec/pyimport.vim new file mode 100644 index 00000000..fb4bc52f --- /dev/null +++ b/sources_non_forked/jedi-vim/test/vspec/pyimport.vim @@ -0,0 +1,34 @@ +source plugin/jedi.vim +source test/_utils.vim + +describe 'pyimport' + before + let g:jedi#use_tabs_not_buffers = 1 + let g:jedi#project_path = 'autoload' + end + + after + try | %bwipeout! | catch | endtry + unlet g:jedi#project_path + end + + it 'open_tab' + Pyimport os + Expect CurrentBufferIsModule('os') == 1 + Pyimport subprocess + Expect CurrentBufferIsModule('subprocess') == 1 + " the empty tab is sometimes also a tab + Expect tabpagenr('$') >= 2 + end + + it 'completion' + " don't know how to test this directly + "execute "Pyimport subproc\" + "Expect CurrentBufferIsModule('subprocess') == 1 + + Expect jedi#py_import_completions('subproc', 0, 0) == 'subprocess' + Expect jedi#py_import_completions('subprocess', 0, 0) == 'subprocess' + let g:comp = jedi#py_import_completions('sre_', 0, 0) + Expect g:comp == "sre_compile\nsre_constants\nsre_parse" + end +end diff --git a/sources_non_forked/jedi-vim/test/vspec/signatures.vim b/sources_non_forked/jedi-vim/test/vspec/signatures.vim new file mode 100644 index 00000000..8ac0ed95 --- /dev/null +++ b/sources_non_forked/jedi-vim/test/vspec/signatures.vim @@ -0,0 +1,143 @@ +source plugin/jedi.vim + +describe 'signatures' + before + enew + set filetype=python + end + + after + try | %bwipeout! | catch | endtry + end + + it 'simple' + normal odef xyz(number): return + normal o + normal oxyz() + doautocmd CursorHoldI + Expect getline(3) == '?!?jedi=0, ?!? (*_*number*_*) ?!?jedi?!?' + + doautocmd InsertLeave + Expect getline(3) == '' + end + + it 'multiple buffers' + set hidden + new + setfiletype python + redir => autocmds + autocmd jedi_call_signatures * + redir END + Expect autocmds =~# 'jedi_call_signatures' + buffer # + redir => autocmds + autocmd jedi_call_signatures * + redir END + Expect autocmds =~# 'jedi_call_signatures' + end + + it 'simple after CursorHoldI with only parenthesis' + noautocmd normal o + doautocmd CursorHoldI + noautocmd normal istaticmethod() + doautocmd CursorHoldI + Expect getline(1) == '?!?jedi=0, ?!? (*_*f: Callable[..., Any]*_*) ?!?jedi?!?' + end + + it 'highlights correct argument' + noautocmd normal o + doautocmd CursorHoldI + noautocmd normal iformat(42, "x") + " Move to x - highlights "x". + noautocmd normal 2h + doautocmd CursorHoldI + Expect getline(1) == '?!?jedi=0, ?!? (value: object, *_*format_spec: str=...*_*) ?!?jedi?!?' + " Move left to 42 - hightlights first argument ("value"). + noautocmd normal 4h + doautocmd CursorHoldI + Expect getline(1) == '?!?jedi=0, ?!? (*_*value: object*_*, format_spec: str=...) ?!?jedi?!?' + end + + it 'no signature' + exe 'normal ostr ' + python3 jedi_vim.show_call_signatures() + Expect getline(1, '$') == ['', 'str '] + end + + it 'signatures disabled' + let g:jedi#show_call_signatures = 0 + + exe 'normal ostr( ' + python3 jedi_vim.show_call_signatures() + Expect getline(1, '$') == ['', 'str( '] + + let g:jedi#show_call_signatures = 1 + end + + it 'command line simple' + let g:jedi#show_call_signatures = 2 + call jedi#configure_call_signatures() + + exe 'normal ostaticmethod( ' + redir => msg + python3 jedi_vim.show_call_signatures() + redir END + Expect msg == "\nstaticmethod(f: Callable[..., Any])" + + redir => msg + doautocmd InsertLeave + redir END + Expect msg == "\n" + + normal Sdef foo(a, b): pass + exe 'normal ofoo(a, b, c, ' + redir => msg + python3 jedi_vim.show_call_signatures() + redir END + Expect msg == "\nfoo(a, b)" + end + + it 'command line truncation' + let g:jedi#show_call_signatures = 2 + call jedi#configure_call_signatures() + + function! Signature() + redir => msg + python3 jedi_vim.show_call_signatures() + redir END + return msg + endfunction + + let funcname = repeat('a', &columns - (30 + (&ruler ? 18 : 0))) + put = 'def '.funcname.'(arg1, arg2, arg3, a, b, c):' + put = ' pass' + execute "normal o\".funcname."( " + Expect Signature() == "\n".funcname."(arg1, …)" + + exe 'normal sarg1, ' + Expect Signature() == "\n".funcname."(…, arg2, …)" + + exe 'normal sarg2, arg3, ' + Expect Signature() == "\n".funcname."(…, a, b, c)" + + exe 'normal sa, b, ' + Expect Signature() == "\n".funcname."(…, c)" + + g/^/d + put = 'def '.funcname.'('.repeat('b', 20).', arg2):' + put = ' pass' + execute "normal o\".funcname."( " + Expect Signature() == "\n".funcname."(…)" + end + + it 'command line no signature' + let g:jedi#show_call_signatures = 2 + call jedi#configure_call_signatures() + + exe 'normal ostr ' + redir => msg + python3 jedi_vim.show_call_signatures() + redir END + Expect msg == "\n" + end +end diff --git a/update_plugins.py b/update_plugins.py index e71905cf..a0e130af 100644 --- a/update_plugins.py +++ b/update_plugins.py @@ -63,6 +63,7 @@ vim-indent-guides https://github.com/nathanaelkane/vim-indent-guides mru.vim https://github.com/vim-scripts/mru.vim editorconfig-vim https://github.com/editorconfig/editorconfig-vim dracula https://github.com/dracula/vim +jedi-vim https://github.com/davidhalter/jedi-vim """.strip() GITHUB_ZIP = "%s/archive/master.zip" diff --git a/vimrcs/plugins_config.vim b/vimrcs/plugins_config.vim index f510083c..d177de89 100644 --- a/vimrcs/plugins_config.vim +++ b/vimrcs/plugins_config.vim @@ -186,3 +186,14 @@ let g:EditorConfig_exclude_patterns = ['fugitive://.*'] " Copy the link to the line of a Git repository to the clipboard nnoremap v :.GBrowse! xnoremap v :'<'>GBrowse! + + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => jedi-vim +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +let g:jedi#auto_vim_configuration = 0 +let g:jedi#goto_assignments_command = "a" +let g:jedi#usages_command = "u" +let g:jedi#completions_command = "" +let g:jedi#rename_command = "r" +let g:jedi#popup_on_dot = 0