mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-01-23 07:00:04 +08:00
pref(bundle): update bundle deoplete
This commit is contained in:
parent
023c48c740
commit
b730079c88
@ -22,3 +22,4 @@ In `bundle/` directory, there are two kinds of plugins: forked plugins without c
|
||||
- [deoplete-lsp](https://github.com/deoplete-plugins/deoplete-lsp/tree/6299a22bedfb4f814d95cb0010291501472f8fd0)
|
||||
- [nvim-cmp](https://github.com/hrsh7th/nvim-cmp/tree/3192a0c57837c1ec5bf298e4f3ec984c7d2d60c0)
|
||||
- [coc-neosnippet](https://github.com/notomo/cmp-neosnippet/tree/2d14526af3f02dcea738b4cea520e6ce55c09979)
|
||||
- [deoplete](https://github.com/Shougo/deoplete.nvim/tree/1c40f648d2b00e70beb4c473b7c0e32b633bd9ae)
|
||||
|
12
bundle/deoplete.nvim/.github/FUNDING.yml
vendored
Normal file
12
bundle/deoplete.nvim/.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: Shougo # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
64
bundle/deoplete.nvim/.github/workflows/workflow.yaml
vendored
Normal file
64
bundle/deoplete.nvim/.github/workflows/workflow.yaml
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
name: Lint, Test & Coverage
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Python ${{ matrix.python-version }} - Neovim (${{ matrix.build }})
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
python-version:
|
||||
- 3.7
|
||||
- 3.8
|
||||
- 3.9
|
||||
build:
|
||||
- nightly
|
||||
- stable
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
if [ -f test/requirements.txt ]; then pip install -r test/requirements.txt; fi
|
||||
- name: Initialize Neovim
|
||||
uses: rhysd/action-setup-vim@v1
|
||||
id: vim
|
||||
with:
|
||||
neovim: true
|
||||
version: ${{ matrix.build }}
|
||||
- name: Clone vim-themis
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: thinca/vim-themis
|
||||
path: vim-themis
|
||||
- name: Run Lint & Test
|
||||
run: make --keep-going THEMIS_VIM=${{ steps.vim.outputs.executable }} test lint
|
||||
|
||||
coverage:
|
||||
name: Generate Codecav Report
|
||||
|
||||
needs: test
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
if [ -f test/requirements.txt ]; then pip install -r test/requirements.txt; fi
|
||||
- name: Generate Report
|
||||
run: pytest --cov=./rplugin/python3/deoplete --cov=./test --cov-report=xml
|
||||
- uses: codecov/codecov-action@v1
|
||||
with:
|
||||
files: ./coverage.xml
|
||||
functionalities: coveragepy, fix, gcov, search, xcode
|
@ -1,22 +0,0 @@
|
||||
dist: xenial
|
||||
|
||||
language: python
|
||||
|
||||
python:
|
||||
- 3.6
|
||||
- 3.7
|
||||
|
||||
install:
|
||||
- eval "$(curl -Ss https://raw.githubusercontent.com/neovim/bot-ci/master/scripts/travis-setup.sh) nightly-x64"
|
||||
- make install
|
||||
|
||||
env:
|
||||
global:
|
||||
- PATH=$HOME/neovim/bin:$PATH
|
||||
- PYTEST_ADDOPTS=--cov rplugin/python3/deoplete
|
||||
|
||||
script:
|
||||
- make --keep-going test lint
|
||||
- coverage report -m --skip-covered
|
||||
- coverage xml
|
||||
- bash <(curl -s https://codecov.io/bash) -X gcov -X coveragepy -X fix -X search -X xcode -f coverage.xml
|
@ -2,10 +2,19 @@
|
||||
|
||||
> Dark powered asynchronous completion framework for neovim/Vim8
|
||||
|
||||
[![Build Status](https://travis-ci.org/Shougo/deoplete.nvim.svg?branch=master)](https://travis-ci.org/Shougo/deoplete.nvim)
|
||||
**Note**: The development of this plugin is finished. Accepts minor patches and
|
||||
issues but no new features.
|
||||
[ddc.vim](https://github.com/Shougo/ddc.vim) is the next generation auto
|
||||
completion plugin. Consider migrating to it.
|
||||
|
||||
[![Join the chat at https://gitter.im/Shougo/deoplete.nvim](https://badges.gitter.im/Shougo/deoplete.nvim.svg)](https://gitter.im/Shougo/deoplete.nvim?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[![Doc](https://img.shields.io/badge/doc-%3Ah%20deoplete-orange.svg)](doc/deoplete.txt)
|
||||
|
||||
Please read [help](doc/deoplete.txt) for details.
|
||||
|
||||
Note: If you need to understand what's different between deoplete and other
|
||||
similar plugins, please read "deoplete-faq" section in the documentation.
|
||||
|
||||
Deoplete is the abbreviation of "dark powered neo-completion". It
|
||||
provides an extensible and asynchronous completion framework for
|
||||
neovim/Vim8.
|
||||
@ -26,7 +35,7 @@ Here are some [completion sources](https://github.com/Shougo/deoplete.nvim/wiki/
|
||||
## Install
|
||||
|
||||
**Note:** deoplete requires Neovim (0.3.0+ and of course, **latest** is
|
||||
recommended) or Vim8 with Python 3.6.1+ and timers enabled. See
|
||||
recommended) or Vim8.1 with Python 3.6.1+ and timers enabled. See
|
||||
[requirements](#requirements) if you aren't sure whether you have this.
|
||||
|
||||
Note: deoplete requires msgpack package 1.0.0+.
|
||||
@ -75,7 +84,8 @@ For manual installation(not recommended)
|
||||
|
||||
deoplete requires Neovim or Vim8 with `if_python3`.
|
||||
|
||||
If `:echo has("python3")` returns `1`, then you have python 3 support; otherwise, see below.
|
||||
If `:echo has("python3")` returns `1`, then you have python 3 support;
|
||||
otherwise, see below.
|
||||
|
||||
You can enable Python3 interface with pip:
|
||||
|
||||
@ -157,3 +167,5 @@ Deoplete for JavaScript
|
||||
![Rust using rls](https://user-images.githubusercontent.com/1750795/38780764-8524b0b8-40a9-11e8-91bc-6e4148c398a3.png)
|
||||
|
||||
![Ruby dictionary completion](https://user-images.githubusercontent.com/1314340/44786516-5bb57a00-abcf-11e8-8687-492fa5f9f905.gif)
|
||||
|
||||
![LanguageClient-neovim integration](https://user-images.githubusercontent.com/4245199/87716288-efd25f80-c7ae-11ea-8080-334d155b3155.png)
|
||||
|
@ -72,7 +72,6 @@ function! deoplete#close_popup() abort
|
||||
return pumvisible() ? "\<C-y>" : ''
|
||||
endfunction
|
||||
function! deoplete#smart_close_popup() abort
|
||||
call deoplete#handler#_skip_next_completion()
|
||||
return pumvisible() ? "\<C-e>" : ''
|
||||
endfunction
|
||||
function! deoplete#cancel_popup() abort
|
||||
@ -88,3 +87,7 @@ endfunction
|
||||
function! deoplete#complete_common_string() abort
|
||||
return deoplete#mapping#_complete_common_string()
|
||||
endfunction
|
||||
function! deoplete#can_complete() abort
|
||||
return !empty(get(get(g:, 'deoplete#_context', {}), 'candidates', []))
|
||||
\ && deoplete#mapping#_can_complete()
|
||||
endfunction
|
||||
|
@ -18,10 +18,10 @@ function! deoplete#custom#_init() abort
|
||||
let s:cached.source_vars = {}
|
||||
endfunction
|
||||
function! deoplete#custom#_init_buffer() abort
|
||||
let b:custom = {}
|
||||
let b:custom.option = {}
|
||||
let b:custom.source_vars = {}
|
||||
let b:custom.filter = {}
|
||||
let b:deoplete_custom = {}
|
||||
let b:deoplete_custom.option = {}
|
||||
let b:deoplete_custom.source_vars = {}
|
||||
let b:deoplete_custom.filter = {}
|
||||
endfunction
|
||||
|
||||
function! deoplete#custom#_update_cache() abort
|
||||
@ -65,11 +65,11 @@ function! deoplete#custom#_get() abort
|
||||
return s:custom
|
||||
endfunction
|
||||
function! deoplete#custom#_get_buffer() abort
|
||||
if !exists('b:custom')
|
||||
if !exists('b:deoplete_custom')
|
||||
call deoplete#custom#_init_buffer()
|
||||
endif
|
||||
|
||||
return b:custom
|
||||
return b:deoplete_custom
|
||||
endfunction
|
||||
|
||||
function! deoplete#custom#_get_source(source_name) abort
|
||||
@ -92,8 +92,14 @@ function! deoplete#custom#_get_filetype_option(name, filetype, default) abort
|
||||
endif
|
||||
|
||||
let option = s:cached.option[a:name]
|
||||
let filetype = has_key(option, a:filetype) ? a:filetype : '_'
|
||||
return get(option, filetype, a:default)
|
||||
" Check filetype -> a.b filetype -> '_'
|
||||
for filetype in [a:filetype] + split(a:filetype, '\.') + ['_']
|
||||
if has_key(option, filetype)
|
||||
return option[filetype]
|
||||
endif
|
||||
endfor
|
||||
|
||||
return a:default
|
||||
endfunction
|
||||
function! deoplete#custom#_get_source_vars(name) abort
|
||||
return get(s:cached.source_vars, a:name, {})
|
||||
|
@ -14,7 +14,7 @@ function! deoplete#handler#_init() abort
|
||||
for event in [
|
||||
\ 'InsertEnter', 'InsertLeave',
|
||||
\ 'BufReadPost', 'BufWritePost',
|
||||
\ 'VimLeavePre',
|
||||
\ 'VimLeavePre', 'FileType',
|
||||
\ ]
|
||||
call s:define_on_event(event)
|
||||
endfor
|
||||
@ -26,11 +26,7 @@ function! deoplete#handler#_init() abort
|
||||
call s:define_completion_via_timer('InsertEnter')
|
||||
endif
|
||||
if deoplete#custom#_get_option('refresh_always')
|
||||
if exists('##TextChangedP')
|
||||
call s:define_completion_via_timer('TextChangedP')
|
||||
else
|
||||
call s:define_completion_via_timer('InsertCharPre')
|
||||
endif
|
||||
call s:define_completion_via_timer('TextChangedP')
|
||||
endif
|
||||
|
||||
" Note: Vim 8 GUI(MacVim and Win32) is broken
|
||||
@ -51,11 +47,7 @@ function! deoplete#handler#_do_complete() abort
|
||||
let context = g:deoplete#_context
|
||||
let event = get(context, 'event', '')
|
||||
if s:is_exiting() || v:insertmode !=# 'i' || s:check_input_method()
|
||||
return
|
||||
endif
|
||||
|
||||
if !has_key(context, 'candidates')
|
||||
\ || deoplete#util#get_input(context.event) !=# context.input
|
||||
\ || !has_key(context, 'candidates')
|
||||
return
|
||||
endif
|
||||
|
||||
@ -65,6 +57,11 @@ function! deoplete#handler#_do_complete() abort
|
||||
let prev.candidates = context.candidates
|
||||
let prev.complete_position = context.complete_position
|
||||
let prev.linenr = line('.')
|
||||
let prev.time = context.time
|
||||
|
||||
if context.event ==# 'Manual'
|
||||
let context.event = ''
|
||||
endif
|
||||
|
||||
let auto_popup = deoplete#custom#_get_option(
|
||||
\ 'auto_complete_popup') !=# 'manual'
|
||||
@ -74,13 +71,10 @@ function! deoplete#handler#_do_complete() abort
|
||||
let auto_popup = v:true
|
||||
endif
|
||||
|
||||
if context.event ==# 'Manual'
|
||||
let context.event = ''
|
||||
elseif !exists('g:deoplete#_saved_completeopt') && auto_popup
|
||||
call deoplete#mapping#_set_completeopt()
|
||||
endif
|
||||
|
||||
if auto_popup
|
||||
" Note: completeopt must be changed before complete() and feedkeys()
|
||||
call deoplete#mapping#_set_completeopt(g:deoplete#_context.is_async)
|
||||
|
||||
call feedkeys("\<Plug>_", 'i')
|
||||
endif
|
||||
endfunction
|
||||
@ -108,16 +102,8 @@ function! deoplete#handler#_check_omnifunc(context) abort
|
||||
let prev.input = a:context.input
|
||||
let prev.candidates = []
|
||||
|
||||
if &completeopt =~# 'noselect'
|
||||
call deoplete#mapping#_set_completeopt()
|
||||
call feedkeys("\<C-x>\<C-o>", 'in')
|
||||
else
|
||||
call deoplete#util#print_error(
|
||||
\ 'omni_patterns feature is disabled.')
|
||||
call deoplete#util#print_error(
|
||||
\ 'You need to set "noselect" in completeopt option.')
|
||||
endif
|
||||
return 1
|
||||
call deoplete#mapping#_set_completeopt(v:true)
|
||||
call feedkeys("\<C-x>\<C-o>", 'in')
|
||||
endif
|
||||
endfor
|
||||
endfor
|
||||
@ -145,7 +131,7 @@ function! s:completion_timer_stop() abort
|
||||
unlet s:completion_timer
|
||||
endfunction
|
||||
|
||||
function! s:check_prev_completion(event) abort
|
||||
function! deoplete#handler#_check_prev_completion(event) abort
|
||||
let prev = g:deoplete#_prev_completion
|
||||
if a:event ==# 'Async' || a:event ==# 'Update' || mode() !=# 'i'
|
||||
\ || empty(get(prev, 'candidates', []))
|
||||
@ -160,8 +146,6 @@ function! s:check_prev_completion(event) abort
|
||||
return
|
||||
endif
|
||||
|
||||
call deoplete#mapping#_set_completeopt()
|
||||
|
||||
let mode = deoplete#custom#_get_option('prev_completion_mode')
|
||||
let candidates = copy(prev.candidates)
|
||||
|
||||
@ -169,9 +153,9 @@ function! s:check_prev_completion(event) abort
|
||||
let input = input[prev.complete_position :]
|
||||
let escaped_input = escape(input, '~\.^$[]*')
|
||||
let pattern = substitute(escaped_input, '\w', '\\w*\0', 'g')
|
||||
call filter(candidates, 'v:val.word =~? pattern')
|
||||
call filter(candidates, { _, val -> val.word =~? pattern })
|
||||
if mode ==# 'length'
|
||||
call filter(candidates, 'len(v:val.word) > len(input)')
|
||||
call filter(candidates, { _, val -> len(val.word) > len(input) })
|
||||
endif
|
||||
elseif mode ==# 'mirror'
|
||||
" pass
|
||||
@ -183,7 +167,7 @@ function! s:check_prev_completion(event) abort
|
||||
\ 'complete_position': prev.complete_position,
|
||||
\ 'candidates': candidates,
|
||||
\ }
|
||||
call feedkeys("\<Plug>+", 'i')
|
||||
return 1
|
||||
endfunction
|
||||
|
||||
function! deoplete#handler#_async_timer_start() abort
|
||||
@ -198,12 +182,26 @@ endfunction
|
||||
function! deoplete#handler#_completion_begin(event) abort
|
||||
call deoplete#custom#_update_cache()
|
||||
|
||||
if s:is_skip(a:event)
|
||||
let auto_popup = deoplete#custom#_get_option(
|
||||
\ 'auto_complete_popup') !=# 'manual'
|
||||
let prev_input = get(g:deoplete#_context, 'input', '')
|
||||
let cur_input = deoplete#util#get_input(a:event)
|
||||
|
||||
let check_back_space = auto_popup
|
||||
\ && cur_input !=# prev_input
|
||||
\ && len(cur_input) + 1 ==# len(prev_input)
|
||||
\ && stridx(prev_input, cur_input) == 0
|
||||
let refresh_backspace = deoplete#custom#_get_option('refresh_backspace')
|
||||
|
||||
if s:is_skip(a:event) || (check_back_space && !refresh_backspace)
|
||||
let g:deoplete#_context.candidates = []
|
||||
let g:deoplete#_context.input = cur_input
|
||||
return
|
||||
endif
|
||||
|
||||
call s:check_prev_completion(a:event)
|
||||
if auto_popup && deoplete#handler#_check_prev_completion(a:event)
|
||||
call feedkeys("\<Plug>+", 'i')
|
||||
endif
|
||||
|
||||
if a:event !=# 'Update' && a:event !=# 'Async'
|
||||
call deoplete#init#_prev_completion()
|
||||
@ -211,6 +209,11 @@ function! deoplete#handler#_completion_begin(event) abort
|
||||
|
||||
call deoplete#util#rpcnotify(
|
||||
\ 'deoplete_auto_completion_begin', {'event': a:event})
|
||||
|
||||
" For <BS> popup flicker
|
||||
if check_back_space && empty(v:completed_item)
|
||||
call feedkeys("\<Plug>_", 'i')
|
||||
endif
|
||||
endfunction
|
||||
function! s:is_skip(event) abort
|
||||
if a:event ==# 'TextChangedP' && !empty(v:completed_item)
|
||||
@ -231,11 +234,19 @@ function! s:is_skip(event) abort
|
||||
return 1
|
||||
endif
|
||||
|
||||
" Check nofile buffers
|
||||
if &l:buftype =~# 'nofile' && bufname('%') !=# '[Command Line]'
|
||||
let nofile_complete_filetypes = deoplete#custom#_get_option(
|
||||
\ 'nofile_complete_filetypes')
|
||||
if index(nofile_complete_filetypes, &l:filetype) < 0
|
||||
return 1
|
||||
endif
|
||||
endif
|
||||
|
||||
let auto_complete = deoplete#custom#_get_option('auto_complete')
|
||||
|
||||
if &paste
|
||||
\ || (a:event !=# 'Manual' && a:event !=# 'Update' && !auto_complete)
|
||||
\ || (&l:completefunc !=# '' && &l:buftype =~# 'nofile')
|
||||
\ || v:insertmode !=# 'i'
|
||||
return 1
|
||||
endif
|
||||
@ -266,6 +277,11 @@ function! s:is_skip_prev_text(event) abort
|
||||
endfunction
|
||||
function! s:is_skip_text(event) abort
|
||||
let input = deoplete#util#get_input(a:event)
|
||||
if !has('nvim') && iconv(iconv(input, 'utf-8', 'utf-16'),
|
||||
\ 'utf-16', 'utf-8') !=# input
|
||||
" In Vim8, invalid bytes brokes nvim-yarp.
|
||||
return 1
|
||||
endif
|
||||
|
||||
let lastchar = matchstr(input, '.$')
|
||||
let skip_multibyte = deoplete#custom#_get_option('skip_multibyte')
|
||||
@ -280,12 +296,17 @@ function! s:is_skip_text(event) abort
|
||||
\ && displaywidth >= &l:textwidth
|
||||
if &l:formatoptions =~# '[ta]'
|
||||
\ || !empty(filter(deoplete#util#get_syn_names(),
|
||||
\ "v:val ==# 'Comment'"))
|
||||
\ { _, val -> val ==# 'Comment' }))
|
||||
\ || is_virtual
|
||||
return 1
|
||||
endif
|
||||
endif
|
||||
|
||||
if a:event =~# '^TextChanged' && s:matched_indentkeys(input) !=# ''
|
||||
call deoplete#util#indent_current_line()
|
||||
return 1
|
||||
endif
|
||||
|
||||
let skip_chars = deoplete#custom#_get_option('skip_chars')
|
||||
|
||||
return (a:event !=# 'Manual' && input !=# ''
|
||||
@ -294,6 +315,32 @@ endfunction
|
||||
function! s:check_input_method() abort
|
||||
return exists('*getimstatus') && getimstatus()
|
||||
endfunction
|
||||
function! s:matched_indentkeys(input) abort
|
||||
if &l:indentexpr ==# ''
|
||||
" Disable auto indent
|
||||
return ''
|
||||
endif
|
||||
|
||||
" Note: check the last word
|
||||
let checkstr = matchstr(a:input, '\w\+$')
|
||||
|
||||
for word in filter(map(split(&l:indentkeys, ','),
|
||||
\ { _, val -> matchstr(val, 'e\|=\zs.*') }),
|
||||
\ { _, val -> val !=# '' && val =~# '\h\w*' })
|
||||
|
||||
if word ==# 'e'
|
||||
let word = 'else'
|
||||
endif
|
||||
|
||||
let lastpos = len(a:input) - len(word)
|
||||
if checkstr ==# word || (word =~# '^\W\+$' &&
|
||||
\ lastpos >= 0 && strridx(a:input, word) == lastpos)
|
||||
return word
|
||||
endif
|
||||
endfor
|
||||
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
function! s:define_on_event(event) abort
|
||||
if !exists('##' . a:event)
|
||||
@ -325,11 +372,27 @@ endfunction
|
||||
|
||||
function! s:on_complete_done() abort
|
||||
if get(v:completed_item, 'word', '') ==# ''
|
||||
\ || !has_key(g:deoplete#_context, 'complete_str')
|
||||
return
|
||||
endif
|
||||
|
||||
call deoplete#handler#_skip_next_completion()
|
||||
|
||||
let max_used = 100
|
||||
let g:deoplete#_recently_used = insert(
|
||||
\ g:deoplete#_recently_used,
|
||||
\ tolower(v:completed_item.word),
|
||||
\ )
|
||||
let min_pattern_length = deoplete#custom#_get_option('min_pattern_length')
|
||||
if len(g:deoplete#_context['complete_str']) > min_pattern_length
|
||||
let g:deoplete#_recently_used = insert(
|
||||
\ g:deoplete#_recently_used,
|
||||
\ tolower(g:deoplete#_context['complete_str']),
|
||||
\ )
|
||||
endif
|
||||
let g:deoplete#_recently_used = deoplete#util#uniq(
|
||||
\ g:deoplete#_recently_used)[: max_used]
|
||||
|
||||
let user_data = get(v:completed_item, 'user_data', '')
|
||||
if type(user_data) !=# v:t_string || user_data ==# ''
|
||||
return
|
||||
|
@ -38,7 +38,7 @@ function! deoplete#init#_channel() abort
|
||||
return 1
|
||||
endif
|
||||
|
||||
let python3 = get(g:, 'python3_host_prog', 'python3')
|
||||
let python3 = expand(get(g:, 'python3_host_prog', 'python3'), 1)
|
||||
if !executable(python3)
|
||||
call deoplete#util#print_error(
|
||||
\ string(python3) . ' is not executable.')
|
||||
@ -49,8 +49,8 @@ function! deoplete#init#_channel() abort
|
||||
call deoplete#util#print_error('deoplete requires nvim 0.3.0+.')
|
||||
return 1
|
||||
endif
|
||||
if !has('nvim') && v:version < 800
|
||||
call deoplete#util#print_error('deoplete requires Vim 8.0+.')
|
||||
if !has('nvim') && v:version < 801
|
||||
call deoplete#util#print_error('deoplete requires Vim 8.1+.')
|
||||
return 1
|
||||
endif
|
||||
|
||||
@ -112,6 +112,7 @@ function! s:init_internal_variables() abort
|
||||
call deoplete#init#_prev_completion()
|
||||
|
||||
let g:deoplete#_context = {}
|
||||
let g:deoplete#_recently_used = []
|
||||
|
||||
if !exists('g:deoplete#_logging')
|
||||
let g:deoplete#_logging = {}
|
||||
@ -136,7 +137,7 @@ function! s:init_internal_variables() abort
|
||||
|
||||
if deoplete#util#has_yarp()
|
||||
" Dummy call is needed to check exists()
|
||||
call neovim_rpc#serveraddr()
|
||||
silent! call neovim_rpc#serveraddr()
|
||||
if !exists('*neovim_rpc#serveraddr')
|
||||
call deoplete#util#print_error(
|
||||
\ 'deoplete requires vim-hug-neovim-rpc plugin in Vim.')
|
||||
@ -220,7 +221,8 @@ function! s:check_custom_var(source_name, old_var, new_var) abort
|
||||
|
||||
call deoplete#util#print_error(
|
||||
\ printf('%s is deprecated variable. '.
|
||||
\ 'Please use deoplete#custom#var() instead.', a:old_var))
|
||||
\ 'Please use deoplete#custom#var("%s", "%s", {value}) instead.',
|
||||
\ a:old_var, a:source_name, a:new_var))
|
||||
call deoplete#custom#var(a:source_name, a:new_var, eval(a:old_var))
|
||||
endfunction
|
||||
function! s:check_custom_option(old_var, new_var) abort
|
||||
@ -230,36 +232,36 @@ function! s:check_custom_option(old_var, new_var) abort
|
||||
|
||||
call deoplete#util#print_error(
|
||||
\ printf('%s is deprecated variable. '.
|
||||
\ 'Please use deoplete#custom#option() instead.', a:old_var))
|
||||
\ 'Please use deoplete#custom#option("%s", {value}) instead.',
|
||||
\ a:old_var, a:new_var))
|
||||
call deoplete#custom#option(a:new_var, eval(a:old_var))
|
||||
endfunction
|
||||
|
||||
function! deoplete#init#_option() abort
|
||||
" Note: HTML omni func use search().
|
||||
return {
|
||||
\ 'auto_complete': v:true,
|
||||
\ 'auto_complete_delay': 0,
|
||||
\ 'auto_complete_popup': 'auto',
|
||||
\ 'auto_refresh_delay': 100,
|
||||
\ 'camel_case': v:false,
|
||||
\ 'auto_refresh_delay': 20,
|
||||
\ 'candidate_marks': [],
|
||||
\ 'overwrite_completeopt': v:true,
|
||||
\ 'check_stderr': v:true,
|
||||
\ 'complete_suffix': v:true,
|
||||
\ 'ignore_case': &ignorecase,
|
||||
\ 'ignore_sources': {},
|
||||
\ 'keyword_patterns': {'_': '[a-zA-Z_]\k*'},
|
||||
\ 'max_list': 500,
|
||||
\ 'min_pattern_length': 2,
|
||||
\ 'num_processes': 4,
|
||||
\ 'num_processes': 1,
|
||||
\ 'nofile_complete_filetypes': ['denite-filter'],
|
||||
\ 'omni_patterns': {},
|
||||
\ 'on_insert_enter': v:true,
|
||||
\ 'on_text_changed_i': v:true,
|
||||
\ 'prev_completion_mode': '',
|
||||
\ 'prev_completion_mode': 'filter',
|
||||
\ 'profile': v:false,
|
||||
\ 'refresh_always': v:true,
|
||||
\ 'refresh_backspace': v:true,
|
||||
\ 'skip_chars': ['(', ')'],
|
||||
\ 'skip_multibyte': v:false,
|
||||
\ 'smart_case': &smartcase,
|
||||
\ 'sources': {},
|
||||
\ 'trigger_key': v:char,
|
||||
\ 'yarp': v:false,
|
||||
@ -272,6 +274,7 @@ function! deoplete#init#_prev_completion() abort
|
||||
\ 'linenr': -1,
|
||||
\ 'candidates': [],
|
||||
\ 'complete_position': -1,
|
||||
\ 'time': reltime(),
|
||||
\ }
|
||||
endfunction
|
||||
|
||||
|
@ -10,6 +10,12 @@ function! deoplete#mapping#_init() abort
|
||||
\ deoplete#mapping#_dummy('deoplete#mapping#_complete')
|
||||
inoremap <expr><silent> <Plug>+
|
||||
\ deoplete#mapping#_dummy('deoplete#mapping#_prev_complete')
|
||||
|
||||
" Note: The dummy mappings may be inserted on other modes.
|
||||
cnoremap <silent> <Plug>_ <Nop>
|
||||
cnoremap <silent> <Plug>+ <Nop>
|
||||
noremap <silent> <Plug>_ <Nop>
|
||||
noremap <silent> <Plug>+ <Nop>
|
||||
endfunction
|
||||
function! deoplete#mapping#_dummy(func) abort
|
||||
return "\<C-r>=".a:func."()\<CR>"
|
||||
@ -35,16 +41,41 @@ function! s:check_completion_info(candidates) abort
|
||||
endif
|
||||
return 0
|
||||
|
||||
let old_candidates = sort(map(copy(info.items), 'v:val.word'))
|
||||
return sort(map(copy(a:candidates), 'v:val.word')) ==# old_candidates
|
||||
let old_candidates = sort(map(copy(info.items), { _, val -> val.word }))
|
||||
return sort(map(copy(a:candidates),
|
||||
\ { _, val -> val.word })) ==# old_candidates
|
||||
endfunction
|
||||
function! deoplete#mapping#_can_complete() abort
|
||||
let context = get(g:, 'deoplete#_context', {})
|
||||
return has_key(context, 'candidates') && has_key(context, 'event')
|
||||
\ && has_key(context, 'input')
|
||||
\ && !s:check_completion_info(context.candidates)
|
||||
\ && &modifiable
|
||||
endfunction
|
||||
function! deoplete#mapping#_complete() abort
|
||||
if !has_key(g:deoplete#_context, 'candidates')
|
||||
\ || s:check_completion_info(g:deoplete#_context.candidates)
|
||||
\ || !&modifiable
|
||||
if !deoplete#mapping#_can_complete()
|
||||
let g:deoplete#_context.candidates = []
|
||||
return ''
|
||||
endif
|
||||
|
||||
if deoplete#util#get_input(g:deoplete#_context.event)
|
||||
\ !=# g:deoplete#_context.input
|
||||
" Use prev completion instead
|
||||
if deoplete#handler#_check_prev_completion(g:deoplete#_context.event)
|
||||
call feedkeys("\<Plug>+", 'i')
|
||||
endif
|
||||
|
||||
return ''
|
||||
endif
|
||||
|
||||
let auto_popup = deoplete#custom#_get_option(
|
||||
\ 'auto_complete_popup') !=# 'manual'
|
||||
|
||||
if auto_popup
|
||||
" Note: completeopt must be changed before complete()
|
||||
call deoplete#mapping#_set_completeopt(g:deoplete#_context.is_async)
|
||||
endif
|
||||
|
||||
" echomsg string(g:deoplete#_context)
|
||||
if empty(g:deoplete#_context.candidates) && deoplete#util#check_popup()
|
||||
" Note: call complete() to close the popup
|
||||
@ -62,20 +93,34 @@ function! deoplete#mapping#_prev_complete() abort
|
||||
return ''
|
||||
endif
|
||||
|
||||
let auto_popup = deoplete#custom#_get_option(
|
||||
\ 'auto_complete_popup') !=# 'manual'
|
||||
|
||||
if auto_popup
|
||||
" Note: completeopt must be changed before complete()
|
||||
call deoplete#mapping#_set_completeopt(v:false)
|
||||
endif
|
||||
|
||||
call complete(g:deoplete#_filtered_prev.complete_position + 1,
|
||||
\ g:deoplete#_filtered_prev.candidates)
|
||||
|
||||
return ''
|
||||
endfunction
|
||||
function! deoplete#mapping#_set_completeopt() abort
|
||||
if exists('g:deoplete#_saved_completeopt')
|
||||
function! deoplete#mapping#_set_completeopt(is_async) abort
|
||||
if !deoplete#custom#_get_option('overwrite_completeopt')
|
||||
return
|
||||
endif
|
||||
let g:deoplete#_saved_completeopt = &completeopt
|
||||
|
||||
if !exists('g:deoplete#_saved_completeopt')
|
||||
let g:deoplete#_saved_completeopt = &completeopt
|
||||
endif
|
||||
set completeopt-=longest
|
||||
set completeopt+=menuone
|
||||
set completeopt-=menu
|
||||
if &completeopt !~# 'noinsert\|noselect'
|
||||
if &completeopt !~# 'noinsert\|noselect' || a:is_async
|
||||
" Note: If is_async, noselect is needed to prevent without confirmation
|
||||
" problem
|
||||
set completeopt-=noinsert
|
||||
set completeopt+=noselect
|
||||
endif
|
||||
endfunction
|
||||
@ -117,16 +162,9 @@ function! deoplete#mapping#_complete_common_string() abort
|
||||
return ''
|
||||
endif
|
||||
|
||||
let complete_str = prev.input[prev.complete_position :]
|
||||
let candidates = filter(copy(prev.candidates),
|
||||
\ 'stridx(tolower(v:val.word), tolower(complete_str)) == 0')
|
||||
|
||||
if empty(candidates) || complete_str ==# ''
|
||||
return ''
|
||||
endif
|
||||
|
||||
let common_str = candidates[0].word
|
||||
for candidate in candidates[1:]
|
||||
let complete_str = deoplete#util#get_input('')[prev.complete_position :]
|
||||
let common_str = prev.candidates[0].word
|
||||
for candidate in prev.candidates[1:]
|
||||
while stridx(tolower(candidate.word), tolower(common_str)) != 0
|
||||
let common_str = common_str[: -2]
|
||||
endwhile
|
||||
|
@ -35,10 +35,6 @@ function! deoplete#util#get_input(event) abort
|
||||
\ '^.*\%' . (mode ==# 'i' ? col('.') : col('.') - 1)
|
||||
\ . 'c' . (mode ==# 'i' ? '' : '.'))
|
||||
|
||||
if a:event ==# 'InsertCharPre'
|
||||
let input .= v:char
|
||||
endif
|
||||
|
||||
return input
|
||||
endfunction
|
||||
function! deoplete#util#get_next_input(event) abort
|
||||
@ -88,7 +84,7 @@ function! s:vimoption2python(option) abort
|
||||
endfunction
|
||||
|
||||
function! deoplete#util#uniq(list) abort
|
||||
let list = map(copy(a:list), '[v:val, v:val]')
|
||||
let list = map(copy(a:list), { _, val -> [val, val] })
|
||||
let i = 0
|
||||
let seen = {}
|
||||
while i < len(list)
|
||||
@ -100,7 +96,7 @@ function! deoplete#util#uniq(list) abort
|
||||
let i += 1
|
||||
endif
|
||||
endwhile
|
||||
return map(list, 'v:val[0]')
|
||||
return map(list, { _, val -> val[0] })
|
||||
endfunction
|
||||
|
||||
function! deoplete#util#get_syn_names() abort
|
||||
@ -183,8 +179,8 @@ endfunction
|
||||
" >0 if a > b
|
||||
" 0 if versions are equal.
|
||||
function! deoplete#util#versioncmp(a, b) abort
|
||||
let a = map(split(a:a, '\.'), 'str2nr(v:val)')
|
||||
let b = map(split(a:b, '\.'), 'str2nr(v:val)')
|
||||
let a = map(split(a:a, '\.'), { _, val -> str2nr(val) })
|
||||
let b = map(split(a:b, '\.'), { _, val -> str2nr(val) })
|
||||
let l = min([len(a), len(b)])
|
||||
let d = 0
|
||||
|
||||
@ -213,3 +209,17 @@ endfunction
|
||||
function! deoplete#util#check_popup() abort
|
||||
return exists('*complete_info') && complete_info().mode ==# 'eval'
|
||||
endfunction
|
||||
|
||||
function! deoplete#util#indent_current_line() abort
|
||||
let pos = getpos('.')
|
||||
let len = len(getline('.'))
|
||||
let equalprg = &l:equalprg
|
||||
try
|
||||
setlocal equalprg=
|
||||
silent normal! ==
|
||||
finally
|
||||
let &l:equalprg = equalprg
|
||||
let pos[2] += len(getline('.')) - len
|
||||
call setpos('.', pos)
|
||||
endtry
|
||||
endfunction
|
||||
|
@ -59,11 +59,11 @@ function! s:still_have_issues() abort
|
||||
let indentation = ' '
|
||||
call health#report_info("If you're still having problems, " .
|
||||
\ "try the following commands:\n" .
|
||||
\ indentation . "$ export NVIM_PYTHON_LOG_FILE=/tmp/log\n" .
|
||||
\ indentation . "$ export NVIM_PYTHON_LOG_LEVEL=DEBUG\n" .
|
||||
\ indentation . "$ nvim\n" .
|
||||
\ indentation . "$ cat /tmp/log_{PID}\n" .
|
||||
\ indentation . ' and then create an issue on github'
|
||||
\ indentation . "- $ export NVIM_PYTHON_LOG_FILE=/tmp/log\n" .
|
||||
\ indentation . "- $ export NVIM_PYTHON_LOG_LEVEL=DEBUG\n" .
|
||||
\ indentation . "- $ nvim\n" .
|
||||
\ indentation . "- $ cat /tmp/log_{PID}\n" .
|
||||
\ indentation . '- and then create an issue on github'
|
||||
\ )
|
||||
endfunction
|
||||
|
||||
|
@ -1,8 +0,0 @@
|
||||
coverage:
|
||||
status:
|
||||
project: false
|
||||
patch: true
|
||||
changes: true
|
||||
|
||||
comment:
|
||||
layout: "diff"
|
@ -1,6 +1,6 @@
|
||||
*deoplete.txt* Dark powered asynchronous completion framework for Neovim/Vim8
|
||||
|
||||
Version: 6.0
|
||||
Version: 6.2
|
||||
Author: Shougo <Shougo.Matsu at gmail.com>
|
||||
License: MIT license
|
||||
|
||||
@ -30,14 +30,14 @@ Compatibility |deoplete-compatibility|
|
||||
INTRODUCTION *deoplete-introduction*
|
||||
|
||||
*deoplete* is the abbreviation of "dark powered neo-completion". It
|
||||
provides asynchronous keyword completion system in the
|
||||
provides an asynchronous keyword completion system in the
|
||||
current buffer.
|
||||
|
||||
Note: deoplete may consume more memory than other plugins do.
|
||||
|
||||
Improvements in deoplete in comparison to |neocomplete|:
|
||||
Improvements in deoplete in comparison to neocomplete:
|
||||
|
||||
1. Real asynchronous completion behavior like |YouCompleteMe| by default.
|
||||
1. Real asynchronous completion behavior like YouCompleteMe by default.
|
||||
2. Uses Python3 to implement sources.
|
||||
3. Removes legacy interface.
|
||||
4. Requires |+python3|.
|
||||
@ -45,8 +45,8 @@ Improvements in deoplete in comparison to |neocomplete|:
|
||||
==============================================================================
|
||||
INSTALL *deoplete-install*
|
||||
|
||||
Note: deoplete requires Neovim (0.3.0+) or Vim8 (latest is recommended) with
|
||||
Python 3.6.1+ and |+timers| enabled.
|
||||
Note: deoplete requires Neovim (0.3.0+) or Vim8.1+ (latest is recommended)
|
||||
with Python 3.6.1+ and |+timers| enabled.
|
||||
|
||||
Please install/upgrade msgpack package (1.0.0+).
|
||||
https://github.com/msgpack/msgpack-python
|
||||
@ -113,7 +113,7 @@ auto_complete
|
||||
auto_complete_delay
|
||||
Delay the completion after input in milliseconds.
|
||||
|
||||
Default value: 0 (milliseconds)
|
||||
Default value: 20 (milliseconds)
|
||||
|
||||
*deoplete-options-auto_complete_popup*
|
||||
auto_complete_popup
|
||||
@ -131,21 +131,19 @@ auto_refresh_delay
|
||||
|
||||
Default value: 100 (milliseconds)
|
||||
|
||||
*deoplete-options-camel_case*
|
||||
camel_case
|
||||
If it is True, lowercase letters are also matched with the
|
||||
corresponding uppercase ones.
|
||||
Ex: "foB" is matched with "FooBar" but not with "foobar".
|
||||
Note: This feature is only available in
|
||||
|deoplete-filter-matcher_fuzzy| or
|
||||
|deoplete-filter-matcher_full_fuzzy|.
|
||||
|
||||
Default value: v:false
|
||||
|
||||
*deoplete-options-candidate_marks*
|
||||
candidate_marks
|
||||
The candidate additional marks.
|
||||
|
||||
If set, this will be used to display an additional mark next
|
||||
to the the first {N} candidates. The first mark is used for
|
||||
the top ranked candidate, the second for the second candidate
|
||||
and so forth.
|
||||
|
||||
In the example below, the first 5 candidates are marked A..G,
|
||||
which serve as mnemonics for commands to insert that
|
||||
candidate.
|
||||
|
||||
Default value: []
|
||||
>
|
||||
call deoplete#custom#option('candidate_marks',
|
||||
@ -174,16 +172,11 @@ complete_suffix
|
||||
|
||||
Default value: v:true
|
||||
|
||||
*deoplete-options-ignore_case*
|
||||
ignore_case
|
||||
If it is True, deoplete ignores case.
|
||||
|
||||
Default value: same with your 'ignorecase' value
|
||||
|
||||
*deoplete-options-ignore_sources*
|
||||
ignore_sources
|
||||
It is a dictionary to decide ignore source names.
|
||||
The key is filetype and the value is source names list.
|
||||
Note: It is disabled in |deoplete#manual_complete()|.
|
||||
|
||||
Default value: {}
|
||||
|
||||
@ -209,15 +202,25 @@ max_list
|
||||
|
||||
Default value: 500
|
||||
|
||||
*deoplete-options-nofile_complete_filetypes*
|
||||
nofile_complete_filetypes
|
||||
If 'buftype' is "nofile", deoplete completion is disabled
|
||||
automatically except the filetype list.
|
||||
|
||||
Default value: ["denite-filter"]
|
||||
|
||||
*deoplete-options-num_processes*
|
||||
num_processes
|
||||
The number of processes used for the deoplete parallel
|
||||
feature.
|
||||
completion feature.
|
||||
The parallel completion increases the completion speed, but it
|
||||
increases the screen flicker.
|
||||
|
||||
If it is 1, this feature is disabled.
|
||||
If it is less than or equal to 0, the number of processes is
|
||||
equal to that of sources.
|
||||
|
||||
Default value: 4
|
||||
Default value: 1
|
||||
|
||||
*deoplete-options-omni_patterns*
|
||||
omni_patterns
|
||||
@ -260,6 +263,14 @@ on_text_changed_i
|
||||
Deoplete enables the auto completion on |TextChangedI| autocmd
|
||||
if this value is True.
|
||||
|
||||
Default value: v:true
|
||||
|
||||
*deoplete-options-overwrite_completeopt*
|
||||
overwrite_completeopt
|
||||
Deoplete overwrites 'completeopt' option.
|
||||
You can disable the feature but if you change it, deoplete may
|
||||
not work.
|
||||
|
||||
Default value: v:true
|
||||
|
||||
*deoplete-options-profile*
|
||||
@ -289,13 +300,22 @@ prev_completion_mode
|
||||
refresh_always
|
||||
Deoplete refreshes the candidates automatically if this value
|
||||
is True.
|
||||
Note: It increases the screen flicker.
|
||||
|
||||
Note: It increases the screen flicker when
|
||||
|deoplete-options-num_processes| != 0.
|
||||
|
||||
Default value: v:true
|
||||
|
||||
*deoplete-options-refresh_backspace*
|
||||
refresh_backspace
|
||||
Deoplete refreshes the candidates automatically when you
|
||||
press <BS> or <C-h> key.
|
||||
|
||||
Default value: v:true
|
||||
|
||||
*deoplete-options-skip_multibyte*
|
||||
skip_multibyte
|
||||
Deoplete skip multibyte text completion automatically if this
|
||||
Deoplete skips multibyte text completion automatically if this
|
||||
value is True.
|
||||
|
||||
Default value: v:false
|
||||
@ -306,20 +326,13 @@ skip_chars
|
||||
|
||||
Default value: ['(', ')']
|
||||
|
||||
*deoplete-options-smart_case*
|
||||
smart_case
|
||||
When a capital letter is included in input, deoplete does
|
||||
not ignore the upper- and lowercase.
|
||||
|
||||
Default value: same with your 'smartcase' value
|
||||
|
||||
*deoplete-options-sources*
|
||||
sources
|
||||
It is a dictionary to specify source names. The key is
|
||||
filetype and the value is source names list. If the key is
|
||||
"_", the value will be used for default filetypes. For
|
||||
example, you can load some sources in C++ filetype.
|
||||
If the value is [], it will load all sources.
|
||||
filetype and the value is a list of source names. If the key
|
||||
is "_", the value will be used for default filetypes. For
|
||||
example, you can load some sources in C++ filetype. If the
|
||||
value is [], it will load all sources.
|
||||
|
||||
Default value: {}
|
||||
>
|
||||
@ -339,7 +352,7 @@ min_pattern_length
|
||||
|
||||
Default: 2
|
||||
|
||||
*deoplete-options-yarp*
|
||||
*deoplete-options-yarp*
|
||||
yarp
|
||||
Use nvim-yarp library instead of neovim remote plugin feature.
|
||||
Note: nvim-yarp plugin is needed.
|
||||
@ -470,7 +483,7 @@ deoplete#custom#source({source-name}, {dict})
|
||||
|
||||
" Disable the candidates in Comment/String syntaxes.
|
||||
call deoplete#custom#source('_',
|
||||
\ 'disabled_syntaxes', ['Comment', 'String'])
|
||||
\ 'disabled_syntaxes', ['Comment', 'String', 'Constant'])
|
||||
|
||||
" Change the truncate width.
|
||||
call deoplete#custom#source('javacomplete2',
|
||||
@ -492,7 +505,8 @@ deoplete#custom#source({source-name}, {dict})
|
||||
" Enable jedi source debug messages
|
||||
" call deoplete#custom#option('profile', v:true)
|
||||
" call deoplete#enable_logging('DEBUG', 'deoplete.log')
|
||||
" call deoplete#custom#source('jedi', 'is_debug_enabled', 1)
|
||||
" call deoplete#custom#source('jedi',
|
||||
\ 'is_debug_enabled', v:true)
|
||||
<
|
||||
*deoplete#custom#var()*
|
||||
deoplete#custom#var({source-name}, {var-name}, {value})
|
||||
@ -510,9 +524,14 @@ KEY MAPPINGS *deoplete-key-mappings*
|
||||
deoplete#auto_complete([{event}])
|
||||
It calls the auto completion of deoplete. You can use it to
|
||||
call auto completion again.
|
||||
{event} is autocmd event name. If it is omit, "Async" is
|
||||
{event} is autocmd event name. If it is omitted, "Async" is
|
||||
used.
|
||||
|
||||
*deoplete#can_complete()*
|
||||
deoplete#can_complete()
|
||||
Return v:true if current word completion is available.
|
||||
Note: |deoplete-options-auto_complete_popup| must be "manual".
|
||||
|
||||
*deoplete#close_popup()*
|
||||
deoplete#close_popup()
|
||||
Insert candidate and close popup menu for deoplete.
|
||||
@ -525,18 +544,18 @@ deoplete#complete()
|
||||
|
||||
*deoplete#complete_common_string()*
|
||||
deoplete#complete_common_string()
|
||||
complete common string in candidates. It will be convenient
|
||||
when candidates have long common string.
|
||||
complete common string in candidates.
|
||||
This can be useful when candidates have a long common prefix.
|
||||
Note: It must be in |:map-<expr>|.
|
||||
|
||||
*deoplete#insert_candidate()*
|
||||
deoplete#insert_candidate({number})
|
||||
Insert {number}th candidate.
|
||||
deoplete#insert_candidate({index})
|
||||
Insert the candidate at index {index}. Indices start at 0.
|
||||
Note: It must be in |:map-<expr>|.
|
||||
|
||||
*deoplete#manual_complete()*
|
||||
deoplete#manual_complete([{sources}])
|
||||
It calls the completion of deoplete. You can use it with
|
||||
Trigger deoplete completion. You can use it with
|
||||
custom completion setups.
|
||||
You can provide a list of {sources}: It can be the name of a
|
||||
source or a list of sources name.
|
||||
@ -544,16 +563,16 @@ deoplete#manual_complete([{sources}])
|
||||
Note: It must be in |:map-<expr>|.
|
||||
|
||||
If you want to trigger deoplete manually, see also
|
||||
|deoplete-options-auto_complete|, which should be 1 then
|
||||
typically.
|
||||
|deoplete-options-auto_complete|, which should typically then
|
||||
be 1.
|
||||
>
|
||||
inoremap <silent><expr> <TAB>
|
||||
\ pumvisible() ? "\<C-n>" :
|
||||
\ <SID>check_back_space() ? "\<TAB>" :
|
||||
\ deoplete#manual_complete()
|
||||
function! s:check_back_space() abort "{{{
|
||||
let col = col('.') - 1
|
||||
return !col || getline('.')[col - 1] =~ '\s'
|
||||
let col = col('.') - 1
|
||||
return !col || getline('.')[col - 1] =~ '\s'
|
||||
endfunction"}}}
|
||||
<
|
||||
*deoplete#smart_close_popup()*
|
||||
@ -566,13 +585,12 @@ deoplete#smart_close_popup()
|
||||
inoremap <expr><BS>
|
||||
\ deoplete#smart_close_popup()."\<C-h>"
|
||||
<
|
||||
Note: This mapping conflicts with |SuperTab| or |endwise|
|
||||
plugins.
|
||||
Note: This mapping conflicts with SuperTab or endwise plugins.
|
||||
Note: This key mapping is for <C-h> or <BS> keymappings.
|
||||
|
||||
*deoplete#undo_completion()*
|
||||
deoplete#undo_completion()
|
||||
Undo inputted candidate.
|
||||
Undo inserted candidate.
|
||||
Note: It must be in |:map-<expr>|.
|
||||
>
|
||||
inoremap <expr><C-g> deoplete#undo_completion()
|
||||
@ -583,7 +601,7 @@ EXAMPLES *deoplete-examples*
|
||||
" Use deoplete.
|
||||
let g:deoplete#enable_at_startup = 1
|
||||
" Use smartcase.
|
||||
call deoplete#custom#option('smart_case', v:true)
|
||||
call deoplete#custom#source('_', 'smart_case', v:true)
|
||||
|
||||
" <CR>: close popup and save indent.
|
||||
inoremap <silent> <CR> <C-r>=<SID>my_cr_function()<CR>
|
||||
@ -656,15 +674,21 @@ file *deoplete-source-file*
|
||||
Source custom variables:
|
||||
enable_buffer_path
|
||||
If it is True, file source completes the files
|
||||
from the buffer path instead of the current
|
||||
directory.
|
||||
from the buffer directory instead of the
|
||||
current directory.
|
||||
(default: v:true)
|
||||
|
||||
enable_slash_completion
|
||||
If it is True, file source completes the files
|
||||
when user input "/".
|
||||
(default: v:false)
|
||||
|
||||
force_completion_length
|
||||
The completion length if the input does not
|
||||
contain "/".
|
||||
If it is less than 0, it is disabled.
|
||||
(default: -1)
|
||||
|
||||
member *deoplete-source-member*
|
||||
This source collects members from current buffer.
|
||||
|
||||
@ -706,7 +730,7 @@ omni *deoplete-source-omni*
|
||||
setting.
|
||||
(default: {})
|
||||
>
|
||||
call deoplete#custom#source('omni', 'functions', {
|
||||
call deoplete#custom#var('omni', 'functions', {
|
||||
\ 'javascript': ['tern#Complete', 'jspc#omni']
|
||||
\})
|
||||
<
|
||||
@ -730,6 +754,10 @@ omni *deoplete-source-omni*
|
||||
==============================================================================
|
||||
FILTERS *deoplete-filters*
|
||||
|
||||
Once candidates have been supplied by one or more sources, they are passed
|
||||
through the filters, which are matchers, converters or sorters. Sources can
|
||||
have specific filters.
|
||||
|
||||
*deoplete-filter-matcher_default*
|
||||
Default matchers: ['matcher_fuzzy']
|
||||
|
||||
@ -778,9 +806,13 @@ matcher_length
|
||||
Length matching matcher.
|
||||
It removes candidates shorter than or equal to the user input.
|
||||
|
||||
*deoplete-filter-matcher_matchfuzzy*
|
||||
matcher_matchfuzzy
|
||||
|matchfuzzy()| matcher.
|
||||
|
||||
*deoplete-filter-sorter_rank*
|
||||
sorter_rank Matched rank order sorter. The higher the head matched word
|
||||
or already typed word.
|
||||
or already typed or inserted word.
|
||||
The locality bonus feature is implemented like VSCode.
|
||||
|
||||
*deoplete-filter-sorter_word*
|
||||
@ -889,8 +921,7 @@ converter_reorder_attr
|
||||
*deoplete-filter-converter_auto_paren*
|
||||
converter_auto_paren
|
||||
It adds parentheses character in a candidate's word.
|
||||
It is useful if you use |neopairs| or |neosnippet|
|
||||
plugins.
|
||||
It is useful if you use neopairs or neosnippet plugins.
|
||||
|
||||
*deoplete-filter-converter_case*
|
||||
converter_case
|
||||
@ -920,7 +951,10 @@ converter_truncate_info
|
||||
converter_truncate_menu
|
||||
It truncates a candidate's menu by the current window width.
|
||||
|
||||
==============================================================================
|
||||
*deoplete-filter-converter_word_abbr*
|
||||
converter_word_abbr
|
||||
Convert candidate word to abbr.
|
||||
|
||||
CREATE SOURCE *deoplete-create-source*
|
||||
|
||||
To create source, you should read default sources implementation in
|
||||
@ -928,7 +962,7 @@ rplugin/python3/deoplete/source/*.py.
|
||||
|
||||
The files are automatically loaded and deoplete creates new Source class
|
||||
object.
|
||||
Source class must extend Base class in ".base".
|
||||
Source class must extend the Base class in ".base".
|
||||
|
||||
Note: The sources must be written in Python3 language.
|
||||
|
||||
@ -946,9 +980,20 @@ __init__ (Function)
|
||||
*deoplete-source-attribute-__*
|
||||
__{name} (Unspecified) (Optional)
|
||||
Additional source information.
|
||||
Note: Recommend sources save variables instead of
|
||||
Note: Sources should save variables instead of
|
||||
global variables.
|
||||
|
||||
*deoplete-source-attribute-camel_case*
|
||||
camel_case
|
||||
If it is True, lowercase letters are also matched with the
|
||||
corresponding uppercase ones.
|
||||
Ex: "foB" is matched with "FooBar" but not with "foobar".
|
||||
Note: This feature is only available in
|
||||
|deoplete-filter-matcher_fuzzy| or
|
||||
|deoplete-filter-matcher_full_fuzzy|.
|
||||
|
||||
Default value: v:false
|
||||
|
||||
*deoplete-source-attribute-converters*
|
||||
converters (List[str]) (Optional)
|
||||
Source default converters list.
|
||||
@ -989,40 +1034,58 @@ filetypes (List[str]) (Optional)
|
||||
Available filetype list.
|
||||
|
||||
Default: []
|
||||
Note: It means this source available in all filetypes.
|
||||
Note: It means this source is available for all filetypes.
|
||||
|
||||
*deoplete-source-attribute-gather_candidates*
|
||||
gather_candidates
|
||||
(Function) (Required)
|
||||
It is called to gather candidates.
|
||||
It takes {self} and {context} as its parameter and returns a
|
||||
It takes {self} and {context} as parameters and returns a
|
||||
list of {candidate}.
|
||||
If the error is occurred, it must return None.
|
||||
If an error occurrs, it must return None.
|
||||
{candidate} must be String or Dictionary contains
|
||||
|deoplete-candidate-attributes|.
|
||||
Here, {context} is the context information when the source is
|
||||
called (|deoplete-notation-{context}|).
|
||||
|
||||
Note: The source must not filter the candidates by user input.
|
||||
It is |deoplete-filters| work. If the source filter the
|
||||
candidates, user cannot filter the candidates by fuzzy match.
|
||||
Instead, let the |deoplete-filters| match and sort the
|
||||
results. If the source filters the candidates, the user
|
||||
cannot then filter the candidates by fuzzy match.
|
||||
Instead, let the |deoplete-filters| match and sort the
|
||||
results. If the source filters the candidates, the user
|
||||
cannot then filter the candidates by fuzzy match.
|
||||
candidates, the user cannot then filter the candidates by
|
||||
fuzzy match.
|
||||
|
||||
*deoplete-source-attribute-get_complete_position*
|
||||
get_complete_position
|
||||
(Function) (Optional)
|
||||
It is called to get complete position.
|
||||
It is called to get the position of the current completion.
|
||||
It takes {self} and {context} as its parameter and returns
|
||||
complete position in current line.
|
||||
Here, {context} is the context information when the source is
|
||||
a number representing the starting position of the completion
|
||||
in the current line.
|
||||
|
||||
Here, {context} is the context information from when the
|
||||
source is called (|deoplete-notation-{context}|).
|
||||
called (|deoplete-notation-{context}|).
|
||||
|
||||
Default: position using |deoplete-options-keyword_patterns|.
|
||||
Note: If |deoplete-source-attribute-is_bytepos| is True, it
|
||||
must return byte position.
|
||||
|
||||
This is useful if you want to complete terms that are more.
|
||||
|
||||
*deoplete-source-attribute-ignore_case*
|
||||
ignore_case
|
||||
If it is True, deoplete ignores case.
|
||||
|
||||
Default value: v:false
|
||||
|
||||
*deoplete-source-attribute-input_pattern*
|
||||
input_pattern
|
||||
(String) (Optional)
|
||||
If it is matched with input, deoplete ignores
|
||||
If it matches the input, deoplete ignores
|
||||
|deoplete-source-attribute-min_pattern_length|.
|
||||
It is useful for omni function sources.
|
||||
Note: It is Python3 regexp.
|
||||
@ -1036,7 +1099,7 @@ input_patterns
|
||||
The dictionary version of
|
||||
|deoplete-source-attribute-input_pattern|.
|
||||
A key is filetype and a value is input pattern.
|
||||
Note: It is Python3 regexp.
|
||||
Note: Values are Python3 regexps.
|
||||
|
||||
*deoplete-source-attribute-is_bytepos*
|
||||
is_bytepos
|
||||
@ -1045,7 +1108,7 @@ is_bytepos
|
||||
|deoplete-source-attribute-get_complete_position|
|
||||
returns byteposition instead of character position.
|
||||
It is useful for Vim script to create sources because Vim
|
||||
script string uses byte position. Python string uses
|
||||
script string uses byte position. Python strings use
|
||||
character position.
|
||||
|
||||
Default: False
|
||||
@ -1067,7 +1130,7 @@ is_silent
|
||||
*deoplete-source-attribute-is_skip_langmap*
|
||||
is_skip_langmap
|
||||
(Bool) (Optional)
|
||||
If it is True, the source skips the |langmap| completion.
|
||||
If it is True, the source skips the 'langmap' completion.
|
||||
|
||||
Default: True
|
||||
|
||||
@ -1087,6 +1150,11 @@ is_volatile
|
||||
*deoplete-source-attribute-mark*
|
||||
mark (String) (Optional)
|
||||
The mark of a source.
|
||||
Note: If the source set candidate menu, the source must set
|
||||
it. If the attribute is empty string, the candidate menu will
|
||||
be disabled.
|
||||
|
||||
Default: ''
|
||||
|
||||
*deoplete-source-attribute-matchers*
|
||||
matchers (List[str]) (Optional)
|
||||
@ -1104,44 +1172,43 @@ matcher_key (String) (Optional)
|
||||
*deoplete-source-attribute-max_abbr_width*
|
||||
max_abbr_width
|
||||
(Integer) (Optional)
|
||||
If the candidate abbr length exceeds the length it will be cut
|
||||
If the candidate abbr length exceeds this value, it will be
|
||||
cut down.
|
||||
down.
|
||||
If it is less than or equal to 0, it will be disabled.
|
||||
|
||||
Default: 80
|
||||
|
||||
*deoplete-source-attribute-max_candidates*
|
||||
max_candidates
|
||||
(Integer) (Optional)
|
||||
If the candidates are more than it, deoplete will ignore the
|
||||
filtering.
|
||||
If there are more candidates than this value, deoplete will
|
||||
ignore the filtering.
|
||||
|
||||
Default: 500
|
||||
|
||||
*deoplete-source-attribute-max_kind_width*
|
||||
max_kind_width
|
||||
(Integer) (Optional)
|
||||
If the candidate kind length exceeds the length it will be cut
|
||||
down.
|
||||
If it is less than or equal to 0, it will be disabled.
|
||||
If the candidate kind length exceeds this value it will be
|
||||
trimmed. If this value is less than or equal to 0, it will be
|
||||
disabled.
|
||||
|
||||
Default: 40
|
||||
|
||||
*deoplete-source-attribute-max_info_width*
|
||||
max_info_width
|
||||
(Integer) (Optional)
|
||||
If the candidate info length exceeds the length it will be cut
|
||||
down.
|
||||
If it is less than or equal to 0, it will be disabled.
|
||||
If the candidate info length exceeds this value it is trimmed.
|
||||
If this value is less than or equal to 0, it will be disabled.
|
||||
|
||||
Default: 200
|
||||
|
||||
*deoplete-source-attribute-max_menu_width*
|
||||
max_menu_width
|
||||
(Integer) (Optional)
|
||||
If the candidate menu length exceeds the length it will be cut
|
||||
If the candidate menu length exceeds this value it is trimmed.
|
||||
down.
|
||||
If it is less than or equal to 0, it will be disabled.
|
||||
If this value is less than or equal to 0, it will be disabled.
|
||||
|
||||
Default: 40
|
||||
|
||||
@ -1199,6 +1266,13 @@ rank (Integer) (Optional)
|
||||
|
||||
Default: 100
|
||||
|
||||
*deoplete-source-attribute-smart_case*
|
||||
smart_case
|
||||
When a capital letter is included in input, deoplete does
|
||||
not ignore the upper- and lowercase.
|
||||
|
||||
Default value: v:false
|
||||
|
||||
*deoplete-source-attribute-sorters*
|
||||
sorters (List[str]) (Optional)
|
||||
Source default sorters list.
|
||||
@ -1249,6 +1323,9 @@ vars (Dictionary) (Optional)
|
||||
The input string of the current line, namely the part
|
||||
before the cursor.
|
||||
|
||||
is_refresh (Bool)
|
||||
If the input is changed, it will be "True".
|
||||
|
||||
is_async (Bool)
|
||||
If the gather is asynchronous, the source must set
|
||||
it to "True". A typical strategy for an asynchronous
|
||||
@ -1287,10 +1364,6 @@ vars (Dictionary) (Optional)
|
||||
context['is_async'] = self._count < 10
|
||||
return [context['input'].split()[-1] + str(self._count)]
|
||||
<
|
||||
is_refresh (Bool)
|
||||
If the input is changed, it will be "True".
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
CANDIDATE ATTRIBUTES *deoplete-candidate-attributes*
|
||||
|
||||
@ -1333,6 +1406,9 @@ The files are automatically loaded and deoplete creates new Filter class
|
||||
object.
|
||||
Filter class must extend Base class in ".base".
|
||||
|
||||
Matchers, sorters and converters are all kinds of filters, and should all
|
||||
be placed in the same filter directory.
|
||||
|
||||
Note: The filters must be written in Python3 language.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
@ -1362,6 +1438,8 @@ filter
|
||||
==============================================================================
|
||||
EXTERNAL SOURCES *deoplete-external-sources*
|
||||
|
||||
Please see https://github.com/Shougo/deoplete.nvim/wiki/Completion-Sources
|
||||
|
||||
neco-vim: "vim" source for Vim script
|
||||
https://github.com/Shougo/neco-vim
|
||||
|
||||
@ -1374,124 +1452,11 @@ https://github.com/Shougo/neoinclude.vim
|
||||
neco-syntax: "syntax" source
|
||||
https://github.com/Shougo/neco-syntax
|
||||
|
||||
vimshell: "vimshell" source for vimshell
|
||||
https://github.com/Shougo/vimshell.vim
|
||||
|
||||
neco-ghc: "ghc" source for Haskell
|
||||
https://github.com/eagletmt/neco-ghc
|
||||
|
||||
neco-look: "look" source to suggest words from sorted dictionary
|
||||
https://github.com/ujihisa/neco-look
|
||||
|
||||
vim-racer: "racer" source for Rust
|
||||
https://github.com/racer-rust/vim-racer
|
||||
|
||||
UltiSnips source: "ultisnips" source for UltiSnips
|
||||
https://github.com/SirVer/ultisnips
|
||||
|
||||
clang-complete: "clang_complete" source for C/C++/Objective-C
|
||||
https://github.com/Rip-Rip/clang_complete
|
||||
|
||||
deoplete-go: "go" source for Go
|
||||
https://github.com/deoplete-plugins/deoplete-go
|
||||
|
||||
elixir.nvim: "elixir" source for Elixir
|
||||
https://github.com/awetzel/elixir.nvim
|
||||
|
||||
deoplete-jedi: "jedi" source for Python
|
||||
https://github.com/deoplete-plugins/deoplete-jedi
|
||||
|
||||
perlomni.vim: "PerlOmni" source for Perl
|
||||
https://github.com/c9s/perlomni.vim
|
||||
|
||||
nvim-typescript: "typescript" source for typescript
|
||||
https://github.com/mhartington/nvim-typescript
|
||||
|
||||
async-clj-omni: "async_clj" source for Clojure
|
||||
https://github.com/SevereOverfl0w/async-clj-omni
|
||||
|
||||
deoplete-ternjs: "ternjs" source for JavaScript
|
||||
https://github.com/carlitux/deoplete-ternjs
|
||||
|
||||
deoplete-swift: "swift" source for Swift
|
||||
https://github.com/landaire/deoplete-swift
|
||||
|
||||
neovim-intellij-complete-deoplete: "intellij" source for Intellij IDE
|
||||
https://github.com/vhakulinen/neovim-intellij-complete-deoplete
|
||||
|
||||
tmux-complete: "tmuxcomplete" source for tmux panes
|
||||
https://github.com/wellle/tmux-complete.vim
|
||||
|
||||
deoplete-github: "github" source for "gitcommit" filetype
|
||||
https://github.com/SevereOverfl0w/deoplete-github
|
||||
|
||||
deoplete-flow: "flow" source for JavaScript
|
||||
https://github.com/steelsojka/deoplete-flow
|
||||
|
||||
deoplete-d: "d" source for D language
|
||||
https://github.com/landaire/deoplete-d
|
||||
|
||||
deoplete-rtags: "rtags" source for "c", "cpp", "objc" and "objcpp" filetypes
|
||||
https://github.com/LuXuryPro/deoplete-rtags
|
||||
|
||||
deoplete-solargraph "solargraph" source for Ruby language
|
||||
https://github.com/uplus/deoplete-solargraph
|
||||
|
||||
deoplete-padawan: "padawan" source for padawan.php
|
||||
https://github.com/pbogut/deoplete-padawan
|
||||
|
||||
webcomplete.vim: "webcomplete" source for browser opened pages
|
||||
https://github.com/thalesmello/webcomplete.vim
|
||||
|
||||
deoplete-julia: "julia" source for Julia
|
||||
https://github.com/JuliaEditorSupport/deoplete-julia
|
||||
|
||||
acid.nvim: "acid" source for Clojure
|
||||
https://github.com/hkupty/acid.nvim
|
||||
|
||||
deoplete-omnisharp: "cs" source for C#
|
||||
https://github.com/Robzz/deoplete-omnisharp/
|
||||
|
||||
deoplete-omnisharp: Improved version of deoplete-omnisharp
|
||||
https://github.com/dimixar/deoplete-omnisharp/
|
||||
|
||||
deoplete-omnisharp: Embedded omnisharp server version of deoplete-omnisharp
|
||||
https://github.com/cyansprite/deoplete-omnisharp
|
||||
|
||||
deoplete-hack: "hack" source for Hack and PHP
|
||||
https://github.com/zefei/deoplete-hack
|
||||
|
||||
deoplete-laravel-plugin: "laravel-plugin" source for "php" and "blade"
|
||||
filetypes
|
||||
https://github.com/rafaelndev/deoplete-laravel-plugin
|
||||
|
||||
deoplete-zsh: "zsh" source for Zsh
|
||||
https://github.com/deoplete-plugins/deoplete-zsh
|
||||
|
||||
deoplete-fish: "fish" source for fish shell
|
||||
https://github.com/ponko2/deoplete-fish
|
||||
|
||||
deoplete-fsharp: "fsharp" source for F#
|
||||
https://github.com/callmekohei/deoplete-fsharp
|
||||
|
||||
autocomplete-flow: "flow" source for JavaScript
|
||||
https://github.com/wokalski/autocomplete-flow
|
||||
|
||||
deoplete-asm: "asm" source for Assembly Language
|
||||
https://github.com/deoplete-plugins/deoplete-asm
|
||||
|
||||
deoplete-abook: "abook" source for abook contacts
|
||||
https://github.com/fszymanski/deoplete-abook
|
||||
|
||||
deoplete-emoji: "emoji" source for emoji codes
|
||||
https://github.com/fszymanski/deoplete-emoji
|
||||
|
||||
LanguageClient-neovim: "LanguageClient" source for Language Server
|
||||
Protocol(LSP)
|
||||
https://github.com/autozimu/LanguageClient-neovim
|
||||
|
||||
deoplete-vim-lsp: "lsp" source for vim-lsp
|
||||
https://github.com/lighttiger2505/deoplete-vim-lsp
|
||||
deoplete-lsp source for neovim builtin LSP features
|
||||
https://github.com/deoplete-plugins/deoplete-lsp
|
||||
|
||||
deoplete-tags: "tag" source for tag files
|
||||
https://github.com/deoplete-plugins/deoplete-tag
|
||||
@ -1617,7 +1582,7 @@ A: Please enable logging feature like this. >
|
||||
|
||||
call deoplete#custom#option('profile', v:true)
|
||||
call deoplete#enable_logging('DEBUG', 'deoplete.log')
|
||||
call deoplete#custom#source('jedi', 'is_debug_enabled', 1)
|
||||
call deoplete#custom#source('jedi', 'is_debug_enabled', v:true)
|
||||
|
||||
Q: "Channel id must be a positive integer" error.
|
||||
https://github.com/Shougo/deoplete.nvim/issues/406
|
||||
@ -1666,6 +1631,13 @@ Q: deoplete conflicts with lexima.vim
|
||||
A: >
|
||||
https://github.com/cohama/lexima.vim/issues/65#issuecomment-339338677
|
||||
|
||||
Q: Vim's build-in completion behavior(|i_CTRL-P| etc) is changed after
|
||||
deoplete is enabled. The first entry is not inserted.
|
||||
|
||||
A: It is the feature of deoplete. The default insertion is disabled to enable
|
||||
completion asynchronously. If you don't like the behavior, you should use
|
||||
other auto completion plugin.
|
||||
|
||||
*deoplete-faq-config*
|
||||
2. Configuration~
|
||||
|
||||
@ -1675,11 +1647,9 @@ Q: I want to silence the |ins-completion-menu| messages in the command line
|
||||
|
||||
A: You can disable the messages through the 'shortmess' option. >
|
||||
|
||||
if has("patch-7.4.314")
|
||||
set shortmess+=c
|
||||
endif
|
||||
set shortmess+=c
|
||||
|
||||
Q: I want to use the auto select feature like |neocomplete|.
|
||||
Q: I want to use the auto select feature like neocomplete.
|
||||
|
||||
A: You can use it by the 'completeopt' option. >
|
||||
|
||||
@ -1747,6 +1717,11 @@ Q: How can I sort all entries alphabetically?
|
||||
A: >
|
||||
call deoplete#custom#source('_', 'sorters', ['sorter_word'])
|
||||
|
||||
Q: I want to disable all sources marks.
|
||||
|
||||
A: >
|
||||
call deoplete#custom#source('_', 'mark', '')
|
||||
|
||||
Q: I want to use head matcher instead of fuzzy matcher.
|
||||
|
||||
A: You can achieve this by following >
|
||||
@ -1848,10 +1823,10 @@ A: >
|
||||
inoremap <silent><expr> <TAB>
|
||||
\ pumvisible() ? "\<C-n>" :
|
||||
\ <SID>check_back_space() ? "\<Tab>" :
|
||||
\ deoplete#complete()
|
||||
\ deoplete#can_complete() ? deoplete#complete() : ''
|
||||
function! s:check_back_space() abort
|
||||
let col = col('.') - 1
|
||||
return !col || getline('.')[col - 1] =~# '\s'
|
||||
let col = col('.') - 1
|
||||
return !col || getline('.')[col - 1] =~# '\s'
|
||||
endfunction
|
||||
|
||||
Q: Why I have to trigger |deoplete#complete()| at least twice for the popup to
|
||||
@ -1876,6 +1851,15 @@ If you really need the feature, it works for me. >
|
||||
inoremap <expr> <C-h> pumvisible() ?
|
||||
\ "\<C-h>" . deoplete#complete() : "\<C-h>"
|
||||
<
|
||||
|
||||
Q: deoplete has the flicker issue when parallel completion feature is enabled.
|
||||
|
||||
A: I recommend for you to disable |deoplete-options-refresh_always|option when
|
||||
you enable deoplete parallel completion. >
|
||||
|
||||
call deoplete#custom#option('num_processes', 4)
|
||||
call deoplete#custom#option('refresh_always', v:false)
|
||||
|
||||
*deoplete-faq-ft-specific*
|
||||
3. Filetype Specific Questions~
|
||||
|
||||
@ -1888,7 +1872,7 @@ A: Please use |deoplete-options-auto_complete|. >
|
||||
|
||||
Q: I want to use C/C++ omni completion with deoplete.
|
||||
|
||||
A: You should use |deoplete-clangx|.
|
||||
A: You should use deoplete-clangx.
|
||||
|
||||
https://github.com/Shougo/deoplete-clangx
|
||||
|
||||
@ -1963,10 +1947,10 @@ A: >
|
||||
|
||||
Q: How to donate money to you?
|
||||
|
||||
A: I don't get the donation, but if you want to donate, please support neovim
|
||||
project. My plugins depends on neovim development.
|
||||
A: I have started github sponsorship to spend more time for Vim/neovim
|
||||
plugins. You can donate money to help me!
|
||||
|
||||
https://salt.bountysource.com/teams/neovim
|
||||
https://github.com/sponsors/Shougo
|
||||
|
||||
Q: What means "dark powered"?
|
||||
|
||||
@ -2005,6 +1989,11 @@ A: deoplete is:
|
||||
If you don't like node.js based plugin or huge plugin base system, you
|
||||
should not choose coc.nvim.
|
||||
|
||||
completion-nvim is Lua based plugin for neovim.
|
||||
You cannot use it in Vim8.
|
||||
If you like Lua, you don't use Vim8, and you don't like external
|
||||
dependency, it is a better choice.
|
||||
|
||||
And the important view is the author.
|
||||
If you like the author or the author created plugins, you should choose the
|
||||
auto completion plugin.
|
||||
@ -2021,9 +2010,26 @@ A: deoplete is:
|
||||
I don't think deoplete is the best for everyone. Please choose auto
|
||||
completion plugin.
|
||||
|
||||
Q: deoplete with coc.nvim does not work.
|
||||
https://github.com/Shougo/deoplete.nvim/issues/1192
|
||||
|
||||
A: Unfortunately, both deoplete and coc.nvim provide auto completion feature.
|
||||
So deoplete conflicts with coc.nvim.
|
||||
You cannot use both. You need to choose coc.nvim or deoplete.
|
||||
Note: But to change |deoplete-options-overwrite_completeopt| may work for
|
||||
you.
|
||||
|
||||
==============================================================================
|
||||
COMPATIBILITY *deoplete-compatibility*
|
||||
|
||||
2021.05.30
|
||||
* "smart_case" and "ignore_case" and "camel_case" are source specific options
|
||||
instead.
|
||||
|
||||
2020.11.07
|
||||
* Disable nofile buffers completion except
|
||||
deoplete-options-nofile_complete_filetypes.
|
||||
|
||||
2020.04.26
|
||||
* Add deprecated variables warnings.
|
||||
|
||||
|
@ -4,19 +4,19 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from importlib.util import find_spec
|
||||
from pynvim import Nvim
|
||||
import typing
|
||||
|
||||
from importlib.util import find_spec
|
||||
from deoplete.deoplete import Deoplete
|
||||
from deoplete.util import Nvim
|
||||
|
||||
|
||||
if find_spec('yarp'):
|
||||
try:
|
||||
# For Vim8
|
||||
import vim
|
||||
elif find_spec('pynvim'):
|
||||
except ModuleNotFoundError:
|
||||
# For neovim
|
||||
# Note: neovim cannot import vim module
|
||||
import pynvim as vim
|
||||
else:
|
||||
import neovim as vim
|
||||
|
||||
Context = typing.Dict[str, typing.Any]
|
||||
|
||||
@ -26,8 +26,8 @@ if hasattr(vim, 'plugin'):
|
||||
@vim.plugin
|
||||
class DeopleteHandlers(object):
|
||||
|
||||
def __init__(self, vim: Nvim):
|
||||
self._vim = vim
|
||||
def __init__(self, _vim: Nvim):
|
||||
self._vim = _vim
|
||||
|
||||
@vim.function('_deoplete_init', sync=False) # type: ignore
|
||||
def init_channel(self,
|
||||
|
@ -4,11 +4,12 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from pynvim import Nvim
|
||||
import typing
|
||||
|
||||
from abc import abstractmethod
|
||||
from deoplete.logger import LoggingMixin
|
||||
from deoplete.util import error_vim, Nvim, UserContext, Candidates
|
||||
from deoplete.util import error_vim, UserContext, Candidates
|
||||
|
||||
|
||||
class Base(LoggingMixin):
|
||||
@ -22,14 +23,14 @@ class Base(LoggingMixin):
|
||||
def on_event(self, context: UserContext) -> None:
|
||||
pass
|
||||
|
||||
def get_var(self, var_name: str) -> typing.Optional[typing.Any]:
|
||||
def get_var(self, var_name: str) -> typing.Any:
|
||||
custom_vars = self.vim.call(
|
||||
'deoplete#custom#_get_filter', self.name)
|
||||
if var_name in custom_vars:
|
||||
return custom_vars[var_name]
|
||||
if var_name in self.vars:
|
||||
return self.vars[var_name]
|
||||
return None
|
||||
return ''
|
||||
|
||||
@abstractmethod
|
||||
def filter(self, context: UserContext) -> Candidates:
|
||||
|
@ -4,12 +4,13 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from abc import abstractmethod
|
||||
from pynvim import Nvim
|
||||
import re
|
||||
import typing
|
||||
from abc import abstractmethod
|
||||
|
||||
from deoplete.logger import LoggingMixin
|
||||
from deoplete.util import debug, error_vim, Nvim, UserContext, Candidates
|
||||
from deoplete.util import debug, error_vim, UserContext, Candidates
|
||||
|
||||
|
||||
class Base(LoggingMixin):
|
||||
@ -51,6 +52,9 @@ class Base(LoggingMixin):
|
||||
self.max_candidates = 500
|
||||
self.matcher_key = ''
|
||||
self.dup = False
|
||||
self.ignore_case = False
|
||||
self.smart_case = False
|
||||
self.camel_case = False
|
||||
|
||||
def get_complete_position(self, context: UserContext) -> int:
|
||||
m = re.search('(?:' + context['keyword_pattern'] + ')$|$',
|
||||
@ -72,14 +76,14 @@ class Base(LoggingMixin):
|
||||
def on_event(self, context: UserContext) -> None:
|
||||
pass
|
||||
|
||||
def get_var(self, var_name: str) -> typing.Optional[typing.Any]:
|
||||
def get_var(self, var_name: str) -> typing.Any:
|
||||
custom_vars = self.vim.call(
|
||||
'deoplete#custom#_get_source_vars', self.name)
|
||||
if var_name in custom_vars:
|
||||
return custom_vars[var_name]
|
||||
if var_name in self.vars:
|
||||
return self.vars[var_name]
|
||||
return None
|
||||
return ''
|
||||
|
||||
def get_filetype_var(self, filetype: str,
|
||||
var_name: str) -> typing.Optional[typing.Any]:
|
||||
|
@ -4,24 +4,24 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from collections import defaultdict
|
||||
from pathlib import Path
|
||||
from pynvim import Nvim
|
||||
import copy
|
||||
import os.path
|
||||
import msgpack
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
import msgpack
|
||||
import typing
|
||||
|
||||
from collections import defaultdict
|
||||
|
||||
from deoplete import logger
|
||||
from deoplete.exceptions import SourceInitError
|
||||
from deoplete.util import (bytepos2charpos, charpos2bytepos, error, error_tb,
|
||||
import_plugin, get_custom, get_syn_names,
|
||||
convert2candidates, uniq_list_dict, Nvim)
|
||||
convert2candidates, uniq_list_dict)
|
||||
|
||||
UserContext = typing.Dict[str, typing.Any]
|
||||
Candidates = typing.Dict[str, typing.Any]
|
||||
Candidates = typing.List[typing.Dict[str, typing.Any]]
|
||||
Result = typing.Dict[str, typing.Any]
|
||||
|
||||
|
||||
@ -75,7 +75,8 @@ class Child(logger.LoggingMixin):
|
||||
self._vim.call('deoplete#auto_complete', 'Update')
|
||||
|
||||
def main(self, name: str, args: typing.List[typing.Any],
|
||||
queue_id: typing.Optional[int]) -> typing.Optional[Candidates]:
|
||||
queue_id: typing.Optional[int]) -> typing.Optional[
|
||||
typing.Dict[str, typing.Any]]:
|
||||
ret = None
|
||||
if name == 'enable_logging':
|
||||
self._enable_logging()
|
||||
@ -103,6 +104,9 @@ class Child(logger.LoggingMixin):
|
||||
self.is_debug_enabled = True
|
||||
|
||||
def _add_source(self, path: str) -> None:
|
||||
# Resolve symbolic link
|
||||
path = str(Path(path).resolve())
|
||||
|
||||
source = None
|
||||
try:
|
||||
Source = import_plugin(path, 'source', 'Source')
|
||||
@ -110,14 +114,15 @@ class Child(logger.LoggingMixin):
|
||||
return
|
||||
|
||||
source = Source(self._vim)
|
||||
name = os.path.splitext(os.path.basename(path))[0]
|
||||
name = Path(path).stem
|
||||
source.name = getattr(source, 'name', name)
|
||||
source.path = path
|
||||
if source.name in self._loaded_sources:
|
||||
loaded_path = self._loaded_sources.get(source.name, '')
|
||||
if source.name in self._loaded_sources and path != loaded_path:
|
||||
# Duplicated name
|
||||
error_tb(self._vim, 'Duplicated source: %s' % source.name)
|
||||
error_tb(self._vim, 'path: "%s" "%s"' %
|
||||
(path, self._loaded_sources[source.name]))
|
||||
(path, loaded_path))
|
||||
source = None
|
||||
except Exception:
|
||||
error_tb(self._vim, 'Could not load source: %s' % path)
|
||||
@ -129,6 +134,9 @@ class Child(logger.LoggingMixin):
|
||||
f'Loaded Source: {source.name} ({path})')
|
||||
|
||||
def _add_filter(self, path: str) -> None:
|
||||
# Resolve symbolic link
|
||||
path = str(Path(path).resolve())
|
||||
|
||||
f = None
|
||||
try:
|
||||
Filter = import_plugin(path, 'filter', 'Filter')
|
||||
@ -136,14 +144,15 @@ class Child(logger.LoggingMixin):
|
||||
return
|
||||
|
||||
f = Filter(self._vim)
|
||||
name = os.path.splitext(os.path.basename(path))[0]
|
||||
name = Path(path).stem
|
||||
f.name = getattr(f, 'name', name)
|
||||
f.path = path
|
||||
if f.name in self._loaded_filters:
|
||||
loaded_path = self._loaded_filters.get(f.name, '')
|
||||
if f.name in self._loaded_filters and path != loaded_path:
|
||||
# Duplicated name
|
||||
error_tb(self._vim, 'Duplicated filter: %s' % f.name)
|
||||
error_tb(self._vim, 'path: "%s" "%s"' %
|
||||
(path, self._loaded_filters[f.name]))
|
||||
(path, loaded_path))
|
||||
f = None
|
||||
except Exception:
|
||||
# Exception occurred when loading a filter. Log stack trace.
|
||||
@ -230,6 +239,8 @@ class Child(logger.LoggingMixin):
|
||||
source.is_volatile, source.is_async)):
|
||||
return self._prev_results[source.name]
|
||||
|
||||
ctx['bufpath'] = context['bufpath']
|
||||
ctx['cwd'] = context['cwd']
|
||||
ctx['is_async'] = False
|
||||
ctx['is_refresh'] = True
|
||||
ctx['max_abbr_width'] = min(source.max_abbr_width,
|
||||
@ -248,6 +259,8 @@ class Child(logger.LoggingMixin):
|
||||
if ctx['max_menu_width'] > 0:
|
||||
ctx['max_menu_width'] = max(10, ctx['max_menu_width'])
|
||||
|
||||
self._set_context_case(source, ctx)
|
||||
|
||||
# Gathering
|
||||
self._profile_start(ctx, source.name)
|
||||
ctx['vars'] = self._vim.vars
|
||||
@ -289,6 +302,19 @@ class Child(logger.LoggingMixin):
|
||||
except Exception as exc:
|
||||
self._handle_source_exception(source, exc)
|
||||
|
||||
def _set_context_case(self, source: typing.Any,
|
||||
context: UserContext) -> None:
|
||||
case = source.smart_case or source.camel_case
|
||||
ignorecase = source.ignore_case
|
||||
if case:
|
||||
if re.search(r'[A-Z]', context['complete_str']):
|
||||
ignorecase = False
|
||||
else:
|
||||
ignorecase = True
|
||||
context['camelcase'] = source.camel_case
|
||||
context['ignorecase'] = ignorecase
|
||||
context['smartcase'] = source.smart_case
|
||||
|
||||
def _handle_source_exception(self,
|
||||
source: typing.Any, exc: Exception) -> None:
|
||||
if isinstance(exc, SourceInitError):
|
||||
@ -330,8 +356,7 @@ class Child(logger.LoggingMixin):
|
||||
error_tb(self._vim, 'Errors from: %s' % f)
|
||||
|
||||
def _get_candidates(self, result: Result,
|
||||
context_input: str, next_input: str
|
||||
) -> typing.Optional[Candidates]:
|
||||
context_input: str, next_input: str) -> Candidates:
|
||||
source = result['source']
|
||||
|
||||
# Gather async results
|
||||
@ -339,7 +364,7 @@ class Child(logger.LoggingMixin):
|
||||
self._gather_async_results(result, source)
|
||||
|
||||
if not result['candidates']:
|
||||
return None
|
||||
return []
|
||||
|
||||
# Source context
|
||||
ctx = copy.copy(result['context'])
|
||||
@ -349,14 +374,7 @@ class Child(logger.LoggingMixin):
|
||||
ctx['complete_str'] = context_input[ctx['char_position']:]
|
||||
ctx['is_sorted'] = False
|
||||
|
||||
# Set ignorecase
|
||||
case = ctx['smartcase'] or ctx['camelcase']
|
||||
if case:
|
||||
if re.search(r'[A-Z]', ctx['complete_str']):
|
||||
ctx['ignorecase'] = False
|
||||
else:
|
||||
ctx['ignorecase'] = True
|
||||
ignorecase = ctx['ignorecase']
|
||||
self._set_context_case(source, ctx)
|
||||
|
||||
# Match
|
||||
matchers = [self._filters[x] for x
|
||||
@ -397,14 +415,19 @@ class Child(logger.LoggingMixin):
|
||||
for candidates in sorted_candidates:
|
||||
ctx['candidates'] += candidates
|
||||
|
||||
ctx['ignorecase'] = ignorecase
|
||||
|
||||
# On post filter
|
||||
if hasattr(source, 'on_post_filter'):
|
||||
ctx['candidates'] = source.on_post_filter(ctx)
|
||||
|
||||
mark = source.mark + ' '
|
||||
|
||||
# Check user mark set
|
||||
user_mark = self._vim.call(
|
||||
'deoplete#custom#_get_source', source.name).get('mark', '')
|
||||
if user_mark == '':
|
||||
user_mark = self._vim.call(
|
||||
'deoplete#custom#_get_source', '_').get('mark', mark)
|
||||
|
||||
refresh = False
|
||||
refresh_always = self._vim.call(
|
||||
'deoplete#custom#_get_option', 'refresh_always')
|
||||
@ -418,10 +441,13 @@ class Child(logger.LoggingMixin):
|
||||
for candidate in ctx['candidates']:
|
||||
candidate['icase'] = 1
|
||||
candidate['equal'] = refresh
|
||||
candidate['source'] = source.name
|
||||
|
||||
# Set default menu
|
||||
if (mark != ' ' and
|
||||
candidate.get('menu', '').find(mark) != 0):
|
||||
if user_mark == '':
|
||||
# Disable menu
|
||||
candidate['menu'] = ''
|
||||
elif mark != ' ' and candidate.get('menu', '').find(mark) != 0:
|
||||
candidate['menu'] = mark + candidate.get('menu', '')
|
||||
|
||||
if source.dup:
|
||||
@ -431,7 +457,7 @@ class Child(logger.LoggingMixin):
|
||||
# Remove duplicates
|
||||
ctx['candidates'] = uniq_list_dict(ctx['candidates'])
|
||||
|
||||
return ctx['candidates'] # type: ignore
|
||||
return list(ctx['candidates'])
|
||||
|
||||
def _itersource(self, context: UserContext
|
||||
) -> typing.Generator[typing.Any, None, None]:
|
||||
@ -443,7 +469,9 @@ class Child(logger.LoggingMixin):
|
||||
'ignore_sources', ft, []))
|
||||
|
||||
for source_name, source in self._get_sources().items():
|
||||
if source.filetypes is None or source_name in ignore_sources:
|
||||
if source.filetypes is None or (
|
||||
source_name in ignore_sources and
|
||||
context['event'] != 'Manual'):
|
||||
continue
|
||||
if context['sources'] and source_name not in context['sources']:
|
||||
continue
|
||||
@ -509,10 +537,10 @@ class Child(logger.LoggingMixin):
|
||||
context['input'].find(result['prev_input']) == 0)
|
||||
|
||||
def _is_skip(self, context: UserContext, source: typing.Any) -> bool:
|
||||
if 'syntax_names' in context and source.disabled_syntaxes:
|
||||
p = re.compile('(' + '|'.join(source.disabled_syntaxes) + ')$')
|
||||
if next(filter(p.search, context['syntax_names']), None):
|
||||
return True
|
||||
if (context.get('syntax_names', []) and source.disabled_syntaxes
|
||||
and len(set(context['syntax_names']) &
|
||||
set(source.disabled_syntaxes)) > 0):
|
||||
return True
|
||||
|
||||
iminsert = self._vim.call('getbufvar', '%', '&iminsert')
|
||||
if iminsert == 1 and source.is_skip_langmap:
|
||||
@ -536,11 +564,14 @@ class Child(logger.LoggingMixin):
|
||||
Each item in `attrs` is the attribute name.
|
||||
"""
|
||||
attrs = (
|
||||
'camel_case',
|
||||
'converters',
|
||||
'disabled_syntaxes',
|
||||
'dup',
|
||||
'filetypes',
|
||||
'ignore_case',
|
||||
'input_pattern',
|
||||
'input_patterns',
|
||||
'is_debug_enabled',
|
||||
'is_silent',
|
||||
'is_volatile',
|
||||
@ -553,6 +584,7 @@ class Child(logger.LoggingMixin):
|
||||
'max_menu_width',
|
||||
'max_pattern_length',
|
||||
'min_pattern_length',
|
||||
'smart_case',
|
||||
'sorters',
|
||||
)
|
||||
|
||||
|
@ -4,11 +4,12 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
from pynvim import Nvim
|
||||
import re
|
||||
import typing
|
||||
|
||||
from deoplete.util import Nvim
|
||||
from deoplete.util import exists_path
|
||||
|
||||
UserContext = typing.Dict[str, typing.Any]
|
||||
|
||||
@ -48,6 +49,7 @@ class Context(object):
|
||||
'deoplete#util#get_next_input', event),
|
||||
'position': self._vim.call('getpos', '.'),
|
||||
'same_filetypes': same_filetypes,
|
||||
'time': self._vim.call('reltime'),
|
||||
}
|
||||
context.update(self._cached) # type: ignore
|
||||
|
||||
@ -79,26 +81,20 @@ class Context(object):
|
||||
bufname = self._vim.call('bufname', bufnr)
|
||||
cwd = self._vim.call('getcwd')
|
||||
buftype = self._vim.call('getbufvar', '%', '&buftype')
|
||||
bufpath = (bufname if os.path.isabs(bufname)
|
||||
else os.path.join(cwd, bufname))
|
||||
if not os.path.exists(bufpath) or 'nofile' in buftype:
|
||||
bufpath = (bufname if Path(bufname).is_absolute()
|
||||
else str(Path(cwd).joinpath(bufname)))
|
||||
if not exists_path(bufpath) or 'nofile' in buftype:
|
||||
bufpath = ''
|
||||
|
||||
self._cached = {
|
||||
'bufnr': bufnr,
|
||||
'bufname': bufname,
|
||||
'bufpath': bufpath,
|
||||
'camelcase': self._vim.call(
|
||||
'deoplete#custom#_get_option', 'camel_case'),
|
||||
'complete_str': '',
|
||||
'custom': self._vim.call('deoplete#custom#_get'),
|
||||
'cwd': cwd,
|
||||
'encoding': self._vim.options['encoding'],
|
||||
'ignorecase': self._vim.call(
|
||||
'deoplete#custom#_get_option', 'ignore_case'),
|
||||
'is_windows': self._vim.call('has', 'win32'),
|
||||
'smartcase': self._vim.call(
|
||||
'deoplete#custom#_get_option', 'smart_case'),
|
||||
}
|
||||
|
||||
def _get_context_filetype(self,
|
||||
|
@ -4,15 +4,15 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from pathlib import Path
|
||||
from pynvim import Nvim
|
||||
import copy
|
||||
import glob
|
||||
import os
|
||||
import typing
|
||||
|
||||
import deoplete.parent
|
||||
from deoplete import logger
|
||||
from deoplete.context import Context
|
||||
from deoplete.util import error, error_tb, Nvim
|
||||
from deoplete.util import error, error_tb
|
||||
|
||||
UserContext = typing.Dict[str, typing.Any]
|
||||
Candidates = typing.Dict[str, typing.Any]
|
||||
@ -26,7 +26,6 @@ class Deoplete(logger.LoggingMixin):
|
||||
|
||||
self._vim = vim
|
||||
self._runtimepath = ''
|
||||
self._runtimepath_list: typing.List[str] = []
|
||||
self._custom: typing.Dict[str, typing.Dict[str, typing.Any]] = {}
|
||||
self._loaded_paths: typing.Set[str] = set()
|
||||
self._prev_results: typing.Dict[int, Candidates] = {}
|
||||
@ -70,6 +69,8 @@ class Deoplete(logger.LoggingMixin):
|
||||
def completion_begin(self, user_context: UserContext) -> None:
|
||||
if not self._context:
|
||||
self.init_context()
|
||||
else:
|
||||
self._context._init_cached()
|
||||
|
||||
context = self._context.get(user_context['event']) # type: ignore
|
||||
context.update(user_context)
|
||||
@ -96,24 +97,30 @@ class Deoplete(logger.LoggingMixin):
|
||||
if needs_poll:
|
||||
self._vim.call('deoplete#handler#_async_timer_start')
|
||||
|
||||
if not candidates:
|
||||
self._vim.call('deoplete#mapping#_restore_completeopt')
|
||||
|
||||
# Async update is skipped if same.
|
||||
prev_completion = self._vim.vars['deoplete#_prev_completion']
|
||||
|
||||
# Skip if async update is same.
|
||||
# Note: If needs_poll, it cannot be skipped.
|
||||
prev_candidates = prev_completion['candidates']
|
||||
event = context['event']
|
||||
if (event == 'Async' or event == 'Update' and
|
||||
prev_candidates and candidates == prev_candidates):
|
||||
same_candidates = prev_candidates and candidates == prev_candidates
|
||||
if not needs_poll and same_candidates and (
|
||||
event == 'Async' or event == 'Update'):
|
||||
return
|
||||
|
||||
# Skip if old completion.
|
||||
if context['time'] < prev_completion['time']:
|
||||
return
|
||||
|
||||
# error(self._vim, candidates)
|
||||
self._vim.vars['deoplete#_context'] = {
|
||||
'complete_position': position,
|
||||
'complete_str': context['input'][position:],
|
||||
'candidates': candidates,
|
||||
'event': context['event'],
|
||||
'input': context['input'],
|
||||
'is_async': is_async,
|
||||
'time': context['time'],
|
||||
'is_async': needs_poll,
|
||||
}
|
||||
|
||||
if candidates or self._vim.call('deoplete#util#check_popup'):
|
||||
@ -165,9 +172,15 @@ class Deoplete(logger.LoggingMixin):
|
||||
|
||||
def _merge_results(self, context: UserContext) -> typing.Tuple[
|
||||
bool, bool, int, typing.List[typing.Any]]:
|
||||
# If parallel feature is enabled, it is updated frequently.
|
||||
# But if it is single process, it cannot be updated.
|
||||
# So it must be updated.
|
||||
async_check = len(self._parents) > 1 or (
|
||||
context['event'] != 'Async' and context['event'] != 'Update')
|
||||
use_prev = (context['input'] == self._prev_input
|
||||
and context['next_input'] == self._prev_next_input
|
||||
and context['event'] != 'Manual')
|
||||
and context['event'] != 'Manual'
|
||||
and async_check)
|
||||
if not use_prev:
|
||||
self._prev_results = {}
|
||||
|
||||
@ -182,7 +195,8 @@ class Deoplete(logger.LoggingMixin):
|
||||
complete_position = min(x['complete_position'] for x in results)
|
||||
|
||||
all_candidates: typing.List[Candidates] = []
|
||||
for result in sorted(results, key=lambda x: x['rank'], reverse=True):
|
||||
for result in sorted(results,
|
||||
key=lambda x: int(x['rank']), reverse=True):
|
||||
candidates = result['candidates']
|
||||
prefix = context['input'][
|
||||
complete_position:result['complete_position']]
|
||||
@ -218,43 +232,38 @@ class Deoplete(logger.LoggingMixin):
|
||||
parent.enable_logging()
|
||||
self._parents.append(parent)
|
||||
|
||||
def _find_rplugins(self,
|
||||
source: str) -> typing.Generator[str, None, None]:
|
||||
def _find_rplugins(self, source: str) -> typing.List[Path]:
|
||||
"""Search for base.py or *.py
|
||||
|
||||
Searches $VIMRUNTIME/*/rplugin/python3/deoplete/$source[s]/
|
||||
"""
|
||||
if not self._runtimepath_list:
|
||||
return
|
||||
|
||||
sources = (
|
||||
os.path.join('rplugin', 'python3', 'deoplete',
|
||||
source, '*.py'),
|
||||
os.path.join('rplugin', 'python3', 'deoplete',
|
||||
source + 's', '*.py'),
|
||||
os.path.join('rplugin', 'python3', 'deoplete',
|
||||
source, '*', '*.py'),
|
||||
)
|
||||
|
||||
for src in sources:
|
||||
for path in self._runtimepath_list:
|
||||
yield from glob.iglob(os.path.join(path, src))
|
||||
result = []
|
||||
result += self._vim.call(
|
||||
'globpath', self._vim.options['runtimepath'],
|
||||
f'rplugin/python3/deoplete/{source}/*.py', 1, 1)
|
||||
result += self._vim.call(
|
||||
'globpath', self._vim.options['runtimepath'],
|
||||
f'rplugin/python3/deoplete/{source}s/*.py', 1, 1)
|
||||
result += self._vim.call(
|
||||
'globpath', self._vim.options['runtimepath'],
|
||||
f'rplugin/python3/deoplete/{source}/*/*.py', 1, 1)
|
||||
return [Path(x) for x in result]
|
||||
|
||||
def _load_sources(self, context: UserContext) -> None:
|
||||
if not self._parents and self._max_parents == 1:
|
||||
self._add_parent(deoplete.parent.SyncParent)
|
||||
|
||||
for path in self._find_rplugins('source'):
|
||||
if (path in self._loaded_paths
|
||||
or os.path.basename(path) == 'base.py'):
|
||||
if str(path) in self._loaded_paths or path.name == 'base.py':
|
||||
continue
|
||||
self._loaded_paths.add(path)
|
||||
self._loaded_paths.add(str(path))
|
||||
|
||||
if len(self._parents) <= self._parent_count:
|
||||
# Add parent automatically
|
||||
self._add_parent(deoplete.parent.AsyncParent)
|
||||
|
||||
self._parents[self._parent_count].add_source(path)
|
||||
self._parents[self._parent_count].add_source(str(path))
|
||||
self.debug( # type: ignore
|
||||
f'Process {self._parent_count}: {path}')
|
||||
|
||||
@ -267,7 +276,7 @@ class Deoplete(logger.LoggingMixin):
|
||||
def _load_filters(self, context: UserContext) -> None:
|
||||
for path in self._find_rplugins('filter'):
|
||||
for parent in self._parents:
|
||||
parent.add_filter(path)
|
||||
parent.add_filter(str(path))
|
||||
|
||||
def _set_source_attributes(self, context: UserContext) -> None:
|
||||
for parent in self._parents:
|
||||
@ -277,7 +286,6 @@ class Deoplete(logger.LoggingMixin):
|
||||
runtimepath = self._vim.options['runtimepath']
|
||||
if runtimepath != self._runtimepath:
|
||||
self._runtimepath = runtimepath
|
||||
self._runtimepath_list = runtimepath.split(',')
|
||||
self._load_sources(context)
|
||||
self._load_filters(context)
|
||||
|
||||
|
@ -4,9 +4,9 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
# For backward compatibility
|
||||
from pynvim import Nvim
|
||||
|
||||
from deoplete.base.filter import Base as _Base
|
||||
from deoplete.util import Nvim
|
||||
|
||||
|
||||
class Base(_Base):
|
||||
|
@ -4,10 +4,11 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from pynvim import Nvim
|
||||
import typing
|
||||
|
||||
from deoplete.base.filter import Base
|
||||
from deoplete.util import Nvim, UserContext, Candidates
|
||||
from deoplete.util import UserContext, Candidates
|
||||
|
||||
|
||||
class Filter(Base):
|
||||
@ -21,8 +22,7 @@ class Filter(Base):
|
||||
}
|
||||
|
||||
def filter(self, context: UserContext) -> Candidates:
|
||||
delimiters: typing.List[str] = self.get_var( # type: ignore
|
||||
'delimiters')
|
||||
delimiters: typing.List[str] = self.get_var('delimiters')
|
||||
for candidate, delimiter in [
|
||||
[x, last_find(x['abbr'], delimiters)]
|
||||
for x in context['candidates']
|
||||
@ -30,7 +30,7 @@ class Filter(Base):
|
||||
not last_find(x['word'], delimiters) and
|
||||
last_find(x['abbr'], delimiters)]:
|
||||
candidate['word'] += delimiter
|
||||
return context['candidates'] # type: ignore
|
||||
return list(context['candidates'])
|
||||
|
||||
|
||||
def last_find(s: str, needles: typing.List[str]) -> typing.Optional[str]:
|
||||
|
@ -4,10 +4,11 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from pynvim import Nvim
|
||||
import re
|
||||
|
||||
from deoplete.base.filter import Base
|
||||
from deoplete.util import Nvim, UserContext, Candidates
|
||||
from deoplete.util import UserContext, Candidates
|
||||
|
||||
|
||||
class Filter(Base):
|
||||
@ -26,4 +27,4 @@ class Filter(Base):
|
||||
(('abbr' in x and p2.search(x['abbr'])) or
|
||||
('info' in x and p2.search(x['info'])))]:
|
||||
candidate['word'] += '('
|
||||
return context['candidates'] # type: ignore
|
||||
return list(context['candidates'])
|
||||
|
@ -4,10 +4,11 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from pynvim import Nvim
|
||||
import re
|
||||
|
||||
from deoplete.base.filter import Base
|
||||
from deoplete.util import Nvim, UserContext, Candidates
|
||||
from deoplete.util import UserContext, Candidates
|
||||
|
||||
|
||||
class Filter(Base):
|
||||
@ -20,7 +21,7 @@ class Filter(Base):
|
||||
def filter(self, context: UserContext) -> Candidates:
|
||||
complete_str = context['complete_str']
|
||||
if not re.search(r'[A-Z]', complete_str):
|
||||
return context['candidates'] # type: ignore
|
||||
return list(context['candidates'])
|
||||
|
||||
complete_lower = complete_str.lower()
|
||||
complete_len = len(complete_str)
|
||||
@ -29,4 +30,4 @@ class Filter(Base):
|
||||
if x['word'].lower().startswith(complete_lower)]:
|
||||
candidate['word'] = complete_str + candidate[
|
||||
'word'][complete_len:]
|
||||
return context['candidates'] # type: ignore
|
||||
return list(context['candidates'])
|
||||
|
@ -4,11 +4,12 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from pynvim import Nvim
|
||||
import re
|
||||
import typing
|
||||
|
||||
from deoplete.base.filter import Base
|
||||
from deoplete.util import Nvim, UserContext, Candidates
|
||||
from deoplete.util import UserContext, Candidates
|
||||
|
||||
|
||||
class Filter(Base):
|
||||
@ -20,26 +21,36 @@ class Filter(Base):
|
||||
|
||||
def filter(self, context: UserContext) -> Candidates:
|
||||
if not context['next_input']:
|
||||
return context['candidates'] # type: ignore
|
||||
return list(context['candidates'])
|
||||
next_input_words = [x for x in re.split(
|
||||
r'([a-zA-Z_]+|\W)', context['next_input']) if x]
|
||||
|
||||
# Skip parentheses if close parentheses is found after cursor
|
||||
cur_pos = self.vim.call('getcurpos')[1:3]
|
||||
check_pairs = []
|
||||
if self.vim.call('searchpair', '(', '', ')', 'bnw'):
|
||||
check_pairs.append(['(', ')'])
|
||||
if self.vim.call('searchpair', '[', '', ']', 'bnw'):
|
||||
check_pairs.append(['[', ']'])
|
||||
pair_pos = self.vim.call('searchpairpos', '(', '', ')', 'nW')
|
||||
if ('(' in context['input'] and cur_pos < pair_pos and
|
||||
cur_pos[0] == pair_pos[0]):
|
||||
check_pairs.append(['(', ')', pair_pos])
|
||||
pair_pos = self.vim.call('searchpairpos', '[', '', ']', 'nW')
|
||||
if ('[' in context['input'] and cur_pos < pair_pos and
|
||||
cur_pos[0] == pair_pos[0]):
|
||||
check_pairs.append(['[', ']', pair_pos])
|
||||
|
||||
for [overlap, candidate, word] in [
|
||||
[x, y, y['word']] for x, y
|
||||
in [[overlap_length(x['word'], next_input_words), x]
|
||||
for x in context['candidates']] if x > 0]:
|
||||
if [x for x in check_pairs if x[0] in word and x[1] in word]:
|
||||
word_end_pos = (context['complete_position'] +
|
||||
self.vim.call('len', word))
|
||||
if [x for x in check_pairs
|
||||
if x[0] in word and x[1] in word[-overlap:] and
|
||||
word_end_pos >= x[2][1]]:
|
||||
continue
|
||||
if 'abbr' not in candidate:
|
||||
candidate['abbr'] = word
|
||||
candidate['word'] = word[: -overlap]
|
||||
return context['candidates'] # type: ignore
|
||||
return list(context['candidates'])
|
||||
|
||||
|
||||
def overlap_length(left: str, next_input_words: typing.List[str]) -> int:
|
||||
|
@ -4,10 +4,11 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from pynvim import Nvim
|
||||
import re
|
||||
|
||||
from deoplete.base.filter import Base
|
||||
from deoplete.util import Nvim, UserContext, Candidates
|
||||
from deoplete.util import UserContext, Candidates
|
||||
|
||||
|
||||
class Filter(Base):
|
||||
@ -22,4 +23,4 @@ class Filter(Base):
|
||||
if '(' in x['word']]:
|
||||
candidate['word'] = re.sub(r'\(.*\)(\$\d+)?', '',
|
||||
candidate['word'])
|
||||
return context['candidates'] # type: ignore
|
||||
return list(context['candidates'])
|
||||
|
@ -4,11 +4,12 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from pynvim import Nvim
|
||||
import re
|
||||
import typing
|
||||
|
||||
from deoplete.base.filter import Base
|
||||
from deoplete.util import Nvim, UserContext, Candidates
|
||||
from deoplete.util import UserContext, Candidates
|
||||
|
||||
|
||||
class Filter(Base):
|
||||
@ -63,10 +64,10 @@ class Filter(Base):
|
||||
return new_candidates
|
||||
|
||||
def filter(self, context: UserContext) -> Candidates:
|
||||
preferred_order_attrs = self.get_var( # type: ignore
|
||||
preferred_order_attrs = self.get_var(
|
||||
'attrs_order').get(context['filetype'], [])
|
||||
if not context['candidates'] or not preferred_order_attrs:
|
||||
return context['candidates'] # type: ignore
|
||||
return list(context['candidates'])
|
||||
|
||||
max_list_size = self.vim.call(
|
||||
'deoplete#custom#_get_option', 'max_list'
|
||||
|
@ -4,8 +4,10 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from pynvim import Nvim
|
||||
|
||||
from deoplete.base.filter import Base
|
||||
from deoplete.util import truncate_skipping, Nvim, UserContext, Candidates
|
||||
from deoplete.util import truncate_skipping, UserContext, Candidates
|
||||
|
||||
|
||||
class Filter(Base):
|
||||
@ -18,11 +20,11 @@ class Filter(Base):
|
||||
def filter(self, context: UserContext) -> Candidates:
|
||||
max_width = context['max_abbr_width']
|
||||
if max_width <= 0:
|
||||
return context['candidates'] # type: ignore
|
||||
return list(context['candidates'])
|
||||
|
||||
footer_width = max_width / 3
|
||||
for candidate in context['candidates']:
|
||||
candidate['abbr'] = truncate_skipping(
|
||||
candidate.get('abbr', candidate['word']),
|
||||
max_width, '..', footer_width)
|
||||
return context['candidates'] # type: ignore
|
||||
return list(context['candidates'])
|
||||
|
@ -4,8 +4,10 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from pynvim import Nvim
|
||||
|
||||
from deoplete.base.filter import Base
|
||||
from deoplete.util import truncate_skipping, Nvim, UserContext, Candidates
|
||||
from deoplete.util import truncate_skipping, UserContext, Candidates
|
||||
|
||||
|
||||
class Filter(Base):
|
||||
@ -18,11 +20,11 @@ class Filter(Base):
|
||||
def filter(self, context: UserContext) -> Candidates:
|
||||
max_width = context['max_info_width']
|
||||
if not context['candidates'] or max_width <= 0:
|
||||
return context['candidates'] # type: ignore
|
||||
return list(context['candidates'])
|
||||
|
||||
footer_width = 1
|
||||
for candidate in context['candidates']:
|
||||
candidate['info'] = truncate_skipping(
|
||||
candidate.get('info', ''),
|
||||
max_width, '..', footer_width)
|
||||
return context['candidates'] # type: ignore
|
||||
return list(context['candidates'])
|
||||
|
@ -4,8 +4,10 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from pynvim import Nvim
|
||||
|
||||
from deoplete.base.filter import Base
|
||||
from deoplete.util import truncate_skipping, Nvim, UserContext, Candidates
|
||||
from deoplete.util import truncate_skipping, UserContext, Candidates
|
||||
|
||||
|
||||
class Filter(Base):
|
||||
@ -19,11 +21,11 @@ class Filter(Base):
|
||||
max_width = context['max_kind_width']
|
||||
if not context['candidates'] or 'kind' not in context[
|
||||
'candidates'][0] or max_width <= 0:
|
||||
return context['candidates'] # type: ignore
|
||||
return list(context['candidates'])
|
||||
|
||||
footer_width = max_width / 3
|
||||
for candidate in context['candidates']:
|
||||
candidate['kind'] = truncate_skipping(
|
||||
candidate.get('kind', ''),
|
||||
max_width, '..', footer_width)
|
||||
return context['candidates'] # type: ignore
|
||||
return list(context['candidates'])
|
||||
|
@ -4,8 +4,10 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from pynvim import Nvim
|
||||
|
||||
from deoplete.base.filter import Base
|
||||
from deoplete.util import truncate_skipping, Nvim, UserContext, Candidates
|
||||
from deoplete.util import truncate_skipping, UserContext, Candidates
|
||||
|
||||
|
||||
class Filter(Base):
|
||||
@ -19,11 +21,11 @@ class Filter(Base):
|
||||
max_width = context['max_menu_width']
|
||||
if not context['candidates'] or 'menu' not in context[
|
||||
'candidates'][0] or max_width <= 0:
|
||||
return context['candidates'] # type: ignore
|
||||
return list(context['candidates'])
|
||||
|
||||
footer_width = max_width / 3
|
||||
for candidate in context['candidates']:
|
||||
candidate['menu'] = truncate_skipping(
|
||||
candidate.get('menu', ''),
|
||||
max_width, '..', footer_width)
|
||||
return context['candidates'] # type: ignore
|
||||
return list(context['candidates'])
|
||||
|
@ -0,0 +1,23 @@
|
||||
# ============================================================================
|
||||
# FILE: converter_word_abbr.py
|
||||
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from pynvim import Nvim
|
||||
|
||||
from deoplete.base.filter import Base
|
||||
from deoplete.util import UserContext, Candidates
|
||||
|
||||
|
||||
class Filter(Base):
|
||||
def __init__(self, vim: Nvim) -> None:
|
||||
super().__init__(vim)
|
||||
|
||||
self.name = 'converter_word_abbr'
|
||||
self.description = 'word abbr converter'
|
||||
|
||||
def filter(self, context: UserContext) -> Candidates:
|
||||
for candidate in context['candidates']:
|
||||
candidate['abbr'] = candidate['word']
|
||||
return list(context['candidates'])
|
@ -4,13 +4,14 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
from pynvim import Nvim
|
||||
import sys
|
||||
import typing
|
||||
|
||||
from deoplete.base.filter import Base
|
||||
from deoplete.util import error, globruntime
|
||||
from deoplete.util import Nvim, UserContext, Candidates
|
||||
from deoplete.util import UserContext, Candidates
|
||||
|
||||
|
||||
class Filter(Base):
|
||||
@ -26,7 +27,7 @@ class Filter(Base):
|
||||
def filter(self, context: UserContext) -> Candidates:
|
||||
if (not context['candidates'] or not context['input']
|
||||
or self._cpsm is False):
|
||||
return context['candidates'] # type: ignore
|
||||
return list(context['candidates'])
|
||||
|
||||
if self._cpsm is None:
|
||||
errmsg = self._init_cpsm(context)
|
||||
@ -49,7 +50,7 @@ class Filter(Base):
|
||||
found = globruntime(self.vim.options['runtimepath'], fname)
|
||||
errmsg = ''
|
||||
if found:
|
||||
sys.path.insert(0, os.path.dirname(found[0]))
|
||||
sys.path.insert(0, str(Path(found[0]).parent))
|
||||
try:
|
||||
import cpsm_py
|
||||
except ImportError as exc:
|
||||
|
@ -4,9 +4,11 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from pynvim import Nvim
|
||||
import re
|
||||
|
||||
from deoplete.base.filter import Base
|
||||
from deoplete.util import fuzzy_escape, Nvim, UserContext, Candidates
|
||||
from deoplete.util import fuzzy_escape, UserContext, Candidates
|
||||
|
||||
|
||||
class Filter(Base):
|
||||
|
@ -4,12 +4,12 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from pynvim import Nvim
|
||||
import re
|
||||
|
||||
from deoplete.base.filter import Base
|
||||
from deoplete.util import (
|
||||
fuzzy_escape, binary_search_begin, binary_search_end)
|
||||
from deoplete.util import Nvim, UserContext, Candidates
|
||||
from deoplete.util import binary_search_begin, binary_search_end
|
||||
from deoplete.util import fuzzy_escape, UserContext, Candidates
|
||||
|
||||
|
||||
class Filter(Base):
|
||||
@ -25,7 +25,7 @@ class Filter(Base):
|
||||
if context['ignorecase']:
|
||||
complete_str = complete_str.lower()
|
||||
if not complete_str:
|
||||
return context['candidates'] # type: ignore
|
||||
return list(context['candidates'])
|
||||
|
||||
if context['is_sorted']:
|
||||
begin = binary_search_begin(
|
||||
|
@ -4,9 +4,11 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from pynvim import Nvim
|
||||
|
||||
from deoplete.base.filter import Base
|
||||
from deoplete.util import binary_search_begin, binary_search_end
|
||||
from deoplete.util import Nvim, UserContext, Candidates
|
||||
from deoplete.util import UserContext, Candidates
|
||||
|
||||
|
||||
class Filter(Base):
|
||||
@ -32,7 +34,7 @@ class Filter(Base):
|
||||
candidates = context['candidates'][begin:end+1]
|
||||
|
||||
if context['ignorecase']:
|
||||
return candidates # type: ignore
|
||||
return list(candidates)
|
||||
else:
|
||||
candidates = context['candidates']
|
||||
|
||||
|
@ -4,8 +4,10 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from pynvim import Nvim
|
||||
|
||||
from deoplete.base.filter import Base
|
||||
from deoplete.util import Nvim, UserContext, Candidates
|
||||
from deoplete.util import UserContext, Candidates
|
||||
|
||||
|
||||
class Filter(Base):
|
||||
|
@ -0,0 +1,28 @@
|
||||
# ============================================================================
|
||||
# FILE: matcher_matchfuzzy.py
|
||||
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from pynvim import Nvim
|
||||
|
||||
from deoplete.base.filter import Base
|
||||
from deoplete.util import UserContext, Candidates
|
||||
|
||||
|
||||
class Filter(Base):
|
||||
|
||||
def __init__(self, vim: Nvim) -> None:
|
||||
super().__init__(vim)
|
||||
|
||||
self.name = 'matcher_matchfuzzy'
|
||||
self.description = 'matchfuzzy() matcher'
|
||||
|
||||
def filter(self, context: UserContext) -> Candidates:
|
||||
if not self.vim.call('exists', '*matchfuzzy'):
|
||||
return []
|
||||
|
||||
return list(self.vim.call(
|
||||
'matchfuzzy', context['candidates'],
|
||||
context['complete_str'], {'key': 'word'}
|
||||
))
|
@ -4,12 +4,13 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from pynvim import Nvim
|
||||
import re
|
||||
import typing
|
||||
|
||||
from deoplete.base.filter import Base
|
||||
from deoplete.util import getlines
|
||||
from deoplete.util import Nvim, UserContext, Candidates, Candidate
|
||||
from deoplete.util import UserContext, Candidates, Candidate
|
||||
|
||||
|
||||
LINES_MAX = 150
|
||||
@ -39,11 +40,15 @@ class Filter(Base):
|
||||
def filter(self, context: UserContext) -> Candidates:
|
||||
complete_str = context['complete_str'].lower()
|
||||
linenr = context['position'][1]
|
||||
recently_used = self.vim.vars['deoplete#_recently_used']
|
||||
|
||||
def compare(x: Candidate) -> int:
|
||||
word = x['word']
|
||||
matched = int(complete_str in word.lower())
|
||||
lower = x['word'].lower()
|
||||
matched = int(complete_str in lower)
|
||||
score = -matched * 40
|
||||
if [x for x in recently_used if lower.startswith(x)]:
|
||||
score -= 1000
|
||||
if word in self._cache:
|
||||
mru = min([abs(x - linenr) for x in self._cache[word]])
|
||||
mru -= LINES_MAX
|
||||
|
@ -4,8 +4,10 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from pynvim import Nvim
|
||||
|
||||
from deoplete.base.filter import Base
|
||||
from deoplete.util import Nvim, UserContext, Candidates
|
||||
from deoplete.util import UserContext, Candidates
|
||||
|
||||
|
||||
class Filter(Base):
|
||||
@ -18,4 +20,4 @@ class Filter(Base):
|
||||
|
||||
def filter(self, context: UserContext) -> Candidates:
|
||||
return sorted(context['candidates'],
|
||||
key=lambda x: x['word'].swapcase())
|
||||
key=lambda x: str(x['word'].swapcase()))
|
||||
|
@ -8,10 +8,9 @@ import time
|
||||
import logging
|
||||
import typing
|
||||
|
||||
from deoplete.util import Nvim
|
||||
|
||||
from functools import wraps
|
||||
from collections import defaultdict
|
||||
from functools import wraps
|
||||
from pynvim import Nvim
|
||||
|
||||
log_format = '%(asctime)s %(levelname)-8s [%(process)d] (%(name)s) %(message)s'
|
||||
log_message_cooldown = 0.5
|
||||
@ -50,19 +49,11 @@ def setup(vim: Nvim, level: str, output_file: str = '') -> None:
|
||||
level = 'DEBUG'
|
||||
root.setLevel(getattr(logging, level))
|
||||
|
||||
try:
|
||||
import pkg_resources
|
||||
|
||||
pynvim_version = pkg_resources.get_distribution('pynvim').version
|
||||
except Exception:
|
||||
pynvim_version = 'unknown'
|
||||
|
||||
log = getLogger('logging')
|
||||
log.info('--- Deoplete Log Start ---')
|
||||
log.info('%s, Python %s, pynvim %s',
|
||||
log.info('%s, Python %s',
|
||||
vim.call('deoplete#util#neovim_version'),
|
||||
'.'.join(map(str, sys.version_info[:3])),
|
||||
pynvim_version)
|
||||
'.'.join(map(str, sys.version_info[:3])))
|
||||
|
||||
if 'deoplete#_logging_notified' not in vim.vars:
|
||||
vim.vars['deoplete#_logging_notified'] = 1
|
||||
|
@ -4,20 +4,20 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
import time
|
||||
import os
|
||||
import msgpack
|
||||
import subprocess
|
||||
import sys
|
||||
import typing
|
||||
from abc import abstractmethod
|
||||
from functools import partial
|
||||
from pathlib import Path
|
||||
from pynvim import Nvim
|
||||
from queue import Queue
|
||||
import msgpack
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import typing
|
||||
|
||||
from deoplete import logger
|
||||
from deoplete.process import Process
|
||||
from deoplete.util import error_tb, error, Nvim
|
||||
from deoplete.util import error_tb, error
|
||||
|
||||
UserContext = typing.Dict[str, typing.Any]
|
||||
|
||||
@ -91,7 +91,7 @@ class AsyncParent(_Parent):
|
||||
Taken from jedi.api.environment._try_get_same_env.
|
||||
"""
|
||||
exe = sys.executable
|
||||
if not os.path.basename(exe).lower().startswith('python'):
|
||||
if not Path(exe).name.lower().startswith('python'):
|
||||
checks: typing.Tuple[typing.Any, ...]
|
||||
if sys.platform == 'win32':
|
||||
checks = (r'Scripts\python.exe', 'python.exe')
|
||||
@ -103,8 +103,8 @@ class AsyncParent(_Parent):
|
||||
'bin/python',
|
||||
)
|
||||
for check in checks:
|
||||
guess = os.path.join(sys.exec_prefix, check)
|
||||
if os.path.isfile(str(guess)):
|
||||
guess = Path(sys.exec_prefix).joinpath(check)
|
||||
if guess.is_file():
|
||||
return str(guess)
|
||||
if 'python3_host_prog' not in self._vim.vars:
|
||||
return 'python3'
|
||||
|
@ -4,11 +4,12 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from pynvim import Nvim
|
||||
import re
|
||||
|
||||
from deoplete.base.source import Base
|
||||
from deoplete.util import parse_buffer_pattern, getlines
|
||||
from deoplete.util import Nvim, UserContext, Candidates
|
||||
from deoplete.util import UserContext, Candidates
|
||||
|
||||
|
||||
class Source(Base):
|
||||
|
@ -4,9 +4,9 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
# For backward compatibility
|
||||
from pynvim import Nvim
|
||||
|
||||
from deoplete.base.source import Base as _Base
|
||||
from deoplete.util import Nvim
|
||||
|
||||
|
||||
class Base(_Base):
|
||||
|
@ -4,11 +4,12 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from pynvim import Nvim
|
||||
import typing
|
||||
|
||||
from deoplete.base.source import Base
|
||||
from deoplete.util import parse_buffer_pattern, getlines
|
||||
from deoplete.util import Nvim, UserContext, Candidates
|
||||
from deoplete.util import UserContext, Candidates
|
||||
|
||||
|
||||
class Source(Base):
|
||||
|
@ -5,13 +5,13 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
from pynvim import Nvim
|
||||
import re
|
||||
import typing
|
||||
from os.path import exists, dirname
|
||||
|
||||
from deoplete.base.source import Base
|
||||
from deoplete.util import expand, Nvim, UserContext, Candidates
|
||||
from deoplete.util import expand, exists_path, UserContext, Candidates
|
||||
|
||||
|
||||
class Source(Base):
|
||||
@ -26,6 +26,7 @@ class Source(Base):
|
||||
self.events: typing.List[str] = ['InsertEnter']
|
||||
self.vars = {
|
||||
'enable_buffer_path': True,
|
||||
'enable_slash_completion': False,
|
||||
'force_completion_length': -1,
|
||||
}
|
||||
|
||||
@ -39,7 +40,7 @@ class Source(Base):
|
||||
def get_complete_position(self, context: UserContext) -> int:
|
||||
pos = int(context['input'].rfind('/'))
|
||||
force_completion_length = int(
|
||||
self.get_var('force_completion_length')) # type: ignore
|
||||
self.get_var('force_completion_length'))
|
||||
if pos < 0 and force_completion_length >= 0:
|
||||
fmt = '[a-zA-Z0-9.-]{{{}}}$'.format(force_completion_length)
|
||||
m = re.search(fmt, context['input'])
|
||||
@ -55,20 +56,38 @@ class Source(Base):
|
||||
if context['input'].rfind('/') >= 0
|
||||
else './')
|
||||
|
||||
p = self._longest_path_that_exists(context, input_str)
|
||||
if not p or p == '/' or re.search('//+$', p):
|
||||
# Note: context['bufpath'] will be empty if not exists file
|
||||
bufname = context['bufname']
|
||||
bufpath = (bufname if Path(bufname).is_absolute()
|
||||
else str(Path(context['cwd']).joinpath(bufname)))
|
||||
buftype = self.vim.call('getbufvar', '%', '&buftype')
|
||||
if not bufname or 'nofile' in buftype or not self.get_var(
|
||||
'enable_buffer_path'):
|
||||
bufpath = ''
|
||||
|
||||
p = self._longest_path_that_exists(context, input_str, bufpath)
|
||||
slash_completion = bool(self.get_var('enable_slash_completion'))
|
||||
if not p or re.search('//+$', p) or (
|
||||
p == '/' and not slash_completion):
|
||||
return []
|
||||
complete_str = self._substitute_path(context, dirname(p) + '/')
|
||||
if not os.path.isdir(complete_str):
|
||||
|
||||
p = expand(p)
|
||||
if p[-1] != '/':
|
||||
p += '/'
|
||||
complete_str = self._substitute_path(context, p, bufpath)
|
||||
if not Path(complete_str).is_dir():
|
||||
return []
|
||||
hidden = context['complete_str'].find('.') == 0
|
||||
contents: typing.List[typing.Any] = [[], []]
|
||||
try:
|
||||
for item in sorted(os.listdir(complete_str), key=str.lower):
|
||||
for item in sorted([str(x.name) for x
|
||||
in Path(complete_str).iterdir()],
|
||||
key=str.lower):
|
||||
if not hidden and item[0] == '.':
|
||||
continue
|
||||
contents[not os.path.isdir(complete_str + item)].append(item)
|
||||
except PermissionError:
|
||||
is_dir = not Path(complete_str + '/' + item).is_dir()
|
||||
contents[is_dir].append(item)
|
||||
except (PermissionError, FileNotFoundError):
|
||||
pass
|
||||
|
||||
dirs, files = contents
|
||||
@ -76,25 +95,32 @@ class Source(Base):
|
||||
] + [{'word': x} for x in files]
|
||||
|
||||
def _longest_path_that_exists(self, context: UserContext,
|
||||
input_str: str) -> str:
|
||||
input_str: str, bufpath: str) -> str:
|
||||
input_str = re.sub(r'[^/]*$', '', input_str)
|
||||
data = re.split(r'((?:%s+|(?:(?<![\w\s/\.])(?:~|\.{1,2})?/)+))' %
|
||||
self._isfname, input_str)
|
||||
data = [x for x in re.split(
|
||||
r'((?:%s+|(?:(?<![\w\s/\.])(?:~|\.{1,2})?/)+))' %
|
||||
self._isfname, input_str)]
|
||||
data = [''.join(data[i:]) for i in range(len(data))]
|
||||
existing_paths = sorted(filter(lambda x: exists(
|
||||
dirname(self._substitute_path(context, x))), data))
|
||||
existing_paths = sorted(filter(
|
||||
lambda x: exists_path(self._substitute_path(
|
||||
context, x, bufpath)), data))
|
||||
return existing_paths[-1] if existing_paths else ''
|
||||
|
||||
def _substitute_path(self, context: UserContext, path: str) -> str:
|
||||
def _substitute_path(self, context: UserContext,
|
||||
path: str, bufpath: str) -> str:
|
||||
m = re.match(r'(\.{1,2})/+', path)
|
||||
if m:
|
||||
if self.get_var('enable_buffer_path') and context['bufpath']:
|
||||
base = context['bufpath']
|
||||
else:
|
||||
base = os.path.join(context['cwd'], 'x')
|
||||
if not m:
|
||||
return expand(path)
|
||||
|
||||
for _ in m.group(1):
|
||||
base = dirname(base)
|
||||
return os.path.abspath(os.path.join(
|
||||
base, path[len(m.group(0)):])) + '/'
|
||||
return expand(path)
|
||||
if bufpath:
|
||||
base = str(Path(bufpath).parent)
|
||||
else:
|
||||
base = context['cwd']
|
||||
|
||||
if m.group(1) == '..':
|
||||
base = str(Path(base).parent)
|
||||
rest = path[len(m.group(0)):]
|
||||
if rest:
|
||||
return str(Path(base).joinpath(rest)) + '/'
|
||||
else:
|
||||
return base
|
||||
|
@ -4,13 +4,14 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from pynvim import Nvim
|
||||
import re
|
||||
import typing
|
||||
|
||||
from deoplete.base.source import Base
|
||||
from deoplete.util import (
|
||||
convert2list, parse_buffer_pattern, set_pattern, getlines)
|
||||
from deoplete.util import Nvim, UserContext, Candidates
|
||||
from deoplete.util import UserContext, Candidates
|
||||
|
||||
|
||||
class Source(Base):
|
||||
|
@ -4,13 +4,14 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from pynvim import Nvim
|
||||
import re
|
||||
import typing
|
||||
|
||||
from deoplete.base.source import Base
|
||||
from deoplete.util import (
|
||||
convert2list, set_pattern, convert2candidates)
|
||||
from deoplete.util import Nvim, UserContext, Candidates
|
||||
from deoplete.util import UserContext, Candidates
|
||||
|
||||
|
||||
class Source(Base):
|
||||
@ -44,6 +45,8 @@ class Source(Base):
|
||||
|
||||
def _get_complete_position(self, context: UserContext,
|
||||
current_ft: str, filetype: str) -> int:
|
||||
complete_pos = -1
|
||||
|
||||
for omnifunc in convert2list(
|
||||
self.get_filetype_var(filetype, 'functions')):
|
||||
if omnifunc == '' and (filetype == current_ft or
|
||||
@ -69,15 +72,16 @@ class Source(Base):
|
||||
'rubycomplete#Complete',
|
||||
'phpcomplete#CompletePHP']:
|
||||
# In the blacklist
|
||||
return -1
|
||||
continue
|
||||
try:
|
||||
complete_pos = int(self.vim.call(self._omnifunc, 1, ''))
|
||||
except Exception:
|
||||
self.print_error('Error occurred calling omnifunction: ' +
|
||||
self._omnifunc)
|
||||
return -1
|
||||
return complete_pos
|
||||
return -1
|
||||
if complete_pos >= 0:
|
||||
break
|
||||
return complete_pos
|
||||
|
||||
def gather_candidates(self, context: UserContext) -> Candidates:
|
||||
try:
|
||||
@ -95,4 +99,4 @@ class Source(Base):
|
||||
candidate['dup'] = 1
|
||||
candidate['equal'] = 1
|
||||
|
||||
return candidates # type: ignore
|
||||
return list(candidates)
|
||||
|
@ -4,22 +4,18 @@
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from os.path import expandvars
|
||||
from pathlib import Path
|
||||
from pynvim import Nvim
|
||||
from pynvim.api import Buffer
|
||||
import glob
|
||||
import importlib.util
|
||||
import re
|
||||
import sys
|
||||
import traceback
|
||||
import typing
|
||||
import unicodedata
|
||||
|
||||
if importlib.util.find_spec('pynvim'):
|
||||
from pynvim import Nvim
|
||||
from pynvim.api import Buffer
|
||||
else:
|
||||
from neovim import Nvim
|
||||
from neovim.api import Buffer
|
||||
|
||||
UserContext = typing.Dict[str, typing.Any]
|
||||
Candidate = typing.Dict[str, typing.Any]
|
||||
Candidates = typing.List[Candidate]
|
||||
@ -61,17 +57,19 @@ def import_plugin(path: str, source: str,
|
||||
|
||||
If the class exists, add its directory to sys.path.
|
||||
"""
|
||||
name = os.path.splitext(os.path.basename(path))[0]
|
||||
name = str(Path(path).name)[: -3]
|
||||
module_name = 'deoplete.%s.%s' % (source, name)
|
||||
|
||||
spec = importlib.util.spec_from_file_location(module_name, path)
|
||||
if not spec:
|
||||
return None
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module) # type: ignore
|
||||
cls = getattr(module, classname, None)
|
||||
if not cls:
|
||||
return None
|
||||
|
||||
dirname = os.path.dirname(path)
|
||||
dirname = str(Path(path).parent)
|
||||
if dirname not in sys.path:
|
||||
sys.path.insert(0, dirname)
|
||||
return cls
|
||||
@ -96,7 +94,7 @@ def error_tb(vim: Nvim, msg: str) -> None:
|
||||
t, v, tb = sys.exc_info()
|
||||
if t and v and tb:
|
||||
lines += traceback.format_exc().splitlines()
|
||||
lines += ['%s. Use :messages / see above for error details.' % msg]
|
||||
lines += ['%s Use :messages / see above for error details.' % msg]
|
||||
if hasattr(vim, 'err_write'):
|
||||
vim.err_write('[deoplete] %s\n' % '\n'.join(lines))
|
||||
else:
|
||||
@ -141,8 +139,8 @@ def get_custom(custom: typing.Dict[str, typing.Any],
|
||||
return default
|
||||
|
||||
|
||||
def get_syn_names(vim: Nvim) -> str:
|
||||
return str(vim.call('deoplete#util#get_syn_names'))
|
||||
def get_syn_names(vim: Nvim) -> typing.List[str]:
|
||||
return list(vim.call('deoplete#util#get_syn_names'))
|
||||
|
||||
|
||||
def parse_file_pattern(f: typing.Iterable[str],
|
||||
@ -169,8 +167,8 @@ def fuzzy_escape(string: str, camelcase: bool) -> str:
|
||||
|
||||
|
||||
def load_external_module(base: str, module: str) -> None:
|
||||
current = os.path.dirname(os.path.abspath(base))
|
||||
module_dir = os.path.join(os.path.dirname(current), module)
|
||||
current = Path(base).parent.resolve()
|
||||
module_dir = str(current.parent.joinpath(module))
|
||||
if module_dir not in sys.path:
|
||||
sys.path.insert(0, module_dir)
|
||||
|
||||
@ -219,7 +217,20 @@ def charwidth(c: str) -> int:
|
||||
|
||||
|
||||
def expand(path: str) -> str:
|
||||
return os.path.expanduser(os.path.expandvars(path))
|
||||
if path.startswith('~'):
|
||||
try:
|
||||
path = str(Path(path).expanduser())
|
||||
except Exception:
|
||||
pass
|
||||
return expandvars(path)
|
||||
|
||||
|
||||
def exists_path(path: str) -> bool:
|
||||
try:
|
||||
return Path(path).exists()
|
||||
except Exception:
|
||||
pass
|
||||
return False
|
||||
|
||||
|
||||
def getlines(vim: Nvim, start: int = 1,
|
||||
@ -230,7 +241,9 @@ def getlines(vim: Nvim, start: int = 1,
|
||||
lines: typing.List[str] = []
|
||||
current = start
|
||||
while current <= int(end):
|
||||
lines += vim.call('getline', current, current + max_len)
|
||||
# Skip very long lines
|
||||
lines += [x for x in vim.call('getline', current, current + max_len)
|
||||
if len(x) < 300]
|
||||
current += max_len + 1
|
||||
return lines
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
|
||||
sys.path.insert(0, os.path.join(BASE_DIR, 'rplugin/python3'))
|
||||
BASE_DIR = Path(__file__).parent.parent
|
||||
sys.path.insert(0, str(Path(BASE_DIR).joinpath('rplugin/python3')))
|
||||
|
Loading…
Reference in New Issue
Block a user