Add coc.nvim plugin (requires nodejs)

This commit is contained in:
Anthony Rose 2020-10-30 13:36:11 +00:00
parent e8543f9d11
commit eb2488bfd1
25 changed files with 103347 additions and 0 deletions

10
coc-settings.json Normal file
View file

@ -0,0 +1,10 @@
{
"languageserver": {
"go": {
"command": "gopls",
"rootPatterns": ["go.mod"],
"trace.server": "verbose",
"filetypes": ["go"]
}
}
}

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

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

View file

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

View file

@ -0,0 +1,283 @@
<p align="center">
<a href="https://www.vim.org/scripts/script.php?script_id=5779">
<img alt="Coc Logo" src="https://user-images.githubusercontent.com/251450/55009068-f4ed2780-501c-11e9-9a3b-cf3aa6ab9272.png" height="160" />
</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-MIT-brightgreen.svg?style=flat-square"></a>
<a href="https://github.com/neoclide/coc.nvim/actions"><img alt="Actions" src="https://img.shields.io/github/workflow/status/neoclide/coc.nvim/coc.nvim%20CI?style=flat-square"></a>
<a href="/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://user-images.githubusercontent.com/251450/55285193-400a9000-53b9-11e9-8cff-ffe4983c5947.gif" width="60%" />
_True snippet and additional text editing support_
## Why?
- 🚀 **Fast**: [instant increment completion](https://github.com/neoclide/coc.nvim/wiki/Completion-with-sources), increment buffer sync using buffer update events.
- 💎 **Reliable**: typed language, tested with CI.
- 🌟 **Featured**: [full LSP support](https://github.com/neoclide/coc.nvim/wiki/Language-servers#supported-features)
- ❤️ **Flexible**: [configured like VSCode](https://github.com/neoclide/coc.nvim/wiki/Using-the-configuration-file), [extensions work like in VSCode](https://github.com/neoclide/coc.nvim/wiki/Using-coc-extensions)
## Quick Start
Install [nodejs](https://nodejs.org/en/download/) >= 10.12:
```sh
curl -sL install-node.now.sh/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', {'do': 'yarn install --frozen-lockfile'}
```
in your `.vimrc` or `init.vim`, then restart Vim and run `:PlugInstall`.
Checkout [Install
coc.nvim](https://github.com/neoclide/coc.nvim/wiki/Install-coc.nvim) for
more info.
You **have to** install coc extension or configure language servers for
LSP support.
Install extensions like:
:CocInstall coc-json coc-tsserver
Or configure language server in `coc-settings.json` opened by
`:CocConfig`, like:
```json
{
"languageserver": {
"go": {
"command": "gopls",
"rootPatterns": ["go.mod"],
"trace.server": "verbose",
"filetypes": ["go"]
}
}
}
```
Checkout wiki for more details:
- [Completion with sources](https://github.com/neoclide/coc.nvim/wiki/Completion-with-sources)
- [Using the configuration file](https://github.com/neoclide/coc.nvim/wiki/Using-the-configuration-file)
- [Using coc extensions](https://github.com/neoclide/coc.nvim/wiki/Using-coc-extensions)
- [Configure language servers](https://github.com/neoclide/coc.nvim/wiki/Language-servers)
- [F.A.Q](https://github.com/neoclide/coc.nvim/wiki/F.A.Q)
Checkout `:h coc-nvim` for vim interface.
## Example vim configuration
Configuration is required to make coc.nvim easier to work with, since it
doesn't change your key-mappings or Vim options. This is done as much as
possible to avoid conflict with your other plugins.
**❗Important**: Some Vim plugins could change key mappings. Please use
`:verbose imap <tab>` to make sure that your keymap has taken effect.
```vim
" TextEdit might fail if hidden is not set.
set hidden
" Some servers have issues with backup files, see #649.
set nobackup
set nowritebackup
" Give more space for displaying messages.
set cmdheight=2
" Having longer updatetime (default is 4000 ms = 4 s) leads to noticeable
" delays and poor user experience.
set updatetime=300
" Don't pass messages to |ins-completion-menu|.
set shortmess+=c
" Always show the signcolumn, otherwise it would shift the text each time
" diagnostics appear/become resolved.
if has("patch-8.1.1564")
" Recently vim can merge signcolumn and number column into one
set signcolumn=number
else
set signcolumn=yes
endif
" Use tab for trigger completion with characters ahead and navigate.
" NOTE: Use command ':verbose imap <tab>' to make sure tab is not mapped by
" other plugin before putting this into your config.
inoremap <silent><expr> <TAB>
\ pumvisible() ? "\<C-n>" :
\ <SID>check_back_space() ? "\<TAB>" :
\ coc#refresh()
inoremap <expr><S-TAB> pumvisible() ? "\<C-p>" : "\<C-h>"
function! s:check_back_space() abort
let col = col('.') - 1
return !col || getline('.')[col - 1] =~# '\s'
endfunction
" Use <c-space> to trigger completion.
if has('nvim')
inoremap <silent><expr> <c-space> coc#refresh()
else
inoremap <silent><expr> <c-@> coc#refresh()
endif
" Make <CR> auto-select the first completion item and notify coc.nvim to
" format on enter, <cr> could be remapped by other vim plugin
inoremap <silent><expr> <cr> pumvisible() ? coc#_select_confirm()
\: "\<C-g>u\<CR>\<c-r>=coc#on_enter()\<CR>"
" Use `[g` and `]g` to navigate diagnostics
" Use `:CocDiagnostics` to get all diagnostics of current buffer in location list.
nmap <silent> [g <Plug>(coc-diagnostic-prev)
nmap <silent> ]g <Plug>(coc-diagnostic-next)
" GoTo code navigation.
nmap <silent> gd <Plug>(coc-definition)
nmap <silent> gy <Plug>(coc-type-definition)
nmap <silent> gi <Plug>(coc-implementation)
nmap <silent> gr <Plug>(coc-references)
" Use K to show documentation in preview window.
nnoremap <silent> K :call <SID>show_documentation()<CR>
function! s:show_documentation()
if (index(['vim','help'], &filetype) >= 0)
execute 'h '.expand('<cword>')
elseif (coc#rpc#ready())
call CocActionAsync('doHover')
else
execute '!' . &keywordprg . " " . expand('<cword>')
endif
endfunction
" Highlight the symbol and its references when holding the cursor.
autocmd CursorHold * silent call CocActionAsync('highlight')
" Symbol renaming.
nmap <leader>rn <Plug>(coc-rename)
" Formatting selected code.
xmap <leader>f <Plug>(coc-format-selected)
nmap <leader>f <Plug>(coc-format-selected)
augroup mygroup
autocmd!
" Setup formatexpr specified filetype(s).
autocmd FileType typescript,json setl formatexpr=CocAction('formatSelected')
" Update signature help on jump placeholder.
autocmd User CocJumpPlaceholder call CocActionAsync('showSignatureHelp')
augroup end
" Applying codeAction to the selected region.
" Example: `<leader>aap` for current paragraph
xmap <leader>a <Plug>(coc-codeaction-selected)
nmap <leader>a <Plug>(coc-codeaction-selected)
" Remap keys for applying codeAction to the current buffer.
nmap <leader>ac <Plug>(coc-codeaction)
" Apply AutoFix to problem on the current line.
nmap <leader>qf <Plug>(coc-fix-current)
" Map function and class text objects
" NOTE: Requires 'textDocument.documentSymbol' support from the language server.
xmap if <Plug>(coc-funcobj-i)
omap if <Plug>(coc-funcobj-i)
xmap af <Plug>(coc-funcobj-a)
omap af <Plug>(coc-funcobj-a)
xmap ic <Plug>(coc-classobj-i)
omap ic <Plug>(coc-classobj-i)
xmap ac <Plug>(coc-classobj-a)
omap ac <Plug>(coc-classobj-a)
" Remap <C-f> and <C-b> for scroll float windows/popups.
" Note coc#float#scroll works on neovim >= 0.4.3 or vim >= 8.2.0750
nnoremap <nowait><expr> <C-f> coc#float#has_scroll() ? coc#float#scroll(1) : "\<C-f>"
nnoremap <nowait><expr> <C-b> coc#float#has_scroll() ? coc#float#scroll(0) : "\<C-b>"
inoremap <nowait><expr> <C-f> coc#float#has_scroll() ? "\<c-r>=coc#float#scroll(1)\<cr>" : "\<Right>"
inoremap <nowait><expr> <C-b> coc#float#has_scroll() ? "\<c-r>=coc#float#scroll(0)\<cr>" : "\<Left>"
" 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 CocAction('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 CocAction('runCommand', 'editor.action.organizeImport')
" Add (Neo)Vim's native statusline support.
" NOTE: Please see `:h coc-status` for integrations with external plugins that
" provide custom statusline: lightline.vim, vim-airline.
set statusline^=%{coc#status()}%{get(b:,'coc_current_function','')}
" Mappings for CoCList
" Show all diagnostics.
nnoremap <silent><nowait> <space>a :<C-u>CocList diagnostics<cr>
" Manage extensions.
nnoremap <silent><nowait> <space>e :<C-u>CocList extensions<cr>
" Show commands.
nnoremap <silent><nowait> <space>c :<C-u>CocList commands<cr>
" Find symbol of current document.
nnoremap <silent><nowait> <space>o :<C-u>CocList outline<cr>
" Search workspace symbols.
nnoremap <silent><nowait> <space>s :<C-u>CocList -I symbols<cr>
" Do default action for next item.
nnoremap <silent><nowait> <space>j :<C-u>CocNext<CR>
" Do default action for previous item.
nnoremap <silent><nowait> <space>k :<C-u>CocPrev<CR>
" Resume latest coc list.
nnoremap <silent><nowait> <space>p :<C-u>CocListResume<CR>
```
## Articles
- [coc.nvim 插件体系介绍](https://zhuanlan.zhihu.com/p/65524706)
- [CocList 入坑指南](https://zhuanlan.zhihu.com/p/71846145)
- [Create coc.nvim extension to improve Vim experience](https://medium.com/@chemzqm/create-coc-nvim-extension-to-improve-vim-experience-4461df269173)
- [How to write a coc.nvim extension (and why)](https://samroeca.com/coc-plugin.html)
## Trouble shooting
Try these steps when you have problem with coc.nvim.
- Make sure your Vim version >= 8.0 by command `:version`.
- If service failed to start, use command `:CocInfo` or `:checkhealth` on Neovim.
- Checkout the log of coc.nvim by command `:CocOpenLog`.
- When you have issues with the language server, it's recommended to [checkout
the output](https://github.com/neoclide/coc.nvim/wiki/Debug-language-server#using-output-channel).
## Feedback
- If you think Coc is useful, consider giving it a star.
- If you have a question, [ask on gitter](https://gitter.im/neoclide/coc.nvim)
- 中文用户请到 [中文 gitter](https://gitter.im/neoclide/coc-cn) 讨论
- If something is not working, [create an
issue](https://github.com/neoclide/coc.nvim/issues/new).
<img src="https://user-images.githubusercontent.com/251450/57566955-fb850200-7404-11e9-960f-711673f1a461.png" width="593" height="574">
## License
MIT

View file

@ -0,0 +1,199 @@
let g:coc#_context = {'start': 0, 'preselect': -1,'candidates': []}
let g:coc_user_config = get(g:, 'coc_user_config', {})
let g:coc_global_extensions = get(g:, 'coc_global_extensions', [])
let g:coc_cygqwin_path_prefixes = get(g:, 'coc_cygqwin_path_prefixes', {})
let g:coc_selected_text = ''
let g:coc_vim_commands = []
let s:watched_keys = []
let s:is_vim = !has('nvim')
let s:error_sign = get(g:, 'coc_status_error_sign', has('mac') ? '❌ ' : 'E')
let s:warning_sign = get(g:, 'coc_status_warning_sign', has('mac') ? '⚠️ ' : 'W')
let s:select_api = exists('*nvim_select_popupmenu_item')
let s:callbacks = {}
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#refresh() abort
return "\<c-r>=coc#start()\<CR>"
endfunction
function! coc#on_enter()
if !coc#rpc#ready()
return ''
endif
if s:is_vim
call coc#rpc#notify('CocAutocmd', ['Enter', bufnr('%')])
else
call coc#rpc#request('CocAutocmd', ['Enter', bufnr('%')])
endif
return ''
endfunction
function! coc#_insert_key(method, key, ...) abort
if get(a:, 1, 1)
call coc#_cancel()
endif
return "\<c-r>=coc#rpc#".a:method."('doKeymap', ['".a:key."'])\<CR>"
endfunction
function! coc#_complete() abort
let items = get(g:coc#_context, 'candidates', [])
let preselect = get(g:coc#_context, 'preselect', -1)
call complete(
\ g:coc#_context.start + 1,
\ items)
if s:select_api && len(items) && preselect != -1
call nvim_select_popupmenu_item(preselect, v:false, v:false, {})
endif
return ''
endfunction
function! coc#_do_complete(start, items, preselect)
let g:coc#_context = {
\ 'start': a:start,
\ 'candidates': a:items,
\ 'preselect': a:preselect
\}
if mode() =~# 'i' && &paste != 1
call feedkeys("\<Plug>CocRefresh", 'i')
endif
endfunction
function! coc#_select_confirm() abort
if !exists('*complete_info')
throw 'coc#_select_confirm requires complete_info function to work'
endif
let selected = complete_info()['selected']
if selected != -1
return "\<C-y>"
elseif pumvisible()
return "\<down>\<C-y>"
endif
return ''
endfunction
function! coc#_selected()
if !pumvisible() | return 0 | endif
return coc#rpc#request('hasSelected', [])
endfunction
function! coc#_hide() abort
if !pumvisible() | return | endif
call feedkeys("\<C-e>", 'in')
endfunction
function! coc#_cancel()
" hack for close pum
if pumvisible() && &paste != 1
let g:coc#_context = {'start': 0, 'preselect': -1,'candidates': []}
call feedkeys("\<Plug>CocRefresh", 'i')
endif
endfunction
function! coc#_select() abort
if !pumvisible() | return | endif
call feedkeys("\<C-y>", 'in')
endfunction
function! coc#start(...)
let opt = coc#util#get_complete_option()
call CocActionAsync('startCompletion', extend(opt, get(a:, 1, {})))
return ''
endfunction
" used for statusline
function! coc#status()
let info = get(b:, 'coc_diagnostic_info', {})
let msgs = []
if get(info, 'error', 0)
call add(msgs, s:error_sign . info['error'])
endif
if get(info, 'warning', 0)
call add(msgs, s:warning_sign . info['warning'])
endif
return s:trim(join(msgs, ' ') . ' ' . get(g:, 'coc_status', ''))
endfunction
function! s:trim(str)
if exists('*trim')
return trim(a:str)
endif
return substitute(a:str, '\s\+$', '', '')
endfunction
function! coc#config(section, value)
let g:coc_user_config[a:section] = a:value
call coc#rpc#notify('updateConfig', [a:section, a:value])
endfunction
function! coc#add_extension(...)
if a:0 == 0 | return | endif
call extend(g:coc_global_extensions, a:000)
endfunction
function! coc#_watch(key)
if s:is_vim | return | endif
if index(s:watched_keys, a:key) == -1
call add(s:watched_keys, a:key)
call dictwatcheradd(g:, a:key, function('s:GlobalChange'))
endif
endfunction
function! coc#_unwatch(key)
if s:is_vim | return | endif
let idx = index(s:watched_keys, a:key)
if idx != -1
call remove(s:watched_keys, idx)
call dictwatcherdel(g:, a:key, function('s:GlobalChange'))
endif
endfunction
function! s:GlobalChange(dict, key, val)
call coc#rpc#notify('GlobalChange', [a:key, get(a:val, 'old', v:null), get(a:val, 'new', v:null)])
endfunction
function! coc#_map()
if !s:select_api | return | endif
for i in range(1, 9)
exe 'inoremap <buffer> '.i.' <Cmd>call nvim_select_popupmenu_item('.(i - 1).', v:true, v:true, {})<cr>'
endfor
endfunction
function! coc#_unmap()
if !s:select_api | return | endif
for i in range(1, 9)
exe 'silent! iunmap <buffer> '.i
endfor
endfunction
function! coc#on_notify(id, method, Cb)
let key = a:id. '-'.a:method
let s:callbacks[key] = a:Cb
call coc#rpc#notify('registNotification', [a:id, a:method])
endfunction
function! coc#do_notify(id, method, result)
let key = a:id. '-'.a:method
let Fn = s:callbacks[key]
if !empty(Fn)
call Fn(a:result)
endif
endfunction

View file

@ -0,0 +1,580 @@
" ============================================================================
" Description: Client api used by vim8
" Author: Qiming Zhao <chemzqm@gmail.com>
" Licence: MIT licence
" Last Modified: June 28, 2019
" ============================================================================
if has('nvim') | finish | endif
let s:funcs = {}
let s:prop_id = 1000
let s:namespace_id = 1
let s:namespace_cache = {}
" helper {{
function! s:buf_line_count(bufnr) abort
if bufnr('%') == a:bufnr
return line('$')
endif
if exists('*getbufline')
let lines = getbufline(a:bufnr, 1, '$')
return len(lines)
endif
let curr = bufnr('%')
execute 'buffer '.a:bufnr
let n = line('$')
execute 'buffer '.curr
return n
endfunction
function! s:execute(cmd)
if a:cmd =~# '^echo'
execute a:cmd
else
silent! execute a:cmd
endif
endfunction
" }}"
" nvim client methods {{
function! s:funcs.set_current_dir(dir) abort
execute 'cd '.a:dir
endfunction
function! s:funcs.set_var(name, value) abort
execute 'let g:'.a:name.'= a:value'
endfunction
function! s:funcs.del_var(name) abort
execute 'unlet g:'.a:name
endfunction
function! s:funcs.set_option(name, value) abort
execute 'let &'.a:name.' = a:value'
endfunction
function! s:funcs.set_current_buf(bufnr) abort
if !bufexists(a:bufnr) | return | endif
execute 'buffer '.a:bufnr
endfunction
function! s:funcs.set_current_win(win_id) abort
let [tabnr, winnr] = win_id2tabwin(a:win_id)
if tabnr == 0 | return | endif
execute 'normal! '.tabnr.'gt'
execute winnr.' wincmd w'
endfunction
function! s:funcs.set_current_tabpage(tabnr) abort
execute 'normal! '.a:tabnr.'gt'
endfunction
function! s:funcs.list_wins() abort
return map(getwininfo(), 'v:val["winid"]')
endfunction
function! s:funcs.call_atomic(calls)
let res = []
for [key, arglist] in a:calls
let name = key[5:]
try
call add(res, call(s:funcs[name], arglist))
catch /.*/
return [res, v:exception]
endtry
endfor
return [res, v:null]
endfunction
function! s:funcs.set_client_info(...) abort
endfunction
function! s:funcs.subscribe(...) abort
endfunction
function! s:funcs.unsubscribe(...) abort
endfunction
function! s:funcs.call_function(method, args) abort
return call(a:method, a:args)
endfunction
function! s:funcs.call_dict_function(dict, method, args) abort
return call(a:method, a:args, a:dict)
endfunction
function! s:funcs.command(command) abort
" command that could cause cursor vanish
if a:command =~# '^echo' || a:command =~# '^redraw' || a:command =~# '^sign place'
call timer_start(0, {-> s:execute(a:command)})
else
execute a:command
endif
endfunction
function! s:funcs.eval(expr) abort
return eval(a:expr)
endfunction
function! s:funcs.get_api_info()
let names = coc#api#func_names()
return [1, {'functions': map(names, '{"name": "nvim_".v:val}')}]
endfunction
function! s:funcs.list_bufs()
return map(getbufinfo({'buflisted': 1}), 'v:val["bufnr"]')
endfunction
function! s:funcs.feedkeys(keys, mode, escape_csi)
call feedkeys(a:keys, a:mode)
endfunction
function! s:funcs.list_runtime_paths()
return split(&runtimepath, ',')
endfunction
function! s:funcs.command_output(cmd)
return execute(a:cmd)
endfunction
function! s:funcs.get_current_line()
return getline('.')
endfunction
function! s:funcs.set_current_line(line)
call setline('.', a:line)
endfunction
function! s:funcs.del_current_line(line)
execute 'normal! dd'
endfunction
function! s:funcs.get_var(var)
return get(g:, a:var, v:null)
endfunction
function! s:funcs.get_vvar(var)
return get(v:, a:var, v:null)
endfunction
function! s:funcs.get_option(name)
return eval('&'.a:name)
endfunction
function! s:funcs.get_current_buf()
return bufnr('%')
endfunction
function! s:funcs.get_current_win()
return win_getid()
endfunction
function! s:funcs.get_current_tabpage()
return tabpagenr()
endfunction
function! s:funcs.list_tabpages()
return range(1, tabpagenr('$'))
endfunction
function! s:funcs.get_mode()
return {'blocking': v:false, 'mode': mode()}
endfunction
function! s:funcs.strwidth(str)
return strwidth(a:str)
endfunction
function! s:funcs.out_write(str)
echon a:str
endfunction
function! s:funcs.err_write(str)
echoerr a:str
endfunction
function! s:funcs.err_writeln(str)
echoerr a:str
endfunction
function! s:funcs.create_namespace(name) abort
if empty(a:name)
let id = s:namespace_id
let s:namespace_id = s:namespace_id + 1
return id
endif
let id = get(s:namespace_cache, a:name, 0)
if !id
let id = s:namespace_id
let s:namespace_id = s:namespace_id + 1
let s:namespace_cache[a:name] = id
endif
return id
endfunction
" }}
" buffer methods {{
function! s:funcs.buf_set_option(bufnr, name, val)
let val = a:val
if val is v:true
let val = 1
elseif val is v:false
let val = 0
endif
return setbufvar(a:bufnr, '&'.a:name, val)
endfunction
function! s:funcs.buf_get_changedtick(bufnr)
return getbufvar(a:bufnr, 'changedtick')
endfunction
function! s:funcs.buf_is_valid(bufnr)
return bufloaded(a:bufnr) ? v:true : v:false
endfunction
function! s:funcs.buf_get_mark(bufnr, name)
let nr = bufnr('%')
if a:bufnr != 0 || a:bufnr != nr
throw 'buf_get_mark support current buffer only'
endif
return [line("'" . a:name), col("'" . a:name)]
endfunction
function! s:funcs.buf_add_highlight(bufnr, srcId, hlGroup, line, colStart, colEnd) abort
if !has('textprop')
return
endif
let bufnr = a:bufnr == 0 ? bufnr('%') : a:bufnr
let key = 'Coc'.a:hlGroup.(a:srcId != -1 ? a:srcId : '')
if empty(prop_type_get(key, {'bufnr': a:bufnr}))
call prop_type_add(key, {'highlight': a:hlGroup, 'combine': 1, 'bufnr': a:bufnr})
if a:srcId != -1
let cached = getbufvar(bufnr, 'prop_namespace_'.a:srcId, [])
call add(cached, key)
call setbufvar(bufnr, 'prop_namespace_'.a:srcId, cached)
endif
endif
let total = strlen(getbufline(bufnr, a:line + 1)[0])
let end = a:colEnd
if end == -1
let end = total
else
let end = min([end, total])
endif
if end <= a:colStart
return
endif
let id = s:prop_id
let s:prop_id = id + 1
try
call prop_add(a:line + 1, a:colStart + 1, {'length': end - a:colStart, 'bufnr': bufnr, 'type': key, 'id': id})
catch /^Vim\%((\a\+)\)\=:E967/
" ignore 967
endtry
endfunction
function! s:funcs.buf_clear_namespace(bufnr, srcId, startLine, endLine) abort
if !has('textprop')
return
endif
if a:srcId == -1
if a:endLine == -1
call prop_clear(a:startLine + 1, {'bufnr': a:bufnr})
else
call prop_clear(a:startLine + 1, a:endLine + 1, {'bufnr': a:bufnr})
endif
else
let cached = getbufvar(a:bufnr, 'prop_namespace_'.a:srcId, [])
if empty(cached)
return
endif
for key in cached
call prop_remove({'type': key, 'bufnr': a:bufnr, 'all': 1})
endfor
endif
endfunction
function! s:funcs.buf_line_count(bufnr) abort
return s:buf_line_count(a:bufnr)
endfunction
function! s:funcs.buf_attach(...)
" not supported
return 1
endfunction
function! s:funcs.buf_detach()
" not supported
return 1
endfunction
function! s:funcs.buf_get_lines(bufnr, start, end, strict) abort
let lines = getbufline(a:bufnr, 1, '$')
let start = a:start < 0 ? a:start + 1 : a:start
let end = a:end < 0 ? a:end + 1 : a:end
if a:strict && end > len(lines)
throw 'line number out of range: '. end
endif
return lines[start : end - 1]
endfunction
function! s:funcs.buf_set_lines(bufnr, start, end, strict, ...) abort
if !bufloaded(a:bufnr)
return
endif
let replacement = get(a:, 1, [])
let lineCount = s:buf_line_count(a:bufnr)
let startLnum = a:start >= 0 ? a:start + 1 : lineCount + a:start + 1
let end = a:end >= 0 ? a:end : lineCount + a:end + 1
if end == lineCount + 1
let end = lineCount
endif
let delCount = end - (startLnum - 1)
let changeBuffer = 0
let curr = bufnr('%')
if a:bufnr != curr && !exists('*setbufline')
let changeBuffer = 1
exe 'buffer '.a:bufnr
endif
if a:bufnr == curr || changeBuffer
" replace
let storeView = winsaveview()
if delCount == len(replacement)
call setline(startLnum, replacement)
else
if len(replacement)
call append(startLnum - 1, replacement)
endif
if delCount
let start = startLnum + len(replacement)
let saved_reg = @"
silent execute start . ','.(start + delCount - 1).'d'
let @" = saved_reg
endif
endif
call winrestview(storeView)
if changeBuffer
exe 'buffer '.curr
endif
elseif exists('*setbufline')
" replace
if delCount == len(replacement)
" 8.0.1039
call setbufline(a:bufnr, startLnum, replacement)
else
if len(replacement)
" 8.10037
call appendbufline(a:bufnr, startLnum - 1, replacement)
endif
if delCount
let start = startLnum + len(replacement)
"8.1.0039
call deletebufline(a:bufnr, start, start + delCount - 1)
endif
endif
endif
endfunction
function! s:funcs.buf_set_name(bufnr, name) abort
let nr = bufnr('%')
if a:bufnr != nr
throw 'buf_set_name support current buffer only'
else
execute '0f'
execute 'file '.fnameescape(a:name)
endif
endfunction
function! s:funcs.buf_get_var(bufnr, name)
return getbufvar(a:bufnr, a:name)
endfunction
function! s:funcs.buf_set_var(bufnr, name, val)
if !bufloaded(a:bufnr) | return | endif
call setbufvar(a:bufnr, a:name, a:val)
endfunction
function! s:funcs.buf_del_var(bufnr, name)
call setbufvar(a:bufnr, a:name, v:null)
endfunction
function! s:funcs.buf_get_option(bufnr, name)
return getbufvar(a:bufnr, '&'.a:name)
endfunction
function! s:funcs.buf_get_name(bufnr)
return bufname(a:bufnr)
endfunction
" }}
" window methods {{
function! s:funcs.win_get_buf(winid)
return winbufnr(a:winid)
endfunction
function! s:funcs.win_get_position(win_id) abort
let [row, col] = win_screenpos(a:win_id)
if row == 0 && col == 0
throw 'Invalid window '.a:win_id
endif
return [row - 1, col - 1]
endfunction
function! s:funcs.win_get_height(win_id) abort
return winheight(a:win_id)
endfunction
function! s:funcs.win_get_width(win_id) abort
return winwidth(a:win_id)
endfunction
if exists('*win_execute')
function! s:win_execute(win_id, cmd, ...) abort
let ref = get(a:000, 0, v:null)
let cmd = ref is v:null ? a:cmd : 'let ref["out"] = ' . a:cmd
call win_execute(a:win_id, cmd)
endfunction
else
function! s:win_execute(win_id, cmd, ...) abort
let ref = get(a:000, 0, v:null)
let cmd = ref is v:null ? a:cmd : 'let ref["out"] = ' . a:cmd
let winid = win_getid()
if winid == a:win_id
execute cmd
else
let goto_status = win_gotoid(a:win_id)
if !goto_status
return
endif
execute cmd
call win_gotoid(winid)
endif
endfunction
endif
function! s:funcs.win_get_cursor(win_id) abort
let ref = {}
call s:win_execute(a:win_id, "[line('.'), col('.')-1]", ref)
return ref['out']
endfunction
function! s:funcs.win_get_var(win_id, name) abort
return gettabwinvar(0, a:win_id, a:name)
endfunction
function! s:funcs.win_set_width(win_id, width) abort
return s:win_execute(a:win_id, 'vertical resize '.a:width)
endfunction
function! s:funcs.win_set_buf(win_id, buf_id) abort
return s:win_execute(a:win_id, 'buffer '.a:buf_id)
endfunction
function! s:funcs.win_get_option(win_id, name) abort
return gettabwinvar(0, a:win_id, '&'.a:name)
endfunction
function! s:funcs.win_set_height(win_id, height) abort
return s:win_execute(a:win_id, 'resize '.a:height)
endfunction
function! s:funcs.win_set_option(win_id, name, value) abort
let val = a:value
if val is v:true
let val = 1
elseif val is v:false
let val = 0
endif
call setwinvar(a:win_id, '&'.a:name, val)
endfunction
function! s:funcs.win_set_var(win_id, name, value) abort
call setwinvar(a:win_id, a:name, a:value)
endfunction
function! s:funcs.win_del_var(win_id, name) abort
call settabwinvar(0, a:win_id, a:name, v:null)
endfunction
function! s:funcs.win_is_valid(win_id) abort
let info = getwininfo(a:win_id)
return !empty(info)
endfunction
function! s:funcs.win_get_number(win_id) abort
let info = getwininfo(a:win_id)
if empty(info)
throw 'Invalid window id '.a:win_id
endif
return info[0]['winnr']
endfunction
function! s:funcs.win_set_cursor(win_id, pos) abort
let [line, col] = a:pos
call s:win_execute(a:win_id, 'call cursor('.line.','.(col + 1).')')
endfunction
function! s:funcs.win_close(win_id, ...) abort
call s:win_execute(a:win_id, 'close!')
endfunction
function! s:funcs.win_get_tabpage(win_id) abort
let info = getwininfo(a:win_id)
if !info
throw 'Invalid window id '.a:win_id
endif
return info[0]['tabnr']
endfunction
" }}
" tabpage methods {{
function! s:funcs.tabpage_get_number(id)
return a:id
endfunction
function! s:funcs.tabpage_list_wins(tabnr)
let info = getwininfo()
return map(filter(info, 'v:val["tabnr"] == a:tabnr'), 'v:val["winid"]')
endfunction
function! s:funcs.tabpage_get_var(tabnr, name)
return gettabvar(a:tabnr, a:name, v:null)
endfunction
function! s:funcs.tabpage_set_var(tabnr, name, value)
call settabvar(a:tabnr, a:name, a:value)
endfunction
function! s:funcs.tabpage_del_var(tabnr, name)
call settabvar(a:tabnr, a:name, v:null)
endfunction
function! s:funcs.tabpage_is_valid(tabnr)
let max = tabpagenr('$')
return a:tabnr <= max
endfunction
function! s:funcs.tabpage_get_win(tabnr)
let wnr = tabpagewinnr(a:tabnr)
return win_getid(wnr, a:tabnr)
endfunction
" }}
function! 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
endtry
return [err, res]
endfunction
function! coc#api#notify(method, args) abort
call call(s:funcs[a:method], a:args)
endfunction
" vim: set sw=2 ts=2 sts=2 et tw=78 foldmarker={{,}} foldmethod=marker foldlevel=0:

View file

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

View file

@ -0,0 +1,942 @@
" Related to float window create
let s:is_vim = !has('nvim')
let s:borderchars = get(g:, 'coc_borderchars',
\ ['─', '│', '─', '│', '┌', '┐', '┘', '└'])
let s:prompt_win_width = get(g:, 'coc_prompt_win_width', 32)
let s:scrollbar_ns = exists('*nvim_create_namespace') ? nvim_create_namespace('coc-scrollbar') : 0
" winvar: border array of numbers, button boolean
" detect if there's float window/popup created by coc.nvim
function! coc#float#has_float() abort
if s:is_vim
if !exists('*popup_list')
return 0
endif
let arr = filter(popup_list(), 'getwinvar(v:val,"float",0)&&popup_getpos(v:val)["visible"]')
return !empty(arr)
endif
for i in range(1, winnr('$'))
if getwinvar(i, 'float')
return 1
endif
endfor
return 0
endfunction
function! coc#float#close_all() abort
if !has('nvim') && exists('*popup_clear')
call popup_clear()
return
endif
let winids = coc#float#get_float_win_list()
for id in winids
call coc#float#close(id)
endfor
endfunction
function! coc#float#jump() abort
if s:is_vim
return
endif
let winids = coc#float#get_float_win_list()
if !empty(winids)
call win_gotoid(winids[0])
endif
endfunction
function! coc#float#get_float_mode(lines, config) abort
let allowSelection = get(a:config, 'allowSelection', 0)
let pumAlignTop = get(a:config, 'pumAlignTop', 0)
let mode = mode()
let checked = (mode == 's' && allowSelection) || index(['i', 'n', 'ic'], mode) != -1
if !checked
return v:null
endif
if !s:is_vim && mode ==# 'i'
" helps to fix undo issue, don't know why.
call feedkeys("\<C-g>u", 'n')
endif
let dimension = coc#float#get_config_cursor(a:lines, a:config)
if empty(dimension)
return v:null
endif
if pumvisible() && ((pumAlignTop && dimension['row'] <0)|| (!pumAlignTop && dimension['row'] > 0))
return v:null
endif
return [mode, bufnr('%'), [line('.'), col('.')], dimension]
endfunction
" create/reuse float window for config position, config including:
" - line: line count relative to cursor, nagetive number means abover cursor.
" - col: column count relative to cursor, nagetive number means left of cursor.
" - width: content width without border and title.
" - height: content height without border and title.
" - title: (optional) title.
" - border: (optional) border as number list, like [1, 1, 1 ,1].
" - cursorline: (optional) enable cursorline when is 1.
" - autohide: (optional) window should be closed on CursorMoved when is 1.
function! coc#float#create_float_win(winid, bufnr, config) abort
call coc#float#close_auto_hide_wins(a:winid)
" use exists
if a:winid && coc#float#valid(a:winid)
if s:is_vim
let [line, col] = s:popup_position(a:config)
call popup_move(a:winid, {
\ 'line': line,
\ 'col': col,
\ 'minwidth': a:config['width'],
\ 'minheight': a:config['height'],
\ 'maxwidth': a:config['width'],
\ 'maxheight': a:config['height'],
\ })
let opts = {
\ 'cursorline': get(a:config, 'cursorline', 0),
\ 'title': get(a:config, 'title', ''),
\ }
if !s:empty_border(get(a:config, 'border', []))
let opts['border'] = a:config['border']
endif
call popup_setoptions(a:winid, opts)
return [a:winid, winbufnr(a:winid)]
else
let config = s:convert_config_nvim(a:config)
" not reuse related windows
call coc#float#nvim_close_related(a:winid)
call nvim_win_set_config(a:winid, config)
call coc#float#nvim_create_related(a:winid, config, a:config)
return [a:winid, winbufnr(a:winid)]
endif
endif
let winid = 0
if s:is_vim
let [line, col] = s:popup_position(a:config)
let bufnr = coc#float#create_float_buf(a:bufnr)
let title = get(a:config, 'title', '')
let opts = {
\ 'title': title,
\ 'line': line,
\ 'col': col,
\ 'padding': empty(title) ? [0, 1, 0, 1] : [0, 0, 0, 0],
\ 'borderchars': s:borderchars,
\ 'highlight': 'CocFloating',
\ 'fixed': 1,
\ 'cursorline': get(a:config, 'cursorline', 0),
\ 'minwidth': a:config['width'],
\ 'minheight': a:config['height'],
\ 'maxwidth': a:config['width'],
\ 'maxheight': a:config['height']
\ }
if get(a:config, 'close', 0)
let opts['close'] = 'button'
endif
if !s:empty_border(get(a:config, 'border', []))
let opts['border'] = a:config['border']
endif
let winid = popup_create(bufnr, opts)
if winid == 0
return []
endif
if has("patch-8.1.2281")
call setwinvar(winid, '&showbreak', 'NONE')
endif
else
let config = s:convert_config_nvim(a:config)
let bufnr = coc#float#create_float_buf(a:bufnr)
let winid = nvim_open_win(bufnr, 0, config)
if winid == 0
return []
endif
call setwinvar(winid, '&winhl', 'Normal:CocFloating,NormalNC:CocFloating,FoldColumn:CocFloating,CursorLine:CocMenuSel')
call setwinvar(winid, '&signcolumn', 'no')
" no left border
if s:empty_border(get(a:config, 'border', [])) || a:config['border'][3] == 0
call setwinvar(winid, '&foldcolumn', 1)
endif
call coc#float#nvim_create_related(winid, config, a:config)
endif
if !s:is_vim
" change cursorline option affects vim's own highlight
call setwinvar(winid, '&cursorline', get(a:config, 'cursorline', 0))
call setwinvar(winid, 'border', get(a:config, 'border', []))
endif
if get(a:config, 'autohide', 0)
call setwinvar(winid, 'autohide', 1)
endif
if s:is_vim || has('nvim-0.5.0')
call setwinvar(winid, '&scrolloff', 0)
endif
call setwinvar(winid, '&list', 0)
call setwinvar(winid, '&number', 0)
call setwinvar(winid, '&relativenumber', 0)
call setwinvar(winid, '&cursorcolumn', 0)
call setwinvar(winid, '&colorcolumn', 0)
call setwinvar(winid, 'float', 1)
call setwinvar(winid, '&wrap', 1)
call setwinvar(winid, '&linebreak', 1)
call setwinvar(winid, '&conceallevel', 2)
let g:coc_last_float_win = winid
call coc#util#do_autocmd('CocOpenFloat')
return [winid, winbufnr(winid)]
endfunction
function! coc#float#valid(winid) abort
if a:winid == 0 || type(a:winid) != 0
return 0
endif
if s:is_vim
return s:popup_visible(a:winid)
endif
if exists('*nvim_win_is_valid') && nvim_win_is_valid(a:winid)
let config = nvim_win_get_config(a:winid)
return !empty(get(config, 'relative', ''))
endif
return 0
endfunction
" create buffer for popup/float window
function! coc#float#create_float_buf(bufnr) abort
" reuse buffer cause error on vim8
if a:bufnr && bufloaded(a:bufnr)
return a:bufnr
endif
if s:is_vim
noa let bufnr = bufadd('')
noa call bufload(bufnr)
else
noa let bufnr = nvim_create_buf(v:false, v:true)
endif
" Don't use popup filetype, it would crash on reuse!
call setbufvar(bufnr, '&buftype', 'nofile')
call setbufvar(bufnr, '&bufhidden', 'hide')
call setbufvar(bufnr, '&swapfile', 0)
call setbufvar(bufnr, '&tabstop', 2)
call setbufvar(bufnr, '&undolevels', -1)
return bufnr
endfunction
" border window for neovim, content config with border
function! coc#float#nvim_border_win(config, border, title, related) abort
if s:empty_border(a:border)
return
endif
" width height col row relative
noa let bufnr = nvim_create_buf(v:false, v:true)
call setbufvar(bufnr, '&bufhidden', 'wipe')
let row = a:border[0] ? a:config['row'] - 1 : a:config['row']
let col = a:border[3] ? a:config['col'] - 1 : a:config['col']
let width = a:config['width'] + a:border[1] + a:border[3]
let height = a:config['height'] + a:border[0] + a:border[2]
let opt = {
\ 'relative': a:config['relative'],
\ 'width': width,
\ 'height': height,
\ 'row': row,
\ 'col': col,
\ 'focusable': v:false,
\ 'style': 'minimal',
\ }
let winid = nvim_open_win(bufnr, 0, opt)
if !winid
return
endif
call setwinvar(winid, '&winhl', 'Normal:CocFloating,NormalNC:CocFloating')
let lines = coc#float#create_border_lines(a:border, a:title, a:config['width'], a:config['height'])
call nvim_buf_set_lines(bufnr, 0, -1, v:false, lines)
call add(a:related, winid)
endfunction
function! coc#float#create_border_lines(border, title, width, height) abort
let list = []
if a:border[0]
let top = (a:border[3] ? s:borderchars[4]: '')
\.repeat(s:borderchars[0], a:width)
\.(a:border[1] ? s:borderchars[5] : '')
if !empty(a:title)
let top = coc#helper#str_compose(top, 1, a:title.' ')
endif
call add(list, top)
endif
let mid = (a:border[3] ? s:borderchars[3]: '')
\.repeat(' ', a:width)
\.(a:border[1] ? s:borderchars[1] : '')
call extend(list, repeat([mid], a:height))
if a:border[2]
let bot = (a:border[3] ? s:borderchars[7]: '')
\.repeat(s:borderchars[2], a:width)
\.(a:border[1] ? s:borderchars[6] : '')
call add(list, bot)
endif
return list
endfunction
" Create float window for input
function! coc#float#create_prompt_win(title, default) abort
call coc#float#close_auto_hide_wins()
noa let bufnr = nvim_create_buf(v:false, v:true)
call nvim_buf_set_lines(bufnr, 0, -1, v:false, [a:default])
call setbufvar(bufnr, '&bufhidden', 'wipe')
" Calculate col
let curr = win_screenpos(winnr())[1] + wincol() - 2
let width = min([max([strdisplaywidth(a:title) + 2, s:prompt_win_width]), &columns - 2])
if width == &columns - 2
let col = 0 - curr
else
let col = curr + width <= &columns - 2 ? 0 : &columns - s:prompt_win_width
endif
let config = {
\ 'relative': 'cursor',
\ 'width': width,
\ 'height': 1,
\ 'row': 0,
\ 'col': col,
\ 'style': 'minimal',
\ }
let winid = nvim_open_win(bufnr, 0, config)
if winid == 0
return []
endif
call setwinvar(winid, '&winhl', 'Normal:CocFloating,NormalNC:CocFloating')
let related = []
call coc#float#nvim_border_win(config, [1,1,1,1], a:title, related)
call setwinvar(winid, 'related', related)
call win_gotoid(winid)
inoremap <buffer> <C-a> <Home>
inoremap <buffer><expr><C-e> pumvisible() ? "\<C-e>" : "\<End>"
exe 'inoremap <silent><buffer> <esc> <C-r>=coc#float#close_i('.winid.')<CR><esc>'
exe 'nnoremap <silent><buffer> <esc> :call coc#float#close('.winid.')<CR>'
exe 'inoremap <expr><nowait><buffer> <cr> "\<c-r>=coc#float#prompt_insert('.winid.')\<cr>\<esc>"'
call feedkeys('A', 'in')
return [bufnr, winid]
endfunction
function! coc#float#close_i(winid) abort
call coc#float#close(a:winid)
return ''
endfunction
function! coc#float#prompt_insert(winid) abort
let text = getline('.')
let bufnr = winbufnr(a:winid)
call coc#rpc#notify('PromptInsert',[text, bufnr])
call timer_start(50, { -> coc#float#close(a:winid)})
return ''
endfunction
" Position of cursor relative to editor
function! s:win_position() abort
let nr = winnr()
let [row, col] = win_screenpos(nr)
return [row + winline() - 2, col + wincol() - 2]
endfunction
" get popup position for vim8 based on config of neovim float window
function! s:popup_position(config) abort
let relative = get(a:config, 'relative', 'editor')
if relative ==# 'cursor'
return [s:popup_cursor(a:config['row']), s:popup_cursor(a:config['col'])]
endif
return [a:config['row'] + 1, a:config['col'] + 1]
endfunction
function! s:popup_cursor(n) abort
if a:n == 0
return 'cursor'
endif
if a:n < 0
return 'cursor'.a:n
endif
return 'cursor+'.a:n
endfunction
" Close float window by id
function! coc#float#close(winid) abort
if !coc#float#valid(a:winid)
return 0
endif
if s:is_vim
call popup_close(a:winid)
return 1
else
call coc#float#nvim_close_related(a:winid)
call nvim_win_close(a:winid, 1)
return 1
endif
return 0
endfunction
" Float window id on current tab.
" return 0 if not found
function! coc#float#get_float_win() abort
if has('nvim')
for i in range(1, winnr('$'))
let id = win_getid(i)
let config = nvim_win_get_config(id)
if (!empty(config) && config['focusable'] == v:true && !empty(config['relative']))
if !getwinvar(id, 'button', 0)
return id
endif
endif
endfor
elseif exists('*popup_list')
let arr = filter(popup_list(), 'popup_getpos(v:val)["visible"]')
if !empty(arr)
return arr[0]
endif
endif
return 0
endfunction
function! coc#float#get_float_win_list() abort
if s:is_vim && exists('*popup_list')
return filter(popup_list(), 'popup_getpos(v:val)["visible"]')
elseif has('nvim') && exists('*nvim_win_get_config')
let res = []
for i in range(1, winnr('$'))
let id = win_getid(i)
let config = nvim_win_get_config(id)
" ignore border & button window
if (!empty(config) && config['focusable'] == v:true && !empty(config['relative']))
if !getwinvar(id, 'button', 0)
call add(res, id)
endif
endif
endfor
return res
endif
return []
endfunction
" Check if a float window is scrollable
function! coc#float#scrollable(winid) abort
let bufnr = winbufnr(a:winid)
if bufnr == -1
return 0
endif
if s:is_vim
let pos = popup_getpos(a:winid)
" scrollbar enabled
if get(popup_getoptions(a:winid), 'scrollbar', 0)
return get(pos, 'scrollbar', 0)
endif
let ch = coc#float#content_height(bufnr, pos['core_width'], getwinvar(a:winid, '&wrap'))
return ch > pos['core_height']
else
let height = nvim_win_get_height(a:winid)
let width = nvim_win_get_width(a:winid)
if width > 1 && getwinvar(a:winid, '&foldcolumn', 0)
" since we use foldcolumn for left pading
let width = width - 1
endif
let ch = coc#float#content_height(bufnr, width, getwinvar(a:winid, '&wrap'))
return ch > height
endif
endfunction
function! coc#float#has_scroll() abort
let win_ids = filter(coc#float#get_float_win_list(), 'coc#float#scrollable(v:val)')
return !empty(win_ids)
endfunction
function! coc#float#scroll(forward, ...)
if !has('nvim-0.4.3') && !has('patch-8.2.0750')
throw 'coc#float#scroll() requires nvim >= 0.4.3 or vim >= 8.2.0750'
endif
let amount = get(a:, 1, 0)
let win_ids = filter(coc#float#get_float_win_list(), 'coc#float#scrollable(v:val)')
if empty(win_ids)
return ''
endif
if has('nvim')
call timer_start(10, { -> s:scroll_nvim(win_ids, a:forward, amount)})
else
call timer_start(10, { -> s:scroll_vim(win_ids, a:forward, amount)})
endif
return mode() =~ '^i' ? "" : "\<Ignore>"
endfunction
function! s:scroll_nvim(win_ids, forward, amount) abort
let curr = win_getid()
for id in a:win_ids
if nvim_win_is_valid(id)
let wrapped = 0
let width = nvim_win_get_width(id)
if getwinvar(id, '&wrap', 0)
if width > 1 && getwinvar(id, '&foldcolumn', 0)
let width = width - 1
endif
for line in nvim_buf_get_lines(winbufnr(id), 0, -1, v:false)
if strdisplaywidth(line) > width
let wrapped = 1
break
endif
endfor
endif
noa call win_gotoid(id)
let height = nvim_win_get_height(id)
let firstline = line('w0')
let lastline = line('w$')
let linecount = line('$')
let delta = a:amount ? a:amount : max([1, height - 1])
if a:forward
if lastline == linecount && strdisplaywidth(line('$')) <= width
continue
endif
if !a:amount && firstline != lastline
execute 'noa normal! Lzt'
else
execute 'noa normal! H'.delta.'jzt'
endif
let lnum = line('.')
while lnum < linecount && line('w0') == firstline && line('w$') == lastline
execute 'noa normal! jzt'
let lnum = lnum + 1
endwhile
else
if !a:amount && firstline != lastline
execute 'noa normal! Hzb'
else
execute 'noa normal! L'.delta.'kzb'
endif
let lnum = line('.')
while lnum > 1 && line('w0') == firstline && line('w$') == lastline
execute 'noa normal! kzb'
let lnum = lnum - 1
endwhile
endif
call coc#float#nvim_scrollbar(id)
endif
endfor
noa call win_gotoid(curr)
redraw
endfunction
function! s:scroll_vim(win_ids, forward, amount) abort
for id in a:win_ids
if s:popup_visible(id)
let pos = popup_getpos(id)
let bufnr = winbufnr(id)
let linecount = get(getbufinfo(bufnr)[0], 'linecount', 0)
" for forward use last line (or last line + 1) as first line
if a:forward
if pos['firstline'] == pos['lastline']
call popup_setoptions(id, {'firstline': min([pos['firstline'] + 1, linecount])})
else
if pos['lastline'] == linecount
let win_width = pos['core_width']
let text = getbufline(bufnr, '$')[0]
if strdisplaywidth(text) <= win_width
" last line shown
return
endif
endif
let lnum = a:amount ? min([linecount, pos['firstline'] + a:amount]) : pos['lastline']
call popup_setoptions(id, {'firstline': lnum})
endif
else
if pos['firstline'] == 1
call win_execute(id, 'normal! gg0')
return
endif
" we could only change firstline
" iterate lines before last lines to fill content height - 1
let total_height = a:amount ? min([a:amount, pos['core_height']]) : pos['core_height'] - 1
if total_height == 0
call popup_setoptions(id, {'firstline': pos['firstline'] - 1})
else
let lines = getbufline(bufnr, 1, '$')
let curr = pos['firstline'] - 1
let width = pos['core_width']
let used = 0
while v:true
if curr == 1
break
endif
let w = max([1, strdisplaywidth(lines[curr - 1])])
let used += float2nr(ceil(str2float(string(w))/width))
if used > total_height
let curr = curr == pos['firstline'] -1 ? curr : curr + 1
break
elseif used == total_height
break
endif
let curr = curr - 1
endwhile
call popup_setoptions(id, {'firstline': curr})
endif
endif
endif
endfor
redraw
endfunction
function! s:popup_visible(id) abort
let pos = popup_getpos(a:id)
if !empty(pos) && get(pos, 'visible', 0)
return 1
endif
return 0
endfunction
function! s:convert_config_nvim(config) abort
let result = coc#helper#dict_omit(a:config, ['title', 'border', 'cursorline', 'autohide', 'close'])
let border = get(a:config, 'border', [])
if !s:empty_border(border)
if result['relative'] ==# 'cursor' && result['row'] < 0
" move top when has bottom border
if get(border, 2, 0)
let result['row'] = result['row'] - 1
endif
else
" move down when has top border
if get(border, 0, 0)
let result['row'] = result['row'] + 1
endif
endif
" move right when has left border
if get(border, 3, 0)
let result['col'] = result['col'] + 1
endif
let result['width'] = result['width'] + 1 - get(border,3, 0)
else
let result['width'] = result['width'] + 1
endif
return result
endfunction
" Close windows that could auto hide
function! coc#float#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
" neovim only
function! coc#float#nvim_close_btn(config, winid, close, border, related) abort
if !a:close
return
endif
let config = {
\ 'relative': a:config['relative'],
\ 'width': 1,
\ 'height': 1,
\ 'row': get(a:border, 0, 0) ? a:config['row'] - 1 : a:config['row'],
\ 'col': a:config['col'] + a:config['width'],
\ 'focusable': v:true,
\ 'style': 'minimal',
\ }
noa let bufnr = nvim_create_buf(v:false, v:true)
call setbufvar(bufnr, '&bufhidden', 'wipe')
call nvim_buf_set_lines(bufnr, 0, -1, v:false, ['X'])
let winid = nvim_open_win(bufnr, 0, config)
" map for winid & close_winid
if winid
call setwinvar(winid, 'button', 1)
call setwinvar(a:winid, 'close_winid', winid)
call setwinvar(winid, '&winhl', 'Normal:CocFloating,NormalNC:CocFloating')
call add(a:related, winid)
endif
endfunction
function! coc#float#nvim_check_close(winid) abort
let target = getwinvar(a:winid, 'target_winid', 0)
if target
call coc#float#close(target)
endif
endfunction
" Create padding window by config of current window & border config
function! coc#float#nvim_right_pad(config, border, related) abort
" Check right border
if !empty(a:border) && get(a:border, 1, 0)
return
endif
let config = {
\ 'relative': a:config['relative'],
\ 'width': 1,
\ 'height': a:config['height'],
\ 'row': a:config['row'],
\ 'col': a:config['col'] + a:config['width'],
\ 'focusable': v:false,
\ 'style': 'minimal',
\ }
noa let bufnr = nvim_create_buf(v:false, v:true)
call setbufvar(bufnr, '&bufhidden', 'wipe')
call nvim_buf_set_lines(bufnr, 0, -1, v:false, repeat([' '], a:config['height']))
let winid = nvim_open_win(bufnr, 0, config)
if winid
call setwinvar(winid, 'ispad', 1)
call setwinvar(winid, '&winhl', 'Normal:CocFloating,NormalNC:CocFloating')
call add(a:related, winid)
endif
endfunction
function! coc#float#content_height(bufnr, width, wrap) abort
if !bufloaded(a:bufnr)
return 0
endif
if !a:wrap
return has('nvim') ? nvim_buf_line_count(a:bufnr) : len(getbufline(a:bufnr, 1, '$'))
endif
let lines = has('nvim') ? nvim_buf_get_lines(a:bufnr, 0, -1, 0) : getbufline(a:bufnr, 1, '$')
let total = 0
for line in lines
let dw = max([1, strdisplaywidth(line)])
let total += float2nr(ceil(str2float(string(dw))/a:width))
endfor
return total
endfunction
function! s:add_related(winid, target) abort
let arr = getwinvar(a:target, 'related', [])
if index(arr, a:winid) >= 0
return
endif
call add(arr, a:winid)
call setwinvar(a:target, 'related', arr)
endfunction
function! coc#float#nvim_refresh_scrollbar() abort
let id = getwinvar(win_getid(), 'scrollbar', 0)
if coc#float#valid(id)
call coc#float#nvim_scrollbar(win_getid())
endif
endfunction
" Close related windows for neovim.
function! coc#float#nvim_close_related(winid) abort
if !has('nvim') || !a:winid
return
endif
let winids = getwinvar(a:winid, 'related', [])
if !empty(winids)
call nvim_win_del_var(a:winid, 'related')
endif
for id in winids
if nvim_win_is_valid(id) && id != a:winid
call nvim_win_close(id, 1)
endif
endfor
endfunction
function! coc#float#nvim_create_related(winid, config, opts) abort
let related = []
call coc#float#nvim_close_btn(a:config, a:winid, get(a:opts, 'close', 0), get(a:opts, 'border', []), related)
call coc#float#nvim_border_win(a:config, get(a:opts, 'border', []), get(a:opts, 'title', ''), related)
call coc#float#nvim_right_pad(a:config, get(a:opts, 'border', []), related)
for id in related
call setwinvar(id, 'target_winid', a:winid)
endfor
call setwinvar(a:winid, 'related', related)
endfunction
" Create scrollbar for winid
" Need called on create, config, buffer change, scrolled
function! coc#float#nvim_scrollbar(winid) abort
if !has('nvim-0.4.3')
return
endif
if a:winid == 0 || !nvim_win_is_valid(a:winid) || getwinvar(a:winid, 'button', 0)
return
endif
let config = nvim_win_get_config(a:winid)
" ignore border & button window
if (!get(config, 'focusable', v:false) || empty(get(config, 'relative', '')))
return
endif
let [row, column] = nvim_win_get_position(a:winid)
let width = nvim_win_get_width(a:winid)
let height = nvim_win_get_height(a:winid)
let bufnr = winbufnr(a:winid)
let cw = getwinvar(a:winid, '&foldcolumn', 0) ? width - 1 : width
let ch = coc#float#content_height(bufnr, cw, getwinvar(a:winid, '&wrap'))
let close_winid = getwinvar(a:winid, 'close_winid', 0)
let border = getwinvar(a:winid, 'border', [])
let move_down = close_winid && !get(border, 0, 0)
if move_down
let height = height - 1
if height == 0
return
endif
endif
let id = 0
if nvim_win_is_valid(getwinvar(a:winid, 'scrollbar', 0))
let id = getwinvar(a:winid, 'scrollbar', 0)
endif
if ch <= height || height == 0
" no scrollbar, remove exists
if id
call nvim_win_del_var(a:winid, 'scrollbar')
call coc#float#close(id)
endif
return
endif
if height == 0
return
endif
if id && bufloaded(winbufnr(id))
let sbuf = winbufnr(id)
else
noa let sbuf = nvim_create_buf(v:false, v:true)
call setbufvar(sbuf, '&bufhidden', 'wipe')
endif
call nvim_buf_set_lines(sbuf, 0, -1, v:false, repeat([' '], height))
let opts = {
\ 'row': move_down ? row + 1 : row,
\ 'col': column + width,
\ 'relative': 'editor',
\ 'width': 1,
\ 'height': height,
\ 'focusable': v:false,
\ 'style': 'minimal',
\ }
if id
call nvim_win_set_config(id, opts)
else
let id = nvim_open_win(sbuf, 0 , opts)
call setwinvar(id, 'isscrollbar', 1)
call setwinvar(id, 'target_winid', a:winid)
endif
let thumb_height = max([1, float2nr(floor(height * (height + 0.0)/ch))])
let curr = win_getid()
if curr != a:winid
noa call win_gotoid(a:winid)
endif
let firstline = line('w0')
let lastline = line('w$')
let linecount = line('$')
if firstline == 1
let start = 0
elseif lastline == linecount
let start = height - thumb_height
else
let start = max([1, float2nr(round((height - thumb_height + 0.0)*(firstline - 1.0)/(ch - height)))])
endif
if curr != a:winid
noa call win_gotoid(curr)
endif
" add highlights
call nvim_buf_clear_namespace(sbuf, s:scrollbar_ns, 0, -1)
for idx in range(0, height - 1)
if idx >= start && idx < start + thumb_height
call nvim_buf_add_highlight(sbuf, s:scrollbar_ns, 'PmenuThumb', idx, 0, 1)
else
call nvim_buf_add_highlight(sbuf, s:scrollbar_ns, 'PmenuSbar', idx, 0, 1)
endif
endfor
" create scrollbar outside window
call setwinvar(a:winid, 'scrollbar', id)
call s:add_related(id, a:winid)
endfunction
function! coc#float#nvim_check_related() abort
if !has('nvim')
return
endif
let invalids = []
for i in range(1, winnr('$'))
let id = win_getid(i)
let target = getwinvar(id, 'target_winid', 0)
if target && !nvim_win_is_valid(target)
call add(invalids, id)
endif
endfor
for id in invalids
noa call nvim_win_close(id, 1)
endfor
endfunction
" Dimension of window with lines relative to cursor
" Width & height excludes border & padding
function! coc#float#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', [0, 0, 0, 0])
if s:empty_border(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 = min([get(a:config, 'maxWidth', 80), &columns - 1])
if maxWidth < 3
return v:null
endif
let maxHeight = min([get(a:config, 'maxHeight', 80), vh])
let ch = 0
let width = min([40, strdisplaywidth(title)]) + 3
for line in a:lines
let dw = max([1, strdisplaywidth(line)])
let width = max([width, dw + 2])
let ch += float2nr(ceil(str2float(string(dw))/(maxWidth - 2)))
endfor
let width = min([maxWidth, width])
let [lineIdx, colIdx] = s:win_position()
" How much we should move left
let offsetX = 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 = 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 : 1
return {
\ 'row': row,
\ 'col': col,
\ 'width': width - 2,
\ 'height': height - bh
\ }
endfunction
function! coc#float#get_config_pum(lines, pumconfig, maxwidth) abort
if !pumvisible()
return v:null
endif
let pw = a:pumconfig['width'] + get(a:pumconfig, 'scrollbar', 0)
let rp = &columns - a:pumconfig['col'] - pw
let showRight = a:pumconfig['col'] > rp ? 0 : 1
let maxWidth = showRight ? min([rp - 1, a:maxwidth]) : min([a:pumconfig['col'] - 1, a:maxwidth])
let maxHeight = &lines - a:pumconfig['row'] - &cmdheight - 1
if maxWidth <= 2 || maxHeight < 1
return v:null
endif
let ch = 0
let width = 0
for line in a:lines
let dw = max([1, strdisplaywidth(line)])
let width = max([width, dw + 2])
let ch += float2nr(ceil(str2float(string(dw))/(maxWidth - 2)))
endfor
let width = min([maxWidth, width])
let height = min([maxHeight, ch])
return {
\ 'col': showRight ? a:pumconfig['col'] + pw : a:pumconfig['col'] - width - 1,
\ 'row': a:pumconfig['row'],
\ 'height': height,
\ 'width': width - 2 + (s:is_vim && ch > height ? -1 : 0),
\ 'relative': 'editor'
\ }
endfunction
function! s:empty_border(border) abort
if empty(a:border)
return 1
endif
if a:border[0] == 0 && a:border[1] == 0 && a:border[2] == 0 && a:border[3] == 0
return 1
endif
return 0
endfunction

View file

@ -0,0 +1,56 @@
" Helper methods for viml
" 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

View file

@ -0,0 +1,292 @@
let s:activated = 0
let s:is_vim = !has('nvim')
let s:saved_ve = &t_ve
let s:saved_cursor = &guicursor
let s:gui = has('gui_running') || has('nvim')
function! coc#list#get_chars()
return {
\ '<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>",
\ '<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-i>': "\<C-i>",
\ '<C-j>': "\<C-j>",
\ '<C-k>': "\<C-k>",
\ '<C-l>': "\<C-l>",
\ '<C-m>': "\<C-m>",
\ '<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>",
\}
endfunction
function! coc#list#getc() abort
let c = getchar()
return type(c) == type(0) ? nr2char(c) : c
endfunction
function! coc#list#getchar() abort
let input = coc#list#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 full_keymap = maparg(input, "l")
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#list#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#list#start_prompt(...) abort
let eventName = get(a:, 1, 'InputChar')
if s:is_vim
call s:start_prompt_vim(eventName)
else
call s:start_prompt(eventName)
endif
endfunction
function! s:start_prompt_vim(eventName) abort
call timer_start(10, {-> s:start_prompt(a:eventName)})
endfunction
function! s:start_prompt(eventName)
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#list#getchar()
if ch ==# "\u26d4"
break
endif
if ch ==# "\<FocusLost>" || ch ==# "\<FocusGained>" || ch ==# "\<CursorHold>"
continue
else
call coc#rpc#notify(a:eventName, [ch, getcharmod()])
endif
endwhile
catch /^Vim:Interrupt$/
let s:activated = 0
call coc#rpc#notify(a:eventName, ["\<C-c>"])
return
endtry
let s:activated = 0
endfunction
function! coc#list#setlines(lines, append)
if a:append
silent call append(line('$'), a:lines)
else
silent call append(0, a:lines)
if exists('*deletebufline')
call deletebufline('%', len(a:lines) + 1, '$')
else
let n = len(a:lines) + 1
let saved_reg = @"
silent execute n.',$d'
let @" = saved_reg
endif
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']
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#stop_prompt(...)
if s:activated
let s:activated = 0
if get(a:, 1, 0) == 0 && !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 ""
call feedkeys("\u26d4", 'int')
endif
endfunction
function! coc#list#status(name)
if !exists('b:list_status') | return '' | endif
return get(b:list_status, a:name, '')
endfunction
function! coc#list#create(position, height, name, numberSelect)
if a:position ==# 'tab'
execute 'silent tabe list:///'.a:name
else
execute 'silent keepalt '.(a:position ==# 'top' ? '' : 'botright').a:height.'sp list:///'.a:name
execute 'resize '.a:height
endif
if a:numberSelect
setl norelativenumber
setl number
else
setl nonumber
setl norelativenumber
setl signcolumn=yes
endif
return [bufnr('%'), win_getid()]
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 cursorline winfixheight
setl tabstop=1 nolist nocursorcolumn undolevels=-1
setl signcolumn=auto
if has('nvim-0.5.0') || has('patch-8.1.0864')
setl scrolloff=0
endif
if exists('&cursorlineopt')
setl cursorlineopt=both
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^.*$/'
nnoremap <silent><nowait><buffer> <esc> <C-w>c
endfunction
function! coc#list#has_preview()
for i in range(1, winnr('$'))
let preview = getwinvar(i, '&previewwindow')
if preview
return 1
endif
endfor
return 0
endfunction
function! coc#list#restore(winid, height)
let res = win_gotoid(a:winid)
if res == 0 | return | endif
if winnr('$') == 1
return
endif
execute 'resize '.a:height
if s:is_vim
redraw
endif
endfunction
function! coc#list#set_height(height) abort
if winnr('$') == 1| return | endif
execute 'resize '.a:height
endfunction

View file

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

View file

@ -0,0 +1,68 @@
let s:is_vim = !has('nvim')
let s:map_next = 1
function! coc#snippet#_select_mappings()
if !get(g:, 'coc_selectmode_mapping', 1)
return
endif
redir => mappings
silent! smap
redir END
for map in map(filter(split(mappings, '\n'),
\ "v:val !~# '^s' && v:val !~# '^\\a*\\s*<\\S\\+>'"),
\ "matchstr(v:val, '^\\a*\\s*\\zs\\S\\+')")
silent! execute 'sunmap' map
silent! execute 'sunmap <buffer>' map
endfor
" same behaviour of ultisnips
snoremap <silent> <BS> <c-g>c
snoremap <silent> <DEL> <c-g>c
snoremap <silent> <c-h> <c-g>c
snoremap <c-r> <c-g>"_c<c-r>
endfunction
function! coc#snippet#show_choices(lnum, col, len, values) abort
let m = mode()
call cursor(a:lnum, a:col + a:len)
if m !=# 'i' | startinsert | endif
call timer_start(20, { -> coc#_do_complete(a:col - 1, a:values, 0)})
redraw
endfunction
function! coc#snippet#enable()
if get(b:, 'coc_snippet_active', 0) == 1
return
endif
let b:coc_snippet_active = 1
silent! unlet g:coc_selected_text
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') =~# 'expand-jump'
let s:map_next = 0
endif
if s:map_next
execute 'inoremap <buffer><nowait><silent>'.nextkey." <C-R>=coc#rpc#request('snippetNext', [])<cr>"
endif
execute 'inoremap <buffer><nowait><silent>'.prevkey." <C-R>=coc#rpc#request('snippetPrev', [])<cr>"
execute 'snoremap <buffer><nowait><silent>'.prevkey." <Esc>:call coc#rpc#request('snippetPrev', [])<cr>"
execute 'snoremap <buffer><nowait><silent>'.nextkey." <Esc>:call coc#rpc#request('snippetNext', [])<cr>"
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
silent! execute 'iunmap <buffer> <silent> '.prevkey
silent! execute 'sunmap <buffer> <silent> '.prevkey
silent! execute 'sunmap <buffer> <silent> '.nextkey
endfunction

View file

@ -0,0 +1,109 @@
" ============================================================================
" Description: Manage long running tasks.
" Author: Qiming Zhao <chemzqm@gmail.com>
" Licence: MIT licence
" Version: 0.1
" Last Modified: April 08, 2019
" ============================================================================
let s:is_vim = !has('nvim')
let s:running_task = {}
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())
" 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)},
\}
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, filter(msgs, 'v:val !=""'))},
\ 'on_stdout': {channel, msgs -> s:on_stdout(a:id, filter(msgs, 'v:val !=""'))},
\ 'on_exit': {channel, code -> s:on_exit(a:id, code)},
\ 'detach': get(a:opts, 'detach', 0),
\}
if get(a:opts, 'pty', 0)
let options['pty'] = 1
endif
let chan_id = jobstart(cmd, options)
if chan_id <= 0
echohl Error | echom 'Failed to start '.a:id.' task' | echohl None
return v:false
endif
let s:running_task[a:id] = chan_id
endif
return v:true
endfunction
function! coc#task#stop(id)
let job = get(s:running_task, a:id, v:null)
if !job | return | endif
if s:is_vim
call job_stop(job, 'term')
else
call jobstop(job)
endif
sleep 50m
let running = coc#task#running(a:id)
if running
echohl Error | echom 'job '.a:id. ' stop failed.' | echohl None
endif
endfunction
function! s:on_exit(id, code) abort
if get(g:, 'coc_vim_leaving', 0) | return | endif
if 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 len(a:msgs)
call coc#rpc#notify('TaskStderr', [a:id, a:msgs])
endif
endfunction
function! s:on_stdout(id, msgs)
if len(a:msgs)
call coc#rpc#notify('TaskStdout', [a:id, a:msgs])
endif
endfunction
function! coc#task#running(id)
if !has_key(s:running_task, a:id) == 1
return v:false
endif
let job = s:running_task[a:id]
if s:is_vim
let status = job_status(job)
return status ==# 'run'
endif
let [code] = jobwait([job], 10)
return code == -1
endfunction

View file

@ -0,0 +1,114 @@
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) 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 8new +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)
else
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
if a:status == 0
execute 'silent! bd! '.bufnr
endif
endfunction
if has('nvim')
let job_id = termopen(a:cmd, {
\ 'cwd': cwd,
\ 'pty': 1,
\ 'on_exit': {job, status -> s:OnExit(status)},
\ 'env': env,
\ })
if !empty(original)
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 winnr = bufwinnr(a:bufnr)
if winnr != -1
exe 'noa '.winnr.'wincmd w'
exe 'noa normal! G'
exe 'noa '.wincmd p
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

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,97 @@
let s:root = expand('<sfile>:h:h:h')
function! s:checkEnvironment() abort
let valid = 1
if !has('nvim-0.3.0')
let valid = 0
call health#report_error('Neovim version not satisfied, 0.3.0 and above required')
endif
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]) < 8 || (str2nr(ms[1]) == 8 && str2nr(ms[2]) < 10)
let valid = 0
call health#report_error('Node.js version '.output.' < 8.10.0, please upgrade node.js')
elseif str2nr(ms[1]) < 10 || (str2nr(ms[1]) == 10 && str2nr(ms[2]) < 12)
let valid = 0
call health#report_warn('Node.js version '.trim(output).' < 10.12.0, please upgrade node.js')
endif
if valid
call health#report_ok('Environment check passed')
endif
if has('pythonx')
try
silent pyx print("")
catch /.*/
call health#report_warn('pyx command not work, some extensions may fail to work, checkout ":h pythonx"')
endtry
endif
return valid
endfunction
function! s:checkCommand()
let file = s:root.'/bin/server.js'
if filereadable(file)
if !filereadable(s:root.'/lib/attach.js')
call health#report_error('Javascript entry not found, run "yarn install --frozen-lockfile" in terminal to fix it.')
else
call health#report_ok('Javascript entry lib/attach.js found')
endif
else
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, reinstall coc.nvim to fix it.')
endif
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:checkInitailize() 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:checkInitailize()
call s:checkAutocmd()
endfunction

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,46 @@
{
"name": "coc.nvim",
"version": "0.0.79",
"description": "LSP based intellisense engine for neovim & vim8.",
"main": "./lib/index.js",
"engines": {
"node": ">=8.10.0"
},
"scripts": {},
"repository": {
"type": "git",
"url": "git+https://github.com/neoclide/coc.nvim.git"
},
"keywords": [
"complete",
"neovim"
],
"author": "Qiming Zhao <chemzqm@gmail.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/neoclide/coc.nvim/issues"
},
"homepage": "https://github.com/neoclide/coc.nvim#readme",
"jest": {
"globals": {
"__TEST__": true
},
"watchman": false,
"clearMocks": true,
"globalSetup": "./jest.js",
"testEnvironment": "node",
"moduleFileExtensions": [
"ts",
"tsx",
"json",
"js"
],
"transform": {
"^.+\\.tsx?$": "ts-jest"
},
"testRegex": "src/__tests__/.*\\.(test|spec)\\.ts$",
"coverageDirectory": "./coverage/"
},
"devDependencies": {},
"dependencies": {}
}

View file

@ -0,0 +1,477 @@
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.3.2')
else
let l:unsupported = !has('patch-8.0.1453')
endif
if l:unsupported == 1
echohl Error
echom "coc.nvim requires at least Vim 8.0.1453 or Neovim 0.3.2, 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.0.1453 or Neovim 0.3.2."
echohl None
sleep 2
else
if has('nvim') && !has('nvim-0.4.3')
echohl WarningMsg
echom "coc.nvim works best on neovim >= 0.4.3, consider upgrade your neovim."
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('patch-8.1.1719')
echohl WarningMsg
echom "coc.nvim need vim >= 8.1.1719 to support features like popup and text property."
echom "Consider upgrade your vim for better experience."
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_workspace_initialized = 0
let g:coc_service_initialized = 0
let s:is_win = has('win32') || has('win64')
let s:root = expand('<sfile>:h:h')
let s:is_vim = !has('nvim')
let s:is_gvim = get(v:, 'progname', '') ==# 'gvim'
if get(g:, 'coc_start_at_startup', 1) && !s:is_gvim
call coc#rpc#start_server()
endif
function! CocTagFunc(pattern, flags, info) abort
if a:flags !=# 'c'
" use standard tag search
return v:null
endif
return coc#rpc#request('getTagList', [])
endfunction
function! CocAction(name, ...) abort
return coc#rpc#request(a:name, a:000)
endfunction
function! CocHasProvider(name) abort
return coc#rpc#request('hasProvider', [a:name])
endfunction
function! CocActionAsync(name, ...) abort
return s:AsyncRequest(a:name, a:000)
endfunction
function! CocRequest(...) abort
return coc#rpc#request('sendRequest', a:000)
endfunction
function! CocNotify(...) abort
return coc#rpc#request('sendNotification', a:000)
endfunction
function! CocRegistNotification(id, method, cb) abort
call coc#on_notify(a:id, a:method, a:cb)
endfunction
function! CocLocations(id, method, ...) abort
let args = [a:id, a:method] + copy(a:000)
call coc#rpc#request('findLocations', args)
endfunction
function! CocLocationsAsync(id, method, ...) abort
let args = [a:id, a:method] + copy(a:000)
call coc#rpc#notify('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:InstallOptions(...)abort
let list = ['-terminal', '-sync']
return join(list, "\n")
endfunction
function! s:OpenConfig()
let home = coc#util#get_config_home()
if !isdirectory(home)
call mkdir(home, 'p')
endif
execute 'edit '.home.'/coc-settings.json'
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] = get(g:terminal_ansi_colors, i, colors[i])
else
let color_map[name] = get(g:, 'terminal_color_'.i, colors[i])
endif
endfor
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
try
exe 'hi default CocListFg'.foreground. ' guifg='.foregroundColor. ' ctermfg='.foreground
exe 'hi default CocListBg'.foreground. ' guibg='.foregroundColor. ' ctermbg='.foreground
catch /.*/
" ignore invalid color
endtry
endfor
endfunction
function! s:CursorRangeFromSelected(type, ...) abort
" add range by operator
call coc#rpc#request('cursorsSelect', [bufnr('%'), 'operator', a:type])
endfunction
function! s:OpenDiagnostics(...) abort
let height = get(a:, 1, 0)
call coc#rpc#request('fillDiagnostics', [bufnr('%')])
if height
execute ':lopen '.height
else
lopen
endif
endfunction
function! s:Disable() abort
if get(g:, 'coc_enabled', 0) == 0
return
endif
augroup coc_nvim
autocmd!
augroup end
call coc#rpc#request('detach', [])
echohl MoreMsg
echom '[coc.nvim] Event disabled'
echohl None
let g:coc_enabled = 0
endfunction
function! s:Autocmd(...) abort
if !g:coc_workspace_initialized
return
endif
call coc#rpc#notify('CocAutocmd', a:000)
endfunction
function! s:SyncAutocmd(...)
if !g:coc_workspace_initialized
return
endif
if g:coc_service_initialized
call coc#rpc#request('CocAutocmd', a:000)
else
call coc#rpc#notify('CocAutocmd', a:000)
endif
endfunction
function! s:Enable(initialize)
if get(g:, 'coc_enabled', 0) == 1
return
endif
let g:coc_enabled = 1
augroup coc_nvim
autocmd!
if exists('##MenuPopupChanged') && exists('*nvim_open_win')
autocmd MenuPopupChanged * call s:Autocmd('MenuPopupChanged', get(v:, 'event', {}), win_screenpos(winnr())[0] + winline() - 2)
endif
if exists('##CompleteChanged')
autocmd CompleteChanged * call s:Autocmd('MenuPopupChanged', get(v:, 'event', {}), win_screenpos(winnr())[0] + winline() - 2)
endif
if coc#rpc#started()
autocmd VimEnter * call coc#rpc#notify('VimEnter', [])
elseif get(g:, 'coc_start_at_startup', 1)
autocmd VimEnter * call coc#rpc#start_server()
endif
if s:is_vim
if exists('##DirChanged')
autocmd DirChanged * call s:Autocmd('DirChanged', getcwd())
endif
if exists('##TerminalOpen')
autocmd TerminalOpen * call s:Autocmd('TermOpen', +expand('<abuf>'))
endif
else
autocmd DirChanged * call s:Autocmd('DirChanged', get(v:event, 'cwd', ''))
autocmd TermOpen * call s:Autocmd('TermOpen', +expand('<abuf>'))
autocmd TermClose * call s:Autocmd('TermClose', +expand('<abuf>'))
autocmd CursorMoved * call coc#float#nvim_refresh_scrollbar()
autocmd WinEnter * call coc#float#nvim_check_close(win_getid())
autocmd CursorHold * call coc#float#nvim_check_related()
if exists('##WinClosed')
autocmd WinClosed * call coc#float#nvim_close_related(+expand('<afile>'))
endif
endif
autocmd WinLeave * call coc#util#clear_highlights()
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 CompleteDone * call s:Autocmd('CompleteDone', get(v:, 'completed_item', {}))
autocmd InsertCharPre * call s:Autocmd('InsertCharPre', v:char)
if exists('##TextChangedP')
autocmd TextChangedP * call s:Autocmd('TextChangedP', +expand('<abuf>'), {'lnum': line('.'), 'col': col('.'), 'pre': strpart(getline('.'), 0, col('.') - 1), 'changedtick': b:changedtick})
endif
autocmd TextChangedI * call s:Autocmd('TextChangedI', +expand('<abuf>'), {'lnum': line('.'), 'col': col('.'), 'pre': strpart(getline('.'), 0, col('.') - 1), 'changedtick': b:changedtick})
autocmd InsertLeave * call s:Autocmd('InsertLeave', +expand('<abuf>'))
autocmd InsertEnter * call s:Autocmd('InsertEnter', +expand('<abuf>'))
autocmd BufHidden * call s:Autocmd('BufHidden', +expand('<abuf>'))
autocmd BufEnter * call s:Autocmd('BufEnter', +expand('<abuf>'))
autocmd TextChanged * call s:Autocmd('TextChanged', +expand('<abuf>'), getbufvar(+expand('<abuf>'), 'changedtick'))
autocmd BufWritePost * call s:Autocmd('BufWritePost', +expand('<abuf>'))
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>'))
autocmd CursorHoldI * call s:Autocmd('CursorHoldI', +expand('<abuf>'))
autocmd BufNewFile,BufReadPost * call s:Autocmd('BufCreate', +expand('<abuf>'))
autocmd BufUnload * call s:SyncAutocmd('BufUnload', +expand('<abuf>'))
autocmd BufWritePre * call s:SyncAutocmd('BufWritePre', +expand('<abuf>'))
autocmd FocusGained * if mode() !~# '^c' | call s:Autocmd('FocusGained') | endif
autocmd VimResized * call s:Autocmd('VimResized', &columns, &lines)
autocmd VimLeavePre * let g:coc_vim_leaving = 1
autocmd BufReadCmd,FileReadCmd,SourceCmd list://* call coc#list#setup(expand('<amatch>'))
autocmd BufWriteCmd __coc_refactor__* :call coc#rpc#notify('saveRefactor', [+expand('<abuf>')])
autocmd ColorScheme * call s:Hi()
augroup end
if a:initialize == 0
call coc#rpc#request('attach', [])
echohl MoreMsg
echom '[coc.nvim] Event enabled'
echohl None
endif
endfunction
function! s:Hi() abort
hi default CocUnderline cterm=underline gui=underline
hi default CocBold term=bold cterm=bold gui=bold
hi default CocErrorSign ctermfg=Red guifg=#ff0000
hi default CocWarningSign ctermfg=Brown guifg=#ff922b
hi default CocInfoSign ctermfg=Yellow guifg=#fab005
hi default CocHintSign ctermfg=Blue guifg=#15aabf
hi default CocSelectedText ctermfg=Red guifg=#fb4934
hi default CocCodeLens ctermfg=Gray guifg=#999999
hi default link CocMenuSel PmenuSel
hi default link CocErrorFloat CocErrorSign
hi default link CocWarningFloat CocWarningSign
hi default link CocInfoFloat CocInfoSign
hi default link CocHintFloat CocHintSign
hi default link CocErrorHighlight CocUnderline
hi default link CocWarningHighlight CocUnderline
hi default link CocInfoHighlight CocUnderline
hi default link CocHintHighlight CocUnderline
hi default link 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 CocHighlightRead CocHighlightText
hi default link CocHighlightWrite CocHighlightText
if has('nvim')
hi default link CocFloating NormalFloat
else
hi default link CocFloating Pmenu
endif
if has('nvim-0.5.0')
hi default CocCursorTransparent gui=strikethrough blend=100
endif
if has('nvim')
let names = ['Error', 'Warning', 'Info', 'Hint']
for name in names
if !hlexists('Coc'.name.'VirtualText')
exe 'hi default link Coc'.name.'VirtualText Coc'.name.'Sign'
endif
endfor
endif
call s:AddAnsiGroups()
endfunction
function! s:FormatFromSelected(type)
call CocActionAsync('formatSelected', a:type)
endfunction
function! s:CodeActionFromSelected(type)
call CocActionAsync('codeAction', a:type)
endfunction
function! s:ShowInfo()
if coc#rpc#ready()
call coc#rpc#notify('showInfo', [])
else
let lines = []
echomsg 'coc.nvim service not started, checking environment...'
let node = get(g:, 'coc_node_path', $COC_NODE_PATH == '' ? 'node' : $COC_NODE_PATH)
if !executable(node)
call add(lines, 'Error: '.node.' is not executable!')
else
let output = trim(system(node . ' --version'))
let ms = matchlist(output, 'v\(\d\+\).\(\d\+\).\(\d\+\)')
if empty(ms) || str2nr(ms[1]) < 10 || (str2nr(ms[1]) == 10 && str2nr(ms[2]) < 12)
call add(lines, 'Error: Node version '.output.' < 10.12.0, please upgrade node.js')
endif
endif
" check bundle
let file = s:root.'/bin/server.js'
if filereadable(file)
let file = s:root.'/lib/attach.js'
if !filereadable(file)
call add(lines, 'Error: javascript bundle not found, please compile the code of coc.nvim.')
endif
else
let file = s:root.'/build/index.js'
if !filereadable(file)
call add(lines, 'Error: javascript bundle not found, please remove coc.nvim folder and reinstall it.')
endif
endif
if !empty(lines)
belowright vnew
setl filetype=nofile
call setline(1, lines)
else
if get(g:, 'coc_start_at_startup',1)
echohl MoreMsg | echon 'Service stopped for some unknown reason, try :CocStart' | echohl None
else
echohl MoreMsg | echon 'Start on startup is disabled, try :CocStart' | echohl None
endif
endif
endif
endfunction
command! -nargs=? CocDiagnostics :call s:OpenDiagnostics(<f-args>)
command! -nargs=0 CocInfo :call s:ShowInfo()
command! -nargs=0 CocOpenLog :call coc#rpc#notify('openLog', [])
command! -nargs=0 CocDisable :call s:Disable()
command! -nargs=0 CocEnable :call s:Enable(0)
command! -nargs=0 CocConfig :call s:OpenConfig()
command! -nargs=0 CocLocalConfig :call coc#rpc#notify('openLocalConfig', [])
command! -nargs=0 CocRestart :call coc#rpc#restart()
command! -nargs=0 CocStart :call coc#rpc#start_server()
command! -nargs=0 CocRebuild :call coc#util#rebuild()
command! -nargs=+ -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 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=* -range CocAction :call coc#rpc#notify('codeActionRange', [<line1>, <line2>, <f-args>])
command! -nargs=* -range CocFix :call coc#rpc#notify('codeActionRange', [<line1>, <line2>, 'quickfix'])
command! -nargs=0 CocUpdate :call coc#util#update_extensions(1)
command! -nargs=0 -bar CocUpdateSync :call coc#util#update_extensions()
command! -nargs=* -bar -complete=custom,s:InstallOptions CocInstall :call coc#util#install_extension([<f-args>])
call s:Enable(1)
call s:Hi()
vnoremap <silent> <Plug>(coc-range-select) :<C-u>call CocActionAsync('rangeSelect', visualmode(), v:true)<CR>
vnoremap <silent> <Plug>(coc-range-select-backward) :<C-u>call CocActionAsync('rangeSelect', visualmode(), v:false)<CR>
nnoremap <Plug>(coc-range-select) :<C-u>call CocActionAsync('rangeSelect', '', v:true)<CR>
nnoremap <Plug>(coc-codelens-action) :<C-u>call CocActionAsync('codeLensAction')<CR>
vnoremap <silent> <Plug>(coc-format-selected) :<C-u>call CocActionAsync('formatSelected', visualmode())<CR>
vnoremap <silent> <Plug>(coc-codeaction-selected) :<C-u>call CocActionAsync('codeAction', visualmode())<CR>
nnoremap <Plug>(coc-codeaction-selected) :<C-u>set operatorfunc=<SID>CodeActionFromSelected<CR>g@
nnoremap <Plug>(coc-codeaction) :<C-u>call CocActionAsync('codeAction', '')<CR>
nnoremap <Plug>(coc-codeaction-line) :<C-u>call CocActionAsync('codeAction', 'n')<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>
inoremap <silent> <Plug>CocRefresh <C-r>=coc#_complete()<CR>
nnoremap <silent> <Plug>(coc-cursors-operator) :<C-u>set operatorfunc=<SID>CursorRangeFromSelected<CR>g@
vnoremap <silent> <Plug>(coc-cursors-range) :<C-u>call coc#rpc#request('cursorsSelect', [bufnr('%'), 'range', visualmode()])<CR>
nnoremap <silent> <Plug>(coc-cursors-word) :<C-u>call coc#rpc#request('cursorsSelect', [bufnr('%'), 'word', 'n'])<CR>
nnoremap <silent> <Plug>(coc-cursors-position) :<C-u>call coc#rpc#request('cursorsSelect', [bufnr('%'), 'position', 'n'])<CR>
vnoremap <silent> <Plug>(coc-funcobj-i) :<C-U>call coc#rpc#request('selectSymbolRange', [v:true, visualmode(), ['Method', 'Function']])<CR>
vnoremap <silent> <Plug>(coc-funcobj-a) :<C-U>call coc#rpc#request('selectSymbolRange', [v:false, visualmode(), ['Method', 'Function']])<CR>
onoremap <silent> <Plug>(coc-funcobj-i) :<C-U>call coc#rpc#request('selectSymbolRange', [v:true, '', ['Method', 'Function']])<CR>
onoremap <silent> <Plug>(coc-funcobj-a) :<C-U>call coc#rpc#request('selectSymbolRange', [v:false, '', ['Method', 'Function']])<CR>
vnoremap <silent> <Plug>(coc-classobj-i) :<C-U>call coc#rpc#request('selectSymbolRange', [v:true, visualmode(), ['Interface', 'Struct', 'Class']])<CR>
vnoremap <silent> <Plug>(coc-classobj-a) :<C-U>call coc#rpc#request('selectSymbolRange', [v:false, visualmode(), ['Interface', 'Struct', 'Class']])<CR>
onoremap <silent> <Plug>(coc-classobj-i) :<C-U>call coc#rpc#request('selectSymbolRange', [v:true, '', ['Interface', 'Struct', 'Class']])<CR>
onoremap <silent> <Plug>(coc-classobj-a) :<C-U>call coc#rpc#request('selectSymbolRange', [v:false, '', ['Interface', 'Struct', 'Class']])<CR>

View file

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

27
vimrc
View file

@ -45,6 +45,7 @@ set autoindent
set autoread set autoread
set background=dark set background=dark
set backspace=indent,eol,start set backspace=indent,eol,start
set cmdheight=2
set colorcolumn=101 set colorcolumn=101
set directory=$TEMP//,/tmp//,. set directory=$TEMP//,/tmp//,.
set display+=lastline set display+=lastline
@ -67,6 +68,7 @@ set relativenumber
set ruler set ruler
set scrolloff=2 set scrolloff=2
set sessionoptions-=options set sessionoptions-=options
set shortmess+=c
set smartcase set smartcase
set smarttab set smarttab
set spl=en_gb nospell set spl=en_gb nospell
@ -75,6 +77,7 @@ set textwidth=72
set ttimeout set ttimeout
set ttimeoutlen=100 set ttimeoutlen=100
set ttyfast set ttyfast
set updatetime=300
set wrap set wrap
"============================================================================= "=============================================================================
@ -113,6 +116,24 @@ if has("eval")
set t_Co=16 set t_Co=16
endif endif
colorscheme PaperColor colorscheme PaperColor
" Use tab for trigger completion with characters ahead and navigate.
" NOTE: Use command ':verbose imap <tab>' to make sure tab is not mapped by
" other plugin before putting this into your config.
inoremap <silent><expr> <TAB>
\ pumvisible() ? "\<C-n>" :
\ <SID>check_back_space() ? "\<TAB>" :
\ coc#refresh()
inoremap <expr><S-TAB> pumvisible() ? "\<C-p>" : "\<C-h>"
function! s:check_back_space() abort
let col = col('.') - 1
return !col || getline('.')[col - 1] =~# '\s'
endfunction
inoremap <silent><expr> <cr> pumvisible() ? coc#_select_confirm()
\: "\<C-g>u\<CR>\<c-r>=coc#on_enter()\<CR>"
endif endif
"============================================================================= "=============================================================================
@ -151,6 +172,12 @@ if has("patch-7.3.541")
set formatoptions+=j set formatoptions+=j
endif endif
if has("patch-8.1.1564")
set signcolumn=number
else
set signcolumn=yes
endif
if has("printer") if has("printer")
set printheader=%t%h%m%=Page\ %N set printheader=%t%h%m%=Page\ %N
set printoptions=paper:A4,number:y,syntax:n set printoptions=paper:A4,number:y,syntax:n