Clean up Vim, make much simpler

This commit is contained in:
Anthony Rose 2023-08-29 10:49:48 +01:00
parent 0fc2aa3f1e
commit 5f21cf445c
301 changed files with 0 additions and 61555 deletions

View file

@ -1,10 +0,0 @@
{
"clangd.arguments": [
"--header-insertion=iwyu",
"--header-insertion-decorators",
"--suggest-missing-includes",
"--clang-tidy"
],
"coc.preferences.jumpCommand": "vsplit",
"powershell.integratedConsole.showOnStartup": false
}

View file

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

View file

@ -1,7 +0,0 @@
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

@ -1,845 +0,0 @@
<p align="center">
<a href="https://www.vim.org/scripts/script.php?script_id=5779">
<img alt="Logo" src="https://alfs.chigua.cn/dianyou/data/platform/default/20220525/coc.png" height="240" />
</a>
<p align="center">Make your Vim/Neovim as smart as VSCode</p>
<p align="center">
<a href="LICENSE.md"><img alt="Software License" src="https://img.shields.io/badge/license-Anti%20996-brightgreen.svg?style=flat-square"></a>
<a href="https://github.com/neoclide/coc.nvim/actions"><img alt="Actions" src="https://img.shields.io/github/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://gitter.im/neoclide/coc.nvim"><img alt="Gitter" src="https://img.shields.io/gitter/room/neoclide/coc.nvim.svg?style=flat-square"></a>
</p>
</p>
---
<img alt="Gif" src="https://alfs.chigua.cn/dianyou/data/platform/default/20220801/2022-08-01%2002-14-03.2022-08-01%2002_15_16.gif" 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 >= 8.1.1719 or Neovim >= 0.4.0.
Install [nodejs](https://nodejs.org/en/download/) >= 14.14:
```bash
curl -sL install-node.vercel.app/lts | bash
```
For [vim-plug](https://github.com/junegunn/vim-plug) users:
```vim
" Use release branch (recommend)
Plug 'neoclide/coc.nvim', {'branch': 'release'}
" Or build from source code by using yarn: https://yarnpkg.com
Plug 'neoclide/coc.nvim', {'branch': 'master', 'do': 'yarn install --frozen-lockfile'}
```
in your `.vimrc` or `init.vim`, then restart Vim and run `:PlugInstall`.
Checkout [Install
coc.nvim](https://github.com/neoclide/coc.nvim/wiki/Install-coc.nvim) for
more info.
You **have to** install coc extension or configure language servers for
LSP support.
Install extensions like:
:CocInstall coc-json coc-tsserver
Or configure language server in `coc-settings.json` opened by
`:CocConfig`, like:
```json
{
"languageserver": {
"go": {
"command": "gopls",
"rootPatterns": ["go.mod"],
"trace.server": "verbose",
"filetypes": ["go"]
}
}
}
```
Checkout 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 could change key mappings. Please use
command like`:verbose imap <tab>` to make sure that your keymap has taken effect.
```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')
" Update signature help on jump placeholder
autocmd User CocJumpPlaceholder call CocActionAsync('showSignatureHelp')
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
-- 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)."
})
-- Update signature help on jump placeholder
vim.api.nvim_create_autocmd("User", {
group = "CocGroup",
pattern = "CocJumpPlaceholder",
command = "call CocActionAsync('showSignatureHelp')",
desc = "Update signature help on jump placeholder"
})
-- 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 code actions affect whole buffer.
keyset("n", "<leader>as", "<Plug>(coc-codeaction-source)", opts)
-- Remap keys for applying codeActions to the current buffer
keyset("n", "<leader>ac", "<Plug>(coc-codeaction)", 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 [Gitter](https://gitter.im/neoclide/coc.nvim).
- 中文用户请到 [中文 gitter](https://gitter.im/neoclide/coc-cn) 讨论
## 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>
</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

@ -1,157 +0,0 @@
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:hide_pum = has('nvim-0.6.1') || has('patch-8.2.3389')
function! coc#expandable() abort
return coc#rpc#request('snippetCheck', [1, 0])
endfunction
function! coc#jumpable() abort
return coc#rpc#request('snippetCheck', [0, 1])
endfunction
function! coc#expandableOrJumpable() abort
return coc#rpc#request('snippetCheck', [1, 1])
endfunction
" add vim command to CocCommand list
function! coc#add_command(id, cmd, ...)
let config = {'id':a:id, 'cmd':a:cmd, 'title': get(a:,1,'')}
call add(g:coc_vim_commands, config)
if !coc#rpc#ready() | return | endif
call coc#rpc#notify('addCommand', [config])
endfunction
function! coc#on_enter()
call coc#rpc#notify('CocAutocmd', ['Enter', bufnr('%')])
return ''
endfunction
function! coc#_insert_key(method, key, ...) abort
let prefix = ''
if get(a:, 1, 1)
if coc#pum#visible()
let prefix = "\<C-r>=coc#pum#close()\<CR>"
elseif pumvisible() && s:hide_pum
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 coc#compat#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 fns = ['init', 'complete', 'should_complete', 'refresh', 'get_startcol', 'on_complete', 'on_enter']
let res = []
for fn in fns
if exists('*coc#source#'.a:name.'#'.fn)
call add(res, fn)
endif
endfor
return res
endfunction
function! coc#_do_complete(name, opt, cb) abort
let handler = 'coc#source#'.a:name.'#complete'
let l:Cb = {res -> a:cb(v:null, res)}
let args = [a:opt, l:Cb]
call call(handler, args)
endfunction

View file

@ -1,898 +0,0 @@
" ============================================================================
" Description: Client api used by vim8
" Author: Qiming Zhao <chemzqm@gmail.com>
" Licence: Anti 996 licence
" Last Modified: 2022-12-20
" ============================================================================
if has('nvim')
finish
endif
scriptencoding utf-8
let s:funcs = {}
let s:prop_offset = get(g:, 'coc_text_prop_offset', 1000)
let s:namespace_id = 1
let s:namespace_cache = {}
let s:max_src_id = 1000
" bufnr => max textprop id
let s:buffer_id = {}
" srcId => list of types
let s:id_types = {}
let s:tab_id = 1
let s:keymap_arguments = ['nowait', 'silent', 'script', 'expr', 'unique']
" helper {{
" Create a window with bufnr for execute win_execute
function! s:create_popup(bufnr) abort
noa let id = popup_create(1, {
\ 'line': 1,
\ 'col': &columns,
\ 'maxwidth': 1,
\ 'maxheight': 1,
\ })
call popup_hide(id)
return id
endfunction
function! s:check_bufnr(bufnr) abort
if !bufloaded(a:bufnr)
throw 'Invalid buffer id: '.a:bufnr
endif
endfunction
" TextChanged not fired when using channel on vim.
function! s:on_textchange(bufnr) abort
let event = mode() ==# 'i' ? 'TextChangedI' : 'TextChanged'
exe 'doautocmd <nomodeline> '.event.' '.bufname(a:bufnr)
endfunction
" execute command for bufnr
function! s:buf_execute(bufnr, cmds) abort
call s:check_bufnr(a:bufnr)
let winid = get(win_findbuf(a:bufnr), 0, -1)
let close = 0
if winid == -1
let winid = s:create_popup(a:bufnr)
let close = 1
endif
for cmd in a:cmds
call win_execute(winid, cmd, 'silent')
endfor
if close
noa call popup_close(winid)
endif
endfunction
function! s:check_winid(winid) abort
if empty(getwininfo(a:winid)) && empty(popup_getpos(a:winid))
throw 'Invalid window id: '.a:winid
endif
endfunction
function! s:is_popup(winid) abort
try
return !empty(popup_getpos(a:winid))
catch /^Vim\%((\a\+)\)\=:E993/
return 0
endtry
endfunction
function! s:tabid_nr(tid) abort
for nr in range(1, tabpagenr('$'))
if gettabvar(nr, '__tid', v:null) is a:tid
return nr
endif
endfor
throw 'Invalid tabpage id: '.a:tid
endfunction
function! s:tabnr_id(nr) abort
let tid = gettabvar(a:nr, '__tid', -1)
if tid == -1
let tid = s:tab_id
call settabvar(a:nr, '__tid', tid)
let s:tab_id = s:tab_id + 1
endif
return tid
endfunction
function! s:generate_id(bufnr) abort
let max = get(s:buffer_id, a:bufnr, s:prop_offset)
let id = max + 1
let s:buffer_id[a:bufnr] = id
return id
endfunction
function! s:win_execute(winid, cmd, ...) abort
let ref = get(a:000, 0, v:null)
let cmd = ref is v:null ? a:cmd : 'let ref["out"] = ' . a:cmd
call win_execute(a:winid, cmd)
endfunction
function! s:win_tabnr(winid) abort
let ref = {}
call win_execute(a:winid, 'let ref["out"] = tabpagenr()')
let tabnr = get(ref, 'out', -1)
if tabnr == -1
throw 'Invalid window id: '.a:winid
endif
return tabnr
endfunction
function! s:buf_line_count(bufnr) abort
if bufnr('%') == a:bufnr
return line('$')
endif
if exists('*getbufinfo')
let info = getbufinfo(a:bufnr)
if empty(info)
return 0
endif
" vim 8.1 has getbufinfo but no linecount
if has_key(info[0], 'linecount')
return info[0]['linecount']
endif
endif
return len(getbufline(a:bufnr, 1, '$'))
endfunction
function! s:execute(cmd)
if a:cmd =~# '^echo'
execute a:cmd
else
silent! execute a:cmd
endif
endfunction
function s:inspect_type(v) abort
let types = ['Number', 'String', 'Funcref', 'List', 'Dictionary', 'Float', 'Boolean', 'Null']
return get(types, type(a:v), 'Unknown')
endfunction
function! s:escape_space(text) abort
return substitute(a:text, ' ', '<space>', 'g')
endfunction
function! s:create_mode_prefix(mode, opts) abort
if a:mode ==# '!'
return 'map!'
endif
return get(a:opts, 'noremap', 0) ? a:mode . 'noremap' : a:mode . 'map'
endfunction
function! s:create_arguments(opts) abort
let arguments = ''
for key in keys(a:opts)
if a:opts[key] && index(s:keymap_arguments, key) != -1
let arguments .= '<'.key.'>'
endif
endfor
return arguments
endfunction
" }}"
" nvim client methods {{
function! s:funcs.set_current_dir(dir) abort
execute 'cd '.fnameescape(a:dir)
return v:null
endfunction
function! s:funcs.set_var(name, value) abort
execute 'let g:'.a:name.'= a:value'
return v:null
endfunction
function! s:funcs.del_var(name) abort
if !has_key(g:, a:name)
throw 'Key not found: '.a:name
endif
execute 'unlet g:'.a:name
return v:null
endfunction
function! s:funcs.set_option(name, value) abort
execute 'let &'.a:name.' = a:value'
return v:null
endfunction
function! s:funcs.get_option(name)
return eval('&'.a:name)
endfunction
function! s:funcs.set_current_buf(bufnr) abort
call s:check_bufnr(a:bufnr)
execute 'buffer '.a:bufnr
return v:null
endfunction
function! s:funcs.set_current_win(winid) abort
call s:win_tabnr(a:winid)
call win_gotoid(a:winid)
return v:null
endfunction
function! s:funcs.set_current_tabpage(tid) abort
let nr = s:tabid_nr(a:tid)
execute 'normal! '.nr.'gt'
return v:null
endfunction
function! s:funcs.list_wins() abort
return map(getwininfo(), 'v:val["winid"]')
endfunction
function! s:funcs.call_atomic(calls)
let results = []
for i in range(len(a:calls))
let [key, arglist] = a:calls[i]
let name = key[5:]
try
call add(results, call(s:funcs[name], arglist))
catch /.*/
return [results, [i, "VimException(".s:inspect_type(v:exception).")", v:exception . ' on function "'.name.'"']]
endtry
endfor
return [results, v:null]
endfunction
function! s:funcs.set_client_info(...) abort
" not supported
return v:null
endfunction
function! s:funcs.subscribe(...) abort
" not supported
return v:null
endfunction
function! s:funcs.unsubscribe(...) abort
" not supported
return v:null
endfunction
function! s:funcs.call_function(method, args) abort
return call(a:method, a:args)
endfunction
function! s:funcs.call_dict_function(dict, method, args) abort
if type(a:dict) == v:t_string
return call(a:method, a:args, eval(a:dict))
endif
return call(a:method, a:args, a:dict)
endfunction
function! s:funcs.command(command) abort
" command that could cause cursor vanish
if a:command =~# '^echo' || a:command =~# '^redraw' || a:command =~# '^sign place'
call timer_start(0, {-> s:execute(a:command)})
else
execute a:command
let err = get(g:, 'errmsg', '')
" get error from python script run.
if !empty(err)
unlet g:errmsg
throw err
endif
endif
endfunction
function! s:funcs.eval(expr) abort
return eval(a:expr)
endfunction
function! s:funcs.get_api_info()
let names = coc#api#func_names()
let channel = coc#rpc#get_channel()
if empty(channel)
throw 'Unable to get channel'
endif
return [ch_info(channel)['id'], {'functions': map(names, '{"name": "nvim_".v:val}')}]
endfunction
function! s:funcs.list_bufs()
return map(getbufinfo(), 'v:val["bufnr"]')
endfunction
function! s:funcs.feedkeys(keys, mode, escape_csi)
call feedkeys(a:keys, a:mode)
return v:null
endfunction
function! s:funcs.list_runtime_paths()
return globpath(&runtimepath, '', 0, 1)
endfunction
function! s:funcs.command_output(cmd)
return execute(a:cmd)
endfunction
function! s:funcs.exec(code, output) abort
let cmds = split(a:code, '\n')
if a:output
return substitute(execute(cmds, 'silent!'), '^\n', '', '')
endif
call execute(cmds)
return v:null
endfunction
" Queues raw user-input, <" is special. To input a literal "<", send <LT>.
function! s:funcs.input(keys) abort
let escaped = substitute(a:keys, '<', '\\<', 'g')
call feedkeys(eval('"'.escaped.'"'), 't')
return v:null
endfunction
function! s:funcs.create_buf(listed, scratch) abort
let bufnr = bufadd('')
call setbufvar(bufnr, '&buflisted', a:listed ? 1 : 0)
if a:scratch
call setbufvar(bufnr, '&modeline', 0)
call setbufvar(bufnr, '&buftype', 'nofile')
call setbufvar(bufnr, '&swapfile', 0)
endif
call bufload(bufnr)
return bufnr
endfunction
function! s:funcs.get_current_line()
return getline('.')
endfunction
function! s:funcs.set_current_line(line)
call setline('.', a:line)
call s:on_textchange(bufnr('%'))
return v:null
endfunction
function! s:funcs.del_current_line()
call deletebufline('%', line('.'))
call s:on_textchange(bufnr('%'))
return v:null
endfunction
function! s:funcs.get_var(var)
return get(g:, a:var, v:null)
endfunction
function! s:funcs.get_vvar(var)
return get(v:, a:var, v:null)
endfunction
function! s:funcs.get_current_buf()
return bufnr('%')
endfunction
function! s:funcs.get_current_win()
return win_getid()
endfunction
function! s:funcs.get_current_tabpage()
return s:tabnr_id(tabpagenr())
endfunction
function! s:funcs.list_tabpages()
let ids = []
for nr in range(1, tabpagenr('$'))
call add(ids, s:tabnr_id(nr))
endfor
return ids
endfunction
function! s:funcs.get_mode()
let m = mode()
return {'blocking': m ==# 'r' ? v:true : v:false, 'mode': m}
endfunction
function! s:funcs.strwidth(str)
return strwidth(a:str)
endfunction
function! s:funcs.out_write(str)
echon a:str
call timer_start(0, {-> s:execute('redraw')})
endfunction
function! s:funcs.err_write(str)
"echoerr a:str
endfunction
function! s:funcs.err_writeln(str)
echohl ErrorMsg
echom a:str
echohl None
call timer_start(0, {-> s:execute('redraw')})
endfunction
function! s:funcs.create_namespace(name) abort
if empty(a:name)
let id = s:namespace_id
let s:namespace_id = s:namespace_id + 1
return id
endif
let id = get(s:namespace_cache, a:name, 0)
if !id
let id = s:namespace_id
let s:namespace_id = s:namespace_id + 1
let s:namespace_cache[a:name] = id
endif
return id
endfunction
function! s:funcs.set_keymap(mode, lhs, rhs, opts) abort
let modekey = s:create_mode_prefix(a:mode, a:opts)
let arguments = s:create_arguments(a:opts)
let lhs = s:escape_space(a:lhs)
let rhs = empty(a:rhs) ? '<Nop>' : s:escape_space(a:rhs)
let cmd = modekey . ' ' . arguments .' '.lhs. ' '.rhs
execute cmd
return v:null
endfunction
function! s:funcs.del_keymap(mode, lhs) abort
let lhs = substitute(a:lhs, ' ', '<space>', 'g')
execute 'silent '.a:mode.'unmap '.lhs
return v:null
endfunction
" }}
" buffer methods {{
function! s:funcs.buf_set_option(bufnr, name, val)
let val = a:val
if val is v:true
let val = 1
elseif val is v:false
let val = 0
endif
call setbufvar(a:bufnr, '&'.a:name, val)
return v:null
endfunction
function! s:funcs.buf_get_option(bufnr, name)
call s:check_bufnr(a:bufnr)
return getbufvar(a:bufnr, '&'.a:name)
endfunction
function! s:funcs.buf_get_changedtick(bufnr)
return getbufvar(a:bufnr, 'changedtick')
endfunction
function! s:funcs.buf_is_valid(bufnr)
return bufexists(a:bufnr) ? v:true : v:false
endfunction
function! s:funcs.buf_is_loaded(bufnr)
return bufloaded(a:bufnr) ? v:true : v:false
endfunction
function! s:funcs.buf_get_mark(bufnr, name)
if a:bufnr != 0 && a:bufnr != bufnr('%')
throw 'buf_get_mark support current buffer only'
endif
return [line("'" . a:name), col("'" . a:name) - 1]
endfunction
function! s:funcs.buf_add_highlight(bufnr, srcId, hlGroup, line, colStart, colEnd, ...) abort
if a:srcId == 0
let srcId = s:max_src_id + 1
let s:max_src_id = srcId
else
let srcId = a:srcId
endif
let bufnr = a:bufnr == 0 ? bufnr('%') : a:bufnr
let type = srcId == -1 ? a:hlGroup : a:hlGroup.'_'.srcId
let types = get(s:id_types, srcId, [])
if index(types, type) == -1
call add(types, type)
let s:id_types[srcId] = types
if empty(prop_type_get(type))
call prop_type_add(type, extend({'highlight': a:hlGroup}, get(a:, 1, {})))
endif
endif
let end = a:colEnd == -1 ? strlen(get(getbufline(bufnr, a:line + 1), 0, '')) + 1 : a:colEnd + 1
if end < a:colStart + 1
return
endif
let id = s:generate_id(a:bufnr)
try
call prop_add(a:line + 1, a:colStart + 1, {'bufnr': bufnr, 'type': type, 'id': id, 'end_col': end})
catch /^Vim\%((\a\+)\)\=:E967/
" ignore 967
endtry
if a:srcId == 0
" return generated srcId
return srcId
endif
return v:null
endfunction
function! s:funcs.buf_clear_namespace(bufnr, srcId, startLine, endLine) abort
let bufnr = a:bufnr == 0 ? bufnr('%') : a:bufnr
let start = a:startLine + 1
let end = a:endLine == -1 ? len(getbufline(bufnr, 1, '$')) : a:endLine
if a:srcId == -1
if has_key(s:buffer_id, a:bufnr)
unlet s:buffer_id[a:bufnr]
endif
call prop_clear(start, end, {'bufnr' : bufnr})
else
for type in get(s:id_types, a:srcId, [])
try
call prop_remove({'bufnr': bufnr, 'all': 1, 'type': type}, start, end)
catch /^Vim\%((\a\+)\)\=:E968/
" ignore 968
endtry
endfor
endif
return v:null
endfunction
function! s:funcs.buf_line_count(bufnr) abort
call s:check_bufnr(a:bufnr)
return s:buf_line_count(a:bufnr)
endfunction
function! s:funcs.buf_attach(...)
" not supported
return 1
endfunction
function! s:funcs.buf_detach()
" not supported
return 1
endfunction
function! s:funcs.buf_get_lines(bufnr, start, end, strict) abort
call s:check_bufnr(a:bufnr)
let len = s:buf_line_count(a:bufnr)
let start = a:start < 0 ? len + a:start + 2 : a:start + 1
let end = a:end < 0 ? len + a:end + 1 : a:end
if a:strict && end > len
throw 'Index out of bounds '. end
endif
return getbufline(a:bufnr, start, end)
endfunction
function! s:funcs.buf_set_lines(bufnr, start, end, strict, ...) abort
call s:check_bufnr(a:bufnr)
let bufnr = a:bufnr == 0 ? bufnr('%') : a:bufnr
let len = s:buf_line_count(bufnr)
let startLnum = a:start < 0 ? len + a:start + 2 : a:start + 1
let endLnum = a:end < 0 ? len + a:end + 1 : a:end
if endLnum > len
if a:strict
throw 'Index out of bounds '. end
else
let endLnum = len
endif
endif
let delCount = endLnum - (startLnum - 1)
let view = bufnr == bufnr('%') ? winsaveview() : v:null
let replacement = get(a:, 1, [])
if delCount == len(replacement)
call setbufline(bufnr, startLnum, replacement)
else
if len(replacement)
call appendbufline(bufnr, startLnum - 1, replacement)
endif
if delCount
let start = startLnum + len(replacement)
silent call deletebufline(bufnr, start, start + delCount - 1)
endif
endif
if view isnot v:null
call winrestview(view)
endif
call s:on_textchange(a:bufnr)
return v:null
endfunction
function! s:funcs.buf_set_name(bufnr, name) abort
call s:check_bufnr(a:bufnr)
call s:buf_execute(a:bufnr, [
\ 'noa 0f',
\ 'file '.fnameescape(a:name)
\ ])
return v:null
endfunction
function! s:funcs.buf_get_name(bufnr)
call s:check_bufnr(a:bufnr)
return bufname(a:bufnr)
endfunction
function! s:funcs.buf_get_var(bufnr, name)
call s:check_bufnr(a:bufnr)
if !has_key(b:, a:name)
throw 'Key not found: '.a:name
endif
return getbufvar(a:bufnr, a:name)
endfunction
function! s:funcs.buf_set_var(bufnr, name, val)
call s:check_bufnr(a:bufnr)
call setbufvar(a:bufnr, a:name, a:val)
return v:null
endfunction
function! s:funcs.buf_del_var(bufnr, name)
call s:check_bufnr(a:bufnr)
if a:bufnr == bufnr('%')
execute 'unlet! b:'.a:name
else
call s:buf_execute(a:bufnr, ['unlet! b:'.a:name])
endif
return v:null
endfunction
function! s:funcs.buf_set_keymap(bufnr, mode, lhs, rhs, opts) abort
let modekey = s:create_mode_prefix(a:mode, a:opts)
let arguments = s:create_arguments(a:opts)
let lhs = s:escape_space(a:lhs)
let rhs = empty(a:rhs) ? '<Nop>' : s:escape_space(a:rhs)
let cmd = modekey . ' ' . arguments .'<buffer> '.lhs. ' '.rhs
if bufnr('%') == a:bufnr || a:bufnr == 0
execute cmd
else
call s:buf_execute(a:bufnr, [cmd])
endif
return v:null
endfunction
function! s:funcs.buf_del_keymap(bufnr, mode, lhs) abort
let lhs = substitute(a:lhs, ' ', '<space>', 'g')
let cmd = 'silent '.a:mode.'unmap <buffer> '.lhs
if bufnr('%') == a:bufnr || a:bufnr == 0
execute cmd
else
call s:buf_execute(a:bufnr, [cmd])
endif
return v:null
endfunction
" }}
" window methods {{
function! s:funcs.win_get_buf(winid)
call s:check_winid(a:winid)
return winbufnr(a:winid)
endfunction
function! s:funcs.win_set_buf(winid, bufnr) abort
call s:check_winid(a:winid)
call s:check_bufnr(a:bufnr)
call s:win_execute(a:winid, 'buffer '.a:bufnr)
return v:null
endfunction
function! s:funcs.win_get_position(winid) abort
let [row, col] = win_screenpos(a:winid)
if row == 0 && col == 0
throw 'Invalid window '.a:winid
endif
return [row - 1, col - 1]
endfunction
function! s:funcs.win_set_height(winid, height) abort
call s:check_winid(a:winid)
if s:is_popup(a:winid)
call popup_move(a:winid, {'maxheight': a:height, 'minheight': a:height})
else
call s:win_execute(a:winid, 'resize '.a:height)
endif
return v:null
endfunction
function! s:funcs.win_get_height(winid) abort
call s:check_winid(a:winid)
if s:is_popup(a:winid)
return popup_getpos(a:winid)['height']
endif
return winheight(a:winid)
endfunction
function! s:funcs.win_set_width(winid, width) abort
call s:check_winid(a:winid)
if s:is_popup(a:winid)
call popup_move(a:winid, {'maxwidth': a:width, 'minwidth': a:width})
else
call s:win_execute(a:winid, 'vertical resize '.a:width)
endif
return v:null
endfunction
function! s:funcs.win_get_width(winid) abort
call s:check_winid(a:winid)
if s:is_popup(a:winid)
return popup_getpos(a:winid)['width']
endif
return winwidth(a:winid)
endfunction
function! s:funcs.win_set_cursor(winid, pos) abort
call s:check_winid(a:winid)
let [line, col] = a:pos
call s:win_execute(a:winid, 'call cursor('.line.','.(col + 1).')')
return v:null
endfunction
function! s:funcs.win_get_cursor(winid) abort
call s:check_winid(a:winid)
let ref = {}
call s:win_execute(a:winid, "[line('.'), col('.')-1]", ref)
return get(ref, 'out', [1, 0])
endfunction
function! s:funcs.win_set_option(winid, name, value) abort
let tabnr = s:win_tabnr(a:winid)
let val = a:value
if val is v:true
let val = 1
elseif val is v:false
let val = 0
endif
call settabwinvar(tabnr, a:winid, '&'.a:name, val)
return v:null
endfunction
function! s:funcs.win_get_option(winid, name, ...) abort
let tabnr = s:win_tabnr(a:winid)
let result = gettabwinvar(tabnr, a:winid, '&'.a:name, get(a:, 1, v:null))
if result is v:null
throw "Invalid option name: '".a:name."'"
endif
return result
endfunction
function! s:funcs.win_get_var(winid, name, ...) abort
let tabnr = s:win_tabnr(a:winid)
return gettabwinvar(tabnr, a:winid, a:name, get(a:, 1, v:null))
endfunction
function! s:funcs.win_set_var(winid, name, value) abort
let tabnr = s:win_tabnr(a:winid)
call settabwinvar(tabnr, a:winid, a:name, a:value)
return v:null
endfunction
function! s:funcs.win_del_var(winid, name) abort
call s:check_winid(a:winid)
call win_execute(a:winid, 'unlet! w:'.a:name)
return v:null
endfunction
function! s:funcs.win_is_valid(winid) abort
let invalid = empty(getwininfo(a:winid)) && empty(popup_getpos(a:winid))
return invalid ? v:false : v:true
endfunction
" Not work for popup
function! s:funcs.win_get_number(winid) abort
if s:is_popup(a:winid)
return 0
endif
let info = getwininfo(a:winid)
if empty(info)
throw 'Invalid window id '.a:winid
endif
return info[0]['winnr']
endfunction
function! s:funcs.win_get_tabpage(winid) abort
let nr = s:win_tabnr(a:winid)
return s:tabnr_id(nr)
endfunction
function! s:funcs.win_close(winid, ...) abort
call s:check_winid(a:winid)
let force = get(a:, 1, 0)
if s:is_popup(a:winid)
call popup_close(a:winid)
else
call s:win_execute(a:winid, 'close'.(force ? '!' : ''))
endif
return v:null
endfunction
" }}
" tabpage methods {{
function! s:funcs.tabpage_get_number(tid)
return s:tabid_nr(a:tid)
endfunction
function! s:funcs.tabpage_list_wins(tid)
let nr = s:tabid_nr(a:tid)
return gettabinfo(nr)[0]['windows']
endfunction
function! s:funcs.tabpage_get_var(tid, name)
let nr = s:tabid_nr(a:tid)
return gettabvar(nr, a:name, v:null)
endfunction
function! s:funcs.tabpage_set_var(tid, name, value)
let nr = s:tabid_nr(a:tid)
call settabvar(nr, a:name, a:value)
return v:null
endfunction
function! s:funcs.tabpage_del_var(tid, name)
let nr = s:tabid_nr(a:tid)
call settabvar(nr, a:name, v:null)
return v:null
endfunction
function! s:funcs.tabpage_is_valid(tid)
for nr in range(1, tabpagenr('$'))
if gettabvar(nr, '__tid', -1) == a:tid
return v:true
endif
endfor
return v:false
endfunction
function! s:funcs.tabpage_get_win(tid)
let nr = s:tabid_nr(a:tid)
return win_getid(tabpagewinnr(nr), nr)
endfunction
" }}
function! coc#api#get_types(srcId) abort
return get(s:id_types, a:srcId, [])
endfunction
function! coc#api#get_id_types() abort
return s:id_types
endfunction
function! coc#api#create_type(srcId, hlGroup, opts) abort
let type = a:hlGroup.'_'.a:srcId
let types = get(s:id_types, a:srcId, [])
if index(types, type) == -1
call add(types, type)
let s:id_types[a:srcId] = types
let combine = get(a:opts, 'hl_mode', 'combine') ==# 'combine'
call prop_type_add(type, {'highlight': a:hlGroup, 'combine': combine})
endif
return type
endfunction
function! coc#api#func_names() abort
return keys(s:funcs)
endfunction
function! coc#api#call(method, args) abort
let err = v:null
let res = v:null
try
let res = call(s:funcs[a:method], a:args)
catch /.*/
let err = v:exception .' on api "'.a:method.'" '.json_encode(a:args)
endtry
return [err, res]
endfunction
function! coc#api#exec(method, args) abort
return call(s:funcs[a:method], a:args)
endfunction
function! coc#api#notify(method, args) abort
try
call call(s:funcs[a:method], a:args)
catch /.*/
call coc#rpc#notify('nvim_error_event', [0, v:exception.' on api "'.a:method.'" '.json_encode(a:args)])
endtry
endfunction
" create id for all tabpages
function! coc#api#tabpage_ids() abort
for nr in range(1, tabpagenr('$'))
if gettabvar(nr, '__tid', -1) == -1
call settabvar(nr, '__tid', s:tab_id)
let s:tab_id = s:tab_id + 1
endif
endfor
endfunction
function! coc#api#get_tabid(nr) abort
return s:tabnr_id(a:nr)
endfunction
" vim: set sw=2 ts=2 sts=2 et tw=78 foldmarker={{,}} foldmethod=marker foldlevel=0:

View file

@ -1,386 +0,0 @@
scriptencoding utf-8
let s:root = expand('<sfile>:h:h:h')
let s:is_vim = !has('nvim')
let s:is_win = has("win32") || has("win64")
let s:clients = {}
if get(g:, 'node_client_debug', 0)
echohl WarningMsg | echo '[coc.nvim] Enable g:node_client_debug could impact your vim experience' | echohl None
let $NODE_CLIENT_LOG_LEVEL = 'debug'
if exists('$NODE_CLIENT_LOG_FILE')
let s:logfile = resolve($NODE_CLIENT_LOG_FILE)
else
let s:logfile = tempname()
let $NODE_CLIENT_LOG_FILE = s:logfile
endif
endif
" create a client
function! coc#client#create(name, command)
let client = {}
let client['command'] = a:command
let client['name'] = a:name
let client['running'] = 0
let client['async_req_id'] = 1
let client['async_callbacks'] = {}
" vim only
let client['channel'] = v:null
" neovim only
let client['chan_id'] = 0
let client['start'] = function('s:start', [], client)
let client['request'] = function('s:request', [], client)
let client['notify'] = function('s:notify', [], client)
let client['request_async'] = function('s:request_async', [], client)
let client['on_async_response'] = function('s:on_async_response', [], client)
let s:clients[a:name] = client
return client
endfunction
function! s:start() dict
if self.running | return | endif
if !isdirectory(getcwd())
echoerr '[coc.nvim] Current cwd is not a valid directory.'
return
endif
let tmpdir = fnamemodify(tempname(), ':p:h')
if s:is_vim
if get(g:, 'node_client_debug', 0)
let file = tmpdir . '/coc.log'
call ch_logfile(file, 'w')
echohl MoreMsg | echo '[coc.nvim] channel log to '.file | echohl None
endif
let options = {
\ 'in_mode': 'json',
\ 'out_mode': 'json',
\ 'err_mode': 'nl',
\ 'err_cb': {channel, message -> s:on_stderr(self.name, split(message, "\n"))},
\ 'exit_cb': {channel, code -> s:on_exit(self.name, code)},
\ 'env': {
\ 'NODE_NO_WARNINGS': '1',
\ 'VIM_NODE_RPC': '1',
\ 'TMPDIR': tmpdir,
\ }
\}
if has("patch-8.1.350")
let options['noblock'] = 1
endif
let job = job_start(self.command, options)
let status = job_status(job)
if status !=# 'run'
let self.running = 0
echohl Error | echom 'Failed to start '.self.name.' service' | echohl None
return
endif
let self['running'] = 1
let self['channel'] = job_getchannel(job)
else
let original = {}
let opts = {
\ 'rpc': 1,
\ 'on_stderr': {channel, msgs -> s:on_stderr(self.name, msgs)},
\ 'on_exit': {channel, code -> s:on_exit(self.name, code)},
\ }
if has('nvim-0.5.0')
" could use env option
let opts['env'] = {
\ 'NODE_NO_WARNINGS': '1',
\ 'TMPDIR': tmpdir
\ }
else
let original = {
\ 'NODE_NO_WARNINGS': getenv('NODE_NO_WARNINGS'),
\ 'TMPDIR': getenv('TMPDIR'),
\ }
call setenv('NODE_NO_WARNINGS', '1')
call setenv('TMPDIR', tmpdir)
endif
let chan_id = jobstart(self.command, opts)
if !empty(original)
for key in keys(original)
call setenv(key, original[key])
endfor
endif
if chan_id <= 0
echohl Error | echom 'Failed to start '.self.name.' service' | echohl None
return
endif
let self['chan_id'] = chan_id
let self['running'] = 1
endif
endfunction
function! s:on_stderr(name, msgs)
if get(g:, 'coc_vim_leaving', 0) | return | endif
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]) < 14 || (str2nr(ms[1]) == 14 && str2nr(ms[2]) < 14)
let msgs = ['Current Node.js version '.trim(output).' < 14.14.0 ', 'Please upgrade your .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
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)
echohl Error | echon '[coc.nvim] use let g:node_client_debug = 1 in your vimrc to enable debug mode.' | echohl None
return
endif
execute 'vs '.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

@ -1,610 +0,0 @@
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

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

View file

@ -1,59 +0,0 @@
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'
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

@ -1,753 +0,0 @@
scriptencoding utf-8
let s:is_vim = !has('nvim')
let s:root = expand('<sfile>:h:h:h')
let s:prompt_win_bufnr = 0
let s:list_win_bufnr = 0
let s:prompt_win_width = get(g:, 'coc_prompt_win_width', 32)
let s:frames = ['· ', '·· ', '···', ' ··', ' ·', ' ']
let s:sign_group = 'PopUpCocDialog'
let s:detail_bufnr = 0
" Float window aside pum
function! coc#dialog#create_pum_float(lines, config) abort
let winid = coc#float#get_float_by_kind('pumdetail')
if empty(a:lines) || !coc#pum#visible()
if winid
call coc#float#close(winid)
endif
return
endif
let pumbounding = coc#pum#info()
let border = get(a:config, 'border', [])
let pw = pumbounding['width'] + (pumbounding['border'] ? 0 : get(pumbounding, 'scrollbar', 0))
let rp = &columns - pumbounding['col'] - pw
let showRight = pumbounding['col'] > rp ? 0 : 1
let maxWidth = showRight ? coc#math#min(rp - 1, a:config['maxWidth']) : coc#math#min(pumbounding['col'] - 1, a:config['maxWidth'])
let bh = get(border, 0 ,0) + get(border, 2, 0)
let maxHeight = &lines - pumbounding['row'] - &cmdheight - 1 - bh
if maxWidth <= 2 || maxHeight < 1
return v:null
endif
let width = 0
for line in a:lines
let dw = max([1, strdisplaywidth(line)])
let width = max([width, dw + 2])
endfor
let width = float2nr(coc#math#min(maxWidth, width))
let ch = coc#string#content_height(a:lines, width - 2)
let height = float2nr(coc#math#min(maxHeight, ch))
let lines = map(a:lines, {_, s -> s =~# '^─' ? repeat('─', width - 2 + (s:is_vim && ch > height ? -1 : 0)) : s})
let opts = {
\ 'lines': lines,
\ 'highlights': get(a:config, 'highlights', []),
\ 'relative': 'editor',
\ 'col': showRight ? pumbounding['col'] + pw : pumbounding['col'] - width,
\ 'row': pumbounding['row'],
\ 'height': height,
\ 'width': width - 2 + (s:is_vim && ch > height ? -1 : 0),
\ 'scrollinside': showRight ? 0 : 1,
\ 'codes': get(a:config, 'codes', []),
\ }
for key in ['border', 'highlight', 'borderhighlight', 'winblend', 'focusable', 'shadow', 'rounded']
if has_key(a:config, key)
let opts[key] = a:config[key]
endif
endfor
call s:close_auto_hide_wins(winid)
let result = coc#float#create_float_win(winid, s:detail_bufnr, opts)
if empty(result)
return
endif
let s:detail_bufnr = result[1]
call setwinvar(result[0], 'kind', 'pumdetail')
if !s:is_vim
call coc#float#nvim_scrollbar(result[0])
endif
endfunction
" Float window below/above cursor
function! coc#dialog#create_cursor_float(winid, bufnr, lines, config) abort
if coc#prompt#activated()
return v:null
endif
let pumAlignTop = get(a:config, 'pumAlignTop', 0)
let modes = get(a:config, 'modes', ['n', 'i', 'ic', 's'])
let mode = mode()
let currbuf = bufnr('%')
let pos = [line('.'), col('.')]
if index(modes, mode) == -1
return v:null
endif
if !s:is_vim && !has('nvim-0.5.0') && mode ==# 'i'
" helps to fix undo issue, don't know why.
call feedkeys("\<C-g>u", 'n')
endif
if mode ==# 's' && has('patch-8.2.4969') && !has('patch-8.2.4996')
echohl WarningMsg | echon 'Popup not created to avoid issue #10466 on vim >= 8.2.4969' | echohl None
return v:null
endif
let dimension = coc#dialog#get_config_cursor(a:lines, a:config)
if empty(dimension)
return v:null
endif
if coc#pum#visible() && ((pumAlignTop && dimension['row'] <0)|| (!pumAlignTop && dimension['row'] > 0))
return v:null
endif
let width = dimension['width']
let lines = map(a:lines, {_, s -> s =~# '^─' ? repeat('─', width) : s})
let config = extend(extend({'lines': lines, 'relative': 'cursor'}, a:config), dimension)
call s:close_auto_hide_wins(a:winid)
let res = coc#float#create_float_win(a:winid, a:bufnr, config)
if empty(res)
return v:null
endif
let alignTop = dimension['row'] < 0
let winid = res[0]
let bufnr = res[1]
redraw
if has('nvim')
call coc#float#nvim_scrollbar(winid)
endif
return [currbuf, pos, winid, bufnr, alignTop]
endfunction
" Use terminal buffer
function! coc#dialog#_create_prompt_vim(title, default, opts) abort
if !has('patch-8.2.0750')
throw 'Input box not supported on vim < 8.2.0750'
endif
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,
\ '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')
endif
let placeHolder = get(a:opts, 'placeHolder', '')
if empty(a:default) && !empty(placeHolder) && has('nvim-0.5.0')
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')
if !has('nvim-0.6.0')
redraw
endif
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
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
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 has('nvim')
call coc#float#nvim_scrollbar(ids[0])
endif
return [ids[0], ids[1], contentCount]
endfunction
" Create dialog at center of screen
function! coc#dialog#create_dialog(lines, config) abort
call s:close_auto_hide_wins()
" dialog always have borders
let title = get(a:config, 'title', '')
let buttons = get(a:config, 'buttons', [])
let highlight = get(a:config, 'highlight', 'CocFloating')
let borderhighlight = get(a:config, 'borderhighlight', [highlight])
let opts = {
\ 'title': title,
\ 'rounded': get(a:config, 'rounded', 0),
\ 'relative': 'editor',
\ 'border': [1,1,1,1],
\ 'close': get(a:config, 'close', 1),
\ 'highlight': highlight,
\ 'highlights': get(a:config, 'highlights', []),
\ 'buttons': buttons,
\ 'borderhighlight': borderhighlight,
\ 'getchar': get(a:config, 'getchar', 0)
\ }
call extend(opts, coc#dialog#get_config_editor(a:lines, a:config))
let bufnr = coc#float#create_buf(0, a:lines)
let res = coc#float#create_float_win(0, bufnr, opts)
if empty(res)
return
endif
if get(a:config, 'cursorline', 0)
call coc#dialog#place_sign(bufnr, 1)
endif
if has('nvim')
redraw
call coc#float#nvim_scrollbar(res[0])
endif
return res
endfunction
function! coc#dialog#prompt_confirm(title, cb) abort
call s:close_auto_hide_wins()
if s:is_vim && exists('*popup_dialog')
try
call popup_dialog(a:title. ' (y/n)?', {
\ 'highlight': 'Normal',
\ 'filter': 'popup_filter_yesno',
\ 'callback': {id, res -> a:cb(v:null, res)},
\ 'borderchars': get(g:, 'coc_borderchars', ['─', '│', '─', '│', '╭', '╮', '╯', '╰']),
\ 'borderhighlight': ['MoreMsg']
\ })
catch /.*/
call a:cb(v:exception)
endtry
return
endif
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
" call timer_start(3000, { -> term_sendkeys(bufnr, "\<C-u>\<C-k>abcd")})
call term_sendkeys(a:bufnr, "\<C-u>\<C-k>".a:value)
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 }])
if has('nvim-0.6.1')
call feedkeys("\<C-x>\<C-z>", 'in')
else
let g:coc_disable_space_report = 1
call feedkeys("\<space>\<bs>", 'in')
endif
execute 'noa set completeopt='.saved_completeopt
endif
endfunction
function! coc#dialog#change_loading(winid, loading) abort
if coc#float#valid(a:winid)
let winid = coc#float#get_related(a:winid, 'loading')
if !a:loading && winid > 0
call coc#float#close(winid)
endif
if a:loading && winid == 0
let bufnr = s:create_loading_buf()
if s:is_vim
let pos = popup_getpos(a:winid)
let winid = popup_create(bufnr, {
\ 'line': pos['line'] + 1,
\ 'col': pos['col'] + pos['width'] - 4,
\ 'maxheight': 1,
\ 'maxwidth': 3,
\ 'zindex': 999,
\ 'highlight': get(popup_getoptions(a:winid), 'highlight', 'CocFloating')
\ })
else
let pos = nvim_win_get_position(a:winid)
let width = nvim_win_get_width(a:winid)
let opts = {
\ 'relative': 'editor',
\ 'row': pos[0],
\ 'col': pos[1] + width - 3,
\ 'focusable': v:false,
\ 'width': 3,
\ 'height': 1,
\ 'style': 'minimal',
\ }
if has('nvim-0.5.1')
let opts['zindex'] = 900
endif
let winid = nvim_open_win(bufnr, v:false, opts)
call setwinvar(winid, '&winhl', getwinvar(a:winid, '&winhl'))
endif
call setwinvar(winid, 'kind', 'loading')
call setbufvar(bufnr, 'target_winid', a:winid)
call setbufvar(bufnr, 'popup', winid)
call coc#float#add_related(winid, a:winid)
endif
endif
endfunction
" Update list with new lines and highlights
function! coc#dialog#update_list(winid, bufnr, lines, highlights) abort
if coc#window#tabnr(a:winid) == tabpagenr()
if getwinvar(a:winid, 'auto_height', 0)
let row = coc#float#get_row(a:winid)
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 s:is_vim
call coc#compat#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)
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', 'CocFloating')],
\ }))
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

View file

@ -1,32 +0,0 @@
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

@ -1,148 +0,0 @@
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

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

View file

@ -1,466 +0,0 @@
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:match_ns = coc#highlight#create_namespace('list-match')
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', '--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
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
if exists('&cursorlineopt')
setl cursorlineopt=both
endif
if s:is_vim
setl nocursorline
else
setl cursorline
setl winhighlight=CursorLine:CocListLine
endif
if has('nvim-0.5.0') || has('patch-8.1.0864')
setl scrolloff=0
endif
setl filetype=list
syntax case ignore
let source = a:source[8:]
let name = toupper(source[0]).source[1:]
execute 'syntax match Coc'.name.'Line /\v^.*$/'
if !s:is_vim
" Repeat press <C-f> and <C-b> would invoke <esc> on vim
nnoremap <silent><nowait><buffer> <esc> <C-w>c
endif
endfunction
function! coc#list#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) abort
let winid = coc#list#get_preview()
if winid == -1
return
endif
if exists('*win_execute')
call win_execute(winid, "normal! ".(a:dir ==# 'up' ? "\<C-u>" : "\<C-d>"))
else
let id = win_getid()
noa call win_gotoid(winid)
execute "normal! ".(a:dir ==# 'up' ? "\<C-u>" : "\<C-d>")
noa call win_gotoid(id)
endif
endfunction
function! coc#list#close_preview(...) 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 coc#compat#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)
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 coc#compat#execute(a:winid, 'syn sync fromstart')
else
call coc#compat#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 coc#compat#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 coc#compat#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

@ -1,11 +0,0 @@
" 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

@ -1,539 +0,0 @@
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 = []
" 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', [])
let key = json_encode(extend({'lines': a:lines}, a:config))
let winid = s:find_win(key)
let kind = get(a:config, 'kind', '')
let row = 0
if winid != -1
let row = getwinvar(winid, 'top', 0)
call filter(s:winids, 'v:val != '.winid)
call coc#float#close(winid, 1)
let winid = v:null
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 - strwidth(actionText), 0])
let lines = lines + [repeat(' ', before).actionText]
let height = height + 1
call s:add_action_highlights(before, height - 1, highlights, actions)
endif
if row == 0
let wintop = coc#notify#get_top()
let row = wintop - height - (empty(border) ? 0 : 2) - 1
if !s:is_vim && !empty(border)
let row = row + 1
endif
endif
let col = &columns - margin - width
if s:is_vim && !empty(border)
let col = col - 2
endif
let winblend = 60
" Avoid animate for transparent background.
if get(a:config, 'winblend', 30) == 0 && empty(synIDattr(synIDtrans(hlID(get(opts, 'highlight', 'CocFloating'))), 'bg', 'gui'))
let winblend = 0
endif
call extend(opts, {
\ 'relative': 'editor',
\ 'width': width,
\ 'height': height,
\ 'col': col,
\ 'row': row + 1,
\ 'lines': lines,
\ 'rounded': 1,
\ 'highlights': highlights,
\ 'winblend': winblend,
\ 'border': border,
\ })
let result = coc#float#create_float_win(0, 0, opts)
if empty(result)
throw 'Unable to create notify window'
endif
let winid = result[0]
let bufnr = result[1]
call setwinvar(winid, 'right', 1)
call setwinvar(winid, 'kind', 'notification')
call setwinvar(winid, 'top', row)
call setwinvar(winid, 'key', key)
call setwinvar(winid, 'actions', actions)
call setwinvar(winid, 'source', get(a:config, 'source', ''))
call setwinvar(winid, '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 character = strpart(getline('.'), col('.') - 1, 1)
if character =~# '^\k'
let word = expand('<cword>')
let idx = index(actions, word)
if idx != -1
call coc#rpc#notify('FloatBtnClick', [winbufnr(a:winid), idx])
call coc#notify#close(a:winid)
endif
endif
endif
endfunction
function! coc#notify#on_close(winid) abort
if index(s:winids, a:winid) >= 0
call filter(s:winids, 'v:val != '.a:winid)
call coc#notify#reflow()
endif
endfunction
function! coc#notify#get_top() abort
let mintop = min(map(coc#notify#win_list(), 'coc#notify#get_win_top(v:val)'))
if mintop != 0
return mintop
endif
return &lines - &cmdheight - (&laststatus == 0 ? 0 : 1 )
endfunction
function! coc#notify#get_win_top(winid) abort
let row = getwinvar(a:winid, 'top', 0)
if row == 0
return row
endif
return row - (s:is_vim ? 0 : getwinvar(a:winid, '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)
call add(a:highlights, {
\ 'lnum': a:lnum,
\ 'hlGroup': 'CocNotificationButton',
\ 'colStart': colStart,
\ 'colEnd': colStart + w
\ })
let colStart = colStart + w + 1
endfor
endfunction
function! s:on_action(err, idx, winid) abort
if !empty(a:err)
throw a:err
endif
if a:idx > 0
call coc#rpc#notify('FloatBtnClick', [winbufnr(a:winid), a:idx - 1])
call coc#notify#close(a:winid)
endif
endfunction
function! s:cancel(winid, ...) abort
let name = get(a:, 1, 'timer')
let timer = coc#window#get_var(a:winid, name)
if !empty(timer)
call timer_stop(timer)
call coc#window#set_var(a:winid, name, v:null)
endif
endfunction
function! s:progress(winid, total, curr, index) abort
if !coc#float#valid(a:winid)
return
endif
if coc#window#visible(a:winid)
let total = a:total
let idx = float2nr(a:curr/5.0)%total
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
noa call setbufline(bufnr, 1, lines)
noa call deletebufline(bufnr, len(lines) + 1, '$')
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#highlight#compose_hlgroup('CocInfoSign', a:bg)}
endif
if a:kind ==# 'warning'
return {'text': s:warning_icon, 'hl': coc#highlight#compose_hlgroup('CocWarningSign', a:bg)}
endif
if a:kind ==# 'error'
return {'text': s:error_icon, 'hl': coc#highlight#compose_hlgroup('CocErrorSign', a:bg)}
endif
return v:null
endfunction
" percent should be float
function! s:get_props(from, to, percent) abort
let obj = {}
for key in keys(a:from)
let changed = a:to[key] - a:from[key]
if !s:is_vim && key ==# 'row'
" Could be float
let obj[key] = a:from[key] + changed * a:percent
else
let obj[key] = a:from[key] + float2nr(round(changed * a:percent))
endif
endfor
return obj
endfunction

View file

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

View file

@ -1,622 +0,0 @@
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
let s:inserted = 0
let s:virtual_text = 0
let s:virtual_text_ns = coc#highlight#create_namespace('pum-virtual')
let s:ignore = s:is_vim || has('nvim-0.5.0') ? "\<Ignore>" : "\<space>\<bs>"
let s:hide_pum = has('nvim-0.6.1') || has('patch-8.2.3389')
let s:virtual_text_support = has('nvim-0.5.0') || has('patch-9.0.0067')
" 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 && s:virtual_text_support
if empty(prop_type_get('CocPumVirtualText'))
call prop_type_add('CocPumVirtualText', {'highlight': 'CocPumVirtualText'})
endif
endif
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
function! coc#pum#close(...) abort
if coc#pum#visible()
let kind = get(a:, 1, '')
if kind ==# 'cancel'
let input = getwinvar(s:pum_winid, 'input', '')
let s:pum_index = -1
call s:insert_word(input, 1)
call s:on_pum_change(0)
doautocmd <nomodeline> TextChangedI
elseif kind ==# 'confirm'
let words = getwinvar(s:pum_winid, 'words', [])
if s:pum_index >= 0
let word = get(words, s:pum_index, '')
call s:insert_word(word, 1)
" have to restore here, so that TextChangedI can trigger indent.
call s:restore_indentkeys()
endif
doautocmd <nomodeline> TextChangedI
endif
call s:close_pum()
if !get(a:, 2, 0)
call coc#rpc#notify('CompleteStop', [kind])
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
call coc#pum#close('confirm')
endif
return ''
endfunction
function! coc#pum#_close() abort
if coc#pum#visible()
call s:close_pum()
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, "int")
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 coc#rpc#notify('CompleteStop', [''])
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
call s:select_by_index(a:index, a:insert)
if a:confirm
call coc#pum#close('confirm')
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 s:ignore
endfunction
function! s:get_height(winid) abort
if has('nvim')
return nvim_win_get_height(a:winid)
endif
return get(popup_getpos(a:winid), 'core_height', 0)
endfunction
function! s:scroll_pum(forward, height, size) abort
let topline = s:get_topline(s:pum_winid)
if !a:forward && topline == 1
if s:pum_index >= 0
call s:select_line(s:pum_winid, 1)
call s:on_pum_change(1)
endif
return
endif
if a:forward && topline + a:height - 1 >= a:size
if s:pum_index >= 0
call s:select_line(s:pum_winid, a:size)
call s:on_pum_change(1)
endif
return
endif
call coc#float#scroll_win(s:pum_winid, a:forward, a:height)
if s:pum_index >= 0
let lnum = s:pum_index + 1
let topline = s:get_topline(s:pum_winid)
if lnum >= topline && lnum <= topline + a:height - 1
return
endif
call s:select_line(s:pum_winid, topline)
call s:on_pum_change(1)
endif
endfunction
function! s:get_topline(winid) abort
if has('nvim')
let info = getwininfo(a:winid)[0]
return info['topline']
else
let pos = popup_getpos(a:winid)
return pos['firstline']
endif
endfunction
function! 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)
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 = 1
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
" The current line is wrong when use feedkeys.
if !s:is_vim
doautocmd <nomodeline> TextChangedP
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'
" 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
" should not be used on finish to have correct line.
if s:is_vim && !a:finish
call coc#pum#repalce(s:start_col + 1, a:word, 1)
else
let saved_completeopt = &completeopt
noa set completeopt=menu
noa call complete(s:start_col + 1, [{ 'empty': v:true, 'word': a:word }])
" exit complete state
if s:hide_pum
call feedkeys("\<C-x>\<C-z>", 'in')
else
let g:coc_disable_space_report = 1
call feedkeys("\<space>\<bs>", 'in')
endif
execute 'noa set completeopt='.saved_completeopt
endif
endif
endfunction
" Replace from col to cursor col with new characters
function! coc#pum#repalce(col, insert, ...) abort
let insert = a:insert
let curr = getline('.')
let removed = strpart(curr, a:col - 1, col('.') - a:col)
let n = strchars(removed)
let start = coc#string#common_start(insert, removed)
let event = get(a:, 1, 0)
if start > 0
let n = n - start
let insert = strcharpart(a:insert, start)
if empty(insert) && n == 0 && !event
let n = 1
let insert = coc#string#last_character(a:insert)
endif
endif
let keys = repeat("\<bs>", n).insert
if len(keys)
if event
let previous =strpart(curr, 0, a:col - 1)
call coc#rpc#notify('PumInsert', [previous.a:insert])
let g:coc_feeding_keys = 1
endif
call feedkeys(keys, 'int')
endif
endfunction
" create or update pum with lines, CompleteOption and config.
" return winid & dimension
function! coc#pum#create(lines, opt, config) abort
if mode() !=# 'i' || a:opt['line'] != line('.')
return
endif
let len = col('.') - a:opt['col'] - 1
if len < 0
return
endif
let input = len == 0 ? '' : strpart(getline('.'), a:opt['col'], len)
if input !=# a:opt['input']
return
endif
let config = s:get_pum_dimension(a:lines, a:opt['col'], a:config)
if empty(config)
return
endif
let s:reversed = get(a:config, 'reverse', 0) && config['row'] < 0
let s:virtual_text = s:virtual_text_support && a:opt['virtualText']
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']))
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 coc#compat#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']
redraw
call 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 s:clear_virtual_text()
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 coc#compat#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 s:clear_virtual_text()
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! s:clear_virtual_text() abort
if s:virtual_text_support
if s:is_vim
if s:prop_id != 0
call prop_remove({'id': s:prop_id})
endif
else
call nvim_buf_clear_namespace(bufnr('%'), s:virtual_text_ns, 0, -1)
endif
endif
endfunction
function! s:close_pum() abort
call s:clear_virtual_text()
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

@ -1,236 +0,0 @@
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/
" ignroe
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(globpath(&runtimepath, "", 0, 1), ",")
let data = [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()
autocmd! coc_dynamic_autocmd
autocmd! coc_dynamic_content
autocmd! coc_dynamic_option
call coc#rpc#request('detach', [])
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 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', [coc#util#path_replace_patterns(), join(globpath(&runtimepath, "", 0, 1), ",")])
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

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

View file

@ -1,210 +0,0 @@
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
function! coc#string#common_start(text, other) abort
let arr = split(a:text, '\zs')
let other = split(a:other, '\zs')
let total = min([len(arr), len(other)])
if total == 0
return 0
endif
for i in range(0, total - 1)
if arr[i] !=# other[i]
return i
endif
endfor
return total
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
" Get character count from start col and end col, 1 based
function! coc#string#get_char_count(text, start_col, end_col) abort
return strchars(strpart(a:text, a:start_col - 1, a:end_col - a:start_col))
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
" get change between two lines
function! coc#string#diff(curr, previous, col) abort
let end = strpart(a:curr, a:col - 1)
let start = strpart(a:curr, 0, a:col -1)
let endOffset = 0
let startOffset = 0
let currLen = strchars(a:curr)
let prevLen = strchars(a:previous)
if len(end)
let endLen = strchars(end)
for i in range(min([prevLen, endLen]))
if strcharpart(end, endLen - 1 - i, 1) ==# strcharpart(a:previous, prevLen -1 -i, 1)
let endOffset = endOffset + 1
else
break
endif
endfor
endif
let remain = endOffset == 0 ? a:previous : strcharpart(a:previous, 0, prevLen - endOffset)
if len(remain)
for i in range(min([strchars(remain), strchars(start)]))
if strcharpart(remain, i, 1) ==# strcharpart(start, i ,1)
let startOffset = startOffset + 1
else
break
endif
endfor
endif
return {
\ 'start': startOffset,
\ 'end': prevLen - endOffset,
\ 'text': strcharpart(a:curr, startOffset, currLen - startOffset - endOffset)
\ }
endfunction
function! coc#string#apply(content, diff) abort
let totalLen = strchars(a:content)
let endLen = totalLen - a:diff['end']
return strcharpart(a:content, 0, a:diff['start']).a:diff['text'].strcharpart(a:content, a:diff['end'], endLen)
endfunction
" insert inserted to line at position, use ... when result is too long
" line should only contains character has strwidth equals 1
function! coc#string#compose(line, position, inserted) abort
let width = strwidth(a:line)
let text = a:inserted
let res = a:line
let need_truncate = a:position + strwidth(text) + 1 > width
if need_truncate
let remain = width - a:position - 3
if remain < 2
" use text for full line, use first & end of a:line, ignore position
let res = strcharpart(a:line, 0, 1)
let w = strwidth(res)
for i in range(strchars(text))
let c = strcharpart(text, i, 1)
let a = strwidth(c)
if w + a <= width - 1
let w = w + a
let res = res . c
endif
endfor
let res = res.strcharpart(a:line, w)
else
let res = strcharpart(a:line, 0, a:position)
let w = strwidth(res)
for i in range(strchars(text))
let c = strcharpart(text, i, 1)
let a = strwidth(c)
if w + a <= width - 3
let w = w + a
let res = res . c
endif
endfor
let res = res.'..'
let w = w + 2
let res = res . strcharpart(a:line, w)
endif
else
let first = strcharpart(a:line, 0, a:position)
let res = first . text . strcharpart(a:line, a:position + strwidth(text))
endif
return res
endfunction

View file

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

View file

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

View file

@ -1,567 +0,0 @@
let s:is_vim = !has('nvim')
let s:is_win = has('win32') || has('win64')
let s:is_mac = has('mac')
let s:sign_api = exists('*sign_getplaced') && exists('*sign_place')
let s:sign_groups = []
let s:outline_preview_bufnr = 0
" Check <Tab> and <CR>
function! coc#ui#check_pum_keymappings(trigger) abort
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] + a:items)
call a:cb(v:null, res)
endif
endfunction
" cmd, cwd
function! coc#ui#open_terminal(opts) abort
if s:is_vim && !exists('*term_start')
echohl WarningMsg | echon "Your vim doesn't have terminal support!" | echohl None
return
endif
if get(a:opts, 'position', 'bottom') ==# 'bottom'
let p = '5new'
else
let p = 'vnew'
endif
execute 'belowright '.p.' +setl\ buftype=nofile '
setl buftype=nofile
setl winfixheight
setl norelativenumber
setl nonumber
setl bufhidden=wipe
if exists('#User#CocTerminalOpen')
exe 'doautocmd <nomodeline> User CocTerminalOpen'
endif
let cmd = get(a:opts, 'cmd', '')
let autoclose = get(a:opts, 'autoclose', 1)
if empty(cmd)
throw 'command required!'
endif
let cwd = get(a:opts, 'cwd', getcwd())
let keepfocus = get(a:opts, 'keepfocus', 0)
let bufnr = bufnr('%')
let Callback = get(a:opts, 'Callback', v:null)
function! s:OnExit(status) closure
let content = join(getbufline(bufnr, 1, '$'), "\n")
if a:status == 0 && autoclose == 1
execute 'silent! bd! '.bufnr
endif
if !empty(Callback)
call call(Callback, [a:status, bufnr, content])
endif
endfunction
if has('nvim')
call termopen(cmd, {
\ 'cwd': cwd,
\ 'on_exit': {job, status -> s:OnExit(status)},
\})
else
if s:is_win
let cmd = 'cmd.exe /C "'.cmd.'"'
endif
call term_start(cmd, {
\ 'cwd': cwd,
\ 'exit_cb': {job, status -> s:OnExit(status)},
\ 'curwin': 1,
\})
endif
if keepfocus
wincmd p
endif
return bufnr
endfunction
" run command in terminal
function! coc#ui#run_terminal(opts, cb)
let cmd = get(a:opts, 'cmd', '')
if empty(cmd)
return a:cb('command required for terminal')
endif
let opts = {
\ 'cmd': cmd,
\ 'cwd': 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#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
if exists('*bufadd') && exists('*bufload')
for file in a:files
let file = fnamemodify(file, ':.')
if bufloaded(file)
call add(bufnrs, bufnr(file))
else
let bufnr = bufadd(file)
call bufload(file)
call add(bufnrs, bufnr)
call setbufvar(bufnr, '&buflisted', 1)
endif
endfor
else
noa keepalt 1new +setl\ bufhidden=wipe
for file in a:files
let file = fnamemodify(file, ':.')
execute 'noa edit +setl\ bufhidden=hide '.fnameescape(file)
if &filetype ==# ''
filetype detect
endif
call add(bufnrs, bufnr('%'))
endfor
noa close
endif
doautocmd BufEnter
return bufnrs
endfunction
function! coc#ui#echo_lines(lines)
echo join(a:lines, "\n")
endfunction
function! coc#ui#echo_signatures(signatures) abort
if pumvisible() | return | endif
echo ""
for i in range(len(a:signatures))
call s:echo_signature(a:signatures[i])
if i != len(a:signatures) - 1
echon "\n"
endif
endfor
endfunction
function! s:echo_signature(parts)
for part in a:parts
let hl = get(part, 'type', 'Normal')
let text = get(part, 'text', '')
if !empty(text)
execute 'echohl '.hl
execute "echon '".substitute(text, "'", "''", 'g')."'"
echohl None
endif
endfor
endfunction
function! coc#ui#iterm_open(dir)
return s:osascript(
\ 'if application "iTerm2" is not running',
\ 'error',
\ 'end if') && s:osascript(
\ 'tell application "iTerm2"',
\ 'tell current window',
\ 'create tab with default profile',
\ 'tell current session',
\ 'write text "cd ' . a:dir . '"',
\ 'write text "clear"',
\ 'activate',
\ 'end tell',
\ 'end tell',
\ 'end tell')
endfunction
function! s:osascript(...) abort
let args = join(map(copy(a:000), '" -e ".shellescape(v:val)'), '')
call s:system('osascript'. args)
return !v:shell_error
endfunction
function! s:system(cmd)
let output = system(a:cmd)
if v:shell_error && output !=# ""
echohl Error | echom output | echohl None
return
endif
return output
endfunction
function! coc#ui#set_lines(bufnr, changedtick, original, replacement, start, end, changes, cursor, col) abort
if !bufloaded(a:bufnr)
return
endif
let delta = 0
if !empty(a:col)
let delta = col('.') - a:col
endif
if getbufvar(a:bufnr, 'changedtick') > a:changedtick && bufnr('%') == a:bufnr
" try apply current line change
let lnum = line('.')
" change for current line
if a:end - a:start == 1 && a:end == lnum && len(a:replacement) == 1
let idx = a:start - lnum + 1
let previous = get(a:original, idx, 0)
if type(previous) == 1
let content = getline('.')
if previous !=# content
let diff = coc#string#diff(content, previous, col('.'))
let changed = get(a:replacement, idx, 0)
if type(changed) == 1 && strcharpart(previous, 0, diff['end']) ==# strcharpart(changed, 0, diff['end'])
let applied = coc#string#apply(changed, diff)
let replacement = copy(a:replacement)
let replacement[idx] = applied
call coc#compat#buf_set_lines(a:bufnr, a:start, a:end, replacement)
return
endif
endif
endif
endif
endif
if exists('*nvim_buf_set_text') && !empty(a:changes)
for item in reverse(copy(a:changes))
call nvim_buf_set_text(a:bufnr, item[1], item[2], item[3], item[4], item[0])
endfor
else
call coc#compat#buf_set_lines(a:bufnr, a:start, a:end, a:replacement)
endif
if !empty(a:cursor)
call cursor(a:cursor[0], a:cursor[1] + delta)
endif
endfunction
function! coc#ui#change_lines(bufnr, list) abort
if !bufloaded(a:bufnr) | return v:null | endif
undojoin
if exists('*setbufline')
for [lnum, line] in a:list
call setbufline(a:bufnr, lnum + 1, line)
endfor
elseif a:bufnr == bufnr('%')
for [lnum, line] in a:list
call setline(lnum + 1, line)
endfor
else
let bufnr = bufnr('%')
exe 'noa buffer '.a:bufnr
for [lnum, line] in a:list
call setline(lnum + 1, line)
endfor
exe 'noa buffer '.bufnr
endif
endfunction
function! coc#ui#open_url(url)
if 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 bufnr = bufnr(a:oldPath)
if bufnr == -1
throw 'Unable to get bufnr of '.a:oldPath
endif
if a:oldPath =~? a:newPath && (s:is_mac || s:is_win)
return coc#ui#safe_rename(bufnr, a:oldPath, a:newPath, a:write)
endif
if bufloaded(a:newPath)
execute 'silent bdelete! '.bufnr(a:newPath)
endif
let current = bufnr == bufnr('%')
let bufname = fnamemodify(a:newPath, ":~:.")
let filepath = fnamemodify(bufname(bufnr), '%:p')
let winid = coc#compat#buf_win_id(bufnr)
let curr = -1
if winid == -1
let curr = win_getid()
let file = fnamemodify(bufname(bufnr), ':.')
execute 'keepalt tab drop '.fnameescape(bufname(bufnr))
let winid = win_getid()
endif
call coc#compat#execute(winid, 'keepalt file '.fnameescape(bufname), 'silent')
call coc#compat#execute(winid, 'doautocmd BufEnter')
if a:write
call coc#compat#execute(winid, 'noa write!', 'silent')
call delete(filepath, '')
endif
if curr != -1
call win_gotoid(curr)
endif
return bufnr
endfunction
" System is case in sensitive and newPath have different case.
function! coc#ui#safe_rename(bufnr, oldPath, newPath, write) abort
let winid = win_getid()
let lines = getbufline(a:bufnr, 1, '$')
execute 'keepalt tab drop '.fnameescape(fnamemodify(a:oldPath, ':.'))
let view = winsaveview()
execute 'keepalt bwipeout! '.a:bufnr
if a:write
call delete(a:oldPath, '')
endif
execute 'keepalt edit '.fnameescape(fnamemodify(a:newPath, ':~:.'))
let bufnr = bufnr('%')
call coc#compat#buf_set_lines(bufnr, 0, -1, lines)
if a:write
execute 'noa write'
endif
call winrestview(view)
call win_gotoid(winid)
return bufnr
endfunction
function! coc#ui#sign_unplace() abort
if exists('*sign_unplace')
for group in s:sign_groups
call sign_unplace(group)
endfor
endif
endfunction
function! coc#ui#update_signs(bufnr, group, signs) abort
if !s:sign_api || !bufloaded(a:bufnr)
return
endif
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 coc#compat#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 a:cmd.' 'bufname
catch /.*/
if bufname('%') != bufname
throw v:exception
endif
endtry
endfunction
" Use noa to setloclist, avoid BufWinEnter autocmd
function! coc#ui#setloclist(nr, items, action, title) abort
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': a:items})
else
noa call setloclist(a:nr, [], a:action, {'title': a:title, 'items': a:items})
endif
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#util#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 coc#compat#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

@ -1,659 +0,0 @@
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 = 34
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#setline(lnum, line)
keepjumps call setline(a:lnum, a:line)
endfunction
function! coc#util#path_replace_patterns() abort
if has('win32unix') && exists('g:coc_cygqwin_path_prefixes')
echohl WarningMsg
echon 'g:coc_cygqwin_path_prefixes is deprecated, use g:coc_uri_prefix_replace_patterns instead'
echohl None
return g:coc_cygqwin_path_prefixes
endif
if exists('g:coc_uri_prefix_replace_patterns')
return g:coc_uri_prefix_replace_patterns
endif
return v:null
endfunction
function! coc#util#version()
if s:is_vim
return string(v:versionlong)
endif
let c = execute('silent version')
let lines = split(matchstr(c, 'NVIM v\zs[^\n-]*'))
return lines[0]
endfunction
function! coc#util#check_refresh(bufnr)
if !bufloaded(a:bufnr)
return 0
endif
if getbufvar(a:bufnr, 'coc_diagnostic_disable', 0)
return 0
endif
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#open_file(cmd, file)
execute a:cmd .' '.fnameescape(fnamemodify(a:file, ':~:.'))
return bufnr('%')
endfunction
function! coc#util#job_command()
if (has_key(g:, 'coc_node_path'))
let node = expand(g:coc_node_path)
else
let node = $COC_NODE_PATH == '' ? 'node' : $COC_NODE_PATH
endif
if !executable(node)
echohl Error | echom '[coc.nvim] "'.node.'" is not executable, checkout https://nodejs.org/en/download/' | echohl None
return
endif
if !filereadable(s:root.'/build/index.js')
if isdirectory(s:root.'/src')
echohl Error | echom '[coc.nvim] build/index.js not found, please install dependencies and compile coc.nvim by: yarn install' | echohl None
else
echohl Error | echon '[coc.nvim] your coc.nvim is broken.' | echohl None
endif
return
endif
return [node] + get(g:, 'coc_node_args', ['--no-warnings']) + [s:root.'/build/index.js']
endfunction
function! coc#util#jump(cmd, filepath, ...) abort
if a:cmd != 'pedit'
silent! normal! m'
endif
let path = a:filepath
if has('win32unix')
let path = substitute(a:filepath, '\v\\', '/', 'g')
endif
let file = fnamemodify(path, ":~:.")
if a:cmd ==# 'pedit'
let extra = empty(get(a:, 1, [])) ? '' : '+'.(a:1[0] + 1)
exe 'pedit '.extra.' '.fnameescape(file)
return
elseif a:cmd ==# 'drop'
let dstbuf = bufadd(path)
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
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'
let saved = &wildignore
set wildignore=
execute a:cmd.' '.fnameescape(a:file)
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
function! coc#util#vim_info()
return {
\ 'root': s:root,
\ 'apiversion': s:vim_api_version,
\ 'mode': mode(),
\ 'config': get(g:, 'coc_user_config', {}),
\ 'floating': has('nvim') && exists('*nvim_open_win') ? v:true : v:false,
\ 'extensionRoot': coc#util#extension_root(),
\ 'globalExtensions': get(g:, 'coc_global_extensions', []),
\ 'lines': &lines,
\ 'columns': &columns,
\ 'cmdheight': &cmdheight,
\ 'pid': coc#util#getpid(),
\ 'filetypeMap': get(g:, 'coc_filetype_map', {}),
\ 'version': coc#util#version(),
\ 'pumevent': 1,
\ 'isVim': has('nvim') ? v:false : v:true,
\ 'isCygwin': has('win32unix') ? v:true : v:false,
\ 'isMacvim': has('gui_macvim') ? v:true : v:false,
\ 'isiTerm': $TERM_PROGRAM ==# "iTerm.app",
\ 'colorscheme': get(g:, 'colors_name', ''),
\ 'workspaceFolders': get(g:, 'WorkspaceFolders', v:null),
\ 'background': &background,
\ 'runtimepath': join(globpath(&runtimepath, '', 0, 1), ','),
\ 'locationlist': get(g:,'coc_enable_locationlist', 1),
\ 'progpath': v:progpath,
\ 'guicursor': &guicursor,
\ 'pumwidth': exists('&pumwidth') ? &pumwidth : 15,
\ 'tabCount': tabpagenr('$'),
\ 'updateHighlight': has('nvim-0.5.0') || has('textprop') ? v:true : v:false,
\ 'vimCommands': get(g:, 'coc_vim_commands', []),
\ 'sign': exists('*sign_place') && exists('*sign_unplace'),
\ 'ambiguousIsNarrow': &ambiwidth ==# 'single' ? v:true : v:false,
\ 'textprop': has('textprop') ? v:true : v:false,
\ 'virtualText': has('nvim-0.5.0') || has('patch-9.0.0067') ? v:true : v:false,
\ 'dialog': 1,
\ 'semanticHighlights': coc#util#semantic_hlgroups()
\}
endfunction
function! coc#util#all_state()
return {
\ 'bufnr': bufnr('%'),
\ 'winid': win_getid(),
\ 'bufnrs': map(getbufinfo({'bufloaded': 1}),'v:val["bufnr"]'),
\ 'winids': map(getwininfo(),'v:val["winid"]'),
\ }
endfunction
function! coc#util#install() abort
let yarncmd = get(g:, 'coc_install_yarn_cmd', executable('yarnpkg') ? 'yarnpkg' : 'yarn')
call coc#ui#open_terminal({
\ 'cwd': s:root,
\ 'cmd': yarncmd.' install --frozen-lockfile --ignore-engines',
\ 'autoclose': 0,
\ })
endfunction
function! coc#util#extension_root() abort
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#unmap(bufnr, keys) abort
if bufnr('%') == a:bufnr
for key in a:keys
exe 'silent! nunmap <buffer> '.key
endfor
endif
endfunction
function! coc#util#refactor_foldlevel(lnum) abort
if a:lnum <= 2 | return 0 | endif
let line = getline(a:lnum)
if line =~# '^\%u3000\s*$' | return 0 | endif
return 1
endfunction
function! coc#util#refactor_fold_text(lnum) abort
let range = ''
let info = get(b:line_infos, a:lnum, [])
if !empty(info)
let range = info[0].':'.info[1]
endif
return trim(getline(a:lnum)[3:]).' '.range
endfunction
" get tabsize & expandtab option
function! coc#util#get_format_opts(bufnr) abort
let bufnr = a:bufnr && bufloaded(a:bufnr) ? a:bufnr : bufnr('%')
let tabsize = getbufvar(bufnr, '&shiftwidth')
if tabsize == 0
let tabsize = getbufvar(bufnr, '&tabstop')
endif
return {
\ 'tabsize': tabsize,
\ 'expandtab': getbufvar(bufnr, '&expandtab'),
\ 'insertFinalNewline': getbufvar(bufnr, '&eol'),
\ 'trimTrailingWhitespace': getbufvar(bufnr, 'coc_trim_trailing_whitespace', 0),
\ 'trimFinalNewlines': getbufvar(bufnr, 'coc_trim_final_newlines', 0)
\ }
endfunction
function! coc#util#get_editoroption(winid) abort
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
let tabSize = getbufvar(bufnr, '&shiftwidth')
if tabSize == 0
let tabSize = getbufvar(bufnr, '&tabstop')
endif
return {
\ 'bufnr': bufnr,
\ 'winid': a:winid,
\ 'tabpageid': coc#util#tabnr_id(info['tabnr']),
\ 'winnr': winnr(),
\ 'visibleRanges': s:visible_ranges(a:winid),
\ 'tabSize': tabSize,
\ 'insertSpaces': getbufvar(bufnr, '&expandtab') ? v:true : v:false
\ }
endfunction
function! coc#util#tabnr_id(tabnr) abort
return s:is_vim ? coc#api#get_tabid(a:tabnr) : nvim_list_tabpages()[a:tabnr - 1]
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
let bufname = bufname(bufnr)
call add(result, {
\ 'winid': info['winid'],
\ 'bufnr': bufnr,
\ 'tabid': coc#util#tabnr_id(info['tabnr']),
\ 'fullpath': empty(bufname) ? '' : fnamemodify(bufname, ':p'),
\ })
endif
endfor
return result
endfunction
function! coc#util#tabpages() abort
if s:is_vim
return coc#api#exec('list_tabpages', [])
endif
return nvim_list_tabpages()
endfunction
function! coc#util#getpid()
if !has('win32unix')
return getpid()
endif
let cmd = 'cat /proc/' . getpid() . '/winpid'
return substitute(system(cmd), '\v\n', '', 'gi')
endfunction
" Get indentkeys for indent on TextChangedP, consider = for word indent only.
function! coc#util#get_indentkeys() abort
if empty(&indentexpr)
return ''
endif
if &indentkeys !~# '='
return ''
endif
return &indentkeys
endfunction
function! coc#util#get_bufoptions(bufnr, max) abort
if !bufloaded(a:bufnr) | return v:null | endif
let bufname = bufname(a:bufnr)
let buftype = getbufvar(a:bufnr, '&buftype')
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,
\ 'size': size,
\ 'lines': lines,
\ 'winid': bufwinid(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': empty(bufname) ? '' : fnamemodify(bufname, ':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()
if !empty(get(g:, 'coc_config_home', ''))
return resolve(expand(g:coc_config_home))
endif
if exists('$VIMCONFIG')
return resolve($VIMCONFIG)
endif
if has('nvim')
if exists('$XDG_CONFIG_HOME')
return resolve($XDG_CONFIG_HOME."/nvim")
endif
if s:is_win
return resolve($HOME.'/AppData/Local/nvim')
endif
return resolve($HOME.'/.config/nvim')
else
if s:is_win
return resolve($HOME."/vimfiles")
endif
return resolve($HOME.'/.vim')
endif
endfunction
function! coc#util#get_data_home()
if get(g:, 'coc_node_env', '') ==# 'test'
return $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')
let dir = resolve($XDG_CONFIG_HOME."/coc")
else
if s:is_win
let dir = resolve(expand('~/AppData/Local/coc'))
else
let dir = resolve(expand('~/.config/coc'))
endif
endif
endif
if !isdirectory(dir)
call coc#notify#create(['creating coc.nvim data directory: '.dir], {
\ 'borderhighlight': 'CocInfoSign',
\ 'timeout': 5000,
\ 'kind': 'info',
\ })
call mkdir(dir, "p", 0755)
endif
return dir
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
" used by vim
function! coc#util#get_buf_lines(bufnr, changedtick)
if !bufloaded(a:bufnr)
return v:null
endif
let changedtick = getbufvar(a:bufnr, 'changedtick')
if changedtick == a:changedtick
return v:null
endif
return {
\ 'lines': getbufline(a:bufnr, 1, '$'),
\ 'changedtick': getbufvar(a:bufnr, 'changedtick')
\ }
endfunction
" used for TextChangedI with InsertCharPre
function! coc#util#get_changeinfo(bufnr)
if bufnr('%') == a:bufnr
return {
\ 'lnum': line('.'),
\ 'line': getline('.'),
\ 'changedtick': b:changedtick,
\}
endif
let winid = bufwinid(a:bufnr)
if winid != -1
let ref = {}
call win_execute(winid, 'let ref = {"lnum": line("."), "line": getline("."), "changedtick": b:changedtick}')
return ref
endif
return v:null
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

View file

@ -1,91 +0,0 @@
let s:is_vim = !has('nvim')
let s:virtual_text_support = has('nvim-0.5.0') || has('patch-9.0.0067')
let s:text_options = has('patch-9.0.0121') || has('nvim-0.6.0')
let s:vim_above = has('patch-9.0.0438')
" This function is called by buffer.setVirtualText
" opts.hl_mode default to 'combine'.
" opts.col vim only, no support on neovim, 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, src_id, line, blocks, opts) abort
if !s:virtual_text_support
return
endif
let align = get(a:opts, 'text_align', 'after')
let indent = ''
if get(a:opts, 'indent', 0)
let indent = matchstr(getline(a:line + 1), '^\s\+')
endif
if s:is_vim
let column = get(a:opts, 'col', 0)
if !has_key(a:opts, 'col') && align ==# 'after'
" add a whitespace, same as neovim.
let indent = ' '
endif
let blocks = a:blocks
if !empty(a:blocks) && (align ==# 'above' || align ==# 'below')
" only first highlight can be used
let hl = a:blocks[0][1]
let text = join(map(copy(a:blocks), "v:val[0]"), '')
let blocks = [[text, hl]]
let column = 0
endif
let first = 1
let base = s:get_option_vim(align, column, get(a:opts, 'text_wrap', 'truncate'))
for [text, hl] in blocks
let type = coc#api#create_type(a:src_id, hl, a:opts)
let opts = extend({ 'text': text, 'type': type }, base)
if first && !empty(indent)
let opts['text'] = indent . text
endif
call prop_add(a:line + 1, column, opts)
let first = 0
endfor
else
let opts = { 'hl_mode': get(a:opts, 'hl_mode', 'combine') }
if s:text_options
if align ==# 'above' || align ==# 'below'
let blocks = empty(indent) ? a:blocks : [[indent, 'Normal']] + a:blocks
let opts['virt_lines'] = [blocks]
if align ==# 'above'
let opts['virt_lines_above'] = v:true
endif
else
let opts['virt_text'] = a:blocks
if align ==# 'right'
let opts['virt_text_pos'] = 'right_align'
else
if type(get(a:opts, 'virt_text_win_col', v:null)) == 0
let opts['virt_text_win_col'] = a:opts['virt_text_win_col']
let opts['virt_text_pos'] = 'overlay'
else
" default to 'after'
let opts['virt_text_pos'] = 'eol'
endif
endif
endif
else
if has('nvim-0.5.1') && type(get(a:opts, 'virt_text_win_col', v:null)) == 0
let opts['virt_text_win_col'] = a:opts['virt_text_win_col']
let opts['virt_text_pos'] = 'overlay'
endif
endif
call nvim_buf_set_extmark(a:bufnr, a:src_id, a:line, 0, opts)
endif
endfunction
function! s:get_option_vim(align, column, wrap) abort
let opts = {}
if s:text_options && a:column == 0
if a:align ==# 'top' && !s:vim_above
let opts['text_align'] = 'right'
else
let opts['text_align'] = a:align
endif
let opts['text_wrap'] = a:wrap
endif
return opts
endfunction

View file

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

View file

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

Binary file not shown.

View file

@ -1,108 +0,0 @@
/*
* 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 '\033]51;' + str + '\x07'
}
function send(args) {
process.stdout.write(createSequences(JSON.stringify(['call', 'CocPopupCallback', args])))
}
process.stdin.on('keypress', (e, key) => {
if (key) {
let k = getKey(key)
if (k == '<bs>') {
return
}
if (k == '<esc>') {
send(['exit', ''])
process.exit()
}
if (k) {
send(['send', k])
return
}
}
})
function getKey(key) {
if (key.ctrl === true) {
if (key.name == 'n') {
return '<C-n>'
}
if (key.name == 'p') {
return '<C-p>'
}
if (key.name == 'j') {
return '<C-j>'
}
if (key.name == 'k') {
return '<C-k>'
}
if (key.name == 'f') {
return '<C-f>'
}
if (key.name == 'b') {
return '<C-b>'
}
if (key.sequence == '\x00') {
return '<C-@>'
}
}
if (key.sequence == '\u001b') {
return '<esc>'
}
if (key.sequence == '\r') {
return '<cr>'
}
if (key.sequence == '\t') {
return key.shift ? '<s-tab>' : '<tab>'
}
if (key.name == 'up') {
return '<up>'
}
if (key.name == 'down') {
return '<down>'
}
return ''
}

View file

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

File diff suppressed because one or more lines are too long

View file

@ -1,414 +0,0 @@
*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|
==============================================================================
This is 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.
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 curosr 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 curosr, 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 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 curosr col.
• `coc#source#{name}#on_complete(item)` Called with selected complete item
when user confirm the completion by |coc#pum#confirm()| or
|coc#_select_confirm()|. Normally used for apply nesessary 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, inclduing:
• 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
`yarn install @types/node@14.14 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: 'node14.14',
outfile: 'lib/index.js'
})
}
start().catch(e => {
console.error(e)
})
<
------------------------------------------------------------------------------
DEBUG EXTENSIONS *coc-api-debug*
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 enabeld).
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.
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']`
Repalce 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 in 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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,85 +0,0 @@
local api = vim.api
local M = {}
-- Get single line extmarks
function M.getHighlights(bufnr, key, s, e)
if not api.nvim_buf_is_loaded(bufnr) then
return nil
end
s = s or 0
e = e or -1
local max = e == -1 and api.nvim_buf_line_count(bufnr) or e + 1
local ns = api.nvim_create_namespace('coc-' .. key)
local markers = api.nvim_buf_get_extmarks(bufnr, ns, {s, 0}, {e, -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]
local endCol = details.end_col
if line < max then
local delta = details.end_row - line
if delta <= 1 and (delta == 0 or endCol == 0) then
if startCol == endCol then
api.nvim_buf_del_extmark(bufnr, ns, id)
else
if delta == 1 then
local text = api.nvim_buf_get_lines(bufnr, line, line + 1, false)[1] or ''
endCol = #text
end
table.insert(res, {details.hl_group, line, startCol, endCol, id})
end
end
end
end
return res
end
local function addHighlights(bufnr, ns, highlights, priority)
for _, items in ipairs(highlights) do
local hlGroup = items[1]
local line = items[2]
local startCol = items[3]
local endCol = items[4]
local hlMode = items[5] and 'combine' or 'replace'
-- 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,
priority = type(priority) == 'number' and math.min(priority, 4096) or 4096
})
end
end
local function addHighlightTimer(bufnr, ns, highlights, priority, maxCount)
local hls = {}
local next = {}
for i, v in ipairs(highlights) do
if i < maxCount then
table.insert(hls, v)
else
table.insert(next, v)
end
end
addHighlights(bufnr, ns, hls, priority)
if #next > 0 then
vim.defer_fn(function()
addHighlightTimer(bufnr, ns, next, priority, maxCount)
end, 30)
end
end
function M.set(bufnr, ns, highlights, priority)
local maxCount = vim.g.coc_highlight_maximum_count
if #highlights > maxCount then
addHighlightTimer(bufnr, ns, highlights, priority, maxCount)
else
addHighlights(bufnr, ns, highlights, priority)
end
end
return M

View file

@ -1,17 +0,0 @@
{
"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

@ -1,796 +0,0 @@
scriptencoding utf-8
if exists('g:did_coc_loaded') || v:version < 800
finish
endif
function! s:checkVersion() abort
let l:unsupported = 0
if get(g:, 'coc_disable_startup_warning', 0) != 1
if has('nvim')
let l:unsupported = !has('nvim-0.4.0')
else
let l:unsupported = !has('patch-8.1.1719')
endif
if l:unsupported == 1
echohl Error
echom "coc.nvim requires at least Vim 8.1.1719 or Neovim 0.4.0, but you're using an older version."
echom "Please upgrade your (neo)vim."
echom "You can add this to your vimrc to avoid this message:"
echom " let g:coc_disable_startup_warning = 1"
echom "Note that some features may error out or behave incorrectly."
echom "Please do not report bugs unless you're using at least Vim 8.1.1719 or Neovim 0.4.0."
echohl None
sleep 2
else
if !has('nvim-0.5.0') && !has('patch-8.2.0750')
echohl WarningMsg
echom "coc.nvim works best on vim >= 8.2.0750 and neovim >= 0.5.0, consider upgrade your vim."
echom "You can add this to your vimrc to avoid this message:"
echom " let g:coc_disable_startup_warning = 1"
echom "Note that some features may behave incorrectly."
echohl None
sleep 2
elseif !has('nvim') && (!has('job') || !has('popupwin') || !has('textprop'))
echohl WarningMsg
echom "coc.nvim requires job, popupwin and textprop features of vim, consider recompile your vim."
echom "You can add this to your vimrc to avoid this message:"
echom " let g:coc_disable_startup_warning = 1"
echom "Note that some features may behave incorrectly."
echohl None
sleep 2
endif
endif
endif
endfunction
call s:checkVersion()
let g:did_coc_loaded = 1
let g:coc_service_initialized = 0
let s:root = expand('<sfile>:h:h')
let s:is_vim = !has('nvim')
let s:is_gvim = s:is_vim && has("gui_running")
if get(g:, 'coc_start_at_startup', 1) && !s:is_gvim
call coc#rpc#start_server()
endif
function! CocTagFunc(pattern, flags, info) abort
if a:flags !=# 'c'
" use standard tag search
return v:null
endif
return coc#rpc#request('getTagList', [])
endfunction
" 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'
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
return coc#rpc#request('hasProvider', [a:name])
endfunction
function! CocActionAsync(name, ...) abort
return s:AsyncRequest(a:name, a:000)
endfunction
function! CocRequest(...) abort
return coc#rpc#request('sendRequest', a:000)
endfunction
function! CocNotify(...) abort
return coc#rpc#request('sendNotification', a:000)
endfunction
function! 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()
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#highlight#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#request('detach', [])
echohl MoreMsg
echom '[coc.nvim] Event disabled'
echohl None
let g:coc_enabled = 0
endfunction
function! s:Autocmd(...) abort
if !get(g:, 'coc_workspace_initialized', 0)
return
endif
call coc#rpc#notify('CocAutocmd', a:000)
endfunction
function! s:HandleCharInsert(char, bufnr) abort
if get(g:, 'coc_feeding_keys', 0)
return
endif
if get(g:, 'coc_disable_space_report', 0)
let g:coc_disable_space_report = 0
if a:char ==# ' '
return
endif
endif
call s:Autocmd('InsertCharPre', a:char, a:bufnr)
endfunction
function! s:HandleTextChangedI(bufnr) abort
if get(g:, 'coc_feeding_keys', 0)
unlet g:coc_feeding_keys
endif
call s:Autocmd('TextChangedI', a:bufnr, coc#util#change_info())
endfunction
function! s:HandleInsertLeave(bufnr) abort
call coc#pum#close()
call s:Autocmd('InsertLeave', a:bufnr)
endfunction
function! s:HandleWinScrolled(winid) abort
if getwinvar(a:winid, 'float', 0)
call coc#float#nvim_scrollbar(a:winid)
endif
call s:Autocmd('WinScrolled', a:winid)
endfunction
function! s: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', [coc#util#path_replace_patterns(), join(globpath(&runtimepath, "", 0, 1), ",")])
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, { -> coc#pum#close()})
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>'))
endif
autocmd TabNew * call s:Autocmd('TabNew', coc#util#tabnr_id(tabpagenr()))
autocmd TabClosed * call s:Autocmd('TabClosed', coc#util#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())
autocmd FileType * call s:Autocmd('FileType', expand('<amatch>'), +expand('<abuf>'))
autocmd InsertCharPre * call s:HandleCharInsert(v:char, bufnr('%'))
if exists('##TextChangedP')
autocmd TextChangedP * call s:Autocmd('TextChangedP', +expand('<abuf>'), coc#util#change_info())
endif
autocmd TextChangedI * call s:HandleTextChangedI(+expand('<abuf>'))
autocmd InsertLeave * call s:HandleInsertLeave(+expand('<abuf>'))
autocmd InsertEnter * call s:Autocmd('InsertEnter', +expand('<abuf>'))
autocmd BufHidden * call s:Autocmd('BufHidden', +expand('<abuf>'))
autocmd BufEnter * call s:Autocmd('BufEnter', +expand('<abuf>'))
autocmd TextChanged * call s:Autocmd('TextChanged', +expand('<abuf>'), getbufvar(+expand('<abuf>'), 'changedtick'))
autocmd BufWritePost * call s:Autocmd('BufWritePost', +expand('<abuf>'), getbufvar(+expand('<abuf>'), 'changedtick'))
autocmd CursorMoved * call s:Autocmd('CursorMoved', +expand('<abuf>'), [line('.'), col('.')])
autocmd CursorMovedI * call s:Autocmd('CursorMovedI', +expand('<abuf>'), [line('.'), col('.')])
autocmd CursorHold * call s:Autocmd('CursorHold', +expand('<abuf>'), [line('.'), col('.')])
autocmd CursorHoldI * call s:Autocmd('CursorHoldI', +expand('<abuf>'), [line('.'), col('.')])
autocmd BufNewFile,BufReadPost * call s:Autocmd('BufCreate', +expand('<abuf>'))
autocmd BufUnload * call s:Autocmd('BufUnload', +expand('<abuf>'))
autocmd BufWritePre * call s:SyncAutocmd('BufWritePre', +expand('<abuf>'), bufname(+expand('<abuf>')), getbufvar(+expand('<abuf>'), 'changedtick'))
autocmd FocusGained * if mode() !~# '^c' | call s:Autocmd('FocusGained') | endif
autocmd FocusLost * call s:Autocmd('FocusLost')
autocmd VimResized * call s:Autocmd('VimResized', &columns, &lines)
autocmd VimLeavePre * 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:Highlight() 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
if coc#highlight#get_contrast('Normal', has('nvim') ? 'NormalFloat' : 'Pmenu') > 2.0
exe 'hi default CocFloating '.coc#highlight#create_bg_command('Normal', &background ==# 'dark' ? -30 : 30)
exe 'hi default CocMenuSel '.coc#highlight#create_bg_command('CocFloating', &background ==# 'dark' ? -20 : 20)
exe 'hi default CocFloatThumb '.coc#highlight#create_bg_command('CocFloating', &background ==# 'dark' ? -40 : 40)
hi default link CocFloatSbar CocFloating
else
exe 'hi default link CocFloating '.(has('nvim') ? 'NormalFloat' : 'Pmenu')
if coc#highlight#get_contrast('CocFloating', 'PmenuSel') > 2.0
exe 'hi default CocMenuSel '.coc#highlight#create_bg_command('CocFloating', &background ==# 'dark' ? -30 : 30)
else
exe 'hi default CocMenuSel '.coc#highlight#get_hl_command(synIDtrans(hlID('PmenuSel')), 'bg', '237', '#13354A')
endif
hi default link CocFloatThumb PmenuThumb
hi default link CocFloatSbar PmenuSbar
endif
if coc#highlight#get_contrast('Normal', 'CursorLine') < 1.3
" Avoid color too close
exe 'hi default CocListLine '.coc#highlight#create_bg_command('Normal', &background ==# 'dark' ? -20 : 20)
else
hi default link CocListLine CursorLine
endif
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 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 has('nvim-0.5.0')
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
call s:AddAnsiGroups()
if get(g:, 'coc_default_semantic_highlight_groups', 1)
let hlMap = {
\ 'Namespace': ['@namespace', 'Include'],
\ 'Type': ['@type', 'Type'],
\ 'Class': ['@constructor', 'Special'],
\ 'Enum': ['@type', 'Type'],
\ 'Interface': ['@type', 'Type'],
\ 'Struct': ['@structure', 'Identifier'],
\ 'TypeParameter': ['@parameter', 'Identifier'],
\ 'Parameter': ['@parameter', 'Identifier'],
\ 'Variable': ['@variable', 'Identifier'],
\ 'Property': ['@property', 'Identifier'],
\ 'EnumMember': ['@property', 'Constant'],
\ 'Event': ['@keyword', 'Keyword'],
\ 'Function': ['@function', 'Function'],
\ 'Method': ['@method', 'Function'],
\ 'Macro': ['@constant.macro', 'Define'],
\ 'Keyword': ['@keyword', 'Keyword'],
\ 'Modifier': ['@storageclass', 'StorageClass'],
\ 'Comment': ['@comment', 'Comment'],
\ 'String': ['@string', 'String'],
\ 'Number': ['@number', 'Number'],
\ 'Boolean': ['@boolean', 'Boolean'],
\ 'Regexp': ['@string.regex', 'String'],
\ 'Operator': ['@operator', 'Operator'],
\ 'Decorator': ['@symbol', 'Identifier'],
\ 'Deprecated': ['@text.strike', 'CocDeprecatedHighlight']
\ }
for [key, value] in items(hlMap)
let ts = get(value, 0, '')
let fallback = get(value, 1, '')
execute 'hi default link CocSem'.key.' '.(coc#highlight#valid(ts) ? ts : fallback)
endfor
endif
let symbolMap = {
\ 'Keyword': ['@keyword', 'Keyword'],
\ 'Namespace': ['@namespace', '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': ['@field', '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': ['@parameter', 'Identifier'],
\ }
for [key, value] in items(symbolMap)
let hlGroup = coc#highlight#valid(value[0]) ? value[0] : get(value, 1, 'CocSymbolDefault')
if hlexists(hlGroup)
execute 'hi default CocSymbol'.key.' '.coc#highlight#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]) < 14 || (str2nr(ms[1]) == 14 && str2nr(ms[2]) < 14)
call add(lines, 'Error: Node version '.output.' < 14.14.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
augroup END
augroup coc_dynamic_content
augroup END
augroup coc_dynamic_option
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) : "\<C-n>"
endif
if empty(mapcheck('<C-p>', 'i'))
inoremap <silent><expr> <C-p> coc#pum#visible() ? coc#pum#prev(1) : "\<C-p>"
endif
if empty(mapcheck('<down>', 'i'))
inoremap <silent><expr> <down> coc#pum#visible() ? coc#pum#next(0) : "\<down>"
endif
if empty(mapcheck('<up>', 'i'))
inoremap <silent><expr> <up> coc#pum#visible() ? coc#pum#prev(0) : "\<up>"
endif
if empty(mapcheck('<C-e>', 'i'))
inoremap <silent><expr> <C-e> coc#pum#visible() ? coc#pum#cancel() : "\<C-e>"
endif
if empty(mapcheck('<C-y>', 'i'))
inoremap <silent><expr> <C-y> coc#pum#visible() ? coc#pum#confirm() : "\<C-y>"
endif
if empty(mapcheck('<PageDown>', 'i'))
inoremap <silent><expr> <PageDown> coc#pum#visible() ? coc#pum#scroll(1) : "\<PageDown>"
endif
if empty(mapcheck('<PageUp>', 'i'))
inoremap <silent><expr> <PageUp> coc#pum#visible() ? coc#pum#scroll(0) : "\<PageUp>"
endif
vnoremap <silent> <Plug>(coc-range-select) :<C-u>call CocActionAsync('rangeSelect', visualmode(), v:true)<CR>
vnoremap <silent> <Plug>(coc-range-select-backward) :<C-u>call CocActionAsync('rangeSelect', visualmode(), v:false)<CR>
nnoremap <Plug>(coc-range-select) :<C-u>call CocActionAsync('rangeSelect', '', v:true)<CR>
nnoremap <Plug>(coc-codelens-action) :<C-u>call CocActionAsync('codeLensAction')<CR>
vnoremap <silent> <Plug>(coc-format-selected) :<C-u>call CocActionAsync('formatSelected', visualmode())<CR>
vnoremap <silent> <Plug>(coc-codeaction-selected) :<C-u>call CocActionAsync('codeAction', visualmode())<CR>
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>

View file

@ -1,3 +0,0 @@
als
edn
esy

View file

@ -1,17 +0,0 @@
root = true
[*]
indent_style = space
indent_size = 2
tab_width = 8
end_of_line = lf
insert_final_newline = true
charset = utf-8
[*.lua]
indent_style = space
indent_size = 2
[{Makefile,**/Makefile,runtime/doc/*.txt}]
indent_style = tab
indent_size = 8

View file

@ -1,77 +0,0 @@
name: Bug report
description: Report a problem in nvim-lspconfig
labels: [bug]
body:
- type: markdown
attributes:
value: |
Before reporting: search existing issues and ensure you are running the latest nightly of neovim and the latest version of nvim-lspconfig. Note that this repository implements configuration and initialization of language servers. Implementation of the language server spec itself is located in the neovim core repository.
- type: textarea
attributes:
label: "Description"
description: "A short description of the problem you are reporting."
validations:
required: true
- type: textarea
attributes:
label: "Neovim version"
description: "Output of `nvim --version`"
placeholder: |
NVIM v0.6.0-dev+209-g0603eba6e
Build type: Release
LuaJIT 2.1.0-beta3
validations:
required: true
- type: input
attributes:
label: "Nvim-lspconfig version"
description: "Commit hash"
placeholder: 1344a859864d4e6d23d3f3adf56d49e6386ec0d2
- type: input
attributes:
label: "Operating system and version"
placeholder: "macOS 11.5"
validations:
required: true
- type: input
attributes:
label: "Affected language servers"
description: "If this issue is specific to one or more language servers, list them here. If not, write 'all'."
placeholder: "clangd"
validations:
required: true
- type: textarea
attributes:
label: "Steps to reproduce"
description: "Steps to reproduce using the minimal config provided below."
placeholder: |
1. `nvim -nu minimal.lua`
2. ...
validations:
required: true
- type: textarea
attributes:
label: "Actual behavior"
description: "Observed behavior."
validations:
required: true
- type: textarea
attributes:
label: "Expected behavior"
description: "A description of the behavior you expected."
- type: textarea
attributes:
label: "Minimal config"
render: Lua
description: "You can download a minimal_init.lua via `curl -fLO https://raw.githubusercontent.com/neovim/nvim-lspconfig/master/test/minimal_init.lua`. Then edit it to include your language server and add necessary configuration and paste it here."
validations:
required: true
- type: input
attributes:
label: "LSP log"
description: "If not using the `minimal_init.lua`, add `vim.lsp.set_log_level('debug')` to your LSP setup, upload the log file at `$HOME/.cache/nvim/lsp.log` to https://gist.github.com, and paste the link here."
validations:
required: true

View file

@ -1,6 +0,0 @@
blank_issues_enabled: false
contact_links:
- name: Question
url: https://neovim.discourse.group/c/language-server-protocol-lsp/7
about: Usage questions and support requests are answered in the Neovim Discourse

View file

@ -1,24 +0,0 @@
name: Feature request
description: Request a feature in nvim-lspconfig
labels: [enhancement]
body:
- type: markdown
attributes:
value: |
Before requesting a new feature, search existing issues. Implementation of the language server protocol itself is located in the neovim core repository, and general feature requests may be better suited for core.
- type: input
attributes:
label: "Language server"
description: "Is the feature specific to a language server? If so, which one(s)?"
placeholder: "clangd"
- type: textarea
attributes:
label: "Requested feature"
validations:
required: true
- type: input
attributes:
label: "Other clients which have this feature"
description: "Is the feature already implemented in another LSP client for (Neo)Vim? If so, which one(s)?"
placeholder: "vim-lsp"

View file

@ -1,11 +0,0 @@
---
name: Pull Request
about: Submit a pull request
title: ''
---
<!--
If you want to make changes to the README.md, do so in scripts/README_template.md.
The CONFIG.md is auto-generated with all the options from the various LSP configuration;
do not edit it manually
-->

View file

@ -1,16 +0,0 @@
#!/usr/bin/env bash
set -e
REF_BRANCH="$1"
PR_BRANCH="$2"
# checks for added lines that contain search pattern and prints them
SEARCH_PATTERN="(dirname|fn\.cwd)"
if git diff --pickaxe-all -U0 -G "${SEARCH_PATTERN}" "${REF_BRANCH}" "${PR_BRANCH}" -- '*.lua' | grep -Ev '(configs|utils)\.lua$' | grep -E "^\+.*${SEARCH_PATTERN}" ; then
echo
echo 'String "dirname" found. There is a high risk that this might contradict the directive:'
echo '"Do not add vim.fn.cwd or util.path.dirname in root_dir".'
echo "see: https://github.com/neovim/nvim-lspconfig/blob/master/CONTRIBUTING.md#adding-a-server-to-lspconfig."
exit 1
fi

View file

@ -1,21 +0,0 @@
name: "Close changes to config"
on: [pull_request_target]
jobs:
close-changes:
runs-on: ubuntu-latest
permissions:
pull-requests: write
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
- run: |
if ! git diff origin/$GITHUB_BASE_REF...$(git branch --show-current) --exit-code -- doc/server_configurations.md doc/server_configurations.txt; then
gh pr close $PR_NUMBER
gh pr comment $PR_NUMBER --body "This pull request has been automatically closed. Changes to server_configurations.md aren't allowed - edit the lua source file instead. Consult https://github.com/neovim/nvim-lspconfig/blob/master/CONTRIBUTING.md#generating-docs."
exit 1
fi

View file

@ -1,21 +0,0 @@
name: codespell
on: [pull_request]
jobs:
codespell:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
fetch-depth: 0
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install codespell
- name: Use codespell
run: |
codespell --quiet-level=2 --check-hidden --skip=./doc/server_configurations.md,./doc/server_configurations.txt --ignore-words=.codespellignorewords || exit

View file

@ -1,12 +0,0 @@
on: [pull_request]
jobs:
lint-commits:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- run: npm install --save-dev @commitlint/{cli,config-conventional}
- run: |
echo "module.exports = { extends: ['@commitlint/config-conventional'] };" > commitlint.config.js
- run: npx commitlint --from HEAD~1 --to HEAD --verbose

View file

@ -1,32 +0,0 @@
name: docgen
on:
push:
branches:
- master
jobs:
docgen:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v2
- uses: rhysd/action-setup-vim@v1
with:
neovim: true
version: nightly
- name: Run docgen
run: |
scripts/docgen.sh
- name: Commit changes
env:
COMMIT_MSG: |
docs: update server_configurations.md
skip-checks: true
run: |
git config user.name github-actions
git config user.email github-actions@github.com
git add doc/server_configurations.md doc/server_configurations.txt
# Only commit and push if we have changes
git diff --quiet && git diff --staged --quiet || (git commit -m "${COMMIT_MSG}"; git push)

View file

@ -1,28 +0,0 @@
name: Close Non-Feature Branches
on:
pull_request_target:
branches:
- master
jobs:
close-master-branch:
runs-on: ubuntu-latest
permissions:
pull-requests: write
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
- name: Close if master branch
if: ${{ github.head_ref == 'master' }}
run: |
gh pr close $PR_NUMBER
gh pr comment $PR_NUMBER --body "This pull request has been automatically closed. Please develop on a feature branch. Thank you."
exit 1

View file

@ -1,54 +0,0 @@
name: lint
on:
pull_request:
branches:
- master
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2
- name: Setup luacheck
run: |
sudo apt update
sudo apt install -y lua5.1 luarocks
sudo luarocks install luacheck
- name: Setup selene
run: |
wget "https://github.com/Kampfkarren/selene/releases/download/$VERSION/selene-$VERSION-linux.zip"
echo "$SHA256_CHECKSUM selene-$VERSION-linux.zip" > "selene-$VERSION-linux.zip.checksum"
sha256sum --check "selene-$VERSION-linux.zip.checksum"
unzip "selene-$VERSION-linux.zip"
install -Dp selene "$HOME/.local/bin/selene"
echo "::add-matcher::.github/workflows/problem_matchers/selene.json"
env:
VERSION: "0.15.0"
SHA256_CHECKSUM: "8ff9272170158fbd9c1af38206ecadc894dc456665dc9bd9f0d43a26e5e8f1af"
- name: Add $HOME/.local/bin to $PATH
run: echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Run luacheck
run: luacheck lua/* test/*
- name: Run selene
run: selene --display-style=quiet .
style-lint:
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2
- name: Lint with stylua
uses: JohnnyMorganz/stylua-action@1.0.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
# CLI arguments
args: --check .

View file

@ -1,30 +0,0 @@
{
"problemMatcher": [
{
"owner": "selene-error",
"severity": "error",
"pattern": [
{
"regexp": "^([^:]+):(\\d+):(\\d+):\\serror(.*)$",
"file": 1,
"line": 2,
"column": 3,
"message": 4
}
]
},
{
"owner": "selene-warning",
"severity": "warning",
"pattern": [
{
"regexp": "^([^:]+):(\\d+):(\\d+):\\swarning(.*)$",
"file": 1,
"line": 2,
"column": 3,
"message": 4
}
]
}
]
}

View file

@ -1,15 +0,0 @@
name: "Dirname Checker"
on: [pull_request]
jobs:
disallowed-root-checker:
runs-on: ubuntu-latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- run: |
if ! bash .github/ci/run_sanitizer.sh ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }}; then
exit 1
fi

View file

@ -1,53 +0,0 @@
name: test
on:
pull_request:
branches:
- master
jobs:
ubuntu:
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2
- name: Setup build dependencies
run: |
sudo apt update &&
sudo apt install -y ninja-build \
gettext \
libtool \
libtool-bin \
autoconf \
automake \
cmake \
g++ \
pkg-config \
unzip \
gperf \
libluajit-5.1-dev \
libunibilium-dev \
libmsgpack-dev \
libtermkey-dev \
libvterm-dev \
libjemalloc-dev \
lua5.1 \
lua-lpeg \
lua-mpack \
lua-bitop
- name: Run test with building Nvim
run: |
make test
macos:
runs-on: macos-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2
- name: Setup build dependencies
run: |
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" &&
brew install ninja libtool automake pkg-config gettext
- name: Run test with building Nvim
run: |
make test

View file

@ -1,3 +0,0 @@
.luacheckcache
neovim
doc/tags

View file

@ -1,14 +0,0 @@
-- vim: ft=lua tw=80
-- Rerun tests only if their modification time changed.
cache = true
ignore = {
"212", -- Unused argument, In the case of callback function, _arg_name is easier to understand than _, so this option is set to off.
"631", -- max_line_length, vscode pkg URL is too long
}
-- Global objects defined by the C code
read_globals = {
"vim",
}

View file

@ -1,6 +0,0 @@
column_width = 120
line_endings = "Unix"
indent_type = "Spaces"
indent_width = 2
quote_style = "AutoPreferSingle"
no_call_parentheses = true

View file

@ -1 +0,0 @@
Notice: CONFIG.md was moved to [doc/server_configurations.md](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md). This notice will be removed after the release of neovim 0.6.

View file

@ -1,109 +0,0 @@
## Requirements
- [Neovim](https://neovim.io/) 0.6 or later
- Lint task requires [luacheck](https://github.com/luarocks/luacheck#installation) and [stylua](https://github.com/JohnnyMorganz/StyLua). If using nix, you can use `nix develop` to install these to a local nix shell.
- Documentation is generated by `scripts/docgen.lua`.
- Only works on linux and macOS
## Scope of lspconfig
The point of lspconfig is to provide the minimal configuration necessary for a server to act in compliance with the language server protocol. In general, if a server requires custom client-side commands or off-spec handlers, then the server configuration should be added *without* those in lspconfig and receive a dedicated plugin such as nvim-jdtls, nvim-metals, etc.
## Pull requests (PRs)
- To avoid duplicate work, create a draft pull request.
- Avoid cosmetic changes to unrelated files in the same commit.
- Use a [feature branch](https://www.atlassian.com/git/tutorials/comparing-workflows) instead of the master branch.
- Use a **rebase workflow** for small PRs.
- After addressing review comments, it's fine to rebase and force-push.
## Adding a server to lspconfig
The general form of adding a new language server is to start with a minimal skeleton. This includes populated the `config` table with a `default_config` and `docs` table.
When choosing a server name, convert all dashes (`-`) to underscores (`_`) If the name of the server is a unique name (`pyright`, `clangd`) or a commonly used abbreviation (`zls`), prefer this as the server name. If the server instead follows the pattern x-language-server, prefer the convention `x_ls` (`jsonnet_ls`).
`default_config` should include, at minimum the following:
* `cmd`: a list which includes the executable name as the first entry, with arguments constituting subsequent list elements (`--stdio` is common).
Note that Windows has a limitation when it comes to directly invoking a server that's installed by `npm` or `gem`, so it requires additional handling.
```lua
local bin_name = 'typescript-language-server'
local cmd = { bin_name, '--stdio' }
if vim.fn.has 'win32' == 1 then
cmd = { 'cmd.exe', '/C', bin_name, '--stdio' }
end
```
* `filetypes`: a list for filetypes a
* `root_dir`: a function (or function handle) which returns the root of the project used to determine if lspconfig should launch a new language server, or attach a previously launched server when you open a new buffer matching the filetype of the server. Note, lspconfig does not offer a dedicated single file mode (this is not codified in the spec). Do not add `vim.fn.cwd` or `util.path.dirname` in `root_dir`. A future version of lspconfig will provide emulation of a single file mode until this is formally codified in the specification. A good fallback is `util.find_git_ancestor`, see other configurations for examples.
Additionally, the following options are often added:
* `init_options`: a table sent during initialization, corresponding to initializationOptions sent in [initializeParams](https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#initializeParams) as part of the first request sent from client to server during startup.
* `settings`: a table sent during [`workspace/didChangeConfiguration`](https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#didChangeConfigurationParams) shortly after server initialization. This is an undocumented convention for most language servers. There is often some duplication with initOptions.
A minimal example for adding a new language server is shown below for `pyright`, a python language server included in lspconfig:
```lua
-- Only `configs` must be required, util is optional if you are using the root resolver functions, which is usually the case.
local configs = require 'lspconfig.configs'
local util = require 'lspconfig.util'
-- Having server name defined here is the convention, this is often times also the first entry in the `cmd` table.
local server_name = 'pyright'
configs[server_name] = {
default_config = {
-- This should be executable on the command line, arguments (such as `--stdio`) are additional entries in the list.
cmd = { 'pyright-langserver' },
-- These are the filetypes that the server will either attach or start in response to opening. The user must have a filetype plugin matching the filetype, either via the built-in runtime files or installed via plugin.
filetypes = { 'python' },
-- The root directory that lspconfig uses to determine if it should start a new language server, or attach the current buffer to a previously running language server.
root_dir = util.find_git_ancestor
end,
},
docs = {
-- extremely important: the package.json that contains language server settings, not the package.json that contains javascript dependencies for the project, or the package.json that contains vscode specific settings
package_json = 'https://raw.githubusercontent.com/microsoft/pyright/master/packages/vscode-pyright/package.json',
-- The description should include at minimum the link to the github project, and ideally the steps to install the language server.
description = [[
https://github.com/microsoft/pyright
`pyright`, a static type checker and language server for python
`pyright` can be installed via `npm`
`npm install -g pyright`
]],
},
}
```
## Commit style
lspconfig, like neovim core, follows the [conventional commit style](https://www.conventionalcommits.org/en/v1.0.0-beta.2/) please submit your commits accordingly. Generally commits will be of the form:
```
feat: add lua-language-server support
fix(lua-language-server): update root directory pattern
docs: update README.md
```
with the commit body containing additional details.
## Lint
PRs are checked with [luacheck](https://github.com/mpeterv/luacheck), [StyLua](https://github.com/JohnnyMorganz/StyLua) and [selene](https://github.com/Kampfkarren/selene). Please run the linter locally before submitting a PR:
make lint
## Generating docs
Github Actions automatically generates `server_configurations.md`. Only modify `scripts/README_template.md` or the `docs` table in the server config (the lua file). Do not modify `server_configurations.md` directly.
To preview the generated `server_configurations.md` locally, run `scripts/docgen.lua` from
`nvim` (from the project root):
nvim -R -Es +'set rtp+=$PWD' +'luafile scripts/docgen.lua'

View file

@ -1,183 +0,0 @@
Copyright Neovim contributors. All rights reserved.
nvim-lsp is licensed under the terms of the Apache 2.0 license.
nvim-lsp's license follows:
====
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

View file

@ -1,12 +0,0 @@
test:
sh ./scripts/run_test.sh
lint:
@printf "\nRunning luacheck\n"
luacheck lua/* test/*
@printf "\nRunning selene\n"
selene --display-style=quiet .
@printf "\nRunning stylua\n"
stylua --check .
.PHONY: test lint

View file

@ -1,209 +0,0 @@
# lspconfig
A [collection of common configurations](doc/server_configurations.md) for Neovim's built-in [language server client](https://neovim.io/doc/user/lsp.html).
This plugin allows for declaratively configuring, launching, and initializing language servers you have installed on your system.
**Disclaimer: Language server configurations are provided on a best-effort basis and are community-maintained. See [contributions](#contributions).**
`lspconfig` has extensive help documentation, see `:help lspconfig`.
# LSP overview
Neovim supports the Language Server Protocol (LSP), which means it acts as a client to language servers and includes a Lua framework `vim.lsp` for building enhanced LSP tools. LSP facilitates features like:
- go-to-definition
- find-references
- hover
- completion
- rename
- format
- refactor
Neovim provides an interface for all of these features, and the language server client is designed to be highly extensible to allow plugins to integrate language server features which are not yet present in Neovim core such as [**auto**-completion](https://github.com/neovim/nvim-lspconfig/wiki/Autocompletion) (as opposed to manual completion with omnifunc) and [snippet integration](https://github.com/neovim/nvim-lspconfig/wiki/Snippets).
These features are not implemented in this repo, but in Neovim core. See `:help lsp` for more details.
## Install
* Requires [Neovim v0.6.0](https://github.com/neovim/neovim/releases/tag/v0.6.0) or [Nightly](https://github.com/neovim/neovim/releases/tag/nightly). Update Neovim and 'lspconfig' before reporting an issue.
* Install 'lspconfig' like any other Vim plugin, e.g. with [vim-plug](https://github.com/junegunn/vim-plug):
```vim
Plug 'neovim/nvim-lspconfig'
```
## Quickstart
1. Install a language server, e.g. [pyright](doc/server_configurations.md#pyright)
```bash
npm i -g pyright
```
2. Add the language server setup to your init.vim. The server name must match those found in the table of contents in [server_configurations.md](doc/server_configurations.md). This list is also accessible via `:help lspconfig-server-configurations`.
```lua
lua << EOF
require'lspconfig'.pyright.setup{}
EOF
```
3. Create a project, this project must contain a file matching the root directory trigger. See [Automatically launching language servers](#Automatically-launching-language-servers) for additional info.
```bash
mkdir test_python_project
cd test_python_project
git init
touch main.py
```
4. Launch neovim, the language server will now be attached and providing diagnostics (see `:LspInfo`)
```
nvim main.py
```
5. See [Keybindings and completion](#Keybindings-and-completion) for mapping useful functions and enabling omnifunc completion
## Automatically launching language servers
In order to automatically launch a language server, 'lspconfig' searches up the directory tree from your current buffer to find a file matching the `root_dir` pattern defined in each server's configuration. For [pyright](doc/server_configurations.md#pyright), this is any directory containing ".git", "setup.py", "setup.cfg", "pyproject.toml", or "requirements.txt").
Language servers require each project to have a `root` in order to provide completion and search across symbols that may not be defined in your current file, and to avoid having to index your entire filesystem on each startup.
## Enabling additional language servers
Enabling most language servers is as easy as installing the language server, ensuring it is on your PATH, and adding the following to your config:
```vim
lua << EOF
require'lspconfig'.rust_analyzer.setup{}
EOF
```
For a full list of servers, see [server_configurations.md](doc/server_configurations.md) or `:help lspconfig-server-configurations`. This document contains installation instructions and additional, optional, customization suggestions for each language server. For some servers that are not on your system path (e.g., `jdtls`, `elixirls`), you will be required to manually add `cmd` as an entry in the table passed to `setup`. Most language servers can be installed in less than a minute.
## Keybindings and completion
'lspconfig' does not map keybindings or enable completion by default. Manual, triggered completion can be provided by neovim's built-in omnifunc. For autocompletion, a general purpose [autocompletion plugin](https://github.com/neovim/nvim-lspconfig/wiki/Autocompletion) is required. The following example configuration provides suggested keymaps for the most commonly used language server functions, and manually triggered completion with omnifunc (\<c-x\>\<c-o\>).
Note: **you must pass the defined `on_attach` as an argument to every `setup {}` call** and **the keybindings in `on_attach` only take effect after the language server has started (attached to the current buffer)**.
```lua
lua << EOF
local nvim_lsp = require('lspconfig')
-- Use an on_attach function to only map the following keys
-- after the language server attaches to the current buffer
local on_attach = function(client, bufnr)
local function buf_set_keymap(...) vim.api.nvim_buf_set_keymap(bufnr, ...) end
local function buf_set_option(...) vim.api.nvim_buf_set_option(bufnr, ...) end
-- Enable completion triggered by <c-x><c-o>
buf_set_option('omnifunc', 'v:lua.vim.lsp.omnifunc')
-- Mappings.
local opts = { noremap=true, silent=true }
-- See `:help vim.lsp.*` for documentation on any of the below functions
buf_set_keymap('n', 'gD', '<cmd>lua vim.lsp.buf.declaration()<CR>', opts)
buf_set_keymap('n', 'gd', '<cmd>lua vim.lsp.buf.definition()<CR>', opts)
buf_set_keymap('n', 'K', '<cmd>lua vim.lsp.buf.hover()<CR>', opts)
buf_set_keymap('n', 'gi', '<cmd>lua vim.lsp.buf.implementation()<CR>', opts)
buf_set_keymap('n', '<C-k>', '<cmd>lua vim.lsp.buf.signature_help()<CR>', opts)
buf_set_keymap('n', '<space>wa', '<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>', opts)
buf_set_keymap('n', '<space>wr', '<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>', opts)
buf_set_keymap('n', '<space>wl', '<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>', opts)
buf_set_keymap('n', '<space>D', '<cmd>lua vim.lsp.buf.type_definition()<CR>', opts)
buf_set_keymap('n', '<space>rn', '<cmd>lua vim.lsp.buf.rename()<CR>', opts)
buf_set_keymap('n', '<space>ca', '<cmd>lua vim.lsp.buf.code_action()<CR>', opts)
buf_set_keymap('n', 'gr', '<cmd>lua vim.lsp.buf.references()<CR>', opts)
buf_set_keymap('n', '<space>e', '<cmd>lua vim.diagnostic.open_float()<CR>', opts)
buf_set_keymap('n', '[d', '<cmd>lua vim.diagnostic.goto_prev()<CR>', opts)
buf_set_keymap('n', ']d', '<cmd>lua vim.diagnostic.goto_next()<CR>', opts)
buf_set_keymap('n', '<space>q', '<cmd>lua vim.diagnostic.setloclist()<CR>', opts)
buf_set_keymap('n', '<space>f', '<cmd>lua vim.lsp.buf.formatting()<CR>', opts)
end
-- Use a loop to conveniently call 'setup' on multiple servers and
-- map buffer local keybindings when the language server attaches
local servers = { 'pyright', 'rust_analyzer', 'tsserver' }
for _, lsp in ipairs(servers) do
nvim_lsp[lsp].setup {
on_attach = on_attach,
flags = {
debounce_text_changes = 150,
}
}
end
EOF
```
The `on_attach` hook is used to only activate the bindings after the language server attaches to the current buffer.
## Debugging
If you have an issue with 'lspconfig', the first step is to reproduce with a [minimal configuration](https://github.com/neovim/nvim-lspconfig/blob/master/test/minimal_init.lua).
The most common reasons a language server does not start or attach are:
1. The language server is not installed. 'lspconfig' does not install language servers for you. You should be able to run the `cmd` defined in each server's lua module from the command line and see that the language server starts. If the `cmd` is an executable name, ensure it is on your path.
2. Not triggering root detection. The language server will only start if it is opened in a directory, or child directory, containing a file which signals the *root* of the project. Most of the time, this is a `.git` folder, but each server defines the root config in the lua file. See [server_configurations.md](doc/server_configurations.md) or the source for the list of root directories.
3. Misconfiguration. You must pass `on_attach` and `capabilities` for **each** `setup {}` if you want these to take effect. You must also **not call `setup {}` twice for the same server**. The second call to `setup {}` will overwrite the first.
:LspInfo provides a handy overview of your active and configured language servers. Note, that it will not report any configuration changes applied in `on_new_config`.
Before reporting a bug, check your logs and the output of `:LspInfo`. Add the following to your init.vim to enable logging:
```lua
lua << EOF
vim.lsp.set_log_level("debug")
EOF
```
Attempt to run the language server, and open the log with:
```
:lua vim.cmd('e'..vim.lsp.get_log_path())
```
Most of the time, the reason for failure is present in the logs.
## Built-in commands
* `:LspInfo` shows the status of active and configured language servers.
The following support tab-completion for all arguments:
* `:LspStart <config_name>` Start the requested server name. Will only successfully start if the command detects a root directory matching the current config. Pass `autostart = false` to your `.setup{}` call for a language server if you would like to launch clients solely with this command. Defaults to all servers matching current buffer filetype.
* `:LspStop <client_id>` Defaults to stopping all buffer clients.
* `:LspRestart <client_id>` Defaults to restarting all buffer clients.
## The wiki
Please see the [wiki](https://github.com/neovim/nvim-lspconfig/wiki) for additional topics, including:
* [Installing language servers automatically](https://github.com/neovim/nvim-lspconfig/wiki/Installing-language-servers-automatically)
* [Snippets support](https://github.com/neovim/nvim-lspconfig/wiki/Snippets)
* [Project local settings](https://github.com/neovim/nvim-lspconfig/wiki/Project-local-settings)
* [Recommended plugins for enhanced language server features](https://github.com/neovim/nvim-lspconfig/wiki/Language-specific-plugins)
## Contributions
If you are missing a language server on the list in [server_configurations.md](doc/server_configurations.md), contributing
a new configuration for it would be appreciated. You can follow these steps:
1. Read [CONTRIBUTING.md](CONTRIBUTING.md).
2. Choose a language from [the coc.nvim wiki](https://github.com/neoclide/coc.nvim/wiki/Language-servers) or
[emacs-lsp](https://github.com/emacs-lsp/lsp-mode#supported-languages).
3. Create a new file at `lua/lspconfig/SERVER_NAME.lua`.
- Copy an [existing config](https://github.com/neovim/nvim-lspconfig/blob/master/lua/lspconfig/server_configurations/)
to get started. Most configs are simple. For an extensive example see
[texlab.lua](https://github.com/neovim/nvim-lspconfig/blob/master/lua/lspconfig/server_configurations/texlab.lua).
4. Ask questions on our [Discourse](https://neovim.discourse.group/c/7-category/7) or in the [Neovim Gitter](https://gitter.im/neovim/neovim).
You can also help out by testing [PRs with the `needs-testing`](https://github.com/neovim/nvim-lspconfig/issues?q=is%3Apr+is%3Aopen+label%3Aneeds-testing) label) that affect language servers you use regularly.

View file

@ -1,648 +0,0 @@
*lspconfig.txt* For Nvim version 0.5.1+ Last change: 2021 Nov 7
==============================================================================
TABLE OF CONTENTS *lspconfig-toc*
1. Introduction (|lspconfig|)
2. LSP overview (|lspconfig-lsp|)
3. Quickstart (|lspconfig-quickstart|)
4. Setup {} (|lspconfig-setup|)
5. Global defaults (|lspconfig-global-defaults|)
6. Server configurations (|lspconfig-configurations|)
6a. Adding servers (|lspconfig-adding-servers|)
7. Root directories (|lspconfig-root-detection|)
7a. Advanced detection (|lspconfig-root-advanced|)
7b. Single file support (|lspconfig-single-file-support|)
8. Commands (|lspconfig-commands|)
9. Keybindings (|lspconfig-keybindings|)
10. Completion (|lspconfig-completion|)
11. Debugging (|lspconfig-debugging|)
12. Logging (|lspconfig-logging|)
13. Scope (|lspconfig-scope|)
==============================================================================
INTRODUCTION *lspconfig*
`lspconfig` is a collection of community contributed configurations for the
built-in language server client in Neovim core. This plugin provides four
primary functionalities:
- default launch commands, initialization options, and settings for each
server
- a root directory resolver which attempts to detect the root of your project
- an autocommand mapping that either launches a new language server or
attempts to attach a language server to each opened buffer if it falls
under a tracked project
- utility commands such as LspInfo, LspStart, LspStop, and LspRestart for
managing language server instances
`lspconfig` is not required to use the built-in client, it is only one front-end
interface for when a language server specific plugin is not available.
See |lspconfig-server-configurations| by typing `K` over it for the complete
list of language servers configurations.
==============================================================================
LSP OVERVIEW *lspconfig-lsp*
Nvim supports the Language Server Protocol (LSP) via the built-in language
server client. LSP facilitates many features, some of which include:
- go-to-definition
- find-references
- hover
- completion
- rename
- format
- refactor
These features are implemented in Neovim core, not `lspconfig`. See `:help lsp`
for more details.
NOTE: Feature availability depends on the implementation details of the
server. A server may implement only a subset of these features. Always
consult the server documentation before filing a bug report on a missing
feature.
==============================================================================
QUICKSTART *lspconfig-quickstart*
- ensure the server is installed and executable from the command line
- enable the server in your Neovim configuration (Lua example):
>
require'lspconfig'.clangd.setup{}
<
- create a new project, ensure that it contains a root marker which matches the
server requirements specified in |lspconfig-server-configurations|.
- open a file within that project, such as `main.c`.
- If you need more information about a server configuration, read the corresponding
entry in |lspconfig-server-configurations|.
==============================================================================
THE SETUP METAMETHOD *lspconfig-setup*
`lspconfig` consists of a collection of language server configurations. Each
configuration exposes a `setup {}` metamethod which makes it easy to directly
use the default configuration or selectively override the defaults.
`setup {}` is the primary interface by which users interact with `lspconfig`.
Using the default configuration for a server is simple:
>
require'lspconfig'.clangd.setup{}
<
The available server names are listed in |lspconfig-server-configurations| and
match the server name in `config.SERVER_NAME` defined in each configuration's
source file.
The purpose of `setup{}` is to wrap the call to Nvim's built-in
`vim.lsp.start_client()` with an autocommand that automatically launch a
language server.
This autocommand calls `start_client()` or `vim.lsp.buf_attach_client()`
depending on whether the current file belongs to a project with a currently
running client. See |lspconfig-root-detection| for more details.
The `setup{}` function takes a table which contains a superset of the keys
listed in `:help vim.lsp.start_client()` with the following unique entries:
- {root_dir}
`function(filename, bufnr)`
Returns either a filepath (string) or nil. The language server will only
start if the function returns a filepath.
If a root directory (string) is returned which is unique from any
previously returned root_dir, a new server will be spawned with that
root directory. See |lspconfig-root-detection| for more details
- {name}
`string`
Defaults to the server's name (`clangd`, `pyright`, etc.).
- {filetypes}
`list[string] | nil`
Set of filetypes for which to attempt to resolve {root_dir}.
May be empty, or server may specify a default value.
- {autostart}
`bool` (default: true)
Controls if the `FileType` autocommand that launches a language server is
created. If `false`, allows for deferring language servers until manually
launched with `:LspStart` (|lspconfig-commands|).
- {single_file_support}
`bool` (default: nil)
Determines if a server is started without a matching root directory.
See |lspconfig-single-file-support|.
- {on_new_config}
`function(new_config, new_root_dir)`
Function executed after a root directory is detected. This is used to
modify the server configuration (including `cmd` itself). Most commonly,
this is used to inject additional arguments into `cmd`.
If overriding `on_new_config`, ensure that you read the
`on_new_config` defined in the source file of the default configuration
in `lspconfig`. The original `on_new_config` snippet for a given server
should likely be included in your new override. Some configurations
use `on_new_config` to dynamically set or modify `cmd`.
Note: all entries passed to `setup {}` override the entry in the default
configuration. There is no composition.
All `config` elements described in `:help vim.lsp.start_client()` can
additionally be overridden via the `setup {}` call. The most commonly
passed overrides to `setup {}` are:
- {capabilities} `table <string, string|table|bool|function>`
a table which represents the neovim client capabilities. Useful for
broadcasting to the server additional functionality (snippets, off-protocol
features) provided by plugins.
- {cmd} `list[string]`
a list where each entry corresponds to the blankspace delimited part of
the command that launches the server. The first entry is the binary used
to run the language server. Additional entries are passed as arguments.
The equivalent `cmd` for:
>
foo --bar baz
<
is:
>
{'foo', '--bar', 'baz}
<
- {handlers} `list[functions]`
a list of handlers which override the function used to process a response
from a given language server. Applied only to the server referenced by
setup. See |lsp-handler|.
- {init_options} `table <string, string|table|bool>`
a table passed during the initialization notification after launching
a language server. Equivalent to the `initializationOptions` field found
in `InitializeParams` in the LSP specification.
See upstream server documentation for available initialization
options.
- {on_attach} `function(client, bufnr)`
Callback invoked by Nvim's built-in client when attaching a buffer to a
language server. Often used to set Nvim (buffer or global) options or to
override the Nvim client properties (`resolved_capabilities`) after a
language server attaches. Most commonly used for settings buffer
local keybindings. See |lspconfig-keybindings| for a usage example.
- {settings} `table <string, string|table|bool>`
The `settings` table is sent in `on_init` via a
`workspace/didChangeConfiguration` notification from the Nvim client to
the language server. These settings allow a user to change optional runtime
settings of the language server.
The script that automatically generates `server_configurations.md` converts
the `package.json` referenced in a server configuration source file
into a list of optional settings listed in |lspconfig-server-configurations|.
As an example, to set the following settings found in the pyright
documentation:
`pyright.disableLanguageServices`: `boolean`
`pyright.disableOrganizeImports`: `boolean`
Nested keys need to be translated into a nested table and passed to
the settings field in `setup {}` as follows:
>
require('lspconfig').pyright.setup{
settings = {
pyright = {
disableLanguageServices = true,
disableOrganizeImports = true,
}
}
}
<
Note that the autogenerated settings occasionally include VS code specific
settings. If a setting is not respected by a language server, consult
upstream documentation.
==============================================================================
OVERRIDING GLOBAL DEFAULTS *lspconfig-global-defaults*
The global defaults for all servers can be overridden by extending the
`default_config` table.
>
local lspconfig = require'lspconfig'
lspconfig.util.default_config = vim.tbl_extend(
"force",
lspconfig.util.default_config,
{
autostart = false,
handlers = {
["window/logMessage"] = function(err, method, params, client_id)
if params and params.type <= vim.lsp.protocol.MessageType.Log then
vim.lsp.handlers["window/logMessage"](err, method, params, client_id)
end
end;
["window/showMessage"] = function(err, method, params, client_id)
if params and params.type <= vim.lsp.protocol.MessageType.Warning.Error then
vim.lsp.handlers["window/showMessage"](err, method, params, client_id)
end
end;
}
}
)
<
`setup {}` can additionally override these defaults in subsequent calls.
==============================================================================
SERVER CONFIGURATIONS *lspconfig-configurations*
See |lspconfig-server-configurations| by typing `K` over it for the complete
list of language servers configurations.
While the `setup {}` function is the primary interface to `lspconfig`, for
servers for which there is not a configuration, it is necessary to define a
configuration directly. This can be useful if there is an outstanding PR that
is in review, or when developing a language server that is unavailable
publicly. This can be done through the `configs` module.
The `configs` module is a singleton where configs are defined. The schema for
validating using `vim.validate` is:
>
configs.SERVER_NAME = {
default_config = {'t'};
on_new_config = {'f', true};
on_attach = {'f', true};
commands = {'t', true};
docs = {'t', true};
}
<
where the structure of the docs table is as follows:
>
docs = {
description = {'s', true};
default_config = {'t', true};
}
<
`commands` is a map of `name:definition` key:value pairs, where `definition`
is a list whose first value is a function implementing the command, and the
rest are either array values which will be formed into flags for the command,
or special keys like `description`. Example:
>
commands = {
TexlabBuild = {
function()
buf_build(0)
end;
"-range";
description = "Build the current buffer";
};
};
<
The `configs.__newindex` metamethod consumes the config definition and returns
an object with a `setup()` method, to be invoked by users:
>
require'lspconfig'.SERVER_NAME.setup{}
After you set `configs.SERVER_NAME` you can add arbitrary language-specific
functions to it if necessary.
Example:
>
configs.texlab.buf_build = buf_build
<
==============================================================================
ADDING NEW SERVERS *lspconfig-adding-servers*
The three steps for adding and enabling a new server configuration are:
- load the `lspconfig` module (note that this is a stylistic choice)
>
local lspconfig = require 'lspconfig'
<
- define the configuration
>
local configs = require 'lspconfig.configs'
-- Check if the config is already defined (useful when reloading this file)
if not configs.foo_lsp then
configs.foo_lsp = {
default_config = {
cmd = {'/home/neovim/lua-language-server/run.sh'};
filetypes = {'lua'};
root_dir = function(fname)
return lspconfig.util.find_git_ancestor(fname)
end;
settings = {};
};
}
end
- call `setup()` to enable the FileType autocmd
>
lspconfig.foo_lsp.setup{}
<
==============================================================================
ROOT DETECTION *lspconfig-root-detection*
*lspconfig-root-dir*
A project's `root_dir` is used by `lspconfig` to determine whether `lspconfig`
should start a new server, or attach a previous one, to the current file.
`lspconfig` automatically launches language servers by defining a filetype
autocommand based on the `filetypes` specified in the default configuration of
each server, optionally overridable by the `filetypes` table passed to
`setup`.
This autocommand triggers a search from the current file position in the
filesystem hierarchy up to the top level directory of your filesystem. The
`root_dir` entry of each configuration is a function that returns true if the
current directory in this traversal matches a given root pattern.
The following utility functions are provided by `lspconfig`. Each function call
below returns a function that takes as its argument the current buffer path.
- `util.root_pattern`: function which takes multiple arguments, each
corresponding to a different root pattern against which the contents of the
current directory are matched using |vim.fin.glob()| while traversing up the
filesystem.
>
root_dir = util.root_pattern('pyproject.toml', 'requirements.txt')
<
- `util.find_git_ancestor`: a function that locates the first parent directory
containing a `.git` directory.
>
root_dir = util.find_git_ancestor
- `util.find_node_modules_ancestor`: a function that locates the first parent
directory containing a `node_modules` directory.
>
root_dir = util.find_node_modules_ancestor
<
- `util.find_package_json_ancestor`: a function that locates the first parent
directory containing a `package.json`.
>
root_dir = util.find_json_ancestor
<
Note: On Windows, `lspconfig` always assumes forward slash normalized paths with
capitalized drive letters.
==============================================================================
ADVANCED ROOT DIRECTORY DETECTION *lspconfig-root-advanced*
*lspconfig-root-composition*
The `root_dir` key in `config` and `setup` can hold any function of the form
>
function custom_root_dir(filename, bufnr)
returns nil | string
>
This allows for rich composition of root directory patterns which is necessary
for some project structures. Example (for Kotlin):
>
local root_files = {
'settings.gradle', -- Gradle (multi-project)
'settings.gradle.kts', -- Gradle (multi-project)
'build.xml', -- Ant
'pom.xml', -- Maven
}
local fallback_root_files = {
'build.gradle', -- Gradle
'build.gradle.kts', -- Gradle
}
root_dir = function(fname)
local primary = util.root_pattern(unpack(root_files))(fname)
local fallback = util.root_pattern(unpack(fallback_root_files))(fname)
return primary or fallback
end
<
Browsing the source of the default configurations is recommended.
==============================================================================
SINGLE FILE SUPPORT *lspconfig-single-file-support*
Language servers require each project to have a `root` in order to provide
features that require cross-file indexing.
Some servers support not passing a root directory as a proxy for single file
mode under which cross-file features may be degraded.
`lspconfig` offers limited support for an implicit single-file mode by:
- first trying to resolve the root directory pattern
- then, if `single_file_support` is enabled for a given language server
configuration, starting the server without sending `rootDirectory` or
`workspaceFolders` during initialization.
- attaching subsequent files in the parent directory to the same server
instance, depending on filetype.
Cross-file features (navigation, hover) may or may not work depending on the
language server. For a full feature-set, consider moving your files to a
directory with a project structure `lspconfig` can infer.
Note that in the event that the LSP specification is extended to support a
standard for single-file mode, lspconfig will adopt that standard.
==============================================================================
COMMANDS *lspconfig-commands*
- `:LspInfo` shows the status of active and configured language servers. Note
that client id refers to the Nvim RPC instance connected to a given
language server.
The following commands support tab-completion for all arguments. All commands
that require a client id can either leverage tab-completion or the info
contained in `:LspInfo`:
- `:LspStart <config_name>` launches the requested (configured) client, but only
if it successfully resolves a root directory. Note: Defaults to all
configured servers matching the current buffer filetype.
- `:LspStop <client_id>` stops the server with the given client id. Defaults to
stopping all servers active on the current buffer.
- `:LspRestart <client_id>` restarts the client with the given client id, and
will attempt to reattach to all previously attached buffers.
==============================================================================
EXAMPLE KEYBINDINGS *lspconfig-keybindings*
`lspconfig`, and the core client, do not map any keybindings by default. The
following is an example Lua block which demonstrates how to leverage
`on-attach` to selectively apply keybindings after a language servers has
attached to a given buffer.
>
local nvim_lsp = require('lspconfig')
-- Use an on_attach function to only map the following keys
-- after the language server attaches to the current buffer
local on_attach = function(client, bufnr)
local function buf_set_keymap(...) vim.api.nvim_buf_set_keymap(bufnr, ...) end
local function buf_set_option(...) vim.api.nvim_buf_set_option(bufnr, ...) end
-- Enable completion triggered by <c-x><c-o>
buf_set_option('omnifunc', 'v:lua.vim.lsp.omnifunc')
-- Mappings.
local opts = { noremap=true, silent=true }
-- See `:help vim.lsp.*` for documentation on any of the below functions
buf_set_keymap('n', 'gD', '<cmd>lua vim.lsp.buf.declaration()<CR>', opts)
buf_set_keymap('n', 'gd', '<cmd>lua vim.lsp.buf.definition()<CR>', opts)
buf_set_keymap('n', 'K', '<cmd>lua vim.lsp.buf.hover()<CR>', opts)
buf_set_keymap('n', 'gi', '<cmd>lua vim.lsp.buf.implementation()<CR>', opts)
buf_set_keymap('n', '<C-k>', '<cmd>lua vim.lsp.buf.signature_help()<CR>', opts)
buf_set_keymap('n', '<space>wa', '<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>', opts)
buf_set_keymap('n', '<space>wr', '<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>', opts)
buf_set_keymap('n', '<space>wl', '<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>', opts)
buf_set_keymap('n', '<space>D', '<cmd>lua vim.lsp.buf.type_definition()<CR>', opts)
buf_set_keymap('n', '<space>rn', '<cmd>lua vim.lsp.buf.rename()<CR>', opts)
buf_set_keymap('n', '<space>ca', '<cmd>lua vim.lsp.buf.code_action()<CR>', opts)
buf_set_keymap('n', 'gr', '<cmd>lua vim.lsp.buf.references()<CR>', opts)
buf_set_keymap('n', '<space>e', '<cmd>lua vim.diagnostic.open_float()<CR>', opts)
buf_set_keymap('n', '[d', '<cmd>lua vim.diagnostic.goto_prev()<CR>', opts)
buf_set_keymap('n', ']d', '<cmd>lua vim.diagnostic.goto_next()<CR>', opts)
buf_set_keymap('n', '<space>q', '<cmd>lua vim.diagnostic.setloclist()<CR>', opts)
buf_set_keymap('n', '<space>f', '<cmd>lua vim.lsp.buf.formatting()<CR>', opts)
end
-- Use a loop to conveniently call 'setup' on multiple servers and
-- map buffer local keybindings when the language server attaches
local servers = { 'pyright', 'rust_analyzer', 'tsserver' }
for _, lsp in ipairs(servers) do
nvim_lsp[lsp].setup {
on_attach = on_attach,
flags = {
debounce_text_changes = 150,
}
}
end
<
Note: these keymappings are meant for illustration and override some
infrequently used default mappings.
==============================================================================
COMPLETION SUPPORT *lspconfig-completion*
Manually triggered completion can be provided by Nvim's built-in omnifunc.
See `:help omnifunc` for more details.
For autocompletion, Nvim does not offer built-in functionality at this time.
Consult the `lspconfig` wiki, which provides configuration examples for using a
completion plugin with the built-in client
==============================================================================
DEBUGGING *lspconfig-debugging*
While using language servers should be easy, debugging issues can be
challenging. First, it is important to identify the source of the issue, which
is typically (in rough order):
- the language server itself
- a plugin
- overrides in a user configuration
- the built-in client in Nvim core
- `lspconfig`
The first step in debugging is to test with a minimal configuration (such as
`../test/minimal_init.lua`). Historically, many users problems are due to
plugins or misconfiguration.
Should that fail, identifying which component is the culprit is challenging.
The following are the only categories of bugs that pertain to `lspconfig`.
- The root directory inferred for your project is wrong, or it should be
detected but is not due to a bug in the `lspconfig` path utilities.
- The server is launching, but you believe that the default settings,
initialization options, or command arguments are suboptimal and should be
replaced based on your understanding of the server documentation.
All bugs Nvim's built-in client should be reported to the Nvim core issue
tracker. All bugs pertaining to plugins should be reported to the respective
plugin. All missing features in a language server should be reported to the
upstream language server issue tracker.
For debugging `lspconfig` issues, the most common hurdles users face are:
- The language server is not installed or is otherwise not executable.
`lspconfig` does not install language servers for you. Ensure the `cmd`
defined in `server_configurations.md` is executable from the command
line. If the absolute path to the binary is not supplied in `cmd`, ensure
it is on your PATH.
- No root detected. `lspconfig` is built around the concept of projects. See
|lspconfig-root-detection| for more details. Most of the time,
initializing a git repo will suffice.
- Misconfiguration. Often users will override `cmd`, `on_init`, or
`handlers`. Ensure that you debug by using a stock configuration to ensure
your customizations are not introducing issues.
|LspInfo| provides an overview of your active and configured language servers
which can be useful for debugging.
Note that it will not report any configuration changes applied in
`on_new_config`.
==============================================================================
LOGGING *lspconfig-logging*
When debugging language servers, it is helpful to enable additional logging in
the built-in client, specifically considering the RPC logs. Example:
>
vim.lsp.set_log_level 'trace'
if vim.fn.has 'nvim-0.5.1' == 1 then
require('vim.lsp.log').set_format_func(vim.inspect)
end
<
Attempt to run the language server, and open the log with:
>
:lua vim.cmd('e'..vim.lsp.get_log_path())
<
Note that `ERROR` messages containing `stderr` only indicate that the log was
sent to `stderr`. Many servers counter-intuitively send harmless messages
via stderr.
==============================================================================
SCOPE *lspconfig-scope*
`lspconfig` is a community effort to create default configurations that fit
within the scope of an official plugin for Nvim. All features that are not
strictly providing default configurations for language servers will be removed
from `lspconfig` in time. The power of the Neovim LSP ecosystem is in the
composability and flexibility of integrating multiple plugins which maximizes
user choice and freedom.
`lspconfig` also opts to adhere strictly to the LSP specification, with some
small allowances when small modifications to a server configuration are
necessary to enable features critical to its usability. For more featureful
options, the `lspconfig` wiki lists community created plugins that build upon
the built-in client to provide functionality tailored to specific language
servers.
==============================================================================
vim:tw=78:ts=8:ft=help:norl:

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,41 +0,0 @@
{
"nodes": {
"flake-utils": {
"locked": {
"lastModified": 1634851050,
"narHash": "sha256-N83GlSGPJJdcqhUxSCS/WwW5pksYf3VP1M13cDRTSVA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c91f3de5adaf1de973b797ef7485e441a65b8935",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1626644568,
"narHash": "sha256-+WxW0u6AJUn/AzIxUuNKtEDxSRcUP0v/iZ/tRXhLGEc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "d5bd34ebf2c2c2b380b76cb86bc68522bc6af4d7",
"type": "github"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

View file

@ -1,18 +0,0 @@
{
description = "Quickstart configurations for the Nvim LSP client";
inputs.flake-utils.url = "github:numtide/flake-utils";
outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let pkgs = nixpkgs.legacyPackages.${system}; in
rec {
devShell = pkgs.mkShell {
buildInputs = [
pkgs.stylua
pkgs.luaPackages.luacheck
];
};
}
);
}

View file

@ -1,92 +0,0 @@
local configs = require 'lspconfig.configs'
local M = {
util = require 'lspconfig.util',
}
M._root = {}
function M.available_servers()
return vim.tbl_keys(configs)
end
-- Called from plugin/lspconfig.vim because it requires knowing that the last
-- script in scriptnames to be executed is lspconfig.
function M._root._setup()
M._root.commands = {
LspInfo = {
function()
require 'lspconfig.ui.lspinfo'()
end,
'-nargs=0',
description = '`:LspInfo` Displays attached, active, and configured language servers',
},
LspStart = {
function(server_name)
if server_name then
if configs[server_name] then
configs[server_name].launch()
end
else
local buffer_filetype = vim.bo.filetype
for _, config in pairs(configs) do
for _, filetype_match in ipairs(config.filetypes or {}) do
if buffer_filetype == filetype_match then
config.launch()
end
end
end
end
end,
'-nargs=? -complete=custom,v:lua.lsp_complete_configured_servers',
description = '`:LspStart` Manually launches a language server.',
},
LspStop = {
function(cmd_args)
for _, client in ipairs(M.util.get_clients_from_cmd_args(cmd_args)) do
client.stop()
end
end,
'-nargs=? -complete=customlist,v:lua.lsp_get_active_client_ids',
description = '`:LspStop` Manually stops the given language client(s).',
},
LspRestart = {
function(cmd_args)
for _, client in ipairs(M.util.get_clients_from_cmd_args(cmd_args)) do
client.stop()
vim.defer_fn(function()
configs[client.name].launch()
end, 500)
end
end,
'-nargs=? -complete=customlist,v:lua.lsp_get_active_client_ids',
description = '`:LspRestart` Manually restart the given language client(s).',
},
}
M.util.create_module_commands('_root', M._root.commands)
end
local mt = {}
function mt:__index(k)
if configs[k] == nil then
local success, config = pcall(require, 'lspconfig.server_configurations.' .. k)
if success then
configs[k] = config
else
vim.notify(
string.format(
'[lspconfig] Cannot access configuration for %s. Ensure this server is listed in '
.. '`server_configurations.md` or added as a custom server.',
k
),
vim.log.levels.WARN
)
-- Return a dummy function for compatibility with user configs
return { setup = function() end }
end
end
return configs[k]
end
return setmetatable(M, mt)

View file

@ -1,299 +0,0 @@
local util = require 'lspconfig.util'
local api, validate, lsp = vim.api, vim.validate, vim.lsp
local tbl_extend = vim.tbl_extend
local configs = {}
function configs.__newindex(t, config_name, config_def)
validate {
name = { config_name, 's' },
default_config = { config_def.default_config, 't' },
on_new_config = { config_def.on_new_config, 'f', true },
on_attach = { config_def.on_attach, 'f', true },
commands = { config_def.commands, 't', true },
}
if config_def.commands then
for k, v in pairs(config_def.commands) do
validate {
['command.name'] = { k, 's' },
['command.fn'] = { v[1], 'f' },
}
end
else
config_def.commands = {}
end
local M = {}
local default_config = tbl_extend('keep', config_def.default_config, util.default_config)
-- Force this part.
default_config.name = config_name
function M.setup(config)
validate {
cmd = { config.cmd, 't', true },
root_dir = { config.root_dir, 'f', true },
filetypes = { config.filetype, 't', true },
on_new_config = { config.on_new_config, 'f', true },
on_attach = { config.on_attach, 'f', true },
commands = { config.commands, 't', true },
}
if config.commands then
for k, v in pairs(config.commands) do
validate {
['command.name'] = { k, 's' },
['command.fn'] = { v[1], 'f' },
}
end
end
config = tbl_extend('keep', config, default_config)
if util.on_setup then
pcall(util.on_setup, config)
end
if config.autostart == true then
local event
local pattern
if config.filetypes then
event = 'FileType'
pattern = table.concat(config.filetypes, ',')
else
event = 'BufReadPost'
pattern = '*'
end
api.nvim_command(
string.format(
"autocmd %s %s unsilent lua require'lspconfig'[%q].manager.try_add()",
event,
pattern,
config.name
)
)
end
local get_root_dir = config.root_dir
function M.launch()
local root_dir
if get_root_dir then
local bufnr = api.nvim_get_current_buf()
local bufname = api.nvim_buf_get_name(bufnr)
if not util.bufname_valid(bufname) then
return
end
root_dir = get_root_dir(util.path.sanitize(bufname), bufnr)
end
if root_dir then
api.nvim_command(
string.format(
"autocmd BufReadPost %s/* unsilent lua require'lspconfig'[%q].manager.try_add_wrapper()",
vim.fn.fnameescape(root_dir),
config.name
)
)
for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do
local bufname = api.nvim_buf_get_name(bufnr)
if util.bufname_valid(bufname) then
local buf_dir = util.path.sanitize(bufname)
if buf_dir:sub(1, root_dir:len()) == root_dir then
M.manager.try_add_wrapper(bufnr)
end
end
end
elseif config.single_file_support then
-- This allows on_new_config to use the parent directory of the file
-- Effectively this is the root from lspconfig's perspective, as we use
-- this to attach additional files in the same parent folder to the same server.
-- We just no longer send rootDirectory or workspaceFolders during initialization.
local bufname = api.nvim_buf_get_name(0)
if not util.bufname_valid(bufname) then
return
end
local pseudo_root = util.path.dirname(util.path.sanitize(bufname))
local client_id = M.manager.add(pseudo_root, true)
vim.lsp.buf_attach_client(vim.api.nvim_get_current_buf(), client_id)
else
vim.notify(
string.format('[lspconfig] Autostart for %s failed: matching root directory not detected.', config_name)
)
end
end
-- Used by :LspInfo
M.get_root_dir = get_root_dir
M.filetypes = config.filetypes
M.handlers = config.handlers
M.cmd = config.cmd
M.autostart = config.autostart
-- In the case of a reload, close existing things.
local reload = false
if M.manager then
for _, client in ipairs(M.manager.clients()) do
client.stop(true)
end
reload = true
M.manager = nil
end
local make_config = function(_root_dir)
local new_config = vim.tbl_deep_extend('keep', vim.empty_dict(), config)
new_config = vim.tbl_deep_extend('keep', new_config, default_config)
new_config.capabilities = new_config.capabilities or lsp.protocol.make_client_capabilities()
new_config.capabilities = vim.tbl_deep_extend('keep', new_config.capabilities, {
workspace = {
configuration = true,
},
})
if config_def.on_new_config then
pcall(config_def.on_new_config, new_config, _root_dir)
end
if config.on_new_config then
pcall(config.on_new_config, new_config, _root_dir)
end
new_config.on_init = util.add_hook_after(new_config.on_init, function(client, result)
-- Handle offset encoding by default
if result.offsetEncoding then
client.offset_encoding = result.offsetEncoding
end
-- Send `settings to server via workspace/didChangeConfiguration
function client.workspace_did_change_configuration(settings)
if not settings then
return
end
if vim.tbl_isempty(settings) then
settings = { [vim.type_idx] = vim.types.dictionary }
end
return client.notify('workspace/didChangeConfiguration', {
settings = settings,
})
end
if not vim.tbl_isempty(new_config.settings) then
client.workspace_did_change_configuration(new_config.settings)
end
end)
-- Save the old _on_attach so that we can reference it via the BufEnter.
new_config._on_attach = new_config.on_attach
new_config.on_attach = vim.schedule_wrap(function(client, bufnr)
if bufnr == api.nvim_get_current_buf() then
M._setup_buffer(client.id, bufnr)
else
api.nvim_command(
string.format(
"autocmd BufEnter <buffer=%d> ++once lua require'lspconfig'[%q]._setup_buffer(%d,%d)",
bufnr,
config_name,
client.id,
bufnr
)
)
end
end)
new_config.root_dir = _root_dir
new_config.workspace_folders = {
{
uri = vim.uri_from_fname(_root_dir),
name = string.format('%s', _root_dir),
},
}
return new_config
end
local manager = util.server_per_root_dir_manager(function(_root_dir)
return make_config(_root_dir)
end)
function manager.try_add(bufnr)
bufnr = bufnr or api.nvim_get_current_buf()
if vim.api.nvim_buf_get_option(bufnr, 'buftype') == 'nofile' then
return
end
local id
local root_dir
local bufname = api.nvim_buf_get_name(bufnr)
if not util.bufname_valid(bufname) then
return
end
local buf_path = util.path.sanitize(bufname)
if get_root_dir then
root_dir = get_root_dir(buf_path, bufnr)
end
if root_dir then
id = manager.add(root_dir, false)
elseif config.single_file_support then
local pseudo_root = util.path.dirname(buf_path)
id = manager.add(pseudo_root, true)
else
vim.notify(
string.format('[lspconfig] Autostart for %s failed: matching root directory not detected.', config_name)
)
end
if id then
lsp.buf_attach_client(bufnr, id)
end
end
function manager.try_add_wrapper(bufnr)
bufnr = bufnr or api.nvim_get_current_buf()
local buf_filetype = vim.api.nvim_buf_get_option(bufnr, 'filetype')
for _, filetype in ipairs(config.filetypes) do
if buf_filetype == filetype then
manager.try_add(bufnr)
return
end
end
end
M.manager = manager
M.make_config = make_config
if reload and not (config.autostart == false) then
for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do
manager.try_add_wrapper(bufnr)
end
end
end
function M._setup_buffer(client_id, bufnr)
local client = lsp.get_client_by_id(client_id)
if not client then
return
end
if client.config._on_attach then
client.config._on_attach(client, bufnr)
end
if client.config.commands and not vim.tbl_isempty(client.config.commands) then
M.commands = vim.tbl_deep_extend('force', M.commands, client.config.commands)
end
if not M.commands_created and not vim.tbl_isempty(M.commands) then
-- Create the module commands
util.create_module_commands(config_name, M.commands)
M.commands_created = true
end
end
M.commands_created = false
M.commands = config_def.commands
M.name = config_name
M.document_config = config_def
rawset(t, config_name, M)
return M
end
return setmetatable({}, configs)

View file

@ -1,38 +0,0 @@
local util = require 'lspconfig.util'
local bin_name = 'ada_language_server'
if vim.fn.has 'win32' == 1 then
bin_name = 'ada_language_server.exe'
end
return {
default_config = {
cmd = { bin_name },
filetypes = { 'ada' },
root_dir = util.root_pattern('Makefile', '.git', '*.gpr', '*.adc'),
},
docs = {
package_json = 'https://raw.githubusercontent.com/AdaCore/ada_language_server/master/integration/vscode/ada/package.json',
description = [[
https://github.com/AdaCore/ada_language_server
Installation instructions can be found [here](https://github.com/AdaCore/ada_language_server#Install).
Can be configured by passing a "settings" object to `als.setup{}`:
```lua
require('lspconfig').als.setup{
settings = {
ada = {
projectFile = "project.gpr";
scenarioVariables = { ... };
}
}
}
```
]],
default_config = {
root_dir = [[util.root_pattern("Makefile", ".git", "*.gpr", "*.adc")]],
},
},
}

View file

@ -1,75 +0,0 @@
local util = require 'lspconfig.util'
-- Angular requires a node_modules directory to probe for @angular/language-service and typescript
-- in order to use your projects configured versions.
-- This defaults to the vim cwd, but will get overwritten by the resolved root of the file.
local function get_probe_dir(root_dir)
local project_root = util.find_node_modules_ancestor(root_dir)
return project_root and (project_root .. '/node_modules') or ''
end
local default_probe_dir = get_probe_dir(vim.fn.getcwd())
local bin_name = 'ngserver'
local args = {
'--stdio',
'--tsProbeLocations',
default_probe_dir,
'--ngProbeLocations',
default_probe_dir,
}
local cmd = { bin_name, unpack(args) }
if vim.fn.has 'win32' == 1 then
cmd = { 'cmd.exe', '/C', bin_name, unpack(args) }
end
return {
default_config = {
cmd = cmd,
filetypes = { 'typescript', 'html', 'typescriptreact', 'typescript.tsx' },
-- Check for angular.json or .git first since that is the root of the project.
-- Don't check for tsconfig.json or package.json since there are multiple of these
-- in an angular monorepo setup.
root_dir = util.root_pattern('angular.json', '.git'),
},
on_new_config = function(new_config, new_root_dir)
local new_probe_dir = get_probe_dir(new_root_dir)
-- We need to check our probe directories because they may have changed.
new_config.cmd = {
'ngserver',
'--stdio',
'--tsProbeLocations',
new_probe_dir,
'--ngProbeLocations',
new_probe_dir,
}
end,
docs = {
description = [[
https://github.com/angular/vscode-ng-language-service
`angular-language-server` can be installed via npm `npm install -g @angular/language-server`.
Note, that if you override the default `cmd`, you must also update `on_new_config` to set `new_config.cmd` during startup.
```lua
local project_library_path = "/path/to/project/lib"
local cmd = {"ngserver", "--stdio", "--tsProbeLocations", project_library_path , "--ngProbeLocations", project_library_path}
require'lspconfig'.angularls.setup{
cmd = cmd,
on_new_config = function(new_config,new_root_dir)
new_config.cmd = cmd
end,
}
```
]],
default_config = {
root_dir = [[root_pattern("angular.json", ".git")]],
},
},
}

View file

@ -1,46 +0,0 @@
local util = require 'lspconfig.util'
local bin_name = 'ansible-language-server'
local cmd = { bin_name, '--stdio' }
if vim.fn.has 'win32' == 1 then
cmd = { 'cmd.exe', '/C', bin_name, '--stdio' }
end
return {
default_config = {
cmd = cmd,
settings = {
ansible = {
python = {
interpreterPath = 'python',
},
ansibleLint = {
path = 'ansible-lint',
enabled = true,
},
ansible = {
path = 'ansible',
},
executionEnvironment = {
enabled = false,
},
},
},
filetypes = { 'yaml', 'yaml.ansible' },
root_dir = util.root_pattern('ansible.cfg', '.ansible-lint'),
single_file_support = true,
},
docs = {
description = [[
https://github.com/ansible/ansible-language-server
Language server for the ansible configuration management tool.
`ansible-language-server` can be installed via `yarn`:
```sh
yarn global add ansible-language-server
```
]],
},
}

View file

@ -1,50 +0,0 @@
local util = require 'lspconfig.util'
return {
default_config = {
cmd = { 'arduino-language-server' },
filetypes = { 'arduino' },
root_dir = util.root_pattern '*.ino',
},
docs = {
description = [[
https://github.com/arduino/arduino-language-server
Language server for Arduino
The `arduino-language-server` can be installed by running:
go get -u github.com/arduino/arduino-language-server
The `arduino-cli` tools must also be installed. Follow these instructions for your distro:
https://arduino.github.io/arduino-cli/latest/installation/
After installing the `arduino-cli` tools, follow these instructions for generating
a configuration file:
https://arduino.github.io/arduino-cli/latest/getting-started/#create-a-configuration-file
and make sure you install any relevant platforms libraries:
https://arduino.github.io/arduino-cli/latest/getting-started/#install-the-core-for-your-board
The language server also requires `clangd` be installed. It will look for `clangd` by default but
the binary path can be overridden if need be.
After all dependencies are installed you'll need to override the lspconfig command for the
language server in your setup function with the necessary configurations:
```lua
lspconfig.arduino_language_server.setup({
cmd = {
-- Required
"arduino-language-server",
"-cli-config", "/path/to/arduino-cli.yaml",
-- Optional
"-cli", "/path/to/arduino-cli",
"-clangd", "/path/to/clangd"
}
})
```
For further instruction about configuration options, run `arduino-language-server --help`.
]],
},
}

View file

@ -1,34 +0,0 @@
local util = require 'lspconfig.util'
local bin_name = 'bash-language-server'
local cmd = { bin_name, 'start' }
if vim.fn.has 'win32' == 1 then
cmd = { 'cmd.exe', '/C', bin_name, 'start' }
end
return {
default_config = {
cmd = cmd,
cmd_env = {
-- Prevent recursive scanning which will cause issues when opening a file
-- directly in the home directory (e.g. ~/foo.sh).
--
-- Default upstream pattern is "**/*@(.sh|.inc|.bash|.command)".
GLOB_PATTERN = vim.env.GLOB_PATTERN or '*@(.sh|.inc|.bash|.command)',
},
filetypes = { 'sh' },
root_dir = util.find_git_ancestor,
single_file_support = true,
},
docs = {
description = [[
https://github.com/mads-hartmann/bash-language-server
Language server for bash, written using tree sitter in typescript.
]],
default_config = {
root_dir = [[util.find_git_ancestor]],
},
},
}

View file

@ -1,26 +0,0 @@
local util = require 'lspconfig.util'
return {
default_config = {
cmd = { 'beancount-langserver' },
filetypes = { 'beancount' },
root_dir = util.find_git_ancestor,
single_file_support = true,
init_options = {
-- this is the path to the beancout journal file
journalFile = '',
-- this is the path to the python binary with beancount installed
pythonPath = 'python3',
},
},
docs = {
description = [[
https://github.com/polarmutex/beancount-language-server#installation
See https://github.com/polarmutex/beancount-language-server#configuration for configuration options
]],
default_config = {
root_dir = [[root_pattern("elm.json")]],
},
},
}

View file

@ -1,47 +0,0 @@
local util = require 'lspconfig.util'
return {
default_config = {
filetypes = { 'bicep' },
root_dir = util.find_git_ancestor,
init_options = {},
},
docs = {
description = [=[
https://github.com/azure/bicep
Bicep language server
Bicep language server can be installed by downloading and extracting a release of bicep-langserver.zip from [Bicep GitHub releases](https://github.com/Azure/bicep/releases).
Bicep language server requires the [dotnet-sdk](https://dotnet.microsoft.com/download) to be installed.
Neovim does not have built-in support for the bicep filetype which is required for lspconfig to automatically launch the language server.
Filetype detection can be added via an autocmd:
```lua
vim.cmd [[ autocmd BufNewFile,BufRead *.bicep set filetype=bicep ]]
```
**By default, bicep language server does not have a `cmd` set.** This is because nvim-lspconfig does not make assumptions about your path. You must add the following to your init.vim or init.lua to set `cmd` to the absolute path ($HOME and ~ are not expanded) of the unzipped run script or binary.
```lua
local bicep_lsp_bin = "/path/to/bicep-langserver/Bicep.LangServer.dll"
require'lspconfig'.bicep.setup{
cmd = { "dotnet", bicep_lsp_bin };
...
}
```
To download the latest release and place in /usr/local/bin/bicep-langserver:
```bash
(cd $(mktemp -d) \
&& curl -fLO https://github.com/Azure/bicep/releases/latest/download/bicep-langserver.zip \
&& rm -rf /usr/local/bin/bicep-langserver \
&& unzip -d /usr/local/bin/bicep-langserver bicep-langserver.zip)
```
]=],
default_config = {
root_dir = [[util.find_git_ancestor]],
},
},
}

View file

@ -1,19 +0,0 @@
local util = require 'lspconfig.util'
return {
default_config = {
filetypes = { 'bsl', 'os' },
root_dir = util.find_git_ancestor,
},
docs = {
description = [[
https://github.com/1c-syntax/bsl-language-server
Language Server Protocol implementation for 1C (BSL) - 1C:Enterprise 8 and OneScript languages.
]],
default_config = {
root_dir = [[root_pattern(".git")]],
},
},
}

View file

@ -1,42 +0,0 @@
local util = require 'lspconfig.util'
return {
default_config = {
cmd = { 'ccls' },
filetypes = { 'c', 'cpp', 'objc', 'objcpp' },
root_dir = util.root_pattern('compile_commands.json', '.ccls', '.git'),
-- ccls does not support sending a null root directory
single_file_support = false,
},
docs = {
description = [[
https://github.com/MaskRay/ccls/wiki
ccls relies on a [JSON compilation database](https://clang.llvm.org/docs/JSONCompilationDatabase.html) specified
as compile_commands.json or, for simpler projects, a .ccls.
For details on how to automatically generate one using CMake look [here](https://cmake.org/cmake/help/latest/variable/CMAKE_EXPORT_COMPILE_COMMANDS.html). Alternatively, you can use [Bear](https://github.com/rizsotto/Bear).
Customization options are passed to ccls at initialization time via init_options, a list of available options can be found [here](https://github.com/MaskRay/ccls/wiki/Customization#initialization-options). For example:
```lua
local lspconfig = require'lspconfig'
lspconfig.ccls.setup {
init_options = {
compilationDatabaseDirectory = "build";
index = {
threads = 0;
};
clang = {
excludeArgs = { "-frounding-math"} ;
};
}
}
```
]],
default_config = {
root_dir = [[root_pattern("compile_commands.json", ".ccls", ".git")]],
},
},
}

View file

@ -1,73 +0,0 @@
local util = require 'lspconfig.util'
-- https://clangd.llvm.org/extensions.html#switch-between-sourceheader
local function switch_source_header(bufnr)
bufnr = util.validate_bufnr(bufnr)
local clangd_client = util.get_active_client_by_name(bufnr, 'clangd')
local params = { uri = vim.uri_from_bufnr(bufnr) }
if clangd_client then
clangd_client.request('textDocument/switchSourceHeader', params, function(err, result)
if err then
error(tostring(err))
end
if not result then
print 'Corresponding file cannot be determined'
return
end
vim.api.nvim_command('edit ' .. vim.uri_to_fname(result))
end, bufnr)
else
print 'method textDocument/switchSourceHeader is not supported by any servers active on the current buffer'
end
end
local root_pattern = util.root_pattern('compile_commands.json', 'compile_flags.txt', '.git')
local default_capabilities = vim.tbl_deep_extend(
'force',
util.default_config.capabilities or vim.lsp.protocol.make_client_capabilities(),
{
textDocument = {
completion = {
editsNearCursor = true,
},
},
offsetEncoding = { 'utf-8', 'utf-16' },
}
)
return {
default_config = {
cmd = { 'clangd' },
filetypes = { 'c', 'cpp', 'objc', 'objcpp' },
root_dir = function(fname)
local filename = util.path.is_absolute(fname) and fname or util.path.join(vim.loop.cwd(), fname)
return root_pattern(filename)
end,
single_file_support = true,
capabilities = default_capabilities,
},
commands = {
ClangdSwitchSourceHeader = {
function()
switch_source_header(0)
end,
description = 'Switch between source/header',
},
},
docs = {
description = [[
https://clangd.llvm.org/installation.html
**NOTE:** Clang >= 9 is recommended! See [this issue for more](https://github.com/neovim/nvim-lsp/issues/23).
clangd relies on a [JSON compilation database](https://clang.llvm.org/docs/JSONCompilationDatabase.html) specified
as compile_commands.json or, for simpler projects, a compile_flags.txt.
For details on how to automatically generate one using CMake look [here](https://cmake.org/cmake/help/latest/variable/CMAKE_EXPORT_COMPILE_COMMANDS.html). Alternatively, you can use [Bear](https://github.com/rizsotto/Bear).
]],
default_config = {
root_dir = [[root_pattern("compile_commands.json", "compile_flags.txt", ".git") or dirname]],
capabilities = [[default capabilities, with offsetEncoding utf-8]],
},
},
}

View file

@ -1,19 +0,0 @@
local util = require 'lspconfig.util'
return {
default_config = {
cmd = { 'clojure-lsp' },
filetypes = { 'clojure', 'edn' },
root_dir = util.root_pattern('project.clj', 'deps.edn', 'build.boot', 'shadow-cljs.edn', '.git'),
},
docs = {
description = [[
https://github.com/snoe/clojure-lsp
Clojure Language Server
]],
default_config = {
root_dir = [[root_pattern("project.clj", "deps.edn", "build.boot", "shadow-cljs.edn", ".git")]],
},
},
}

View file

@ -1,23 +0,0 @@
local util = require 'lspconfig.util'
return {
default_config = {
cmd = { 'cmake-language-server' },
filetypes = { 'cmake' },
root_dir = util.root_pattern('.git', 'compile_commands.json', 'build'),
single_file_support = true,
init_options = {
buildDirectory = 'build',
},
},
docs = {
description = [[
https://github.com/regen100/cmake-language-server
CMake LSP Implementation
]],
default_config = {
root_dir = [[root_pattern(".git", "compile_commands.json", "build") or dirname]],
},
},
}

View file

@ -1,46 +0,0 @@
local util = require 'lspconfig.util'
return {
default_config = {
cmd = { 'codeql', 'execute', 'language-server', '--check-errors', 'ON_CHANGE', '-q' },
filetypes = { 'ql' },
root_dir = util.root_pattern 'qlpack.yml',
log_level = vim.lsp.protocol.MessageType.Warning,
before_init = function(initialize_params)
initialize_params['workspaceFolders'] = {
{
name = 'workspace',
uri = initialize_params['rootUri'],
},
}
end,
settings = {
search_path = vim.empty_dict(),
},
},
docs = {
description = [[
Reference:
https://help.semmle.com/codeql/codeql-cli.html
Binaries:
https://github.com/github/codeql-cli-binaries
]],
default_config = {
settings = {
search_path = [[list containing all search paths, eg: '~/codeql-home/codeql-repo']],
},
},
},
on_new_config = function(config)
if type(config.settings.search_path) == 'table' and not vim.tbl_isempty(config.settings.search_path) then
local search_path = '--search-path='
for _, path in ipairs(config.settings.search_path) do
search_path = search_path .. vim.fn.expand(path) .. ':'
end
config.cmd = { 'codeql', 'execute', 'language-server', '--check-errors', 'ON_CHANGE', '-q', search_path }
else
config.cmd = { 'codeql', 'execute', 'language-server', '--check-errors', 'ON_CHANGE', '-q' }
end
end,
}

View file

@ -1,20 +0,0 @@
local util = require 'lspconfig.util'
return {
default_config = {
cmd = { 'crystalline' },
filetypes = { 'crystal' },
root_dir = util.root_pattern 'shard.yml' or util.find_git_ancestor,
single_file_support = true,
},
docs = {
description = [[
https://github.com/elbywan/crystalline
Crystal language server.
]],
default_config = {
root_dir = [[root_pattern('shard.yml', '.git') or dirname]],
},
},
}

View file

@ -1,23 +0,0 @@
local util = require 'lspconfig.util'
return {
default_config = {
cmd = { 'csharp-ls' },
root_dir = util.root_pattern('*.sln', '*.csproj', '.git'),
filetypes = { 'cs' },
init_options = {
AutomaticWorkspaceInit = true,
},
},
docs = {
description = [[
https://github.com/razzmatazz/csharp-language-server
Language Server for C#.
csharp-ls requires the [dotnet-sdk](https://dotnet.microsoft.com/download) to be installed.
The preferred way to install csharp-ls is with `dotnet tool install --global csharp-ls`.
]],
},
}

View file

@ -1,49 +0,0 @@
local util = require 'lspconfig.util'
local bin_name = 'vscode-css-language-server'
local cmd = { bin_name, '--stdio' }
if vim.fn.has 'win32' == 1 then
cmd = { 'cmd.exe', '/C', bin_name, '--stdio' }
end
return {
default_config = {
cmd = cmd,
filetypes = { 'css', 'scss', 'less' },
root_dir = util.root_pattern('package.json', '.git'),
single_file_support = true,
settings = {
css = { validate = true },
scss = { validate = true },
less = { validate = true },
},
},
docs = {
description = [[
https://github.com/hrsh7th/vscode-langservers-extracted
`css-languageserver` can be installed via `npm`:
```sh
npm i -g vscode-langservers-extracted
```
Neovim does not currently include built-in snippets. `vscode-css-language-server` only provides completions when snippet support is enabled. To enable completion, install a snippet plugin and add the following override to your language client capabilities during setup.
```lua
--Enable (broadcasting) snippet capability for completion
local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities.textDocument.completion.completionItem.snippetSupport = true
require'lspconfig'.cssls.setup {
capabilities = capabilities,
}
```
]],
default_config = {
root_dir = [[root_pattern("package.json", ".git") or bufdir]],
},
},
}

View file

@ -1,31 +0,0 @@
local util = require 'lspconfig.util'
local bin_name = 'cssmodules-language-server'
local cmd = { bin_name }
if vim.fn.has 'win32' == 1 then
cmd = { 'cmd.exe', '/C', bin_name }
end
return {
default_config = {
cmd = cmd,
filetypes = { 'javascript', 'javascriptreact', 'typescript', 'typescriptreact' },
root_dir = util.find_package_json_ancestor,
},
docs = {
description = [[
https://github.com/antonk52/cssmodules-language-server
Language server for autocompletion and go-to-definition functionality for CSS modules.
You can install cssmodules-language-server via npm:
```sh
npm install -g cssmodules-language-server
```
]],
default_config = {
root_dir = [[root_pattern("package.json")]],
},
},
}

View file

@ -1,33 +0,0 @@
local util = require 'lspconfig.util'
local bin_name = 'cucumber-language-server'
local cmd = { bin_name, '--stdio' }
if vim.fn.has 'win32' == 1 then
cmd = { 'cmd.exe', '/C', bin_name, '--stdio' }
end
return {
default_config = {
cmd = cmd,
filetypes = { 'cucumber' },
root_dir = util.find_git_ancestor,
},
docs = {
description = [[
https://cucumber.io
https://github.com/cucumber/common
https://www.npmjs.com/package/@cucumber/language-server
Language server for Cucumber.
`cucumber-language-server` can be installed via `npm`:
```sh
npm install -g @cucumber/language-server
```
]],
default_config = {
root_dir = [[util.find_git_ancestor]],
},
},
}

View file

@ -1,61 +0,0 @@
local util = require 'lspconfig.util'
local bin_name = 'dart'
local find_dart_sdk_root_path = function()
if os.getenv 'FLUTTER_SDK' then
local flutter_path = os.getenv 'FLUTTER_SDK'
return util.path.join(flutter_path, 'cache', 'dart-sdk', 'bin', 'dart')
elseif vim.fn['executable'] 'flutter' == 1 then
local flutter_path = vim.fn['resolve'](vim.fn['exepath'] 'flutter')
local flutter_bin = vim.fn['fnamemodify'](flutter_path, ':h')
return util.path.join(flutter_bin, 'cache', 'dart-sdk', 'bin', 'dart')
elseif vim.fn['executable'] 'dart' == 1 then
return vim.fn['resolve'](vim.fn['exepath'] 'dart')
else
return ''
end
end
local analysis_server_snapshot_path = function()
local dart_sdk_root_path = vim.fn['fnamemodify'](find_dart_sdk_root_path(), ':h')
local snapshot = util.path.join(dart_sdk_root_path, 'snapshots', 'analysis_server.dart.snapshot')
if vim.fn['has'] 'win32' == 1 or vim.fn['has'] 'win64' == 1 then
snapshot = snapshot:gsub('/', '\\')
end
return snapshot
end
return {
default_config = {
cmd = { bin_name, analysis_server_snapshot_path(), '--lsp' },
filetypes = { 'dart' },
root_dir = util.root_pattern 'pubspec.yaml',
init_options = {
onlyAnalyzeProjectsWithOpenFiles = true,
suggestFromUnimportedLibraries = true,
closingLabels = true,
outline = true,
flutterOutline = true,
},
settings = {
dart = {
completeFunctionCalls = true,
showTodos = true,
},
},
},
docs = {
package_json = 'https://raw.githubusercontent.com/Dart-Code/Dart-Code/master/package.json',
description = [[
https://github.com/dart-lang/sdk/tree/master/pkg/analysis_server/tool/lsp_spec
Language server for dart.
]],
default_config = {
root_dir = [[root_pattern("pubspec.yaml")]],
},
},
}

View file

@ -1,115 +0,0 @@
local util = require 'lspconfig.util'
local lsp = vim.lsp
local function buf_cache(bufnr)
local params = {}
params['referrer'] = { uri = vim.uri_from_bufnr(bufnr) }
params['uris'] = {}
lsp.buf_request(bufnr, 'deno/cache', params, function(err)
if err then
error(tostring(err))
end
end)
end
local function virtual_text_document_handler(uri, result)
if not result then
return nil
end
for client_id, res in pairs(result) do
local lines = vim.split(res.result, '\n')
local bufnr = vim.uri_to_bufnr(uri)
local current_buf = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
if #current_buf ~= 0 then
return nil
end
vim.api.nvim_buf_set_lines(bufnr, 0, -1, nil, lines)
vim.api.nvim_buf_set_option(bufnr, 'readonly', true)
vim.api.nvim_buf_set_option(bufnr, 'modified', false)
vim.api.nvim_buf_set_option(bufnr, 'modifiable', false)
lsp.buf_attach_client(bufnr, client_id)
end
end
local function virtual_text_document(uri)
local params = {
textDocument = {
uri = uri,
},
}
local result = lsp.buf_request_sync(0, 'deno/virtualTextDocument', params)
virtual_text_document_handler(uri, result)
end
local function denols_handler(err, result, ctx)
if not result or vim.tbl_isempty(result) then
return nil
end
for _, res in pairs(result) do
local uri = res.uri or res.targetUri
if uri:match '^deno:' then
virtual_text_document(uri)
res['uri'] = uri
res['targetUri'] = uri
end
end
lsp.handlers[ctx.method](err, result, ctx)
end
return {
default_config = {
cmd = { 'deno', 'lsp' },
filetypes = {
'javascript',
'javascriptreact',
'javascript.jsx',
'typescript',
'typescriptreact',
'typescript.tsx',
},
root_dir = util.root_pattern('deno.json', 'deno.jsonc', 'tsconfig.json', '.git'),
init_options = {
enable = true,
lint = false,
unstable = false,
},
handlers = {
['textDocument/definition'] = denols_handler,
['textDocument/references'] = denols_handler,
},
},
commands = {
DenolsCache = {
function()
buf_cache(0)
end,
description = 'Cache a module and all of its dependencies.',
},
},
docs = {
package_json = 'https://raw.githubusercontent.com/denoland/vscode_deno/main/package.json',
description = [[
https://github.com/denoland/deno
Deno's built-in language server
To approrpiately highlight codefences returned from denols, you will need to augment vim.g.markdown_fenced languages
in your init.lua. Example:
```lua
vim.g.markdown_fenced_languages = {
"ts=typescript"
}
```
]],
default_config = {
root_dir = [[root_pattern("deno.json", "deno.jsonc", "tsconfig.json", ".git")]],
},
},
}

View file

@ -1,26 +0,0 @@
local util = require 'lspconfig.util'
return {
default_config = {
cmd = { 'dhall-lsp-server' },
filetypes = { 'dhall' },
root_dir = util.find_git_ancestor,
single_file_support = true,
},
docs = {
description = [[
https://github.com/dhall-lang/dhall-haskell/tree/master/dhall-lsp-server
language server for dhall
`dhall-lsp-server` can be installed via cabal:
```sh
cabal install dhall-lsp-server
```
prebuilt binaries can be found [here](https://github.com/dhall-lang/dhall-haskell/releases).
]],
default_config = {
root_dir = [[root_pattern(".git") or dirname]],
},
},
}

View file

@ -1,29 +0,0 @@
local util = require 'lspconfig.util'
local bin_name = 'diagnostic-languageserver'
local cmd = { bin_name, '--stdio' }
if vim.fn.has 'win32' == 1 then
cmd = { 'cmd.exe', '/C', bin_name, '--stdio' }
end
return {
default_config = {
cmd = cmd,
root_dir = util.find_git_ancestor,
single_file_support = true,
filetypes = {},
},
docs = {
description = [[
https://github.com/iamcco/diagnostic-languageserver
Diagnostic language server integrate with linters.
]],
default_config = {
filetypes = 'Empty by default, override to add filetypes',
root_dir = "Vim's starting directory",
init_options = 'Configuration from https://github.com/iamcco/diagnostic-languageserver#config--document',
},
},
}

View file

@ -1,30 +0,0 @@
local util = require 'lspconfig.util'
local bin_name = 'docker-langserver'
local cmd = { bin_name, '--stdio' }
if vim.fn.has 'win32' == 1 then
cmd = { 'cmd.exe', '/C', bin_name, '--stdio' }
end
return {
default_config = {
cmd = cmd,
filetypes = { 'dockerfile' },
root_dir = util.root_pattern 'Dockerfile',
single_file_support = true,
},
docs = {
description = [[
https://github.com/rcjsuen/dockerfile-language-server-nodejs
`docker-langserver` can be installed via `npm`:
```sh
npm install -g dockerfile-language-server-nodejs
```
]],
default_config = {
root_dir = [[root_pattern("Dockerfile")]],
},
},
}

View file

@ -1,27 +0,0 @@
local util = require 'lspconfig.util'
local bin_name = 'dot-language-server'
local cmd = { bin_name, '--stdio' }
if vim.fn.has 'win32' == 1 then
cmd = { 'cmd.exe', '/C', bin_name, '--stdio' }
end
return {
default_config = {
cmd = cmd,
filetypes = { 'dot' },
root_dir = util.find_git_ancestor,
single_file_support = true,
},
docs = {
description = [[
https://github.com/nikeee/dot-language-server
`dot-language-server` can be installed via `npm`:
```sh
npm install -g dot-language-server
```
]],
},
}

View file

@ -1,43 +0,0 @@
local util = require 'lspconfig.util'
return {
default_config = {
cmd = { 'efm-langserver' },
root_dir = util.find_git_ancestor,
single_file_support = true,
},
docs = {
description = [[
https://github.com/mattn/efm-langserver
General purpose Language Server that can use specified error message format generated from specified command.
Requires at minimum EFM version [v0.0.38](https://github.com/mattn/efm-langserver/releases/tag/v0.0.38) to support
launching the language server on single files. If on an older version of EFM, disable single file support:
```lua
require('lspconfig')['efm'].setup{
settings = ..., -- You must populate this according to the EFM readme
filetypes = ..., -- Populate this according to the note below
single_file_support = false, -- This is the important line for supporting older version of EFM
}
```
Note: In order for neovim's built-in language server client to send the appropriate `languageId` to EFM, **you must
specify `filetypes` in your call to `setup{}`**. Otherwise `lspconfig` will launch EFM on the `BufEnter` instead
of the `FileType` autocommand, and the `filetype` variable used to populate the `languageId` will not yet be set.
```lua
require('lspconfig')['efm'].setup{
settings = ..., -- You must populate this according to the EFM readme
filetypes = { 'python','cpp','lua' }
}
```
]],
default_config = {
root_dir = [[util.root_pattern(".git")]],
},
},
}

View file

@ -1,40 +0,0 @@
local util = require 'lspconfig.util'
return {
default_config = {
filetypes = { 'elixir', 'eelixir' },
root_dir = function(fname)
return util.root_pattern('mix.exs', '.git')(fname) or vim.loop.os_homedir()
end,
},
docs = {
package_json = 'https://raw.githubusercontent.com/elixir-lsp/vscode-elixir-ls/master/package.json',
description = [[
https://github.com/elixir-lsp/elixir-ls
`elixir-ls` can be installed by following the instructions [here](https://github.com/elixir-lsp/elixir-ls#building-and-running).
```bash
curl -fLO https://github.com/elixir-lsp/elixir-ls/releases/latest/download/elixir-ls.zip
unzip elixir-ls.zip -d /path/to/elixir-ls
# Unix
chmod +x /path/to/elixir-ls/language_server.sh
```
**By default, elixir-ls doesn't have a `cmd` set.** This is because nvim-lspconfig does not make assumptions about your path. You must add the following to your init.vim or init.lua to set `cmd` to the absolute path ($HOME and ~ are not expanded) of your unzipped elixir-ls.
```lua
require'lspconfig'.elixirls.setup{
-- Unix
cmd = { "/path/to/elixir-ls/language_server.sh" };
-- Windows
cmd = { "/path/to/elixir-ls/language_server.bat" };
...
}
```
]],
default_config = {
root_dir = [[root_pattern("mix.exs", ".git") or vim.loop.os_homedir()]],
},
},
}

View file

@ -1,48 +0,0 @@
local util = require 'lspconfig.util'
local lsp = vim.lsp
local api = vim.api
local bin_name = 'elm-language-server'
local cmd = { bin_name }
if vim.fn.has 'win32' == 1 then
cmd = { 'cmd.exe', '/C', bin_name }
end
local default_capabilities = lsp.protocol.make_client_capabilities()
default_capabilities.offsetEncoding = { 'utf-8', 'utf-16' }
local elm_root_pattern = util.root_pattern 'elm.json'
return {
default_config = {
cmd = cmd,
-- TODO(ashkan) if we comment this out, it will allow elmls to operate on elm.json. It seems like it could do that, but no other editor allows it right now.
filetypes = { 'elm' },
root_dir = function(fname)
local filetype = api.nvim_buf_get_option(0, 'filetype')
if filetype == 'elm' or (filetype == 'json' and fname:match 'elm%.json$') then
return elm_root_pattern(fname)
end
end,
init_options = {
elmPath = 'elm',
elmFormatPath = 'elm-format',
elmTestPath = 'elm-test',
elmAnalyseTrigger = 'change',
},
},
docs = {
package_json = 'https://raw.githubusercontent.com/elm-tooling/elm-language-client-vscode/master/package.json',
description = [[
https://github.com/elm-tooling/elm-language-server#installation
If you don't want to use Nvim to install it, then you can use:
```sh
npm install -g elm elm-test elm-format @elm-tooling/elm-language-server
```
]],
default_config = {
root_dir = [[root_pattern("elm.json")]],
},
},
}

Some files were not shown because too many files have changed in this diff Show more