feat: added vimrc, omz, gitconfigs, writing c script to switch between configs

This commit is contained in:
Emi Aline Boucly 2025-11-17 22:10:20 +01:00
parent eeb46bf2fd
commit 2552607472
4225 changed files with 461057 additions and 0 deletions

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,869 @@
<p align="center">
<a href="https://www.vim.org/scripts/script.php?script_id=5779">
<img alt="Logo" src="https://github.com/neoclide/coc.nvim/assets/251450/9c2bc011-35f0-4ef5-93ba-bc3f17e65bb7" height="240" />
</a>
<p align="center">Make your Vim/Neovim as smart as VS Code</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/actions/workflow/status/neoclide/coc.nvim/ci.yml?style=flat-square&branch=master"></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://matrix.to/#/#coc.nvim:matrix.org"><img alt="Matrix" src="https://img.shields.io/matrix/coc.nvim%3Amatrix.org?style=flat-square"></a>
<a href="https://deepwiki.com/neoclide/coc.nvim"><img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki"></a>
</p>
</p>
---
<img alt="Custom coc popup menu with snippet support" src="https://github.com/neoclide/coc.nvim/assets/251450/05f60ab8-dcb1-40f7-9e4a-3c03f5db5398" width="60%" />
_Custom popup menu with snippet support_
## Why?
- 🚀 **Fast**: separated NodeJS process that does not slow down Vim most of the time.
- 💎 **Reliable**: typed language, tested with CI.
- 🌟 **Featured**: all LSP 3.16 features are supported, see `:h coc-lsp`.
- ❤️ **Flexible**: [configured like VS Code](https://github.com/neoclide/coc.nvim/wiki/Using-the-configuration-file), [Coc extensions function similarly to VS Code extensions](https://github.com/neoclide/coc.nvim/wiki/Using-coc-extensions)
## Quick Start
Make sure use Vim >= 9.0.0438 or Neovim >= 0.8.0.
Install [nodejs](https://nodejs.org/en/download/) >= 16.18.0:
```bash
curl -sL install-node.vercel.app/lts | bash
```
For [vim-plug](https://github.com/junegunn/vim-plug) users:
```vim
" Use release branch (recommended)
Plug 'neoclide/coc.nvim', {'branch': 'release'}
" Or build from source code by using npm
Plug 'neoclide/coc.nvim', {'branch': 'master', 'do': 'npm ci'}
```
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 extensions or configure language servers for
LSP support.
Install extensions like this:
:CocInstall coc-json coc-tsserver
Or you can configure a language server in your `coc-settings.json`(open it using `:CocConfig`) like this:
```json
{
"languageserver": {
"go": {
"command": "gopls",
"rootPatterns": ["go.mod"],
"trace.server": "verbose",
"filetypes": ["go"]
}
}
}
```
Checkout the 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 can change your key mappings. Please use
command like`:verbose imap <tab>` to make sure that your keymap has taken effect.
```vim
" https://raw.githubusercontent.com/neoclide/coc.nvim/master/doc/coc-example-config.vim
" May need for Vim (not Neovim) since coc.nvim calculates byte offset by count
" utf-8 byte sequence
set encoding=utf-8
" Some servers have issues with backup files, see #649
set nobackup
set nowritebackup
" Having longer updatetime (default is 4000 ms = 4s) 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 tab for trigger completion with characters ahead and navigate
" NOTE: There's always complete item selected by default, you may want to enable
" no select by `"suggest.noselect": true` in your configuration file
" 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) :
\ CheckBackspace() ? "\<Tab>" :
\ coc#refresh()
inoremap <expr><S-TAB> coc#pum#visible() ? coc#pum#prev(1) : "\<C-h>"
" Make <CR> to accept selected completion item or notify coc.nvim to format
" <C-g>u breaks current undo, 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>"
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
" Use `[g` and `]g` to navigate diagnostics
" Use `:CocDiagnostics` to get all diagnostics of current buffer in location list
nmap <silent><nowait> [g <Plug>(coc-diagnostic-prev)
nmap <silent><nowait> ]g <Plug>(coc-diagnostic-next)
" GoTo code navigation
nmap <silent><nowait> gd <Plug>(coc-definition)
nmap <silent><nowait> gy <Plug>(coc-type-definition)
nmap <silent><nowait> gi <Plug>(coc-implementation)
nmap <silent><nowait> 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')
augroup end
" Applying code actions to the selected code block
" Example: `<leader>aap` for current paragraph
xmap <leader>a <Plug>(coc-codeaction-selected)
nmap <leader>a <Plug>(coc-codeaction-selected)
" Remap keys for applying code actions at the cursor position
nmap <leader>ac <Plug>(coc-codeaction-cursor)
" Remap keys for apply code actions affect whole buffer
nmap <leader>as <Plug>(coc-codeaction-source)
" Apply the most preferred quickfix action to fix diagnostic on the current line
nmap <leader>qf <Plug>(coc-fix-current)
" Remap keys for applying refactor code actions
nmap <silent> <leader>re <Plug>(coc-codeaction-refactor)
xmap <silent> <leader>r <Plug>(coc-codeaction-refactor-selected)
nmap <silent> <leader>r <Plug>(coc-codeaction-refactor-selected)
" 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> to 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>
```
## Example Lua configuration
NOTE: This only works in Neovim 0.7.0dev+.
```lua
-- https://raw.githubusercontent.com/neoclide/coc.nvim/master/doc/coc-example-config.lua
-- Some servers have issues with backup files, see #649
vim.opt.backup = false
vim.opt.writebackup = false
-- Having longer updatetime (default is 4000 ms = 4s) leads to noticeable
-- delays and poor user experience
vim.opt.updatetime = 300
-- Always show the signcolumn, otherwise it would shift the text each time
-- diagnostics appeared/became resolved
vim.opt.signcolumn = "yes"
local keyset = vim.keymap.set
-- Autocomplete
function _G.check_back_space()
local col = vim.fn.col('.') - 1
return col == 0 or vim.fn.getline('.'):sub(col, col):match('%s') ~= nil
end
-- Use Tab for trigger completion with characters ahead and navigate
-- NOTE: There's always a completion item selected by default, you may want to enable
-- no select by setting `"suggest.noselect": true` in your configuration file
-- NOTE: Use command ':verbose imap <tab>' to make sure Tab is not mapped by
-- other plugins before putting this into your config
local opts = {silent = true, noremap = true, expr = true, replace_keycodes = false}
keyset("i", "<TAB>", 'coc#pum#visible() ? coc#pum#next(1) : v:lua.check_back_space() ? "<TAB>" : coc#refresh()', opts)
keyset("i", "<S-TAB>", [[coc#pum#visible() ? coc#pum#prev(1) : "\<C-h>"]], opts)
-- Make <CR> to accept selected completion item or notify coc.nvim to format
-- <C-g>u breaks current undo, please make your own choice
keyset("i", "<cr>", [[coc#pum#visible() ? coc#pum#confirm() : "\<C-g>u\<CR>\<c-r>=coc#on_enter()\<CR>"]], opts)
-- Use <c-j> to trigger snippets
keyset("i", "<c-j>", "<Plug>(coc-snippets-expand-jump)")
-- Use <c-space> to trigger completion
keyset("i", "<c-space>", "coc#refresh()", {silent = true, expr = true})
-- Use `[g` and `]g` to navigate diagnostics
-- Use `:CocDiagnostics` to get all diagnostics of current buffer in location list
keyset("n", "[g", "<Plug>(coc-diagnostic-prev)", {silent = true})
keyset("n", "]g", "<Plug>(coc-diagnostic-next)", {silent = true})
-- GoTo code navigation
keyset("n", "gd", "<Plug>(coc-definition)", {silent = true})
keyset("n", "gy", "<Plug>(coc-type-definition)", {silent = true})
keyset("n", "gi", "<Plug>(coc-implementation)", {silent = true})
keyset("n", "gr", "<Plug>(coc-references)", {silent = true})
-- Use K to show documentation in preview window
function _G.show_docs()
local cw = vim.fn.expand('<cword>')
if vim.fn.index({'vim', 'help'}, vim.bo.filetype) >= 0 then
vim.api.nvim_command('h ' .. cw)
elseif vim.api.nvim_eval('coc#rpc#ready()') then
vim.fn.CocActionAsync('doHover')
else
vim.api.nvim_command('!' .. vim.o.keywordprg .. ' ' .. cw)
end
end
keyset("n", "K", '<CMD>lua _G.show_docs()<CR>', {silent = true})
-- Highlight the symbol and its references on a CursorHold event(cursor is idle)
vim.api.nvim_create_augroup("CocGroup", {})
vim.api.nvim_create_autocmd("CursorHold", {
group = "CocGroup",
command = "silent call CocActionAsync('highlight')",
desc = "Highlight symbol under cursor on CursorHold"
})
-- Symbol renaming
keyset("n", "<leader>rn", "<Plug>(coc-rename)", {silent = true})
-- Formatting selected code
keyset("x", "<leader>f", "<Plug>(coc-format-selected)", {silent = true})
keyset("n", "<leader>f", "<Plug>(coc-format-selected)", {silent = true})
-- Setup formatexpr specified filetype(s)
vim.api.nvim_create_autocmd("FileType", {
group = "CocGroup",
pattern = "typescript,json",
command = "setl formatexpr=CocAction('formatSelected')",
desc = "Setup formatexpr specified filetype(s)."
})
-- Apply codeAction to the selected region
-- Example: `<leader>aap` for current paragraph
local opts = {silent = true, nowait = true}
keyset("x", "<leader>a", "<Plug>(coc-codeaction-selected)", opts)
keyset("n", "<leader>a", "<Plug>(coc-codeaction-selected)", opts)
-- Remap keys for apply code actions at the cursor position.
keyset("n", "<leader>ac", "<Plug>(coc-codeaction-cursor)", opts)
-- Remap keys for apply source code actions for current file.
keyset("n", "<leader>as", "<Plug>(coc-codeaction-source)", opts)
-- Apply the most preferred quickfix action on the current line.
keyset("n", "<leader>qf", "<Plug>(coc-fix-current)", opts)
-- Remap keys for apply refactor code actions.
keyset("n", "<leader>re", "<Plug>(coc-codeaction-refactor)", { silent = true })
keyset("x", "<leader>r", "<Plug>(coc-codeaction-refactor-selected)", { silent = true })
keyset("n", "<leader>r", "<Plug>(coc-codeaction-refactor-selected)", { silent = true })
-- Run the Code Lens actions on the current line
keyset("n", "<leader>cl", "<Plug>(coc-codelens-action)", opts)
-- Map function and class text objects
-- NOTE: Requires 'textDocument.documentSymbol' support from the language server
keyset("x", "if", "<Plug>(coc-funcobj-i)", opts)
keyset("o", "if", "<Plug>(coc-funcobj-i)", opts)
keyset("x", "af", "<Plug>(coc-funcobj-a)", opts)
keyset("o", "af", "<Plug>(coc-funcobj-a)", opts)
keyset("x", "ic", "<Plug>(coc-classobj-i)", opts)
keyset("o", "ic", "<Plug>(coc-classobj-i)", opts)
keyset("x", "ac", "<Plug>(coc-classobj-a)", opts)
keyset("o", "ac", "<Plug>(coc-classobj-a)", opts)
-- Remap <C-f> and <C-b> to scroll float windows/popups
---@diagnostic disable-next-line: redefined-local
local opts = {silent = true, nowait = true, expr = true}
keyset("n", "<C-f>", 'coc#float#has_scroll() ? coc#float#scroll(1) : "<C-f>"', opts)
keyset("n", "<C-b>", 'coc#float#has_scroll() ? coc#float#scroll(0) : "<C-b>"', opts)
keyset("i", "<C-f>",
'coc#float#has_scroll() ? "<c-r>=coc#float#scroll(1)<cr>" : "<Right>"', opts)
keyset("i", "<C-b>",
'coc#float#has_scroll() ? "<c-r>=coc#float#scroll(0)<cr>" : "<Left>"', opts)
keyset("v", "<C-f>", 'coc#float#has_scroll() ? coc#float#scroll(1) : "<C-f>"', opts)
keyset("v", "<C-b>", 'coc#float#has_scroll() ? coc#float#scroll(0) : "<C-b>"', opts)
-- Use CTRL-S for selections ranges
-- Requires 'textDocument/selectionRange' support of language server
keyset("n", "<C-s>", "<Plug>(coc-range-select)", {silent = true})
keyset("x", "<C-s>", "<Plug>(coc-range-select)", {silent = true})
-- Add `:Format` command to format current buffer
vim.api.nvim_create_user_command("Format", "call CocAction('format')", {})
-- " Add `:Fold` command to fold current buffer
vim.api.nvim_create_user_command("Fold", "call CocAction('fold', <f-args>)", {nargs = '?'})
-- Add `:OR` command for organize imports of the current buffer
vim.api.nvim_create_user_command("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
vim.opt.statusline:prepend("%{coc#status()}%{get(b:,'coc_current_function','')}")
-- Mappings for CoCList
-- code actions and coc stuff
---@diagnostic disable-next-line: redefined-local
local opts = {silent = true, nowait = true}
-- Show all diagnostics
keyset("n", "<space>a", ":<C-u>CocList diagnostics<cr>", opts)
-- Manage extensions
keyset("n", "<space>e", ":<C-u>CocList extensions<cr>", opts)
-- Show commands
keyset("n", "<space>c", ":<C-u>CocList commands<cr>", opts)
-- Find symbol of current document
keyset("n", "<space>o", ":<C-u>CocList outline<cr>", opts)
-- Search workspace symbols
keyset("n", "<space>s", ":<C-u>CocList -I symbols<cr>", opts)
-- Do default action for next item
keyset("n", "<space>j", ":<C-u>CocNext<cr>", opts)
-- Do default action for previous item
keyset("n", "<space>k", ":<C-u>CocPrev<cr>", opts)
-- Resume latest coc list
keyset("n", "<space>p", ":<C-u>CocListResume<cr>", opts)
```
## 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 if you experience problems with coc.nvim:
- Ensure your Vim version >= 8.0 using `:version`
- If a service failed to start, use `:CocInfo` or `:checkhealth` if you use Neovim
- Checkout the log of coc.nvim with `:CocOpenLog`
- If you have issues with the language server, it's recommended to [checkout
the language server output](https://github.com/neoclide/coc.nvim/wiki/Debug-language-server#using-output-channel)
## Feedback
- Have a question? Start a discussion on [GitHub Discussions](https://github.com/neoclide/coc.nvim/discussions).
- File a bug in [GitHub Issues](https://github.com/neoclide/coc.nvim/issues).
- Chat with us on [Matrix](https://matrix.to/#/#coc.nvim:matrix.org).
- 中文用户请到 [中文 Matrix](https://matrix.to/#/#neoclide_coc-cn:gitter.im) 讨论
## 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/46/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/46/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/47/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/47/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/48/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/48/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/cocnvim/backer/49/website?requireActive=false" target="_blank"><img src="https://opencollective.com/cocnvim/backer/49/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>
<tbody>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/chemzqm"><img src="https://avatars.githubusercontent.com/u/251450?v=4?s=50" width="50px;" alt="Qiming zhao"/><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" valign="top" width="14.28%"><a href="https://fann.im/"><img src="https://avatars.githubusercontent.com/u/345274?v=4?s=50" width="50px;" alt="Heyward Fann"/><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" valign="top" width="14.28%"><a href="https://github.com/weirongxu"><img src="https://avatars.githubusercontent.com/u/1709861?v=4?s=50" width="50px;" alt="Raidou"/><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" valign="top" width="14.28%"><a href="https://github.com/kevinhwang91"><img src="https://avatars.githubusercontent.com/u/17562139?v=4?s=50" width="50px;" alt="kevinhwang91"/><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" valign="top" width="14.28%"><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" valign="top" width="14.28%"><a href="https://github.com/Avi-D-coder"><img src="https://avatars.githubusercontent.com/u/29133776?v=4?s=50" width="50px;" alt="Avi Dessauer"/><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" valign="top" width="14.28%"><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" valign="top" width="14.28%"><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="Yatao Li"/><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" valign="top" width="14.28%"><a href="https://github.com/xiyaowong"><img src="https://avatars.githubusercontent.com/u/47070852?v=4?s=50" width="50px;" alt="wongxy"/><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" valign="top" width="14.28%"><a href="https://github.com/sam-mccall"><img src="https://avatars.githubusercontent.com/u/548993?v=4?s=50" width="50px;" alt="Sam McCall"/><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" valign="top" width="14.28%"><a href="https://samroeca.com/pages/about.html#about"><img src="https://avatars.githubusercontent.com/u/3723671?v=4?s=50" width="50px;" alt="Samuel Roeca"/><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" valign="top" width="14.28%"><a href="https://github.com/amiralies"><img src="https://avatars.githubusercontent.com/u/13261088?v=4?s=50" width="50px;" alt="Amirali Esmaeili"/><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" valign="top" width="14.28%"><a href="https://bit.ly/3cLKGE4"><img src="https://avatars.githubusercontent.com/u/3051781?v=4?s=50" width="50px;" alt="Jack Rowlingson"/><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" valign="top" width="14.28%"><a href="https://github.com/tomtomjhj"><img src="https://avatars.githubusercontent.com/u/19489738?v=4?s=50" width="50px;" alt="Jaehwang Jung"/><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" valign="top" width="14.28%"><a href="https://github.com/antoinemadec"><img src="https://avatars.githubusercontent.com/u/10830594?v=4?s=50" width="50px;" alt="Antoine"/><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" valign="top" width="14.28%"><a href="https://github.com/cosminadrianpopescu"><img src="https://avatars.githubusercontent.com/u/5187873?v=4?s=50" width="50px;" alt="Cosmin Popescu"/><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" valign="top" width="14.28%"><a href="https://ducnx.com/"><img src="https://avatars.githubusercontent.com/u/1186411?v=4?s=50" width="50px;" alt="Duc Nghiem Xuan"/><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" valign="top" width="14.28%"><a href="https://nosubstance.me/"><img src="https://avatars.githubusercontent.com/u/1269815?v=4?s=50" width="50px;" alt="Francisco Lopes"/><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" valign="top" width="14.28%"><a href="https://github.com/daquexian"><img src="https://avatars.githubusercontent.com/u/11607199?v=4?s=50" width="50px;" alt="daquexian"/><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" valign="top" width="14.28%"><a href="https://github.com/apps/dependabot"><img src="https://avatars.githubusercontent.com/in/29110?v=4?s=50" width="50px;" alt="dependabot[bot]"/><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" valign="top" width="14.28%"><a href="https://github.com/apps/greenkeeper"><img src="https://avatars.githubusercontent.com/in/505?v=4?s=50" width="50px;" alt="greenkeeper[bot]"/><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" valign="top" width="14.28%"><a href="https://chris-kipp.io/"><img src="https://avatars.githubusercontent.com/u/13974112?v=4?s=50" width="50px;" alt="Chris Kipp"/><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" valign="top" width="14.28%"><a href="https://dmitmel.github.io/"><img src="https://avatars.githubusercontent.com/u/15367354?v=4?s=50" width="50px;" alt="Dmytro Meleshko"/><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" valign="top" width="14.28%"><a href="https://github.com/kirillbobyrev"><img src="https://avatars.githubusercontent.com/u/3352968?v=4?s=50" width="50px;" alt="Kirill Bobyrev"/><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" valign="top" width="14.28%"><a href="https://github.com/gbcreation"><img src="https://avatars.githubusercontent.com/u/454315?v=4?s=50" width="50px;" alt="Gontran Baerts"/><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" valign="top" width="14.28%"><a href="https://andys8.de/"><img src="https://avatars.githubusercontent.com/u/13085980?v=4?s=50" width="50px;" alt="Andy"/><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" valign="top" width="14.28%"><a href="https://www.alexcj96.com/"><img src="https://avatars.githubusercontent.com/u/33961674?v=4?s=50" width="50px;" alt="Cheng JIANG"/><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" valign="top" width="14.28%"><a href="https://github.com/cpearce-py"><img src="https://avatars.githubusercontent.com/u/53532946?v=4?s=50" width="50px;" alt="Corin"/><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" valign="top" width="14.28%"><a href="https://github.com/wodesuck"><img src="https://avatars.githubusercontent.com/u/3124581?v=4?s=50" width="50px;" alt="Daniel Zhang"/><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" valign="top" width="14.28%"><a href="https://github.com/Ferdi265"><img src="https://avatars.githubusercontent.com/u/4077106?v=4?s=50" width="50px;" alt="Ferdinand Bachmann"/><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" valign="top" width="14.28%"><a href="https://goushi.me/"><img src="https://avatars.githubusercontent.com/u/16915589?v=4?s=50" width="50px;" alt="Guangqing Chen"/><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" valign="top" width="14.28%"><a href="http://jademeskill.com/"><img src="https://avatars.githubusercontent.com/u/2108?v=4?s=50" width="50px;" alt="Jade Meskill"/><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" valign="top" width="14.28%"><a href="https://github.com/jpoppe"><img src="https://avatars.githubusercontent.com/u/65505?v=4?s=50" width="50px;" alt="Jasper Poppe"/><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" valign="top" width="14.28%"><a href="https://github.com/jean"><img src="https://avatars.githubusercontent.com/u/84800?v=4?s=50" width="50px;" alt="Jean Jordaan"/><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" valign="top" width="14.28%"><a href="https://xuann.wang/"><img src="https://avatars.githubusercontent.com/u/44045911?v=4?s=50" width="50px;" alt="Kid"/><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" valign="top" width="14.28%"><a href="https://github.com/Kavantix"><img src="https://avatars.githubusercontent.com/u/6243755?v=4?s=50" width="50px;" alt="Pieter van Loon"/><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" valign="top" width="14.28%"><a href="https://github.com/rliebz"><img src="https://avatars.githubusercontent.com/u/5321575?v=4?s=50" width="50px;" alt="Robert Liebowitz"/><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" valign="top" width="14.28%"><a href="https://megalithic.io/"><img src="https://avatars.githubusercontent.com/u/3678?v=4?s=50" width="50px;" alt="Seth Messer"/><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" valign="top" width="14.28%"><a href="https://github.com/UncleBill"><img src="https://avatars.githubusercontent.com/u/1141198?v=4?s=50" width="50px;" alt="UncleBill"/><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" valign="top" width="14.28%"><a href="http://zsaber.com/"><img src="https://avatars.githubusercontent.com/u/6846867?v=4?s=50" width="50px;" alt="ZERO"/><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" valign="top" width="14.28%"><a href="https://fsouza.blog/"><img src="https://avatars.githubusercontent.com/u/108725?v=4?s=50" width="50px;" alt="fsouza"/><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" valign="top" width="14.28%"><a href="https://onichandame.com/"><img src="https://avatars.githubusercontent.com/u/23728505?v=4?s=50" width="50px;" alt="XiaoZhang"/><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" valign="top" width="14.28%"><a href="https://github.com/whyreal"><img src="https://avatars.githubusercontent.com/u/2084642?v=4?s=50" width="50px;" alt="whyreal"/><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" valign="top" width="14.28%"><a href="https://github.com/yehuohan"><img src="https://avatars.githubusercontent.com/u/17680752?v=4?s=50" width="50px;" alt="yehuohan"/><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" valign="top" width="14.28%"><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" valign="top" width="14.28%"><a href="https://blog.gopherhub.org/"><img src="https://avatars.githubusercontent.com/u/41671631?v=4?s=50" width="50px;" alt="Raphael"/><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" valign="top" width="14.28%"><a href="https://tbodt.com/"><img src="https://avatars.githubusercontent.com/u/5678977?v=4?s=50" width="50px;" alt="tbodt"/><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" valign="top" width="14.28%"><a href="https://aaronmcdaid.github.io/"><img src="https://avatars.githubusercontent.com/u/64350?v=4?s=50" width="50px;" alt="Aaron McDaid"/><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" valign="top" width="14.28%"><a href="https://github.com/versi786"><img src="https://avatars.githubusercontent.com/u/7347942?v=4?s=50" width="50px;" alt="Aasif Versi"/><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" valign="top" width="14.28%"><a href="https://github.com/abnerf"><img src="https://avatars.githubusercontent.com/u/56300?v=4?s=50" width="50px;" alt="Abner Silva"/><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" valign="top" width="14.28%"><a href="http://sheerun.net/"><img src="https://avatars.githubusercontent.com/u/292365?v=4?s=50" width="50px;" alt="Adam Stankiewicz"/><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" valign="top" width="14.28%"><a href="https://wirow.io/"><img src="https://avatars.githubusercontent.com/u/496683?v=4?s=50" width="50px;" alt="Adamansky Anton"/><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" valign="top" width="14.28%"><a href="https://gabri.me/"><img src="https://avatars.githubusercontent.com/u/63876?v=4?s=50" width="50px;" alt="Ahmed El Gabri"/><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" valign="top" width="14.28%"><a href="http://theg4sh.ru/"><img src="https://avatars.githubusercontent.com/u/5094691?v=4?s=50" width="50px;" alt="Alexandr Kondratev"/><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" valign="top" width="14.28%"><a href="https://github.com/andrewkshim"><img src="https://avatars.githubusercontent.com/u/1403410?v=4?s=50" width="50px;" alt="Andrew Shim"/><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" valign="top" width="14.28%"><a href="http://andylindeman.com/"><img src="https://avatars.githubusercontent.com/u/395621?v=4?s=50" width="50px;" alt="Andy Lindeman"/><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" valign="top" width="14.28%"><a href="https://github.com/Augustin82"><img src="https://avatars.githubusercontent.com/u/2370810?v=4?s=50" width="50px;" alt="Augustin"/><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" valign="top" width="14.28%"><a href="https://bananium.fr/"><img src="https://avatars.githubusercontent.com/u/3650385?v=4?s=50" width="50px;" alt="Bastien Orivel"/><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" valign="top" width="14.28%"><a href="https://github.com/ayroblu"><img src="https://avatars.githubusercontent.com/u/4915682?v=4?s=50" width="50px;" alt="Ben Lu"/><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" valign="top" width="14.28%"><a href="https://github.com/vantreeseba"><img src="https://avatars.githubusercontent.com/u/316782?v=4?s=50" width="50px;" alt="Ben"/><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" valign="top" width="14.28%"><a href="https://github.com/bmon"><img src="https://avatars.githubusercontent.com/u/2115272?v=4?s=50" width="50px;" alt="Brendan Roy"/><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" valign="top" width="14.28%"><a href="https://github.com/brianembry"><img src="https://avatars.githubusercontent.com/u/35347666?v=4?s=50" width="50px;" alt="brianembry"/><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" valign="top" width="14.28%"><a href="https://keybase.io/bri_"><img src="https://avatars.githubusercontent.com/u/284789?v=4?s=50" width="50px;" alt="br"/><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" valign="top" width="14.28%"><a href="https://github.com/casonadams"><img src="https://avatars.githubusercontent.com/u/17597548?v=4?s=50" width="50px;" alt="Cason Adams"/><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" valign="top" width="14.28%"><a href="https://github.com/y9c"><img src="https://avatars.githubusercontent.com/u/5415510?v=4?s=50" width="50px;" alt="Chang Y"/><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" valign="top" width="14.28%"><a href="https://yous.be/"><img src="https://avatars.githubusercontent.com/u/853977?v=4?s=50" width="50px;" alt="Chayoung You"/><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" valign="top" width="14.28%"><a href="https://github.com/chenlijun99"><img src="https://avatars.githubusercontent.com/u/20483759?v=4?s=50" width="50px;" alt="Chen Lijun"/><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" valign="top" width="14.28%"><a href="https://github.com/beeender"><img src="https://avatars.githubusercontent.com/u/449296?v=4?s=50" width="50px;" alt="Chen Mulong"/><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" valign="top" width="14.28%"><a href="http://weyl.io/"><img src="https://avatars.githubusercontent.com/u/59620?v=4?s=50" width="50px;" alt="Chris Weyl"/><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" valign="top" width="14.28%"><a href="https://github.com/dezza"><img src="https://avatars.githubusercontent.com/u/402927?v=4?s=50" width="50px;" alt="dezza"/><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" valign="top" width="14.28%"><a href="https://github.com/ceedubs"><img src="https://avatars.githubusercontent.com/u/977929?v=4?s=50" width="50px;" alt="Cody Allen"/><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" valign="top" width="14.28%"><a href="https://www.25.wf/"><img src="https://avatars.githubusercontent.com/u/145502?v=4?s=50" width="50px;" alt="Damien Rajon"/><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" valign="top" width="14.28%"><a href="https://github.com/daern91"><img src="https://avatars.githubusercontent.com/u/6084427?v=4?s=50" width="50px;" alt="Daniel Eriksson"/><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" valign="top" width="14.28%"><a href="https://github.com/danjenson"><img src="https://avatars.githubusercontent.com/u/4793438?v=4?s=50" width="50px;" alt="Daniel Jenson"/><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" valign="top" width="14.28%"><a href="https://github.com/davidmh"><img src="https://avatars.githubusercontent.com/u/594302?v=4?s=50" width="50px;" alt="David Mejorado"/><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" valign="top" width="14.28%"><a href="https://github.com/pderichai"><img src="https://avatars.githubusercontent.com/u/13430946?v=4?s=50" width="50px;" alt="Deric Pang"/><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" valign="top" width="14.28%"><a href="https://www.dingtao.org/blog"><img src="https://avatars.githubusercontent.com/u/12852587?v=4?s=50" width="50px;" alt="Ding Tao"/><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" valign="top" width="14.28%"><a href="https://github.com/doronbehar"><img src="https://avatars.githubusercontent.com/u/10998835?v=4?s=50" width="50px;" alt="Doron Behar"/><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" valign="top" width="14.28%"><a href="https://github.com/kovetskiy"><img src="https://avatars.githubusercontent.com/u/8445924?v=4?s=50" width="50px;" alt="Egor Kovetskiy"/><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" valign="top" width="14.28%"><a href="https://github.com/elkowar"><img src="https://avatars.githubusercontent.com/u/5300871?v=4?s=50" width="50px;" alt="ElKowar"/><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" valign="top" width="14.28%"><a href="https://github.com/demelev"><img src="https://avatars.githubusercontent.com/u/3952209?v=4?s=50" width="50px;" alt="Emeliov Dmitrii"/><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" valign="top" width="14.28%"><a href="https://github.com/sawmurai"><img src="https://avatars.githubusercontent.com/u/6454986?v=4?s=50" width="50px;" alt="Fabian Becker"/><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" valign="top" width="14.28%"><a href="https://github.com/FallenWarrior2k"><img src="https://avatars.githubusercontent.com/u/20320149?v=4?s=50" width="50px;" alt="FallenWarrior2k"/><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" valign="top" width="14.28%"><a href="https://fnune.com/"><img src="https://avatars.githubusercontent.com/u/16181067?v=4?s=50" width="50px;" alt="Fausto Núñez Alberro"/><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" valign="top" width="14.28%"><a href="https://github.com/FelipeCRamos"><img src="https://avatars.githubusercontent.com/u/7572843?v=4?s=50" width="50px;" alt="Felipe Ramos"/><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" valign="top" width="14.28%"><a href="https://github.com/frbor"><img src="https://avatars.githubusercontent.com/u/2320183?v=4?s=50" width="50px;" alt="Fredrik Borg"/><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" valign="top" width="14.28%"><a href="http://www.gavinsim.co.uk/"><img src="https://avatars.githubusercontent.com/u/812273?v=4?s=50" width="50px;" alt="Gavin Sim"/><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" valign="top" width="14.28%"><a href="https://fahn.co/"><img src="https://avatars.githubusercontent.com/u/15943089?v=4?s=50" width="50px;" alt="Gibson Fahnestock"/><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" valign="top" width="14.28%"><a href="https://github.com/giovannigiordano"><img src="https://avatars.githubusercontent.com/u/15145952?v=4?s=50" width="50px;" alt="Giovanni Giordano"/><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" valign="top" width="14.28%"><a href="https://github.com/qubbit"><img src="https://avatars.githubusercontent.com/u/1987473?v=4?s=50" width="50px;" alt="Gopal Adhikari"/><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" valign="top" width="14.28%"><a href="https://github.com/hanh090"><img src="https://avatars.githubusercontent.com/u/3643657?v=4?s=50" width="50px;" alt="Hanh Le"/><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" valign="top" width="14.28%"><a href="https://github.com/hedyhli"><img src="https://avatars.githubusercontent.com/u/50042066?v=4?s=50" width="50px;" alt="hedy"/><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" valign="top" width="14.28%"><a href="https://www.hendriklammers.com/"><img src="https://avatars.githubusercontent.com/u/754556?v=4?s=50" width="50px;" alt="Hendrik Lammers"/><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" valign="top" width="14.28%"><a href="https://github.com/henrybarreto"><img src="https://avatars.githubusercontent.com/u/23109089?v=4?s=50" width="50px;" alt="Henry Barreto"/><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" valign="top" width="14.28%"><a href="https://hugo.barrera.io/"><img src="https://avatars.githubusercontent.com/u/730811?v=4?s=50" width="50px;" alt="Hugo"/><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" valign="top" width="14.28%"><a href="https://github.com/jackieli-tes"><img src="https://avatars.githubusercontent.com/u/64778297?v=4?s=50" width="50px;" alt="Jackie Li"/><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" valign="top" width="14.28%"><a href="https://github.com/MrQubo"><img src="https://avatars.githubusercontent.com/u/16545322?v=4?s=50" width="50px;" alt="Jakub Nowak"/><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" valign="top" width="14.28%"><a href="https://github.com/euoia"><img src="https://avatars.githubusercontent.com/u/1271216?v=4?s=50" width="50px;" alt="James Pickard"/><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" valign="top" width="14.28%"><a href="https://github.com/jsfaint"><img src="https://avatars.githubusercontent.com/u/571829?v=4?s=50" width="50px;" alt="Jia Sui"/><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" valign="top" width="14.28%"><a href="https://github.com/expipiplus1"><img src="https://avatars.githubusercontent.com/u/857308?v=4?s=50" width="50px;" alt="Ellie Hermaszewska"/><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" valign="top" width="14.28%"><a href="https://cincodenada.com/"><img src="https://avatars.githubusercontent.com/u/479715?v=4?s=50" width="50px;" alt="Joel Bradshaw"/><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" valign="top" width="14.28%"><a href="https://github.com/irizwaririz"><img src="https://avatars.githubusercontent.com/u/10111643?v=4?s=50" width="50px;" alt="John Carlo Roberto"/><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" valign="top" width="14.28%"><a href="https://github.com/Jomik"><img src="https://avatars.githubusercontent.com/u/699655?v=4?s=50" width="50px;" alt="Jonas Holst Damtoft"/><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" valign="top" width="14.28%"><a href="http://inlehmansterms.net/"><img src="https://avatars.githubusercontent.com/u/3144695?v=4?s=50" width="50px;" alt="Jonathan Lehman"/><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" valign="top" width="14.28%"><a href="https://joosep.xyz/"><img src="https://avatars.githubusercontent.com/u/9450943?v=4?s=50" width="50px;" alt="Joosep Alviste"/><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" valign="top" width="14.28%"><a href="https://github.com/josa42"><img src="https://avatars.githubusercontent.com/u/423234?v=4?s=50" width="50px;" alt="Josa Gesell"/><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" valign="top" width="14.28%"><a href="https://jawa.dev/"><img src="https://avatars.githubusercontent.com/u/194275?v=4?s=50" width="50px;" alt="Joshua Rubin"/><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" valign="top" width="14.28%"><a href="https://github.com/perrin4869"><img src="https://avatars.githubusercontent.com/u/5774716?v=4?s=50" width="50px;" alt="Julian Grinblat"/><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" valign="top" width="14.28%"><a href="https://valentjn.github.io/"><img src="https://avatars.githubusercontent.com/u/19839841?v=4?s=50" width="50px;" alt="Julian Valentin"/><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" valign="top" width="14.28%"><a href="https://kabbamine.github.io/"><img src="https://avatars.githubusercontent.com/u/5658084?v=4?s=50" width="50px;" alt="KabbAmine"/><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" valign="top" width="14.28%"><a href="https://moncargo.io/"><img src="https://avatars.githubusercontent.com/u/10719495?v=4?s=50" width="50px;" alt="Kay Gosho"/><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" valign="top" width="14.28%"><a href="https://kennyvh.com/"><img src="https://avatars.githubusercontent.com/u/29909203?v=4?s=50" width="50px;" alt="Kenny Huynh"/><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" valign="top" width="14.28%"><a href="https://github.com/kevinrambaud"><img src="https://avatars.githubusercontent.com/u/7501477?v=4?s=50" width="50px;" alt="Kevin Rambaud"/><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" valign="top" width="14.28%"><a href="https://github.com/kiancross"><img src="https://avatars.githubusercontent.com/u/11011464?v=4?s=50" width="50px;" alt="Kian Cross"/><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" valign="top" width="14.28%"><a href="https://ko-fi.com/kristijanhusak"><img src="https://avatars.githubusercontent.com/u/1782860?v=4?s=50" width="50px;" alt="Kristijan Husak"/><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" valign="top" width="14.28%"><a href="https://github.com/NullVoxPopuli"><img src="https://avatars.githubusercontent.com/u/199018?v=4?s=50" width="50px;" alt="NullVoxPopuli"/><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" valign="top" width="14.28%"><a href="https://github.com/lassepe"><img src="https://avatars.githubusercontent.com/u/10076790?v=4?s=50" width="50px;" alt="Lasse Peters"/><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" valign="top" width="14.28%"><a href="https://github.com/Linerre"><img src="https://avatars.githubusercontent.com/u/49512984?v=4?s=50" width="50px;" alt="Noel Errenil"/><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" valign="top" width="14.28%"><a href="https://github.com/LinArcX"><img src="https://avatars.githubusercontent.com/u/10884422?v=4?s=50" width="50px;" alt="LinArcX"/><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" valign="top" width="14.28%"><a href="https://paypal.me/liuchengxu"><img src="https://avatars.githubusercontent.com/u/8850248?v=4?s=50" width="50px;" alt="Liu-Cheng Xu"/><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" valign="top" width="14.28%"><a href="https://malloc.me/"><img src="https://avatars.githubusercontent.com/u/4153572?v=4?s=50" width="50px;" alt="Marc"/><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" valign="top" width="14.28%"><a href="https://github.com/mgaw"><img src="https://avatars.githubusercontent.com/u/2177016?v=4?s=50" width="50px;" alt="Marius Gawrisch"/><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" valign="top" width="14.28%"><a href="http://www.markhz.com/"><img src="https://avatars.githubusercontent.com/u/2789742?v=4?s=50" width="50px;" alt="Mark Hintz"/><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" valign="top" width="14.28%"><a href="https://github.com/MatElGran"><img src="https://avatars.githubusercontent.com/u/1052778?v=4?s=50" width="50px;" alt="Mathieu Le Tiec"/><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" valign="top" width="14.28%"><a href="https://matt-w.net/"><img src="https://avatars.githubusercontent.com/u/8656127?v=4?s=50" width="50px;" alt="Matt White"/><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" valign="top" width="14.28%"><a href="https://github.com/ml-evs"><img src="https://avatars.githubusercontent.com/u/7916000?v=4?s=50" width="50px;" alt="Matthew Evans"/><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" valign="top" width="14.28%"><a href="https://github.com/Me1onRind"><img src="https://avatars.githubusercontent.com/u/19531270?v=4?s=50" width="50px;" alt="Me1onRind"/><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" valign="top" width="14.28%"><a href="https://github.com/Qyriad"><img src="https://avatars.githubusercontent.com/u/1542224?v=4?s=50" width="50px;" alt="Qyriad"/><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" valign="top" width="14.28%"><a href="https://leo.is-a.dev/"><img src="https://avatars.githubusercontent.com/u/35312043?v=4?s=50" width="50px;" alt="Narcis B."/><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" valign="top" width="14.28%"><a href="https://github.com/Neur1n"><img src="https://avatars.githubusercontent.com/u/17579247?v=4?s=50" width="50px;" alt="Neur1n"/><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" valign="top" width="14.28%"><a href="https://github.com/nicoder"><img src="https://avatars.githubusercontent.com/u/365210?v=4?s=50" width="50px;" alt="Nicolas Dermine"/><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" valign="top" width="14.28%"><a href="https://github.com/NoahTheDuke"><img src="https://avatars.githubusercontent.com/u/603677?v=4?s=50" width="50px;" alt="Noah"/><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" valign="top" width="14.28%"><a href="https://github.com/IndexXuan"><img src="https://avatars.githubusercontent.com/u/6322673?v=4?s=50" width="50px;" alt="PENG Rui"/><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" valign="top" width="14.28%"><a href="https://liaoph.com/"><img src="https://avatars.githubusercontent.com/u/6123425?v=4?s=50" width="50px;" alt="Paco"/><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" valign="top" width="14.28%"><a href="https://github.com/peng1999"><img src="https://avatars.githubusercontent.com/u/12483662?v=4?s=50" width="50px;" alt="Peng Guanwen"/><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" valign="top" width="14.28%"><a href="https://www.twitter.com/badeip"><img src="https://avatars.githubusercontent.com/u/1106732?v=4?s=50" width="50px;" alt="Petter Wahlman"/><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" valign="top" width="14.28%"><a href="https://github.com/pvonmoradi"><img src="https://avatars.githubusercontent.com/u/1058151?v=4?s=50" width="50px;" alt="Pooya Moradi"/><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" valign="top" width="14.28%"><a href="https://github.com/QuadeMorrison"><img src="https://avatars.githubusercontent.com/u/10917383?v=4?s=50" width="50px;" alt="Quade Morrison"/><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" valign="top" width="14.28%"><a href="https://github.com/vogler"><img src="https://avatars.githubusercontent.com/u/493741?v=4?s=50" width="50px;" alt="Ralf Vogler"/><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" valign="top" width="14.28%"><a href="https://github.com/crccw"><img src="https://avatars.githubusercontent.com/u/41463?v=4?s=50" width="50px;" alt="Ran Chen"/><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" valign="top" width="14.28%"><a href="https://bigardone.dev/"><img src="https://avatars.githubusercontent.com/u/1090272?v=4?s=50" width="50px;" alt="Ricardo García Vega"/><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" valign="top" width="14.28%"><a href="https://github.com/nomasprime"><img src="https://avatars.githubusercontent.com/u/140855?v=4?s=50" width="50px;" alt="Rick Jones"/><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" valign="top" width="14.28%"><a href="https://github.com/rschristian"><img src="https://avatars.githubusercontent.com/u/33403762?v=4?s=50" width="50px;" alt="Ryan Christian"/><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" valign="top" width="14.28%"><a href="http://salo.so/"><img src="https://avatars.githubusercontent.com/u/4694263?v=4?s=50" width="50px;" alt="Salo"/><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" valign="top" width="14.28%"><a href="https://github.com/Hazelfire"><img src="https://avatars.githubusercontent.com/u/13807753?v=4?s=50" width="50px;" alt="Sam Nolan"/><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" valign="top" width="14.28%"><a href="https://github.com/rickysaurav"><img src="https://avatars.githubusercontent.com/u/13986039?v=4?s=50" width="50px;" alt="Saurav"/><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" valign="top" width="14.28%"><a href="https://github.com/smackesey"><img src="https://avatars.githubusercontent.com/u/1531373?v=4?s=50" width="50px;" alt="Sean Mackesey"/><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" valign="top" width="14.28%"><a href="https://github.com/sheeldotme"><img src="https://avatars.githubusercontent.com/u/6991406?v=4?s=50" width="50px;" alt="Sheel Patel"/><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" valign="top" width="14.28%"><a href="https://github.com/solomonwzs"><img src="https://avatars.githubusercontent.com/u/907942?v=4?s=50" width="50px;" alt="Solomon Ng"/><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" valign="top" width="14.28%"><a href="https://github.com/kadimisetty"><img src="https://avatars.githubusercontent.com/u/535947?v=4?s=50" width="50px;" alt="Sri Kadimisetty"/><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" valign="top" width="14.28%"><a href="https://github.com/stephenprater"><img src="https://avatars.githubusercontent.com/u/149870?v=4?s=50" width="50px;" alt="Stephen Prater"/><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" valign="top" width="14.28%"><a href="https://kibs.dk/"><img src="https://avatars.githubusercontent.com/u/14085?v=4?s=50" width="50px;" alt="Sune Kibsgaard"/><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" valign="top" width="14.28%"><a href="https://github.com/Aquaakuma"><img src="https://avatars.githubusercontent.com/u/31891793?v=4?s=50" width="50px;" alt="Aquaakuma"/><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" valign="top" width="14.28%"><a href="https://github.com/coil398"><img src="https://avatars.githubusercontent.com/u/7694377?v=4?s=50" width="50px;" alt="Takumi Kawase"/><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" valign="top" width="14.28%"><a href="https://github.com/theblobscp"><img src="https://avatars.githubusercontent.com/u/81673375?v=4?s=50" width="50px;" alt="The Blob SCP"/><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" valign="top" width="14.28%"><a href="https://github.com/przepompownia"><img src="https://avatars.githubusercontent.com/u/11404453?v=4?s=50" width="50px;" alt="Tomasz N"/><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" valign="top" width="14.28%"><a href="https://github.com/gasuketsu"><img src="https://avatars.githubusercontent.com/u/15703757?v=4?s=50" width="50px;" alt="Tomoyuki Harada"/><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" valign="top" width="14.28%"><a href="https://github.com/tonyfettes"><img src="https://avatars.githubusercontent.com/u/29998228?v=4?s=50" width="50px;" alt="Tony Fettes"/><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" valign="top" width="14.28%"><a href="https://www.git-pull.com/"><img src="https://avatars.githubusercontent.com/u/26336?v=4?s=50" width="50px;" alt="Tony Narlock"/><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" valign="top" width="14.28%"><a href="https://blog.wwwjfy.net/"><img src="https://avatars.githubusercontent.com/u/126527?v=4?s=50" width="50px;" alt="Tony Wang"/><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" valign="top" width="14.28%"><a href="https://github.com/Varal7"><img src="https://avatars.githubusercontent.com/u/8019486?v=4?s=50" width="50px;" alt="Victor Quach"/><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" valign="top" width="14.28%"><a href="https://github.com/whisperity"><img src="https://avatars.githubusercontent.com/u/1969470?v=4?s=50" width="50px;" alt="Whisperity"/><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" valign="top" width="14.28%"><a href="https://github.com/willtrnr"><img src="https://avatars.githubusercontent.com/u/1878110?v=4?s=50" width="50px;" alt="William Turner"/><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" valign="top" width="14.28%"><a href="https://drafts.damnever.com/"><img src="https://avatars.githubusercontent.com/u/6223594?v=4?s=50" width="50px;" alt="Xiaochao Dong"/><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" valign="top" width="14.28%"><a href="https://github.com/hyhugh"><img src="https://avatars.githubusercontent.com/u/16500351?v=4?s=50" width="50px;" alt="Hugh Hou"/><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" valign="top" width="14.28%"><a href="https://github.com/jackielii"><img src="https://avatars.githubusercontent.com/u/360983?v=4?s=50" width="50px;" alt="Jackie Li"/><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" valign="top" width="14.28%"><a href="https://github.com/TheConfuZzledDude"><img src="https://avatars.githubusercontent.com/u/3160203?v=4?s=50" width="50px;" alt="Zachary Freed"/><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" valign="top" width="14.28%"><a href="https://github.com/akiyosi"><img src="https://avatars.githubusercontent.com/u/8478977?v=4?s=50" width="50px;" alt="akiyosi"/><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" valign="top" width="14.28%"><a href="https://github.com/alexjg"><img src="https://avatars.githubusercontent.com/u/224635?v=4?s=50" width="50px;" alt="alexjg"/><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" valign="top" width="14.28%"><a href="https://github.com/aste4"><img src="https://avatars.githubusercontent.com/u/47511385?v=4?s=50" width="50px;" alt="aste4"/><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" valign="top" width="14.28%"><a href="https://github.com/clyfish"><img src="https://avatars.githubusercontent.com/u/541215?v=4?s=50" width="50px;" alt="clyfish"/><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" valign="top" width="14.28%"><a href="https://github.com/dev7ba"><img src="https://avatars.githubusercontent.com/u/93706552?v=4?s=50" width="50px;" alt="dev7ba"/><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" valign="top" width="14.28%"><a href="https://github.com/diartyz"><img src="https://avatars.githubusercontent.com/u/4486152?v=4?s=50" width="50px;" alt="diartyz"/><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" valign="top" width="14.28%"><a href="https://github.com/doza-daniel"><img src="https://avatars.githubusercontent.com/u/13752683?v=4?s=50" width="50px;" alt="doza-daniel"/><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" valign="top" width="14.28%"><a href="https://github.com/equal-l2"><img src="https://avatars.githubusercontent.com/u/8597717?v=4?s=50" width="50px;" alt="equal-l2"/><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" valign="top" width="14.28%"><a href="https://github.com/FongHou"><img src="https://avatars.githubusercontent.com/u/13973254?v=4?s=50" width="50px;" alt="fong"/><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" valign="top" width="14.28%"><a href="https://blog.hexuhua.vercel.app/"><img src="https://avatars.githubusercontent.com/u/26080416?v=4?s=50" width="50px;" alt="hexh"/><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" valign="top" width="14.28%"><a href="https://github.com/hhiraba"><img src="https://avatars.githubusercontent.com/u/4624806?v=4?s=50" width="50px;" alt="hhiraba"/><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" valign="top" width="14.28%"><a href="https://github.com/ic-768"><img src="https://avatars.githubusercontent.com/u/83115125?v=4?s=50" width="50px;" alt="ic-768"/><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" valign="top" width="14.28%"><a href="https://github.com/javiertury"><img src="https://avatars.githubusercontent.com/u/1520320?v=4?s=50" width="50px;" alt="javiertury"/><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" valign="top" width="14.28%"><a href="https://github.com/seiyeah78"><img src="https://avatars.githubusercontent.com/u/6185139?v=4?s=50" width="50px;" alt="karasu"/><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" valign="top" width="14.28%"><a href="https://github.com/kevineato"><img src="https://avatars.githubusercontent.com/u/13666221?v=4?s=50" width="50px;" alt="kevineato"/><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" valign="top" width="14.28%"><a href="https://github.com/m4c0"><img src="https://avatars.githubusercontent.com/u/1664510?v=4?s=50" width="50px;" alt="Eduardo Costa"/><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" valign="top" width="14.28%"><a href="https://github.com/micchy326"><img src="https://avatars.githubusercontent.com/u/23257067?v=4?s=50" width="50px;" alt="micchy326"/><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" valign="top" width="14.28%"><a href="https://keybase.io/midchildan"><img src="https://avatars.githubusercontent.com/u/7343721?v=4?s=50" width="50px;" alt="midchildan"/><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" valign="top" width="14.28%"><a href="https://github.com/minefuto"><img src="https://avatars.githubusercontent.com/u/46558834?v=4?s=50" width="50px;" alt="minefuto"/><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" valign="top" width="14.28%"><a href="https://twitter.com/robokomy"><img src="https://avatars.githubusercontent.com/u/20733354?v=4?s=50" width="50px;" alt="miyanokomiya"/><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" valign="top" width="14.28%"><a href="https://github.com/miyaviee"><img src="https://avatars.githubusercontent.com/u/15247561?v=4?s=50" width="50px;" alt="miyaviee"/><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" valign="top" width="14.28%"><a href="https://github.com/monkoose"><img src="https://avatars.githubusercontent.com/u/6261276?v=4?s=50" width="50px;" alt="monkoose"/><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" valign="top" width="14.28%"><a href="https://github.com/mujx"><img src="https://avatars.githubusercontent.com/u/6430350?v=4?s=50" width="50px;" alt="mujx"/><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" valign="top" width="14.28%"><a href="https://github.com/mvilim"><img src="https://avatars.githubusercontent.com/u/40682862?v=4?s=50" width="50px;" alt="mvilim"/><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" valign="top" width="14.28%"><a href="https://naruaway.com/"><img src="https://avatars.githubusercontent.com/u/2931577?v=4?s=50" width="50px;" alt="naruaway"/><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" valign="top" width="14.28%"><a href="https://github.com/piersy"><img src="https://avatars.githubusercontent.com/u/5087847?v=4?s=50" width="50px;" alt="piersy"/><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" valign="top" width="14.28%"><a href="https://github.com/ryantig"><img src="https://avatars.githubusercontent.com/u/324810?v=4?s=50" width="50px;" alt="ryantig"/><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" valign="top" width="14.28%"><a href="https://catcat.cc/"><img src="https://avatars.githubusercontent.com/u/19602440?v=4?s=50" width="50px;" alt="rydesun"/><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" valign="top" width="14.28%"><a href="https://github.com/sc00ter"><img src="https://avatars.githubusercontent.com/u/1271025?v=4?s=50" width="50px;" alt="sc00ter"/><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" valign="top" width="14.28%"><a href="https://github.com/smhc"><img src="https://avatars.githubusercontent.com/u/6404304?v=4?s=50" width="50px;" alt="smhc"/><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" valign="top" width="14.28%"><a href="https://github.com/stkaplan"><img src="https://avatars.githubusercontent.com/u/594990?v=4?s=50" width="50px;" alt="Sam Kaplan"/><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" valign="top" width="14.28%"><a href="https://github.com/tasuten"><img src="https://avatars.githubusercontent.com/u/1623176?v=4?s=50" width="50px;" alt="tasuten"/><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" valign="top" width="14.28%"><a href="http://todesking.com/"><img src="https://avatars.githubusercontent.com/u/112881?v=4?s=50" width="50px;" alt="todesking"/><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" valign="top" width="14.28%"><a href="https://github.com/typicode"><img src="https://avatars.githubusercontent.com/u/5502029?v=4?s=50" width="50px;" alt="typicode"/><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" valign="top" width="14.28%"><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" valign="top" width="14.28%"><a href="https://bandism.net/"><img src="https://avatars.githubusercontent.com/u/22633385?v=4?s=50" width="50px;" alt="Ikko Ashimine"/><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" valign="top" width="14.28%"><a href="https://github.com/rammiah"><img src="https://avatars.githubusercontent.com/u/26727562?v=4?s=50" width="50px;" alt="Rammiah"/><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>
<td align="center" valign="top" width="14.28%"><a href="https://keybase.io/lambdalisue"><img src="https://avatars.githubusercontent.com/u/546312?v=4?s=50" width="50px;" alt="Alisue"/><br /><sub><b>Alisue</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/issues?q=author%3Alambdalisue" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://bigshans.github.io"><img src="https://avatars.githubusercontent.com/u/26884666?v=4?s=50" width="50px;" alt="bigshans"/><br /><sub><b>bigshans</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=bigshans" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/rob-3"><img src="https://avatars.githubusercontent.com/u/24816247?v=4?s=50" width="50px;" alt="Robert Boyd III"/><br /><sub><b>Robert Boyd III</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/issues?q=author%3Arob-3" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://creasty.com"><img src="https://avatars.githubusercontent.com/u/1695538?v=4?s=50" width="50px;" alt="Yuki Iwanaga"/><br /><sub><b>Yuki Iwanaga</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=creasty" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.dosk.win/"><img src="https://avatars.githubusercontent.com/u/2389889?v=4?s=50" width="50px;" alt="SpringHack"/><br /><sub><b>SpringHack</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/issues?q=author%3Aspringhack" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://git.lmburns.com"><img src="https://avatars.githubusercontent.com/u/44355502?v=4?s=50" width="50px;" alt="Lucas Burns"/><br /><sub><b>Lucas Burns</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=lmburns" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="http://qiqi.boy.im"><img src="https://avatars.githubusercontent.com/u/3774036?v=4?s=50" width="50px;" alt="qiqiboy"/><br /><sub><b>qiqiboy</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=qiqiboy" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/timsu92"><img src="https://avatars.githubusercontent.com/u/33785401?v=4?s=50" width="50px;" alt="timsu92"/><br /><sub><b>timsu92</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=timsu92" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://sartak.org"><img src="https://avatars.githubusercontent.com/u/45430?v=4?s=50" width="50px;" alt="Shawn M Moore"/><br /><sub><b>Shawn M Moore</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=sartak" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/aauren"><img src="https://avatars.githubusercontent.com/u/1392295?v=4?s=50" width="50px;" alt="Aaron U'Ren"/><br /><sub><b>Aaron U'Ren</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/issues?q=author%3Aaauren" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/SirCharlieMars"><img src="https://avatars.githubusercontent.com/u/31679231?v=4?s=50" width="50px;" alt="SeniorMars"/><br /><sub><b>SeniorMars</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=SirCharlieMars" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/CollieIsCute"><img src="https://avatars.githubusercontent.com/u/43088530?v=4?s=50" width="50px;" alt="牧羊犬真Q"/><br /><sub><b>牧羊犬真Q</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=CollieIsCute" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://geraldspreer.com"><img src="https://avatars.githubusercontent.com/u/1745692?v=4?s=50" width="50px;" alt="geraldspreer"/><br /><sub><b>geraldspreer</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=geraldspreer" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="http://3ximus.github.io/cv"><img src="https://avatars.githubusercontent.com/u/9083012?v=4?s=50" width="50px;" alt="Fabio"/><br /><sub><b>Fabio</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=3ximus" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/skysky97"><img src="https://avatars.githubusercontent.com/u/18086458?v=4?s=50" width="50px;" alt="Li Yunting"/><br /><sub><b>Li Yunting</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/issues?q=author%3Askysky97" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/LebJe"><img src="https://avatars.githubusercontent.com/u/51171427?v=4?s=50" width="50px;" alt="Jeff L."/><br /><sub><b>Jeff L.</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=LebJe" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://hachyderm.io/@mcmire"><img src="https://avatars.githubusercontent.com/u/7371?v=4?s=50" width="50px;" alt="Elliot Winkler"/><br /><sub><b>Elliot Winkler</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=mcmire" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.lebstertm.com"><img src="https://avatars.githubusercontent.com/u/15955811?v=4?s=50" width="50px;" alt="Svetlozar Iliev"/><br /><sub><b>Svetlozar Iliev</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=asmodeus812" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://43081j.com/"><img src="https://avatars.githubusercontent.com/u/5677153?v=4?s=50" width="50px;" alt="James Garbutt"/><br /><sub><b>James Garbutt</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=43081j" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Kaiser-Yang"><img src="https://avatars.githubusercontent.com/u/58209855?v=4?s=50" width="50px;" alt="Qingzhou Yue"/><br /><sub><b>Qingzhou Yue</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=Kaiser-Yang" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/de-vries-maarten/"><img src="https://avatars.githubusercontent.com/u/786213?v=4?s=50" width="50px;" alt="Maarten de Vries"/><br /><sub><b>Maarten de Vries</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=de-vri-es" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/A4-Tacks"><img src="https://avatars.githubusercontent.com/u/102709083?v=4?s=50" width="50px;" alt="A4-Tacks"/><br /><sub><b>A4-Tacks</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=A4-Tacks" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zhixiao-zhang"><img src="https://avatars.githubusercontent.com/u/89405463?v=4?s=50" width="50px;" alt="forceofsystem"/><br /><sub><b>forceofsystem</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=zhixiao-zhang" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/statiolake"><img src="https://avatars.githubusercontent.com/u/20490597?v=4?s=50" width="50px;" alt="lake"/><br /><sub><b>lake</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=statiolake" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.davidosomething.com/"><img src="https://avatars.githubusercontent.com/u/609213?v=4?s=50" width="50px;" alt="David O'Trakoun"/><br /><sub><b>David O'Trakoun</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=davidosomething" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/aispeaking"><img src="https://avatars.githubusercontent.com/u/139532597?v=4?s=50" width="50px;" alt="aispeaking"/><br /><sub><b>aispeaking</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=aispeaking" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/cclauss"><img src="https://avatars.githubusercontent.com/u/3709715?v=4?s=50" width="50px;" alt="Christian Clauss"/><br /><sub><b>Christian Clauss</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=cclauss" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="http://mehalter.com"><img src="https://avatars.githubusercontent.com/u/1591837?v=4?s=50" width="50px;" alt="Micah Halter"/><br /><sub><b>Micah Halter</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=mehalter" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/cridemichel"><img src="https://avatars.githubusercontent.com/u/15322138?v=4?s=50" width="50px;" alt="Cristiano De Michele"/><br /><sub><b>Cristiano De Michele</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=cridemichel" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://yongjie.codes/"><img src="https://avatars.githubusercontent.com/u/14101781?v=4?s=50" width="50px;" alt="Yong Jie"/><br /><sub><b>Yong Jie</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=YongJieYongJie" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://eight45.net"><img src="https://avatars.githubusercontent.com/u/489362?v=4?s=50" width="50px;" alt="Kira Oakley"/><br /><sub><b>Kira Oakley</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=hackergrrl" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://merwan.github.io"><img src="https://avatars.githubusercontent.com/u/222879?v=4?s=50" width="50px;" alt="Merouane Atig"/><br /><sub><b>Merouane Atig</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=merwan" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://gera2ld.space/"><img src="https://avatars.githubusercontent.com/u/3139113?v=4?s=50" width="50px;" alt="Gerald"/><br /><sub><b>Gerald</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=gera2ld" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://nicklas.sedlock.xyz/"><img src="https://avatars.githubusercontent.com/u/47660390?v=4?s=50" width="50px;" alt="Nicklas Sedlock"/><br /><sub><b>Nicklas Sedlock</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=V-Mann-Nick" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/tcx4c70"><img src="https://avatars.githubusercontent.com/u/16728230?v=4?s=50" width="50px;" alt="Adam Tao"/><br /><sub><b>Adam Tao</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=tcx4c70" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/itsf4llofstars"><img src="https://avatars.githubusercontent.com/u/90528743?v=4?s=50" width="50px;" alt="itsf4llofstars"/><br /><sub><b>itsf4llofstars</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=itsf4llofstars" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/brainwo"><img src="https://avatars.githubusercontent.com/u/45139213?v=4?s=50" width="50px;" alt="Brian Wo"/><br /><sub><b>Brian Wo</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=brainwo" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://wsdjeg.net/"><img src="https://avatars.githubusercontent.com/u/13142418?v=4?s=50" width="50px;" alt="Eric Wong"/><br /><sub><b>Eric Wong</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=wsdjeg" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/oxalica"><img src="https://avatars.githubusercontent.com/u/14816024?v=4?s=50" width="50px;" alt="oxalica"/><br /><sub><b>oxalica</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=oxalica" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/laktak"><img src="https://avatars.githubusercontent.com/u/959858?v=4?s=50" width="50px;" alt="Christian Zangl"/><br /><sub><b>Christian Zangl</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=laktak" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zoumi"><img src="https://avatars.githubusercontent.com/u/5162901?v=4?s=50" width="50px;" alt="zoumi"/><br /><sub><b>zoumi</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=zoumi" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/atitcreate"><img src="https://avatars.githubusercontent.com/u/40348360?v=4?s=50" width="50px;" alt="atitcreate"/><br /><sub><b>atitcreate</b></sub></a><br /><a href="https://github.com/neoclide/coc.nvim/commits?author=atitcreate" title="Code">💻</a></td>
</tr>
</tbody>
</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](./LICENSE.md)

View file

@ -0,0 +1,167 @@
scriptencoding utf-8
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:utf = has('nvim') || &encoding =~# '^utf'
let s:error_sign = get(g:, 'coc_status_error_sign', has('mac') && s:utf ? "\u274c " : 'E ')
let s:warning_sign = get(g:, 'coc_status_warning_sign', has('mac') && s:utf ? "\u26a0\ufe0f " : 'W ')
let s:select_api = exists('*nvim_select_popupmenu_item')
let s:callbacks = {}
let s:fns = ['init', 'complete', 'should_complete', 'refresh', 'get_startcol', 'on_complete', 'on_enter']
let s:all_fns = s:fns + map(copy(s:fns), 'toupper(strpart(v:val, 0, 1)) . strpart(v:val, 1)')
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
" Only clear augroup starts with coc
function! coc#clearGroups(prefix) abort
for group in getcompletion('coc', 'augroup')
if group =~# '^' . a:prefix
execute 'autocmd! ' . group
endif
endfor
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 coc#pum#visible()
let prefix = "\<C-r>=coc#pum#close()\<CR>"
elseif pumvisible()
let prefix = "\<C-x>\<C-z>"
endif
endif
return prefix."\<c-r>=coc#rpc#".a:method."('doKeymap', ['".a:key."'])\<CR>"
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
let status = get(g:, 'coc_status', '')
if get(a:, 1, 0)
let status = substitute(status, '%', '%%', 'g')
endif
return trim(join(msgs, ' ') . ' ' . 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
" Deprecated, use variable instead.
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('registerNotification', [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(...)
call CocActionAsync('startCompletion', get(a:, 1, {}))
return ''
endfunction
" Could be used by coc extensions
function! coc#_cancel(...)
call coc#pum#close()
endfunction
function! coc#refresh() abort
return "\<c-r>=coc#start()\<CR>"
endfunction
function! coc#_select_confirm() abort
return "\<C-r>=coc#pum#select_confirm()\<CR>"
endfunction
function! coc#_suggest_variables() abort
return {
\ 'disable': get(b:, 'coc_suggest_disable', 0),
\ 'disabled_sources': get(b:, 'coc_disabled_sources', []),
\ 'blacklist': get(b:, 'coc_suggest_blacklist', []),
\ }
endfunction
function! coc#_remote_fns(name)
let res = []
for fn in s:all_fns
if exists('*coc#source#'.a:name.'#'.fn)
call add(res, fn)
endif
endfor
return res
endfunction
function! coc#_do_complete(name, opt, cb) abort
let method = get(a:opt, 'vim9', v:false) ? 'Complete' : 'complete'
let handler = 'coc#source#'.a:name.'#'.method
let l:Cb = {res -> a:cb(v:null, res)}
let args = [a:opt, l:Cb]
call call(handler, args)
endfunction

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,368 @@
scriptencoding utf-8
let s:is_vim = !has('nvim')
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())
echoerr '[coc.nvim] Current cwd is not a valid directory.'
return
endif
let tmpdir = fnamemodify(tempname(), ':p:h')
let env = { 'NODE_NO_WARNINGS': '1', 'TMPDIR': coc#util#win32unix_to_node(tmpdir)}
if s:is_vim
let env['VIM_NODE_RPC'] = 1
if get(g:, 'node_client_debug', 0) || $COC_VIM_CHANNEL_ENABLE == '1'
let file = tmpdir . '/coc.log'
call ch_logfile(file, 'w')
echohl MoreMsg | echo '[coc.nvim] channel log to '.file | echohl None
endif
let options = {
\ 'noblock': 1,
\ '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': env
\}
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['channel'] = job_getchannel(job)
else
let opts = {
\ 'rpc': 1,
\ 'on_stderr': {channel, msgs -> s:on_stderr(self.name, msgs)},
\ 'on_exit': {channel, code -> s:on_exit(self.name, code)},
\ 'env': env
\ }
let chan_id = jobstart(self.command, opts)
if chan_id <= 0
echohl Error | echom 'Failed to start '.self.name.' service' | echohl None
return
endif
let self['chan_id'] = chan_id
endif
let self['running'] = 1
endfunction
function! s:on_stderr(name, msgs)
if get(g:, 'coc_vim_leaving', 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]
if a:name ==# 'coc' && len(filter(copy(data), 'v:val =~# "SyntaxError: "'))
call coc#client#check_version()
return
endif
if get(g:, 'coc_disable_uncaught_error', 0) | return | endif
call s:on_error(a:name, data)
endfunction
function! coc#client#check_version() abort
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
let cmd = node . ' --version'
let output = system(cmd)
let msgs = []
if v:shell_error
let msgs = ['Unexpected result from "'.cmd.'"'] + split(output, '\n')
else
let ms = matchlist(output, 'v\(\d\+\).\(\d\+\).\(\d\+\)')
if empty(ms)
let msgs = ['Unable to get node version by "'.cmd.'" please install NodeJS from https://nodejs.org/en/download/']
elseif str2nr(ms[1]) < 16 || (str2nr(ms[1]) == 16 && str2nr(ms[2]) < 18)
let msgs = ['Current Node.js version '.trim(output).' < 16.18.0 ', 'Please upgrade your Node.js']
endif
endif
if !empty(msgs)
call s:on_error('coc', msgs)
endif
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 && a:code != -1
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 'Error on "'.a:method.'" request: '.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
if s:is_vim
throw v:exception
else
throw 'Error on request: '.v:exception
endif
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
try
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
catch /.*/
return 0
endtry
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#kill(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 empty(client) || exists('$COC_NVIM_REMOTE_ADDRESS')
return 1
endif
if running
if s:is_vim
call job_stop(ch_getjob(client['channel']), 'kill')
else
call jobstop(client['chan_id'])
endif
endif
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)
throw '[coc.nvim] use let g:node_client_debug = 1 in your vimrc to enable debug mode.'
return
endif
execute 'vs '.s:logfile
endfunction
function! coc#client#get_log()
if !get(g:, 'node_client_debug', 0)
throw '[coc.nvim] use let g:node_client_debug = 1 in your vimrc to enable debug mode.'
return ''
endif
return s:logfile
endfunction
function! s:on_error(name, msgs) abort
echohl ErrorMsg
echo join(a:msgs, "\n")
echohl None
let client = get(s:clients, a:name, v:null)
if !empty(client)
let errors = get(client, 'stderr', [])
call extend(errors, a:msgs)
let client['stderr'] = errors
endif
endfunction

View file

@ -0,0 +1,610 @@
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
let s:patterns = {}
let s:patterns['hex'] = '\v#?(\x{2})(\x{2})(\x{2})'
let s:patterns['shortHex'] = '\v#(\x{1})(\x{1})(\x{1})'
let s:xterm_colors = {
\ '0': '#000000', '1': '#800000', '2': '#008000', '3': '#808000', '4': '#000080',
\ '5': '#800080', '6': '#008080', '7': '#c0c0c0', '8': '#808080', '9': '#ff0000',
\ '10': '#00ff00', '11': '#ffff00', '12': '#0000ff', '13': '#ff00ff', '14': '#00ffff',
\ '15': '#ffffff', '16': '#000000', '17': '#00005f', '18': '#000087', '19': '#0000af',
\ '20': '#0000df', '21': '#0000ff', '22': '#005f00', '23': '#005f5f', '24': '#005f87',
\ '25': '#005faf', '26': '#005fdf', '27': '#005fff', '28': '#008700', '29': '#00875f',
\ '30': '#008787', '31': '#0087af', '32': '#0087df', '33': '#0087ff', '34': '#00af00',
\ '35': '#00af5f', '36': '#00af87', '37': '#00afaf', '38': '#00afdf', '39': '#00afff',
\ '40': '#00df00', '41': '#00df5f', '42': '#00df87', '43': '#00dfaf', '44': '#00dfdf',
\ '45': '#00dfff', '46': '#00ff00', '47': '#00ff5f', '48': '#00ff87', '49': '#00ffaf',
\ '50': '#00ffdf', '51': '#00ffff', '52': '#5f0000', '53': '#5f005f', '54': '#5f0087',
\ '55': '#5f00af', '56': '#5f00df', '57': '#5f00ff', '58': '#5f5f00', '59': '#5f5f5f',
\ '60': '#5f5f87', '61': '#5f5faf', '62': '#5f5fdf', '63': '#5f5fff', '64': '#5f8700',
\ '65': '#5f875f', '66': '#5f8787', '67': '#5f87af', '68': '#5f87df', '69': '#5f87ff',
\ '70': '#5faf00', '71': '#5faf5f', '72': '#5faf87', '73': '#5fafaf', '74': '#5fafdf',
\ '75': '#5fafff', '76': '#5fdf00', '77': '#5fdf5f', '78': '#5fdf87', '79': '#5fdfaf',
\ '80': '#5fdfdf', '81': '#5fdfff', '82': '#5fff00', '83': '#5fff5f', '84': '#5fff87',
\ '85': '#5fffaf', '86': '#5fffdf', '87': '#5fffff', '88': '#870000', '89': '#87005f',
\ '90': '#870087', '91': '#8700af', '92': '#8700df', '93': '#8700ff', '94': '#875f00',
\ '95': '#875f5f', '96': '#875f87', '97': '#875faf', '98': '#875fdf', '99': '#875fff',
\ '100': '#878700', '101': '#87875f', '102': '#878787', '103': '#8787af', '104': '#8787df',
\ '105': '#8787ff', '106': '#87af00', '107': '#87af5f', '108': '#87af87', '109': '#87afaf',
\ '110': '#87afdf', '111': '#87afff', '112': '#87df00', '113': '#87df5f', '114': '#87df87',
\ '115': '#87dfaf', '116': '#87dfdf', '117': '#87dfff', '118': '#87ff00', '119': '#87ff5f',
\ '120': '#87ff87', '121': '#87ffaf', '122': '#87ffdf', '123': '#87ffff', '124': '#af0000',
\ '125': '#af005f', '126': '#af0087', '127': '#af00af', '128': '#af00df', '129': '#af00ff',
\ '130': '#af5f00', '131': '#af5f5f', '132': '#af5f87', '133': '#af5faf', '134': '#af5fdf',
\ '135': '#af5fff', '136': '#af8700', '137': '#af875f', '138': '#af8787', '139': '#af87af',
\ '140': '#af87df', '141': '#af87ff', '142': '#afaf00', '143': '#afaf5f', '144': '#afaf87',
\ '145': '#afafaf', '146': '#afafdf', '147': '#afafff', '148': '#afdf00', '149': '#afdf5f',
\ '150': '#afdf87', '151': '#afdfaf', '152': '#afdfdf', '153': '#afdfff', '154': '#afff00',
\ '155': '#afff5f', '156': '#afff87', '157': '#afffaf', '158': '#afffdf', '159': '#afffff',
\ '160': '#df0000', '161': '#df005f', '162': '#df0087', '163': '#df00af', '164': '#df00df',
\ '165': '#df00ff', '166': '#df5f00', '167': '#df5f5f', '168': '#df5f87', '169': '#df5faf',
\ '170': '#df5fdf', '171': '#df5fff', '172': '#df8700', '173': '#df875f', '174': '#df8787',
\ '175': '#df87af', '176': '#df87df', '177': '#df87ff', '178': '#dfaf00', '179': '#dfaf5f',
\ '180': '#dfaf87', '181': '#dfafaf', '182': '#dfafdf', '183': '#dfafff', '184': '#dfdf00',
\ '185': '#dfdf5f', '186': '#dfdf87', '187': '#dfdfaf', '188': '#dfdfdf', '189': '#dfdfff',
\ '190': '#dfff00', '191': '#dfff5f', '192': '#dfff87', '193': '#dfffaf', '194': '#dfffdf',
\ '195': '#dfffff', '196': '#ff0000', '197': '#ff005f', '198': '#ff0087', '199': '#ff00af',
\ '200': '#ff00df', '201': '#ff00ff', '202': '#ff5f00', '203': '#ff5f5f', '204': '#ff5f87',
\ '205': '#ff5faf', '206': '#ff5fdf', '207': '#ff5fff', '208': '#ff8700', '209': '#ff875f',
\ '210': '#ff8787', '211': '#ff87af', '212': '#ff87df', '213': '#ff87ff', '214': '#ffaf00',
\ '215': '#ffaf5f', '216': '#ffaf87', '217': '#ffafaf', '218': '#ffafdf', '219': '#ffafff',
\ '220': '#ffdf00', '221': '#ffdf5f', '222': '#ffdf87', '223': '#ffdfaf', '224': '#ffdfdf',
\ '225': '#ffdfff', '226': '#ffff00', '227': '#ffff5f', '228': '#ffff87', '229': '#ffffaf',
\ '230': '#ffffdf', '231': '#ffffff', '232': '#080808', '233': '#121212', '234': '#1c1c1c',
\ '235': '#262626', '236': '#303030', '237': '#3a3a3a', '238': '#444444', '239': '#4e4e4e',
\ '240': '#585858', '241': '#606060', '242': '#666666', '243': '#767676', '244': '#808080',
\ '245': '#8a8a8a', '246': '#949494', '247': '#9e9e9e', '248': '#a8a8a8', '249': '#b2b2b2',
\ '250': '#bcbcbc', '251': '#c6c6c6', '252': '#d0d0d0', '253': '#dadada', '254': '#e4e4e4',
\ '255': '#eeeeee'}
let s:xterm_16colors = {
\ 'black': '#000000',
\ 'darkblue': '#00008B',
\ 'darkgreen': '#00CD00',
\ 'darkcyan': '#00CDCD',
\ 'darkred': '#CD0000',
\ 'darkmagenta': '#8B008B',
\ 'brown': '#CDCD00',
\ 'darkyellow': '#CDCD00',
\ 'lightgrey': '#E5E5E5',
\ 'lightgray': '#E5E5E5',
\ 'gray': '#E5E5E5',
\ 'grey': '#E5E5E5',
\ 'darkgrey': '#7F7F7F',
\ 'darkgray': '#7F7F7F',
\ 'blue': '#5C5CFF',
\ 'lightblue': '#5C5CFF',
\ 'green': '#00FF00',
\ 'lightgreen': '#00FF00',
\ 'cyan': '#00FFFF',
\ 'lightcyan': '#00FFFF',
\ 'red': '#FF0000',
\ 'lightred': '#FF0000',
\ 'magenta': '#FF00FF',
\ 'lightmagenta': '#FF00FF',
\ 'yellow': '#FFFF00',
\ 'lightyellow': '#FFFF00',
\ 'white': '#FFFFFF',
\ }
let s:w3c_color_names = {
\ 'aliceblue': '#F0F8FF',
\ 'antiquewhite': '#FAEBD7',
\ 'aqua': '#00FFFF',
\ 'aquamarine': '#7FFFD4',
\ 'azure': '#F0FFFF',
\ 'beige': '#F5F5DC',
\ 'bisque': '#FFE4C4',
\ 'black': '#000000',
\ 'blanchedalmond': '#FFEBCD',
\ 'blue': '#0000FF',
\ 'blueviolet': '#8A2BE2',
\ 'brown': '#A52A2A',
\ 'burlywood': '#DEB887',
\ 'cadetblue': '#5F9EA0',
\ 'chartreuse': '#7FFF00',
\ 'chocolate': '#D2691E',
\ 'coral': '#FF7F50',
\ 'cornflowerblue': '#6495ED',
\ 'cornsilk': '#FFF8DC',
\ 'crimson': '#DC143C',
\ 'cyan': '#00FFFF',
\ 'darkblue': '#00008B',
\ 'darkcyan': '#008B8B',
\ 'darkgoldenrod': '#B8860B',
\ 'darkgray': '#A9A9A9',
\ 'darkgreen': '#006400',
\ 'darkkhaki': '#BDB76B',
\ 'darkmagenta': '#8B008B',
\ 'darkolivegreen': '#556B2F',
\ 'darkorange': '#FF8C00',
\ 'darkorchid': '#9932CC',
\ 'darkred': '#8B0000',
\ 'darksalmon': '#E9967A',
\ 'darkseagreen': '#8FBC8F',
\ 'darkslateblue': '#483D8B',
\ 'darkslategray': '#2F4F4F',
\ 'darkturquoise': '#00CED1',
\ 'darkviolet': '#9400D3',
\ 'deeppink': '#FF1493',
\ 'deepskyblue': '#00BFFF',
\ 'dimgray': '#696969',
\ 'dodgerblue': '#1E90FF',
\ 'firebrick': '#B22222',
\ 'floralwhite': '#FFFAF0',
\ 'forestgreen': '#228B22',
\ 'fuchsia': '#FF00FF',
\ 'gainsboro': '#DCDCDC',
\ 'ghostwhite': '#F8F8FF',
\ 'gold': '#FFD700',
\ 'goldenrod': '#DAA520',
\ 'gray': '#808080',
\ 'green': '#008000',
\ 'greenyellow': '#ADFF2F',
\ 'honeydew': '#F0FFF0',
\ 'hotpink': '#FF69B4',
\ 'indianred': '#CD5C5C',
\ 'indigo': '#4B0082',
\ 'ivory': '#FFFFF0',
\ 'khaki': '#F0E68C',
\ 'lavender': '#E6E6FA',
\ 'lavenderblush': '#FFF0F5',
\ 'lawngreen': '#7CFC00',
\ 'lemonchiffon': '#FFFACD',
\ 'lightblue': '#ADD8E6',
\ 'lightcoral': '#F08080',
\ 'lightcyan': '#E0FFFF',
\ 'lightgoldenrodyellow': '#FAFAD2',
\ 'lightgray': '#D3D3D3',
\ 'lightgreen': '#90EE90',
\ 'lightpink': '#FFB6C1',
\ 'lightsalmon': '#FFA07A',
\ 'lightseagreen': '#20B2AA',
\ 'lightskyblue': '#87CEFA',
\ 'lightslategray': '#778899',
\ 'lightsteelblue': '#B0C4DE',
\ 'lightyellow': '#FFFFE0',
\ 'lime': '#00FF00',
\ 'limegreen': '#32CD32',
\ 'linen': '#FAF0E6',
\ 'magenta': '#FF00FF',
\ 'maroon': '#800000',
\ 'mediumaquamarine': '#66CDAA',
\ 'mediumblue': '#0000CD',
\ 'mediumorchid': '#BA55D3',
\ 'mediumpurple': '#9370D8',
\ 'mediumseagreen': '#3CB371',
\ 'mediumslateblue': '#7B68EE',
\ 'mediumspringgreen': '#00FA9A',
\ 'mediumturquoise': '#48D1CC',
\ 'mediumvioletred': '#C71585',
\ 'midnightblue': '#191970',
\ 'mintcream': '#F5FFFA',
\ 'mistyrose': '#FFE4E1',
\ 'moccasin': '#FFE4B5',
\ 'navajowhite': '#FFDEAD',
\ 'navy': '#000080',
\ 'oldlace': '#FDF5E6',
\ 'olive': '#808000',
\ 'olivedrab': '#6B8E23',
\ 'orange': '#FFA500',
\ 'orangered': '#FF4500',
\ 'orchid': '#DA70D6',
\ 'palegoldenrod': '#EEE8AA',
\ 'palegreen': '#98FB98',
\ 'paleturquoise': '#AFEEEE',
\ 'palevioletred': '#D87093',
\ 'papayawhip': '#FFEFD5',
\ 'peachpuff': '#FFDAB9',
\ 'peru': '#CD853F',
\ 'pink': '#FFC0CB',
\ 'plum': '#DDA0DD',
\ 'powderblue': '#B0E0E6',
\ 'purple': '#800080',
\ 'red': '#FF0000',
\ 'rosybrown': '#BC8F8F',
\ 'royalblue': '#4169E1',
\ 'saddlebrown': '#8B4513',
\ 'salmon': '#FA8072',
\ 'sandybrown': '#F4A460',
\ 'seagreen': '#2E8B57',
\ 'seashell': '#FFF5EE',
\ 'sienna': '#A0522D',
\ 'silver': '#C0C0C0',
\ 'skyblue': '#87CEEB',
\ 'slateblue': '#6A5ACD',
\ 'slategray': '#708090',
\ 'snow': '#FFFAFA',
\ 'springgreen': '#00FF7F',
\ 'steelblue': '#4682B4',
\ 'tan': '#D2B48C',
\ 'teal': '#008080',
\ 'thistle': '#D8BFD8',
\ 'tomato': '#FF6347',
\ 'turquoise': '#40E0D0',
\ 'violet': '#EE82EE',
\ 'wheat': '#F5DEB3',
\ 'white': '#FFFFFF',
\ 'whitesmoke': '#F5F5F5',
\ 'yellow': '#FFFF00',
\ 'yellowgreen': '#9ACD32'
\ }
" 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#term2rgb(term) abort
if a:term < 0 || a:term > 255
return '#000000'
endif
return s:xterm_colors[a:term]
endfunction
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)
endfunction
function! coc#color#rgbToHex(...)
let [r, g, b] = ( a:0==1 ? a:1 : a:000 )
let num = printf('%02x', float2nr(r)) . ''
\ . printf('%02x', float2nr(g)) . ''
\ . printf('%02x', float2nr(b)) . ''
return '#' . num
endfunction
function! coc#color#hexToRgb(color)
if type(a:color) == 2
let color = printf('%x', a:color)
else
let color = a:color
end
let matches = matchlist(color, s:patterns['hex'])
let factor = 0x1
if empty(matches)
let matches = matchlist(color, s:patterns['shortHex'])
let factor = 0x10
end
if len(matches) < 4
echohl Error
echom 'Couldnt parse ' . string(color) . ' ' . string(matches)
echohl None
return
end
let r = str2nr(matches[1], 16) * factor
let g = str2nr(matches[2], 16) * factor
let b = str2nr(matches[3], 16) * factor
return [r, g, b]
endfunction
function! coc#color#lighten(color, ...)
let amount = a:0 ?
\(type(a:1) < 2 ?
\str2float(a:1) : a:1 )
\: 5
let rgb = coc#color#hexToRgb(a:color)
let rgb = map(rgb, 'v:val + amount*(255 - v:val)/255')
let rgb = map(rgb, 'v:val > 255.0 ? 255.0 : v:val')
let rgb = map(rgb, 'float2nr(v:val)')
let hex = coc#color#rgbToHex(rgb)
return hex
endfunction
function! coc#color#darken(color, ...)
let amount = a:0 ?
\(type(a:1) < 2 ?
\str2float(a:1) : a:1 )
\: 5.0
let rgb = coc#color#hexToRgb(a:color)
let rgb = map(rgb, 'v:val - amount*v:val/255')
let rgb = map(rgb, 'v:val < 0.0 ? 0.0 : v:val')
let rgb = map(rgb, 'float2nr(v:val)')
let hex = coc#color#rgbToHex(rgb)
return hex
endfu
function! coc#color#luminance(rgb) abort
let vals = []
for val in a:rgb
let val = (val + 0.0)/255
if val <= 0.03928
call add(vals, val/12.92)
else
call add(vals, pow((val + 0.055)/1.055, 2.4))
endif
endfor
return vals[0] * 0.2126 + vals[1] * 0.7152 + vals[2] * 0.0722
endfunction
function! coc#color#contrast(rgb1, rgb2) abort
let lnum1 = coc#color#luminance(a:rgb1)
let lnum2 = coc#color#luminance(a:rgb2)
let brightest = lnum1 > lnum2 ? lnum1 : lnum2
let darkest = lnum1 < lnum2 ? lnum1 : lnum2
return (brightest + 0.05) / (darkest + 0.05)
endfunction
function! coc#color#hex_contrast(hex1, hex2) abort
return coc#color#contrast(coc#color#hexToRgb(a:hex1), coc#color#hexToRgb(a:hex2))
endfunction
function! coc#color#nameToHex(name, term) abort
if a:term
return has_key(s:xterm_16colors, a:name) ? s:xterm_16colors[a:name] : v:null
endif
return has_key(s:w3c_color_names, a:name) ? s:w3c_color_names[a:name] : v:null
endfunction
" [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,118 @@
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
return get(win_findbuf(a:bufnr), 0, -1)
endfunction
function! coc#compat#buf_set_lines(bufnr, start, end, replacement) abort
if bufloaded(a:bufnr)
call coc#compat#call('buf_set_lines', [a:bufnr, a:start, a:end, 0, a:replacement])
endif
endfunction
function! coc#compat#buf_line_count(bufnr) abort
if !bufloaded(a:bufnr)
return 0
endif
return coc#compat#call('buf_line_count', [a:bufnr])
endfunction
" remove keymap for bufnr, not throw error
function! coc#compat#buf_del_keymap(bufnr, mode, lhs) abort
if a:bufnr != 0 && !bufexists(a:bufnr)
return
endif
try
call coc#compat#call('buf_del_keymap', [a:bufnr, a:mode, a:lhs])
catch /E31/
" ignore keymap doesn't exist
endtry
endfunction
function! coc#compat#buf_add_keymap(bufnr, mode, lhs, rhs, opts) abort
if a:bufnr != 0 && !bufexists(a:bufnr)
return
endif
call coc#compat#call('buf_set_keymap', [a:bufnr, a:mode, a:lhs, a:rhs, a:opts])
endfunction
function! coc#compat#clear_matches(winid) abort
silent! call clearmatches(a:winid)
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
call matchaddpos(a:group, a:pos, a:priority, -1, {'window': a:winid})
endif
endfunction
" hlGroup, pos, priority
function! coc#compat#matchaddgroups(winid, groups) abort
for group in a:groups
call matchaddpos(group['hlGroup'], [group['pos']], group['priority'], -1, {'window': a:winid})
endfor
endfunction
" Delete var, not throw version.
function! coc#compat#del_var(name) abort
if s:is_vim
execute 'unlet! g:' . a:name
else
silent! call nvim_del_var(a:name)
endif
endfunction
function! coc#compat#tabnr_id(tabnr) abort
if s:is_vim
return coc#api#TabNrId(a:tabnr)
endif
return nvim_list_tabpages()[a:tabnr - 1]
endfunction
function! coc#compat#list_runtime_paths() abort
return coc#compat#call('list_runtime_paths', [])
endfunction
function! coc#compat#buf_execute(bufnr, cmds, ...) abort
let silent = get(a:, 1, 'silent')
if s:is_vim
let cmds = copy(a:cmds)->map({_, val -> 'legacy ' . val})
call coc#api#BufExecute(a:bufnr, cmds, silent)
else
endif
endfunction
function coc#compat#execute(command, ...) abort
return execute(a:command, get(a:, 1, 'silent'))
endfunction
function! coc#compat#eval(expr) abort
return eval(a:expr)
endfunction
function coc#compat#win_execute(id, command, ...) abort
return win_execute(a:id, a:command, get(a:, 1, 'silent'))
endfunction
" call api function on vim or neovim
function! coc#compat#call(fname, args) abort
if s:is_vim
return call('coc#api#' . toupper(a:fname[0]) . a:fname[1:], a:args)
endif
return call('nvim_' . a:fname, a:args)
endfunction
function! coc#compat#send_error(fname, tracestack) abort
let msg = v:exception .. ' - on "' .. a:fname .. '"'
if a:tracestack
let msg = msg .. " \n" .. v:throwpoint
endif
call coc#rpc#notify('nvim_error_event', [0, msg])
endfunction
" vim: set sw=2 ts=2 sts=2 et tw=78 foldlevel=0:

View file

@ -0,0 +1,62 @@
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()
let line = getline('.')
return [line('.') - 1, coc#string#character_index(line, col('.') - 1)]
endfunction
" Move cursor to position.
function! coc#cursor#move_to(line, character) abort
let content = getline(a:line + 1)
call cursor(a:line + 1, coc#string#byte_index(content, a:character) + 1)
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#character_index(getline(sl), sc - 1)
if m ==# 'V'
return [sl - 1, start_idx, el, 0]
endif
let line = getline(el)
let end_idx = coc#string#character_index(line, ec - 1)
if m !=# 'char'
if &selection ==# 'exclusive' && !(sl == el && start_idx == end_idx)
let end_idx = end_idx - 1
endif
let end_idx = end_idx == coc#string#character_length(line) ? end_idx : end_idx + 1
endif
return [sl - 1, start_idx, el - 1, end_idx]
endfunction

View file

@ -0,0 +1,771 @@
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
let s:term_support = s:is_vim ? has('terminal') : 1
" 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'] + (pumbounding['border'] ? 0 : get(pumbounding, 'scrollbar', 0))
let rp = &columns - pumbounding['col'] - pw
let showRight = pumbounding['col'] > rp ? 0 : 1
let maxWidth = showRight ? min([rp - 1, a:config['maxWidth']]) : 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 = width < maxWidth ? width : maxWidth
let ch = coc#string#content_height(a:lines, width - 2)
let height = ch < maxHeight ? ch : maxHeight
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', 'title']
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
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]
call win_execute(winid, 'setl nonumber')
if s:is_vim
call timer_start(0, { -> execute('redraw')})
else
redraw
call coc#float#nvim_scrollbar(winid)
endif
return [currbuf, pos, winid, bufnr, alignTop]
endfunction
" Use terminal buffer
function! coc#dialog#_create_prompt_vim(title, default, opts) abort
execute 'hi link CocPopupTerminal '.get(a:opts, 'highlight', 'CocFloating')
let node = expand(get(g:, 'coc_node_path', 'node'))
let placeHolder = get(a:opts, 'placeHolder', '')
let opt = {
\ 'term_rows': 1,
\ 'hidden': 1,
\ 'term_finish': 'close',
\ 'norestore': 1,
\ 'tty_type': 'conpty',
\ 'term_highlight': 'CocPopupTerminal'
\ }
let bufnr = term_start([node, s:root . '/bin/prompt.js', a:default, empty(placeHolder) ? '' : placeHolder], opt)
call term_setapi(bufnr, 'Coc')
call setbufvar(bufnr, 'current', type(a:default) == v:t_string ? a:default : '')
let res = s:create_prompt_win(bufnr, a:title, a:default, a:opts)
if empty(res)
return
endif
let winid = res[0]
" call win_gotoid(winid)
call coc#util#do_autocmd('CocOpenFloatPrompt')
let pos = popup_getpos(winid)
" width height row col
let dimension = [pos['width'], pos['height'], pos['line'] - 1, pos['col'] - 1]
return [bufnr, winid, dimension]
endfunction
" Use normal buffer on neovim
function! coc#dialog#_create_prompt_nvim(title, default, opts) abort
let result = s:create_prompt_win(s:prompt_win_bufnr, a:title, a:default, a:opts)
if empty(result)
return
endif
let winid = result[0]
let s:prompt_win_bufnr = result[1]
let bufnr = s:prompt_win_bufnr
call sign_unplace(s:sign_group, { '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()\<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>']
let escaped = key ==# '<C-space>' ? '\<C-@\>' : substitute(key, '\(<\|>\)', '\\\1', 'g')
exe 'inoremap <nowait><buffer> '.key.' <Cmd>call coc#rpc#notify("PromptKeyPress", ['.bufnr.', "'.escaped.'"])<CR>'
endfor
endif
let mode = mode()
if mode ==# 'n'
call feedkeys('A', 'int')
elseif mode ==# 'i'
call feedkeys("\<end>", 'int')
else
call feedkeys("\<esc>A", 'int')
endif
let placeHolder = get(a:opts, 'placeHolder', '')
if empty(a:default) && !empty(placeHolder)
let src_id = coc#highlight#create_namespace('input-box')
call nvim_buf_set_extmark(bufnr, src_id, 0, 0, {
\ 'virt_text': [[placeHolder, 'CocInputBoxVirtualText']],
\ 'virt_text_pos': 'overlay',
\ })
endif
call coc#util#do_autocmd('CocOpenFloatPrompt')
let id = coc#float#get_related(winid, 'border')
let pos = nvim_win_get_position(id)
let dimension = [nvim_win_get_width(id), nvim_win_get_height(id), pos[0], pos[1]]
return [bufnr, winid, dimension]
endfunction
" Create float window for input
function! coc#dialog#create_prompt_win(title, default, opts) abort
call s:close_auto_hide_wins()
if s:is_vim
if !s:term_support
" use popup_menu or inputlist instead
let pickItems = get(a:opts, 'quickpick', [])
if len(pickItems) > 0
call coc#ui#quickpick(a:title, pickItems, {err, res -> s:on_quickpick_selected(err, res)})
else
call inputsave()
let value = input(a:title.':', a:default)
call inputrestore()
if empty(value)
" Cancel
call timer_start(50, { -> coc#rpc#notify('CocAutocmd', ['BufWinLeave', -1, -1])})
else
call timer_start(50, { -> coc#rpc#notify('PromptInsert', [value, -1])})
endif
endif
return [-1, -1, [0, 0, 0, 0]]
endif
return coc#dialog#_create_prompt_vim(a:title, a:default, a:opts)
endif
return coc#dialog#_create_prompt_nvim(a:title, a:default, a:opts)
endfunction
" Create list window under target window
function! coc#dialog#create_list(target, dimension, opts) abort
if a:target < 0
return [-1, -1]
endif
let maxHeight = get(a:opts, 'maxHeight', 30)
let height = get(a:opts, 'linecount', 1)
let height = min([maxHeight, height, &lines - &cmdheight - 1 - a:dimension['row'] + a:dimension['height']])
let chars = get(a:opts, 'rounded', 1) ? ['╯', '╰'] : ['┘', '└']
let width = a:dimension['width'] - 2
let config = extend(copy(a:opts), {
\ 'relative': 'editor',
\ 'row': a:dimension['row'] + a:dimension['height'],
\ 'col': a:dimension['col'],
\ 'width': width,
\ '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, 'core_width', width)
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 = 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 !s:is_vim
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 !s:is_vim
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
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]
call sign_unplace(s:sign_group, { 'buffer': s:prompt_win_bufnr })
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)
endfunction
" works on neovim only
function! coc#dialog#get_prompt_win() abort
if s:prompt_win_bufnr == 0
return -1
endif
return get(win_findbuf(s:prompt_win_bufnr), 0, -1)
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() abort
let value = getline('.')
call coc#rpc#notify('PromptInsert', [value, 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)
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_input_value(winid, bufnr, value) abort
if !coc#float#valid(a:winid)
return
endif
if win_getid() != a:winid
call win_gotoid(a:winid)
endif
if s:is_vim
if !s:term_support
call term_sendkeys(a:bufnr, "\<C-u>\<C-k>".a:value)
endif
" call timer_start(3000, { -> term_sendkeys(bufnr, "\<C-u>\<C-k>abcd")})
else
let mode = mode()
if mode ==# 'i'
call feedkeys("\<end>", 'int')
else
call feedkeys("\<esc>A", 'int')
endif
" Use complete to replace text before
let saved_completeopt = &completeopt
if saved_completeopt =~ 'menuone'
noa set completeopt=menu
endif
noa call complete(1, [{ 'empty': 1, 'word': a:value }])
call feedkeys("\<C-x>\<C-z>", 'in')
execute 'noa set completeopt='.saved_completeopt
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',
\ 'zindex': 900,
\ }
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)
let width = getwinvar(a:winid, 'core_width', 80)
let height = s:get_height(a:lines, width)
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 a:winid >= 0
if s:is_vim
call win_execute(a:winid, 'exe ' . max([a:line, 1]), 'silent!')
call popup_setoptions(a:winid, {'cursorline' : 1})
call popup_setoptions(a:winid, {'cursorline' : 0})
else
call nvim_win_set_cursor(a:winid, [max([a:line, 1]), 0])
endif
call coc#dialog#place_sign(a:bufnr, a:line)
endif
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
function! s:create_prompt_win(bufnr, title, default, opts) abort
let config = s:get_prompt_dimension(a:title, a:default, a:opts)
return coc#float#create_float_win(0, a: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', 'CocFloatBorder')],
\ }))
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 getwinvar(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:get_height(lines, width) abort
let height = 0
for line in a:lines
let height += float2nr(strdisplaywidth(line) / a:width) + 1
endfor
return max([1, height])
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
function! s:on_quickpick_selected(errMsg, res) abort
if !empty(a:errMsg)
throw a:errMsg
endif
call timer_start(50, { -> coc#rpc#notify('InputListSelect', [a:res - 1])})
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,159 @@
scriptencoding utf-8
let s:is_vim = !has('nvim')
let s:func_map = {
\ 'del_markers': 'coc#vim9#Del_markers',
\ 'buffer_update': 'coc#vim9#Buffer_update',
\ 'update_highlights': 'coc#vim9#Update_highlights',
\ 'set_highlights': 'coc#vim9#Set_highlights',
\ 'clear_highlights': 'coc#vim9#Clear_highlights',
\ 'add_highlight': 'coc#vim9#Add_highlight',
\ 'clear_all': 'coc#vim9#Clear_all',
\ 'highlight_ranges': 'coc#vim9#Highlight_ranges',
\ }
function! s:call(name, args) abort
try
if s:is_vim
call call(s:func_map[a:name], a:args)
else
call call(v:lua.require('coc.highlight')[a:name], a:args)
endif
catch /.*/
" Need try catch here on vim9
let name = s:is_vim ? get(s:func_map, a:name, a:name) : 'coc.highlight.' . a:name
call coc#compat#send_error(name, s:is_vim)
endtry
endfunction
" Update highlights of whole buffer, bufnr: number, key: any, highlights: list<any>, priority: number = 10, changedtick: any = null
function! coc#highlight#buffer_update(...) abort
call s:call('buffer_update', a:000)
endfunction
" Update highlights, id: number, key: string, highlights: list<any>, start: number = 0, end: number = -1, priority: any = null
function! coc#highlight#update_highlights(...) abort
call s:call('update_highlights', a:000)
endfunction
" Add multiple highlights, bufnr: number, key: any, highlights: list<any>, priority: number = 0
function! coc#highlight#set(...) abort
call s:call('set_highlights', a:000)
endfunction
" bufnr: number, ids: list<number>
function! coc#highlight#del_markers(...) abort
call s:call('del_markers', a:000)
endfunction
" id: number, key: any, start_line: number = 0, end_line: number = -1
function! coc#highlight#clear_highlight(...) abort
call s:call('clear_highlights', a:000)
endfunction
" Add single highlight, id: number, src_id: number, hl_group: string, line: number, col_start: number, col_end: number, opts: dict<any> = {}
function! coc#highlight#add_highlight(...) abort
call s:call('add_highlight', a:000)
endfunction
" Clear all extmark or textprop highlights of coc.nvim
function! coc#highlight#clear_all() abort
call s:call('clear_all', [])
endfunction
" highlight LSP ranges. id: number, key: any, hlGroup: string, ranges: list<any>, opts: dict<any> = {}
function! coc#highlight#ranges(...) abort
call s:call('highlight_ranges', a:000)
endfunction
" Get list of highlights, bufnr, key, [start, end] 0 based line index.
function! coc#highlight#get_highlights(bufnr, key, ...) abort
if s:is_vim
return coc#vim9#Get_highlights(a:bufnr, a:key, get(a:, 1, 0), get(a:, 2, -1))
endif
return v:lua.require('coc.highlight').get_highlights(a:bufnr, a:key, get(a:, 1, 0), get(a:, 2, -1))
endfunction
" highlight buffer in winid with CodeBlock and 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
" clear highlights
let bufnr = winbufnr(a:winid)
let kind = getwinvar(a:winid, 'kind', '')
if kind !=# 'pum'
call win_execute(a:winid, 'syntax clear')
if !empty(a:codes)
call coc#highlight#highlight_lines(a:winid, a:codes)
endif
endif
call coc#highlight#buffer_update(bufnr, -1, a:highlights)
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
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 win_execute(a:winid, cmds, 'silent!')
endif
endfunction
" add matches for window. winid, bufnr, ranges, hlGroup, priority
function! coc#highlight#match_ranges(winid, bufnr, ranges, hlGroup, priority) abort
if s:is_vim
return coc#vim9#Match_ranges(a:winid, a:bufnr, a:ranges, a:hlGroup, a:priority)
endif
return v:lua.require('coc.highlight').match_ranges(a:winid, a:bufnr, a:ranges, a:hlGroup, a:priority)
endfunction
" Clear matches by hlGroup regexp, used by extension
function! coc#highlight#clear_match_group(winid, match) abort
call coc#window#clear_match_group(a:winid, a:match)
endfunction
" Clear matches by match ids, use 0 for current win.
function! coc#highlight#clear_matches(winid, ids)
call coc#window#clear_matches(a:winid, a:ids)
endfunction
function! coc#highlight#create_namespace(key) abort
if type(a:key) == v:t_number
return a:key
endif
return coc#compat#call('create_namespace', ['coc-'. a:key])
endfunction

View file

@ -0,0 +1,140 @@
scriptencoding utf-8
function! coc#hlgroup#valid(hlGroup) abort
return hlexists(a:hlGroup) && execute('hi '.a:hlGroup, 'silent!') !~# ' cleared$'
endfunction
function! coc#hlgroup#compose(fg, bg) abort
let fgId = synIDtrans(hlID(a:fg))
let bgId = synIDtrans(hlID(a:bg))
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 = ''
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
return cmd
endfunction
" Compose hlGroups with foreground and background colors.
function! coc#hlgroup#compose_hlgroup(fgGroup, bgGroup) abort
let hlGroup = 'Fg'.a:fgGroup.'Bg'.a:bgGroup
if a:fgGroup ==# a:bgGroup
return a:fgGroup
endif
if coc#hlgroup#valid(hlGroup)
return hlGroup
endif
let cmd = coc#hlgroup#compose(a:fgGroup, a:bgGroup)
if empty(cmd)
return 'Normal'
endif
execute 'silent hi ' . hlGroup . cmd
return hlGroup
endfunction
" hlGroup id, key => 'fg' | 'bg', kind => 'cterm' | 'gui'
function! coc#hlgroup#get_color(id, key, kind) abort
if synIDattr(a:id, 'reverse', a:kind) !=# '1'
return synIDattr(a:id, a:key, a:kind)
endif
return synIDattr(a:id, a:key ==# 'bg' ? 'fg' : 'bg', a:kind)
endfunction
function! coc#hlgroup#get_hl_command(id, key, cterm, gui) abort
let cterm = coc#hlgroup#get_color(a:id, a:key, 'cterm')
let gui = coc#hlgroup#get_color(a:id, a:key, 'gui')
let cmd = ' cterm'.a:key.'=' . (empty(cterm) ? a:cterm : cterm)
let cmd .= ' gui'.a:key.'=' . (empty(gui) ? a:gui : gui)
return cmd
endfunction
function! coc#hlgroup#get_hex_color(id, kind, fallback) abort
let term_colors = s:use_term_colors()
let attr = coc#hlgroup#get_color(a:id, a:kind, term_colors ? 'cterm' : 'gui')
let hex = s:to_hex_color(attr, term_colors)
if empty(hex) && !term_colors
let attr = coc#hlgroup#get_color(a:id, a:kind, 'cterm')
let hex = s:to_hex_color(attr, 1)
endif
return empty(hex) ? a:fallback : hex
endfunction
function! coc#hlgroup#get_contrast(group1, group2) abort
let normal = coc#hlgroup#get_hex_color(synIDtrans(hlID('Normal')), 'bg', '#000000')
let bg1 = coc#hlgroup#get_hex_color(synIDtrans(hlID(a:group1)), 'bg', normal)
let bg2 = coc#hlgroup#get_hex_color(synIDtrans(hlID(a:group2)), 'bg', normal)
return coc#color#hex_contrast(bg1, bg2)
endfunction
" Darken or lighten background
function! coc#hlgroup#create_bg_command(group, amount) abort
let id = synIDtrans(hlID(a:group))
let normal = coc#hlgroup#get_hex_color(synIDtrans(hlID('Normal')), 'bg', &background ==# 'dark' ? '#282828' : '#fefefe')
let bg = coc#hlgroup#get_hex_color(id, 'bg', normal)
let hex = a:amount > 0 ? coc#color#darken(bg, a:amount) : coc#color#lighten(bg, -a:amount)
let ctermbg = coc#color#rgb2term(strpart(hex, 1))
if s:use_term_colors() && !s:check_ctermbg(id, ctermbg) && abs(a:amount) < 20.0
return coc#hlgroup#create_bg_command(a:group, a:amount * 2)
endif
return 'ctermbg=' . ctermbg.' guibg=' . hex
endfunction
function! s:check_ctermbg(id, cterm) abort
let attr = coc#hlgroup#get_color(a:id, 'bg', 'cterm')
if empty(attr)
let attr = coc#hlgroup#get_color(synIDtrans(hlID('Normal')), 'bg', 'cterm')
endif
if attr ==# a:cterm
return 0
endif
return 1
endfunction
function! s:to_hex_color(color, term) abort
if empty(a:color)
return ''
endif
if a:color =~# '^#\x\+$'
return a:color
endif
if a:term && a:color =~# '^\d\+$'
return coc#color#term2rgb(a:color)
endif
let hex = coc#color#nameToHex(tolower(a:color), a:term)
return empty(hex) ? '' : hex
endfunction
" Can't use script variable as nvim change it after VimEnter
function! s:use_term_colors() abort
return &termguicolors == 0 && !has('gui_running')
endfunction

View file

@ -0,0 +1,69 @@
scriptencoding utf-8
let s:is_vim = !has('nvim')
let s:inline_ns = coc#highlight#create_namespace('inlineSuggest')
let s:is_supported = has('patch-9.0.0185') || has('nvim-0.7')
let s:hl_group = 'CocInlineVirtualText'
let s:annot_hlgroup = 'CocInlineAnnotation'
function! coc#inline#visible() abort
return coc#vtext#exists(bufnr('%'), s:inline_ns)
endfunction
function! coc#inline#trigger(...) abort
call coc#inline#clear()
call CocActionAsync('inlineTrigger', bufnr('%'), get(a:, 1))
return ''
endfunction
function! coc#inline#cancel() abort
call coc#inline#clear()
call CocActionAsync('inlineCancel')
return ''
endfunction
function! coc#inline#accept(...) abort
if coc#inline#visible()
call CocActionAsync('inlineAccept', bufnr('%'), get(a:, 1, 'all'))
endif
return ''
endfunction
function! coc#inline#next() abort
if coc#inline#visible()
call CocActionAsync('inlineNext', bufnr('%'))
endif
return ''
endfunction
function! coc#inline#prev() abort
if coc#inline#visible()
call CocActionAsync('inlinePrev', bufnr('%'))
endif
return ''
endfunction
function! coc#inline#clear(...) abort
let bufnr = get(a:, 1, bufnr('%'))
call coc#compat#call('buf_clear_namespace', [bufnr, s:inline_ns, 0, -1])
endfunction
function! coc#inline#_insert(bufnr, lineidx, col, lines, annot) abort
if !s:is_supported || bufnr('%') != a:bufnr || mode() !~ '^i' || col('.') != a:col
return v:false
endif
call coc#inline#clear(a:bufnr)
call coc#pum#clear_vtext()
let option = {
\ 'col': a:col,
\ 'hl_mode': 'replace',
\ }
let blocks = [[a:lines[0], s:hl_group]]
if !empty(a:annot)
let blocks += [[' '], [a:annot, s:annot_hlgroup]]
endif
if len(a:lines) > 1
let option['virt_lines'] = map(a:lines[1:], {idx, line -> [[line, s:hl_group]]})
endif
call coc#vtext#add(a:bufnr, s:inline_ns, a:lineidx, blocks, option)
return v:true
endfunction

View file

@ -0,0 +1,474 @@
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'
\ }
let s:pwinid = -1
let s:pbufnr = -1
let s:sign_range = 'CocCursorLine'
let s:sign_popup_range = 'PopUpCocList'
let s:current_line_hl = 'CocListCurrent'
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', '--buffer', '--workspace-folder', '--normal', '--no-sort',
\ '--input=', '--strict', '--regex', '--interactive', '--number-select',
\ '--auto-preview', '--ignore-case', '--no-quit', '--first', '--reverse', '--height=']
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'
call coc#ui#safe_open('silent tabe', 'list:///'.a:name)
else
call s:save_views(-1)
let height = max([1, a:height])
let cmd = 'silent keepalt '.(a:position ==# 'top' ? '' : 'botright').height.'sp'
call coc#ui#safe_open(cmd, 'list:///'.a:name)
call s:set_height(height)
call s:restore_views()
endif
if a:numberSelect
setl norelativenumber
setl number
else
setl nonumber
setl norelativenumber
endif
if exists('&winfixbuf')
setl winfixbuf
endif
setl colorcolumn=""
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
setl foldcolumn=0
if exists('&cursorlineopt')
setl cursorlineopt=both
endif
if s:is_vim
setl nocursorline
else
setl cursorline
setl winhighlight=CursorLine:CocListLine
endif
setl scrolloff=0
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#close(winid, position, target_win, saved_height) abort
let tabnr = coc#window#tabnr(a:winid)
if a:position ==# 'tab'
if tabnr != -1
call coc#list#close_preview(tabnr, 0)
endif
call coc#window#close(a:winid)
else
call s:save_views(a:winid)
if tabnr != -1
call coc#list#close_preview(tabnr, 0)
endif
if type(a:target_win) == v:t_number
call win_gotoid(a:target_win)
endif
call coc#window#close(a:winid)
call s:restore_views()
if type(a:saved_height) == v:t_number
call coc#window#set_height(a:target_win, a:saved_height)
endif
" call coc#rpc#notify('Log', ["close", a:target_win, v])
endif
endfunction
function! coc#list#select(bufnr, line) abort
if s:is_vim && !empty(a:bufnr) && bufloaded(a:bufnr)
call sign_unplace(s:sign_group, { 'buffer': a:bufnr })
if a:line > 0
call sign_place(6, s:sign_group, s:current_line_hl, a:bufnr, {'lnum': a:line})
endif
endif
endfunction
" Check if previewwindow exists on current tab.
function! coc#list#has_preview()
if s:pwinid != -1 && coc#window#visible(s:pwinid)
return 1
endif
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
if s:pwinid != -1 && coc#window#visible(s:pwinid)
return s:pwinid
endif
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, floatPreview) abort
let winid = coc#list#get_preview()
if winid == -1
return
endif
if a:floatPreview
let forward = a:dir ==# 'up' ? 0 : 1
let amount = 1
if s:is_vim
call coc#float#scroll_win(winid, forward, amount)
else
call timer_start(0, { -> coc#float#scroll_win(winid, forward, amount)})
endif
return
endif
call win_execute(winid, "normal! ".(a:dir ==# 'up' ? "\<C-u>" : "\<C-d>"))
endfunction
function! coc#list#close_preview(...) abort
let tabnr = get(a:, 1, tabpagenr())
let winid = coc#list#get_preview(tabnr)
if winid != -1
let keep = get(a:, 2, 1) && tabnr == tabpagenr() && !coc#window#is_float(winid)
if keep
call s:save_views(winid)
endif
call coc#window#close(winid)
if keep
call s:restore_views()
endif
endif
endfunction
function! s:get_preview_lines(lines, config) abort
if empty(a:lines)
if get(a:config, 'scheme', 'file') !=# 'file'
let bufnr = s:load_buffer(get(a:config, 'name', ''))
return bufnr == 0 ? [''] : getbufline(bufnr, 1, '$')
else
return ['']
endif
endif
return a:lines
endfunction
function! coc#list#float_preview(lines, config) abort
let position = get(a:config, 'position', 'bottom')
if position ==# 'tab'
throw 'unable to use float preview'
endif
let remain = 0
let winrow = win_screenpos(winnr())[0]
if position ==# 'bottom'
let remain = winrow - 2
else
let winbottom = winrow + winheight(winnr())
let remain = &lines - &cmdheight - 1 - winbottom
endif
let lines = s:get_preview_lines(a:lines, a:config)
let height = s:get_preview_height(lines, a:config)
let height = min([remain, height + 2])
if height < 0
return
endif
let row = position ==# 'bottom' ? winrow - 3 - height : winrow + winheight(winnr())
let title = fnamemodify(get(a:config, 'name', ''), ':.')
let total = get(get(b:, 'list_status', {}), 'total', 0)
if !empty(total)
let title .= ' ('.line('.').'/'.total.')'
endif
let lnum = min([get(a:config, 'lnum', 1), len(lines)])
let opts = {
\ 'relative': 'editor',
\ 'width': winwidth(winnr()) - 2,
\ 'borderhighlight': 'MoreMsg',
\ 'highlight': 'Normal',
\ 'height': height,
\ 'col': 0,
\ 'index': lnum - 1,
\ 'row': row,
\ 'border': [1,1,1,1],
\ 'rounded': 1,
\ 'lines': lines,
\ 'scrollinside': 1,
\ 'title': title,
\ }
let result = coc#float#create_float_win(s:pwinid, s:pbufnr, opts)
if empty(result)
return
endif
let s:pwinid = result[0]
let s:pbufnr = result[1]
call setwinvar(s:pwinid, 'previewwindow', 1)
let topline = s:get_topline(a:config, lnum, height)
call coc#window#restview(s:pwinid, lnum, topline)
call s:preview_highlights(s:pwinid, s:pbufnr, a:config, 1)
endfunction
" Improve preview performance by reused window & buffer.
" lines - list of lines
" config.position - could be 'bottom' '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.range - (optional) highlight range. with hlGroup.
" config.hlGroup - (optional) highlight group.
" config.maxHeight - (optional) max height of window, valid for 'bottom' & 'top' position.
function! coc#list#preview(lines, config) abort
let lines = s:get_preview_lines(a:lines, a:config)
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
let lnum = get(a:config, 'lnum', 1)
let position = get(a:config, 'position', 'bottom')
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_preview_height(lines, a:config)
call s:save_views(-1)
execute 'noa '.mod.' sb +resize\ '.height.' '.bufnr
call s:restore_views()
let winid = win_getid()
endif
call setbufvar(bufnr, '&synmaxcol', 500)
noa call winrestview({"lnum": lnum ,"topline":s:get_topline(a:config, lnum, winheight(winid))})
call s:set_preview_options(winid)
noa call win_gotoid(curr)
else
let height = s:get_preview_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 s:save_views(winid)
call nvim_win_set_height(winid, height)
call s:restore_views()
endif
endif
call coc#window#restview(winid, lnum, s:get_topline(a:config, lnum, height))
endif
call s:preview_highlights(winid, bufnr, a:config, 0)
endfunction
function! s:preview_highlights(winid, bufnr, config, float) abort
let name = fnamemodify(get(a:config, 'name', ''), ':.')
let newname = s:prefix.' '.name
if newname !=# bufname(a:bufnr)
if s:is_vim
call win_execute(a:winid, 'noa file '.fnameescape(newname), 'silent!')
else
silent! noa call nvim_buf_set_name(a:bufnr, newname)
endif
endif
let filetype = get(a:config, 'filetype', '')
let extname = matchstr(name, '\.\zs[^.]\+$')
if empty(filetype) && !empty(extname)
let filetype = get(s:filetype_map, extname, '')
endif
" highlights
let sign_group = s:is_vim && a:float ? s:sign_popup_range : s:sign_range
call win_execute(a:winid, ['syntax clear', 'call clearmatches()'])
call sign_unplace(sign_group, {'buffer': a:bufnr})
let lnum = get(a:config, 'lnum', 1)
if !empty(filetype)
if get(g:, 'coc_list_preview_filetype', 0)
call win_execute(a:winid, 'setf '.filetype)
else
let start = max([0, lnum - 300])
let end = min([coc#compat#buf_line_count(a:bufnr), lnum + 300])
call coc#highlight#highlight_lines(a:winid, [{'filetype': filetype, 'startLine': start, 'endLine': end}])
call win_execute(a:winid, 'syn sync fromstart')
endif
else
call win_execute(a:winid, 'filetype detect')
let ft = getbufvar(a:bufnr, '&filetype', '')
if !empty(extname) && !empty(ft)
let s:filetype_map[extname] = ft
endif
endif
" selection range
let targetRange = get(a:config, 'targetRange', v:null)
if !empty(targetRange)
for lnum in range(targetRange['start']['line'] + 1, targetRange['end']['line'] + 1)
call sign_place(0, sign_group, s:current_line_hl, a:bufnr, {'lnum': lnum})
endfor
endif
let range = get(a:config, 'range', v:null)
if !empty(range)
let hlGroup = get(a:config, 'hlGroup', 'Search')
call coc#highlight#match_ranges(a:winid, a:bufnr, [range], hlGroup, 10)
endif
endfunction
function! s:get_preview_height(lines, config) abort
if get(a:config, 'splitRight', 0) || get(a:config, 'position', 'bottom') == '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, winheight) abort
let toplineStyle = get(a:config, 'toplineStyle', 'offset')
if toplineStyle == 'middle'
return max([1, a:lnum - a:winheight/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, '&foldenable', 0)
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
" save views on current tabpage
function! s:save_views(exclude) abort
" Not work as expected when cursor becomes hidden
if s:is_vim
return
endif
for nr in range(1, winnr('$'))
let winid = win_getid(nr)
if winid != a:exclude && getwinvar(nr, 'previewwindow', 0) == 0 && !coc#window#is_float(winid)
call win_execute(winid, 'let w:coc_list_saved_view = winsaveview()')
endif
endfor
endfunction
function! s:restore_views() abort
if s:is_vim
return
endif
for nr in range(1, winnr('$'))
let saved = getwinvar(nr, 'coc_list_saved_view', v:null)
if !empty(saved)
let winid = win_getid(nr)
call win_execute(winid, 'noa call winrestview(w:coc_list_saved_view) | unlet w:coc_list_saved_view')
endif
endfor
endfunction
function! s:set_height(height) abort
let curr = winheight(0)
if curr != a:height
execute 'resize '.a:height
endif
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,577 @@
scriptencoding utf-8
let s:is_vim = !has('nvim')
let s:utf = has('nvim') || &encoding =~# '^utf'
let s:error_icon = get(g:, 'coc_notify_error_icon', s:utf ? "\uf057" : 'E')
let s:warning_icon = get(g:, 'coc_notify_warning_icon', s:utf ? "\u26a0" : 'W')
let s:info_icon = get(g:, 'coc_notify_info_icon', s:utf ? "\uf06a" : '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 = []
let s:fn_keys = ["\<F1>","\<F2>","\<F3>","\<F4>","\<F5>","\<F6>","\<F7>","\<F8>","\<F9>"]
" 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[]]
" close - close button [boolean]
function! coc#notify#create(lines, config) abort
let actions = get(a:config, 'actions', [])
if s:is_vim
let actions = map(actions, 'v:val. "<F".(v:key + 1).">"')
endif
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
" Close duplicated window
if winid != -1
let row = getwinvar(winid, 'top', 0)
call filter(s:winids, 'v:val != '.winid)
call coc#float#close(winid, 1)
endif
let opts = coc#dict#pick(a:config, ['highlight', 'borderhighlight', 'focusable', 'shadow', 'close'])
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 - strdisplaywidth(actionText), 0])
let lines = lines + [repeat(' ', before).actionText]
let height = height + 1
call s:add_action_highlights(before, height - 1, highlights, actions)
if s:is_vim
let opts['filter'] = function('s:NotifyFilter', [len(actions)])
endif
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,
\ 'close': s:is_vim,
\ 'border': border,
\ })
let result = coc#float#create_float_win(0, 0, opts)
if empty(result)
return
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, 'borders', !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 hls = filter(coc#highlight#get_highlights(bufnr('%'), -1), "v:val[0] ==# 'CocNotificationButton'")
if empty(hls)
" Something went wrong.
return
endif
if line('.') != hls[0][1] + 1
return
endif
let col = col('.')
let line = getline('.')
for idx in range(0, len(hls) - 1)
let item = hls[idx]
let start_idx = coc#string#byte_index(line, item[2])
let end_idx = coc#string#byte_index(line, item[3])
if col > start_idx && col <= end_idx
call coc#notify#choose(a:winid, idx)
endif
endfor
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, 'borders', 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, 1)
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)
let len = s:is_vim ? stridx(text, '<') : 0
call add(a:highlights, {
\ 'lnum': a:lnum,
\ 'hlGroup': s:is_vim ? 'CocNotificationKey' : 'CocNotificationButton',
\ 'colStart': colStart + len,
\ '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#notify#choose(a:winid, a:idx - 1)
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 win_execute(a:winid, 'unlet w:timer', 'silent!')
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
let option = coc#float#get_options(a:winid)
let width = option['width']
if idx != a:index
" update percent & message
let bufnr = winbufnr(a:winid)
let percent = coc#window#get_var(a:winid, 'percent')
let lines = []
if !empty(percent)
let line = repeat(s:progress_char, width - 4).printf('%4s', percent)
let total = width - 4
call add(lines, line)
else
call add(lines, repeat(s:progress_char, width))
endif
let message = coc#window#get_var(a:winid, 'message')
if !empty(message)
let lines = lines + coc#string#reflow(split(message, '\v\r?\n'), width)
endif
if s:is_vim
noa call setbufline(bufnr, 1, lines)
noa call deletebufline(bufnr, len(lines) + 1, '$')
else
call nvim_buf_set_lines(bufnr, 0, -1, v:false, lines)
endif
let height = option['height']
let delta = len(lines) - height
if delta > 0 && height < 3
call coc#float#change_height(a:winid, min([delta, 3 - height]))
let tabnr = coc#window#tabnr(a:winid)
call coc#notify#reflow(tabnr)
if len(lines) > 3
call coc#float#nvim_scrollbar(a:winid)
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, 1)
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, 'borders', 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#hlgroup#compose_hlgroup('CocInfoSign', a:bg)}
endif
if a:kind ==# 'warning'
return {'text': s:warning_icon, 'hl': coc#hlgroup#compose_hlgroup('CocWarningSign', a:bg)}
endif
if a:kind ==# 'error'
return {'text': s:error_icon, 'hl': coc#hlgroup#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
function! coc#notify#choose(winid, idx) abort
call s:cancel(a:winid, 'close_timer')
call coc#rpc#notify('FloatBtnClick', [winbufnr(a:winid), a:idx])
call coc#notify#close(a:winid)
endfunction
function! s:NotifyFilter(count, winid, key) abort
let max = min([a:count, 9])
for idx in range(1, max)
if a:key == s:fn_keys[idx - 1]
call coc#notify#choose(a:winid, idx - 1)
return 1
endif
endfor
return 0
endfunction

View file

@ -0,0 +1,219 @@
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-space>": '<C-space>',
\ "\<C-_>": '<C-_>',
\ "\<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>',
\ "\<A-bs>": '<A-bs>',
\ }
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 !s:is_vim && !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>', 0])
let s:session_names = []
call s:reset()
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 !s:is_vim
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,613 @@
scriptencoding utf-8
let s:is_vim = !has('nvim')
let s:pum_bufnr = 0
let s:pum_winid = -1
let s:pum_index = -1
let s:pum_size = 0
" word of complete item inserted
let s:inserted = 0
let s:virtual_text = 0
let s:virtual_text_ns = coc#highlight#create_namespace('pum-virtual')
" bufnr, &indentkeys
let s:saved_indenetkeys = []
let s:saved_textwidth = []
let s:prop_id = 0
let s:reversed = 0
let s:check_hl_group = 0
let s:start_col = -1
if s:is_vim
if empty(prop_type_get('CocPumVirtualText'))
call prop_type_add('CocPumVirtualText', {'highlight': 'CocPumVirtualText'})
endif
endif
function! coc#pum#has_item_selected() abort
return coc#pum#visible() && s:pum_index != -1
endfunction
function! coc#pum#visible() abort
if s:pum_winid == -1
return 0
endif
" getwinvar check current tab only.
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, 1)
endif
endfunction
" kind, and skipRequest (default to false)
function! coc#pum#close(...) abort
if coc#pum#visible()
let inserted = 0
let kind = get(a:, 1, '')
if kind ==# 'cancel'
let input = getwinvar(s:pum_winid, 'input', '')
let s:pum_index = -1
let inserted = s:insert_word(input, 1)
call s:on_pum_change(0)
elseif kind ==# 'confirm'
let words = getwinvar(s:pum_winid, 'words', [])
if s:pum_index >= 0
let word = get(words, s:pum_index, '')
let inserted = s:insert_word(word, 1)
" have to restore here, so that TextChangedI can trigger indent.
call s:restore_indentkeys()
endif
endif
call s:close_pum()
if !get(a:, 2, 0)
" Needed to wait TextChangedI fired
if inserted
call timer_start(0, {-> coc#rpc#request('stopCompletion', [kind])})
else
call coc#rpc#request('stopCompletion', [kind])
endif
endif
endif
return ''
endfunction
function! coc#pum#select_confirm() abort
if coc#pum#visible()
if s:pum_index < 0
let s:pum_index = 0
call s:on_pum_change(0)
endif
" Avoid change of text not allowed
return "\<C-r>=coc#pum#close('confirm')\<CR>"
endif
return ''
endfunction
function! coc#pum#_close() abort
if coc#pum#visible()
call s:close_pum()
if s:is_vim
call timer_start(0, {-> execute('redraw')})
endif
endif
endfunction
function! coc#pum#_one_more() abort
if coc#pum#visible()
let parts = getwinvar(s:pum_winid, 'parts', [])
let start = strlen(parts[0])
let input = strpart(getline('.'), start, col('.') - 1 - start)
let words = getwinvar(s:pum_winid, 'words', [])
let word = get(words, s:pum_index == -1 ? 0 : s:pum_index, '')
if !empty(word) && strcharpart(word, 0, strchars(input)) ==# input
let ch = strcharpart(word, strchars(input), 1)
if !empty(ch)
call feedkeys(ch, "nt")
endif
endif
endif
return ''
endfunction
function! coc#pum#_insert() abort
if coc#pum#visible()
if s:pum_index >= 0
let words = getwinvar(s:pum_winid, 'words', [])
let word = get(words, s:pum_index, '')
call s:insert_word(word, 1)
call s:restore_indentkeys()
endif
doautocmd <nomodeline> TextChangedI
call s:close_pum()
call timer_start(0, {-> coc#rpc#request('stopCompletion', [''])})
endif
return ''
endfunction
function! coc#pum#insert() abort
return "\<C-r>=coc#pum#_insert()\<CR>"
endfunction
" Add one more character from the matched complete item(or first one),
" the word should starts with input, the same as vim's CTRL-L behavior.
function! coc#pum#one_more() abort
return "\<C-r>=coc#pum#_one_more()\<CR>"
endfunction
function! coc#pum#next(insert) abort
return "\<C-r>=coc#pum#_navigate(1,".a:insert.")\<CR>"
endfunction
function! coc#pum#prev(insert) abort
return "\<C-r>=coc#pum#_navigate(0,".a:insert.")\<CR>"
endfunction
function! coc#pum#stop() abort
return "\<C-r>=coc#pum#close()\<CR>"
endfunction
function! coc#pum#cancel() abort
return "\<C-r>=coc#pum#close('cancel')\<CR>"
endfunction
function! coc#pum#confirm() abort
return "\<C-r>=coc#pum#close('confirm')\<CR>"
endfunction
function! coc#pum#select(index, insert, confirm) abort
if coc#pum#visible()
if a:index == -1
call coc#pum#close('cancel')
return ''
endif
if a:index < 0 || a:index >= s:pum_size
throw 'index out of range ' . a:index
endif
if a:confirm
if s:pum_index != a:index
let s:pum_index = a:index
let s:inserted = 1
call s:on_pum_change(0)
endif
call coc#pum#close('confirm')
else
call s:select_by_index(a:index, a:insert)
endif
endif
return ''
endfunction
function! coc#pum#info() abort
let bufnr = winbufnr(s:pum_winid)
let words = getwinvar(s:pum_winid, 'words', [])
let word = s:pum_index < 0 ? '' : get(words, s:pum_index, '')
let base = {
\ 'word': word,
\ 'index': s:pum_index,
\ 'size': s:pum_size,
\ 'startcol': s:start_col,
\ 'inserted': s:pum_index >=0 && s:inserted ? v:true : v:false,
\ 'reversed': s:reversed ? v:true : v:false,
\ }
if s:is_vim
let pos = popup_getpos(s:pum_winid)
let border = has_key(popup_getoptions(s:pum_winid), 'border')
let add = pos['scrollbar'] && border ? 1 : 0
return extend(base, {
\ 'scrollbar': pos['scrollbar'],
\ 'row': pos['line'] - 1,
\ 'col': pos['col'] - 1,
\ 'width': pos['width'] + add,
\ 'height': pos['height'],
\ 'border': border,
\ })
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 extend(base, {
\ '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),
\ 'border': winid != s:pum_winid,
\ })
endif
endfunction
function! coc#pum#scroll(forward) abort
if coc#pum#visible()
let height = s:get_height(s:pum_winid)
if s:pum_size > height
call timer_start(1, { -> s:scroll_pum(a:forward, height, s:pum_size)})
endif
endif
" Required on old version vim/neovim.
return "\<Ignore>"
endfunction
function! s:get_height(winid) abort
if s:is_vim
return get(popup_getpos(a:winid), 'core_height', 0)
endif
return nvim_win_get_height(a:winid)
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 s:is_vim
let pos = popup_getpos(a:winid)
return pos['firstline']
endif
let info = getwininfo(a:winid)[0]
return info['topline']
endfunction
function! coc#pum#_navigate(next, insert) abort
if coc#pum#visible()
call s:save_indentkeys()
let index = s:get_index(a:next)
call s:select_by_index(index, a:insert)
call coc#rpc#notify('PumNavigate', [bufnr('%')])
endif
return ''
endfunction
function! s:select_by_index(index, insert) abort
let lnum = a:index == -1 ? 0 : s:index_to_lnum(a:index)
call s:set_cursor(s:pum_winid, lnum)
if !s:is_vim
call coc#float#nvim_scrollbar(s:pum_winid)
endif
if a:insert
let s:inserted = a:index >= 0
if a:index < 0
let input = getwinvar(s:pum_winid, 'input', '')
call s:insert_word(input, 0)
call coc#pum#close_detail()
else
let words = getwinvar(s:pum_winid, 'words', [])
let word = get(words, a:index, '')
call s:insert_word(word, 0)
endif
endif
call s:on_pum_change(1)
endfunction
function! s:get_index(next) abort
if a:next
let index = s:pum_index + 1 == s:pum_size ? -1 : s:pum_index + 1
else
let index = s:pum_index == -1 ? s:pum_size - 1 : s:pum_index - 1
endif
return index
endfunction
function! s:insert_word(word, finish) abort
if s:start_col != -1 && mode() ==# 'i'
" Not insert same characters
let inserted = strpart(getline('.'), s:start_col, col('.') - 1)
if inserted !=# a:word
" avoid auto wrap using 'textwidth'
if !a:finish && &textwidth > 0
let textwidth = &textwidth
noa setl textwidth=0
call timer_start(0, { -> execute('noa setl textwidth='.textwidth)})
endif
let saved_completeopt = &completeopt
noa set completeopt=noinsert,noselect
noa call complete(s:start_col + 1, [{ 'empty': v:true, 'word': a:word }])
noa call feedkeys("\<C-n>\<C-x>\<C-z>", 'in')
call timer_start(0, { -> execute('noa set completeopt='.saved_completeopt)})
return 1
endif
endif
return 0
endfunction
" Replace from col to cursor col with new characters
function! coc#pum#replace(col, insert, delta) abort
if a:delta == 1
call feedkeys("\<right>", 'in')
endif
let saved_completeopt = &completeopt
noa set completeopt=noinsert,noselect
noa call complete(a:col, [{ 'empty': v:true, 'word': a:insert }])
noa call feedkeys("\<C-n>\<C-x>\<C-z>", 'n')
execute 'noa set completeopt='.saved_completeopt
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:reversed = get(a:config, 'reverse', 0) && config['row'] < 0
let s:virtual_text = get(a:opt, 'virtualText', v:false)
let s:pum_size = len(a:lines)
let s:pum_index = a:opt['index']
let lnum = s:index_to_lnum(s:pum_index)
call extend(config, {
\ 'lines': s:reversed ? reverse(copy(a:lines)) : a:lines,
\ 'relative': 'cursor',
\ 'nopad': 1,
\ 'cursorline': 1,
\ 'index': lnum - 1,
\ 'focusable': v:false
\ })
call extend(config, coc#dict#pick(a:config, ['highlight', 'rounded', 'highlights', 'winblend', 'shadow', 'border', 'borderhighlight', 'title']))
if s:reversed
for item in config['highlights']
let item['lnum'] = s:pum_size - item['lnum'] - 1
endfor
endif
if empty(get(config, 'winblend', 0)) && exists('&pumblend')
let config['winblend'] = &pumblend
endif
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]
let s:start_col = a:opt['startcol']
call setwinvar(s:pum_winid, 'above', config['row'] < 0)
let firstline = s:get_firstline(lnum, s:pum_size, config['height'])
if s:is_vim
call popup_setoptions(s:pum_winid, { 'firstline': firstline })
else
call win_execute(s:pum_winid, 'call winrestview({"lnum":'.lnum.',"topline":'.firstline.'})')
endif
call coc#dialog#place_sign(s:pum_bufnr, s:pum_index == -1 ? 0 : lnum)
" content before col and content after cursor
let linetext = getline('.')
let parts = [strpart(linetext, 0, s:start_col), strpart(linetext, col('.') - 1)]
let input = strpart(getline('.'), s:start_col, col('.') - 1 - s:start_col)
call setwinvar(s:pum_winid, 'input', input)
call setwinvar(s:pum_winid, 'parts', parts)
call setwinvar(s:pum_winid, 'words', a:opt['words'])
call setwinvar(s:pum_winid, 'kind', 'pum')
if !s:is_vim
if s:pum_size > config['height']
call timer_start(0,{ -> coc#float#nvim_scrollbar(s:pum_winid)})
else
call coc#float#close_related(s:pum_winid, 'scrollbar')
endif
endif
call s:on_pum_change(0)
endfunction
function! s:save_indentkeys() abort
let bufnr = bufnr('%')
if !empty(&indentexpr) && get(s:saved_indenetkeys, 0, 0) != bufnr
let s:saved_indenetkeys = [bufnr, &indentkeys]
execute 'setl indentkeys='
endif
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 s:virtual_text
if s:inserted
call coc#pum#clear_vtext()
else
call s:insert_virtual_text()
endif
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])
endfunction
function! s:index_to_lnum(index) abort
if s:reversed
if a:index <= 0
return s:pum_size
endif
return s:pum_size - a:index
endif
return max([1, a:index + 1])
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 columns = &columns
let pumwidth = max([15, exists('&pumwidth') ? &pumwidth : 0])
let width = min([columns, max([pumwidth, 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]) && vh - lineIdx < min([10, vh/2])
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
" should use strdiplaywidth here
let text = strpart(getline('.'), a:col, col('.') - 1 - a:col)
let col = - strdisplaywidth(text, a:col) - 1
let row = showTop ? - height : 1
let delta = colIdx + col
if width > pumwidth && delta + width > columns
let width = max([columns - delta, pumwidth])
endif
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 core_height = pos['core_height']
let lastline = pos['firstline'] + core_height - 1
if a:line > lastline
call popup_setoptions(a:winid, {
\ 'firstline': pos['firstline'] + a:line - lastline,
\ })
elseif a:line < pos['firstline']
if s:reversed
call popup_setoptions(a:winid, {
\ 'firstline': a:line == 0 ? s:pum_size - core_height + 1 : a:line - core_height + 1,
\ })
else
call popup_setoptions(a:winid, {
\ 'firstline': max([1, a:line]),
\ })
endif
endif
endif
call s:select_line(a:winid, a:line)
endfunction
function! s:select_line(winid, line) abort
let s:pum_index = s:reversed ? (a:line == 0 ? -1 : s:pum_size - a:line) : a:line - 1
let lnum = s:reversed ? (a:line == 0 ? s:pum_size : a:line) : max([1, a:line])
if s:is_vim
call win_execute(a:winid, 'exe '.lnum)
else
call nvim_win_set_cursor(a:winid, [lnum, 0])
endif
call coc#dialog#place_sign(s:pum_bufnr, a:line == 0 ? 0 : lnum)
endfunction
function! s:insert_virtual_text() abort
let bufnr = bufnr('%')
if !s:virtual_text || s:pum_index < 0
call coc#pum#clear_vtext()
else
" Check if could create
let insert = ''
let line = line('.') - 1
let words = getwinvar(s:pum_winid, 'words', [])
let word = get(words, s:pum_index, '')
let input = strpart(getline('.'), s:start_col, col('.') - 1 - s:start_col)
if strlen(word) > strlen(input) && strcharpart(word, 0, strchars(input)) ==# input
let insert = strcharpart(word, strchars(input))
endif
if s:is_vim
if s:prop_id != 0
call prop_remove({'id': s:prop_id}, line + 1, line + 1)
endif
if !empty(insert)
let s:prop_id = prop_add(line + 1, col('.'), {
\ 'text': insert,
\ 'type': 'CocPumVirtualText'
\ })
endif
else
call nvim_buf_clear_namespace(bufnr, s:virtual_text_ns, line, line + 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, col('.') - 1, opts)
endif
endif
endif
endfunction
function! coc#pum#clear_vtext() abort
if s:is_vim
if s:prop_id != 0
call prop_remove({'id': s:prop_id})
endif
let s:prop_id = 0
else
call nvim_buf_clear_namespace(bufnr('%'), s:virtual_text_ns, 0, -1)
endif
endfunction
function! s:close_pum() abort
call coc#pum#clear_vtext()
call coc#float#close(s:pum_winid, 1)
let s:pum_winid = 0
let s:pum_size = 0
let winid = coc#float#get_float_by_kind('pumdetail')
if winid
call coc#float#close(winid, 1)
endif
call s:restore_indentkeys()
endfunction
function! s:restore_indentkeys() abort
if get(s:saved_indenetkeys, 0, 0) == bufnr('%')
call setbufvar(s:saved_indenetkeys[0], '&indentkeys', get(s:saved_indenetkeys, 1, ''))
let s:saved_indenetkeys = []
endif
endfunction

View file

@ -0,0 +1,237 @@
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')
let s:chan_id = 0
let s:root = expand('<sfile>:h:h:h')
function! coc#rpc#start_server()
let test = get(g:, 'coc_node_env', '') ==# 'test'
if test && !s:is_vim && !exists('$COC_NVIM_REMOTE_ADDRESS')
" server already started, chan_id could be available later
let s:client = coc#client#create(s:name, [])
let s:client['running'] = s:chan_id != 0
let s:client['chan_id'] = s:chan_id
return
endif
if exists('$COC_NVIM_REMOTE_ADDRESS')
let address = $COC_NVIM_REMOTE_ADDRESS
if s:is_vim
let s:client = coc#client#create(s:name, [])
" TODO don't know if vim support named pipe on windows.
let address = address =~# ':\d\+$' ? address : 'unix:'.address
let channel = ch_open(address, {
\ 'mode': 'json',
\ 'close_cb': {channel -> s:on_channel_close()},
\ 'noblock': 1,
\ 'timeout': 1000,
\ })
if ch_status(channel) == 'open'
let s:client['running'] = 1
let s:client['channel'] = channel
endif
else
let s:client = coc#client#create(s:name, [])
try
let mode = address =~# ':\d\+$' ? 'tcp' : 'pipe'
let chan_id = sockconnect(mode, address, { 'rpc': 1 })
if chan_id > 0
let s:client['running'] = 1
let s:client['chan_id'] = chan_id
endif
catch /connection\ refused/
" ignore
endtry
endif
if !s:client['running']
echohl Error | echom '[coc.nvim] Unable connect to '.address.' from variable $COC_NVIM_REMOTE_ADDRESS' | echohl None
elseif !test
let logfile = exists('$NVIM_COC_LOG_FILE') ? $NVIM_COC_LOG_FILE : ''
let loglevel = exists('$NVIM_COC_LOG_LEVEL') ? $NVIM_COC_LOG_LEVEL : ''
let runtimepath = join(coc#compat#list_runtime_paths(), ",")
let data = [coc#util#win32unix_to_node(s:root), coc#util#get_data_home(), coc#util#get_config_home(), logfile, loglevel, runtimepath]
if s:is_vim
call ch_sendraw(s:client['channel'], json_encode(data)."\n")
else
call call('rpcnotify', [s:client['chan_id'], 'init'] + data)
endif
endif
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
call s:check_vim_enter()
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
" Used for test on neovim only
function! coc#rpc#set_channel(chan_id) abort
let s:chan_id = a:chan_id
let s:client['running'] = a:chan_id != 0
let s:client['chan_id'] = a:chan_id
endfunction
function! coc#rpc#get_channel() abort
if empty(s:client)
return v:null
endif
return coc#client#get_channel(s:client)
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#show_errors()
let client = coc#client#get_client('coc')
if !empty(client)
let lines = get(client, 'stderr', [])
keepalt new +setlocal\ buftype=nofile [Stderr of coc.nvim]
setl noswapfile wrap bufhidden=wipe nobuflisted nospell
call append(0, lines)
exe "normal! z" . len(lines) . "\<cr>"
exe "normal! gg"
endif
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#clearGroups('coc_dynamic_')
call coc#rpc#request('detach', [])
if !empty(get(g:, 'coc_status', ''))
unlet g:coc_status
endif
let g:coc_service_initialized = 0
sleep 100m
if exists('$COC_NVIM_REMOTE_ADDRESS')
call coc#rpc#close_connection()
sleep 100m
call coc#rpc#start_server()
else
let s:client['command'] = coc#util#job_command()
call coc#client#restart(s:name)
call s:check_vim_enter()
endif
echohl MoreMsg | echom 'starting coc.nvim service' | echohl None
endif
endfunction
function! coc#rpc#close_connection() abort
let channel = coc#rpc#get_channel()
if channel == v:null
return
endif
if s:is_vim
" Unlike neovim, vim not close the socket as expected.
call ch_close(channel)
else
call chanclose(channel)
endif
let s:client['running'] = 0
let s:client['channel'] = v:null
let s:client['chan_id'] = 0
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 call(a: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
function! s:check_vim_enter() abort
if s:client['running'] && v:vim_did_enter
call coc#rpc#notify('VimEnter', [join(coc#compat#list_runtime_paths(), ",")])
endif
endfunction
" Used on vim and remote address only
function! s:on_channel_close() abort
if get(g:, 'coc_node_env', '') !=# 'test'
echohl Error | echom '[coc.nvim] channel closed' | echohl None
endif
if !empty(s:client)
let s:client['running'] = 0
let s:client['channel'] = v:null
let s:client['async_req_id'] = 1
endif
endfunction

View file

@ -0,0 +1,170 @@
scriptencoding utf-8
let s:is_vim = !has('nvim')
let s:map_next = 1
let s:map_prev = 1
function! coc#snippet#_select_mappings(bufnr)
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
call coc#compat#buf_del_keymap(a:bufnr, 's', 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, position, input) abort
call coc#snippet#move(a:position)
call CocActionAsync('startCompletion', {
\ 'source': '$words',
\ 'col': a:col
\ })
redraw
endfunction
function! coc#snippet#enable(...)
let bufnr = get(a:, 1, bufnr('%'))
if getbufvar(bufnr, 'coc_snippet_active', 0) == 1
return
endif
let complete = get(a:, 2, 0)
call setbufvar(bufnr, 'coc_snippet_active', 1)
call coc#snippet#_select_mappings(bufnr)
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
call s:buf_add_keymap(bufnr, 'i', nextkey, "<Cmd>:call coc#snippet#jump(1, ".complete.")<cr>")
endif
call s:buf_add_keymap(bufnr, 's', nextkey, "<Cmd>:call coc#snippet#jump(1, ".complete.")<cr>")
endif
if !empty(prevkey)
if s:map_prev
call s:buf_add_keymap(bufnr, 'i', prevkey, "<Cmd>:call coc#snippet#jump(0, ".complete.")<cr>")
endif
call s:buf_add_keymap(bufnr, 's', prevkey, "<Cmd>:call coc#snippet#jump(0, ".complete.")<cr>")
endif
endfunction
function! coc#snippet#disable(...)
let bufnr = get(a:, 1, bufnr('%'))
if getbufvar(bufnr, 'coc_snippet_active', 0) == 0
return
endif
call setbufvar(bufnr, '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
call coc#compat#buf_del_keymap(bufnr, 'i', nextkey)
endif
if s:map_prev
call coc#compat#buf_del_keymap(bufnr, 'i', prevkey)
endif
call coc#compat#buf_del_keymap(bufnr, 's', nextkey)
call coc#compat#buf_del_keymap(bufnr, 's', prevkey)
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
if pumvisible()
let pre = exists('*complete_info') && complete_info()['selected'] == -1 ? "\<C-n>" : ''
call feedkeys(pre."\<C-y>", 'in')
return ''
endif
if coc#pum#visible()
" Discard the return value, otherwise weird characters will be inserted
call coc#pum#close('confirm')
return ''
endif
endif
call coc#pum#close()
call coc#rpc#request(a:direction == 1 ? 'snippetNext' : 'snippetPrev', [])
return ''
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('zvv%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>".(col('.') == 1 ? '' : 'l') : ''
let cmd .= printf('zvv%s', len > 0 ? len . 'h' : '')
let cmd .= "o\<C-g>"
endif
if s:is_vim
" Can't use 't' since the code of <esc> can be changed.
call feedkeys(cmd, 'n')
else
call feedkeys(cmd, 'nt')
endif
endfunction
function! coc#snippet#move(position) abort
let m = mode()
if m ==? 's'
call feedkeys("\<Esc>", 'in')
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, coc#string#byte_index(line, a:position.character) + 1]
endfunction
function! s:buf_add_keymap(bufnr, mode, lhs, rhs) abort
let opts = {'nowait': v:true, 'silent': v:true}
call coc#compat#buf_add_keymap(a:bufnr, a:mode, a:lhs, a:rhs, opts)
endfunction

View file

@ -0,0 +1,149 @@
scriptencoding utf-8
function! coc#string#last_character(line) abort
return strcharpart(a:line, strchars(a:line) - 1, 1)
endfunction
" Get utf16 code unit index from col (0 based)
function! coc#string#character_index(line, byteIdx) abort
if a:byteIdx <= 0
return 0
endif
let i = 0
for char in split(strpart(a:line, 0, a:byteIdx), '\zs')
let i += char2nr(char) > 65535 ? 2 : 1
endfor
return i
endfunction
" Convert utf16 character index to byte index
function! coc#string#byte_index(line, character) abort
if a:character <= 0
return 0
endif
" code unit index
let i = 0
let len = 0
for char in split(a:line, '\zs')
let i += char2nr(char) > 65535 ? 2 : 1
let len += strlen(char)
if i >= a:character
break
endif
endfor
return len
endfunction
function! coc#string#character_length(text) abort
let i = 0
for char in split(a:text, '\zs')
let i += char2nr(char) > 65535 ? 2 : 1
endfor
return i
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
" Used when 'wrap' and 'linebreak' is enabled
function! coc#string#content_height(lines, width) abort
let len = 0
let pattern = empty(&breakat) ? '.\zs' : '['.substitute(&breakat, '\([\[\]\-]\)', '\\\1', 'g').']\zs'
for line in a:lines
if strwidth(line) <= a:width
let len += 1
else
let currlen = 0
for part in split(line, pattern)
let wl = strwidth(part)
if currlen == 0 && wl > 0
let len += 1
endif
let delta = currlen + wl - a:width
if delta >= 0
let len = len + (delta > 0)
let currlen = delta == 0 ? 0 : wl
if wl >= a:width
let currlen = wl%a:width
let len += float2nr(ceil(wl/(a:width + 0.0))) - (currlen == 0)
endif
else
let currlen = currlen + wl
endif
endfor
endif
endfor
return len
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,162 @@
" ============================================================================
" 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,
\ 'noblock' : 1,
\ '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 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),
\ 'env': env,
\}
if get(a:opts, 'pty', 0)
let options['pty'] = 1
endif
let chan_id = jobstart(cmd, options)
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 !s:is_vim
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,150 @@
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('&winfixbuf')
setl winfixbuf
endif
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 s:is_vim
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]
else
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)]
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 s:is_vim
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
else
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 win_execute(winid, 'noa normal! G')
endif
endif
endfunction
function! coc#terminal#close(bufnr) abort
if !s:is_vim
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
function! coc#terminal#show(bufnr, opts) abort
if !bufloaded(a:bufnr)
return v:false
endif
let winids = win_findbuf(a:bufnr)
if index(winids, win_getid()) != -1
execute 'normal! G'
return v:true
endif
let curr_winid = -1
for winid in winids
if get(get(getwininfo(winid), 0, {}), 'tabnr', 0) == tabpagenr()
let curr_winid = winid
else
call coc#window#close(winid)
endif
endfor
let height = get(a:opts, 'height', 8)
if curr_winid == -1
execute 'below '.a:bufnr.'sb'
execute 'resize '.height
call coc#util#do_autocmd('CocTerminalOpen')
else
call win_gotoid(curr_winid)
endif
execute 'normal! G'
if get(a:opts, 'preserveFocus', v:false)
execute 'wincmd p'
endif
return v:true
endfunction

View file

@ -0,0 +1,239 @@
vim9script
export def LinesEqual(one: list<string>, two: list<string>): bool
if len(one) != len(two)
return false
endif
for i in range(0, len(one) - 1)
if one[i] !=# two[i]
return false
endif
endfor
return true
enddef
# Slice like javascript by character index
export def Slice(str: string, start_idx: number, end_idx: any = null): string
if end_idx == null
return str[start_idx : ]
endif
if start_idx >= end_idx
return ''
endif
return str[start_idx : end_idx - 1]
enddef
# Function to check if a string starts with a given prefix
export def StartsWith(str: string, prefix: string): bool
return str =~# '^' .. prefix
enddef
# Function to check if a string ends with a given suffix
export def EndsWith(str: string, suffix: string): bool
return str =~# suffix .. '$'
enddef
# UTF16 character index in line to byte index.
export def Byte_index(line: string, character: number): number
if character == 0
return 0
endif
var i = 0
var len = 0
for char in split(line, '\zs')
i += char2nr(char) > 65535 ? 2 : 1
len += strlen(char)
if i >= character
break
endif
endfor
return len
enddef
# Character index of current vim encoding.
export def Char_index(line: string, colIdx: number): number
return strpart(line, 0, colIdx)->strchars()
enddef
# Using character indexes
export def LcsDiff(str1: string, str2: string): list<dict<any>>
def Lcs(a: string, b: string): string
var matrix = []
for i in range(0, strchars(a))
matrix[i] = []
for j in range(0, strchars(b))
if i == 0 || j == 0
matrix[i][j] = 0
elseif a[i] == b[j]
matrix[i][j] = matrix[i - 1][j - 1] + 1
else
matrix[i][j] = max([matrix[i - 1][j], matrix[i][j - 1]])
endif
endfor
endfor
var result = ''
var i = strchars(a) - 1
var j = strchars(b) - 1
while i >= 0 && j >= 0
if a[i] == b[j]
result = a[i] .. result
i -= 1
j -= 1
elseif matrix[i - 1][j] > matrix[i][j - 1]
i -= 1
else
j -= 1
endif
endwhile
return result
enddef
const len1 = strchars(str1)
const len2 = strchars(str2)
var common = Lcs(str1, str2)
var result = []
var i1 = 0
var i2 = 0
var ic = 0
while ic < strchars(common)
# 处理str1中不在公共序列的部分
while i1 < len1 && str1[i1] != common[ic]
result->add({type: '-', char: str1[i1]})
i1 += 1
endwhile
# 处理str2中不在公共序列的部分
while i2 < len2 && str2[i2] != common[ic]
result->add({type: '+', char: str2[i2]})
i2 += 1
endwhile
# 添加公共字符
if ic < strchars(common)
result->add({type: '=', char: common[ic]})
i1 += 1
i2 += 1
ic += 1
endif
endwhile
# 处理剩余字符
while i1 < len1
result->add({type: '-', char: str1[i1]})
i1 += 1
endwhile
while i2 < len2
result->add({type: '+', char: str2[i2]})
i2 += 1
endwhile
return result
enddef
# Get the single changed part, by character index of cursor.
def SimpleStringDiff(oldStr: string, newStr: string, charIdx: number = -1): dict<any>
var suffixLen = 0
const old_length = strchars(oldStr)
const new_length = strchars(newStr)
var maxSuffixLen = 0
if charIdx >= 0
maxSuffixLen = min([old_length, new_length - charIdx])
while suffixLen < maxSuffixLen
if strcharpart(oldStr, old_length - suffixLen - 1, 1) !=
strcharpart(newStr, new_length - suffixLen - 1, 1)
break
endif
suffixLen += 1
endwhile
else
maxSuffixLen = min([old_length, new_length])
while suffixLen < maxSuffixLen
if strcharpart(oldStr, old_length - suffixLen - 1, 1) !=
strcharpart(newStr, new_length - suffixLen - 1, 1)
break
endif
suffixLen += 1
endwhile
endif
var prefixLen = 0
var remainingLen = min([old_length - suffixLen, new_length - suffixLen])
while prefixLen < remainingLen
if strcharpart(oldStr, prefixLen, 1) != strcharpart(newStr, prefixLen, 1)
break
endif
prefixLen += 1
endwhile
# Reduce suffixLen
if suffixLen == new_length - charIdx
const max = min([old_length, new_length]) - prefixLen - suffixLen
var i = 0
while i < max
if strcharpart(oldStr, old_length - suffixLen - 1, 1) !=
strcharpart(newStr, new_length - suffixLen - 1, 1)
break
endif
suffixLen += 1
i += 1
endwhile
endif
const endIndex = old_length - suffixLen
echo suffixLen
return {
oldStart: prefixLen,
oldEnd: endIndex,
newText: Slice(newStr, prefixLen, new_length - suffixLen),
}
enddef
# Search for new start position of diff in new string
export def SearchChangePosition(newStr: string, oldStr: string, diff: dict<any>): number
var result = -1
const delta = diff.oldEnd - diff.oldStart
const oldText = Slice(oldStr, diff.oldStart, diff.oldEnd)
def CheckPosition(idx: number): bool
if delta == 0 || Slice(newStr, idx, idx + delta) ==# oldText
result = idx
return true
endif
return false
enddef
if Slice(oldStr, 0, diff.oldStart) ==# Slice(newStr, 0, diff.oldStart) && CheckPosition(diff.oldStart)
return result
endif
const diffs = LcsDiff(oldStr, newStr)
# oldStr index
var used = 0
# newStr index
var index = 0
# Until used reached diff.oldStart
var i = 0
for d in diffs
if d.type ==# '-'
used += 1
elseif d.type ==# '+'
index += 1
else
used += 1
index += 1
endif
if used == diff.oldStart && CheckPosition(index)
break
endif
endfor
return result
enddef
# 0 based start index and end index
export def SimpleApplyDiff(text: string, startIdx: number, endIdx: number, insert: string): string
return Slice(text, 0, startIdx) .. insert .. Slice(text, endIdx)
enddef
# Apply change from original to current for newText
export def DiffApply(original: string, current: string, newText: string, colIdx: number): any
if original ==# current
return newText
endif
const charIdx = colIdx == -1 ? -1 : Char_index(current, colIdx)
const diff = SimpleStringDiff(original, current, charIdx)
const delta = diff.oldEnd - diff.oldStart
const idx = SearchChangePosition(newText, original, diff)
if idx == -1
return null
endif
return SimpleApplyDiff(newText, idx, idx + delta, diff.newText)
enddef

View file

@ -0,0 +1,544 @@
let s:is_vim = !has('nvim')
let s:is_win = has('win32') || has('win64')
let s:is_mac = has('mac')
let s:root = expand('<sfile>:h:h:h')
let s:sign_api = exists('*sign_getplaced') && exists('*sign_place')
let s:sign_groups = []
let s:outline_preview_bufnr = 0
let s:is_win32unix = has('win32unix')
" Check <Tab> and <CR>
function! coc#ui#check_pum_keymappings(trigger) abort
if get(g:, 'coc_disable_mappings_check', 0) == 1
return
endif
if a:trigger !=# 'none'
for key in ['<cr>', '<tab>', '<c-y>', '<s-tab>']
let arg = maparg(key, 'i', 0, 1)
if get(arg, 'expr', 0)
let rhs = get(arg, 'rhs', '')
if rhs =~# '\<pumvisible()' && rhs !~# '\<coc#pum#visible()'
let rhs = substitute(rhs, '\Cpumvisible()', 'coc#pum#visible()', 'g')
let rhs = substitute(rhs, '\c"\\<C-n>"', 'coc#pum#next(1)', '')
let rhs = substitute(rhs, '\c"\\<C-p>"', 'coc#pum#prev(1)', '')
let rhs = substitute(rhs, '\c"\\<C-y>"', 'coc#pum#confirm()', '')
execute 'inoremap <silent><nowait><expr> '.arg['lhs'].' '.rhs
endif
endif
endfor
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] + map(range(1, len(a:items)), 'v:val . ". " . a:items[v:val - 1]'))
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 s:is_vim
if s:is_win
let cmd = 'cmd.exe /C "'.cmd.'"'
endif
call term_start(cmd, {
\ 'cwd': cwd,
\ 'term_finish': 'close',
\ 'exit_cb': {job, status -> s:OnExit(status)},
\ 'curwin': 1,
\})
else
call termopen(cmd, {
\ 'cwd': cwd,
\ 'on_exit': {job, status -> s:OnExit(status)},
\})
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': empty(get(a:opts, 'cwd', '')) ? getcwd() : a:opts['cwd'],
\ '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#fix() abort
let file = s:root .. '/esbuild.js'
if filereadable(file)
let opts = {
\ 'cmd': 'npm ci',
\ 'cwd': s:root,
\ 'keepfocus': 1,
\ 'Callback': {_ -> execute('CocRestart')}
\}
call coc#ui#open_terminal(opts)
endif
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
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
for filepath in a:files
let file = fnamemodify(coc#util#node_to_win32unix(filepath), ':.')
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
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, linecount) abort
try
if s:is_vim
call coc#vim9#Set_lines(a:bufnr, a:changedtick, a:original, a:replacement, a:start, a:end, a:changes, a:cursor, a:col, a:linecount)
else
call v:lua.require('coc.text').set_lines(a:bufnr, a:changedtick, a:original, a:replacement, a:start, a:end, a:changes, a:cursor, a:col, a:linecount)
endif
catch /.*/
" Need try catch here on vim9
call coc#compat#send_error('coc#ui#set_lines', s:is_vim)
endtry
endfunction
function! coc#ui#change_lines(bufnr, list) abort
if !bufloaded(a:bufnr)
return v:null
endif
undojoin
for [lnum, line] in a:list
call setbufline(a:bufnr, lnum + 1, line)
endfor
endfunction
function! coc#ui#open_url(url)
if isdirectory(a:url) && $TERM_PROGRAM ==# "iTerm.app"
call coc#ui#iterm_open(a:url)
return
endif
if !empty(get(g:, 'coc_open_url_command', ''))
call system(g:coc_open_url_command.' '.a:url)
return
endif
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 oldPath = coc#util#node_to_win32unix(a:oldPath)
let newPath = coc#util#node_to_win32unix(a:newPath)
let bufnr = bufnr(oldPath)
if bufnr == -1
throw 'Unable to get bufnr of '.oldPath
endif
if oldPath =~? newPath && (s:is_mac || s:is_win || s:is_win32unix)
return coc#ui#safe_rename(bufnr, oldPath, newPath, a:write)
endif
if bufloaded(newPath)
execute 'silent bdelete! '.bufnr(newPath)
endif
" TODO use nvim_buf_set_name instead
let current = bufnr == bufnr('%')
let bufname = fnamemodify(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 win_execute(winid, 'keepalt file '.fnameescape(bufname), 'silent')
call win_execute(winid, 'doautocmd BufEnter')
if a:write
call win_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
call sign_unplace(a:group, {'buffer': a:bufnr})
for def in a:signs
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)
endfor
endfunction
function! coc#ui#outline_preview(config) abort
let view_id = get(w:, 'cocViewId', '')
if view_id !=# 'OUTLINE'
return
endif
let wininfo = get(getwininfo(win_getid()), 0, v:null)
if empty(wininfo)
return
endif
let border = get(a:config, 'border', v:true)
let th = &lines - &cmdheight - 2
let range = a:config['range']
let height = min([range['end']['line'] - range['start']['line'] + 1, th - 4])
let to_left = &columns - wininfo['wincol'] - wininfo['width'] < wininfo['wincol']
let start_lnum = range['start']['line'] + 1
let end_lnum = range['end']['line'] + 1 - start_lnum > &lines ? start_lnum + &lines : range['end']['line'] + 1
let lines = getbufline(a:config['bufnr'], start_lnum, end_lnum)
let content_width = max(map(copy(lines), 'strdisplaywidth(v:val)'))
let width = min([content_width, a:config['maxWidth'], to_left ? wininfo['wincol'] - 3 : &columns - wininfo['wincol'] - wininfo['width']])
let filetype = getbufvar(a:config['bufnr'], '&filetype')
let cursor_row = coc#cursor#screen_pos()[0]
let config = {
\ 'relative': 'editor',
\ 'row': cursor_row - 1 + height < th ? cursor_row - (border ? 1 : 0) : th - height - (border ? 1 : -1),
\ 'col': to_left ? wininfo['wincol'] - 4 - width : wininfo['wincol'] + wininfo['width'],
\ 'width': width,
\ 'height': height,
\ 'lines': lines,
\ 'border': border ? [1,1,1,1] : v:null,
\ 'rounded': get(a:config, 'rounded', 1) ? 1 : 0,
\ 'winblend': a:config['winblend'],
\ 'highlight': a:config['highlight'],
\ 'borderhighlight': a:config['borderhighlight'],
\ }
let winid = coc#float#get_float_by_kind('outline-preview')
let result = coc#float#create_float_win(winid, s:outline_preview_bufnr, config)
if empty(result)
return v:null
endif
call setwinvar(result[0], 'kind', 'outline-preview')
let s:outline_preview_bufnr = result[1]
if !empty(filetype)
call win_execute(result[0], 'setfiletype '.filetype)
endif
return result[1]
endfunction
function! coc#ui#outline_close_preview() abort
let winid = coc#float#get_float_by_kind('outline-preview')
if winid
call coc#float#close(winid)
endif
endfunction
" Ignore error from autocmd when file opened
function! coc#ui#safe_open(cmd, file) abort
let bufname = fnameescape(a:file)
try
execute 'silent! '. a:cmd.' '.bufname
catch /.*/
if bufname('%') != bufname
throw 'Error on open '. v:exception
endif
endtry
endfunction
" Use noa to setloclist, avoid BufWinEnter autocmd
function! coc#ui#setloclist(nr, items, action, title) abort
let items = s:is_win32unix ? map(copy(a:items), 's:convert_qfitem(v:val)'): a:items
if a:action ==# ' '
let title = get(getloclist(a:nr, {'title': 1}), 'title', '')
let action = title ==# a:title ? 'r' : ' '
noa call setloclist(a:nr, [], action, {'title': a:title, 'items': items})
else
noa call setloclist(a:nr, [], a:action, {'title': a:title, 'items': items})
endif
endfunction
function! s:convert_qfitem(item) abort
let result = copy(a:item)
if has_key(result, 'filename')
let result['filename'] = coc#util#node_to_win32unix(result['filename'])
endif
return result
endfunction
function! coc#ui#get_mouse() abort
if get(g:, 'coc_node_env', '') ==# 'test'
return get(g:, 'mouse_position', [win_getid(), line('.'), col('.')])
endif
return [v:mouse_winid,v:mouse_lnum,v:mouse_col]
endfunction
" viewId - identifier of tree view
" bufnr - bufnr tree view
" winid - winid of tree view
" bufname - bufname of tree view
" command - split command
" optional options - bufhidden, canSelectMany, winfixwidth
function! coc#ui#create_tree(opts) abort
let viewId = a:opts['viewId']
let bufname = a:opts['bufname']
let tabid = coc#compat#tabnr_id(tabpagenr())
let winid = s:get_tree_winid(a:opts)
let bufnr = a:opts['bufnr']
if !bufloaded(bufnr)
let bufnr = -1
endif
if winid != -1
call win_gotoid(winid)
if bufnr('%') == bufnr
return [bufnr, winid, tabid]
elseif bufnr != -1
execute 'silent keepalt buffer '.bufnr
else
execute 'silent keepalt edit +setl\ buftype=nofile '.bufname
call s:set_tree_defaults(a:opts)
endif
else
" need to split
let cmd = get(a:opts, 'command', 'belowright 30vs')
execute 'silent keepalt '.cmd.' +setl\ buftype=nofile '.bufname
call s:set_tree_defaults(a:opts)
let winid = win_getid()
endif
let w:cocViewId = viewId
return [winbufnr(winid), winid, tabid]
endfunction
" valid window id or -1
function! s:get_tree_winid(opts) abort
let viewId = a:opts['viewId']
let winid = a:opts['winid']
if winid != -1 && coc#window#visible(winid)
return winid
endif
if winid != -1
call win_execute(winid, 'noa close!', 'silent!')
endif
return coc#window#find('cocViewId', viewId)
endfunction
function! s:set_tree_defaults(opts) abort
let bufhidden = get(a:opts, 'bufhidden', 'wipe')
let signcolumn = get(a:opts, 'canSelectMany', v:false) ? 'yes' : 'no'
let winfixwidth = get(a:opts, 'winfixwidth', v:false) ? ' winfixwidth' : ''
execute 'setl bufhidden='.bufhidden.' signcolumn='.signcolumn.winfixwidth
setl nolist nonumber norelativenumber foldcolumn=0
setl nocursorline nobuflisted wrap undolevels=-1 filetype=coctree nomodifiable noswapfile
endfunction

View file

@ -0,0 +1,731 @@
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 = 38
let s:is_win32unix = has('win32unix')
let s:win32unix_prefix = ''
let s:win32unix_fix_home = 0
if s:is_win32unix
let home = expand('$HOME')
if strpart(home, 0, 6) ==# '/home/'
let s:win32unix_fix_home = 1
let s:win32unix_prefix = '/'
elseif strpart(home, 0, 3) =~# '^/\w/'
let s:win32unix_prefix = '/'
else
let s:win32unix_prefix = matchstr(home, '^\/\w\+\/')
endif
endif
let s:win32unix_prefix_len = strlen(s:win32unix_prefix)
function! coc#util#merge_winhl(curr, hls) abort
let highlightMap = {}
for parts in map(split(a:curr, ','), 'split(v:val, ":")')
if len(parts) == 2
let highlightMap[parts[0]] = parts[1]
endif
endfor
for item in a:hls
let highlightMap[item[0]] = item[1]
endfor
return join(map(items(highlightMap), 'v:val[0].":".v:val[1]'), ',')
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' && v:val !~# ' cleared$'")
return map(filtered, "matchstr(v:val,'\\v^CocSem\\w+')")
endfunction
" get cursor position
function! coc#util#cursor()
return [line('.') - 1, coc#string#character_length(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#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
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': winid == -1 ? -1 : coc#window#get_cursor(winid)[0],
\ 'locationlist': locationlist
\ }
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: npm ci' | echohl None
else
echohl Error | echon '[coc.nvim] your coc.nvim is broken.' | echohl None
endif
return
endif
let default = ['--no-warnings']
let output = system(node . ' --version')
if v:shell_error
echohl Error | echom '[coc.nvim] Unexpected result from "'.node.' --version"' | echohl None
return
endif
let ms = matchlist(output, 'v\(\d\+\).\(\d\+\).\(\d\+\)')
if empty(ms)
echohl Error | echom '[coc.nvim] Unable to get node version by "'.node.' --version"' | echohl None
return
endif
if str2nr(ms[1]) >= 25
let default += ['--localstorage-file=' . coc#util#get_data_home() . '/localstorage']
endif
return [node] + get(g:, 'coc_node_args', default) + [s:root.'/build/index.js']
endfunction
function! coc#util#open_file(cmd, file)
let file = coc#util#node_to_win32unix(a:file)
execute a:cmd .' '.fnameescape(fnamemodify(file, ':~:.'))
return bufnr('%')
endfunction
function! coc#util#jump(cmd, filepath, ...) abort
if a:cmd != 'pedit'
silent! normal! m'
endif
let path = coc#util#node_to_win32unix(a:filepath)
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'
let dstbuf = bufadd(path)
if bufnr('%') != dstbuf
let binfo = getbufinfo(dstbuf)
if len(binfo) == 1 && empty(binfo[0].windows)
execute 'buffer '.dstbuf
let &buflisted = 1
else
let saved = &wildignore
set wildignore=
execute 'drop '.fnameescape(file)
execute 'set wildignore='.saved
endif
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)
let col = coc#string#byte_index(line, a:1[1]) + 1
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.
execute a:cmd
endif
" Set current buffer to the file
exe 'keepjumps buffer ' . buf
else
if a:cmd =~# 'drop'
if a:cmd ==# 'tab drop' && bufexists(a:file)
let bufnr = bufnr(a:file)
if bufnr == bufnr('%')
return
endif
let winid = coc#window#buf_winid(bufnr)
if winid != -1
call win_gotoid(winid)
return
endif
endif
let saved = &wildignore
set wildignore=
let l:old_page_idx = tabpagenr()
let l:old_page_cnt = tabpagenr('$')
execute 'noautocmd '.a:cmd.' '.fnameescape(a:file)
if tabpagenr('$') > l:old_page_cnt
doautocmd TabNew
doautocmd BufNew
doautocmd BufAdd
endif
let l:new_page_idx = tabpagenr()
if l:new_page_idx != l:old_page_idx
exec 'noautocmd tabnext '.l:old_page_idx
doautocmd TabLeave
doautocmd BufLeave
exec 'noautocmd tabnext '.l:new_page_idx
endif
doautocmd TabEnter
doautocmd BufReadPre
doautocmd BufReadPost
doautocmd BufEnter
if l:new_page_idx != l:old_page_idx
doautocmd BufWinEnter
endif
execute 'set wildignore='.saved
else
execute a:cmd.' '.fnameescape(a:file)
endif
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
" Global vim information
function! coc#util#vim_info()
return {
\ 'root': coc#util#win32unix_to_node(s:root),
\ 'apiversion': s:vim_api_version,
\ 'mode': mode(),
\ 'config': get(g:, 'coc_user_config', {}),
\ 'floating': !s:is_vim && 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(),
\ 'pumevent': 1,
\ 'dialog': !s:is_vim || has('popupwin') ? v:true : v:false,
\ 'terminal': !s:is_vim || has('terminal') ? v:true : v:false,
\ 'unixPrefix': s:win32unix_prefix,
\ 'jumpAutocmd': coc#util#check_jump_autocmd(),
\ 'isVim': s:is_vim ? v:true : v:false,
\ 'isCygwin': s:is_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(coc#compat#list_runtime_paths(), ','),
\ 'locationlist': get(g:,'coc_enable_locationlist', 1),
\ 'progpath': v:progpath,
\ 'guicursor': &guicursor,
\ 'pumwidth': exists('&pumwidth') ? &pumwidth : 15,
\ 'tabCount': tabpagenr('$'),
\ 'vimCommands': get(g:, 'coc_vim_commands', []),
\ 'virtualText': v:true,
\ 'sign': exists('*sign_place') && exists('*sign_unplace'),
\ 'ambiguousIsNarrow': &ambiwidth ==# 'single' ? v:true : v:false,
\ 'textprop': has('textprop') ? v:true : v:false,
\ 'semanticHighlights': coc#util#semantic_hlgroups()
\}
endfunction
function! coc#util#check_jump_autocmd() abort
let autocmd_event = 'User'
let autocmd_group = 'CocJumpPlaceholder'
if exists('#' . autocmd_event . '#' . autocmd_group)
let content = execute('autocmd ' . autocmd_event . ' ' . autocmd_group)
if content =~# 'showSignatureHelp'
return v:true
endif
endif
return v:false
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
call coc#ui#open_terminal({
\ 'cwd': s:root,
\ 'cmd': 'npm ci',
\ 'autoclose': 0,
\ })
endfunction
function! coc#util#extension_root() abort
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#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
let info = get(getwininfo(a:winid), 0, v:null)
if empty(info) || coc#window#is_float(a:winid)
return v:null
endif
let bufnr = info['bufnr']
let buftype = getbufvar(bufnr, '&buftype')
" avoid window for other purpose.
if buftype !=# '' && buftype !=# 'acwrite'
return v:null
endif
return {
\ 'bufnr': bufnr,
\ 'winid': a:winid,
\ 'tabpageid': coc#compat#tabnr_id(info['tabnr']),
\ 'winnr': winnr(),
\ 'visibleRanges': s:visible_ranges(a:winid),
\ 'formatOptions': coc#util#get_format_opts(bufnr),
\ }
endfunction
function! coc#util#get_loaded_bufs() abort
return map(getbufinfo({'bufloaded': 1}),'v:val["bufnr"]')
endfunction
function! coc#util#editor_infos() abort
let result = []
for info in getwininfo()
if !coc#window#is_float(info['winid'])
let bufnr = info['bufnr']
let buftype = getbufvar(bufnr, '&buftype')
if buftype !=# '' && buftype !=# 'acwrite'
continue
endif
call add(result, {
\ 'winid': info['winid'],
\ 'bufnr': bufnr,
\ 'tabid': coc#compat#tabnr_id(info['tabnr']),
\ 'fullpath': coc#util#get_fullpath(bufnr),
\ })
endif
endfor
return result
endfunction
function! coc#util#getpid()
if !s:is_win32unix
return getpid()
endif
let cmd = 'cat /proc/' . getpid() . '/winpid'
return substitute(system(cmd), '\v\n', '', 'gi')
endfunction
function! coc#util#get_bufoptions(bufnr, max) abort
if !bufloaded(a:bufnr)
return v:null
endif
let bufname = bufname(a:bufnr)
let buftype = getbufvar(a:bufnr, '&buftype')
let commandline = get(getbufinfo(a:bufnr)[0], 'command', 0) || bufname(a:bufnr) == '[Command Line]'
let size = coc#util#bufsize(a:bufnr)
let lines = v:null
if getbufvar(a:bufnr, 'coc_enabled', 1)
\ && (buftype == '' || buftype == 'acwrite' || getbufvar(a:bufnr, 'coc_force_attach', 0))
\ && size != -2
\ && size < a:max
let lines = getbufline(a:bufnr, 1, '$')
endif
return {
\ 'bufnr': a:bufnr,
\ 'commandline': commandline,
\ 'size': size,
\ 'lines': lines,
\ 'winid': bufwinid(a:bufnr),
\ 'winids': win_findbuf(a:bufnr),
\ 'bufname': bufname,
\ 'buftype': buftype,
\ 'previewwindow': v:false,
\ 'eol': getbufvar(a:bufnr, '&eol'),
\ 'variables': coc#util#variables(a:bufnr),
\ 'filetype': getbufvar(a:bufnr, '&filetype'),
\ 'lisp': getbufvar(a:bufnr, '&lisp'),
\ 'iskeyword': getbufvar(a:bufnr, '&iskeyword'),
\ 'changedtick': getbufvar(a:bufnr, 'changedtick'),
\ 'fullpath': coc#util#get_fullpath(a:bufnr)
\}
endfunction
" Get fullpath for NodeJs of current buffer or bufnr
function! coc#util#get_fullpath(...) abort
let nr = a:0 == 0 ? bufnr('%') : a:1
if !bufloaded(nr)
return ''
endif
if s:is_vim && getbufvar(nr, '&buftype') ==# 'terminal'
let job = term_getjob(nr)
let pid = job_info(job)->get('process', 0)
let cwd = fnamemodify(getcwd(), ':~')
return 'term://' . cwd . '//' . pid . ':' . substitute(bufname(nr), '^!', '', '')
endif
let name = bufname(nr)
return empty(name) ? '' : coc#util#win32unix_to_node(fnamemodify(name, ':p'))
endfunction
function! coc#util#bufsize(bufnr) abort
if bufnr('%') == a:bufnr
return line2byte(line("$") + 1)
endif
let bufname = bufname(a:bufnr)
if !getbufvar(a:bufnr, '&modified') && filereadable(bufname)
return getfsize(bufname)
endif
return strlen(join(getbufline(a:bufnr, 1, '$'), '\n'))
endfunction
function! coc#util#get_config_home(...)
let skip_convert = get(a:, 1, 0)
let dir = ''
if !empty(get(g:, 'coc_config_home', ''))
let dir = resolve(expand(g:coc_config_home))
else
if exists('$VIMCONFIG')
let dir = resolve($VIMCONFIG)
else
if s:is_vim
if s:is_win || s:is_win32unix
let dir = s:resolve($HOME, "vimfiles")
else
if isdirectory(s:resolve($HOME, '.vim'))
let dir = s:resolve($HOME, '.vim')
else
if exists('$XDG_CONFIG_HOME') && isdirectory(resolve($XDG_CONFIG_HOME))
let dir = s:resolve($XDG_CONFIG_HOME, 'vim')
else
let dir = s:resolve($HOME, '.config/vim')
endif
endif
endif
else
let appname = empty($NVIM_APPNAME) ? 'nvim' : $NVIM_APPNAME
if exists('$XDG_CONFIG_HOME')
let dir = s:resolve($XDG_CONFIG_HOME, appname)
else
if s:is_win
let dir = s:resolve($HOME, 'AppData/Local/'.appname)
else
let dir = s:resolve($HOME, '.config/'.appname)
endif
endif
endif
endif
endif
return skip_convert ? coc#util#fix_home(dir) : coc#util#win32unix_to_node(dir)
endfunction
function! coc#util#get_data_home()
if get(g:, 'coc_node_env', '') ==# 'test' && !empty($COC_DATA_HOME)
return coc#util#win32unix_to_node($COC_DATA_HOME)
endif
if !empty(get(g:, 'coc_data_home', ''))
let dir = resolve(expand(g:coc_data_home))
else
if exists('$XDG_CONFIG_HOME') && isdirectory(resolve($XDG_CONFIG_HOME))
let dir = s:resolve($XDG_CONFIG_HOME, 'coc')
else
if s:is_win || s:is_win32unix
let dir = resolve(expand('~/AppData/Local/coc'))
else
let dir = resolve(expand('~/.config/coc'))
endif
endif
endif
let dir = coc#util#fix_home(dir)
if !isdirectory(dir)
call coc#notify#create(['creating coc.nvim data directory: '.dir], {
\ 'borderhighlight': 'CocInfoSign',
\ 'timeout': 5000,
\ 'kind': 'info',
\ })
call mkdir(dir, "p", 0755)
endif
return coc#util#win32unix_to_node(dir)
endfunction
" Get the fixed home dir on mysys2, use user's home
" /home/YourName => /c/User/YourName
function! coc#util#fix_home(filepath) abort
if s:win32unix_fix_home && strpart(a:filepath, 0, 6) ==# '/home/'
return substitute(a:filepath, '^/home', '/c/User', '')
endif
return a:filepath
endfunction
" /cygdrive/c/Users/YourName
" /mnt/c/Users/YourName
" /c/Users/YourName
function! coc#util#win32unix_to_node(filepath) abort
if s:is_win32unix
let fullpath = coc#util#fix_home(a:filepath)
if strpart(fullpath, 0, s:win32unix_prefix_len) ==# s:win32unix_prefix
let part = strpart(fullpath, s:win32unix_prefix_len)
return toupper(part[0]) . ':' . substitute(part[1:], '/', '\', 'g')
endif
endif
return a:filepath
endfunction
function! coc#util#node_to_win32unix(filepath) abort
if s:is_win32unix && a:filepath =~# '^\w:\\'
let part = tolower(a:filepath[0]) . a:filepath[2:]
return s:win32unix_prefix . substitute(part, '\\', '/', 'g')
endif
return a:filepath
endfunction
function! coc#util#get_complete_option()
let pos = getcurpos()
let line = getline(pos[1])
let input = matchstr(strpart(line, 0, pos[2] - 1), '\k*$')
let col = pos[2] - strlen(input)
let position = {
\ 'line': line('.')-1,
\ 'character': coc#string#character_length(strpart(getline('.'), 0, col('.') - 1))
\ }
let word = matchstr(strpart(line, col - 1), '^\k\+')
let followWord = len(word) > 0 ? strcharpart(word, strchars(input)) : ''
return {
\ 'word': word,
\ 'followWord': followWord,
\ 'position': position,
\ '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,
\}
endfunction
function! coc#util#get_changedtick(bufnr) abort
if s:is_vim && bufloaded(a:bufnr)
call listener_flush(a:bufnr)
endif
return getbufvar(a:bufnr, 'changedtick')
endfunction
" Get the valid position from line, character of current buffer
function! coc#util#valid_position(line, character) abort
let total = line('$') - 1
if a:line > total
return [total, 0]
endif
let max = max([0, coc#string#character_length(getline(a:line + 1)) - (mode() ==# 'n' ? 1 : 0)])
return a:character > max ? [a:line, max] : [a:line, a:character]
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
" for avoid bug with vim&neovim https://github.com/neoclide/coc.nvim/discussions/5287
function! s:resolve(path, part) abort
return resolve(a:path . '/' . a:part)
endfunction

View file

@ -0,0 +1,525 @@
vim9script
scriptencoding utf-8
const default_priority = 1024
const priorities = {
'CocListSearch': 2048,
'CocSearch': 2048,
}
const diagnostic_hlgroups = ['CocUnusedHighlight', 'CocDeprecatedHighlight', 'CocHintHighlight', 'CocInfoHighlight', 'CocWarningHighlight', 'CocErrorHighlight']
const maxCount = get(g:, 'coc_highlight_maximum_count', 500)
const maxTimePerBatchMs = 16
var maxEditCount = get(g:, 'coc_edits_maximum_count', 200)
var saved_event_ignore: string = ''
def Is_timeout(start_time: list<any>, max: number): bool
return (start_time->reltime()->reltimefloat()) * 1000 > max
enddef
# Some hlGroups have higher priorities.
def Get_priority(hlGroup: string, priority: any): number
if has_key(priorities, hlGroup)
return priorities[hlGroup]
endif
if type(priority) != v:t_number
return default_priority
endif
const idx = index(diagnostic_hlgroups, hlGroup)
if idx != -1
return priority + idx
endif
return priority
enddef
def Convert_item(item: any): list<any>
if type(item) == v:t_list
return item
endif
# hlGroup, lnum, colStart, colEnd, combine, start_incl, end_incl
const combine = has_key(priorities, item.hlGroup) ? 1 : get(item, 'combine', 0)
const start_incl = get(item, 'start_incl', 0)
const end_incl = get(item, 'end_incl', 0)
return [item.hlGroup, item.lnum, item.colStart, item.colEnd, combine, start_incl, end_incl]
enddef
# Check if lines synchronized as expected
export def Check_sha256(bufnr: number, expected: string): bool
if !exists('*sha256')
return true
endif
return getbufline(bufnr, 1, '$')->join("\n")->sha256() ==# expected
enddef
def Create_namespace(key: any): number
if type(key) == v:t_number
if key == -1
return coc#api#Create_namespace('anonymous')
endif
return key
endif
if type(key) != v:t_string
throw 'Expect number or string for namespace key.'
endif
return coc#api#Create_namespace($'coc-{key}')
enddef
export def Clear_highlights(id: number, key: any, start_line: number = 0, end_line: number = -1): void
const buf = id == 0 ? bufnr('%') : id
if bufloaded(buf)
const ns = Create_namespace(key)
coc#api#Buf_clear_namespace(buf, ns, start_line, end_line)
endif
enddef
export def Add_highlight(id: number, key: any, hl_group: string, line: number, col_start: number, col_end: number, opts: dict<any> = {}): void
const buf = id == 0 ? bufnr('%') : id
if bufloaded(buf)
const ns = Create_namespace(key)
coc#api#Buf_add_highlight1(buf, ns, hl_group, line, col_start, col_end, opts)
endif
enddef
export def Clear_all(): void
const namespaces = coc#api#Get_namespaces()
const bufnrs = getbufinfo({'bufloaded': 1})->mapnew((_, o: dict<any>): number => o.bufnr)
for ns in values(namespaces)
for bufnr in bufnrs
coc#api#Buf_clear_namespace(bufnr, ns, 0, -1)
endfor
endfor
enddef
# From `coc#highlight#set(`:
# type HighlightItem = [hlGroup, lnum, colStart, colEnd, combine?, start_incl?, end_incl?]
# From `src/core/highlights.ts`:
# type HighlightItemDef = [string, number, number, number, number?, number?, number?]
# type HighlightItem = list<any>
# type HighlightItemList = list<HighlightItem>
# NOTE: Can't use type on vim9.0.0438
export def Set_highlights(bufnr: number, key: any, highlights: list<any>, priority: any = null): void
if bufloaded(bufnr)
const changedtick = getbufvar(bufnr, 'changedtick', 0)
const ns = Create_namespace(key)
Add_highlights_timer(bufnr, ns, highlights, priority, changedtick)
endif
enddef
def Add_highlights_timer(bufnr: number, ns: number, highlights: list<any>, priority: any, changedtick: number): void
if !bufloaded(bufnr) || getbufvar(bufnr, 'changedtick', 0) != changedtick
return
endif
const total = len(highlights)
const start_time = reltime()
var end_idx = 0
for i in range(0, total - 1, maxCount)
end_idx = i + maxCount - 1
const hls = highlights[i : end_idx]
Add_highlights(bufnr, ns, hls, priority)
if Is_timeout(start_time, maxTimePerBatchMs)
break
endif
endfor
if end_idx < total - 1
const next = highlights[end_idx + 1 : ]
timer_start(10, (_) => Add_highlights_timer(bufnr, ns, next, priority, changedtick))
endif
enddef
def Add_highlights(bufnr: number, ns: number, highlights: list<any>, priority: any): void
final types = coc#api#GetNamespaceTypes(ns)->copy()
for highlightItem in highlights
const item = Convert_item(highlightItem)
var [ hlGroup: string, lnum: number, colStart: number, colEnd: number; _ ] = item
if colEnd == -1
colEnd = getbufline(bufnr, lnum + 1)->get(0, '')->strlen()
endif
const type: string = $'{hlGroup}_{ns}'
if index(types, type) == -1
const opts: dict<any> = {
'priority': Get_priority(hlGroup, priority),
'hl_mode': get(item, 4, 1) ? 'combine' : 'override',
'start_incl': get(item, 5, 0),
'end_incl': get(item, 6, 0),
}
coc#api#CreateType(ns, hlGroup, opts)
add(types, type)
endif
const propId: number = coc#api#GeneratePropId(bufnr)
try
prop_add(lnum + 1, colStart + 1, {'bufnr': bufnr, 'type': type, 'id': propId, 'end_col': colEnd + 1})
catch /^Vim\%((\a\+)\)\=:\(E967\|E964\)/
# ignore 967
endtry
endfor
enddef
export def Update_highlights(id: number, key: string, highlights: list<any>, start: number = 0, end: number = -1, priority: any = null, changedtick: any = null): void
const bufnr = id == 0 ? bufnr('%') : id
if bufloaded(bufnr)
const tick = getbufvar(bufnr, 'changedtick')
if type(changedtick) == v:t_number && changedtick != tick
return
endif
const ns = Create_namespace(key)
coc#api#Buf_clear_namespace(bufnr, ns, start, end)
Add_highlights_timer(bufnr, ns, highlights, priority, tick)
endif
enddef
# key could be -1 or string or number
export def Buffer_update(bufnr: number, key: any, highlights: list<any>, priority: any = null, changedtick: any = null): void
if bufloaded(bufnr)
const ns = Create_namespace(key)
coc#api#Buf_clear_namespace(bufnr, ns, 0, -1)
if empty(highlights)
return
endif
const tick = getbufvar(bufnr, 'changedtick', 0)
if type(changedtick) == v:t_number && tick != changedtick
return
endif
# highlight current region first
const winid = bufwinid(bufnr)
if winid == -1
Add_highlights_timer(bufnr, ns, highlights, priority, tick)
else
const info = getwininfo(winid)->get(0, {})
const topline = info.topline
const botline = info.botline
if topline <= 5
Add_highlights_timer(bufnr, ns, highlights, priority, tick)
else
final curr_hls = []
final other_hls = []
for hl in highlights
const lnum = type(hl) == v:t_list ? hl[1] + 1 : hl.lnum + 1
if lnum >= topline && lnum <= botline
add(curr_hls, hl)
else
add(other_hls, hl)
endif
endfor
const hls = extend(curr_hls, other_hls)
Add_highlights_timer(bufnr, ns, hls, priority, tick)
endif
endif
endif
enddef
export def Highlight_ranges(id: number, key: any, hlGroup: string, ranges: list<any>, opts: dict<any> = {}): void
const bufnr = id == 0 ? bufnr('%') : id
if bufloaded(bufnr)
final highlights: list<any> = []
if get(opts, 'clear', false) == true
const ns = Create_namespace(key)
coc#api#Buf_clear_namespace(bufnr, ns, 0, -1)
endif
for range in ranges
const start_pos = range.start
const end_pos = range.end
const lines = getbufline(bufnr, start_pos.line + 1, end_pos.line + 1)
for index in range(start_pos.line, end_pos.line)
const line = get(lines, index - start_pos.line, '')
if len(line) == 0
continue
endif
const colStart = index == start_pos.line ? coc#text#Byte_index(line, start_pos.character) : 0
const colEnd = index == end_pos.line ? coc#text#Byte_index(line, end_pos.character) : strlen(line)
if colStart >= colEnd
continue
endif
const combine = get(opts, 'combine', false) ? 1 : 0
const start_incl = get(opts, 'start_incl', false) ? 1 : 0
const end_incl = get(opts, 'end_incl', false) ? 1 : 0
add(highlights, [hlGroup, index, colStart, colEnd, combine, start_incl, end_incl])
endfor
endfor
const priority = has_key(opts, 'priority') ? opts.priority : 4096
Set_highlights(bufnr, key, highlights, priority)
endif
enddef
export def Match_ranges(id: number, buf: number, ranges: list<any>, hlGroup: string, priority: any = 99): list<number>
const winid = id == 0 ? win_getid() : id
const bufnr = buf == 0 ? winbufnr(winid) : buf
if empty(getwininfo(winid)) || (buf != 0 && winbufnr(winid) != buf)
return []
endif
final ids = []
final pos = []
for range in ranges
const start_pos = range.start
const end_pos = range.end
const lines = getbufline(bufnr, start_pos.line + 1, end_pos.line + 1)
for index in range(start_pos.line, end_pos.line)
const line = get(lines, index - start_pos.line, '')
if len(line) == 0
continue
endif
const colStart = index == start_pos.line ? coc#text#Byte_index(line, start_pos.character) : 0
const colEnd = index == end_pos.line ? coc#text#Byte_index(line, end_pos.character) : strlen(line)
if colStart >= colEnd
continue
endif
add(pos, [index + 1, colStart + 1, colEnd - colStart])
endfor
endfor
const count = len(pos)
if count > 0
const pr = type(priority) == v:t_number ? priority : 99
const opts = {'window': winid}
if count < 9 || has('patch-9.0.0622')
ids->add(matchaddpos(hlGroup, pos, pr, -1, opts))
else
# limit to 8 each time
for i in range(0, count - 1, 8)
const end = min([i + 8, count]) - 1
ids->add(matchaddpos(hlGroup, pos[i : end], pr, -1, opts))
endfor
endif
endif
return ids
enddef
# key could be string or number, use -1 for all highlights.
export def Get_highlights(bufnr: number, key: any, start: number, end: number): list<any>
if !bufloaded(bufnr)
return []
endif
const ns = type(key) == v:t_number ? key : Create_namespace(key)
const types: list<string> = coc#api#GetNamespaceTypes(ns)
if empty(types)
return []
endif
final res: list<any> = []
const endLnum: number = end == -1 ? -1 : end + 1
for prop in prop_list(start + 1, {'bufnr': bufnr, 'types': types, 'end_lnum': endLnum})
if prop.start == 0 || prop.end == 0
# multi line textprop are not supported, simply ignore it
continue
endif
const startCol: number = prop.col - 1
const endCol: number = startCol + prop.length
const hl = prop_type_get(prop.type)->get('highlight', '')
add(res, [ hl, prop.lnum - 1, startCol, endCol, prop.id ])
endfor
return res
enddef
export def Del_markers(bufnr: number, key: any, ids: list<number>): void
if bufloaded(bufnr)
for id in ids
prop_remove({'bufnr': bufnr, 'id': id})
endfor
endif
enddef
# Can't use strdisplaywidth as it doesn't support bufnr
def Calc_padding_size(bufnr: number, indent: string): number
const tabSize: number = getbufvar(bufnr, '&shiftwidth') ?? getbufvar(bufnr, '&tabstop', 8)
var padding: number = 0
for character in indent
if character == "\t"
padding += tabSize - (padding % tabSize)
else
padding += 1
endif
endfor
return padding
enddef
def Add_vtext_item(bufnr: number, ns: number, opts: dict<any>, pre: string, priority: number): void
var propColumn: number = get(opts, 'col', 0)
const align = get(opts, 'text_align', 'after')
const line = opts.line
const blocks = opts.blocks
var blockList: list<list<string>> = blocks
const virt_lines = get(opts, 'virt_lines', [])
var isAboveBelow = align ==# 'above' || align ==# 'below'
if !empty(blocks) && isAboveBelow
# only first highlight can be used
const highlightGroup: string = blocks[0][1]
const text: string = blocks->mapnew((_, block: list<string>): string => block[0])->join('')
blockList = [[text, highlightGroup]]
propColumn = 0
endif
var first: bool = true
final base: dict<any> = { 'priority': priority }
if propColumn == 0 && align != 'overlay'
base.text_align = align
endif
if has_key(opts, 'text_wrap')
base.text_wrap = opts.text_wrap
endif
var before: string = ''
for blockItem in blockList
const text = empty(before) ? blockItem[0] : $'{before}{blockItem[0]}'
const highlightGroup: string = get(blockItem, 1, '')
if empty(highlightGroup)
# should be spaces
before = text
continue
endif
before = ''
const type: string = coc#api#CreateType(ns, highlightGroup, opts)
final propOpts: dict<any> = extend({ 'text': text, 'type': type, 'bufnr': bufnr }, base)
if first && propColumn == 0
# add a whitespace, same as neovim.
if align ==# 'after'
propOpts.text_padding_left = 1
elseif !empty(pre) && isAboveBelow
propOpts.text_padding_left = Calc_padding_size(bufnr, pre)
endif
endif
prop_add(line + 1, propColumn, propOpts)
first = false
endfor
for item_list in virt_lines
for [text, highlightGroup] in item_list
const type: string = coc#api#CreateType(ns, highlightGroup, opts)
final propOpts: dict<any> = { 'text': text, 'type': type, 'bufnr': bufnr, 'text_align': 'below'}
prop_add(line + 1, 0, propOpts)
endfor
endfor
enddef
export def Add_vtext(bufnr: number, ns: number, line: number, blocks: list<list<string>>, opts: dict<any>): void
var propIndent: string = ''
if get(opts, 'indent', false)
propIndent = matchstr(get(getbufline(bufnr, line + 1), 0, ''), '^\s\+')
endif
final conf = {'line': line, 'blocks': blocks}
Add_vtext_item(bufnr, ns, extend(conf, opts), propIndent, get(opts, 'priority', 0))
enddef
def Add_vtext_items(bufnr: number, ns: number, items: list<any>, indent: bool, priority: number): void
const length = len(items)
if length > 0
var buflines: list<string> = []
var start = 0
var propIndent: string = ''
if indent
start = items[0].line
const endLine = items[length - 1].line
buflines = getbufline(bufnr, start + 1, endLine + 1)
endif
for item in items
if indent
propIndent = matchstr(buflines[item.line - start], '^\s\+')
endif
Add_vtext_item(bufnr, ns, item, propIndent, priority)
endfor
endif
enddef
def Add_vtexts_timer(bufnr: number, ns: number, items: list<any>, indent: bool,
priority: number, changedtick: number): void
if !bufloaded(bufnr) || getbufvar(bufnr, 'changedtick', 0) != changedtick
return
endif
if len(items) > maxCount
const hls = items[ : maxCount - 1]
const next = items[maxCount : ]
Add_vtext_items(bufnr, ns, hls, indent, priority)
timer_start(10, (_) => Add_vtexts_timer(bufnr, ns, next, indent, priority, changedtick))
else
Add_vtext_items(bufnr, ns, items, indent, priority)
endif
enddef
export def Set_virtual_texts(bufnr: number, ns: number, items: list<any>, indent: bool, priority: number): void
if bufloaded(bufnr)
const changedtick = getbufvar(bufnr, 'changedtick', 0)
Add_vtexts_timer(bufnr, ns, items, indent, priority, changedtick)
endif
enddef
# Apply many text changes while preserve text props can be slow,
def Apply_changes(bufnr: number, changes: list<any>): void
const start_time = reltime()
const total = len(changes)
var timeout: bool = false
var i = total - 1
while i >= 0
const item = changes[i]
# item is null for some unknown reason
if !empty(item)
coc#api#SetBufferText(bufnr, item[1], item[2], item[3], item[4], item[0])
endif
i -= 1
endwhile
const duration = (start_time->reltime()->reltimefloat()) * 1000
if duration > 200
maxEditCount = maxEditCount / 2
coc#api#EchoHl($'Text edits cost {float2nr(duration)}ms, consider configure g:coc_edits_maximum_count < {total}', 'WarningMsg')
endif
enddef
# Replace text before cursor at current line, insert should not includes line break.
# 0 based start col
export def Set_lines(bufnr: number, changedtick: number, original: list<string>, replacement: list<string>,
start: number, end: number, changes: any, cursor: any, col: any, linecount: number): void
if bufloaded(bufnr)
const current = bufnr == bufnr('%')
const view = current ? winsaveview() : null
var start_row: number = start
var end_row: number = end
var replace = copy(replacement)
var finished: bool = false
var change_list = copy(changes)
var delta: number = 0
if current && type(col) == v:t_number
delta = col('.') - col
endif
if changedtick != getbufvar(bufnr, 'changedtick') && end_row > start_row
const line_delta = bufnr->getbufinfo()->get(0).linecount - linecount
if line_delta == 0
# Check current line change first
const curr_lines = getbufline(bufnr, start_row + 1, end_row)
const pos = getpos('.')
const row = current ? pos[1] - start_row - 1 : -1
for idx in range(0, len(curr_lines) - 1)
var oldStr = get(original, idx, '')
var newStr = get(curr_lines, idx, '')
var replaceStr = get(replace, idx, null)
var colIdx = idx == row ? pos[2] - 1 : -1
if oldStr !=# newStr && replaceStr != null
if replaceStr ==# oldStr
replaceStr = newStr
else
replaceStr = coc#text#DiffApply(oldStr, newStr, replaceStr, colIdx)
endif
if replaceStr != null
replace[idx] = replaceStr
endif
change_list = []
endif
endfor
else
# Check if change lines before or after
# Consider changed before first
if coc#text#LinesEqual(replace, getbufline(bufnr, start_row + 1 + line_delta, end_row + line_delta))
start_row += line_delta
end_row += line_delta
change_list = []
elseif !coc#text#LinesEqual(replace, getbufline(bufnr, start_row + 1, end_row))
return
endif
endif
endif
if !empty(change_list) && len(change_list) <= maxEditCount
Apply_changes(bufnr, change_list)
else
coc#api#SetBufferLines(bufnr, start_row + 1, end_row, replace)
endif
if current
winrestview(view)
endif
coc#api#OnTextChange(bufnr)
if !empty(cursor) && current
cursor(cursor[0], cursor[1] + delta)
endif
endif
enddef
defcompile

View file

@ -0,0 +1,60 @@
let s:is_vim = !has('nvim')
" Add multiple virtual texts, use timer when needed.
" bufnr - The buffer number
" ns - Id created by Nvim_create_namespace()
" items - list of item:
" item.line - Zero based line number
" item.blocks - List with [text, hl_group]
" item.hl_mode - Default to 'combine'.
" item.col - vim & nvim >= 0.10.0, default to 0.
" item.virt_text_win_col - neovim only.
" item.text_align - Could be 'after' 'right' 'below' 'above'.
" item.text_wrap - Could be 'wrap' and 'truncate', vim9 only.
" indent - Prepend indent of current line when true
" priority - Highlight priority
function! coc#vtext#set(bufnr, ns, items, indent, priority) abort
try
if s:is_vim
call coc#vim9#Set_virtual_texts(a:bufnr, a:ns, a:items, a:indent, a:priority)
else
call v:lua.require('coc.vtext').set(a:bufnr, a:ns, a:items, a:indent, a:priority)
endif
catch /.*/
call coc#compat#send_error('coc#vtext#set', s:is_vim)
endtry
endfunction
" Check virtual text of namespace exists
function! coc#vtext#exists(bufnr, ns) abort
if s:is_vim
let types = coc#api#GetNamespaceTypes(a:ns)
if empty(types)
return 0
endif
return !empty(prop_list(1, {'bufnr': a:bufnr, 'types': types, 'end_lnum': -1}))
endif
return !empty(nvim_buf_get_extmarks(a:bufnr, a:ns, [0, 0], [-1, -1], {}))
endfunction
" This function is called by buffer.setVirtualText
" ns - Id created by coc#highlight#create_namespace()
" line - Zero based line number
" blocks - List with [text, hl_group]
" opts.hl_mode - Default to 'combine'.
" opts.col - vim & nvim >= 0.10.0, default to 0.
" opts.virt_text_win_col - neovim only.
" opts.text_align - Could be 'after' 'right' 'below' 'above', converted on neovim.
" opts.text_wrap - Could be 'wrap' and 'truncate', vim9 only.
" opts.indent - add indent when using 'above' and 'below' as text_align
function! coc#vtext#add(bufnr, ns, line, blocks, opts) abort
try
if s:is_vim
call coc#vim9#Add_vtext(a:bufnr, a:ns, a:line, a:blocks, a:opts)
else
call v:lua.require('coc.vtext').add(a:bufnr, a:ns, a:line, a:blocks, a:opts)
endif
catch /.*/
call coc#compat#send_error('coc#vtext#add', s:is_vim)
endtry
endfunction

View file

@ -0,0 +1,215 @@
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
" getwininfo not work with popup on vim
if s:is_vim && index(popup_list(), a:winid) != -1
call win_execute(a:winid, 'let g:__coc_tabnr = tabpagenr()')
let nr = g:__coc_tabnr
unlet g:__coc_tabnr
return nr
endif
let info = getwininfo(a:winid)
return empty(info) ? -1 : info[0]['tabnr']
endfunction
" (1, 0) based line, column
function! coc#window#get_cursor(winid) abort
if exists('*nvim_win_get_cursor')
return nvim_win_get_cursor(a:winid)
endif
let pos = getcurpos(a:winid)
return [pos[1], pos[2] - 1]
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
else
if !nvim_win_is_valid(a:winid)
return 0
endif
return coc#window#tabnr(a:winid) == tabpagenr()
endif
endfunction
" winid is popup and shown
function! s:visible_popup(winid) abort
if index(popup_list(), a:winid) != -1
return get(popup_getpos(a:winid), 'visible', 0) == 1
endif
return 0
endfunction
" Return default or 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
let tabnr = coc#window#tabnr(a:winid)
if tabnr == -1
return get(a:, 1, v:null)
endif
return gettabwinvar(tabnr, a:winid, a:name, get(a:, 1, v:null))
endfunction
" Not throw like setwinvar
function! coc#window#set_var(winid, name, value) abort
let tabnr = coc#window#tabnr(a:winid)
if tabnr == -1
return
endif
call settabwinvar(tabnr, a:winid, a:name, a:value)
endfunction
function! coc#window#is_float(winid) abort
if s:is_vim
return index(popup_list(), a:winid) != -1
else
if nvim_win_is_valid(a:winid)
let config = nvim_win_get_config(a:winid)
return !empty(get(config, 'relative', ''))
endif
endif
return 0
endfunction
" Reset current lnum & topline of window
function! coc#window#restview(winid, lnum, topline) abort
if empty(getwininfo(a:winid))
return
endif
if s:is_vim && s:visible_popup(a:winid)
call popup_setoptions(a:winid, {'firstline': a:topline})
return
endif
call win_execute(a:winid, ['noa call winrestview({"lnum":'.a:lnum.',"topline":'.a:topline.'})'])
endfunction
function! coc#window#set_height(winid, height) abort
if empty(getwininfo(a:winid))
return
endif
if !s:is_vim
call nvim_win_set_height(a:winid, a:height)
else
if coc#window#is_float(a:winid)
call popup_move(a:winid, {'minheight': a:height, 'maxheight': a:height})
else
call win_execute(a:winid, 'noa resize '.a:height)
endif
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 win_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 win_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 = map(getwininfo(), 'v:val["winid"]')
return uniq(map(winids, 'winbufnr(v:val)'))
endfunction
function! coc#window#buf_winid(bufnr) abort
let winids = map(getwininfo(), 'v:val["winid"]')
for winid in winids
if winbufnr(winid) == a:bufnr
return winid
endif
endfor
return -1
endfunction
" Avoid errors
function! coc#window#close(winid) abort
if empty(a:winid) || a:winid == -1
return
endif
if coc#window#is_float(a:winid)
call coc#float#close(a:winid)
return
endif
call win_execute(a:winid, 'noa close!', 'silent!')
endfunction
function! coc#window#visible_range(winid) abort
let winid = a:winid == 0 ? win_getid() : a:winid
let info = get(getwininfo(winid), 0, v:null)
if empty(info)
return v:null
endif
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
" Clear matches by hlGroup regexp.
function! coc#window#clear_match_group(winid, match) abort
let winid = a:winid == 0 ? win_getid() : a:winid
if !empty(getwininfo(winid))
let arr = filter(getmatches(winid), 'v:val["group"] =~# "'.a:match.'"')
for item in arr
call matchdelete(item['id'], winid)
endfor
endif
endfunction
" Clear matches by match ids, use 0 for current win.
function! coc#window#clear_matches(winid, ids) abort
let winid = a:winid == 0 ? win_getid() : a:winid
if !empty(getwininfo(winid))
for id in a:ids
try
call matchdelete(id, winid)
catch /^Vim\%((\a\+)\)\=:E803/
" ignore
endtry
endfor
endif
endfunction

View file

@ -0,0 +1,128 @@
scriptencoding utf-8
let s:root = expand('<sfile>:h:h:h')
function! s:report_ok(report) abort
if has('nvim-0.10')
call v:lua.vim.health.ok(a:report)
else
call health#report_ok(a:report)
endif
endfunction
function! s:report_error(report, advises) abort
if has('nvim-0.10')
call v:lua.vim.health.error(a:report, a:advises)
else
call health#report_error(a:report, a:advises)
endif
endfunction
function! s:report_warn(report) abort
if has('nvim-0.10')
call v:lua.vim.health.warn(a:report)
else
call health#report_warn(a:report)
endif
endfunction
function! s:checkVim(test, name, patchlevel) abort
if a:test
if !has(a:patchlevel)
call s:report_error(a:name . ' version not satisfied, ' . a:patchlevel . ' and above required')
return 0
else
call s: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.8.0')
\ + s:checkVim(!has('nvim'), 'vim', 'patch-9.0.0438')
let node = get(g:, 'coc_node_path', $COC_NODE_PATH == '' ? 'node' : $COC_NODE_PATH)
if !executable(node)
let valid = 0
call s: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 s:report_error(output)
endif
let ms = matchlist(output, 'v\(\d\+\).\(\d\+\).\(\d\+\)')
if empty(ms)
let valid = 0
call s:report_error('Unable to detect version of node, make sure your node executable is http://nodejs.org/')
elseif str2nr(ms[1]) < 16 || (str2nr(ms[1]) == 16 && str2nr(ms[2]) < 18)
let valid = 0
call s:report_warn('Node.js version '.trim(output).' < 16.18.0, please upgrade node.js')
endif
if valid
call s:report_ok('Environment check passed')
endif
if has('pythonx')
try
silent pyx print("")
catch /.*/
call s:report_warn('pyx command not work, some extensions may fail to work, checkout ":h pythonx"')
if has('nvim')
call s: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 s:report_ok('Javascript bundle build/index.js found')
else
call s: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 s:report_warn('Use CocActionAsync to replace CocAction for better performance on '.cmd)
call s:report_warn('Checkout the file '.ms[1])
endif
endif
let n = n + 1
endfor
endfor
endfunction
function! s:checkInitialize() abort
if get(g:, 'coc_start_at_startup', 1) == 0
call s:report_warn('coc.nvim was disabled on startup, run :CocStart to start manually')
return 1
endif
if coc#client#is_running('coc')
call s:report_ok('Service started')
return 1
endif
call s:report_error('service could not be initialized', [
\ 'Use command ":messages" to get error messages.',
\ 'Open an 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

Binary file not shown.

Binary file not shown.

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

View file

@ -0,0 +1,111 @@
/*
* Used for prompt popup on vim
*/
const readline = require("readline")
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: true,
escapeCodeTimeout: 0,
prompt: ''
})
let value = process.argv[2]
let placeholder = process.argv[3]
let clear = false
if (value) {
rl.write(value)
} else if (placeholder) {
clear = true
rl.write('\x1B[90m' + placeholder + '\x1B[39m')
rl.write('', {ctrl: true, name: 'a'})
}
rl.on('line', input => {
send(['confirm', clear ? '' : 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)
if (clear && rl.line.includes('\x1B')) {
clear = false
rl.write('', {ctrl: true, name: 'k'})
return
}
send(['change', rl.line])
}
function createSequences(str) {
return '\x1b]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()
}
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 == 't') {
return '<C-t>'
}
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 ''
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,443 @@
*coc-api.txt* NodeJS client for Vim & Neovim.
CONTENTS
Vim sources |coc-api-vim-source|
Extension introduction |coc-api-intro|
Extension package json |coc-api-json|
Single file extensions |coc-api-single|
Create custom Extensions |coc-api-extension|
Debug extensions |coc-api-debug|
==============================================================================
The guide for extend coc.nvim by create vim completion sources and coc.nvim
extensions.
------------------------------------------------------------------------------
VIM SOURCES *coc-api-vim-source*
During initialization, coc.nvim searches vim's |runtimepath| for file pattern
`autoload/coc/source/${name}.vim`, matched files would be loaded as vim
completion sources.
Note: LSP completion features like `TextEdit`, `additionalTextEdits`,
`command` are not supported by vim sources, use the NodeJS API
`languages.registerCompletionItemProvider` for LSP completion.
For example, create a file `autoload/coc/source/email.vim` inside your plugin
folder. With code:
>
" vim source for emails
function! coc#source#email#init() abort
return {
\ 'priority': 9,
\ 'shortcut': 'Email',
\ 'triggerCharacters': ['@']
\}
endfunction
function! coc#source#email#complete(option, cb) abort
let items = ['foo@gmail.com', 'bar@yahoo.com']
call a:cb(items)
endfunction
<
`init` and `complete` are required functions for vim sources, error message
will be shown when not exists.
vim9script can be also used on vim9 (not supported on neovim), the function
first letter need to be uppercased, like:
>
vim9script
export def Init(): dict<any>
return {
priority: 9,
shortcut: 'Email',
triggerCharacters: ['@']
}
enddef
export def Complete(option: dict<any>, Callback: func(list<any>))
const items = ['foo@gmail.com', 'bar@yahoo.com']
Callback(items)
enddef
<
Source option: ~
The source option object is returned by `coc#source#{name}#init`
function, available properties:
• shortcut: The shortcut characters shown in popup menu, first three
characters from the source name would be used when not exists.
• priority: The priority of source, default to `9`.
• filetypes: Array of filetype names this source should be triggered
by. Available for all filetypes when not exists.
• firstMatch: When is truthy value, only the completion item that has the
first letter matching the user input will be shown.
• triggerCharacters: Trigger characters for this source, default to `[]`.
• triggerOnly: The source should only be triggered by trigger characters,
when trigger characters is false or empty, the source would only be
triggered by api |coc#start()|.
• isSnippet: All complete items returned by `complete` are snippets,
which would have snippet indicator text added to the label in popup
menu. The "isSnippet" property of completion item override this
option.
All options are optional.
Source configurations: ~
Vim sources register |coc-configuration| for allow the user to customize the
source behavior.
• `coc.source.${name}.enable` Enable the source, default to `true`.
• `coc.source.${name}.disableSyntaxes` Disabled syntax names when trigger
completion.
• `coc.source.${name}.firstMatch` Default to "firstMatch" of source option.
• `coc.source.${name}.priority` Default to "priority" of source option.
• `coc.source.${name}.shortcut` Default to "shortcut" of source option.
• `coc.source.${name}.filetypes` Default to "filetypes" of source option.
Complete function: ~
The complete function is called with complete option as the first argument
and a callback function as the second argument, the callback function should
be called with list of complete item or `v:null` synchronously or
asynchronously.
Note: synchronously compute complete items blocks vim's operation.
Note: Error during completion is not thrown, use |:CocOpenLog| to check the
error log.
Complete option have following properties:
• bufnr: Current buffer number.
• line: Content line when trigger completion.
• col: Start col of completion, start col of the keywords before cursor by
default, 0 based.
• input: Input text between start col and cursor col.
• filetype: Filetype of current buffer.
• filepath: Fullpath of current buffer.
• changedtick: b:changedtick value when trigger completion.
• triggerCharacter: The character which trigger the completion, could be
empty string.
• colnr: Cursor col when trigger completion, 1 based.
• linenr: Line number of cursor, 1 based.
Complete items extends vim's |complete-items| with the following properties:
• deprecated: The complete item would be rendered with strike through
highlight when truthy.
• labelDetails: Additional details for a completion item label, which have
optional `detail` and/or `description` text.
• sortText: A string that should be used when comparing this item with other
items, word is used when not exists.
• filterText: A string that should be used when filtering a set of
complete items, word is used when not exists.
• insertText: The text to insert, could be textmate snippet text, word is
used when not exists.
• isSnippet: The text to insert is snippet when is truthy value, when
truthy and `on_complete` not provided by vim source, the `insertText` is
expanded as textmate snippet when confirm completion.
• documentation: Array of `Documentation`, which provide `filetype` and
`content` text to be displayed in preview window.
Only the "word" property is mandatory for complete items.
Optional functions: ~
The vim source could provide some optional functions which would be invoked
by coc.nvim:
• `coc#source#{name}#get_startcol(option)` Used to alter the start col of
completion, the returned col must <= current cursor col.
• `coc#source#{name}#on_complete(item)` Called with selected complete item
when user confirm the completion by |coc#pum#confirm()| or
|coc#pum#select_confirm()|. Normally used for apply necessary edits to the
buffer.
• `coc#source#{name}#on_enter(option)` Called on |BufEnter| with option
contains:
• bufnr: The buffer number.
• uri: The uri text of buffer.
• languageId: The mapped filetype of buffer, see |coc-document-filetype|.
• `coc#source#{name}#refresh()` Called when the user trigger refresh action
for the source.
------------------------------------------------------------------------------
EXTENSION INTRODUCTION *coc-api-intro*
Every extension of coc.nvim has a JavaScript entry file, that file is loaded
by NodeJS API `vm.runInContext` with an identical global context (like iframe
in browser).
The JavaScript entry file should be a CommonJS module with `activate` method
exported, and `require('coc.nvim')` can be used to access modules exported by
coc.nvim, for example:
>
const {window} = require('coc.nvim')
exports.activate = async context => {
window.showInformationMessage('extension activated')
}
<
When `exports.deactivate` is exported from the JavaScript entry file as a
function, it would be called on extension deactivate.
Limitation of extension context: ~
Some methods/properties provided by NodeJS can't be used inside extension
context, including:
• `process.reallyExit()`
• `process.abort()`
• `process.setuid()`
• `process.setgid()`
• `process.setgroups()`
• `process._fatalException()`
• `process.exit()`
• `process.kill()`
• `process.umask()` Could only be used to get umask value.
• `process.chdir()` Could be called, but no effect at all.
Some globals may can't be accessed directly, for example `TextDecoder`,
`TextEncoder`, use `globalThis` like `globalThis.TextDecoder` to access them.
*coc-api-console*
Stdin and stdout of the NodeJS process is used for communication between vim
and NodeJS process, use the methods related to `process.stdin` and
`process.stdout` may cause unexpected behavior. However, some methods of
`console` are provided for debugging purpose.
Messages from `console` of extension would be redirected to the log file
|:CocOpenLog|. Available methods:
• `debug(...args: any[])` Write debug message to the log file.
• `log(...args: any[])` Write info message to the log file.
• `info(...args: any[])` Write info message to the log file.
• `error(...args: any[])` Write error message to the log file.
• `warn(...args: any[])` Write warning message to the log file.
Check the full NodeJS API interfaces at:
https://github.com/neoclide/coc.nvim/blob/master/typings/index.d.ts
------------------------------------------------------------------------------
EXTENSION PACKAGE JSON *coc-api-json*
The package.json file inside extension root defines the meta data of the
extension. For example:
>
{
"name": "coc-my-extension",
"version": "1.0.0",
"main": "lib/index.js",
"engines": {
"coc": "^0.0.82"
},
"activationEvents": [
"*",
],
"contributes": {
"rootPatterns": [{
"filetype": "myfiletype",
"patterns": [
"project_root.json"
]
}],
"commands": [{
"title": "My command",
"category": "myextension",
"id": "myextension.myCommand"
}],
"configuration": {
"type": "object",
"properties": {
"myextension.enable": {
"type": "boolean",
"default": true,
"scope": "resource",
"description": "Enable running of my extension."
}
}
}
}
}
<
Required properties of package.json:
• name: The unique name of extension, to publish the extension, the name
should not be taken by exists packages at https://www.npmjs.com/
• version: The semver version of extension.
• engines: Should have `coc` property with minimal required coc.nvim version.
The `main` property contains the relative filepath of the javascript entry
file, `index.js` would be used when not exists.
The `activationEvents` property tell coc.nvim when to activate the extension,
when the property not exists or `*` is included, the extension would be
activated during coc.nvim initialize. Other possible events:
• onLanguage: Activate the extension when document of specific languageId
exists, ex: `"onLanguage:vim"` activate the extension when there's buffer with
languageId as vim loaded.
• onFileSystem: Activate the extension when document with custom schema
loaded, ex: `"onFileSystem:fugitive"` activate the extension when there's
buffer with schema `fugitive` loaded.
• onCommand: activate the extension when specific command invoked by user,
ex: `"onCommand:tsserver.reloadProjects"`
• workspaceContains: activate the extension when the glob pattern match one
of the file in current workspace folder, ex:
`"workspaceContains:**/package.json"`
Optional `contributes` property contains the meta data that contributed to
coc.nvim, including:
• rootPatterns: The patterns to resolve |coc-workspace-folders| for
associated filetype.
• commands: List of commands with `id` and `title` that can be invoked by
|:CocCommand|.
• configuration: Contains `properties` object or a list of configurations
that each one provide `properties` objects which define the configuration
properties contributed by this extension.
The `contributes` property could also contains other properties that used by
other extensions, for example: the `jsonValidation` property could be used by
coc-json.
It's recommended to install `coc-json` for json intellisense support.
------------------------------------------------------------------------------
SINGLE FILE EXTENSIONS *coc-api-single*
The easiest way to access the NodeJS API is make use of single file
extensions.
All Javascript files that ends with `.js` inside the folder "coc-extensions"
under |g:coc_config_home| are considered as coc extensions.
The javascript files would be loaded during coc.nvim initialize by default.
To contribute extension meta data, create file `${name}.json` aside with
`${name}.js`, the json file works the same as package.json of extension
|coc-api-json|, except that only `activationEvents` and `contributes`
properties are used.
Single file extensions can't be managed by extensions list.
------------------------------------------------------------------------------
CREATE CUSTOM EXTENSIONS *coc-api-extension*
To make an extension installable by |:CocInstall|, the easiest way is make use
of https://github.com/fannheyward/create-coc-extension. Simply run command
>
npm init coc-extension [extension-name]
<
or
>
yarn create coc-extension [extension-name]
<
in terminal and you will be prompted for create a javascript/typescript
extension step by step.
To manually create an extension, follow these step:
• Create an empty folder and goto that folder.
• Create the package.json file |coc-api-json|.
• Create a javascript file with name `index.js` and write code.
• Add the created folder to your vim's runtimepath by
add `set runtimepath^=/path/to/folder` in your vimrc.
Recommended steps:
• Install types of NodeJS and coc.nvim by terminal command
`npm install @types/node@latest coc.nvim` in extension folder.
• Bundle the javascript files when using multiple node dependencies by
esbuild to save the time of installation. A typical build script looks
like: >
async function start() {
await require('esbuild').build({
entryPoints: ['src/index.ts'],
bundle: true,
minify: process.env.NODE_ENV === 'production',
sourcemap: process.env.NODE_ENV === 'development',
mainFields: ['module', 'main'],
external: ['coc.nvim'],
platform: 'node',
target: 'node16.18',
outfile: 'lib/index.js'
})
}
start().catch(e => {
console.error(e)
})
<
------------------------------------------------------------------------------
DEBUG EXTENSIONS *coc-api-debug*
*coc-api-channel*
Channel errors: ~
Channel feature on vim9 is used by coc.nvim to communicate between vim and
NodeJS, the error messages caused by channel commands are not displayed on the
screen. Most of the time the error should be caught by coc.nvim and can be
checked by |CocOpenLog|. But for some API functions including `callVim()`
`exVim()` and `evalVim()`, the errors only update the |v:errmsg| and appears
in vim's channel log, which can be checked by use |g:node_client_debug| or
set environment variable `$COC_VIM_CHANNEL_ENABLE` to `"1"`.
Uncaught errors: ~
When an uncaught error raised on the NodeJS process, the error message would
be send to vim through stderr, and echoed by vim (unless
|g:coc_disable_uncaught_error| is enabled).
The error messages are not stored by vim's message history, use
|:CocPrintErrors| to show previous errors.
When error happens on the vim side, the promise would be rejected when sending
request to vim, for notifications, vim would send `nvim_error_event` to the
NodeJS process, and the node-client would create error log for it (could be
opened by |:CocOpenLog|).
Use the log file: ~
• Configure `NVIM_COC_LOG_LEVEL` to `trace` in vimrc:
`let $NVIM_COC_LOG_LEVEL='trace'`
• Configure `NVIM_COC_LOG_FILE` to a fixed in vimrc:
`let $NVIM_COC_LOG_FILE=/tmp/coc.log`, otherwise it would be different for
each vim instance.
• Use |coc-api-console| to add console statements in javascript/typescript
code and compile the extension when needed.
• Tail the log file by `tail` command and make the issue happen.
Add source map support: ~
When the javascript code is bundled by esbuild, it would be useful to have
correct source map support for the error stack.
• Install global source-map-support by `npm install -g source-map-support`
• Find out the npm root by `npm root -g`
• Load source-map-support with coc.nvim by append arguments to node in vimrc:
`let g:coc_node_args = ['-r', '/path/to/npm/root/source-map-support/register']`
Replace the part `/path/to/npm/root` with result from `npm root -g` terminal
command.
Note: the source-map-support module slows down the coc.nvim initialization.
Debug javascript code with chrome: ~
• Add `let g:coc_node_args = ['--nolazy', '--inspect-brk=5858']`
• Open vim and you will get the error message indicate that the debugger is
listening.
• Open Chrome browser with url chrome://inspect/#devices, configure
the `Target discovery settings` and you will get the remote target to
inspect.
• Click the inspect link to open the devtools.
• Click the sources label to debug javascript code.
Other debugger clients can be used as well, see:
https://nodejs.org/en/docs/guides/debugging-getting-started/
==============================================================================
vim:tw=78:sta:noet:ts=8:sts=0:ft=help:fen:

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,179 @@
-- https://raw.githubusercontent.com/neoclide/coc.nvim/refs/heads/master/doc/coc-example-config.lua
-- Some servers have issues with backup files, see #649
vim.opt.backup = false
vim.opt.writebackup = false
-- Having longer updatetime (default is 4000 ms = 4s) leads to noticeable
-- delays and poor user experience
vim.opt.updatetime = 300
-- Always show the signcolumn, otherwise it would shift the text each time
-- diagnostics appeared/became resolved
vim.opt.signcolumn = 'yes'
local keyset = vim.keymap.set
-- Autocomplete
function _G.check_back_space()
local col = vim.fn.col('.') - 1
return col == 0 or vim.fn.getline('.'):sub(col, col):match('%s') ~= nil
end
-- Use Tab for trigger completion with characters ahead and navigate
-- NOTE: There's always a completion item selected by default, you may want to enable
-- no select by setting `"suggest.noselect": true` in your configuration file
-- NOTE: Use command ':verbose imap <tab>' to make sure Tab is not mapped by
-- other plugins before putting this into your config
local opts = { silent = true, noremap = true, expr = true, replace_keycodes = false }
keyset('i', '<TAB>', 'coc#pum#visible() ? coc#pum#next(1) : v:lua.check_back_space() ? "<TAB>" : coc#refresh()', opts)
keyset('i', '<S-TAB>', [[coc#pum#visible() ? coc#pum#prev(1) : "\<C-h>"]], opts)
-- Make <CR> to accept selected completion item or notify coc.nvim to format
-- <C-g>u breaks current undo, please make your own choice
keyset('i', '<cr>', [[coc#pum#visible() ? coc#pum#confirm() : "\<C-g>u\<CR>\<c-r>=coc#on_enter()\<CR>"]], opts)
-- Use <c-j> to trigger snippets
keyset('i', '<c-j>', '<Plug>(coc-snippets-expand-jump)')
-- Use <c-space> to trigger completion
keyset('i', '<c-space>', 'coc#refresh()', { silent = true, expr = true })
-- Use `[g` and `]g` to navigate diagnostics
-- Use `:CocDiagnostics` to get all diagnostics of current buffer in location list
keyset('n', '[g', '<Plug>(coc-diagnostic-prev)', { silent = true })
keyset('n', ']g', '<Plug>(coc-diagnostic-next)', { silent = true })
-- GoTo code navigation
keyset('n', 'gd', '<Plug>(coc-definition)', { silent = true })
keyset('n', 'gy', '<Plug>(coc-type-definition)', { silent = true })
keyset('n', 'gi', '<Plug>(coc-implementation)', { silent = true })
keyset('n', 'gr', '<Plug>(coc-references)', { silent = true })
-- Use K to show documentation in preview window
function _G.show_docs()
local cw = vim.fn.expand('<cword>')
if vim.fn.index({ 'vim', 'help' }, vim.bo.filetype) >= 0 then
vim.api.nvim_command('h ' .. cw)
elseif vim.api.nvim_eval('coc#rpc#ready()') then
vim.fn.CocActionAsync('doHover')
else
vim.api.nvim_command('!' .. vim.o.keywordprg .. ' ' .. cw)
end
end
keyset('n', 'K', '<CMD>lua _G.show_docs()<CR>', { silent = true })
-- Highlight the symbol and its references on a CursorHold event(cursor is idle)
vim.api.nvim_create_augroup('CocGroup', {})
vim.api.nvim_create_autocmd('CursorHold', {
group = 'CocGroup',
command = "silent call CocActionAsync('highlight')",
desc = 'Highlight symbol under cursor on CursorHold'
})
-- Symbol renaming
keyset('n', '<leader>rn', '<Plug>(coc-rename)', { silent = true })
-- Formatting selected code
keyset('x', '<leader>f', '<Plug>(coc-format-selected)', { silent = true })
keyset('n', '<leader>f', '<Plug>(coc-format-selected)', { silent = true })
-- Setup formatexpr specified filetype(s)
vim.api.nvim_create_autocmd('FileType', {
group = 'CocGroup',
pattern = 'typescript,json',
command = "setl formatexpr=CocAction('formatSelected')",
desc = 'Setup formatexpr specified filetype(s).'
})
-- Apply codeAction to the selected region
-- Example: `<leader>aap` for current paragraph
local opts = { silent = true, nowait = true }
keyset('x', '<leader>a', '<Plug>(coc-codeaction-selected)', opts)
keyset('n', '<leader>a', '<Plug>(coc-codeaction-selected)', opts)
-- Remap keys for apply code actions at the cursor position.
keyset('n', '<leader>ac', '<Plug>(coc-codeaction-cursor)', opts)
-- Remap keys for apply source code actions for current file.
keyset('n', '<leader>as', '<Plug>(coc-codeaction-source)', opts)
-- Apply the most preferred quickfix action on the current line.
keyset('n', '<leader>qf', '<Plug>(coc-fix-current)', opts)
-- Remap keys for apply refactor code actions.
keyset('n', '<leader>re', '<Plug>(coc-codeaction-refactor)', { silent = true })
keyset('x', '<leader>r', '<Plug>(coc-codeaction-refactor-selected)', { silent = true })
keyset('n', '<leader>r', '<Plug>(coc-codeaction-refactor-selected)', { silent = true })
-- Run the Code Lens actions on the current line
keyset('n', '<leader>cl', '<Plug>(coc-codelens-action)', opts)
-- Map function and class text objects
-- NOTE: Requires 'textDocument.documentSymbol' support from the language server
keyset('x', 'if', '<Plug>(coc-funcobj-i)', opts)
keyset('o', 'if', '<Plug>(coc-funcobj-i)', opts)
keyset('x', 'af', '<Plug>(coc-funcobj-a)', opts)
keyset('o', 'af', '<Plug>(coc-funcobj-a)', opts)
keyset('x', 'ic', '<Plug>(coc-classobj-i)', opts)
keyset('o', 'ic', '<Plug>(coc-classobj-i)', opts)
keyset('x', 'ac', '<Plug>(coc-classobj-a)', opts)
keyset('o', 'ac', '<Plug>(coc-classobj-a)', opts)
-- Remap <C-f> and <C-b> to scroll float windows/popups
---@diagnostic disable-next-line: redefined-local
local opts = { silent = true, nowait = true, expr = true }
keyset('n', '<C-f>', 'coc#float#has_scroll() ? coc#float#scroll(1) : "<C-f>"', opts)
keyset('n', '<C-b>', 'coc#float#has_scroll() ? coc#float#scroll(0) : "<C-b>"', opts)
keyset('i', '<C-f>',
'coc#float#has_scroll() ? "<c-r>=coc#float#scroll(1)<cr>" : "<Right>"', opts)
keyset('i', '<C-b>',
'coc#float#has_scroll() ? "<c-r>=coc#float#scroll(0)<cr>" : "<Left>"', opts)
keyset('v', '<C-f>', 'coc#float#has_scroll() ? coc#float#scroll(1) : "<C-f>"', opts)
keyset('v', '<C-b>', 'coc#float#has_scroll() ? coc#float#scroll(0) : "<C-b>"', opts)
-- Use CTRL-S for selections ranges
-- Requires 'textDocument/selectionRange' support of language server
keyset('n', '<C-s>', '<Plug>(coc-range-select)', { silent = true })
keyset('x', '<C-s>', '<Plug>(coc-range-select)', { silent = true })
-- Add `:Format` command to format current buffer
vim.api.nvim_create_user_command('Format', "call CocAction('format')", {})
-- " Add `:Fold` command to fold current buffer
vim.api.nvim_create_user_command('Fold', "call CocAction('fold', <f-args>)", { nargs = '?' })
-- Add `:OR` command for organize imports of the current buffer
vim.api.nvim_create_user_command('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
vim.opt.statusline:prepend("%{coc#status()}%{get(b:,'coc_current_function','')}")
-- Mappings for CoCList
-- code actions and coc stuff
---@diagnostic disable-next-line: redefined-local
local opts = { silent = true, nowait = true }
-- Show all diagnostics
keyset('n', '<space>a', ':<C-u>CocList diagnostics<cr>', opts)
-- Manage extensions
keyset('n', '<space>e', ':<C-u>CocList extensions<cr>', opts)
-- Show commands
keyset('n', '<space>c', ':<C-u>CocList commands<cr>', opts)
-- Find symbol of current document
keyset('n', '<space>o', ':<C-u>CocList outline<cr>', opts)
-- Search workspace symbols
keyset('n', '<space>s', ':<C-u>CocList -I symbols<cr>', opts)
-- Do default action for next item
keyset('n', '<space>j', ':<C-u>CocNext<cr>', opts)
-- Do default action for previous item
keyset('n', '<space>k', ':<C-u>CocPrev<cr>', opts)
-- Resume latest coc list
keyset('n', '<space>p', ':<C-u>CocListResume<cr>', opts)

View file

@ -0,0 +1,158 @@
" https://raw.githubusercontent.com/neoclide/coc.nvim/refs/heads/master/doc/coc-example-config.vim
" May need for Vim (not Neovim) since coc.nvim calculates byte offset by count
" utf-8 byte sequence
set encoding=utf-8
" Some servers have issues with backup files, see #649
set nobackup
set nowritebackup
" Having longer updatetime (default is 4000 ms = 4s) 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 tab for trigger completion with characters ahead and navigate
" NOTE: There's always complete item selected by default, you may want to enable
" no select by `"suggest.noselect": true` in your configuration file
" 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) :
\ CheckBackspace() ? "\<Tab>" :
\ coc#refresh()
inoremap <expr><S-TAB> coc#pum#visible() ? coc#pum#prev(1) : "\<C-h>"
" Make <CR> to accept selected completion item or notify coc.nvim to format
" <C-g>u breaks current undo, 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>"
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
" 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')
augroup end
" Applying code actions to the selected code block
" Example: `<leader>aap` for current paragraph
xmap <leader>a <Plug>(coc-codeaction-selected)
nmap <leader>a <Plug>(coc-codeaction-selected)
" Remap keys for applying code actions at the cursor position
nmap <leader>ac <Plug>(coc-codeaction-cursor)
" Remap keys for apply code actions affect whole buffer
nmap <leader>as <Plug>(coc-codeaction-source)
" Apply the most preferred quickfix action to fix diagnostic on the current line
nmap <leader>qf <Plug>(coc-fix-current)
" Remap keys for applying refactor code actions
nmap <silent> <leader>re <Plug>(coc-codeaction-refactor)
xmap <silent> <leader>r <Plug>(coc-codeaction-refactor-selected)
nmap <silent> <leader>r <Plug>(coc-codeaction-refactor-selected)
" 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> to scroll float windows/popups
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>"
" 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>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,814 @@
$COC_NODE_PATH coc.txt /*$COC_NODE_PATH*
$COC_VIM_CHANNEL_ENABLE coc.txt /*$COC_VIM_CHANNEL_ENABLE*
:CocCommand coc.txt /*:CocCommand*
:CocConfig coc.txt /*:CocConfig*
:CocDiagnostics coc.txt /*:CocDiagnostics*
:CocDisable coc.txt /*:CocDisable*
:CocEnable coc.txt /*:CocEnable*
:CocFirst coc.txt /*:CocFirst*
:CocInfo coc.txt /*:CocInfo*
:CocInstall coc.txt /*:CocInstall*
:CocLast coc.txt /*:CocLast*
:CocList coc.txt /*:CocList*
:CocListCancel coc.txt /*:CocListCancel*
:CocListResume coc.txt /*:CocListResume*
:CocLocalConfig coc.txt /*:CocLocalConfig*
:CocNext coc.txt /*:CocNext*
:CocOpenLog coc.txt /*:CocOpenLog*
:CocOutline coc.txt /*:CocOutline*
:CocPrev coc.txt /*:CocPrev*
:CocPrintErrors coc.txt /*:CocPrintErrors*
:CocRestart coc.txt /*:CocRestart*
:CocSearch coc.txt /*:CocSearch*
:CocStart coc.txt /*:CocStart*
:CocUninstall coc.txt /*:CocUninstall*
:CocUpdate coc.txt /*:CocUpdate*
:CocUpdateSync coc.txt /*:CocUpdateSync*
:CocWatch coc.txt /*:CocWatch*
<Plug>(coc-classobj-a) coc.txt /*<Plug>(coc-classobj-a)*
<Plug>(coc-classobj-i) coc.txt /*<Plug>(coc-classobj-i)*
<Plug>(coc-codeaction) coc.txt /*<Plug>(coc-codeaction)*
<Plug>(coc-codeaction-cursor) coc.txt /*<Plug>(coc-codeaction-cursor)*
<Plug>(coc-codeaction-line) coc.txt /*<Plug>(coc-codeaction-line)*
<Plug>(coc-codeaction-refactor) coc.txt /*<Plug>(coc-codeaction-refactor)*
<Plug>(coc-codeaction-refactor-selected) coc.txt /*<Plug>(coc-codeaction-refactor-selected)*
<Plug>(coc-codeaction-selected) coc.txt /*<Plug>(coc-codeaction-selected)*
<Plug>(coc-codeaction-source) coc.txt /*<Plug>(coc-codeaction-source)*
<Plug>(coc-codelens-action) coc.txt /*<Plug>(coc-codelens-action)*
<Plug>(coc-command-repeat) coc.txt /*<Plug>(coc-command-repeat)*
<Plug>(coc-cursors-operator) coc.txt /*<Plug>(coc-cursors-operator)*
<Plug>(coc-cursors-position) coc.txt /*<Plug>(coc-cursors-position)*
<Plug>(coc-cursors-range) coc.txt /*<Plug>(coc-cursors-range)*
<Plug>(coc-cursors-word) coc.txt /*<Plug>(coc-cursors-word)*
<Plug>(coc-declaration) coc.txt /*<Plug>(coc-declaration)*
<Plug>(coc-definition) coc.txt /*<Plug>(coc-definition)*
<Plug>(coc-diagnostic-info) coc.txt /*<Plug>(coc-diagnostic-info)*
<Plug>(coc-diagnostic-next) coc.txt /*<Plug>(coc-diagnostic-next)*
<Plug>(coc-diagnostic-next-error) coc.txt /*<Plug>(coc-diagnostic-next-error)*
<Plug>(coc-diagnostic-prev) coc.txt /*<Plug>(coc-diagnostic-prev)*
<Plug>(coc-diagnostic-prev-error) coc.txt /*<Plug>(coc-diagnostic-prev-error)*
<Plug>(coc-fix-current) coc.txt /*<Plug>(coc-fix-current)*
<Plug>(coc-float-hide) coc.txt /*<Plug>(coc-float-hide)*
<Plug>(coc-float-jump) coc.txt /*<Plug>(coc-float-jump)*
<Plug>(coc-format) coc.txt /*<Plug>(coc-format)*
<Plug>(coc-format-selected) coc.txt /*<Plug>(coc-format-selected)*
<Plug>(coc-funcobj-a) coc.txt /*<Plug>(coc-funcobj-a)*
<Plug>(coc-funcobj-i) coc.txt /*<Plug>(coc-funcobj-i)*
<Plug>(coc-implementation) coc.txt /*<Plug>(coc-implementation)*
<Plug>(coc-openlink) coc.txt /*<Plug>(coc-openlink)*
<Plug>(coc-range-select) coc.txt /*<Plug>(coc-range-select)*
<Plug>(coc-range-select-backward) coc.txt /*<Plug>(coc-range-select-backward)*
<Plug>(coc-refactor) coc.txt /*<Plug>(coc-refactor)*
<Plug>(coc-references) coc.txt /*<Plug>(coc-references)*
<Plug>(coc-references-used) coc.txt /*<Plug>(coc-references-used)*
<Plug>(coc-rename) coc.txt /*<Plug>(coc-rename)*
<Plug>(coc-type-definition) coc.txt /*<Plug>(coc-type-definition)*
CocAction('activeExtension') coc.txt /*CocAction('activeExtension')*
CocAction('addRanges') coc.txt /*CocAction('addRanges')*
CocAction('addWorkspaceFolder') coc.txt /*CocAction('addWorkspaceFolder')*
CocAction('codeAction') coc.txt /*CocAction('codeAction')*
CocAction('codeActionRange') coc.txt /*CocAction('codeActionRange')*
CocAction('codeActions') coc.txt /*CocAction('codeActions')*
CocAction('codeLensAction') coc.txt /*CocAction('codeLensAction')*
CocAction('colorPresentation') coc.txt /*CocAction('colorPresentation')*
CocAction('commands') coc.txt /*CocAction('commands')*
CocAction('deactivateExtension') coc.txt /*CocAction('deactivateExtension')*
CocAction('declarations') coc.txt /*CocAction('declarations')*
CocAction('definitionHover') coc.txt /*CocAction('definitionHover')*
CocAction('definitions') coc.txt /*CocAction('definitions')*
CocAction('diagnosticInfo') coc.txt /*CocAction('diagnosticInfo')*
CocAction('diagnosticList') coc.txt /*CocAction('diagnosticList')*
CocAction('diagnosticPreview') coc.txt /*CocAction('diagnosticPreview')*
CocAction('diagnosticRefresh') coc.txt /*CocAction('diagnosticRefresh')*
CocAction('diagnosticToggle') coc.txt /*CocAction('diagnosticToggle')*
CocAction('diagnosticToggleBuffer') coc.txt /*CocAction('diagnosticToggleBuffer')*
CocAction('doCodeAction') coc.txt /*CocAction('doCodeAction')*
CocAction('doHover') coc.txt /*CocAction('doHover')*
CocAction('doQuickfix') coc.txt /*CocAction('doQuickfix')*
CocAction('documentSymbols') coc.txt /*CocAction('documentSymbols')*
CocAction('ensureDocument') coc.txt /*CocAction('ensureDocument')*
CocAction('extensionStats') coc.txt /*CocAction('extensionStats')*
CocAction('fixAll') coc.txt /*CocAction('fixAll')*
CocAction('fold') coc.txt /*CocAction('fold')*
CocAction('format') coc.txt /*CocAction('format')*
CocAction('formatSelected') coc.txt /*CocAction('formatSelected')*
CocAction('getCurrentFunctionSymbol') coc.txt /*CocAction('getCurrentFunctionSymbol')*
CocAction('getHover') coc.txt /*CocAction('getHover')*
CocAction('getWordEdit') coc.txt /*CocAction('getWordEdit')*
CocAction('getWorkspaceSymbols') coc.txt /*CocAction('getWorkspaceSymbols')*
CocAction('hideOutline') coc.txt /*CocAction('hideOutline')*
CocAction('highlight') coc.txt /*CocAction('highlight')*
CocAction('implementations') coc.txt /*CocAction('implementations')*
CocAction('incomingCalls') coc.txt /*CocAction('incomingCalls')*
CocAction('inspectSemanticToken') coc.txt /*CocAction('inspectSemanticToken')*
CocAction('jumpDeclaration') coc.txt /*CocAction('jumpDeclaration')*
CocAction('jumpDefinition') coc.txt /*CocAction('jumpDefinition')*
CocAction('jumpImplementation') coc.txt /*CocAction('jumpImplementation')*
CocAction('jumpReferences') coc.txt /*CocAction('jumpReferences')*
CocAction('jumpTypeDefinition') coc.txt /*CocAction('jumpTypeDefinition')*
CocAction('jumpUsed') coc.txt /*CocAction('jumpUsed')*
CocAction('links') coc.txt /*CocAction('links')*
CocAction('openLink') coc.txt /*CocAction('openLink')*
CocAction('organizeImport') coc.txt /*CocAction('organizeImport')*
CocAction('outgoingCalls') coc.txt /*CocAction('outgoingCalls')*
CocAction('pickColor') coc.txt /*CocAction('pickColor')*
CocAction('quickfixes') coc.txt /*CocAction('quickfixes')*
CocAction('rangeSelect') coc.txt /*CocAction('rangeSelect')*
CocAction('refactor') coc.txt /*CocAction('refactor')*
CocAction('references') coc.txt /*CocAction('references')*
CocAction('reloadExtension') coc.txt /*CocAction('reloadExtension')*
CocAction('removeWorkspaceFolder') coc.txt /*CocAction('removeWorkspaceFolder')*
CocAction('rename') coc.txt /*CocAction('rename')*
CocAction('resolveWorkspaceSymbol') coc.txt /*CocAction('resolveWorkspaceSymbol')*
CocAction('runCommand') coc.txt /*CocAction('runCommand')*
CocAction('selectionRanges') coc.txt /*CocAction('selectionRanges')*
CocAction('semanticHighlight') coc.txt /*CocAction('semanticHighlight')*
CocAction('sendNotification') coc.txt /*CocAction('sendNotification')*
CocAction('sendRequest') coc.txt /*CocAction('sendRequest')*
CocAction('services') coc.txt /*CocAction('services')*
CocAction('showIncomingCalls') coc.txt /*CocAction('showIncomingCalls')*
CocAction('showOutgoingCalls') coc.txt /*CocAction('showOutgoingCalls')*
CocAction('showOutline') coc.txt /*CocAction('showOutline')*
CocAction('showSignatureHelp') coc.txt /*CocAction('showSignatureHelp')*
CocAction('showSubTypes') coc.txt /*CocAction('showSubTypes')*
CocAction('showSuperTypes') coc.txt /*CocAction('showSuperTypes')*
CocAction('snippetCancel') coc.txt /*CocAction('snippetCancel')*
CocAction('snippetInsert') coc.txt /*CocAction('snippetInsert')*
CocAction('sourceStat') coc.txt /*CocAction('sourceStat')*
CocAction('toggleExtension') coc.txt /*CocAction('toggleExtension')*
CocAction('toggleService') coc.txt /*CocAction('toggleService')*
CocAction('toggleSource') coc.txt /*CocAction('toggleSource')*
CocAction('typeDefinitions') coc.txt /*CocAction('typeDefinitions')*
CocAction('uninstallExtension') coc.txt /*CocAction('uninstallExtension')*
CocAction() coc.txt /*CocAction()*
CocActionAsync() coc.txt /*CocActionAsync()*
CocBold coc.txt /*CocBold*
CocCodeLens coc.txt /*CocCodeLens*
CocCursorRange coc.txt /*CocCursorRange*
CocDeprecatedHighlight coc.txt /*CocDeprecatedHighlight*
CocDiagnosticChange coc.txt /*CocDiagnosticChange*
CocDisabled coc.txt /*CocDisabled*
CocErrorFloat coc.txt /*CocErrorFloat*
CocErrorHighlight coc.txt /*CocErrorHighlight*
CocErrorLine coc.txt /*CocErrorLine*
CocErrorSign coc.txt /*CocErrorSign*
CocErrorVirtualText coc.txt /*CocErrorVirtualText*
CocFadeOut coc.txt /*CocFadeOut*
CocFloatActive coc.txt /*CocFloatActive*
CocFloatBorder coc.txt /*CocFloatBorder*
CocFloatDividingLine coc.txt /*CocFloatDividingLine*
CocFloatSbar coc.txt /*CocFloatSbar*
CocFloatThumb coc.txt /*CocFloatThumb*
CocFloating coc.txt /*CocFloating*
CocHasProvider() coc.txt /*CocHasProvider()*
CocHighlightRead coc.txt /*CocHighlightRead*
CocHighlightText coc.txt /*CocHighlightText*
CocHighlightWrite coc.txt /*CocHighlightWrite*
CocHintFloat coc.txt /*CocHintFloat*
CocHintHighlight coc.txt /*CocHintHighlight*
CocHintLine coc.txt /*CocHintLine*
CocHintSign coc.txt /*CocHintSign*
CocHintVirtualText coc.txt /*CocHintVirtualText*
CocHoverRange coc.txt /*CocHoverRange*
CocInfoHighlight coc.txt /*CocInfoHighlight*
CocInfoLine coc.txt /*CocInfoLine*
CocInfoSign coc.txt /*CocInfoSign*
CocInfoVirtualText coc.txt /*CocInfoVirtualText*
CocInlayHint coc.txt /*CocInlayHint*
CocInlayHintParameter coc.txt /*CocInlayHintParameter*
CocInlayHintType coc.txt /*CocInlayHintType*
CocInline coc.txt /*CocInline*
CocInlineAnnotation coc.txt /*CocInlineAnnotation*
CocInlineVirtualText coc.txt /*CocInlineVirtualText*
CocInputBoxVirtualText coc.txt /*CocInputBoxVirtualText*
CocItalic coc.txt /*CocItalic*
CocJumpPlaceholder coc.txt /*CocJumpPlaceholder*
CocLink coc.txt /*CocLink*
CocLinkedEditing coc.txt /*CocLinkedEditing*
CocList coc.txt /*CocList*
CocListLine coc.txt /*CocListLine*
CocListMode coc.txt /*CocListMode*
CocListPath coc.txt /*CocListPath*
CocListSearch coc.txt /*CocListSearch*
CocLocations() coc.txt /*CocLocations()*
CocLocationsAsync() coc.txt /*CocLocationsAsync()*
CocLocationsChange coc.txt /*CocLocationsChange*
CocMarkdownCode coc.txt /*CocMarkdownCode*
CocMarkdownHeader coc.txt /*CocMarkdownHeader*
CocMarkdownLink coc.txt /*CocMarkdownLink*
CocMenuSel coc.txt /*CocMenuSel*
CocNotification coc.txt /*CocNotification*
CocNotificationButton coc.txt /*CocNotificationButton*
CocNotificationError coc.txt /*CocNotificationError*
CocNotificationInfo coc.txt /*CocNotificationInfo*
CocNotificationKey coc.txt /*CocNotificationKey*
CocNotificationProgress coc.txt /*CocNotificationProgress*
CocNotificationWarning coc.txt /*CocNotificationWarning*
CocNotify() coc.txt /*CocNotify()*
CocNvimInit coc.txt /*CocNvimInit*
CocOpenFloat coc.txt /*CocOpenFloat*
CocOpenFloatPrompt coc.txt /*CocOpenFloatPrompt*
CocPum coc.txt /*CocPum*
CocPumDeprecated coc.txt /*CocPumDeprecated*
CocPumDetail coc.txt /*CocPumDetail*
CocPumMenu coc.txt /*CocPumMenu*
CocPumSearch coc.txt /*CocPumSearch*
CocPumShortcut coc.txt /*CocPumShortcut*
CocPumVirtualText coc.txt /*CocPumVirtualText*
CocRegisterNotification() coc.txt /*CocRegisterNotification()*
CocRequest() coc.txt /*CocRequest()*
CocRequestAsync() coc.txt /*CocRequestAsync()*
CocSearch coc.txt /*CocSearch*
CocSelectedLine coc.txt /*CocSelectedLine*
CocSelectedRange coc.txt /*CocSelectedRange*
CocSelectedText coc.txt /*CocSelectedText*
CocSem coc.txt /*CocSem*
CocSnippetVisual coc.txt /*CocSnippetVisual*
CocStatusChange coc.txt /*CocStatusChange*
CocStrikeThrough coc.txt /*CocStrikeThrough*
CocSymbol coc.txt /*CocSymbol*
CocSymbolArray coc.txt /*CocSymbolArray*
CocSymbolBoolean coc.txt /*CocSymbolBoolean*
CocSymbolClass coc.txt /*CocSymbolClass*
CocSymbolColor coc.txt /*CocSymbolColor*
CocSymbolConstant coc.txt /*CocSymbolConstant*
CocSymbolConstructor coc.txt /*CocSymbolConstructor*
CocSymbolDefault coc.txt /*CocSymbolDefault*
CocSymbolEnum coc.txt /*CocSymbolEnum*
CocSymbolEnumMember coc.txt /*CocSymbolEnumMember*
CocSymbolEvent coc.txt /*CocSymbolEvent*
CocSymbolField coc.txt /*CocSymbolField*
CocSymbolFile coc.txt /*CocSymbolFile*
CocSymbolFolder coc.txt /*CocSymbolFolder*
CocSymbolFunction coc.txt /*CocSymbolFunction*
CocSymbolInterface coc.txt /*CocSymbolInterface*
CocSymbolKey coc.txt /*CocSymbolKey*
CocSymbolKeyword coc.txt /*CocSymbolKeyword*
CocSymbolMethod coc.txt /*CocSymbolMethod*
CocSymbolModule coc.txt /*CocSymbolModule*
CocSymbolNamespace coc.txt /*CocSymbolNamespace*
CocSymbolNull coc.txt /*CocSymbolNull*
CocSymbolNumber coc.txt /*CocSymbolNumber*
CocSymbolObject coc.txt /*CocSymbolObject*
CocSymbolOperator coc.txt /*CocSymbolOperator*
CocSymbolPackage coc.txt /*CocSymbolPackage*
CocSymbolProperty coc.txt /*CocSymbolProperty*
CocSymbolReference coc.txt /*CocSymbolReference*
CocSymbolSnippet coc.txt /*CocSymbolSnippet*
CocSymbolString coc.txt /*CocSymbolString*
CocSymbolStruct coc.txt /*CocSymbolStruct*
CocSymbolText coc.txt /*CocSymbolText*
CocSymbolTypeParameter coc.txt /*CocSymbolTypeParameter*
CocSymbolUnit coc.txt /*CocSymbolUnit*
CocSymbolValue coc.txt /*CocSymbolValue*
CocSymbolVariable coc.txt /*CocSymbolVariable*
CocTagFunc() coc.txt /*CocTagFunc()*
CocTerminalOpen coc.txt /*CocTerminalOpen*
CocTree coc.txt /*CocTree*
CocTreeDescription coc.txt /*CocTreeDescription*
CocTreeOpenClose coc.txt /*CocTreeOpenClose*
CocTreeSelected coc.txt /*CocTreeSelected*
CocTreeTitle coc.txt /*CocTreeTitle*
CocUnderline coc.txt /*CocUnderline*
CocUnusedHighlight coc.txt /*CocUnusedHighlight*
CocWarningHighlight coc.txt /*CocWarningHighlight*
CocWarningLine coc.txt /*CocWarningLine*
CocWarningSign coc.txt /*CocWarningSign*
CocWarningVirtualText coc.txt /*CocWarningVirtualText*
b:coc_additional_keywords coc.txt /*b:coc_additional_keywords*
b:coc_current_function coc.txt /*b:coc_current_function*
b:coc_cursors_activated coc.txt /*b:coc_cursors_activated*
b:coc_diagnostic_disable coc.txt /*b:coc_diagnostic_disable*
b:coc_diagnostic_info coc.txt /*b:coc_diagnostic_info*
b:coc_diagnostic_map coc.txt /*b:coc_diagnostic_map*
b:coc_disable_autoformat coc.txt /*b:coc_disable_autoformat*
b:coc_disabled_sources coc.txt /*b:coc_disabled_sources*
b:coc_enabled coc.txt /*b:coc_enabled*
b:coc_force_attach coc.txt /*b:coc_force_attach*
b:coc_inline_disable coc.txt /*b:coc_inline_disable*
b:coc_root_patterns coc.txt /*b:coc_root_patterns*
b:coc_snippet_active coc.txt /*b:coc_snippet_active*
b:coc_suggest_blacklist coc.txt /*b:coc_suggest_blacklist*
b:coc_suggest_disable coc.txt /*b:coc_suggest_disable*
b:coc_trim_final_newlines coc.txt /*b:coc_trim_final_newlines*
b:coc_trim_trailing_whitespace coc.txt /*b:coc_trim_trailing_whitespace*
coc#add_command() coc.txt /*coc#add_command()*
coc#compat#call() coc.txt /*coc#compat#call()*
coc#config() coc.txt /*coc#config()*
coc#expandable() coc.txt /*coc#expandable()*
coc#expandableOrJumpable() coc.txt /*coc#expandableOrJumpable()*
coc#float#close() coc.txt /*coc#float#close()*
coc#float#close_all() coc.txt /*coc#float#close_all()*
coc#float#has_float() coc.txt /*coc#float#has_float()*
coc#float#has_scroll() coc.txt /*coc#float#has_scroll()*
coc#float#scroll() coc.txt /*coc#float#scroll()*
coc#inline#accept() coc.txt /*coc#inline#accept()*
coc#inline#cancel() coc.txt /*coc#inline#cancel()*
coc#inline#next() coc.txt /*coc#inline#next()*
coc#inline#prev() coc.txt /*coc#inline#prev()*
coc#inline#trigger() coc.txt /*coc#inline#trigger()*
coc#inline#visible() coc.txt /*coc#inline#visible()*
coc#jumpable() coc.txt /*coc#jumpable()*
coc#notify coc.txt /*coc#notify*
coc#notify#close_all() coc.txt /*coc#notify#close_all()*
coc#notify#copy() coc.txt /*coc#notify#copy()*
coc#notify#do_action() coc.txt /*coc#notify#do_action()*
coc#notify#keep() coc.txt /*coc#notify#keep()*
coc#notify#show_sources() coc.txt /*coc#notify#show_sources()*
coc#on_enter() coc.txt /*coc#on_enter()*
coc#pum coc.txt /*coc#pum*
coc#pum#cancel() coc.txt /*coc#pum#cancel()*
coc#pum#confirm() coc.txt /*coc#pum#confirm()*
coc#pum#has_item_selected coc.txt /*coc#pum#has_item_selected*
coc#pum#info() coc.txt /*coc#pum#info()*
coc#pum#insert() coc.txt /*coc#pum#insert()*
coc#pum#next() coc.txt /*coc#pum#next()*
coc#pum#one_more() coc.txt /*coc#pum#one_more()*
coc#pum#prev() coc.txt /*coc#pum#prev()*
coc#pum#scroll() coc.txt /*coc#pum#scroll()*
coc#pum#select() coc.txt /*coc#pum#select()*
coc#pum#select_confirm() coc.txt /*coc#pum#select_confirm()*
coc#pum#stop() coc.txt /*coc#pum#stop()*
coc#pum#visible() coc.txt /*coc#pum#visible()*
coc#refresh() coc.txt /*coc#refresh()*
coc#snippet#next() coc.txt /*coc#snippet#next()*
coc#snippet#prev() coc.txt /*coc#snippet#prev()*
coc#start() coc.txt /*coc#start()*
coc#status() coc.txt /*coc#status()*
coc#util#api_version() coc.txt /*coc#util#api_version()*
coc#util#extension_root() coc.txt /*coc#util#extension_root()*
coc#util#get_config() coc.txt /*coc#util#get_config()*
coc#util#get_config_home() coc.txt /*coc#util#get_config_home()*
coc#util#get_data_home() coc.txt /*coc#util#get_data_home()*
coc#util#job_command() coc.txt /*coc#util#job_command()*
coc#util#root_patterns() coc.txt /*coc#util#root_patterns()*
coc-actions coc.txt /*coc-actions*
coc-api-channel coc-api.txt /*coc-api-channel*
coc-api-console coc-api.txt /*coc-api-console*
coc-api-debug coc-api.txt /*coc-api-debug*
coc-api-extension coc-api.txt /*coc-api-extension*
coc-api-intro coc-api.txt /*coc-api-intro*
coc-api-json coc-api.txt /*coc-api-json*
coc-api-single coc-api.txt /*coc-api-single*
coc-api-vim-source coc-api.txt /*coc-api-vim-source*
coc-api.txt coc-api.txt /*coc-api.txt*
coc-autocmds coc.txt /*coc-autocmds*
coc-buffer-variables coc.txt /*coc-buffer-variables*
coc-callHierarchy coc.txt /*coc-callHierarchy*
coc-changelog coc.txt /*coc-changelog*
coc-code-actions coc.txt /*coc-code-actions*
coc-code-lens coc.txt /*coc-code-lens*
coc-commands coc.txt /*coc-commands*
coc-completion coc.txt /*coc-completion*
coc-completion-customize coc.txt /*coc-completion-customize*
coc-completion-default coc.txt /*coc-completion-default*
coc-completion-example coc.txt /*coc-completion-example*
coc-completion-functions coc.txt /*coc-completion-functions*
coc-completion-variables coc.txt /*coc-completion-variables*
coc-config coc-config.txt /*coc-config*
coc-config-callHierarchy coc-config.txt /*coc-config-callHierarchy*
coc-config-callHierarchy-enableTooltip coc-config.txt /*coc-config-callHierarchy-enableTooltip*
coc-config-callHierarchy-openCommand coc-config.txt /*coc-config-callHierarchy-openCommand*
coc-config-callHierarchy-splitCommand coc-config.txt /*coc-config-callHierarchy-splitCommand*
coc-config-codeLens coc-config.txt /*coc-config-codeLens*
coc-config-codeLens-display coc-config.txt /*coc-config-codeLens-display*
coc-config-codeLens-enable coc-config.txt /*coc-config-codeLens-enable*
coc-config-codeLens-position coc-config.txt /*coc-config-codeLens-position*
coc-config-codeLens-separator coc-config.txt /*coc-config-codeLens-separator*
coc-config-codeLens-subseparator coc-config.txt /*coc-config-codeLens-subseparator*
coc-config-colors coc-config.txt /*coc-config-colors*
coc-config-colors-enable coc-config.txt /*coc-config-colors-enable*
coc-config-colors-highlightPriority coc-config.txt /*coc-config-colors-highlightPriority*
coc-config-cursors coc-config.txt /*coc-config-cursors*
coc-config-cursors-cancelKey coc-config.txt /*coc-config-cursors-cancelKey*
coc-config-cursors-nextKey coc-config.txt /*coc-config-cursors-nextKey*
coc-config-cursors-previousKey coc-config.txt /*coc-config-cursors-previousKey*
coc-config-cursors-wrapscan coc-config.txt /*coc-config-cursors-wrapscan*
coc-config-diagnostic coc-config.txt /*coc-config-diagnostic*
coc-config-diagnostic-autoRefresh coc-config.txt /*coc-config-diagnostic-autoRefresh*
coc-config-diagnostic-checkCurrentLine coc-config.txt /*coc-config-diagnostic-checkCurrentLine*
coc-config-diagnostic-displayByAle coc-config.txt /*coc-config-diagnostic-displayByAle*
coc-config-diagnostic-displayByVimDiagnostic coc-config.txt /*coc-config-diagnostic-displayByVimDiagnostic*
coc-config-diagnostic-enable coc-config.txt /*coc-config-diagnostic-enable*
coc-config-diagnostic-enableHighlightLineNumber coc-config.txt /*coc-config-diagnostic-enableHighlightLineNumber*
coc-config-diagnostic-enableMessage coc-config.txt /*coc-config-diagnostic-enableMessage*
coc-config-diagnostic-enableSign coc-config.txt /*coc-config-diagnostic-enableSign*
coc-config-diagnostic-errorSign coc-config.txt /*coc-config-diagnostic-errorSign*
coc-config-diagnostic-filetypeMap coc-config.txt /*coc-config-diagnostic-filetypeMap*
coc-config-diagnostic-floatConfig coc-config.txt /*coc-config-diagnostic-floatConfig*
coc-config-diagnostic-format coc-config.txt /*coc-config-diagnostic-format*
coc-config-diagnostic-highlightLimit coc-config.txt /*coc-config-diagnostic-highlightLimit*
coc-config-diagnostic-highlightPriority coc-config.txt /*coc-config-diagnostic-highlightPriority*
coc-config-diagnostic-hintSign coc-config.txt /*coc-config-diagnostic-hintSign*
coc-config-diagnostic-infoSign coc-config.txt /*coc-config-diagnostic-infoSign*
coc-config-diagnostic-level coc-config.txt /*coc-config-diagnostic-level*
coc-config-diagnostic-locationlistLevel coc-config.txt /*coc-config-diagnostic-locationlistLevel*
coc-config-diagnostic-locationlistUpdate coc-config.txt /*coc-config-diagnostic-locationlistUpdate*
coc-config-diagnostic-messageDelay coc-config.txt /*coc-config-diagnostic-messageDelay*
coc-config-diagnostic-messageLevel coc-config.txt /*coc-config-diagnostic-messageLevel*
coc-config-diagnostic-messageTarget coc-config.txt /*coc-config-diagnostic-messageTarget*
coc-config-diagnostic-refreshOnInsertMode coc-config.txt /*coc-config-diagnostic-refreshOnInsertMode*
coc-config-diagnostic-showDeprecated coc-config.txt /*coc-config-diagnostic-showDeprecated*
coc-config-diagnostic-showRelatedInformation coc-config.txt /*coc-config-diagnostic-showRelatedInformation*
coc-config-diagnostic-showUnused coc-config.txt /*coc-config-diagnostic-showUnused*
coc-config-diagnostic-signLevel coc-config.txt /*coc-config-diagnostic-signLevel*
coc-config-diagnostic-signPriority coc-config.txt /*coc-config-diagnostic-signPriority*
coc-config-diagnostic-virtualText coc-config.txt /*coc-config-diagnostic-virtualText*
coc-config-diagnostic-virtualTextAlign coc-config.txt /*coc-config-diagnostic-virtualTextAlign*
coc-config-diagnostic-virtualTextCurrentLineOnly coc-config.txt /*coc-config-diagnostic-virtualTextCurrentLineOnly*
coc-config-diagnostic-virtualTextFormat coc-config.txt /*coc-config-diagnostic-virtualTextFormat*
coc-config-diagnostic-virtualTextLevel coc-config.txt /*coc-config-diagnostic-virtualTextLevel*
coc-config-diagnostic-virtualTextLimitInOneLine coc-config.txt /*coc-config-diagnostic-virtualTextLimitInOneLine*
coc-config-diagnostic-virtualTextLineSeparator coc-config.txt /*coc-config-diagnostic-virtualTextLineSeparator*
coc-config-diagnostic-virtualTextLines coc-config.txt /*coc-config-diagnostic-virtualTextLines*
coc-config-diagnostic-virtualTextPrefix coc-config.txt /*coc-config-diagnostic-virtualTextPrefix*
coc-config-diagnostic-virtualTextWinCol coc-config.txt /*coc-config-diagnostic-virtualTextWinCol*
coc-config-diagnostic-warningSign coc-config.txt /*coc-config-diagnostic-warningSign*
coc-config-dialog coc-config.txt /*coc-config-dialog*
coc-config-dialog-confirmKey coc-config.txt /*coc-config-dialog-confirmKey*
coc-config-dialog-floatBorderHighlight coc-config.txt /*coc-config-dialog-floatBorderHighlight*
coc-config-dialog-floatHighlight coc-config.txt /*coc-config-dialog-floatHighlight*
coc-config-dialog-maxHeight coc-config.txt /*coc-config-dialog-maxHeight*
coc-config-dialog-maxWidth coc-config.txt /*coc-config-dialog-maxWidth*
coc-config-dialog-pickerButtonShortcut coc-config.txt /*coc-config-dialog-pickerButtonShortcut*
coc-config-dialog-pickerButtons coc-config.txt /*coc-config-dialog-pickerButtons*
coc-config-dialog-rounded coc-config.txt /*coc-config-dialog-rounded*
coc-config-dialog-shortcutHighlight coc-config.txt /*coc-config-dialog-shortcutHighlight*
coc-config-documentHighlight coc-config.txt /*coc-config-documentHighlight*
coc-config-documentHighlight-limit coc-config.txt /*coc-config-documentHighlight-limit*
coc-config-documentHighlight-priority coc-config.txt /*coc-config-documentHighlight-priority*
coc-config-documentHighlight-timeout coc-config.txt /*coc-config-documentHighlight-timeout*
coc-config-editor coc-config.txt /*coc-config-editor*
coc-config-editor-autocmdTimeout coc-config.txt /*coc-config-editor-autocmdTimeout*
coc-config-editor-codeActionsOnSave coc-config.txt /*coc-config-editor-codeActionsOnSave*
coc-config-extensions coc-config.txt /*coc-config-extensions*
coc-config-extensions-recommendations coc-config.txt /*coc-config-extensions-recommendations*
coc-config-extensions-silentAutoupdate coc-config.txt /*coc-config-extensions-silentAutoupdate*
coc-config-extensions-updateCheck coc-config.txt /*coc-config-extensions-updateCheck*
coc-config-extensions-updateUIInTab coc-config.txt /*coc-config-extensions-updateUIInTab*
coc-config-fileSystemWatch coc-config.txt /*coc-config-fileSystemWatch*
coc-config-filesystemwatch-enable coc-config.txt /*coc-config-filesystemwatch-enable*
coc-config-filesystemwatch-ignoredFolders coc-config.txt /*coc-config-filesystemwatch-ignoredFolders*
coc-config-filesystemwatch-watchmanPath coc-config.txt /*coc-config-filesystemwatch-watchmanPath*
coc-config-float coc-config.txt /*coc-config-float*
coc-config-floatFactory coc-config.txt /*coc-config-floatFactory*
coc-config-floatFactory-floatConfig coc-config.txt /*coc-config-floatFactory-floatConfig*
coc-config-hover coc-config.txt /*coc-config-hover*
coc-config-hover-autoHide coc-config.txt /*coc-config-hover-autoHide*
coc-config-hover-floatConfig coc-config.txt /*coc-config-hover-floatConfig*
coc-config-hover-previewMaxHeight coc-config.txt /*coc-config-hover-previewMaxHeight*
coc-config-hover-target coc-config.txt /*coc-config-hover-target*
coc-config-http coc-config.txt /*coc-config-http*
coc-config-http-proxy coc-config.txt /*coc-config-http-proxy*
coc-config-http-proxyAuthorization coc-config.txt /*coc-config-http-proxyAuthorization*
coc-config-http-proxyCA coc-config.txt /*coc-config-http-proxyCA*
coc-config-http-proxyStrictSSL coc-config.txt /*coc-config-http-proxyStrictSSL*
coc-config-inlayHint coc-config.txt /*coc-config-inlayHint*
coc-config-inlayHint-display coc-config.txt /*coc-config-inlayHint-display*
coc-config-inlayHint-enable coc-config.txt /*coc-config-inlayHint-enable*
coc-config-inlayHint-enableParameter coc-config.txt /*coc-config-inlayHint-enableParameter*
coc-config-inlayHint-position coc-config.txt /*coc-config-inlayHint-position*
coc-config-inlayHint-refreshOnInsertMode coc-config.txt /*coc-config-inlayHint-refreshOnInsertMode*
coc-config-inlineSuggest coc-config.txt /*coc-config-inlineSuggest*
coc-config-inlineSuggest-autoTrigger coc-config.txt /*coc-config-inlineSuggest-autoTrigger*
coc-config-inlineSuggest-triggerCompletionWait coc-config.txt /*coc-config-inlineSuggest-triggerCompletionWait*
coc-config-languageserver coc-config.txt /*coc-config-languageserver*
coc-config-links coc-config.txt /*coc-config-links*
coc-config-links-enable coc-config.txt /*coc-config-links-enable*
coc-config-links-highlight coc-config.txt /*coc-config-links-highlight*
coc-config-links-tooltip coc-config.txt /*coc-config-links-tooltip*
coc-config-list coc-config.txt /*coc-config-list*
coc-config-list-alignColumns coc-config.txt /*coc-config-list-alignColumns*
coc-config-list-extendedSearchMode coc-config.txt /*coc-config-list-extendedSearchMode*
coc-config-list-floatPreview coc-config.txt /*coc-config-list-floatPreview*
coc-config-list-height coc-config.txt /*coc-config-list-height*
coc-config-list-indicator coc-config.txt /*coc-config-list-indicator*
coc-config-list-insertMappings coc-config.txt /*coc-config-list-insertMappings*
coc-config-list-interactiveDebounceTime coc-config.txt /*coc-config-list-interactiveDebounceTime*
coc-config-list-limitLines coc-config.txt /*coc-config-list-limitLines*
coc-config-list-maxPreviewHeight coc-config.txt /*coc-config-list-maxPreviewHeight*
coc-config-list-menuAction coc-config.txt /*coc-config-list-menuAction*
coc-config-list-nextKeymap coc-config.txt /*coc-config-list-nextKeymap*
coc-config-list-normalMappings coc-config.txt /*coc-config-list-normalMappings*
coc-config-list-previewHighlightGroup coc-config.txt /*coc-config-list-previewHighlightGroup*
coc-config-list-previewSplitRight coc-config.txt /*coc-config-list-previewSplitRight*
coc-config-list-previewToplineOffset coc-config.txt /*coc-config-list-previewToplineOffset*
coc-config-list-previewToplineStyle coc-config.txt /*coc-config-list-previewToplineStyle*
coc-config-list-previousKeymap coc-config.txt /*coc-config-list-previousKeymap*
coc-config-list-selectedSignText coc-config.txt /*coc-config-list-selectedSignText*
coc-config-list-signOffset coc-config.txt /*coc-config-list-signOffset*
coc-config-list-smartCase coc-config.txt /*coc-config-list-smartCase*
coc-config-list-source-diagnostics-includeCode coc-config.txt /*coc-config-list-source-diagnostics-includeCode*
coc-config-list-source-diagnostics-pathFormat coc-config.txt /*coc-config-list-source-diagnostics-pathFormat*
coc-config-list-source-outline-ctagsFiletypes coc-config.txt /*coc-config-list-source-outline-ctagsFiletypes*
coc-config-list-source-symbols-excludes coc-config.txt /*coc-config-list-source-symbols-excludes*
coc-config-list-statusLineSegments coc-config.txt /*coc-config-list-statusLineSegments*
coc-config-notification coc-config.txt /*coc-config-notification*
coc-config-notification-border coc-config.txt /*coc-config-notification-border*
coc-config-notification-disabledProgressSources coc-config.txt /*coc-config-notification-disabledProgressSources*
coc-config-notification-focusable coc-config.txt /*coc-config-notification-focusable*
coc-config-notification-highlightGroup coc-config.txt /*coc-config-notification-highlightGroup*
coc-config-notification-marginRight coc-config.txt /*coc-config-notification-marginRight*
coc-config-notification-maxHeight coc-config.txt /*coc-config-notification-maxHeight*
coc-config-notification-maxWidth coc-config.txt /*coc-config-notification-maxWidth*
coc-config-notification-minProgressWidth coc-config.txt /*coc-config-notification-minProgressWidth*
coc-config-notification-statusLineProgress coc-config.txt /*coc-config-notification-statusLineProgress*
coc-config-notification-timeout coc-config.txt /*coc-config-notification-timeout*
coc-config-notification-winblend coc-config.txt /*coc-config-notification-winblend*
coc-config-npm coc-config.txt /*coc-config-npm*
coc-config-npm-binPath coc-config.txt /*coc-config-npm-binPath*
coc-config-outline coc-config.txt /*coc-config-outline*
coc-config-outline-autoHide coc-config.txt /*coc-config-outline-autoHide*
coc-config-outline-autoPreview coc-config.txt /*coc-config-outline-autoPreview*
coc-config-outline-autoWidth coc-config.txt /*coc-config-outline-autoWidth*
coc-config-outline-checkBufferSwitch coc-config.txt /*coc-config-outline-checkBufferSwitch*
coc-config-outline-codeActionKinds coc-config.txt /*coc-config-outline-codeActionKinds*
coc-config-outline-detailAsDescription coc-config.txt /*coc-config-outline-detailAsDescription*
coc-config-outline-expandLevel coc-config.txt /*coc-config-outline-expandLevel*
coc-config-outline-followCursor coc-config.txt /*coc-config-outline-followCursor*
coc-config-outline-keepWindow coc-config.txt /*coc-config-outline-keepWindow*
coc-config-outline-previewBorder coc-config.txt /*coc-config-outline-previewBorder*
coc-config-outline-previewBorderHighlightGroup coc-config.txt /*coc-config-outline-previewBorderHighlightGroup*
coc-config-outline-previewBorderRounded coc-config.txt /*coc-config-outline-previewBorderRounded*
coc-config-outline-previewHighlightGroup coc-config.txt /*coc-config-outline-previewHighlightGroup*
coc-config-outline-previewMaxWidth coc-config.txt /*coc-config-outline-previewMaxWidth*
coc-config-outline-previewWinblend coc-config.txt /*coc-config-outline-previewWinblend*
coc-config-outline-showLineNumber coc-config.txt /*coc-config-outline-showLineNumber*
coc-config-outline-sortBy coc-config.txt /*coc-config-outline-sortBy*
coc-config-outline-splitCommand coc-config.txt /*coc-config-outline-splitCommand*
coc-config-outline-switchSortKey coc-config.txt /*coc-config-outline-switchSortKey*
coc-config-outline-togglePreviewKey coc-config.txt /*coc-config-outline-togglePreviewKey*
coc-config-preferences coc-config.txt /*coc-config-preferences*
coc-config-pullDiagnostic coc-config.txt /*coc-config-pullDiagnostic*
coc-config-pullDiagnostic-ignored coc-config.txt /*coc-config-pullDiagnostic-ignored*
coc-config-pullDiagnostic-onChange coc-config.txt /*coc-config-pullDiagnostic-onChange*
coc-config-pullDiagnostic-onSave coc-config.txt /*coc-config-pullDiagnostic-onSave*
coc-config-pullDiagnostic-workspace coc-config.txt /*coc-config-pullDiagnostic-workspace*
coc-config-refactor coc-config.txt /*coc-config-refactor*
coc-config-refactor-afterContext coc-config.txt /*coc-config-refactor-afterContext*
coc-config-refactor-beforeContext coc-config.txt /*coc-config-refactor-beforeContext*
coc-config-refactor-openCommand coc-config.txt /*coc-config-refactor-openCommand*
coc-config-refactor-saveToFile coc-config.txt /*coc-config-refactor-saveToFile*
coc-config-refactor-showMenu coc-config.txt /*coc-config-refactor-showMenu*
coc-config-semanticTokens coc-config.txt /*coc-config-semanticTokens*
coc-config-semanticTokens-combinedModifiers coc-config.txt /*coc-config-semanticTokens-combinedModifiers*
coc-config-semanticTokens-enable coc-config.txt /*coc-config-semanticTokens-enable*
coc-config-semanticTokens-highlightPriority coc-config.txt /*coc-config-semanticTokens-highlightPriority*
coc-config-semanticTokens-incrementTypes coc-config.txt /*coc-config-semanticTokens-incrementTypes*
coc-config-signature coc-config.txt /*coc-config-signature*
coc-config-signature-enable coc-config.txt /*coc-config-signature-enable*
coc-config-signature-floatConfig coc-config.txt /*coc-config-signature-floatConfig*
coc-config-signature-hideOnTextChange coc-config.txt /*coc-config-signature-hideOnTextChange*
coc-config-signature-preferShownAbove coc-config.txt /*coc-config-signature-preferShownAbove*
coc-config-signature-target coc-config.txt /*coc-config-signature-target*
coc-config-signature-triggerSignatureWait coc-config.txt /*coc-config-signature-triggerSignatureWait*
coc-config-snippet coc-config.txt /*coc-config-snippet*
coc-config-snippet-highlight coc-config.txt /*coc-config-snippet-highlight*
coc-config-snippet-nextPlaceholderOnDelete coc-config.txt /*coc-config-snippet-nextPlaceholderOnDelete*
coc-config-snippet-statusText coc-config.txt /*coc-config-snippet-statusText*
coc-config-suggest coc-config.txt /*coc-config-suggest*
coc-config-suggest-acceptSuggestionOnCommitCharacter coc-config.txt /*coc-config-suggest-acceptSuggestionOnCommitCharacter*
coc-config-suggest-asciiCharactersOnly coc-config.txt /*coc-config-suggest-asciiCharactersOnly*
coc-config-suggest-asciiMatch coc-config.txt /*coc-config-suggest-asciiMatch*
coc-config-suggest-autoTrigger coc-config.txt /*coc-config-suggest-autoTrigger*
coc-config-suggest-completionItemKindLabels coc-config.txt /*coc-config-suggest-completionItemKindLabels*
coc-config-suggest-defaultSortMethod coc-config.txt /*coc-config-suggest-defaultSortMethod*
coc-config-suggest-detailField coc-config.txt /*coc-config-suggest-detailField*
coc-config-suggest-enableFloat coc-config.txt /*coc-config-suggest-enableFloat*
coc-config-suggest-enablePreselect coc-config.txt /*coc-config-suggest-enablePreselect*
coc-config-suggest-filterGraceful coc-config.txt /*coc-config-suggest-filterGraceful*
coc-config-suggest-filterOnBackspace coc-config.txt /*coc-config-suggest-filterOnBackspace*
coc-config-suggest-floatConfig coc-config.txt /*coc-config-suggest-floatConfig*
coc-config-suggest-formatItems coc-config.txt /*coc-config-suggest-formatItems*
coc-config-suggest-highPrioritySourceLimit coc-config.txt /*coc-config-suggest-highPrioritySourceLimit*
coc-config-suggest-ignoreRegexps coc-config.txt /*coc-config-suggest-ignoreRegexps*
coc-config-suggest-insertMode coc-config.txt /*coc-config-suggest-insertMode*
coc-config-suggest-invalidInsertCharacters coc-config.txt /*coc-config-suggest-invalidInsertCharacters*
coc-config-suggest-labelMaxLength coc-config.txt /*coc-config-suggest-labelMaxLength*
coc-config-suggest-languageSourcePriority coc-config.txt /*coc-config-suggest-languageSourcePriority*
coc-config-suggest-localityBonus coc-config.txt /*coc-config-suggest-localityBonus*
coc-config-suggest-lowPrioritySourceLimit coc-config.txt /*coc-config-suggest-lowPrioritySourceLimit*
coc-config-suggest-maxCompleteItemCount coc-config.txt /*coc-config-suggest-maxCompleteItemCount*
coc-config-suggest-minTriggerInputLength coc-config.txt /*coc-config-suggest-minTriggerInputLength*
coc-config-suggest-noselect coc-config.txt /*coc-config-suggest-noselect*
coc-config-suggest-preferCompleteThanJumpPlaceholder coc-config.txt /*coc-config-suggest-preferCompleteThanJumpPlaceholder*
coc-config-suggest-pumFloatConfig coc-config.txt /*coc-config-suggest-pumFloatConfig*
coc-config-suggest-reTriggerAfterIndent coc-config.txt /*coc-config-suggest-reTriggerAfterIndent*
coc-config-suggest-removeCurrentWord coc-config.txt /*coc-config-suggest-removeCurrentWord*
coc-config-suggest-removeDuplicateItems coc-config.txt /*coc-config-suggest-removeDuplicateItems*
coc-config-suggest-reversePumAboveCursor coc-config.txt /*coc-config-suggest-reversePumAboveCursor*
coc-config-suggest-segmenterLocales coc-config.txt /*coc-config-suggest-segmenterLocales*
coc-config-suggest-selection coc-config.txt /*coc-config-suggest-selection*
coc-config-suggest-snippetIndicator coc-config.txt /*coc-config-suggest-snippetIndicator*
coc-config-suggest-snippetsSupport coc-config.txt /*coc-config-suggest-snippetsSupport*
coc-config-suggest-timeout coc-config.txt /*coc-config-suggest-timeout*
coc-config-suggest-triggerAfterInsertEnter coc-config.txt /*coc-config-suggest-triggerAfterInsertEnter*
coc-config-suggest-triggerCompletionWait coc-config.txt /*coc-config-suggest-triggerCompletionWait*
coc-config-suggest-virtualText coc-config.txt /*coc-config-suggest-virtualText*
coc-config-tree coc-config.txt /*coc-config-tree*
coc-config-tree-closedIcon coc-config.txt /*coc-config-tree-closedIcon*
coc-config-tree-key-actions coc-config.txt /*coc-config-tree-key-actions*
coc-config-tree-key-activeFilter coc-config.txt /*coc-config-tree-key-activeFilter*
coc-config-tree-key-close coc-config.txt /*coc-config-tree-key-close*
coc-config-tree-key-collapseAll coc-config.txt /*coc-config-tree-key-collapseAll*
coc-config-tree-key-invoke coc-config.txt /*coc-config-tree-key-invoke*
coc-config-tree-key-selectNext coc-config.txt /*coc-config-tree-key-selectNext*
coc-config-tree-key-selectPrevious coc-config.txt /*coc-config-tree-key-selectPrevious*
coc-config-tree-key-toggle coc-config.txt /*coc-config-tree-key-toggle*
coc-config-tree-key-toggleSelection coc-config.txt /*coc-config-tree-key-toggleSelection*
coc-config-tree-openedIcon coc-config.txt /*coc-config-tree-openedIcon*
coc-config-typeHierarchy coc-config.txt /*coc-config-typeHierarchy*
coc-config-typeHierarchy-enableTooltip coc-config.txt /*coc-config-typeHierarchy-enableTooltip*
coc-config-typeHierarchy-openCommand coc-config.txt /*coc-config-typeHierarchy-openCommand*
coc-config-typeHierarchy-splitCommand coc-config.txt /*coc-config-typeHierarchy-splitCommand*
coc-config-workspace coc-config.txt /*coc-config-workspace*
coc-config-workspace-bottomUpFiletypes coc-config.txt /*coc-config-workspace-bottomUpFiletypes*
coc-config-workspace-ignoredFiletypes coc-config.txt /*coc-config-workspace-ignoredFiletypes*
coc-config-workspace-ignoredFolders coc-config.txt /*coc-config-workspace-ignoredFolders*
coc-config-workspace-openOutputCommand coc-config.txt /*coc-config-workspace-openOutputCommand*
coc-config-workspace-openResourceCommand coc-config.txt /*coc-config-workspace-openResourceCommand*
coc-config-workspace-removeEmptyWorkspaceFolder coc-config.txt /*coc-config-workspace-removeEmptyWorkspaceFolder*
coc-config-workspace-rootPatterns coc-config.txt /*coc-config-workspace-rootPatterns*
coc-config-workspace-workspaceFolderCheckCwd coc-config.txt /*coc-config-workspace-workspaceFolderCheckCwd*
coc-config-workspace-workspaceFolderFallbackCwd coc-config.txt /*coc-config-workspace-workspaceFolderFallbackCwd*
coc-config.txt coc-config.txt /*coc-config.txt*
coc-configuration coc.txt /*coc-configuration*
coc-configuration-expand coc.txt /*coc-configuration-expand*
coc-configuration-scope coc.txt /*coc-configuration-scope*
coc-contents coc.txt /*coc-contents*
coc-cursors coc.txt /*coc-cursors*
coc-diagnostics coc.txt /*coc-diagnostics*
coc-diagnostics-jump coc.txt /*coc-diagnostics-jump*
coc-diagnostics-refresh coc.txt /*coc-diagnostics-refresh*
coc-diagnostics-toggle coc.txt /*coc-diagnostics-toggle*
coc-dialog coc.txt /*coc-dialog*
coc-dialog-basic coc.txt /*coc-dialog-basic*
coc-dialog-confirm coc.txt /*coc-dialog-confirm*
coc-dialog-input coc.txt /*coc-dialog-input*
coc-dialog-menu coc.txt /*coc-dialog-menu*
coc-dialog-picker coc.txt /*coc-dialog-picker*
coc-dialog-quickpick coc.txt /*coc-dialog-quickpick*
coc-document coc.txt /*coc-document*
coc-document-attached coc.txt /*coc-document-attached*
coc-document-colors coc.txt /*coc-document-colors*
coc-document-filetype coc.txt /*coc-document-filetype*
coc-document-highlights coc.txt /*coc-document-highlights*
coc-document-links coc.txt /*coc-document-links*
coc-environment-variables coc.txt /*coc-environment-variables*
coc-extensions coc.txt /*coc-extensions*
coc-extensions-folder coc.txt /*coc-extensions-folder*
coc-extensions-npm coc.txt /*coc-extensions-npm*
coc-faq coc.txt /*coc-faq*
coc-filesystemwatch coc.txt /*coc-filesystemwatch*
coc-floating coc.txt /*coc-floating*
coc-floating-close coc.txt /*coc-floating-close*
coc-floating-config coc.txt /*coc-floating-config*
coc-floating-focus coc.txt /*coc-floating-focus*
coc-floating-scroll coc.txt /*coc-floating-scroll*
coc-fold coc.txt /*coc-fold*
coc-format coc.txt /*coc-format*
coc-format-document coc.txt /*coc-format-document*
coc-format-onsave coc.txt /*coc-format-onsave*
coc-format-ontype coc.txt /*coc-format-ontype*
coc-format-options coc.txt /*coc-format-options*
coc-format-selected coc.txt /*coc-format-selected*
coc-functions coc.txt /*coc-functions*
coc-global-variables coc.txt /*coc-global-variables*
coc-highlights coc.txt /*coc-highlights*
coc-highlights-diagnostics coc.txt /*coc-highlights-diagnostics*
coc-highlights-document coc.txt /*coc-highlights-document*
coc-highlights-float coc.txt /*coc-highlights-float*
coc-highlights-inlayHint coc.txt /*coc-highlights-inlayHint*
coc-hover coc.txt /*coc-hover*
coc-hover-example coc.txt /*coc-hover-example*
coc-inlayHint coc.txt /*coc-inlayHint*
coc-inlineCompletion coc.txt /*coc-inlineCompletion*
coc-inlineCompletion-customize coc.txt /*coc-inlineCompletion-customize*
coc-inlineCompletion-default coc.txt /*coc-inlineCompletion-default*
coc-inlineCompletion-functions coc.txt /*coc-inlineCompletion-functions*
coc-installation coc.txt /*coc-installation*
coc-interface coc.txt /*coc-interface*
coc-introduction coc.txt /*coc-introduction*
coc-key-mappings coc.txt /*coc-key-mappings*
coc-languageserver coc.txt /*coc-languageserver*
coc-linked-editing coc.txt /*coc-linked-editing*
coc-list coc.txt /*coc-list*
coc-list-command coc.txt /*coc-list-command*
coc-list-commands coc.txt /*coc-list-commands*
coc-list-completion-sources coc.txt /*coc-list-completion-sources*
coc-list-configuration coc.txt /*coc-list-configuration*
coc-list-context coc.txt /*coc-list-context*
coc-list-diagnostics coc.txt /*coc-list-diagnostics*
coc-list-extensions coc.txt /*coc-list-extensions*
coc-list-folders coc.txt /*coc-list-folders*
coc-list-links coc.txt /*coc-list-links*
coc-list-lists coc.txt /*coc-list-lists*
coc-list-location coc.txt /*coc-list-location*
coc-list-mappings coc.txt /*coc-list-mappings*
coc-list-mappings-custom coc.txt /*coc-list-mappings-custom*
coc-list-options coc.txt /*coc-list-options*
coc-list-outline coc.txt /*coc-list-outline*
coc-list-services coc.txt /*coc-list-services*
coc-list-sources coc.txt /*coc-list-sources*
coc-list-symbols coc.txt /*coc-list-symbols*
coc-list-target coc.txt /*coc-list-target*
coc-locations coc.txt /*coc-locations*
coc-locations-api coc.txt /*coc-locations-api*
coc-lsp coc.txt /*coc-lsp*
coc-notification coc.txt /*coc-notification*
coc-nvim.txt coc.txt /*coc-nvim.txt*
coc-outline coc.txt /*coc-outline*
coc-outline-example coc.txt /*coc-outline-example*
coc-plugins coc.txt /*coc-plugins*
coc-preferences-bracketEnterImprove coc-config.txt /*coc-preferences-bracketEnterImprove*
coc-preferences-currentFunctionSymbolAutoUpdate coc-config.txt /*coc-preferences-currentFunctionSymbolAutoUpdate*
coc-preferences-currentFunctionSymbolDebounceTime coc-config.txt /*coc-preferences-currentFunctionSymbolDebounceTime*
coc-preferences-enableGFMBreaksInmakrdownDocument coc-config.txt /*coc-preferences-enableGFMBreaksInmakrdownDocument*
coc-preferences-enableLinkedEditing coc-config.txt /*coc-preferences-enableLinkedEditing*
coc-preferences-enableMarkdown coc-config.txt /*coc-preferences-enableMarkdown*
coc-preferences-enableMessageDialog coc-config.txt /*coc-preferences-enableMessageDialog*
coc-preferences-excludeImageLinksInMarkdownDocument coc-config.txt /*coc-preferences-excludeImageLinksInMarkdownDocument*
coc-preferences-floatActions coc-config.txt /*coc-preferences-floatActions*
coc-preferences-formatOnSave coc-config.txt /*coc-preferences-formatOnSave*
coc-preferences-formatOnSaveTimeout coc-config.txt /*coc-preferences-formatOnSaveTimeout*
coc-preferences-formatOnType coc-config.txt /*coc-preferences-formatOnType*
coc-preferences-formatterExtension coc-config.txt /*coc-preferences-formatterExtension*
coc-preferences-jumpCommand coc-config.txt /*coc-preferences-jumpCommand*
coc-preferences-maxFileSize coc-config.txt /*coc-preferences-maxFileSize*
coc-preferences-messageDialogKind coc-config.txt /*coc-preferences-messageDialogKind*
coc-preferences-messageLevel coc-config.txt /*coc-preferences-messageLevel*
coc-preferences-promptInput coc-config.txt /*coc-preferences-promptInput*
coc-preferences-renameFillCurrent coc-config.txt /*coc-preferences-renameFillCurrent*
coc-preferences-silentAutoupdate coc-config.txt /*coc-preferences-silentAutoupdate*
coc-preferences-tagDefinitionTimeout coc-config.txt /*coc-preferences-tagDefinitionTimeout*
coc-preferences-useQuickfixForLocations coc-config.txt /*coc-preferences-useQuickfixForLocations*
coc-preferences-watchmanPath coc-config.txt /*coc-preferences-watchmanPath*
coc-preferences-willSaveHandlerTimeout coc-config.txt /*coc-preferences-willSaveHandlerTimeout*
coc-pullDiagnostics coc.txt /*coc-pullDiagnostics*
coc-refactor-buffer coc.txt /*coc-refactor-buffer*
coc-rename coc.txt /*coc-rename*
coc-requirements coc.txt /*coc-requirements*
coc-selection-range coc.txt /*coc-selection-range*
coc-semantic-highlights coc.txt /*coc-semantic-highlights*
coc-signature coc.txt /*coc-signature*
coc-snippets coc.txt /*coc-snippets*
coc-status coc.txt /*coc-status*
coc-status-airline coc.txt /*coc-status-airline*
coc-status-lightline coc.txt /*coc-status-lightline*
coc-status-manual coc.txt /*coc-status-manual*
coc-tree coc.txt /*coc-tree*
coc-tree-filter coc.txt /*coc-tree-filter*
coc-tree-mappings coc.txt /*coc-tree-mappings*
coc-typeHierarchy coc.txt /*coc-typeHierarchy*
coc-variables coc.txt /*coc-variables*
coc-window-variables coc.txt /*coc-window-variables*
coc-workspace coc.txt /*coc-workspace*
coc-workspace-edits coc.txt /*coc-workspace-edits*
coc-workspace-folders coc.txt /*coc-workspace-folders*
coc-workspace-output coc.txt /*coc-workspace-output*
coc-workspace-rename coc.txt /*coc-workspace-rename*
diagnostic-structure coc.txt /*diagnostic-structure*
g:WorkspaceFolders coc.txt /*g:WorkspaceFolders*
g:coc_border_joinchars coc.txt /*g:coc_border_joinchars*
g:coc_borderchars coc.txt /*g:coc_borderchars*
g:coc_config_home coc.txt /*g:coc_config_home*
g:coc_data_home coc.txt /*g:coc_data_home*
g:coc_default_semantic_highlight_groups coc.txt /*g:coc_default_semantic_highlight_groups*
g:coc_disable_mappings_check coc.txt /*g:coc_disable_mappings_check*
g:coc_disable_startup_warning coc.txt /*g:coc_disable_startup_warning*
g:coc_disable_transparent_cursor coc.txt /*g:coc_disable_transparent_cursor*
g:coc_disable_uncaught_error coc.txt /*g:coc_disable_uncaught_error*
g:coc_enable_locationlist coc.txt /*g:coc_enable_locationlist*
g:coc_filetype_map coc.txt /*g:coc_filetype_map*
g:coc_global_extensions coc.txt /*g:coc_global_extensions*
g:coc_highlight_maximum_count coc.txt /*g:coc_highlight_maximum_count*
g:coc_jump_locations coc.txt /*g:coc_jump_locations*
g:coc_last_float_win coc.txt /*g:coc_last_float_win*
g:coc_last_hover_message coc.txt /*g:coc_last_hover_message*
g:coc_list_preview_filetype coc.txt /*g:coc_list_preview_filetype*
g:coc_markdown_disabled_languages coc.txt /*g:coc_markdown_disabled_languages*
g:coc_max_treeview_width coc.txt /*g:coc_max_treeview_width*
g:coc_node_args coc.txt /*g:coc_node_args*
g:coc_node_path coc.txt /*g:coc_node_path*
g:coc_notify coc.txt /*g:coc_notify*
g:coc_notify_error_icon coc.txt /*g:coc_notify_error_icon*
g:coc_notify_info_icon coc.txt /*g:coc_notify_info_icon*
g:coc_notify_warning_icon coc.txt /*g:coc_notify_warning_icon*
g:coc_open_url_command coc.txt /*g:coc_open_url_command*
g:coc_process_pid coc.txt /*g:coc_process_pid*
g:coc_prompt_win_width coc.txt /*g:coc_prompt_win_width*
g:coc_quickfix_open_command coc.txt /*g:coc_quickfix_open_command*
g:coc_selected_text coc.txt /*g:coc_selected_text*
g:coc_selectmode_mapping coc.txt /*g:coc_selectmode_mapping*
g:coc_service_initialized coc.txt /*g:coc_service_initialized*
g:coc_snippet_next coc.txt /*g:coc_snippet_next*
g:coc_snippet_prev coc.txt /*g:coc_snippet_prev*
g:coc_start_at_startup coc.txt /*g:coc_start_at_startup*
g:coc_status coc.txt /*g:coc_status*
g:coc_status_error_sign coc.txt /*g:coc_status_error_sign*
g:coc_status_warning_sign coc.txt /*g:coc_status_warning_sign*
g:coc_terminal_height coc.txt /*g:coc_terminal_height*
g:coc_text_prop_offset coc.txt /*g:coc_text_prop_offset*
g:coc_user_config coc.txt /*g:coc_user_config*
g:node_client_debug coc.txt /*g:node_client_debug*
w:cocViewId coc.txt /*w:cocViewId*

View file

@ -0,0 +1 @@
ref: refs/heads/release

View file

@ -0,0 +1 @@
3b0b28802a1b55d0dab1a440a6e1d3b37d3af968

View file

@ -0,0 +1,14 @@
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "origin"]
url = https://github.com/neoclide/coc.nvim.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[branch "release"]
remote = origin
merge = refs/heads/release

View file

@ -0,0 +1 @@
Unnamed repository; edit this file 'description' to name the repository.

View file

@ -0,0 +1,15 @@
#!/bin/sh
#
# An example hook script to check the commit log message taken by
# applypatch from an e-mail message.
#
# The hook should exit with non-zero status after issuing an
# appropriate message if it wants to stop the commit. The hook is
# allowed to edit the commit message file.
#
# To enable this hook, rename this file to "applypatch-msg".
. git-sh-setup
commitmsg="$(git rev-parse --git-path hooks/commit-msg)"
test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
:

View file

@ -0,0 +1,24 @@
#!/bin/sh
#
# An example hook script to check the commit log message.
# Called by "git commit" with one argument, the name of the file
# that has the commit message. The hook should exit with non-zero
# status after issuing an appropriate message if it wants to stop the
# commit. The hook is allowed to edit the commit message file.
#
# To enable this hook, rename this file to "commit-msg".
# Uncomment the below to add a Signed-off-by line to the message.
# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
# hook is more suited to it.
#
# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
# This example catches duplicate Signed-off-by lines.
test "" = "$(grep '^Signed-off-by: ' "$1" |
sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
echo >&2 Duplicate Signed-off-by lines.
exit 1
}

View file

@ -0,0 +1,174 @@
#!/usr/bin/perl
use strict;
use warnings;
use IPC::Open2;
# An example hook script to integrate Watchman
# (https://facebook.github.io/watchman/) with git to speed up detecting
# new and modified files.
#
# The hook is passed a version (currently 2) and last update token
# formatted as a string and outputs to stdout a new update token and
# all files that have been modified since the update token. Paths must
# be relative to the root of the working tree and separated by a single NUL.
#
# To enable this hook, rename this file to "query-watchman" and set
# 'git config core.fsmonitor .git/hooks/query-watchman'
#
my ($version, $last_update_token) = @ARGV;
# Uncomment for debugging
# print STDERR "$0 $version $last_update_token\n";
# Check the hook interface version
if ($version ne 2) {
die "Unsupported query-fsmonitor hook version '$version'.\n" .
"Falling back to scanning...\n";
}
my $git_work_tree = get_working_dir();
my $retry = 1;
my $json_pkg;
eval {
require JSON::XS;
$json_pkg = "JSON::XS";
1;
} or do {
require JSON::PP;
$json_pkg = "JSON::PP";
};
launch_watchman();
sub launch_watchman {
my $o = watchman_query();
if (is_work_tree_watched($o)) {
output_result($o->{clock}, @{$o->{files}});
}
}
sub output_result {
my ($clockid, @files) = @_;
# Uncomment for debugging watchman output
# open (my $fh, ">", ".git/watchman-output.out");
# binmode $fh, ":utf8";
# print $fh "$clockid\n@files\n";
# close $fh;
binmode STDOUT, ":utf8";
print $clockid;
print "\0";
local $, = "\0";
print @files;
}
sub watchman_clock {
my $response = qx/watchman clock "$git_work_tree"/;
die "Failed to get clock id on '$git_work_tree'.\n" .
"Falling back to scanning...\n" if $? != 0;
return $json_pkg->new->utf8->decode($response);
}
sub watchman_query {
my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty')
or die "open2() failed: $!\n" .
"Falling back to scanning...\n";
# In the query expression below we're asking for names of files that
# changed since $last_update_token but not from the .git folder.
#
# To accomplish this, we're using the "since" generator to use the
# recency index to select candidate nodes and "fields" to limit the
# output to file names only. Then we're using the "expression" term to
# further constrain the results.
my $last_update_line = "";
if (substr($last_update_token, 0, 1) eq "c") {
$last_update_token = "\"$last_update_token\"";
$last_update_line = qq[\n"since": $last_update_token,];
}
my $query = <<" END";
["query", "$git_work_tree", {$last_update_line
"fields": ["name"],
"expression": ["not", ["dirname", ".git"]]
}]
END
# Uncomment for debugging the watchman query
# open (my $fh, ">", ".git/watchman-query.json");
# print $fh $query;
# close $fh;
print CHLD_IN $query;
close CHLD_IN;
my $response = do {local $/; <CHLD_OUT>};
# Uncomment for debugging the watch response
# open ($fh, ">", ".git/watchman-response.json");
# print $fh $response;
# close $fh;
die "Watchman: command returned no output.\n" .
"Falling back to scanning...\n" if $response eq "";
die "Watchman: command returned invalid output: $response\n" .
"Falling back to scanning...\n" unless $response =~ /^\{/;
return $json_pkg->new->utf8->decode($response);
}
sub is_work_tree_watched {
my ($output) = @_;
my $error = $output->{error};
if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) {
$retry--;
my $response = qx/watchman watch "$git_work_tree"/;
die "Failed to make watchman watch '$git_work_tree'.\n" .
"Falling back to scanning...\n" if $? != 0;
$output = $json_pkg->new->utf8->decode($response);
$error = $output->{error};
die "Watchman: $error.\n" .
"Falling back to scanning...\n" if $error;
# Uncomment for debugging watchman output
# open (my $fh, ">", ".git/watchman-output.out");
# close $fh;
# Watchman will always return all files on the first query so
# return the fast "everything is dirty" flag to git and do the
# Watchman query just to get it over with now so we won't pay
# the cost in git to look up each individual file.
my $o = watchman_clock();
$error = $output->{error};
die "Watchman: $error.\n" .
"Falling back to scanning...\n" if $error;
output_result($o->{clock}, ("/"));
$last_update_token = $o->{clock};
eval { launch_watchman() };
return 0;
}
die "Watchman: $error.\n" .
"Falling back to scanning...\n" if $error;
return 1;
}
sub get_working_dir {
my $working_dir;
if ($^O =~ 'msys' || $^O =~ 'cygwin') {
$working_dir = Win32::GetCwd();
$working_dir =~ tr/\\/\//;
} else {
require Cwd;
$working_dir = Cwd::cwd();
}
return $working_dir;
}

View file

@ -0,0 +1,8 @@
#!/bin/sh
#
# An example hook script to prepare a packed repository for use over
# dumb transports.
#
# To enable this hook, rename this file to "post-update".
exec git update-server-info

View file

@ -0,0 +1,14 @@
#!/bin/sh
#
# An example hook script to verify what is about to be committed
# by applypatch from an e-mail message.
#
# The hook should exit with non-zero status after issuing an
# appropriate message if it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-applypatch".
. git-sh-setup
precommit="$(git rev-parse --git-path hooks/pre-commit)"
test -x "$precommit" && exec "$precommit" ${1+"$@"}
:

View file

@ -0,0 +1,49 @@
#!/bin/sh
#
# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-commit".
if git rev-parse --verify HEAD >/dev/null 2>&1
then
against=HEAD
else
# Initial commit: diff against an empty tree object
against=$(git hash-object -t tree /dev/null)
fi
# If you want to allow non-ASCII filenames set this variable to true.
allownonascii=$(git config --type=bool hooks.allownonascii)
# Redirect output to stderr.
exec 1>&2
# Cross platform projects tend to avoid non-ASCII filenames; prevent
# them from being added to the repository. We exploit the fact that the
# printable range starts at the space character and ends with tilde.
if [ "$allownonascii" != "true" ] &&
# Note that the use of brackets around a tr range is ok here, (it's
# even required, for portability to Solaris 10's /usr/bin/tr), since
# the square bracket bytes happen to fall in the designated range.
test $(git diff --cached --name-only --diff-filter=A -z $against |
LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
then
cat <<\EOF
Error: Attempt to add a non-ASCII file name.
This can cause problems if you want to work with people on other platforms.
To be portable it is advisable to rename the file.
If you know what you are doing you can disable this check using:
git config hooks.allownonascii true
EOF
exit 1
fi
# If there are whitespace errors, print the offending file names and fail.
exec git diff-index --check --cached $against --

View file

@ -0,0 +1,13 @@
#!/bin/sh
#
# An example hook script to verify what is about to be committed.
# Called by "git merge" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message to
# stderr if it wants to stop the merge commit.
#
# To enable this hook, rename this file to "pre-merge-commit".
. git-sh-setup
test -x "$GIT_DIR/hooks/pre-commit" &&
exec "$GIT_DIR/hooks/pre-commit"
:

View file

@ -0,0 +1,53 @@
#!/bin/sh
# An example hook script to verify what is about to be pushed. Called by "git
# push" after it has checked the remote status, but before anything has been
# pushed. If this script exits with a non-zero status nothing will be pushed.
#
# This hook is called with the following parameters:
#
# $1 -- Name of the remote to which the push is being done
# $2 -- URL to which the push is being done
#
# If pushing without using a named remote those arguments will be equal.
#
# Information about the commits which are being pushed is supplied as lines to
# the standard input in the form:
#
# <local ref> <local oid> <remote ref> <remote oid>
#
# This sample shows how to prevent push of commits where the log message starts
# with "WIP" (work in progress).
remote="$1"
url="$2"
zero=$(git hash-object --stdin </dev/null | tr '[0-9a-f]' '0')
while read local_ref local_oid remote_ref remote_oid
do
if test "$local_oid" = "$zero"
then
# Handle delete
:
else
if test "$remote_oid" = "$zero"
then
# New branch, examine all commits
range="$local_oid"
else
# Update to existing branch, examine new commits
range="$remote_oid..$local_oid"
fi
# Check for WIP commit
commit=$(git rev-list -n 1 --grep '^WIP' "$range")
if test -n "$commit"
then
echo >&2 "Found WIP commit in $local_ref, not pushing"
exit 1
fi
fi
done
exit 0

View file

@ -0,0 +1,169 @@
#!/bin/sh
#
# Copyright (c) 2006, 2008 Junio C Hamano
#
# The "pre-rebase" hook is run just before "git rebase" starts doing
# its job, and can prevent the command from running by exiting with
# non-zero status.
#
# The hook is called with the following parameters:
#
# $1 -- the upstream the series was forked from.
# $2 -- the branch being rebased (or empty when rebasing the current branch).
#
# This sample shows how to prevent topic branches that are already
# merged to 'next' branch from getting rebased, because allowing it
# would result in rebasing already published history.
publish=next
basebranch="$1"
if test "$#" = 2
then
topic="refs/heads/$2"
else
topic=`git symbolic-ref HEAD` ||
exit 0 ;# we do not interrupt rebasing detached HEAD
fi
case "$topic" in
refs/heads/??/*)
;;
*)
exit 0 ;# we do not interrupt others.
;;
esac
# Now we are dealing with a topic branch being rebased
# on top of master. Is it OK to rebase it?
# Does the topic really exist?
git show-ref -q "$topic" || {
echo >&2 "No such branch $topic"
exit 1
}
# Is topic fully merged to master?
not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
if test -z "$not_in_master"
then
echo >&2 "$topic is fully merged to master; better remove it."
exit 1 ;# we could allow it, but there is no point.
fi
# Is topic ever merged to next? If so you should not be rebasing it.
only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
only_next_2=`git rev-list ^master ${publish} | sort`
if test "$only_next_1" = "$only_next_2"
then
not_in_topic=`git rev-list "^$topic" master`
if test -z "$not_in_topic"
then
echo >&2 "$topic is already up to date with master"
exit 1 ;# we could allow it, but there is no point.
else
exit 0
fi
else
not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
/usr/bin/perl -e '
my $topic = $ARGV[0];
my $msg = "* $topic has commits already merged to public branch:\n";
my (%not_in_next) = map {
/^([0-9a-f]+) /;
($1 => 1);
} split(/\n/, $ARGV[1]);
for my $elem (map {
/^([0-9a-f]+) (.*)$/;
[$1 => $2];
} split(/\n/, $ARGV[2])) {
if (!exists $not_in_next{$elem->[0]}) {
if ($msg) {
print STDERR $msg;
undef $msg;
}
print STDERR " $elem->[1]\n";
}
}
' "$topic" "$not_in_next" "$not_in_master"
exit 1
fi
<<\DOC_END
This sample hook safeguards topic branches that have been
published from being rewound.
The workflow assumed here is:
* Once a topic branch forks from "master", "master" is never
merged into it again (either directly or indirectly).
* Once a topic branch is fully cooked and merged into "master",
it is deleted. If you need to build on top of it to correct
earlier mistakes, a new topic branch is created by forking at
the tip of the "master". This is not strictly necessary, but
it makes it easier to keep your history simple.
* Whenever you need to test or publish your changes to topic
branches, merge them into "next" branch.
The script, being an example, hardcodes the publish branch name
to be "next", but it is trivial to make it configurable via
$GIT_DIR/config mechanism.
With this workflow, you would want to know:
(1) ... if a topic branch has ever been merged to "next". Young
topic branches can have stupid mistakes you would rather
clean up before publishing, and things that have not been
merged into other branches can be easily rebased without
affecting other people. But once it is published, you would
not want to rewind it.
(2) ... if a topic branch has been fully merged to "master".
Then you can delete it. More importantly, you should not
build on top of it -- other people may already want to
change things related to the topic as patches against your
"master", so if you need further changes, it is better to
fork the topic (perhaps with the same name) afresh from the
tip of "master".
Let's look at this example:
o---o---o---o---o---o---o---o---o---o "next"
/ / / /
/ a---a---b A / /
/ / / /
/ / c---c---c---c B /
/ / / \ /
/ / / b---b C \ /
/ / / / \ /
---o---o---o---o---o---o---o---o---o---o---o "master"
A, B and C are topic branches.
* A has one fix since it was merged up to "next".
* B has finished. It has been fully merged up to "master" and "next",
and is ready to be deleted.
* C has not merged to "next" at all.
We would want to allow C to be rebased, refuse A, and encourage
B to be deleted.
To compute (1):
git rev-list ^master ^topic next
git rev-list ^master next
if these match, topic has not merged in next at all.
To compute (2):
git rev-list master..topic
if this is empty, it is fully merged to "master".
DOC_END

View file

@ -0,0 +1,24 @@
#!/bin/sh
#
# An example hook script to make use of push options.
# The example simply echoes all push options that start with 'echoback='
# and rejects all pushes when the "reject" push option is used.
#
# To enable this hook, rename this file to "pre-receive".
if test -n "$GIT_PUSH_OPTION_COUNT"
then
i=0
while test "$i" -lt "$GIT_PUSH_OPTION_COUNT"
do
eval "value=\$GIT_PUSH_OPTION_$i"
case "$value" in
echoback=*)
echo "echo from the pre-receive-hook: ${value#*=}" >&2
;;
reject)
exit 1
esac
i=$((i + 1))
done
fi

View file

@ -0,0 +1,42 @@
#!/bin/sh
#
# An example hook script to prepare the commit log message.
# Called by "git commit" with the name of the file that has the
# commit message, followed by the description of the commit
# message's source. The hook's purpose is to edit the commit
# message file. If the hook fails with a non-zero status,
# the commit is aborted.
#
# To enable this hook, rename this file to "prepare-commit-msg".
# This hook includes three examples. The first one removes the
# "# Please enter the commit message..." help message.
#
# The second includes the output of "git diff --name-status -r"
# into the message, just before the "git status" output. It is
# commented because it doesn't cope with --amend or with squashed
# commits.
#
# The third example adds a Signed-off-by line to the message, that can
# still be edited. This is rarely a good idea.
COMMIT_MSG_FILE=$1
COMMIT_SOURCE=$2
SHA1=$3
/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE"
# case "$COMMIT_SOURCE,$SHA1" in
# ,|template,)
# /usr/bin/perl -i.bak -pe '
# print "\n" . `git diff --cached --name-status -r`
# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;;
# *) ;;
# esac
# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE"
# if test -z "$COMMIT_SOURCE"
# then
# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE"
# fi

View file

@ -0,0 +1,78 @@
#!/bin/sh
# An example hook script to update a checked-out tree on a git push.
#
# This hook is invoked by git-receive-pack(1) when it reacts to git
# push and updates reference(s) in its repository, and when the push
# tries to update the branch that is currently checked out and the
# receive.denyCurrentBranch configuration variable is set to
# updateInstead.
#
# By default, such a push is refused if the working tree and the index
# of the remote repository has any difference from the currently
# checked out commit; when both the working tree and the index match
# the current commit, they are updated to match the newly pushed tip
# of the branch. This hook is to be used to override the default
# behaviour; however the code below reimplements the default behaviour
# as a starting point for convenient modification.
#
# The hook receives the commit with which the tip of the current
# branch is going to be updated:
commit=$1
# It can exit with a non-zero status to refuse the push (when it does
# so, it must not modify the index or the working tree).
die () {
echo >&2 "$*"
exit 1
}
# Or it can make any necessary changes to the working tree and to the
# index to bring them to the desired state when the tip of the current
# branch is updated to the new commit, and exit with a zero status.
#
# For example, the hook can simply run git read-tree -u -m HEAD "$1"
# in order to emulate git fetch that is run in the reverse direction
# with git push, as the two-tree form of git read-tree -u -m is
# essentially the same as git switch or git checkout that switches
# branches while keeping the local changes in the working tree that do
# not interfere with the difference between the branches.
# The below is a more-or-less exact translation to shell of the C code
# for the default behaviour for git's push-to-checkout hook defined in
# the push_to_deploy() function in builtin/receive-pack.c.
#
# Note that the hook will be executed from the repository directory,
# not from the working tree, so if you want to perform operations on
# the working tree, you will have to adapt your code accordingly, e.g.
# by adding "cd .." or using relative paths.
if ! git update-index -q --ignore-submodules --refresh
then
die "Up-to-date check failed"
fi
if ! git diff-files --quiet --ignore-submodules --
then
die "Working directory has unstaged changes"
fi
# This is a rough translation of:
#
# head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX
if git cat-file -e HEAD 2>/dev/null
then
head=HEAD
else
head=$(git hash-object -t tree --stdin </dev/null)
fi
if ! git diff-index --quiet --cached --ignore-submodules $head --
then
die "Working directory has staged changes"
fi
if ! git read-tree -u -m "$commit"
then
die "Could not update working tree to new HEAD"
fi

View file

@ -0,0 +1,77 @@
#!/bin/sh
# An example hook script to validate a patch (and/or patch series) before
# sending it via email.
#
# The hook should exit with non-zero status after issuing an appropriate
# message if it wants to prevent the email(s) from being sent.
#
# To enable this hook, rename this file to "sendemail-validate".
#
# By default, it will only check that the patch(es) can be applied on top of
# the default upstream branch without conflicts in a secondary worktree. After
# validation (successful or not) of the last patch of a series, the worktree
# will be deleted.
#
# The following config variables can be set to change the default remote and
# remote ref that are used to apply the patches against:
#
# sendemail.validateRemote (default: origin)
# sendemail.validateRemoteRef (default: HEAD)
#
# Replace the TODO placeholders with appropriate checks according to your
# needs.
validate_cover_letter () {
file="$1"
# TODO: Replace with appropriate checks (e.g. spell checking).
true
}
validate_patch () {
file="$1"
# Ensure that the patch applies without conflicts.
git am -3 "$file" || return
# TODO: Replace with appropriate checks for this patch
# (e.g. checkpatch.pl).
true
}
validate_series () {
# TODO: Replace with appropriate checks for the whole series
# (e.g. quick build, coding style checks, etc.).
true
}
# main -------------------------------------------------------------------------
if test "$GIT_SENDEMAIL_FILE_COUNTER" = 1
then
remote=$(git config --default origin --get sendemail.validateRemote) &&
ref=$(git config --default HEAD --get sendemail.validateRemoteRef) &&
worktree=$(mktemp --tmpdir -d sendemail-validate.XXXXXXX) &&
git worktree add -fd --checkout "$worktree" "refs/remotes/$remote/$ref" &&
git config --replace-all sendemail.validateWorktree "$worktree"
else
worktree=$(git config --get sendemail.validateWorktree)
fi || {
echo "sendemail-validate: error: failed to prepare worktree" >&2
exit 1
}
unset GIT_DIR GIT_WORK_TREE
cd "$worktree" &&
if grep -q "^diff --git " "$1"
then
validate_patch "$1"
else
validate_cover_letter "$1"
fi &&
if test "$GIT_SENDEMAIL_FILE_COUNTER" = "$GIT_SENDEMAIL_FILE_TOTAL"
then
git config --unset-all sendemail.validateWorktree &&
trap 'git worktree remove -ff "$worktree"' EXIT &&
validate_series
fi

View file

@ -0,0 +1,128 @@
#!/bin/sh
#
# An example hook script to block unannotated tags from entering.
# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
#
# To enable this hook, rename this file to "update".
#
# Config
# ------
# hooks.allowunannotated
# This boolean sets whether unannotated tags will be allowed into the
# repository. By default they won't be.
# hooks.allowdeletetag
# This boolean sets whether deleting tags will be allowed in the
# repository. By default they won't be.
# hooks.allowmodifytag
# This boolean sets whether a tag may be modified after creation. By default
# it won't be.
# hooks.allowdeletebranch
# This boolean sets whether deleting branches will be allowed in the
# repository. By default they won't be.
# hooks.denycreatebranch
# This boolean sets whether remotely creating branches will be denied
# in the repository. By default this is allowed.
#
# --- Command line
refname="$1"
oldrev="$2"
newrev="$3"
# --- Safety check
if [ -z "$GIT_DIR" ]; then
echo "Don't run this script from the command line." >&2
echo " (if you want, you could supply GIT_DIR then run" >&2
echo " $0 <ref> <oldrev> <newrev>)" >&2
exit 1
fi
if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
echo "usage: $0 <ref> <oldrev> <newrev>" >&2
exit 1
fi
# --- Config
allowunannotated=$(git config --type=bool hooks.allowunannotated)
allowdeletebranch=$(git config --type=bool hooks.allowdeletebranch)
denycreatebranch=$(git config --type=bool hooks.denycreatebranch)
allowdeletetag=$(git config --type=bool hooks.allowdeletetag)
allowmodifytag=$(git config --type=bool hooks.allowmodifytag)
# check for no description
projectdesc=$(sed -e '1q' "$GIT_DIR/description")
case "$projectdesc" in
"Unnamed repository"* | "")
echo "*** Project description file hasn't been set" >&2
exit 1
;;
esac
# --- Check types
# if $newrev is 0000...0000, it's a commit to delete a ref.
zero=$(git hash-object --stdin </dev/null | tr '[0-9a-f]' '0')
if [ "$newrev" = "$zero" ]; then
newrev_type=delete
else
newrev_type=$(git cat-file -t $newrev)
fi
case "$refname","$newrev_type" in
refs/tags/*,commit)
# un-annotated tag
short_refname=${refname##refs/tags/}
if [ "$allowunannotated" != "true" ]; then
echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
exit 1
fi
;;
refs/tags/*,delete)
# delete tag
if [ "$allowdeletetag" != "true" ]; then
echo "*** Deleting a tag is not allowed in this repository" >&2
exit 1
fi
;;
refs/tags/*,tag)
# annotated tag
if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
then
echo "*** Tag '$refname' already exists." >&2
echo "*** Modifying a tag is not allowed in this repository." >&2
exit 1
fi
;;
refs/heads/*,commit)
# branch
if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
echo "*** Creating a branch is not allowed in this repository" >&2
exit 1
fi
;;
refs/heads/*,delete)
# delete branch
if [ "$allowdeletebranch" != "true" ]; then
echo "*** Deleting a branch is not allowed in this repository" >&2
exit 1
fi
;;
refs/remotes/*,commit)
# tracking branch
;;
refs/remotes/*,delete)
# delete tracking branch
if [ "$allowdeletebranch" != "true" ]; then
echo "*** Deleting a tracking branch is not allowed in this repository" >&2
exit 1
fi
;;
*)
# Anything else (is there anything else?)
echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
exit 1
;;
esac
# --- Finished
exit 0

Binary file not shown.

View file

@ -0,0 +1,6 @@
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~

View file

@ -0,0 +1,2 @@
0000000000000000000000000000000000000000 fb9d4ec150fa3bb22e6f2820955c70ef8feaa08b Ako <emi.boucly38@gmail.com> 1763406742 +0100 clone: from https://github.com/neoclide/coc.nvim.git
fb9d4ec150fa3bb22e6f2820955c70ef8feaa08b 3b0b28802a1b55d0dab1a440a6e1d3b37d3af968 Ako <emi.boucly38@gmail.com> 1763406742 +0100 checkout: moving from master to release

View file

@ -0,0 +1 @@
0000000000000000000000000000000000000000 fb9d4ec150fa3bb22e6f2820955c70ef8feaa08b Ako <emi.boucly38@gmail.com> 1763406742 +0100 clone: from https://github.com/neoclide/coc.nvim.git

View file

@ -0,0 +1 @@
0000000000000000000000000000000000000000 3b0b28802a1b55d0dab1a440a6e1d3b37d3af968 Ako <emi.boucly38@gmail.com> 1763406742 +0100 branch: Created from refs/remotes/origin/release

View file

@ -0,0 +1 @@
0000000000000000000000000000000000000000 fb9d4ec150fa3bb22e6f2820955c70ef8feaa08b Ako <emi.boucly38@gmail.com> 1763406742 +0100 clone: from https://github.com/neoclide/coc.nvim.git

View file

@ -0,0 +1,168 @@
# pack-refs with: peeled fully-peeled sorted
39b10c25befcb29014ca125ec923a964db630186 refs/remotes/origin/deps
93b57d1bec5a57c6067628b21c815bbe76418c07 refs/remotes/origin/fix/document-sync
11b3e12ff563495ce4efd894e7001d3dd24db6cc refs/remotes/origin/fix/rm-localstorage-flag
fb9d4ec150fa3bb22e6f2820955c70ef8feaa08b refs/remotes/origin/master
3b0b28802a1b55d0dab1a440a6e1d3b37d3af968 refs/remotes/origin/release
f04dc51c6ec7b94bd4c69d309261872e937df414 refs/tags/v0.0.1
^22b92e27d5b49e33cd447e6d3e78f5105644e45b
dbb91163451b3d49e3a890123b2c2fedc08a5b71 refs/tags/v0.0.10
^8fc87b49d98c129ef8ac361dd8f7a585c1a4610e
ac3e875abc499d477ef082e3d7b195f64da2ebc8 refs/tags/v0.0.11
^26c61ae7351ae82434d4ab8e7428ae1ea013a3da
78e5b95768bf7abd229d31bbf010f31eaf690141 refs/tags/v0.0.12
^beb9bbaf53e731aa35655864f2a67d804fd19151
18b96cd70dc51abe94a342761645f1aa52c1c0f2 refs/tags/v0.0.13
^956373fc765ef7170bb0486b39543f8871bc49ba
77c9c882d883ba94a9c2afb14a5159d74e3a5f8a refs/tags/v0.0.14
^fbe0c0ba5a347d8c15645c1de220cb46b07451c6
4b9cecf2cbc9339baac934bd8388292965d4025f refs/tags/v0.0.15
^ea30ddd9d84bb0a8f1a0493dbbbbab89f40c1360
b38d9d1d156c1c43aad28a4320e409f66c7c37ec refs/tags/v0.0.16
^03afb5a5ee3c5b6019165de21bd258bb25608966
8689f4e500fa5f2ccf1ee79ef152867548aa2e94 refs/tags/v0.0.17
^793f383eebf3bd7494612647d5874ee17dbd3f34
6728d3c52d55f1c628dadfcb5d1c731ba834a8d0 refs/tags/v0.0.18
^09ab945bffee37f18044ad35a8b16de3b028d9f8
4ab50af897330613ec231ad5910b7bb68c8dd631 refs/tags/v0.0.19
^7fcbd2f2884d849d202c1f4fdfbb484eab662d9b
0b6ef2692c9c8d25c0fc025be519a3838c1360d4 refs/tags/v0.0.2
^6ff769957caa30a8406b081d33d517de93e062b7
da60344da81230d606a894debdc1a3148de4d307 refs/tags/v0.0.20
^631a15712b584e2bab7785b4eb77b607a4ccf6ad
c5ca3063d0299b62c07bd19f2db7278637c52a16 refs/tags/v0.0.21
^2c388b7570c1bf656cb172b5d58f3ee598c3206e
7f9888ece8d96549183c8f55e6b808e31cae7564 refs/tags/v0.0.22
^332e3dab1b565e655b59d610a9c8af792c6bd402
ff7f1d21b33849ecd2edf9fec7783c109dac75f2 refs/tags/v0.0.23
^69693d5a67563e206ebdd3b86892828333eaacf8
c663a491409346291cce776fdf6a8e36cda78446 refs/tags/v0.0.24
^4eab01fd64ab0833341233e0f668a22b2b1d630a
6e342249be39a00bfc7e6af275ea2d3aca8580c6 refs/tags/v0.0.25
^4302b8c4b31c0058f282ea82a981079f8fb0c6f1
f9e51efe089a6860b14a34d7bc61f12b8fa6e708 refs/tags/v0.0.26
^a531abd8d388bcfd4dd3e74fea657b1c73a8e2ba
acb825d9ae78708260647a20e80d0af5acc043b1 refs/tags/v0.0.27
^cfc5de3af5677b1807b1689946ec032b5a3d74fb
741427096aa90832ccee8643e3075de8dc3a1403 refs/tags/v0.0.28
^17e840426bcbd08eafa835ed3755bfbef0041766
028470fe9d8b36bd8fa098639acaa32f390f77b6 refs/tags/v0.0.29
^d090fe35ba7a41f28afbeb7af48ef2ea4793bdd6
6dfd03d1e235727e542a598b55c1c1abed45360b refs/tags/v0.0.3
^bf55a14df878b8beb27e58e4b7d791ef6cfc7ad6
5bc7a6b73566fc51eabc38a1d3a1b03a33b61e75 refs/tags/v0.0.30
^cce7b97ac7f9bb7b79d80ae190c5d94370759250
400b95d41c0ad718dcf257c20266727c0bf8258b refs/tags/v0.0.31
^389b061290ba28ff415c22f0111a717b5a8d658c
a885e47304d1c8d59ba53a66392303230f9d2361 refs/tags/v0.0.32
^a2e1ce587ef7785a2f8837ecd271fee3bd534463
bfda8e212117089cd847c589926de321e7e86b6f refs/tags/v0.0.33
^d0400c4d3eac8f3c09f47a54157702d0e152ca38
e28bc3ed716e17f2ca0bf0b28b049403a9f54b47 refs/tags/v0.0.34
^abc90a8546003f066a12506e6b845f29aade10aa
dca9eedc871bfa28c77d1c3aa1ec276a50a8337f refs/tags/v0.0.35
^822831326d13a35cfb8f3e39766878bb19ef9ba9
3d2a66fb479fe869df0dfccfd9c15754b0acebff refs/tags/v0.0.36
^413e0c621109145abdec310815a45fc8ca5b7ab3
70935de626fbf94efdbad904f221be3a586e52cb refs/tags/v0.0.37
^853325fc6deba3739768e412c0051189df40f2c5
ddd4e73034c3ff257546438c4b5797a9122fbf1a refs/tags/v0.0.38
^4a9ddf7818b7335397694123bf7e3c8520b6157b
ed872b6f29566ef151e7848df192bcd810e3246b refs/tags/v0.0.39
^7bfc761508e83fa7c9b71e21803d87c71bcd7303
3f483ba0053eae8a8b2d10c1ac1d0166538e3cab refs/tags/v0.0.4
^0006071c02be4825947d4d204a194c11a4d51339
6657ac490b22ba480351d773338540d8c9c9b561 refs/tags/v0.0.40
^ab3d5bb636b283eed4230b6de67f5c0060ba2c99
c63b9ede6e8c58b1a07501b39b7f52bc83ebb72f refs/tags/v0.0.41
^f6213c07d27c09ae641ca12b675993f36d9ef245
a07572a395c157a6b375499ddb1a06bf9c4c8b73 refs/tags/v0.0.42
^77ce9449cc48c67f26b61a9983a92dca05efa4c3
4cc4eb6681cbed19071e173eed7cea823ed0b9f4 refs/tags/v0.0.43
^3cde2877fc081ddaa2c33771c7ff1c48b28e3757
0205f69b2f88192ff9f6d26ba553e7f8dd204333 refs/tags/v0.0.44
^36142bfbcd7830842741481524cd2199086fe9ed
7efd2aa105390e4425ab59c4551f5603130eaf47 refs/tags/v0.0.45
^81a898f86fd2de10b819fc7d1232c0ebdc789f17
66b8f38b24e5ffeba217dc30f8e82c3365bc3581 refs/tags/v0.0.46
^0b964d8e53ea7b195ed6bf3690868597da1fcf30
471cba59e14ff83faa0355d55feccf02cd68bcc2 refs/tags/v0.0.47
^3a2c77577af7a2a87249095eb9b21ae288eb9ad6
1f6bb8a5d9e078d17db46c8801014d152af7de08 refs/tags/v0.0.48
^7e22262a35ab7f88a766163da8a2c45047d7d492
4758fc8a6faa7a02b19ba7061cc9a0ed58a476f3 refs/tags/v0.0.49
^137f1e5ebe127c0b3fa9737ef1bfb9b998a7b936
06dc4ebecacc2e811c7e7227b6defa0dca7b883e refs/tags/v0.0.5
^f79d99f96b609d22422316aade582d89ec4040ac
cff78d9bcde15e78c19c570060a775ac8bc767e2 refs/tags/v0.0.50
^c764e78653f2a16cf79c3a96c8dde1cef474d1cc
3dc13b9ef6e42c2c2808b165a761a7ee219c5421 refs/tags/v0.0.51
^cc96ec2ae3105637b360b359bc1d6f9952b954eb
e265598fe7dbfbe4a057d2d9ac52362569c47561 refs/tags/v0.0.52
^a4f5c8b00fdeb10c3749a56683dc64b020ee1f4f
5f9c14126d9d2595abbfc826a6f5f770d1440d1b refs/tags/v0.0.53
^ec1afd6ff1aee4e3d4decf0783f4c1b150c0b6d4
ef91d772500e667dc24ad86facf80279defc06c7 refs/tags/v0.0.54
^18bf65dd7a8cd60ff4104308d5394f8cf2a3c263
ff195f7fec41d04d6455f975b7ec9161219c40f4 refs/tags/v0.0.55
^2a367a85c4fe32d9dd9edc90b28dd6eea6008c7a
0174bf62b5d3964c1c95969a69a7e570e8e6066c refs/tags/v0.0.56
^a41122142a706886bb7f4a15f8b264691ea803a6
166f0453763e8eab0d9b7a89f9caf0a0e8426c63 refs/tags/v0.0.57
fa79c9dbc91a7dd48bcf20fc22932ee84dc0d888 refs/tags/v0.0.58
d0138b596a98504075e8e501e413726a60039c47 refs/tags/v0.0.59
^7ad16b1cfcaca1a374f4f860bfd30f61d01f1a94
c58c164e6066dfff2b5595287af6e0ec2e30fc52 refs/tags/v0.0.6
^521dce04581fa28f1815f2910ba8620607e5b29a
8e686aaabfadea22e99d0999c20f846587518eb4 refs/tags/v0.0.60
^87bd430d1fd6c666803599d5a5d2ac5f298a1b27
8c3515a64d1b62281c151b5d3758fdce40889d2b refs/tags/v0.0.61
^739bcaa607218343ab0c975d630d7ddb4395ed34
9a9b0fe72c03a8bf8309d01b234bdc412ad66433 refs/tags/v0.0.62
^f22fc67289232f6f5ebe43ff4a880a3075eaa9b9
d322272d4efa14c7a893816ead32d69fa40c1a5b refs/tags/v0.0.63
^b4a00e70ac676578f42c4378adc11a5ff7496805
467ae709ff5731e850b024e2839d5bfb83c97f95 refs/tags/v0.0.64
^81ab35e88023ec56e4e031aff9a53e855f09615c
610f0273ef253ac9fa3dbd84a1eadbddced0eeaf refs/tags/v0.0.65
^f7874ec7d7f8d2c72a603d10c40915c74ca2dcaa
55d10a1a74d38cc95ed423f9f6e8cd2e83a953c0 refs/tags/v0.0.66
^f9652d2f59d665a91b8c7fad299bc81a81e957a9
5d4d7901aa2cef84d5aa9ce2a813dfddc1d332ee refs/tags/v0.0.67
^8741e930c9c5cef97befd3e6f256b121aebe15b3
6bfe462eafecd0d5863e0e56644e28760cbbbd0a refs/tags/v0.0.68
^a0ab9a09d08e28169954be07327ab13907541d6f
3bb539522d08c140c75343b669f5a21cdadcc7b0 refs/tags/v0.0.69
^ea70c2a428d23922a75d59fa6ba1014cbc9b556e
d53854344d5527c13453fd980768693e3b6f5165 refs/tags/v0.0.7
^4ac8dcefe15550e0c9beba4bf414eee85e510dc5
4c94035b279d00357077096921333ac31a88b1ed refs/tags/v0.0.70
^99537d3c524e567ec343a01ffd2bd0aaf9605a4b
aa292e6a5c8c9d93aa6cd64edb69d14ace740f0c refs/tags/v0.0.71
^fa429d0bbcc0eca6ff85fc9a4d55e43406beec19
3a6e4290021487dca233ac920f31432b24346a25 refs/tags/v0.0.72
^22daa03a7d7b7c14125c0d4f5c11ff80e3d70606
a14804a77d9343b924c85846c92050328bf22d0f refs/tags/v0.0.73
^d9f01a6023da4f2186291d32f6a1bf71b47309e6
b9022bf188fd185bca80b7042b9237e866992924 refs/tags/v0.0.74
^9edc0edaa180fa6e8d5834f8ffc2e9a1f01e1a73
522d4fcd2b20775716a37056e3c650b2900d422d refs/tags/v0.0.75
^5b392c532585e3f88e1a143d7f969a992843e908
0c953758c729c088fe0112f1b88fd8ca7032fce7 refs/tags/v0.0.76
^a362bc4352ad986f4e8eacd2ec0b8e2d6895ce77
008095e129a0516de03c89b87c5a33c984fdf919 refs/tags/v0.0.77
^149c37453982ed83f98fbd73820d8d0f72f23cf0
048a909ffe0253039bca94e26dc1d140204919c0 refs/tags/v0.0.78
^705f94fdd3e9919b6f3c69e4dd44bf3bb5167f60
f545756ad2cc5f4f58c96006ee49846a5ee07f1d refs/tags/v0.0.79
^6242534f300920296ca27bbecd9d13a0aebbcdbe
6e7ff454aa9f15db16813b8d3961ee185d897b27 refs/tags/v0.0.8
^3535df0dbc3ecb81dd2a5912e303b7a8bceaa9d4
edcba0e3f573707081f73669790073183e643148 refs/tags/v0.0.80
^ce448a6945d90609bc5c063577e12b859de0834b
d0ace6360b8af6f053f1c501834d69c5ba459628 refs/tags/v0.0.81
^0fd56dd25fc36606afe2290240aecb6e6ab85092
7bc1f1b3dfb4838b1f6c4f046fa4d196818d92c9 refs/tags/v0.0.82
^1d3c525e2d6af0c07ed19fa7a5016ffc6a9e8421
e75b3e3bf054b50611f222076a46947585baed84 refs/tags/v0.0.9
^afd3d356b09837b5036bd098387f13fa26057128

View file

@ -0,0 +1 @@
fb9d4ec150fa3bb22e6f2820955c70ef8feaa08b

View file

@ -0,0 +1 @@
3b0b28802a1b55d0dab1a440a6e1d3b37d3af968

View file

@ -0,0 +1 @@
ref: refs/remotes/origin/master

View file

@ -0,0 +1,87 @@
0006071c02be4825947d4d204a194c11a4d51339
03afb5a5ee3c5b6019165de21bd258bb25608966
09ab945bffee37f18044ad35a8b16de3b028d9f8
0b964d8e53ea7b195ed6bf3690868597da1fcf30
0fd56dd25fc36606afe2290240aecb6e6ab85092
11b3e12ff563495ce4efd894e7001d3dd24db6cc
137f1e5ebe127c0b3fa9737ef1bfb9b998a7b936
149c37453982ed83f98fbd73820d8d0f72f23cf0
166f0453763e8eab0d9b7a89f9caf0a0e8426c63
17e840426bcbd08eafa835ed3755bfbef0041766
18bf65dd7a8cd60ff4104308d5394f8cf2a3c263
1d3c525e2d6af0c07ed19fa7a5016ffc6a9e8421
22b92e27d5b49e33cd447e6d3e78f5105644e45b
22daa03a7d7b7c14125c0d4f5c11ff80e3d70606
26c61ae7351ae82434d4ab8e7428ae1ea013a3da
2a367a85c4fe32d9dd9edc90b28dd6eea6008c7a
2c388b7570c1bf656cb172b5d58f3ee598c3206e
332e3dab1b565e655b59d610a9c8af792c6bd402
3535df0dbc3ecb81dd2a5912e303b7a8bceaa9d4
36142bfbcd7830842741481524cd2199086fe9ed
389b061290ba28ff415c22f0111a717b5a8d658c
39b10c25befcb29014ca125ec923a964db630186
3a2c77577af7a2a87249095eb9b21ae288eb9ad6
3b0b28802a1b55d0dab1a440a6e1d3b37d3af968
3cde2877fc081ddaa2c33771c7ff1c48b28e3757
413e0c621109145abdec310815a45fc8ca5b7ab3
4302b8c4b31c0058f282ea82a981079f8fb0c6f1
4a9ddf7818b7335397694123bf7e3c8520b6157b
4ac8dcefe15550e0c9beba4bf414eee85e510dc5
4eab01fd64ab0833341233e0f668a22b2b1d630a
521dce04581fa28f1815f2910ba8620607e5b29a
5b392c532585e3f88e1a143d7f969a992843e908
6242534f300920296ca27bbecd9d13a0aebbcdbe
631a15712b584e2bab7785b4eb77b607a4ccf6ad
69693d5a67563e206ebdd3b86892828333eaacf8
6ff769957caa30a8406b081d33d517de93e062b7
705f94fdd3e9919b6f3c69e4dd44bf3bb5167f60
739bcaa607218343ab0c975d630d7ddb4395ed34
77ce9449cc48c67f26b61a9983a92dca05efa4c3
793f383eebf3bd7494612647d5874ee17dbd3f34
7ad16b1cfcaca1a374f4f860bfd30f61d01f1a94
7bfc761508e83fa7c9b71e21803d87c71bcd7303
7e22262a35ab7f88a766163da8a2c45047d7d492
7fcbd2f2884d849d202c1f4fdfbb484eab662d9b
81a898f86fd2de10b819fc7d1232c0ebdc789f17
81ab35e88023ec56e4e031aff9a53e855f09615c
822831326d13a35cfb8f3e39766878bb19ef9ba9
853325fc6deba3739768e412c0051189df40f2c5
8741e930c9c5cef97befd3e6f256b121aebe15b3
87bd430d1fd6c666803599d5a5d2ac5f298a1b27
8fc87b49d98c129ef8ac361dd8f7a585c1a4610e
93b57d1bec5a57c6067628b21c815bbe76418c07
956373fc765ef7170bb0486b39543f8871bc49ba
99537d3c524e567ec343a01ffd2bd0aaf9605a4b
9edc0edaa180fa6e8d5834f8ffc2e9a1f01e1a73
a0ab9a09d08e28169954be07327ab13907541d6f
a2e1ce587ef7785a2f8837ecd271fee3bd534463
a362bc4352ad986f4e8eacd2ec0b8e2d6895ce77
a41122142a706886bb7f4a15f8b264691ea803a6
a4f5c8b00fdeb10c3749a56683dc64b020ee1f4f
a531abd8d388bcfd4dd3e74fea657b1c73a8e2ba
ab3d5bb636b283eed4230b6de67f5c0060ba2c99
abc90a8546003f066a12506e6b845f29aade10aa
afd3d356b09837b5036bd098387f13fa26057128
b4a00e70ac676578f42c4378adc11a5ff7496805
beb9bbaf53e731aa35655864f2a67d804fd19151
bf55a14df878b8beb27e58e4b7d791ef6cfc7ad6
c764e78653f2a16cf79c3a96c8dde1cef474d1cc
cc96ec2ae3105637b360b359bc1d6f9952b954eb
cce7b97ac7f9bb7b79d80ae190c5d94370759250
ce448a6945d90609bc5c063577e12b859de0834b
cfc5de3af5677b1807b1689946ec032b5a3d74fb
d0400c4d3eac8f3c09f47a54157702d0e152ca38
d090fe35ba7a41f28afbeb7af48ef2ea4793bdd6
d9f01a6023da4f2186291d32f6a1bf71b47309e6
ea30ddd9d84bb0a8f1a0493dbbbbab89f40c1360
ea70c2a428d23922a75d59fa6ba1014cbc9b556e
ec1afd6ff1aee4e3d4decf0783f4c1b150c0b6d4
f22fc67289232f6f5ebe43ff4a880a3075eaa9b9
f6213c07d27c09ae641ca12b675993f36d9ef245
f7874ec7d7f8d2c72a603d10c40915c74ca2dcaa
f79d99f96b609d22422316aade582d89ec4040ac
f9652d2f59d665a91b8c7fad299bc81a81e957a9
fa429d0bbcc0eca6ff85fc9a4d55e43406beec19
fa79c9dbc91a7dd48bcf20fc22932ee84dc0d888
fb9d4ec150fa3bb22e6f2820955c70ef8feaa08b
fbe0c0ba5a347d8c15645c1de220cb46b07451c6

View file

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

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,33 @@
local M = {}
local ns = vim.api.nvim_create_namespace('coc-diagnostic')
function M.refresh()
vim.diagnostic.reset(ns)
for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do
if vim.api.nvim_buf_is_loaded(bufnr) then
local ok, items = pcall(vim.api.nvim_buf_get_var, bufnr, 'coc_diagnostic_map')
if ok and type(items) == 'table' and vim.tbl_count(items) >= 0 then
local diagnostics = {}
for _, d in ipairs(items) do
diagnostics[#diagnostics + 1] = {
bufnr = bufnr,
lnum = d.location.range.start.line,
end_lnum = d.location.range['end'].line,
col = d.location.range.start.character,
end_col = d.location.range['end'].character,
severity = d.level,
message = d.message,
source = d.source,
code = d.code,
namespace = ns,
}
end
vim.diagnostic.set(ns, bufnr, diagnostics)
end
end
end
end
return M

View file

@ -0,0 +1,428 @@
local util = require('coc.util')
local api = vim.api
local M = {}
local default_priority = 1024
local priorities = {
CocListSearch = 2048,
CocSearch = 2048
}
local diagnostic_hlgroups = {
CocUnusedHighlight = 0,
CocDeprecatedHighlight = 1,
CocHintHighlight = 2,
CocInfoHighlight = 3,
CocWarningHighlight = 4,
CocErrorHighlight = 5
}
local maxCount = vim.g.coc_highlight_maximum_count or 500
local n10 = vim.fn.has('nvim-0.10') == 1 and true or false
-- 16 ms
local maxTimePerBatchMs = 16
local function is_null(value)
return value == nil or value == vim.NIL
end
local function is_enabled(value)
return value == 1 or value == true
end
-- 0 based character index to 0 based byte index
local function byte_index(text, character)
if character == 0 then
return 0
end
local list = vim.str_utf_pos(text)
local bytes = list[character + 1]
if bytes == nil then
return #text
end
return bytes - 1
end
local function create_namespace(key)
if type(key) == 'number' then
if key == -1 then
return api.nvim_create_namespace('')
end
return key
end
if type(key) ~= 'string' then
error('Expect number or string for namespace key, got ' .. type(key))
end
return api.nvim_create_namespace('coc-' .. key)
end
local function get_priority(hl_group, priority)
if priorities[hl_group] ~= nil then
return priorities[hl_group]
end
if type(priority) ~= 'number' then
return default_priority
end
local n = diagnostic_hlgroups[hl_group]
if n ~= nil then
return priority + n
end
return priority
end
local function convert_item(item)
if #item == 0 then
local combine = 0
if item.combine or priorities[item.hlGroup] ~= nil then
combine = 1
end
return {item.hlGroup, item.lnum, item.colStart, item.colEnd, combine, item.start_incl, item.end_incl}
end
return item
end
local function getValuesWithPrefix(dict, prefix)
local result = {}
local prefixLength = #prefix
for key, value in pairs(dict) do
if type(key) == 'string' and string.sub(key, 1, prefixLength) == prefix then
table.insert(result, value)
end
end
return result
end
local function addHighlights(bufnr, ns, highlights, priority)
for _, items in ipairs(highlights) do
local converted = convert_item(items)
local hlGroup = converted[1]
local line = converted[2]
local startCol = converted[3]
local endCol = converted[4]
local hlMode = is_enabled(converted[5]) and 'combine' or 'replace'
if endCol == -1 then
local text = vim.fn.getbufline(bufnr, line + 1)[1] or ''
endCol = #text
end
priority = get_priority(hlGroup, priority)
-- Error: col value outside range
pcall(api.nvim_buf_set_extmark, bufnr, ns, line, startCol, {
end_col = endCol,
hl_group = hlGroup,
hl_mode = hlMode,
right_gravity = true,
end_right_gravity = is_enabled(converted[7]),
priority = math.min(priority, 4096)
})
end
end
local function addHighlightTimer(bufnr, ns, highlights, priority, changedtick)
if not api.nvim_buf_is_loaded(bufnr) then
return nil
end
if api.nvim_buf_get_var(bufnr, 'changedtick') ~= changedtick then
return nil
end
local total = #highlights
local i = 1
local start = util.getCurrentTime()
local next = {}
while i <= total do
local end_idx = math.min(i + maxCount - 1, total)
local hls = vim.list_slice(highlights, i, end_idx)
addHighlights(bufnr, ns, hls, priority)
local duration = util.getCurrentTime() - start
if duration > maxTimePerBatchMs and end_idx < total then
next = vim.list_slice(highlights, end_idx + 1, total)
break
end
i = end_idx + 1
end
if #next > 0 then
vim.defer_fn(function()
addHighlightTimer(bufnr, ns, next, priority, changedtick)
end, 10)
end
end
-- Get single line extmarks
-- @param bufnr - buffer number
-- @param key - namespace id or key string.
-- @param start_line - start line index, default to 0.
-- @param end_line - end line index, default to -1.
function M.get_highlights(bufnr, key, start_line, end_line)
if not api.nvim_buf_is_loaded(bufnr) then
return nil
end
start_line = type(start_line) == 'number' and start_line or 0
end_line = type(end_line) == 'number' and end_line or -1
local max = end_line == -1 and api.nvim_buf_line_count(bufnr) or end_line + 1
local ns = type(key) == 'number' and key or create_namespace(key)
local markers = api.nvim_buf_get_extmarks(bufnr, ns, {start_line, 0}, {end_line, -1}, {details = true})
local res = {}
for _, mark in ipairs(markers) do
local id = mark[1]
local line = mark[2]
local startCol = mark[3]
local details = mark[4] or {}
local endCol = details.end_col
if line < max then
local delta = details.end_row - line
if delta == 1 and endCol == 0 then
local text = vim.fn.getbufline(bufnr, line + 1)[1] or ''
endCol = #text
elseif delta > 0 then
endCol = -1
end
if startCol >= endCol then
api.nvim_buf_del_extmark(bufnr, ns, id)
else
table.insert(res, {details.hl_group, line, startCol, endCol, id})
end
end
end
return res
end
-- Add single highlight
-- @param id - buffer number or 0 for current buffer.
-- @param key - namespace key or namespace number or -1.
-- @param hl_group - highlight group.
-- @param line - 0 based line index.
-- @param col_start - 0 based col index, inclusive.
-- @param col_end - 0 based col index, exclusive.
-- @param opts - Optional table with priority and combine as boolean.
function M.add_highlight(id, key, hl_group, line, col_start, col_end, opts)
local bufnr = id == 0 and api.nvim_get_current_buf() or id
opts = is_null(opts) and {} or opts
if api.nvim_buf_is_loaded(bufnr) then
local priority = get_priority(hl_group, opts.priority)
if col_end == -1 then
local text = vim.fn.getbufline(bufnr, line + 1)[1] or ''
col_end = #text
end
if col_end > 0 and col_end > col_start then
local ns = create_namespace(key)
pcall(api.nvim_buf_set_extmark, bufnr, ns, line, col_start, {
end_col = col_end,
hl_group = hl_group,
hl_mode = is_enabled(opts.combine) and 'combine' or 'replace',
right_gravity = true,
end_right_gravity = is_enabled(opts.end_incl),
priority = math.min(priority, 4096)
})
end
end
end
-- Clear all namespaces with coc- namespace prefix.
function M.clear_all()
local namespaces = getValuesWithPrefix(api.nvim_get_namespaces(), 'coc-')
local bufnrs = api.nvim_list_bufs()
for _, bufnr in ipairs(bufnrs) do
if api.nvim_buf_is_loaded(bufnr) then
for _, ns in ipairs(namespaces) do
api.nvim_buf_clear_namespace(bufnr, ns, 0, -1)
end
end
end
end
-- Remove extmarks by id table.
-- @param bufnr - buffer number
-- @param key - namespace id or key string.
-- @param ids - table with ids of extmarks.
function M.del_markers(bufnr, key, ids)
if api.nvim_buf_is_loaded(bufnr) then
local ns = create_namespace(key)
for _, id in ipairs(ids) do
api.nvim_buf_del_extmark(bufnr, ns, id)
end
end
end
-- Add highlights to buffer.
-- @param bufnr - buffer number
-- @param key - namespace id or key string.
-- @param highlights - highlight items, item could be HighlightItem dict or number list.
-- @param priority - optional priority
function M.set_highlights(bufnr, key, highlights, priority)
if api.nvim_buf_is_loaded(bufnr) then
local changedtick = api.nvim_buf_get_var(bufnr, 'changedtick')
local ns = create_namespace(key)
addHighlightTimer(bufnr, ns, highlights, priority, changedtick)
end
end
-- Clear namespace highlights of region.
-- @param id - buffer number or 0 for current buffer.
-- @param key - namespace id or key string.
-- @param start_line - start line index, default to 0.
-- @param end_line - end line index, default to -1.
function M.clear_highlights(id, key, start_line, end_line)
local bufnr = id == 0 and api.nvim_get_current_buf() or id
start_line = type(start_line) == 'number' and start_line or 0
end_line = type(end_line) == 'number' and end_line or -1
if api.nvim_buf_is_loaded(bufnr) then
local ns = create_namespace(key)
api.nvim_buf_clear_namespace(bufnr, ns, start_line, end_line)
end
end
-- Update highlights of specific region.
-- @param id - buffer number or 0 for current buffer.
-- @param key - namespace id or key string.
-- @param highlights - highlight items, item could be HighlightItem dict or number list.
-- @param start_line - start line index, default to 0.
-- @param end_line - end line index, default to -1.
-- @param priority - optional priority.
-- @param changedtick - optional buffer changedtick.
function M.update_highlights(id, key, highlights, start_line, end_line, priority, changedtick)
local bufnr = id == 0 and api.nvim_get_current_buf() or id
start_line = type(start_line) == 'number' and start_line or 0
end_line = type(end_line) == 'number' and end_line or -1
if api.nvim_buf_is_loaded(bufnr) then
local ns = create_namespace(key)
local tick = api.nvim_buf_get_var(bufnr, 'changedtick')
if type(changedtick) == 'number' and changedtick ~= tick then
return
end
api.nvim_buf_clear_namespace(bufnr, ns, start_line, end_line)
addHighlightTimer(bufnr, ns, highlights, priority, tick)
end
end
-- Update namespace highlights of whole buffer.
-- @param bufnr - buffer number.
-- @param key - namespace id or key string.
-- @param highlights - highlight items, item could be HighlightItem dict or number list.
-- @param priority - optional priority.
-- @param changedtick - optional buffer changedtick.
function M.buffer_update(bufnr, key, highlights, priority, changedtick)
if api.nvim_buf_is_loaded(bufnr) then
local ns = create_namespace(key)
api.nvim_buf_clear_namespace(bufnr, ns, 0, -1)
if #highlights > 0 then
local tick = api.nvim_buf_get_var(bufnr, 'changedtick')
if type(changedtick) ~= 'number' or tick == changedtick then
local winid = vim.fn.bufwinid(bufnr)
if winid == -1 then
addHighlightTimer(bufnr, ns, highlights, priority, tick)
else
local info = vim.fn.getwininfo(winid)[1]
local topline = info.topline
local botline = info.botline
if topline <= 5 then
addHighlightTimer(bufnr, ns, highlights, priority, tick)
else
local curr_hls = {}
local other_hls = {}
for _, hl in ipairs(highlights) do
local lnum = hl[2] ~= nil and hl[2] + 1 or hl.lnum + 1
if lnum >= topline and lnum <= botline then
table.insert(curr_hls, hl)
else
table.insert(other_hls, hl)
end
end
vim.list_extend(curr_hls, other_hls)
addHighlightTimer(bufnr, ns, curr_hls, priority, tick)
end
end
end
end
end
end
-- Add highlights to LSP ranges
-- @param id - buffer number or 0 for current buffer.
-- @param key - namespace id or key string.
-- @param hl_group - highlight group.
-- @param ranges - LSP range list.
-- @param opts - Optional table with priority and clear, combine as boolean.
function M.highlight_ranges(id, key, hl_group, ranges, opts)
local bufnr = id == 0 and api.nvim_get_current_buf() or id
if is_null(opts) or type(opts) ~= 'table' then
opts = {}
end
if api.nvim_buf_is_loaded(bufnr) then
if opts.clear then
local ns = create_namespace(key)
api.nvim_buf_clear_namespace(bufnr, ns, 0, -1)
end
local highlights = {}
for _, range in ipairs(ranges) do
local sp = range['start']
local ep = range['end']
local lines = vim.fn.getbufline(bufnr, sp.line + 1, ep.line + 1)
for index=sp.line,ep.line,1 do
local line = lines[index - sp.line + 1] or ''
if #line > 0 then
local colStart = index == sp.line and byte_index(line, sp.character) or 0
local colEnd = index == ep.line and byte_index(line, ep.character) or #line
if colEnd > colStart then
local combine = is_enabled(opts.combine) and 1 or 0
table.insert(highlights, {hl_group, index, colStart, colEnd, combine, opts.start_incl, opts.end_incl})
end
end
end
end
if #highlights > 0 then
local priority = type(opts.priority) == 'number' and opts.priority or 4096
M.set_highlights(bufnr, key, highlights, priority)
end
end
end
-- Use matchaddpos to add highlights to window.
-- @param id - window id, or 0 for current window.
-- @param buf - buffer number, or 0 for current buffer.
-- @param ranges - LSP ranges.
-- @param hlGroup - highlight group.
-- @param priority - Optional priority, default to 99.
function M.match_ranges(id, buf, ranges, hl_group, priority)
local winid = id == 0 and api.nvim_get_current_win() or id
local bufnr = buf == 0 and vim.fn.winbufnr(winid) or buf
if not api.nvim_win_is_valid(winid) or vim.fn.winbufnr(winid) ~= bufnr then
return {}
end
local ids = {}
local pos = {}
for _, range in ipairs(ranges) do
local sp = range['start']
local ep = range['end']
local lines = vim.fn.getbufline(bufnr, sp.line + 1, ep.line + 1)
for index=sp.line,ep.line,1 do
local line = lines[index - sp.line + 1] or ''
if #line > 0 then
local colStart = index == sp.line and byte_index(line, sp.character) or 0
local colEnd = index == ep.line and byte_index(line, ep.character) or #line
if colEnd > colStart then
table.insert(pos, {index + 1, colStart + 1, colEnd - colStart})
end
end
end
end
local count = #pos
if count > 0 then
priority = type(priority) == 'number' and priority or 99
local opts = {window = winid}
if count < 9 or n10 then
---@diagnostic disable-next-line: param-type-mismatch
table.insert(ids, vim.fn.matchaddpos(hl_group, pos, priority, -1, opts))
else
local group = {}
for i=1,count,8 do
for j = i,math.min(i+7, count) do
table.insert(group, pos[j])
end
---@diagnostic disable-next-line: param-type-mismatch
table.insert(ids, vim.fn.matchaddpos(hl_group, group, priority, -1, opts))
group = {}
end
end
end
return ids
end
return M

View file

@ -0,0 +1,428 @@
local api = vim.api
local M = {}
local function splitText(text, col)
return text:sub(1, col - 1), text:sub(col)
end
local function copy(t)
local list = {}
for k, v in pairs(t) do
list[k] = v
end
return list
end
local function insertList(target, insert, linePos, colPos)
local result = {}
for i = 1, #target do
if i < linePos or i > linePos then
table.insert(result, target[i])
else
local before, after = splitText(target[i], colPos)
for j = 1, #insert do
local text = insert[j]
if j == 1 then
text = before .. text
end
if j == #insert then
text = text .. after
end
table.insert(result, text)
end
end
end
return result
end
local function lcsDiff(str1, str2) -- 计算最长公共子序列
local function lcs(a, b)
local matrix = {}
for i = 0, #a do
matrix[i] = {}
for j = 0, #b do
if i == 0 or j == 0 then
matrix[i][j] = 0
elseif a:sub(i, i) == b:sub(j, j) then
matrix[i][j] = matrix[i - 1][j - 1] + 1
else
matrix[i][j] = math.max(matrix[i - 1][j], matrix[i][j - 1])
end
end
end
local result = ''
local i, j = #a, #b
while i > 0 and j > 0 do
if a:sub(i, i) == b:sub(j, j) then
result = a:sub(i, i) .. result
i = i - 1
j = j - 1
elseif matrix[i - 1][j] > matrix[i][j - 1] then
i = i - 1
else
j = j - 1
end
end
return result
end
local common = lcs(str1, str2)
local result = {}
local i1, i2, ic = 1, 1, 1
while ic <= #common do
-- 处理str1中不在公共序列的部分
while i1 <= #str1 and str1:sub(i1, i1) ~= common:sub(ic, ic) do
table.insert(result, { type = '-', char = str1:sub(i1, i1) })
i1 = i1 + 1
end
-- 处理str2中不在公共序列的部分
while i2 <= #str2 and str2:sub(i2, i2) ~= common:sub(ic, ic) do
table.insert(result, { type = '+', char = str2:sub(i2, i2) })
i2 = i2 + 1
end
-- 添加公共字符
if ic <= #common then
table.insert(result, { type = '=', char = common:sub(ic, ic) })
i1 = i1 + 1
i2 = i2 + 1
ic = ic + 1
end
end
-- 处理剩余字符
while i1 <= #str1 do
table.insert(result, { type = '-', char = str1:sub(i1, i1) })
i1 = i1 + 1
end
while i2 <= #str2 do
table.insert(result, { type = '+', char = str2:sub(i2, i2) })
i2 = i2 + 1
end
return result
end
-- Try find new col in changed text
-- Not 100% correct, but works most of the time.
-- Return nil when not found
local function findNewCol(text, col, newText)
local before, after = splitText(text, col)
if #before == 0 then
return 1
end
if #after == 0 then
return #newText + 1
end
if #before <= #after and string.sub(newText, 1, #before) == before then
return col
end
if string.sub(newText, -#after) == after then
return #newText - #after + 1
end
local diff = lcsDiff(text, newText)
local used = 1
local index = 1
for _, item in ipairs(diff) do
if item.type == '-' then
used = used + #item.char
elseif item.type == '+' then
index = index + #item.char
elseif item.type == '=' then
local total = used + #item.char
if total >= col then
local plus = col - used
used = col
index = index + plus
else
used = total
index = index + #item.char
end
end
if used == col then
break
end
if used > col then
return nil
end
end
return used == col and index or nil
end
local function findInsert(arr1, arr2, linePos, colPos)
local l1 = #arr1
local l2 = #arr2
if l1 < l2 or linePos < 1 or linePos > #arr1 then
return nil
end
arr2 = copy(arr2)
for i = 1, #arr1 - linePos, 1 do
local a = arr1[l1 - i + 1]
local idx = l2 - i + 1
local b = arr2[idx]
if b == nil then
return nil
end
if a ~= b then
return nil
end
table.remove(arr2, idx)
end
local before, after = splitText(arr1[linePos], colPos)
local last = arr2[#arr2]
if #after > 0 and last:sub(-#after) ~= after then
return nil
end
arr2[#arr2] = last:sub(1, - #after - 1)
for index, value in ipairs(arr2) do
local text = arr1[index]
if index < #arr2 and text ~= value then
return nil
end
if index == #arr2 and text:sub(1, #value) ~= value then
return nil
end
end
local pos = {}
pos.line = #arr2
pos.col = #(arr2[#arr2]) + 1
local inserted = {}
for i = pos.line, linePos, 1 do
if i == pos.line then
local text = arr1[i]:sub(pos.col)
table.insert(inserted, text)
elseif i == linePos then
table.insert(inserted, before)
else
table.insert(inserted, arr1[i])
end
end
return pos, inserted
end
local function findStringDiff(oldStr, newStr, reverseFirst)
local len1, len2 = #oldStr, #newStr
local maxLen = math.max(len1, len2)
-- 先从后往前找差异
if reverseFirst then
local end1, end2 = len1, len2
while end1 >= 1 and end2 >= 1 do
local c1 = oldStr:sub(end1, end1)
local c2 = newStr:sub(end2, end2)
if c1 ~= c2 then
break
end
end1 = end1 - 1
end2 = end2 - 1
end
-- 如果完全相同
if end1 < 1 and end2 < 1 then
return nil
end
-- 然后从前往后找差异
local start = 1
while start <= end1 and start <= end2 do
local c1 = oldStr:sub(start, start)
local c2 = newStr:sub(start, start)
if c1 ~= c2 then
break
end
start = start + 1
end
return {
startPos = start,
endPosOld = end1,
inserted = newStr:sub(start, end2)
}
else
local start = 1
while start <= maxLen do
local c1 = start <= len1 and oldStr:sub(start, start) or nil
local c2 = start <= len2 and newStr:sub(start, start) or nil
if c1 ~= c2 then
break
end
start = start + 1
end
-- 如果完全相同
if start > maxLen then
return nil
end
-- 然后从后往前找差异
local end1, end2 = len1, len2
while end1 >= start and end2 >= start do
local c1 = oldStr:sub(end1, end1)
local c2 = newStr:sub(end2, end2)
if c1 ~= c2 then
break
end
end1 = end1 - 1
end2 = end2 - 1
end
return {
startPos = start,
endPosOld = end1,
inserted = newStr:sub(start, end2)
}
end
end
local function replaceSubstring(original, startPos, endPos, replacement)
local prefix = original:sub(1, startPos - 1)
local suffix = original:sub(endPos + 1)
return prefix .. replacement .. suffix
end
local function hasConflict(diff1, diff2)
-- 如果任一diff为nil无变化则无冲突
if not diff1 or not diff2 then
return false
end
-- 获取两个diff的修改范围
local start1, end1 = diff1.startPos, diff1.endPosOld
local start2, end2 = diff2.startPos, diff2.endPosOld
-- 处理删除的情况endPos可能小于startPos
end1 = math.max(end1, start1 - 1)
end2 = math.max(end2, start2 - 1)
-- 检查范围是否重叠
local overlap = not (end1 < start2 or end2 < start1)
return overlap
end
local function diffApply(original, current, newText, reverseFirst)
local diff1 = findStringDiff(original, current, reverseFirst)
local diff2 = findStringDiff(original, newText, not reverseFirst)
if hasConflict(diff1, diff2) then
diff1 = findStringDiff(original, current, not reverseFirst)
diff2 = findStringDiff(original, newText, reverseFirst)
end
if diff1 == nil or diff2 == nil or hasConflict(diff1, diff2) then
return nil
end
local result
if diff1.startPos < diff2.startPos then
result = replaceSubstring(original, diff2.startPos, diff2.endPosOld, diff2.inserted)
result = replaceSubstring(result, diff1.startPos, diff1.endPosOld, diff1.inserted)
else
result = replaceSubstring(original, diff1.startPos, diff1.endPosOld, diff1.inserted)
result = replaceSubstring(result, diff2.startPos, diff2.endPosOld, diff2.inserted)
end
return result
end
-- Change single line by use nvim_buf_set_text
-- 1 based line number, current line, applied line
function M.changeLineText(bufnr, lnum, current, applied)
local diff = findStringDiff(current, applied)
if diff ~= nil then
local lineIdx = lnum - 1
api.nvim_buf_set_text(bufnr, lineIdx, diff.startPos - 1, lineIdx, diff.endPosOld, {diff.inserted})
end
end
-- Check if new line insert.
-- Check text change instead of insert only.
-- Check change across multiple lines.
function M.set_lines(bufnr, changedtick, originalLines, replacement, startLine, endLine, changes, cursor, col, linecount)
if not api.nvim_buf_is_loaded(bufnr) then
return nil
end
local delta = 0
local column = vim.fn.col('.')
if type(col) == 'number' then
delta = column - col
end
local applied = nil
local idx = 0
local currentBuf = api.nvim_get_current_buf() == bufnr
local current = currentBuf and vim.fn.getline('.') or ''
if currentBuf and api.nvim_buf_get_var(bufnr, 'changedtick') > changedtick then
local lnum = vim.fn.line('.')
idx = lnum - startLine
if idx >= 1 then
local original = originalLines[idx]
local count = vim.fn.line('$')
if count ~= linecount then
-- Check content insert before cursor.
if count > linecount then
local currentLines = api.nvim_buf_get_lines(bufnr, startLine, endLine + count - linecount, false)
-- Cursor not inside
if currentLines[idx] == nil then
return nil
end
-- Compare to original lines, find insert position, text
local pos, inserted = findInsert(currentLines, originalLines, idx, column)
if pos ~= nil then
local newText = replacement[pos.line]
if newText == nil then
return nil
end
local colPos = findNewCol(originalLines[pos.line], pos.col, newText)
if colPos == nil then
return nil
end
replacement = insertList(replacement, inserted, pos.line, colPos)
endLine = endLine + count - linecount
changes = vim.NIL
else
return nil
end
else
return nil
end
else
-- current line changed
if original ~= nil and original ~= current then
local newText = replacement[idx]
if newText ~= nil then
if newText == original then
applied = current
else
applied = diffApply(original, current, newText, column > #current/2)
end
end
end
end
end
end
if applied ~= nil then
replacement[idx] = applied
if #replacement < 30 then
-- use nvim_buf_set_text to keep extmarks
for i = 1, math.min(#replacement, #originalLines) do
local text = idx == i and current or originalLines[i]
M.changeLineText(bufnr, startLine + i, text, replacement[i])
end
if #replacement > #originalLines then
local newLines = vim.list_slice(replacement, #originalLines + 1)
api.nvim_buf_set_lines(bufnr, endLine, endLine, false, newLines)
elseif #originalLines > #replacement then
api.nvim_buf_set_lines(bufnr, startLine + #replacement, endLine, false, {})
end
else
api.nvim_buf_set_lines(bufnr, startLine, endLine, false, replacement)
end
else
if type(changes) == 'table' and #changes > 0 then
-- reverse iteration
for i = #changes, 1, -1 do
local item = changes[i]
api.nvim_buf_set_text(bufnr, item[2], item[3], item[4], item[5], item[1])
end
else
api.nvim_buf_set_lines(bufnr, startLine, endLine, false, replacement)
end
end
if currentBuf and type(cursor) == 'table' then
vim.fn.cursor({cursor[1], cursor[2] + delta})
end
end
return M

View file

@ -0,0 +1,47 @@
local M = {}
local unpackFn = unpack
if unpackFn == nil then
unpackFn = table.unpack
end
M.unpack = unpackFn
function M.sendErrorMsg(msg)
vim.defer_fn(function()
vim.api.nvim_call_function('coc#rpc#notify', {'nvim_error_event', {0, 'Lua ' .. _VERSION .. ':'.. msg}})
end, 10)
end
function M.getCurrentTime()
return os.clock() * 1000
end
local function errorHandler(err)
local traceback = debug.traceback(2)
return err .. "\n" .. traceback
end
-- catch the error and send notification to NodeJS
function M.call(module, func, args)
local m = require(module)
local method = m[func]
local result = nil
if method ~= nil then
local ok, err = xpcall(function ()
result = method(unpackFn(args))
end, errorHandler)
if not ok then
local msg = 'Error on ' .. module .. '[' .. func .. ']" ' .. err
M.sendErrorMsg(msg)
error(msg)
end
else
local msg = 'Method "' .. module .. '[' .. func .. ']" not exists'
M.sendErrorMsg(msg)
error(msg)
end
return result
end
return M

View file

@ -0,0 +1,112 @@
local api = vim.api
local M = {}
local n10 = vim.fn.has('nvim-0.10')
local maxCount = vim.g.coc_highlight_maximum_count or 500
local function addVirtualText(bufnr, ns, opts, pre, priority)
local align = opts.text_align or 'after'
local config = { hl_mode = opts.hl_mode or 'combine' }
local column = opts.col or 0
if align == 'above' or align == 'below' then
if #pre == 0 then
config.virt_lines = { opts.blocks }
else
local list = { {pre, 'Normal'}}
vim.list_extend(list, opts.blocks)
config.virt_lines = { list }
end
if align == 'above' then
config.virt_lines_above = true
end
else
config.virt_text = opts.blocks
if n10 and column ~= 0 then
config.virt_text_pos = 'inline'
elseif align == 'right' then
config.virt_text_pos = 'right_align'
elseif type(opts.virt_text_win_col) == 'number' then
config.virt_text_win_col = opts.virt_text_win_col
config.virt_text_pos = 'overlay'
elseif align == 'overlay' then
config.virt_text_pos = 'overlay'
else
config.virt_text_pos = 'eol'
end
if type(opts.virt_lines) == 'table' then
config.virt_lines = opts.virt_lines
config.virt_text_pos = 'overlay'
end
end
if type(priority) == 'number' then
config.priority = math.min(priority, 4096)
end
local col = column ~= 0 and column - 1 or 0
-- api.nvim_buf_set_extmark(bufnr, ns, opts.line, col, config)
-- Error: col value outside range
pcall(api.nvim_buf_set_extmark, bufnr, ns, opts.line, col, config)
end
-- This function is called by buffer.setVirtualText
function M.add(bufnr, ns, line, blocks, opts)
local pre = ''
if opts.indent == true then
local str = vim.fn.getbufline(bufnr, line + 1)[1] or ''
pre = string.match(str, "^%s*") or ''
end
local conf = {line = line, blocks = blocks}
for key, value in pairs(opts) do
conf[key] = value
end
addVirtualText(bufnr, ns, conf, pre, opts.priority)
end
-- opts.line - Zero based line number
-- opts.blocks - List with [text, hl_group]
-- opts.hl_mode - Default to 'combine'.
-- opts.col - nvim >= 0.10.0, 1 based.
-- opts.virt_text_win_col
-- opts.text_align - Could be 'after' 'right' 'below' 'above', converted on neovim.
-- indent - add indent when using 'above' and 'below' as text_align
local function addVirtualTexts(bufnr, ns, items, indent, priority)
if #items == 0 then
return nil
end
local buflines = {}
local start = 0
if indent then
start = items[1].line
local endLine = items[#items].line
buflines = api.nvim_buf_get_lines(bufnr, start, endLine + 1, false) or {}
end
for _, opts in ipairs(items) do
local pre = indent and string.match(buflines[opts.line - start + 1], "^%s*") or ''
addVirtualText(bufnr, ns, opts, pre, priority)
end
end
local function addVirtualTextsTimer(bufnr, ns, items, indent, priority, changedtick)
if not api.nvim_buf_is_loaded(bufnr) then
return nil
end
if vim.fn.getbufvar(bufnr, 'changedtick', 0) ~= changedtick then
return nil
end
if #items > maxCount then
local markers = {}
local next = {}
vim.list_extend(markers, items, 1, maxCount)
vim.list_extend(next, items, maxCount, #items)
addVirtualTexts(bufnr, ns, markers, indent, priority)
vim.defer_fn(function()
addVirtualTextsTimer(bufnr, ns, next, indent, priority, changedtick)
end, 10)
else
addVirtualTexts(bufnr, ns, items, indent, priority)
end
end
function M.set(bufnr, ns, items, indent, priority)
local changedtick = vim.fn.getbufvar(bufnr, 'changedtick', 0)
addVirtualTextsTimer(bufnr, ns, items, indent, priority, changedtick)
end
return M

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,14 @@
if vim.fn.has('nvim-0.10') then
vim.api.nvim_create_autocmd({ 'BufEnter' }, {
callback = function()
require('coc.diagnostic').refresh()
end,
})
vim.api.nvim_create_autocmd('User', {
pattern = 'CocDiagnosticChange',
callback = function()
require('coc.diagnostic').refresh()
end,
})
end

View file

@ -0,0 +1,824 @@
scriptencoding utf-8
let s:is_vim = !has('nvim')
let s:is_gvim = s:is_vim && has("gui_running")
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 s:is_vim
let l:unsupported = !has('patch-9.0.0438')
else
let l:unsupported = !has('nvim-0.8.0')
endif
if l:unsupported == 1
echohl Error
echom "coc.nvim requires at least Vim 9.0.0438 or Neovim 0.8.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 9.0.0438 or Neovim 0.8.0."
echohl None
sleep 2
endif
endif
endfunction
call s:checkVersion()
let g:did_coc_loaded = 1
let g:coc_service_initialized = 0
let s:root = expand('<sfile>:h:h')
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
" Used by popup prompt on vim
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'
" notify exit for vim terminal prompt to ensure cleanup
call coc#rpc#notify('PromptExit', [a:bufnr])
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'
call coc#rpc#notify('PromptKeyPress', [a:bufnr, a:arglist[1]])
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
let bufnr = empty(a:000) ? bufnr('%') : a:1
return coc#rpc#request('hasProvider', [a:name, bufnr])
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! CocRegisterNotification(id, method, cb) abort
call coc#on_notify(a:id, a:method, a:cb)
endfunction
" Deprecated, use CocRegisterNotification instead
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(1)
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 '.fnameescape(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:CreateHighlight(group, fg, bg) abort
let cmd = coc#hlgroup#compose(a:fg, a:bg)
if !empty(trim(cmd))
exe 'hi default '.a:group.' '.cmd
else
exe 'hi default link '.a:group.' '.a:fg
endif
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
autocmd! coc_nvim
call coc#rpc#notify('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:HandleBufEnter(bufnr) abort
if s:is_vim
call coc#api#Buf_flush(a:bufnr)
endif
call s:Autocmd('BufEnter', a:bufnr)
endfunction
function! s:HandleCharInsert(char, bufnr) abort
call s:Autocmd('InsertCharPre', a:char, a:bufnr)
endfunction
function! s:HandleTextChangedI(event, bufnr) abort
if s:is_vim
" make sure lines event before changed event.
call coc#api#Buf_flush(a:bufnr)
endif
call s:Autocmd(a:event, a:bufnr, coc#util#change_info())
endfunction
function! s:HandleTextChanged(bufnr) abort
if s:is_vim
" make sure lines event before changed event.
call coc#api#Buf_flush(a:bufnr)
endif
call s:Autocmd('TextChanged', a:bufnr, getbufvar(a:bufnr, 'changedtick'))
endfunction
function! s:HandleInsertLeave(bufnr) abort
call coc#pum#close()
call s:Autocmd('InsertLeave', a:bufnr)
endfunction
function! s:HandleWinScrolled(winid, event) abort
if getwinvar(a:winid, 'float', 0)
call coc#float#nvim_scrollbar(a:winid)
endif
if !empty(a:event)
let opt = get(a:event, 'all', {})
if get(opt, 'topline', 0) == 0 && get(opt, 'height', 0) == 0
" visible region not changed.
return
endif
for key in keys(a:event)
let winid = str2nr(key)
if winid != 0
let info = getwininfo(winid)
if !empty(info)
call s:Autocmd('WinScrolled', winid, info[0]['bufnr'], [info[0]['topline'], info[0]['botline']])
endif
endif
endfor
else
" v:event not exists on old version vim9
let info = getwininfo(a:winid)
if !empty(info)
call s:Autocmd('WinScrolled', a:winid, info[0]['bufnr'], [info[0]['topline'], info[0]['botline']])
endif
endif
endfunction
function! s:HandleWinClosed(winid) abort
call coc#float#on_close(a:winid)
call coc#notify#on_close(a:winid)
call s:Autocmd('WinClosed', 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:VimLeavePre() abort
let g:coc_vim_leaving = 1
call s:Autocmd('VimLeavePre')
if s:is_vim && exists('$COC_NVIM_REMOTE_ADDRESS')
" Helps to avoid connection error.
call coc#rpc#close_connection()
return
endif
if get(g:, 'coc_node_env', '') ==# 'test'
return
endif
if s:is_vim
call timer_start(1, { -> coc#client#kill('coc')})
endif
endfunction
function! s:VimEnter() abort
if coc#rpc#started()
if !exists('$COC_NVIM_REMOTE_ADDRESS')
call coc#rpc#notify('VimEnter', [join(coc#compat#list_runtime_paths(), ",")])
endif
elseif get(g:, 'coc_start_at_startup', 1)
call coc#rpc#start_server()
endif
call s:Highlight()
endfunction
function! s:Enable(initialize)
if get(g:, 'coc_enabled', 0) == 1
return
endif
let g:coc_enabled = 1
sign define CocCurrentLine linehl=CocMenuSel
sign define CocListCurrent linehl=CocListLine
sign define CocTreeSelected linehl=CocTreeSelected
if s:is_vim
call coc#api#Tabpage_ids()
endif
augroup coc_nvim
autocmd!
if !v:vim_did_enter
autocmd VimEnter * call s:VimEnter()
else
call s:Highlight()
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
autocmd CursorMoved list:///* call coc#list#select(bufnr('%'), line('.'))
autocmd TabNew * call coc#api#Tabpage_ids()
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
if exists('##CompleteChanged')
autocmd CompleteChanged * call timer_start(1, { -> execute('if pumvisible() | call coc#pum#close() | endif')})
endif
autocmd CursorHold * call coc#float#check_related()
if exists('##WinClosed')
autocmd WinClosed * call s:HandleWinClosed(+expand('<amatch>'))
elseif exists('##TabEnter')
autocmd TabEnter * call coc#notify#reflow()
endif
if exists('##WinScrolled')
autocmd WinScrolled * call s:HandleWinScrolled(+expand('<amatch>'), v:event)
endif
autocmd ModeChanged * call s:Autocmd('ModeChanged', v:event)
autocmd TabNew * call s:Autocmd('TabNew', coc#compat#tabnr_id(tabpagenr()))
autocmd TabClosed * call s:Autocmd('TabClosed', coc#compat#call('list_tabpages', []))
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(), coc#window#visible_range(win_getid()))
autocmd FileType * call s:Autocmd('FileType', expand('<amatch>'), +expand('<abuf>'))
autocmd InsertCharPre * call s:HandleCharInsert(v:char, bufnr('%'))
autocmd TextChangedP * call s:HandleTextChangedI('TextChangedP', +expand('<abuf>'))
autocmd TextChangedI * call s:HandleTextChangedI('TextChangedI', +expand('<abuf>'))
autocmd TextChanged * call s:HandleTextChanged(+expand('<abuf>'))
autocmd InsertLeave * call s:HandleInsertLeave(+expand('<abuf>'))
autocmd BufEnter * call s:HandleBufEnter(+expand('<abuf>'))
autocmd InsertEnter * call s:Autocmd('InsertEnter', +expand('<abuf>'))
autocmd BufHidden * call s:Autocmd('BufHidden', +expand('<abuf>'))
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('.')], win_getid())
autocmd CursorHoldI * call s:Autocmd('CursorHoldI', +expand('<abuf>'), [line('.'), col('.')], win_getid())
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 * call s: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:Highlight() | call s:Autocmd('ColorScheme')
augroup end
if a:initialize == 0
call coc#rpc#request('attach', [])
echohl MoreMsg
echom '[coc.nvim] Event enabled'
echohl None
endif
endfunction
function! s:StaticHighlight() abort
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 guisp=#ebdbb2
hi default CocBold term=bold cterm=bold gui=bold
hi default CocItalic term=italic cterm=italic gui=italic
hi default CocStrikeThrough term=strikethrough cterm=strikethrough gui=strikethrough
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 CocLink term=underline cterm=underline gui=underline guisp=#15aabf
hi default link CocFloatActive CocSearch
hi default link CocFadeOut Conceal
hi default link CocMarkdownCode markdownCode
hi default link CocMarkdownHeader markdownH1
hi default link CocDeprecatedHighlight CocStrikeThrough
hi default link CocUnusedHighlight CocFadeOut
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
" Notification
hi default CocNotificationProgress ctermfg=Blue guifg=#15aabf guibg=NONE
hi default link CocNotificationButton CocUnderline
hi default link CocNotificationKey Comment
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 CocPumDetail Comment
hi default link CocPumMenu CocFloating
hi default link CocPumShortcut Comment
hi default link CocPumDeprecated CocStrikeThrough
hi default CocVirtualText ctermfg=12 guifg=#504945
hi default link CocPumVirtualText CocVirtualText
hi default link CocInputBoxVirtualText CocVirtualText
hi default link CocFloatDividingLine CocVirtualText
if &t_Co == 256
hi def CocInlineVirtualText guifg=#808080 ctermfg=244
else
hi def CocInlineVirtualText guifg=#808080 ctermfg=12
endif
hi def link CocInlineAnnotation MoreMsg
endfunction
call s:StaticHighlight()
call s:AddAnsiGroups()
function! s:Highlight() abort
let normalFloat = s:is_vim ? 'Pmenu' : 'NormalFloat'
if coc#hlgroup#get_contrast('Normal', normalFloat) > 2.0
exe 'hi default CocFloating '.coc#hlgroup#create_bg_command('Normal', &background ==# 'dark' ? -30 : 30)
exe 'hi default CocMenuSel '.coc#hlgroup#create_bg_command('CocFloating', &background ==# 'dark' ? -20 : 20)
exe 'hi default CocFloatThumb '.coc#hlgroup#create_bg_command('CocFloating', &background ==# 'dark' ? -40 : 40)
hi default link CocFloatSbar CocFloating
else
exe 'hi default link CocFloating '.normalFloat
if coc#hlgroup#get_contrast('CocFloating', 'PmenuSel') > 2.0
exe 'hi default CocMenuSel '.coc#hlgroup#create_bg_command('CocFloating', &background ==# 'dark' ? -30 : 30)
else
exe 'hi default CocMenuSel '.coc#hlgroup#get_hl_command(synIDtrans(hlID('PmenuSel')), 'bg', '237', '#13354A')
endif
hi default link CocFloatThumb PmenuThumb
hi default link CocFloatSbar PmenuSbar
endif
exe 'hi default link CocFloatBorder ' .. (hlexists('FloatBorder') ? 'FloatBorder' : 'CocFloating')
if coc#hlgroup#get_contrast('Normal', 'CursorLine') < 1.3
" Avoid color too close
exe 'hi default CocListLine '.coc#hlgroup#create_bg_command('Normal', &background ==# 'dark' ? -20 : 20)
else
hi default link CocListLine CursorLine
endif
if !s:is_vim
hi default CocCursorTransparent gui=strikethrough blend=100
endif
let sign_colors = {
\ 'Error': ['Red', '#ff0000'],
\ 'Warn': ['Brown', '#ff922b'],
\ 'Info': ['Yellow', '#fab005'],
\ 'Hint': ['Blue', '#15aabf']
\ }
for name in ['Error', 'Warning', 'Info', 'Hint']
let suffix = name ==# 'Warning' ? 'Warn' : name
if hlexists('DiagnosticUnderline'.suffix)
exe 'hi default link Coc'.name.'Highlight DiagnosticUnderline'.suffix
else
exe 'hi default link Coc'.name.'Highlight CocUnderline'
endif
if hlexists('DiagnosticSign'.suffix)
exe 'hi default link Coc'.name.'Sign DiagnosticSign'.suffix
else
exe 'hi default Coc'.name.'Sign ctermfg='.sign_colors[suffix][0].' guifg='.sign_colors[suffix][1]
endif
if hlexists('DiagnosticVirtualText'.suffix)
exe 'hi default link Coc'.name.'VirtualText DiagnosticVirtualText'.suffix
else
call s:CreateHighlight('Coc'.name.'VirtualText', 'Coc'.name.'Sign', 'Normal')
endif
if hlexists('Diagnostic'.suffix)
exe 'hi default link Coc'.name.'Float Diagnostic'.suffix
else
call s:CreateHighlight('Coc'.name.'Float', 'Coc'.name.'Sign', 'CocFloating')
endif
endfor
call s:CreateHighlight('CocInlayHint', 'CocHintSign', 'SignColumn')
for name in ['Parameter', 'Type']
exe 'hi default link CocInlayHint'.name.' CocInlayHint'
endfor
if get(g:, 'coc_default_semantic_highlight_groups', 1)
let hlMap = {
\ 'TypeNamespace': ['@module', 'Include'],
\ 'TypeType': ['@type', 'Type'],
\ 'TypeClass': ['@constructor', 'Special'],
\ 'TypeEnum': ['@type', 'Type'],
\ 'TypeInterface': ['@type', 'Type'],
\ 'TypeStruct': ['@structure', 'Identifier'],
\ 'TypeTypeParameter': ['@variable.parameter', 'Identifier'],
\ 'TypeParameter': ['@variable.parameter', 'Identifier'],
\ 'TypeVariable': ['@variable', 'Identifier'],
\ 'TypeProperty': ['@property', 'Identifier'],
\ 'TypeEnumMember': ['@property', 'Constant'],
\ 'TypeEvent': ['@keyword', 'Keyword'],
\ 'TypeFunction': ['@function', 'Function'],
\ 'TypeMethod': ['@function.method', 'Function'],
\ 'TypeMacro': ['@constant.macro', 'Define'],
\ 'TypeKeyword': ['@keyword', 'Keyword'],
\ 'TypeModifier': ['@keyword.storage', 'StorageClass'],
\ 'TypeComment': ['@comment', 'Comment'],
\ 'TypeString': ['@string', 'String'],
\ 'TypeNumber': ['@number', 'Number'],
\ 'TypeBoolean': ['@boolean', 'Boolean'],
\ 'TypeRegexp': ['@string.regexp', 'String'],
\ 'TypeOperator': ['@operator', 'Operator'],
\ 'TypeDecorator': ['@string.special.symbol', 'Identifier'],
\ 'ModDeprecated': ['@markup.strikethrough', 'CocDeprecatedHighlight']
\ }
for [key, value] in items(hlMap)
let ts = get(value, 0, '')
let fallback = get(value, 1, '')
execute 'hi default link CocSem'.key.' '.(coc#hlgroup#valid(ts) ? ts : fallback)
endfor
endif
let symbolMap = {
\ 'Keyword': ['@keyword', 'Keyword'],
\ 'Namespace': ['@module', 'Include'],
\ 'Class': ['@constructor', 'Special'],
\ 'Method': ['@method', 'Function'],
\ 'Property': ['@property', 'Identifier'],
\ 'Text': ['@text', 'CocSymbolDefault'],
\ 'Unit': ['@unit', 'CocSymbolDefault'],
\ 'Value': ['@value', 'CocSymbolDefault'],
\ 'Snippet': ['@snippet', 'CocSymbolDefault'],
\ 'Color': ['@color', 'Float'],
\ 'Reference': ['@text.reference', 'Constant'],
\ 'Folder': ['@folder', 'CocSymbolDefault'],
\ 'File': ['@file', 'Statement'],
\ 'Module': ['@module', 'Statement'],
\ 'Package': ['@package', 'Statement'],
\ 'Field': ['@variable.member', 'Identifier'],
\ 'Constructor': ['@constructor', 'Special'],
\ 'Enum': ['@type', 'CocSymbolDefault'],
\ 'Interface': ['@type', 'CocSymbolDefault'],
\ 'Function': ['@function', 'Function'],
\ 'Variable': ['@variable.builtin', 'Special'],
\ 'Constant': ['@constant', 'Constant'],
\ 'String': ['@string', 'String'],
\ 'Number': ['@number', 'Number'],
\ 'Boolean': ['@boolean', 'Boolean'],
\ 'Array': ['@array', 'CocSymbolDefault'],
\ 'Object': ['@object', 'CocSymbolDefault'],
\ 'Key': ['@key', 'Identifier'],
\ 'Null': ['@null', 'Type'],
\ 'EnumMember': ['@property', 'Identifier'],
\ 'Struct': ['@structure', 'Keyword'],
\ 'Event': ['@constant', 'Constant'],
\ 'Operator': ['@operator', 'Operator'],
\ 'TypeParameter': ['@variable.parameter', 'Identifier'],
\ }
for [key, value] in items(symbolMap)
let hlGroup = coc#hlgroup#valid(value[0]) ? value[0] : get(value, 1, 'CocSymbolDefault')
if hlexists(hlGroup)
execute 'hi default CocSymbol'.key.' '.coc#hlgroup#get_hl_command(synIDtrans(hlID(hlGroup)), 'fg', '223', '#ebdbb2')
endif
endfor
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]) < 16 || (str2nr(ms[1]) == 16 && str2nr(ms[2]) < 18)
call add(lines, 'Error: Node version '.output.' < 16.18.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
function! s:CursorRangeFromSelected(type, ...) abort
" add range by operator
call coc#rpc#request('cursorsSelect', [bufnr('%'), 'operator', a:type])
endfunction
function! s:FormatFromSelected(type)
call CocActionAsync('formatSelected', a:type)
endfunction
function! s:CodeActionFromSelected(type)
call CocActionAsync('codeAction', a:type)
endfunction
function! s:CodeActionRefactorFromSelected(type)
call CocActionAsync('codeAction', a:type, ['refactor'] ,v:true)
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 CocPrintErrors :call coc#rpc#show_errors()
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)
augroup coc_dynamic_autocmd
autocmd!
augroup END
augroup coc_dynamic_content
autocmd!
augroup END
augroup coc_dynamic_option
autocmd!
augroup END
" Default key-mappings for completion
if empty(mapcheck('<C-n>', 'i'))
inoremap <silent><expr> <C-n> coc#pum#visible() ? coc#pum#next(1) : coc#inline#visible() ? coc#inline#next() : "\<C-n>"
endif
if empty(mapcheck('<C-p>', 'i'))
inoremap <silent><expr> <C-p> coc#pum#visible() ? coc#pum#prev(1) : coc#inline#visible() ? coc#inline#prev() : "\<C-p>"
endif
if empty(mapcheck('<down>', 'i'))
inoremap <silent><expr> <down> coc#pum#visible() ? coc#pum#next(0) : coc#inline#visible() ? coc#inline#next() :"\<down>"
endif
if empty(mapcheck('<up>', 'i'))
inoremap <silent><expr> <up> coc#pum#visible() ? coc#pum#prev(0) : coc#inline#visible() ? coc#inline#prev() :"\<up>"
endif
if empty(mapcheck('<C-e>', 'i'))
inoremap <silent><expr> <C-e> coc#pum#visible() ? coc#pum#cancel() : coc#inline#visible() ? coc#inline#cancel() : "\<C-e>"
endif
if empty(mapcheck('<C-y>', 'i'))
inoremap <silent><expr> <C-y> coc#pum#visible() ? coc#pum#confirm() : coc#inline#visible() ? coc#inline#accept() :"\<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>
vnoremap <Plug>(coc-codeaction-refactor-selected) :<C-u>call CocActionAsync('codeAction', visualmode(), ['refactor'], v:true)<CR>
nnoremap <Plug>(coc-codeaction-selected) :<C-u>set operatorfunc=<SID>CodeActionFromSelected<CR>g@
nnoremap <Plug>(coc-codeaction-refactor-selected) :<C-u>set operatorfunc=<SID>CodeActionRefactorFromSelected<CR>g@
nnoremap <Plug>(coc-codeaction) :<C-u>call CocActionAsync('codeAction', '')<CR>
nnoremap <Plug>(coc-codeaction-line) :<C-u>call CocActionAsync('codeAction', 'currline')<CR>
nnoremap <Plug>(coc-codeaction-cursor) :<C-u>call CocActionAsync('codeAction', 'cursor')<CR>
nnoremap <Plug>(coc-codeaction-refactor) :<C-u>call CocActionAsync('codeAction', 'cursor', ['refactor'], v:true)<CR>
nnoremap <Plug>(coc-codeaction-source) :<C-u>call CocActionAsync('codeAction', '', ['source'], v:true)<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>