mirror of
https://github.com/davidhalter/jedi-vim.git
synced 2025-12-07 03:04:30 +08:00
Compare commits
148 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a1c900a26 | ||
|
|
57757bd334 | ||
|
|
ea52ca5305 | ||
|
|
04ba9a2430 | ||
|
|
dc0fdc55cb | ||
|
|
a76965238a | ||
|
|
6193c9fd95 | ||
|
|
acbb712906 | ||
|
|
48b3e5c0e7 | ||
|
|
74fd73d017 | ||
|
|
6efd966481 | ||
|
|
862fbbc8a9 | ||
|
|
87abaf0781 | ||
|
|
01e6e6bcf7 | ||
|
|
2c157e323e | ||
|
|
6edda9063a | ||
|
|
e23687462b | ||
|
|
104d817f0c | ||
|
|
2949389be4 | ||
|
|
c4fc2cde8c | ||
|
|
5858a999de | ||
|
|
1e9bdc863a | ||
|
|
3a27747773 | ||
|
|
4ca918e830 | ||
|
|
a17b033303 | ||
|
|
a0207fadf9 | ||
|
|
e83112f9aa | ||
|
|
b2e8c65e35 | ||
|
|
686f39ac00 | ||
|
|
055199f2aa | ||
|
|
8d24b83754 | ||
|
|
a3696bee36 | ||
|
|
5d4658f989 | ||
|
|
18b1a519b0 | ||
|
|
acb98fc706 | ||
|
|
e99cfd32de | ||
|
|
41ecaa5c15 | ||
|
|
5dd5631027 | ||
|
|
b689409a2a | ||
|
|
ea4de13344 | ||
|
|
1f7bc2a0fb | ||
|
|
c9bdefca54 | ||
|
|
e8790b1d8f | ||
|
|
e2abec21c5 | ||
|
|
c0ded0baf2 | ||
|
|
7dfc56992a | ||
|
|
2572136fcb | ||
|
|
55120b28e4 | ||
|
|
d57edde2e8 | ||
|
|
fab26f4551 | ||
|
|
4dcc6437e3 | ||
|
|
c80a08d983 | ||
|
|
ac6b2f1e3e | ||
|
|
12e97c7a04 | ||
|
|
08f13af066 | ||
|
|
5880f2de93 | ||
|
|
b4b2f3ef54 | ||
|
|
50abb5e95a | ||
|
|
89c995e7d9 | ||
|
|
4f2499e4f2 | ||
|
|
7665d73eae | ||
|
|
b3d715c5fc | ||
|
|
b9f8317595 | ||
|
|
d3f40d13ec | ||
|
|
016fb7c78e | ||
|
|
e736eea934 | ||
|
|
6c6b4dcf92 | ||
|
|
73289427ba | ||
|
|
1a053d2a23 | ||
|
|
636ad08d32 | ||
|
|
d32962f3b2 | ||
|
|
717446dd71 | ||
|
|
9c9a513aaf | ||
|
|
69aa410afa | ||
|
|
914754a04e | ||
|
|
f26b2a8802 | ||
|
|
d879d2f216 | ||
|
|
23c14f6826 | ||
|
|
1f7e661d9d | ||
|
|
c6fe4fee76 | ||
|
|
ea5e87a703 | ||
|
|
d02a72e792 | ||
|
|
42d24387ac | ||
|
|
ba5915bf26 | ||
|
|
c5c13d69d6 | ||
|
|
f36749776d | ||
|
|
7f4f2db260 | ||
|
|
2f65c636f8 | ||
|
|
b6dfc5fd49 | ||
|
|
2a43448f3b | ||
|
|
c6f05cd82c | ||
|
|
132d8506ab | ||
|
|
399c57ff72 | ||
|
|
1126ffde9b | ||
|
|
88502891ba | ||
|
|
b33392c8c8 | ||
|
|
ffec4d7fc5 | ||
|
|
43a9a9b191 | ||
|
|
e05f34646e | ||
|
|
713e78dd39 | ||
|
|
e49638ffc8 | ||
|
|
4c430ed536 | ||
|
|
40fc5ab27f | ||
|
|
9a4a4f4074 | ||
|
|
c6716c6392 | ||
|
|
5123dbbbc7 | ||
|
|
ee0f759a2e | ||
|
|
66b6a20041 | ||
|
|
8e077adb2f | ||
|
|
e7cb9a186e | ||
|
|
b5774a9554 | ||
|
|
f0d80048f1 | ||
|
|
9e2244c44e | ||
|
|
cc087ef463 | ||
|
|
efaef9cee3 | ||
|
|
58561d45f1 | ||
|
|
84b8eeb954 | ||
|
|
2bb7677b43 | ||
|
|
81ada14f0b | ||
|
|
7cade1fb62 | ||
|
|
1773837a11 | ||
|
|
67fd8c6572 | ||
|
|
d3d9a91ae6 | ||
|
|
0361d6c633 | ||
|
|
a54729ef63 | ||
|
|
5f98bfb62e | ||
|
|
745dc8a559 | ||
|
|
84a5299c8f | ||
|
|
d4006ab1bf | ||
|
|
ed8153ef2b | ||
|
|
f07ff6a535 | ||
|
|
6781eb17da | ||
|
|
5ad782d920 | ||
|
|
d75aaa470e | ||
|
|
56eb0f6d63 | ||
|
|
835e329883 | ||
|
|
49fa267e59 | ||
|
|
fa1aaa10cf | ||
|
|
e54a17ec71 | ||
|
|
48a9ea085d | ||
|
|
72a2643f7c | ||
|
|
57cbf1421f | ||
|
|
7894b38c0c | ||
|
|
1c3078e9f9 | ||
|
|
79b332a3c6 | ||
|
|
24a0369d0f | ||
|
|
d430570fd0 | ||
|
|
79c6172be7 |
7
.coveragerc
Normal file
7
.coveragerc
Normal file
@@ -0,0 +1,7 @@
|
||||
[run]
|
||||
branch = 1
|
||||
# Used by/for neovim-python-client.
|
||||
concurrency = greenlet
|
||||
|
||||
[report]
|
||||
include = pythonx/jedi_*.py,test/*
|
||||
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
github: [davidhalter]
|
||||
63
.github/workflows/ci.yml
vendored
Normal file
63
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
name: ci
|
||||
on: push
|
||||
|
||||
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//./}
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -3,4 +3,6 @@
|
||||
*.py[cod]
|
||||
.ropeproject
|
||||
doc/tags
|
||||
.cache
|
||||
.pytest-cache
|
||||
build
|
||||
.coverage*
|
||||
|
||||
32
.travis.yml
32
.travis.yml
@@ -1,15 +1,31 @@
|
||||
sudo: false
|
||||
dist: bionic
|
||||
language: python
|
||||
python: 3.6
|
||||
python: 3.8
|
||||
env:
|
||||
matrix:
|
||||
- ENV=test
|
||||
- ENV=check
|
||||
- ENV=test
|
||||
- ENV=check
|
||||
- ENV=test_coverage
|
||||
install:
|
||||
- |
|
||||
if [ "$ENV" = "test" ]; then
|
||||
python3.6 -m pip install pytest
|
||||
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:
|
||||
- vim --version
|
||||
- make "$ENV"
|
||||
- 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
|
||||
|
||||
@@ -51,5 +51,7 @@ Bagrat Aznauryan (@n9code)
|
||||
Tomoyuki Kashiro (@kashiro)
|
||||
Tommy Allen (@tweekmonster)
|
||||
Mingliang (@Aulddays)
|
||||
Brian Mego (@brianmego)
|
||||
Stevan Milic (@stevanmilic) <stevan.milic@yahoo.com>
|
||||
|
||||
@something are github user names.
|
||||
|
||||
43
Makefile
43
Makefile
@@ -1,16 +1,35 @@
|
||||
test:
|
||||
py.test
|
||||
BUILD_VIRTUAL_ENV:=build/venv
|
||||
|
||||
build:
|
||||
mkdir $@
|
||||
build/vint: | build
|
||||
virtualenv $@
|
||||
$@/bin/pip install vim-vint
|
||||
check: LINT_FILES:=after autoload ftplugin plugin
|
||||
check: build/vint
|
||||
build/vint/bin/vint $(LINT_FILES)
|
||||
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 .cache build
|
||||
rm -rf build
|
||||
|
||||
.PHONY: test check clean
|
||||
.PHONY: test check clean vint flake8
|
||||
|
||||
32
README.rst
32
README.rst
@@ -1,3 +1,5 @@
|
||||
.. image:: https://github.com/davidhalter/jedi-vim/blob/master/doc/logotype-a.svg
|
||||
|
||||
#################################################
|
||||
jedi-vim - awesome Python autocompletion with VIM
|
||||
#################################################
|
||||
@@ -56,9 +58,10 @@ generators, there is broad support.
|
||||
Apart from that, jedi-vim supports the following commands
|
||||
|
||||
- Completion ``<C-Space>``
|
||||
- Goto assignments ``<leader>g`` (typical goto function)
|
||||
- Goto definitions ``<leader>d`` (follow identifier as far as possible,
|
||||
- Goto assignment ``<leader>g`` (typical goto function)
|
||||
- Goto definition ``<leader>d`` (follow identifier as far as possible,
|
||||
includes imports and statements)
|
||||
- Goto (typing) stub ``<leader>s``
|
||||
- Show Documentation/Pydoc ``K`` (shows a popup with assignments)
|
||||
- Renaming ``<leader>r``
|
||||
- Usages ``<leader>n`` (shows all the usages of a name)
|
||||
@@ -70,9 +73,8 @@ Installation
|
||||
|
||||
Requirements
|
||||
------------
|
||||
You need a VIM version that was compiled with Python 2.6 or later
|
||||
(``+python`` or ``+python3``), which is typical for most distributions on
|
||||
Linux. You can check this from within VIM using
|
||||
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
|
||||
@@ -81,9 +83,8 @@ Manual installation
|
||||
You might want to use `pathogen <https://github.com/tpope/vim-pathogen>`_ or
|
||||
`Vundle <https://github.com/gmarik/vundle>`_ to install jedi-vim.
|
||||
|
||||
The first thing you need after that is an up-to-date version of Jedi. You can
|
||||
either install it via ``pip install jedi`` or with
|
||||
``git submodule update --init`` in your jedi-vim repository.
|
||||
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:
|
||||
|
||||
@@ -99,6 +100,9 @@ Add the following line in your `~/.vimrc`
|
||||
|
||||
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
|
||||
-----------------------------------
|
||||
@@ -178,8 +182,10 @@ and usually saves one keypress.
|
||||
|
||||
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, the default), which has the advantage of being easier to refer
|
||||
to, or in Vim's command line aligned with the function call (set to 2), which
|
||||
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
|
||||
@@ -195,12 +201,18 @@ get more information. If you set them to ``""``, they are not assigned.
|
||||
|
||||
let g:jedi#goto_command = "<leader>d"
|
||||
let g:jedi#goto_assignments_command = "<leader>g"
|
||||
let g:jedi#goto_stubs_command = "<leader>s"
|
||||
let g:jedi#goto_definitions_command = ""
|
||||
let g:jedi#documentation_command = "K"
|
||||
let g:jedi#usages_command = "<leader>n"
|
||||
let g:jedi#completions_command = "<C-Space>"
|
||||
let g:jedi#rename_command = "<leader>r"
|
||||
|
||||
A few examples of setting up your project:
|
||||
|
||||
.. code-block:: vim
|
||||
|
||||
let g:jedi#environment_path = "<leader>d"
|
||||
|
||||
Finally, if you don't want completion, but all the other features, use:
|
||||
|
||||
|
||||
@@ -26,7 +26,9 @@ if g:jedi#show_call_signatures > 0 && has('conceal')
|
||||
hi def link jediFunction CursorLine
|
||||
hi def link jediFat TabLine
|
||||
else
|
||||
hi jediFunction term=NONE cterm=NONE ctermfg=6 guifg=Black gui=NONE ctermbg=0 guibg=Grey
|
||||
hi jediFat term=bold,underline cterm=bold,underline gui=bold,underline ctermbg=0 guibg=#555555
|
||||
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
|
||||
|
||||
@@ -19,6 +19,7 @@ let s:default_settings = {
|
||||
\ 'goto_command': "'<leader>d'",
|
||||
\ 'goto_assignments_command': "'<leader>g'",
|
||||
\ 'goto_definitions_command': "''",
|
||||
\ 'goto_stubs_command': "'<leader>s'",
|
||||
\ 'completions_command': "'<C-Space>'",
|
||||
\ 'call_signatures_command': "'<leader>n'",
|
||||
\ 'usages_command': "'<leader>n'",
|
||||
@@ -26,7 +27,7 @@ let s:default_settings = {
|
||||
\ 'completions_enabled': 1,
|
||||
\ 'popup_on_dot': 'g:jedi#completions_enabled',
|
||||
\ 'documentation_command': "'K'",
|
||||
\ 'show_call_signatures': 1,
|
||||
\ 'show_call_signatures': has('conceal') ? 1 : 2,
|
||||
\ 'show_call_signatures_delay': 500,
|
||||
\ 'call_signature_escape': "'?!?'",
|
||||
\ 'auto_close_doc': 1,
|
||||
@@ -34,7 +35,9 @@ let s:default_settings = {
|
||||
\ 'popup_select_first': 1,
|
||||
\ 'quickfix_window_height': 10,
|
||||
\ 'force_py_version': "'auto'",
|
||||
\ 'smart_auto_mappings': 1,
|
||||
\ 'environment_path': "'auto'",
|
||||
\ 'project_path': "'auto'",
|
||||
\ 'smart_auto_mappings': 0,
|
||||
\ 'use_tag_stack': 1
|
||||
\ }
|
||||
|
||||
@@ -51,86 +54,68 @@ for [s:key, s:val] in items(s:default_settings)
|
||||
endif
|
||||
endfor
|
||||
|
||||
let s:supports_buffer_usages = has('nvim') || exists('*prop_add')
|
||||
|
||||
|
||||
" ------------------------------------------------------------------------
|
||||
" Python initialization
|
||||
" ------------------------------------------------------------------------
|
||||
let s:script_path = fnameescape(expand('<sfile>:p:h:h'))
|
||||
let s:script_path = expand('<sfile>:p:h:h')
|
||||
|
||||
function! s:init_python() abort
|
||||
if g:jedi#force_py_version !=# 'auto'
|
||||
" Always use the user supplied version.
|
||||
try
|
||||
return jedi#setup_py_version(g:jedi#force_py_version)
|
||||
catch
|
||||
throw 'Could not setup g:jedi#force_py_version: '.v:exception
|
||||
endtry
|
||||
endif
|
||||
|
||||
" Handle "auto" version.
|
||||
if has('nvim') || (has('python') && has('python3'))
|
||||
" Neovim usually has both python providers. Skipping the `has` check
|
||||
" avoids starting both of them.
|
||||
|
||||
" Get default python version from interpreter in $PATH.
|
||||
let s:def_py = system('python -c '.shellescape('import sys; sys.stdout.write(str(sys.version_info[0]))'))
|
||||
if v:shell_error != 0 || !len(s:def_py)
|
||||
if !exists('g:jedi#squelch_py_warning')
|
||||
echohl WarningMsg
|
||||
echom 'Warning: jedi-vim failed to get Python version from sys.version_info: ' . s:def_py
|
||||
echom 'Falling back to version 2.'
|
||||
echohl None
|
||||
endif
|
||||
let s:def_py = 2
|
||||
elseif &verbose
|
||||
echom 'jedi-vim: auto-detected Python: '.s:def_py
|
||||
endif
|
||||
|
||||
" Make sure that the auto-detected version is available in Vim.
|
||||
if !has('nvim') || has('python'.(s:def_py == 2 ? '' : s:def_py))
|
||||
return jedi#setup_py_version(s:def_py)
|
||||
endif
|
||||
|
||||
" Add a warning in case the auto-detected version is not available,
|
||||
" usually because of a missing neovim module in a VIRTUAL_ENV.
|
||||
if has('nvim')
|
||||
echohl WarningMsg
|
||||
echom 'jedi-vim: the detected Python version ('.s:def_py.')'
|
||||
\ 'is not functional.'
|
||||
\ 'Is the "neovim" module installed?'
|
||||
\ 'While jedi-vim will work, it might not use the'
|
||||
\ 'expected Python path.'
|
||||
echohl None
|
||||
endif
|
||||
endif
|
||||
|
||||
if has('python')
|
||||
call jedi#setup_py_version(2)
|
||||
elseif has('python3')
|
||||
call jedi#setup_py_version(3)
|
||||
else
|
||||
throw 'jedi-vim requires Vim with support for Python 2 or 3.'
|
||||
" 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
|
||||
unlet! s:_init_python
|
||||
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()
|
||||
catch
|
||||
let s:_init_python = 0
|
||||
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')
|
||||
echoerr 'Error: jedi-vim failed to initialize Python: '
|
||||
\ .v:exception.' (in '.v:throwpoint.')'
|
||||
unsilent call s:display_exception()
|
||||
endif
|
||||
endtry
|
||||
endif
|
||||
@@ -138,79 +123,79 @@ function! jedi#init_python() abort
|
||||
endfunction
|
||||
|
||||
|
||||
let s:python_version = 'null'
|
||||
function! jedi#setup_py_version(py_version) abort
|
||||
if a:py_version == 2
|
||||
let cmd_exec = 'python'
|
||||
let s:python_version = 2
|
||||
elseif a:py_version == 3
|
||||
let cmd_exec = 'python3'
|
||||
let s:python_version = 3
|
||||
else
|
||||
throw 'jedi#setup_py_version: invalid py_version: '.a:py_version
|
||||
endif
|
||||
|
||||
execute 'command! -nargs=1 PythonJedi '.cmd_exec.' <args>'
|
||||
|
||||
let s:init_outcome = 0
|
||||
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:',
|
||||
\ ' vim.command(''let s:init_outcome = "could not import jedi_vim: {0}: {1}"''.format(exc.__class__.__name__, exc))',
|
||||
\ 'else:',
|
||||
\ ' vim.command(''let s:init_outcome = 1'')']
|
||||
try
|
||||
exe 'PythonJedi exec('''.escape(join(init_lines, '\n'), "'").''')'
|
||||
catch
|
||||
throw printf('jedi#setup_py_version: failed to run Python for initialization: %s.', v:exception)
|
||||
endtry
|
||||
if s:init_outcome is 0
|
||||
throw 'jedi#setup_py_version: failed to run Python for initialization.'
|
||||
elseif s:init_outcome isnot 1
|
||||
throw printf('jedi#setup_py_version: %s.', s:init_outcome)
|
||||
\ ' _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 s:python_version ==# 'null'
|
||||
try
|
||||
call s:init_python()
|
||||
catch
|
||||
echohl WarningMsg | echom v:exception | echohl None
|
||||
return
|
||||
endtry
|
||||
endif
|
||||
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 'Using Python version:' s:python_version
|
||||
let pyeval = s:python_version == 3 ? 'py3eval' : 'pyeval'
|
||||
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
|
||||
PythonJedi import vim; vim.command('let s:pythonjedi_called = 1')
|
||||
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 'PythonJedi failed to run, likely a Python config issue.'
|
||||
if exists(':CheckHealth') == 2
|
||||
echom 'Try :CheckHealth for more information.'
|
||||
echom 'python3 failed to run, likely a Python config issue.'
|
||||
if exists(':checkhealth') == 2
|
||||
echom 'Try :checkhealth for more information.'
|
||||
endif
|
||||
echohl None
|
||||
else
|
||||
PythonJedi from jedi_vim_debug import display_debug_info
|
||||
PythonJedi display_debug_info()
|
||||
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 ' - jedi-vim git version: '
|
||||
echon substitute(system('git -C '.s:script_path.' describe --tags --always --dirty'), '\v\n$', '', '')
|
||||
echo ' - jedi git submodule status: '
|
||||
echon substitute(system('git -C '.s:script_path.' submodule status'), '\v\n$', '', '')
|
||||
echo "\n"
|
||||
echo '##### Settings'
|
||||
echo "\n"
|
||||
echo '```'
|
||||
let jedi_settings = items(filter(copy(g:), "v:key =~# '\\v^jedi#'"))
|
||||
let has_nondefault_settings = 0
|
||||
@@ -252,23 +237,6 @@ function! jedi#debug_info() abort
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! jedi#force_py_version(py_version) abort
|
||||
let g:jedi#force_py_version = a:py_version
|
||||
return jedi#setup_py_version(a:py_version)
|
||||
endfunction
|
||||
|
||||
|
||||
function! jedi#force_py_version_switch() abort
|
||||
if g:jedi#force_py_version == 2
|
||||
call jedi#force_py_version(3)
|
||||
elseif g:jedi#force_py_version == 3
|
||||
call jedi#force_py_version(2)
|
||||
else
|
||||
throw "Don't know how to switch from ".g:jedi#force_py_version.'!'
|
||||
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
|
||||
@@ -293,57 +261,150 @@ call jedi#init_python() " Might throw an error.
|
||||
" functions that call python code
|
||||
" ------------------------------------------------------------------------
|
||||
function! jedi#goto() abort
|
||||
PythonJedi jedi_vim.goto(mode="goto")
|
||||
python3 jedi_vim.goto(mode="goto")
|
||||
endfunction
|
||||
|
||||
function! jedi#goto_assignments() abort
|
||||
PythonJedi jedi_vim.goto(mode="assignment")
|
||||
python3 jedi_vim.goto(mode="assignment")
|
||||
endfunction
|
||||
|
||||
function! jedi#goto_definitions() abort
|
||||
PythonJedi jedi_vim.goto(mode="definition")
|
||||
python3 jedi_vim.goto(mode="definition")
|
||||
endfunction
|
||||
|
||||
function! jedi#goto_stubs() abort
|
||||
python3 jedi_vim.goto(mode="stubs")
|
||||
endfunction
|
||||
|
||||
function! jedi#usages() abort
|
||||
PythonJedi jedi_vim.goto(mode="related_name")
|
||||
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! * <buffer='.winbufnr(winnr).'>'
|
||||
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#<buffer>')
|
||||
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 <buffer> 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 <buffer> 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 <buffer='.b.'> call jedi#_hide_usages_in_win()'
|
||||
endif
|
||||
endfor
|
||||
augroup END
|
||||
endif
|
||||
|
||||
python3 jedi_vim.clear_usages()
|
||||
endfunction
|
||||
|
||||
function! jedi#rename(...) abort
|
||||
PythonJedi jedi_vim.rename()
|
||||
python3 jedi_vim.rename()
|
||||
endfunction
|
||||
|
||||
function! jedi#rename_visual(...) abort
|
||||
PythonJedi jedi_vim.rename_visual()
|
||||
python3 jedi_vim.rename_visual()
|
||||
endfunction
|
||||
|
||||
function! jedi#completions(findstart, base) abort
|
||||
PythonJedi jedi_vim.completions()
|
||||
python3 jedi_vim.completions()
|
||||
endfunction
|
||||
|
||||
function! jedi#enable_speed_debugging() abort
|
||||
PythonJedi 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, speed=True, warnings=False, notices=False)
|
||||
endfunction
|
||||
|
||||
function! jedi#enable_debugging() abort
|
||||
PythonJedi jedi_vim.jedi.set_debug_function(jedi_vim.print_to_stdout)
|
||||
python3 jedi_vim.jedi.set_debug_function(jedi_vim.print_to_stdout)
|
||||
endfunction
|
||||
|
||||
function! jedi#disable_debugging() abort
|
||||
PythonJedi jedi_vim.jedi.set_debug_function(None)
|
||||
python3 jedi_vim.jedi.set_debug_function(None)
|
||||
endfunction
|
||||
|
||||
function! jedi#py_import(args) abort
|
||||
PythonJedi jedi_vim.py_import()
|
||||
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
|
||||
PythonJedi jedi_vim.py_import_completions()
|
||||
python3 jedi_vim.py_import_completions()
|
||||
endfun
|
||||
|
||||
function! jedi#clear_cache(bang) abort
|
||||
PythonJedi jedi_vim.jedi.cache.clear_time_caches(True)
|
||||
if a:bang
|
||||
PythonJedi jedi_vim.jedi.parser.utils.ParserPickling.clear_cache()
|
||||
python3 jedi_vim.jedi.cache.clear_time_caches(True)
|
||||
else
|
||||
python3 jedi_vim.jedi.cache.clear_time_caches(False)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
@@ -352,7 +413,7 @@ endfunction
|
||||
" show_documentation
|
||||
" ------------------------------------------------------------------------
|
||||
function! jedi#show_documentation() abort
|
||||
PythonJedi if jedi_vim.show_documentation() is None: vim.command('return')
|
||||
python3 if jedi_vim.show_documentation() is None: vim.command('return')
|
||||
|
||||
let bn = bufnr('__doc__')
|
||||
if bn > 0
|
||||
@@ -385,27 +446,57 @@ function! jedi#show_documentation() abort
|
||||
|
||||
" quit comands
|
||||
nnoremap <buffer> q ZQ
|
||||
execute 'nnoremap <buffer> '.g:jedi#documentation_command.' ZQ'
|
||||
if len(g:jedi#documentation_command)
|
||||
execute 'nnoremap <buffer> '.g:jedi#documentation_command.' ZQ'
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" ------------------------------------------------------------------------
|
||||
" helper functions
|
||||
" ------------------------------------------------------------------------
|
||||
|
||||
function! jedi#add_goto_window(len) abort
|
||||
set lazyredraw
|
||||
cclose
|
||||
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
|
||||
set nolazyredraw
|
||||
|
||||
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 <buffer> <CR> :call jedi#goto_window_on_enter()<CR>
|
||||
endif
|
||||
|
||||
augroup jedi_goto_window
|
||||
au!
|
||||
au WinLeave <buffer> q " automatically leave, if an option is chosen
|
||||
if a:for_usages
|
||||
autocmd BufWinLeave <buffer> call jedi#clear_usages()
|
||||
else
|
||||
autocmd WinLeave <buffer> q " automatically leave, if an option is chosen
|
||||
endif
|
||||
augroup END
|
||||
redraw!
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -415,7 +506,7 @@ function! jedi#goto_window_on_enter() abort
|
||||
if l:data.bufnr
|
||||
" close goto_window buffer
|
||||
normal! ZQ
|
||||
PythonJedi jedi_vim.new_buffer(vim.eval('bufname(l:data.bufnr)'))
|
||||
python3 jedi_vim.new_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
|
||||
@@ -461,22 +552,23 @@ function! jedi#show_call_signatures() abort
|
||||
|
||||
" Caching. On the same line only.
|
||||
if line == s:show_call_signatures_last[0]
|
||||
" Check if the number of commas and parenthesis before or after the
|
||||
" 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]
|
||||
if substitute(curline[:col-2], '[^,()]', '', 'g')
|
||||
\ == substitute(prevline[:prevcol-2], '[^,()]', '', 'g')
|
||||
\ && substitute(curline[(col-2):], '[^,()]', '', 'g')
|
||||
\ == substitute(prevline[(prevcol-2):], '[^,()]', '', 'g')
|
||||
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
|
||||
PythonJedi jedi_vim.show_call_signatures()
|
||||
python3 jedi_vim.show_call_signatures()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
@@ -487,7 +579,7 @@ function! jedi#clear_call_signatures() abort
|
||||
endif
|
||||
|
||||
let s:show_call_signatures_last = [0, 0, '']
|
||||
PythonJedi jedi_vim.clear_call_signatures()
|
||||
python3 jedi_vim.clear_call_signatures()
|
||||
endfunction
|
||||
|
||||
|
||||
@@ -632,7 +724,7 @@ function! jedi#setup_completion() abort
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"PythonJedi jedi_vim.jedi.set_debug_function(jedi_vim.print_to_stdout, speed=True, warnings=False, notices=False)
|
||||
"PythonJedi jedi_vim.jedi.set_debug_function(jedi_vim.print_to_stdout)
|
||||
"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:
|
||||
|
||||
7
codecov.yml
Normal file
7
codecov.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
coverage:
|
||||
status:
|
||||
project: true
|
||||
patch: true
|
||||
changes: true
|
||||
|
||||
comment: off
|
||||
75
conftest.py
75
conftest.py
@@ -1,75 +0,0 @@
|
||||
import os
|
||||
import subprocess
|
||||
import urllib.request
|
||||
import zipfile
|
||||
|
||||
import pytest
|
||||
|
||||
VSPEC_URL = 'https://github.com/kana/vim-vspec/archive/1.4.1.zip'
|
||||
CACHE_FOLDER = '.cache'
|
||||
VSPEC_FOLDER = os.path.join(CACHE_FOLDER, 'vim-vspec-1.4.1')
|
||||
VSPEC_RUNNER = os.path.join(VSPEC_FOLDER, 'bin/vspec')
|
||||
TEST_DIR = 'test'
|
||||
|
||||
|
||||
class IntegrationTestFile(object):
|
||||
def __init__(self, path):
|
||||
self.path = path
|
||||
|
||||
def run(self):
|
||||
output = subprocess.check_output(
|
||||
[VSPEC_RUNNER, '.', VSPEC_FOLDER, self.path])
|
||||
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("{0} failed:\n{1}".format(
|
||||
self.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("{0} failed: no 'ok' found:\n{1}".format(
|
||||
self.path, output.decode('utf-8')), pytrace=False)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
name = os.path.basename(self.path)
|
||||
name, _, _ = name.rpartition('.')
|
||||
return name
|
||||
|
||||
def __repr__(self):
|
||||
return "<%s: %s>" % (type(self), self.path)
|
||||
|
||||
|
||||
def pytest_configure(config):
|
||||
if not os.path.isdir(CACHE_FOLDER):
|
||||
os.mkdir(CACHE_FOLDER)
|
||||
|
||||
if not os.path.exists(VSPEC_FOLDER):
|
||||
name, hdrs = urllib.request.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 pytest_generate_tests(metafunc):
|
||||
"""
|
||||
:type metafunc: _pytest.python.Metafunc
|
||||
"""
|
||||
def collect_tests():
|
||||
for f in os.listdir(TEST_DIR):
|
||||
if f.endswith('.vim') and f != 'utils.vim':
|
||||
yield IntegrationTestFile(os.path.join(TEST_DIR, f))
|
||||
|
||||
tests = list(collect_tests())
|
||||
metafunc.parametrize('case', tests, ids=[test.name for test in tests])
|
||||
@@ -24,7 +24,7 @@ Contents *jedi-vim-contents*
|
||||
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 definition (deprecated) |g:jedi#goto_definitions_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|
|
||||
@@ -44,6 +44,7 @@ Contents *jedi-vim-contents*
|
||||
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|
|
||||
7. Testing |jedi-vim-testing|
|
||||
8. Contributing |jedi-vim-contributing|
|
||||
9. License |jedi-vim-license|
|
||||
@@ -60,7 +61,7 @@ Jedi-vim is a Vim binding to the awesome Python autocompletion library
|
||||
- Infers function arguments from Sphinx/Epydoc strings
|
||||
- Doesn't execute Python code
|
||||
- Supports Virtualenv
|
||||
- Supports Python 2.5+ and 3.2+
|
||||
- Supports Python 2.7 and 3.4+
|
||||
|
||||
By leveraging this library, jedi-vim adds the following capabilities to Vim:
|
||||
|
||||
@@ -78,15 +79,6 @@ By leveraging this library, jedi-vim adds the following capabilities to Vim:
|
||||
|
||||
First of all, jedi-vim requires Vim to be compiled with the `+python` option.
|
||||
|
||||
The jedi library has to be installed for jedi-vim to work properly. You can
|
||||
install it first, by using e.g. your distribution's package manager, or by
|
||||
using pip: >
|
||||
|
||||
pip install jedi
|
||||
|
||||
However, you can also install it as a git submodule if you don't want to use
|
||||
jedi for anything but this plugin. How to do this is detailed below.
|
||||
|
||||
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
|
||||
@@ -107,11 +99,7 @@ feature (such as MacVim on OS X, which also contains a console binary).
|
||||
------------------------------------------------------------------------------
|
||||
2.1. Installing manually *jedi-vim-installation-manually*
|
||||
|
||||
1a. Get the latest repository from Github: >
|
||||
|
||||
git clone http://github.com/davidhalter/jedi-vim path/to/bundles/jedi-vim
|
||||
|
||||
1b. If you want to install jedi as a submodule instead, issue this command: >
|
||||
1. If you want to install jedi as a submodule instead, issue this command: >
|
||||
|
||||
git clone --recursive http://github.com/davidhalter/jedi-vim
|
||||
|
||||
@@ -161,8 +149,8 @@ repositories. On Arch Linux, install vim-jedi. On Debian (8+) or Ubuntu
|
||||
==============================================================================
|
||||
3. Supported Python features *jedi-vim-support*
|
||||
|
||||
The Jedi library does all the hard work behind the scenes. It supports
|
||||
completion of a large number of Python features, among them:
|
||||
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
|
||||
@@ -183,12 +171,14 @@ completion of a large number of Python features, among them:
|
||||
- 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
|
||||
- `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.jedidjah.ch.
|
||||
features, please refer to the Jedi documentation at
|
||||
http://jedi.readthedocs.io.
|
||||
|
||||
==============================================================================
|
||||
4. Usage *jedi-vim-usage*
|
||||
@@ -285,12 +275,11 @@ 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_definitions_command` *g:jedi#goto_definitions_command*
|
||||
Function: `jedi#goto_definitions()`
|
||||
Default: - Go to original definition
|
||||
5.4. `g:jedi#goto_stubs_command` *g:jedi#goto_stubs_command*
|
||||
Function: `jedi#goto_stubs()`
|
||||
Default: <leader>s Go to stub
|
||||
|
||||
NOTE: Deprecated. Use |g:jedi#goto_command| / |jedi#goto()| instead, which
|
||||
currently uses this internally.
|
||||
Finds the stub of the function/class under the cursor.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
5.5. `g:jedi#documentation_command` *g:jedi#documentation_command*
|
||||
@@ -308,7 +297,7 @@ Default: <leader>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 occurences of the old variable name
|
||||
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.
|
||||
|
||||
@@ -439,10 +428,10 @@ Default: 500
|
||||
|
||||
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 buffer instead.
|
||||
(0), they open in the current window instead.
|
||||
|
||||
Options: 0 or 1
|
||||
Default: 0 (Command output is put in a new tab)
|
||||
Default: 0 (Command output reuses current window)
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
6.9. `g:jedi#squelch_py_warning` *g:jedi#squelch_py_warning*
|
||||
@@ -480,33 +469,32 @@ small a horizontal split happens.
|
||||
------------------------------------------------------------------------------
|
||||
6.12. `g:jedi#force_py_version` *g:jedi#force_py_version*
|
||||
|
||||
If you have installed both python 2 and python 3, you can force which one jedi
|
||||
should use by setting this variable. It forces the internal Vim command, which
|
||||
will be used for every jedi call to the respective python interpreter.
|
||||
The variable can be set in the .vimrc like this to force python 3:
|
||||
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 = 3
|
||||
let g:jedi#force_py_version = 2
|
||||
|
||||
This variable can be switched during runtime using the following function:
|
||||
Function: `jedi#force_py_version_switch()`
|
||||
By default jedi loads the latest Python version installed on your system that
|
||||
can be found.
|
||||
|
||||
or set directly using this function, which has the same name as the variable:
|
||||
Function: `jedi#force_py_version(py_version)`
|
||||
This variable can be changed during runtime.
|
||||
|
||||
Options: 2 or 3
|
||||
Default: "auto" (will use sys.version_info from "python" in your $PATH)
|
||||
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<space>` jedi-vim automatically
|
||||
adds the "import" statement and displays the autocomplete popup.
|
||||
can add the "import" statement and trigger the autocompletion popup.
|
||||
|
||||
This option can be disabled in the .vimrc:
|
||||
|
||||
`let g:jedi#smart_auto_mappings = 0`
|
||||
You can enable this using: >
|
||||
|
||||
let g:jedi#smart_auto_mappings = 1
|
||||
<
|
||||
Options: 0 or 1
|
||||
Default: 1 (enabled by default)
|
||||
Default: 0 (disabled by default)
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
6.14. `g:jedi#use_tag_stack` *g:jedi#use_tag_stack*
|
||||
@@ -519,6 +507,17 @@ 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*
|
||||
|
||||
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"
|
||||
Default: "auto"
|
||||
|
||||
==============================================================================
|
||||
7. Testing *jedi-vim-testing*
|
||||
|
||||
|
||||
140
doc/logotype-a.svg
Normal file
140
doc/logotype-a.svg
Normal file
@@ -0,0 +1,140 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="897.845px" height="247.51px" viewBox="0 0 897.845 247.51" enable-background="new 0 0 897.845 247.51"
|
||||
xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="287.3965" y1="65.2686" x2="287.3965" y2="106.4546">
|
||||
<stop offset="0" style="stop-color:#E27817"/>
|
||||
<stop offset="0.3906" style="stop-color:#E47519"/>
|
||||
<stop offset="0.7116" style="stop-color:#E96B1F"/>
|
||||
<stop offset="1" style="stop-color:#F15A29"/>
|
||||
</linearGradient>
|
||||
<polygon fill="url(#SVGID_1_)" points="285.068,66.556 272.054,95.664 302.739,95.664 302.739,66.556 "/>
|
||||
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="216.8877" y1="65.2686" x2="216.8877" y2="106.4546">
|
||||
<stop offset="0" style="stop-color:#E27817"/>
|
||||
<stop offset="0.3906" style="stop-color:#E47519"/>
|
||||
<stop offset="0.7116" style="stop-color:#E96B1F"/>
|
||||
<stop offset="1" style="stop-color:#F15A29"/>
|
||||
</linearGradient>
|
||||
<polygon fill="url(#SVGID_2_)" points="180.483,95.664 193.893,95.664 240.172,95.664 253.292,66.556 180.483,66.556 "/>
|
||||
<g>
|
||||
<polygon fill="#019733" points="256.464,59.293 253.603,65.696 253.593,65.696 253.197,66.592 240.172,95.7 215.738,150.321
|
||||
199.788,185.978 231.676,185.978 231.676,185.969 272.071,95.7 275.634,87.737 285.089,66.592 288.355,59.293 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon fill="#019733" points="215.738,150.321 194.605,95.7 180.483,95.7 180.483,135.118 199.788,185.969 199.788,185.978
|
||||
"/>
|
||||
</g>
|
||||
<path fill="#019733" d="M151.355,59.294v100.005h-28.989h-11.292v-7.972c3.644-4.232,6.749-9.936,6.749-16.218
|
||||
c0-2.846-0.456-5.578-1.294-8.104h0.011l-4.274-12.151c-0.238-1.16-0.633-2.257-1.15-3.281v-0.032l-5.878-11.59
|
||||
c-1.201-2.808-3.975-4.897-7.34-5.362c0.281-4.969,2.837-8.87,5.932-8.87l-3.137-1.004l3.137-3.033
|
||||
c-5.01,0-9.098,5.775-9.388,13.021c-3.116,0.609-5.672,2.598-6.79,5.258l-5.723,11.271c-0.052,0.104-0.104,0.197-0.155,0.3v0.01
|
||||
c-0.528,1.057-0.932,2.174-1.169,3.344l-4.232,12.079c-0.012,0.02-0.012,0.03-0.021,0.042c-0.828,2.525-1.294,5.258-1.294,8.104
|
||||
c0,6.282,3.25,11.985,6.904,16.218v35.616h29.112h11.294h58.105V59.294H151.355z M86.554,117.834
|
||||
c-0.673,2.019-2.442,3.252-3.954,2.744c-1.51-0.508-2.194-2.547-1.521-4.565c0.673-2.017,2.443-3.25,3.953-2.742
|
||||
C86.544,113.777,87.228,115.817,86.554,117.834z M110.163,120.578c-1.51,0.508-3.27-0.726-3.954-2.744
|
||||
c-0.672-2.017,0.011-4.057,1.521-4.563c1.512-0.508,3.282,0.726,3.955,2.742C112.357,118.031,111.674,120.07,110.163,120.578z"/>
|
||||
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="134.6348" y1="65.2686" x2="134.6348" y2="106.4546">
|
||||
<stop offset="0" style="stop-color:#E27817"/>
|
||||
<stop offset="0.3906" style="stop-color:#E47519"/>
|
||||
<stop offset="0.7116" style="stop-color:#E96B1F"/>
|
||||
<stop offset="1" style="stop-color:#F15A29"/>
|
||||
</linearGradient>
|
||||
<polygon fill="url(#SVGID_3_)" points="151.292,66.556 117.914,66.556 117.914,95.664 145.981,95.664 151.292,95.664
|
||||
151.355,95.664 151.355,66.592 151.292,66.592 "/>
|
||||
<g opacity="0.5">
|
||||
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="244.0713" y1="198.6924" x2="244.0713" y2="111.1674">
|
||||
<stop offset="0" style="stop-color:#019733"/>
|
||||
<stop offset="0.1363" style="stop-color:#0B732D;stop-opacity:0.8637"/>
|
||||
<stop offset="0.2826" style="stop-color:#145529;stop-opacity:0.7174"/>
|
||||
<stop offset="0.4366" style="stop-color:#1A3D25;stop-opacity:0.5634"/>
|
||||
<stop offset="0.5997" style="stop-color:#1F2C22;stop-opacity:0.4003"/>
|
||||
<stop offset="0.778" style="stop-color:#222221;stop-opacity:0.222"/>
|
||||
<stop offset="1" style="stop-color:#231F20;stop-opacity:0"/>
|
||||
</linearGradient>
|
||||
<polygon fill="url(#SVGID_4_)" points="256.464,59.293 253.603,65.696 253.593,65.696 253.197,66.592 240.172,95.7
|
||||
215.738,150.321 199.788,185.978 231.676,185.978 231.676,185.969 272.071,95.7 275.634,87.737 285.089,66.592 288.355,59.293
|
||||
"/>
|
||||
</g>
|
||||
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="165.9131" y1="41.1123" x2="165.9131" y2="128.6277">
|
||||
<stop offset="0" style="stop-color:#019733"/>
|
||||
<stop offset="0.1363" style="stop-color:#0B732D;stop-opacity:0.8637"/>
|
||||
<stop offset="0.2826" style="stop-color:#145529;stop-opacity:0.7174"/>
|
||||
<stop offset="0.4366" style="stop-color:#1A3D25;stop-opacity:0.5634"/>
|
||||
<stop offset="0.5997" style="stop-color:#1F2C22;stop-opacity:0.4003"/>
|
||||
<stop offset="0.778" style="stop-color:#222221;stop-opacity:0.222"/>
|
||||
<stop offset="1" style="stop-color:#231F20;stop-opacity:0"/>
|
||||
</linearGradient>
|
||||
<rect x="151.355" y="59.294" opacity="0.5" fill="url(#SVGID_5_)" width="29.116" height="127.649"/>
|
||||
<g opacity="0.58">
|
||||
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="198.1104" y1="83.4141" x2="198.1104" y2="154.2879">
|
||||
<stop offset="0" style="stop-color:#019733"/>
|
||||
<stop offset="0.0409" style="stop-color:#038E32;stop-opacity:0.9591"/>
|
||||
<stop offset="0.2465" style="stop-color:#0F662B;stop-opacity:0.7535"/>
|
||||
<stop offset="0.4491" style="stop-color:#184726;stop-opacity:0.5509"/>
|
||||
<stop offset="0.6453" style="stop-color:#1E3123;stop-opacity:0.3547"/>
|
||||
<stop offset="0.8322" style="stop-color:#222421;stop-opacity:0.1678"/>
|
||||
<stop offset="1" style="stop-color:#231F20;stop-opacity:0"/>
|
||||
</linearGradient>
|
||||
<polygon fill="url(#SVGID_6_)" points="215.738,150.321 194.605,95.7 180.483,95.7 180.483,135.118 199.788,185.969
|
||||
199.788,185.978 "/>
|
||||
</g>
|
||||
<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="127.7627" y1="192.1367" x2="127.7627" y2="137.5901">
|
||||
<stop offset="0" style="stop-color:#019733"/>
|
||||
<stop offset="0.0409" style="stop-color:#038E32;stop-opacity:0.9591"/>
|
||||
<stop offset="0.2465" style="stop-color:#0F662B;stop-opacity:0.7535"/>
|
||||
<stop offset="0.4491" style="stop-color:#184726;stop-opacity:0.5509"/>
|
||||
<stop offset="0.6453" style="stop-color:#1E3123;stop-opacity:0.3547"/>
|
||||
<stop offset="0.8322" style="stop-color:#222421;stop-opacity:0.1678"/>
|
||||
<stop offset="1" style="stop-color:#231F20;stop-opacity:0"/>
|
||||
</linearGradient>
|
||||
<path opacity="0.6" fill="url(#SVGID_7_)" d="M151.355,59.294v100.005h-28.989h-11.292v-7.972
|
||||
c3.644-4.232,6.749-9.936,6.749-16.218c0-2.846-0.456-5.578-1.294-8.104h0.011l-4.274-12.151c-0.238-1.16-0.633-2.257-1.15-3.281
|
||||
v-0.032l-5.878-11.59c-1.201-2.808-3.975-4.897-7.34-5.362c0.281-4.969,2.837-8.87,5.932-8.87l-3.137-1.004l3.137-3.033
|
||||
c-5.01,0-9.098,5.775-9.388,13.021c-3.116,0.609-5.672,2.598-6.79,5.258l-5.723,11.271c-0.052,0.104-0.104,0.197-0.155,0.3v0.01
|
||||
c-0.528,1.057-0.932,2.174-1.169,3.344l-4.232,12.079c-0.012,0.02-0.012,0.03-0.021,0.042c-0.828,2.525-1.294,5.258-1.294,8.104
|
||||
c0,6.282,3.25,11.985,6.904,16.218v35.616h29.112h11.294h58.105V59.294H151.355z M86.554,117.834
|
||||
c-0.673,2.019-2.442,3.252-3.954,2.744c-1.51-0.508-2.194-2.547-1.521-4.565c0.673-2.017,2.443-3.25,3.953-2.742
|
||||
C86.544,113.777,87.228,115.817,86.554,117.834z M110.163,120.578c-1.51,0.508-3.27-0.726-3.954-2.744
|
||||
c-0.672-2.017,0.011-4.057,1.521-4.563c1.512-0.508,3.282,0.726,3.955,2.742C112.357,118.031,111.674,120.07,110.163,120.578z"/>
|
||||
<g opacity="0.5">
|
||||
<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="244.0713" y1="53.3584" x2="244.0713" y2="78.0277">
|
||||
<stop offset="0" style="stop-color:#019733"/>
|
||||
<stop offset="0.1363" style="stop-color:#0B732D;stop-opacity:0.8637"/>
|
||||
<stop offset="0.2826" style="stop-color:#145529;stop-opacity:0.7174"/>
|
||||
<stop offset="0.4366" style="stop-color:#1A3D25;stop-opacity:0.5634"/>
|
||||
<stop offset="0.5997" style="stop-color:#1F2C22;stop-opacity:0.4003"/>
|
||||
<stop offset="0.778" style="stop-color:#222221;stop-opacity:0.222"/>
|
||||
<stop offset="1" style="stop-color:#231F20;stop-opacity:0"/>
|
||||
</linearGradient>
|
||||
<polygon fill="url(#SVGID_8_)" points="256.464,59.293 253.603,65.696 253.593,65.696 253.197,66.592 240.172,95.7
|
||||
215.738,150.321 199.788,185.978 231.676,185.978 231.676,185.969 272.071,95.7 275.634,87.737 285.089,66.592 288.355,59.293
|
||||
"/>
|
||||
</g>
|
||||
<polygon fill="#019733" points="180.483,59.198 183.329,66.556 180.471,66.556 "/>
|
||||
<polygon fill="#019733" points="180.483,59.198 183.329,66.556 180.471,66.556 "/>
|
||||
<g>
|
||||
<polygon fill="#019733" points="290.713,66.592 285.054,66.592 288.32,59.293 "/>
|
||||
<polygon fill="#019733" points="308.417,120.554 283.562,95.7 300.261,95.7 "/>
|
||||
<polygon opacity="0.6" fill="#019733" points="308.417,120.554 283.562,95.7 300.261,95.7 "/>
|
||||
<polygon fill="#019733" points="290.713,66.592 285.054,66.592 288.32,59.293 "/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#666666" d="M358.849,130.077v23.827h28.81V77.887h16.547v91.732h-62.987v-39.542H358.849z"/>
|
||||
<path fill="#666666" d="M434.61,93.602v22.677h45.356v14.949H434.61v22.677h45.356v15.715h-62.987V77.887h62.987v15.715H434.61z"
|
||||
/>
|
||||
<path fill="#666666" d="M492.744,169.619V77.887h56.342l6.643,8.05v75.634l-6.579,8.049H492.744z M539.184,93.602h-28.811v60.303
|
||||
h28.811V93.602z"/>
|
||||
<path fill="#666666" d="M586.136,169.619h-17.632V77.887h17.632V169.619z"/>
|
||||
<path fill="#666666" d="M598.913,116.278h33.281v14.949h-33.281V116.278z"/>
|
||||
<path fill="#666666" d="M691.412,77.887h16.544l-19.995,91.732h-21.462l-21.527-91.732h17.63l13.798,70.588L691.412,77.887z"/>
|
||||
<path fill="#666666" d="M738.364,169.619h-17.631V77.887h17.631V169.619z"/>
|
||||
<path fill="#666666" d="M768.77,169.619h-17.632V77.887h17.632l17.886,50.273l18.59-50.273h16.545v91.732h-16.545v-38.392
|
||||
l-12.84,38.392h-10.35l-13.286-38.392V169.619z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 9.8 KiB |
@@ -16,6 +16,9 @@ if g:jedi#auto_initialization
|
||||
if len(g:jedi#goto_definitions_command)
|
||||
execute 'nnoremap <buffer> '.g:jedi#goto_definitions_command.' :call jedi#goto_definitions()<CR>'
|
||||
endif
|
||||
if len(g:jedi#goto_stubs_command)
|
||||
execute 'nnoremap <buffer> '.g:jedi#goto_stubs_command.' :call jedi#goto_stubs()<CR>'
|
||||
endif
|
||||
if len(g:jedi#usages_command)
|
||||
execute 'nnoremap <buffer> '.g:jedi#usages_command.' :call jedi#usages()<CR>'
|
||||
endif
|
||||
@@ -29,7 +32,7 @@ if g:jedi#auto_initialization
|
||||
execute 'nnoremap <silent> <buffer>'.g:jedi#documentation_command.' :call jedi#show_documentation()<CR>'
|
||||
endif
|
||||
|
||||
if g:jedi#show_call_signatures > 0 && has('conceal')
|
||||
if g:jedi#show_call_signatures > 0
|
||||
call jedi#configure_call_signatures()
|
||||
endif
|
||||
|
||||
|
||||
@@ -15,6 +15,11 @@ if get(g:, 'jedi#auto_vim_configuration', 1)
|
||||
" 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
|
||||
@@ -48,7 +53,25 @@ endif
|
||||
" Pyimport command
|
||||
command! -nargs=1 -complete=custom,jedi#py_import_completions Pyimport :call jedi#py_import(<q-args>)
|
||||
|
||||
command! -nargs=0 -bar JediDebugInfo call jedi#debug_info()
|
||||
command! -nargs=? -complete=file JediChooseEnvironment :call jedi#choose_environment(<q-args>)
|
||||
command! -nargs=? -complete=file JediLoadProject :call jedi#load_project(<q-args>)
|
||||
|
||||
|
||||
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(<bang>0)
|
||||
|
||||
" vim: set et ts=4:
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
[pytest]
|
||||
# Ignore all files
|
||||
norecursedirs = *
|
||||
Submodule pythonx/jedi updated: 02f238ce08...4b5b2e791b
@@ -25,6 +25,16 @@ 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__ = []
|
||||
@@ -57,7 +67,9 @@ class VimError(Exception):
|
||||
self.executing = executing
|
||||
|
||||
def __str__(self):
|
||||
return self.message + '; created by: ' + repr(self.executing)
|
||||
return "{}; created by {!r} (in {})".format(
|
||||
self.message, self.executing, self.throwpoint
|
||||
)
|
||||
|
||||
|
||||
def _catch_exception(string, is_eval):
|
||||
@@ -73,11 +85,11 @@ def _catch_exception(string, is_eval):
|
||||
|
||||
|
||||
def vim_command(string):
|
||||
_catch_exception(string, False)
|
||||
_catch_exception(string, is_eval=False)
|
||||
|
||||
|
||||
def vim_eval(string):
|
||||
return _catch_exception(string, True)
|
||||
return _catch_exception(string, is_eval=True)
|
||||
|
||||
|
||||
def no_jedi_warning(error=None):
|
||||
@@ -100,10 +112,9 @@ sys.path.insert(0, parso_path)
|
||||
|
||||
try:
|
||||
import jedi
|
||||
except ImportError as e:
|
||||
no_jedi_warning(str(e))
|
||||
except ImportError:
|
||||
jedi = None
|
||||
jedi_import_error = str(e)
|
||||
jedi_import_error = sys.exc_info()
|
||||
else:
|
||||
try:
|
||||
version = jedi.__version__
|
||||
@@ -125,6 +136,58 @@ finally:
|
||||
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:
|
||||
@@ -148,18 +211,104 @@ def _check_jedi_availability(show_error=False):
|
||||
return func_receiver
|
||||
|
||||
|
||||
# Tuple of cache key / project
|
||||
_current_project_cache = None, None
|
||||
|
||||
|
||||
def get_project():
|
||||
vim_environment_path = vim_eval("g:jedi#environment_path")
|
||||
vim_project_path = vim_eval("g:jedi#project_path")
|
||||
|
||||
global _current_project_cache
|
||||
cache_key = dict(project_path=vim_project_path, environment_path=vim_environment_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)
|
||||
|
||||
_current_project_cache = cache_key, project
|
||||
return project
|
||||
|
||||
|
||||
@catch_and_print_exceptions
|
||||
def get_script(source=None, column=None):
|
||||
jedi.settings.additional_dynamic_modules = \
|
||||
[b.name for b in vim.buffers if b.name is not None and b.name.endswith('.py')]
|
||||
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 <buffer> <ESC> :bw<CR>')
|
||||
vim_command('noremap <buffer> <CR> :python3 jedi_vim.choose_environment_hit_enter()<CR>')
|
||||
|
||||
|
||||
@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)
|
||||
_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]
|
||||
buf_path = vim.current.buffer.name
|
||||
encoding = vim_eval('&encoding') or 'latin1'
|
||||
return jedi.Script(source, row, column, buf_path, encoding)
|
||||
return row, column
|
||||
|
||||
|
||||
@_check_jedi_availability(show_error=False)
|
||||
@@ -173,7 +322,7 @@ def completions():
|
||||
if vim.eval('a:findstart') == '1':
|
||||
count = 0
|
||||
for char in reversed(vim.current.line[:column]):
|
||||
if not re.match('[\w\d]', char):
|
||||
if not re.match(r'[\w\d]', char):
|
||||
break
|
||||
count += 1
|
||||
vim.command('return %i' % (column - count))
|
||||
@@ -190,20 +339,26 @@ def completions():
|
||||
# here again hacks, because jedi has a different interface than vim
|
||||
column += len(base)
|
||||
try:
|
||||
script = get_script(source=source, column=column)
|
||||
completions = script.completions()
|
||||
signatures = script.call_signatures()
|
||||
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),
|
||||
info=PythonToVimStr(c.docstring()), # docstr
|
||||
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)
|
||||
@@ -229,82 +384,372 @@ def tempfile(content):
|
||||
finally:
|
||||
os.unlink(f.name)
|
||||
|
||||
|
||||
@_check_jedi_availability(show_error=True)
|
||||
@catch_and_print_exceptions
|
||||
def goto(mode="goto", no_output=False):
|
||||
def goto(mode="goto"):
|
||||
"""
|
||||
:param str mode: "related_name", "definition", "assignment", "auto"
|
||||
:return: list of definitions/assignments
|
||||
:rtype: list
|
||||
:param str mode: "definition", "assignment", "goto"
|
||||
:rtype: list of jedi.api.classes.Name
|
||||
"""
|
||||
script = get_script()
|
||||
pos = get_pos()
|
||||
if mode == "goto":
|
||||
definitions = [x for x in script.goto_definitions()
|
||||
if not x.in_builtin_module()]
|
||||
if not definitions:
|
||||
definitions = script.goto_assignments()
|
||||
elif mode == "related_name":
|
||||
definitions = script.usages()
|
||||
names = script.goto(*pos, follow_imports=True)
|
||||
elif mode == "definition":
|
||||
definitions = script.goto_definitions()
|
||||
names = script.infer(*pos)
|
||||
elif mode == "assignment":
|
||||
definitions = script.goto_assignments()
|
||||
names = script.goto(*pos)
|
||||
elif mode == "stubs":
|
||||
names = script.goto(*pos, follow_imports=True, only_stubs=True)
|
||||
|
||||
|
||||
if no_output:
|
||||
return definitions
|
||||
if not definitions:
|
||||
if not names:
|
||||
echo_highlight("Couldn't find any definitions for this.")
|
||||
elif len(definitions) == 1 and mode != "related_name":
|
||||
d = list(definitions)[0]
|
||||
if d.in_builtin_module():
|
||||
if d.is_keyword:
|
||||
echo_highlight("Cannot get the definition of Python keywords.")
|
||||
else:
|
||||
echo_highlight("Builtin modules cannot be displayed (%s)."
|
||||
% d.desc_with_module)
|
||||
else:
|
||||
using_tagstack = int(vim_eval('g:jedi#use_tag_stack')) == 1
|
||||
if (d.module_path or '') != vim.current.buffer.name:
|
||||
result = new_buffer(d.module_path,
|
||||
using_tagstack=using_tagstack)
|
||||
if not result:
|
||||
return []
|
||||
if d.module_path and os.path.exists(d.module_path) and using_tagstack:
|
||||
tagname = d.name
|
||||
with tempfile('{0}\t{1}\t{2}'.format(tagname, d.module_path,
|
||||
'call cursor({0}, {1})'.format(d.line, d.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 = d.line, d.column
|
||||
elif len(names) == 1 and mode != "related_name":
|
||||
n = list(names)[0]
|
||||
_goto_specific_name(n)
|
||||
else:
|
||||
# multiple solutions
|
||||
lst = []
|
||||
for d in definitions:
|
||||
if d.in_builtin_module():
|
||||
lst.append(dict(text=PythonToVimStr('Builtin ' + d.description)))
|
||||
elif d.module_path is None:
|
||||
# Typically a namespace, in the future maybe other things as
|
||||
# well.
|
||||
lst.append(dict(text=PythonToVimStr(d.description)))
|
||||
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:
|
||||
echo_highlight("Builtin modules cannot be displayed (%s)."
|
||||
% (n.full_name or n.name))
|
||||
else:
|
||||
using_tagstack = int(vim_eval('g:jedi#use_tag_stack')) == 1
|
||||
module_path = str(n.module_path or '')
|
||||
if module_path != vim.current.buffer.name:
|
||||
result = new_buffer(module_path, options=options,
|
||||
using_tagstack=using_tagstack)
|
||||
if not result:
|
||||
return []
|
||||
if (using_tagstack and module_path and
|
||||
os.path.exists(module_path)):
|
||||
tagname = n.name
|
||||
with tempfile('{0}\t{1}\t{2}'.format(
|
||||
tagname, 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:
|
||||
lst.append(dict(filename=PythonToVimStr(d.module_path),
|
||||
lnum=d.line, col=d.column + 1,
|
||||
text=PythonToVimStr(d.description)))
|
||||
vim_eval('setqflist(%s)' % repr(lst))
|
||||
vim_eval('jedi#add_goto_window(' + str(len(lst)) + ')')
|
||||
return definitions
|
||||
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)
|
||||
@@ -312,21 +757,27 @@ def goto(mode="goto", no_output=False):
|
||||
def show_documentation():
|
||||
script = get_script()
|
||||
try:
|
||||
definitions = script.goto_definitions()
|
||||
except jedi.NotFoundError:
|
||||
definitions = []
|
||||
names = script.help(*get_pos())
|
||||
except Exception:
|
||||
# print to stdout, will be in :messages
|
||||
definitions = []
|
||||
names = []
|
||||
print("Exception, this shouldn't happen.")
|
||||
print(traceback.format_exc())
|
||||
|
||||
if not definitions:
|
||||
if not names:
|
||||
echo_highlight('No documentation found for that.')
|
||||
vim.command('return')
|
||||
else:
|
||||
docs = ['Docstring for %s\n%s\n%s' % (d.desc_with_module, '=' * 40, d.docstring())
|
||||
if d.docstring() else '|No Docstring for %s|' % d for d in definitions]
|
||||
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')))
|
||||
@@ -365,9 +816,12 @@ def show_call_signatures(signatures=()):
|
||||
if int(vim_eval("has('conceal') && g:jedi#show_call_signatures")) == 0:
|
||||
return
|
||||
|
||||
if signatures == ():
|
||||
signatures = get_script().call_signatures()
|
||||
# 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
|
||||
@@ -375,6 +829,7 @@ def show_call_signatures(signatures=()):
|
||||
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
|
||||
@@ -389,13 +844,19 @@ def show_call_signatures(signatures=()):
|
||||
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]
|
||||
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
|
||||
@@ -528,8 +989,14 @@ def rename():
|
||||
vim_command('augroup END')
|
||||
|
||||
vim_command("let s:jedi_replace_orig = expand('<cword>')")
|
||||
line = vim_eval('getline(".")')
|
||||
vim_command('normal! diw')
|
||||
vim_command('startinsert')
|
||||
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.
|
||||
@@ -573,34 +1040,31 @@ def do_rename(replace, orig=None):
|
||||
saved_tab = int(vim_eval('tabpagenr()'))
|
||||
saved_win = int(vim_eval('winnr()'))
|
||||
|
||||
temp_rename = goto(mode="related_name", no_output=True)
|
||||
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: (x.module_path, x.line, x.column))
|
||||
key=lambda x: (str(x.module_path), x.line, x.column))
|
||||
buffers = set()
|
||||
for r in temp_rename:
|
||||
if r.in_builtin_module():
|
||||
continue
|
||||
|
||||
if os.path.abspath(vim.current.buffer.name) != r.module_path:
|
||||
assert r.module_path is not None
|
||||
result = new_buffer(r.module_path)
|
||||
module_path = r.module_path
|
||||
if os.path.abspath(vim.current.buffer.name) != str(module_path):
|
||||
assert module_path is not None
|
||||
result = new_buffer(module_path)
|
||||
if not result:
|
||||
echo_highlight("Jedi-vim: failed to create buffer window for {0}!".format(r.module_path))
|
||||
echo_highlight('Failed to create buffer window for %s!' % (
|
||||
module_path))
|
||||
continue
|
||||
|
||||
buffers.add(vim.current.buffer.name)
|
||||
|
||||
# Save view.
|
||||
saved_view = vim_eval('string(winsaveview())')
|
||||
|
||||
# Replace original word.
|
||||
vim.current.window.cursor = (r.line, r.column)
|
||||
vim_command('normal! c{0:d}l{1}'.format(len(orig), replace))
|
||||
|
||||
# Restore view.
|
||||
vim_command('call winrestview(%s)' % saved_view)
|
||||
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))
|
||||
@@ -616,35 +1080,25 @@ def do_rename(replace, orig=None):
|
||||
@_check_jedi_availability(show_error=True)
|
||||
@catch_and_print_exceptions
|
||||
def py_import():
|
||||
# args are the same as for the :edit command
|
||||
args = shsplit(vim.eval('a:args'))
|
||||
import_path = args.pop()
|
||||
text = 'import %s' % import_path
|
||||
scr = jedi.Script(text, 1, len(text), '')
|
||||
try:
|
||||
completion = scr.goto_assignments()[0]
|
||||
except IndexError:
|
||||
echo_highlight('Cannot find %s in sys.path!' % import_path)
|
||||
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:
|
||||
if completion.in_builtin_module():
|
||||
echo_highlight('%s is a builtin module.' % import_path)
|
||||
else:
|
||||
cmd_args = ' '.join([a.replace(' ', '\\ ') for a in args])
|
||||
new_buffer(completion.module_path, cmd_args)
|
||||
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')
|
||||
try:
|
||||
import jedi
|
||||
except ImportError:
|
||||
if jedi is None:
|
||||
print('Pyimport completion requires jedi module: https://github.com/davidhalter/jedi')
|
||||
comps = []
|
||||
else:
|
||||
text = 'import %s' % argl
|
||||
script = jedi.Script(text, 1, len(text), '')
|
||||
comps = ['%s%s' % (argl, c.complete) for c in script.completions()]
|
||||
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))
|
||||
|
||||
|
||||
|
||||
@@ -1,44 +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():
|
||||
import vim
|
||||
|
||||
def echo(msg):
|
||||
vim.command('echo {0}'.format(msg))
|
||||
|
||||
echo("printf(' - sys.version: `%s`', {0!r})".format(
|
||||
echo(' - global sys.executable: `{0}`'.format(sys.executable))
|
||||
echo(' - global sys.version: `{0}`'.format(
|
||||
', '.join([x.strip()
|
||||
for x in __import__('sys').version.split('\n')])))
|
||||
echo("printf(' - site module: `%s`', {0!r})".format(
|
||||
__import__('site').__file__))
|
||||
for x in sys.version.split('\n')])))
|
||||
echo(' - global site module: `{0}`'.format(__import__('site').__file__))
|
||||
|
||||
try:
|
||||
import jedi_vim
|
||||
except Exception as e:
|
||||
echo("printf('ERROR: jedi_vim is not available: %s: %s', "
|
||||
"{0!r}, {1!r})".format(e.__class__.__name__, str(e)))
|
||||
except Exception:
|
||||
echo_error('ERROR: could not import jedi_vim: {0}'.format(
|
||||
format_exc_info()))
|
||||
return
|
||||
|
||||
try:
|
||||
if jedi_vim.jedi is None:
|
||||
echo("'ERROR: could not import the \"jedi\" Python module.'")
|
||||
echo("printf(' The error was: %s', {0!r})".format(
|
||||
getattr(jedi_vim, "jedi_import_error", "UNKNOWN")))
|
||||
if jedi_vim.jedi is None:
|
||||
if hasattr(jedi_vim, 'jedi_import_error'):
|
||||
error_msg = format_exc_info(jedi_vim.jedi_import_error)
|
||||
else:
|
||||
echo("printf('Jedi path: `%s`', {0!r})".format(
|
||||
jedi_vim.jedi.__file__))
|
||||
echo("printf(' - version: %s', {0!r})".format(
|
||||
jedi_vim.jedi.__version__))
|
||||
echo("' - sys_path:'")
|
||||
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
|
||||
for p in sys_path:
|
||||
echo("printf(' - `%s`', {0!r})".format(p))
|
||||
except Exception as e:
|
||||
echo("printf('There was an error accessing jedi_vim.jedi: %s', "
|
||||
"{0!r})".format(e))
|
||||
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,
|
||||
))
|
||||
|
||||
Submodule pythonx/parso updated: 2ca629a2f6...ef90bba3b3
5
setup.cfg
Normal file
5
setup.cfg
Normal file
@@ -0,0 +1,5 @@
|
||||
[tool:pytest]
|
||||
testpaths = test
|
||||
|
||||
[flake8]
|
||||
max-line-length = 100
|
||||
@@ -1,71 +0,0 @@
|
||||
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 '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
|
||||
|
||||
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'
|
||||
normal a().filenaX
|
||||
Expect getline('.') == 'IndentationError().filename'
|
||||
end
|
||||
|
||||
it 'multi complete'
|
||||
normal oImpXErrX()
|
||||
Expect getline('.') == 'ImportError()'
|
||||
end
|
||||
|
||||
it 'cycling through entries popup_select_first=0'
|
||||
let g:jedi#popup_select_first = 0
|
||||
execute "normal oraise impX\<C-n>"
|
||||
" It looks like this is currently not working properly.
|
||||
"Expect getline('.') == 'raise ImportError'
|
||||
end
|
||||
|
||||
it 'cycling through entries popup_select_first=1'
|
||||
execute "normal oraise impX\<C-n>"
|
||||
Expect getline('.') == 'raise ImportWarning'
|
||||
end
|
||||
|
||||
it 'longest'
|
||||
" -longest completes the first one
|
||||
set completeopt -=longest
|
||||
execute "normal oraise baseX"
|
||||
Expect getline('.') == 'raise BaseException'
|
||||
set completeopt +=longest
|
||||
end
|
||||
|
||||
it 'dot_open'
|
||||
end
|
||||
end
|
||||
|
||||
" vim: et:ts=4:sw=4
|
||||
65
test/test_integration.py
Normal file
65
test/test_integration.py
Normal file
@@ -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)
|
||||
8
test/vimrc
Normal file
8
test/vimrc
Normal file
@@ -0,0 +1,8 @@
|
||||
" Minimal vimrc to use jedi-vim.
|
||||
"
|
||||
" Not used anywhere yet, but allows for easy testing.
|
||||
let script_dir = fnamemodify(expand('<sfile>'), ':h:h')
|
||||
let &runtimepath = script_dir.','.&runtimepath.','.script_dir.'/after'
|
||||
|
||||
syntax on
|
||||
filetype plugin indent on
|
||||
29
test/vspec/choose-venv.vim
Normal file
29
test/vspec/choose-venv.vim
Normal file
@@ -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 \<CR>"
|
||||
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
|
||||
131
test/vspec/completions.vim
Normal file
131
test/vspec/completions.vim
Normal file
@@ -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\<C-n>"
|
||||
|
||||
Expect getline('.') == 'raise ImportError'
|
||||
set completeopt-=longest
|
||||
end
|
||||
|
||||
it 'cycling through entries popup_select_first=1'
|
||||
execute "normal oraise impX\<C-n>"
|
||||
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 <Down>. This is not the case with Vim.
|
||||
if has('nvim')
|
||||
execute "normal oraise impX\<C-n>"
|
||||
Expect getline('.') == 'raise ImportWarning'
|
||||
|
||||
execute "normal oraise impX\<C-n>\<C-n>"
|
||||
Expect getline('.') == 'raise imp'
|
||||
else
|
||||
execute "normal oraise impX\<C-n>"
|
||||
Expect getline('.') == 'raise ImportError'
|
||||
|
||||
execute "normal oraise impX\<C-n>\<C-n>"
|
||||
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
|
||||
@@ -4,12 +4,11 @@ source plugin/jedi.vim
|
||||
|
||||
describe 'completions_disabled'
|
||||
before
|
||||
new
|
||||
set filetype=python
|
||||
end
|
||||
|
||||
after
|
||||
bd!
|
||||
try | %bwipeout! | catch | endtry
|
||||
end
|
||||
|
||||
it 'typing'
|
||||
@@ -6,16 +6,19 @@ describe 'documentation docstrings'
|
||||
end
|
||||
|
||||
after
|
||||
bd!
|
||||
bd!
|
||||
try | %bwipeout! | catch | endtry
|
||||
end
|
||||
|
||||
it 'simple'
|
||||
Expect maparg('K') == ':call jedi#show_documentation()<CR>'
|
||||
put = 'ImportError'
|
||||
normal GK
|
||||
Expect bufname('%') == "__doc__"
|
||||
Expect &filetype == 'rst'
|
||||
let content = join(getline(1,'$'), "\n")
|
||||
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('%') == ''
|
||||
@@ -1,10 +1,10 @@
|
||||
let mapleader = '\'
|
||||
source plugin/jedi.vim
|
||||
source test/utils.vim
|
||||
source test/_utils.vim
|
||||
|
||||
describe 'goto simple'
|
||||
describe 'goto simple:'
|
||||
before
|
||||
new " open a new split
|
||||
new
|
||||
set filetype=python
|
||||
put =[
|
||||
\ 'def a(): pass',
|
||||
@@ -22,77 +22,57 @@ describe 'goto simple'
|
||||
|
||||
it 'goto definitions'
|
||||
normal \d
|
||||
Expect line('.') == 1
|
||||
Expect col('.') == 5
|
||||
Expect line('.') == 2
|
||||
Expect col('.') == 1
|
||||
end
|
||||
|
||||
it 'goto assignments'
|
||||
silent normal \g
|
||||
normal \g
|
||||
Expect line('.') == 2
|
||||
Expect col('.') == 1
|
||||
|
||||
" cursor before `=` means that it stays there.
|
||||
silent normal \g
|
||||
normal \g
|
||||
Expect line('.') == 2
|
||||
Expect col('.') == 1
|
||||
|
||||
" going to the last line changes it.
|
||||
normal! $
|
||||
silent normal \g
|
||||
normal \g
|
||||
Expect line('.') == 1
|
||||
Expect col('.') == 5
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
describe 'goto with tabs'
|
||||
describe 'goto with tabs:'
|
||||
before
|
||||
set filetype=python
|
||||
let g:jedi#use_tabs_not_buffers = 1
|
||||
end
|
||||
|
||||
after
|
||||
bd!
|
||||
bd!
|
||||
try | %bwipeout! | catch | endtry
|
||||
end
|
||||
|
||||
it 'follow import'
|
||||
put = ['import subprocess', 'subprocess']
|
||||
silent normal G\g
|
||||
normal G\g
|
||||
Expect getline('.') == 'import subprocess'
|
||||
Expect line('.') == 2
|
||||
Expect col('.') == 8
|
||||
|
||||
silent normal G\d
|
||||
normal G\d
|
||||
Expect CurrentBufferIsModule('subprocess') == 1
|
||||
Expect line('.') == 1
|
||||
Expect col('.') == 1
|
||||
Expect tabpagenr('$') == 2
|
||||
Expect winnr('$') == 1
|
||||
tabprevious
|
||||
bwipe
|
||||
|
||||
Expect tabpagenr('$') == 1
|
||||
Expect bufname('%') == ''
|
||||
end
|
||||
|
||||
it 'multi definitions'
|
||||
" This used to behave differently. Now we don't have any real multi
|
||||
" definitions.
|
||||
|
||||
" put = ['import tokenize']
|
||||
" silent normal G$\d
|
||||
" Expect CurrentBufferIsModule('tokenize') == 1
|
||||
" Expect CurrentBufferIsModule('token') == 0
|
||||
" execute "normal \<CR>"
|
||||
" Expect tabpagenr('$') == 2
|
||||
" Expect winnr('$') == 1
|
||||
" Expect CurrentBufferIsModule('token') == 1
|
||||
|
||||
" bd
|
||||
" silent normal G$\d
|
||||
" execute "normal j\<CR>"
|
||||
" Expect tabpagenr('$') == 2
|
||||
" Expect winnr('$') == 1
|
||||
" Expect CurrentBufferIsModule('tokenize') == 1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -103,8 +83,7 @@ describe 'goto with buffers'
|
||||
end
|
||||
|
||||
after
|
||||
bd!
|
||||
bd!
|
||||
try | %bwipeout! | catch | endtry
|
||||
set nohidden
|
||||
end
|
||||
|
||||
@@ -112,7 +91,7 @@ describe 'goto with buffers'
|
||||
put = ['import os']
|
||||
normal G$
|
||||
call jedi#goto_assignments()
|
||||
PythonJedi jedi_vim.goto()
|
||||
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.
|
||||
@@ -124,48 +103,29 @@ describe 'goto with buffers'
|
||||
Expect line('.') == 1
|
||||
Expect col('.') == 1
|
||||
end
|
||||
|
||||
it 'multi definitions'
|
||||
" set hidden
|
||||
" put = ['import tokenize']
|
||||
" silent normal G$\d
|
||||
" Expect CurrentBufferIsModule('tokenize') == 0
|
||||
" Expect CurrentBufferIsModule('token') == 0
|
||||
" execute "normal \<CR>"
|
||||
" Expect tabpagenr('$') == 1
|
||||
" Expect winnr('$') == 1
|
||||
" Expect CurrentBufferIsModule('token') == 1
|
||||
|
||||
" bd
|
||||
" silent normal G$\d
|
||||
" execute "normal j\<CR>"
|
||||
" Expect tabpagenr('$') == 1
|
||||
" Expect winnr('$') == 1
|
||||
" Expect CurrentBufferIsModule('tokenize') == 1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
describe 'goto with splits'
|
||||
before
|
||||
enew!
|
||||
set filetype=python
|
||||
let g:jedi#use_splits_not_buffers = 'left'
|
||||
end
|
||||
|
||||
after
|
||||
bd!
|
||||
bd!
|
||||
try | %bwipeout! | catch | endtry
|
||||
end
|
||||
|
||||
it 'follow import'
|
||||
put = ['import subprocess', 'subprocess']
|
||||
silent normal G\g
|
||||
normal G\g
|
||||
Expect getline('.') == 'import subprocess'
|
||||
Expect line('.') == 2
|
||||
Expect col('.') == 8
|
||||
|
||||
silent normal G\d
|
||||
normal G\d
|
||||
Expect CurrentBufferIsModule('subprocess') == 1
|
||||
Expect line('.') == 1
|
||||
Expect col('.') == 1
|
||||
@@ -179,6 +139,7 @@ end
|
||||
|
||||
describe 'goto wildignore'
|
||||
before
|
||||
enew!
|
||||
set filetype=python
|
||||
set wildignore=*,with\ spaces,*.pyc
|
||||
set hidden
|
||||
@@ -189,12 +150,11 @@ describe 'goto wildignore'
|
||||
|
||||
put = ['from subprocess import Popen', 'Popen']
|
||||
Expect CurrentBufferIsModule('subprocess') == 0
|
||||
silent normal G
|
||||
normal G
|
||||
end
|
||||
|
||||
after
|
||||
bd!
|
||||
bd!
|
||||
try | %bwipeout! | catch | endtry
|
||||
set wildignore&vim
|
||||
end
|
||||
|
||||
13
test/vspec/jedi_debug_info.vim
Normal file
13
test/vspec/jedi_debug_info.vim
Normal file
@@ -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] == '</details>'
|
||||
end
|
||||
end
|
||||
|
||||
" vim: et:ts=4:sw=4
|
||||
@@ -1,14 +1,15 @@
|
||||
source plugin/jedi.vim
|
||||
source test/utils.vim
|
||||
source test/_utils.vim
|
||||
|
||||
describe 'pyimport'
|
||||
before
|
||||
let g:jedi#use_tabs_not_buffers = 1
|
||||
let g:jedi#project_path = 'autoload'
|
||||
end
|
||||
|
||||
after
|
||||
bd!
|
||||
bd!
|
||||
try | %bwipeout! | catch | endtry
|
||||
unlet g:jedi#project_path
|
||||
end
|
||||
|
||||
it 'open_tab'
|
||||
@@ -27,10 +28,7 @@ describe 'pyimport'
|
||||
|
||||
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('zip', 0, 0)
|
||||
" Sometimes zipapp is in there sometimes not, depends on Python
|
||||
" version.
|
||||
let g:comp = substitute(g:comp, '^zipapp\n', '', '')
|
||||
Expect g:comp == "zipfile\nzipimport"
|
||||
let g:comp = jedi#py_import_completions('sre_', 0, 0)
|
||||
Expect g:comp == "sre_compile\nsre_constants\nsre_parse"
|
||||
end
|
||||
end
|
||||
@@ -2,22 +2,19 @@ source plugin/jedi.vim
|
||||
|
||||
describe 'signatures'
|
||||
before
|
||||
enew
|
||||
set filetype=python
|
||||
end
|
||||
|
||||
after
|
||||
bd!
|
||||
bd!
|
||||
try | %bwipeout! | catch | endtry
|
||||
end
|
||||
|
||||
it 'simple'
|
||||
normal odef xyz(number): return
|
||||
normal o
|
||||
normal oxyz(
|
||||
normal G$
|
||||
" equals doautocmd CursorMovedI
|
||||
Python jedi_vim.show_call_signatures()
|
||||
|
||||
normal oxyz()
|
||||
doautocmd CursorHoldI
|
||||
Expect getline(3) == '?!?jedi=0, ?!? (*_*number*_*) ?!?jedi?!?'
|
||||
|
||||
doautocmd InsertLeave
|
||||
@@ -37,28 +34,44 @@ describe 'signatures'
|
||||
autocmd jedi_call_signatures * <buffer>
|
||||
redir END
|
||||
Expect autocmds =~# 'jedi_call_signatures'
|
||||
bd!
|
||||
end
|
||||
|
||||
it 'simple after CursorHoldI with only parenthesis'
|
||||
noautocmd normal o
|
||||
doautocmd CursorHoldI
|
||||
noautocmd normal istr(
|
||||
noautocmd normal istaticmethod()
|
||||
doautocmd CursorHoldI
|
||||
Expect getline(1) == '?!?jedi=0, ?!? (*_*object*_*) ?!?jedi?!?'
|
||||
Expect getline(1) == '?!?jedi=0, ?!? (*_*f: Callable[..., Any]*_*) ?!?jedi?!?'
|
||||
end
|
||||
|
||||
it 'highlights correct argument'
|
||||
noautocmd normal o
|
||||
doautocmd CursorHoldI
|
||||
noautocmd normal iprint(42, sep="X", )
|
||||
" Move to "=" - hightlights "sep=...".
|
||||
noautocmd normal 5h
|
||||
doautocmd CursorHoldI
|
||||
Expect getline(1) =~# '\V\^?!?jedi=0, ?!? (*values: object, *_*sep: Optional[Text]=...*_*'
|
||||
" Move left to "=" - hightlights first argument ("values").
|
||||
" NOTE: it is arguable that maybe "sep=..." should be highlighted
|
||||
" still, but this tests for the cache to be "busted", and that
|
||||
" fresh results are retrieved from Jedi.
|
||||
noautocmd normal h
|
||||
doautocmd CursorHoldI
|
||||
Expect getline(1) =~# '\V\^?!?jedi=0, ?!? (*_**values: object*_*, sep: Optional[Text]=...,'
|
||||
end
|
||||
|
||||
it 'no signature'
|
||||
normal ostr
|
||||
Python jedi_vim.show_call_signatures()
|
||||
exe 'normal ostr '
|
||||
python3 jedi_vim.show_call_signatures()
|
||||
Expect getline(1, '$') == ['', 'str ']
|
||||
end
|
||||
|
||||
it 'signatures disabled'
|
||||
let g:jedi#show_call_signatures = 0
|
||||
|
||||
normal ostr(
|
||||
Python jedi_vim.show_call_signatures()
|
||||
exe 'normal ostr( '
|
||||
python3 jedi_vim.show_call_signatures()
|
||||
Expect getline(1, '$') == ['', 'str( ']
|
||||
|
||||
let g:jedi#show_call_signatures = 1
|
||||
@@ -68,21 +81,21 @@ describe 'signatures'
|
||||
let g:jedi#show_call_signatures = 2
|
||||
call jedi#configure_call_signatures()
|
||||
|
||||
normal ostr(
|
||||
exe 'normal ostaticmethod( '
|
||||
redir => msg
|
||||
Python jedi_vim.show_call_signatures()
|
||||
python3 jedi_vim.show_call_signatures()
|
||||
redir END
|
||||
Expect msg == "\nstr(object)"
|
||||
Expect msg == "\nstaticmethod(f: Callable[..., Any])"
|
||||
|
||||
redir => msg
|
||||
doautocmd InsertLeave
|
||||
doautocmd InsertLeave
|
||||
redir END
|
||||
Expect msg == "\n"
|
||||
|
||||
normal Sdef foo(a, b): pass
|
||||
normal ofoo(a, b, c,
|
||||
exe 'normal ofoo(a, b, c, '
|
||||
redir => msg
|
||||
Python jedi_vim.show_call_signatures()
|
||||
python3 jedi_vim.show_call_signatures()
|
||||
redir END
|
||||
Expect msg == "\nfoo(a, b)"
|
||||
end
|
||||
@@ -93,30 +106,30 @@ describe 'signatures'
|
||||
|
||||
function! Signature()
|
||||
redir => msg
|
||||
Python jedi_vim.show_call_signatures()
|
||||
python3 jedi_vim.show_call_signatures()
|
||||
redir END
|
||||
return msg
|
||||
endfunction
|
||||
|
||||
let funcname = repeat('a', &columns - 30)
|
||||
let funcname = repeat('a', &columns - (30 + (&ruler ? 18 : 0)))
|
||||
put = 'def '.funcname.'(arg1, arg2, arg3, a, b, c):'
|
||||
put = ' pass'
|
||||
execute "normal o".funcname."( "
|
||||
execute "normal o\<BS>".funcname."( "
|
||||
Expect Signature() == "\n".funcname."(arg1, …)"
|
||||
|
||||
normal sarg1,
|
||||
exe 'normal sarg1, '
|
||||
Expect Signature() == "\n".funcname."(…, arg2, …)"
|
||||
|
||||
normal sarg2, arg3,
|
||||
exe 'normal sarg2, arg3, '
|
||||
Expect Signature() == "\n".funcname."(…, a, b, c)"
|
||||
|
||||
normal sa, b,
|
||||
exe 'normal sa, b, '
|
||||
Expect Signature() == "\n".funcname."(…, c)"
|
||||
|
||||
g/^/d
|
||||
put = 'def '.funcname.'('.repeat('b', 20).', arg2):'
|
||||
put = ' pass'
|
||||
execute "normal o".funcname."( "
|
||||
execute "normal o\<BS>".funcname."( "
|
||||
Expect Signature() == "\n".funcname."(…)"
|
||||
end
|
||||
|
||||
@@ -124,9 +137,9 @@ describe 'signatures'
|
||||
let g:jedi#show_call_signatures = 2
|
||||
call jedi#configure_call_signatures()
|
||||
|
||||
normal ostr
|
||||
exe 'normal ostr '
|
||||
redir => msg
|
||||
Python jedi_vim.show_call_signatures()
|
||||
python3 jedi_vim.show_call_signatures()
|
||||
redir END
|
||||
Expect msg == "\n"
|
||||
end
|
||||
@@ -1,2 +0,0 @@
|
||||
def test_integration(case, monkeypatch, pytestconfig):
|
||||
case.run()
|
||||
Reference in New Issue
Block a user