Compare commits

...

2 commits

Author SHA1 Message Date
17f75da318 Load coc-powershell 2024-11-05 11:32:11 +00:00
0c5f1c730a Add COC 2024-11-05 11:26:38 +00:00
38 changed files with 18192 additions and 0 deletions

13
pack/acp/start/coc.nvim/.gitignore vendored Normal file
View file

@ -0,0 +1,13 @@
lib
*.map
coverage
__pycache__
.pyc
.log
src
publish.sh
doc/tags
doc/tags-cn
node_modules
src/__tests__/tags
typings

View file

@ -0,0 +1,7 @@
Copyright 2018-2018 by Qiming Zhao <chemzqm@gmail.com>aaa
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -0,0 +1,611 @@
<p align="center">
<a href="https://www.vim.org/scripts/script.php?script_id=5779">
<img alt="Logo" src="https://alfs.chigua.cn/dianyou/data/platform/default/20220525/coc.png" height="240" />
</a>
<p align="center">Make your Vim/Neovim as smart as VSCode.</p>
<p align="center">
<a href="LICENSE.md"><img alt="Software License" src="https://img.shields.io/badge/license-Anti%20996-brightgreen.svg?style=flat-square"></a>
<a href="https://github.com/neoclide/coc.nvim/actions"><img alt="Actions" src="https://img.shields.io/github/workflow/status/neoclide/coc.nvim/coc.nvim%20CI?style=flat-square"></a>
<a href="https://codecov.io/gh/neoclide/coc.nvim"><img alt="Codecov Coverage Status" src="https://img.shields.io/codecov/c/github/neoclide/coc.nvim.svg?style=flat-square"></a>
<a href="doc/coc.txt"><img alt="Doc" src="https://img.shields.io/badge/doc-%3Ah%20coc.txt-brightgreen.svg?style=flat-square"></a>
<a href="https://gitter.im/neoclide/coc.nvim"><img alt="Gitter" src="https://img.shields.io/gitter/room/neoclide/coc.nvim.svg?style=flat-square"></a>
</p>
</p>
---
## Why?
- 🚀 **Fast**: [instant increment completion](https://github.com/neoclide/coc.nvim/wiki/Completion-with-sources), increment buffer sync using buffer update events.
- 💎 **Reliable**: typed language, tested with CI.
- 🌟 **Featured**: [full LSP support](https://github.com/neoclide/coc.nvim/wiki/Language-servers#supported-features)
- ❤️ **Flexible**: [configured like VSCode](https://github.com/neoclide/coc.nvim/wiki/Using-the-configuration-file), [extensions work like in VSCode](https://github.com/neoclide/coc.nvim/wiki/Using-coc-extensions)
## Quick Start
Install [nodejs](https://nodejs.org/en/download/) >= 12.12:
```bash
curl -sL install-node.vercel.app/lts | bash
```
For [vim-plug](https://github.com/junegunn/vim-plug) users:
```vim
" Use release branch (recommend)
Plug 'neoclide/coc.nvim', {'branch': 'release'}
" Or build from source code by using yarn: https://yarnpkg.com
Plug 'neoclide/coc.nvim', {'branch': 'master', 'do': 'yarn install --frozen-lockfile'}
```
in your `.vimrc` or `init.vim`, then restart Vim and run `:PlugInstall`.
Checkout [Install
coc.nvim](https://github.com/neoclide/coc.nvim/wiki/Install-coc.nvim) for
more info.
You **have to** install coc extension or configure language servers for
LSP support.
Install extensions like:
:CocInstall coc-json coc-tsserver
Or configure language server in `coc-settings.json` opened by
`:CocConfig`, like:
```json
{
"languageserver": {
"go": {
"command": "gopls",
"rootPatterns": ["go.mod"],
"trace.server": "verbose",
"filetypes": ["go"]
}
}
}
```
Checkout wiki for more details:
- [Completion with sources](https://github.com/neoclide/coc.nvim/wiki/Completion-with-sources)
- [Using the configuration file](https://github.com/neoclide/coc.nvim/wiki/Using-the-configuration-file)
- [Using coc extensions](https://github.com/neoclide/coc.nvim/wiki/Using-coc-extensions)
- [Configure language servers](https://github.com/neoclide/coc.nvim/wiki/Language-servers)
- [F.A.Q](https://github.com/neoclide/coc.nvim/wiki/F.A.Q)
Checkout `:h coc-nvim` for vim interface.
## Example vim configuration
Configuration is required to make coc.nvim easier to work with, since it
doesn't change your key-mappings or Vim options. This is done as much as
possible to avoid conflict with your other plugins.
**❗Important**: Some Vim plugins could change key mappings. Please use
command like`:verbose imap <tab>` to make sure that your keymap has taken effect.
```vim
" Some servers have issues with backup files, see #649.
set nobackup
set nowritebackup
" Having longer updatetime (default is 4000 ms = 4 s) leads to noticeable
" delays and poor user experience.
set updatetime=300
" Always show the signcolumn, otherwise it would shift the text each time
" diagnostics appear/become resolved.
set signcolumn=yes
"Use <C-n> and <C-p> for navigate completion list like built in completion.
inoremap <silent><expr> <C-n> coc#pum#visible() ? coc#pum#next(1) : "\<C-n>"
inoremap <silent><expr> <C-p> coc#pum#visible() ? coc#pum#prev(1) : "\<C-n>"
" Use tab for trigger completion with characters ahead and navigate.
" NOTE: Use command ':verbose imap <tab>' to make sure tab is not mapped by
" other plugin before putting this into your config.
inoremap <silent><expr> <TAB>
\ coc#pum#visible() ? coc#pum#next(1):
\ <SID>CheckBackspace() ? "\<Tab>" :
\ coc#refresh()
inoremap <expr><S-TAB> coc#pum#visible() ? coc#pum#prev(1) : "\<C-h>"
function! CheckBackspace() abort
let col = col('.') - 1
return !col || getline('.')[col - 1] =~# '\s'
endfunction
" Use <c-space> to trigger completion.
if has('nvim')
inoremap <silent><expr> <c-space> coc#refresh()
else
inoremap <silent><expr> <c-@> coc#refresh()
endif
" Make <CR> to accept selected completion item or notify coc.nvim to format
" <C-g>u starts a new undo break, please make your own choice.
inoremap <silent><expr> <CR> coc#pum#visible() ? coc#pum#confirm()
\: "\<C-g>u\<CR>\<c-r>=coc#on_enter()\<CR>"
" Use `[g` and `]g` to navigate diagnostics
" Use `:CocDiagnostics` to get all diagnostics of current buffer in location list.
nmap <silent> [g <Plug>(coc-diagnostic-prev)
nmap <silent> ]g <Plug>(coc-diagnostic-next)
" GoTo code navigation.
nmap <silent> gd <Plug>(coc-definition)
nmap <silent> gy <Plug>(coc-type-definition)
nmap <silent> gi <Plug>(coc-implementation)
nmap <silent> gr <Plug>(coc-references)
" Use K to show documentation in preview window.
nnoremap <silent> K :call ShowDocumentation()<CR>
function! ShowDocumentation()
if CocAction('hasProvider', 'hover')
call CocActionAsync('doHover')
else
call feedkeys('K', 'in')
endif
endfunction
" Highlight the symbol and its references when holding the cursor.
autocmd CursorHold * silent call CocActionAsync('highlight')
" Symbol renaming.
nmap <leader>rn <Plug>(coc-rename)
" Formatting selected code.
xmap <leader>f <Plug>(coc-format-selected)
nmap <leader>f <Plug>(coc-format-selected)
augroup mygroup
autocmd!
" Setup formatexpr specified filetype(s).
autocmd FileType typescript,json setl formatexpr=CocAction('formatSelected')
" Update signature help on jump placeholder.
autocmd User CocJumpPlaceholder call CocActionAsync('showSignatureHelp')
augroup end
" Applying codeAction to the selected region.
" Example: `<leader>aap` for current paragraph
xmap <leader>a <Plug>(coc-codeaction-selected)
nmap <leader>a <Plug>(coc-codeaction-selected)
" Remap keys for applying codeAction to the current buffer.
nmap <leader>ac <Plug>(coc-codeaction)
" Apply AutoFix to problem on the current line.
nmap <leader>qf <Plug>(coc-fix-current)
" Run the Code Lens action on the current line.
nmap <leader>cl <Plug>(coc-codelens-action)
" Map function and class text objects
" NOTE: Requires 'textDocument.documentSymbol' support from the language server.
xmap if <Plug>(coc-funcobj-i)
omap if <Plug>(coc-funcobj-i)
xmap af <Plug>(coc-funcobj-a)
omap af <Plug>(coc-funcobj-a)
xmap ic <Plug>(coc-classobj-i)
omap ic <Plug>(coc-classobj-i)
xmap ac <Plug>(coc-classobj-a)
omap ac <Plug>(coc-classobj-a)
" Remap <C-f> and <C-b> for scroll float windows/popups.
if has('nvim-0.4.0') || has('patch-8.2.0750')
nnoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? coc#float#scroll(1) : "\<C-f>"
nnoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? coc#float#scroll(0) : "\<C-b>"
inoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? "\<c-r>=coc#float#scroll(1)\<cr>" : "\<Right>"
inoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? "\<c-r>=coc#float#scroll(0)\<cr>" : "\<Left>"
vnoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? coc#float#scroll(1) : "\<C-f>"
vnoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? coc#float#scroll(0) : "\<C-b>"
endif
" Use CTRL-S for selections ranges.
" Requires 'textDocument/selectionRange' support of language server.
nmap <silent> <C-s> <Plug>(coc-range-select)
xmap <silent> <C-s> <Plug>(coc-range-select)
" Add `:Format` command to format current buffer.
command! -nargs=0 Format :call CocActionAsync('format')
" Add `:Fold` command to fold current buffer.
command! -nargs=? Fold :call CocAction('fold', <f-args>)
" Add `:OR` command for organize imports of the current buffer.
command! -nargs=0 OR :call CocActionAsync('runCommand', 'editor.action.organizeImport')
" Add (Neo)Vim's native statusline support.
" NOTE: Please see `:h coc-status` for integrations with external plugins that
" provide custom statusline: lightline.vim, vim-airline.
set statusline^=%{coc#status()}%{get(b:,'coc_current_function','')}
" Mappings for CoCList
" Show all diagnostics.
nnoremap <silent><nowait> <space>a :<C-u>CocList diagnostics<cr>
" Manage extensions.
nnoremap <silent><nowait> <space>e :<C-u>CocList extensions<cr>
" Show commands.
nnoremap <silent><nowait> <space>c :<C-u>CocList commands<cr>
" Find symbol of current document.
nnoremap <silent><nowait> <space>o :<C-u>CocList outline<cr>
" Search workspace symbols.
nnoremap <silent><nowait> <space>s :<C-u>CocList -I symbols<cr>
" Do default action for next item.
nnoremap <silent><nowait> <space>j :<C-u>CocNext<CR>
" Do default action for previous item.
nnoremap <silent><nowait> <space>k :<C-u>CocPrev<CR>
" Resume latest coc list.
nnoremap <silent><nowait> <space>p :<C-u>CocListResume<CR>
```
## Articles
- [coc.nvim 插件体系介绍](https://zhuanlan.zhihu.com/p/65524706)
- [CocList 入坑指南](https://zhuanlan.zhihu.com/p/71846145)
- [Create coc.nvim extension to improve Vim experience](https://medium.com/@chemzqm/create-coc-nvim-extension-to-improve-vim-experience-4461df269173)
- [How to write a coc.nvim extension (and why)](https://samroeca.com/coc-plugin.html)
## Troubleshooting
Try these steps when you have problem with coc.nvim.
- Make sure your Vim version >= 8.0 by command `:version`.
- If service failed to start, use command `:CocInfo` or `:checkhealth` on Neovim.
- Checkout the log of coc.nvim by command `:CocOpenLog`.
- When you have issues with the language server, it's recommended to [checkout
the output](https://github.com/neoclide/coc.nvim/wiki/Debug-language-server#using-output-channel).
## Feedback
- If you think Coc is useful, consider giving it a star.
- If you have a question, [ask on gitter](https://gitter.im/neoclide/coc.nvim)
- 中文用户请到 [中文 gitter](https://gitter.im/neoclide/coc-cn) 讨论
- If something is not working, [create an
issue](https://github.com/neoclide/coc.nvim/issues/new).
## Backers
[Become a backer](https://opencollective.com/cocnvim#backer) and get your image on our README on GitHub with a link to your site.
<a href="https://opencollective.com/cocnvim/backer/0/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/0/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/1/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/1/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/2/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/2/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/3/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/3/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/4/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/4/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/5/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/5/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/6/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/6/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/7/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/7/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/8/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/8/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/9/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/9/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/10/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/10/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/11/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/11/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/12/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/12/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/13/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/13/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/14/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/14/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/15/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/15/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/16/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/16/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/17/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/17/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/18/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/18/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/19/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/19/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/20/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/20/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/21/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/21/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/22/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/22/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/23/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/23/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/24/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/24/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/25/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/25/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/26/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/26/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/27/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/27/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/28/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/28/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/29/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/29/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/30/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/30/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/31/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/31/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/32/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/32/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/33/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/33/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/34/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/34/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/35/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/35/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/36/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/36/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/37/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/37/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/38/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/38/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/39/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/39/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/40/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/40/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/41/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/41/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/42/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/42/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/43/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/43/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/44/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/44/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/45/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/45/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim#backer" target="_blank"><img src="https://images.opencollective.com/static/images/become_backer.svg"></a>
## Contributors
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
<tr>
<td align="center"><a href="https://github.com/chemzqm"><img src="https://avatars.githubusercontent.com/u/251450?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Qiming zhao</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=chemzqm" title="Code">💻</a></td>
<td align="center"><a href="https://fann.im/"><img src="https://avatars.githubusercontent.com/u/345274?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Heyward Fann</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=fannheyward" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/weirongxu"><img src="https://avatars.githubusercontent.com/u/1709861?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Raidou</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=weirongxu" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/kevinhwang91"><img src="https://avatars.githubusercontent.com/u/17562139?v=4?s=50" width="50px;" alt=""/><br /><sub><b>kevinhwang91</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=kevinhwang91" title="Code">💻</a></td>
<td align="center"><a href="http://yuuko.cn/"><img src="https://avatars.githubusercontent.com/u/5492542?v=4?s=50" width="50px;" alt=""/><br /><sub><b>年糕小豆汤</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=iamcco" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Avi-D-coder"><img src="https://avatars.githubusercontent.com/u/29133776?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Avi Dessauer</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=Avi-D-coder" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/voldikss"><img src="https://avatars.githubusercontent.com/u/20282795?v=4?s=50" width="50px;" alt=""/><br /><sub><b>最上川</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=voldikss" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://www.microsoft.com/en-us/research/people/yatli/"><img src="https://avatars.githubusercontent.com/u/20684720?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Yatao Li</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=yatli" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/xiyaowong"><img src="https://avatars.githubusercontent.com/u/47070852?v=4?s=50" width="50px;" alt=""/><br /><sub><b>wongxy</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=xiyaowong" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/sam-mccall"><img src="https://avatars.githubusercontent.com/u/548993?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Sam McCall</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=sam-mccall" title="Code">💻</a></td>
<td align="center"><a href="https://samroeca.com/pages/about.html#about"><img src="https://avatars.githubusercontent.com/u/3723671?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Samuel Roeca</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=pappasam" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/amiralies"><img src="https://avatars.githubusercontent.com/u/13261088?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Amirali Esmaeili</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=amiralies" title="Code">💻</a></td>
<td align="center"><a href="https://bit.ly/3cLKGE4"><img src="https://avatars.githubusercontent.com/u/3051781?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Jack Rowlingson</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=jrowlingson" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/tomtomjhj"><img src="https://avatars.githubusercontent.com/u/19489738?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Jaehwang Jung</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=tomtomjhj" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/antoinemadec"><img src="https://avatars.githubusercontent.com/u/10830594?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Antoine</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=antoinemadec" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/cosminadrianpopescu"><img src="https://avatars.githubusercontent.com/u/5187873?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Cosmin Popescu</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=cosminadrianpopescu" title="Code">💻</a></td>
<td align="center"><a href="https://ducnx.com/"><img src="https://avatars.githubusercontent.com/u/1186411?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Duc Nghiem Xuan</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=xuanduc987" title="Code">💻</a></td>
<td align="center"><a href="https://nosubstance.me/"><img src="https://avatars.githubusercontent.com/u/1269815?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Francisco Lopes</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=oblitum" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/daquexian"><img src="https://avatars.githubusercontent.com/u/11607199?v=4?s=50" width="50px;" alt=""/><br /><sub><b>daquexian</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=daquexian" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/apps/dependabot"><img src="https://avatars.githubusercontent.com/in/29110?v=4?s=50" width="50px;" alt=""/><br /><sub><b>dependabot[bot]</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=dependabot[bot]" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/apps/greenkeeper"><img src="https://avatars.githubusercontent.com/in/505?v=4?s=50" width="50px;" alt=""/><br /><sub><b>greenkeeper[bot]</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=greenkeeper[bot]" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://chris-kipp.io/"><img src="https://avatars.githubusercontent.com/u/13974112?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Chris Kipp</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=ckipp01" title="Code">💻</a></td>
<td align="center"><a href="https://dmitmel.github.io/"><img src="https://avatars.githubusercontent.com/u/15367354?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Dmytro Meleshko</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=dmitmel" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/kirillbobyrev"><img src="https://avatars.githubusercontent.com/u/3352968?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Kirill Bobyrev</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=kirillbobyrev" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/gbcreation"><img src="https://avatars.githubusercontent.com/u/454315?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Gontran Baerts</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=gbcreation" title="Code">💻</a></td>
<td align="center"><a href="https://andys8.de/"><img src="https://avatars.githubusercontent.com/u/13085980?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Andy</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=andys8" title="Code">💻</a></td>
<td align="center"><a href="https://www.alexcj96.com/"><img src="https://avatars.githubusercontent.com/u/33961674?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Cheng JIANG</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=GopherJ" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/cpearce-py"><img src="https://avatars.githubusercontent.com/u/53532946?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Corin</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=cpearce-py" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/wodesuck"><img src="https://avatars.githubusercontent.com/u/3124581?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Daniel Zhang</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=wodesuck" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Ferdi265"><img src="https://avatars.githubusercontent.com/u/4077106?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Ferdinand Bachmann</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=Ferdi265" title="Code">💻</a></td>
<td align="center"><a href="https://goushi.me/"><img src="https://avatars.githubusercontent.com/u/16915589?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Guangqing Chen</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=gou4shi1" title="Code">💻</a></td>
<td align="center"><a href="http://jademeskill.com/"><img src="https://avatars.githubusercontent.com/u/2108?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Jade Meskill</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=iamruinous" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/jpoppe"><img src="https://avatars.githubusercontent.com/u/65505?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Jasper Poppe</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=jpoppe" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/jean"><img src="https://avatars.githubusercontent.com/u/84800?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Jean Jordaan</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=jean" title="Code">💻</a></td>
<td align="center"><a href="https://xuann.wang/"><img src="https://avatars.githubusercontent.com/u/44045911?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Kid</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=kidonng" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/Kavantix"><img src="https://avatars.githubusercontent.com/u/6243755?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Pieter van Loon</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=Kavantix" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/rliebz"><img src="https://avatars.githubusercontent.com/u/5321575?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Robert Liebowitz</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=rliebz" title="Code">💻</a></td>
<td align="center"><a href="https://megalithic.io/"><img src="https://avatars.githubusercontent.com/u/3678?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Seth Messer</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=megalithic" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/UncleBill"><img src="https://avatars.githubusercontent.com/u/1141198?v=4?s=50" width="50px;" alt=""/><br /><sub><b>UncleBill</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=UncleBill" title="Code">💻</a></td>
<td align="center"><a href="http://zsaber.com/"><img src="https://avatars.githubusercontent.com/u/6846867?v=4?s=50" width="50px;" alt=""/><br /><sub><b>ZERO</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=ZSaberLv0" title="Code">💻</a></td>
<td align="center"><a href="https://fsouza.blog/"><img src="https://avatars.githubusercontent.com/u/108725?v=4?s=50" width="50px;" alt=""/><br /><sub><b>fsouza</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=fsouza" title="Code">💻</a></td>
<td align="center"><a href="https://onichandame.com/"><img src="https://avatars.githubusercontent.com/u/23728505?v=4?s=50" width="50px;" alt=""/><br /><sub><b>XiaoZhang</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=onichandame" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/whyreal"><img src="https://avatars.githubusercontent.com/u/2084642?v=4?s=50" width="50px;" alt=""/><br /><sub><b>whyreal</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=whyreal" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/yehuohan"><img src="https://avatars.githubusercontent.com/u/17680752?v=4?s=50" width="50px;" alt=""/><br /><sub><b>yehuohan</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=yehuohan" title="Code">💻</a></td>
<td align="center"><a href="http://www.bakudan.farm/"><img src="https://avatars.githubusercontent.com/u/4504807?v=4?s=50" width="50px;" alt=""/><br /><sub><b>バクダンくん</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=Bakudankun" title="Code">💻</a></td>
<td align="center"><a href="https://blog.gopherhub.org/"><img src="https://avatars.githubusercontent.com/u/41671631?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Raphael</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=glepnir" title="Code">💻</a></td>
<td align="center"><a href="https://tbodt.com/"><img src="https://avatars.githubusercontent.com/u/5678977?v=4?s=50" width="50px;" alt=""/><br /><sub><b>tbodt</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=tbodt" title="Code">💻</a></td>
<td align="center"><a href="https://aaronmcdaid.github.io/"><img src="https://avatars.githubusercontent.com/u/64350?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Aaron McDaid</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=aaronmcdaid" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/versi786"><img src="https://avatars.githubusercontent.com/u/7347942?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Aasif Versi</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=versi786" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/abnerf"><img src="https://avatars.githubusercontent.com/u/56300?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Abner Silva</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=abnerf" title="Code">💻</a></td>
<td align="center"><a href="http://sheerun.net/"><img src="https://avatars.githubusercontent.com/u/292365?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Adam Stankiewicz</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=sheerun" title="Code">💻</a></td>
<td align="center"><a href="https://wirow.io/"><img src="https://avatars.githubusercontent.com/u/496683?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Adamansky Anton</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=adamansky" title="Code">💻</a></td>
<td align="center"><a href="https://gabri.me/"><img src="https://avatars.githubusercontent.com/u/63876?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Ahmed El Gabri</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=ahmedelgabri" title="Code">💻</a></td>
<td align="center"><a href="http://theg4sh.ru/"><img src="https://avatars.githubusercontent.com/u/5094691?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Alexandr Kondratev</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=theg4sh" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/andrewkshim"><img src="https://avatars.githubusercontent.com/u/1403410?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Andrew Shim</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=andrewkshim" title="Code">💻</a></td>
<td align="center"><a href="http://andylindeman.com/"><img src="https://avatars.githubusercontent.com/u/395621?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Andy Lindeman</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=alindeman" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/Augustin82"><img src="https://avatars.githubusercontent.com/u/2370810?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Augustin</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=Augustin82" title="Code">💻</a></td>
<td align="center"><a href="https://bananium.fr/"><img src="https://avatars.githubusercontent.com/u/3650385?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Bastien Orivel</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=Eijebong" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/ayroblu"><img src="https://avatars.githubusercontent.com/u/4915682?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Ben Lu</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=ayroblu" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/vantreeseba"><img src="https://avatars.githubusercontent.com/u/316782?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Ben</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=vantreeseba" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/bmon"><img src="https://avatars.githubusercontent.com/u/2115272?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Brendan Roy</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=bmon" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/brianembry"><img src="https://avatars.githubusercontent.com/u/35347666?v=4?s=50" width="50px;" alt=""/><br /><sub><b>brianembry</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=brianembry" title="Code">💻</a></td>
<td align="center"><a href="https://keybase.io/bri_"><img src="https://avatars.githubusercontent.com/u/284789?v=4?s=50" width="50px;" alt=""/><br /><sub><b>br</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=b-" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/casonadams"><img src="https://avatars.githubusercontent.com/u/17597548?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Cason Adams</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=casonadams" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/y9c"><img src="https://avatars.githubusercontent.com/u/5415510?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Chang Y</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=y9c" title="Code">💻</a></td>
<td align="center"><a href="https://yous.be/"><img src="https://avatars.githubusercontent.com/u/853977?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Chayoung You</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=yous" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/chenlijun99"><img src="https://avatars.githubusercontent.com/u/20483759?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Chen Lijun</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=chenlijun99" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/beeender"><img src="https://avatars.githubusercontent.com/u/449296?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Chen Mulong</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=beeender" title="Code">💻</a></td>
<td align="center"><a href="http://weyl.io/"><img src="https://avatars.githubusercontent.com/u/59620?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Chris Weyl</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=rsrchboy" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/dezza"><img src="https://avatars.githubusercontent.com/u/402927?v=4?s=50" width="50px;" alt=""/><br /><sub><b>dezza</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=dezza" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/ceedubs"><img src="https://avatars.githubusercontent.com/u/977929?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Cody Allen</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=ceedubs" title="Code">💻</a></td>
<td align="center"><a href="https://www.25.wf/"><img src="https://avatars.githubusercontent.com/u/145502?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Damien Rajon</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=pyrho" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/daern91"><img src="https://avatars.githubusercontent.com/u/6084427?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Daniel Eriksson</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=daern91" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/danjenson"><img src="https://avatars.githubusercontent.com/u/4793438?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Daniel Jenson</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=danjenson" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/davidmh"><img src="https://avatars.githubusercontent.com/u/594302?v=4?s=50" width="50px;" alt=""/><br /><sub><b>David Mejorado</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=davidmh" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/pderichai"><img src="https://avatars.githubusercontent.com/u/13430946?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Deric Pang</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=pderichai" title="Code">💻</a></td>
<td align="center"><a href="https://www.dingtao.org/blog"><img src="https://avatars.githubusercontent.com/u/12852587?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Ding Tao</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=miyatsu" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/doronbehar"><img src="https://avatars.githubusercontent.com/u/10998835?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Doron Behar</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=doronbehar" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/kovetskiy"><img src="https://avatars.githubusercontent.com/u/8445924?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Egor Kovetskiy</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=kovetskiy" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/elkowar"><img src="https://avatars.githubusercontent.com/u/5300871?v=4?s=50" width="50px;" alt=""/><br /><sub><b>ElKowar</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=elkowar" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/demelev"><img src="https://avatars.githubusercontent.com/u/3952209?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Emeliov Dmitrii</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=demelev" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/sawmurai"><img src="https://avatars.githubusercontent.com/u/6454986?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Fabian Becker</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=sawmurai" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/FallenWarrior2k"><img src="https://avatars.githubusercontent.com/u/20320149?v=4?s=50" width="50px;" alt=""/><br /><sub><b>FallenWarrior2k</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=FallenWarrior2k" title="Code">💻</a></td>
<td align="center"><a href="https://fnune.com/"><img src="https://avatars.githubusercontent.com/u/16181067?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Fausto Núñez Alberro</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=fnune" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/FelipeCRamos"><img src="https://avatars.githubusercontent.com/u/7572843?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Felipe Ramos</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=FelipeCRamos" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/frbor"><img src="https://avatars.githubusercontent.com/u/2320183?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Fredrik Borg</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=frbor" title="Code">💻</a></td>
<td align="center"><a href="http://www.gavinsim.co.uk/"><img src="https://avatars.githubusercontent.com/u/812273?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Gavin Sim</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=gavsim" title="Code">💻</a></td>
<td align="center"><a href="https://fahn.co/"><img src="https://avatars.githubusercontent.com/u/15943089?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Gibson Fahnestock</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=gibfahn" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/giovannigiordano"><img src="https://avatars.githubusercontent.com/u/15145952?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Giovanni Giordano</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=giovannigiordano" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/qubbit"><img src="https://avatars.githubusercontent.com/u/1987473?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Gopal Adhikari</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=qubbit" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/hanh090"><img src="https://avatars.githubusercontent.com/u/3643657?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Hanh Le</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=hanh090" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/hedyhli"><img src="https://avatars.githubusercontent.com/u/50042066?v=4?s=50" width="50px;" alt=""/><br /><sub><b>hedy</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=hedyhli" title="Code">💻</a></td>
<td align="center"><a href="https://www.hendriklammers.com/"><img src="https://avatars.githubusercontent.com/u/754556?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Hendrik Lammers</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=hendriklammers" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/henrybarreto"><img src="https://avatars.githubusercontent.com/u/23109089?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Henry Barreto</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=henrybarreto" title="Code">💻</a></td>
<td align="center"><a href="https://hugo.barrera.io/"><img src="https://avatars.githubusercontent.com/u/730811?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Hugo</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=WhyNotHugo" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/jackieli-tes"><img src="https://avatars.githubusercontent.com/u/64778297?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Jackie Li</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=jackieli-tes" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/MrQubo"><img src="https://avatars.githubusercontent.com/u/16545322?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Jakub Nowak</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=MrQubo" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/euoia"><img src="https://avatars.githubusercontent.com/u/1271216?v=4?s=50" width="50px;" alt=""/><br /><sub><b>James Pickard</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=euoia" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/jsfaint"><img src="https://avatars.githubusercontent.com/u/571829?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Jia Sui</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=jsfaint" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/expipiplus1"><img src="https://avatars.githubusercontent.com/u/857308?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Ellie Hermaszewska</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=expipiplus1" title="Code">💻</a></td>
<td align="center"><a href="https://cincodenada.com/"><img src="https://avatars.githubusercontent.com/u/479715?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Joel Bradshaw</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=cincodenada" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/irizwaririz"><img src="https://avatars.githubusercontent.com/u/10111643?v=4?s=50" width="50px;" alt=""/><br /><sub><b>John Carlo Roberto</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=irizwaririz" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Jomik"><img src="https://avatars.githubusercontent.com/u/699655?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Jonas Holst Damtoft</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=Jomik" title="Code">💻</a></td>
<td align="center"><a href="http://inlehmansterms.net/"><img src="https://avatars.githubusercontent.com/u/3144695?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Jonathan Lehman</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=jdlehman" title="Code">💻</a></td>
<td align="center"><a href="https://joosep.xyz/"><img src="https://avatars.githubusercontent.com/u/9450943?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Joosep Alviste</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=JoosepAlviste" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/josa42"><img src="https://avatars.githubusercontent.com/u/423234?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Josa Gesell</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=josa42" title="Code">💻</a></td>
<td align="center"><a href="https://jawa.dev/"><img src="https://avatars.githubusercontent.com/u/194275?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Joshua Rubin</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=joshuarubin" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/perrin4869"><img src="https://avatars.githubusercontent.com/u/5774716?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Julian Grinblat</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=perrin4869" title="Code">💻</a></td>
<td align="center"><a href="https://valentjn.github.io/"><img src="https://avatars.githubusercontent.com/u/19839841?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Julian Valentin</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=valentjn" title="Code">💻</a></td>
<td align="center"><a href="https://kabbamine.github.io/"><img src="https://avatars.githubusercontent.com/u/5658084?v=4?s=50" width="50px;" alt=""/><br /><sub><b>KabbAmine</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=KabbAmine" title="Code">💻</a></td>
<td align="center"><a href="https://moncargo.io/"><img src="https://avatars.githubusercontent.com/u/10719495?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Kay Gosho</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=acro5piano" title="Code">💻</a></td>
<td align="center"><a href="https://kennyvh.com/"><img src="https://avatars.githubusercontent.com/u/29909203?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Kenny Huynh</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=hkennyv" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/kevinrambaud"><img src="https://avatars.githubusercontent.com/u/7501477?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Kevin Rambaud</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=kevinrambaud" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/kiancross"><img src="https://avatars.githubusercontent.com/u/11011464?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Kian Cross</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=kiancross" title="Code">💻</a></td>
<td align="center"><a href="https://ko-fi.com/kristijanhusak"><img src="https://avatars.githubusercontent.com/u/1782860?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Kristijan Husak</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=kristijanhusak" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/NullVoxPopuli"><img src="https://avatars.githubusercontent.com/u/199018?v=4?s=50" width="50px;" alt=""/><br /><sub><b>NullVoxPopuli</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=NullVoxPopuli" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/lassepe"><img src="https://avatars.githubusercontent.com/u/10076790?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Lasse Peters</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=lassepe" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Linerre"><img src="https://avatars.githubusercontent.com/u/49512984?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Noel Errenil</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=Linerre" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/LinArcX"><img src="https://avatars.githubusercontent.com/u/10884422?v=4?s=50" width="50px;" alt=""/><br /><sub><b>LinArcX</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=LinArcX" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://paypal.me/liuchengxu"><img src="https://avatars.githubusercontent.com/u/8850248?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Liu-Cheng Xu</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=liuchengxu" title="Code">💻</a></td>
<td align="center"><a href="https://malloc.me/"><img src="https://avatars.githubusercontent.com/u/4153572?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Marc</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=foxtrot" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/mgaw"><img src="https://avatars.githubusercontent.com/u/2177016?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Marius Gawrisch</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=mgaw" title="Code">💻</a></td>
<td align="center"><a href="http://www.markhz.com/"><img src="https://avatars.githubusercontent.com/u/2789742?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Mark Hintz</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=mhintz" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/MatElGran"><img src="https://avatars.githubusercontent.com/u/1052778?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Mathieu Le Tiec</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=MatElGran" title="Code">💻</a></td>
<td align="center"><a href="https://matt-w.net/"><img src="https://avatars.githubusercontent.com/u/8656127?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Matt White</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=matt-fff" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/ml-evs"><img src="https://avatars.githubusercontent.com/u/7916000?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Matthew Evans</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=ml-evs" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/Me1onRind"><img src="https://avatars.githubusercontent.com/u/19531270?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Me1onRind</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=Me1onRind" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Qyriad"><img src="https://avatars.githubusercontent.com/u/1542224?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Qyriad</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=Qyriad" title="Code">💻</a></td>
<td align="center"><a href="https://leo.is-a.dev/"><img src="https://avatars.githubusercontent.com/u/35312043?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Narcis B.</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=leonardssh" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Neur1n"><img src="https://avatars.githubusercontent.com/u/17579247?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Neur1n</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=Neur1n" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/nicoder"><img src="https://avatars.githubusercontent.com/u/365210?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Nicolas Dermine</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=nicoder" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/NoahTheDuke"><img src="https://avatars.githubusercontent.com/u/603677?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Noah</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=NoahTheDuke" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/IndexXuan"><img src="https://avatars.githubusercontent.com/u/6322673?v=4?s=50" width="50px;" alt=""/><br /><sub><b>PENG Rui</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=IndexXuan" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://liaoph.com/"><img src="https://avatars.githubusercontent.com/u/6123425?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Paco</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=paco0x" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/peng1999"><img src="https://avatars.githubusercontent.com/u/12483662?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Peng Guanwen</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=peng1999" title="Code">💻</a></td>
<td align="center"><a href="https://www.twitter.com/badeip"><img src="https://avatars.githubusercontent.com/u/1106732?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Petter Wahlman</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=ilAYAli" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/pvonmoradi"><img src="https://avatars.githubusercontent.com/u/1058151?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Pooya Moradi</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=pvonmoradi" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/QuadeMorrison"><img src="https://avatars.githubusercontent.com/u/10917383?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Quade Morrison</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=QuadeMorrison" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/vogler"><img src="https://avatars.githubusercontent.com/u/493741?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Ralf Vogler</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=vogler" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/crccw"><img src="https://avatars.githubusercontent.com/u/41463?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Ran Chen</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=crccw" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://bigardone.dev/"><img src="https://avatars.githubusercontent.com/u/1090272?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Ricardo García Vega</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=bigardone" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/nomasprime"><img src="https://avatars.githubusercontent.com/u/140855?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Rick Jones</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=nomasprime" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/rschristian"><img src="https://avatars.githubusercontent.com/u/33403762?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Ryan Christian</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=rschristian" title="Code">💻</a></td>
<td align="center"><a href="http://salo.so/"><img src="https://avatars.githubusercontent.com/u/4694263?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Salo</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=winterbesos" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Hazelfire"><img src="https://avatars.githubusercontent.com/u/13807753?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Sam Nolan</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=Hazelfire" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/rickysaurav"><img src="https://avatars.githubusercontent.com/u/13986039?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Saurav</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=rickysaurav" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/smackesey"><img src="https://avatars.githubusercontent.com/u/1531373?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Sean Mackesey</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=smackesey" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/sheeldotme"><img src="https://avatars.githubusercontent.com/u/6991406?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Sheel Patel</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=sheeldotme" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/solomonwzs"><img src="https://avatars.githubusercontent.com/u/907942?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Solomon Ng</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=solomonwzs" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/kadimisetty"><img src="https://avatars.githubusercontent.com/u/535947?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Sri Kadimisetty</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=kadimisetty" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/stephenprater"><img src="https://avatars.githubusercontent.com/u/149870?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Stephen Prater</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=stephenprater" title="Code">💻</a></td>
<td align="center"><a href="https://kibs.dk/"><img src="https://avatars.githubusercontent.com/u/14085?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Sune Kibsgaard</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=kibs" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Aquaakuma"><img src="https://avatars.githubusercontent.com/u/31891793?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Aquaakuma</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=Aquaakuma" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/coil398"><img src="https://avatars.githubusercontent.com/u/7694377?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Takumi Kawase</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=coil398" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/theblobscp"><img src="https://avatars.githubusercontent.com/u/81673375?v=4?s=50" width="50px;" alt=""/><br /><sub><b>The Blob SCP</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=theblobscp" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/przepompownia"><img src="https://avatars.githubusercontent.com/u/11404453?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Tomasz N</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=przepompownia" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/gasuketsu"><img src="https://avatars.githubusercontent.com/u/15703757?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Tomoyuki Harada</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=gasuketsu" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/tonyfettes"><img src="https://avatars.githubusercontent.com/u/29998228?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Tony Fettes</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=tonyfettes" title="Code">💻</a></td>
<td align="center"><a href="https://www.git-pull.com/"><img src="https://avatars.githubusercontent.com/u/26336?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Tony Narlock</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=tony" title="Code">💻</a></td>
<td align="center"><a href="https://blog.wwwjfy.net/"><img src="https://avatars.githubusercontent.com/u/126527?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Tony Wang</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=wwwjfy" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Varal7"><img src="https://avatars.githubusercontent.com/u/8019486?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Victor Quach</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=Varal7" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/whisperity"><img src="https://avatars.githubusercontent.com/u/1969470?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Whisperity</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=whisperity" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/willtrnr"><img src="https://avatars.githubusercontent.com/u/1878110?v=4?s=50" width="50px;" alt=""/><br /><sub><b>William Turner</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=willtrnr" title="Code">💻</a></td>
<td align="center"><a href="https://drafts.damnever.com/"><img src="https://avatars.githubusercontent.com/u/6223594?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Xiaochao Dong</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=damnever" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/hyhugh"><img src="https://avatars.githubusercontent.com/u/16500351?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Hugh Hou</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=hyhugh" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/jackielii"><img src="https://avatars.githubusercontent.com/u/360983?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Jackie Li</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=jackielii" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/TheConfuZzledDude"><img src="https://avatars.githubusercontent.com/u/3160203?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Zachary Freed</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=TheConfuZzledDude" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/akiyosi"><img src="https://avatars.githubusercontent.com/u/8478977?v=4?s=50" width="50px;" alt=""/><br /><sub><b>akiyosi</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=akiyosi" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/alexjg"><img src="https://avatars.githubusercontent.com/u/224635?v=4?s=50" width="50px;" alt=""/><br /><sub><b>alexjg</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=alexjg" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/aste4"><img src="https://avatars.githubusercontent.com/u/47511385?v=4?s=50" width="50px;" alt=""/><br /><sub><b>aste4</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=aste4" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/clyfish"><img src="https://avatars.githubusercontent.com/u/541215?v=4?s=50" width="50px;" alt=""/><br /><sub><b>clyfish</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=clyfish" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/dev7ba"><img src="https://avatars.githubusercontent.com/u/93706552?v=4?s=50" width="50px;" alt=""/><br /><sub><b>dev7ba</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=dev7ba" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/diartyz"><img src="https://avatars.githubusercontent.com/u/4486152?v=4?s=50" width="50px;" alt=""/><br /><sub><b>diartyz</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=diartyz" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/doza-daniel"><img src="https://avatars.githubusercontent.com/u/13752683?v=4?s=50" width="50px;" alt=""/><br /><sub><b>doza-daniel</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=doza-daniel" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/equal-l2"><img src="https://avatars.githubusercontent.com/u/8597717?v=4?s=50" width="50px;" alt=""/><br /><sub><b>equal-l2</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=equal-l2" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/FongHou"><img src="https://avatars.githubusercontent.com/u/13973254?v=4?s=50" width="50px;" alt=""/><br /><sub><b>fong</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=FongHou" title="Code">💻</a></td>
<td align="center"><a href="https://blog.hexuhua.vercel.app/"><img src="https://avatars.githubusercontent.com/u/26080416?v=4?s=50" width="50px;" alt=""/><br /><sub><b>hexh</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=hexh250786313" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/hhiraba"><img src="https://avatars.githubusercontent.com/u/4624806?v=4?s=50" width="50px;" alt=""/><br /><sub><b>hhiraba</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=hhiraba" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/ic-768"><img src="https://avatars.githubusercontent.com/u/83115125?v=4?s=50" width="50px;" alt=""/><br /><sub><b>ic-768</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=ic-768" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/javiertury"><img src="https://avatars.githubusercontent.com/u/1520320?v=4?s=50" width="50px;" alt=""/><br /><sub><b>javiertury</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=javiertury" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/seiyeah78"><img src="https://avatars.githubusercontent.com/u/6185139?v=4?s=50" width="50px;" alt=""/><br /><sub><b>karasu</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=seiyeah78" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/kevineato"><img src="https://avatars.githubusercontent.com/u/13666221?v=4?s=50" width="50px;" alt=""/><br /><sub><b>kevineato</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=kevineato" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/m4c0"><img src="https://avatars.githubusercontent.com/u/1664510?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Eduardo Costa</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=m4c0" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/micchy326"><img src="https://avatars.githubusercontent.com/u/23257067?v=4?s=50" width="50px;" alt=""/><br /><sub><b>micchy326</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=micchy326" title="Code">💻</a></td>
<td align="center"><a href="https://keybase.io/midchildan"><img src="https://avatars.githubusercontent.com/u/7343721?v=4?s=50" width="50px;" alt=""/><br /><sub><b>midchildan</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=midchildan" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/minefuto"><img src="https://avatars.githubusercontent.com/u/46558834?v=4?s=50" width="50px;" alt=""/><br /><sub><b>minefuto</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=minefuto" title="Code">💻</a></td>
<td align="center"><a href="https://twitter.com/robokomy"><img src="https://avatars.githubusercontent.com/u/20733354?v=4?s=50" width="50px;" alt=""/><br /><sub><b>miyanokomiya</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=miyanokomiya" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/miyaviee"><img src="https://avatars.githubusercontent.com/u/15247561?v=4?s=50" width="50px;" alt=""/><br /><sub><b>miyaviee</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=miyaviee" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/monkoose"><img src="https://avatars.githubusercontent.com/u/6261276?v=4?s=50" width="50px;" alt=""/><br /><sub><b>monkoose</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=monkoose" title="Code">💻</a> <a href="https://github.com/neoclide/coc.nvim/issues?q=author%3Amonkoose" title="Bug reports">🐛</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/mujx"><img src="https://avatars.githubusercontent.com/u/6430350?v=4?s=50" width="50px;" alt=""/><br /><sub><b>mujx</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=mujx" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/mvilim"><img src="https://avatars.githubusercontent.com/u/40682862?v=4?s=50" width="50px;" alt=""/><br /><sub><b>mvilim</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=mvilim" title="Code">💻</a></td>
<td align="center"><a href="https://naruaway.com/"><img src="https://avatars.githubusercontent.com/u/2931577?v=4?s=50" width="50px;" alt=""/><br /><sub><b>naruaway</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=naruaway" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/piersy"><img src="https://avatars.githubusercontent.com/u/5087847?v=4?s=50" width="50px;" alt=""/><br /><sub><b>piersy</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=piersy" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/ryantig"><img src="https://avatars.githubusercontent.com/u/324810?v=4?s=50" width="50px;" alt=""/><br /><sub><b>ryantig</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=ryantig" title="Code">💻</a></td>
<td align="center"><a href="https://catcat.cc/"><img src="https://avatars.githubusercontent.com/u/19602440?v=4?s=50" width="50px;" alt=""/><br /><sub><b>rydesun</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=rydesun" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/sc00ter"><img src="https://avatars.githubusercontent.com/u/1271025?v=4?s=50" width="50px;" alt=""/><br /><sub><b>sc00ter</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=sc00ter" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/smhc"><img src="https://avatars.githubusercontent.com/u/6404304?v=4?s=50" width="50px;" alt=""/><br /><sub><b>smhc</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=smhc" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/stkaplan"><img src="https://avatars.githubusercontent.com/u/594990?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Sam Kaplan</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=stkaplan" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/tasuten"><img src="https://avatars.githubusercontent.com/u/1623176?v=4?s=50" width="50px;" alt=""/><br /><sub><b>tasuten</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=tasuten" title="Code">💻</a></td>
<td align="center"><a href="http://todesking.com/"><img src="https://avatars.githubusercontent.com/u/112881?v=4?s=50" width="50px;" alt=""/><br /><sub><b>todesking</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=todesking" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/typicode"><img src="https://avatars.githubusercontent.com/u/5502029?v=4?s=50" width="50px;" alt=""/><br /><sub><b>typicode</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=typicode" title="Code">💻</a></td>
<td align="center"><a href="https://limingfei56.github.io/"><img src="https://avatars.githubusercontent.com/u/8553407?v=4?s=50" width="50px;" alt=""/><br /><sub><b>李鸣飞</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=LiMingFei56" title="Code">💻</a></td>
<td align="center"><a href="https://bandism.net/"><img src="https://avatars.githubusercontent.com/u/22633385?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Ikko Ashimine</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=eltociear" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/rammiah"><img src="https://avatars.githubusercontent.com/u/26727562?v=4?s=50" width="50px;" alt=""/><br /><sub><b>Rammiah</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/issues?q=author%3Arammiah" title="Bug reports">🐛</a></td>
</tr>
</table>
<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->
<!-- ALL-CONTRIBUTORS-LIST:END -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://allcontributors.org) specification.
Contributions of any kind are welcome!
## License
Anti 996

View file

@ -0,0 +1,183 @@
scriptencoding utf-8
let g:coc#_context = {'start': 0, 'preselect': -1,'candidates': []}
let g:coc_user_config = get(g:, 'coc_user_config', {})
let g:coc_global_extensions = get(g:, 'coc_global_extensions', [])
let g:coc_selected_text = ''
let g:coc_vim_commands = []
let s:watched_keys = []
let s:is_vim = !has('nvim')
let s:error_sign = get(g:, 'coc_status_error_sign', has('mac') ? '❌ ' : 'E')
let s:warning_sign = get(g:, 'coc_status_warning_sign', has('mac') ? '⚠️ ' : 'W')
let s:select_api = exists('*nvim_select_popupmenu_item')
let s:callbacks = {}
let s:hide_pum = has('nvim-0.6.1') || has('patch-8.2.3389')
function! coc#expandable() abort
return coc#rpc#request('snippetCheck', [1, 0])
endfunction
function! coc#jumpable() abort
return coc#rpc#request('snippetCheck', [0, 1])
endfunction
function! coc#expandableOrJumpable() abort
return coc#rpc#request('snippetCheck', [1, 1])
endfunction
" add vim command to CocCommand list
function! coc#add_command(id, cmd, ...)
let config = {'id':a:id, 'cmd':a:cmd, 'title': get(a:,1,'')}
call add(g:coc_vim_commands, config)
if !coc#rpc#ready() | return | endif
call coc#rpc#notify('addCommand', [config])
endfunction
function! coc#on_enter()
call coc#rpc#notify('CocAutocmd', ['Enter', bufnr('%')])
return ''
endfunction
function! coc#_insert_key(method, key, ...) abort
let prefix = ''
if get(a:, 1, 1)
if pumvisible()
if s:hide_pum
let prefix = "\<C-x>\<C-z>"
else
let g:coc_disable_space_report = 1
let prefix = "\<space>\<bs>"
endif
endif
endif
return prefix."\<c-r>=coc#rpc#".a:method."('doKeymap', ['".a:key."'])\<CR>"
endfunction
function! coc#_complete() abort
let items = get(g:coc#_context, 'candidates', [])
let preselect = get(g:coc#_context, 'preselect', -1)
let startcol = g:coc#_context.start + 1
if s:select_api && len(items) && preselect != -1
noa call complete(startcol, items)
call nvim_select_popupmenu_item(preselect, v:false, v:false, {})
" use <cmd> specific key to preselect item at once
call feedkeys("\<Cmd>\<CR>" , 'i')
else
if pumvisible()
let g:coc_disable_complete_done = 1
endif
call complete(startcol, items)
endif
return ''
endfunction
function! coc#_do_complete(start, items, preselect, changedtick)
if b:changedtick != a:changedtick
return
endif
let g:coc#_context = {
\ 'start': a:start,
\ 'candidates': a:items,
\ 'preselect': a:preselect
\}
if mode() =~# 'i'
call coc#_complete()
endif
endfunction
function! coc#_cancel(...)
call coc#pum#close()
endfunction
" used for statusline
function! coc#status()
let info = get(b:, 'coc_diagnostic_info', {})
let msgs = []
if !empty(info) && get(info, 'error', 0)
call add(msgs, s:error_sign . info['error'])
endif
if !empty(info) && get(info, 'warning', 0)
call add(msgs, s:warning_sign . info['warning'])
endif
return coc#compat#trim(join(msgs, ' ') . ' ' . get(g:, 'coc_status', ''))
endfunction
function! coc#config(section, value)
let g:coc_user_config[a:section] = a:value
call coc#rpc#notify('updateConfig', [a:section, a:value])
endfunction
function! coc#add_extension(...)
if a:0 == 0 | return | endif
call extend(g:coc_global_extensions, a:000)
endfunction
function! coc#_watch(key)
if s:is_vim | return | endif
if index(s:watched_keys, a:key) == -1
call add(s:watched_keys, a:key)
call dictwatcheradd(g:, a:key, function('s:GlobalChange'))
endif
endfunction
function! coc#_unwatch(key)
if s:is_vim | return | endif
let idx = index(s:watched_keys, a:key)
if idx != -1
call remove(s:watched_keys, idx)
call dictwatcherdel(g:, a:key, function('s:GlobalChange'))
endif
endfunction
function! s:GlobalChange(dict, key, val)
call coc#rpc#notify('GlobalChange', [a:key, get(a:val, 'old', v:null), get(a:val, 'new', v:null)])
endfunction
function! coc#on_notify(id, method, Cb)
let key = a:id. '-'.a:method
let s:callbacks[key] = a:Cb
call coc#rpc#notify('registNotification', [a:id, a:method])
endfunction
function! coc#do_notify(id, method, result)
let key = a:id. '-'.a:method
let Fn = s:callbacks[key]
if !empty(Fn)
call Fn(a:result)
endif
endfunction
function! coc#start(...)
let opt = coc#util#get_complete_option()
call CocActionAsync('startCompletion', extend(opt, get(a:, 1, {})))
return ''
endfunction
function! coc#refresh() abort
return "\<c-r>=coc#start()\<CR>"
endfunction
function! coc#_select_confirm() abort
call timer_start(10, { -> coc#pum#select_confirm()})
return s:is_vim || has('nvim-0.5.0') ? "\<Ignore>" : "\<space>\<bs>"
endfunction
function! coc#complete_indent() abort
let curpos = getcurpos()
let indent_len = len(matchstr(getline('.'), '^\s*'))
let startofline = &startofline
let virtualedit = &virtualedit
set nostartofline
set virtualedit=all
normal! ==
let &startofline = startofline
let &virtualedit = virtualedit
let shift = len(matchstr(getline('.'), '^\s*')) - indent_len
let curpos[2] += shift
let curpos[4] += shift
call cursor(curpos[1:])
if shift != 0
if s:is_vim
call timer_start(0, { -> execute('redraw')})
endif
endif
endfunction

View file

@ -0,0 +1,678 @@
" ============================================================================
" Description: Client api used by vim8
" Author: Qiming Zhao <chemzqm@gmail.com>
" Licence: Anti 996 licence
" Last Modified: Jun 03, 2022
" ============================================================================
if has('nvim') | finish | endif
scriptencoding utf-8
let s:funcs = {}
let s:prop_offset = get(g:, 'coc_text_prop_offset', 1000)
let s:namespace_id = 1
let s:namespace_cache = {}
let s:max_src_id = 1000
" bufnr => max textprop id
let s:buffer_id = {}
" srcId => list of types
let s:id_types = {}
" helper {{
function! s:buf_line_count(bufnr) abort
if bufnr('%') == a:bufnr
return line('$')
endif
if exists('*getbufinfo')
let info = getbufinfo(a:bufnr)
if empty(info)
return 0
endif
" vim 8.1 has getbufinfo but no linecount
if has_key(info[0], 'linecount')
return info[0]['linecount']
endif
endif
if exists('*getbufline')
let lines = getbufline(a:bufnr, 1, '$')
return len(lines)
endif
let curr = bufnr('%')
execute 'noa buffer '.a:bufnr
let n = line('$')
execute 'noa buffer '.curr
return n
endfunction
function! s:execute(cmd)
if a:cmd =~# '^echo'
execute a:cmd
else
silent! execute a:cmd
endif
endfunction
" }}"
" nvim client methods {{
function! s:funcs.set_current_dir(dir) abort
execute 'cd '.a:dir
endfunction
function! s:funcs.set_var(name, value) abort
execute 'let g:'.a:name.'= a:value'
endfunction
function! s:funcs.del_var(name) abort
execute 'unlet g:'.a:name
endfunction
function! s:funcs.set_option(name, value) abort
execute 'let &'.a:name.' = a:value'
endfunction
function! s:funcs.set_current_buf(bufnr) abort
if !bufexists(a:bufnr) | return | endif
execute 'buffer '.a:bufnr
endfunction
function! s:funcs.set_current_win(win_id) abort
let [tabnr, winnr] = win_id2tabwin(a:win_id)
if tabnr == 0 | return | endif
execute 'normal! '.tabnr.'gt'
execute winnr.' wincmd w'
endfunction
function! s:funcs.set_current_tabpage(tabnr) abort
execute 'normal! '.a:tabnr.'gt'
endfunction
function! s:funcs.list_wins() abort
return map(getwininfo(), 'v:val["winid"]')
endfunction
function s:inspect_type(v) abort
let types = ['Number', 'String', 'Funcref', 'List', 'Dictionary', 'Float', 'Boolean', 'Null']
return get(types, type(a:v), 'Unknown')
endfunction
function! s:funcs.call_atomic(calls)
let res = []
for i in range(len(a:calls))
let [key, arglist] = a:calls[i]
let name = key[5:]
try
call add(res, call(s:funcs[name], arglist))
catch /.*/
return [res, [i, "VimException(".s:inspect_type(v:exception).")", v:exception . ' on '.v:throwpoint]]
endtry
endfor
return [res, v:null]
endfunction
function! s:funcs.set_client_info(...) abort
endfunction
function! s:funcs.subscribe(...) abort
endfunction
function! s:funcs.unsubscribe(...) abort
endfunction
function! s:funcs.call_function(method, args) abort
return call(a:method, a:args)
endfunction
function! s:funcs.call_dict_function(dict, method, args) abort
return call(a:method, a:args, a:dict)
endfunction
function! s:funcs.command(command) abort
" command that could cause cursor vanish
if a:command =~# '^echo' || a:command =~# '^redraw' || a:command =~# '^sign place'
call timer_start(0, {-> s:execute(a:command)})
else
execute a:command
let err = get(g:, 'errmsg', '')
" get error from python script run.
if !empty(err)
unlet g:errmsg
throw err
endif
endif
endfunction
function! s:funcs.eval(expr) abort
return eval(a:expr)
endfunction
function! s:funcs.get_api_info()
let names = coc#api#func_names()
return [1, {'functions': map(names, '{"name": "nvim_".v:val}')}]
endfunction
function! s:funcs.list_bufs()
return map(getbufinfo({'bufloaded': 1}), 'v:val["bufnr"]')
endfunction
function! s:funcs.feedkeys(keys, mode, escape_csi)
call feedkeys(a:keys, a:mode)
endfunction
function! s:funcs.list_runtime_paths()
return globpath(&runtimepath, '', 0, 1)
endfunction
function! s:funcs.command_output(cmd)
return execute(a:cmd)
endfunction
function! s:funcs.get_current_line()
return getline('.')
endfunction
function! s:funcs.set_current_line(line)
call setline('.', a:line)
endfunction
function! s:funcs.del_current_line(line)
execute 'normal! dd'
endfunction
function! s:funcs.get_var(var)
return get(g:, a:var, v:null)
endfunction
function! s:funcs.get_vvar(var)
return get(v:, a:var, v:null)
endfunction
function! s:funcs.get_option(name)
return eval('&'.a:name)
endfunction
function! s:funcs.get_current_buf()
return bufnr('%')
endfunction
function! s:funcs.get_current_win()
return win_getid()
endfunction
function! s:funcs.get_current_tabpage()
return tabpagenr()
endfunction
function! s:funcs.list_tabpages()
return range(1, tabpagenr('$'))
endfunction
function! s:funcs.get_mode()
return {'blocking': v:false, 'mode': mode()}
endfunction
function! s:funcs.strwidth(str)
return strwidth(a:str)
endfunction
function! s:funcs.out_write(str)
echon a:str
call timer_start(0, {-> s:execute('redraw')})
endfunction
function! s:funcs.err_write(str)
"echoerr a:str
endfunction
function! s:funcs.err_writeln(str)
echohl ErrorMsg
echom a:str
echohl None
call timer_start(0, {-> s:execute('redraw')})
endfunction
function! s:funcs.create_namespace(name) abort
if empty(a:name)
let id = s:namespace_id
let s:namespace_id = s:namespace_id + 1
return id
endif
let id = get(s:namespace_cache, a:name, 0)
if !id
let id = s:namespace_id
let s:namespace_id = s:namespace_id + 1
let s:namespace_cache[a:name] = id
endif
return id
endfunction
" }}
" buffer methods {{
function! s:funcs.buf_set_option(bufnr, name, val)
let val = a:val
if val is v:true
let val = 1
elseif val is v:false
let val = 0
endif
return setbufvar(a:bufnr, '&'.a:name, val)
endfunction
function! s:funcs.buf_get_changedtick(bufnr)
return getbufvar(a:bufnr, 'changedtick')
endfunction
function! s:funcs.buf_is_valid(bufnr)
return bufloaded(a:bufnr) ? v:true : v:false
endfunction
function! s:funcs.buf_get_mark(bufnr, name)
let nr = bufnr('%')
if a:bufnr != 0 || a:bufnr != nr
throw 'buf_get_mark support current buffer only'
endif
return [line("'" . a:name), col("'" . a:name)]
endfunction
function! s:funcs.buf_add_highlight(bufnr, srcId, hlGroup, line, colStart, colEnd, ...) abort
if !has('patch-8.1.1719')
return
endif
if a:srcId == 0
let srcId = s:max_src_id + 1
let s:max_src_id = srcId
else
let srcId = a:srcId
endif
let bufnr = a:bufnr == 0 ? bufnr('%') : a:bufnr
let type = a:hlGroup.'_'.srcId
let types = get(s:id_types, srcId, [])
if index(types, type) == -1
call add(types, type)
let s:id_types[srcId] = types
call prop_type_add(type, extend({'highlight': a:hlGroup}, get(a:, 1, {})))
endif
let end = a:colEnd == -1 ? strlen(getbufline(bufnr, a:line + 1)[0]) + 1 : a:colEnd + 1
if end < a:colStart + 1
return
endif
let id = s:generate_id(a:bufnr)
try
call prop_add(a:line + 1, a:colStart + 1, {'bufnr': bufnr, 'type': type, 'id': id, 'end_col': end})
catch /^Vim\%((\a\+)\)\=:E967/
" ignore 967
endtry
if a:srcId == 0
" return generated srcId
return srcId
endif
endfunction
function! s:funcs.buf_clear_namespace(bufnr, srcId, startLine, endLine) abort
if !has('patch-8.1.1719')
return
endif
let bufnr = a:bufnr == 0 ? bufnr('%') : a:bufnr
let start = a:startLine + 1
let end = a:endLine == -1 ? len(getbufline(bufnr, 1, '$')) : a:endLine
if a:srcId == -1
if has_key(s:buffer_id, a:bufnr)
unlet s:buffer_id[a:bufnr]
endif
call prop_clear(start, end, {'bufnr' : bufnr})
else
for type in get(s:id_types, a:srcId, [])
try
call prop_remove({'bufnr': bufnr, 'all': 1, 'type': type}, start, end)
catch /^Vim\%((\a\+)\)\=:E968/
" ignore 968
endtry
endfor
endif
endfunction
function! s:funcs.buf_line_count(bufnr) abort
return s:buf_line_count(a:bufnr)
endfunction
function! s:funcs.buf_attach(...)
" not supported
return 1
endfunction
function! s:funcs.buf_detach()
" not supported
return 1
endfunction
function! s:funcs.buf_get_lines(bufnr, start, end, strict) abort
let lines = getbufline(a:bufnr, 1, '$')
let start = a:start < 0 ? a:start + 1 : a:start
let end = a:end < 0 ? a:end + 1 : a:end
if a:strict && end > len(lines)
throw 'line number out of range: '. end
endif
return lines[start : end - 1]
endfunction
function! s:funcs.buf_set_lines(bufnr, start, end, strict, ...) abort
let bufnr = a:bufnr == 0 ? bufnr('%') : a:bufnr
if !bufloaded(bufnr)
return
endif
let replacement = get(a:, 1, [])
let lineCount = s:buf_line_count(bufnr)
let startLnum = a:start >= 0 ? a:start + 1 : lineCount + a:start + 2
let end = a:end >= 0 ? a:end : lineCount + a:end + 1
if end == lineCount + 1
let end = lineCount
endif
let delCount = end - (startLnum - 1)
let changeBuffer = 0
let curr = bufnr('%')
if bufnr != curr && !exists('*setbufline')
let changeBuffer = 1
exe 'buffer '.bufnr
endif
if bufnr == curr || changeBuffer
" replace
let storeView = winsaveview()
if delCount == len(replacement)
call setline(startLnum, replacement)
else
if len(replacement)
call append(startLnum - 1, replacement)
endif
if delCount
let start = startLnum + len(replacement)
let saved_reg = @"
let system_reg = @*
if exists('*deletebufline')
silent call deletebufline(curr, start, start + delCount - 1)
else
silent execute start . ','.(start + delCount - 1).'d'
endif
let @" = saved_reg
let @* = system_reg
endif
endif
call winrestview(storeView)
if changeBuffer
exe 'buffer '.curr
endif
elseif exists('*setbufline')
" replace
if delCount == len(replacement)
" 8.0.1039
call setbufline(bufnr, startLnum, replacement)
else
if len(replacement)
" 8.10037
call appendbufline(bufnr, startLnum - 1, replacement)
endif
if delCount
let start = startLnum + len(replacement)
let saved_reg = @"
let system_reg = @*
"8.1.0039
silent call deletebufline(bufnr, start, start + delCount - 1)
let @" = saved_reg
let @* = system_reg
endif
endif
endif
endfunction
function! s:funcs.buf_set_name(bufnr, name) abort
let nr = bufnr('%')
if a:bufnr != nr
throw 'buf_set_name support current buffer only'
else
execute '0f'
execute 'file '.fnameescape(a:name)
endif
endfunction
function! s:funcs.buf_get_var(bufnr, name)
return getbufvar(a:bufnr, a:name)
endfunction
function! s:funcs.buf_set_var(bufnr, name, val)
if !bufloaded(a:bufnr) | return | endif
call setbufvar(a:bufnr, a:name, a:val)
endfunction
function! s:funcs.buf_del_var(bufnr, name)
if bufnr == bufnr('%')
execute 'unlet! b:'.a:name
elseif exists('*win_execute')
let winid = coc#compat#buf_win_id(a:bufnr)
if winid != -1
call win_execute(winid, 'unlet! b:'.a:name)
endif
endif
endfunction
function! s:funcs.buf_get_option(bufnr, name)
return getbufvar(a:bufnr, '&'.a:name)
endfunction
function! s:funcs.buf_get_name(bufnr)
return bufname(a:bufnr)
endfunction
" }}
" window methods {{
function! s:funcs.win_get_buf(winid)
return winbufnr(a:winid)
endfunction
function! s:funcs.win_get_position(win_id) abort
let [row, col] = win_screenpos(a:win_id)
if row == 0 && col == 0
throw 'Invalid window '.a:win_id
endif
return [row - 1, col - 1]
endfunction
function! s:funcs.win_get_height(win_id) abort
return winheight(a:win_id)
endfunction
function! s:funcs.win_get_width(win_id) abort
return winwidth(a:win_id)
endfunction
if exists('*win_execute')
function! s:win_execute(win_id, cmd, ...) abort
let ref = get(a:000, 0, v:null)
let cmd = ref is v:null ? a:cmd : 'let ref["out"] = ' . a:cmd
call win_execute(a:win_id, cmd)
endfunction
else
function! s:win_execute(win_id, cmd, ...) abort
let ref = get(a:000, 0, v:null)
let cmd = ref is v:null ? a:cmd : 'let ref["out"] = ' . a:cmd
let winid = win_getid()
if winid == a:win_id
execute cmd
else
let goto_status = win_gotoid(a:win_id)
if !goto_status
return
endif
execute cmd
call win_gotoid(winid)
endif
endfunction
endif
function! s:get_tabnr(winid) abort
let ref = {}
call s:win_execute(a:winid, 'tabpagenr()', ref)
return get(ref, 'out', 0)
endfunction
function! s:funcs.win_get_cursor(win_id) abort
let ref = {}
call s:win_execute(a:win_id, "[line('.'), col('.')-1]", ref)
return get(ref, 'out', 0)
endfunction
function! s:funcs.win_get_var(win_id, name, ...) abort
let tabnr = s:get_tabnr(a:win_id)
if tabnr
return gettabwinvar(tabnr, a:win_id, a:name, get(a:, 1, v:null))
endif
throw 'window '.a:win_id. ' not a visible window'
endfunction
function! s:funcs.win_set_width(win_id, width) abort
call s:win_execute(a:win_id, 'vertical resize '.a:width)
endfunction
function! s:funcs.win_set_buf(win_id, buf_id) abort
call s:win_execute(a:win_id, 'buffer '.a:buf_id)
endfunction
function! s:funcs.win_get_option(win_id, name) abort
let tabnr = s:get_tabnr(a:win_id)
if tabnr
return gettabwinvar(tabnr, a:win_id, '&'.a:name)
endif
throw 'window '.a:win_id. ' not a valid window'
endfunction
function! s:funcs.win_set_height(win_id, height) abort
return s:win_execute(a:win_id, 'resize '.a:height)
endfunction
function! s:funcs.win_set_option(win_id, name, value) abort
let val = a:value
if val is v:true
let val = 1
elseif val is v:false
let val = 0
endif
let tabnr = s:get_tabnr(a:win_id)
if tabnr
call settabwinvar(tabnr, a:win_id, '&'.a:name, val)
else
throw 'window '.a:win_id. ' not a valid window'
endif
endfunction
function! s:funcs.win_set_var(win_id, name, value) abort
let tabnr = s:get_tabnr(a:win_id)
if tabnr
call settabwinvar(tabnr, a:win_id, a:name, a:value)
else
throw "Invalid window id ".a:win_id
endif
endfunction
function! s:funcs.win_del_var(win_id, name) abort
call s:win_execute(a:win_id, 'unlet! w:'.a:name)
endfunction
function! s:funcs.win_is_valid(win_id) abort
let info = getwininfo(a:win_id)
return empty(info) ? v:false : v:true
endfunction
function! s:funcs.win_get_number(win_id) abort
let info = getwininfo(a:win_id)
if empty(info)
throw 'Invalid window id '.a:win_id
endif
return info[0]['winnr']
endfunction
function! s:funcs.win_set_cursor(win_id, pos) abort
let [line, col] = a:pos
call s:win_execute(a:win_id, 'call cursor('.line.','.(col + 1).')')
endfunction
function! s:funcs.win_close(win_id, ...) abort
let force = get(a:, 1, 0)
call s:win_execute(a:win_id, 'close'.(force ? '!' : ''))
endfunction
function! s:funcs.win_get_tabpage(win_id) abort
let tabnr = s:get_tabnr(a:win_id)
if !tabnr
throw 'Invalid window id '.a:win_id
endif
return tabnr
endfunction
" }}
" tabpage methods {{
function! s:funcs.tabpage_get_number(id)
return a:id
endfunction
function! s:funcs.tabpage_list_wins(tabnr)
let info = getwininfo()
return map(filter(info, 'v:val["tabnr"] == a:tabnr'), 'v:val["winid"]')
endfunction
function! s:funcs.tabpage_get_var(tabnr, name)
return gettabvar(a:tabnr, a:name, v:null)
endfunction
function! s:funcs.tabpage_set_var(tabnr, name, value)
call settabvar(a:tabnr, a:name, a:value)
endfunction
function! s:funcs.tabpage_del_var(tabnr, name)
call settabvar(a:tabnr, a:name, v:null)
endfunction
function! s:funcs.tabpage_is_valid(tabnr)
let max = tabpagenr('$')
return a:tabnr <= max
endfunction
function! s:funcs.tabpage_get_win(tabnr)
let wnr = tabpagewinnr(a:tabnr)
return win_getid(wnr, a:tabnr)
endfunction
function! s:generate_id(bufnr) abort
let max = get(s:buffer_id, a:bufnr, s:prop_offset)
let id = max + 1
let s:buffer_id[a:bufnr] = id
return id
endfunction
" }}
function! coc#api#get_types(srcId) abort
return get(s:id_types, a:srcId, [])
endfunction
function! coc#api#func_names() abort
return keys(s:funcs)
endfunction
function! coc#api#call(method, args) abort
let err = v:null
let res = v:null
try
let res = call(s:funcs[a:method], a:args)
catch /.*/
let err = v:exception .' on api "'.a:method.'" '.json_encode(a:args)
endtry
return [err, res]
endfunction
function! coc#api#exec(method, args) abort
return call(s:funcs[a:method], a:args)
endfunction
function! coc#api#notify(method, args) abort
try
call call(s:funcs[a:method], a:args)
catch /.*/
let g:b = v:exception
call coc#rpc#notify('nvim_error_event', [0, v:exception.' on api "'.a:method.'" '.json_encode(a:args)])
endtry
endfunction
" vim: set sw=2 ts=2 sts=2 et tw=78 foldmarker={{,}} foldmethod=marker foldlevel=0:

View file

@ -0,0 +1,340 @@
scriptencoding utf-8
let s:root = expand('<sfile>:h:h:h')
let s:is_vim = !has('nvim')
let s:is_win = has("win32") || has("win64")
let s:clients = {}
if get(g:, 'node_client_debug', 0)
echohl WarningMsg | echo '[coc.nvim] Enable g:node_client_debug could impact your vim experience' | echohl None
let $NODE_CLIENT_LOG_LEVEL = 'debug'
if exists('$NODE_CLIENT_LOG_FILE')
let s:logfile = resolve($NODE_CLIENT_LOG_FILE)
else
let s:logfile = tempname()
let $NODE_CLIENT_LOG_FILE = s:logfile
endif
endif
" create a client
function! coc#client#create(name, command)
let client = {}
let client['command'] = a:command
let client['name'] = a:name
let client['running'] = 0
let client['async_req_id'] = 1
let client['async_callbacks'] = {}
" vim only
let client['channel'] = v:null
" neovim only
let client['chan_id'] = 0
let client['start'] = function('s:start', [], client)
let client['request'] = function('s:request', [], client)
let client['notify'] = function('s:notify', [], client)
let client['request_async'] = function('s:request_async', [], client)
let client['on_async_response'] = function('s:on_async_response', [], client)
let s:clients[a:name] = client
return client
endfunction
function! s:start() dict
if self.running | return | endif
if !isdirectory(getcwd())
echohl Error | echon '[coc.nvim] Current cwd is not a valid directory.' | echohl None
return
endif
let timeout = string(get(g:, 'coc_channel_timeout', 30))
let tmpdir = fnamemodify(tempname(), ':p:h')
if s:is_vim
if get(g:, 'node_client_debug', 0)
let file = tmpdir . '/coc.log'
call ch_logfile(file, 'w')
echohl MoreMsg | echo '[coc.nvim] channel log to '.file | echohl None
endif
let options = {
\ 'in_mode': 'json',
\ 'out_mode': 'json',
\ 'err_mode': 'nl',
\ 'err_cb': {channel, message -> s:on_stderr(self.name, split(message, "\n"))},
\ 'exit_cb': {channel, code -> s:on_exit(self.name, code)},
\ 'env': {
\ 'NODE_NO_WARNINGS': '1',
\ 'VIM_NODE_RPC': '1',
\ 'COC_NVIM': '1',
\ 'COC_CHANNEL_TIMEOUT': timeout,
\ 'TMPDIR': tmpdir,
\ }
\}
if has("patch-8.1.350")
let options['noblock'] = 1
endif
let job = job_start(self.command, options)
let status = job_status(job)
if status !=# 'run'
let self.running = 0
echohl Error | echom 'Failed to start '.self.name.' service' | echohl None
return
endif
let self['running'] = 1
let self['channel'] = job_getchannel(job)
else
let original = {}
let opts = {
\ 'rpc': 1,
\ 'on_stderr': {channel, msgs -> s:on_stderr(self.name, msgs)},
\ 'on_exit': {channel, code -> s:on_exit(self.name, code)},
\ }
if has('nvim-0.5.0')
" could use env option
let opts['env'] = {
\ 'COC_NVIM': '1',
\ 'NODE_NO_WARNINGS': '1',
\ 'COC_CHANNEL_TIMEOUT': timeout,
\ 'TMPDIR': tmpdir
\ }
else
if exists('*getenv')
let original = {
\ 'NODE_NO_WARNINGS': getenv('NODE_NO_WARNINGS'),
\ 'TMPDIR': getenv('TMPDIR'),
\ }
endif
if exists('*setenv')
call setenv('COC_NVIM', '1')
call setenv('NODE_NO_WARNINGS', '1')
call setenv('COC_CHANNEL_TIMEOUT', timeout)
call setenv('TMPDIR', tmpdir)
else
let $NODE_NO_WARNINGS = 1
let $TMPDIR = tmpdir
endif
endif
let chan_id = jobstart(self.command, opts)
if !empty(original)
if exists('*setenv')
for key in keys(original)
call setenv(key, original[key])
endfor
else
let $TMPDIR = original['TMPDIR']
endif
endif
if chan_id <= 0
echohl Error | echom 'Failed to start '.self.name.' service' | echohl None
return
endif
let self['chan_id'] = chan_id
let self['running'] = 1
endif
endfunction
function! s:on_stderr(name, msgs)
if get(g:, 'coc_vim_leaving', 0) | return | endif
if get(g:, 'coc_disable_uncaught_error', 0) | return | endif
let data = filter(copy(a:msgs), '!empty(v:val)')
if empty(data) | return | endif
let client = a:name ==# 'coc' ? '[coc.nvim]' : '['.a:name.']'
let data[0] = client.': '.data[0]
call coc#ui#echo_messages('Error', data)
endfunction
function! s:on_exit(name, code) abort
if get(g:, 'coc_vim_leaving', 0) | return | endif
let client = get(s:clients, a:name, v:null)
if empty(client) | return | endif
if client['running'] != 1 | return | endif
let client['running'] = 0
let client['chan_id'] = 0
let client['channel'] = v:null
let client['async_req_id'] = 1
if a:code != 0 && a:code != 143
echohl Error | echom 'client '.a:name. ' abnormal exit with: '.a:code | echohl None
endif
endfunction
function! coc#client#get_client(name) abort
return get(s:clients, a:name, v:null)
endfunction
function! coc#client#get_channel(client)
if s:is_vim
return a:client['channel']
endif
return a:client['chan_id']
endfunction
function! s:request(method, args) dict
let channel = coc#client#get_channel(self)
if empty(channel) | return '' | endif
try
if s:is_vim
let res = ch_evalexpr(channel, [a:method, a:args], {'timeout': 60 * 1000})
if type(res) == 1 && res ==# ''
throw 'request '.a:method. ' '.string(a:args).' timeout after 60s'
endif
let [l:errmsg, res] = res
if !empty(l:errmsg)
throw l:errmsg
else
return res
endif
else
return call('rpcrequest', [channel, a:method] + a:args)
endif
catch /.*/
if v:exception =~# 'E475'
if get(g:, 'coc_vim_leaving', 0) | return | endif
echohl Error | echom '['.self.name.'] server connection lost' | echohl None
let name = self.name
call s:on_exit(name, 0)
execute 'silent do User ConnectionLost'.toupper(name[0]).name[1:]
elseif v:exception =~# 'E12'
" neovim's bug, ignore it
else
echohl Error | echo 'Error on request ('.a:method.'): '.v:exception | echohl None
endif
endtry
endfunction
function! s:notify(method, args) dict
let channel = coc#client#get_channel(self)
if empty(channel)
return ''
endif
try
if s:is_vim
call ch_sendraw(channel, json_encode([0, [a:method, a:args]])."\n")
else
call call('rpcnotify', [channel, a:method] + a:args)
endif
catch /.*/
if v:exception =~# 'E475'
if get(g:, 'coc_vim_leaving', 0)
return
endif
echohl Error | echom '['.self.name.'] server connection lost' | echohl None
let name = self.name
call s:on_exit(name, 0)
execute 'silent do User ConnectionLost'.toupper(name[0]).name[1:]
elseif v:exception =~# 'E12'
" neovim's bug, ignore it
else
echohl Error | echo 'Error on notify ('.a:method.'): '.v:exception | echohl None
endif
endtry
endfunction
function! s:request_async(method, args, cb) dict
let channel = coc#client#get_channel(self)
if empty(channel) | return '' | endif
if type(a:cb) != 2
echohl Error | echom '['.self['name'].'] Callback should be function' | echohl None
return
endif
let id = self.async_req_id
let self.async_req_id = id + 1
let self.async_callbacks[id] = a:cb
call self['notify']('nvim_async_request_event', [id, a:method, a:args])
endfunction
function! s:on_async_response(id, resp, isErr) dict
let Callback = get(self.async_callbacks, a:id, v:null)
if empty(Callback)
" should not happen
echohl Error | echom 'callback not found' | echohl None
return
endif
call remove(self.async_callbacks, a:id)
if a:isErr
call call(Callback, [a:resp, v:null])
else
call call(Callback, [v:null, a:resp])
endif
endfunction
function! coc#client#is_running(name) abort
let client = get(s:clients, a:name, v:null)
if empty(client) | return 0 | endif
if !client['running'] | return 0 | endif
if s:is_vim
let status = job_status(ch_getjob(client['channel']))
return status ==# 'run'
else
let chan_id = client['chan_id']
let [code] = jobwait([chan_id], 10)
return code == -1
endif
endfunction
function! coc#client#stop(name) abort
let client = get(s:clients, a:name, v:null)
if empty(client) | return 1 | endif
let running = coc#client#is_running(a:name)
if !running
echohl WarningMsg | echom 'client '.a:name. ' not running.' | echohl None
return 1
endif
if s:is_vim
call job_stop(ch_getjob(client['channel']), 'term')
else
call jobstop(client['chan_id'])
endif
sleep 200m
if coc#client#is_running(a:name)
echohl Error | echom 'client '.a:name. ' stop failed.' | echohl None
return 0
endif
call s:on_exit(a:name, 0)
echohl MoreMsg | echom 'client '.a:name.' stopped!' | echohl None
return 1
endfunction
function! coc#client#request(name, method, args)
let client = get(s:clients, a:name, v:null)
if !empty(client)
return client['request'](a:method, a:args)
endif
endfunction
function! coc#client#notify(name, method, args)
let client = get(s:clients, a:name, v:null)
if !empty(client)
call client['notify'](a:method, a:args)
endif
endfunction
function! coc#client#request_async(name, method, args, cb)
let client = get(s:clients, a:name, v:null)
if !empty(client)
call client['request_async'](a:method, a:args, a:cb)
endif
endfunction
function! coc#client#on_response(name, id, resp, isErr)
let client = get(s:clients, a:name, v:null)
if !empty(client)
call client['on_async_response'](a:id, a:resp, a:isErr)
endif
endfunction
function! coc#client#restart(name) abort
let stopped = coc#client#stop(a:name)
if !stopped | return | endif
let client = get(s:clients, a:name, v:null)
if !empty(client)
call client['start']()
endif
endfunction
function! coc#client#restart_all()
for key in keys(s:clients)
call coc#client#restart(key)
endfor
endfunction
function! coc#client#open_log()
if !get(g:, 'node_client_debug', 0)
echohl Error | echon '[coc.nvim] use let g:node_client_debug = 1 in your vimrc to enabled debug mode.' | echohl None
return
endif
execute 'vs '.s:logfile
endfunction

View file

@ -0,0 +1,283 @@
scriptencoding utf-8
let s:activate = ""
let s:quit = ""
if has("gui_macvim") && has('gui_running')
let s:app = "MacVim"
elseif $TERM_PROGRAM ==# "Apple_Terminal"
let s:app = "Terminal"
elseif $TERM_PROGRAM ==# "iTerm.app"
let s:app = "iTerm2"
elseif has('mac')
let s:app = "System Events"
let s:quit = "quit"
let s:activate = 'activate'
endif
" Returns an approximate grey index for the given grey level
fun! s:grey_number(x)
if &t_Co == 88
if a:x < 23
return 0
elseif a:x < 69
return 1
elseif a:x < 103
return 2
elseif a:x < 127
return 3
elseif a:x < 150
return 4
elseif a:x < 173
return 5
elseif a:x < 196
return 6
elseif a:x < 219
return 7
elseif a:x < 243
return 8
else
return 9
endif
else
if a:x < 14
return 0
else
let l:n = (a:x - 8) / 10
let l:m = (a:x - 8) % 10
if l:m < 5
return l:n
else
return l:n + 1
endif
endif
endif
endfun
" Returns the actual grey level represented by the grey index
fun! s:grey_level(n)
if &t_Co == 88
if a:n == 0
return 0
elseif a:n == 1
return 46
elseif a:n == 2
return 92
elseif a:n == 3
return 115
elseif a:n == 4
return 139
elseif a:n == 5
return 162
elseif a:n == 6
return 185
elseif a:n == 7
return 208
elseif a:n == 8
return 231
else
return 255
endif
else
if a:n == 0
return 0
else
return 8 + (a:n * 10)
endif
endif
endfun
" Returns the palette index for the given grey index
fun! s:grey_colour(n)
if &t_Co == 88
if a:n == 0
return 16
elseif a:n == 9
return 79
else
return 79 + a:n
endif
else
if a:n == 0
return 16
elseif a:n == 25
return 231
else
return 231 + a:n
endif
endif
endfun
" Returns an approximate colour index for the given colour level
fun! s:rgb_number(x)
if &t_Co == 88
if a:x < 69
return 0
elseif a:x < 172
return 1
elseif a:x < 230
return 2
else
return 3
endif
else
if a:x < 75
return 0
else
let l:n = (a:x - 55) / 40
let l:m = (a:x - 55) % 40
if l:m < 20
return l:n
else
return l:n + 1
endif
endif
endif
endfun
" Returns the palette index for the given R/G/B colour indices
fun! s:rgb_colour(x, y, z)
if &t_Co == 88
return 16 + (a:x * 16) + (a:y * 4) + a:z
else
return 16 + (a:x * 36) + (a:y * 6) + a:z
endif
endfun
" Returns the actual colour level for the given colour index
fun! s:rgb_level(n)
if &t_Co == 88
if a:n == 0
return 0
elseif a:n == 1
return 139
elseif a:n == 2
return 205
else
return 255
endif
else
if a:n == 0
return 0
else
return 55 + (a:n * 40)
endif
endif
endfun
" Returns the palette index to approximate the given R/G/B colour levels
fun! s:colour(r, g, b)
" Get the closest grey
let l:gx = s:grey_number(a:r)
let l:gy = s:grey_number(a:g)
let l:gz = s:grey_number(a:b)
" Get the closest colour
let l:x = s:rgb_number(a:r)
let l:y = s:rgb_number(a:g)
let l:z = s:rgb_number(a:b)
if l:gx == l:gy && l:gy == l:gz
" There are two possibilities
let l:dgr = s:grey_level(l:gx) - a:r
let l:dgg = s:grey_level(l:gy) - a:g
let l:dgb = s:grey_level(l:gz) - a:b
let l:dgrey = (l:dgr * l:dgr) + (l:dgg * l:dgg) + (l:dgb * l:dgb)
let l:dr = s:rgb_level(l:gx) - a:r
let l:dg = s:rgb_level(l:gy) - a:g
let l:db = s:rgb_level(l:gz) - a:b
let l:drgb = (l:dr * l:dr) + (l:dg * l:dg) + (l:db * l:db)
if l:dgrey < l:drgb
" Use the grey
return s:grey_colour(l:gx)
else
" Use the colour
return s:rgb_colour(l:x, l:y, l:z)
endif
else
" Only one possibility
return s:rgb_colour(l:x, l:y, l:z)
endif
endfun
function! coc#color#rgb2term(rgb)
let l:r = ("0x" . strpart(a:rgb, 0, 2)) + 0
let l:g = ("0x" . strpart(a:rgb, 2, 2)) + 0
let l:b = ("0x" . strpart(a:rgb, 4, 2)) + 0
return s:colour(l:r, l:g, l:b)
endfun
" [r, g, b] ['255', '255', '255']
" return ['65535', '65535', '65535'] or return v:false to cancel
function! coc#color#pick_color(default_color)
if has('mac')
let default_color = map(a:default_color, {idx, val -> str2nr(val) * 65535 / 255 })
" This is the AppleScript magic:
let ascrpt = ['-e "tell application \"' . s:app . '\""',
\ '-e "' . s:activate . '"',
\ "-e \"set AppleScript's text item delimiters to {\\\",\\\"}\"",
\ '-e "set theColor to (choose color default color {' . default_color[0] . ", " . default_color[1] . ", " . default_color[2] . '}) as text"',
\ '-e "' . s:quit . '"',
\ '-e "end tell"',
\ '-e "return theColor"']
let res = trim(system("osascript " . join(ascrpt, ' ') . " 2>/dev/null"))
if empty(res)
return v:false
else
return split(trim(res), ',')
endif
endif
let hex_color = printf('#%02x%02x%02x', a:default_color[0], a:default_color[1], a:default_color[2])
if has('unix')
if executable('zenity')
let res = trim(system('zenity --title="Select a color" --color-selection --color="' . hex_color . '" 2> /dev/null'))
if empty(res)
return v:false
else
" res format is rgb(255,255,255)
return map(split(res[4:-2], ','), {idx, val -> string(str2nr(trim(val)) * 65535 / 255)})
endif
endif
endif
let rgb = v:false
if !has('python')
echohl Error | echom 'python support required, checkout :echo has(''python'')' | echohl None
return
endif
try
execute 'py import gtk'
catch /.*/
echohl Error | echom 'python gtk module not found' | echohl None
return
endtry
python << endpython
import vim
import gtk, sys
# message strings
wnd_title_insert = "Insert a color"
csd = gtk.ColorSelectionDialog(wnd_title_insert)
cs = csd.colorsel
cs.set_current_color(gtk.gdk.color_parse(vim.eval("hex_color")))
cs.set_current_alpha(65535)
cs.set_has_opacity_control(False)
# cs.set_has_palette(int(vim.eval("s:display_palette")))
if csd.run()==gtk.RESPONSE_OK:
c = cs.get_current_color()
s = [str(int(c.red)),',',str(int(c.green)),',',str(int(c.blue))]
thecolor = ''.join(s)
vim.command(":let rgb = split('%s',',')" % thecolor)
csd.destroy()
endpython
return rgb
endfunction

View file

@ -0,0 +1,244 @@
scriptencoding utf-8
let s:is_vim = !has('nvim')
" first window id for bufnr
" builtin bufwinid returns window of current tab only
function! coc#compat#buf_win_id(bufnr) abort
let info = filter(getwininfo(), 'v:val["bufnr"] =='.a:bufnr)
if empty(info)
return -1
endif
return info[0]['winid']
endfunction
function! coc#compat#buf_set_lines(bufnr, start, end, replacement) abort
if s:is_vim
call coc#api#exec('buf_set_lines', [a:bufnr, a:start, a:end, 0, a:replacement])
else
call nvim_buf_set_lines(a:bufnr, a:start, a:end, 0, a:replacement)
endif
endfunction
function! coc#compat#buf_line_count(bufnr) abort
if exists('*nvim_buf_line_count')
return nvim_buf_line_count(a:bufnr)
endif
if bufnr('%') == a:bufnr
return line('$')
endif
if exists('*getbufinfo')
let info = getbufinfo(a:bufnr)
if empty(info)
return 0
endif
" vim 8.1 has getbufinfo but no linecount
if has_key(info[0], 'linecount')
return info[0]['linecount']
endif
endif
if exists('*getbufline')
let lines = getbufline(a:bufnr, 1, '$')
return len(lines)
endif
let curr = bufnr('%')
execute 'noa buffer '.a:bufnr
let n = line('$')
execute 'noa buffer '.curr
return n
endfunction
function! coc#compat#prepend_lines(bufnr, replacement) abort
if exists('*appendbufline')
call appendbufline(a:bufnr, 0, a:replacement)
elseif !s:is_vim
call nvim_buf_set_lines(a:bufnr, 0, 0, 0, a:replacement)
else
throw 'appendbufline() required for prepend lines.'
endif
endfunction
function! coc#compat#win_is_valid(winid) abort
if exists('*nvim_win_is_valid')
return nvim_win_is_valid(a:winid)
endif
return !empty(getwininfo(a:winid))
endfunction
" clear matches by window id, not throw on none exists window.
" may not work on vim < 8.1.1084 & neovim < 0.4.0
function! coc#compat#clear_matches(winid) abort
if !coc#compat#win_is_valid(a:winid)
return
endif
let curr = win_getid()
if curr == a:winid
call clearmatches()
return
endif
if s:is_vim
if has('patch-8.1.1084')
call clearmatches(a:winid)
endif
else
if exists('*nvim_set_current_win')
noa call nvim_set_current_win(a:winid)
call clearmatches()
noa call nvim_set_current_win(curr)
endif
endif
endfunction
function! coc#compat#matchaddpos(group, pos, priority, winid) abort
let curr = win_getid()
if curr == a:winid
call matchaddpos(a:group, a:pos, a:priority, -1)
else
if s:is_vim
if has('patch-8.1.0218')
call matchaddpos(a:group, a:pos, a:priority, -1, {'window': a:winid})
endif
else
if has('nvim-0.4.0')
call matchaddpos(a:group, a:pos, a:priority, -1, {'window': a:winid})
elseif exists('*nvim_set_current_win')
noa call nvim_set_current_win(a:winid)
call matchaddpos(a:group, a:pos, a:priority, -1)
noa call nvim_set_current_win(curr)
endif
endif
endif
endfunction
function! coc#compat#buf_del_var(bufnr, name) abort
if !bufloaded(a:bufnr)
return
endif
if exists('*nvim_buf_del_var')
silent! call nvim_buf_del_var(a:bufnr, a:name)
else
if a:bufnr == bufnr('%')
execute 'unlet! b:'.a:name
elseif exists('*win_execute')
let winid = coc#compat#buf_win_id(a:bufnr)
if winid != -1
call win_execute(winid, 'unlet! b:'.a:name)
endif
endif
endif
endfunction
" hlGroup, pos, priority
function! coc#compat#matchaddgroups(winid, groups) abort
" add by winid
if has('patch-8.1.0218') || has('nvim-0.4.0')
for group in a:groups
call matchaddpos(group['hlGroup'], [group['pos']], group['priority'], -1, {'window': a:winid})
endfor
return
endif
let curr = win_getid()
if curr == a:winid
for group in a:groups
call matchaddpos(group['hlGroup'], [group['pos']], group['priority'], -1)
endfor
elseif exists('*nvim_set_current_win')
noa call nvim_set_current_win(a:winid)
for group in a:groups
call matchaddpos(group['hlGroup'], [group['pos']], group['priority'], -1)
endfor
noa call nvim_set_current_win(curr)
endif
endfunction
function! coc#compat#del_var(name) abort
if exists('*nvim_del_var')
silent! call nvim_del_var(a:name)
else
execute 'unlet! '.a:name
endif
endfunction
" remove keymap for specific buffer
function! coc#compat#buf_del_keymap(bufnr, mode, lhs) abort
if !bufloaded(a:bufnr)
return
endif
if exists('*nvim_buf_del_keymap')
try
call nvim_buf_del_keymap(a:bufnr, a:mode, a:lhs)
catch /^Vim\%((\a\+)\)\=:E5555/
" ignore keymap doesn't exist
endtry
return
endif
if bufnr == a:bufnr
execute 'silent! '.a:mode.'unmap <buffer> '.a:lhs
return
endif
if exists('*win_execute')
let winid = coc#compat#buf_win_id(a:bufnr)
if winid != -1
call win_execute(winid, a:mode.'unmap <buffer> '.a:lhs, 'silent!')
endif
endif
endfunction
function! coc#compat#buf_add_keymap(bufnr, mode, lhs, rhs, opts) abort
if !bufloaded(a:bufnr)
return
endif
if exists('*nvim_buf_set_keymap')
call nvim_buf_set_keymap(a:bufnr, a:mode, a:lhs, a:rhs, a:opts)
else
let cmd = a:mode . 'noremap '
for key in keys(a:opts)
if get(a:opts, key, 0)
let cmd .= '<'.key.'>'
endif
endfor
let cmd .= '<buffer> '.a:lhs.' '.a:rhs
if bufnr('%') == a:bufnr
execute cmd
elseif exists('*win_execute')
let winid = coc#compat#buf_win_id(a:bufnr)
if winid != -1
call win_execute(winid, cmd)
endif
endif
endif
endfunction
" execute command or list of commands in window
function! coc#compat#execute(winid, command, ...) abort
if exists('*win_execute')
if type(a:command) == v:t_string
keepalt call win_execute(a:winid, a:command, get(a:, 1, ''))
elseif type(a:command) == v:t_list
keepalt call win_execute(a:winid, join(a:command, "\n"), get(a:, 1, ''))
endif
elseif has('nvim')
if !nvim_win_is_valid(a:winid)
return
endif
let curr = nvim_get_current_win()
noa keepalt call nvim_set_current_win(a:winid)
if type(a:command) == v:t_string
exe get(a:, 1, '').' '.a:command
elseif type(a:command) == v:t_list
for cmd in a:command
exe get(a:, 1, '').' '.cmd
endfor
endif
noa keepalt call nvim_set_current_win(curr)
else
throw 'win_execute does not exist, please upgrade vim.'
endif
endfunc
function! coc#compat#trim(str)
if exists('*trim')
return trim(a:str)
endif
" TODO trim from beginning
return substitute(a:str, '\s\+$', '', '')
endfunction

View file

@ -0,0 +1,60 @@
scriptencoding utf-8
" Position of cursor relative to screen cell
function! coc#cursor#screen_pos() abort
let nr = winnr()
let [row, col] = win_screenpos(nr)
return [row + winline() - 2, col + wincol() - 2]
endfunction
function! coc#cursor#move_by_col(delta)
let pos = getcurpos()
call cursor(pos[1], pos[2] + a:delta)
endfunction
" Get cursor position.
function! coc#cursor#position()
return [line('.') - 1, strchars(strpart(getline('.'), 0, col('.') - 1))]
endfunction
" Move cursor to position.
function! coc#cursor#move_to(line, character) abort
let content = getline(a:line + 1)
let pre = strcharpart(content, 0, a:character)
let col = strlen(pre) + 1
call cursor(a:line + 1, col)
endfunction
" Character offset of current cursor, vim provide bytes offset only.
function! coc#cursor#char_offset() abort
let offset = 0
let lnum = line('.')
for i in range(1, lnum)
if i == lnum
let offset += strchars(strpart(getline('.'), 0, col('.')-1))
else
let offset += strchars(getline(i)) + 1
endif
endfor
return offset
endfunction
" Returns latest selection range
function! coc#cursor#get_selection(char) abort
let m = a:char ? 'char' : visualmode()
if empty(m)
return v:null
endif
let [_, sl, sc, soff] = getpos(m ==# 'char' ? "'[" : "'<")
let [_, el, ec, eoff] = getpos(m ==# 'char' ? "']" : "'>")
let start_idx = coc#string#get_character(getline(sl), sc)
if m ==# 'V'
return [sl - 1, start_idx, el, 0]
endif
let line = getline(el)
let end_idx = coc#string#get_character(line, ec)
if m !=# 'char'
let end_idx = end_idx == strchars(line) ? end_idx : end_idx + 1
endif
return [sl - 1, start_idx, el - 1, end_idx]
endfunction

View file

@ -0,0 +1,684 @@
scriptencoding utf-8
let s:is_vim = !has('nvim')
let s:root = expand('<sfile>:h:h:h')
let s:prompt_win_bufnr = 0
let s:list_win_bufnr = 0
let s:prompt_win_width = get(g:, 'coc_prompt_win_width', 32)
let s:frames = ['· ', '·· ', '···', ' ··', ' ·', ' ']
let s:sign_group = 'PopUpCocDialog'
let s:detail_bufnr = 0
" Float window aside pum
function! coc#dialog#create_pum_float(lines, config) abort
let winid = coc#float#get_float_by_kind('pumdetail')
if empty(a:lines) || !coc#pum#visible()
if winid
call coc#float#close(winid)
endif
return
endif
let pumbounding = coc#pum#info()
let border = get(a:config, 'border', [])
let pw = pumbounding['width'] + (empty(border) ? get(pumbounding, 'scrollbar', 0) : 0)
let rp = &columns - pumbounding['col'] - pw
let showRight = pumbounding['col'] > rp ? 0 : 1
let maxWidth = showRight ? coc#math#min(rp - 1, a:config['maxWidth']) : coc#math#min(pumbounding['col'] - 1, a:config['maxWidth'])
let bh = get(border, 0 ,0) + get(border, 2, 0)
let maxHeight = &lines - pumbounding['row'] - &cmdheight - 1 - bh
if maxWidth <= 2 || maxHeight < 1
return v:null
endif
let width = 0
for line in a:lines
let dw = max([1, strdisplaywidth(line)])
let width = max([width, dw + 2])
endfor
let width = float2nr(coc#math#min(maxWidth, width))
let ch = coc#string#content_height(a:lines, width - 2)
let height = float2nr(coc#math#min(maxHeight, ch))
let lines = map(a:lines, {_, s -> s =~# '^─' ? repeat('─', width - 2 + (s:is_vim && ch > height ? -1 : 0)) : s})
let opts = {
\ 'lines': lines,
\ 'highlights': get(a:config, 'highlights', []),
\ 'relative': 'editor',
\ 'col': showRight ? pumbounding['col'] + pw : pumbounding['col'] - width,
\ 'row': pumbounding['row'],
\ 'height': height,
\ 'width': width - 2 + (s:is_vim && ch > height ? -1 : 0),
\ 'scrollinside': showRight ? 0 : 1,
\ 'codes': get(a:config, 'codes', []),
\ }
for key in ['border', 'highlight', 'borderhighlight', 'winblend', 'focusable', 'shadow', 'rounded']
if has_key(a:config, key)
let opts[key] = a:config[key]
endif
endfor
call s:close_auto_hide_wins(winid)
let result = coc#float#create_float_win(winid, s:detail_bufnr, opts)
if empty(result)
return
endif
let s:detail_bufnr = result[1]
call setwinvar(result[0], 'kind', 'pumdetail')
if !s:is_vim
call coc#float#nvim_scrollbar(result[0])
endif
endfunction
" Float window below/above cursor
function! coc#dialog#create_cursor_float(winid, bufnr, lines, config) abort
if coc#prompt#activated()
return v:null
endif
let pumAlignTop = get(a:config, 'pumAlignTop', 0)
let modes = get(a:config, 'modes', ['n', 'i', 'ic', 's'])
let mode = mode()
let currbuf = bufnr('%')
let pos = [line('.'), col('.')]
if index(modes, mode) == -1
return v:null
endif
if !s:is_vim && !has('nvim-0.5.0') && mode ==# 'i'
" helps to fix undo issue, don't know why.
call feedkeys("\<C-g>u", 'n')
endif
if mode ==# 's' && has('patch-8.2.4969') && !has('patch-8.2.4996')
echohl WarningMsg | echon 'Popup not created to avoid issue #10466 on vim >= 8.2.4969' | echohl None
return v:null
endif
let dimension = coc#dialog#get_config_cursor(a:lines, a:config)
if empty(dimension)
return v:null
endif
if coc#pum#visible() && ((pumAlignTop && dimension['row'] <0)|| (!pumAlignTop && dimension['row'] > 0))
return v:null
endif
let width = dimension['width']
let lines = map(a:lines, {_, s -> s =~# '^─' ? repeat('─', width) : s})
let config = extend(extend({'lines': lines, 'relative': 'cursor'}, a:config), dimension)
call s:close_auto_hide_wins(a:winid)
let res = coc#float#create_float_win(a:winid, a:bufnr, config)
if empty(res)
return v:null
endif
let alignTop = dimension['row'] < 0
let winid = res[0]
let bufnr = res[1]
redraw
if has('nvim')
call coc#float#nvim_scrollbar(winid)
endif
return [currbuf, pos, winid, bufnr, alignTop]
endfunction
" Create float window for input
function! coc#dialog#create_prompt_win(title, default, opts) abort
call s:close_auto_hide_wins()
let bufnr = has('nvim') ? s:prompt_win_bufnr : 0
if s:is_vim
execute 'hi link CocPopupTerminal '.get(a:opts, 'highlight', 'CocFloating')
let node = expand(get(g:, 'coc_node_path', 'node'))
let bufnr = term_start([node, s:root . '/bin/prompt.js', a:default], {
\ 'term_rows': 1,
\ 'term_highlight': 'CocPopupTerminal',
\ 'hidden': 1,
\ 'term_finish': 'close'
\ })
call term_setapi(bufnr, 'Coc')
call setbufvar(bufnr, 'current', type(a:default) == v:t_string ? a:default : '')
endif
let config = s:get_prompt_dimension(a:title, a:default, a:opts)
let res = coc#float#create_float_win(0, bufnr, extend(config, {
\ 'style': 'minimal',
\ 'border': get(a:opts, 'border', [1,1,1,1]),
\ 'rounded': get(a:opts, 'rounded', 1),
\ 'prompt': 1,
\ 'title': a:title,
\ 'lines': s:is_vim ? v:null : [a:default],
\ 'highlight': get(a:opts, 'highlight', 'CocFloating'),
\ 'borderhighlight': [get(a:opts, 'borderhighlight', 'CocFloating')],
\ }))
if empty(res)
return
endif
let winid = res[0]
let bufnr = res[1]
if has('nvim')
let s:prompt_win_bufnr = res[1]
execute 'sign unplace 6 buffer='.s:prompt_win_bufnr
call nvim_set_current_win(winid)
inoremap <buffer> <C-a> <Home>
inoremap <buffer><expr><C-e> pumvisible() ? "\<C-e>" : "\<End>"
exe 'imap <silent><nowait><buffer> <esc> <esc><esc>'
exe 'nnoremap <silent><buffer> <esc> :call coc#float#close('.winid.')<CR>'
exe 'inoremap <silent><expr><nowait><buffer> <cr> "\<C-r>=coc#dialog#prompt_insert(getline(''.''))\<cr>\<esc>"'
if get(a:opts, 'list', 0)
for key in ['<C-j>', '<C-k>', '<C-n>', '<C-p>', '<up>', '<down>', '<C-f>', '<C-b>', '<C-space>']
" Can't use < in remap
let escaped = key ==# '<C-space>' ? "C-@" : strcharpart(key, 1, strchars(key) - 2)
exe 'inoremap <nowait><buffer> '.key.' <Cmd>call coc#rpc#notify("PromptKeyPress", ['.bufnr.', "'.escaped.'"])<CR>'
endfor
endif
call feedkeys('A', 'in')
endif
call coc#util#do_autocmd('CocOpenFloatPrompt')
if s:is_vim
let pos = popup_getpos(winid)
" width height row col
let dimension = [pos['width'], pos['height'], pos['line'] - 1, pos['col'] - 1]
else
let id = coc#float#get_related(winid, 'border')
if !has('nvim-0.6.0')
redraw
endif
let pos = nvim_win_get_position(id)
let dimension = [nvim_win_get_width(id), nvim_win_get_height(id), pos[0], pos[1]]
endif
return [bufnr, winid, dimension]
endfunction
" Create list window under target window
function! coc#dialog#create_list(target, dimension, opts) abort
let maxHeight = get(a:opts, 'maxHeight', 10)
let height = max([1, len(get(a:opts, 'lines', []))])
let height = min([maxHeight, height, &lines - &cmdheight - 1 - a:dimension['row'] + a:dimension['height']])
let chars = get(a:opts, 'rounded', 1) ? ['╯', '╰'] : ['┘', '└']
let config = extend(copy(a:opts), {
\ 'relative': 'editor',
\ 'row': a:dimension['row'] + a:dimension['height'],
\ 'col': a:dimension['col'],
\ 'width': a:dimension['width'] - 2,
\ 'height': height,
\ 'border': [1, 1, 1, 1],
\ 'scrollinside': 1,
\ 'borderchars': extend(['─', '│', '─', '│', '├', '┤'], chars)
\ })
let bufnr = 0
let result = coc#float#create_float_win(0, s:list_win_bufnr, config)
if empty(result)
return
endif
let winid = result[0]
call coc#float#add_related(winid, a:target)
call setwinvar(winid, 'auto_height', get(a:opts, 'autoHeight', 1))
call setwinvar(winid, 'max_height', maxHeight)
call setwinvar(winid, 'target_winid', a:target)
call setwinvar(winid, 'kind', 'list')
call coc#dialog#check_scroll_vim(a:target)
return result
endfunction
" Create menu picker for pick single item
function! coc#dialog#create_menu(lines, config) abort
call s:close_auto_hide_wins()
let highlight = get(a:config, 'highlight', 'CocFloating')
let borderhighlight = get(a:config, 'borderhighlight', [highlight])
let relative = get(a:config, 'relative', 'cursor')
let lines = copy(a:lines)
let content = get(a:config, 'content', '')
let maxWidth = get(a:config, 'maxWidth', 80)
let highlights = get(a:config, 'highlights', [])
let contentCount = 0
if !empty(content)
let contentLines = coc#string#reflow(split(content, '\r\?\n'), maxWidth)
let contentCount = len(contentLines)
let lines = extend(contentLines, lines)
if !empty(highlights)
for item in highlights
let item['lnum'] = item['lnum'] + contentCount
endfor
endif
endif
let opts = {
\ 'lines': lines,
\ 'highlight': highlight,
\ 'title': get(a:config, 'title', ''),
\ 'borderhighlight': borderhighlight,
\ 'maxWidth': maxWidth,
\ 'maxHeight': get(a:config, 'maxHeight', 80),
\ 'rounded': get(a:config, 'rounded', 0),
\ 'border': [1, 1, 1, 1],
\ 'highlights': highlights,
\ 'relative': relative,
\ }
if relative ==# 'editor'
let dimension = coc#dialog#get_config_editor(lines, opts)
else
let dimension = coc#dialog#get_config_cursor(lines, opts)
endif
call extend(opts, dimension)
let ids = coc#float#create_float_win(0, s:prompt_win_bufnr, opts)
if empty(ids)
return
endif
let s:prompt_win_bufnr = ids[1]
call coc#dialog#set_cursor(ids[0], ids[1], contentCount + 1)
redraw
if has('nvim')
call coc#float#nvim_scrollbar(ids[0])
endif
return [ids[0], ids[1], contentCount]
endfunction
" Create dialog at center of screen
function! coc#dialog#create_dialog(lines, config) abort
call s:close_auto_hide_wins()
" dialog always have borders
let title = get(a:config, 'title', '')
let buttons = get(a:config, 'buttons', [])
let highlight = get(a:config, 'highlight', 'CocFloating')
let borderhighlight = get(a:config, 'borderhighlight', [highlight])
let opts = {
\ 'title': title,
\ 'rounded': get(a:config, 'rounded', 0),
\ 'relative': 'editor',
\ 'border': [1,1,1,1],
\ 'close': get(a:config, 'close', 1),
\ 'highlight': highlight,
\ 'highlights': get(a:config, 'highlights', []),
\ 'buttons': buttons,
\ 'borderhighlight': borderhighlight,
\ 'getchar': get(a:config, 'getchar', 0)
\ }
call extend(opts, coc#dialog#get_config_editor(a:lines, a:config))
let bufnr = coc#float#create_buf(0, a:lines)
let res = coc#float#create_float_win(0, bufnr, opts)
if empty(res)
return
endif
if get(a:config, 'cursorline', 0)
call coc#dialog#place_sign(bufnr, 1)
endif
if has('nvim')
redraw
call coc#float#nvim_scrollbar(res[0])
endif
return res
endfunction
function! coc#dialog#prompt_confirm(title, cb) abort
call s:close_auto_hide_wins()
if s:is_vim && exists('*popup_dialog')
try
call popup_dialog(a:title. ' (y/n)?', {
\ 'highlight': 'Normal',
\ 'filter': 'popup_filter_yesno',
\ 'callback': {id, res -> a:cb(v:null, res)},
\ 'borderchars': get(g:, 'coc_borderchars', ['─', '│', '─', '│', '╭', '╮', '╯', '╰']),
\ 'borderhighlight': ['MoreMsg']
\ })
catch /.*/
call a:cb(v:exception)
endtry
return
endif
if has('nvim-0.4.0')
let text = ' '. a:title . ' (y/n)? '
let maxWidth = coc#math#min(78, &columns - 2)
let width = coc#math#min(maxWidth, strdisplaywidth(text))
let maxHeight = &lines - &cmdheight - 1
let height = coc#math#min(maxHeight, float2nr(ceil(str2float(string(strdisplaywidth(text)))/width)))
let arr = coc#float#create_float_win(0, s:prompt_win_bufnr, {
\ 'col': &columns/2 - width/2 - 1,
\ 'row': maxHeight/2 - height/2 - 1,
\ 'width': width,
\ 'height': height,
\ 'border': [1,1,1,1],
\ 'focusable': v:false,
\ 'relative': 'editor',
\ 'highlight': 'Normal',
\ 'borderhighlight': 'MoreMsg',
\ 'style': 'minimal',
\ 'lines': [text],
\ })
if empty(arr)
call a:cb('Window create failed!')
return
endif
let winid = arr[0]
let s:prompt_win_bufnr = arr[1]
let res = 0
redraw
" same result as vim
while 1
let key = nr2char(getchar())
if key == "\<C-c>"
let res = -1
break
elseif key == "\<esc>" || key == 'n' || key == 'N'
let res = 0
break
elseif key == 'y' || key == 'Y'
let res = 1
break
endif
endw
call coc#float#close(winid)
call a:cb(v:null, res)
" use relative editor since neovim doesn't support center position
elseif exists('*confirm')
let choice = confirm(a:title, "&Yes\n&No")
call a:cb(v:null, choice == 1)
else
echohl MoreMsg
echom a:title.' (y/n)'
echohl None
let confirm = nr2char(getchar())
redraw!
if !(confirm ==? "y" || confirm ==? "\r")
echohl Moremsg | echo 'Cancelled.' | echohl None
return 0
call a:cb(v:null, 0)
end
call a:cb(v:null, 1)
endif
endfunction
function! coc#dialog#get_config_editor(lines, config) abort
let title = get(a:config, 'title', '')
let maxheight = min([get(a:config, 'maxHeight', 78), &lines - &cmdheight - 6])
let maxwidth = min([get(a:config, 'maxWidth', 78), &columns - 2])
let buttons = get(a:config, 'buttons', [])
let minwidth = s:min_btns_width(buttons)
if maxheight <= 0 || maxwidth <= 0 || minwidth > maxwidth
throw 'Not enough spaces for float window'
endif
let ch = 0
let width = min([strdisplaywidth(title) + 1, maxwidth])
for line in a:lines
let dw = max([1, strdisplaywidth(line)])
if dw < maxwidth && dw > width
let width = dw
elseif dw >= maxwidth
let width = maxwidth
endif
let ch += float2nr(ceil(str2float(string(dw))/maxwidth))
endfor
let width = max([minwidth, width])
let height = coc#math#min(ch ,maxheight)
return {
\ 'row': &lines/2 - (height + 4)/2,
\ 'col': &columns/2 - (width + 2)/2,
\ 'width': width,
\ 'height': height,
\ }
endfunction
function! coc#dialog#prompt_insert(text) abort
call coc#rpc#notify('PromptInsert', [a:text, bufnr('%')])
return ''
endfunction
" Dimension of window with lines relative to cursor
" Width & height excludes border & padding
function! coc#dialog#get_config_cursor(lines, config) abort
let preferTop = get(a:config, 'preferTop', 0)
let title = get(a:config, 'title', '')
let border = get(a:config, 'border', [])
if empty(border) && len(title)
let border = [1, 1, 1, 1]
endif
let bh = get(border, 0, 0) + get(border, 2, 0)
let vh = &lines - &cmdheight - 1
if vh <= 0
return v:null
endif
let maxWidth = coc#math#min(get(a:config, 'maxWidth', &columns - 1), &columns - 1)
if maxWidth < 3
return v:null
endif
let maxHeight = coc#math#min(get(a:config, 'maxHeight', vh), vh)
let width = coc#math#min(40, strdisplaywidth(title)) + 3
for line in a:lines
let dw = max([1, strdisplaywidth(line)])
let width = max([width, dw + 2])
endfor
let width = coc#math#min(maxWidth, width)
let ch = coc#string#content_height(a:lines, width - 2)
let [lineIdx, colIdx] = coc#cursor#screen_pos()
" How much we should move left
let offsetX = coc#math#min(get(a:config, 'offsetX', 0), colIdx)
let showTop = 0
let hb = vh - lineIdx -1
if lineIdx > bh + 2 && (preferTop || (lineIdx > hb && hb < ch + bh))
let showTop = 1
endif
let height = coc#math#min(maxHeight, ch + bh, showTop ? lineIdx - 1 : hb)
if height <= bh
return v:null
endif
let col = - max([offsetX, colIdx - (&columns - 1 - width)])
let row = showTop ? - height + bh : 1
return {
\ 'row': row,
\ 'col': col,
\ 'width': width - 2,
\ 'height': height - bh
\ }
endfunction
function! coc#dialog#change_border_hl(winid, hlgroup) abort
if !hlexists(a:hlgroup)
return
endif
if s:is_vim
if coc#float#valid(a:winid)
call popup_setoptions(a:winid, {'borderhighlight': repeat([a:hlgroup], 4)})
redraw
endif
else
let winid = coc#float#get_related(a:winid, 'border')
if winid > 0
call setwinvar(winid, '&winhl', 'Normal:'.a:hlgroup.',NormalNC:'.a:hlgroup)
endif
endif
endfunction
function! coc#dialog#change_title(winid, title) abort
if s:is_vim
if coc#float#valid(a:winid)
call popup_setoptions(a:winid, {'title': a:title})
redraw
endif
else
let winid = coc#float#get_related(a:winid, 'border')
if winid > 0
let bufnr = winbufnr(winid)
let line = getbufline(bufnr, 1)[0]
let top = strcharpart(line, 0, 1)
\.repeat('─', strchars(line) - 2)
\.strcharpart(line, strchars(line) - 1, 1)
if !empty(a:title)
let top = coc#string#compose(top, 1, a:title.' ')
endif
call nvim_buf_set_lines(bufnr, 0, 1, v:false, [top])
endif
endif
endfunction
function! coc#dialog#change_loading(winid, loading) abort
if coc#float#valid(a:winid)
let winid = coc#float#get_related(a:winid, 'loading')
if !a:loading && winid > 0
call coc#float#close(winid)
endif
if a:loading && winid == 0
let bufnr = s:create_loading_buf()
if s:is_vim
let pos = popup_getpos(a:winid)
let winid = popup_create(bufnr, {
\ 'line': pos['line'] + 1,
\ 'col': pos['col'] + pos['width'] - 4,
\ 'maxheight': 1,
\ 'maxwidth': 3,
\ 'zindex': 999,
\ 'highlight': get(popup_getoptions(a:winid), 'highlight', 'CocFloating')
\ })
else
let pos = nvim_win_get_position(a:winid)
let width = nvim_win_get_width(a:winid)
let opts = {
\ 'relative': 'editor',
\ 'row': pos[0],
\ 'col': pos[1] + width - 3,
\ 'focusable': v:false,
\ 'width': 3,
\ 'height': 1,
\ 'style': 'minimal',
\ }
if has('nvim-0.5.1')
let opts['zindex'] = 900
endif
let winid = nvim_open_win(bufnr, v:false, opts)
call setwinvar(winid, '&winhl', getwinvar(a:winid, '&winhl'))
endif
call setwinvar(winid, 'kind', 'loading')
call setbufvar(bufnr, 'target_winid', a:winid)
call setbufvar(bufnr, 'popup', winid)
call coc#float#add_related(winid, a:winid)
endif
endif
endfunction
" Update list with new lines and highlights
function! coc#dialog#update_list(winid, bufnr, lines, highlights) abort
if coc#window#tabnr(a:winid) == tabpagenr()
if getwinvar(a:winid, 'auto_height', 0)
let row = coc#float#get_row(a:winid)
" core height
let height = max([1, len(copy(a:lines))])
let height = min([getwinvar(a:winid, 'max_height', 10), height, &lines - &cmdheight - 1 - row])
let curr = s:is_vim ? popup_getpos(a:winid)['core_height'] : nvim_win_get_height(a:winid)
let delta = height - curr
if delta != 0
call coc#float#change_height(a:winid, delta)
endif
endif
call coc#compat#buf_set_lines(a:bufnr, 0, -1, a:lines)
call coc#highlight#add_highlights(a:winid, [], a:highlights)
if s:is_vim
let target = getwinvar(a:winid, 'target_winid', -1)
if target != -1
call coc#dialog#check_scroll_vim(target)
endif
call win_execute(a:winid, 'exe 1')
endif
endif
endfunction
" Fix width of prompt window same as list window on scrollbar change
function! coc#dialog#check_scroll_vim(winid) abort
if s:is_vim && coc#float#valid(a:winid)
let winid = coc#float#get_related(a:winid, 'list')
if winid
redraw
let pos = popup_getpos(winid)
let width = pos['width'] + (pos['scrollbar'] ? 1 : 0)
if width != popup_getpos(a:winid)['width']
call popup_move(a:winid, {
\ 'minwidth': width - 2,
\ 'maxwidth': width - 2,
\ })
endif
endif
endif
endfunction
function! coc#dialog#set_cursor(winid, bufnr, line) abort
if s:is_vim
call coc#compat#execute(a:winid, 'exe '.a:line, 'silent!')
call popup_setoptions(a:winid, {'cursorline' : 1})
call popup_setoptions(a:winid, {'cursorline' : 0})
else
call nvim_win_set_cursor(a:winid, [a:line, 0])
endif
call coc#dialog#place_sign(a:bufnr, a:line)
endfunction
function! coc#dialog#place_sign(bufnr, line) abort
call sign_unplace(s:sign_group, { 'buffer': a:bufnr })
if a:line > 0
call sign_place(6, s:sign_group, 'CocCurrentLine', a:bufnr, {'lnum': a:line})
endif
endfunction
" Could be center(with optional marginTop) or cursor
function! s:get_prompt_dimension(title, default, opts) abort
let relative = get(a:opts, 'position', 'cursor') ==# 'cursor' ? 'cursor' : 'editor'
let curr = win_screenpos(winnr())[1] + wincol() - 2
let minWidth = get(a:opts, 'minWidth', s:prompt_win_width)
let width = min([max([strwidth(a:default) + 2, strwidth(a:title) + 2, minWidth]), &columns - 2])
if get(a:opts, 'maxWidth', 0)
let width = min([width, a:opts['maxWidth']])
endif
if relative ==# 'cursor'
let [lineIdx, colIdx] = coc#cursor#screen_pos()
if width == &columns - 2
let col = 0 - curr
else
let col = curr + width <= &columns - 2 ? 0 : curr + width - &columns + 2
endif
let config = {
\ 'row': lineIdx == 0 ? 1 : 0,
\ 'col': colIdx == 0 ? 0 : col - 1,
\ }
else
let marginTop = get(a:opts, 'marginTop', v:null)
if marginTop is v:null
let row = (&lines - &cmdheight - 2) / 2
else
let row = marginTop < 2 ? 1 : min([marginTop, &columns - &cmdheight])
endif
let config = {
\ 'col': float2nr((&columns - width) / 2),
\ 'row': row - s:is_vim,
\ }
endif
return extend(config, {'relative': relative, 'width': width, 'height': 1})
endfunction
function! s:min_btns_width(buttons) abort
if empty(a:buttons)
return 0
endif
let minwidth = len(a:buttons)*3 - 1
for txt in a:buttons
let minwidth = minwidth + strdisplaywidth(txt)
endfor
return minwidth
endfunction
" Close windows that should auto hide
function! s:close_auto_hide_wins(...) abort
let winids = coc#float#get_float_win_list()
let except = get(a:, 1, 0)
for id in winids
if except && id == except
continue
endif
if coc#window#get_var(id, 'autohide', 0)
call coc#float#close(id)
endif
endfor
endfunction
function! s:create_loading_buf() abort
let bufnr = coc#float#create_buf(0)
call s:change_loading_buf(bufnr, 0)
return bufnr
endfunction
function! s:change_loading_buf(bufnr, idx) abort
if bufloaded(a:bufnr)
let target = getbufvar(a:bufnr, 'target_winid', v:null)
if !empty(target) && !coc#float#valid(target)
call coc#float#close(getbufvar(a:bufnr, 'popup'))
return
endif
let line = get(s:frames, a:idx, ' ')
call setbufline(a:bufnr, 1, line)
call coc#highlight#add_highlight(a:bufnr, -1, 'CocNotificationProgress', 0, 0, -1)
let idx = a:idx == len(s:frames) - 1 ? 0 : a:idx + 1
call timer_start(100, { -> s:change_loading_buf(a:bufnr, idx)})
endif
endfunction

View file

@ -0,0 +1,32 @@
scriptencoding utf-8
function! coc#dict#equal(one, two) abort
for key in keys(a:one)
if a:one[key] != a:two[key]
return 0
endif
endfor
return 1
endfunction
" Return new dict with keys removed
function! coc#dict#omit(dict, keys) abort
let res = {}
for key in keys(a:dict)
if index(a:keys, key) == -1
let res[key] = a:dict[key]
endif
endfor
return res
endfunction
" Return new dict with keys only
function! coc#dict#pick(dict, keys) abort
let res = {}
for key in keys(a:dict)
if index(a:keys, key) != -1
let res[key] = a:dict[key]
endif
endfor
return res
endfunction

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,148 @@
scriptencoding utf-8
" Helper methods for viml
function! coc#helper#get_charactor(line, col) abort
return strchars(strpart(a:line, 0, a:col - 1))
endfunction
function! coc#helper#last_character(line) abort
return strcharpart(a:line, strchars(a:line) - 1, 1)
endfunction
function! coc#helper#obj_equal(one, two) abort
for key in keys(a:one)
if a:one[key] != a:two[key]
return 0
endif
endfor
return 1
endfunction
" get change between two lines
function! coc#helper#str_diff(curr, previous, col) abort
let end = strpart(a:curr, a:col - 1)
let start = strpart(a:curr, 0, a:col -1)
let endOffset = 0
let startOffset = 0
let currLen = strchars(a:curr)
let prevLen = strchars(a:previous)
if len(end)
let endLen = strchars(end)
for i in range(min([prevLen, endLen]))
if strcharpart(end, endLen - 1 - i, 1) ==# strcharpart(a:previous, prevLen -1 -i, 1)
let endOffset = endOffset + 1
else
break
endif
endfor
endif
let remain = endOffset == 0 ? a:previous : strcharpart(a:previous, 0, prevLen - endOffset)
if len(remain)
for i in range(min([strchars(remain), strchars(start)]))
if strcharpart(remain, i, 1) ==# strcharpart(start, i ,1)
let startOffset = startOffset + 1
else
break
endif
endfor
endif
return {
\ 'start': startOffset,
\ 'end': prevLen - endOffset,
\ 'text': strcharpart(a:curr, startOffset, currLen - startOffset - endOffset)
\ }
endfunction
function! coc#helper#str_apply(content, diff) abort
let totalLen = strchars(a:content)
let endLen = totalLen - a:diff['end']
return strcharpart(a:content, 0, a:diff['start']).a:diff['text'].strcharpart(a:content, a:diff['end'], endLen)
endfunction
" insert inserted to line at position, use ... when result is too long
" line should only contains character has strwidth equals 1
function! coc#helper#str_compose(line, position, inserted) abort
let width = strwidth(a:line)
let text = a:inserted
let res = a:line
let need_truncate = a:position + strwidth(text) + 1 > width
if need_truncate
let remain = width - a:position - 3
if remain < 2
" use text for full line, use first & end of a:line, ignore position
let res = strcharpart(a:line, 0, 1)
let w = strwidth(res)
for i in range(strchars(text))
let c = strcharpart(text, i, 1)
let a = strwidth(c)
if w + a <= width - 1
let w = w + a
let res = res.c
endif
endfor
let res = res.strcharpart(a:line, w)
else
let res = strcharpart(a:line, 0, a:position)
let w = strwidth(res)
for i in range(strchars(text))
let c = strcharpart(text, i, 1)
let a = strwidth(c)
if w + a <= width - 3
let w = w + a
let res = res.c
endif
endfor
let res = res.'..'
let w = w + 2
let res = res.strcharpart(a:line, w)
endif
else
let first = strcharpart(a:line, 0, a:position)
let res = first.text.strcharpart(a:line, a:position + strwidth(text))
endif
return res
endfunction
" Return new dict with keys removed
function! coc#helper#dict_omit(dict, keys) abort
let res = {}
for key in keys(a:dict)
if index(a:keys, key) == -1
let res[key] = a:dict[key]
endif
endfor
return res
endfunction
" Return new dict with keys only
function! coc#helper#dict_pick(dict, keys) abort
let res = {}
for key in keys(a:dict)
if index(a:keys, key) != -1
let res[key] = a:dict[key]
endif
endfor
return res
endfunction
" support for float values
function! coc#helper#min(first, ...) abort
let val = a:first
for i in range(0, len(a:000) - 1)
if a:000[i] < val
let val = a:000[i]
endif
endfor
return val
endfunction
" support for float values
function! coc#helper#max(first, ...) abort
let val = a:first
for i in range(0, len(a:000) - 1)
if a:000[i] > val
let val = a:000[i]
endif
endfor
return val
endfunction

View file

@ -0,0 +1,734 @@
scriptencoding utf-8
let s:is_vim = !has('nvim')
let s:clear_match_by_window = has('nvim-0.6.0') || has('patch-8.1.1084')
let s:set_extmark = has('nvim') && exists('*nvim_buf_set_extmark')
let s:prop_offset = get(g:, 'coc_text_prop_offset', 1000)
let s:namespace_map = {}
let s:ns_id = 1
let s:diagnostic_hlgroups = ['CocErrorHighlight', 'CocWarningHighlight', 'CocInfoHighlight', 'CocHintHighlight', 'CocDeprecatedHighlight', 'CocUnusedHighlight']
" Maximum count to highlight each time.
let g:coc_highlight_maximum_count = get(g:, 'coc_highlight_maximum_count', 100)
if has('nvim-0.5.0') && s:clear_match_by_window == 0
try
call getmatches(0)
let s:clear_match_by_window = 1
catch /^Vim\%((\a\+)\)\=:E118/
" ignored
endtry
endif
" Update buffer region by region.
function! coc#highlight#buffer_update(bufnr, key, highlights, ...) abort
if !bufloaded(a:bufnr)
return
endif
if empty(a:highlights)
call coc#highlight#clear_highlight(a:bufnr, a:key, 0, -1)
return
endif
let priority = get(a:, 1, v:null)
let changedtick = getbufvar(a:bufnr, 'changedtick', 0)
if type(get(a:, 2, v:null)) == 0 && changedtick > a:2
return
endif
let hls = map(copy(a:highlights), "{'hlGroup':v:val[0],'lnum':v:val[1],'colStart':v:val[2],'colEnd':v:val[3],'combine':get(v:val,4,1),'start_incl':get(v:val,5,0),'end_incl':get(v:val,6,0)}")
if len(hls) <= g:coc_highlight_maximum_count || get(g:, 'coc_node_env', '') ==# 'test'
call coc#highlight#update_highlights(a:bufnr, a:key, hls, 0, -1, priority)
return
endif
let linecount = coc#compat#buf_line_count(a:bufnr)
let groups = s:group_hls(hls, linecount)
call s:update_highlights_timer(a:bufnr, changedtick, a:key, priority, groups, 0)
endfunction
" Update highlights by check exists highlights.
" 0 based, end exclusive start and end
function! coc#highlight#update_highlights(bufnr, key, highlights, ...) abort
let bufnr = a:bufnr == 0 ? bufnr('%') : a:bufnr
if !bufloaded(bufnr)
return
endif
let start = get(a:, 1, 0)
let end = get(a:, 2, -1)
if end == 0
return
endif
let linecount = coc#compat#buf_line_count(a:bufnr)
if end >= linecount
let end = -1
endif
if empty(a:highlights)
call coc#highlight#clear_highlight(bufnr, a:key, start, end)
return
endif
let priority = get(a:, 3, v:null)
let total = len(a:highlights)
" index list that exists with current highlights
let exists = []
let ns = coc#highlight#create_namespace(a:key)
if has('nvim-0.5.0') || exists('*prop_list')
let endLnum = end < 0 ? linecount - 1 : end - 1
let firstLnum = a:highlights[0]['lnum']
if firstLnum > start
call coc#highlight#clear_highlight(bufnr, a:key, start, firstLnum)
let start = firstLnum
endif
let lastLnum = a:highlights[total - 1]['lnum']
if lastLnum < endLnum
call coc#highlight#clear_highlight(bufnr, a:key, lastLnum + 1, endLnum + 1)
let endLnum = lastLnum
endif
let current = coc#highlight#get_highlights(bufnr, a:key, start, endLnum)
let currIndex = 0
if !empty(current)
for [lnum, items] in s:to_group(current)
let indexes = []
let currIndexes = range(0, len(items) - 1)
let removeIndexes = []
while currIndex != total
let hi = a:highlights[currIndex]
if hi['lnum'] == lnum
let findIndex = -1
for idx in currIndexes
let item = items[idx]
if hi['hlGroup'] ==# item[0] && hi['colStart'] == item[2] && hi['colEnd'] == item[3]
call add(indexes, currIndex)
let findIndex = idx
break
elseif item[2] > hi['colStart']
break
endif
endfor
if findIndex != -1
call filter(currIndexes, 'v:val != '.findIndex)
endif
elseif hi['lnum'] > lnum
break
endif
let currIndex = currIndex + 1
endwhile
for idx in currIndexes
if s:is_vim
call prop_remove({'bufnr': bufnr, 'id': items[idx][4]})
else
call nvim_buf_del_extmark(bufnr, ns, items[idx][4])
endif
endfor
call extend(exists, indexes)
endfor
endif
else
call coc#highlight#clear_highlight(bufnr, a:key, start, end)
endif
let indexes = range(0, total - 1)
if !empty(exists)
let indexes = filter(indexes, 'index(exists, v:val) == -1')
endif
for idx in indexes
let hi = a:highlights[idx]
let opts = {
\ 'combine': get(hi, 'combine', 0),
\ 'start_incl': get(hi, 'start_incl', 0),
\ 'end_incl': get(hi, 'end_incl', 0),
\ }
if type(priority) == 0
let opts['priority'] = s:get_priority(a:key, hi['hlGroup'], priority)
endif
call coc#highlight#add_highlight(bufnr, ns, hi['hlGroup'], hi['lnum'], hi['colStart'], hi['colEnd'], opts)
endfor
endfunction
" Get list of highlights by range or all buffer.
" 0 based line, start_col and end_col
" 0 based start & end line, end inclusive.
function! coc#highlight#get_highlights(bufnr, key, ...) abort
if !bufloaded(a:bufnr)
return v:null
endif
if !has_key(s:namespace_map, a:key)
return []
endif
let start = get(a:, 1, 0)
let end = get(a:, 2, -1)
let res = []
let ns = s:namespace_map[a:key]
if exists('*prop_list')
let types = coc#api#get_types(ns)
if empty(types)
return res
endif
" Could filter by end_lnum and types
if has('patch-8.2.3652')
let endLnum = end == -1 ? -1 : end + 1
for prop in prop_list(start + 1, {'bufnr': a:bufnr, 'types': types, 'end_lnum': endLnum})
if prop['start'] == 0 || prop['end'] == 0
" multi line textprop are not supported, simply ignore it
continue
endif
let startCol = prop['col'] - 1
let endCol = startCol + prop['length']
call add(res, [s:prop_type_hlgroup(prop['type']), prop['lnum'] - 1, startCol, endCol, prop['id']])
endfor
else
if end == -1
let end = coc#compat#buf_line_count(a:bufnr)
else
let end = end + 1
endif
for line in range(start + 1, end)
for prop in prop_list(line, {'bufnr': a:bufnr})
if index(types, prop['type']) == -1 || prop['start'] == 0 || prop['end'] == 0
" multi line textprop are not supported, simply ignore it
continue
endif
let startCol = prop['col'] - 1
let endCol = startCol + prop['length']
call add(res, [s:prop_type_hlgroup(prop['type']), line - 1, startCol, endCol, prop['id']])
endfor
endfor
endif
elseif has('nvim-0.5.0')
let start = [start, 0]
let maximum = end == -1 ? nvim_buf_line_count(a:bufnr) : end + 1
let end = end == -1 ? -1 : [end + 1, 0]
let markers = nvim_buf_get_extmarks(a:bufnr, ns, start, -1, {'details': v:true})
for [marker_id, line, start_col, details] in markers
if line >= maximum
" Could be markers exceed end of line
continue
endif
let delta = details['end_row'] - line
if delta > 1 || (delta == 1 && details['end_col'] != 0)
" can't handle, single line only
continue
endif
let endCol = details['end_col']
if endCol == start_col
call nvim_buf_del_extmark(a:bufnr, ns, marker_id)
continue
endif
if delta == 1
let text = get(nvim_buf_get_lines(a:bufnr, line, line + 1, 0), 0, '')
let endCol = strlen(text)
endif
call add(res, [details['hl_group'], line, start_col, endCol, marker_id])
endfor
else
throw 'Get highlights requires neovim 0.5.0 or vim support prop_list'
endif
return res
endfunction
" Add multiple highlights to buffer.
" type HighlightItem = [hlGroup, lnum, colStart, colEnd, combine?, start_incl?, end_incl?]
function! coc#highlight#set(bufnr, key, highlights, priority) abort
if !bufloaded(a:bufnr)
return
endif
let ns = coc#highlight#create_namespace(a:key)
if len(a:highlights) > g:coc_highlight_maximum_count
call s:add_highlights_timer(a:bufnr, ns, a:highlights, a:priority)
else
call s:add_highlights(a:bufnr, ns, a:highlights, a:priority)
endif
endfunction
" Clear highlights by 0 based line numbers.
function! coc#highlight#clear(bufnr, key, lnums) abort
if !bufloaded(a:bufnr) || empty(a:lnums)
return
endif
let ns = coc#highlight#create_namespace(a:key)
for lnum in a:lnums
if has('nvim')
call nvim_buf_clear_namespace(a:bufnr, ns, lnum, lnum + 1)
else
call coc#api#exec('buf_clear_namespace', [a:bufnr, ns, lnum, lnum + 1])
endif
endfor
" clear highlights in invalid line.
if has('nvim')
let linecount = nvim_buf_line_count(a:bufnr)
call nvim_buf_clear_namespace(a:bufnr, ns, linecount, -1)
endif
endfunction
function! coc#highlight#del_markers(bufnr, key, ids) abort
if !bufloaded(a:bufnr)
return
endif
let ns = coc#highlight#create_namespace(a:key)
for id in a:ids
if s:is_vim
call prop_remove({'bufnr': a:bufnr, 'id': id})
else
call nvim_buf_del_extmark(a:bufnr, ns, id)
endif
endfor
endfunction
" highlight LSP range,
function! coc#highlight#ranges(bufnr, key, hlGroup, ranges, ...) abort
let bufnr = a:bufnr == 0 ? bufnr('%') : a:bufnr
if !bufloaded(bufnr) || !exists('*getbufline')
return
endif
let opts = get(a:, 1, {})
let synmaxcol = getbufvar(a:bufnr, '&synmaxcol', 1000)
if synmaxcol == 0
let synmaxcol = 1000
endif
let synmaxcol = min([synmaxcol, 1000])
let srcId = coc#highlight#create_namespace(a:key)
for range in a:ranges
let start = range['start']
let end = range['end']
for lnum in range(start['line'] + 1, end['line'] + 1)
let arr = getbufline(bufnr, lnum)
let line = empty(arr) ? '' : arr[0]
if empty(line)
continue
endif
if start['character'] > synmaxcol || end['character'] > synmaxcol
continue
endif
" TODO don't know how to count UTF16 code point, should work most cases.
let colStart = lnum == start['line'] + 1 ? strlen(strcharpart(line, 0, start['character'])) : 0
let colEnd = lnum == end['line'] + 1 ? strlen(strcharpart(line, 0, end['character'])) : strlen(line)
if colStart == colEnd
continue
endif
call coc#highlight#add_highlight(bufnr, srcId, a:hlGroup, lnum - 1, colStart, colEnd, opts)
endfor
endfor
endfunction
function! coc#highlight#add_highlight(bufnr, src_id, hl_group, line, col_start, col_end, ...) abort
let opts = get(a:, 1, {})
let priority = get(opts, 'priority', v:null)
if !s:is_vim
if s:set_extmark && a:src_id != -1
" get(opts, 'start_incl', 0) ? v:true : v:false,
try
call nvim_buf_set_extmark(a:bufnr, a:src_id, a:line, a:col_start, {
\ 'end_col': a:col_end,
\ 'hl_group': a:hl_group,
\ 'hl_mode': get(opts, 'combine', 1) ? 'combine' : 'replace',
\ 'right_gravity': v:true,
\ 'end_right_gravity': v:false,
\ 'priority': type(priority) == 0 ? min([priority, 4096]) : 4096,
\ })
catch /^Vim\%((\a\+)\)\=:E5555/
" the end_col could be invalid, ignore this error
endtry
else
call nvim_buf_add_highlight(a:bufnr, a:src_id, a:hl_group, a:line, a:col_start, a:col_end)
endif
else
call coc#api#exec('buf_add_highlight', [a:bufnr, a:src_id, a:hl_group, a:line, a:col_start, a:col_end, opts])
endif
endfunction
function! coc#highlight#clear_highlight(bufnr, key, start_line, end_line) abort
let bufnr = a:bufnr == 0 ? bufnr('%') : a:bufnr
if !bufloaded(bufnr)
return
endif
let src_id = coc#highlight#create_namespace(a:key)
if has('nvim')
call nvim_buf_clear_namespace(a:bufnr, src_id, a:start_line, a:end_line)
else
call coc#api#exec('buf_clear_namespace', [a:bufnr, src_id, a:start_line, a:end_line])
endif
endfunction
" highlight buffer in winid with CodeBlock &HighlightItems
" export interface HighlightItem {
" lnum: number // 0 based
" hlGroup: string
" colStart: number // 0 based
" colEnd: number
" }
" export interface CodeBlock {
" filetype?: string
" hlGroup?: string
" startLine: number // 0 based
" endLine: number
" }
function! coc#highlight#add_highlights(winid, codes, highlights) abort
if get(g:, 'coc_node_env', '') ==# 'test'
call setwinvar(a:winid, 'highlights', a:highlights)
endif
" clear highlights
call coc#compat#execute(a:winid, 'syntax clear')
let bufnr = winbufnr(a:winid)
call coc#highlight#clear_highlight(bufnr, -1, 0, -1)
if !empty(a:codes)
call coc#highlight#highlight_lines(a:winid, a:codes)
endif
if !empty(a:highlights)
for item in a:highlights
let hlGroup = item['hlGroup']
let opts = hlGroup =~# 'Search$' ? {'priority': 999, 'combine': 1} : {}
call coc#highlight#add_highlight(bufnr, -1, hlGroup, item['lnum'], item['colStart'], item['colEnd'])
endfor
endif
endfunction
" Add highlights to line groups of winid, support hlGroup and filetype
" config should have startLine, endLine (0 based, end excluded) and filetype or hlGroup
" endLine should > startLine and endLine is excluded
"
" export interface CodeBlock {
" filetype?: string
" hlGroup?: string
" startLine: number // 0 based
" endLine: number
" }
function! coc#highlight#highlight_lines(winid, blocks) abort
let region_id = 1
let defined = []
let cmds = []
for config in a:blocks
let start = config['startLine'] + 1
let end = config['endLine'] == -1 ? len(getbufline(winbufnr(a:winid), 1, '$')) + 1 : config['endLine'] + 1
let filetype = get(config, 'filetype', '')
let hlGroup = get(config, 'hlGroup', '')
if !empty(hlGroup)
call add(cmds, 'syntax region '.hlGroup.' start=/\%'.start.'l/ end=/\%'.end.'l/')
else
let filetype = matchstr(filetype, '\v^\w+')
if empty(filetype) || filetype == 'txt' || index(get(g:, 'coc_markdown_disabled_languages', []), filetype) != -1
continue
endif
if index(defined, filetype) == -1
call add(cmds, 'syntax include @'.toupper(filetype).' syntax/'.filetype.'.vim')
call add(cmds, 'unlet! b:current_syntax')
call add(defined, filetype)
endif
call add(cmds, 'syntax region CodeBlock'.region_id.' start=/\%'.start.'l/ end=/\%'.end.'l/ contains=@'.toupper(filetype).' keepend')
let region_id = region_id + 1
endif
endfor
if !empty(cmds)
call coc#compat#execute(a:winid, cmds, 'silent!')
endif
endfunction
" Compose hlGroups with foreground and background colors.
function! coc#highlight#compose_hlgroup(fgGroup, bgGroup) abort
let hlGroup = 'Fg'.a:fgGroup.'Bg'.a:bgGroup
if a:fgGroup ==# a:bgGroup
return a:fgGroup
endif
if hlexists(hlGroup) && match(execute('hi '.hlGroup, 'silent!'), 'cleared') == -1
return hlGroup
endif
let fgId = synIDtrans(hlID(a:fgGroup))
let bgId = synIDtrans(hlID(a:bgGroup))
let isGuiReversed = synIDattr(fgId, 'reverse', 'gui') !=# '1' || synIDattr(bgId, 'reverse', 'gui') !=# '1'
let guifg = isGuiReversed ? synIDattr(fgId, 'fg', 'gui') : synIDattr(fgId, 'bg', 'gui')
let guibg = isGuiReversed ? synIDattr(bgId, 'bg', 'gui') : synIDattr(bgId, 'fg', 'gui')
let isCtermReversed = synIDattr(fgId, 'reverse', 'cterm') !=# '1' || synIDattr(bgId, 'reverse', 'cterm') !=# '1'
let ctermfg = isCtermReversed ? synIDattr(fgId, 'fg', 'cterm') : synIDattr(fgId, 'bg', 'cterm')
let ctermbg = isCtermReversed ? synIDattr(bgId, 'bg', 'cterm') : synIDattr(bgId, 'fg', 'cterm')
let bold = synIDattr(fgId, 'bold') ==# '1'
let italic = synIDattr(fgId, 'italic') ==# '1'
let underline = synIDattr(fgId, 'underline') ==# '1'
let cmd = 'silent hi ' . hlGroup
if !empty(guifg)
let cmd .= ' guifg=' . guifg
endif
if !empty(ctermfg)
let cmd .= ' ctermfg=' . ctermfg
elseif guifg =~# '^#'
let cmd .= ' ctermfg=' . coc#color#rgb2term(strpart(guifg, 1))
endif
if !empty(guibg)
let cmd .= ' guibg=' . guibg
endif
if !empty(ctermbg)
let cmd .= ' ctermbg=' . ctermbg
elseif guibg =~# '^#'
let cmd .= ' ctermbg=' . coc#color#rgb2term(strpart(guibg, 1))
endif
if bold
let cmd .= ' cterm=bold gui=bold'
elseif italic
let cmd .= ' cterm=italic gui=italic'
elseif underline
let cmd .= ' cterm=underline gui=underline'
endif
if cmd ==# 'silent hi ' . hlGroup
return 'Normal'
endif
execute cmd
return hlGroup
endfunction
" add matches for winid, use 0 for current window.
function! coc#highlight#match_ranges(winid, bufnr, ranges, hlGroup, priority) abort
let winid = a:winid == 0 ? win_getid() : a:winid
let bufnr = a:bufnr == 0 ? winbufnr(winid) : a:bufnr
if empty(getwininfo(winid)) || (a:bufnr != 0 && winbufnr(a:winid) != a:bufnr)
" not valid
return []
endif
if !s:clear_match_by_window
let curr = win_getid()
if has('nvim')
noa call nvim_set_current_win(winid)
else
noa call win_gotoid(winid)
endif
endif
let ids = []
for range in a:ranges
let pos = []
let start = range['start']
let end = range['end']
for lnum in range(start['line'] + 1, end['line'] + 1)
let arr = getbufline(bufnr, lnum)
let line = empty(arr) ? '' : arr[0]
if empty(line)
continue
endif
let colStart = lnum == start['line'] + 1 ? strlen(strcharpart(line, 0, start['character'])) + 1 : 1
let colEnd = lnum == end['line'] + 1 ? strlen(strcharpart(line, 0, end['character'])) + 1 : strlen(line) + 1
if colStart == colEnd
continue
endif
call add(pos, [lnum, colStart, colEnd - colStart])
endfor
if !empty(pos)
let opts = s:clear_match_by_window ? {'window': a:winid} : {}
let i = 1
let l = []
for p in pos
call add(l, p)
if i % 8 == 0
let id = matchaddpos(a:hlGroup, l, a:priority, -1, opts)
call add(ids, id)
let l = []
endif
let i += 1
endfor
if !empty(l)
let id = matchaddpos(a:hlGroup, l, a:priority, -1, opts)
call add(ids, id)
endif
endif
endfor
if !s:clear_match_by_window
if has('nvim')
noa call nvim_set_current_win(curr)
else
noa call win_gotoid(curr)
endif
endif
return ids
endfunction
" Clear matches by hlGroup regexp.
function! coc#highlight#clear_match_group(winid, match) abort
let winid = a:winid == 0 ? win_getid() : a:winid
if empty(getwininfo(winid))
" not valid
return
endif
if s:clear_match_by_window
let arr = filter(getmatches(winid), 'v:val["group"] =~# "'.a:match.'"')
for item in arr
call matchdelete(item['id'], winid)
endfor
else
let curr = win_getid()
let switch = exists('*nvim_set_current_win') && curr != winid
if switch
noa call nvim_set_current_win(a:winid)
endif
if win_getid() == winid
let arr = filter(getmatches(), 'v:val["group"] =~# "'.a:match.'"')
for item in arr
call matchdelete(item['id'])
endfor
endif
if switch
noa call nvim_set_current_win(curr)
endif
endif
endfunction
" Clear matches by match ids, use 0 for current win.
function! coc#highlight#clear_matches(winid, ids)
let winid = a:winid == 0 ? win_getid() : a:winid
if empty(getwininfo(winid))
" not valid
return
endif
if s:clear_match_by_window
for id in a:ids
try
call matchdelete(id, winid)
catch /^Vim\%((\a\+)\)\=:E803/
" ignore
endtry
endfor
else
let curr = win_getid()
let switch = exists('*nvim_set_current_win') && curr != winid
if switch
noa call nvim_set_current_win(a:winid)
endif
if win_getid() == winid
for id in a:ids
try
call matchdelete(id)
catch /^Vim\%((\a\+)\)\=:E803/
" ignore
endtry
endfor
endif
if switch
noa call nvim_set_current_win(curr)
endif
endif
endfunction
function! coc#highlight#clear_all() abort
for src_id in values(s:namespace_map)
for bufnr in map(getbufinfo({'bufloaded': 1}), 'v:val["bufnr"]')
if has('nvim')
call nvim_buf_clear_namespace(bufnr, src_id, 0, -1)
else
call coc#api#exec('buf_clear_namespace', [bufnr, src_id, 0, -1])
endif
endfor
endfor
endfunction
function! coc#highlight#create_namespace(key) abort
if type(a:key) == 0
return a:key
endif
if has_key(s:namespace_map, a:key)
return s:namespace_map[a:key]
endif
if has('nvim')
let s:namespace_map[a:key] = nvim_create_namespace('coc-'.a:key)
else
let s:namespace_map[a:key] = s:ns_id
let s:ns_id = s:ns_id + 1
endif
return s:namespace_map[a:key]
endfunction
function! coc#highlight#get_syntax_name(lnum, col)
return synIDattr(synIDtrans(synID(a:lnum,a:col,1)),"name")
endfunction
function! s:prop_type_hlgroup(type) abort
return substitute(a:type, '_\d\+$', '', '')
endfunction
function! s:update_highlights_timer(bufnr, changedtick, key, priority, groups, idx) abort
if getbufvar(a:bufnr, 'changedtick', 0) != a:changedtick
return
endif
let group = get(a:groups, a:idx, v:null)
if empty(group)
return
endif
if empty(group['highlights'])
call coc#highlight#clear_highlight(a:bufnr, a:key, group['start'], group['end'])
else
call coc#highlight#update_highlights(a:bufnr, a:key, group['highlights'], group['start'], group['end'], a:priority)
endif
if a:idx < len(a:groups) - 1
call timer_start(50, { -> s:update_highlights_timer(a:bufnr, a:changedtick, a:key, a:priority, a:groups, a:idx + 1)})
endif
endfunction
function! s:add_highlights_timer(bufnr, ns, highlights, priority) abort
let hls = []
let next = []
for i in range(0, len(a:highlights) - 1)
if i < g:coc_highlight_maximum_count
call add(hls, a:highlights[i])
else
call add(next, a:highlights[i])
endif
endfor
call s:add_highlights(a:bufnr, a:ns, hls, a:priority)
if len(next)
call timer_start(30, {->s:add_highlights_timer(a:bufnr, a:ns, next, a:priority)})
endif
endfunction
function! s:add_highlights(bufnr, ns, highlights, priority) abort
for item in a:highlights
let opts = {
\ 'priority': a:priority,
\ 'combine': get(item, 4, 1) ? 1 : 0,
\ 'start_incl': get(item, 5, 0) ? 1 : 0,
\ 'end_incl': get(item, 6, 0) ? 1 : 0,
\ }
call coc#highlight#add_highlight(a:bufnr, a:ns, item[0], item[1], item[2], item[3], opts)
endfor
endfunction
function! s:to_group(items) abort
let res = []
let before = v:null
for item in a:items
if empty(before) || before[0] != item[1]
let before = [item[1], [item]]
call add(res, before)
else
call add(before[1], item)
endif
endfor
return res
endfunction
function! s:get_priority(key, hlGroup, priority) abort
if a:hlGroup ==# 'CocSearch'
return 999
endif
if strpart(a:key, 0, 10) !=# 'diagnostic'
return a:priority
endif
return a:priority - index(s:diagnostic_hlgroups, a:hlGroup)
endfunction
function! s:group_hls(hls, linecount) abort
" start, end, highlights
let groups = []
if empty(a:hls)
call add(groups, {'start': 0, 'end': a:linecount, 'highlights': []})
return groups
endif
let start = 0
let highlights = []
let lastLnum = -1
for item in a:hls
let lnum = item['lnum']
if lnum >= a:linecount
break
endif
if len(highlights) < g:coc_highlight_maximum_count || lnum == lastLnum
call add(highlights, item)
let lastLnum = lnum
else
call add(groups, {'start': start, 'end': lastLnum + 1, 'highlights': highlights})
let highlights = []
let start = lastLnum + 1
call add(highlights, item)
let lastLnum = lnum
endif
endfor
call add(groups, {'start': start, 'end': a:linecount, 'highlights': highlights})
return groups
endfunction

View file

@ -0,0 +1,303 @@
scriptencoding utf-8
let s:is_vim = !has('nvim')
let s:prefix = '[List Preview]'
let s:sign_group = 'CocList'
" filetype detect could be slow.
let s:filetype_map = {
\ 'c': 'c',
\ 'py': 'python',
\ 'vim': 'vim',
\ 'ts': 'typescript',
\ 'js': 'javascript',
\ 'html': 'html',
\ 'css': 'css'
\ }
function! coc#list#getchar() abort
return coc#prompt#getchar()
endfunction
function! coc#list#setlines(bufnr, lines, append)
if a:append
silent call appendbufline(a:bufnr, '$', a:lines)
else
if exists('*deletebufline')
silent call deletebufline(a:bufnr, len(a:lines) + 1, '$')
else
let n = len(a:lines) + 1
let saved_reg = @"
silent execute n.',$d'
let @" = saved_reg
endif
silent call setbufline(a:bufnr, 1, a:lines)
endif
endfunction
function! coc#list#options(...)
let list = ['--top', '--tab', '--normal', '--no-sort', '--input', '--strict',
\ '--regex', '--interactive', '--number-select', '--auto-preview',
\ '--ignore-case', '--no-quit', '--first', '--reverse']
if get(g:, 'coc_enabled', 0)
let names = coc#rpc#request('listNames', [])
call extend(list, names)
endif
return join(list, "\n")
endfunction
function! coc#list#names(...) abort
let names = coc#rpc#request('listNames', [])
return join(names, "\n")
endfunction
function! coc#list#status(name)
if !exists('b:list_status') | return '' | endif
return get(b:list_status, a:name, '')
endfunction
function! coc#list#create(position, height, name, numberSelect)
if a:position ==# 'tab'
execute 'silent tabe list:///'.a:name
else
execute 'silent keepalt '.(a:position ==# 'top' ? '' : 'botright').a:height.'sp list:///'.a:name
execute 'resize '.a:height
endif
if a:numberSelect
setl norelativenumber
setl number
else
setl nonumber
setl norelativenumber
endif
return [bufnr('%'), win_getid(), tabpagenr()]
endfunction
" close list windows
function! coc#list#clean_up() abort
for i in range(1, winnr('$'))
let bufname = bufname(winbufnr(i))
if bufname =~# 'list://'
execute i.'close!'
endif
endfor
endfunction
function! coc#list#setup(source)
let b:list_status = {}
setl buftype=nofile nobuflisted nofen nowrap
setl norelativenumber bufhidden=wipe nocursorline winfixheight
setl tabstop=1 nolist nocursorcolumn undolevels=-1
setl signcolumn=auto
if has('nvim-0.5.0') || has('patch-8.1.0864')
setl scrolloff=0
endif
setl filetype=list
syntax case ignore
let source = a:source[8:]
let name = toupper(source[0]).source[1:]
execute 'syntax match Coc'.name.'Line /\v^.*$/'
if !s:is_vim
" Repeat press <C-f> and <C-b> would invoke <esc> on vim
nnoremap <silent><nowait><buffer> <esc> <C-w>c
endif
endfunction
function! coc#list#select(bufnr, line) abort
call sign_unplace(s:sign_group, { 'buffer': a:bufnr })
if a:line > 0
call sign_place(6, s:sign_group, 'CocListCurrent', a:bufnr, {'lnum': a:line})
endif
endfunction
" Check if previewwindow exists on current tab.
function! coc#list#has_preview()
for i in range(1, winnr('$'))
let preview = getwinvar(i, 'previewwindow', getwinvar(i, '&previewwindow', 0))
if preview
return i
endif
endfor
return 0
endfunction
" Get previewwindow from tabnr, use 0 for current tab
function! coc#list#get_preview(...) abort
let tabnr = get(a:, 1, 0) == 0 ? tabpagenr() : a:1
let info = gettabinfo(tabnr)
if !empty(info)
for win in info[0]['windows']
if gettabwinvar(tabnr, win, 'previewwindow', 0)
return win
endif
endfor
endif
return -1
endfunction
function! coc#list#scroll_preview(dir) abort
let winnr = coc#list#has_preview()
if !winnr
return
endif
let winid = win_getid(winnr)
if exists('*win_execute')
call win_execute(winid, "normal! ".(a:dir ==# 'up' ? "\<C-u>" : "\<C-d>"))
else
let id = win_getid()
noa call win_gotoid(winid)
execute "normal! ".(a:dir ==# 'up' ? "\<C-u>" : "\<C-d>")
noa call win_gotoid(id)
endif
endfunction
function! coc#list#close_preview(tabnr) abort
let winid = coc#list#get_preview(a:tabnr)
if winid != -1
call coc#window#close(winid)
endif
endfunction
" Improve preview performance by reused window & buffer.
" lines - list of lines
" config.position - could be 'below' 'top' 'tab'.
" config.winid - id of original window.
" config.name - (optional )name of preview buffer.
" config.splitRight - (optional) split to right when 1.
" config.lnum - (optional) current line number
" config.filetype - (optional) filetype of lines.
" config.hlGroup - (optional) highlight group.
" config.maxHeight - (optional) max height of window, valid for 'below' & 'top' position.
function! coc#list#preview(lines, config) abort
let name = fnamemodify(get(a:config, 'name', ''), ':.')
let lines = a:lines
if empty(lines)
if get(a:config, 'scheme', 'file') != 'file'
let bufnr = s:load_buffer(name)
let lines = bufnr == 0 ? [''] : getbufline(bufnr, 1, '$')
else
" Show empty lines so not close window.
let lines = ['']
endif
endif
let winid = coc#list#get_preview(0)
let bufnr = winid == -1 ? 0 : winbufnr(winid)
" Try reuse buffer & window
let bufnr = coc#float#create_buf(bufnr, lines)
if bufnr == 0
return
endif
call setbufvar(bufnr, '&synmaxcol', 500)
let filetype = get(a:config, 'filetype', '')
let extname = matchstr(name, '\.\zs[^.]\+$')
if empty(filetype) && !empty(extname)
let filetype = get(s:filetype_map, extname, '')
endif
let range = get(a:config, 'range', v:null)
let hlGroup = get(a:config, 'hlGroup', 'Search')
let lnum = get(a:config, 'lnum', 1)
let position = get(a:config, 'position', 'below')
let original = get(a:config, 'winid', -1)
if winid == -1
let change = position != 'tab' && get(a:config, 'splitRight', 0)
let curr = win_getid()
if change
if original && win_id2win(original)
noa call win_gotoid(original)
else
noa wincmd t
endif
execute 'noa belowright vert sb '.bufnr
let winid = win_getid()
elseif position == 'tab' || get(a:config, 'splitRight', 0)
execute 'noa belowright vert sb '.bufnr
let winid = win_getid()
else
let mod = position == 'top' ? 'below' : 'above'
let height = s:get_height(lines, a:config)
execute 'noa '.mod.' sb +resize\ '.height.' '.bufnr
let winid = win_getid()
endif
noa call winrestview({"lnum": lnum ,"topline":s:get_topline(a:config, lnum, winid)})
call s:set_preview_options(winid)
noa call win_gotoid(curr)
else
let height = s:get_height(lines, a:config)
if height > 0
if s:is_vim
let curr = win_getid()
noa call win_gotoid(winid)
execute 'silent! noa resize '.height
noa call win_gotoid(curr)
else
call nvim_win_set_height(winid, height)
endif
endif
call coc#compat#execute(winid, ['syntax clear', 'noa call winrestview({"lnum":'.lnum.',"topline":'.s:get_topline(a:config, lnum, winid).'})'])
endif
call setwinvar(winid, '&foldenable', 0)
if s:prefix.' '.name != bufname(bufnr)
if s:is_vim
call win_execute(winid, 'noa file '.fnameescape(s:prefix.' '.name), 'silent!')
else
silent! noa call nvim_buf_set_name(bufnr, s:prefix.' '.name)
endif
endif
" highlights
if !empty(filetype)
let start = max([0, lnum - 300])
let end = min([len(lines), lnum + 300])
call coc#highlight#highlight_lines(winid, [{'filetype': filetype, 'startLine': start, 'endLine': end}])
call coc#compat#execute(winid, 'syn sync fromstart')
else
call coc#compat#execute(winid, 'filetype detect')
let ft = getbufvar(bufnr, '&filetype', '')
if !empty(extname) && !empty(ft)
let s:filetype_map[extname] = ft
endif
endif
call sign_unplace('CocCursorLine', {'buffer': bufnr})
call coc#compat#execute(winid, 'call clearmatches()')
if !s:is_vim
" vim send <esc> to buffer on FocusLost, <C-w> and other cases
call coc#compat#execute(winid, 'nnoremap <silent><nowait><buffer> <esc> :call CocActionAsync("listCancel")<CR>')
endif
if !empty(range)
call sign_place(1, 'CocCursorLine', 'CocCurrentLine', bufnr, {'lnum': lnum})
call coc#highlight#match_ranges(winid, bufnr, [range], hlGroup, 10)
endif
endfunction
function! s:get_height(lines, config) abort
if get(a:config, 'splitRight', 0) || get(a:config, 'position', 'below') == 'tab'
return 0
endif
let height = min([get(a:config, 'maxHeight', 10), len(a:lines), &lines - &cmdheight - 2])
return height
endfunction
function! s:load_buffer(name) abort
if exists('*bufadd') && exists('*bufload')
let bufnr = bufadd(a:name)
call bufload(bufnr)
return bufnr
endif
return 0
endfunction
function! s:get_topline(config, lnum, winid) abort
let toplineStyle = get(a:config, 'toplineStyle', 'offset')
if toplineStyle == 'middle'
return max([1, a:lnum - winheight(a:winid)/2])
endif
let toplineOffset = get(a:config, 'toplineOffset', 3)
return max([1, a:lnum - toplineOffset])
endfunction
function! s:set_preview_options(winid) abort
call setwinvar(a:winid, '&foldmethod', 'manual')
call setwinvar(a:winid, '&signcolumn', 'no')
call setwinvar(a:winid, '&number', 1)
call setwinvar(a:winid, '&cursorline', 0)
call setwinvar(a:winid, '&relativenumber', 0)
call setwinvar(a:winid, 'previewwindow', 1)
endfunction

View file

@ -0,0 +1,11 @@
" support for float values
function! coc#math#min(first, ...) abort
let val = a:first
for i in range(0, len(a:000) - 1)
if a:000[i] < val
let val = a:000[i]
endif
endfor
return val
endfunction

View file

@ -0,0 +1,532 @@
scriptencoding utf-8
let s:is_vim = !has('nvim')
let s:utf = &encoding =~# '^utf'
let s:error_icon = get(g:, 'coc_notify_error_icon', s:utf ? '' : 'E')
let s:warning_icon = get(g:, 'coc_notify_warning_icon', s:utf ? '⚠' : 'W')
let s:info_icon = get(g:, 'coc_notify_info_icon', s:utf ? '' : 'I')
let s:interval = get(g:, 'coc_notify_interval', s:is_vim ? 50 : 20)
let s:phl = 'CocNotificationProgress'
let s:progress_char = '─'
let s:duration = 300.0
let s:winids = []
" Valid notify winids on current tab
function! coc#notify#win_list() abort
call filter(s:winids, 'coc#float#valid(v:val)')
return filter(copy(s:winids), '!empty(getwinvar(v:val,"float"))')
endfunction
function! coc#notify#close_all() abort
for winid in coc#notify#win_list()
call coc#notify#close(winid)
endfor
endfunction
" Do action for winid or first notify window with actions.
function! coc#notify#do_action(...) abort
let winids = a:0 > 0 ? a:000 : coc#notify#win_list()
for winid in winids
if coc#float#valid(winid) && getwinvar(winid, 'closing', 0) != 1
let actions = getwinvar(winid, 'actions', [])
if !empty(actions)
let items = map(copy(actions), '(v:key + 1).". ".v:val')
let msg = join(getbufline(winbufnr(winid), 1, '$'), ' ')
call coc#ui#quickpick(msg, items, {err, res -> s:on_action(err, res, winid) })
break
endif
endif
endfor
endfunction
" Copy notification contents
function! coc#notify#copy() abort
let lines = []
for winid in coc#notify#win_list()
let key = getwinvar(winid, 'key', v:null)
if type(key) == v:t_string
call extend(lines, json_decode(key)['lines'])
endif
endfor
if empty(lines)
echohl WarningMsg | echon 'No content to copy' | echohl None
return
endif
call setreg('*', join(lines, "\n"))
endfunction
" Show source name in window
function! coc#notify#show_sources() abort
if !exists('*getbufline') || !exists('*appendbufline')
throw "getbufline and appendbufline functions required, please upgrade your vim."
endif
let winids = filter(coc#notify#win_list(), 'coc#window#get_var(v:val,"closing") != 1')
for winid in winids
let key = getwinvar(winid, 'key', v:null)
if type(key) == v:t_string
let bufnr = winbufnr(winid)
let obj = json_decode(key)
let sourcename = get(obj, 'source', '')
let lnum = get(obj, 'kind', '') ==# 'progress' ? 1 : 0
let content = get(getbufline(bufnr, lnum + 1), 0, '')
if empty(sourcename) || content ==# sourcename
continue
endif
call appendbufline(bufnr, lnum, sourcename)
call coc#highlight#add_highlight(bufnr, -1, 'Title', lnum, 0, -1)
call coc#float#scroll_win(winid, 0, 1)
endif
endfor
redra
endfunction
function! coc#notify#close_by_source(source) abort
let winids = filter(coc#notify#win_list(), 'coc#window#get_var(v:val,"closing") != 1')
for winid in winids
let key = getwinvar(winid, 'key', v:null)
if type(key) == v:t_string
let obj = json_decode(key)
if get(obj, 'source', '') ==# a:source
call coc#notify#close(winid)
endif
endif
endfor
endfunction
" Cancel auto hide
function! coc#notify#keep() abort
for winid in coc#notify#win_list()
call s:cancel(winid, 'close_timer')
endfor
endfunction
" borderhighlight - border highlight [string]
" maxWidth - max content width, default 60 [number]
" minWidth - minimal width [number]
" maxHeight - max content height, default 10 [number]
" highlight - default highlight [string]
" winblend - winblend [number]
" timeout - auto close timeout, default 5000 [number]
" title - title text
" marginRight - margin right, default 10 [number]
" focusable - focusable [number]
" source - source name [string]
" kind - kind for create icon [string]
" actions - action names [string[]]
function! coc#notify#create(lines, config) abort
let actions = get(a:config, 'actions', [])
let key = json_encode(extend({'lines': a:lines}, a:config))
let winid = s:find_win(key)
let kind = get(a:config, 'kind', '')
let row = 0
if winid != -1
let row = getwinvar(winid, 'top', 0)
call filter(s:winids, 'v:val != '.winid)
call coc#float#close(winid)
let winid = v:null
endif
let opts = coc#dict#pick(a:config, ['highlight', 'borderhighlight', 'focusable', 'shadow'])
let border = has_key(opts, 'borderhighlight') ? [1, 1, 1, 1] : []
let icon = s:get_icon(kind, get(a:config, 'highlight', 'CocFloating'))
let margin = get(a:config, 'marginRight', 10)
let maxWidth = min([&columns - margin - 2, get(a:config, 'maxWidth', 80)])
if maxWidth <= 0
throw 'No enough spaces for notification'
endif
let lines = map(copy(a:lines), 'tr(v:val, "\t", " ")')
if has_key(a:config, 'title')
if !empty(border)
let opts['title'] = a:config['title']
else
let lines = [a:config['title']] + lines
endif
endif
let width = max(map(copy(lines), 'strwidth(v:val)')) + (empty(icon) ? 1 : 3)
if width > maxWidth
let lines = coc#string#reflow(lines, maxWidth)
let width = max(map(copy(lines), 'strwidth(v:val)')) + (empty(icon) ? 1 : 3)
endif
let highlights = []
if !empty(icon)
let ic = icon['text']
if empty(lines)
call add(lines, ic)
else
let lines[0] = ic.' '.lines[0]
endif
call add(highlights, {'lnum': 0, 'hlGroup': icon['hl'], 'colStart': 0, 'colEnd': strlen(ic)})
endif
let actionText = join(actions, ' ')
call map(lines, 'v:key == 0 ? v:val : repeat(" ", '.(empty(icon) ? 0 : 2).').v:val')
let minWidth = get(a:config, 'minWidth', kind ==# 'progress' ? 30 : 10)
let width = max(extend(map(lines + [get(opts, 'title', '').' '], 'strwidth(v:val)'), [minWidth, strwidth(actionText) + 1]))
let width = min([maxWidth, width])
let height = min([get(a:config, 'maxHeight', 3), len(lines)])
if kind ==# 'progress'
let lines = [repeat(s:progress_char, width)] + lines
let height = height + 1
endif
if !empty(actions)
let before = max([width - strwidth(actionText), 0])
let lines = lines + [repeat(' ', before).actionText]
let height = height + 1
call s:add_action_highlights(before, height - 1, highlights, actions)
endif
if row == 0
let wintop = coc#notify#get_top()
let row = wintop - height - (empty(border) ? 0 : 2) - 1
if !s:is_vim && !empty(border)
let row = row + 1
endif
endif
let col = &columns - margin - width
if s:is_vim && !empty(border)
let col = col - 2
endif
let winblend = 60
" Avoid animate for transparent background.
if get(a:config, 'winblend', 30) == 0 && empty(synIDattr(synIDtrans(hlID(get(opts, 'highlight', 'CocFloating'))), 'bg', 'gui'))
let winblend = 0
endif
call extend(opts, {
\ 'relative': 'editor',
\ 'width': width,
\ 'height': height,
\ 'col': col,
\ 'row': row + 1,
\ 'lines': lines,
\ 'rounded': 1,
\ 'highlights': highlights,
\ 'winblend': winblend,
\ 'border': border,
\ })
let result = coc#float#create_float_win(0, 0, opts)
if empty(result)
throw 'Unable to create notify window'
endif
let winid = result[0]
let bufnr = result[1]
call setwinvar(winid, 'right', 1)
call setwinvar(winid, 'kind', 'notification')
call setwinvar(winid, 'top', row)
call setwinvar(winid, 'key', key)
call setwinvar(winid, 'actions', actions)
call setwinvar(winid, 'source', get(a:config, 'source', ''))
call setwinvar(winid, 'border', !empty(border))
call coc#float#nvim_scrollbar(winid)
call add(s:winids, winid)
let from = {'row': opts['row'], 'winblend': opts['winblend']}
let to = {'row': row, 'winblend': get(a:config, 'winblend', 30)}
call timer_start(s:interval, { -> s:animate(winid, from, to, 0)})
if kind ==# 'progress'
call timer_start(s:interval, { -> s:progress(winid, width, 0, -1)})
endif
if !s:is_vim
call coc#compat#buf_add_keymap(bufnr, 'n', '<LeftRelease>', ':call coc#notify#nvim_click('.winid.')<CR>', {
\ 'silent': v:true,
\ 'nowait': v:true
\ })
endif
" Enable auto close
if empty(actions) && kind !=# 'progress'
let timer = timer_start(get(a:config, 'timeout', 10000), { -> coc#notify#close(winid)})
call setwinvar(winid, 'close_timer', timer)
endif
return [winid, bufnr]
endfunction
function! coc#notify#nvim_click(winid) abort
if getwinvar(a:winid, 'closing', 0)
return
endif
call s:cancel(a:winid, 'close_timer')
let actions = getwinvar(a:winid, 'actions', [])
if !empty(actions)
let character = strpart(getline('.'), col('.') - 1, 1)
if character =~# '^\k'
let word = expand('<cword>')
let idx = index(actions, word)
if idx != -1
call coc#rpc#notify('FloatBtnClick', [winbufnr(a:winid), idx])
call coc#notify#close(a:winid)
endif
endif
endif
endfunction
function! coc#notify#on_close(winid) abort
if index(s:winids, a:winid) >= 0
call filter(s:winids, 'v:val != '.a:winid)
call coc#notify#reflow()
endif
endfunction
function! coc#notify#get_top() abort
let mintop = min(map(coc#notify#win_list(), 'coc#notify#get_win_top(v:val)'))
if mintop != 0
return mintop
endif
return &lines - &cmdheight - (&laststatus == 0 ? 0 : 1 )
endfunction
function! coc#notify#get_win_top(winid) abort
let row = getwinvar(a:winid, 'top', 0)
if row == 0
return row
endif
return row - (s:is_vim ? 0 : getwinvar(a:winid, 'border', 0))
endfunction
" Close with timer
function! coc#notify#close(winid) abort
if !coc#float#valid(a:winid) || coc#window#get_var(a:winid, 'closing', 0) == 1
return
endif
if !coc#window#visible(a:winid)
call coc#float#close(a:winid)
return
endif
let row = coc#window#get_var(a:winid, 'top')
if type(row) != v:t_number
call coc#float#close(a:winid)
return
endif
call coc#window#set_var(a:winid, 'closing', 1)
call s:cancel(a:winid)
let winblend = coc#window#get_var(a:winid, 'winblend', 0)
let curr = s:is_vim ? {'row': row} : {'winblend': winblend}
let dest = s:is_vim ? {'row': row + 1} : {'winblend': winblend == 0 ? 0 : 60}
call s:animate(a:winid, curr, dest, 0, 1)
endfunction
function! s:add_action_highlights(before, lnum, highlights, actions) abort
let colStart = a:before
for text in a:actions
let w = strwidth(text)
call add(a:highlights, {
\ 'lnum': a:lnum,
\ 'hlGroup': 'CocNotificationButton',
\ 'colStart': colStart,
\ 'colEnd': colStart + w
\ })
let colStart = colStart + w + 1
endfor
endfunction
function! s:on_action(err, idx, winid) abort
if !empty(a:err)
throw a:err
endif
if a:idx > 0
call coc#rpc#notify('FloatBtnClick', [winbufnr(a:winid), a:idx - 1])
call coc#notify#close(a:winid)
endif
endfunction
function! s:cancel(winid, ...) abort
let name = get(a:, 1, 'timer')
let timer = coc#window#get_var(a:winid, name)
if !empty(timer)
call timer_stop(timer)
call coc#window#set_var(a:winid, name, v:null)
endif
endfunction
function! s:progress(winid, total, curr, index) abort
if !coc#float#valid(a:winid)
return
endif
if coc#window#visible(a:winid)
let total = a:total
let idx = float2nr(a:curr/5.0)%total
if idx != a:index
" update percent
let bufnr = winbufnr(a:winid)
let percent = coc#window#get_var(a:winid, 'percent')
if !empty(percent)
let width = strchars(getbufline(bufnr, 1)[0])
let line = repeat(s:progress_char, width - 4).printf('%4s', percent)
let total = width - 4
call setbufline(bufnr, 1, line)
endif
let message = coc#window#get_var(a:winid, 'message')
if !empty(message)
let linecount = coc#compat#buf_line_count(bufnr)
let hasAction = !empty(coc#window#get_var(a:winid, 'actions', []))
if getbufvar(bufnr, 'message', 0) == 0
call appendbufline(bufnr, linecount - hasAction, message)
call setbufvar(bufnr, 'message', 1)
call coc#float#change_height(a:winid, 1)
let tabnr = coc#window#tabnr(a:winid)
call coc#notify#reflow(tabnr)
else
call setbufline(bufnr, linecount - hasAction, message)
endif
endif
let bytes = strlen(s:progress_char)
call coc#highlight#clear_highlight(bufnr, -1, 0, 1)
let colStart = bytes * idx
if idx + 4 <= total
let colEnd = bytes * (idx + 4)
call coc#highlight#add_highlight(bufnr, -1, s:phl, 0, colStart, colEnd)
else
let colEnd = bytes * total
call coc#highlight#add_highlight(bufnr, -1, s:phl, 0, colStart, colEnd)
call coc#highlight#add_highlight(bufnr, -1, s:phl, 0, 0, bytes * (idx + 4 - total))
endif
endif
call timer_start(s:interval, { -> s:progress(a:winid, total, a:curr + 1, idx)})
else
" Not block CursorHold event
call timer_start(&updatetime + 100, { -> s:progress(a:winid, a:total, a:curr, a:index)})
endif
endfunction
" Optional row & winblend
function! s:config_win(winid, props) abort
let change_row = has_key(a:props, 'row')
if s:is_vim
if change_row
call popup_move(a:winid, {'line': a:props['row'] + 1})
endif
else
if change_row
let [row, column] = nvim_win_get_position(a:winid)
call nvim_win_set_config(a:winid, {
\ 'row': a:props['row'],
\ 'col': column,
\ 'relative': 'editor',
\ })
call s:nvim_move_related(a:winid, a:props['row'])
endif
call coc#float#nvim_set_winblend(a:winid, get(a:props, 'winblend', v:null))
call coc#float#nvim_refresh_scrollbar(a:winid)
endif
endfunction
function! s:nvim_move_related(winid, row) abort
let winids = coc#window#get_var(a:winid, 'related')
if empty(winids)
return
endif
for winid in winids
if nvim_win_is_valid(winid)
let [row, column] = nvim_win_get_position(winid)
let delta = coc#window#get_var(winid, 'delta', 0)
call nvim_win_set_config(winid, {
\ 'row': a:row + delta,
\ 'col': column,
\ 'relative': 'editor',
\ })
endif
endfor
endfunction
function! s:animate(winid, from, to, prev, ...) abort
if !coc#float#valid(a:winid)
return
endif
let curr = a:prev + s:interval
let percent = coc#math#min(curr / s:duration, 1)
let props = s:get_props(a:from, a:to, percent)
call s:config_win(a:winid, props)
let close = get(a:, 1, 0)
if percent < 1
call timer_start(s:interval, { -> s:animate(a:winid, a:from, a:to, curr, close)})
elseif close
call filter(s:winids, 'v:val != '.a:winid)
let tabnr = coc#window#tabnr(a:winid)
if tabnr != -1
call coc#float#close(a:winid)
call coc#notify#reflow(tabnr)
endif
endif
endfunction
function! coc#notify#reflow(...) abort
let tabnr = get(a:, 1, tabpagenr())
let winids = filter(copy(s:winids), 'coc#window#tabnr(v:val) == '.tabnr.' && coc#window#get_var(v:val,"closing") != 1')
if empty(winids)
return
endif
let animate = tabnr == tabpagenr()
let wins = map(copy(winids), {_, val -> {
\ 'winid': val,
\ 'row': coc#window#get_var(val,'top',0),
\ 'top': coc#window#get_var(val,'top',0) - (s:is_vim ? 0 : coc#window#get_var(val, 'border', 0)),
\ 'height': coc#float#get_height(val),
\ }})
call sort(wins, {a, b -> b['top'] - a['top']})
let bottom = &lines - &cmdheight - (&laststatus == 0 ? 0 : 1 )
let moved = 0
for item in wins
let winid = item['winid']
let delta = bottom - (item['top'] + item['height'] + 1)
if delta != 0
call s:cancel(winid)
let dest = item['row'] + delta
call coc#window#set_var(winid, 'top', dest)
if animate
call s:move_win_timer(winid, {'row': item['row']}, {'row': dest}, 0)
else
call s:config_win(winid, {'row': dest})
endif
let moved = moved + delta
endif
let bottom = item['top'] + delta
endfor
endfunction
function! s:move_win_timer(winid, from, to, curr) abort
if !coc#float#valid(a:winid)
return
endif
if coc#window#get_var(a:winid, 'closing', 0) == 1
return
endif
let percent = coc#math#min(a:curr / s:duration, 1)
let next = a:curr + s:interval
if a:curr > 0
call s:config_win(a:winid, s:get_props(a:from, a:to, percent))
endif
if percent < 1
let timer = timer_start(s:interval, { -> s:move_win_timer(a:winid, a:from, a:to, next)})
call coc#window#set_var(a:winid, 'timer', timer)
endif
endfunction
function! s:find_win(key) abort
for winid in coc#notify#win_list()
if getwinvar(winid, 'key', '') ==# a:key
return winid
endif
endfor
return -1
endfunction
function! s:get_icon(kind, bg) abort
if a:kind ==# 'info'
return {'text': s:info_icon, 'hl': coc#highlight#compose_hlgroup('CocInfoSign', a:bg)}
endif
if a:kind ==# 'warning'
return {'text': s:warning_icon, 'hl': coc#highlight#compose_hlgroup('CocWarningSign', a:bg)}
endif
if a:kind ==# 'error'
return {'text': s:error_icon, 'hl': coc#highlight#compose_hlgroup('CocErrorSign', a:bg)}
endif
return v:null
endfunction
" percent should be float
function! s:get_props(from, to, percent) abort
let obj = {}
for key in keys(a:from)
let changed = a:to[key] - a:from[key]
if !s:is_vim && key ==# 'row'
" Could be float
let obj[key] = a:from[key] + changed * a:percent
else
let obj[key] = a:from[key] + float2nr(round(changed * a:percent))
endif
endfor
return obj
endfunction

View file

@ -0,0 +1,214 @@
scriptencoding utf-8
let s:is_vim = !has('nvim')
let s:activated = 0
let s:session_names = []
let s:saved_ve = &t_ve
let s:saved_cursor = &guicursor
let s:gui = has('gui_running') || has('nvim')
let s:char_map = {
\ "\<Plug>": '<plug>',
\ "\<Esc>": '<esc>',
\ "\<Tab>": '<tab>',
\ "\<S-Tab>": '<s-tab>',
\ "\<bs>": '<bs>',
\ "\<right>": '<right>',
\ "\<left>": '<left>',
\ "\<up>": '<up>',
\ "\<down>": '<down>',
\ "\<home>": '<home>',
\ "\<end>": '<end>',
\ "\<cr>": '<cr>',
\ "\<PageUp>":'<PageUp>' ,
\ "\<PageDown>":'<PageDown>' ,
\ "\<FocusGained>":'<FocusGained>',
\ "\<FocusLost>":'<FocusLost>',
\ "\<ScrollWheelUp>": '<ScrollWheelUp>',
\ "\<ScrollWheelDown>": '<ScrollWheelDown>',
\ "\<LeftMouse>": '<LeftMouse>',
\ "\<LeftDrag>": '<LeftDrag>',
\ "\<LeftRelease>": '<LeftRelease>',
\ "\<2-LeftMouse>": '<2-LeftMouse>',
\ "\<C-a>": '<C-a>',
\ "\<C-b>": '<C-b>',
\ "\<C-c>": '<C-c>',
\ "\<C-d>": '<C-d>',
\ "\<C-e>": '<C-e>',
\ "\<C-f>": '<C-f>',
\ "\<C-g>": '<C-g>',
\ "\<C-h>": '<C-h>',
\ "\<C-j>": '<C-j>',
\ "\<C-k>": '<C-k>',
\ "\<C-l>": '<C-l>',
\ "\<C-n>": '<C-n>',
\ "\<C-o>": '<C-o>',
\ "\<C-p>": '<C-p>',
\ "\<C-q>": '<C-q>',
\ "\<C-r>": '<C-r>',
\ "\<C-s>": '<C-s>',
\ "\<C-t>": '<C-t>',
\ "\<C-u>": '<C-u>',
\ "\<C-v>": '<C-v>',
\ "\<C-w>": '<C-w>',
\ "\<C-x>": '<C-x>',
\ "\<C-y>": '<C-y>',
\ "\<C-z>": '<C-z>',
\ "\<A-a>": '<A-a>',
\ "\<A-b>": '<A-b>',
\ "\<A-c>": '<A-c>',
\ "\<A-d>": '<A-d>',
\ "\<A-e>": '<A-e>',
\ "\<A-f>": '<A-f>',
\ "\<A-g>": '<A-g>',
\ "\<A-h>": '<A-h>',
\ "\<A-i>": '<A-i>',
\ "\<A-j>": '<A-j>',
\ "\<A-k>": '<A-k>',
\ "\<A-l>": '<A-l>',
\ "\<A-m>": '<A-m>',
\ "\<A-n>": '<A-n>',
\ "\<A-o>": '<A-o>',
\ "\<A-p>": '<A-p>',
\ "\<A-q>": '<A-q>',
\ "\<A-r>": '<A-r>',
\ "\<A-s>": '<A-s>',
\ "\<A-t>": '<A-t>',
\ "\<A-u>": '<A-u>',
\ "\<A-v>": '<A-v>',
\ "\<A-w>": '<A-w>',
\ "\<A-x>": '<A-x>',
\ "\<A-y>": '<A-y>',
\ "\<A-z>": '<A-z>',
\ }
function! coc#prompt#getc() abort
let c = getchar()
return type(c) is 0 ? nr2char(c) : c
endfunction
function! coc#prompt#getchar() abort
let input = coc#prompt#getc()
if 1 != &iminsert
return input
endif
"a language keymap is activated, so input must be resolved to the mapped values.
let partial_keymap = mapcheck(input, 'l')
while partial_keymap !=# ''
let dict = maparg(input, 'l', 0, 1)
if empty(dict) || get(dict, 'expr', 0)
return input
endif
let full_keymap = get(dict, 'rhs', '')
if full_keymap ==# "" && len(input) >= 3 "HACK: assume there are no keymaps longer than 3.
return input
elseif full_keymap ==# partial_keymap
return full_keymap
endif
let c = coc#prompt#getc()
if c ==# "\<Esc>" || c ==# "\<CR>"
"if the short sequence has a valid mapping, return that.
if !empty(full_keymap)
return full_keymap
endif
return input
endif
let input .= c
let partial_keymap = mapcheck(input, 'l')
endwhile
return input
endfunction
function! coc#prompt#start_prompt(session) abort
let s:session_names = s:filter(s:session_names, a:session)
call add(s:session_names, a:session)
if s:activated | return | endif
if s:is_vim
call s:start_prompt_vim()
else
call s:start_prompt()
endif
endfunction
function! s:start_prompt_vim() abort
call timer_start(10, {-> s:start_prompt()})
endfunction
function! s:start_prompt()
if s:activated | return | endif
if !get(g:, 'coc_disable_transparent_cursor', 0)
if s:gui
if has('nvim-0.5.0') && !empty(s:saved_cursor)
set guicursor+=a:ver1-CocCursorTransparent/lCursor
endif
elseif s:is_vim
set t_ve=
endif
endif
let s:activated = 1
try
while s:activated
let ch = coc#prompt#getchar()
if ch ==# "\<FocusLost>" || ch ==# "\<FocusGained>" || ch ==# "\<CursorHold>"
continue
else
let curr = s:current_session()
let mapped = get(s:char_map, ch, ch)
if !empty(curr)
call coc#rpc#notify('InputChar', [curr, mapped, getcharmod()])
endif
if mapped == '<esc>'
let s:session_names = []
call s:reset()
break
endif
endif
endwhile
catch /^Vim:Interrupt$/
let s:activated = 0
call coc#rpc#notify('InputChar', [s:current_session(), '<esc>'])
return
endtry
let s:activated = 0
endfunction
function! coc#prompt#stop_prompt(session)
let s:session_names = s:filter(s:session_names, a:session)
if len(s:session_names)
return
endif
if s:activated
let s:activated = 0
call s:reset()
call feedkeys("\<esc>", 'int')
endif
endfunction
function! coc#prompt#activated() abort
return s:activated
endfunction
function! s:reset() abort
if !get(g:, 'coc_disable_transparent_cursor',0)
" neovim has bug with revert empty &guicursor
if s:gui && !empty(s:saved_cursor)
if has('nvim-0.5.0')
set guicursor+=a:ver1-Cursor/lCursor
let &guicursor = s:saved_cursor
endif
elseif s:is_vim
let &t_ve = s:saved_ve
endif
endif
echo ""
endfunction
function! s:current_session() abort
if empty(s:session_names)
return v:null
endif
return s:session_names[len(s:session_names) - 1]
endfunction
function! s:filter(list, id) abort
return filter(copy(a:list), 'v:val !=# a:id')
endfunction

View file

@ -0,0 +1,490 @@
scriptencoding utf-8
let s:is_vim = !has('nvim')
let s:float = has('nvim-0.4.0') || has('patch-8.1.1719')
let s:pum_bufnr = 0
let s:pum_winid = 0
let s:pum_index = -1
let s:inserted = 0
let s:virtual_text = 0
let s:virtual_text_ns = 0
let s:ignore = s:is_vim || has('nvim-0.5.0') ? "\<Ignore>" : "\<space>\<bs>"
let s:hide_pum = has('nvim-0.6.1') || has('patch-8.2.3389')
function! coc#pum#visible() abort
if !s:float || !s:pum_winid
return 0
endif
return getwinvar(s:pum_winid, 'float', 0) == 1
endfunction
function! coc#pum#winid() abort
return s:pum_winid
endfunction
function! coc#pum#close_detail() abort
let winid = coc#float#get_float_by_kind('pumdetail')
if winid
call coc#float#close(winid)
if s:is_vim
call timer_start(0, { -> execute('redraw')})
endif
endif
endfunction
function! coc#pum#close(...) abort
if coc#float#valid(s:pum_winid)
if get(a:, 1, '') ==# 'cancel'
let input = getwinvar(s:pum_winid, 'input', '')
let s:pum_index = -1
call s:insert_word(input)
call s:on_pum_change(0)
doautocmd TextChangedI
elseif get(a:, 1, '') ==# 'confirm'
let words = getwinvar(s:pum_winid, 'words', [])
if s:pum_index >= 0
let word = get(words, s:pum_index, '')
call s:insert_word(word)
endif
doautocmd TextChangedI
endif
call s:close_pum()
if !get(a:, 2, 0)
let pretext = strpart(getline('.'), 0, col('.') - 1)
call coc#rpc#notify('CompleteStop', [get(a:, 1, ''), pretext])
endif
endif
endfunction
function! coc#pum#select_confirm() abort
if s:pum_index < 0
let s:pum_index = 0
call s:on_pum_change(0)
endif
call coc#pum#close('confirm')
endfunction
function! coc#pum#insert() abort
call timer_start(10, { -> s:insert_current()})
return s:ignore
endfunction
function! coc#pum#_close() abort
if coc#float#valid(s:pum_winid)
call s:close_pum()
if s:is_vim
call timer_start(0, { -> execute('redraw')})
endif
endif
endfunction
function! s:insert_current() abort
if coc#float#valid(s:pum_winid)
if s:pum_index >= 0
let words = getwinvar(s:pum_winid, 'words', [])
let word = get(words, s:pum_index, '')
call s:insert_word(word)
endif
doautocmd TextChangedI
call s:close_pum()
let pretext = strpart(getline('.'), 0, col('.') - 1)
call coc#rpc#notify('CompleteStop', ['', pretext])
endif
endfunction
function! s:close_pum() abort
call s:clear_virtual_text()
call coc#float#close(s:pum_winid)
let s:pum_winid = 0
let winid = coc#float#get_float_by_kind('pumdetail')
if winid
call coc#float#close(winid)
endif
endfunction
function! coc#pum#next(insert) abort
call timer_start(10, { -> s:navigate(1, a:insert)})
return s:ignore
endfunction
function! coc#pum#prev(insert) abort
call timer_start(10, { -> s:navigate(0, a:insert)})
return s:ignore
endfunction
function! coc#pum#stop() abort
call timer_start(10, { -> coc#pum#close()})
return s:ignore
endfunction
function! coc#pum#cancel() abort
call timer_start(10, { -> coc#pum#close('cancel')})
return s:ignore
endfunction
function! coc#pum#confirm() abort
call timer_start(10, { -> coc#pum#close('confirm')})
return s:ignore
endfunction
function! coc#pum#select(index, insert, confirm) abort
if !coc#float#valid(s:pum_winid)
return ''
endif
if a:index == -1
call coc#pum#close('cancel')
return ''
endif
let total = coc#compat#buf_line_count(s:pum_bufnr)
if a:index < 0 || a:index >= total
throw 'index out of range ' . a:index
endif
call s:select_by_index(a:index, a:insert)
if a:confirm
call coc#pum#close('confirm')
endif
return ''
endfunction
function! coc#pum#info() abort
let bufnr = winbufnr(s:pum_winid)
let size = coc#compat#buf_line_count(bufnr)
let words = getwinvar(s:pum_winid, 'words', [])
let word = s:pum_index < 0 ? '' : get(words, s:pum_index, '')
if s:is_vim
let pos = popup_getpos(s:pum_winid)
let add = pos['scrollbar'] && has_key(popup_getoptions(s:pum_winid), 'border') ? 1 : 0
return {
\ 'word': word,
\ 'index': s:pum_index,
\ 'scrollbar': pos['scrollbar'],
\ 'row': pos['line'] - 1,
\ 'col': pos['col'] - 1,
\ 'width': pos['width'] + add,
\ 'height': pos['height'],
\ 'size': size,
\ 'inserted': s:inserted ? v:true : v:false,
\ }
else
let scrollbar = coc#float#get_related(s:pum_winid, 'scrollbar')
let winid = coc#float#get_related(s:pum_winid, 'border', s:pum_winid)
let pos = nvim_win_get_position(winid)
return {
\ 'word': word,
\ 'index': s:pum_index,
\ 'scrollbar': scrollbar && nvim_win_is_valid(scrollbar) ? 1 : 0,
\ 'row': pos[0],
\ 'col': pos[1],
\ 'width': nvim_win_get_width(winid),
\ 'height': nvim_win_get_height(winid),
\ 'size': size,
\ 'inserted': s:inserted ? v:true : v:false,
\ }
endif
endfunction
function! coc#pum#scroll(forward) abort
if coc#pum#visible()
let size = coc#compat#buf_line_count(s:pum_bufnr)
let height = s:get_height(s:pum_winid)
if size > height
call timer_start(10, { -> s:scroll_pum(a:forward, height, size)})
endif
endif
return s:ignore
endfunction
function! s:get_height(winid) abort
if has('nvim')
return nvim_win_get_height(a:winid)
endif
return get(popup_getpos(a:winid), 'core_height', 0)
endfunction
function! s:scroll_pum(forward, height, size) abort
let topline = s:get_topline(s:pum_winid)
if !a:forward && topline == 1
if s:pum_index >= 0
call s:select_line(s:pum_winid, 1)
call s:on_pum_change(1)
endif
return
endif
if a:forward && topline + a:height - 1 >= a:size
if s:pum_index >= 0
call s:select_line(s:pum_winid, a:size)
call s:on_pum_change(1)
endif
return
endif
call coc#float#scroll_win(s:pum_winid, a:forward, a:height)
if s:pum_index >= 0
let lnum = s:pum_index + 1
let topline = s:get_topline(s:pum_winid)
if lnum >= topline && lnum <= topline + a:height - 1
return
endif
call s:select_line(s:pum_winid, topline)
call s:on_pum_change(1)
endif
endfunction
function! s:get_topline(winid) abort
if has('nvim')
let info = getwininfo(a:winid)[0]
return info['topline']
else
let pos = popup_getpos(a:winid)
return pos['firstline']
endif
endfunction
function! s:navigate(next, insert) abort
if !coc#float#valid(s:pum_winid)
return
endif
let index = s:get_index(a:next)
call s:select_by_index(index, a:insert)
endfunction
function! s:select_by_index(index, insert) abort
call s:set_cursor(s:pum_winid, a:index + 1)
if !s:is_vim
call coc#float#nvim_scrollbar(s:pum_winid)
endif
if a:insert
let s:inserted = 1
if a:index < 0
let input = getwinvar(s:pum_winid, 'input', '')
call s:insert_word(input)
call coc#pum#close_detail()
else
let words = getwinvar(s:pum_winid, 'words', [])
let word = get(words, a:index, '')
call s:insert_word(word)
endif
doautocmd TextChangedP
endif
call s:on_pum_change(1)
endfunction
function! s:get_index(next) abort
let size = coc#compat#buf_line_count(s:pum_bufnr)
if a:next
let index = s:pum_index + 1 == size ? -1 : s:pum_index + 1
else
let index = s:pum_index == -1 ? size - 1 : s:pum_index - 1
endif
return index
endfunction
function! s:insert_word(word) abort
let parts = getwinvar(s:pum_winid, 'parts', [])
if !empty(parts) && mode() ==# 'i'
let curr = getline('.')
if curr ==# parts[0].a:word.parts[1]
return
endif
let saved_completeopt = &completeopt
if saved_completeopt =~ 'menuone'
noa set completeopt=menu
endif
noa call complete(strlen(parts[0]) + 1, [a:word])
if s:hide_pum
" exit complete state
call feedkeys("\<C-x>\<C-z>", 'in')
else
let g:coc_disable_space_report = 1
call feedkeys("\<space>\<bs>", 'in')
endif
execute 'noa set completeopt='.saved_completeopt
endif
endfunction
" create or update pum with lines, CompleteOption and config.
" return winid & dimension
function! coc#pum#create(lines, opt, config) abort
if mode() !=# 'i' || a:opt['line'] != line('.')
return
endif
let len = col('.') - a:opt['col'] - 1
if len < 0
return
endif
let input = len == 0 ? '' : strpart(getline('.'), a:opt['col'], len)
if input !=# a:opt['input']
return
endif
let config = s:get_pum_dimension(a:lines, a:opt['col'], a:config)
if empty(config)
return
endif
let s:virtual_text = has('nvim-0.5.0') && a:opt['virtualText']
if s:virtual_text && !s:virtual_text_ns
let s:virtual_text_ns = coc#highlight#create_namespace('pum-virtual')
endif
let selected = a:opt['index'] + 1
call extend(config, {
\ 'lines': a:lines,
\ 'relative': 'cursor',
\ 'nopad': 1,
\ 'cursorline': 1,
\ 'index': a:opt['index'],
\ 'focusable': v:false
\ })
call extend(config, coc#dict#pick(a:config, ['highlight', 'rounded', 'highlights', 'winblend', 'shadow', 'border', 'borderhighlight']))
let result = coc#float#create_float_win(s:pum_winid, s:pum_bufnr, config)
if empty(result)
return
endif
let s:inserted = 0
let s:pum_winid = result[0]
let s:pum_bufnr = result[1]
call setwinvar(s:pum_winid, 'above', config['row'] < 0)
let lnum = max([1, a:opt['index'] + 1])
if s:is_vim
call popup_setoptions(s:pum_winid, {
\ 'firstline': s:get_firstline(lnum, len(a:lines), config['height'])
\ })
else
let firstline = s:get_firstline(lnum, len(a:lines), config['height'])
call coc#compat#execute(s:pum_winid, 'call winrestview({"lnum":'.lnum.',"topline":'.firstline.'})')
endif
let s:pum_index = get(config, 'index', -1)
call coc#dialog#place_sign(s:pum_bufnr, s:pum_index + 1)
call setwinvar(s:pum_winid, 'kind', 'pum')
" content before col and content after cursor
let linetext = getline('.')
let parts = [strpart(linetext, 0, a:opt['col']), strpart(linetext, col('.') - 1)]
call setwinvar(s:pum_winid, 'input', input)
call setwinvar(s:pum_winid, 'parts', parts)
call setwinvar(s:pum_winid, 'words', a:opt['words'])
if !s:is_vim
if len(a:lines) > config['height']
redraw
call coc#float#nvim_scrollbar(s:pum_winid)
else
call coc#float#close_related(s:pum_winid, 'scrollbar')
endif
endif
call timer_start(10, { -> s:on_pum_change(0)})
endfunction
function! s:get_firstline(lnum, total, height) abort
if a:lnum <= a:height
return 1
endif
return min([a:total - a:height + 1, a:lnum - (a:height*2/3)])
endfunction
function! s:on_pum_change(move) abort
if coc#float#valid(s:pum_winid)
if s:virtual_text_ns
call s:insert_virtual_text()
endif
let ev = extend(coc#pum#info(), {'move': a:move ? v:true : v:false})
call coc#rpc#notify('CocAutocmd', ['MenuPopupChanged', ev, win_screenpos(winnr())[0] + winline() - 2])
endif
endfunction
function! s:get_pum_dimension(lines, col, config) abort
let linecount = len(a:lines)
let [lineIdx, colIdx] = coc#cursor#screen_pos()
let bh = empty(get(a:config, 'border', [])) ? 0 : 2
let width = min([&columns, max([exists('&pumwidth') ? &pumwidth : 15, a:config['width']])])
let vh = &lines - &cmdheight - 1 - !empty(&tabline)
if vh <= 0
return v:null
endif
let pumheight = empty(&pumheight) ? vh : &pumheight
let showTop = getwinvar(s:pum_winid, 'above', v:null)
if type(showTop) != v:t_number
if vh - lineIdx - bh - 1 < min([pumheight, linecount]) && lineIdx > vh - lineIdx
let showTop = 1
else
let showTop = 0
endif
endif
let height = showTop ? min([lineIdx - bh - !empty(&tabline), linecount, pumheight]) : min([vh - lineIdx - bh - 1, linecount, pumheight])
if height <= 0
return v:null
endif
let col = - (col('.') - a:col - 1) - 1
let row = showTop ? - height : 1
let delta = colIdx + col
if delta < 0
let col = col - delta
elseif delta + width > &columns
let col = max([-colIdx, col - (delta + width - &columns)])
endif
return {
\ 'row': row,
\ 'col': col,
\ 'width': width,
\ 'height': height
\ }
endfunction
" can't use coc#dialog#set_cursor on vim8, don't know why
function! s:set_cursor(winid, line) abort
if s:is_vim
let pos = popup_getpos(a:winid)
let lastline = pos['firstline'] + pos['core_height'] - 1
if a:line > lastline
call popup_setoptions(a:winid, {
\ 'firstline': pos['firstline'] + a:line - lastline,
\ })
elseif a:line < pos['firstline']
call popup_setoptions(a:winid, {
\ 'firstline': max([1, a:line]),
\ })
endif
endif
call s:select_line(a:winid, a:line)
endfunction
function! s:select_line(winid, line) abort
let s:pum_index = a:line - 1
let lnum = max([1, a:line])
if s:is_vim
call coc#compat#execute(a:winid, 'exe '.lnum)
else
call nvim_win_set_cursor(a:winid, [lnum, 0])
endif
call coc#dialog#place_sign(winbufnr(a:winid), a:line)
endfunction
function! s:insert_virtual_text() abort
if !s:virtual_text_ns
return
endif
let bufnr = bufnr('%')
if !s:virtual_text || !coc#pum#visible() || s:pum_index < 0
call nvim_buf_clear_namespace(bufnr, s:virtual_text_ns, 0, -1)
else
" Check if could create
let insert = ''
let words = getwinvar(s:pum_winid, 'words', [])
let word = get(words, s:pum_index, '')
let parts = getwinvar(s:pum_winid, 'parts', [])
let input = strpart(getline('.'), strlen(parts[0]), col('.') - 1)
if strchars(word) > strchars(input) && strcharpart(word, 0, strchars(input)) ==# input
let insert = strcharpart(word, strchars(input))
endif
call nvim_buf_clear_namespace(bufnr, s:virtual_text_ns, 0, -1)
if !empty(insert)
let opts = {
\ 'hl_mode': 'combine',
\ 'virt_text': [[insert, 'CocPumVirtualText']],
\ 'virt_text_pos': 'overlay',
\ 'virt_text_win_col': virtcol('.') - 1,
\ }
call nvim_buf_set_extmark(bufnr, s:virtual_text_ns, line('.') - 1, col('.') - 1, opts)
endif
endif
endfunction
function! s:clear_virtual_text() abort
if s:virtual_text_ns
call nvim_buf_clear_namespace(bufnr('%'), s:virtual_text_ns, 0, -1)
endif
endfunction

View file

@ -0,0 +1,130 @@
scriptencoding utf-8
let s:is_win = has("win32") || has("win64")
let s:client = v:null
let s:name = 'coc'
let s:is_vim = !has('nvim')
function! coc#rpc#start_server()
if get(g:, 'coc_node_env', '') ==# 'test'
" server already started
let s:client = coc#client#create(s:name, [])
let chan_id = get(g:, 'coc_node_channel_id', 0)
let s:client['running'] = chan_id != 0
let s:client['chan_id'] = chan_id
return
endif
if empty(s:client)
let cmd = coc#util#job_command()
if empty(cmd) | return | endif
let $COC_VIMCONFIG = coc#util#get_config_home()
let $COC_DATA_HOME = coc#util#get_data_home()
let s:client = coc#client#create(s:name, cmd)
endif
if !coc#client#is_running('coc')
call s:client['start']()
endif
endfunction
function! coc#rpc#started() abort
return !empty(s:client)
endfunction
function! coc#rpc#ready()
if empty(s:client) || s:client['running'] == 0
return 0
endif
return 1
endfunction
function! coc#rpc#set_channel(chan_id) abort
let g:coc_node_channel_id = a:chan_id
if a:chan_id != 0
let s:client['running'] = 1
let s:client['chan_id'] = a:chan_id
endif
endfunction
function! coc#rpc#kill()
let pid = get(g:, 'coc_process_pid', 0)
if !pid | return | endif
if s:is_win
call system('taskkill /PID '.pid)
else
call system('kill -9 '.pid)
endif
endfunction
function! coc#rpc#get_errors()
return split(execute('messages'), "\n")
endfunction
function! coc#rpc#stop()
if empty(s:client)
return
endif
try
if s:is_vim
call job_stop(ch_getjob(s:client['channel']), 'term')
else
call jobstop(s:client['chan_id'])
endif
catch /.*/
" ignore
endtry
endfunction
function! coc#rpc#restart()
if empty(s:client)
call coc#rpc#start_server()
else
call coc#highlight#clear_all()
call coc#ui#sign_unplace()
call coc#float#close_all()
call coc#rpc#request('detach', [])
sleep 100m
let s:client['command'] = coc#util#job_command()
call coc#client#restart(s:name)
echohl MoreMsg | echom 'starting coc.nvim service' | echohl None
endif
endfunction
function! coc#rpc#request(method, args) abort
if !coc#rpc#ready()
return ''
endif
return s:client['request'](a:method, a:args)
endfunction
function! coc#rpc#notify(method, args) abort
if !coc#rpc#ready()
return ''
endif
call s:client['notify'](a:method, a:args)
return ''
endfunction
function! coc#rpc#request_async(method, args, cb) abort
if !coc#rpc#ready()
return cb('coc.nvim service not started.')
endif
call s:client['request_async'](a:method, a:args, a:cb)
endfunction
" receive async response
function! coc#rpc#async_response(id, resp, isErr) abort
if empty(s:client)
return
endif
call coc#client#on_response(s:name, a:id, a:resp, a:isErr)
endfunction
" send async response to server
function! coc#rpc#async_request(id, method, args)
let l:Cb = {err, ... -> coc#rpc#notify('nvim_async_response_event', [a:id, err, get(a:000, 0, v:null)])}
let args = a:args + [l:Cb]
try
call call(a:method, args)
catch /.*/
call coc#rpc#notify('nvim_async_response_event', [a:id, v:exception, v:null])
endtry
endfunction

View file

@ -0,0 +1,155 @@
scriptencoding utf-8
let s:is_vim = !has('nvim')
let s:map_next = 1
let s:map_prev = 1
let s:cmd_mapping = has('nvim') || has('patch-8.2.1978')
function! coc#snippet#_select_mappings()
if !get(g:, 'coc_selectmode_mapping', 1)
return
endif
redir => mappings
silent! smap
redir END
for map in map(filter(split(mappings, '\n'),
\ "v:val !~# '^s' && v:val !~# '^\\a*\\s*<\\S\\+>'"),
\ "matchstr(v:val, '^\\a*\\s*\\zs\\S\\+')")
silent! execute 'sunmap' map
silent! execute 'sunmap <buffer>' map
endfor
" same behaviour of ultisnips
snoremap <silent> <BS> <c-g>c
snoremap <silent> <DEL> <c-g>c
snoremap <silent> <c-h> <c-g>c
snoremap <c-r> <c-g>"_c<c-r>
endfunction
function! coc#snippet#show_choices(lnum, col, len, values) abort
let m = mode()
call cursor(a:lnum, a:col + a:len)
if m !=# 'i'
call feedkeys("\<Esc>i", 'in')
endif
let changedtick = b:changedtick
call timer_start(20, { -> coc#_do_complete(a:col - 1, a:values, 0, changedtick)})
redraw
endfunction
function! coc#snippet#enable(...)
if get(b:, 'coc_snippet_active', 0) == 1
return
endif
let complete = get(a:, 1, 0)
let b:coc_snippet_active = 1
call coc#snippet#_select_mappings()
let nextkey = get(g:, 'coc_snippet_next', '<C-j>')
let prevkey = get(g:, 'coc_snippet_prev', '<C-k>')
if maparg(nextkey, 'i') =~# 'snippet'
let s:map_next = 0
endif
if maparg(prevkey, 'i') =~# 'snippet'
let s:map_prev = 0
endif
if !empty(nextkey)
if s:map_next
execute 'inoremap <buffer><nowait><silent>'.nextkey." <C-R>=coc#snippet#jump(1, ".complete.")<cr>"
endif
execute 'snoremap <buffer><nowait><silent>'.nextkey." <Esc>:call coc#snippet#jump(1, ".complete.")<cr>"
endif
if !empty(prevkey)
if s:map_prev
execute 'inoremap <buffer><nowait><silent>'.prevkey." <C-R>=coc#snippet#jump(0, ".complete.")<cr>"
endif
execute 'snoremap <buffer><nowait><silent>'.prevkey." <Esc>:call coc#snippet#jump(0, ".complete.")<cr>"
endif
endfunction
function! coc#snippet#prev() abort
call coc#rpc#request('snippetPrev', [])
return ''
endfunction
function! coc#snippet#next() abort
call coc#rpc#request('snippetNext', [])
return ''
endfunction
function! coc#snippet#jump(direction, complete) abort
if a:direction == 1 && a:complete && pumvisible()
let pre = exists('*complete_info') && complete_info()['selected'] == -1 ? "\<C-n>" : ''
call feedkeys(pre."\<C-y>", 'in')
return ''
endif
call coc#rpc#request(a:direction == 1 ? 'snippetNext' : 'snippetPrev', [])
return ''
endfunction
function! coc#snippet#disable()
if get(b:, 'coc_snippet_active', 0) == 0
return
endif
let b:coc_snippet_active = 0
let nextkey = get(g:, 'coc_snippet_next', '<C-j>')
let prevkey = get(g:, 'coc_snippet_prev', '<C-k>')
if s:map_next
silent! execute 'iunmap <buffer> <silent> '.nextkey
endif
if s:map_prev
silent! execute 'iunmap <buffer> <silent> '.prevkey
endif
silent! execute 'sunmap <buffer> <silent> '.prevkey
silent! execute 'sunmap <buffer> <silent> '.nextkey
endfunction
function! coc#snippet#select(start, end, text) abort
if coc#pum#visible()
call coc#pum#close()
endif
if mode() == 's'
call feedkeys("\<Esc>", 'in')
endif
if &selection ==# 'exclusive'
let cursor = coc#snippet#to_cursor(a:start)
call cursor([cursor[0], cursor[1]])
let cmd = ''
let cmd .= mode()[0] ==# 'i' ? "\<Esc>".(col('.') == 1 ? '' : 'l') : ''
let cmd .= printf('v%s', strchars(a:text) . 'l')
let cmd .= "\<C-g>"
else
let cursor = coc#snippet#to_cursor(a:end)
call cursor([cursor[0], cursor[1] - 1])
let len = strchars(a:text) - 1
let cmd = ''
let cmd .= mode()[0] ==# 'i' ? "\<Esc>l" : ''
let cmd .= printf('v%s', len > 0 ? len . 'h' : '')
let cmd .= "o\<C-g>"
endif
call feedkeys(cmd, 'n')
endfunction
function! coc#snippet#move(position) abort
let m = mode()
if m == 's'
call feedkeys("\<Esc>", 'in')
elseif coc#pum#visible()
call coc#pum#close()
endif
let pos = coc#snippet#to_cursor(a:position)
call cursor(pos)
if pos[1] > strlen(getline(pos[0]))
startinsert!
else
startinsert
endif
endfunction
function! coc#snippet#to_cursor(position) abort
let line = getline(a:position.line + 1)
if line is v:null
return [a:position.line + 1, a:position.character + 1]
endif
return [a:position.line + 1, byteidx(line, a:position.character) + 1]
endfunction

View file

@ -0,0 +1,154 @@
scriptencoding utf-8
function! coc#string#get_character(line, col) abort
return strchars(strpart(a:line, 0, a:col - 1))
endfunction
function! coc#string#last_character(line) abort
return strcharpart(a:line, strchars(a:line) - 1, 1)
endfunction
function! coc#string#reflow(lines, width) abort
let lines = []
let currlen = 0
let parts = []
for line in a:lines
for part in split(line, '\s\+')
let w = strwidth(part)
if currlen + w + 1 >= a:width
if len(parts) > 0
call add(lines, join(parts, ' '))
endif
if w >= a:width
call add(lines, part)
let currlen = 0
let parts = []
else
let currlen = w
let parts = [part]
endif
continue
endif
call add(parts, part)
let currlen = currlen + w + 1
endfor
endfor
if len(parts) > 0
call add(lines, join(parts, ' '))
endif
return empty(lines) ? [''] : lines
endfunction
function! coc#string#content_height(lines, width) abort
let len = 0
for line in a:lines
if strwidth(line) <= a:width
let len = len + 1
else
let currlen = 0
for part in split(line, '\<\|\>\|\ze\s')
let w = strwidth(part)
if currlen + w >= a:width
if currlen + w == a:width
let len = len + 1
let currlen = 0
else
let len = len + (a:width + w)/a:width
let currlen = w%a:width
endif
else
let currlen = currlen + w
endif
endfor
if currlen > 0
let len = len + 1
endif
endif
endfor
return len == 0 ? 1 : len
endfunction
" get change between two lines
function! coc#string#diff(curr, previous, col) abort
let end = strpart(a:curr, a:col - 1)
let start = strpart(a:curr, 0, a:col -1)
let endOffset = 0
let startOffset = 0
let currLen = strchars(a:curr)
let prevLen = strchars(a:previous)
if len(end)
let endLen = strchars(end)
for i in range(min([prevLen, endLen]))
if strcharpart(end, endLen - 1 - i, 1) ==# strcharpart(a:previous, prevLen -1 -i, 1)
let endOffset = endOffset + 1
else
break
endif
endfor
endif
let remain = endOffset == 0 ? a:previous : strcharpart(a:previous, 0, prevLen - endOffset)
if len(remain)
for i in range(min([strchars(remain), strchars(start)]))
if strcharpart(remain, i, 1) ==# strcharpart(start, i ,1)
let startOffset = startOffset + 1
else
break
endif
endfor
endif
return {
\ 'start': startOffset,
\ 'end': prevLen - endOffset,
\ 'text': strcharpart(a:curr, startOffset, currLen - startOffset - endOffset)
\ }
endfunction
function! coc#string#apply(content, diff) abort
let totalLen = strchars(a:content)
let endLen = totalLen - a:diff['end']
return strcharpart(a:content, 0, a:diff['start']).a:diff['text'].strcharpart(a:content, a:diff['end'], endLen)
endfunction
" insert inserted to line at position, use ... when result is too long
" line should only contains character has strwidth equals 1
function! coc#string#compose(line, position, inserted) abort
let width = strwidth(a:line)
let text = a:inserted
let res = a:line
let need_truncate = a:position + strwidth(text) + 1 > width
if need_truncate
let remain = width - a:position - 3
if remain < 2
" use text for full line, use first & end of a:line, ignore position
let res = strcharpart(a:line, 0, 1)
let w = strwidth(res)
for i in range(strchars(text))
let c = strcharpart(text, i, 1)
let a = strwidth(c)
if w + a <= width - 1
let w = w + a
let res = res . c
endif
endfor
let res = res.strcharpart(a:line, w)
else
let res = strcharpart(a:line, 0, a:position)
let w = strwidth(res)
for i in range(strchars(text))
let c = strcharpart(text, i, 1)
let a = strwidth(c)
if w + a <= width - 3
let w = w + a
let res = res . c
endif
endfor
let res = res.'..'
let w = w + 2
let res = res . strcharpart(a:line, w)
endif
else
let first = strcharpart(a:line, 0, a:position)
let res = first . text . strcharpart(a:line, a:position + strwidth(text))
endif
return res
endfunction

View file

@ -0,0 +1,179 @@
" ============================================================================
" Description: Manage long running tasks.
" Author: Qiming Zhao <chemzqm@gmail.com>
" Licence: Anti 966 licence
" Version: 0.1
" Last Modified: Dec 12, 2020
" ============================================================================
scriptencoding utf-8
let s:is_vim = !has('nvim')
let s:running_task = {}
" neovim emit strings that part of lines.
let s:out_remain_text = {}
let s:err_remain_text = {}
function! coc#task#start(id, opts)
if coc#task#running(a:id)
call coc#task#stop(a:id)
endif
let cmd = [a:opts['cmd']] + get(a:opts, 'args', [])
let cwd = get(a:opts, 'cwd', getcwd())
let env = get(a:opts, 'env', {})
" cmd args cwd pty
if s:is_vim
let options = {
\ 'cwd': cwd,
\ 'err_mode': 'nl',
\ 'out_mode': 'nl',
\ 'err_cb': {channel, message -> s:on_stderr(a:id, [message])},
\ 'out_cb': {channel, message -> s:on_stdout(a:id, [message])},
\ 'exit_cb': {channel, code -> s:on_exit(a:id, code)},
\ 'env': env,
\}
if has("patch-8.1.350")
let options['noblock'] = 1
endif
if get(a:opts, 'pty', 0)
let options['pty'] = 1
endif
let job = job_start(cmd, options)
let status = job_status(job)
if status !=# 'run'
echohl Error | echom 'Failed to start '.a:id.' task' | echohl None
return v:false
endif
let s:running_task[a:id] = job
else
let options = {
\ 'cwd': cwd,
\ 'on_stderr': {channel, msgs -> s:on_stderr(a:id, msgs)},
\ 'on_stdout': {channel, msgs -> s:on_stdout(a:id, msgs)},
\ 'on_exit': {channel, code -> s:on_exit(a:id, code)},
\ 'detach': get(a:opts, 'detach', 0),
\}
let original = {}
if !empty(env)
if has('nvim-0.5.0')
let options['env'] = env
elseif exists('*setenv') && exists('*getenv')
for key in keys(env)
let original[key] = getenv(key)
call setenv(key, env[key])
endfor
endif
endif
if get(a:opts, 'pty', 0)
let options['pty'] = 1
endif
let chan_id = jobstart(cmd, options)
if !empty(original)
for key in keys(original)
call setenv(key, original[key])
endfor
endif
if chan_id <= 0
echohl Error | echom 'Failed to start '.a:id.' task' | echohl None
return v:false
endif
let s:running_task[a:id] = chan_id
endif
return v:true
endfunction
function! coc#task#stop(id)
let job = get(s:running_task, a:id, v:null)
if !job | return | endif
if s:is_vim
call job_stop(job, 'term')
else
call jobstop(job)
endif
sleep 50m
let running = coc#task#running(a:id)
if running
echohl Error | echom 'job '.a:id. ' stop failed.' | echohl None
endif
endfunction
function! s:on_exit(id, code) abort
if get(g:, 'coc_vim_leaving', 0) | return | endif
if has('nvim')
let s:out_remain_text[a:id] = ''
let s:err_remain_text[a:id] = ''
endif
if has_key(s:running_task, a:id)
call remove(s:running_task, a:id)
endif
call coc#rpc#notify('TaskExit', [a:id, a:code])
endfunction
function! s:on_stderr(id, msgs)
if get(g:, 'coc_vim_leaving', 0) | return | endif
if empty(a:msgs)
return
endif
if s:is_vim
call coc#rpc#notify('TaskStderr', [a:id, a:msgs])
else
let remain = get(s:err_remain_text, a:id, '')
let eof = (a:msgs == [''])
let msgs = copy(a:msgs)
if len(remain) > 0
if msgs[0] == ''
let msgs[0] = remain
else
let msgs[0] = remain . msgs[0]
endif
endif
let last = msgs[len(msgs) - 1]
let s:err_remain_text[a:id] = len(last) > 0 ? last : ''
" all lines from 0 to n - 2
if len(msgs) > 1
call coc#rpc#notify('TaskStderr', [a:id, msgs[:len(msgs)-2]])
elseif eof && len(msgs[0]) > 0
call coc#rpc#notify('TaskStderr', [a:id, msgs])
endif
endif
endfunction
function! s:on_stdout(id, msgs)
if empty(a:msgs)
return
endif
if s:is_vim
call coc#rpc#notify('TaskStdout', [a:id, a:msgs])
else
let remain = get(s:out_remain_text, a:id, '')
let eof = (a:msgs == [''])
let msgs = copy(a:msgs)
if len(remain) > 0
if msgs[0] == ''
let msgs[0] = remain
else
let msgs[0] = remain . msgs[0]
endif
endif
let last = msgs[len(msgs) - 1]
let s:out_remain_text[a:id] = len(last) > 0 ? last : ''
" all lines from 0 to n - 2
if len(msgs) > 1
call coc#rpc#notify('TaskStdout', [a:id, msgs[:len(msgs)-2]])
elseif eof && len(msgs[0]) > 0
call coc#rpc#notify('TaskStdout', [a:id, msgs])
endif
endif
endfunction
function! coc#task#running(id)
if !has_key(s:running_task, a:id) == 1
return v:false
endif
let job = s:running_task[a:id]
if s:is_vim
let status = job_status(job)
return status ==# 'run'
endif
let [code] = jobwait([job], 10)
return code == -1
endfunction

View file

@ -0,0 +1,115 @@
scriptencoding utf-8
let s:is_vim = !has('nvim')
let s:channel_map = {}
let s:is_win = has('win32') || has('win64')
" start terminal, return [bufnr, pid]
function! coc#terminal#start(cmd, cwd, env, strict) abort
if s:is_vim && !has('terminal')
throw 'terminal feature not supported by current vim.'
endif
let cwd = empty(a:cwd) ? getcwd() : a:cwd
execute 'belowright '.get(g:, 'coc_terminal_height', 8).'new +setl\ buftype=nofile'
setl winfixheight
setl norelativenumber
setl nonumber
setl bufhidden=hide
if exists('#User#CocTerminalOpen')
exe 'doautocmd <nomodeline> User CocTerminalOpen'
endif
let bufnr = bufnr('%')
let env = {}
let original = {}
if !empty(a:env)
" use env option when possible
if s:is_vim
let env = copy(a:env)
elseif exists('*setenv')
for key in keys(a:env)
let original[key] = getenv(key)
call setenv(key, a:env[key])
endfor
endif
endif
function! s:OnExit(status) closure
call coc#rpc#notify('CocAutocmd', ['TermExit', bufnr, a:status])
if a:status == 0
execute 'silent! bd! '.bufnr
endif
endfunction
if has('nvim')
let job_id = termopen(a:cmd, {
\ 'cwd': cwd,
\ 'pty': v:true,
\ 'on_exit': {job, status -> s:OnExit(status)},
\ 'env': env,
\ 'clear_env': a:strict ? v:true : v:false
\ })
if !empty(original) && exists('*setenv')
for key in keys(original)
call setenv(key, original[key])
endfor
endif
if job_id == 0
throw 'create terminal job failed'
endif
wincmd p
let s:channel_map[bufnr] = job_id
return [bufnr, jobpid(job_id)]
else
let cmd = s:is_win ? join(a:cmd, ' ') : a:cmd
let res = term_start(cmd, {
\ 'cwd': cwd,
\ 'term_kill': s:is_win ? 'kill' : 'term',
\ 'term_finish': 'close',
\ 'exit_cb': {job, status -> s:OnExit(status)},
\ 'curwin': 1,
\ 'env': env,
\})
if res == 0
throw 'create terminal job failed'
endif
let job = term_getjob(bufnr)
let s:channel_map[bufnr] = job_getchannel(job)
wincmd p
return [bufnr, job_info(job).process]
endif
endfunction
function! coc#terminal#send(bufnr, text, add_new_line) abort
let chan = get(s:channel_map, a:bufnr, v:null)
if empty(chan) | return| endif
if has('nvim')
let lines = split(a:text, '\v\r?\n')
if a:add_new_line && !empty(lines[len(lines) - 1])
if s:is_win
call add(lines, "\r\n")
else
call add(lines, '')
endif
endif
call chansend(chan, lines)
let winid = bufwinid(a:bufnr)
if winid != -1
call coc#compat#execute(winid, 'noa normal! G')
endif
else
if !a:add_new_line
call ch_sendraw(chan, a:text)
else
call ch_sendraw(chan, a:text.(s:is_win ? "\r\n" : "\n"))
endif
endif
endfunction
function! coc#terminal#close(bufnr) abort
if has('nvim')
let job_id = get(s:channel_map, a:bufnr, 0)
if !empty(job_id)
silent! call chanclose(job_id)
endif
endif
exe 'silent! bd! '.a:bufnr
endfunction

View file

@ -0,0 +1,446 @@
let s:is_vim = !has('nvim')
let s:is_win = has('win32') || has('win64')
let s:is_mac = has('mac')
let s:sign_api = exists('*sign_getplaced') && exists('*sign_place')
let s:sign_groups = []
" Check <Tab> and <CR>
function! coc#ui#check_pum_keymappings() abort
let keys = []
for key in ['<cr>', '<tab>']
if maparg(key, 'i') =~# 'pumvisible()'
call add(keys, key)
endif
endfor
if len(keys)
let lines = [
\ 'coc.nvim switched to custom popup menu from 0.0.82',
\ 'you have to change key-mappings for '.join(keys, ', ').' to make them work.',
\ 'see :h coc-completion-example']
call coc#notify#create(lines, {
\ 'borderhighlight': 'CocInfoSign',
\ 'timeout': 30000,
\ 'kind': 'warning',
\ })
endif
endfunction
function! coc#ui#quickpick(title, items, cb) abort
if exists('*popup_menu')
function! s:QuickpickHandler(id, result) closure
call a:cb(v:null, a:result)
endfunction
function! s:QuickpickFilter(id, key) closure
for i in range(1, len(a:items))
if a:key == string(i)
call popup_close(a:id, i)
return 1
endif
endfor
" No shortcut, pass to generic filter
return popup_filter_menu(a:id, a:key)
endfunction
try
call popup_menu(a:items, {
\ 'title': a:title,
\ 'filter': function('s:QuickpickFilter'),
\ 'callback': function('s:QuickpickHandler'),
\ })
redraw
catch /.*/
call a:cb(v:exception)
endtry
else
let res = inputlist([a:title] + a:items)
call a:cb(v:null, res)
endif
endfunction
" cmd, cwd
function! coc#ui#open_terminal(opts) abort
if s:is_vim && !exists('*term_start')
echohl WarningMsg | echon "Your vim doesn't have terminal support!" | echohl None
return
endif
if get(a:opts, 'position', 'bottom') ==# 'bottom'
let p = '5new'
else
let p = 'vnew'
endif
execute 'belowright '.p.' +setl\ buftype=nofile '
setl buftype=nofile
setl winfixheight
setl norelativenumber
setl nonumber
setl bufhidden=wipe
if exists('#User#CocTerminalOpen')
exe 'doautocmd <nomodeline> User CocTerminalOpen'
endif
let cmd = get(a:opts, 'cmd', '')
let autoclose = get(a:opts, 'autoclose', 1)
if empty(cmd)
throw 'command required!'
endif
let cwd = get(a:opts, 'cwd', getcwd())
let keepfocus = get(a:opts, 'keepfocus', 0)
let bufnr = bufnr('%')
let Callback = get(a:opts, 'Callback', v:null)
function! s:OnExit(status) closure
let content = join(getbufline(bufnr, 1, '$'), "\n")
if a:status == 0 && autoclose == 1
execute 'silent! bd! '.bufnr
endif
if !empty(Callback)
call call(Callback, [a:status, bufnr, content])
endif
endfunction
if has('nvim')
call termopen(cmd, {
\ 'cwd': cwd,
\ 'on_exit': {job, status -> s:OnExit(status)},
\})
else
if s:is_win
let cmd = 'cmd.exe /C "'.cmd.'"'
endif
call term_start(cmd, {
\ 'cwd': cwd,
\ 'exit_cb': {job, status -> s:OnExit(status)},
\ 'curwin': 1,
\})
endif
if keepfocus
wincmd p
endif
return bufnr
endfunction
" run command in terminal
function! coc#ui#run_terminal(opts, cb)
let cmd = get(a:opts, 'cmd', '')
if empty(cmd)
return a:cb('command required for terminal')
endif
let opts = {
\ 'cmd': cmd,
\ 'cwd': get(a:opts, 'cwd', getcwd()),
\ 'keepfocus': get(a:opts, 'keepfocus', 0),
\ 'Callback': {status, bufnr, content -> a:cb(v:null, {'success': status == 0 ? v:true : v:false, 'bufnr': bufnr, 'content': content})}
\}
call coc#ui#open_terminal(opts)
endfunction
function! coc#ui#echo_hover(msg)
echohl MoreMsg
echo a:msg
echohl None
let g:coc_last_hover_message = a:msg
endfunction
function! coc#ui#echo_messages(hl, msgs)
if a:hl !~# 'Error' && (mode() !~# '\v^(i|n)$')
return
endif
let msgs = filter(copy(a:msgs), '!empty(v:val)')
if empty(msgs)
return
endif
execute 'echohl '.a:hl
echom a:msgs[0]
redraw
echo join(msgs, "\n")
echohl None
endfunction
function! coc#ui#preview_info(lines, filetype, ...) abort
pclose
keepalt new +setlocal\ previewwindow|setlocal\ buftype=nofile|setlocal\ noswapfile|setlocal\ wrap [Document]
setl bufhidden=wipe
setl nobuflisted
setl nospell
exe 'setl filetype='.a:filetype
setl conceallevel=0
setl nofoldenable
for command in a:000
execute command
endfor
call append(0, a:lines)
exe "normal! z" . len(a:lines) . "\<cr>"
exe "normal! gg"
wincmd p
endfunction
function! coc#ui#open_files(files)
let bufnrs = []
" added on latest vim8
if exists('*bufadd') && exists('*bufload')
for file in a:files
let file = fnamemodify(file, ':.')
if bufloaded(file)
call add(bufnrs, bufnr(file))
else
let bufnr = bufadd(file)
call bufload(file)
call add(bufnrs, bufnr)
call setbufvar(bufnr, '&buflisted', 1)
endif
endfor
else
noa keepalt 1new +setl\ bufhidden=wipe
for file in a:files
let file = fnamemodify(file, ':.')
execute 'noa edit +setl\ bufhidden=hide '.fnameescape(file)
if &filetype ==# ''
filetype detect
endif
call add(bufnrs, bufnr('%'))
endfor
noa close
endif
doautocmd BufEnter
return bufnrs
endfunction
function! coc#ui#echo_lines(lines)
echo join(a:lines, "\n")
endfunction
function! coc#ui#echo_signatures(signatures) abort
if pumvisible() | return | endif
echo ""
for i in range(len(a:signatures))
call s:echo_signature(a:signatures[i])
if i != len(a:signatures) - 1
echon "\n"
endif
endfor
endfunction
function! s:echo_signature(parts)
for part in a:parts
let hl = get(part, 'type', 'Normal')
let text = get(part, 'text', '')
if !empty(text)
execute 'echohl '.hl
execute "echon '".substitute(text, "'", "''", 'g')."'"
echohl None
endif
endfor
endfunction
function! coc#ui#iterm_open(dir)
return s:osascript(
\ 'if application "iTerm2" is not running',
\ 'error',
\ 'end if') && s:osascript(
\ 'tell application "iTerm2"',
\ 'tell current window',
\ 'create tab with default profile',
\ 'tell current session',
\ 'write text "cd ' . a:dir . '"',
\ 'write text "clear"',
\ 'activate',
\ 'end tell',
\ 'end tell',
\ 'end tell')
endfunction
function! s:osascript(...) abort
let args = join(map(copy(a:000), '" -e ".shellescape(v:val)'), '')
call s:system('osascript'. args)
return !v:shell_error
endfunction
function! s:system(cmd)
let output = system(a:cmd)
if v:shell_error && output !=# ""
echohl Error | echom output | echohl None
return
endif
return output
endfunction
function! coc#ui#set_lines(bufnr, changedtick, original, replacement, start, end, changes, cursor, col) abort
if !bufloaded(a:bufnr)
return
endif
let delta = 0
if !empty(a:col)
let delta = col('.') - a:col
endif
if getbufvar(a:bufnr, 'changedtick') > a:changedtick && bufnr('%') == a:bufnr
" try apply current line change
let lnum = line('.')
" change for current line
if a:end - a:start == 1 && a:end == lnum && len(a:replacement) == 1
let idx = a:start - lnum + 1
let previous = get(a:original, idx, 0)
if type(previous) == 1
let content = getline('.')
if previous !=# content
let diff = coc#string#diff(content, previous, col('.'))
let changed = get(a:replacement, idx, 0)
if type(changed) == 1 && strcharpart(previous, 0, diff['end']) ==# strcharpart(changed, 0, diff['end'])
let applied = coc#string#apply(changed, diff)
let replacement = copy(a:replacement)
let replacement[idx] = applied
call coc#compat#buf_set_lines(a:bufnr, a:start, a:end, replacement)
return
endif
endif
endif
endif
endif
if exists('*nvim_buf_set_text') && !empty(a:changes)
for item in reverse(copy(a:changes))
call nvim_buf_set_text(a:bufnr, item[1], item[2], item[3], item[4], item[0])
endfor
else
call coc#compat#buf_set_lines(a:bufnr, a:start, a:end, a:replacement)
endif
if !empty(a:cursor)
call cursor(a:cursor[0], a:cursor[1] + delta)
endif
endfunction
function! coc#ui#change_lines(bufnr, list) abort
if !bufloaded(a:bufnr) | return v:null | endif
undojoin
if exists('*setbufline')
for [lnum, line] in a:list
call setbufline(a:bufnr, lnum + 1, line)
endfor
elseif a:bufnr == bufnr('%')
for [lnum, line] in a:list
call setline(lnum + 1, line)
endfor
else
let bufnr = bufnr('%')
exe 'noa buffer '.a:bufnr
for [lnum, line] in a:list
call setline(lnum + 1, line)
endfor
exe 'noa buffer '.bufnr
endif
endfunction
function! coc#ui#open_url(url)
if has('mac') && executable('open')
call system('open '.a:url)
return
endif
if executable('xdg-open')
call system('xdg-open '.a:url)
return
endif
call system('cmd /c start "" /b '. substitute(a:url, '&', '^&', 'g'))
if v:shell_error
echohl Error | echom 'Failed to open '.a:url | echohl None
return
endif
endfunction
function! coc#ui#rename_file(oldPath, newPath, write) abort
let bufnr = bufnr(a:oldPath)
if bufnr == -1
throw 'Unable to get bufnr of '.a:oldPath
endif
if a:oldPath =~? a:newPath && (s:is_mac || s:is_win)
return coc#ui#safe_rename(bufnr, a:oldPath, a:newPath, a:write)
endif
if bufloaded(a:newPath)
execute 'silent bdelete! '.bufnr(a:newPath)
endif
let current = bufnr == bufnr('%')
let bufname = fnamemodify(a:newPath, ":~:.")
let filepath = fnamemodify(bufname(bufnr), '%:p')
let winid = coc#compat#buf_win_id(bufnr)
let curr = -1
if winid == -1
let curr = win_getid()
let file = fnamemodify(bufname(bufnr), ':.')
execute 'keepalt tab drop '.fnameescape(bufname(bufnr))
let winid = win_getid()
endif
call coc#compat#execute(winid, 'keepalt file '.fnameescape(bufname), 'silent')
call coc#compat#execute(winid, 'doautocmd BufEnter')
if a:write
call coc#compat#execute(winid, 'noa write!', 'silent')
call delete(filepath, '')
endif
if curr != -1
call win_gotoid(curr)
endif
return bufnr
endfunction
" System is case in sensitive and newPath have different case.
function! coc#ui#safe_rename(bufnr, oldPath, newPath, write) abort
let winid = win_getid()
let lines = getbufline(a:bufnr, 1, '$')
execute 'keepalt tab drop '.fnameescape(fnamemodify(a:oldPath, ':.'))
let view = winsaveview()
execute 'keepalt bwipeout! '.a:bufnr
if a:write
call delete(a:oldPath, '')
endif
execute 'keepalt edit '.fnameescape(fnamemodify(a:newPath, ':~:.'))
let bufnr = bufnr('%')
call coc#compat#buf_set_lines(bufnr, 0, -1, lines)
if a:write
execute 'noa write'
endif
call winrestview(view)
call win_gotoid(winid)
return bufnr
endfunction
function! coc#ui#sign_unplace() abort
if exists('*sign_unplace')
for group in s:sign_groups
call sign_unplace(group)
endfor
endif
endfunction
function! coc#ui#update_signs(bufnr, group, signs) abort
if !s:sign_api || !bufloaded(a:bufnr)
return
endif
if len(a:signs)
call add(s:sign_groups, a:group)
endif
let current = get(get(sign_getplaced(a:bufnr, {'group': a:group}), 0, {}), 'signs', [])
let exists = []
let unplaceList = []
for item in current
let index = 0
let placed = 0
for def in a:signs
if def['name'] ==# item['name'] && def['lnum'] == item['lnum']
let placed = 1
call add(exists, index)
break
endif
let index = index + 1
endfor
if !placed
call add(unplaceList, item['id'])
endif
endfor
for idx in range(0, len(a:signs) - 1)
if index(exists, idx) == -1
let def = a:signs[idx]
let opts = {'lnum': def['lnum']}
if has_key(def, 'priority')
let opts['priority'] = def['priority']
endif
call sign_place(0, a:group, def['name'], a:bufnr, opts)
endif
endfor
for id in unplaceList
call sign_unplace(a:group, {'buffer': a:bufnr, 'id': id})
endfor
endfunction

View file

@ -0,0 +1,625 @@
scriptencoding utf-8
let s:root = expand('<sfile>:h:h:h')
let s:is_win = has('win32') || has('win64')
let s:is_vim = !has('nvim')
let s:vim_api_version = 31
function! coc#util#remote_fns(name)
let fns = ['init', 'complete', 'should_complete', 'refresh', 'get_startcol', 'on_complete', 'on_enter']
let res = []
for fn in fns
if exists('*coc#source#'.a:name.'#'.fn)
call add(res, fn)
endif
endfor
return res
endfunction
function! coc#util#do_complete(name, opt, cb) abort
let handler = 'coc#source#'.a:name.'#complete'
let l:Cb = {res -> a:cb(v:null, res)}
let args = [a:opt, l:Cb]
call call(handler, args)
endfunction
function! coc#util#suggest_variables(bufnr) abort
return {
\ 'disable': getbufvar(a:bufnr, 'coc_suggest_disable', 0),
\ 'disabled_sources': getbufvar(a:bufnr, 'coc_disabled_sources', []),
\ 'blacklist': getbufvar(a:bufnr, 'coc_suggest_blacklist', []),
\ }
endfunction
function! coc#util#api_version() abort
return s:vim_api_version
endfunction
function! coc#util#semantic_hlgroups() abort
let res = split(execute('hi'), "\n")
let filtered = filter(res, "v:val =~# '^CocSem'")
return map(filtered, "matchstr(v:val,'\\v^CocSem\\w+')")
endfunction
" get cursor position
function! coc#util#cursor()
return [line('.') - 1, strchars(strpart(getline('.'), 0, col('.') - 1))]
endfunction
function! coc#util#change_info() abort
return {'lnum': line('.'), 'col': col('.'), 'line': getline('.'), 'changedtick': b:changedtick}
endfunction
function! coc#util#jumpTo(line, character) abort
echohl WarningMsg | echon 'coc#util#jumpTo is deprecated, use coc#cursor#move_to instead.' | echohl None
call coc#cursor#move_to(a:line, a:character)
endfunction
function! coc#util#root_patterns() abort
return coc#rpc#request('rootPatterns', [bufnr('%')])
endfunction
function! coc#util#get_config(key) abort
return coc#rpc#request('getConfig', [a:key])
endfunction
function! coc#util#open_terminal(opts) abort
return coc#ui#open_terminal(a:opts)
endfunction
function! coc#util#synname() abort
return synIDattr(synID(line('.'), col('.') - 1, 1), 'name')
endfunction
function! coc#util#setline(lnum, line)
keepjumps call setline(a:lnum, a:line)
endfunction
function! coc#util#path_replace_patterns() abort
if has('win32unix') && exists('g:coc_cygqwin_path_prefixes')
echohl WarningMsg
echon 'g:coc_cygqwin_path_prefixes is deprecated, use g:coc_uri_prefix_replace_patterns instead'
echohl None
return g:coc_cygqwin_path_prefixes
endif
if exists('g:coc_uri_prefix_replace_patterns')
return g:coc_uri_prefix_replace_patterns
endif
return v:null
endfunction
function! coc#util#version()
if s:is_vim
return string(v:versionlong)
endif
let c = execute('silent version')
let lines = split(matchstr(c, 'NVIM v\zs[^\n-]*'))
return lines[0]
endfunction
function! coc#util#check_refresh(bufnr)
if !bufloaded(a:bufnr)
return 0
endif
if getbufvar(a:bufnr, 'coc_diagnostic_disable', 0)
return 0
endif
if get(g: , 'EasyMotion_loaded', 0)
return EasyMotion#is_active() != 1
endif
return 1
endfunction
function! coc#util#diagnostic_info(bufnr, checkInsert) abort
let checked = coc#util#check_refresh(a:bufnr)
if !checked
return v:null
endif
if a:checkInsert && mode() =~# '^i'
return v:null
endif
let locationlist = ''
let winid = -1
for info in getwininfo()
if info['bufnr'] == a:bufnr
let winid = info['winid']
let locationlist = get(getloclist(winid, {'title': 1}), 'title', '')
break
endif
endfor
return {
\ 'bufnr': bufnr('%'),
\ 'winid': winid,
\ 'lnum': line('.'),
\ 'locationlist': locationlist
\ }
endfunction
function! coc#util#open_file(cmd, file)
execute a:cmd .' '.fnameescape(fnamemodify(a:file, ':~:.'))
return bufnr('%')
endfunction
function! coc#util#job_command()
if (has_key(g:, 'coc_node_path'))
let node = expand(g:coc_node_path)
else
let node = $COC_NODE_PATH == '' ? 'node' : $COC_NODE_PATH
endif
if !executable(node)
echohl Error | echom '[coc.nvim] "'.node.'" is not executable, checkout https://nodejs.org/en/download/' | echohl None
return
endif
if !filereadable(s:root.'/build/index.js')
if isdirectory(s:root.'/src')
echohl Error | echom '[coc.nvim] build/index.js not found, please install dependencies and compile coc.nvim by: yarn install' | echohl None
else
echohl Error | echon '[coc.nvim] your coc.nvim is broken.' | echohl None
endif
return
endif
return [node] + get(g:, 'coc_node_args', ['--no-warnings']) + [s:root.'/build/index.js']
endfunction
function! coc#util#jump(cmd, filepath, ...) abort
if a:cmd != 'pedit'
silent! normal! m'
endif
let path = a:filepath
if (has('win32unix'))
let path = substitute(a:filepath, '\v\\', '/', 'g')
endif
let file = fnamemodify(path, ":~:.")
if a:cmd == 'pedit'
let extra = empty(get(a:, 1, [])) ? '' : '+'.(a:1[0] + 1)
exe 'pedit '.extra.' '.fnameescape(file)
return
elseif a:cmd == 'drop' && exists('*bufadd')
let dstbuf = bufadd(path)
let binfo = getbufinfo(dstbuf)
if len(binfo) == 1 && empty(binfo[0].windows)
exec 'buffer '.dstbuf
let &buflisted = 1
else
exec 'drop '.fnameescape(file)
endif
elseif a:cmd == 'edit' && bufloaded(file)
exe 'b '.bufnr(file)
else
call s:safer_open(a:cmd, file)
endif
if !empty(get(a:, 1, []))
let line = getline(a:1[0] + 1)
" TODO need to use utf16 here
let col = byteidx(line, a:1[1]) + 1
if col == 0
let col = 999
endif
call cursor(a:1[0] + 1, col)
endif
if &filetype ==# ''
filetype detect
endif
if s:is_vim
redraw
endif
endfunction
function! s:safer_open(cmd, file) abort
" How to support :pedit and :drop?
let is_supported_cmd = index(["edit", "split", "vsplit", "tabe"], a:cmd) >= 0
" Use special handling only for URI.
let looks_like_uri = match(a:file, "^.*://") >= 0
if looks_like_uri && is_supported_cmd && has('win32') && exists('*bufadd')
" Workaround a bug for Win32 paths.
"
" reference:
" - https://github.com/vim/vim/issues/541
" - https://github.com/neoclide/coc-java/issues/82
" - https://github.com/vim-jp/issues/issues/6
let buf = bufadd(a:file)
if a:cmd != 'edit'
" Open split, tab, etc. by a:cmd.
exe a:cmd
endif
" Set current buffer to the file
exe 'keepjumps buffer ' . buf
else
exe a:cmd.' '.fnameescape(a:file)
endif
endfunction
function! coc#util#variables(bufnr) abort
let info = getbufinfo(a:bufnr)
let variables = empty(info) ? {} : copy(info[0]['variables'])
for key in keys(variables)
if key !~# '\v^coc'
unlet variables[key]
endif
endfor
return variables
endfunction
function! coc#util#with_callback(method, args, cb)
function! s:Cb() closure
try
let res = call(a:method, a:args)
call a:cb(v:null, res)
catch /.*/
call a:cb(v:exception)
endtry
endfunction
let timeout = s:is_vim ? 10 : 0
call timer_start(timeout, {-> s:Cb() })
endfunction
function! coc#util#timer(method, args)
call timer_start(0, { -> s:Call(a:method, a:args)})
endfunction
function! s:Call(method, args)
try
call call(a:method, a:args)
redraw
catch /.*/
return 0
endtry
endfunction
function! coc#util#vim_info()
return {
\ 'apiversion': s:vim_api_version,
\ 'mode': mode(),
\ 'config': get(g:, 'coc_user_config', {}),
\ 'floating': has('nvim') && exists('*nvim_open_win') ? v:true : v:false,
\ 'extensionRoot': coc#util#extension_root(),
\ 'globalExtensions': get(g:, 'coc_global_extensions', []),
\ 'lines': &lines,
\ 'columns': &columns,
\ 'cmdheight': &cmdheight,
\ 'pid': coc#util#getpid(),
\ 'filetypeMap': get(g:, 'coc_filetype_map', {}),
\ 'version': coc#util#version(),
\ 'completeOpt': &completeopt,
\ 'pumevent': 1,
\ 'isVim': has('nvim') ? v:false : v:true,
\ 'isCygwin': has('win32unix') ? v:true : v:false,
\ 'isMacvim': has('gui_macvim') ? v:true : v:false,
\ 'isiTerm': $TERM_PROGRAM ==# "iTerm.app",
\ 'colorscheme': get(g:, 'colors_name', ''),
\ 'workspaceFolders': get(g:, 'WorkspaceFolders', v:null),
\ 'background': &background,
\ 'runtimepath': join(globpath(&runtimepath, '', 0, 1), ','),
\ 'locationlist': get(g:,'coc_enable_locationlist', 1),
\ 'progpath': v:progpath,
\ 'guicursor': &guicursor,
\ 'pumwidth': exists('&pumwidth') ? &pumwidth : 15,
\ 'tabCount': tabpagenr('$'),
\ 'updateHighlight': has('nvim-0.5.0') || has('patch-8.1.1719') ? v:true : v:false,
\ 'vimCommands': get(g:, 'coc_vim_commands', []),
\ 'sign': exists('*sign_place') && exists('*sign_unplace'),
\ 'ambiguousIsNarrow': &ambiwidth ==# 'single' ? v:true : v:false,
\ 'textprop': has('textprop') && has('patch-8.1.1719') && !has('nvim') ? v:true : v:false,
\ 'dialog': has('nvim-0.4.0') || has('patch-8.2.0750') ? v:true : v:false,
\ 'semanticHighlights': coc#util#semantic_hlgroups()
\}
endfunction
function! coc#util#all_state()
return {
\ 'bufnr': bufnr('%'),
\ 'winid': win_getid(),
\ 'bufnrs': map(getbufinfo({'bufloaded': 1}),'v:val["bufnr"]'),
\ 'winids': map(getwininfo(),'v:val["winid"]'),
\ }
endfunction
function! coc#util#install() abort
let yarncmd = get(g:, 'coc_install_yarn_cmd', executable('yarnpkg') ? 'yarnpkg' : 'yarn')
call coc#ui#open_terminal({
\ 'cwd': s:root,
\ 'cmd': yarncmd.' install --frozen-lockfile --ignore-engines',
\ 'autoclose': 0,
\ })
endfunction
function! coc#util#extension_root() abort
if get(g:, 'coc_node_env', '') ==# 'test'
return s:root.'/src/__tests__/extensions'
endif
if !empty(get(g:, 'coc_extension_root', ''))
echohl Error | echon 'g:coc_extension_root not used any more, use g:coc_data_home instead' | echohl None
endif
return coc#util#get_data_home().'/extensions'
endfunction
function! coc#util#update_extensions(...) abort
let async = get(a:, 1, 0)
if async
call coc#rpc#notify('updateExtensions', [])
else
call coc#rpc#request('updateExtensions', [v:true])
endif
endfunction
function! coc#util#install_extension(args) abort
let names = filter(copy(a:args), 'v:val !~# "^-"')
let isRequest = index(a:args, '-sync') != -1
if isRequest
call coc#rpc#request('installExtensions', names)
else
call coc#rpc#notify('installExtensions', names)
endif
endfunction
function! coc#util#do_autocmd(name) abort
if exists('#User#'.a:name)
exe 'doautocmd <nomodeline> User '.a:name
endif
endfunction
function! coc#util#rebuild()
let dir = coc#util#extension_root()
if !isdirectory(dir) | return | endif
call coc#ui#open_terminal({
\ 'cwd': dir,
\ 'cmd': 'npm rebuild',
\ 'keepfocus': 1,
\})
endfunction
function! coc#util#unmap(bufnr, keys) abort
if bufnr('%') == a:bufnr
for key in a:keys
exe 'silent! nunmap <buffer> '.key
endfor
endif
endfunction
function! coc#util#refactor_foldlevel(lnum) abort
if a:lnum <= 2 | return 0 | endif
let line = getline(a:lnum)
if line =~# '^\%u3000\s*$' | return 0 | endif
return 1
endfunction
function! coc#util#refactor_fold_text(lnum) abort
let range = ''
let info = get(b:line_infos, a:lnum, [])
if !empty(info)
let range = info[0].':'.info[1]
endif
return trim(getline(a:lnum)[3:]).' '.range
endfunction
" get tabsize & expandtab option
function! coc#util#get_format_opts(bufnr) abort
let bufnr = a:bufnr && bufloaded(a:bufnr) ? a:bufnr : bufnr('%')
let tabsize = getbufvar(bufnr, '&shiftwidth')
if tabsize == 0
let tabsize = getbufvar(bufnr, '&tabstop')
endif
return {
\ 'tabsize': tabsize,
\ 'expandtab': getbufvar(bufnr, '&expandtab'),
\ 'insertFinalNewline': getbufvar(bufnr, '&eol'),
\ 'trimTrailingWhitespace': getbufvar(bufnr, 'coc_trim_trailing_whitespace', 0),
\ 'trimFinalNewlines': getbufvar(bufnr, 'coc_trim_final_newlines', 0)
\ }
endfunction
function! coc#util#get_editoroption(winid) abort
if !coc#compat#win_is_valid(a:winid)
return v:null
endif
if has('nvim') && exists('*nvim_win_get_config')
" avoid float window
let config = nvim_win_get_config(a:winid)
if !empty(get(config, 'relative', ''))
return v:null
endif
endif
let info = getwininfo(a:winid)[0]
let bufnr = info['bufnr']
let buftype = getbufvar(bufnr, '&buftype')
" avoid window for other purpose.
if buftype !=# '' && buftype !=# 'acwrite'
return v:null
endif
let tabSize = getbufvar(bufnr, '&shiftwidth')
if tabSize == 0
let tabSize = getbufvar(bufnr, '&tabstop')
endif
return {
\ 'bufnr': bufnr,
\ 'winid': a:winid,
\ 'winids': map(getwininfo(), 'v:val["winid"]'),
\ 'tabpagenr': info['tabnr'],
\ 'winnr': winnr(),
\ 'visibleRanges': s:visible_ranges(a:winid),
\ 'tabSize': tabSize,
\ 'insertSpaces': getbufvar(bufnr, '&expandtab') ? v:true : v:false
\ }
endfunction
function! coc#util#getpid()
if !has('win32unix')
return getpid()
endif
let cmd = 'cat /proc/' . getpid() . '/winpid'
return substitute(system(cmd), '\v\n', '', 'gi')
endfunction
" Get indentkeys for indent on TextChangedP, consider = for word indent only.
function! coc#util#get_indentkeys() abort
if empty(&indentexpr)
return ''
endif
if &indentkeys !~# '='
return ''
endif
return &indentkeys
endfunction
function! coc#util#get_bufoptions(bufnr) abort
if !bufloaded(a:bufnr) | return v:null | endif
let bufname = bufname(a:bufnr)
let buftype = getbufvar(a:bufnr, '&buftype')
let winid = bufwinid(a:bufnr)
let size = -1
if bufnr('%') == a:bufnr
let size = line2byte(line("$") + 1)
elseif !empty(bufname)
let size = getfsize(bufname)
endif
let lines = v:null
if getbufvar(a:bufnr, 'coc_enabled', 1) && (buftype == '' || buftype == 'acwrite') && size < get(g:, 'coc_max_filesize', 2097152)
let lines = getbufline(a:bufnr, 1, '$')
endif
return {
\ 'bufnr': a:bufnr,
\ 'size': size,
\ 'lines': lines,
\ 'winid': winid,
\ 'bufname': bufname,
\ 'buftype': buftype,
\ 'previewwindow': v:false,
\ 'eol': getbufvar(a:bufnr, '&eol'),
\ 'indentkeys': coc#util#get_indentkeys(),
\ 'variables': coc#util#variables(a:bufnr),
\ 'filetype': getbufvar(a:bufnr, '&filetype'),
\ 'iskeyword': getbufvar(a:bufnr, '&iskeyword'),
\ 'changedtick': getbufvar(a:bufnr, 'changedtick'),
\ 'fullpath': empty(bufname) ? '' : fnamemodify(bufname, ':p'),
\}
endfunction
function! coc#util#get_config_home()
if !empty(get(g:, 'coc_config_home', ''))
return resolve(expand(g:coc_config_home))
endif
if exists('$VIMCONFIG')
return resolve($VIMCONFIG)
endif
if has('nvim')
if exists('$XDG_CONFIG_HOME')
return resolve($XDG_CONFIG_HOME."/nvim")
endif
if s:is_win
return resolve($HOME.'/AppData/Local/nvim')
endif
return resolve($HOME.'/.config/nvim')
else
if s:is_win
return resolve($HOME."/vimfiles")
endif
return resolve($HOME.'/.vim')
endif
endfunction
function! coc#util#get_data_home()
if !empty(get(g:, 'coc_data_home', ''))
let dir = resolve(expand(g:coc_data_home))
else
if exists('$XDG_CONFIG_HOME')
let dir = resolve($XDG_CONFIG_HOME."/coc")
else
if s:is_win
let dir = resolve(expand('~/AppData/Local/coc'))
else
let dir = resolve(expand('~/.config/coc'))
endif
endif
endif
if !isdirectory(dir)
call coc#notify#create(['creating data directory: '.dir], {
\ 'borderhighlight': 'CocInfoSign',
\ 'timeout': 5000,
\ 'kind': 'info',
\ })
call mkdir(dir, "p", 0755)
endif
return dir
endfunction
function! coc#util#get_complete_option()
if get(b:,"coc_suggest_disable",0)
return v:null
endif
let pos = getcurpos()
let line = getline(pos[1])
let input = matchstr(strpart(line, 0, pos[2] - 1), '\k*$')
let col = pos[2] - strlen(input)
return {
\ 'word': matchstr(strpart(line, col - 1), '^\k\+'),
\ 'input': empty(input) ? '' : input,
\ 'line': line,
\ 'filetype': &filetype,
\ 'filepath': expand('%:p'),
\ 'bufnr': bufnr('%'),
\ 'linenr': pos[1],
\ 'colnr' : pos[2],
\ 'col': col - 1,
\ 'changedtick': b:changedtick,
\ 'blacklist': get(b:, 'coc_suggest_blacklist', []),
\ 'disabled': get(b:, 'coc_disabled_sources', []),
\ 'indentkeys': coc#util#get_indentkeys()
\}
endfunction
" used by vim
function! coc#util#get_buf_lines(bufnr, changedtick)
if !bufloaded(a:bufnr)
return v:null
endif
let changedtick = getbufvar(a:bufnr, 'changedtick')
if changedtick == a:changedtick
return v:null
endif
return {
\ 'lines': getbufline(a:bufnr, 1, '$'),
\ 'changedtick': getbufvar(a:bufnr, 'changedtick')
\ }
endfunction
" used for TextChangedI with InsertCharPre
function! coc#util#get_changeinfo()
return {
\ 'bufnr': bufnr('%'),
\ 'lnum': line('.'),
\ 'line': getline('.'),
\ 'changedtick': b:changedtick,
\}
endfunction
function! s:visible_ranges(winid) abort
let info = getwininfo(a:winid)[0]
let res = []
if !has_key(info, 'topline') || !has_key(info, 'botline')
return res
endif
let begin = 0
let curr = info['topline']
let max = info['botline']
if win_getid() != a:winid
return [[curr, max]]
endif
while curr <= max
let closedend = foldclosedend(curr)
if closedend == -1
let begin = begin == 0 ? curr : begin
if curr == max
call add(res, [begin, curr])
endif
let curr = curr + 1
else
if begin != 0
call add(res, [begin, curr - 1])
let begin = closedend + 1
endif
let curr = closedend + 1
endif
endwhile
return res
endfunction

View file

@ -0,0 +1,205 @@
let g:coc_max_treeview_width = get(g:, 'coc_max_treeview_width', 40)
let s:is_vim = !has('nvim')
" Get tabpagenr of winid, return -1 if window doesn't exist
function! coc#window#tabnr(winid) abort
if exists('*nvim_win_get_tabpage')
try
return nvim_win_get_tabpage(a:winid)
catch /Invalid window id/
return -1
endtry
endif
if exists('*win_execute')
let ref = {}
call win_execute(a:winid, 'let ref["out"] = tabpagenr()')
return get(ref, 'out', -1)
elseif !s:is_vim
let info = getwininfo(a:winid)
return empty(info) ? -1 : info[0]['tabnr']
else
throw 'win_execute() does not exist, please upgrade your vim.'
endif
endfunction
function! coc#window#get_cursor(winid) abort
if exists('*nvim_win_get_cursor')
return nvim_win_get_cursor(a:winid)
endif
return coc#api#exec('win_get_cursor', [a:winid])
endfunction
" Check if winid visible on current tabpage
function! coc#window#visible(winid) abort
if s:is_vim
if coc#window#tabnr(a:winid) != tabpagenr()
return 0
endif
" Check possible hidden popup
try
return get(popup_getpos(a:winid), 'visible', 0) == 1
catch /^Vim\%((\a\+)\)\=:E993/
return 1
endtry
endif
if !nvim_win_is_valid(a:winid)
return 0
endif
return coc#window#tabnr(a:winid) == tabpagenr()
endfunction
" Return v:null when name or window doesn't exist,
" 'getwinvar' only works on window of current tab
function! coc#window#get_var(winid, name, ...) abort
if !s:is_vim
try
if a:name =~# '^&'
return nvim_win_get_option(a:winid, a:name[1:])
else
return nvim_win_get_var(a:winid, a:name)
endif
catch /E5555/
return get(a:, 1, v:null)
endtry
else
try
return coc#api#exec('win_get_var', [a:winid, a:name, get(a:, 1, v:null)])
catch /.*/
return get(a:, 1, v:null)
endtry
endif
endfunction
" Not throw like setwinvar
function! coc#window#set_var(winid, name, value) abort
try
if !s:is_vim
if a:name =~# '^&'
call nvim_win_set_option(a:winid, a:name[1:], a:value)
else
call nvim_win_set_var(a:winid, a:name, a:value)
endif
else
call coc#api#exec('win_set_var', [a:winid, a:name, a:value])
endif
catch /Invalid window id/
" ignore
endtry
endfunction
function! coc#window#is_float(winid) abort
if s:is_vim
if exists('*popup_list')
return index(popup_list(), a:winid) != -1
else
try
return !empty(popup_getpos(a:winid))
catch /^Vim\%((\a\+)\)\=:E993/
return 0
endtry
endif
return 0
elseif exists('*nvim_win_get_config')
let config = nvim_win_get_config(a:winid)
return !empty(config) && !empty(get(config, 'relative', ''))
endif
endfunction
function! coc#window#set_height(winid, height) abort
if empty(getwininfo(a:winid))
return
endif
if exists('*nvim_win_set_height')
call nvim_win_set_height(a:winid, a:height)
else
call coc#compat#execute(a:winid, 'noa resize '.a:height, 'silent')
endif
endfunction
function! coc#window#adjust_width(winid) abort
let bufnr = winbufnr(a:winid)
if bufloaded(bufnr)
let maxwidth = 0
let lines = getbufline(bufnr, 1, '$')
if len(lines) > 2
call coc#compat#execute(a:winid, 'setl nowrap')
for line in lines
let w = strwidth(line)
if w > maxwidth
let maxwidth = w
endif
endfor
endif
if maxwidth > winwidth(a:winid)
call coc#compat#execute(a:winid, 'vertical resize '.min([maxwidth, g:coc_max_treeview_width]))
endif
endif
endfunction
" Get single window by window variable, current tab only
function! coc#window#find(key, val) abort
for i in range(1, winnr('$'))
let res = getwinvar(i, a:key)
if res == a:val
return win_getid(i)
endif
endfor
return -1
endfunction
" Visible buffer numbers
function! coc#window#bufnrs() abort
let winids = []
if exists('*nvim_list_wins')
let winids = nvim_list_wins()
else
let winids = map(getwininfo(), 'v:val["winid"]')
endif
return uniq(map(winids, 'winbufnr(v:val)'))
endfunction
" Avoid errors
function! coc#window#close(winid) abort
if empty(a:winid) || a:winid == -1
return
endif
if exists('*nvim_win_is_valid') && exists('*nvim_win_close')
if nvim_win_is_valid(a:winid)
call nvim_win_close(a:winid, 1)
endif
elseif exists('*win_execute')
call coc#compat#execute(a:winid, 'noa close!', 'silent!')
else
let curr = win_getid()
if curr == a:winid
silent! close!
else
let res = win_gotoid(a:winid)
if res
silent! close!
call win_gotoid(curr)
endif
endif
endif
endfunction
function! coc#window#visible_range(bufnr) abort
let winid = bufwinid(a:bufnr)
if winid == -1
return v:null
endif
let info = getwininfo(winid)[0]
return [info['topline'], info['botline']]
endfunction
function! coc#window#visible_ranges(bufnr) abort
let wins = gettabinfo(tabpagenr())[0]['windows']
let res = []
for id in wins
let info = getwininfo(id)[0]
if info['bufnr'] == a:bufnr
call add(res, [info['topline'], info['botline']])
endif
endfor
return res
endfunction

View file

@ -0,0 +1,100 @@
scriptencoding utf-8
let s:root = expand('<sfile>:h:h:h')
function! s:checkVim(test, name, patchlevel) abort
if a:test
if !has(a:patchlevel)
call health#report_error(a:name . ' version not satisfied, ' . a:patchlevel . ' and above required')
return 0
else
call health#report_ok(a:name . ' version satisfied')
return 1
endif
endif
return 0
endfunction
function! s:checkEnvironment() abort
let valid
\ = s:checkVim(has('nvim'), 'nvim', 'nvim-0.4.0')
\ + s:checkVim(!has('nvim'), 'vim', 'patch-8.1.1719')
let node = get(g:, 'coc_node_path', $COC_NODE_PATH == '' ? 'node' : $COC_NODE_PATH)
if !executable(node)
let valid = 0
call health#report_error('Executable node.js not found, install node.js from http://nodejs.org/')
endif
let output = system(node . ' --version')
if v:shell_error && output !=# ""
let valid = 0
call health#report_error(output)
endif
let ms = matchlist(output, 'v\(\d\+\).\(\d\+\).\(\d\+\)')
if empty(ms)
let valid = 0
call health#report_error('Unable to detect version of node, make sure your node executable is http://nodejs.org/')
elseif str2nr(ms[1]) < 12 || (str2nr(ms[1]) == 12 && str2nr(ms[2]) < 12)
let valid = 0
call health#report_warn('Node.js version '.trim(output).' < 12.12.0, please upgrade node.js')
endif
if valid
call health#report_ok('Environment check passed')
endif
if has('pythonx')
try
silent pyx print("")
catch /.*/
call health#report_warn('pyx command not work, some extensions may fail to work, checkout ":h pythonx"')
if has('nvim')
call health#report_warn('Install pynvim by command: pip install pynvim --upgrade')
endif
endtry
endif
return valid
endfunction
function! s:checkCommand()
let file = s:root.'/build/index.js'
if filereadable(file)
call health#report_ok('Javascript bundle build/index.js found')
else
call health#report_error('Javascript entry not found, please compile coc.nvim by esbuild.')
endif
endfunction
function! s:checkAutocmd()
let cmds = ['CursorHold', 'CursorHoldI', 'CursorMovedI', 'InsertCharPre', 'TextChangedI']
for cmd in cmds
let lines = split(execute('verbose autocmd '.cmd), '\n')
let n = 0
for line in lines
if line =~# 'CocAction(' && n < len(lines) - 1
let next = lines[n + 1]
let ms = matchlist(next, 'Last set from \(.*\)')
if !empty(ms)
call health#report_warn('Use CocActionAsync to replace CocAction for better performance on '.cmd)
call health#report_warn('Checkout the file '.ms[1])
endif
endif
let n = n + 1
endfor
endfor
endfunction
function! s:checkInitialize() abort
if coc#client#is_running('coc')
call health#report_ok('Service started')
return 1
endif
call health#report_error('service could not be initialized', [
\ 'Use command ":messages" to get error messages.',
\ 'Open a issue at https://github.com/neoclide/coc.nvim/issues for feedback.'
\])
return 0
endfunction
function! health#coc#check() abort
call s:checkEnvironment()
call s:checkCommand()
call s:checkInitialize()
call s:checkAutocmd()
endfunction

View file

@ -0,0 +1,97 @@
/*
* Used for prompt popup on vim
*/
const readline = require("readline")
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
escapeCodeTimeout: 0,
prompt: ''
})
rl.setPrompt('')
let value = process.argv[2]
if (value) {
rl.write(value)
}
rl.on('line', input => {
send(['confirm', input])
process.exit()
})
let original_ttyWrite = rl._ttyWrite
rl._ttyWrite = function (code, key) {
if (key.name === 'enter') {
send(['send', '<C-j>'])
return ''
}
original_ttyWrite.apply(rl, arguments)
send(['change', rl.line])
}
function createSequences(str) {
return '\033]51;' + str + '\x07'
}
function send(args) {
process.stdout.write(createSequences(JSON.stringify(['call', 'CocPopupCallback', args])))
}
process.stdin.on('keypress', (e, key) => {
if (key) {
let k = getKey(key)
if (k == '<bs>') {
return
}
if (k == '<esc>') {
send(['exit', ''])
process.exit()
return
}
if (k) {
send(['send', k])
return
}
}
})
function getKey(key) {
if (key.ctrl === true) {
if (key.name == 'n') {
return '<C-n>'
}
if (key.name == 'p') {
return '<C-p>'
}
if (key.name == 'j') {
return '<C-j>'
}
if (key.name == 'k') {
return '<C-k>'
}
if (key.name == 'f') {
return '<C-f>'
}
if (key.name == 'b') {
return '<C-b>'
}
if (key.sequence == '\x00') {
return '<C-@>'
}
}
if (key.sequence == '\u001b') {
return '<esc>'
}
if (key.sequence == '\r') {
return '<cr>'
}
if (key.sequence == '\t') {
return key.shift ? '<s-tab>' : '<tab>'
}
if (key.name == 'up') {
return '<up>'
}
if (key.name == 'down') {
return '<down>'
}
return ''
}

View file

@ -0,0 +1,12 @@
#!/bin/bash
terminateTree() {
for cpid in $(pgrep -P $1); do
terminateTree $cpid
done
kill -9 $1 > /dev/null 2>&1
}
for pid in $*; do
terminateTree $pid
done

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,17 @@
{
"name": "coc.nvim-release",
"version": "0.0.82",
"description": "LSP based intellisense engine for neovim & vim8.",
"engines": {
"node": ">=12.12.0"
},
"repository": {
"type": "git",
"url": "git+https://github.com/neoclide/coc.nvim.git"
},
"author": "Qiming Zhao <chemzqm@gmail.com>",
"bugs": {
"url": "https://github.com/neoclide/coc.nvim/issues"
},
"homepage": "https://github.com/neoclide/coc.nvim#readme"
}

View file

@ -0,0 +1,703 @@
scriptencoding utf-8
if exists('g:did_coc_loaded') || v:version < 800
finish
endif
function! s:checkVersion() abort
let l:unsupported = 0
if get(g:, 'coc_disable_startup_warning', 0) != 1
if has('nvim')
let l:unsupported = !has('nvim-0.4.0')
else
let l:unsupported = !has('patch-8.1.1719')
endif
if l:unsupported == 1
echohl Error
echom "coc.nvim requires at least Vim 8.1.1719 or Neovim 0.4.0, but you're using an older version."
echom "Please upgrade your (neo)vim."
echom "You can add this to your vimrc to avoid this message:"
echom " let g:coc_disable_startup_warning = 1"
echom "Note that some features may error out or behave incorrectly."
echom "Please do not report bugs unless you're using at least Vim 8.1.1719 or Neovim 0.4.0."
echohl None
sleep 2
else
if !has('nvim-0.5.0') && !has('patch-8.2.0750')
echohl WarningMsg
echom "coc.nvim works best on vim >= 8.2.0750 and neovim >= 0.5.0, consider upgrade your vim."
echom "You can add this to your vimrc to avoid this message:"
echom " let g:coc_disable_startup_warning = 1"
echom "Note that some features may behave incorrectly."
echohl None
sleep 2
endif
endif
endif
endfunction
call s:checkVersion()
let g:did_coc_loaded = 1
let g:coc_service_initialized = 0
let s:is_win = has('win32') || has('win64')
let s:root = expand('<sfile>:h:h')
let s:is_vim = !has('nvim')
let s:is_gvim = s:is_vim && has("gui_running")
if get(g:, 'coc_start_at_startup', 1) && !s:is_gvim
call coc#rpc#start_server()
endif
function! CocTagFunc(pattern, flags, info) abort
if a:flags !=# 'c'
" use standard tag search
return v:null
endif
return coc#rpc#request('getTagList', [])
endfunction
function! CocPopupCallback(bufnr, arglist) abort
if len(a:arglist) == 2
if a:arglist[0] == 'confirm'
call coc#rpc#notify('PromptInsert', [a:arglist[1], a:bufnr])
elseif a:arglist[0] == 'exit'
execute 'silent! bd! '.a:bufnr
"call coc#rpc#notify('PromptUpdate', [a:arglist[1]])
elseif a:arglist[0] == 'change'
let text = a:arglist[1]
let current = getbufvar(a:bufnr, 'current', '')
if text !=# current
call setbufvar(a:bufnr, 'current', text)
let cursor = term_getcursor(a:bufnr)
let info = {
\ 'lnum': cursor[0],
\ 'col': cursor[1],
\ 'line': text,
\ 'changedtick': 0
\ }
call coc#rpc#notify('CocAutocmd', ['TextChangedI', a:bufnr, info])
endif
elseif a:arglist[0] == 'send'
let key = a:arglist[1]
let escaped = strcharpart(key, 1, strchars(key) - 2)
call coc#rpc#notify('PromptKeyPress', [a:bufnr, escaped])
endif
endif
endfunction
function! CocAction(name, ...) abort
if !get(g:, 'coc_service_initialized', 0)
throw 'coc.nvim not ready when invoke CocAction "'.a:name.'"'
endif
return coc#rpc#request(a:name, a:000)
endfunction
function! CocHasProvider(name) abort
return coc#rpc#request('hasProvider', [a:name])
endfunction
function! CocActionAsync(name, ...) abort
return s:AsyncRequest(a:name, a:000)
endfunction
function! CocRequest(...) abort
return coc#rpc#request('sendRequest', a:000)
endfunction
function! CocNotify(...) abort
return coc#rpc#request('sendNotification', a:000)
endfunction
function! CocRegistNotification(id, method, cb) abort
call coc#on_notify(a:id, a:method, a:cb)
endfunction
function! CocLocations(id, method, ...) abort
let args = [a:id, a:method] + copy(a:000)
return coc#rpc#request('findLocations', args)
endfunction
function! CocLocationsAsync(id, method, ...) abort
let args = [a:id, a:method] + copy(a:000)
return s:AsyncRequest('findLocations', args)
endfunction
function! CocRequestAsync(...)
return s:AsyncRequest('sendRequest', a:000)
endfunction
function! s:AsyncRequest(name, args) abort
let Cb = empty(a:args)? v:null : a:args[len(a:args) - 1]
if type(Cb) == 2
if !coc#rpc#ready()
call Cb('service not started', v:null)
else
call coc#rpc#request_async(a:name, a:args[0:-2], Cb)
endif
return ''
endif
call coc#rpc#notify(a:name, a:args)
return ''
endfunction
function! s:CommandList(...) abort
let list = coc#rpc#request('commandList', a:000)
return join(list, "\n")
endfunction
function! s:ExtensionList(...) abort
let stats = CocAction('extensionStats')
call filter(stats, 'v:val["isLocal"] == v:false')
let list = map(stats, 'v:val["id"]')
return join(list, "\n")
endfunction
function! s:SearchOptions(...) abort
let list = ['-e', '--regexp', '-F', '--fixed-strings', '-L', '--follow',
\ '-g', '--glob', '--hidden', '--no-hidden', '--no-ignore-vcs',
\ '--word-regexp', '-w', '--smart-case', '-S', '--no-config',
\ '--line-regexp', '--no-ignore', '-x']
return join(list, "\n")
endfunction
function! s:LoadedExtensions(...) abort
let list = CocAction('loadedExtensions')
return join(list, "\n")
endfunction
function! s:InstallOptions(...)abort
let list = ['-terminal', '-sync']
return join(list, "\n")
endfunction
function! s:OpenConfig()
let home = coc#util#get_config_home()
if !isdirectory(home)
echohl MoreMsg
echom 'Config directory "'.home.'" does not exist, create? (y/n)'
echohl None
let confirm = nr2char(getchar())
redraw!
if !(confirm ==? "y" || confirm ==? "\r")
return
else
call mkdir(home, 'p')
end
endif
execute 'edit '.home.'/coc-settings.json'
call coc#rpc#notify('checkJsonExtension', [])
endfunction
function! s:get_color(item, fallback) abort
let t = type(a:item)
if t == 1
return a:item
endif
if t == 4
let item = get(a:item, 'gui', {})
let color = get(item, &background, a:fallback)
return type(color) == 1 ? color : a:fallback
endif
return a:fallback
endfunction
function! s:AddAnsiGroups() abort
let color_map = {}
let colors = ['#282828', '#cc241d', '#98971a', '#d79921', '#458588', '#b16286', '#689d6a', '#a89984', '#928374']
let names = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'grey']
for i in range(0, len(names) - 1)
let name = names[i]
if exists('g:terminal_ansi_colors')
let color_map[name] = s:get_color(get(g:terminal_ansi_colors, i, colors[i]), colors[i])
else
let color_map[name] = get(g:, 'terminal_color_'.i, colors[i])
endif
endfor
try
for name in keys(color_map)
let foreground = toupper(name[0]).name[1:]
let foregroundColor = color_map[name]
for key in keys(color_map)
let background = toupper(key[0]).key[1:]
let backgroundColor = color_map[key]
exe 'hi default CocList'.foreground.background.' guifg='.foregroundColor.' guibg='.backgroundColor
endfor
exe 'hi default CocListFg'.foreground. ' guifg='.foregroundColor. ' ctermfg='.foreground
exe 'hi default CocListBg'.foreground. ' guibg='.foregroundColor. ' ctermbg='.foreground
endfor
catch /.*/
" ignore invalid color
endtry
endfunction
function! s:CursorRangeFromSelected(type, ...) abort
" add range by operator
call coc#rpc#request('cursorsSelect', [bufnr('%'), 'operator', a:type])
endfunction
function! s:OpenDiagnostics(...) abort
let height = get(a:, 1, 0)
call coc#rpc#request('fillDiagnostics', [bufnr('%')])
if height
execute ':lopen '.height
else
lopen
endif
endfunction
function! s:Disable() abort
if get(g:, 'coc_enabled', 0) == 0
return
endif
augroup coc_nvim
autocmd!
augroup end
call coc#rpc#request('detach', [])
echohl MoreMsg
echom '[coc.nvim] Event disabled'
echohl None
let g:coc_enabled = 0
endfunction
function! s:Autocmd(...) abort
if !get(g:, 'coc_workspace_initialized', 0)
return
endif
call coc#rpc#notify('CocAutocmd', a:000)
endfunction
function! s:HandleCharInsert(char, bufnr) abort
if get(g:, 'coc_disable_space_report', 0)
let g:coc_disable_space_report = 0
if a:char ==# ' '
return
endif
endif
call s:Autocmd('InsertCharPre', a:char, a:bufnr)
endfunction
function! s:HandleWinScrolled(winid) abort
if getwinvar(a:winid, 'float', 0)
call coc#float#nvim_scrollbar(a:winid)
endif
call s:Autocmd('WinScrolled', a:winid)
endfunction
function! s:SyncAutocmd(...)
if !get(g:, 'coc_workspace_initialized', 0)
return
endif
call coc#rpc#request('CocAutocmd', a:000)
endfunction
function! s:Enable(initialize)
if get(g:, 'coc_enabled', 0) == 1
return
endif
let g:coc_enabled = 1
augroup coc_nvim
autocmd!
if coc#rpc#started()
autocmd VimEnter * call coc#rpc#notify('VimEnter', [])
elseif get(g:, 'coc_start_at_startup', 1)
autocmd VimEnter * call coc#rpc#start_server()
endif
if s:is_vim
if exists('##DirChanged')
autocmd DirChanged * call s:Autocmd('DirChanged', getcwd())
endif
if exists('##TerminalOpen')
autocmd TerminalOpen * call s:Autocmd('TermOpen', +expand('<abuf>'))
endif
else
autocmd DirChanged * call s:Autocmd('DirChanged', get(v:event, 'cwd', ''))
autocmd TermOpen * call s:Autocmd('TermOpen', +expand('<abuf>'))
autocmd WinEnter * call coc#float#nvim_win_enter(win_getid())
endif
autocmd CursorMoved list:///* call coc#list#select(bufnr('%'), line('.'))
if exists('##WinClosed')
autocmd WinClosed * call coc#float#on_close(+expand('<amatch>'))
autocmd WinClosed * call coc#notify#on_close(+expand('<amatch>'))
elseif exists('##TabEnter')
autocmd TabEnter * call coc#notify#reflow()
endif
if has('nvim-0.4.0') || has('patch-8.1.1719')
autocmd CursorHold * call coc#float#check_related()
endif
if exists('##WinScrolled')
autocmd WinScrolled * call s:HandleWinScrolled(+expand('<amatch>'))
endif
autocmd TabNew * call s:Autocmd('TabNew', tabpagenr())
autocmd TabClosed * call s:Autocmd('TabClosed', +expand('<afile>'))
autocmd WinLeave * call s:Autocmd('WinLeave', win_getid())
autocmd WinEnter * call s:Autocmd('WinEnter', win_getid())
autocmd BufWinLeave * call s:Autocmd('BufWinLeave', +expand('<abuf>'), bufwinid(+expand('<abuf>')))
autocmd BufWinEnter * call s:Autocmd('BufWinEnter', +expand('<abuf>'), win_getid())
autocmd FileType * call s:Autocmd('FileType', expand('<amatch>'), +expand('<abuf>'))
autocmd InsertCharPre * call s:HandleCharInsert(v:char, bufnr('%'))
if exists('##TextChangedP')
autocmd TextChangedP * call s:Autocmd('TextChangedP', +expand('<abuf>'), coc#util#change_info())
endif
autocmd TextChangedI * call s:Autocmd('TextChangedI', +expand('<abuf>'), coc#util#change_info())
autocmd InsertLeave * call s:Autocmd('InsertLeave', +expand('<abuf>'))
autocmd InsertEnter * call s:Autocmd('InsertEnter', +expand('<abuf>'))
autocmd BufHidden * call s:Autocmd('BufHidden', +expand('<abuf>'))
autocmd BufEnter * call s:Autocmd('BufEnter', +expand('<abuf>'))
autocmd TextChanged * call s:Autocmd('TextChanged', +expand('<abuf>'), getbufvar(+expand('<abuf>'), 'changedtick'))
autocmd BufWritePost * call s:Autocmd('BufWritePost', +expand('<abuf>'), getbufvar(+expand('<abuf>'), 'changedtick'))
autocmd CursorMoved * call s:Autocmd('CursorMoved', +expand('<abuf>'), [line('.'), col('.')])
autocmd CursorMovedI * call s:Autocmd('CursorMovedI', +expand('<abuf>'), [line('.'), col('.')])
autocmd CursorHold * call s:Autocmd('CursorHold', +expand('<abuf>'), [line('.'), col('.')])
autocmd CursorHoldI * call s:Autocmd('CursorHoldI', +expand('<abuf>'), [line('.'), col('.')])
autocmd BufNewFile,BufReadPost * call s:Autocmd('BufCreate', +expand('<abuf>'))
autocmd BufUnload * call s:Autocmd('BufUnload', +expand('<abuf>'))
autocmd BufWritePre * call s:SyncAutocmd('BufWritePre', +expand('<abuf>'), bufname(+expand('<abuf>')), getbufvar(+expand('<abuf>'), 'changedtick'))
autocmd FocusGained * if mode() !~# '^c' | call s:Autocmd('FocusGained') | endif
autocmd FocusLost * call s:Autocmd('FocusLost')
autocmd VimResized * call s:Autocmd('VimResized', &columns, &lines)
autocmd VimLeavePre * let g:coc_vim_leaving = 1
autocmd VimLeavePre * call s:Autocmd('VimLeavePre')
autocmd BufReadCmd,FileReadCmd,SourceCmd list://* call coc#list#setup(expand('<amatch>'))
autocmd BufWriteCmd __coc_refactor__* :call coc#rpc#notify('saveRefactor', [+expand('<abuf>')])
autocmd ColorScheme * call s:Hi()
augroup end
if a:initialize == 0
call coc#rpc#request('attach', [])
echohl MoreMsg
echom '[coc.nvim] Event enabled'
echohl None
endif
endfunction
function! s:FgColor(hlGroup) abort
let fgId = synIDtrans(hlID(a:hlGroup))
let ctermfg = synIDattr(fgId, 'reverse', 'cterm') ==# '1' ? synIDattr(fgId, 'bg', 'cterm') : synIDattr(fgId, 'fg', 'cterm')
let guifg = synIDattr(fgId, 'reverse', 'gui') ==# '1' ? synIDattr(fgId, 'bg', 'gui') : synIDattr(fgId, 'fg', 'gui')
let cmd = ' ctermfg=' . (empty(ctermfg) ? '223' : ctermfg)
let cmd .= ' guifg=' . (empty(guifg) ? '#ebdbb2' : guifg)
return cmd
endfunction
function! s:Hi() abort
hi default CocErrorSign ctermfg=Red guifg=#ff0000 guibg=NONE
hi default CocWarningSign ctermfg=Brown guifg=#ff922b guibg=NONE
hi default CocInfoSign ctermfg=Yellow guifg=#fab005 guibg=NONE
hi default CocHintSign ctermfg=Blue guifg=#15aabf guibg=NONE
hi default CocSelectedText ctermfg=Red guifg=#fb4934 guibg=NONE
hi default CocCodeLens ctermfg=Gray guifg=#999999 guibg=NONE
hi default CocUnderline term=underline cterm=underline gui=underline
hi default CocBold term=bold cterm=bold gui=bold
hi default CocItalic term=italic cterm=italic gui=italic
if s:is_vim || has('nvim-0.4.0')
hi default CocStrikeThrough term=strikethrough cterm=strikethrough gui=strikethrough
else
hi default CocStrikeThrough guifg=#989898 ctermfg=gray
endif
hi default CocMarkdownLink ctermfg=Blue guifg=#15aabf guibg=NONE
hi default CocDisabled guifg=#999999 ctermfg=gray
hi default CocSearch ctermfg=Blue guifg=#15aabf guibg=NONE
hi default link CocFadeOut Conceal
hi default link CocMarkdownCode markdownCode
hi default link CocMarkdownHeader markdownH1
hi default link CocMenuSel CursorLine
hi default link CocErrorFloat CocErrorSign
hi default link CocWarningFloat CocWarningSign
hi default link CocInfoFloat CocInfoSign
hi default link CocHintFloat CocHintSign
hi default link CocErrorHighlight CocUnderline
hi default link CocWarningHighlight CocUnderline
hi default link CocInfoHighlight CocUnderline
hi default link CocHintHighlight CocUnderline
hi default link CocDeprecatedHighlight CocStrikeThrough
hi default link CocUnusedHighlight CocFadeOut
hi default link CocListLine CursorLine
hi default link CocListSearch CocSearch
hi default link CocListMode ModeMsg
hi default link CocListPath Comment
hi default link CocHighlightText CursorColumn
hi default link CocHoverRange Search
hi default link CocCursorRange Search
hi default link CocLinkedEditing CocCursorRange
hi default link CocHighlightRead CocHighlightText
hi default link CocHighlightWrite CocHighlightText
hi default link CocInlayHint CocHintSign
" Notification
hi default CocNotificationProgress ctermfg=Blue guifg=#15aabf guibg=NONE
hi default link CocNotificationButton CocUnderline
hi default link CocNotificationError CocErrorFloat
hi default link CocNotificationWarning CocWarningFloat
hi default link CocNotificationInfo CocInfoFloat
" Snippet
hi default link CocSnippetVisual Visual
" Tree view highlights
hi default link CocTreeTitle Title
hi default link CocTreeDescription Comment
hi default link CocTreeOpenClose CocBold
hi default link CocTreeSelected CursorLine
hi default link CocSelectedRange CocHighlightText
" Symbol highlights
hi default link CocSymbolDefault MoreMsg
"Pum
hi default link CocPumSearch CocSearch
hi default link CocPumMenu Normal
hi default link CocPumShortcut Comment
hi default link CocPumDeprecated CocStrikeThrough
hi default CocPumVirtualText ctermfg=239 guifg=#504945
if has('nvim')
hi default link CocFloating NormalFloat
else
hi default link CocFloating Pmenu
endif
if !exists('*sign_getdefined') || empty(sign_getdefined('CocCurrentLine'))
sign define CocCurrentLine linehl=CocMenuSel
endif
if !exists('*sign_getdefined') || empty(sign_getdefined('CocListCurrent'))
sign define CocListCurrent linehl=CocListLine
endif
if !exists('*sign_getdefined') || empty(sign_getdefined('CocTreeSelected'))
sign define CocTreeSelected linehl=CocTreeSelected
endif
if has('nvim-0.5.0')
hi default CocCursorTransparent gui=strikethrough blend=100
endif
if has('nvim')
let names = ['Error', 'Warning', 'Info', 'Hint']
for name in names
if !hlexists('Coc'.name.'VirtualText')
let suffix = name ==# 'Warning' ? 'Warn' : name
if hlexists('DiagnosticVirtualText'.suffix)
exe 'hi default link Coc'.name.'VirtualText DiagnosticVirtualText'.suffix
else
exe 'hi default link Coc'.name.'VirtualText Coc'.name.'Sign'
endif
endif
endfor
endif
call s:AddAnsiGroups()
if get(g:, 'coc_default_semantic_highlight_groups', 1)
let hlMap = {
\ 'Namespace': ['TSNamespace', 'Include'],
\ 'Type': ['TSType', 'Type'],
\ 'Class': ['TSConstructor', 'Special'],
\ 'Enum': ['TSEnum', 'Type'],
\ 'Interface': ['TSInterface', 'Type'],
\ 'Struct': ['TSStruct', 'Identifier'],
\ 'TypeParameter': ['TSParameter', 'Identifier'],
\ 'Parameter': ['TSParameter', 'Identifier'],
\ 'Variable': ['TSSymbol', 'Identifier'],
\ 'Property': ['TSProperty', 'Identifier'],
\ 'EnumMember': ['TSEnumMember', 'Constant'],
\ 'Event': ['TSEvent', 'Keyword'],
\ 'Function': ['TSFunction', 'Function'],
\ 'Method': ['TSMethod', 'Function'],
\ 'Macro': ['TSConstMacro', 'Define'],
\ 'Keyword': ['TSKeyword', 'Keyword'],
\ 'Modifier': ['TSModifier', 'StorageClass'],
\ 'Comment': ['TSComment', 'Comment'],
\ 'String': ['TSString', 'String'],
\ 'Number': ['TSNumber', 'Number'],
\ 'Boolean': ['TSBoolean', 'Boolean'],
\ 'Regexp': ['TSStringRegex', 'String'],
\ 'Operator': ['TSOperator', 'Operator'],
\ 'Decorator': ['TSSymbol', 'Identifier'],
\ 'Deprecated': ['TSStrike', 'CocDeprecatedHighlight']
\ }
for [key, value] in items(hlMap)
let ts = get(value, 0, '')
let fallback = get(value, 1, '')
execute 'hi default link CocSem'.key.' '.(hlexists(ts) ? ts : fallback)
endfor
endif
let symbolMap = {
\ 'Keyword': ['TSKeyword', 'Keyword'],
\ 'Namespace': ['TSNamespace', 'Include'],
\ 'Class': ['TSConstructor', 'Special'],
\ 'Method': ['TSMethod', 'Function'],
\ 'Property': ['TSProperty', 'Identifier'],
\ 'Text': ['TSText', 'CocSymbolDefault'],
\ 'Unit': ['TSUnit', 'CocSymbolDefault'],
\ 'Value': ['TSValue', 'CocSymbolDefault'],
\ 'Snippet': ['TSSnippet', 'CocSymbolDefault'],
\ 'Color': ['TSColor', 'Float'],
\ 'Reference': ['TSTextReference', 'Constant'],
\ 'Folder': ['TSFolder', 'CocSymbolDefault'],
\ 'File': ['TSFile', 'Statement'],
\ 'Module': ['TSModule', 'Statement'],
\ 'Package': ['TSPackage', 'Statement'],
\ 'Field': ['TSField', 'Identifier'],
\ 'Constructor': ['TSConstructor', 'Special'],
\ 'Enum': ['TSEnum', 'CocSymbolDefault'],
\ 'Interface': ['TSInterface', 'CocSymbolDefault'],
\ 'Function': ['TSFunction', 'Function'],
\ 'Variable': ['TSVariableBuiltin', 'Special'],
\ 'Constant': ['TSConstant', 'Constant'],
\ 'String': ['TSString', 'String'],
\ 'Number': ['TSNumber', 'Number'],
\ 'Boolean': ['TSBoolean', 'Boolean'],
\ 'Array': ['TSArray', 'CocSymbolDefault'],
\ 'Object': ['TSObject', 'CocSymbolDefault'],
\ 'Key': ['TSKey', 'Identifier'],
\ 'Null': ['TSNull', 'Type'],
\ 'EnumMember': ['TSEnumMember', 'Identifier'],
\ 'Struct': ['TSStruct', 'Keyword'],
\ 'Event': ['TSEvent', 'Constant'],
\ 'Operator': ['TSOperator', 'Operator'],
\ 'TypeParameter': ['TSParameter', 'Identifier'],
\ }
for [key, value] in items(symbolMap)
let hlGroup = hlexists(value[0]) ? value[0] : get(value, 1, 'CocSymbolDefault')
if hlexists(hlGroup)
execute 'hi default CocSymbol'.key.' '.s:FgColor(hlGroup)
endif
endfor
endfunction
function! s:FormatFromSelected(type)
call CocActionAsync('formatSelected', a:type)
endfunction
function! s:CodeActionFromSelected(type)
call CocActionAsync('codeAction', a:type)
endfunction
function! s:ShowInfo()
if coc#rpc#ready()
call coc#rpc#notify('showInfo', [])
else
let lines = []
echomsg 'coc.nvim service not started, checking environment...'
let node = get(g:, 'coc_node_path', $COC_NODE_PATH == '' ? 'node' : $COC_NODE_PATH)
if !executable(node)
call add(lines, 'Error: '.node.' is not executable!')
else
let output = trim(system(node . ' --version'))
let ms = matchlist(output, 'v\(\d\+\).\(\d\+\).\(\d\+\)')
if empty(ms) || str2nr(ms[1]) < 12 || (str2nr(ms[1]) == 12 && str2nr(ms[2]) < 12)
call add(lines, 'Error: Node version '.output.' < 12.12.0, please upgrade node.js')
endif
endif
" check bundle
let file = s:root.'/build/index.js'
if !filereadable(file)
call add(lines, 'Error: javascript bundle not found, please compile code of coc.nvim by esbuild.')
endif
if !empty(lines)
botright vnew
setl filetype=nofile
call setline(1, lines)
else
if get(g:, 'coc_start_at_startup',1)
echohl MoreMsg | echon 'Service stopped for some unknown reason, try :CocStart' | echohl None
else
echohl MoreMsg | echon 'Start on startup is disabled, try :CocStart' | echohl None
endif
endif
endif
endfunction
command! -nargs=0 CocOutline :call coc#rpc#notify('showOutline', [])
command! -nargs=? CocDiagnostics :call s:OpenDiagnostics(<f-args>)
command! -nargs=0 CocInfo :call s:ShowInfo()
command! -nargs=0 CocOpenLog :call coc#rpc#notify('openLog', [])
command! -nargs=0 CocDisable :call s:Disable()
command! -nargs=0 CocEnable :call s:Enable(0)
command! -nargs=0 CocConfig :call s:OpenConfig()
command! -nargs=0 CocLocalConfig :call coc#rpc#notify('openLocalConfig', [])
command! -nargs=0 CocRestart :call coc#rpc#restart()
command! -nargs=0 CocStart :call coc#rpc#start_server()
command! -nargs=0 CocRebuild :call coc#util#rebuild()
command! -nargs=1 -complete=custom,s:LoadedExtensions CocWatch :call coc#rpc#notify('watchExtension', [<f-args>])
command! -nargs=+ -complete=custom,s:SearchOptions CocSearch :call coc#rpc#notify('search', [<f-args>])
command! -nargs=+ -complete=custom,s:ExtensionList CocUninstall :call CocActionAsync('uninstallExtension', <f-args>)
command! -nargs=* -complete=custom,s:CommandList -range CocCommand :call coc#rpc#notify('runCommand', [<f-args>])
command! -nargs=* -complete=custom,coc#list#options CocList :call coc#rpc#notify('openList', [<f-args>])
command! -nargs=? -complete=custom,coc#list#names CocListResume :call coc#rpc#notify('listResume', [<f-args>])
command! -nargs=? -complete=custom,coc#list#names CocListCancel :call coc#rpc#notify('listCancel', [])
command! -nargs=? -complete=custom,coc#list#names CocPrev :call coc#rpc#notify('listPrev', [<f-args>])
command! -nargs=? -complete=custom,coc#list#names CocNext :call coc#rpc#notify('listNext', [<f-args>])
command! -nargs=? -complete=custom,coc#list#names CocFirst :call coc#rpc#notify('listFirst', [<f-args>])
command! -nargs=? -complete=custom,coc#list#names CocLast :call coc#rpc#notify('listLast', [<f-args>])
command! -nargs=0 CocUpdate :call coc#util#update_extensions(1)
command! -nargs=0 -bar CocUpdateSync :call coc#util#update_extensions()
command! -nargs=* -bar -complete=custom,s:InstallOptions CocInstall :call coc#util#install_extension([<f-args>])
call s:Enable(1)
call s:Hi()
" Default key-mappings for completion
if empty(mapcheck("\<C-n>", 'i'))
inoremap <silent><expr> <C-n> coc#pum#visible() ? coc#pum#next(1) : "\<C-n>"
endif
if empty(mapcheck("\<C-p>", 'i'))
inoremap <silent><expr> <C-p> coc#pum#visible() ? coc#pum#prev(1) : "\<C-p>"
endif
if empty(mapcheck("\<down>", 'i'))
inoremap <silent><expr> <down> coc#pum#visible() ? coc#pum#next(0) : "\<down>"
endif
if empty(mapcheck("\<up>", 'i'))
inoremap <silent><expr> <up> coc#pum#visible() ? coc#pum#prev(0) : "\<up>"
endif
if empty(mapcheck("\<C-e>", 'i'))
inoremap <silent><expr> <C-e> coc#pum#visible() ? coc#pum#cancel() : "\<C-e>"
endif
if empty(mapcheck("\<C-y>", 'i'))
inoremap <silent><expr> <C-y> coc#pum#visible() ? coc#pum#confirm() : "\<C-y>"
endif
if empty(mapcheck("\<PageDown>", 'i'))
inoremap <silent><expr> <PageDown> coc#pum#visible() ? coc#pum#scroll(1) : "\<PageDown>"
endif
if empty(mapcheck("\<PageUp>", 'i'))
inoremap <silent><expr> <PageUp> coc#pum#visible() ? coc#pum#scroll(0) : "\<PageUp>"
endif
vnoremap <silent> <Plug>(coc-range-select) :<C-u>call CocActionAsync('rangeSelect', visualmode(), v:true)<CR>
vnoremap <silent> <Plug>(coc-range-select-backward) :<C-u>call CocActionAsync('rangeSelect', visualmode(), v:false)<CR>
nnoremap <Plug>(coc-range-select) :<C-u>call CocActionAsync('rangeSelect', '', v:true)<CR>
nnoremap <Plug>(coc-codelens-action) :<C-u>call CocActionAsync('codeLensAction')<CR>
vnoremap <silent> <Plug>(coc-format-selected) :<C-u>call CocActionAsync('formatSelected', visualmode())<CR>
vnoremap <silent> <Plug>(coc-codeaction-selected) :<C-u>call CocActionAsync('codeAction', visualmode())<CR>
nnoremap <Plug>(coc-codeaction-selected) :<C-u>set operatorfunc=<SID>CodeActionFromSelected<CR>g@
nnoremap <Plug>(coc-codeaction) :<C-u>call CocActionAsync('codeAction', '')<CR>
nnoremap <Plug>(coc-codeaction-line) :<C-u>call CocActionAsync('codeAction', 'line')<CR>
nnoremap <Plug>(coc-codeaction-cursor) :<C-u>call CocActionAsync('codeAction', 'cursor')<CR>
nnoremap <silent> <Plug>(coc-rename) :<C-u>call CocActionAsync('rename')<CR>
nnoremap <silent> <Plug>(coc-format-selected) :<C-u>set operatorfunc=<SID>FormatFromSelected<CR>g@
nnoremap <silent> <Plug>(coc-format) :<C-u>call CocActionAsync('format')<CR>
nnoremap <silent> <Plug>(coc-diagnostic-info) :<C-u>call CocActionAsync('diagnosticInfo')<CR>
nnoremap <silent> <Plug>(coc-diagnostic-next) :<C-u>call CocActionAsync('diagnosticNext')<CR>
nnoremap <silent> <Plug>(coc-diagnostic-prev) :<C-u>call CocActionAsync('diagnosticPrevious')<CR>
nnoremap <silent> <Plug>(coc-diagnostic-next-error) :<C-u>call CocActionAsync('diagnosticNext', 'error')<CR>
nnoremap <silent> <Plug>(coc-diagnostic-prev-error) :<C-u>call CocActionAsync('diagnosticPrevious', 'error')<CR>
nnoremap <silent> <Plug>(coc-definition) :<C-u>call CocActionAsync('jumpDefinition')<CR>
nnoremap <silent> <Plug>(coc-declaration) :<C-u>call CocActionAsync('jumpDeclaration')<CR>
nnoremap <silent> <Plug>(coc-implementation) :<C-u>call CocActionAsync('jumpImplementation')<CR>
nnoremap <silent> <Plug>(coc-type-definition) :<C-u>call CocActionAsync('jumpTypeDefinition')<CR>
nnoremap <silent> <Plug>(coc-references) :<C-u>call CocActionAsync('jumpReferences')<CR>
nnoremap <silent> <Plug>(coc-references-used) :<C-u>call CocActionAsync('jumpUsed')<CR>
nnoremap <silent> <Plug>(coc-openlink) :<C-u>call CocActionAsync('openLink')<CR>
nnoremap <silent> <Plug>(coc-fix-current) :<C-u>call CocActionAsync('doQuickfix')<CR>
nnoremap <silent> <Plug>(coc-float-hide) :<C-u>call coc#float#close_all()<CR>
nnoremap <silent> <Plug>(coc-float-jump) :<c-u>call coc#float#jump()<cr>
nnoremap <silent> <Plug>(coc-command-repeat) :<C-u>call CocAction('repeatCommand')<CR>
nnoremap <silent> <Plug>(coc-refactor) :<C-u>call CocActionAsync('refactor')<CR>
nnoremap <silent> <Plug>(coc-cursors-operator) :<C-u>set operatorfunc=<SID>CursorRangeFromSelected<CR>g@
vnoremap <silent> <Plug>(coc-cursors-range) :<C-u>call CocAction('cursorsSelect', bufnr('%'), 'range', visualmode())<CR>
nnoremap <silent> <Plug>(coc-cursors-word) :<C-u>call CocAction('cursorsSelect', bufnr('%'), 'word', 'n')<CR>
nnoremap <silent> <Plug>(coc-cursors-position) :<C-u>call CocAction('cursorsSelect', bufnr('%'), 'position', 'n')<CR>
vnoremap <silent> <Plug>(coc-funcobj-i) :<C-U>call CocAction('selectSymbolRange', v:true, visualmode(), ['Method', 'Function'])<CR>
vnoremap <silent> <Plug>(coc-funcobj-a) :<C-U>call CocAction('selectSymbolRange', v:false, visualmode(), ['Method', 'Function'])<CR>
onoremap <silent> <Plug>(coc-funcobj-i) :<C-U>call CocAction('selectSymbolRange', v:true, '', ['Method', 'Function'])<CR>
onoremap <silent> <Plug>(coc-funcobj-a) :<C-U>call CocAction('selectSymbolRange', v:false, '', ['Method', 'Function'])<CR>
vnoremap <silent> <Plug>(coc-classobj-i) :<C-U>call CocAction('selectSymbolRange', v:true, visualmode(), ['Interface', 'Struct', 'Class'])<CR>
vnoremap <silent> <Plug>(coc-classobj-a) :<C-U>call CocAction('selectSymbolRange', v:false, visualmode(), ['Interface', 'Struct', 'Class'])<CR>
onoremap <silent> <Plug>(coc-classobj-i) :<C-U>call CocAction('selectSymbolRange', v:true, '', ['Interface', 'Struct', 'Class'])<CR>
onoremap <silent> <Plug>(coc-classobj-a) :<C-U>call CocAction('selectSymbolRange', v:false, '', ['Interface', 'Struct', 'Class'])<CR>

1
vimrc
View file

@ -273,6 +273,7 @@ end
if has('nvim') if has('nvim')
set mouse=nv set mouse=nv
let g:coc_global_extensions=['coc-powershell']
end end
if has('patch-7.3.541') if has('patch-7.3.541')