mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-01-23 12:50: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)
|
- [deoplete-lsp](https://github.com/deoplete-plugins/deoplete-lsp/tree/6299a22bedfb4f814d95cb0010291501472f8fd0)
|
||||||
- [nvim-cmp](https://github.com/hrsh7th/nvim-cmp/tree/3192a0c57837c1ec5bf298e4f3ec984c7d2d60c0)
|
- [nvim-cmp](https://github.com/hrsh7th/nvim-cmp/tree/3192a0c57837c1ec5bf298e4f3ec984c7d2d60c0)
|
||||||
- [coc-neosnippet](https://github.com/notomo/cmp-neosnippet/tree/2d14526af3f02dcea738b4cea520e6ce55c09979)
|
- [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
|
> 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)
|
[![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)
|
[![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
|
Deoplete is the abbreviation of "dark powered neo-completion". It
|
||||||
provides an extensible and asynchronous completion framework for
|
provides an extensible and asynchronous completion framework for
|
||||||
neovim/Vim8.
|
neovim/Vim8.
|
||||||
@ -26,7 +35,7 @@ Here are some [completion sources](https://github.com/Shougo/deoplete.nvim/wiki/
|
|||||||
## Install
|
## Install
|
||||||
|
|
||||||
**Note:** deoplete requires Neovim (0.3.0+ and of course, **latest** is
|
**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.
|
[requirements](#requirements) if you aren't sure whether you have this.
|
||||||
|
|
||||||
Note: deoplete requires msgpack package 1.0.0+.
|
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`.
|
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:
|
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)
|
![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)
|
![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>" : ''
|
return pumvisible() ? "\<C-y>" : ''
|
||||||
endfunction
|
endfunction
|
||||||
function! deoplete#smart_close_popup() abort
|
function! deoplete#smart_close_popup() abort
|
||||||
call deoplete#handler#_skip_next_completion()
|
|
||||||
return pumvisible() ? "\<C-e>" : ''
|
return pumvisible() ? "\<C-e>" : ''
|
||||||
endfunction
|
endfunction
|
||||||
function! deoplete#cancel_popup() abort
|
function! deoplete#cancel_popup() abort
|
||||||
@ -88,3 +87,7 @@ endfunction
|
|||||||
function! deoplete#complete_common_string() abort
|
function! deoplete#complete_common_string() abort
|
||||||
return deoplete#mapping#_complete_common_string()
|
return deoplete#mapping#_complete_common_string()
|
||||||
endfunction
|
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 = {}
|
let s:cached.source_vars = {}
|
||||||
endfunction
|
endfunction
|
||||||
function! deoplete#custom#_init_buffer() abort
|
function! deoplete#custom#_init_buffer() abort
|
||||||
let b:custom = {}
|
let b:deoplete_custom = {}
|
||||||
let b:custom.option = {}
|
let b:deoplete_custom.option = {}
|
||||||
let b:custom.source_vars = {}
|
let b:deoplete_custom.source_vars = {}
|
||||||
let b:custom.filter = {}
|
let b:deoplete_custom.filter = {}
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! deoplete#custom#_update_cache() abort
|
function! deoplete#custom#_update_cache() abort
|
||||||
@ -65,11 +65,11 @@ function! deoplete#custom#_get() abort
|
|||||||
return s:custom
|
return s:custom
|
||||||
endfunction
|
endfunction
|
||||||
function! deoplete#custom#_get_buffer() abort
|
function! deoplete#custom#_get_buffer() abort
|
||||||
if !exists('b:custom')
|
if !exists('b:deoplete_custom')
|
||||||
call deoplete#custom#_init_buffer()
|
call deoplete#custom#_init_buffer()
|
||||||
endif
|
endif
|
||||||
|
|
||||||
return b:custom
|
return b:deoplete_custom
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! deoplete#custom#_get_source(source_name) abort
|
function! deoplete#custom#_get_source(source_name) abort
|
||||||
@ -92,8 +92,14 @@ function! deoplete#custom#_get_filetype_option(name, filetype, default) abort
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
let option = s:cached.option[a:name]
|
let option = s:cached.option[a:name]
|
||||||
let filetype = has_key(option, a:filetype) ? a:filetype : '_'
|
" Check filetype -> a.b filetype -> '_'
|
||||||
return get(option, filetype, a:default)
|
for filetype in [a:filetype] + split(a:filetype, '\.') + ['_']
|
||||||
|
if has_key(option, filetype)
|
||||||
|
return option[filetype]
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
|
||||||
|
return a:default
|
||||||
endfunction
|
endfunction
|
||||||
function! deoplete#custom#_get_source_vars(name) abort
|
function! deoplete#custom#_get_source_vars(name) abort
|
||||||
return get(s:cached.source_vars, a:name, {})
|
return get(s:cached.source_vars, a:name, {})
|
||||||
|
@ -14,7 +14,7 @@ function! deoplete#handler#_init() abort
|
|||||||
for event in [
|
for event in [
|
||||||
\ 'InsertEnter', 'InsertLeave',
|
\ 'InsertEnter', 'InsertLeave',
|
||||||
\ 'BufReadPost', 'BufWritePost',
|
\ 'BufReadPost', 'BufWritePost',
|
||||||
\ 'VimLeavePre',
|
\ 'VimLeavePre', 'FileType',
|
||||||
\ ]
|
\ ]
|
||||||
call s:define_on_event(event)
|
call s:define_on_event(event)
|
||||||
endfor
|
endfor
|
||||||
@ -26,11 +26,7 @@ function! deoplete#handler#_init() abort
|
|||||||
call s:define_completion_via_timer('InsertEnter')
|
call s:define_completion_via_timer('InsertEnter')
|
||||||
endif
|
endif
|
||||||
if deoplete#custom#_get_option('refresh_always')
|
if deoplete#custom#_get_option('refresh_always')
|
||||||
if exists('##TextChangedP')
|
call s:define_completion_via_timer('TextChangedP')
|
||||||
call s:define_completion_via_timer('TextChangedP')
|
|
||||||
else
|
|
||||||
call s:define_completion_via_timer('InsertCharPre')
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" Note: Vim 8 GUI(MacVim and Win32) is broken
|
" 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 context = g:deoplete#_context
|
||||||
let event = get(context, 'event', '')
|
let event = get(context, 'event', '')
|
||||||
if s:is_exiting() || v:insertmode !=# 'i' || s:check_input_method()
|
if s:is_exiting() || v:insertmode !=# 'i' || s:check_input_method()
|
||||||
return
|
\ || !has_key(context, 'candidates')
|
||||||
endif
|
|
||||||
|
|
||||||
if !has_key(context, 'candidates')
|
|
||||||
\ || deoplete#util#get_input(context.event) !=# context.input
|
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -65,6 +57,11 @@ function! deoplete#handler#_do_complete() abort
|
|||||||
let prev.candidates = context.candidates
|
let prev.candidates = context.candidates
|
||||||
let prev.complete_position = context.complete_position
|
let prev.complete_position = context.complete_position
|
||||||
let prev.linenr = line('.')
|
let prev.linenr = line('.')
|
||||||
|
let prev.time = context.time
|
||||||
|
|
||||||
|
if context.event ==# 'Manual'
|
||||||
|
let context.event = ''
|
||||||
|
endif
|
||||||
|
|
||||||
let auto_popup = deoplete#custom#_get_option(
|
let auto_popup = deoplete#custom#_get_option(
|
||||||
\ 'auto_complete_popup') !=# 'manual'
|
\ 'auto_complete_popup') !=# 'manual'
|
||||||
@ -74,13 +71,10 @@ function! deoplete#handler#_do_complete() abort
|
|||||||
let auto_popup = v:true
|
let auto_popup = v:true
|
||||||
endif
|
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
|
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')
|
call feedkeys("\<Plug>_", 'i')
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
@ -108,16 +102,8 @@ function! deoplete#handler#_check_omnifunc(context) abort
|
|||||||
let prev.input = a:context.input
|
let prev.input = a:context.input
|
||||||
let prev.candidates = []
|
let prev.candidates = []
|
||||||
|
|
||||||
if &completeopt =~# 'noselect'
|
call deoplete#mapping#_set_completeopt(v:true)
|
||||||
call deoplete#mapping#_set_completeopt()
|
call feedkeys("\<C-x>\<C-o>", 'in')
|
||||||
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
|
|
||||||
endif
|
endif
|
||||||
endfor
|
endfor
|
||||||
endfor
|
endfor
|
||||||
@ -145,7 +131,7 @@ function! s:completion_timer_stop() abort
|
|||||||
unlet s:completion_timer
|
unlet s:completion_timer
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:check_prev_completion(event) abort
|
function! deoplete#handler#_check_prev_completion(event) abort
|
||||||
let prev = g:deoplete#_prev_completion
|
let prev = g:deoplete#_prev_completion
|
||||||
if a:event ==# 'Async' || a:event ==# 'Update' || mode() !=# 'i'
|
if a:event ==# 'Async' || a:event ==# 'Update' || mode() !=# 'i'
|
||||||
\ || empty(get(prev, 'candidates', []))
|
\ || empty(get(prev, 'candidates', []))
|
||||||
@ -160,8 +146,6 @@ function! s:check_prev_completion(event) abort
|
|||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
call deoplete#mapping#_set_completeopt()
|
|
||||||
|
|
||||||
let mode = deoplete#custom#_get_option('prev_completion_mode')
|
let mode = deoplete#custom#_get_option('prev_completion_mode')
|
||||||
let candidates = copy(prev.candidates)
|
let candidates = copy(prev.candidates)
|
||||||
|
|
||||||
@ -169,9 +153,9 @@ function! s:check_prev_completion(event) abort
|
|||||||
let input = input[prev.complete_position :]
|
let input = input[prev.complete_position :]
|
||||||
let escaped_input = escape(input, '~\.^$[]*')
|
let escaped_input = escape(input, '~\.^$[]*')
|
||||||
let pattern = substitute(escaped_input, '\w', '\\w*\0', 'g')
|
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'
|
if mode ==# 'length'
|
||||||
call filter(candidates, 'len(v:val.word) > len(input)')
|
call filter(candidates, { _, val -> len(val.word) > len(input) })
|
||||||
endif
|
endif
|
||||||
elseif mode ==# 'mirror'
|
elseif mode ==# 'mirror'
|
||||||
" pass
|
" pass
|
||||||
@ -183,7 +167,7 @@ function! s:check_prev_completion(event) abort
|
|||||||
\ 'complete_position': prev.complete_position,
|
\ 'complete_position': prev.complete_position,
|
||||||
\ 'candidates': candidates,
|
\ 'candidates': candidates,
|
||||||
\ }
|
\ }
|
||||||
call feedkeys("\<Plug>+", 'i')
|
return 1
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! deoplete#handler#_async_timer_start() abort
|
function! deoplete#handler#_async_timer_start() abort
|
||||||
@ -198,12 +182,26 @@ endfunction
|
|||||||
function! deoplete#handler#_completion_begin(event) abort
|
function! deoplete#handler#_completion_begin(event) abort
|
||||||
call deoplete#custom#_update_cache()
|
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.candidates = []
|
||||||
|
let g:deoplete#_context.input = cur_input
|
||||||
return
|
return
|
||||||
endif
|
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'
|
if a:event !=# 'Update' && a:event !=# 'Async'
|
||||||
call deoplete#init#_prev_completion()
|
call deoplete#init#_prev_completion()
|
||||||
@ -211,6 +209,11 @@ function! deoplete#handler#_completion_begin(event) abort
|
|||||||
|
|
||||||
call deoplete#util#rpcnotify(
|
call deoplete#util#rpcnotify(
|
||||||
\ 'deoplete_auto_completion_begin', {'event': a:event})
|
\ '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
|
endfunction
|
||||||
function! s:is_skip(event) abort
|
function! s:is_skip(event) abort
|
||||||
if a:event ==# 'TextChangedP' && !empty(v:completed_item)
|
if a:event ==# 'TextChangedP' && !empty(v:completed_item)
|
||||||
@ -231,11 +234,19 @@ function! s:is_skip(event) abort
|
|||||||
return 1
|
return 1
|
||||||
endif
|
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')
|
let auto_complete = deoplete#custom#_get_option('auto_complete')
|
||||||
|
|
||||||
if &paste
|
if &paste
|
||||||
\ || (a:event !=# 'Manual' && a:event !=# 'Update' && !auto_complete)
|
\ || (a:event !=# 'Manual' && a:event !=# 'Update' && !auto_complete)
|
||||||
\ || (&l:completefunc !=# '' && &l:buftype =~# 'nofile')
|
|
||||||
\ || v:insertmode !=# 'i'
|
\ || v:insertmode !=# 'i'
|
||||||
return 1
|
return 1
|
||||||
endif
|
endif
|
||||||
@ -266,6 +277,11 @@ function! s:is_skip_prev_text(event) abort
|
|||||||
endfunction
|
endfunction
|
||||||
function! s:is_skip_text(event) abort
|
function! s:is_skip_text(event) abort
|
||||||
let input = deoplete#util#get_input(a:event)
|
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 lastchar = matchstr(input, '.$')
|
||||||
let skip_multibyte = deoplete#custom#_get_option('skip_multibyte')
|
let skip_multibyte = deoplete#custom#_get_option('skip_multibyte')
|
||||||
@ -280,12 +296,17 @@ function! s:is_skip_text(event) abort
|
|||||||
\ && displaywidth >= &l:textwidth
|
\ && displaywidth >= &l:textwidth
|
||||||
if &l:formatoptions =~# '[ta]'
|
if &l:formatoptions =~# '[ta]'
|
||||||
\ || !empty(filter(deoplete#util#get_syn_names(),
|
\ || !empty(filter(deoplete#util#get_syn_names(),
|
||||||
\ "v:val ==# 'Comment'"))
|
\ { _, val -> val ==# 'Comment' }))
|
||||||
\ || is_virtual
|
\ || is_virtual
|
||||||
return 1
|
return 1
|
||||||
endif
|
endif
|
||||||
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')
|
let skip_chars = deoplete#custom#_get_option('skip_chars')
|
||||||
|
|
||||||
return (a:event !=# 'Manual' && input !=# ''
|
return (a:event !=# 'Manual' && input !=# ''
|
||||||
@ -294,6 +315,32 @@ endfunction
|
|||||||
function! s:check_input_method() abort
|
function! s:check_input_method() abort
|
||||||
return exists('*getimstatus') && getimstatus()
|
return exists('*getimstatus') && getimstatus()
|
||||||
endfunction
|
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
|
function! s:define_on_event(event) abort
|
||||||
if !exists('##' . a:event)
|
if !exists('##' . a:event)
|
||||||
@ -325,11 +372,27 @@ endfunction
|
|||||||
|
|
||||||
function! s:on_complete_done() abort
|
function! s:on_complete_done() abort
|
||||||
if get(v:completed_item, 'word', '') ==# ''
|
if get(v:completed_item, 'word', '') ==# ''
|
||||||
|
\ || !has_key(g:deoplete#_context, 'complete_str')
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
call deoplete#handler#_skip_next_completion()
|
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', '')
|
let user_data = get(v:completed_item, 'user_data', '')
|
||||||
if type(user_data) !=# v:t_string || user_data ==# ''
|
if type(user_data) !=# v:t_string || user_data ==# ''
|
||||||
return
|
return
|
||||||
|
@ -38,7 +38,7 @@ function! deoplete#init#_channel() abort
|
|||||||
return 1
|
return 1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let python3 = get(g:, 'python3_host_prog', 'python3')
|
let python3 = expand(get(g:, 'python3_host_prog', 'python3'), 1)
|
||||||
if !executable(python3)
|
if !executable(python3)
|
||||||
call deoplete#util#print_error(
|
call deoplete#util#print_error(
|
||||||
\ string(python3) . ' is not executable.')
|
\ 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+.')
|
call deoplete#util#print_error('deoplete requires nvim 0.3.0+.')
|
||||||
return 1
|
return 1
|
||||||
endif
|
endif
|
||||||
if !has('nvim') && v:version < 800
|
if !has('nvim') && v:version < 801
|
||||||
call deoplete#util#print_error('deoplete requires Vim 8.0+.')
|
call deoplete#util#print_error('deoplete requires Vim 8.1+.')
|
||||||
return 1
|
return 1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -112,6 +112,7 @@ function! s:init_internal_variables() abort
|
|||||||
call deoplete#init#_prev_completion()
|
call deoplete#init#_prev_completion()
|
||||||
|
|
||||||
let g:deoplete#_context = {}
|
let g:deoplete#_context = {}
|
||||||
|
let g:deoplete#_recently_used = []
|
||||||
|
|
||||||
if !exists('g:deoplete#_logging')
|
if !exists('g:deoplete#_logging')
|
||||||
let g:deoplete#_logging = {}
|
let g:deoplete#_logging = {}
|
||||||
@ -136,7 +137,7 @@ function! s:init_internal_variables() abort
|
|||||||
|
|
||||||
if deoplete#util#has_yarp()
|
if deoplete#util#has_yarp()
|
||||||
" Dummy call is needed to check exists()
|
" Dummy call is needed to check exists()
|
||||||
call neovim_rpc#serveraddr()
|
silent! call neovim_rpc#serveraddr()
|
||||||
if !exists('*neovim_rpc#serveraddr')
|
if !exists('*neovim_rpc#serveraddr')
|
||||||
call deoplete#util#print_error(
|
call deoplete#util#print_error(
|
||||||
\ 'deoplete requires vim-hug-neovim-rpc plugin in Vim.')
|
\ '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(
|
call deoplete#util#print_error(
|
||||||
\ printf('%s is deprecated variable. '.
|
\ 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))
|
call deoplete#custom#var(a:source_name, a:new_var, eval(a:old_var))
|
||||||
endfunction
|
endfunction
|
||||||
function! s:check_custom_option(old_var, new_var) abort
|
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(
|
call deoplete#util#print_error(
|
||||||
\ printf('%s is deprecated variable. '.
|
\ 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))
|
call deoplete#custom#option(a:new_var, eval(a:old_var))
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! deoplete#init#_option() abort
|
function! deoplete#init#_option() abort
|
||||||
" Note: HTML omni func use search().
|
|
||||||
return {
|
return {
|
||||||
\ 'auto_complete': v:true,
|
\ 'auto_complete': v:true,
|
||||||
\ 'auto_complete_delay': 0,
|
\ 'auto_complete_delay': 0,
|
||||||
\ 'auto_complete_popup': 'auto',
|
\ 'auto_complete_popup': 'auto',
|
||||||
\ 'auto_refresh_delay': 100,
|
\ 'auto_refresh_delay': 20,
|
||||||
\ 'camel_case': v:false,
|
|
||||||
\ 'candidate_marks': [],
|
\ 'candidate_marks': [],
|
||||||
|
\ 'overwrite_completeopt': v:true,
|
||||||
\ 'check_stderr': v:true,
|
\ 'check_stderr': v:true,
|
||||||
\ 'complete_suffix': v:true,
|
\ 'complete_suffix': v:true,
|
||||||
\ 'ignore_case': &ignorecase,
|
|
||||||
\ 'ignore_sources': {},
|
\ 'ignore_sources': {},
|
||||||
\ 'keyword_patterns': {'_': '[a-zA-Z_]\k*'},
|
\ 'keyword_patterns': {'_': '[a-zA-Z_]\k*'},
|
||||||
\ 'max_list': 500,
|
\ 'max_list': 500,
|
||||||
\ 'min_pattern_length': 2,
|
\ 'min_pattern_length': 2,
|
||||||
\ 'num_processes': 4,
|
\ 'num_processes': 1,
|
||||||
|
\ 'nofile_complete_filetypes': ['denite-filter'],
|
||||||
\ 'omni_patterns': {},
|
\ 'omni_patterns': {},
|
||||||
\ 'on_insert_enter': v:true,
|
\ 'on_insert_enter': v:true,
|
||||||
\ 'on_text_changed_i': v:true,
|
\ 'on_text_changed_i': v:true,
|
||||||
\ 'prev_completion_mode': '',
|
\ 'prev_completion_mode': 'filter',
|
||||||
\ 'profile': v:false,
|
\ 'profile': v:false,
|
||||||
\ 'refresh_always': v:true,
|
\ 'refresh_always': v:true,
|
||||||
|
\ 'refresh_backspace': v:true,
|
||||||
\ 'skip_chars': ['(', ')'],
|
\ 'skip_chars': ['(', ')'],
|
||||||
\ 'skip_multibyte': v:false,
|
\ 'skip_multibyte': v:false,
|
||||||
\ 'smart_case': &smartcase,
|
|
||||||
\ 'sources': {},
|
\ 'sources': {},
|
||||||
\ 'trigger_key': v:char,
|
\ 'trigger_key': v:char,
|
||||||
\ 'yarp': v:false,
|
\ 'yarp': v:false,
|
||||||
@ -272,6 +274,7 @@ function! deoplete#init#_prev_completion() abort
|
|||||||
\ 'linenr': -1,
|
\ 'linenr': -1,
|
||||||
\ 'candidates': [],
|
\ 'candidates': [],
|
||||||
\ 'complete_position': -1,
|
\ 'complete_position': -1,
|
||||||
|
\ 'time': reltime(),
|
||||||
\ }
|
\ }
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
@ -10,6 +10,12 @@ function! deoplete#mapping#_init() abort
|
|||||||
\ deoplete#mapping#_dummy('deoplete#mapping#_complete')
|
\ deoplete#mapping#_dummy('deoplete#mapping#_complete')
|
||||||
inoremap <expr><silent> <Plug>+
|
inoremap <expr><silent> <Plug>+
|
||||||
\ deoplete#mapping#_dummy('deoplete#mapping#_prev_complete')
|
\ 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
|
endfunction
|
||||||
function! deoplete#mapping#_dummy(func) abort
|
function! deoplete#mapping#_dummy(func) abort
|
||||||
return "\<C-r>=".a:func."()\<CR>"
|
return "\<C-r>=".a:func."()\<CR>"
|
||||||
@ -35,16 +41,41 @@ function! s:check_completion_info(candidates) abort
|
|||||||
endif
|
endif
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
let old_candidates = sort(map(copy(info.items), 'v:val.word'))
|
let old_candidates = sort(map(copy(info.items), { _, val -> val.word }))
|
||||||
return sort(map(copy(a:candidates), 'v:val.word')) ==# old_candidates
|
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
|
endfunction
|
||||||
function! deoplete#mapping#_complete() abort
|
function! deoplete#mapping#_complete() abort
|
||||||
if !has_key(g:deoplete#_context, 'candidates')
|
if !deoplete#mapping#_can_complete()
|
||||||
\ || s:check_completion_info(g:deoplete#_context.candidates)
|
let g:deoplete#_context.candidates = []
|
||||||
\ || !&modifiable
|
|
||||||
return ''
|
return ''
|
||||||
endif
|
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)
|
" echomsg string(g:deoplete#_context)
|
||||||
if empty(g:deoplete#_context.candidates) && deoplete#util#check_popup()
|
if empty(g:deoplete#_context.candidates) && deoplete#util#check_popup()
|
||||||
" Note: call complete() to close the popup
|
" Note: call complete() to close the popup
|
||||||
@ -62,20 +93,34 @@ function! deoplete#mapping#_prev_complete() abort
|
|||||||
return ''
|
return ''
|
||||||
endif
|
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,
|
call complete(g:deoplete#_filtered_prev.complete_position + 1,
|
||||||
\ g:deoplete#_filtered_prev.candidates)
|
\ g:deoplete#_filtered_prev.candidates)
|
||||||
|
|
||||||
return ''
|
return ''
|
||||||
endfunction
|
endfunction
|
||||||
function! deoplete#mapping#_set_completeopt() abort
|
function! deoplete#mapping#_set_completeopt(is_async) abort
|
||||||
if exists('g:deoplete#_saved_completeopt')
|
if !deoplete#custom#_get_option('overwrite_completeopt')
|
||||||
return
|
return
|
||||||
endif
|
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-=longest
|
||||||
set completeopt+=menuone
|
set completeopt+=menuone
|
||||||
set completeopt-=menu
|
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
|
set completeopt+=noselect
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
@ -117,16 +162,9 @@ function! deoplete#mapping#_complete_common_string() abort
|
|||||||
return ''
|
return ''
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let complete_str = prev.input[prev.complete_position :]
|
let complete_str = deoplete#util#get_input('')[prev.complete_position :]
|
||||||
let candidates = filter(copy(prev.candidates),
|
let common_str = prev.candidates[0].word
|
||||||
\ 'stridx(tolower(v:val.word), tolower(complete_str)) == 0')
|
for candidate in prev.candidates[1:]
|
||||||
|
|
||||||
if empty(candidates) || complete_str ==# ''
|
|
||||||
return ''
|
|
||||||
endif
|
|
||||||
|
|
||||||
let common_str = candidates[0].word
|
|
||||||
for candidate in candidates[1:]
|
|
||||||
while stridx(tolower(candidate.word), tolower(common_str)) != 0
|
while stridx(tolower(candidate.word), tolower(common_str)) != 0
|
||||||
let common_str = common_str[: -2]
|
let common_str = common_str[: -2]
|
||||||
endwhile
|
endwhile
|
||||||
|
@ -35,10 +35,6 @@ function! deoplete#util#get_input(event) abort
|
|||||||
\ '^.*\%' . (mode ==# 'i' ? col('.') : col('.') - 1)
|
\ '^.*\%' . (mode ==# 'i' ? col('.') : col('.') - 1)
|
||||||
\ . 'c' . (mode ==# 'i' ? '' : '.'))
|
\ . 'c' . (mode ==# 'i' ? '' : '.'))
|
||||||
|
|
||||||
if a:event ==# 'InsertCharPre'
|
|
||||||
let input .= v:char
|
|
||||||
endif
|
|
||||||
|
|
||||||
return input
|
return input
|
||||||
endfunction
|
endfunction
|
||||||
function! deoplete#util#get_next_input(event) abort
|
function! deoplete#util#get_next_input(event) abort
|
||||||
@ -88,7 +84,7 @@ function! s:vimoption2python(option) abort
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! deoplete#util#uniq(list) abort
|
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 i = 0
|
||||||
let seen = {}
|
let seen = {}
|
||||||
while i < len(list)
|
while i < len(list)
|
||||||
@ -100,7 +96,7 @@ function! deoplete#util#uniq(list) abort
|
|||||||
let i += 1
|
let i += 1
|
||||||
endif
|
endif
|
||||||
endwhile
|
endwhile
|
||||||
return map(list, 'v:val[0]')
|
return map(list, { _, val -> val[0] })
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! deoplete#util#get_syn_names() abort
|
function! deoplete#util#get_syn_names() abort
|
||||||
@ -183,8 +179,8 @@ endfunction
|
|||||||
" >0 if a > b
|
" >0 if a > b
|
||||||
" 0 if versions are equal.
|
" 0 if versions are equal.
|
||||||
function! deoplete#util#versioncmp(a, b) abort
|
function! deoplete#util#versioncmp(a, b) abort
|
||||||
let a = map(split(a:a, '\.'), 'str2nr(v:val)')
|
let a = map(split(a:a, '\.'), { _, val -> str2nr(val) })
|
||||||
let b = map(split(a:b, '\.'), 'str2nr(v:val)')
|
let b = map(split(a:b, '\.'), { _, val -> str2nr(val) })
|
||||||
let l = min([len(a), len(b)])
|
let l = min([len(a), len(b)])
|
||||||
let d = 0
|
let d = 0
|
||||||
|
|
||||||
@ -213,3 +209,17 @@ endfunction
|
|||||||
function! deoplete#util#check_popup() abort
|
function! deoplete#util#check_popup() abort
|
||||||
return exists('*complete_info') && complete_info().mode ==# 'eval'
|
return exists('*complete_info') && complete_info().mode ==# 'eval'
|
||||||
endfunction
|
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 = ' '
|
let indentation = ' '
|
||||||
call health#report_info("If you're still having problems, " .
|
call health#report_info("If you're still having problems, " .
|
||||||
\ "try the following commands:\n" .
|
\ "try the following commands:\n" .
|
||||||
\ indentation . "$ export NVIM_PYTHON_LOG_FILE=/tmp/log\n" .
|
\ indentation . "- $ export NVIM_PYTHON_LOG_FILE=/tmp/log\n" .
|
||||||
\ indentation . "$ export NVIM_PYTHON_LOG_LEVEL=DEBUG\n" .
|
\ indentation . "- $ export NVIM_PYTHON_LOG_LEVEL=DEBUG\n" .
|
||||||
\ indentation . "$ nvim\n" .
|
\ indentation . "- $ nvim\n" .
|
||||||
\ indentation . "$ cat /tmp/log_{PID}\n" .
|
\ indentation . "- $ cat /tmp/log_{PID}\n" .
|
||||||
\ indentation . ' and then create an issue on github'
|
\ indentation . '- and then create an issue on github'
|
||||||
\ )
|
\ )
|
||||||
endfunction
|
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
|
*deoplete.txt* Dark powered asynchronous completion framework for Neovim/Vim8
|
||||||
|
|
||||||
Version: 6.0
|
Version: 6.2
|
||||||
Author: Shougo <Shougo.Matsu at gmail.com>
|
Author: Shougo <Shougo.Matsu at gmail.com>
|
||||||
License: MIT license
|
License: MIT license
|
||||||
|
|
||||||
@ -30,14 +30,14 @@ Compatibility |deoplete-compatibility|
|
|||||||
INTRODUCTION *deoplete-introduction*
|
INTRODUCTION *deoplete-introduction*
|
||||||
|
|
||||||
*deoplete* is the abbreviation of "dark powered neo-completion". It
|
*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.
|
current buffer.
|
||||||
|
|
||||||
Note: deoplete may consume more memory than other plugins do.
|
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.
|
2. Uses Python3 to implement sources.
|
||||||
3. Removes legacy interface.
|
3. Removes legacy interface.
|
||||||
4. Requires |+python3|.
|
4. Requires |+python3|.
|
||||||
@ -45,8 +45,8 @@ Improvements in deoplete in comparison to |neocomplete|:
|
|||||||
==============================================================================
|
==============================================================================
|
||||||
INSTALL *deoplete-install*
|
INSTALL *deoplete-install*
|
||||||
|
|
||||||
Note: deoplete requires Neovim (0.3.0+) or Vim8 (latest is recommended) with
|
Note: deoplete requires Neovim (0.3.0+) or Vim8.1+ (latest is recommended)
|
||||||
Python 3.6.1+ and |+timers| enabled.
|
with Python 3.6.1+ and |+timers| enabled.
|
||||||
|
|
||||||
Please install/upgrade msgpack package (1.0.0+).
|
Please install/upgrade msgpack package (1.0.0+).
|
||||||
https://github.com/msgpack/msgpack-python
|
https://github.com/msgpack/msgpack-python
|
||||||
@ -113,7 +113,7 @@ auto_complete
|
|||||||
auto_complete_delay
|
auto_complete_delay
|
||||||
Delay the completion after input in milliseconds.
|
Delay the completion after input in milliseconds.
|
||||||
|
|
||||||
Default value: 0 (milliseconds)
|
Default value: 20 (milliseconds)
|
||||||
|
|
||||||
*deoplete-options-auto_complete_popup*
|
*deoplete-options-auto_complete_popup*
|
||||||
auto_complete_popup
|
auto_complete_popup
|
||||||
@ -131,21 +131,19 @@ auto_refresh_delay
|
|||||||
|
|
||||||
Default value: 100 (milliseconds)
|
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*
|
*deoplete-options-candidate_marks*
|
||||||
candidate_marks
|
candidate_marks
|
||||||
The candidate additional 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: []
|
Default value: []
|
||||||
>
|
>
|
||||||
call deoplete#custom#option('candidate_marks',
|
call deoplete#custom#option('candidate_marks',
|
||||||
@ -174,16 +172,11 @@ complete_suffix
|
|||||||
|
|
||||||
Default value: v:true
|
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*
|
*deoplete-options-ignore_sources*
|
||||||
ignore_sources
|
ignore_sources
|
||||||
It is a dictionary to decide ignore source names.
|
It is a dictionary to decide ignore source names.
|
||||||
The key is filetype and the value is source names list.
|
The key is filetype and the value is source names list.
|
||||||
|
Note: It is disabled in |deoplete#manual_complete()|.
|
||||||
|
|
||||||
Default value: {}
|
Default value: {}
|
||||||
|
|
||||||
@ -209,15 +202,25 @@ max_list
|
|||||||
|
|
||||||
Default value: 500
|
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*
|
*deoplete-options-num_processes*
|
||||||
num_processes
|
num_processes
|
||||||
The number of processes used for the deoplete parallel
|
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 1, this feature is disabled.
|
||||||
If it is less than or equal to 0, the number of processes is
|
If it is less than or equal to 0, the number of processes is
|
||||||
equal to that of sources.
|
equal to that of sources.
|
||||||
|
|
||||||
Default value: 4
|
Default value: 1
|
||||||
|
|
||||||
*deoplete-options-omni_patterns*
|
*deoplete-options-omni_patterns*
|
||||||
omni_patterns
|
omni_patterns
|
||||||
@ -260,6 +263,14 @@ on_text_changed_i
|
|||||||
Deoplete enables the auto completion on |TextChangedI| autocmd
|
Deoplete enables the auto completion on |TextChangedI| autocmd
|
||||||
if this value is True.
|
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
|
Default value: v:true
|
||||||
|
|
||||||
*deoplete-options-profile*
|
*deoplete-options-profile*
|
||||||
@ -289,13 +300,22 @@ prev_completion_mode
|
|||||||
refresh_always
|
refresh_always
|
||||||
Deoplete refreshes the candidates automatically if this value
|
Deoplete refreshes the candidates automatically if this value
|
||||||
is True.
|
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
|
Default value: v:true
|
||||||
|
|
||||||
*deoplete-options-skip_multibyte*
|
*deoplete-options-skip_multibyte*
|
||||||
skip_multibyte
|
skip_multibyte
|
||||||
Deoplete skip multibyte text completion automatically if this
|
Deoplete skips multibyte text completion automatically if this
|
||||||
value is True.
|
value is True.
|
||||||
|
|
||||||
Default value: v:false
|
Default value: v:false
|
||||||
@ -306,20 +326,13 @@ skip_chars
|
|||||||
|
|
||||||
Default value: ['(', ')']
|
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*
|
*deoplete-options-sources*
|
||||||
sources
|
sources
|
||||||
It is a dictionary to specify source names. The key is
|
It is a dictionary to specify source names. The key is
|
||||||
filetype and the value is source names list. If the key is
|
filetype and the value is a list of source names. If the key
|
||||||
"_", the value will be used for default filetypes. For
|
is "_", the value will be used for default filetypes. For
|
||||||
example, you can load some sources in C++ filetype.
|
example, you can load some sources in C++ filetype. If the
|
||||||
If the value is [], it will load all sources.
|
value is [], it will load all sources.
|
||||||
|
|
||||||
Default value: {}
|
Default value: {}
|
||||||
>
|
>
|
||||||
@ -339,7 +352,7 @@ min_pattern_length
|
|||||||
|
|
||||||
Default: 2
|
Default: 2
|
||||||
|
|
||||||
*deoplete-options-yarp*
|
*deoplete-options-yarp*
|
||||||
yarp
|
yarp
|
||||||
Use nvim-yarp library instead of neovim remote plugin feature.
|
Use nvim-yarp library instead of neovim remote plugin feature.
|
||||||
Note: nvim-yarp plugin is needed.
|
Note: nvim-yarp plugin is needed.
|
||||||
@ -470,7 +483,7 @@ deoplete#custom#source({source-name}, {dict})
|
|||||||
|
|
||||||
" Disable the candidates in Comment/String syntaxes.
|
" Disable the candidates in Comment/String syntaxes.
|
||||||
call deoplete#custom#source('_',
|
call deoplete#custom#source('_',
|
||||||
\ 'disabled_syntaxes', ['Comment', 'String'])
|
\ 'disabled_syntaxes', ['Comment', 'String', 'Constant'])
|
||||||
|
|
||||||
" Change the truncate width.
|
" Change the truncate width.
|
||||||
call deoplete#custom#source('javacomplete2',
|
call deoplete#custom#source('javacomplete2',
|
||||||
@ -492,7 +505,8 @@ deoplete#custom#source({source-name}, {dict})
|
|||||||
" Enable jedi source debug messages
|
" Enable jedi source debug messages
|
||||||
" call deoplete#custom#option('profile', v:true)
|
" call deoplete#custom#option('profile', v:true)
|
||||||
" call deoplete#enable_logging('DEBUG', 'deoplete.log')
|
" 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()*
|
||||||
deoplete#custom#var({source-name}, {var-name}, {value})
|
deoplete#custom#var({source-name}, {var-name}, {value})
|
||||||
@ -510,9 +524,14 @@ KEY MAPPINGS *deoplete-key-mappings*
|
|||||||
deoplete#auto_complete([{event}])
|
deoplete#auto_complete([{event}])
|
||||||
It calls the auto completion of deoplete. You can use it to
|
It calls the auto completion of deoplete. You can use it to
|
||||||
call auto completion again.
|
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.
|
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()*
|
||||||
deoplete#close_popup()
|
deoplete#close_popup()
|
||||||
Insert candidate and close popup menu for deoplete.
|
Insert candidate and close popup menu for deoplete.
|
||||||
@ -525,18 +544,18 @@ deoplete#complete()
|
|||||||
|
|
||||||
*deoplete#complete_common_string()*
|
*deoplete#complete_common_string()*
|
||||||
deoplete#complete_common_string()
|
deoplete#complete_common_string()
|
||||||
complete common string in candidates. It will be convenient
|
complete common string in candidates.
|
||||||
when candidates have long common string.
|
This can be useful when candidates have a long common prefix.
|
||||||
Note: It must be in |:map-<expr>|.
|
Note: It must be in |:map-<expr>|.
|
||||||
|
|
||||||
*deoplete#insert_candidate()*
|
*deoplete#insert_candidate()*
|
||||||
deoplete#insert_candidate({number})
|
deoplete#insert_candidate({index})
|
||||||
Insert {number}th candidate.
|
Insert the candidate at index {index}. Indices start at 0.
|
||||||
Note: It must be in |:map-<expr>|.
|
Note: It must be in |:map-<expr>|.
|
||||||
|
|
||||||
*deoplete#manual_complete()*
|
*deoplete#manual_complete()*
|
||||||
deoplete#manual_complete([{sources}])
|
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.
|
custom completion setups.
|
||||||
You can provide a list of {sources}: It can be the name of a
|
You can provide a list of {sources}: It can be the name of a
|
||||||
source or a list of sources name.
|
source or a list of sources name.
|
||||||
@ -544,16 +563,16 @@ deoplete#manual_complete([{sources}])
|
|||||||
Note: It must be in |:map-<expr>|.
|
Note: It must be in |:map-<expr>|.
|
||||||
|
|
||||||
If you want to trigger deoplete manually, see also
|
If you want to trigger deoplete manually, see also
|
||||||
|deoplete-options-auto_complete|, which should be 1 then
|
|deoplete-options-auto_complete|, which should typically then
|
||||||
typically.
|
be 1.
|
||||||
>
|
>
|
||||||
inoremap <silent><expr> <TAB>
|
inoremap <silent><expr> <TAB>
|
||||||
\ pumvisible() ? "\<C-n>" :
|
\ pumvisible() ? "\<C-n>" :
|
||||||
\ <SID>check_back_space() ? "\<TAB>" :
|
\ <SID>check_back_space() ? "\<TAB>" :
|
||||||
\ deoplete#manual_complete()
|
\ deoplete#manual_complete()
|
||||||
function! s:check_back_space() abort "{{{
|
function! s:check_back_space() abort "{{{
|
||||||
let col = col('.') - 1
|
let col = col('.') - 1
|
||||||
return !col || getline('.')[col - 1] =~ '\s'
|
return !col || getline('.')[col - 1] =~ '\s'
|
||||||
endfunction"}}}
|
endfunction"}}}
|
||||||
<
|
<
|
||||||
*deoplete#smart_close_popup()*
|
*deoplete#smart_close_popup()*
|
||||||
@ -566,13 +585,12 @@ deoplete#smart_close_popup()
|
|||||||
inoremap <expr><BS>
|
inoremap <expr><BS>
|
||||||
\ deoplete#smart_close_popup()."\<C-h>"
|
\ deoplete#smart_close_popup()."\<C-h>"
|
||||||
<
|
<
|
||||||
Note: This mapping conflicts with |SuperTab| or |endwise|
|
Note: This mapping conflicts with SuperTab or endwise plugins.
|
||||||
plugins.
|
|
||||||
Note: This key mapping is for <C-h> or <BS> keymappings.
|
Note: This key mapping is for <C-h> or <BS> keymappings.
|
||||||
|
|
||||||
*deoplete#undo_completion()*
|
*deoplete#undo_completion()*
|
||||||
deoplete#undo_completion()
|
deoplete#undo_completion()
|
||||||
Undo inputted candidate.
|
Undo inserted candidate.
|
||||||
Note: It must be in |:map-<expr>|.
|
Note: It must be in |:map-<expr>|.
|
||||||
>
|
>
|
||||||
inoremap <expr><C-g> deoplete#undo_completion()
|
inoremap <expr><C-g> deoplete#undo_completion()
|
||||||
@ -583,7 +601,7 @@ EXAMPLES *deoplete-examples*
|
|||||||
" Use deoplete.
|
" Use deoplete.
|
||||||
let g:deoplete#enable_at_startup = 1
|
let g:deoplete#enable_at_startup = 1
|
||||||
" Use smartcase.
|
" Use smartcase.
|
||||||
call deoplete#custom#option('smart_case', v:true)
|
call deoplete#custom#source('_', 'smart_case', v:true)
|
||||||
|
|
||||||
" <CR>: close popup and save indent.
|
" <CR>: close popup and save indent.
|
||||||
inoremap <silent> <CR> <C-r>=<SID>my_cr_function()<CR>
|
inoremap <silent> <CR> <C-r>=<SID>my_cr_function()<CR>
|
||||||
@ -656,15 +674,21 @@ file *deoplete-source-file*
|
|||||||
Source custom variables:
|
Source custom variables:
|
||||||
enable_buffer_path
|
enable_buffer_path
|
||||||
If it is True, file source completes the files
|
If it is True, file source completes the files
|
||||||
from the buffer path instead of the current
|
from the buffer directory instead of the
|
||||||
directory.
|
current directory.
|
||||||
(default: v:true)
|
(default: v:true)
|
||||||
|
|
||||||
|
enable_slash_completion
|
||||||
|
If it is True, file source completes the files
|
||||||
|
when user input "/".
|
||||||
|
(default: v:false)
|
||||||
|
|
||||||
force_completion_length
|
force_completion_length
|
||||||
The completion length if the input does not
|
The completion length if the input does not
|
||||||
contain "/".
|
contain "/".
|
||||||
If it is less than 0, it is disabled.
|
If it is less than 0, it is disabled.
|
||||||
(default: -1)
|
(default: -1)
|
||||||
|
|
||||||
member *deoplete-source-member*
|
member *deoplete-source-member*
|
||||||
This source collects members from current buffer.
|
This source collects members from current buffer.
|
||||||
|
|
||||||
@ -706,7 +730,7 @@ omni *deoplete-source-omni*
|
|||||||
setting.
|
setting.
|
||||||
(default: {})
|
(default: {})
|
||||||
>
|
>
|
||||||
call deoplete#custom#source('omni', 'functions', {
|
call deoplete#custom#var('omni', 'functions', {
|
||||||
\ 'javascript': ['tern#Complete', 'jspc#omni']
|
\ 'javascript': ['tern#Complete', 'jspc#omni']
|
||||||
\})
|
\})
|
||||||
<
|
<
|
||||||
@ -730,6 +754,10 @@ omni *deoplete-source-omni*
|
|||||||
==============================================================================
|
==============================================================================
|
||||||
FILTERS *deoplete-filters*
|
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*
|
*deoplete-filter-matcher_default*
|
||||||
Default matchers: ['matcher_fuzzy']
|
Default matchers: ['matcher_fuzzy']
|
||||||
|
|
||||||
@ -778,9 +806,13 @@ matcher_length
|
|||||||
Length matching matcher.
|
Length matching matcher.
|
||||||
It removes candidates shorter than or equal to the user input.
|
It removes candidates shorter than or equal to the user input.
|
||||||
|
|
||||||
|
*deoplete-filter-matcher_matchfuzzy*
|
||||||
|
matcher_matchfuzzy
|
||||||
|
|matchfuzzy()| matcher.
|
||||||
|
|
||||||
*deoplete-filter-sorter_rank*
|
*deoplete-filter-sorter_rank*
|
||||||
sorter_rank Matched rank order sorter. The higher the head matched word
|
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.
|
The locality bonus feature is implemented like VSCode.
|
||||||
|
|
||||||
*deoplete-filter-sorter_word*
|
*deoplete-filter-sorter_word*
|
||||||
@ -889,8 +921,7 @@ converter_reorder_attr
|
|||||||
*deoplete-filter-converter_auto_paren*
|
*deoplete-filter-converter_auto_paren*
|
||||||
converter_auto_paren
|
converter_auto_paren
|
||||||
It adds parentheses character in a candidate's word.
|
It adds parentheses character in a candidate's word.
|
||||||
It is useful if you use |neopairs| or |neosnippet|
|
It is useful if you use neopairs or neosnippet plugins.
|
||||||
plugins.
|
|
||||||
|
|
||||||
*deoplete-filter-converter_case*
|
*deoplete-filter-converter_case*
|
||||||
converter_case
|
converter_case
|
||||||
@ -920,7 +951,10 @@ converter_truncate_info
|
|||||||
converter_truncate_menu
|
converter_truncate_menu
|
||||||
It truncates a candidate's menu by the current window width.
|
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*
|
CREATE SOURCE *deoplete-create-source*
|
||||||
|
|
||||||
To create source, you should read default sources implementation in
|
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
|
The files are automatically loaded and deoplete creates new Source class
|
||||||
object.
|
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.
|
Note: The sources must be written in Python3 language.
|
||||||
|
|
||||||
@ -946,9 +980,20 @@ __init__ (Function)
|
|||||||
*deoplete-source-attribute-__*
|
*deoplete-source-attribute-__*
|
||||||
__{name} (Unspecified) (Optional)
|
__{name} (Unspecified) (Optional)
|
||||||
Additional source information.
|
Additional source information.
|
||||||
Note: Recommend sources save variables instead of
|
Note: Sources should save variables instead of
|
||||||
global variables.
|
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*
|
*deoplete-source-attribute-converters*
|
||||||
converters (List[str]) (Optional)
|
converters (List[str]) (Optional)
|
||||||
Source default converters list.
|
Source default converters list.
|
||||||
@ -989,40 +1034,58 @@ filetypes (List[str]) (Optional)
|
|||||||
Available filetype list.
|
Available filetype list.
|
||||||
|
|
||||||
Default: []
|
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*
|
*deoplete-source-attribute-gather_candidates*
|
||||||
gather_candidates
|
gather_candidates
|
||||||
(Function) (Required)
|
(Function) (Required)
|
||||||
It is called to gather candidates.
|
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}.
|
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
|
{candidate} must be String or Dictionary contains
|
||||||
|deoplete-candidate-attributes|.
|
|deoplete-candidate-attributes|.
|
||||||
Here, {context} is the context information when the source is
|
Here, {context} is the context information when the source is
|
||||||
called (|deoplete-notation-{context}|).
|
called (|deoplete-notation-{context}|).
|
||||||
|
|
||||||
Note: The source must not filter the candidates by user input.
|
Note: The source must not filter the candidates by user input.
|
||||||
It is |deoplete-filters| work. If the source filter the
|
Instead, let the |deoplete-filters| match and sort the
|
||||||
candidates, user cannot filter the candidates by fuzzy match.
|
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*
|
*deoplete-source-attribute-get_complete_position*
|
||||||
get_complete_position
|
get_complete_position
|
||||||
(Function) (Optional)
|
(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
|
It takes {self} and {context} as its parameter and returns
|
||||||
complete position in current line.
|
a number representing the starting position of the completion
|
||||||
Here, {context} is the context information when the source is
|
in the current line.
|
||||||
|
|
||||||
|
Here, {context} is the context information from when the
|
||||||
|
source is called (|deoplete-notation-{context}|).
|
||||||
called (|deoplete-notation-{context}|).
|
called (|deoplete-notation-{context}|).
|
||||||
|
|
||||||
Default: position using |deoplete-options-keyword_patterns|.
|
Default: position using |deoplete-options-keyword_patterns|.
|
||||||
Note: If |deoplete-source-attribute-is_bytepos| is True, it
|
Note: If |deoplete-source-attribute-is_bytepos| is True, it
|
||||||
must return byte position.
|
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*
|
*deoplete-source-attribute-input_pattern*
|
||||||
input_pattern
|
input_pattern
|
||||||
(String) (Optional)
|
(String) (Optional)
|
||||||
If it is matched with input, deoplete ignores
|
If it matches the input, deoplete ignores
|
||||||
|deoplete-source-attribute-min_pattern_length|.
|
|deoplete-source-attribute-min_pattern_length|.
|
||||||
It is useful for omni function sources.
|
It is useful for omni function sources.
|
||||||
Note: It is Python3 regexp.
|
Note: It is Python3 regexp.
|
||||||
@ -1036,7 +1099,7 @@ input_patterns
|
|||||||
The dictionary version of
|
The dictionary version of
|
||||||
|deoplete-source-attribute-input_pattern|.
|
|deoplete-source-attribute-input_pattern|.
|
||||||
A key is filetype and a value is 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*
|
*deoplete-source-attribute-is_bytepos*
|
||||||
is_bytepos
|
is_bytepos
|
||||||
@ -1045,7 +1108,7 @@ is_bytepos
|
|||||||
|deoplete-source-attribute-get_complete_position|
|
|deoplete-source-attribute-get_complete_position|
|
||||||
returns byteposition instead of character position.
|
returns byteposition instead of character position.
|
||||||
It is useful for Vim script to create sources because Vim
|
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.
|
character position.
|
||||||
|
|
||||||
Default: False
|
Default: False
|
||||||
@ -1067,7 +1130,7 @@ is_silent
|
|||||||
*deoplete-source-attribute-is_skip_langmap*
|
*deoplete-source-attribute-is_skip_langmap*
|
||||||
is_skip_langmap
|
is_skip_langmap
|
||||||
(Bool) (Optional)
|
(Bool) (Optional)
|
||||||
If it is True, the source skips the |langmap| completion.
|
If it is True, the source skips the 'langmap' completion.
|
||||||
|
|
||||||
Default: True
|
Default: True
|
||||||
|
|
||||||
@ -1087,6 +1150,11 @@ is_volatile
|
|||||||
*deoplete-source-attribute-mark*
|
*deoplete-source-attribute-mark*
|
||||||
mark (String) (Optional)
|
mark (String) (Optional)
|
||||||
The mark of a source.
|
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*
|
*deoplete-source-attribute-matchers*
|
||||||
matchers (List[str]) (Optional)
|
matchers (List[str]) (Optional)
|
||||||
@ -1104,44 +1172,43 @@ matcher_key (String) (Optional)
|
|||||||
*deoplete-source-attribute-max_abbr_width*
|
*deoplete-source-attribute-max_abbr_width*
|
||||||
max_abbr_width
|
max_abbr_width
|
||||||
(Integer) (Optional)
|
(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.
|
down.
|
||||||
If it is less than or equal to 0, it will be disabled.
|
If it is less than or equal to 0, it will be disabled.
|
||||||
|
|
||||||
Default: 80
|
Default: 80
|
||||||
|
|
||||||
*deoplete-source-attribute-max_candidates*
|
*deoplete-source-attribute-max_candidates*
|
||||||
max_candidates
|
max_candidates
|
||||||
(Integer) (Optional)
|
(Integer) (Optional)
|
||||||
If the candidates are more than it, deoplete will ignore the
|
If there are more candidates than this value, deoplete will
|
||||||
filtering.
|
ignore the filtering.
|
||||||
|
|
||||||
Default: 500
|
Default: 500
|
||||||
|
|
||||||
*deoplete-source-attribute-max_kind_width*
|
*deoplete-source-attribute-max_kind_width*
|
||||||
max_kind_width
|
max_kind_width
|
||||||
(Integer) (Optional)
|
(Integer) (Optional)
|
||||||
If the candidate kind length exceeds the length it will be cut
|
If the candidate kind length exceeds this value it will be
|
||||||
down.
|
trimmed. If this value is less than or equal to 0, it will be
|
||||||
If it is less than or equal to 0, it will be disabled.
|
disabled.
|
||||||
|
|
||||||
Default: 40
|
Default: 40
|
||||||
|
|
||||||
*deoplete-source-attribute-max_info_width*
|
*deoplete-source-attribute-max_info_width*
|
||||||
max_info_width
|
max_info_width
|
||||||
(Integer) (Optional)
|
(Integer) (Optional)
|
||||||
If the candidate info length exceeds the length it will be cut
|
If the candidate info length exceeds this value it is trimmed.
|
||||||
down.
|
If this value is less than or equal to 0, it will be disabled.
|
||||||
If it is less than or equal to 0, it will be disabled.
|
|
||||||
|
|
||||||
Default: 200
|
Default: 200
|
||||||
|
|
||||||
*deoplete-source-attribute-max_menu_width*
|
*deoplete-source-attribute-max_menu_width*
|
||||||
max_menu_width
|
max_menu_width
|
||||||
(Integer) (Optional)
|
(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.
|
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
|
Default: 40
|
||||||
|
|
||||||
@ -1199,6 +1266,13 @@ rank (Integer) (Optional)
|
|||||||
|
|
||||||
Default: 100
|
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*
|
*deoplete-source-attribute-sorters*
|
||||||
sorters (List[str]) (Optional)
|
sorters (List[str]) (Optional)
|
||||||
Source default sorters list.
|
Source default sorters list.
|
||||||
@ -1249,6 +1323,9 @@ vars (Dictionary) (Optional)
|
|||||||
The input string of the current line, namely the part
|
The input string of the current line, namely the part
|
||||||
before the cursor.
|
before the cursor.
|
||||||
|
|
||||||
|
is_refresh (Bool)
|
||||||
|
If the input is changed, it will be "True".
|
||||||
|
|
||||||
is_async (Bool)
|
is_async (Bool)
|
||||||
If the gather is asynchronous, the source must set
|
If the gather is asynchronous, the source must set
|
||||||
it to "True". A typical strategy for an asynchronous
|
it to "True". A typical strategy for an asynchronous
|
||||||
@ -1287,10 +1364,6 @@ vars (Dictionary) (Optional)
|
|||||||
context['is_async'] = self._count < 10
|
context['is_async'] = self._count < 10
|
||||||
return [context['input'].split()[-1] + str(self._count)]
|
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*
|
CANDIDATE ATTRIBUTES *deoplete-candidate-attributes*
|
||||||
|
|
||||||
@ -1333,6 +1406,9 @@ The files are automatically loaded and deoplete creates new Filter class
|
|||||||
object.
|
object.
|
||||||
Filter class must extend Base class in ".base".
|
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.
|
Note: The filters must be written in Python3 language.
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
@ -1362,6 +1438,8 @@ filter
|
|||||||
==============================================================================
|
==============================================================================
|
||||||
EXTERNAL SOURCES *deoplete-external-sources*
|
EXTERNAL SOURCES *deoplete-external-sources*
|
||||||
|
|
||||||
|
Please see https://github.com/Shougo/deoplete.nvim/wiki/Completion-Sources
|
||||||
|
|
||||||
neco-vim: "vim" source for Vim script
|
neco-vim: "vim" source for Vim script
|
||||||
https://github.com/Shougo/neco-vim
|
https://github.com/Shougo/neco-vim
|
||||||
|
|
||||||
@ -1374,124 +1452,11 @@ https://github.com/Shougo/neoinclude.vim
|
|||||||
neco-syntax: "syntax" source
|
neco-syntax: "syntax" source
|
||||||
https://github.com/Shougo/neco-syntax
|
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
|
deoplete-zsh: "zsh" source for Zsh
|
||||||
https://github.com/deoplete-plugins/deoplete-zsh
|
https://github.com/deoplete-plugins/deoplete-zsh
|
||||||
|
|
||||||
deoplete-fish: "fish" source for fish shell
|
deoplete-lsp source for neovim builtin LSP features
|
||||||
https://github.com/ponko2/deoplete-fish
|
https://github.com/deoplete-plugins/deoplete-lsp
|
||||||
|
|
||||||
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-tags: "tag" source for tag files
|
deoplete-tags: "tag" source for tag files
|
||||||
https://github.com/deoplete-plugins/deoplete-tag
|
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#custom#option('profile', v:true)
|
||||||
call deoplete#enable_logging('DEBUG', 'deoplete.log')
|
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.
|
Q: "Channel id must be a positive integer" error.
|
||||||
https://github.com/Shougo/deoplete.nvim/issues/406
|
https://github.com/Shougo/deoplete.nvim/issues/406
|
||||||
@ -1666,6 +1631,13 @@ Q: deoplete conflicts with lexima.vim
|
|||||||
A: >
|
A: >
|
||||||
https://github.com/cohama/lexima.vim/issues/65#issuecomment-339338677
|
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*
|
*deoplete-faq-config*
|
||||||
2. Configuration~
|
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. >
|
A: You can disable the messages through the 'shortmess' option. >
|
||||||
|
|
||||||
if has("patch-7.4.314")
|
set shortmess+=c
|
||||||
set shortmess+=c
|
|
||||||
endif
|
|
||||||
|
|
||||||
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. >
|
A: You can use it by the 'completeopt' option. >
|
||||||
|
|
||||||
@ -1747,6 +1717,11 @@ Q: How can I sort all entries alphabetically?
|
|||||||
A: >
|
A: >
|
||||||
call deoplete#custom#source('_', 'sorters', ['sorter_word'])
|
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.
|
Q: I want to use head matcher instead of fuzzy matcher.
|
||||||
|
|
||||||
A: You can achieve this by following >
|
A: You can achieve this by following >
|
||||||
@ -1848,10 +1823,10 @@ A: >
|
|||||||
inoremap <silent><expr> <TAB>
|
inoremap <silent><expr> <TAB>
|
||||||
\ pumvisible() ? "\<C-n>" :
|
\ pumvisible() ? "\<C-n>" :
|
||||||
\ <SID>check_back_space() ? "\<Tab>" :
|
\ <SID>check_back_space() ? "\<Tab>" :
|
||||||
\ deoplete#complete()
|
\ deoplete#can_complete() ? deoplete#complete() : ''
|
||||||
function! s:check_back_space() abort
|
function! s:check_back_space() abort
|
||||||
let col = col('.') - 1
|
let col = col('.') - 1
|
||||||
return !col || getline('.')[col - 1] =~# '\s'
|
return !col || getline('.')[col - 1] =~# '\s'
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
Q: Why I have to trigger |deoplete#complete()| at least twice for the popup to
|
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() ?
|
inoremap <expr> <C-h> pumvisible() ?
|
||||||
\ "\<C-h>" . deoplete#complete() : "\<C-h>"
|
\ "\<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*
|
*deoplete-faq-ft-specific*
|
||||||
3. Filetype Specific Questions~
|
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.
|
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
|
https://github.com/Shougo/deoplete-clangx
|
||||||
|
|
||||||
@ -1963,10 +1947,10 @@ A: >
|
|||||||
|
|
||||||
Q: How to donate money to you?
|
Q: How to donate money to you?
|
||||||
|
|
||||||
A: I don't get the donation, but if you want to donate, please support neovim
|
A: I have started github sponsorship to spend more time for Vim/neovim
|
||||||
project. My plugins depends on neovim development.
|
plugins. You can donate money to help me!
|
||||||
|
|
||||||
https://salt.bountysource.com/teams/neovim
|
https://github.com/sponsors/Shougo
|
||||||
|
|
||||||
Q: What means "dark powered"?
|
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
|
If you don't like node.js based plugin or huge plugin base system, you
|
||||||
should not choose coc.nvim.
|
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.
|
And the important view is the author.
|
||||||
If you like the author or the author created plugins, you should choose the
|
If you like the author or the author created plugins, you should choose the
|
||||||
auto completion plugin.
|
auto completion plugin.
|
||||||
@ -2021,9 +2010,26 @@ A: deoplete is:
|
|||||||
I don't think deoplete is the best for everyone. Please choose auto
|
I don't think deoplete is the best for everyone. Please choose auto
|
||||||
completion plugin.
|
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*
|
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
|
2020.04.26
|
||||||
* Add deprecated variables warnings.
|
* Add deprecated variables warnings.
|
||||||
|
|
||||||
|
@ -4,19 +4,19 @@
|
|||||||
# License: MIT license
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
|
from importlib.util import find_spec
|
||||||
|
from pynvim import Nvim
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
from importlib.util import find_spec
|
|
||||||
from deoplete.deoplete import Deoplete
|
from deoplete.deoplete import Deoplete
|
||||||
from deoplete.util import Nvim
|
|
||||||
|
|
||||||
|
try:
|
||||||
if find_spec('yarp'):
|
# For Vim8
|
||||||
import vim
|
import vim
|
||||||
elif find_spec('pynvim'):
|
except ModuleNotFoundError:
|
||||||
|
# For neovim
|
||||||
|
# Note: neovim cannot import vim module
|
||||||
import pynvim as vim
|
import pynvim as vim
|
||||||
else:
|
|
||||||
import neovim as vim
|
|
||||||
|
|
||||||
Context = typing.Dict[str, typing.Any]
|
Context = typing.Dict[str, typing.Any]
|
||||||
|
|
||||||
@ -26,8 +26,8 @@ if hasattr(vim, 'plugin'):
|
|||||||
@vim.plugin
|
@vim.plugin
|
||||||
class DeopleteHandlers(object):
|
class DeopleteHandlers(object):
|
||||||
|
|
||||||
def __init__(self, vim: Nvim):
|
def __init__(self, _vim: Nvim):
|
||||||
self._vim = vim
|
self._vim = _vim
|
||||||
|
|
||||||
@vim.function('_deoplete_init', sync=False) # type: ignore
|
@vim.function('_deoplete_init', sync=False) # type: ignore
|
||||||
def init_channel(self,
|
def init_channel(self,
|
||||||
|
@ -4,11 +4,12 @@
|
|||||||
# License: MIT license
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
|
from pynvim import Nvim
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
from abc import abstractmethod
|
from abc import abstractmethod
|
||||||
from deoplete.logger import LoggingMixin
|
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):
|
class Base(LoggingMixin):
|
||||||
@ -22,14 +23,14 @@ class Base(LoggingMixin):
|
|||||||
def on_event(self, context: UserContext) -> None:
|
def on_event(self, context: UserContext) -> None:
|
||||||
pass
|
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(
|
custom_vars = self.vim.call(
|
||||||
'deoplete#custom#_get_filter', self.name)
|
'deoplete#custom#_get_filter', self.name)
|
||||||
if var_name in custom_vars:
|
if var_name in custom_vars:
|
||||||
return custom_vars[var_name]
|
return custom_vars[var_name]
|
||||||
if var_name in self.vars:
|
if var_name in self.vars:
|
||||||
return self.vars[var_name]
|
return self.vars[var_name]
|
||||||
return None
|
return ''
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def filter(self, context: UserContext) -> Candidates:
|
def filter(self, context: UserContext) -> Candidates:
|
||||||
|
@ -4,12 +4,13 @@
|
|||||||
# License: MIT license
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
|
from abc import abstractmethod
|
||||||
|
from pynvim import Nvim
|
||||||
import re
|
import re
|
||||||
import typing
|
import typing
|
||||||
from abc import abstractmethod
|
|
||||||
|
|
||||||
from deoplete.logger import LoggingMixin
|
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):
|
class Base(LoggingMixin):
|
||||||
@ -51,6 +52,9 @@ class Base(LoggingMixin):
|
|||||||
self.max_candidates = 500
|
self.max_candidates = 500
|
||||||
self.matcher_key = ''
|
self.matcher_key = ''
|
||||||
self.dup = False
|
self.dup = False
|
||||||
|
self.ignore_case = False
|
||||||
|
self.smart_case = False
|
||||||
|
self.camel_case = False
|
||||||
|
|
||||||
def get_complete_position(self, context: UserContext) -> int:
|
def get_complete_position(self, context: UserContext) -> int:
|
||||||
m = re.search('(?:' + context['keyword_pattern'] + ')$|$',
|
m = re.search('(?:' + context['keyword_pattern'] + ')$|$',
|
||||||
@ -72,14 +76,14 @@ class Base(LoggingMixin):
|
|||||||
def on_event(self, context: UserContext) -> None:
|
def on_event(self, context: UserContext) -> None:
|
||||||
pass
|
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(
|
custom_vars = self.vim.call(
|
||||||
'deoplete#custom#_get_source_vars', self.name)
|
'deoplete#custom#_get_source_vars', self.name)
|
||||||
if var_name in custom_vars:
|
if var_name in custom_vars:
|
||||||
return custom_vars[var_name]
|
return custom_vars[var_name]
|
||||||
if var_name in self.vars:
|
if var_name in self.vars:
|
||||||
return self.vars[var_name]
|
return self.vars[var_name]
|
||||||
return None
|
return ''
|
||||||
|
|
||||||
def get_filetype_var(self, filetype: str,
|
def get_filetype_var(self, filetype: str,
|
||||||
var_name: str) -> typing.Optional[typing.Any]:
|
var_name: str) -> typing.Optional[typing.Any]:
|
||||||
|
@ -4,24 +4,24 @@
|
|||||||
# License: MIT license
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
|
from collections import defaultdict
|
||||||
|
from pathlib import Path
|
||||||
|
from pynvim import Nvim
|
||||||
import copy
|
import copy
|
||||||
import os.path
|
import msgpack
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import msgpack
|
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
from collections import defaultdict
|
|
||||||
|
|
||||||
from deoplete import logger
|
from deoplete import logger
|
||||||
from deoplete.exceptions import SourceInitError
|
from deoplete.exceptions import SourceInitError
|
||||||
from deoplete.util import (bytepos2charpos, charpos2bytepos, error, error_tb,
|
from deoplete.util import (bytepos2charpos, charpos2bytepos, error, error_tb,
|
||||||
import_plugin, get_custom, get_syn_names,
|
import_plugin, get_custom, get_syn_names,
|
||||||
convert2candidates, uniq_list_dict, Nvim)
|
convert2candidates, uniq_list_dict)
|
||||||
|
|
||||||
UserContext = typing.Dict[str, typing.Any]
|
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]
|
Result = typing.Dict[str, typing.Any]
|
||||||
|
|
||||||
|
|
||||||
@ -75,7 +75,8 @@ class Child(logger.LoggingMixin):
|
|||||||
self._vim.call('deoplete#auto_complete', 'Update')
|
self._vim.call('deoplete#auto_complete', 'Update')
|
||||||
|
|
||||||
def main(self, name: str, args: typing.List[typing.Any],
|
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
|
ret = None
|
||||||
if name == 'enable_logging':
|
if name == 'enable_logging':
|
||||||
self._enable_logging()
|
self._enable_logging()
|
||||||
@ -103,6 +104,9 @@ class Child(logger.LoggingMixin):
|
|||||||
self.is_debug_enabled = True
|
self.is_debug_enabled = True
|
||||||
|
|
||||||
def _add_source(self, path: str) -> None:
|
def _add_source(self, path: str) -> None:
|
||||||
|
# Resolve symbolic link
|
||||||
|
path = str(Path(path).resolve())
|
||||||
|
|
||||||
source = None
|
source = None
|
||||||
try:
|
try:
|
||||||
Source = import_plugin(path, 'source', 'Source')
|
Source = import_plugin(path, 'source', 'Source')
|
||||||
@ -110,14 +114,15 @@ class Child(logger.LoggingMixin):
|
|||||||
return
|
return
|
||||||
|
|
||||||
source = Source(self._vim)
|
source = Source(self._vim)
|
||||||
name = os.path.splitext(os.path.basename(path))[0]
|
name = Path(path).stem
|
||||||
source.name = getattr(source, 'name', name)
|
source.name = getattr(source, 'name', name)
|
||||||
source.path = path
|
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
|
# Duplicated name
|
||||||
error_tb(self._vim, 'Duplicated source: %s' % source.name)
|
error_tb(self._vim, 'Duplicated source: %s' % source.name)
|
||||||
error_tb(self._vim, 'path: "%s" "%s"' %
|
error_tb(self._vim, 'path: "%s" "%s"' %
|
||||||
(path, self._loaded_sources[source.name]))
|
(path, loaded_path))
|
||||||
source = None
|
source = None
|
||||||
except Exception:
|
except Exception:
|
||||||
error_tb(self._vim, 'Could not load source: %s' % path)
|
error_tb(self._vim, 'Could not load source: %s' % path)
|
||||||
@ -129,6 +134,9 @@ class Child(logger.LoggingMixin):
|
|||||||
f'Loaded Source: {source.name} ({path})')
|
f'Loaded Source: {source.name} ({path})')
|
||||||
|
|
||||||
def _add_filter(self, path: str) -> None:
|
def _add_filter(self, path: str) -> None:
|
||||||
|
# Resolve symbolic link
|
||||||
|
path = str(Path(path).resolve())
|
||||||
|
|
||||||
f = None
|
f = None
|
||||||
try:
|
try:
|
||||||
Filter = import_plugin(path, 'filter', 'Filter')
|
Filter = import_plugin(path, 'filter', 'Filter')
|
||||||
@ -136,14 +144,15 @@ class Child(logger.LoggingMixin):
|
|||||||
return
|
return
|
||||||
|
|
||||||
f = Filter(self._vim)
|
f = Filter(self._vim)
|
||||||
name = os.path.splitext(os.path.basename(path))[0]
|
name = Path(path).stem
|
||||||
f.name = getattr(f, 'name', name)
|
f.name = getattr(f, 'name', name)
|
||||||
f.path = path
|
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
|
# Duplicated name
|
||||||
error_tb(self._vim, 'Duplicated filter: %s' % f.name)
|
error_tb(self._vim, 'Duplicated filter: %s' % f.name)
|
||||||
error_tb(self._vim, 'path: "%s" "%s"' %
|
error_tb(self._vim, 'path: "%s" "%s"' %
|
||||||
(path, self._loaded_filters[f.name]))
|
(path, loaded_path))
|
||||||
f = None
|
f = None
|
||||||
except Exception:
|
except Exception:
|
||||||
# Exception occurred when loading a filter. Log stack trace.
|
# Exception occurred when loading a filter. Log stack trace.
|
||||||
@ -230,6 +239,8 @@ class Child(logger.LoggingMixin):
|
|||||||
source.is_volatile, source.is_async)):
|
source.is_volatile, source.is_async)):
|
||||||
return self._prev_results[source.name]
|
return self._prev_results[source.name]
|
||||||
|
|
||||||
|
ctx['bufpath'] = context['bufpath']
|
||||||
|
ctx['cwd'] = context['cwd']
|
||||||
ctx['is_async'] = False
|
ctx['is_async'] = False
|
||||||
ctx['is_refresh'] = True
|
ctx['is_refresh'] = True
|
||||||
ctx['max_abbr_width'] = min(source.max_abbr_width,
|
ctx['max_abbr_width'] = min(source.max_abbr_width,
|
||||||
@ -248,6 +259,8 @@ class Child(logger.LoggingMixin):
|
|||||||
if ctx['max_menu_width'] > 0:
|
if ctx['max_menu_width'] > 0:
|
||||||
ctx['max_menu_width'] = max(10, ctx['max_menu_width'])
|
ctx['max_menu_width'] = max(10, ctx['max_menu_width'])
|
||||||
|
|
||||||
|
self._set_context_case(source, ctx)
|
||||||
|
|
||||||
# Gathering
|
# Gathering
|
||||||
self._profile_start(ctx, source.name)
|
self._profile_start(ctx, source.name)
|
||||||
ctx['vars'] = self._vim.vars
|
ctx['vars'] = self._vim.vars
|
||||||
@ -289,6 +302,19 @@ class Child(logger.LoggingMixin):
|
|||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
self._handle_source_exception(source, 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,
|
def _handle_source_exception(self,
|
||||||
source: typing.Any, exc: Exception) -> None:
|
source: typing.Any, exc: Exception) -> None:
|
||||||
if isinstance(exc, SourceInitError):
|
if isinstance(exc, SourceInitError):
|
||||||
@ -330,8 +356,7 @@ class Child(logger.LoggingMixin):
|
|||||||
error_tb(self._vim, 'Errors from: %s' % f)
|
error_tb(self._vim, 'Errors from: %s' % f)
|
||||||
|
|
||||||
def _get_candidates(self, result: Result,
|
def _get_candidates(self, result: Result,
|
||||||
context_input: str, next_input: str
|
context_input: str, next_input: str) -> Candidates:
|
||||||
) -> typing.Optional[Candidates]:
|
|
||||||
source = result['source']
|
source = result['source']
|
||||||
|
|
||||||
# Gather async results
|
# Gather async results
|
||||||
@ -339,7 +364,7 @@ class Child(logger.LoggingMixin):
|
|||||||
self._gather_async_results(result, source)
|
self._gather_async_results(result, source)
|
||||||
|
|
||||||
if not result['candidates']:
|
if not result['candidates']:
|
||||||
return None
|
return []
|
||||||
|
|
||||||
# Source context
|
# Source context
|
||||||
ctx = copy.copy(result['context'])
|
ctx = copy.copy(result['context'])
|
||||||
@ -349,14 +374,7 @@ class Child(logger.LoggingMixin):
|
|||||||
ctx['complete_str'] = context_input[ctx['char_position']:]
|
ctx['complete_str'] = context_input[ctx['char_position']:]
|
||||||
ctx['is_sorted'] = False
|
ctx['is_sorted'] = False
|
||||||
|
|
||||||
# Set ignorecase
|
self._set_context_case(source, ctx)
|
||||||
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']
|
|
||||||
|
|
||||||
# Match
|
# Match
|
||||||
matchers = [self._filters[x] for x
|
matchers = [self._filters[x] for x
|
||||||
@ -397,14 +415,19 @@ class Child(logger.LoggingMixin):
|
|||||||
for candidates in sorted_candidates:
|
for candidates in sorted_candidates:
|
||||||
ctx['candidates'] += candidates
|
ctx['candidates'] += candidates
|
||||||
|
|
||||||
ctx['ignorecase'] = ignorecase
|
|
||||||
|
|
||||||
# On post filter
|
# On post filter
|
||||||
if hasattr(source, 'on_post_filter'):
|
if hasattr(source, 'on_post_filter'):
|
||||||
ctx['candidates'] = source.on_post_filter(ctx)
|
ctx['candidates'] = source.on_post_filter(ctx)
|
||||||
|
|
||||||
mark = source.mark + ' '
|
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 = False
|
||||||
refresh_always = self._vim.call(
|
refresh_always = self._vim.call(
|
||||||
'deoplete#custom#_get_option', 'refresh_always')
|
'deoplete#custom#_get_option', 'refresh_always')
|
||||||
@ -418,10 +441,13 @@ class Child(logger.LoggingMixin):
|
|||||||
for candidate in ctx['candidates']:
|
for candidate in ctx['candidates']:
|
||||||
candidate['icase'] = 1
|
candidate['icase'] = 1
|
||||||
candidate['equal'] = refresh
|
candidate['equal'] = refresh
|
||||||
|
candidate['source'] = source.name
|
||||||
|
|
||||||
# Set default menu
|
# Set default menu
|
||||||
if (mark != ' ' and
|
if user_mark == '':
|
||||||
candidate.get('menu', '').find(mark) != 0):
|
# Disable menu
|
||||||
|
candidate['menu'] = ''
|
||||||
|
elif mark != ' ' and candidate.get('menu', '').find(mark) != 0:
|
||||||
candidate['menu'] = mark + candidate.get('menu', '')
|
candidate['menu'] = mark + candidate.get('menu', '')
|
||||||
|
|
||||||
if source.dup:
|
if source.dup:
|
||||||
@ -431,7 +457,7 @@ class Child(logger.LoggingMixin):
|
|||||||
# Remove duplicates
|
# Remove duplicates
|
||||||
ctx['candidates'] = uniq_list_dict(ctx['candidates'])
|
ctx['candidates'] = uniq_list_dict(ctx['candidates'])
|
||||||
|
|
||||||
return ctx['candidates'] # type: ignore
|
return list(ctx['candidates'])
|
||||||
|
|
||||||
def _itersource(self, context: UserContext
|
def _itersource(self, context: UserContext
|
||||||
) -> typing.Generator[typing.Any, None, None]:
|
) -> typing.Generator[typing.Any, None, None]:
|
||||||
@ -443,7 +469,9 @@ class Child(logger.LoggingMixin):
|
|||||||
'ignore_sources', ft, []))
|
'ignore_sources', ft, []))
|
||||||
|
|
||||||
for source_name, source in self._get_sources().items():
|
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
|
continue
|
||||||
if context['sources'] and source_name not in context['sources']:
|
if context['sources'] and source_name not in context['sources']:
|
||||||
continue
|
continue
|
||||||
@ -509,10 +537,10 @@ class Child(logger.LoggingMixin):
|
|||||||
context['input'].find(result['prev_input']) == 0)
|
context['input'].find(result['prev_input']) == 0)
|
||||||
|
|
||||||
def _is_skip(self, context: UserContext, source: typing.Any) -> bool:
|
def _is_skip(self, context: UserContext, source: typing.Any) -> bool:
|
||||||
if 'syntax_names' in context and source.disabled_syntaxes:
|
if (context.get('syntax_names', []) and source.disabled_syntaxes
|
||||||
p = re.compile('(' + '|'.join(source.disabled_syntaxes) + ')$')
|
and len(set(context['syntax_names']) &
|
||||||
if next(filter(p.search, context['syntax_names']), None):
|
set(source.disabled_syntaxes)) > 0):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
iminsert = self._vim.call('getbufvar', '%', '&iminsert')
|
iminsert = self._vim.call('getbufvar', '%', '&iminsert')
|
||||||
if iminsert == 1 and source.is_skip_langmap:
|
if iminsert == 1 and source.is_skip_langmap:
|
||||||
@ -536,11 +564,14 @@ class Child(logger.LoggingMixin):
|
|||||||
Each item in `attrs` is the attribute name.
|
Each item in `attrs` is the attribute name.
|
||||||
"""
|
"""
|
||||||
attrs = (
|
attrs = (
|
||||||
|
'camel_case',
|
||||||
'converters',
|
'converters',
|
||||||
'disabled_syntaxes',
|
'disabled_syntaxes',
|
||||||
'dup',
|
'dup',
|
||||||
'filetypes',
|
'filetypes',
|
||||||
|
'ignore_case',
|
||||||
'input_pattern',
|
'input_pattern',
|
||||||
|
'input_patterns',
|
||||||
'is_debug_enabled',
|
'is_debug_enabled',
|
||||||
'is_silent',
|
'is_silent',
|
||||||
'is_volatile',
|
'is_volatile',
|
||||||
@ -553,6 +584,7 @@ class Child(logger.LoggingMixin):
|
|||||||
'max_menu_width',
|
'max_menu_width',
|
||||||
'max_pattern_length',
|
'max_pattern_length',
|
||||||
'min_pattern_length',
|
'min_pattern_length',
|
||||||
|
'smart_case',
|
||||||
'sorters',
|
'sorters',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -4,11 +4,12 @@
|
|||||||
# License: MIT license
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
import os
|
from pathlib import Path
|
||||||
|
from pynvim import Nvim
|
||||||
import re
|
import re
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
from deoplete.util import Nvim
|
from deoplete.util import exists_path
|
||||||
|
|
||||||
UserContext = typing.Dict[str, typing.Any]
|
UserContext = typing.Dict[str, typing.Any]
|
||||||
|
|
||||||
@ -48,6 +49,7 @@ class Context(object):
|
|||||||
'deoplete#util#get_next_input', event),
|
'deoplete#util#get_next_input', event),
|
||||||
'position': self._vim.call('getpos', '.'),
|
'position': self._vim.call('getpos', '.'),
|
||||||
'same_filetypes': same_filetypes,
|
'same_filetypes': same_filetypes,
|
||||||
|
'time': self._vim.call('reltime'),
|
||||||
}
|
}
|
||||||
context.update(self._cached) # type: ignore
|
context.update(self._cached) # type: ignore
|
||||||
|
|
||||||
@ -79,26 +81,20 @@ class Context(object):
|
|||||||
bufname = self._vim.call('bufname', bufnr)
|
bufname = self._vim.call('bufname', bufnr)
|
||||||
cwd = self._vim.call('getcwd')
|
cwd = self._vim.call('getcwd')
|
||||||
buftype = self._vim.call('getbufvar', '%', '&buftype')
|
buftype = self._vim.call('getbufvar', '%', '&buftype')
|
||||||
bufpath = (bufname if os.path.isabs(bufname)
|
bufpath = (bufname if Path(bufname).is_absolute()
|
||||||
else os.path.join(cwd, bufname))
|
else str(Path(cwd).joinpath(bufname)))
|
||||||
if not os.path.exists(bufpath) or 'nofile' in buftype:
|
if not exists_path(bufpath) or 'nofile' in buftype:
|
||||||
bufpath = ''
|
bufpath = ''
|
||||||
|
|
||||||
self._cached = {
|
self._cached = {
|
||||||
'bufnr': bufnr,
|
'bufnr': bufnr,
|
||||||
'bufname': bufname,
|
'bufname': bufname,
|
||||||
'bufpath': bufpath,
|
'bufpath': bufpath,
|
||||||
'camelcase': self._vim.call(
|
|
||||||
'deoplete#custom#_get_option', 'camel_case'),
|
|
||||||
'complete_str': '',
|
'complete_str': '',
|
||||||
'custom': self._vim.call('deoplete#custom#_get'),
|
'custom': self._vim.call('deoplete#custom#_get'),
|
||||||
'cwd': cwd,
|
'cwd': cwd,
|
||||||
'encoding': self._vim.options['encoding'],
|
'encoding': self._vim.options['encoding'],
|
||||||
'ignorecase': self._vim.call(
|
|
||||||
'deoplete#custom#_get_option', 'ignore_case'),
|
|
||||||
'is_windows': self._vim.call('has', 'win32'),
|
'is_windows': self._vim.call('has', 'win32'),
|
||||||
'smartcase': self._vim.call(
|
|
||||||
'deoplete#custom#_get_option', 'smart_case'),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def _get_context_filetype(self,
|
def _get_context_filetype(self,
|
||||||
|
@ -4,15 +4,15 @@
|
|||||||
# License: MIT license
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
from pynvim import Nvim
|
||||||
import copy
|
import copy
|
||||||
import glob
|
|
||||||
import os
|
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
import deoplete.parent
|
import deoplete.parent
|
||||||
from deoplete import logger
|
from deoplete import logger
|
||||||
from deoplete.context import Context
|
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]
|
UserContext = typing.Dict[str, typing.Any]
|
||||||
Candidates = typing.Dict[str, typing.Any]
|
Candidates = typing.Dict[str, typing.Any]
|
||||||
@ -26,7 +26,6 @@ class Deoplete(logger.LoggingMixin):
|
|||||||
|
|
||||||
self._vim = vim
|
self._vim = vim
|
||||||
self._runtimepath = ''
|
self._runtimepath = ''
|
||||||
self._runtimepath_list: typing.List[str] = []
|
|
||||||
self._custom: typing.Dict[str, typing.Dict[str, typing.Any]] = {}
|
self._custom: typing.Dict[str, typing.Dict[str, typing.Any]] = {}
|
||||||
self._loaded_paths: typing.Set[str] = set()
|
self._loaded_paths: typing.Set[str] = set()
|
||||||
self._prev_results: typing.Dict[int, Candidates] = {}
|
self._prev_results: typing.Dict[int, Candidates] = {}
|
||||||
@ -70,6 +69,8 @@ class Deoplete(logger.LoggingMixin):
|
|||||||
def completion_begin(self, user_context: UserContext) -> None:
|
def completion_begin(self, user_context: UserContext) -> None:
|
||||||
if not self._context:
|
if not self._context:
|
||||||
self.init_context()
|
self.init_context()
|
||||||
|
else:
|
||||||
|
self._context._init_cached()
|
||||||
|
|
||||||
context = self._context.get(user_context['event']) # type: ignore
|
context = self._context.get(user_context['event']) # type: ignore
|
||||||
context.update(user_context)
|
context.update(user_context)
|
||||||
@ -96,24 +97,30 @@ class Deoplete(logger.LoggingMixin):
|
|||||||
if needs_poll:
|
if needs_poll:
|
||||||
self._vim.call('deoplete#handler#_async_timer_start')
|
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']
|
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']
|
prev_candidates = prev_completion['candidates']
|
||||||
event = context['event']
|
event = context['event']
|
||||||
if (event == 'Async' or event == 'Update' and
|
same_candidates = prev_candidates and candidates == prev_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
|
return
|
||||||
|
|
||||||
# error(self._vim, candidates)
|
# error(self._vim, candidates)
|
||||||
self._vim.vars['deoplete#_context'] = {
|
self._vim.vars['deoplete#_context'] = {
|
||||||
'complete_position': position,
|
'complete_position': position,
|
||||||
|
'complete_str': context['input'][position:],
|
||||||
'candidates': candidates,
|
'candidates': candidates,
|
||||||
'event': context['event'],
|
'event': context['event'],
|
||||||
'input': context['input'],
|
'input': context['input'],
|
||||||
'is_async': is_async,
|
'time': context['time'],
|
||||||
|
'is_async': needs_poll,
|
||||||
}
|
}
|
||||||
|
|
||||||
if candidates or self._vim.call('deoplete#util#check_popup'):
|
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[
|
def _merge_results(self, context: UserContext) -> typing.Tuple[
|
||||||
bool, bool, int, typing.List[typing.Any]]:
|
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
|
use_prev = (context['input'] == self._prev_input
|
||||||
and context['next_input'] == self._prev_next_input
|
and context['next_input'] == self._prev_next_input
|
||||||
and context['event'] != 'Manual')
|
and context['event'] != 'Manual'
|
||||||
|
and async_check)
|
||||||
if not use_prev:
|
if not use_prev:
|
||||||
self._prev_results = {}
|
self._prev_results = {}
|
||||||
|
|
||||||
@ -182,7 +195,8 @@ class Deoplete(logger.LoggingMixin):
|
|||||||
complete_position = min(x['complete_position'] for x in results)
|
complete_position = min(x['complete_position'] for x in results)
|
||||||
|
|
||||||
all_candidates: typing.List[Candidates] = []
|
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']
|
candidates = result['candidates']
|
||||||
prefix = context['input'][
|
prefix = context['input'][
|
||||||
complete_position:result['complete_position']]
|
complete_position:result['complete_position']]
|
||||||
@ -218,43 +232,38 @@ class Deoplete(logger.LoggingMixin):
|
|||||||
parent.enable_logging()
|
parent.enable_logging()
|
||||||
self._parents.append(parent)
|
self._parents.append(parent)
|
||||||
|
|
||||||
def _find_rplugins(self,
|
def _find_rplugins(self, source: str) -> typing.List[Path]:
|
||||||
source: str) -> typing.Generator[str, None, None]:
|
|
||||||
"""Search for base.py or *.py
|
"""Search for base.py or *.py
|
||||||
|
|
||||||
Searches $VIMRUNTIME/*/rplugin/python3/deoplete/$source[s]/
|
Searches $VIMRUNTIME/*/rplugin/python3/deoplete/$source[s]/
|
||||||
"""
|
"""
|
||||||
if not self._runtimepath_list:
|
|
||||||
return
|
|
||||||
|
|
||||||
sources = (
|
result = []
|
||||||
os.path.join('rplugin', 'python3', 'deoplete',
|
result += self._vim.call(
|
||||||
source, '*.py'),
|
'globpath', self._vim.options['runtimepath'],
|
||||||
os.path.join('rplugin', 'python3', 'deoplete',
|
f'rplugin/python3/deoplete/{source}/*.py', 1, 1)
|
||||||
source + 's', '*.py'),
|
result += self._vim.call(
|
||||||
os.path.join('rplugin', 'python3', 'deoplete',
|
'globpath', self._vim.options['runtimepath'],
|
||||||
source, '*', '*.py'),
|
f'rplugin/python3/deoplete/{source}s/*.py', 1, 1)
|
||||||
)
|
result += self._vim.call(
|
||||||
|
'globpath', self._vim.options['runtimepath'],
|
||||||
for src in sources:
|
f'rplugin/python3/deoplete/{source}/*/*.py', 1, 1)
|
||||||
for path in self._runtimepath_list:
|
return [Path(x) for x in result]
|
||||||
yield from glob.iglob(os.path.join(path, src))
|
|
||||||
|
|
||||||
def _load_sources(self, context: UserContext) -> None:
|
def _load_sources(self, context: UserContext) -> None:
|
||||||
if not self._parents and self._max_parents == 1:
|
if not self._parents and self._max_parents == 1:
|
||||||
self._add_parent(deoplete.parent.SyncParent)
|
self._add_parent(deoplete.parent.SyncParent)
|
||||||
|
|
||||||
for path in self._find_rplugins('source'):
|
for path in self._find_rplugins('source'):
|
||||||
if (path in self._loaded_paths
|
if str(path) in self._loaded_paths or path.name == 'base.py':
|
||||||
or os.path.basename(path) == 'base.py'):
|
|
||||||
continue
|
continue
|
||||||
self._loaded_paths.add(path)
|
self._loaded_paths.add(str(path))
|
||||||
|
|
||||||
if len(self._parents) <= self._parent_count:
|
if len(self._parents) <= self._parent_count:
|
||||||
# Add parent automatically
|
# Add parent automatically
|
||||||
self._add_parent(deoplete.parent.AsyncParent)
|
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
|
self.debug( # type: ignore
|
||||||
f'Process {self._parent_count}: {path}')
|
f'Process {self._parent_count}: {path}')
|
||||||
|
|
||||||
@ -267,7 +276,7 @@ class Deoplete(logger.LoggingMixin):
|
|||||||
def _load_filters(self, context: UserContext) -> None:
|
def _load_filters(self, context: UserContext) -> None:
|
||||||
for path in self._find_rplugins('filter'):
|
for path in self._find_rplugins('filter'):
|
||||||
for parent in self._parents:
|
for parent in self._parents:
|
||||||
parent.add_filter(path)
|
parent.add_filter(str(path))
|
||||||
|
|
||||||
def _set_source_attributes(self, context: UserContext) -> None:
|
def _set_source_attributes(self, context: UserContext) -> None:
|
||||||
for parent in self._parents:
|
for parent in self._parents:
|
||||||
@ -277,7 +286,6 @@ class Deoplete(logger.LoggingMixin):
|
|||||||
runtimepath = self._vim.options['runtimepath']
|
runtimepath = self._vim.options['runtimepath']
|
||||||
if runtimepath != self._runtimepath:
|
if runtimepath != self._runtimepath:
|
||||||
self._runtimepath = runtimepath
|
self._runtimepath = runtimepath
|
||||||
self._runtimepath_list = runtimepath.split(',')
|
|
||||||
self._load_sources(context)
|
self._load_sources(context)
|
||||||
self._load_filters(context)
|
self._load_filters(context)
|
||||||
|
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
# License: MIT license
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
# For backward compatibility
|
from pynvim import Nvim
|
||||||
|
|
||||||
from deoplete.base.filter import Base as _Base
|
from deoplete.base.filter import Base as _Base
|
||||||
from deoplete.util import Nvim
|
|
||||||
|
|
||||||
|
|
||||||
class Base(_Base):
|
class Base(_Base):
|
||||||
|
@ -4,10 +4,11 @@
|
|||||||
# License: MIT license
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
|
from pynvim import Nvim
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
from deoplete.base.filter import Base
|
from deoplete.base.filter import Base
|
||||||
from deoplete.util import Nvim, UserContext, Candidates
|
from deoplete.util import UserContext, Candidates
|
||||||
|
|
||||||
|
|
||||||
class Filter(Base):
|
class Filter(Base):
|
||||||
@ -21,8 +22,7 @@ class Filter(Base):
|
|||||||
}
|
}
|
||||||
|
|
||||||
def filter(self, context: UserContext) -> Candidates:
|
def filter(self, context: UserContext) -> Candidates:
|
||||||
delimiters: typing.List[str] = self.get_var( # type: ignore
|
delimiters: typing.List[str] = self.get_var('delimiters')
|
||||||
'delimiters')
|
|
||||||
for candidate, delimiter in [
|
for candidate, delimiter in [
|
||||||
[x, last_find(x['abbr'], delimiters)]
|
[x, last_find(x['abbr'], delimiters)]
|
||||||
for x in context['candidates']
|
for x in context['candidates']
|
||||||
@ -30,7 +30,7 @@ class Filter(Base):
|
|||||||
not last_find(x['word'], delimiters) and
|
not last_find(x['word'], delimiters) and
|
||||||
last_find(x['abbr'], delimiters)]:
|
last_find(x['abbr'], delimiters)]:
|
||||||
candidate['word'] += delimiter
|
candidate['word'] += delimiter
|
||||||
return context['candidates'] # type: ignore
|
return list(context['candidates'])
|
||||||
|
|
||||||
|
|
||||||
def last_find(s: str, needles: typing.List[str]) -> typing.Optional[str]:
|
def last_find(s: str, needles: typing.List[str]) -> typing.Optional[str]:
|
||||||
|
@ -4,10 +4,11 @@
|
|||||||
# License: MIT license
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
|
from pynvim import Nvim
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from deoplete.base.filter import Base
|
from deoplete.base.filter import Base
|
||||||
from deoplete.util import Nvim, UserContext, Candidates
|
from deoplete.util import UserContext, Candidates
|
||||||
|
|
||||||
|
|
||||||
class Filter(Base):
|
class Filter(Base):
|
||||||
@ -26,4 +27,4 @@ class Filter(Base):
|
|||||||
(('abbr' in x and p2.search(x['abbr'])) or
|
(('abbr' in x and p2.search(x['abbr'])) or
|
||||||
('info' in x and p2.search(x['info'])))]:
|
('info' in x and p2.search(x['info'])))]:
|
||||||
candidate['word'] += '('
|
candidate['word'] += '('
|
||||||
return context['candidates'] # type: ignore
|
return list(context['candidates'])
|
||||||
|
@ -4,10 +4,11 @@
|
|||||||
# License: MIT license
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
|
from pynvim import Nvim
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from deoplete.base.filter import Base
|
from deoplete.base.filter import Base
|
||||||
from deoplete.util import Nvim, UserContext, Candidates
|
from deoplete.util import UserContext, Candidates
|
||||||
|
|
||||||
|
|
||||||
class Filter(Base):
|
class Filter(Base):
|
||||||
@ -20,7 +21,7 @@ class Filter(Base):
|
|||||||
def filter(self, context: UserContext) -> Candidates:
|
def filter(self, context: UserContext) -> Candidates:
|
||||||
complete_str = context['complete_str']
|
complete_str = context['complete_str']
|
||||||
if not re.search(r'[A-Z]', 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_lower = complete_str.lower()
|
||||||
complete_len = len(complete_str)
|
complete_len = len(complete_str)
|
||||||
@ -29,4 +30,4 @@ class Filter(Base):
|
|||||||
if x['word'].lower().startswith(complete_lower)]:
|
if x['word'].lower().startswith(complete_lower)]:
|
||||||
candidate['word'] = complete_str + candidate[
|
candidate['word'] = complete_str + candidate[
|
||||||
'word'][complete_len:]
|
'word'][complete_len:]
|
||||||
return context['candidates'] # type: ignore
|
return list(context['candidates'])
|
||||||
|
@ -4,11 +4,12 @@
|
|||||||
# License: MIT license
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
|
from pynvim import Nvim
|
||||||
import re
|
import re
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
from deoplete.base.filter import Base
|
from deoplete.base.filter import Base
|
||||||
from deoplete.util import Nvim, UserContext, Candidates
|
from deoplete.util import UserContext, Candidates
|
||||||
|
|
||||||
|
|
||||||
class Filter(Base):
|
class Filter(Base):
|
||||||
@ -20,26 +21,36 @@ class Filter(Base):
|
|||||||
|
|
||||||
def filter(self, context: UserContext) -> Candidates:
|
def filter(self, context: UserContext) -> Candidates:
|
||||||
if not context['next_input']:
|
if not context['next_input']:
|
||||||
return context['candidates'] # type: ignore
|
return list(context['candidates'])
|
||||||
next_input_words = [x for x in re.split(
|
next_input_words = [x for x in re.split(
|
||||||
r'([a-zA-Z_]+|\W)', context['next_input']) if x]
|
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 = []
|
check_pairs = []
|
||||||
if self.vim.call('searchpair', '(', '', ')', 'bnw'):
|
pair_pos = self.vim.call('searchpairpos', '(', '', ')', 'nW')
|
||||||
check_pairs.append(['(', ')'])
|
if ('(' in context['input'] and cur_pos < pair_pos and
|
||||||
if self.vim.call('searchpair', '[', '', ']', 'bnw'):
|
cur_pos[0] == pair_pos[0]):
|
||||||
check_pairs.append(['[', ']'])
|
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 [
|
for [overlap, candidate, word] in [
|
||||||
[x, y, y['word']] for x, y
|
[x, y, y['word']] for x, y
|
||||||
in [[overlap_length(x['word'], next_input_words), x]
|
in [[overlap_length(x['word'], next_input_words), x]
|
||||||
for x in context['candidates']] if x > 0]:
|
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
|
continue
|
||||||
if 'abbr' not in candidate:
|
if 'abbr' not in candidate:
|
||||||
candidate['abbr'] = word
|
candidate['abbr'] = word
|
||||||
candidate['word'] = word[: -overlap]
|
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:
|
def overlap_length(left: str, next_input_words: typing.List[str]) -> int:
|
||||||
|
@ -4,10 +4,11 @@
|
|||||||
# License: MIT license
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
|
from pynvim import Nvim
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from deoplete.base.filter import Base
|
from deoplete.base.filter import Base
|
||||||
from deoplete.util import Nvim, UserContext, Candidates
|
from deoplete.util import UserContext, Candidates
|
||||||
|
|
||||||
|
|
||||||
class Filter(Base):
|
class Filter(Base):
|
||||||
@ -22,4 +23,4 @@ class Filter(Base):
|
|||||||
if '(' in x['word']]:
|
if '(' in x['word']]:
|
||||||
candidate['word'] = re.sub(r'\(.*\)(\$\d+)?', '',
|
candidate['word'] = re.sub(r'\(.*\)(\$\d+)?', '',
|
||||||
candidate['word'])
|
candidate['word'])
|
||||||
return context['candidates'] # type: ignore
|
return list(context['candidates'])
|
||||||
|
@ -4,11 +4,12 @@
|
|||||||
# License: MIT license
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
|
from pynvim import Nvim
|
||||||
import re
|
import re
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
from deoplete.base.filter import Base
|
from deoplete.base.filter import Base
|
||||||
from deoplete.util import Nvim, UserContext, Candidates
|
from deoplete.util import UserContext, Candidates
|
||||||
|
|
||||||
|
|
||||||
class Filter(Base):
|
class Filter(Base):
|
||||||
@ -63,10 +64,10 @@ class Filter(Base):
|
|||||||
return new_candidates
|
return new_candidates
|
||||||
|
|
||||||
def filter(self, context: UserContext) -> 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'], [])
|
'attrs_order').get(context['filetype'], [])
|
||||||
if not context['candidates'] or not preferred_order_attrs:
|
if not context['candidates'] or not preferred_order_attrs:
|
||||||
return context['candidates'] # type: ignore
|
return list(context['candidates'])
|
||||||
|
|
||||||
max_list_size = self.vim.call(
|
max_list_size = self.vim.call(
|
||||||
'deoplete#custom#_get_option', 'max_list'
|
'deoplete#custom#_get_option', 'max_list'
|
||||||
|
@ -4,8 +4,10 @@
|
|||||||
# License: MIT license
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
|
from pynvim import Nvim
|
||||||
|
|
||||||
from deoplete.base.filter import Base
|
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):
|
class Filter(Base):
|
||||||
@ -18,11 +20,11 @@ class Filter(Base):
|
|||||||
def filter(self, context: UserContext) -> Candidates:
|
def filter(self, context: UserContext) -> Candidates:
|
||||||
max_width = context['max_abbr_width']
|
max_width = context['max_abbr_width']
|
||||||
if max_width <= 0:
|
if max_width <= 0:
|
||||||
return context['candidates'] # type: ignore
|
return list(context['candidates'])
|
||||||
|
|
||||||
footer_width = max_width / 3
|
footer_width = max_width / 3
|
||||||
for candidate in context['candidates']:
|
for candidate in context['candidates']:
|
||||||
candidate['abbr'] = truncate_skipping(
|
candidate['abbr'] = truncate_skipping(
|
||||||
candidate.get('abbr', candidate['word']),
|
candidate.get('abbr', candidate['word']),
|
||||||
max_width, '..', footer_width)
|
max_width, '..', footer_width)
|
||||||
return context['candidates'] # type: ignore
|
return list(context['candidates'])
|
||||||
|
@ -4,8 +4,10 @@
|
|||||||
# License: MIT license
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
|
from pynvim import Nvim
|
||||||
|
|
||||||
from deoplete.base.filter import Base
|
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):
|
class Filter(Base):
|
||||||
@ -18,11 +20,11 @@ class Filter(Base):
|
|||||||
def filter(self, context: UserContext) -> Candidates:
|
def filter(self, context: UserContext) -> Candidates:
|
||||||
max_width = context['max_info_width']
|
max_width = context['max_info_width']
|
||||||
if not context['candidates'] or max_width <= 0:
|
if not context['candidates'] or max_width <= 0:
|
||||||
return context['candidates'] # type: ignore
|
return list(context['candidates'])
|
||||||
|
|
||||||
footer_width = 1
|
footer_width = 1
|
||||||
for candidate in context['candidates']:
|
for candidate in context['candidates']:
|
||||||
candidate['info'] = truncate_skipping(
|
candidate['info'] = truncate_skipping(
|
||||||
candidate.get('info', ''),
|
candidate.get('info', ''),
|
||||||
max_width, '..', footer_width)
|
max_width, '..', footer_width)
|
||||||
return context['candidates'] # type: ignore
|
return list(context['candidates'])
|
||||||
|
@ -4,8 +4,10 @@
|
|||||||
# License: MIT license
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
|
from pynvim import Nvim
|
||||||
|
|
||||||
from deoplete.base.filter import Base
|
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):
|
class Filter(Base):
|
||||||
@ -19,11 +21,11 @@ class Filter(Base):
|
|||||||
max_width = context['max_kind_width']
|
max_width = context['max_kind_width']
|
||||||
if not context['candidates'] or 'kind' not in context[
|
if not context['candidates'] or 'kind' not in context[
|
||||||
'candidates'][0] or max_width <= 0:
|
'candidates'][0] or max_width <= 0:
|
||||||
return context['candidates'] # type: ignore
|
return list(context['candidates'])
|
||||||
|
|
||||||
footer_width = max_width / 3
|
footer_width = max_width / 3
|
||||||
for candidate in context['candidates']:
|
for candidate in context['candidates']:
|
||||||
candidate['kind'] = truncate_skipping(
|
candidate['kind'] = truncate_skipping(
|
||||||
candidate.get('kind', ''),
|
candidate.get('kind', ''),
|
||||||
max_width, '..', footer_width)
|
max_width, '..', footer_width)
|
||||||
return context['candidates'] # type: ignore
|
return list(context['candidates'])
|
||||||
|
@ -4,8 +4,10 @@
|
|||||||
# License: MIT license
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
|
from pynvim import Nvim
|
||||||
|
|
||||||
from deoplete.base.filter import Base
|
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):
|
class Filter(Base):
|
||||||
@ -19,11 +21,11 @@ class Filter(Base):
|
|||||||
max_width = context['max_menu_width']
|
max_width = context['max_menu_width']
|
||||||
if not context['candidates'] or 'menu' not in context[
|
if not context['candidates'] or 'menu' not in context[
|
||||||
'candidates'][0] or max_width <= 0:
|
'candidates'][0] or max_width <= 0:
|
||||||
return context['candidates'] # type: ignore
|
return list(context['candidates'])
|
||||||
|
|
||||||
footer_width = max_width / 3
|
footer_width = max_width / 3
|
||||||
for candidate in context['candidates']:
|
for candidate in context['candidates']:
|
||||||
candidate['menu'] = truncate_skipping(
|
candidate['menu'] = truncate_skipping(
|
||||||
candidate.get('menu', ''),
|
candidate.get('menu', ''),
|
||||||
max_width, '..', footer_width)
|
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
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
import os
|
from pathlib import Path
|
||||||
|
from pynvim import Nvim
|
||||||
import sys
|
import sys
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
from deoplete.base.filter import Base
|
from deoplete.base.filter import Base
|
||||||
from deoplete.util import error, globruntime
|
from deoplete.util import error, globruntime
|
||||||
from deoplete.util import Nvim, UserContext, Candidates
|
from deoplete.util import UserContext, Candidates
|
||||||
|
|
||||||
|
|
||||||
class Filter(Base):
|
class Filter(Base):
|
||||||
@ -26,7 +27,7 @@ class Filter(Base):
|
|||||||
def filter(self, context: UserContext) -> Candidates:
|
def filter(self, context: UserContext) -> Candidates:
|
||||||
if (not context['candidates'] or not context['input']
|
if (not context['candidates'] or not context['input']
|
||||||
or self._cpsm is False):
|
or self._cpsm is False):
|
||||||
return context['candidates'] # type: ignore
|
return list(context['candidates'])
|
||||||
|
|
||||||
if self._cpsm is None:
|
if self._cpsm is None:
|
||||||
errmsg = self._init_cpsm(context)
|
errmsg = self._init_cpsm(context)
|
||||||
@ -49,7 +50,7 @@ class Filter(Base):
|
|||||||
found = globruntime(self.vim.options['runtimepath'], fname)
|
found = globruntime(self.vim.options['runtimepath'], fname)
|
||||||
errmsg = ''
|
errmsg = ''
|
||||||
if found:
|
if found:
|
||||||
sys.path.insert(0, os.path.dirname(found[0]))
|
sys.path.insert(0, str(Path(found[0]).parent))
|
||||||
try:
|
try:
|
||||||
import cpsm_py
|
import cpsm_py
|
||||||
except ImportError as exc:
|
except ImportError as exc:
|
||||||
|
@ -4,9 +4,11 @@
|
|||||||
# License: MIT license
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
|
from pynvim import Nvim
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from deoplete.base.filter import Base
|
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):
|
class Filter(Base):
|
||||||
|
@ -4,12 +4,12 @@
|
|||||||
# License: MIT license
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
|
from pynvim import Nvim
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from deoplete.base.filter import Base
|
from deoplete.base.filter import Base
|
||||||
from deoplete.util import (
|
from deoplete.util import binary_search_begin, binary_search_end
|
||||||
fuzzy_escape, binary_search_begin, binary_search_end)
|
from deoplete.util import fuzzy_escape, UserContext, Candidates
|
||||||
from deoplete.util import Nvim, UserContext, Candidates
|
|
||||||
|
|
||||||
|
|
||||||
class Filter(Base):
|
class Filter(Base):
|
||||||
@ -25,7 +25,7 @@ class Filter(Base):
|
|||||||
if context['ignorecase']:
|
if context['ignorecase']:
|
||||||
complete_str = complete_str.lower()
|
complete_str = complete_str.lower()
|
||||||
if not complete_str:
|
if not complete_str:
|
||||||
return context['candidates'] # type: ignore
|
return list(context['candidates'])
|
||||||
|
|
||||||
if context['is_sorted']:
|
if context['is_sorted']:
|
||||||
begin = binary_search_begin(
|
begin = binary_search_begin(
|
||||||
|
@ -4,9 +4,11 @@
|
|||||||
# License: MIT license
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
|
from pynvim import Nvim
|
||||||
|
|
||||||
from deoplete.base.filter import Base
|
from deoplete.base.filter import Base
|
||||||
from deoplete.util import binary_search_begin, binary_search_end
|
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):
|
class Filter(Base):
|
||||||
@ -32,7 +34,7 @@ class Filter(Base):
|
|||||||
candidates = context['candidates'][begin:end+1]
|
candidates = context['candidates'][begin:end+1]
|
||||||
|
|
||||||
if context['ignorecase']:
|
if context['ignorecase']:
|
||||||
return candidates # type: ignore
|
return list(candidates)
|
||||||
else:
|
else:
|
||||||
candidates = context['candidates']
|
candidates = context['candidates']
|
||||||
|
|
||||||
|
@ -4,8 +4,10 @@
|
|||||||
# License: MIT license
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
|
from pynvim import Nvim
|
||||||
|
|
||||||
from deoplete.base.filter import Base
|
from deoplete.base.filter import Base
|
||||||
from deoplete.util import Nvim, UserContext, Candidates
|
from deoplete.util import UserContext, Candidates
|
||||||
|
|
||||||
|
|
||||||
class Filter(Base):
|
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
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
|
from pynvim import Nvim
|
||||||
import re
|
import re
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
from deoplete.base.filter import Base
|
from deoplete.base.filter import Base
|
||||||
from deoplete.util import getlines
|
from deoplete.util import getlines
|
||||||
from deoplete.util import Nvim, UserContext, Candidates, Candidate
|
from deoplete.util import UserContext, Candidates, Candidate
|
||||||
|
|
||||||
|
|
||||||
LINES_MAX = 150
|
LINES_MAX = 150
|
||||||
@ -39,11 +40,15 @@ class Filter(Base):
|
|||||||
def filter(self, context: UserContext) -> Candidates:
|
def filter(self, context: UserContext) -> Candidates:
|
||||||
complete_str = context['complete_str'].lower()
|
complete_str = context['complete_str'].lower()
|
||||||
linenr = context['position'][1]
|
linenr = context['position'][1]
|
||||||
|
recently_used = self.vim.vars['deoplete#_recently_used']
|
||||||
|
|
||||||
def compare(x: Candidate) -> int:
|
def compare(x: Candidate) -> int:
|
||||||
word = x['word']
|
word = x['word']
|
||||||
matched = int(complete_str in word.lower())
|
lower = x['word'].lower()
|
||||||
|
matched = int(complete_str in lower)
|
||||||
score = -matched * 40
|
score = -matched * 40
|
||||||
|
if [x for x in recently_used if lower.startswith(x)]:
|
||||||
|
score -= 1000
|
||||||
if word in self._cache:
|
if word in self._cache:
|
||||||
mru = min([abs(x - linenr) for x in self._cache[word]])
|
mru = min([abs(x - linenr) for x in self._cache[word]])
|
||||||
mru -= LINES_MAX
|
mru -= LINES_MAX
|
||||||
|
@ -4,8 +4,10 @@
|
|||||||
# License: MIT license
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
|
from pynvim import Nvim
|
||||||
|
|
||||||
from deoplete.base.filter import Base
|
from deoplete.base.filter import Base
|
||||||
from deoplete.util import Nvim, UserContext, Candidates
|
from deoplete.util import UserContext, Candidates
|
||||||
|
|
||||||
|
|
||||||
class Filter(Base):
|
class Filter(Base):
|
||||||
@ -18,4 +20,4 @@ class Filter(Base):
|
|||||||
|
|
||||||
def filter(self, context: UserContext) -> Candidates:
|
def filter(self, context: UserContext) -> Candidates:
|
||||||
return sorted(context['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 logging
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
from deoplete.util import Nvim
|
|
||||||
|
|
||||||
from functools import wraps
|
|
||||||
from collections import defaultdict
|
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_format = '%(asctime)s %(levelname)-8s [%(process)d] (%(name)s) %(message)s'
|
||||||
log_message_cooldown = 0.5
|
log_message_cooldown = 0.5
|
||||||
@ -50,19 +49,11 @@ def setup(vim: Nvim, level: str, output_file: str = '') -> None:
|
|||||||
level = 'DEBUG'
|
level = 'DEBUG'
|
||||||
root.setLevel(getattr(logging, level))
|
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 = getLogger('logging')
|
||||||
log.info('--- Deoplete Log Start ---')
|
log.info('--- Deoplete Log Start ---')
|
||||||
log.info('%s, Python %s, pynvim %s',
|
log.info('%s, Python %s',
|
||||||
vim.call('deoplete#util#neovim_version'),
|
vim.call('deoplete#util#neovim_version'),
|
||||||
'.'.join(map(str, sys.version_info[:3])),
|
'.'.join(map(str, sys.version_info[:3])))
|
||||||
pynvim_version)
|
|
||||||
|
|
||||||
if 'deoplete#_logging_notified' not in vim.vars:
|
if 'deoplete#_logging_notified' not in vim.vars:
|
||||||
vim.vars['deoplete#_logging_notified'] = 1
|
vim.vars['deoplete#_logging_notified'] = 1
|
||||||
|
@ -4,20 +4,20 @@
|
|||||||
# License: MIT license
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
import time
|
|
||||||
import os
|
|
||||||
import msgpack
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
import typing
|
|
||||||
from abc import abstractmethod
|
from abc import abstractmethod
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from pynvim import Nvim
|
||||||
from queue import Queue
|
from queue import Queue
|
||||||
|
import msgpack
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import typing
|
||||||
|
|
||||||
from deoplete import logger
|
from deoplete import logger
|
||||||
from deoplete.process import Process
|
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]
|
UserContext = typing.Dict[str, typing.Any]
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ class AsyncParent(_Parent):
|
|||||||
Taken from jedi.api.environment._try_get_same_env.
|
Taken from jedi.api.environment._try_get_same_env.
|
||||||
"""
|
"""
|
||||||
exe = sys.executable
|
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, ...]
|
checks: typing.Tuple[typing.Any, ...]
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
checks = (r'Scripts\python.exe', 'python.exe')
|
checks = (r'Scripts\python.exe', 'python.exe')
|
||||||
@ -103,8 +103,8 @@ class AsyncParent(_Parent):
|
|||||||
'bin/python',
|
'bin/python',
|
||||||
)
|
)
|
||||||
for check in checks:
|
for check in checks:
|
||||||
guess = os.path.join(sys.exec_prefix, check)
|
guess = Path(sys.exec_prefix).joinpath(check)
|
||||||
if os.path.isfile(str(guess)):
|
if guess.is_file():
|
||||||
return str(guess)
|
return str(guess)
|
||||||
if 'python3_host_prog' not in self._vim.vars:
|
if 'python3_host_prog' not in self._vim.vars:
|
||||||
return 'python3'
|
return 'python3'
|
||||||
|
@ -4,11 +4,12 @@
|
|||||||
# License: MIT license
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
|
from pynvim import Nvim
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from deoplete.base.source import Base
|
from deoplete.base.source import Base
|
||||||
from deoplete.util import parse_buffer_pattern, getlines
|
from deoplete.util import parse_buffer_pattern, getlines
|
||||||
from deoplete.util import Nvim, UserContext, Candidates
|
from deoplete.util import UserContext, Candidates
|
||||||
|
|
||||||
|
|
||||||
class Source(Base):
|
class Source(Base):
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
# License: MIT license
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
# For backward compatibility
|
from pynvim import Nvim
|
||||||
|
|
||||||
from deoplete.base.source import Base as _Base
|
from deoplete.base.source import Base as _Base
|
||||||
from deoplete.util import Nvim
|
|
||||||
|
|
||||||
|
|
||||||
class Base(_Base):
|
class Base(_Base):
|
||||||
|
@ -4,11 +4,12 @@
|
|||||||
# License: MIT license
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
|
from pynvim import Nvim
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
from deoplete.base.source import Base
|
from deoplete.base.source import Base
|
||||||
from deoplete.util import parse_buffer_pattern, getlines
|
from deoplete.util import parse_buffer_pattern, getlines
|
||||||
from deoplete.util import Nvim, UserContext, Candidates
|
from deoplete.util import UserContext, Candidates
|
||||||
|
|
||||||
|
|
||||||
class Source(Base):
|
class Source(Base):
|
||||||
|
@ -5,13 +5,13 @@
|
|||||||
# License: MIT license
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
import os
|
from pathlib import Path
|
||||||
|
from pynvim import Nvim
|
||||||
import re
|
import re
|
||||||
import typing
|
import typing
|
||||||
from os.path import exists, dirname
|
|
||||||
|
|
||||||
from deoplete.base.source import Base
|
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):
|
class Source(Base):
|
||||||
@ -26,6 +26,7 @@ class Source(Base):
|
|||||||
self.events: typing.List[str] = ['InsertEnter']
|
self.events: typing.List[str] = ['InsertEnter']
|
||||||
self.vars = {
|
self.vars = {
|
||||||
'enable_buffer_path': True,
|
'enable_buffer_path': True,
|
||||||
|
'enable_slash_completion': False,
|
||||||
'force_completion_length': -1,
|
'force_completion_length': -1,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,7 +40,7 @@ class Source(Base):
|
|||||||
def get_complete_position(self, context: UserContext) -> int:
|
def get_complete_position(self, context: UserContext) -> int:
|
||||||
pos = int(context['input'].rfind('/'))
|
pos = int(context['input'].rfind('/'))
|
||||||
force_completion_length = int(
|
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:
|
if pos < 0 and force_completion_length >= 0:
|
||||||
fmt = '[a-zA-Z0-9.-]{{{}}}$'.format(force_completion_length)
|
fmt = '[a-zA-Z0-9.-]{{{}}}$'.format(force_completion_length)
|
||||||
m = re.search(fmt, context['input'])
|
m = re.search(fmt, context['input'])
|
||||||
@ -55,20 +56,38 @@ class Source(Base):
|
|||||||
if context['input'].rfind('/') >= 0
|
if context['input'].rfind('/') >= 0
|
||||||
else './')
|
else './')
|
||||||
|
|
||||||
p = self._longest_path_that_exists(context, input_str)
|
# Note: context['bufpath'] will be empty if not exists file
|
||||||
if not p or p == '/' or re.search('//+$', p):
|
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 []
|
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 []
|
return []
|
||||||
hidden = context['complete_str'].find('.') == 0
|
hidden = context['complete_str'].find('.') == 0
|
||||||
contents: typing.List[typing.Any] = [[], []]
|
contents: typing.List[typing.Any] = [[], []]
|
||||||
try:
|
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] == '.':
|
if not hidden and item[0] == '.':
|
||||||
continue
|
continue
|
||||||
contents[not os.path.isdir(complete_str + item)].append(item)
|
is_dir = not Path(complete_str + '/' + item).is_dir()
|
||||||
except PermissionError:
|
contents[is_dir].append(item)
|
||||||
|
except (PermissionError, FileNotFoundError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
dirs, files = contents
|
dirs, files = contents
|
||||||
@ -76,25 +95,32 @@ class Source(Base):
|
|||||||
] + [{'word': x} for x in files]
|
] + [{'word': x} for x in files]
|
||||||
|
|
||||||
def _longest_path_that_exists(self, context: UserContext,
|
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)
|
input_str = re.sub(r'[^/]*$', '', input_str)
|
||||||
data = re.split(r'((?:%s+|(?:(?<![\w\s/\.])(?:~|\.{1,2})?/)+))' %
|
data = [x for x in re.split(
|
||||||
self._isfname, input_str)
|
r'((?:%s+|(?:(?<![\w\s/\.])(?:~|\.{1,2})?/)+))' %
|
||||||
|
self._isfname, input_str)]
|
||||||
data = [''.join(data[i:]) for i in range(len(data))]
|
data = [''.join(data[i:]) for i in range(len(data))]
|
||||||
existing_paths = sorted(filter(lambda x: exists(
|
existing_paths = sorted(filter(
|
||||||
dirname(self._substitute_path(context, x))), data))
|
lambda x: exists_path(self._substitute_path(
|
||||||
|
context, x, bufpath)), data))
|
||||||
return existing_paths[-1] if existing_paths else ''
|
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)
|
m = re.match(r'(\.{1,2})/+', path)
|
||||||
if m:
|
if not m:
|
||||||
if self.get_var('enable_buffer_path') and context['bufpath']:
|
return expand(path)
|
||||||
base = context['bufpath']
|
|
||||||
else:
|
|
||||||
base = os.path.join(context['cwd'], 'x')
|
|
||||||
|
|
||||||
for _ in m.group(1):
|
if bufpath:
|
||||||
base = dirname(base)
|
base = str(Path(bufpath).parent)
|
||||||
return os.path.abspath(os.path.join(
|
else:
|
||||||
base, path[len(m.group(0)):])) + '/'
|
base = context['cwd']
|
||||||
return expand(path)
|
|
||||||
|
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
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
|
from pynvim import Nvim
|
||||||
import re
|
import re
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
from deoplete.base.source import Base
|
from deoplete.base.source import Base
|
||||||
from deoplete.util import (
|
from deoplete.util import (
|
||||||
convert2list, parse_buffer_pattern, set_pattern, getlines)
|
convert2list, parse_buffer_pattern, set_pattern, getlines)
|
||||||
from deoplete.util import Nvim, UserContext, Candidates
|
from deoplete.util import UserContext, Candidates
|
||||||
|
|
||||||
|
|
||||||
class Source(Base):
|
class Source(Base):
|
||||||
|
@ -4,13 +4,14 @@
|
|||||||
# License: MIT license
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
|
from pynvim import Nvim
|
||||||
import re
|
import re
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
from deoplete.base.source import Base
|
from deoplete.base.source import Base
|
||||||
from deoplete.util import (
|
from deoplete.util import (
|
||||||
convert2list, set_pattern, convert2candidates)
|
convert2list, set_pattern, convert2candidates)
|
||||||
from deoplete.util import Nvim, UserContext, Candidates
|
from deoplete.util import UserContext, Candidates
|
||||||
|
|
||||||
|
|
||||||
class Source(Base):
|
class Source(Base):
|
||||||
@ -44,6 +45,8 @@ class Source(Base):
|
|||||||
|
|
||||||
def _get_complete_position(self, context: UserContext,
|
def _get_complete_position(self, context: UserContext,
|
||||||
current_ft: str, filetype: str) -> int:
|
current_ft: str, filetype: str) -> int:
|
||||||
|
complete_pos = -1
|
||||||
|
|
||||||
for omnifunc in convert2list(
|
for omnifunc in convert2list(
|
||||||
self.get_filetype_var(filetype, 'functions')):
|
self.get_filetype_var(filetype, 'functions')):
|
||||||
if omnifunc == '' and (filetype == current_ft or
|
if omnifunc == '' and (filetype == current_ft or
|
||||||
@ -69,15 +72,16 @@ class Source(Base):
|
|||||||
'rubycomplete#Complete',
|
'rubycomplete#Complete',
|
||||||
'phpcomplete#CompletePHP']:
|
'phpcomplete#CompletePHP']:
|
||||||
# In the blacklist
|
# In the blacklist
|
||||||
return -1
|
continue
|
||||||
try:
|
try:
|
||||||
complete_pos = int(self.vim.call(self._omnifunc, 1, ''))
|
complete_pos = int(self.vim.call(self._omnifunc, 1, ''))
|
||||||
except Exception:
|
except Exception:
|
||||||
self.print_error('Error occurred calling omnifunction: ' +
|
self.print_error('Error occurred calling omnifunction: ' +
|
||||||
self._omnifunc)
|
self._omnifunc)
|
||||||
return -1
|
return -1
|
||||||
return complete_pos
|
if complete_pos >= 0:
|
||||||
return -1
|
break
|
||||||
|
return complete_pos
|
||||||
|
|
||||||
def gather_candidates(self, context: UserContext) -> Candidates:
|
def gather_candidates(self, context: UserContext) -> Candidates:
|
||||||
try:
|
try:
|
||||||
@ -95,4 +99,4 @@ class Source(Base):
|
|||||||
candidate['dup'] = 1
|
candidate['dup'] = 1
|
||||||
candidate['equal'] = 1
|
candidate['equal'] = 1
|
||||||
|
|
||||||
return candidates # type: ignore
|
return list(candidates)
|
||||||
|
@ -4,22 +4,18 @@
|
|||||||
# License: MIT license
|
# License: MIT license
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
import os
|
from os.path import expandvars
|
||||||
import re
|
from pathlib import Path
|
||||||
import sys
|
from pynvim import Nvim
|
||||||
|
from pynvim.api import Buffer
|
||||||
import glob
|
import glob
|
||||||
import importlib.util
|
import importlib.util
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
import typing
|
import typing
|
||||||
import unicodedata
|
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]
|
UserContext = typing.Dict[str, typing.Any]
|
||||||
Candidate = typing.Dict[str, typing.Any]
|
Candidate = typing.Dict[str, typing.Any]
|
||||||
Candidates = typing.List[Candidate]
|
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.
|
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)
|
module_name = 'deoplete.%s.%s' % (source, name)
|
||||||
|
|
||||||
spec = importlib.util.spec_from_file_location(module_name, path)
|
spec = importlib.util.spec_from_file_location(module_name, path)
|
||||||
|
if not spec:
|
||||||
|
return None
|
||||||
module = importlib.util.module_from_spec(spec)
|
module = importlib.util.module_from_spec(spec)
|
||||||
spec.loader.exec_module(module) # type: ignore
|
spec.loader.exec_module(module) # type: ignore
|
||||||
cls = getattr(module, classname, None)
|
cls = getattr(module, classname, None)
|
||||||
if not cls:
|
if not cls:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
dirname = os.path.dirname(path)
|
dirname = str(Path(path).parent)
|
||||||
if dirname not in sys.path:
|
if dirname not in sys.path:
|
||||||
sys.path.insert(0, dirname)
|
sys.path.insert(0, dirname)
|
||||||
return cls
|
return cls
|
||||||
@ -96,7 +94,7 @@ def error_tb(vim: Nvim, msg: str) -> None:
|
|||||||
t, v, tb = sys.exc_info()
|
t, v, tb = sys.exc_info()
|
||||||
if t and v and tb:
|
if t and v and tb:
|
||||||
lines += traceback.format_exc().splitlines()
|
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'):
|
if hasattr(vim, 'err_write'):
|
||||||
vim.err_write('[deoplete] %s\n' % '\n'.join(lines))
|
vim.err_write('[deoplete] %s\n' % '\n'.join(lines))
|
||||||
else:
|
else:
|
||||||
@ -141,8 +139,8 @@ def get_custom(custom: typing.Dict[str, typing.Any],
|
|||||||
return default
|
return default
|
||||||
|
|
||||||
|
|
||||||
def get_syn_names(vim: Nvim) -> str:
|
def get_syn_names(vim: Nvim) -> typing.List[str]:
|
||||||
return str(vim.call('deoplete#util#get_syn_names'))
|
return list(vim.call('deoplete#util#get_syn_names'))
|
||||||
|
|
||||||
|
|
||||||
def parse_file_pattern(f: typing.Iterable[str],
|
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:
|
def load_external_module(base: str, module: str) -> None:
|
||||||
current = os.path.dirname(os.path.abspath(base))
|
current = Path(base).parent.resolve()
|
||||||
module_dir = os.path.join(os.path.dirname(current), module)
|
module_dir = str(current.parent.joinpath(module))
|
||||||
if module_dir not in sys.path:
|
if module_dir not in sys.path:
|
||||||
sys.path.insert(0, module_dir)
|
sys.path.insert(0, module_dir)
|
||||||
|
|
||||||
@ -219,7 +217,20 @@ def charwidth(c: str) -> int:
|
|||||||
|
|
||||||
|
|
||||||
def expand(path: str) -> str:
|
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,
|
def getlines(vim: Nvim, start: int = 1,
|
||||||
@ -230,7 +241,9 @@ def getlines(vim: Nvim, start: int = 1,
|
|||||||
lines: typing.List[str] = []
|
lines: typing.List[str] = []
|
||||||
current = start
|
current = start
|
||||||
while current <= int(end):
|
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
|
current += max_len + 1
|
||||||
return lines
|
return lines
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import os
|
from pathlib import Path
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
|
BASE_DIR = Path(__file__).parent.parent
|
||||||
sys.path.insert(0, os.path.join(BASE_DIR, 'rplugin/python3'))
|
sys.path.insert(0, str(Path(BASE_DIR).joinpath('rplugin/python3')))
|
||||||
|
Loading…
Reference in New Issue
Block a user