diff --git a/pack/acp/start/coc.nvim/.gitignore b/pack/acp/start/coc.nvim/.gitignore
new file mode 100644
index 0000000..f9ec5e3
--- /dev/null
+++ b/pack/acp/start/coc.nvim/.gitignore
@@ -0,0 +1,13 @@
+lib
+*.map
+coverage
+__pycache__
+.pyc
+.log
+src
+publish.sh
+doc/tags
+doc/tags-cn
+node_modules
+src/__tests__/tags
+typings
diff --git a/pack/acp/start/coc.nvim/LICENSE.md b/pack/acp/start/coc.nvim/LICENSE.md
new file mode 100644
index 0000000..bee2bf1
--- /dev/null
+++ b/pack/acp/start/coc.nvim/LICENSE.md
@@ -0,0 +1,7 @@
+Copyright 2018-2018 by Qiming Zhao 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.
diff --git a/pack/acp/start/coc.nvim/Readme.md b/pack/acp/start/coc.nvim/Readme.md
new file mode 100644
index 0000000..008ff55
--- /dev/null
+++ b/pack/acp/start/coc.nvim/Readme.md
@@ -0,0 +1,611 @@
+
+
+
+
+
Make your Vim/Neovim as smart as VSCode.
+
+
+
+
+
+
+
+
+
+---
+
+## Why?
+
+- ๐ **Fast**: [instant increment completion](https://github.com/neoclide/coc.nvim/wiki/Completion-with-sources), increment buffer sync using buffer update events.
+- ๐ **Reliable**: typed language, tested with CI.
+- ๐ **Featured**: [full LSP support](https://github.com/neoclide/coc.nvim/wiki/Language-servers#supported-features)
+- โค๏ธ **Flexible**: [configured like VSCode](https://github.com/neoclide/coc.nvim/wiki/Using-the-configuration-file), [extensions work like in VSCode](https://github.com/neoclide/coc.nvim/wiki/Using-coc-extensions)
+
+## Quick Start
+
+Install [nodejs](https://nodejs.org/en/download/) >= 12.12:
+
+```bash
+curl -sL install-node.vercel.app/lts | bash
+```
+
+For [vim-plug](https://github.com/junegunn/vim-plug) users:
+
+```vim
+" Use release branch (recommend)
+Plug 'neoclide/coc.nvim', {'branch': 'release'}
+
+" Or build from source code by using yarn: https://yarnpkg.com
+Plug 'neoclide/coc.nvim', {'branch': 'master', 'do': 'yarn install --frozen-lockfile'}
+```
+
+in your `.vimrc` or `init.vim`, then restart Vim and run `:PlugInstall`.
+
+Checkout [Install
+coc.nvim](https://github.com/neoclide/coc.nvim/wiki/Install-coc.nvim) for
+more info.
+
+You **have to** install coc extension or configure language servers for
+LSP support.
+
+Install extensions like:
+
+ :CocInstall coc-json coc-tsserver
+
+Or configure language server in `coc-settings.json` opened by
+`:CocConfig`, like:
+
+```json
+{
+ "languageserver": {
+ "go": {
+ "command": "gopls",
+ "rootPatterns": ["go.mod"],
+ "trace.server": "verbose",
+ "filetypes": ["go"]
+ }
+ }
+}
+```
+
+Checkout wiki for more details:
+
+- [Completion with sources](https://github.com/neoclide/coc.nvim/wiki/Completion-with-sources)
+- [Using the configuration file](https://github.com/neoclide/coc.nvim/wiki/Using-the-configuration-file)
+- [Using coc extensions](https://github.com/neoclide/coc.nvim/wiki/Using-coc-extensions)
+- [Configure language servers](https://github.com/neoclide/coc.nvim/wiki/Language-servers)
+- [F.A.Q](https://github.com/neoclide/coc.nvim/wiki/F.A.Q)
+
+Checkout `:h coc-nvim` for vim interface.
+
+## Example vim configuration
+
+Configuration is required to make coc.nvim easier to work with, since it
+doesn't change your key-mappings or Vim options. This is done as much as
+possible to avoid conflict with your other plugins.
+
+**โ๏ธImportant**: Some Vim plugins could change key mappings. Please use
+command like`:verbose imap ` to make sure that your keymap has taken effect.
+
+```vim
+" Some servers have issues with backup files, see #649.
+set nobackup
+set nowritebackup
+
+" Having longer updatetime (default is 4000 ms = 4 s) leads to noticeable
+" delays and poor user experience.
+set updatetime=300
+
+" Always show the signcolumn, otherwise it would shift the text each time
+" diagnostics appear/become resolved.
+set signcolumn=yes
+
+"Use and for navigate completion list like built in completion.
+inoremap coc#pum#visible() ? coc#pum#next(1) : "\"
+inoremap coc#pum#visible() ? coc#pum#prev(1) : "\"
+
+" Use tab for trigger completion with characters ahead and navigate.
+" NOTE: Use command ':verbose imap ' to make sure tab is not mapped by
+" other plugin before putting this into your config.
+inoremap
+ \ coc#pum#visible() ? coc#pum#next(1):
+ \ CheckBackspace() ? "\" :
+ \ coc#refresh()
+inoremap coc#pum#visible() ? coc#pum#prev(1) : "\"
+
+function! CheckBackspace() abort
+ let col = col('.') - 1
+ return !col || getline('.')[col - 1] =~# '\s'
+endfunction
+
+" Use to trigger completion.
+if has('nvim')
+ inoremap coc#refresh()
+else
+ inoremap coc#refresh()
+endif
+
+" Make to accept selected completion item or notify coc.nvim to format
+" u starts a new undo break, please make your own choice.
+inoremap coc#pum#visible() ? coc#pum#confirm()
+ \: "\u\\=coc#on_enter()\"
+
+" Use `[g` and `]g` to navigate diagnostics
+" Use `:CocDiagnostics` to get all diagnostics of current buffer in location list.
+nmap [g (coc-diagnostic-prev)
+nmap ]g (coc-diagnostic-next)
+
+" GoTo code navigation.
+nmap gd (coc-definition)
+nmap gy (coc-type-definition)
+nmap gi (coc-implementation)
+nmap gr (coc-references)
+
+" Use K to show documentation in preview window.
+nnoremap K :call ShowDocumentation()
+
+function! ShowDocumentation()
+ if CocAction('hasProvider', 'hover')
+ call CocActionAsync('doHover')
+ else
+ call feedkeys('K', 'in')
+ endif
+endfunction
+
+" Highlight the symbol and its references when holding the cursor.
+autocmd CursorHold * silent call CocActionAsync('highlight')
+
+" Symbol renaming.
+nmap rn (coc-rename)
+
+" Formatting selected code.
+xmap f (coc-format-selected)
+nmap f (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: `aap` for current paragraph
+xmap a (coc-codeaction-selected)
+nmap a (coc-codeaction-selected)
+
+" Remap keys for applying codeAction to the current buffer.
+nmap ac (coc-codeaction)
+" Apply AutoFix to problem on the current line.
+nmap qf (coc-fix-current)
+
+" Run the Code Lens action on the current line.
+nmap cl (coc-codelens-action)
+
+" Map function and class text objects
+" NOTE: Requires 'textDocument.documentSymbol' support from the language server.
+xmap if (coc-funcobj-i)
+omap if (coc-funcobj-i)
+xmap af (coc-funcobj-a)
+omap af (coc-funcobj-a)
+xmap ic (coc-classobj-i)
+omap ic (coc-classobj-i)
+xmap ac (coc-classobj-a)
+omap ac (coc-classobj-a)
+
+" Remap and for scroll float windows/popups.
+if has('nvim-0.4.0') || has('patch-8.2.0750')
+ nnoremap coc#float#has_scroll() ? coc#float#scroll(1) : "\"
+ nnoremap coc#float#has_scroll() ? coc#float#scroll(0) : "\"
+ inoremap coc#float#has_scroll() ? "\=coc#float#scroll(1)\" : "\"
+ inoremap coc#float#has_scroll() ? "\=coc#float#scroll(0)\" : "\"
+ vnoremap coc#float#has_scroll() ? coc#float#scroll(1) : "\"
+ vnoremap coc#float#has_scroll() ? coc#float#scroll(0) : "\"
+endif
+
+" Use CTRL-S for selections ranges.
+" Requires 'textDocument/selectionRange' support of language server.
+nmap (coc-range-select)
+xmap (coc-range-select)
+
+" Add `:Format` command to format current buffer.
+command! -nargs=0 Format :call CocActionAsync('format')
+
+" Add `:Fold` command to fold current buffer.
+command! -nargs=? Fold :call CocAction('fold', )
+
+" Add `:OR` command for organize imports of the current buffer.
+command! -nargs=0 OR :call CocActionAsync('runCommand', 'editor.action.organizeImport')
+
+" Add (Neo)Vim's native statusline support.
+" NOTE: Please see `:h coc-status` for integrations with external plugins that
+" provide custom statusline: lightline.vim, vim-airline.
+set statusline^=%{coc#status()}%{get(b:,'coc_current_function','')}
+
+" Mappings for CoCList
+" Show all diagnostics.
+nnoremap a :CocList diagnostics
+" Manage extensions.
+nnoremap e :CocList extensions
+" Show commands.
+nnoremap c :CocList commands
+" Find symbol of current document.
+nnoremap o :CocList outline
+" Search workspace symbols.
+nnoremap s :CocList -I symbols
+" Do default action for next item.
+nnoremap j :CocNext
+" Do default action for previous item.
+nnoremap k :CocPrev
+" Resume latest coc list.
+nnoremap p :CocListResume
+```
+
+## Articles
+
+- [coc.nvim ๆไปถไฝ็ณปไป็ป](https://zhuanlan.zhihu.com/p/65524706)
+- [CocList ๅ
ฅๅๆๅ](https://zhuanlan.zhihu.com/p/71846145)
+- [Create coc.nvim extension to improve Vim experience](https://medium.com/@chemzqm/create-coc-nvim-extension-to-improve-vim-experience-4461df269173)
+- [How to write a coc.nvim extension (and why)](https://samroeca.com/coc-plugin.html)
+
+## Troubleshooting
+
+Try these steps when you have problem with coc.nvim.
+
+- Make sure your Vim version >= 8.0 by command `:version`.
+- If service failed to start, use command `:CocInfo` or `:checkhealth` on Neovim.
+- Checkout the log of coc.nvim by command `:CocOpenLog`.
+- When you have issues with the language server, it's recommended to [checkout
+ the output](https://github.com/neoclide/coc.nvim/wiki/Debug-language-server#using-output-channel).
+
+## Feedback
+
+- If you think Coc is useful, consider giving it a star.
+- If you have a question, [ask on gitter](https://gitter.im/neoclide/coc.nvim)
+- ไธญๆ็จๆท่ฏทๅฐ [ไธญๆ gitter](https://gitter.im/neoclide/coc-cn) ่ฎจ่ฎบ
+- If something is not working, [create an
+ issue](https://github.com/neoclide/coc.nvim/issues/new).
+
+## Backers
+
+[Become a backer](https://opencollective.com/cocnvim#backer) and get your image on our README on GitHub with a link to your site.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Contributors
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+This project follows the [all-contributors](https://allcontributors.org) specification.
+Contributions of any kind are welcome!
+
+## License
+
+Anti 996
diff --git a/pack/acp/start/coc.nvim/autoload/coc.vim b/pack/acp/start/coc.nvim/autoload/coc.vim
new file mode 100644
index 0000000..d5cdaf6
--- /dev/null
+++ b/pack/acp/start/coc.nvim/autoload/coc.vim
@@ -0,0 +1,183 @@
+scriptencoding utf-8
+let g:coc#_context = {'start': 0, 'preselect': -1,'candidates': []}
+let g:coc_user_config = get(g:, 'coc_user_config', {})
+let g:coc_global_extensions = get(g:, 'coc_global_extensions', [])
+let g:coc_selected_text = ''
+let g:coc_vim_commands = []
+let s:watched_keys = []
+let s:is_vim = !has('nvim')
+let s:error_sign = get(g:, 'coc_status_error_sign', has('mac') ? 'โ ' : 'E')
+let s:warning_sign = get(g:, 'coc_status_warning_sign', has('mac') ? 'โ ๏ธ ' : 'W')
+let s:select_api = exists('*nvim_select_popupmenu_item')
+let s:callbacks = {}
+let s:hide_pum = has('nvim-0.6.1') || has('patch-8.2.3389')
+
+function! coc#expandable() abort
+ return coc#rpc#request('snippetCheck', [1, 0])
+endfunction
+
+function! coc#jumpable() abort
+ return coc#rpc#request('snippetCheck', [0, 1])
+endfunction
+
+function! coc#expandableOrJumpable() abort
+ return coc#rpc#request('snippetCheck', [1, 1])
+endfunction
+
+" add vim command to CocCommand list
+function! coc#add_command(id, cmd, ...)
+ let config = {'id':a:id, 'cmd':a:cmd, 'title': get(a:,1,'')}
+ call add(g:coc_vim_commands, config)
+ if !coc#rpc#ready() | return | endif
+ call coc#rpc#notify('addCommand', [config])
+endfunction
+
+function! coc#on_enter()
+ call coc#rpc#notify('CocAutocmd', ['Enter', bufnr('%')])
+ return ''
+endfunction
+
+function! coc#_insert_key(method, key, ...) abort
+ let prefix = ''
+ if get(a:, 1, 1)
+ if pumvisible()
+ if s:hide_pum
+ let prefix = "\\"
+ else
+ let g:coc_disable_space_report = 1
+ let prefix = "\\"
+ endif
+ endif
+ endif
+ return prefix."\=coc#rpc#".a:method."('doKeymap', ['".a:key."'])\"
+endfunction
+
+function! coc#_complete() abort
+ let items = get(g:coc#_context, 'candidates', [])
+ let preselect = get(g:coc#_context, 'preselect', -1)
+ let startcol = g:coc#_context.start + 1
+ if s:select_api && len(items) && preselect != -1
+ noa call complete(startcol, items)
+ call nvim_select_popupmenu_item(preselect, v:false, v:false, {})
+ " use specific key to preselect item at once
+ call feedkeys("\\" , 'i')
+ else
+ if pumvisible()
+ let g:coc_disable_complete_done = 1
+ endif
+ call complete(startcol, items)
+ endif
+ return ''
+endfunction
+
+function! coc#_do_complete(start, items, preselect, changedtick)
+ if b:changedtick != a:changedtick
+ return
+ endif
+ let g:coc#_context = {
+ \ 'start': a:start,
+ \ 'candidates': a:items,
+ \ 'preselect': a:preselect
+ \}
+ if mode() =~# 'i'
+ call coc#_complete()
+ endif
+endfunction
+
+function! coc#_cancel(...)
+ call coc#pum#close()
+endfunction
+
+" used for statusline
+function! coc#status()
+ let info = get(b:, 'coc_diagnostic_info', {})
+ let msgs = []
+ if !empty(info) && get(info, 'error', 0)
+ call add(msgs, s:error_sign . info['error'])
+ endif
+ if !empty(info) && get(info, 'warning', 0)
+ call add(msgs, s:warning_sign . info['warning'])
+ endif
+ return coc#compat#trim(join(msgs, ' ') . ' ' . get(g:, 'coc_status', ''))
+endfunction
+
+function! coc#config(section, value)
+ let g:coc_user_config[a:section] = a:value
+ call coc#rpc#notify('updateConfig', [a:section, a:value])
+endfunction
+
+function! coc#add_extension(...)
+ if a:0 == 0 | return | endif
+ call extend(g:coc_global_extensions, a:000)
+endfunction
+
+function! coc#_watch(key)
+ if s:is_vim | return | endif
+ if index(s:watched_keys, a:key) == -1
+ call add(s:watched_keys, a:key)
+ call dictwatcheradd(g:, a:key, function('s:GlobalChange'))
+ endif
+endfunction
+
+function! coc#_unwatch(key)
+ if s:is_vim | return | endif
+ let idx = index(s:watched_keys, a:key)
+ if idx != -1
+ call remove(s:watched_keys, idx)
+ call dictwatcherdel(g:, a:key, function('s:GlobalChange'))
+ endif
+endfunction
+
+function! s:GlobalChange(dict, key, val)
+ call coc#rpc#notify('GlobalChange', [a:key, get(a:val, 'old', v:null), get(a:val, 'new', v:null)])
+endfunction
+
+function! coc#on_notify(id, method, Cb)
+ let key = a:id. '-'.a:method
+ let s:callbacks[key] = a:Cb
+ call coc#rpc#notify('registNotification', [a:id, a:method])
+endfunction
+
+function! coc#do_notify(id, method, result)
+ let key = a:id. '-'.a:method
+ let Fn = s:callbacks[key]
+ if !empty(Fn)
+ call Fn(a:result)
+ endif
+endfunction
+
+function! coc#start(...)
+ let opt = coc#util#get_complete_option()
+ call CocActionAsync('startCompletion', extend(opt, get(a:, 1, {})))
+ return ''
+endfunction
+
+function! coc#refresh() abort
+ return "\=coc#start()\"
+endfunction
+
+function! coc#_select_confirm() abort
+ call timer_start(10, { -> coc#pum#select_confirm()})
+ return s:is_vim || has('nvim-0.5.0') ? "\" : "\\"
+endfunction
+
+function! coc#complete_indent() abort
+ let curpos = getcurpos()
+ let indent_len = len(matchstr(getline('.'), '^\s*'))
+ let startofline = &startofline
+ let virtualedit = &virtualedit
+ set nostartofline
+ set virtualedit=all
+ normal! ==
+ let &startofline = startofline
+ let &virtualedit = virtualedit
+ let shift = len(matchstr(getline('.'), '^\s*')) - indent_len
+ let curpos[2] += shift
+ let curpos[4] += shift
+ call cursor(curpos[1:])
+ if shift != 0
+ if s:is_vim
+ call timer_start(0, { -> execute('redraw')})
+ endif
+ endif
+endfunction
diff --git a/pack/acp/start/coc.nvim/autoload/coc/api.vim b/pack/acp/start/coc.nvim/autoload/coc/api.vim
new file mode 100644
index 0000000..b3af8b1
--- /dev/null
+++ b/pack/acp/start/coc.nvim/autoload/coc/api.vim
@@ -0,0 +1,678 @@
+" ============================================================================
+" Description: Client api used by vim8
+" Author: Qiming Zhao
+" Licence: Anti 996 licence
+" Last Modified: Jun 03, 2022
+" ============================================================================
+if has('nvim') | finish | endif
+scriptencoding utf-8
+let s:funcs = {}
+let s:prop_offset = get(g:, 'coc_text_prop_offset', 1000)
+let s:namespace_id = 1
+let s:namespace_cache = {}
+let s:max_src_id = 1000
+" bufnr => max textprop id
+let s:buffer_id = {}
+" srcId => list of types
+let s:id_types = {}
+
+" helper {{
+function! s:buf_line_count(bufnr) abort
+ if bufnr('%') == a:bufnr
+ return line('$')
+ endif
+ if exists('*getbufinfo')
+ let info = getbufinfo(a:bufnr)
+ if empty(info)
+ return 0
+ endif
+ " vim 8.1 has getbufinfo but no linecount
+ if has_key(info[0], 'linecount')
+ return info[0]['linecount']
+ endif
+ endif
+ if exists('*getbufline')
+ let lines = getbufline(a:bufnr, 1, '$')
+ return len(lines)
+ endif
+ let curr = bufnr('%')
+ execute 'noa buffer '.a:bufnr
+ let n = line('$')
+ execute 'noa buffer '.curr
+ return n
+endfunction
+
+function! s:execute(cmd)
+ if a:cmd =~# '^echo'
+ execute a:cmd
+ else
+ silent! execute a:cmd
+ endif
+endfunction
+" }}"
+
+" nvim client methods {{
+function! s:funcs.set_current_dir(dir) abort
+ execute 'cd '.a:dir
+endfunction
+
+function! s:funcs.set_var(name, value) abort
+ execute 'let g:'.a:name.'= a:value'
+endfunction
+
+function! s:funcs.del_var(name) abort
+ execute 'unlet g:'.a:name
+endfunction
+
+function! s:funcs.set_option(name, value) abort
+ execute 'let &'.a:name.' = a:value'
+endfunction
+
+function! s:funcs.set_current_buf(bufnr) abort
+ if !bufexists(a:bufnr) | return | endif
+ execute 'buffer '.a:bufnr
+endfunction
+
+function! s:funcs.set_current_win(win_id) abort
+ let [tabnr, winnr] = win_id2tabwin(a:win_id)
+ if tabnr == 0 | return | endif
+ execute 'normal! '.tabnr.'gt'
+ execute winnr.' wincmd w'
+endfunction
+
+function! s:funcs.set_current_tabpage(tabnr) abort
+ execute 'normal! '.a:tabnr.'gt'
+endfunction
+
+function! s:funcs.list_wins() abort
+ return map(getwininfo(), 'v:val["winid"]')
+endfunction
+
+function s:inspect_type(v) abort
+ let types = ['Number', 'String', 'Funcref', 'List', 'Dictionary', 'Float', 'Boolean', 'Null']
+ return get(types, type(a:v), 'Unknown')
+endfunction
+
+function! s:funcs.call_atomic(calls)
+ let res = []
+ for i in range(len(a:calls))
+ let [key, arglist] = a:calls[i]
+ let name = key[5:]
+ try
+ call add(res, call(s:funcs[name], arglist))
+ catch /.*/
+ return [res, [i, "VimException(".s:inspect_type(v:exception).")", v:exception . ' on '.v:throwpoint]]
+ endtry
+ endfor
+ return [res, v:null]
+endfunction
+
+function! s:funcs.set_client_info(...) abort
+endfunction
+
+function! s:funcs.subscribe(...) abort
+endfunction
+
+function! s:funcs.unsubscribe(...) abort
+endfunction
+
+function! s:funcs.call_function(method, args) abort
+ return call(a:method, a:args)
+endfunction
+
+function! s:funcs.call_dict_function(dict, method, args) abort
+ return call(a:method, a:args, a:dict)
+endfunction
+
+function! s:funcs.command(command) abort
+ " command that could cause cursor vanish
+ if a:command =~# '^echo' || a:command =~# '^redraw' || a:command =~# '^sign place'
+ call timer_start(0, {-> s:execute(a:command)})
+ else
+ execute a:command
+ let err = get(g:, 'errmsg', '')
+ " get error from python script run.
+ if !empty(err)
+ unlet g:errmsg
+ throw err
+ endif
+ endif
+endfunction
+
+function! s:funcs.eval(expr) abort
+ return eval(a:expr)
+endfunction
+
+function! s:funcs.get_api_info()
+ let names = coc#api#func_names()
+ return [1, {'functions': map(names, '{"name": "nvim_".v:val}')}]
+endfunction
+
+function! s:funcs.list_bufs()
+ return map(getbufinfo({'bufloaded': 1}), 'v:val["bufnr"]')
+endfunction
+
+function! s:funcs.feedkeys(keys, mode, escape_csi)
+ call feedkeys(a:keys, a:mode)
+endfunction
+
+function! s:funcs.list_runtime_paths()
+ return globpath(&runtimepath, '', 0, 1)
+endfunction
+
+function! s:funcs.command_output(cmd)
+ return execute(a:cmd)
+endfunction
+
+function! s:funcs.get_current_line()
+ return getline('.')
+endfunction
+
+function! s:funcs.set_current_line(line)
+ call setline('.', a:line)
+endfunction
+
+function! s:funcs.del_current_line(line)
+ execute 'normal! dd'
+endfunction
+
+function! s:funcs.get_var(var)
+ return get(g:, a:var, v:null)
+endfunction
+
+function! s:funcs.get_vvar(var)
+ return get(v:, a:var, v:null)
+endfunction
+
+function! s:funcs.get_option(name)
+ return eval('&'.a:name)
+endfunction
+
+function! s:funcs.get_current_buf()
+ return bufnr('%')
+endfunction
+
+function! s:funcs.get_current_win()
+ return win_getid()
+endfunction
+
+function! s:funcs.get_current_tabpage()
+ return tabpagenr()
+endfunction
+
+function! s:funcs.list_tabpages()
+ return range(1, tabpagenr('$'))
+endfunction
+
+function! s:funcs.get_mode()
+ return {'blocking': v:false, 'mode': mode()}
+endfunction
+
+function! s:funcs.strwidth(str)
+ return strwidth(a:str)
+endfunction
+
+function! s:funcs.out_write(str)
+ echon a:str
+ call timer_start(0, {-> s:execute('redraw')})
+endfunction
+
+function! s:funcs.err_write(str)
+ "echoerr a:str
+endfunction
+
+function! s:funcs.err_writeln(str)
+ echohl ErrorMsg
+ echom a:str
+ echohl None
+ call timer_start(0, {-> s:execute('redraw')})
+endfunction
+
+function! s:funcs.create_namespace(name) abort
+ if empty(a:name)
+ let id = s:namespace_id
+ let s:namespace_id = s:namespace_id + 1
+ return id
+ endif
+ let id = get(s:namespace_cache, a:name, 0)
+ if !id
+ let id = s:namespace_id
+ let s:namespace_id = s:namespace_id + 1
+ let s:namespace_cache[a:name] = id
+ endif
+ return id
+endfunction
+" }}
+
+" buffer methods {{
+function! s:funcs.buf_set_option(bufnr, name, val)
+ let val = a:val
+ if val is v:true
+ let val = 1
+ elseif val is v:false
+ let val = 0
+ endif
+ return setbufvar(a:bufnr, '&'.a:name, val)
+endfunction
+
+function! s:funcs.buf_get_changedtick(bufnr)
+ return getbufvar(a:bufnr, 'changedtick')
+endfunction
+
+function! s:funcs.buf_is_valid(bufnr)
+ return bufloaded(a:bufnr) ? v:true : v:false
+endfunction
+
+function! s:funcs.buf_get_mark(bufnr, name)
+ let nr = bufnr('%')
+ if a:bufnr != 0 || a:bufnr != nr
+ throw 'buf_get_mark support current buffer only'
+ endif
+ return [line("'" . a:name), col("'" . a:name)]
+endfunction
+
+function! s:funcs.buf_add_highlight(bufnr, srcId, hlGroup, line, colStart, colEnd, ...) abort
+ if !has('patch-8.1.1719')
+ return
+ endif
+ if a:srcId == 0
+ let srcId = s:max_src_id + 1
+ let s:max_src_id = srcId
+ else
+ let srcId = a:srcId
+ endif
+ let bufnr = a:bufnr == 0 ? bufnr('%') : a:bufnr
+ let type = a:hlGroup.'_'.srcId
+ let types = get(s:id_types, srcId, [])
+ if index(types, type) == -1
+ call add(types, type)
+ let s:id_types[srcId] = types
+ call prop_type_add(type, extend({'highlight': a:hlGroup}, get(a:, 1, {})))
+ endif
+ let end = a:colEnd == -1 ? strlen(getbufline(bufnr, a:line + 1)[0]) + 1 : a:colEnd + 1
+ if end < a:colStart + 1
+ return
+ endif
+ let id = s:generate_id(a:bufnr)
+ try
+ call prop_add(a:line + 1, a:colStart + 1, {'bufnr': bufnr, 'type': type, 'id': id, 'end_col': end})
+ catch /^Vim\%((\a\+)\)\=:E967/
+ " ignore 967
+ endtry
+ if a:srcId == 0
+ " return generated srcId
+ return srcId
+ endif
+endfunction
+
+function! s:funcs.buf_clear_namespace(bufnr, srcId, startLine, endLine) abort
+ if !has('patch-8.1.1719')
+ return
+ endif
+ let bufnr = a:bufnr == 0 ? bufnr('%') : a:bufnr
+ let start = a:startLine + 1
+ let end = a:endLine == -1 ? len(getbufline(bufnr, 1, '$')) : a:endLine
+ if a:srcId == -1
+ if has_key(s:buffer_id, a:bufnr)
+ unlet s:buffer_id[a:bufnr]
+ endif
+ call prop_clear(start, end, {'bufnr' : bufnr})
+ else
+ for type in get(s:id_types, a:srcId, [])
+ try
+ call prop_remove({'bufnr': bufnr, 'all': 1, 'type': type}, start, end)
+ catch /^Vim\%((\a\+)\)\=:E968/
+ " ignore 968
+ endtry
+ endfor
+ endif
+endfunction
+
+function! s:funcs.buf_line_count(bufnr) abort
+ return s:buf_line_count(a:bufnr)
+endfunction
+
+function! s:funcs.buf_attach(...)
+ " not supported
+ return 1
+endfunction
+
+function! s:funcs.buf_detach()
+ " not supported
+ return 1
+endfunction
+
+function! s:funcs.buf_get_lines(bufnr, start, end, strict) abort
+ let lines = getbufline(a:bufnr, 1, '$')
+ let start = a:start < 0 ? a:start + 1 : a:start
+ let end = a:end < 0 ? a:end + 1 : a:end
+ if a:strict && end > len(lines)
+ throw 'line number out of range: '. end
+ endif
+ return lines[start : end - 1]
+endfunction
+
+function! s:funcs.buf_set_lines(bufnr, start, end, strict, ...) abort
+ let bufnr = a:bufnr == 0 ? bufnr('%') : a:bufnr
+ if !bufloaded(bufnr)
+ return
+ endif
+ let replacement = get(a:, 1, [])
+ let lineCount = s:buf_line_count(bufnr)
+ let startLnum = a:start >= 0 ? a:start + 1 : lineCount + a:start + 2
+ let end = a:end >= 0 ? a:end : lineCount + a:end + 1
+ if end == lineCount + 1
+ let end = lineCount
+ endif
+ let delCount = end - (startLnum - 1)
+ let changeBuffer = 0
+ let curr = bufnr('%')
+ if bufnr != curr && !exists('*setbufline')
+ let changeBuffer = 1
+ exe 'buffer '.bufnr
+ endif
+ if bufnr == curr || changeBuffer
+ " replace
+ let storeView = winsaveview()
+ if delCount == len(replacement)
+ call setline(startLnum, replacement)
+ else
+ if len(replacement)
+ call append(startLnum - 1, replacement)
+ endif
+ if delCount
+ let start = startLnum + len(replacement)
+ let saved_reg = @"
+ let system_reg = @*
+ if exists('*deletebufline')
+ silent call deletebufline(curr, start, start + delCount - 1)
+ else
+ silent execute start . ','.(start + delCount - 1).'d'
+ endif
+ let @" = saved_reg
+ let @* = system_reg
+ endif
+ endif
+ call winrestview(storeView)
+ if changeBuffer
+ exe 'buffer '.curr
+ endif
+ elseif exists('*setbufline')
+ " replace
+ if delCount == len(replacement)
+ " 8.0.1039
+ call setbufline(bufnr, startLnum, replacement)
+ else
+ if len(replacement)
+ " 8.10037
+ call appendbufline(bufnr, startLnum - 1, replacement)
+ endif
+ if delCount
+ let start = startLnum + len(replacement)
+ let saved_reg = @"
+ let system_reg = @*
+ "8.1.0039
+ silent call deletebufline(bufnr, start, start + delCount - 1)
+ let @" = saved_reg
+ let @* = system_reg
+ endif
+ endif
+ endif
+endfunction
+
+function! s:funcs.buf_set_name(bufnr, name) abort
+ let nr = bufnr('%')
+ if a:bufnr != nr
+ throw 'buf_set_name support current buffer only'
+ else
+ execute '0f'
+ execute 'file '.fnameescape(a:name)
+ endif
+endfunction
+
+function! s:funcs.buf_get_var(bufnr, name)
+ return getbufvar(a:bufnr, a:name)
+endfunction
+
+function! s:funcs.buf_set_var(bufnr, name, val)
+ if !bufloaded(a:bufnr) | return | endif
+ call setbufvar(a:bufnr, a:name, a:val)
+endfunction
+
+function! s:funcs.buf_del_var(bufnr, name)
+ if bufnr == bufnr('%')
+ execute 'unlet! b:'.a:name
+ elseif exists('*win_execute')
+ let winid = coc#compat#buf_win_id(a:bufnr)
+ if winid != -1
+ call win_execute(winid, 'unlet! b:'.a:name)
+ endif
+ endif
+endfunction
+
+function! s:funcs.buf_get_option(bufnr, name)
+ return getbufvar(a:bufnr, '&'.a:name)
+endfunction
+
+function! s:funcs.buf_get_name(bufnr)
+ return bufname(a:bufnr)
+endfunction
+" }}
+
+" window methods {{
+function! s:funcs.win_get_buf(winid)
+ return winbufnr(a:winid)
+endfunction
+
+function! s:funcs.win_get_position(win_id) abort
+ let [row, col] = win_screenpos(a:win_id)
+ if row == 0 && col == 0
+ throw 'Invalid window '.a:win_id
+ endif
+ return [row - 1, col - 1]
+endfunction
+
+function! s:funcs.win_get_height(win_id) abort
+ return winheight(a:win_id)
+endfunction
+
+function! s:funcs.win_get_width(win_id) abort
+ return winwidth(a:win_id)
+endfunction
+
+if exists('*win_execute')
+ function! s:win_execute(win_id, cmd, ...) abort
+ let ref = get(a:000, 0, v:null)
+ let cmd = ref is v:null ? a:cmd : 'let ref["out"] = ' . a:cmd
+ call win_execute(a:win_id, cmd)
+ endfunction
+else
+ function! s:win_execute(win_id, cmd, ...) abort
+ let ref = get(a:000, 0, v:null)
+ let cmd = ref is v:null ? a:cmd : 'let ref["out"] = ' . a:cmd
+ let winid = win_getid()
+ if winid == a:win_id
+ execute cmd
+ else
+ let goto_status = win_gotoid(a:win_id)
+ if !goto_status
+ return
+ endif
+ execute cmd
+ call win_gotoid(winid)
+ endif
+ endfunction
+endif
+
+function! s:get_tabnr(winid) abort
+ let ref = {}
+ call s:win_execute(a:winid, 'tabpagenr()', ref)
+ return get(ref, 'out', 0)
+endfunction
+
+function! s:funcs.win_get_cursor(win_id) abort
+ let ref = {}
+ call s:win_execute(a:win_id, "[line('.'), col('.')-1]", ref)
+ return get(ref, 'out', 0)
+endfunction
+
+function! s:funcs.win_get_var(win_id, name, ...) abort
+ let tabnr = s:get_tabnr(a:win_id)
+ if tabnr
+ return gettabwinvar(tabnr, a:win_id, a:name, get(a:, 1, v:null))
+ endif
+ throw 'window '.a:win_id. ' not a visible window'
+endfunction
+
+function! s:funcs.win_set_width(win_id, width) abort
+ call s:win_execute(a:win_id, 'vertical resize '.a:width)
+endfunction
+
+function! s:funcs.win_set_buf(win_id, buf_id) abort
+ call s:win_execute(a:win_id, 'buffer '.a:buf_id)
+endfunction
+
+function! s:funcs.win_get_option(win_id, name) abort
+ let tabnr = s:get_tabnr(a:win_id)
+ if tabnr
+ return gettabwinvar(tabnr, a:win_id, '&'.a:name)
+ endif
+ throw 'window '.a:win_id. ' not a valid window'
+endfunction
+
+function! s:funcs.win_set_height(win_id, height) abort
+ return s:win_execute(a:win_id, 'resize '.a:height)
+endfunction
+
+function! s:funcs.win_set_option(win_id, name, value) abort
+ let val = a:value
+ if val is v:true
+ let val = 1
+ elseif val is v:false
+ let val = 0
+ endif
+ let tabnr = s:get_tabnr(a:win_id)
+ if tabnr
+ call settabwinvar(tabnr, a:win_id, '&'.a:name, val)
+ else
+ throw 'window '.a:win_id. ' not a valid window'
+ endif
+endfunction
+
+function! s:funcs.win_set_var(win_id, name, value) abort
+ let tabnr = s:get_tabnr(a:win_id)
+ if tabnr
+ call settabwinvar(tabnr, a:win_id, a:name, a:value)
+ else
+ throw "Invalid window id ".a:win_id
+ endif
+endfunction
+
+function! s:funcs.win_del_var(win_id, name) abort
+ call s:win_execute(a:win_id, 'unlet! w:'.a:name)
+endfunction
+
+function! s:funcs.win_is_valid(win_id) abort
+ let info = getwininfo(a:win_id)
+ return empty(info) ? v:false : v:true
+endfunction
+
+function! s:funcs.win_get_number(win_id) abort
+ let info = getwininfo(a:win_id)
+ if empty(info)
+ throw 'Invalid window id '.a:win_id
+ endif
+ return info[0]['winnr']
+endfunction
+
+function! s:funcs.win_set_cursor(win_id, pos) abort
+ let [line, col] = a:pos
+ call s:win_execute(a:win_id, 'call cursor('.line.','.(col + 1).')')
+endfunction
+
+function! s:funcs.win_close(win_id, ...) abort
+ let force = get(a:, 1, 0)
+ call s:win_execute(a:win_id, 'close'.(force ? '!' : ''))
+endfunction
+
+function! s:funcs.win_get_tabpage(win_id) abort
+ let tabnr = s:get_tabnr(a:win_id)
+ if !tabnr
+ throw 'Invalid window id '.a:win_id
+ endif
+ return tabnr
+endfunction
+" }}
+
+" tabpage methods {{
+function! s:funcs.tabpage_get_number(id)
+ return a:id
+endfunction
+
+function! s:funcs.tabpage_list_wins(tabnr)
+ let info = getwininfo()
+ return map(filter(info, 'v:val["tabnr"] == a:tabnr'), 'v:val["winid"]')
+endfunction
+
+function! s:funcs.tabpage_get_var(tabnr, name)
+ return gettabvar(a:tabnr, a:name, v:null)
+endfunction
+
+function! s:funcs.tabpage_set_var(tabnr, name, value)
+ call settabvar(a:tabnr, a:name, a:value)
+endfunction
+
+function! s:funcs.tabpage_del_var(tabnr, name)
+ call settabvar(a:tabnr, a:name, v:null)
+endfunction
+
+function! s:funcs.tabpage_is_valid(tabnr)
+ let max = tabpagenr('$')
+ return a:tabnr <= max
+endfunction
+
+function! s:funcs.tabpage_get_win(tabnr)
+ let wnr = tabpagewinnr(a:tabnr)
+ return win_getid(wnr, a:tabnr)
+endfunction
+
+function! s:generate_id(bufnr) abort
+ let max = get(s:buffer_id, a:bufnr, s:prop_offset)
+ let id = max + 1
+ let s:buffer_id[a:bufnr] = id
+ return id
+endfunction
+" }}
+
+function! coc#api#get_types(srcId) abort
+ return get(s:id_types, a:srcId, [])
+endfunction
+
+function! coc#api#func_names() abort
+ return keys(s:funcs)
+endfunction
+
+function! coc#api#call(method, args) abort
+ let err = v:null
+ let res = v:null
+ try
+ let res = call(s:funcs[a:method], a:args)
+ catch /.*/
+ let err = v:exception .' on api "'.a:method.'" '.json_encode(a:args)
+ endtry
+ return [err, res]
+endfunction
+
+function! coc#api#exec(method, args) abort
+ return call(s:funcs[a:method], a:args)
+endfunction
+
+function! coc#api#notify(method, args) abort
+ try
+ call call(s:funcs[a:method], a:args)
+ catch /.*/
+ let g:b = v:exception
+ call coc#rpc#notify('nvim_error_event', [0, v:exception.' on api "'.a:method.'" '.json_encode(a:args)])
+ endtry
+endfunction
+" vim: set sw=2 ts=2 sts=2 et tw=78 foldmarker={{,}} foldmethod=marker foldlevel=0:
diff --git a/pack/acp/start/coc.nvim/autoload/coc/client.vim b/pack/acp/start/coc.nvim/autoload/coc/client.vim
new file mode 100644
index 0000000..dae1e77
--- /dev/null
+++ b/pack/acp/start/coc.nvim/autoload/coc/client.vim
@@ -0,0 +1,340 @@
+scriptencoding utf-8
+let s:root = expand(':h:h:h')
+let s:is_vim = !has('nvim')
+let s:is_win = has("win32") || has("win64")
+let s:clients = {}
+
+if get(g:, 'node_client_debug', 0)
+ echohl WarningMsg | echo '[coc.nvim] Enable g:node_client_debug could impact your vim experience' | echohl None
+ let $NODE_CLIENT_LOG_LEVEL = 'debug'
+ if exists('$NODE_CLIENT_LOG_FILE')
+ let s:logfile = resolve($NODE_CLIENT_LOG_FILE)
+ else
+ let s:logfile = tempname()
+ let $NODE_CLIENT_LOG_FILE = s:logfile
+ endif
+endif
+
+" create a client
+function! coc#client#create(name, command)
+ let client = {}
+ let client['command'] = a:command
+ let client['name'] = a:name
+ let client['running'] = 0
+ let client['async_req_id'] = 1
+ let client['async_callbacks'] = {}
+ " vim only
+ let client['channel'] = v:null
+ " neovim only
+ let client['chan_id'] = 0
+ let client['start'] = function('s:start', [], client)
+ let client['request'] = function('s:request', [], client)
+ let client['notify'] = function('s:notify', [], client)
+ let client['request_async'] = function('s:request_async', [], client)
+ let client['on_async_response'] = function('s:on_async_response', [], client)
+ let s:clients[a:name] = client
+ return client
+endfunction
+
+function! s:start() dict
+ if self.running | return | endif
+ if !isdirectory(getcwd())
+ echohl Error | echon '[coc.nvim] Current cwd is not a valid directory.' | echohl None
+ return
+ endif
+ let timeout = string(get(g:, 'coc_channel_timeout', 30))
+ let tmpdir = fnamemodify(tempname(), ':p:h')
+ if s:is_vim
+ if get(g:, 'node_client_debug', 0)
+ let file = tmpdir . '/coc.log'
+ call ch_logfile(file, 'w')
+ echohl MoreMsg | echo '[coc.nvim] channel log to '.file | echohl None
+ endif
+ let options = {
+ \ 'in_mode': 'json',
+ \ 'out_mode': 'json',
+ \ 'err_mode': 'nl',
+ \ 'err_cb': {channel, message -> s:on_stderr(self.name, split(message, "\n"))},
+ \ 'exit_cb': {channel, code -> s:on_exit(self.name, code)},
+ \ 'env': {
+ \ 'NODE_NO_WARNINGS': '1',
+ \ 'VIM_NODE_RPC': '1',
+ \ 'COC_NVIM': '1',
+ \ 'COC_CHANNEL_TIMEOUT': timeout,
+ \ 'TMPDIR': tmpdir,
+ \ }
+ \}
+ if has("patch-8.1.350")
+ let options['noblock'] = 1
+ endif
+ let job = job_start(self.command, options)
+ let status = job_status(job)
+ if status !=# 'run'
+ let self.running = 0
+ echohl Error | echom 'Failed to start '.self.name.' service' | echohl None
+ return
+ endif
+ let self['running'] = 1
+ let self['channel'] = job_getchannel(job)
+ else
+ let original = {}
+ let opts = {
+ \ 'rpc': 1,
+ \ 'on_stderr': {channel, msgs -> s:on_stderr(self.name, msgs)},
+ \ 'on_exit': {channel, code -> s:on_exit(self.name, code)},
+ \ }
+ if has('nvim-0.5.0')
+ " could use env option
+ let opts['env'] = {
+ \ 'COC_NVIM': '1',
+ \ 'NODE_NO_WARNINGS': '1',
+ \ 'COC_CHANNEL_TIMEOUT': timeout,
+ \ 'TMPDIR': tmpdir
+ \ }
+ else
+ if exists('*getenv')
+ let original = {
+ \ 'NODE_NO_WARNINGS': getenv('NODE_NO_WARNINGS'),
+ \ 'TMPDIR': getenv('TMPDIR'),
+ \ }
+ endif
+ if exists('*setenv')
+ call setenv('COC_NVIM', '1')
+ call setenv('NODE_NO_WARNINGS', '1')
+ call setenv('COC_CHANNEL_TIMEOUT', timeout)
+ call setenv('TMPDIR', tmpdir)
+ else
+ let $NODE_NO_WARNINGS = 1
+ let $TMPDIR = tmpdir
+ endif
+ endif
+ let chan_id = jobstart(self.command, opts)
+ if !empty(original)
+ if exists('*setenv')
+ for key in keys(original)
+ call setenv(key, original[key])
+ endfor
+ else
+ let $TMPDIR = original['TMPDIR']
+ endif
+ endif
+ if chan_id <= 0
+ echohl Error | echom 'Failed to start '.self.name.' service' | echohl None
+ return
+ endif
+ let self['chan_id'] = chan_id
+ let self['running'] = 1
+ endif
+endfunction
+
+function! s:on_stderr(name, msgs)
+ if get(g:, 'coc_vim_leaving', 0) | return | endif
+ if get(g:, 'coc_disable_uncaught_error', 0) | return | endif
+ let data = filter(copy(a:msgs), '!empty(v:val)')
+ if empty(data) | return | endif
+ let client = a:name ==# 'coc' ? '[coc.nvim]' : '['.a:name.']'
+ let data[0] = client.': '.data[0]
+ call coc#ui#echo_messages('Error', data)
+endfunction
+
+function! s:on_exit(name, code) abort
+ if get(g:, 'coc_vim_leaving', 0) | return | endif
+ let client = get(s:clients, a:name, v:null)
+ if empty(client) | return | endif
+ if client['running'] != 1 | return | endif
+ let client['running'] = 0
+ let client['chan_id'] = 0
+ let client['channel'] = v:null
+ let client['async_req_id'] = 1
+ if a:code != 0 && a:code != 143
+ echohl Error | echom 'client '.a:name. ' abnormal exit with: '.a:code | echohl None
+ endif
+endfunction
+
+function! coc#client#get_client(name) abort
+ return get(s:clients, a:name, v:null)
+endfunction
+
+function! coc#client#get_channel(client)
+ if s:is_vim
+ return a:client['channel']
+ endif
+ return a:client['chan_id']
+endfunction
+
+function! s:request(method, args) dict
+ let channel = coc#client#get_channel(self)
+ if empty(channel) | return '' | endif
+ try
+ if s:is_vim
+ let res = ch_evalexpr(channel, [a:method, a:args], {'timeout': 60 * 1000})
+ if type(res) == 1 && res ==# ''
+ throw 'request '.a:method. ' '.string(a:args).' timeout after 60s'
+ endif
+ let [l:errmsg, res] = res
+ if !empty(l:errmsg)
+ throw l:errmsg
+ else
+ return res
+ endif
+ else
+ return call('rpcrequest', [channel, a:method] + a:args)
+ endif
+ catch /.*/
+ if v:exception =~# 'E475'
+ if get(g:, 'coc_vim_leaving', 0) | return | endif
+ echohl Error | echom '['.self.name.'] server connection lost' | echohl None
+ let name = self.name
+ call s:on_exit(name, 0)
+ execute 'silent do User ConnectionLost'.toupper(name[0]).name[1:]
+ elseif v:exception =~# 'E12'
+ " neovim's bug, ignore it
+ else
+ echohl Error | echo 'Error on request ('.a:method.'): '.v:exception | echohl None
+ endif
+ endtry
+endfunction
+
+function! s:notify(method, args) dict
+ let channel = coc#client#get_channel(self)
+ if empty(channel)
+ return ''
+ endif
+ try
+ if s:is_vim
+ call ch_sendraw(channel, json_encode([0, [a:method, a:args]])."\n")
+ else
+ call call('rpcnotify', [channel, a:method] + a:args)
+ endif
+ catch /.*/
+ if v:exception =~# 'E475'
+ if get(g:, 'coc_vim_leaving', 0)
+ return
+ endif
+ echohl Error | echom '['.self.name.'] server connection lost' | echohl None
+ let name = self.name
+ call s:on_exit(name, 0)
+ execute 'silent do User ConnectionLost'.toupper(name[0]).name[1:]
+ elseif v:exception =~# 'E12'
+ " neovim's bug, ignore it
+ else
+ echohl Error | echo 'Error on notify ('.a:method.'): '.v:exception | echohl None
+ endif
+ endtry
+endfunction
+
+function! s:request_async(method, args, cb) dict
+ let channel = coc#client#get_channel(self)
+ if empty(channel) | return '' | endif
+ if type(a:cb) != 2
+ echohl Error | echom '['.self['name'].'] Callback should be function' | echohl None
+ return
+ endif
+ let id = self.async_req_id
+ let self.async_req_id = id + 1
+ let self.async_callbacks[id] = a:cb
+ call self['notify']('nvim_async_request_event', [id, a:method, a:args])
+endfunction
+
+function! s:on_async_response(id, resp, isErr) dict
+ let Callback = get(self.async_callbacks, a:id, v:null)
+ if empty(Callback)
+ " should not happen
+ echohl Error | echom 'callback not found' | echohl None
+ return
+ endif
+ call remove(self.async_callbacks, a:id)
+ if a:isErr
+ call call(Callback, [a:resp, v:null])
+ else
+ call call(Callback, [v:null, a:resp])
+ endif
+endfunction
+
+function! coc#client#is_running(name) abort
+ let client = get(s:clients, a:name, v:null)
+ if empty(client) | return 0 | endif
+ if !client['running'] | return 0 | endif
+ if s:is_vim
+ let status = job_status(ch_getjob(client['channel']))
+ return status ==# 'run'
+ else
+ let chan_id = client['chan_id']
+ let [code] = jobwait([chan_id], 10)
+ return code == -1
+ endif
+endfunction
+
+function! coc#client#stop(name) abort
+ let client = get(s:clients, a:name, v:null)
+ if empty(client) | return 1 | endif
+ let running = coc#client#is_running(a:name)
+ if !running
+ echohl WarningMsg | echom 'client '.a:name. ' not running.' | echohl None
+ return 1
+ endif
+ if s:is_vim
+ call job_stop(ch_getjob(client['channel']), 'term')
+ else
+ call jobstop(client['chan_id'])
+ endif
+ sleep 200m
+ if coc#client#is_running(a:name)
+ echohl Error | echom 'client '.a:name. ' stop failed.' | echohl None
+ return 0
+ endif
+ call s:on_exit(a:name, 0)
+ echohl MoreMsg | echom 'client '.a:name.' stopped!' | echohl None
+ return 1
+endfunction
+
+function! coc#client#request(name, method, args)
+ let client = get(s:clients, a:name, v:null)
+ if !empty(client)
+ return client['request'](a:method, a:args)
+ endif
+endfunction
+
+function! coc#client#notify(name, method, args)
+ let client = get(s:clients, a:name, v:null)
+ if !empty(client)
+ call client['notify'](a:method, a:args)
+ endif
+endfunction
+
+function! coc#client#request_async(name, method, args, cb)
+ let client = get(s:clients, a:name, v:null)
+ if !empty(client)
+ call client['request_async'](a:method, a:args, a:cb)
+ endif
+endfunction
+
+function! coc#client#on_response(name, id, resp, isErr)
+ let client = get(s:clients, a:name, v:null)
+ if !empty(client)
+ call client['on_async_response'](a:id, a:resp, a:isErr)
+ endif
+endfunction
+
+function! coc#client#restart(name) abort
+ let stopped = coc#client#stop(a:name)
+ if !stopped | return | endif
+ let client = get(s:clients, a:name, v:null)
+ if !empty(client)
+ call client['start']()
+ endif
+endfunction
+
+function! coc#client#restart_all()
+ for key in keys(s:clients)
+ call coc#client#restart(key)
+ endfor
+endfunction
+
+function! coc#client#open_log()
+ if !get(g:, 'node_client_debug', 0)
+ echohl Error | echon '[coc.nvim] use let g:node_client_debug = 1 in your vimrc to enabled debug mode.' | echohl None
+ return
+ endif
+ execute 'vs '.s:logfile
+endfunction
diff --git a/pack/acp/start/coc.nvim/autoload/coc/color.vim b/pack/acp/start/coc.nvim/autoload/coc/color.vim
new file mode 100644
index 0000000..fbe515a
--- /dev/null
+++ b/pack/acp/start/coc.nvim/autoload/coc/color.vim
@@ -0,0 +1,283 @@
+scriptencoding utf-8
+
+let s:activate = ""
+let s:quit = ""
+if has("gui_macvim") && has('gui_running')
+ let s:app = "MacVim"
+elseif $TERM_PROGRAM ==# "Apple_Terminal"
+ let s:app = "Terminal"
+elseif $TERM_PROGRAM ==# "iTerm.app"
+ let s:app = "iTerm2"
+elseif has('mac')
+ let s:app = "System Events"
+ let s:quit = "quit"
+ let s:activate = 'activate'
+endif
+
+" Returns an approximate grey index for the given grey level
+fun! s:grey_number(x)
+ if &t_Co == 88
+ if a:x < 23
+ return 0
+ elseif a:x < 69
+ return 1
+ elseif a:x < 103
+ return 2
+ elseif a:x < 127
+ return 3
+ elseif a:x < 150
+ return 4
+ elseif a:x < 173
+ return 5
+ elseif a:x < 196
+ return 6
+ elseif a:x < 219
+ return 7
+ elseif a:x < 243
+ return 8
+ else
+ return 9
+ endif
+ else
+ if a:x < 14
+ return 0
+ else
+ let l:n = (a:x - 8) / 10
+ let l:m = (a:x - 8) % 10
+ if l:m < 5
+ return l:n
+ else
+ return l:n + 1
+ endif
+ endif
+ endif
+endfun
+
+" Returns the actual grey level represented by the grey index
+fun! s:grey_level(n)
+ if &t_Co == 88
+ if a:n == 0
+ return 0
+ elseif a:n == 1
+ return 46
+ elseif a:n == 2
+ return 92
+ elseif a:n == 3
+ return 115
+ elseif a:n == 4
+ return 139
+ elseif a:n == 5
+ return 162
+ elseif a:n == 6
+ return 185
+ elseif a:n == 7
+ return 208
+ elseif a:n == 8
+ return 231
+ else
+ return 255
+ endif
+ else
+ if a:n == 0
+ return 0
+ else
+ return 8 + (a:n * 10)
+ endif
+ endif
+endfun
+
+" Returns the palette index for the given grey index
+fun! s:grey_colour(n)
+ if &t_Co == 88
+ if a:n == 0
+ return 16
+ elseif a:n == 9
+ return 79
+ else
+ return 79 + a:n
+ endif
+ else
+ if a:n == 0
+ return 16
+ elseif a:n == 25
+ return 231
+ else
+ return 231 + a:n
+ endif
+ endif
+endfun
+
+" Returns an approximate colour index for the given colour level
+fun! s:rgb_number(x)
+ if &t_Co == 88
+ if a:x < 69
+ return 0
+ elseif a:x < 172
+ return 1
+ elseif a:x < 230
+ return 2
+ else
+ return 3
+ endif
+ else
+ if a:x < 75
+ return 0
+ else
+ let l:n = (a:x - 55) / 40
+ let l:m = (a:x - 55) % 40
+ if l:m < 20
+ return l:n
+ else
+ return l:n + 1
+ endif
+ endif
+ endif
+endfun
+
+" Returns the palette index for the given R/G/B colour indices
+fun! s:rgb_colour(x, y, z)
+ if &t_Co == 88
+ return 16 + (a:x * 16) + (a:y * 4) + a:z
+ else
+ return 16 + (a:x * 36) + (a:y * 6) + a:z
+ endif
+endfun
+
+" Returns the actual colour level for the given colour index
+fun! s:rgb_level(n)
+ if &t_Co == 88
+ if a:n == 0
+ return 0
+ elseif a:n == 1
+ return 139
+ elseif a:n == 2
+ return 205
+ else
+ return 255
+ endif
+ else
+ if a:n == 0
+ return 0
+ else
+ return 55 + (a:n * 40)
+ endif
+ endif
+endfun
+
+" Returns the palette index to approximate the given R/G/B colour levels
+fun! s:colour(r, g, b)
+ " Get the closest grey
+ let l:gx = s:grey_number(a:r)
+ let l:gy = s:grey_number(a:g)
+ let l:gz = s:grey_number(a:b)
+
+ " Get the closest colour
+ let l:x = s:rgb_number(a:r)
+ let l:y = s:rgb_number(a:g)
+ let l:z = s:rgb_number(a:b)
+
+ if l:gx == l:gy && l:gy == l:gz
+ " There are two possibilities
+ let l:dgr = s:grey_level(l:gx) - a:r
+ let l:dgg = s:grey_level(l:gy) - a:g
+ let l:dgb = s:grey_level(l:gz) - a:b
+ let l:dgrey = (l:dgr * l:dgr) + (l:dgg * l:dgg) + (l:dgb * l:dgb)
+ let l:dr = s:rgb_level(l:gx) - a:r
+ let l:dg = s:rgb_level(l:gy) - a:g
+ let l:db = s:rgb_level(l:gz) - a:b
+ let l:drgb = (l:dr * l:dr) + (l:dg * l:dg) + (l:db * l:db)
+ if l:dgrey < l:drgb
+ " Use the grey
+ return s:grey_colour(l:gx)
+ else
+ " Use the colour
+ return s:rgb_colour(l:x, l:y, l:z)
+ endif
+ else
+ " Only one possibility
+ return s:rgb_colour(l:x, l:y, l:z)
+ endif
+endfun
+
+function! coc#color#rgb2term(rgb)
+ let l:r = ("0x" . strpart(a:rgb, 0, 2)) + 0
+ let l:g = ("0x" . strpart(a:rgb, 2, 2)) + 0
+ let l:b = ("0x" . strpart(a:rgb, 4, 2)) + 0
+ return s:colour(l:r, l:g, l:b)
+endfun
+
+" [r, g, b] ['255', '255', '255']
+" return ['65535', '65535', '65535'] or return v:false to cancel
+function! coc#color#pick_color(default_color)
+ if has('mac')
+ let default_color = map(a:default_color, {idx, val -> str2nr(val) * 65535 / 255 })
+ " This is the AppleScript magic:
+ let ascrpt = ['-e "tell application \"' . s:app . '\""',
+ \ '-e "' . s:activate . '"',
+ \ "-e \"set AppleScript's text item delimiters to {\\\",\\\"}\"",
+ \ '-e "set theColor to (choose color default color {' . default_color[0] . ", " . default_color[1] . ", " . default_color[2] . '}) as text"',
+ \ '-e "' . s:quit . '"',
+ \ '-e "end tell"',
+ \ '-e "return theColor"']
+ let res = trim(system("osascript " . join(ascrpt, ' ') . " 2>/dev/null"))
+ if empty(res)
+ return v:false
+ else
+ return split(trim(res), ',')
+ endif
+ endif
+
+ let hex_color = printf('#%02x%02x%02x', a:default_color[0], a:default_color[1], a:default_color[2])
+
+ if has('unix')
+ if executable('zenity')
+ let res = trim(system('zenity --title="Select a color" --color-selection --color="' . hex_color . '" 2> /dev/null'))
+ if empty(res)
+ return v:false
+ else
+ " res format is rgb(255,255,255)
+ return map(split(res[4:-2], ','), {idx, val -> string(str2nr(trim(val)) * 65535 / 255)})
+ endif
+ endif
+ endif
+
+ let rgb = v:false
+ if !has('python')
+ echohl Error | echom 'python support required, checkout :echo has(''python'')' | echohl None
+ return
+ endif
+ try
+ execute 'py import gtk'
+ catch /.*/
+ echohl Error | echom 'python gtk module not found' | echohl None
+ return
+ endtry
+python << endpython
+
+import vim
+import gtk, sys
+
+# message strings
+wnd_title_insert = "Insert a color"
+
+csd = gtk.ColorSelectionDialog(wnd_title_insert)
+cs = csd.colorsel
+
+cs.set_current_color(gtk.gdk.color_parse(vim.eval("hex_color")))
+
+cs.set_current_alpha(65535)
+cs.set_has_opacity_control(False)
+# cs.set_has_palette(int(vim.eval("s:display_palette")))
+
+if csd.run()==gtk.RESPONSE_OK:
+ c = cs.get_current_color()
+ s = [str(int(c.red)),',',str(int(c.green)),',',str(int(c.blue))]
+ thecolor = ''.join(s)
+ vim.command(":let rgb = split('%s',',')" % thecolor)
+
+csd.destroy()
+
+endpython
+ return rgb
+endfunction
+
diff --git a/pack/acp/start/coc.nvim/autoload/coc/compat.vim b/pack/acp/start/coc.nvim/autoload/coc/compat.vim
new file mode 100644
index 0000000..9353c60
--- /dev/null
+++ b/pack/acp/start/coc.nvim/autoload/coc/compat.vim
@@ -0,0 +1,244 @@
+scriptencoding utf-8
+let s:is_vim = !has('nvim')
+
+" first window id for bufnr
+" builtin bufwinid returns window of current tab only
+function! coc#compat#buf_win_id(bufnr) abort
+ let info = filter(getwininfo(), 'v:val["bufnr"] =='.a:bufnr)
+ if empty(info)
+ return -1
+ endif
+ return info[0]['winid']
+endfunction
+
+function! coc#compat#buf_set_lines(bufnr, start, end, replacement) abort
+ if s:is_vim
+ call coc#api#exec('buf_set_lines', [a:bufnr, a:start, a:end, 0, a:replacement])
+ else
+ call nvim_buf_set_lines(a:bufnr, a:start, a:end, 0, a:replacement)
+ endif
+endfunction
+
+function! coc#compat#buf_line_count(bufnr) abort
+ if exists('*nvim_buf_line_count')
+ return nvim_buf_line_count(a:bufnr)
+ endif
+ if bufnr('%') == a:bufnr
+ return line('$')
+ endif
+ if exists('*getbufinfo')
+ let info = getbufinfo(a:bufnr)
+ if empty(info)
+ return 0
+ endif
+ " vim 8.1 has getbufinfo but no linecount
+ if has_key(info[0], 'linecount')
+ return info[0]['linecount']
+ endif
+ endif
+ if exists('*getbufline')
+ let lines = getbufline(a:bufnr, 1, '$')
+ return len(lines)
+ endif
+ let curr = bufnr('%')
+ execute 'noa buffer '.a:bufnr
+ let n = line('$')
+ execute 'noa buffer '.curr
+ return n
+endfunction
+
+function! coc#compat#prepend_lines(bufnr, replacement) abort
+ if exists('*appendbufline')
+ call appendbufline(a:bufnr, 0, a:replacement)
+ elseif !s:is_vim
+ call nvim_buf_set_lines(a:bufnr, 0, 0, 0, a:replacement)
+ else
+ throw 'appendbufline() required for prepend lines.'
+ endif
+endfunction
+
+function! coc#compat#win_is_valid(winid) abort
+ if exists('*nvim_win_is_valid')
+ return nvim_win_is_valid(a:winid)
+ endif
+ return !empty(getwininfo(a:winid))
+endfunction
+
+" clear matches by window id, not throw on none exists window.
+" may not work on vim < 8.1.1084 & neovim < 0.4.0
+function! coc#compat#clear_matches(winid) abort
+ if !coc#compat#win_is_valid(a:winid)
+ return
+ endif
+ let curr = win_getid()
+ if curr == a:winid
+ call clearmatches()
+ return
+ endif
+ if s:is_vim
+ if has('patch-8.1.1084')
+ call clearmatches(a:winid)
+ endif
+ else
+ if exists('*nvim_set_current_win')
+ noa call nvim_set_current_win(a:winid)
+ call clearmatches()
+ noa call nvim_set_current_win(curr)
+ endif
+ endif
+endfunction
+
+function! coc#compat#matchaddpos(group, pos, priority, winid) abort
+ let curr = win_getid()
+ if curr == a:winid
+ call matchaddpos(a:group, a:pos, a:priority, -1)
+ else
+ if s:is_vim
+ if has('patch-8.1.0218')
+ call matchaddpos(a:group, a:pos, a:priority, -1, {'window': a:winid})
+ endif
+ else
+ if has('nvim-0.4.0')
+ call matchaddpos(a:group, a:pos, a:priority, -1, {'window': a:winid})
+ elseif exists('*nvim_set_current_win')
+ noa call nvim_set_current_win(a:winid)
+ call matchaddpos(a:group, a:pos, a:priority, -1)
+ noa call nvim_set_current_win(curr)
+ endif
+ endif
+ endif
+endfunction
+
+function! coc#compat#buf_del_var(bufnr, name) abort
+ if !bufloaded(a:bufnr)
+ return
+ endif
+ if exists('*nvim_buf_del_var')
+ silent! call nvim_buf_del_var(a:bufnr, a:name)
+ else
+ if a:bufnr == bufnr('%')
+ execute 'unlet! b:'.a:name
+ elseif exists('*win_execute')
+ let winid = coc#compat#buf_win_id(a:bufnr)
+ if winid != -1
+ call win_execute(winid, 'unlet! b:'.a:name)
+ endif
+ endif
+ endif
+endfunction
+
+" hlGroup, pos, priority
+function! coc#compat#matchaddgroups(winid, groups) abort
+ " add by winid
+ if has('patch-8.1.0218') || has('nvim-0.4.0')
+ for group in a:groups
+ call matchaddpos(group['hlGroup'], [group['pos']], group['priority'], -1, {'window': a:winid})
+ endfor
+ return
+ endif
+ let curr = win_getid()
+ if curr == a:winid
+ for group in a:groups
+ call matchaddpos(group['hlGroup'], [group['pos']], group['priority'], -1)
+ endfor
+ elseif exists('*nvim_set_current_win')
+ noa call nvim_set_current_win(a:winid)
+ for group in a:groups
+ call matchaddpos(group['hlGroup'], [group['pos']], group['priority'], -1)
+ endfor
+ noa call nvim_set_current_win(curr)
+ endif
+endfunction
+
+function! coc#compat#del_var(name) abort
+ if exists('*nvim_del_var')
+ silent! call nvim_del_var(a:name)
+ else
+ execute 'unlet! '.a:name
+ endif
+endfunction
+
+" remove keymap for specific buffer
+function! coc#compat#buf_del_keymap(bufnr, mode, lhs) abort
+ if !bufloaded(a:bufnr)
+ return
+ endif
+ if exists('*nvim_buf_del_keymap')
+ try
+ call nvim_buf_del_keymap(a:bufnr, a:mode, a:lhs)
+ catch /^Vim\%((\a\+)\)\=:E5555/
+ " ignore keymap doesn't exist
+ endtry
+ return
+ endif
+ if bufnr == a:bufnr
+ execute 'silent! '.a:mode.'unmap '.a:lhs
+ return
+ endif
+ if exists('*win_execute')
+ let winid = coc#compat#buf_win_id(a:bufnr)
+ if winid != -1
+ call win_execute(winid, a:mode.'unmap '.a:lhs, 'silent!')
+ endif
+ endif
+endfunction
+
+function! coc#compat#buf_add_keymap(bufnr, mode, lhs, rhs, opts) abort
+ if !bufloaded(a:bufnr)
+ return
+ endif
+ if exists('*nvim_buf_set_keymap')
+ call nvim_buf_set_keymap(a:bufnr, a:mode, a:lhs, a:rhs, a:opts)
+ else
+ let cmd = a:mode . 'noremap '
+ for key in keys(a:opts)
+ if get(a:opts, key, 0)
+ let cmd .= '<'.key.'>'
+ endif
+ endfor
+ let cmd .= ' '.a:lhs.' '.a:rhs
+ if bufnr('%') == a:bufnr
+ execute cmd
+ elseif exists('*win_execute')
+ let winid = coc#compat#buf_win_id(a:bufnr)
+ if winid != -1
+ call win_execute(winid, cmd)
+ endif
+ endif
+ endif
+endfunction
+
+" execute command or list of commands in window
+function! coc#compat#execute(winid, command, ...) abort
+ if exists('*win_execute')
+ if type(a:command) == v:t_string
+ keepalt call win_execute(a:winid, a:command, get(a:, 1, ''))
+ elseif type(a:command) == v:t_list
+ keepalt call win_execute(a:winid, join(a:command, "\n"), get(a:, 1, ''))
+ endif
+ elseif has('nvim')
+ if !nvim_win_is_valid(a:winid)
+ return
+ endif
+ let curr = nvim_get_current_win()
+ noa keepalt call nvim_set_current_win(a:winid)
+ if type(a:command) == v:t_string
+ exe get(a:, 1, '').' '.a:command
+ elseif type(a:command) == v:t_list
+ for cmd in a:command
+ exe get(a:, 1, '').' '.cmd
+ endfor
+ endif
+ noa keepalt call nvim_set_current_win(curr)
+ else
+ throw 'win_execute does not exist, please upgrade vim.'
+ endif
+endfunc
+
+function! coc#compat#trim(str)
+ if exists('*trim')
+ return trim(a:str)
+ endif
+ " TODO trim from beginning
+ return substitute(a:str, '\s\+$', '', '')
+endfunction
diff --git a/pack/acp/start/coc.nvim/autoload/coc/cursor.vim b/pack/acp/start/coc.nvim/autoload/coc/cursor.vim
new file mode 100644
index 0000000..d9cfa2c
--- /dev/null
+++ b/pack/acp/start/coc.nvim/autoload/coc/cursor.vim
@@ -0,0 +1,60 @@
+scriptencoding utf-8
+
+" Position of cursor relative to screen cell
+function! coc#cursor#screen_pos() abort
+ let nr = winnr()
+ let [row, col] = win_screenpos(nr)
+ return [row + winline() - 2, col + wincol() - 2]
+endfunction
+
+function! coc#cursor#move_by_col(delta)
+ let pos = getcurpos()
+ call cursor(pos[1], pos[2] + a:delta)
+endfunction
+
+" Get cursor position.
+function! coc#cursor#position()
+ return [line('.') - 1, strchars(strpart(getline('.'), 0, col('.') - 1))]
+endfunction
+
+" Move cursor to position.
+function! coc#cursor#move_to(line, character) abort
+ let content = getline(a:line + 1)
+ let pre = strcharpart(content, 0, a:character)
+ let col = strlen(pre) + 1
+ call cursor(a:line + 1, col)
+endfunction
+
+" Character offset of current cursor, vim provide bytes offset only.
+function! coc#cursor#char_offset() abort
+ let offset = 0
+ let lnum = line('.')
+ for i in range(1, lnum)
+ if i == lnum
+ let offset += strchars(strpart(getline('.'), 0, col('.')-1))
+ else
+ let offset += strchars(getline(i)) + 1
+ endif
+ endfor
+ return offset
+endfunction
+
+" Returns latest selection range
+function! coc#cursor#get_selection(char) abort
+ let m = a:char ? 'char' : visualmode()
+ if empty(m)
+ return v:null
+ endif
+ let [_, sl, sc, soff] = getpos(m ==# 'char' ? "'[" : "'<")
+ let [_, el, ec, eoff] = getpos(m ==# 'char' ? "']" : "'>")
+ let start_idx = coc#string#get_character(getline(sl), sc)
+ if m ==# 'V'
+ return [sl - 1, start_idx, el, 0]
+ endif
+ let line = getline(el)
+ let end_idx = coc#string#get_character(line, ec)
+ if m !=# 'char'
+ let end_idx = end_idx == strchars(line) ? end_idx : end_idx + 1
+ endif
+ return [sl - 1, start_idx, el - 1, end_idx]
+endfunction
diff --git a/pack/acp/start/coc.nvim/autoload/coc/dialog.vim b/pack/acp/start/coc.nvim/autoload/coc/dialog.vim
new file mode 100644
index 0000000..036c1d7
--- /dev/null
+++ b/pack/acp/start/coc.nvim/autoload/coc/dialog.vim
@@ -0,0 +1,684 @@
+scriptencoding utf-8
+let s:is_vim = !has('nvim')
+let s:root = expand(':h:h:h')
+let s:prompt_win_bufnr = 0
+let s:list_win_bufnr = 0
+let s:prompt_win_width = get(g:, 'coc_prompt_win_width', 32)
+let s:frames = ['ยท ', 'ยทยท ', 'ยทยทยท', ' ยทยท', ' ยท', ' ']
+let s:sign_group = 'PopUpCocDialog'
+let s:detail_bufnr = 0
+
+" Float window aside pum
+function! coc#dialog#create_pum_float(lines, config) abort
+ let winid = coc#float#get_float_by_kind('pumdetail')
+ if empty(a:lines) || !coc#pum#visible()
+ if winid
+ call coc#float#close(winid)
+ endif
+ return
+ endif
+ let pumbounding = coc#pum#info()
+ let border = get(a:config, 'border', [])
+ let pw = pumbounding['width'] + (empty(border) ? get(pumbounding, 'scrollbar', 0) : 0)
+ let rp = &columns - pumbounding['col'] - pw
+ let showRight = pumbounding['col'] > rp ? 0 : 1
+ let maxWidth = showRight ? coc#math#min(rp - 1, a:config['maxWidth']) : coc#math#min(pumbounding['col'] - 1, a:config['maxWidth'])
+ let bh = get(border, 0 ,0) + get(border, 2, 0)
+ let maxHeight = &lines - pumbounding['row'] - &cmdheight - 1 - bh
+ if maxWidth <= 2 || maxHeight < 1
+ return v:null
+ endif
+ let width = 0
+ for line in a:lines
+ let dw = max([1, strdisplaywidth(line)])
+ let width = max([width, dw + 2])
+ endfor
+ let width = float2nr(coc#math#min(maxWidth, width))
+ let ch = coc#string#content_height(a:lines, width - 2)
+ let height = float2nr(coc#math#min(maxHeight, ch))
+ let lines = map(a:lines, {_, s -> s =~# '^โ' ? repeat('โ', width - 2 + (s:is_vim && ch > height ? -1 : 0)) : s})
+ let opts = {
+ \ 'lines': lines,
+ \ 'highlights': get(a:config, 'highlights', []),
+ \ 'relative': 'editor',
+ \ 'col': showRight ? pumbounding['col'] + pw : pumbounding['col'] - width,
+ \ 'row': pumbounding['row'],
+ \ 'height': height,
+ \ 'width': width - 2 + (s:is_vim && ch > height ? -1 : 0),
+ \ 'scrollinside': showRight ? 0 : 1,
+ \ 'codes': get(a:config, 'codes', []),
+ \ }
+ for key in ['border', 'highlight', 'borderhighlight', 'winblend', 'focusable', 'shadow', 'rounded']
+ if has_key(a:config, key)
+ let opts[key] = a:config[key]
+ endif
+ endfor
+ call s:close_auto_hide_wins(winid)
+ let result = coc#float#create_float_win(winid, s:detail_bufnr, opts)
+ if empty(result)
+ return
+ endif
+ let s:detail_bufnr = result[1]
+ call setwinvar(result[0], 'kind', 'pumdetail')
+ if !s:is_vim
+ call coc#float#nvim_scrollbar(result[0])
+ endif
+endfunction
+
+" Float window below/above cursor
+function! coc#dialog#create_cursor_float(winid, bufnr, lines, config) abort
+ if coc#prompt#activated()
+ return v:null
+ endif
+ let pumAlignTop = get(a:config, 'pumAlignTop', 0)
+ let modes = get(a:config, 'modes', ['n', 'i', 'ic', 's'])
+ let mode = mode()
+ let currbuf = bufnr('%')
+ let pos = [line('.'), col('.')]
+ if index(modes, mode) == -1
+ return v:null
+ endif
+ if !s:is_vim && !has('nvim-0.5.0') && mode ==# 'i'
+ " helps to fix undo issue, don't know why.
+ call feedkeys("\u", 'n')
+ endif
+ if mode ==# 's' && has('patch-8.2.4969') && !has('patch-8.2.4996')
+ echohl WarningMsg | echon 'Popup not created to avoid issue #10466 on vim >= 8.2.4969' | echohl None
+ return v:null
+ endif
+ let dimension = coc#dialog#get_config_cursor(a:lines, a:config)
+ if empty(dimension)
+ return v:null
+ endif
+ if coc#pum#visible() && ((pumAlignTop && dimension['row'] <0)|| (!pumAlignTop && dimension['row'] > 0))
+ return v:null
+ endif
+ let width = dimension['width']
+ let lines = map(a:lines, {_, s -> s =~# '^โ' ? repeat('โ', width) : s})
+ let config = extend(extend({'lines': lines, 'relative': 'cursor'}, a:config), dimension)
+ call s:close_auto_hide_wins(a:winid)
+ let res = coc#float#create_float_win(a:winid, a:bufnr, config)
+ if empty(res)
+ return v:null
+ endif
+ let alignTop = dimension['row'] < 0
+ let winid = res[0]
+ let bufnr = res[1]
+ redraw
+ if has('nvim')
+ call coc#float#nvim_scrollbar(winid)
+ endif
+ return [currbuf, pos, winid, bufnr, alignTop]
+endfunction
+
+" Create float window for input
+function! coc#dialog#create_prompt_win(title, default, opts) abort
+ call s:close_auto_hide_wins()
+ let bufnr = has('nvim') ? s:prompt_win_bufnr : 0
+ if s:is_vim
+ execute 'hi link CocPopupTerminal '.get(a:opts, 'highlight', 'CocFloating')
+ let node = expand(get(g:, 'coc_node_path', 'node'))
+ let bufnr = term_start([node, s:root . '/bin/prompt.js', a:default], {
+ \ 'term_rows': 1,
+ \ 'term_highlight': 'CocPopupTerminal',
+ \ 'hidden': 1,
+ \ 'term_finish': 'close'
+ \ })
+ call term_setapi(bufnr, 'Coc')
+ call setbufvar(bufnr, 'current', type(a:default) == v:t_string ? a:default : '')
+ endif
+ let config = s:get_prompt_dimension(a:title, a:default, a:opts)
+ let res = coc#float#create_float_win(0, bufnr, extend(config, {
+ \ 'style': 'minimal',
+ \ 'border': get(a:opts, 'border', [1,1,1,1]),
+ \ 'rounded': get(a:opts, 'rounded', 1),
+ \ 'prompt': 1,
+ \ 'title': a:title,
+ \ 'lines': s:is_vim ? v:null : [a:default],
+ \ 'highlight': get(a:opts, 'highlight', 'CocFloating'),
+ \ 'borderhighlight': [get(a:opts, 'borderhighlight', 'CocFloating')],
+ \ }))
+ if empty(res)
+ return
+ endif
+ let winid = res[0]
+ let bufnr = res[1]
+ if has('nvim')
+ let s:prompt_win_bufnr = res[1]
+ execute 'sign unplace 6 buffer='.s:prompt_win_bufnr
+ call nvim_set_current_win(winid)
+ inoremap
+ inoremap pumvisible() ? "\" : "\"
+ exe 'imap '
+ exe 'nnoremap :call coc#float#close('.winid.')'
+ exe 'inoremap "\=coc#dialog#prompt_insert(getline(''.''))\\"'
+ if get(a:opts, 'list', 0)
+ for key in ['', '', '', '', '', '', '', '', '']
+ " Can't use < in remap
+ let escaped = key ==# '' ? "C-@" : strcharpart(key, 1, strchars(key) - 2)
+ exe 'inoremap '.key.' call coc#rpc#notify("PromptKeyPress", ['.bufnr.', "'.escaped.'"])'
+ endfor
+ endif
+ call feedkeys('A', 'in')
+ endif
+ call coc#util#do_autocmd('CocOpenFloatPrompt')
+ if s:is_vim
+ let pos = popup_getpos(winid)
+ " width height row col
+ let dimension = [pos['width'], pos['height'], pos['line'] - 1, pos['col'] - 1]
+ else
+ let id = coc#float#get_related(winid, 'border')
+ if !has('nvim-0.6.0')
+ redraw
+ endif
+ let pos = nvim_win_get_position(id)
+ let dimension = [nvim_win_get_width(id), nvim_win_get_height(id), pos[0], pos[1]]
+ endif
+ return [bufnr, winid, dimension]
+endfunction
+
+" Create list window under target window
+function! coc#dialog#create_list(target, dimension, opts) abort
+ let maxHeight = get(a:opts, 'maxHeight', 10)
+ let height = max([1, len(get(a:opts, 'lines', []))])
+ let height = min([maxHeight, height, &lines - &cmdheight - 1 - a:dimension['row'] + a:dimension['height']])
+ let chars = get(a:opts, 'rounded', 1) ? ['โฏ', 'โฐ'] : ['โ', 'โ']
+ let config = extend(copy(a:opts), {
+ \ 'relative': 'editor',
+ \ 'row': a:dimension['row'] + a:dimension['height'],
+ \ 'col': a:dimension['col'],
+ \ 'width': a:dimension['width'] - 2,
+ \ 'height': height,
+ \ 'border': [1, 1, 1, 1],
+ \ 'scrollinside': 1,
+ \ 'borderchars': extend(['โ', 'โ', 'โ', 'โ', 'โ', 'โค'], chars)
+ \ })
+ let bufnr = 0
+ let result = coc#float#create_float_win(0, s:list_win_bufnr, config)
+ if empty(result)
+ return
+ endif
+ let winid = result[0]
+ call coc#float#add_related(winid, a:target)
+ call setwinvar(winid, 'auto_height', get(a:opts, 'autoHeight', 1))
+ call setwinvar(winid, 'max_height', maxHeight)
+ call setwinvar(winid, 'target_winid', a:target)
+ call setwinvar(winid, 'kind', 'list')
+ call coc#dialog#check_scroll_vim(a:target)
+ return result
+endfunction
+
+" Create menu picker for pick single item
+function! coc#dialog#create_menu(lines, config) abort
+ call s:close_auto_hide_wins()
+ let highlight = get(a:config, 'highlight', 'CocFloating')
+ let borderhighlight = get(a:config, 'borderhighlight', [highlight])
+ let relative = get(a:config, 'relative', 'cursor')
+ let lines = copy(a:lines)
+ let content = get(a:config, 'content', '')
+ let maxWidth = get(a:config, 'maxWidth', 80)
+ let highlights = get(a:config, 'highlights', [])
+ let contentCount = 0
+ if !empty(content)
+ let contentLines = coc#string#reflow(split(content, '\r\?\n'), maxWidth)
+ let contentCount = len(contentLines)
+ let lines = extend(contentLines, lines)
+ if !empty(highlights)
+ for item in highlights
+ let item['lnum'] = item['lnum'] + contentCount
+ endfor
+ endif
+ endif
+ let opts = {
+ \ 'lines': lines,
+ \ 'highlight': highlight,
+ \ 'title': get(a:config, 'title', ''),
+ \ 'borderhighlight': borderhighlight,
+ \ 'maxWidth': maxWidth,
+ \ 'maxHeight': get(a:config, 'maxHeight', 80),
+ \ 'rounded': get(a:config, 'rounded', 0),
+ \ 'border': [1, 1, 1, 1],
+ \ 'highlights': highlights,
+ \ 'relative': relative,
+ \ }
+ if relative ==# 'editor'
+ let dimension = coc#dialog#get_config_editor(lines, opts)
+ else
+ let dimension = coc#dialog#get_config_cursor(lines, opts)
+ endif
+ call extend(opts, dimension)
+ let ids = coc#float#create_float_win(0, s:prompt_win_bufnr, opts)
+ if empty(ids)
+ return
+ endif
+ let s:prompt_win_bufnr = ids[1]
+ call coc#dialog#set_cursor(ids[0], ids[1], contentCount + 1)
+ redraw
+ if has('nvim')
+ call coc#float#nvim_scrollbar(ids[0])
+ endif
+ return [ids[0], ids[1], contentCount]
+endfunction
+
+" Create dialog at center of screen
+function! coc#dialog#create_dialog(lines, config) abort
+ call s:close_auto_hide_wins()
+ " dialog always have borders
+ let title = get(a:config, 'title', '')
+ let buttons = get(a:config, 'buttons', [])
+ let highlight = get(a:config, 'highlight', 'CocFloating')
+ let borderhighlight = get(a:config, 'borderhighlight', [highlight])
+ let opts = {
+ \ 'title': title,
+ \ 'rounded': get(a:config, 'rounded', 0),
+ \ 'relative': 'editor',
+ \ 'border': [1,1,1,1],
+ \ 'close': get(a:config, 'close', 1),
+ \ 'highlight': highlight,
+ \ 'highlights': get(a:config, 'highlights', []),
+ \ 'buttons': buttons,
+ \ 'borderhighlight': borderhighlight,
+ \ 'getchar': get(a:config, 'getchar', 0)
+ \ }
+ call extend(opts, coc#dialog#get_config_editor(a:lines, a:config))
+ let bufnr = coc#float#create_buf(0, a:lines)
+ let res = coc#float#create_float_win(0, bufnr, opts)
+ if empty(res)
+ return
+ endif
+ if get(a:config, 'cursorline', 0)
+ call coc#dialog#place_sign(bufnr, 1)
+ endif
+ if has('nvim')
+ redraw
+ call coc#float#nvim_scrollbar(res[0])
+ endif
+ return res
+endfunction
+
+function! coc#dialog#prompt_confirm(title, cb) abort
+ call s:close_auto_hide_wins()
+ if s:is_vim && exists('*popup_dialog')
+ try
+ call popup_dialog(a:title. ' (y/n)?', {
+ \ 'highlight': 'Normal',
+ \ 'filter': 'popup_filter_yesno',
+ \ 'callback': {id, res -> a:cb(v:null, res)},
+ \ 'borderchars': get(g:, 'coc_borderchars', ['โ', 'โ', 'โ', 'โ', 'โญ', 'โฎ', 'โฏ', 'โฐ']),
+ \ 'borderhighlight': ['MoreMsg']
+ \ })
+ catch /.*/
+ call a:cb(v:exception)
+ endtry
+ return
+ endif
+ if has('nvim-0.4.0')
+ let text = ' '. a:title . ' (y/n)? '
+ let maxWidth = coc#math#min(78, &columns - 2)
+ let width = coc#math#min(maxWidth, strdisplaywidth(text))
+ let maxHeight = &lines - &cmdheight - 1
+ let height = coc#math#min(maxHeight, float2nr(ceil(str2float(string(strdisplaywidth(text)))/width)))
+ let arr = coc#float#create_float_win(0, s:prompt_win_bufnr, {
+ \ 'col': &columns/2 - width/2 - 1,
+ \ 'row': maxHeight/2 - height/2 - 1,
+ \ 'width': width,
+ \ 'height': height,
+ \ 'border': [1,1,1,1],
+ \ 'focusable': v:false,
+ \ 'relative': 'editor',
+ \ 'highlight': 'Normal',
+ \ 'borderhighlight': 'MoreMsg',
+ \ 'style': 'minimal',
+ \ 'lines': [text],
+ \ })
+ if empty(arr)
+ call a:cb('Window create failed!')
+ return
+ endif
+ let winid = arr[0]
+ let s:prompt_win_bufnr = arr[1]
+ let res = 0
+ redraw
+ " same result as vim
+ while 1
+ let key = nr2char(getchar())
+ if key == "\"
+ let res = -1
+ break
+ elseif key == "\" || key == 'n' || key == 'N'
+ let res = 0
+ break
+ elseif key == 'y' || key == 'Y'
+ let res = 1
+ break
+ endif
+ endw
+ call coc#float#close(winid)
+ call a:cb(v:null, res)
+ " use relative editor since neovim doesn't support center position
+ elseif exists('*confirm')
+ let choice = confirm(a:title, "&Yes\n&No")
+ call a:cb(v:null, choice == 1)
+ else
+ echohl MoreMsg
+ echom a:title.' (y/n)'
+ echohl None
+ let confirm = nr2char(getchar())
+ redraw!
+ if !(confirm ==? "y" || confirm ==? "\r")
+ echohl Moremsg | echo 'Cancelled.' | echohl None
+ return 0
+ call a:cb(v:null, 0)
+ end
+ call a:cb(v:null, 1)
+ endif
+endfunction
+
+function! coc#dialog#get_config_editor(lines, config) abort
+ let title = get(a:config, 'title', '')
+ let maxheight = min([get(a:config, 'maxHeight', 78), &lines - &cmdheight - 6])
+ let maxwidth = min([get(a:config, 'maxWidth', 78), &columns - 2])
+ let buttons = get(a:config, 'buttons', [])
+ let minwidth = s:min_btns_width(buttons)
+ if maxheight <= 0 || maxwidth <= 0 || minwidth > maxwidth
+ throw 'Not enough spaces for float window'
+ endif
+ let ch = 0
+ let width = min([strdisplaywidth(title) + 1, maxwidth])
+ for line in a:lines
+ let dw = max([1, strdisplaywidth(line)])
+ if dw < maxwidth && dw > width
+ let width = dw
+ elseif dw >= maxwidth
+ let width = maxwidth
+ endif
+ let ch += float2nr(ceil(str2float(string(dw))/maxwidth))
+ endfor
+ let width = max([minwidth, width])
+ let height = coc#math#min(ch ,maxheight)
+ return {
+ \ 'row': &lines/2 - (height + 4)/2,
+ \ 'col': &columns/2 - (width + 2)/2,
+ \ 'width': width,
+ \ 'height': height,
+ \ }
+endfunction
+
+function! coc#dialog#prompt_insert(text) abort
+ call coc#rpc#notify('PromptInsert', [a:text, bufnr('%')])
+ return ''
+endfunction
+
+" Dimension of window with lines relative to cursor
+" Width & height excludes border & padding
+function! coc#dialog#get_config_cursor(lines, config) abort
+ let preferTop = get(a:config, 'preferTop', 0)
+ let title = get(a:config, 'title', '')
+ let border = get(a:config, 'border', [])
+ if empty(border) && len(title)
+ let border = [1, 1, 1, 1]
+ endif
+ let bh = get(border, 0, 0) + get(border, 2, 0)
+ let vh = &lines - &cmdheight - 1
+ if vh <= 0
+ return v:null
+ endif
+ let maxWidth = coc#math#min(get(a:config, 'maxWidth', &columns - 1), &columns - 1)
+ if maxWidth < 3
+ return v:null
+ endif
+ let maxHeight = coc#math#min(get(a:config, 'maxHeight', vh), vh)
+ let width = coc#math#min(40, strdisplaywidth(title)) + 3
+ for line in a:lines
+ let dw = max([1, strdisplaywidth(line)])
+ let width = max([width, dw + 2])
+ endfor
+ let width = coc#math#min(maxWidth, width)
+ let ch = coc#string#content_height(a:lines, width - 2)
+ let [lineIdx, colIdx] = coc#cursor#screen_pos()
+ " How much we should move left
+ let offsetX = coc#math#min(get(a:config, 'offsetX', 0), colIdx)
+ let showTop = 0
+ let hb = vh - lineIdx -1
+ if lineIdx > bh + 2 && (preferTop || (lineIdx > hb && hb < ch + bh))
+ let showTop = 1
+ endif
+ let height = coc#math#min(maxHeight, ch + bh, showTop ? lineIdx - 1 : hb)
+ if height <= bh
+ return v:null
+ endif
+ let col = - max([offsetX, colIdx - (&columns - 1 - width)])
+ let row = showTop ? - height + bh : 1
+ return {
+ \ 'row': row,
+ \ 'col': col,
+ \ 'width': width - 2,
+ \ 'height': height - bh
+ \ }
+endfunction
+
+function! coc#dialog#change_border_hl(winid, hlgroup) abort
+ if !hlexists(a:hlgroup)
+ return
+ endif
+ if s:is_vim
+ if coc#float#valid(a:winid)
+ call popup_setoptions(a:winid, {'borderhighlight': repeat([a:hlgroup], 4)})
+ redraw
+ endif
+ else
+ let winid = coc#float#get_related(a:winid, 'border')
+ if winid > 0
+ call setwinvar(winid, '&winhl', 'Normal:'.a:hlgroup.',NormalNC:'.a:hlgroup)
+ endif
+ endif
+endfunction
+
+function! coc#dialog#change_title(winid, title) abort
+ if s:is_vim
+ if coc#float#valid(a:winid)
+ call popup_setoptions(a:winid, {'title': a:title})
+ redraw
+ endif
+ else
+ let winid = coc#float#get_related(a:winid, 'border')
+ if winid > 0
+ let bufnr = winbufnr(winid)
+ let line = getbufline(bufnr, 1)[0]
+ let top = strcharpart(line, 0, 1)
+ \.repeat('โ', strchars(line) - 2)
+ \.strcharpart(line, strchars(line) - 1, 1)
+ if !empty(a:title)
+ let top = coc#string#compose(top, 1, a:title.' ')
+ endif
+ call nvim_buf_set_lines(bufnr, 0, 1, v:false, [top])
+ endif
+ endif
+endfunction
+
+function! coc#dialog#change_loading(winid, loading) abort
+ if coc#float#valid(a:winid)
+ let winid = coc#float#get_related(a:winid, 'loading')
+ if !a:loading && winid > 0
+ call coc#float#close(winid)
+ endif
+ if a:loading && winid == 0
+ let bufnr = s:create_loading_buf()
+ if s:is_vim
+ let pos = popup_getpos(a:winid)
+ let winid = popup_create(bufnr, {
+ \ 'line': pos['line'] + 1,
+ \ 'col': pos['col'] + pos['width'] - 4,
+ \ 'maxheight': 1,
+ \ 'maxwidth': 3,
+ \ 'zindex': 999,
+ \ 'highlight': get(popup_getoptions(a:winid), 'highlight', 'CocFloating')
+ \ })
+ else
+ let pos = nvim_win_get_position(a:winid)
+ let width = nvim_win_get_width(a:winid)
+ let opts = {
+ \ 'relative': 'editor',
+ \ 'row': pos[0],
+ \ 'col': pos[1] + width - 3,
+ \ 'focusable': v:false,
+ \ 'width': 3,
+ \ 'height': 1,
+ \ 'style': 'minimal',
+ \ }
+ if has('nvim-0.5.1')
+ let opts['zindex'] = 900
+ endif
+ let winid = nvim_open_win(bufnr, v:false, opts)
+ call setwinvar(winid, '&winhl', getwinvar(a:winid, '&winhl'))
+ endif
+ call setwinvar(winid, 'kind', 'loading')
+ call setbufvar(bufnr, 'target_winid', a:winid)
+ call setbufvar(bufnr, 'popup', winid)
+ call coc#float#add_related(winid, a:winid)
+ endif
+ endif
+endfunction
+
+" Update list with new lines and highlights
+function! coc#dialog#update_list(winid, bufnr, lines, highlights) abort
+ if coc#window#tabnr(a:winid) == tabpagenr()
+ if getwinvar(a:winid, 'auto_height', 0)
+ let row = coc#float#get_row(a:winid)
+ " core height
+ let height = max([1, len(copy(a:lines))])
+ let height = min([getwinvar(a:winid, 'max_height', 10), height, &lines - &cmdheight - 1 - row])
+ let curr = s:is_vim ? popup_getpos(a:winid)['core_height'] : nvim_win_get_height(a:winid)
+ let delta = height - curr
+ if delta != 0
+ call coc#float#change_height(a:winid, delta)
+ endif
+ endif
+ call coc#compat#buf_set_lines(a:bufnr, 0, -1, a:lines)
+ call coc#highlight#add_highlights(a:winid, [], a:highlights)
+ if s:is_vim
+ let target = getwinvar(a:winid, 'target_winid', -1)
+ if target != -1
+ call coc#dialog#check_scroll_vim(target)
+ endif
+ call win_execute(a:winid, 'exe 1')
+ endif
+ endif
+endfunction
+
+" Fix width of prompt window same as list window on scrollbar change
+function! coc#dialog#check_scroll_vim(winid) abort
+ if s:is_vim && coc#float#valid(a:winid)
+ let winid = coc#float#get_related(a:winid, 'list')
+ if winid
+ redraw
+ let pos = popup_getpos(winid)
+ let width = pos['width'] + (pos['scrollbar'] ? 1 : 0)
+ if width != popup_getpos(a:winid)['width']
+ call popup_move(a:winid, {
+ \ 'minwidth': width - 2,
+ \ 'maxwidth': width - 2,
+ \ })
+ endif
+ endif
+ endif
+endfunction
+
+function! coc#dialog#set_cursor(winid, bufnr, line) abort
+ if s:is_vim
+ call coc#compat#execute(a:winid, 'exe '.a:line, 'silent!')
+ call popup_setoptions(a:winid, {'cursorline' : 1})
+ call popup_setoptions(a:winid, {'cursorline' : 0})
+ else
+ call nvim_win_set_cursor(a:winid, [a:line, 0])
+ endif
+ call coc#dialog#place_sign(a:bufnr, a:line)
+endfunction
+
+function! coc#dialog#place_sign(bufnr, line) abort
+ call sign_unplace(s:sign_group, { 'buffer': a:bufnr })
+ if a:line > 0
+ call sign_place(6, s:sign_group, 'CocCurrentLine', a:bufnr, {'lnum': a:line})
+ endif
+endfunction
+
+" Could be center(with optional marginTop) or cursor
+function! s:get_prompt_dimension(title, default, opts) abort
+ let relative = get(a:opts, 'position', 'cursor') ==# 'cursor' ? 'cursor' : 'editor'
+ let curr = win_screenpos(winnr())[1] + wincol() - 2
+ let minWidth = get(a:opts, 'minWidth', s:prompt_win_width)
+ let width = min([max([strwidth(a:default) + 2, strwidth(a:title) + 2, minWidth]), &columns - 2])
+ if get(a:opts, 'maxWidth', 0)
+ let width = min([width, a:opts['maxWidth']])
+ endif
+ if relative ==# 'cursor'
+ let [lineIdx, colIdx] = coc#cursor#screen_pos()
+ if width == &columns - 2
+ let col = 0 - curr
+ else
+ let col = curr + width <= &columns - 2 ? 0 : curr + width - &columns + 2
+ endif
+ let config = {
+ \ 'row': lineIdx == 0 ? 1 : 0,
+ \ 'col': colIdx == 0 ? 0 : col - 1,
+ \ }
+ else
+ let marginTop = get(a:opts, 'marginTop', v:null)
+ if marginTop is v:null
+ let row = (&lines - &cmdheight - 2) / 2
+ else
+ let row = marginTop < 2 ? 1 : min([marginTop, &columns - &cmdheight])
+ endif
+ let config = {
+ \ 'col': float2nr((&columns - width) / 2),
+ \ 'row': row - s:is_vim,
+ \ }
+ endif
+ return extend(config, {'relative': relative, 'width': width, 'height': 1})
+endfunction
+
+function! s:min_btns_width(buttons) abort
+ if empty(a:buttons)
+ return 0
+ endif
+ let minwidth = len(a:buttons)*3 - 1
+ for txt in a:buttons
+ let minwidth = minwidth + strdisplaywidth(txt)
+ endfor
+ return minwidth
+endfunction
+
+" Close windows that should auto hide
+function! s:close_auto_hide_wins(...) abort
+ let winids = coc#float#get_float_win_list()
+ let except = get(a:, 1, 0)
+ for id in winids
+ if except && id == except
+ continue
+ endif
+ if coc#window#get_var(id, 'autohide', 0)
+ call coc#float#close(id)
+ endif
+ endfor
+endfunction
+
+function! s:create_loading_buf() abort
+ let bufnr = coc#float#create_buf(0)
+ call s:change_loading_buf(bufnr, 0)
+ return bufnr
+endfunction
+
+function! s:change_loading_buf(bufnr, idx) abort
+ if bufloaded(a:bufnr)
+ let target = getbufvar(a:bufnr, 'target_winid', v:null)
+ if !empty(target) && !coc#float#valid(target)
+ call coc#float#close(getbufvar(a:bufnr, 'popup'))
+ return
+ endif
+ let line = get(s:frames, a:idx, ' ')
+ call setbufline(a:bufnr, 1, line)
+ call coc#highlight#add_highlight(a:bufnr, -1, 'CocNotificationProgress', 0, 0, -1)
+ let idx = a:idx == len(s:frames) - 1 ? 0 : a:idx + 1
+ call timer_start(100, { -> s:change_loading_buf(a:bufnr, idx)})
+ endif
+endfunction
diff --git a/pack/acp/start/coc.nvim/autoload/coc/dict.vim b/pack/acp/start/coc.nvim/autoload/coc/dict.vim
new file mode 100644
index 0000000..00c494b
--- /dev/null
+++ b/pack/acp/start/coc.nvim/autoload/coc/dict.vim
@@ -0,0 +1,32 @@
+scriptencoding utf-8
+
+function! coc#dict#equal(one, two) abort
+ for key in keys(a:one)
+ if a:one[key] != a:two[key]
+ return 0
+ endif
+ endfor
+ return 1
+endfunction
+
+" Return new dict with keys removed
+function! coc#dict#omit(dict, keys) abort
+ let res = {}
+ for key in keys(a:dict)
+ if index(a:keys, key) == -1
+ let res[key] = a:dict[key]
+ endif
+ endfor
+ return res
+endfunction
+
+" Return new dict with keys only
+function! coc#dict#pick(dict, keys) abort
+ let res = {}
+ for key in keys(a:dict)
+ if index(a:keys, key) != -1
+ let res[key] = a:dict[key]
+ endif
+ endfor
+ return res
+endfunction
diff --git a/pack/acp/start/coc.nvim/autoload/coc/float.vim b/pack/acp/start/coc.nvim/autoload/coc/float.vim
new file mode 100644
index 0000000..65c83a2
--- /dev/null
+++ b/pack/acp/start/coc.nvim/autoload/coc/float.vim
@@ -0,0 +1,1423 @@
+scriptencoding utf-8
+let s:is_vim = !has('nvim')
+let s:borderchars = get(g:, 'coc_borderchars', ['โ', 'โ', 'โ', 'โ', 'โ', 'โ', 'โ', 'โ'])
+let s:rounded_borderchars = s:borderchars[0:3] + ['โญ', 'โฎ', 'โฏ', 'โฐ']
+let s:borderjoinchars = get(g:, 'coc_border_joinchars', ['โฌ', 'โค', 'โด', 'โ'])
+let s:popup_list_api = exists('*popup_list')
+" Popup ids, used when popup_list() doesn't exist
+let s:popup_list = []
+let s:pad_bufnr = -1
+
+" Check visible float/popup exists.
+function! coc#float#has_float(...) abort
+ return len(coc#float#get_float_win_list(get(a:, 1, 0))) > 0
+endfunction
+
+function! coc#float#close_all(...) abort
+ let winids = coc#float#get_float_win_list(get(a:, 1, 0))
+ for id in winids
+ try
+ call coc#float#close(id)
+ catch /E5555:/
+ " ignore
+ endtry
+ endfor
+endfunction
+
+function! coc#float#jump() abort
+ if has('nvim')
+ let winids = coc#float#get_float_win_list()
+ if !empty(winids)
+ call win_gotoid(winids[0])
+ endif
+ endif
+endfunction
+
+function! coc#float#valid(winid) abort
+ if a:winid <= 0
+ return 0
+ endif
+ if !s:is_vim
+ if !nvim_win_is_valid(a:winid)
+ return 0
+ endif
+ return !empty(nvim_win_get_config(a:winid)['relative'])
+ endif
+ try
+ return !empty(popup_getpos(a:winid))
+ catch /^Vim\%((\a\+)\)\=:E993/
+ " not a popup window
+ return 0
+ endtry
+endfunction
+
+function! coc#float#get_height(winid) abort
+ if !s:is_vim
+ let borderwin = coc#float#get_related(a:winid, 'border')
+ if borderwin
+ return nvim_win_get_height(borderwin)
+ endif
+ return nvim_win_get_height(a:winid)
+ endif
+ return get(popup_getpos(a:winid), 'height', 0)
+endfunction
+
+function! coc#float#change_height(winid, delta) abort
+ if s:is_vim
+ let curr = get(popup_getpos(a:winid), 'core_height', v:null)
+ if curr isnot v:null
+ call popup_move(a:winid, {
+ \ 'maxheight': max([1, curr + a:delta]),
+ \ 'minheight': max([1, curr + a:delta]),
+ \ })
+ endif
+ else
+ let winids = copy(coc#window#get_var(a:winid, 'related', []))
+ call filter(winids, 'index(["border","pad","scrollbar"],coc#window#get_var(v:val,"kind","")) >= 0')
+ call add(winids, a:winid)
+ for winid in winids
+ if coc#window#get_var(winid, 'kind', '') ==# 'border'
+ let bufnr = winbufnr(winid)
+ if a:delta > 0
+ call appendbufline(bufnr, 1, repeat(getbufline(bufnr, 2), a:delta))
+ else
+ call deletebufline(bufnr, 2, 2 - a:delta - 1)
+ endif
+ endif
+ let height = nvim_win_get_height(winid)
+ call nvim_win_set_height(winid, max([1, height + a:delta]))
+ endfor
+ endif
+endfunction
+
+" create or config float window, returns [winid, bufnr], config including:
+" - relative: could be 'editor' 'cursor'
+" - row: line count relative to editor/cursor, nagetive number means abover cursor.
+" - col: column count relative to editor/cursor, nagetive number means left of cursor.
+" - width: content width without border and title.
+" - height: content height without border and title.
+" - lines: (optional) lines to insert, default to v:null.
+" - 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.
+" - highlight: (optional) highlight of window, default to 'CocFloating'
+" - borderhighlight: (optional) should be array or string for border highlights,
+" highlight all borders with first value.
+" - close: (optional) show close button when is 1.
+" - highlights: (optional) highlight items.
+" - buttons: (optional) array of button text for create buttons at bottom.
+" - codes: (optional) list of CodeBlock.
+" - winblend: (optional) winblend option for float window, neovim only.
+" - shadow: (optional) use shadow as border style, neovim only.
+" - focusable: (optional) neovim only, default to true.
+" - scrollinside: (optional) neovim only, create scrollbar inside window.
+" - rounded: (optional) use rounded borderchars, ignored when borderchars exists.
+" - borderchars: (optional) borderchars, should be length of 8
+" - nopad: (optional) not add pad when 1
+" - index: (optional) line index
+function! coc#float#create_float_win(winid, bufnr, config) abort
+ let lines = get(a:config, 'lines', v:null)
+ let bufnr = a:bufnr
+ try
+ let bufnr = coc#float#create_buf(a:bufnr, lines, 'hide')
+ catch /E523:/
+ " happens when using getchar() #3921
+ return []
+ endtry
+ let lnum = max([1, get(a:config, 'index', 0) + 1])
+ " use exists
+ if a:winid && coc#float#valid(a:winid)
+ if s:is_vim
+ let [line, col] = s:popup_position(a:config)
+ let opts = {
+ \ 'firstline': 1,
+ \ 'line': line,
+ \ 'col': col,
+ \ 'minwidth': a:config['width'],
+ \ 'minheight': a:config['height'],
+ \ 'maxwidth': a:config['width'],
+ \ 'maxheight': a:config['height'],
+ \ 'title': get(a:config, 'title', ''),
+ \ 'highlight': get(a:config, 'highlight', 'CocFloating'),
+ \ 'borderhighlight': [s:get_borderhighlight(a:config)],
+ \ }
+ if !s:empty_border(get(a:config, 'border', []))
+ let opts['border'] = a:config['border']
+ endif
+ call popup_setoptions(a:winid, opts)
+ call win_execute(a:winid, 'exe '.lnum)
+ call coc#float#vim_buttons(a:winid, a:config)
+ call s:add_highlights(a:winid, a:config, 0)
+ return [a:winid, winbufnr(a:winid)]
+ else
+ let config = s:convert_config_nvim(a:config, 0)
+ let hlgroup = get(a:config, 'highlight', 'CocFloating')
+ let winhl = 'Normal:'.hlgroup.',NormalNC:'.hlgroup.',FoldColumn:'.hlgroup
+ if winhl !=# getwinvar(a:winid, '&winhl', '')
+ call setwinvar(a:winid, '&winhl', winhl)
+ endif
+ call nvim_win_set_buf(a:winid, bufnr)
+ call nvim_win_set_config(a:winid, config)
+ call nvim_win_set_cursor(a:winid, [lnum, 0])
+ call coc#float#nvim_create_related(a:winid, config, a:config)
+ call s:add_highlights(a:winid, a:config, 0)
+ return [a:winid, bufnr]
+ endif
+ endif
+ let winid = 0
+ if s:is_vim
+ let [line, col] = s:popup_position(a:config)
+ let title = get(a:config, 'title', '')
+ let buttons = get(a:config, 'buttons', [])
+ let hlgroup = get(a:config, 'highlight', 'CocFloating')
+ let nopad = get(a:config, 'nopad', 0)
+ let border = s:empty_border(get(a:config, 'border', [])) ? [0, 0, 0, 0] : a:config['border']
+ let opts = {
+ \ 'title': title,
+ \ 'line': line,
+ \ 'col': col,
+ \ 'fixed': 1,
+ \ 'padding': [0, !nopad && !border[1], 0, !nopad && !border[3]],
+ \ 'borderchars': s:get_borderchars(a:config),
+ \ 'highlight': hlgroup,
+ \ 'minwidth': a:config['width'],
+ \ 'minheight': a:config['height'],
+ \ 'maxwidth': a:config['width'],
+ \ 'maxheight': a:config['height'],
+ \ 'close': get(a:config, 'close', 0) ? 'button' : 'none',
+ \ 'border': border,
+ \ 'callback': { -> coc#float#on_close(winid)},
+ \ 'borderhighlight': [s:get_borderhighlight(a:config)],
+ \ }
+ let winid = popup_create(bufnr, opts)
+ if !s:popup_list_api
+ call add(s:popup_list, winid)
+ endif
+ call s:set_float_defaults(winid, a:config)
+ call win_execute(winid, 'exe '.lnum)
+ call coc#float#vim_buttons(winid, a:config)
+ else
+ let config = s:convert_config_nvim(a:config, 1)
+ let border = get(a:config, 'border', [])
+ if has('nvim-0.5.0') && get(a:config, 'shadow', 0) && empty(get(a:config, 'buttons', v:null)) && empty(get(border, 2, 0))
+ let config['border'] = 'shadow'
+ endif
+ noa let winid = nvim_open_win(bufnr, 0, config)
+ if winid is 0
+ return []
+ endif
+ " cursorline highlight not work on old neovim
+ call s:set_float_defaults(winid, a:config)
+ call nvim_win_set_cursor(winid, [lnum, 0])
+ call coc#float#nvim_create_related(winid, config, a:config)
+ call coc#float#nvim_set_winblend(winid, get(a:config, 'winblend', v:null))
+ endif
+ call s:add_highlights(winid, a:config, 1)
+ let g:coc_last_float_win = winid
+ call coc#util#do_autocmd('CocOpenFloat')
+ return [winid, bufnr]
+endfunction
+
+function! coc#float#nvim_create_related(winid, config, opts) abort
+ let related = getwinvar(a:winid, 'related', [])
+ let exists = !empty(related)
+ let border = get(a:opts, 'border', [])
+ let borderhighlight = s:get_borderhighlight(a:opts)
+ let buttons = get(a:opts, 'buttons', [])
+ let pad = !get(a:opts, 'nopad', 0) && (empty(border) || get(border, 1, 0) == 0)
+ let shadow = get(a:opts, 'shadow', 0)
+ if get(a:opts, 'close', 0)
+ call coc#float#nvim_close_btn(a:config, a:winid, border, borderhighlight, related)
+ elseif exists
+ call coc#float#close_related(a:winid, 'close')
+ endif
+ if !empty(buttons)
+ call coc#float#nvim_buttons(a:config, a:winid, buttons, get(a:opts, 'getchar', 0), get(border, 2, 0), pad, borderhighlight, shadow, related)
+ elseif exists
+ call coc#float#close_related(a:winid, 'buttons')
+ endif
+ if !s:empty_border(border)
+ let borderchars = s:get_borderchars(a:opts)
+ call coc#float#nvim_border_win(a:config, borderchars, a:winid, border, get(a:opts, 'title', ''), !empty(buttons), borderhighlight, shadow, related)
+ elseif exists
+ call coc#float#close_related(a:winid, 'border')
+ endif
+ " Check right border
+ if pad
+ call coc#float#nvim_right_pad(a:config, a:winid, related)
+ elseif exists
+ call coc#float#close_related(a:winid, 'pad')
+ endif
+ call setwinvar(a:winid, 'related', filter(related, 'nvim_win_is_valid(v:val)'))
+endfunction
+
+" border window for neovim, content config with border
+function! coc#float#nvim_border_win(config, borderchars, winid, border, title, hasbtn, hlgroup, shadow, related) abort
+ let winid = coc#float#get_related(a:winid, 'border')
+ 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] + (a:hasbtn ? 2 : 0)
+ let lines = coc#float#create_border_lines(a:border, a:borderchars, a:title, a:config['width'], a:config['height'], a:hasbtn)
+ let bufnr = winid ? winbufnr(winid) : 0
+ let bufnr = coc#float#create_buf(bufnr, lines)
+ let opt = {
+ \ 'relative': a:config['relative'],
+ \ 'width': width,
+ \ 'height': height,
+ \ 'row': row,
+ \ 'col': col,
+ \ 'focusable': v:false,
+ \ 'style': 'minimal',
+ \ }
+ if has('nvim-0.5.0') && a:shadow && !a:hasbtn && a:border[2]
+ let opt['border'] = 'shadow'
+ endif
+ if winid
+ call nvim_win_set_config(winid, opt)
+ call setwinvar(winid, '&winhl', 'Normal:'.a:hlgroup.',NormalNC:'.a:hlgroup)
+ else
+ noa let winid = nvim_open_win(bufnr, 0, opt)
+ call setwinvar(winid, 'delta', -1)
+ let winhl = 'Normal:'.a:hlgroup.',NormalNC:'.a:hlgroup
+ call s:nvim_add_related(winid, a:winid, 'border', winhl, a:related)
+ endif
+endfunction
+
+" neovim only
+function! coc#float#nvim_close_btn(config, winid, border, hlgroup, related) abort
+ let winid = coc#float#get_related(a:winid, 'close')
+ 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',
+ \ }
+ if has('nvim-0.5.1')
+ let config['zindex'] = 300
+ endif
+ if winid
+ call nvim_win_set_config(winid, coc#dict#pick(config, ['relative', 'row', 'col']))
+ else
+ let bufnr = coc#float#create_buf(0, ['X'])
+ noa let winid = nvim_open_win(bufnr, 0, config)
+ let winhl = 'Normal:'.a:hlgroup.',NormalNC:'.a:hlgroup
+ call s:nvim_add_related(winid, a:winid, 'close', winhl, a:related)
+ endif
+endfunction
+
+" Create padding window by config of current window & border config
+function! coc#float#nvim_right_pad(config, winid, related) abort
+ let winid = coc#float#get_related(a:winid, 'pad')
+ 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',
+ \ }
+ if has('nvim-0.5.1')
+ let config['zindex'] = 300
+ endif
+ if winid && nvim_win_is_valid(winid)
+ if has('nvim-0.5.0')
+ call nvim_win_set_config(winid, coc#dict#pick(config, ['relative', 'row', 'col']))
+ call nvim_win_set_height(winid, config['height'])
+ return
+ endif
+ noa call nvim_win_close(winid, 1)
+ endif
+ let s:pad_bufnr = bufloaded(s:pad_bufnr) ? s:pad_bufnr : coc#float#create_buf(0, repeat([''], &lines), 'hide')
+ noa let winid = nvim_open_win(s:pad_bufnr, 0, config)
+ call s:nvim_add_related(winid, a:winid, 'pad', '', a:related)
+endfunction
+
+" draw buttons window for window with config
+function! coc#float#nvim_buttons(config, winid, buttons, getchar, borderbottom, pad, borderhighlight, shadow, related) abort
+ let winid = coc#float#get_related(a:winid, 'buttons')
+ let width = a:config['width'] + (a:pad ? 1 : 0)
+ let config = {
+ \ 'row': a:config['row'] + a:config['height'],
+ \ 'col': a:config['col'],
+ \ 'width': width,
+ \ 'height': 2 + (a:borderbottom ? 1 : 0),
+ \ 'relative': a:config['relative'],
+ \ 'focusable': 1,
+ \ 'style': 'minimal',
+ \ }
+ if has('nvim-0.5.1')
+ let config['zindex'] = 300
+ if a:shadow
+ let config['border'] = 'shadow'
+ endif
+ endif
+ if winid
+ let bufnr = winbufnr(winid)
+ call s:create_btns_buffer(bufnr, width, a:buttons, a:borderbottom)
+ call nvim_win_set_config(winid, config)
+ else
+ let bufnr = s:create_btns_buffer(0, width, a:buttons, a:borderbottom)
+ noa let winid = nvim_open_win(bufnr, 0, config)
+ if winid
+ call s:nvim_add_related(winid, a:winid, 'buttons', '', a:related)
+ call s:nvim_create_keymap(winid)
+ endif
+ endif
+ if bufnr
+ call nvim_buf_clear_namespace(bufnr, -1, 0, -1)
+ call nvim_buf_add_highlight(bufnr, 1, a:borderhighlight, 0, 0, -1)
+ if a:borderbottom
+ call nvim_buf_add_highlight(bufnr, 1, a:borderhighlight, 2, 0, -1)
+ endif
+ let vcols = getbufvar(bufnr, 'vcols', [])
+ " TODO need change vol to col
+ for col in vcols
+ call nvim_buf_add_highlight(bufnr, 1, a:borderhighlight, 1, col, col + 3)
+ endfor
+ if a:getchar
+ let keys = s:gen_filter_keys(getbufline(bufnr, 2)[0])
+ call matchaddpos('MoreMsg', map(keys[0], "[2,v:val]"), 99, -1, {'window': winid})
+ call timer_start(10, {-> coc#float#getchar(winid, keys[1])})
+ endif
+ endif
+endfunction
+
+function! coc#float#getchar(winid, keys) abort
+ let ch = coc#prompt#getc()
+ let target = getwinvar(a:winid, 'target_winid', 0)
+ if ch ==# "\"
+ call coc#float#close(target)
+ return
+ endif
+ if ch ==# "\"
+ if getwinvar(v:mouse_winid, 'kind', '') ==# 'close'
+ call coc#float#close(target)
+ return
+ endif
+ if v:mouse_winid == a:winid && v:mouse_lnum == 2
+ let vcols = getbufvar(winbufnr(a:winid), 'vcols', [])
+ let col = v:mouse_col - 1
+ if index(vcols, col) < 0
+ let filtered = filter(vcols, 'v:val < col')
+ call coc#rpc#notify('FloatBtnClick', [winbufnr(target), len(filtered)])
+ call coc#float#close(target)
+ return
+ endif
+ endif
+ else
+ let idx = index(a:keys, ch)
+ if idx >= 0
+ call coc#rpc#notify('FloatBtnClick', [winbufnr(target), idx])
+ call coc#float#close(target)
+ return
+ endif
+ endif
+ call coc#float#getchar(a:winid, a:keys)
+endfunction
+
+" Create or refresh scrollbar for winid
+" Need called on create, config, buffer change, scrolled
+function! coc#float#nvim_scrollbar(winid) abort
+ if !has('nvim-0.4.0')
+ return
+ endif
+ let winids = nvim_tabpage_list_wins(nvim_get_current_tabpage())
+ if index(winids, a:winid) == -1
+ return
+ endif
+ let config = nvim_win_get_config(a:winid)
+ let [row, column] = nvim_win_get_position(a:winid)
+ let relative = 'editor'
+ if row == 0 && column == 0
+ " fix bad value when ext_multigrid is enabled. https://github.com/neovim/neovim/issues/11935
+ let [row, column] = [config.row, config.col]
+ let relative = config.relative
+ endif
+ 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 closewin = coc#float#get_related(a:winid, 'close')
+ let border = getwinvar(a:winid, 'border', [])
+ let scrollinside = getwinvar(a:winid, 'scrollinside', 0) && get(border, 1, 0)
+ let winblend = getwinvar(a:winid, '&winblend', 0)
+ let move_down = closewin && !get(border, 0, 0)
+ let id = coc#float#get_related(a:winid, 'scrollbar')
+ if ch <= height || height <= 1
+ " no scrollbar, remove exists
+ if id
+ call s:close_win(id)
+ endif
+ return
+ endif
+ if move_down
+ let height = height - 1
+ endif
+ call coc#float#close_related(a:winid, 'pad')
+ let sbuf = id ? winbufnr(id) : 0
+ let sbuf = coc#float#create_buf(sbuf, repeat([' '], height))
+ let opts = {
+ \ 'row': move_down ? row + 1 : row,
+ \ 'col': column + width - scrollinside,
+ \ 'relative': relative,
+ \ 'width': 1,
+ \ 'height': height,
+ \ 'focusable': v:false,
+ \ 'style': 'minimal',
+ \ }
+ if has('nvim-0.5.1')
+ let opts['zindex'] = 300
+ endif
+ if id
+ call nvim_win_set_config(id, opts)
+ else
+ noa let id = nvim_open_win(sbuf, 0 , opts)
+ if id == 0
+ return
+ endif
+ if winblend
+ call setwinvar(id, '&winblend', winblend)
+ endif
+ call setwinvar(id, 'kind', 'scrollbar')
+ call setwinvar(id, 'target_winid', a:winid)
+ call coc#float#add_related(id, a:winid)
+ endif
+ if !scrollinside
+ call coc#float#nvim_scroll_adjust(a:winid)
+ endif
+ let thumb_height = max([1, float2nr(floor(height * (height + 0.0)/ch))])
+ let wininfo = getwininfo(a:winid)[0]
+ let start = 0
+ if wininfo['topline'] != 1
+ " needed for correct getwininfo
+ let firstline = wininfo['topline']
+ let lastline = s:nvim_get_botline(firstline, height, cw, bufnr)
+ let linecount = nvim_buf_line_count(winbufnr(a:winid))
+ if 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
+ endif
+ " add highlights
+ call nvim_buf_clear_namespace(sbuf, -1, 0, -1)
+ for idx in range(0, height - 1)
+ if idx >= start && idx < start + thumb_height
+ call nvim_buf_add_highlight(sbuf, -1, 'PmenuThumb', idx, 0, 1)
+ else
+ call nvim_buf_add_highlight(sbuf, -1, 'PmenuSbar', idx, 0, 1)
+ endif
+ endfor
+endfunction
+
+function! coc#float#create_border_lines(border, borderchars, title, width, height, hasbtn) abort
+ let borderchars = a:borderchars
+ let list = []
+ if a:border[0]
+ let top = (a:border[3] ? borderchars[4]: '')
+ \.repeat(borderchars[0], a:width)
+ \.(a:border[1] ? borderchars[5] : '')
+ if !empty(a:title)
+ let top = coc#string#compose(top, 1, a:title.' ')
+ endif
+ call add(list, top)
+ endif
+ let mid = (a:border[3] ? borderchars[3]: '')
+ \.repeat(' ', a:width)
+ \.(a:border[1] ? borderchars[1] : '')
+ call extend(list, repeat([mid], a:height + (a:hasbtn ? 2 : 0)))
+ if a:hasbtn
+ let list[len(list) - 2] = (a:border[3] ? s:borderjoinchars[3]: '')
+ \.repeat(' ', a:width)
+ \.(a:border[1] ? s:borderjoinchars[1] : '')
+ endif
+ if a:border[2]
+ let bot = (a:border[3] ? borderchars[7]: '')
+ \.repeat(borderchars[2], a:width)
+ \.(a:border[1] ? borderchars[6] : '')
+ call add(list, bot)
+ endif
+ return list
+endfunction
+
+" Close float window by id
+function! coc#float#close(winid) abort
+ call coc#float#close_related(a:winid)
+ call s:close_win(a:winid)
+ return 1
+endfunction
+
+" Get visible float windows
+function! coc#float#get_float_win_list(...) abort
+ let res = []
+ let list_all = get(a:, 1, 0)
+ if s:is_vim
+ if s:popup_list_api
+ return filter(popup_list(), 'popup_getpos(v:val)["visible"]'.(list_all ? '' : '&& getwinvar(v:val, "float", 0)'))
+ endif
+ return filter(s:popup_list, 's:popup_visible(v:val)')
+ else
+ let res = []
+ for i in range(1, winnr('$'))
+ let id = win_getid(i)
+ let config = nvim_win_get_config(id)
+ if empty(config) || empty(config['relative'])
+ continue
+ endif
+ " ignore border & button window & others
+ if list_all == 0 && !getwinvar(id, 'float', 0)
+ continue
+ endif
+ call add(res, id)
+ endfor
+ return res
+ endif
+ return []
+endfunction
+
+function! coc#float#get_float_by_kind(kind) abort
+ if s:is_vim
+ if s:popup_list_api
+ return get(filter(popup_list(), 'popup_getpos(v:val)["visible"] && getwinvar(v:val, "kind", "") ==# "'.a:kind.'"'), 0, 0)
+ endif
+ return get(filter(s:popup_list, 's:popup_visible(v:val) && getwinvar(v:val, "kind", "") ==# "'.a:kind.'"'), 0, 0)
+ else
+ let res = []
+ for i in range(1, winnr('$'))
+ let winid = win_getid(i)
+ let config = nvim_win_get_config(winid)
+ if !empty(config['relative']) && getwinvar(winid, 'kind', '') ==# a:kind
+ return winid
+ endif
+ endfor
+ endif
+ return 0
+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)
+ 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 padding
+ 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.0') && !has('patch-8.2.0750')
+ throw 'coc#float#scroll() requires nvim >= 0.4.0 or vim >= 8.2.0750'
+ endif
+ let amount = get(a:, 1, 0)
+ let winids = filter(coc#float#get_float_win_list(), 'coc#float#scrollable(v:val) && getwinvar(v:val,"kind","") !=# "pum"')
+ if empty(winids)
+ return mode() =~ '^i' || mode() ==# 'v' ? "" : "\"
+ endif
+ for winid in winids
+ call s:scroll_win(winid, a:forward, amount)
+ endfor
+ return mode() =~ '^i' || mode() ==# 'v' ? "" : "\"
+endfunction
+
+function! coc#float#scroll_win(winid, forward, amount) abort
+ let opts = s:get_options(a:winid)
+ let lines = getbufline(winbufnr(a:winid), 1, '$')
+ let maxfirst = s:max_firstline(lines, opts['height'], opts['width'])
+ let topline = opts['topline']
+ let height = opts['height']
+ let width = opts['width']
+ let scrolloff = getwinvar(a:winid, '&scrolloff', 0)
+ if a:forward && topline >= maxfirst
+ return
+ endif
+ if !a:forward && topline == 1
+ return
+ endif
+ if a:amount == 0
+ let topline = s:get_topline(opts['topline'], lines, a:forward, height, width)
+ else
+ let topline = topline + (a:forward ? a:amount : - a:amount)
+ endif
+ let topline = a:forward ? min([maxfirst, topline]) : max([1, topline])
+ let lnum = s:get_cursorline(topline, lines, scrolloff, width, height)
+ call s:win_setview(a:winid, topline, lnum)
+ let top = s:get_options(a:winid)['topline']
+ " not changed
+ if top == opts['topline']
+ if a:forward
+ call s:win_setview(a:winid, topline + 1, lnum + 1)
+ else
+ call s:win_setview(a:winid, topline - 1, lnum - 1)
+ endif
+ 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! coc#float#nvim_refresh_scrollbar(winid) abort
+ let id = coc#float#get_related(a:winid, 'scrollbar')
+ if id && nvim_win_is_valid(id)
+ call coc#float#nvim_scrollbar(a:winid)
+ endif
+endfunction
+
+function! coc#float#on_close(winid) abort
+ let winids = coc#float#get_float_win_list()
+ for winid in winids
+ let target = getwinvar(winid, 'target_winid', -1)
+ if target == a:winid
+ call coc#float#close(winid)
+ endif
+ endfor
+endfunction
+
+" Close related windows, or specific kind
+function! coc#float#close_related(winid, ...) abort
+ if !coc#float#valid(a:winid)
+ return
+ endif
+ let timer = coc#window#get_var(a:winid, 'timer', 0)
+ if timer
+ call timer_stop(timer)
+ endif
+ let kind = get(a:, 1, '')
+ let winids = coc#window#get_var(a:winid, 'related', [])
+ for id in winids
+ let curr = coc#window#get_var(id, 'kind', '')
+ if empty(kind) || curr ==# kind
+ if curr == 'list'
+ call coc#float#close(id)
+ elseif s:is_vim
+ " vim doesn't throw
+ noa call popup_close(id)
+ else
+ silent! noa call nvim_win_close(id, 1)
+ endif
+ endif
+ endfor
+endfunction
+
+" Close related windows if target window is not visible.
+function! coc#float#check_related() abort
+ let invalids = []
+ let ids = coc#float#get_float_win_list(1)
+ for id in ids
+ let target = getwinvar(id, 'target_winid', 0)
+ if (target && index(ids, target) == -1) || getwinvar(id, 'kind', '') == 'pumdetail'
+ call add(invalids, id)
+ endif
+ endfor
+ if !s:popup_list_api
+ let s:popup_list = filter(ids, "index(invalids, v:val) == -1")
+ endif
+ for id in invalids
+ call coc#float#close(id)
+ endfor
+endfunction
+
+" Show float window/popup for user confirm.
+" Create buttons popup on vim
+function! coc#float#vim_buttons(winid, config) abort
+ if !has('patch-8.2.0750')
+ return
+ endif
+ let related = getwinvar(a:winid, 'related', [])
+ let winid = coc#float#get_related(a:winid, 'buttons')
+ let btns = get(a:config, 'buttons', [])
+ if empty(btns)
+ if winid
+ call s:close_win(winid)
+ " fix padding
+ let opts = popup_getoptions(a:winid)
+ let padding = get(opts, 'padding', v:null)
+ if !empty(padding)
+ let padding[2] = padding[2] - 2
+ endif
+ call popup_setoptions(a:winid, {'padding': padding})
+ endif
+ return
+ endif
+ let border = get(a:config, 'border', v:null)
+ if !winid
+ " adjusting popup padding
+ let opts = popup_getoptions(a:winid)
+ let padding = get(opts, 'padding', v:null)
+ if type(padding) == 7
+ let padding = [0, 0, 2, 0]
+ elseif len(padding) == 0
+ let padding = [1, 1, 3, 1]
+ else
+ let padding[2] = padding[2] + 2
+ endif
+ call popup_setoptions(a:winid, {'padding': padding})
+ endif
+ let borderhighlight = get(get(a:config, 'borderhighlight', []), 0, '')
+ let pos = popup_getpos(a:winid)
+ let bw = empty(border) ? 0 : get(border, 1, 0) + get(border, 3, 0)
+ let borderbottom = empty(border) ? 0 : get(border, 2, 0)
+ let borderleft = empty(border) ? 0 : get(border, 3, 0)
+ let width = pos['width'] - bw + get(pos, 'scrollbar', 0)
+ let bufnr = s:create_btns_buffer(winid ? winbufnr(winid): 0,width, btns, borderbottom)
+ let height = 2 + (borderbottom ? 1 : 0)
+ let keys = s:gen_filter_keys(getbufline(bufnr, 2)[0])
+ let options = {
+ \ 'filter': {id, key -> coc#float#vim_filter(id, key, keys[1])},
+ \ 'highlight': get(opts, 'highlight', 'CocFloating')
+ \ }
+ let config = {
+ \ 'line': pos['line'] + pos['height'] - height,
+ \ 'col': pos['col'] + borderleft,
+ \ 'minwidth': width,
+ \ 'minheight': height,
+ \ 'maxwidth': width,
+ \ 'maxheight': height,
+ \ }
+ if winid != 0
+ call popup_move(winid, config)
+ call popup_setoptions(winid, options)
+ call win_execute(winid, 'call clearmatches()')
+ else
+ let options = extend({
+ \ 'filtermode': 'nvi',
+ \ 'padding': [0, 0, 0, 0],
+ \ 'fixed': 1,
+ \ 'zindex': 99,
+ \ }, options)
+ call extend(options, config)
+ let winid = popup_create(bufnr, options)
+ if !s:popup_list_api
+ call add(s:popup_list, winid)
+ endif
+ endif
+ if winid != 0
+ if !empty(borderhighlight)
+ call coc#highlight#add_highlight(bufnr, -1, borderhighlight, 0, 0, -1)
+ call coc#highlight#add_highlight(bufnr, -1, borderhighlight, 2, 0, -1)
+ call win_execute(winid, 'call matchadd("'.borderhighlight.'", "'.s:borderchars[1].'")')
+ endif
+ call setwinvar(winid, 'kind', 'buttons')
+ call setwinvar(winid, 'target_winid', a:winid)
+ call add(related, winid)
+ call setwinvar(a:winid, 'related', related)
+ call matchaddpos('MoreMsg', map(keys[0], "[2,v:val]"), 99, -1, {'window': winid})
+ endif
+endfunction
+
+function! coc#float#nvim_float_click() abort
+ let kind = getwinvar(win_getid(), 'kind', '')
+ if kind == 'buttons'
+ if line('.') != 2
+ return
+ endif
+ let vw = strdisplaywidth(strpart(getline('.'), 0, col('.') - 1))
+ let vcols = getbufvar(bufnr('%'), 'vcols', [])
+ if index(vcols, vw) >= 0
+ return
+ endif
+ let idx = 0
+ if !empty(vcols)
+ let filtered = filter(vcols, 'v:val < vw')
+ let idx = idx + len(filtered)
+ endif
+ let winid = win_getid()
+ let target = getwinvar(winid, 'target_winid', 0)
+ if target
+ call coc#rpc#notify('FloatBtnClick', [winbufnr(target), idx])
+ call coc#float#close(target)
+ endif
+ elseif kind == 'close'
+ let target = getwinvar(win_getid(), 'target_winid', 0)
+ call coc#float#close(target)
+ endif
+endfunction
+
+" Add mapping if necessary
+function! coc#float#nvim_win_enter(winid) abort
+ let kind = getwinvar(a:winid, 'kind', '')
+ if kind == 'buttons' || kind == 'close'
+ if empty(maparg('', 'n'))
+ nnoremap :call coc#float#nvim_float_click()
+ endif
+ endif
+endfunction
+
+function! coc#float#vim_filter(winid, key, keys) abort
+ let key = tolower(a:key)
+ let idx = index(a:keys, key)
+ let target = getwinvar(a:winid, 'target_winid', 0)
+ if target && idx >= 0
+ call coc#rpc#notify('FloatBtnClick', [winbufnr(target), idx])
+ call coc#float#close(target)
+ return 1
+ endif
+ return 0
+endfunction
+
+function! coc#float#get_related(winid, kind, ...) abort
+ if coc#float#valid(a:winid)
+ for winid in coc#window#get_var(a:winid, 'related', [])
+ if coc#window#get_var(winid, 'kind', '') ==# a:kind
+ return winid
+ endif
+ endfor
+ endif
+ return get(a:, 1, 0)
+endfunction
+
+function! coc#float#get_row(winid) abort
+ let winid = s:is_vim ? a:winid : coc#float#get_related(a:winid, 'border', a:winid)
+ if coc#float#valid(winid)
+ if s:is_vim
+ let pos = popup_getpos(winid)
+ return pos['line'] - 1
+ endif
+ let pos = nvim_win_get_position(winid)
+ return pos[0]
+ endif
+endfunction
+
+" Create temporarily buffer with optional lines and &bufhidden
+function! coc#float#create_buf(bufnr, ...) abort
+ if a:bufnr > 0 && bufloaded(a:bufnr)
+ let bufnr = a:bufnr
+ else
+ if s:is_vim
+ noa let bufnr = bufadd('')
+ noa call bufload(bufnr)
+ call setbufvar(bufnr, '&buflisted', 0)
+ else
+ noa let bufnr = nvim_create_buf(v:false, v:true)
+ endif
+ let bufhidden = get(a:, 2, 'wipe')
+ call setbufvar(bufnr, '&buftype', 'nofile')
+ call setbufvar(bufnr, '&bufhidden', bufhidden)
+ call setbufvar(bufnr, '&swapfile', 0)
+ call setbufvar(bufnr, '&undolevels', -1)
+ " neovim's bug
+ call setbufvar(bufnr, '&modifiable', 1)
+ endif
+ let lines = get(a:, 1, v:null)
+ if type(lines) == v:t_list
+ if has('nvim')
+ call nvim_buf_set_lines(bufnr, 0, -1, v:false, lines)
+ else
+ silent noa call setbufline(bufnr, 1, lines)
+ silent noa call deletebufline(bufnr, len(lines) + 1, '$')
+ endif
+ endif
+ return bufnr
+endfunction
+
+" Change border window & close window when scrollbar is shown.
+function! coc#float#nvim_scroll_adjust(winid) abort
+ let winid = coc#float#get_related(a:winid, 'border')
+ if !winid
+ return
+ endif
+ let bufnr = winbufnr(winid)
+ let lines = nvim_buf_get_lines(bufnr, 0, -1, 0)
+ if len(lines) >= 2
+ let cw = nvim_win_get_width(a:winid)
+ let width = nvim_win_get_width(winid)
+ if width - cw != 1 + (strcharpart(lines[1], 0, 1) ==# s:borderchars[3] ? 1 : 0)
+ return
+ endif
+ call nvim_win_set_width(winid, width + 1)
+ let lastline = len(lines) - 1
+ for i in range(0, lastline)
+ let line = lines[i]
+ if i == 0
+ let add = s:borderchars[0]
+ elseif i == lastline
+ let add = s:borderchars[2]
+ else
+ let add = ' '
+ endif
+ let prev = strcharpart(line, 0, strchars(line) - 1)
+ let lines[i] = prev . add . coc#string#last_character(line)
+ endfor
+ call nvim_buf_set_lines(bufnr, 0, -1, 0, lines)
+ " Move right close button
+ if coc#window#get_var(a:winid, 'right', 0) == 0
+ let id = coc#float#get_related(a:winid, 'close')
+ if id
+ let [row, col] = nvim_win_get_position(id)
+ call nvim_win_set_config(id, {
+ \ 'relative': 'editor',
+ \ 'row': row,
+ \ 'col': col + 1,
+ \ })
+ endif
+ elseif has('nvim-0.6.0')
+ " Move winid and all related left by 1
+ let winids = [a:winid] + coc#window#get_var(a:winid, 'related', [])
+ for winid in winids
+ if nvim_win_is_valid(winid)
+ if coc#window#get_var(winid, 'kind', '') != 'close'
+ let [row, column] = nvim_win_get_position(winid)
+ call nvim_win_set_config(winid, {
+ \ 'row': row,
+ \ 'col': column - 1,
+ \ 'relative': 'editor',
+ \ })
+ endif
+ endif
+ endfor
+ endif
+ endif
+endfunction
+
+function! coc#float#nvim_set_winblend(winid, winblend) abort
+ if a:winblend is v:null
+ return
+ endif
+ call coc#window#set_var(a:winid, '&winblend', a:winblend)
+ for winid in coc#window#get_var(a:winid, 'related', [])
+ call coc#window#set_var(winid, '&winblend', a:winblend)
+ endfor
+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, create) abort
+ let valids = ['relative', 'win', 'anchor', 'width', 'height', 'bufpos', 'col', 'row', 'focusable']
+ let result = coc#dict#pick(a:config, valids)
+ 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) && !get(a:config, 'prompt', 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'] = float2nr(result['width'] + 1 - get(border,3, 0))
+ else
+ let result['width'] = float2nr(result['width'] + (get(a:config, 'nopad', 0) ? 0 : 1))
+ endif
+ if has('nvim-0.5.1') && a:create
+ let result['noautocmd'] = v:true
+ endif
+ let result['height'] = float2nr(result['height'])
+ return result
+endfunction
+
+function! s:create_btns_buffer(bufnr, width, buttons, borderbottom) abort
+ let n = len(a:buttons)
+ let spaces = a:width - n + 1
+ let tw = 0
+ for txt in a:buttons
+ let tw += strdisplaywidth(txt)
+ endfor
+ if spaces < tw
+ throw 'window is too small for buttons.'
+ endif
+ let ds = (spaces - tw)/n
+ let dl = ds/2
+ let dr = ds%2 == 0 ? ds/2 : ds/2 + 1
+ let btnline = ''
+ let idxes = []
+ for idx in range(0, n - 1)
+ let txt = toupper(a:buttons[idx][0]).a:buttons[idx][1:]
+ let btnline .= repeat(' ', dl).txt.repeat(' ', dr)
+ if idx != n - 1
+ call add(idxes, strdisplaywidth(btnline))
+ let btnline .= s:borderchars[1]
+ endif
+ endfor
+ let lines = [repeat(s:borderchars[0], a:width), btnline]
+ if a:borderbottom
+ call add(lines, repeat(s:borderchars[0], a:width))
+ endif
+ for idx in idxes
+ let lines[0] = strcharpart(lines[0], 0, idx).s:borderjoinchars[0].strcharpart(lines[0], idx + 1)
+ if a:borderbottom
+ let lines[2] = strcharpart(lines[0], 0, idx).s:borderjoinchars[2].strcharpart(lines[0], idx + 1)
+ endif
+ endfor
+ let bufnr = coc#float#create_buf(a:bufnr, lines)
+ call setbufvar(bufnr, 'vcols', idxes)
+ return bufnr
+endfunction
+
+function! s:gen_filter_keys(line) abort
+ let cols = []
+ let used = []
+ let next = 1
+ for idx in range(0, strchars(a:line) - 1)
+ let ch = strcharpart(a:line, idx, 1)
+ let nr = char2nr(ch)
+ if next
+ if (nr >= 65 && nr <= 90) || (nr >= 97 && nr <= 122)
+ let lc = tolower(ch)
+ if index(used, lc) < 0 && (!s:is_vim || empty(maparg(lc, 'n')))
+ let col = len(strcharpart(a:line, 0, idx)) + 1
+ call add(used, lc)
+ call add(cols, col)
+ let next = 0
+ endif
+ endif
+ else
+ if ch == s:borderchars[1]
+ let next = 1
+ endif
+ endif
+ endfor
+ return [cols, used]
+endfunction
+
+function! s:close_win(winid) abort
+ if a:winid <= 0
+ return
+ endif
+ " vim not throw for none exists winid
+ if s:is_vim
+ call popup_close(a:winid)
+ else
+ if nvim_win_is_valid(a:winid)
+ call nvim_win_close(a:winid, 1)
+ endif
+ endif
+endfunction
+
+function! s:nvim_create_keymap(winid) abort
+ if exists('*nvim_buf_set_keymap')
+ let bufnr = winbufnr(a:winid)
+ call nvim_buf_set_keymap(bufnr, 'n', '', ':call coc#float#nvim_float_click()', {
+ \ 'silent': v:true,
+ \ 'nowait': v:true
+ \ })
+ else
+ let curr = win_getid()
+ let m = mode()
+ if m == 'n' || m == 'i' || m == 'ic'
+ noa call win_gotoid(a:winid)
+ nnoremap :call coc#float#nvim_float_click()
+ noa call win_gotoid(curr)
+ endif
+ endif
+endfunction
+
+" getwininfo is buggy on neovim, use topline, width & height should for content
+function! s:nvim_get_botline(topline, height, width, bufnr) abort
+ let lines = getbufline(a:bufnr, a:topline, a:topline + a:height - 1)
+ let botline = a:topline
+ let count = 0
+ for i in range(0, len(lines) - 1)
+ let w = max([1, strdisplaywidth(lines[i])])
+ let lh = float2nr(ceil(str2float(string(w))/a:width))
+ let count = count + lh
+ let botline = a:topline + i
+ if count >= a:height
+ break
+ endif
+ endfor
+ return botline
+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')
+ let border = get(a:config, 'border', [0, 0, 0, 0])
+ let delta = get(border, 0, 0) + get(border, 2, 0)
+ if relative ==# 'cursor'
+ if a:config['row'] < 0
+ let delta = - delta
+ elseif a:config['row'] == 0
+ let delta = - get(border, 0, 0)
+ else
+ let delta = 0
+ endif
+ return [s:popup_cursor(a:config['row'] + delta), s:popup_cursor(a:config['col'])]
+ endif
+ return [a:config['row'] + 1, a:config['col'] + 1]
+endfunction
+
+function! coc#float#add_related(winid, target) abort
+ let arr = coc#window#get_var(a:target, 'related', [])
+ if index(arr, a:winid) >= 0
+ return
+ endif
+ call add(arr, a:winid)
+ call coc#window#set_var(a:target, 'related', arr)
+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
+
+" max firstline of lines, height > 0, width > 0
+function! s:max_firstline(lines, height, width) abort
+ let max = len(a:lines)
+ let remain = a:height
+ for line in reverse(copy(a:lines))
+ let w = max([1, strdisplaywidth(line)])
+ let dh = float2nr(ceil(str2float(string(w))/a:width))
+ if remain - dh < 0
+ break
+ endif
+ let remain = remain - dh
+ let max = max - 1
+ endfor
+ return min([len(a:lines), max + 1])
+endfunction
+
+" Get best lnum by topline
+function! s:get_cursorline(topline, lines, scrolloff, width, height) abort
+ let lastline = len(a:lines)
+ if a:topline == lastline
+ return lastline
+ endif
+ let bottomline = a:topline
+ let used = 0
+ for lnum in range(a:topline, lastline)
+ let w = max([1, strdisplaywidth(a:lines[lnum - 1])])
+ let dh = float2nr(ceil(str2float(string(w))/a:width))
+ if used + dh >= a:height || lnum == lastline
+ let bottomline = lnum
+ break
+ endif
+ let used += dh
+ endfor
+ let cursorline = a:topline + a:scrolloff
+ if cursorline + a:scrolloff > bottomline
+ " unable to satisfy scrolloff
+ let cursorline = (a:topline + bottomline)/2
+ endif
+ return cursorline
+endfunction
+
+" Get firstline for full scroll
+function! s:get_topline(topline, lines, forward, height, width) abort
+ let used = 0
+ let lnums = a:forward ? range(a:topline, len(a:lines)) : reverse(range(1, a:topline))
+ let topline = a:forward ? len(a:lines) : 1
+ for lnum in lnums
+ let w = max([1, strdisplaywidth(a:lines[lnum - 1])])
+ let dh = float2nr(ceil(str2float(string(w))/a:width))
+ if used + dh >= a:height
+ let topline = lnum
+ break
+ endif
+ let used += dh
+ endfor
+ if topline == a:topline
+ if a:forward
+ let topline = min([len(a:lines), topline + 1])
+ else
+ let topline = max([1, topline - 1])
+ endif
+ endif
+ return topline
+endfunction
+
+" topline content_height content_width
+function! s:get_options(winid) abort
+ if has('nvim')
+ let width = nvim_win_get_width(a:winid)
+ if coc#window#get_var(a:winid, '&foldcolumn', 0)
+ let width = width - 1
+ endif
+ let info = getwininfo(a:winid)[0]
+ return {
+ \ 'topline': info['topline'],
+ \ 'height': nvim_win_get_height(a:winid),
+ \ 'width': width
+ \ }
+ else
+ let pos = popup_getpos(a:winid)
+ return {
+ \ 'topline': pos['firstline'],
+ \ 'width': pos['core_width'],
+ \ 'height': pos['core_height']
+ \ }
+ endif
+endfunction
+
+function! s:win_setview(winid, topline, lnum) abort
+ if has('nvim')
+ call coc#compat#execute(a:winid, 'call winrestview({"lnum":'.a:lnum.',"topline":'.a:topline.'})')
+ call timer_start(10, { -> coc#float#nvim_refresh_scrollbar(a:winid) })
+ else
+ call coc#compat#execute(a:winid, 'exe '.a:lnum)
+ call popup_setoptions(a:winid, {
+ \ 'firstline': a:topline,
+ \ })
+ endif
+endfunction
+
+function! s:set_float_defaults(winid, config) abort
+ if has('nvim')
+ let hlgroup = get(a:config, 'highlight', 'CocFloating')
+ call setwinvar(a:winid, '&winhl', 'Normal:'.hlgroup.',NormalNC:'.hlgroup.',FoldColumn:'.hlgroup)
+ call setwinvar(a:winid, 'border', get(a:config, 'border', []))
+ call setwinvar(a:winid, 'scrollinside', get(a:config, 'scrollinside', 0))
+ if !get(a:config, 'nopad', 0)
+ call setwinvar(a:winid, '&foldcolumn', s:nvim_enable_foldcolumn(get(a:config, 'border', v:null)))
+ endif
+ endif
+ call setwinvar(a:winid, '&spell', 0)
+ call setwinvar(a:winid, '&linebreak', 1)
+ call setwinvar(a:winid, '&conceallevel', 0)
+ call setwinvar(a:winid, '&signcolumn', 'no')
+ call setwinvar(a:winid, '&list', 0)
+ call setwinvar(a:winid, '&number', 0)
+ call setwinvar(a:winid, '&relativenumber', 0)
+ call setwinvar(a:winid, '&cursorline', 0)
+ call setwinvar(a:winid, '&cursorcolumn', 0)
+ call setwinvar(a:winid, '&colorcolumn', 0)
+ call setwinvar(a:winid, '&wrap', !get(a:config, 'cursorline', 0))
+ if s:is_vim || has('nvim-0.5.0')
+ call setwinvar(a:winid, '&scrolloff', 0)
+ endif
+ if has('nvim-0.6.0') || has("patch-8.1.2281")
+ call setwinvar(a:winid, '&showbreak', 'NONE')
+ endif
+ if exists('*win_execute')
+ call win_execute(a:winid, 'setl fillchars+=eob:\ ')
+ endif
+ if get(a:config, 'autohide', 0)
+ call setwinvar(a:winid, 'autohide', 1)
+ endif
+ call setwinvar(a:winid, 'float', 1)
+endfunction
+
+function! s:nvim_add_related(winid, target, kind, winhl, related) abort
+ if a:winid <= 0
+ return
+ endif
+ " minimal not work
+ if !has('nvim-0.4.3')
+ call setwinvar(a:winid, '&colorcolumn', 0)
+ call setwinvar(a:winid, '&number', 0)
+ call setwinvar(a:winid, '&relativenumber', 0)
+ call setwinvar(a:winid, '&foldcolumn', 0)
+ call setwinvar(a:winid, '&signcolumn', 0)
+ call setwinvar(a:winid, '&list', 0)
+ endif
+ let winhl = empty(a:winhl) ? coc#window#get_var(a:target, '&winhl', '') : a:winhl
+ call setwinvar(a:winid, '&winhl', winhl)
+ call setwinvar(a:winid, 'target_winid', a:target)
+ call setwinvar(a:winid, 'kind', a:kind)
+ call add(a:related, a:winid)
+endfunction
+
+function! s:nvim_enable_foldcolumn(border) abort
+ if a:border is 1
+ return 0
+ endif
+ if type(a:border) == v:t_list && get(a:border, 3, 0) == 1
+ return 0
+ endif
+ return 1
+endfunction
+
+function! s:add_highlights(winid, config, create) abort
+ let codes = get(a:config, 'codes', [])
+ let highlights = get(a:config, 'highlights', [])
+ if empty(codes) && empty(highlights) && a:create
+ return
+ endif
+ let bgGroup = get(a:config, 'highlight', 'CocFloating')
+ for obj in codes
+ let hlGroup = get(obj, 'hlGroup', v:null)
+ if !empty(hlGroup)
+ let obj['hlGroup'] = coc#highlight#compose_hlgroup(hlGroup, bgGroup)
+ endif
+ endfor
+ call coc#highlight#add_highlights(a:winid, codes, highlights)
+endfunction
+
+function! s:empty_border(border) abort
+ if empty(a:border) || empty(filter(copy(a:border), 'v:val != 0'))
+ return 1
+ endif
+ return 0
+endfunction
+
+function! s:get_borderchars(config) abort
+ let borderchars = get(a:config, 'borderchars', [])
+ if !empty(borderchars)
+ return borderchars
+ endif
+ return get(a:config, 'rounded', 0) ? s:rounded_borderchars : s:borderchars
+endfunction
+
+function! s:scroll_win(winid, forward, amount) abort
+ if s:is_vim
+ call coc#float#scroll_win(a:winid, a:forward, a:amount)
+ else
+ call timer_start(0, { -> coc#float#scroll_win(a:winid, a:forward, a:amount)})
+ endif
+endfunction
+
+function! s:get_borderhighlight(config) abort
+ let hlgroup = get(a:config, 'highlight', 'CocFloating')
+ let borderhighlight = get(a:config, 'borderhighlight', v:null)
+ if empty(borderhighlight)
+ return hlgroup
+ endif
+ let highlight = type(borderhighlight) == 3 ? borderhighlight[0] : borderhighlight
+ return coc#highlight#compose_hlgroup(highlight, hlgroup)
+endfunction
diff --git a/pack/acp/start/coc.nvim/autoload/coc/helper.vim b/pack/acp/start/coc.nvim/autoload/coc/helper.vim
new file mode 100644
index 0000000..8bdc9b8
--- /dev/null
+++ b/pack/acp/start/coc.nvim/autoload/coc/helper.vim
@@ -0,0 +1,148 @@
+scriptencoding utf-8
+" Helper methods for viml
+
+function! coc#helper#get_charactor(line, col) abort
+ return strchars(strpart(a:line, 0, a:col - 1))
+endfunction
+
+function! coc#helper#last_character(line) abort
+ return strcharpart(a:line, strchars(a:line) - 1, 1)
+endfunction
+
+function! coc#helper#obj_equal(one, two) abort
+ for key in keys(a:one)
+ if a:one[key] != a:two[key]
+ return 0
+ endif
+ endfor
+ return 1
+endfunction
+
+" get change between two lines
+function! coc#helper#str_diff(curr, previous, col) abort
+ let end = strpart(a:curr, a:col - 1)
+ let start = strpart(a:curr, 0, a:col -1)
+ let endOffset = 0
+ let startOffset = 0
+ let currLen = strchars(a:curr)
+ let prevLen = strchars(a:previous)
+ if len(end)
+ let endLen = strchars(end)
+ for i in range(min([prevLen, endLen]))
+ if strcharpart(end, endLen - 1 - i, 1) ==# strcharpart(a:previous, prevLen -1 -i, 1)
+ let endOffset = endOffset + 1
+ else
+ break
+ endif
+ endfor
+ endif
+ let remain = endOffset == 0 ? a:previous : strcharpart(a:previous, 0, prevLen - endOffset)
+ if len(remain)
+ for i in range(min([strchars(remain), strchars(start)]))
+ if strcharpart(remain, i, 1) ==# strcharpart(start, i ,1)
+ let startOffset = startOffset + 1
+ else
+ break
+ endif
+ endfor
+ endif
+ return {
+ \ 'start': startOffset,
+ \ 'end': prevLen - endOffset,
+ \ 'text': strcharpart(a:curr, startOffset, currLen - startOffset - endOffset)
+ \ }
+endfunction
+
+function! coc#helper#str_apply(content, diff) abort
+ let totalLen = strchars(a:content)
+ let endLen = totalLen - a:diff['end']
+ return strcharpart(a:content, 0, a:diff['start']).a:diff['text'].strcharpart(a:content, a:diff['end'], endLen)
+endfunction
+
+" insert inserted to line at position, use ... when result is too long
+" line should only contains character has strwidth equals 1
+function! coc#helper#str_compose(line, position, inserted) abort
+ let width = strwidth(a:line)
+ let text = a:inserted
+ let res = a:line
+ let need_truncate = a:position + strwidth(text) + 1 > width
+ if need_truncate
+ let remain = width - a:position - 3
+ if remain < 2
+ " use text for full line, use first & end of a:line, ignore position
+ let res = strcharpart(a:line, 0, 1)
+ let w = strwidth(res)
+ for i in range(strchars(text))
+ let c = strcharpart(text, i, 1)
+ let a = strwidth(c)
+ if w + a <= width - 1
+ let w = w + a
+ let res = res.c
+ endif
+ endfor
+ let res = res.strcharpart(a:line, w)
+ else
+ let res = strcharpart(a:line, 0, a:position)
+ let w = strwidth(res)
+ for i in range(strchars(text))
+ let c = strcharpart(text, i, 1)
+ let a = strwidth(c)
+ if w + a <= width - 3
+ let w = w + a
+ let res = res.c
+ endif
+ endfor
+ let res = res.'..'
+ let w = w + 2
+ let res = res.strcharpart(a:line, w)
+ endif
+ else
+ let first = strcharpart(a:line, 0, a:position)
+ let res = first.text.strcharpart(a:line, a:position + strwidth(text))
+ endif
+ return res
+endfunction
+
+" Return new dict with keys removed
+function! coc#helper#dict_omit(dict, keys) abort
+ let res = {}
+ for key in keys(a:dict)
+ if index(a:keys, key) == -1
+ let res[key] = a:dict[key]
+ endif
+ endfor
+ return res
+endfunction
+
+" Return new dict with keys only
+function! coc#helper#dict_pick(dict, keys) abort
+ let res = {}
+ for key in keys(a:dict)
+ if index(a:keys, key) != -1
+ let res[key] = a:dict[key]
+ endif
+ endfor
+ return res
+endfunction
+
+" support for float values
+function! coc#helper#min(first, ...) abort
+ let val = a:first
+ for i in range(0, len(a:000) - 1)
+ if a:000[i] < val
+ let val = a:000[i]
+ endif
+ endfor
+ return val
+endfunction
+
+" support for float values
+function! coc#helper#max(first, ...) abort
+ let val = a:first
+ for i in range(0, len(a:000) - 1)
+ if a:000[i] > val
+ let val = a:000[i]
+ endif
+ endfor
+ return val
+endfunction
diff --git a/pack/acp/start/coc.nvim/autoload/coc/highlight.vim b/pack/acp/start/coc.nvim/autoload/coc/highlight.vim
new file mode 100644
index 0000000..cb52692
--- /dev/null
+++ b/pack/acp/start/coc.nvim/autoload/coc/highlight.vim
@@ -0,0 +1,734 @@
+scriptencoding utf-8
+let s:is_vim = !has('nvim')
+let s:clear_match_by_window = has('nvim-0.6.0') || has('patch-8.1.1084')
+let s:set_extmark = has('nvim') && exists('*nvim_buf_set_extmark')
+let s:prop_offset = get(g:, 'coc_text_prop_offset', 1000)
+let s:namespace_map = {}
+let s:ns_id = 1
+let s:diagnostic_hlgroups = ['CocErrorHighlight', 'CocWarningHighlight', 'CocInfoHighlight', 'CocHintHighlight', 'CocDeprecatedHighlight', 'CocUnusedHighlight']
+" Maximum count to highlight each time.
+let g:coc_highlight_maximum_count = get(g:, 'coc_highlight_maximum_count', 100)
+
+if has('nvim-0.5.0') && s:clear_match_by_window == 0
+ try
+ call getmatches(0)
+ let s:clear_match_by_window = 1
+ catch /^Vim\%((\a\+)\)\=:E118/
+ " ignored
+ endtry
+endif
+
+" Update buffer region by region.
+function! coc#highlight#buffer_update(bufnr, key, highlights, ...) abort
+ if !bufloaded(a:bufnr)
+ return
+ endif
+ if empty(a:highlights)
+ call coc#highlight#clear_highlight(a:bufnr, a:key, 0, -1)
+ return
+ endif
+ let priority = get(a:, 1, v:null)
+ let changedtick = getbufvar(a:bufnr, 'changedtick', 0)
+ if type(get(a:, 2, v:null)) == 0 && changedtick > a:2
+ return
+ endif
+ let hls = map(copy(a:highlights), "{'hlGroup':v:val[0],'lnum':v:val[1],'colStart':v:val[2],'colEnd':v:val[3],'combine':get(v:val,4,1),'start_incl':get(v:val,5,0),'end_incl':get(v:val,6,0)}")
+ if len(hls) <= g:coc_highlight_maximum_count || get(g:, 'coc_node_env', '') ==# 'test'
+ call coc#highlight#update_highlights(a:bufnr, a:key, hls, 0, -1, priority)
+ return
+ endif
+ let linecount = coc#compat#buf_line_count(a:bufnr)
+ let groups = s:group_hls(hls, linecount)
+ call s:update_highlights_timer(a:bufnr, changedtick, a:key, priority, groups, 0)
+endfunction
+
+" Update highlights by check exists highlights.
+" 0 based, end exclusive start and end
+function! coc#highlight#update_highlights(bufnr, key, highlights, ...) abort
+ let bufnr = a:bufnr == 0 ? bufnr('%') : a:bufnr
+ if !bufloaded(bufnr)
+ return
+ endif
+ let start = get(a:, 1, 0)
+ let end = get(a:, 2, -1)
+ if end == 0
+ return
+ endif
+ let linecount = coc#compat#buf_line_count(a:bufnr)
+ if end >= linecount
+ let end = -1
+ endif
+ if empty(a:highlights)
+ call coc#highlight#clear_highlight(bufnr, a:key, start, end)
+ return
+ endif
+ let priority = get(a:, 3, v:null)
+ let total = len(a:highlights)
+ " index list that exists with current highlights
+ let exists = []
+ let ns = coc#highlight#create_namespace(a:key)
+ if has('nvim-0.5.0') || exists('*prop_list')
+ let endLnum = end < 0 ? linecount - 1 : end - 1
+ let firstLnum = a:highlights[0]['lnum']
+ if firstLnum > start
+ call coc#highlight#clear_highlight(bufnr, a:key, start, firstLnum)
+ let start = firstLnum
+ endif
+ let lastLnum = a:highlights[total - 1]['lnum']
+ if lastLnum < endLnum
+ call coc#highlight#clear_highlight(bufnr, a:key, lastLnum + 1, endLnum + 1)
+ let endLnum = lastLnum
+ endif
+ let current = coc#highlight#get_highlights(bufnr, a:key, start, endLnum)
+ let currIndex = 0
+ if !empty(current)
+ for [lnum, items] in s:to_group(current)
+ let indexes = []
+ let currIndexes = range(0, len(items) - 1)
+ let removeIndexes = []
+ while currIndex != total
+ let hi = a:highlights[currIndex]
+ if hi['lnum'] == lnum
+ let findIndex = -1
+ for idx in currIndexes
+ let item = items[idx]
+ if hi['hlGroup'] ==# item[0] && hi['colStart'] == item[2] && hi['colEnd'] == item[3]
+ call add(indexes, currIndex)
+ let findIndex = idx
+ break
+ elseif item[2] > hi['colStart']
+ break
+ endif
+ endfor
+ if findIndex != -1
+ call filter(currIndexes, 'v:val != '.findIndex)
+ endif
+ elseif hi['lnum'] > lnum
+ break
+ endif
+ let currIndex = currIndex + 1
+ endwhile
+ for idx in currIndexes
+ if s:is_vim
+ call prop_remove({'bufnr': bufnr, 'id': items[idx][4]})
+ else
+ call nvim_buf_del_extmark(bufnr, ns, items[idx][4])
+ endif
+ endfor
+ call extend(exists, indexes)
+ endfor
+ endif
+ else
+ call coc#highlight#clear_highlight(bufnr, a:key, start, end)
+ endif
+ let indexes = range(0, total - 1)
+ if !empty(exists)
+ let indexes = filter(indexes, 'index(exists, v:val) == -1')
+ endif
+ for idx in indexes
+ let hi = a:highlights[idx]
+ let opts = {
+ \ 'combine': get(hi, 'combine', 0),
+ \ 'start_incl': get(hi, 'start_incl', 0),
+ \ 'end_incl': get(hi, 'end_incl', 0),
+ \ }
+ if type(priority) == 0
+ let opts['priority'] = s:get_priority(a:key, hi['hlGroup'], priority)
+ endif
+ call coc#highlight#add_highlight(bufnr, ns, hi['hlGroup'], hi['lnum'], hi['colStart'], hi['colEnd'], opts)
+ endfor
+endfunction
+
+" Get list of highlights by range or all buffer.
+" 0 based line, start_col and end_col
+" 0 based start & end line, end inclusive.
+function! coc#highlight#get_highlights(bufnr, key, ...) abort
+ if !bufloaded(a:bufnr)
+ return v:null
+ endif
+ if !has_key(s:namespace_map, a:key)
+ return []
+ endif
+ let start = get(a:, 1, 0)
+ let end = get(a:, 2, -1)
+ let res = []
+ let ns = s:namespace_map[a:key]
+ if exists('*prop_list')
+ let types = coc#api#get_types(ns)
+ if empty(types)
+ return res
+ endif
+ " Could filter by end_lnum and types
+ if has('patch-8.2.3652')
+ let endLnum = end == -1 ? -1 : end + 1
+ for prop in prop_list(start + 1, {'bufnr': a:bufnr, 'types': types, 'end_lnum': endLnum})
+ if prop['start'] == 0 || prop['end'] == 0
+ " multi line textprop are not supported, simply ignore it
+ continue
+ endif
+ let startCol = prop['col'] - 1
+ let endCol = startCol + prop['length']
+ call add(res, [s:prop_type_hlgroup(prop['type']), prop['lnum'] - 1, startCol, endCol, prop['id']])
+ endfor
+ else
+ if end == -1
+ let end = coc#compat#buf_line_count(a:bufnr)
+ else
+ let end = end + 1
+ endif
+ for line in range(start + 1, end)
+ for prop in prop_list(line, {'bufnr': a:bufnr})
+ if index(types, prop['type']) == -1 || prop['start'] == 0 || prop['end'] == 0
+ " multi line textprop are not supported, simply ignore it
+ continue
+ endif
+ let startCol = prop['col'] - 1
+ let endCol = startCol + prop['length']
+ call add(res, [s:prop_type_hlgroup(prop['type']), line - 1, startCol, endCol, prop['id']])
+ endfor
+ endfor
+ endif
+ elseif has('nvim-0.5.0')
+ let start = [start, 0]
+ let maximum = end == -1 ? nvim_buf_line_count(a:bufnr) : end + 1
+ let end = end == -1 ? -1 : [end + 1, 0]
+ let markers = nvim_buf_get_extmarks(a:bufnr, ns, start, -1, {'details': v:true})
+ for [marker_id, line, start_col, details] in markers
+ if line >= maximum
+ " Could be markers exceed end of line
+ continue
+ endif
+ let delta = details['end_row'] - line
+ if delta > 1 || (delta == 1 && details['end_col'] != 0)
+ " can't handle, single line only
+ continue
+ endif
+ let endCol = details['end_col']
+ if endCol == start_col
+ call nvim_buf_del_extmark(a:bufnr, ns, marker_id)
+ continue
+ endif
+ if delta == 1
+ let text = get(nvim_buf_get_lines(a:bufnr, line, line + 1, 0), 0, '')
+ let endCol = strlen(text)
+ endif
+ call add(res, [details['hl_group'], line, start_col, endCol, marker_id])
+ endfor
+ else
+ throw 'Get highlights requires neovim 0.5.0 or vim support prop_list'
+ endif
+ return res
+endfunction
+
+" Add multiple highlights to buffer.
+" type HighlightItem = [hlGroup, lnum, colStart, colEnd, combine?, start_incl?, end_incl?]
+function! coc#highlight#set(bufnr, key, highlights, priority) abort
+ if !bufloaded(a:bufnr)
+ return
+ endif
+ let ns = coc#highlight#create_namespace(a:key)
+ if len(a:highlights) > g:coc_highlight_maximum_count
+ call s:add_highlights_timer(a:bufnr, ns, a:highlights, a:priority)
+ else
+ call s:add_highlights(a:bufnr, ns, a:highlights, a:priority)
+ endif
+endfunction
+
+" Clear highlights by 0 based line numbers.
+function! coc#highlight#clear(bufnr, key, lnums) abort
+ if !bufloaded(a:bufnr) || empty(a:lnums)
+ return
+ endif
+ let ns = coc#highlight#create_namespace(a:key)
+ for lnum in a:lnums
+ if has('nvim')
+ call nvim_buf_clear_namespace(a:bufnr, ns, lnum, lnum + 1)
+ else
+ call coc#api#exec('buf_clear_namespace', [a:bufnr, ns, lnum, lnum + 1])
+ endif
+ endfor
+ " clear highlights in invalid line.
+ if has('nvim')
+ let linecount = nvim_buf_line_count(a:bufnr)
+ call nvim_buf_clear_namespace(a:bufnr, ns, linecount, -1)
+ endif
+endfunction
+
+function! coc#highlight#del_markers(bufnr, key, ids) abort
+ if !bufloaded(a:bufnr)
+ return
+ endif
+ let ns = coc#highlight#create_namespace(a:key)
+ for id in a:ids
+ if s:is_vim
+ call prop_remove({'bufnr': a:bufnr, 'id': id})
+ else
+ call nvim_buf_del_extmark(a:bufnr, ns, id)
+ endif
+ endfor
+endfunction
+
+" highlight LSP range,
+function! coc#highlight#ranges(bufnr, key, hlGroup, ranges, ...) abort
+ let bufnr = a:bufnr == 0 ? bufnr('%') : a:bufnr
+ if !bufloaded(bufnr) || !exists('*getbufline')
+ return
+ endif
+ let opts = get(a:, 1, {})
+ let synmaxcol = getbufvar(a:bufnr, '&synmaxcol', 1000)
+ if synmaxcol == 0
+ let synmaxcol = 1000
+ endif
+ let synmaxcol = min([synmaxcol, 1000])
+ let srcId = coc#highlight#create_namespace(a:key)
+ for range in a:ranges
+ let start = range['start']
+ let end = range['end']
+ for lnum in range(start['line'] + 1, end['line'] + 1)
+ let arr = getbufline(bufnr, lnum)
+ let line = empty(arr) ? '' : arr[0]
+ if empty(line)
+ continue
+ endif
+ if start['character'] > synmaxcol || end['character'] > synmaxcol
+ continue
+ endif
+ " TODO don't know how to count UTF16 code point, should work most cases.
+ let colStart = lnum == start['line'] + 1 ? strlen(strcharpart(line, 0, start['character'])) : 0
+ let colEnd = lnum == end['line'] + 1 ? strlen(strcharpart(line, 0, end['character'])) : strlen(line)
+ if colStart == colEnd
+ continue
+ endif
+ call coc#highlight#add_highlight(bufnr, srcId, a:hlGroup, lnum - 1, colStart, colEnd, opts)
+ endfor
+ endfor
+endfunction
+
+function! coc#highlight#add_highlight(bufnr, src_id, hl_group, line, col_start, col_end, ...) abort
+ let opts = get(a:, 1, {})
+ let priority = get(opts, 'priority', v:null)
+ if !s:is_vim
+ if s:set_extmark && a:src_id != -1
+ " get(opts, 'start_incl', 0) ? v:true : v:false,
+ try
+ call nvim_buf_set_extmark(a:bufnr, a:src_id, a:line, a:col_start, {
+ \ 'end_col': a:col_end,
+ \ 'hl_group': a:hl_group,
+ \ 'hl_mode': get(opts, 'combine', 1) ? 'combine' : 'replace',
+ \ 'right_gravity': v:true,
+ \ 'end_right_gravity': v:false,
+ \ 'priority': type(priority) == 0 ? min([priority, 4096]) : 4096,
+ \ })
+ catch /^Vim\%((\a\+)\)\=:E5555/
+ " the end_col could be invalid, ignore this error
+ endtry
+ else
+ call nvim_buf_add_highlight(a:bufnr, a:src_id, a:hl_group, a:line, a:col_start, a:col_end)
+ endif
+ else
+ call coc#api#exec('buf_add_highlight', [a:bufnr, a:src_id, a:hl_group, a:line, a:col_start, a:col_end, opts])
+ endif
+endfunction
+
+function! coc#highlight#clear_highlight(bufnr, key, start_line, end_line) abort
+ let bufnr = a:bufnr == 0 ? bufnr('%') : a:bufnr
+ if !bufloaded(bufnr)
+ return
+ endif
+ let src_id = coc#highlight#create_namespace(a:key)
+ if has('nvim')
+ call nvim_buf_clear_namespace(a:bufnr, src_id, a:start_line, a:end_line)
+ else
+ call coc#api#exec('buf_clear_namespace', [a:bufnr, src_id, a:start_line, a:end_line])
+ endif
+endfunction
+
+" highlight buffer in winid with CodeBlock &HighlightItems
+" export interface HighlightItem {
+" lnum: number // 0 based
+" hlGroup: string
+" colStart: number // 0 based
+" colEnd: number
+" }
+" export interface CodeBlock {
+" filetype?: string
+" hlGroup?: string
+" startLine: number // 0 based
+" endLine: number
+" }
+function! coc#highlight#add_highlights(winid, codes, highlights) abort
+ if get(g:, 'coc_node_env', '') ==# 'test'
+ call setwinvar(a:winid, 'highlights', a:highlights)
+ endif
+ " clear highlights
+ call coc#compat#execute(a:winid, 'syntax clear')
+ let bufnr = winbufnr(a:winid)
+ call coc#highlight#clear_highlight(bufnr, -1, 0, -1)
+ if !empty(a:codes)
+ call coc#highlight#highlight_lines(a:winid, a:codes)
+ endif
+ if !empty(a:highlights)
+ for item in a:highlights
+ let hlGroup = item['hlGroup']
+ let opts = hlGroup =~# 'Search$' ? {'priority': 999, 'combine': 1} : {}
+ call coc#highlight#add_highlight(bufnr, -1, hlGroup, item['lnum'], item['colStart'], item['colEnd'])
+ endfor
+ endif
+endfunction
+
+
+" Add highlights to line groups of winid, support hlGroup and filetype
+" config should have startLine, endLine (0 based, end excluded) and filetype or hlGroup
+" endLine should > startLine and endLine is excluded
+"
+" export interface CodeBlock {
+" filetype?: string
+" hlGroup?: string
+" startLine: number // 0 based
+" endLine: number
+" }
+function! coc#highlight#highlight_lines(winid, blocks) abort
+ let region_id = 1
+ let defined = []
+ let cmds = []
+ for config in a:blocks
+ let start = config['startLine'] + 1
+ let end = config['endLine'] == -1 ? len(getbufline(winbufnr(a:winid), 1, '$')) + 1 : config['endLine'] + 1
+ let filetype = get(config, 'filetype', '')
+ let hlGroup = get(config, 'hlGroup', '')
+ if !empty(hlGroup)
+ call add(cmds, 'syntax region '.hlGroup.' start=/\%'.start.'l/ end=/\%'.end.'l/')
+ else
+ let filetype = matchstr(filetype, '\v^\w+')
+ if empty(filetype) || filetype == 'txt' || index(get(g:, 'coc_markdown_disabled_languages', []), filetype) != -1
+ continue
+ endif
+ if index(defined, filetype) == -1
+ call add(cmds, 'syntax include @'.toupper(filetype).' syntax/'.filetype.'.vim')
+ call add(cmds, 'unlet! b:current_syntax')
+ call add(defined, filetype)
+ endif
+ call add(cmds, 'syntax region CodeBlock'.region_id.' start=/\%'.start.'l/ end=/\%'.end.'l/ contains=@'.toupper(filetype).' keepend')
+ let region_id = region_id + 1
+ endif
+ endfor
+ if !empty(cmds)
+ call coc#compat#execute(a:winid, cmds, 'silent!')
+ endif
+endfunction
+
+" Compose hlGroups with foreground and background colors.
+function! coc#highlight#compose_hlgroup(fgGroup, bgGroup) abort
+ let hlGroup = 'Fg'.a:fgGroup.'Bg'.a:bgGroup
+ if a:fgGroup ==# a:bgGroup
+ return a:fgGroup
+ endif
+ if hlexists(hlGroup) && match(execute('hi '.hlGroup, 'silent!'), 'cleared') == -1
+ return hlGroup
+ endif
+ let fgId = synIDtrans(hlID(a:fgGroup))
+ let bgId = synIDtrans(hlID(a:bgGroup))
+ let isGuiReversed = synIDattr(fgId, 'reverse', 'gui') !=# '1' || synIDattr(bgId, 'reverse', 'gui') !=# '1'
+ let guifg = isGuiReversed ? synIDattr(fgId, 'fg', 'gui') : synIDattr(fgId, 'bg', 'gui')
+ let guibg = isGuiReversed ? synIDattr(bgId, 'bg', 'gui') : synIDattr(bgId, 'fg', 'gui')
+ let isCtermReversed = synIDattr(fgId, 'reverse', 'cterm') !=# '1' || synIDattr(bgId, 'reverse', 'cterm') !=# '1'
+ let ctermfg = isCtermReversed ? synIDattr(fgId, 'fg', 'cterm') : synIDattr(fgId, 'bg', 'cterm')
+ let ctermbg = isCtermReversed ? synIDattr(bgId, 'bg', 'cterm') : synIDattr(bgId, 'fg', 'cterm')
+ let bold = synIDattr(fgId, 'bold') ==# '1'
+ let italic = synIDattr(fgId, 'italic') ==# '1'
+ let underline = synIDattr(fgId, 'underline') ==# '1'
+ let cmd = 'silent hi ' . hlGroup
+ if !empty(guifg)
+ let cmd .= ' guifg=' . guifg
+ endif
+ if !empty(ctermfg)
+ let cmd .= ' ctermfg=' . ctermfg
+ elseif guifg =~# '^#'
+ let cmd .= ' ctermfg=' . coc#color#rgb2term(strpart(guifg, 1))
+ endif
+ if !empty(guibg)
+ let cmd .= ' guibg=' . guibg
+ endif
+ if !empty(ctermbg)
+ let cmd .= ' ctermbg=' . ctermbg
+ elseif guibg =~# '^#'
+ let cmd .= ' ctermbg=' . coc#color#rgb2term(strpart(guibg, 1))
+ endif
+ if bold
+ let cmd .= ' cterm=bold gui=bold'
+ elseif italic
+ let cmd .= ' cterm=italic gui=italic'
+ elseif underline
+ let cmd .= ' cterm=underline gui=underline'
+ endif
+ if cmd ==# 'silent hi ' . hlGroup
+ return 'Normal'
+ endif
+ execute cmd
+ return hlGroup
+endfunction
+
+" add matches for winid, use 0 for current window.
+function! coc#highlight#match_ranges(winid, bufnr, ranges, hlGroup, priority) abort
+ let winid = a:winid == 0 ? win_getid() : a:winid
+ let bufnr = a:bufnr == 0 ? winbufnr(winid) : a:bufnr
+ if empty(getwininfo(winid)) || (a:bufnr != 0 && winbufnr(a:winid) != a:bufnr)
+ " not valid
+ return []
+ endif
+ if !s:clear_match_by_window
+ let curr = win_getid()
+ if has('nvim')
+ noa call nvim_set_current_win(winid)
+ else
+ noa call win_gotoid(winid)
+ endif
+ endif
+ let ids = []
+ for range in a:ranges
+ let pos = []
+ let start = range['start']
+ let end = range['end']
+ for lnum in range(start['line'] + 1, end['line'] + 1)
+ let arr = getbufline(bufnr, lnum)
+ let line = empty(arr) ? '' : arr[0]
+ if empty(line)
+ continue
+ endif
+ let colStart = lnum == start['line'] + 1 ? strlen(strcharpart(line, 0, start['character'])) + 1 : 1
+ let colEnd = lnum == end['line'] + 1 ? strlen(strcharpart(line, 0, end['character'])) + 1 : strlen(line) + 1
+ if colStart == colEnd
+ continue
+ endif
+ call add(pos, [lnum, colStart, colEnd - colStart])
+ endfor
+ if !empty(pos)
+ let opts = s:clear_match_by_window ? {'window': a:winid} : {}
+ let i = 1
+ let l = []
+ for p in pos
+ call add(l, p)
+ if i % 8 == 0
+ let id = matchaddpos(a:hlGroup, l, a:priority, -1, opts)
+ call add(ids, id)
+ let l = []
+ endif
+ let i += 1
+ endfor
+ if !empty(l)
+ let id = matchaddpos(a:hlGroup, l, a:priority, -1, opts)
+ call add(ids, id)
+ endif
+ endif
+ endfor
+ if !s:clear_match_by_window
+ if has('nvim')
+ noa call nvim_set_current_win(curr)
+ else
+ noa call win_gotoid(curr)
+ endif
+ endif
+ return ids
+endfunction
+
+" Clear matches by hlGroup regexp.
+function! coc#highlight#clear_match_group(winid, match) abort
+ let winid = a:winid == 0 ? win_getid() : a:winid
+ if empty(getwininfo(winid))
+ " not valid
+ return
+ endif
+ if s:clear_match_by_window
+ let arr = filter(getmatches(winid), 'v:val["group"] =~# "'.a:match.'"')
+ for item in arr
+ call matchdelete(item['id'], winid)
+ endfor
+ else
+ let curr = win_getid()
+ let switch = exists('*nvim_set_current_win') && curr != winid
+ if switch
+ noa call nvim_set_current_win(a:winid)
+ endif
+ if win_getid() == winid
+ let arr = filter(getmatches(), 'v:val["group"] =~# "'.a:match.'"')
+ for item in arr
+ call matchdelete(item['id'])
+ endfor
+ endif
+ if switch
+ noa call nvim_set_current_win(curr)
+ endif
+ endif
+endfunction
+
+" Clear matches by match ids, use 0 for current win.
+function! coc#highlight#clear_matches(winid, ids)
+ let winid = a:winid == 0 ? win_getid() : a:winid
+ if empty(getwininfo(winid))
+ " not valid
+ return
+ endif
+ if s:clear_match_by_window
+ for id in a:ids
+ try
+ call matchdelete(id, winid)
+ catch /^Vim\%((\a\+)\)\=:E803/
+ " ignore
+ endtry
+ endfor
+ else
+ let curr = win_getid()
+ let switch = exists('*nvim_set_current_win') && curr != winid
+ if switch
+ noa call nvim_set_current_win(a:winid)
+ endif
+ if win_getid() == winid
+ for id in a:ids
+ try
+ call matchdelete(id)
+ catch /^Vim\%((\a\+)\)\=:E803/
+ " ignore
+ endtry
+ endfor
+ endif
+ if switch
+ noa call nvim_set_current_win(curr)
+ endif
+ endif
+endfunction
+
+function! coc#highlight#clear_all() abort
+ for src_id in values(s:namespace_map)
+ for bufnr in map(getbufinfo({'bufloaded': 1}), 'v:val["bufnr"]')
+ if has('nvim')
+ call nvim_buf_clear_namespace(bufnr, src_id, 0, -1)
+ else
+ call coc#api#exec('buf_clear_namespace', [bufnr, src_id, 0, -1])
+ endif
+ endfor
+ endfor
+endfunction
+
+function! coc#highlight#create_namespace(key) abort
+ if type(a:key) == 0
+ return a:key
+ endif
+ if has_key(s:namespace_map, a:key)
+ return s:namespace_map[a:key]
+ endif
+ if has('nvim')
+ let s:namespace_map[a:key] = nvim_create_namespace('coc-'.a:key)
+ else
+ let s:namespace_map[a:key] = s:ns_id
+ let s:ns_id = s:ns_id + 1
+ endif
+ return s:namespace_map[a:key]
+endfunction
+
+function! coc#highlight#get_syntax_name(lnum, col)
+ return synIDattr(synIDtrans(synID(a:lnum,a:col,1)),"name")
+endfunction
+
+function! s:prop_type_hlgroup(type) abort
+ return substitute(a:type, '_\d\+$', '', '')
+endfunction
+
+function! s:update_highlights_timer(bufnr, changedtick, key, priority, groups, idx) abort
+ if getbufvar(a:bufnr, 'changedtick', 0) != a:changedtick
+ return
+ endif
+ let group = get(a:groups, a:idx, v:null)
+ if empty(group)
+ return
+ endif
+ if empty(group['highlights'])
+ call coc#highlight#clear_highlight(a:bufnr, a:key, group['start'], group['end'])
+ else
+ call coc#highlight#update_highlights(a:bufnr, a:key, group['highlights'], group['start'], group['end'], a:priority)
+ endif
+ if a:idx < len(a:groups) - 1
+ call timer_start(50, { -> s:update_highlights_timer(a:bufnr, a:changedtick, a:key, a:priority, a:groups, a:idx + 1)})
+ endif
+endfunction
+
+function! s:add_highlights_timer(bufnr, ns, highlights, priority) abort
+ let hls = []
+ let next = []
+ for i in range(0, len(a:highlights) - 1)
+ if i < g:coc_highlight_maximum_count
+ call add(hls, a:highlights[i])
+ else
+ call add(next, a:highlights[i])
+ endif
+ endfor
+ call s:add_highlights(a:bufnr, a:ns, hls, a:priority)
+ if len(next)
+ call timer_start(30, {->s:add_highlights_timer(a:bufnr, a:ns, next, a:priority)})
+ endif
+endfunction
+
+function! s:add_highlights(bufnr, ns, highlights, priority) abort
+ for item in a:highlights
+ let opts = {
+ \ 'priority': a:priority,
+ \ 'combine': get(item, 4, 1) ? 1 : 0,
+ \ 'start_incl': get(item, 5, 0) ? 1 : 0,
+ \ 'end_incl': get(item, 6, 0) ? 1 : 0,
+ \ }
+ call coc#highlight#add_highlight(a:bufnr, a:ns, item[0], item[1], item[2], item[3], opts)
+ endfor
+endfunction
+
+function! s:to_group(items) abort
+ let res = []
+ let before = v:null
+ for item in a:items
+ if empty(before) || before[0] != item[1]
+ let before = [item[1], [item]]
+ call add(res, before)
+ else
+ call add(before[1], item)
+ endif
+ endfor
+ return res
+endfunction
+
+function! s:get_priority(key, hlGroup, priority) abort
+ if a:hlGroup ==# 'CocSearch'
+ return 999
+ endif
+ if strpart(a:key, 0, 10) !=# 'diagnostic'
+ return a:priority
+ endif
+ return a:priority - index(s:diagnostic_hlgroups, a:hlGroup)
+endfunction
+
+function! s:group_hls(hls, linecount) abort
+ " start, end, highlights
+ let groups = []
+ if empty(a:hls)
+ call add(groups, {'start': 0, 'end': a:linecount, 'highlights': []})
+ return groups
+ endif
+ let start = 0
+ let highlights = []
+ let lastLnum = -1
+ for item in a:hls
+ let lnum = item['lnum']
+ if lnum >= a:linecount
+ break
+ endif
+ if len(highlights) < g:coc_highlight_maximum_count || lnum == lastLnum
+ call add(highlights, item)
+ let lastLnum = lnum
+ else
+ call add(groups, {'start': start, 'end': lastLnum + 1, 'highlights': highlights})
+ let highlights = []
+ let start = lastLnum + 1
+ call add(highlights, item)
+ let lastLnum = lnum
+ endif
+ endfor
+ call add(groups, {'start': start, 'end': a:linecount, 'highlights': highlights})
+ return groups
+endfunction
diff --git a/pack/acp/start/coc.nvim/autoload/coc/list.vim b/pack/acp/start/coc.nvim/autoload/coc/list.vim
new file mode 100644
index 0000000..ec01d1b
--- /dev/null
+++ b/pack/acp/start/coc.nvim/autoload/coc/list.vim
@@ -0,0 +1,303 @@
+scriptencoding utf-8
+let s:is_vim = !has('nvim')
+let s:prefix = '[List Preview]'
+let s:sign_group = 'CocList'
+" filetype detect could be slow.
+let s:filetype_map = {
+ \ 'c': 'c',
+ \ 'py': 'python',
+ \ 'vim': 'vim',
+ \ 'ts': 'typescript',
+ \ 'js': 'javascript',
+ \ 'html': 'html',
+ \ 'css': 'css'
+ \ }
+
+function! coc#list#getchar() abort
+ return coc#prompt#getchar()
+endfunction
+
+function! coc#list#setlines(bufnr, lines, append)
+ if a:append
+ silent call appendbufline(a:bufnr, '$', a:lines)
+ else
+ if exists('*deletebufline')
+ silent call deletebufline(a:bufnr, len(a:lines) + 1, '$')
+ else
+ let n = len(a:lines) + 1
+ let saved_reg = @"
+ silent execute n.',$d'
+ let @" = saved_reg
+ endif
+ silent call setbufline(a:bufnr, 1, a:lines)
+ endif
+endfunction
+
+function! coc#list#options(...)
+ let list = ['--top', '--tab', '--normal', '--no-sort', '--input', '--strict',
+ \ '--regex', '--interactive', '--number-select', '--auto-preview',
+ \ '--ignore-case', '--no-quit', '--first', '--reverse']
+ if get(g:, 'coc_enabled', 0)
+ let names = coc#rpc#request('listNames', [])
+ call extend(list, names)
+ endif
+ return join(list, "\n")
+endfunction
+
+function! coc#list#names(...) abort
+ let names = coc#rpc#request('listNames', [])
+ return join(names, "\n")
+endfunction
+
+function! coc#list#status(name)
+ if !exists('b:list_status') | return '' | endif
+ return get(b:list_status, a:name, '')
+endfunction
+
+function! coc#list#create(position, height, name, numberSelect)
+ if a:position ==# 'tab'
+ execute 'silent tabe list:///'.a:name
+ else
+ execute 'silent keepalt '.(a:position ==# 'top' ? '' : 'botright').a:height.'sp list:///'.a:name
+ execute 'resize '.a:height
+ endif
+ if a:numberSelect
+ setl norelativenumber
+ setl number
+ else
+ setl nonumber
+ setl norelativenumber
+ endif
+ return [bufnr('%'), win_getid(), tabpagenr()]
+endfunction
+
+" close list windows
+function! coc#list#clean_up() abort
+ for i in range(1, winnr('$'))
+ let bufname = bufname(winbufnr(i))
+ if bufname =~# 'list://'
+ execute i.'close!'
+ endif
+ endfor
+endfunction
+
+function! coc#list#setup(source)
+ let b:list_status = {}
+ setl buftype=nofile nobuflisted nofen nowrap
+ setl norelativenumber bufhidden=wipe nocursorline winfixheight
+ setl tabstop=1 nolist nocursorcolumn undolevels=-1
+ setl signcolumn=auto
+ if has('nvim-0.5.0') || has('patch-8.1.0864')
+ setl scrolloff=0
+ endif
+ setl filetype=list
+ syntax case ignore
+ let source = a:source[8:]
+ let name = toupper(source[0]).source[1:]
+ execute 'syntax match Coc'.name.'Line /\v^.*$/'
+ if !s:is_vim
+ " Repeat press and would invoke on vim
+ nnoremap c
+ endif
+endfunction
+
+function! coc#list#select(bufnr, line) abort
+ call sign_unplace(s:sign_group, { 'buffer': a:bufnr })
+ if a:line > 0
+ call sign_place(6, s:sign_group, 'CocListCurrent', a:bufnr, {'lnum': a:line})
+ endif
+endfunction
+
+" Check if previewwindow exists on current tab.
+function! coc#list#has_preview()
+ for i in range(1, winnr('$'))
+ let preview = getwinvar(i, 'previewwindow', getwinvar(i, '&previewwindow', 0))
+ if preview
+ return i
+ endif
+ endfor
+ return 0
+endfunction
+
+" Get previewwindow from tabnr, use 0 for current tab
+function! coc#list#get_preview(...) abort
+ let tabnr = get(a:, 1, 0) == 0 ? tabpagenr() : a:1
+ let info = gettabinfo(tabnr)
+ if !empty(info)
+ for win in info[0]['windows']
+ if gettabwinvar(tabnr, win, 'previewwindow', 0)
+ return win
+ endif
+ endfor
+ endif
+ return -1
+endfunction
+
+function! coc#list#scroll_preview(dir) abort
+ let winnr = coc#list#has_preview()
+ if !winnr
+ return
+ endif
+ let winid = win_getid(winnr)
+ if exists('*win_execute')
+ call win_execute(winid, "normal! ".(a:dir ==# 'up' ? "\" : "\"))
+ else
+ let id = win_getid()
+ noa call win_gotoid(winid)
+ execute "normal! ".(a:dir ==# 'up' ? "\" : "\")
+ noa call win_gotoid(id)
+ endif
+endfunction
+
+function! coc#list#close_preview(tabnr) abort
+ let winid = coc#list#get_preview(a:tabnr)
+ if winid != -1
+ call coc#window#close(winid)
+ endif
+endfunction
+
+" Improve preview performance by reused window & buffer.
+" lines - list of lines
+" config.position - could be 'below' 'top' 'tab'.
+" config.winid - id of original window.
+" config.name - (optional )name of preview buffer.
+" config.splitRight - (optional) split to right when 1.
+" config.lnum - (optional) current line number
+" config.filetype - (optional) filetype of lines.
+" config.hlGroup - (optional) highlight group.
+" config.maxHeight - (optional) max height of window, valid for 'below' & 'top' position.
+function! coc#list#preview(lines, config) abort
+ let name = fnamemodify(get(a:config, 'name', ''), ':.')
+ let lines = a:lines
+ if empty(lines)
+ if get(a:config, 'scheme', 'file') != 'file'
+ let bufnr = s:load_buffer(name)
+ let lines = bufnr == 0 ? [''] : getbufline(bufnr, 1, '$')
+ else
+ " Show empty lines so not close window.
+ let lines = ['']
+ endif
+ endif
+ let winid = coc#list#get_preview(0)
+ let bufnr = winid == -1 ? 0 : winbufnr(winid)
+ " Try reuse buffer & window
+ let bufnr = coc#float#create_buf(bufnr, lines)
+ if bufnr == 0
+ return
+ endif
+ call setbufvar(bufnr, '&synmaxcol', 500)
+ let filetype = get(a:config, 'filetype', '')
+ let extname = matchstr(name, '\.\zs[^.]\+$')
+ if empty(filetype) && !empty(extname)
+ let filetype = get(s:filetype_map, extname, '')
+ endif
+ let range = get(a:config, 'range', v:null)
+ let hlGroup = get(a:config, 'hlGroup', 'Search')
+ let lnum = get(a:config, 'lnum', 1)
+ let position = get(a:config, 'position', 'below')
+ let original = get(a:config, 'winid', -1)
+ if winid == -1
+ let change = position != 'tab' && get(a:config, 'splitRight', 0)
+ let curr = win_getid()
+ if change
+ if original && win_id2win(original)
+ noa call win_gotoid(original)
+ else
+ noa wincmd t
+ endif
+ execute 'noa belowright vert sb '.bufnr
+ let winid = win_getid()
+ elseif position == 'tab' || get(a:config, 'splitRight', 0)
+ execute 'noa belowright vert sb '.bufnr
+ let winid = win_getid()
+ else
+ let mod = position == 'top' ? 'below' : 'above'
+ let height = s:get_height(lines, a:config)
+ execute 'noa '.mod.' sb +resize\ '.height.' '.bufnr
+ let winid = win_getid()
+ endif
+ noa call winrestview({"lnum": lnum ,"topline":s:get_topline(a:config, lnum, winid)})
+ call s:set_preview_options(winid)
+ noa call win_gotoid(curr)
+ else
+ let height = s:get_height(lines, a:config)
+ if height > 0
+ if s:is_vim
+ let curr = win_getid()
+ noa call win_gotoid(winid)
+ execute 'silent! noa resize '.height
+ noa call win_gotoid(curr)
+ else
+ call nvim_win_set_height(winid, height)
+ endif
+ endif
+ call coc#compat#execute(winid, ['syntax clear', 'noa call winrestview({"lnum":'.lnum.',"topline":'.s:get_topline(a:config, lnum, winid).'})'])
+ endif
+ call setwinvar(winid, '&foldenable', 0)
+ if s:prefix.' '.name != bufname(bufnr)
+ if s:is_vim
+ call win_execute(winid, 'noa file '.fnameescape(s:prefix.' '.name), 'silent!')
+ else
+ silent! noa call nvim_buf_set_name(bufnr, s:prefix.' '.name)
+ endif
+ endif
+ " highlights
+ if !empty(filetype)
+ let start = max([0, lnum - 300])
+ let end = min([len(lines), lnum + 300])
+ call coc#highlight#highlight_lines(winid, [{'filetype': filetype, 'startLine': start, 'endLine': end}])
+ call coc#compat#execute(winid, 'syn sync fromstart')
+ else
+ call coc#compat#execute(winid, 'filetype detect')
+ let ft = getbufvar(bufnr, '&filetype', '')
+ if !empty(extname) && !empty(ft)
+ let s:filetype_map[extname] = ft
+ endif
+ endif
+ call sign_unplace('CocCursorLine', {'buffer': bufnr})
+ call coc#compat#execute(winid, 'call clearmatches()')
+ if !s:is_vim
+ " vim send to buffer on FocusLost, and other cases
+ call coc#compat#execute(winid, 'nnoremap