25 changed files with 19043 additions and 0 deletions
@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
|
||||
Copyright 2018-2018 by Qiming Zhao <chemzqm@gmail.com>aaa |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
@ -0,0 +1,587 @@
@@ -0,0 +1,587 @@
|
||||
" ============================================================================ |
||||
" Description: Client api used by vim8 |
||||
" Author: Qiming Zhao <chemzqm@gmail.com> |
||||
" Licence: MIT licence |
||||
" Last Modified: Nov 11, 2020 |
||||
" ============================================================================ |
||||
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 = {} |
||||
|
||||
" helper {{ |
||||
function! s:buf_line_count(bufnr) abort |
||||
if bufnr('%') == a:bufnr |
||||
return line('$') |
||||
endif |
||||
if exists('*getbufline') |
||||
let lines = getbufline(a:bufnr, 1, '$') |
||||
return len(lines) |
||||
endif |
||||
let curr = bufnr('%') |
||||
execute 'buffer '.a:bufnr |
||||
let n = line('$') |
||||
execute 'buffer '.curr |
||||
return n |
||||
endfunction |
||||
|
||||
function! s:execute(cmd) |
||||
if a:cmd =~# '^echo' |
||||
execute a:cmd |
||||
else |
||||
silent! execute a:cmd |
||||
endif |
||||
endfunction |
||||
" }}" |
||||
|
||||
" nvim client methods {{ |
||||
function! s:funcs.set_current_dir(dir) abort |
||||
execute 'cd '.a:dir |
||||
endfunction |
||||
|
||||
function! s:funcs.set_var(name, value) abort |
||||
execute 'let g:'.a:name.'= a:value' |
||||
endfunction |
||||
|
||||
function! s:funcs.del_var(name) abort |
||||
execute 'unlet g:'.a:name |
||||
endfunction |
||||
|
||||
function! s:funcs.set_option(name, value) abort |
||||
execute 'let &'.a:name.' = a:value' |
||||
endfunction |
||||
|
||||
function! s:funcs.set_current_buf(bufnr) abort |
||||
if !bufexists(a:bufnr) | return | endif |
||||
execute 'buffer '.a:bufnr |
||||
endfunction |
||||
|
||||
function! s:funcs.set_current_win(win_id) abort |
||||
let [tabnr, winnr] = win_id2tabwin(a:win_id) |
||||
if tabnr == 0 | return | endif |
||||
execute 'normal! '.tabnr.'gt' |
||||
execute winnr.' wincmd w' |
||||
endfunction |
||||
|
||||
function! s:funcs.set_current_tabpage(tabnr) abort |
||||
execute 'normal! '.a:tabnr.'gt' |
||||
endfunction |
||||
|
||||
function! s:funcs.list_wins() abort |
||||
return map(getwininfo(), 'v:val["winid"]') |
||||
endfunction |
||||
|
||||
function! s:funcs.call_atomic(calls) |
||||
let res = [] |
||||
for [key, arglist] in a:calls |
||||
let name = key[5:] |
||||
try |
||||
call add(res, call(s:funcs[name], arglist)) |
||||
catch /.*/ |
||||
return [res, v:exception] |
||||
endtry |
||||
endfor |
||||
return [res, v:null] |
||||
endfunction |
||||
|
||||
function! s:funcs.set_client_info(...) abort |
||||
endfunction |
||||
|
||||
function! s:funcs.subscribe(...) abort |
||||
endfunction |
||||
|
||||
function! s:funcs.unsubscribe(...) abort |
||||
endfunction |
||||
|
||||
function! s:funcs.call_function(method, args) abort |
||||
return call(a:method, a:args) |
||||
endfunction |
||||
|
||||
function! s:funcs.call_dict_function(dict, method, args) abort |
||||
return call(a:method, a:args, a:dict) |
||||
endfunction |
||||
|
||||
function! s:funcs.command(command) abort |
||||
" command that could cause cursor vanish |
||||
if a:command =~# '^echo' || a:command =~# '^redraw' || a:command =~# '^sign place' |
||||
call timer_start(0, {-> s:execute(a:command)}) |
||||
else |
||||
execute a:command |
||||
endif |
||||
endfunction |
||||
|
||||
function! s:funcs.eval(expr) abort |
||||
return eval(a:expr) |
||||
endfunction |
||||
|
||||
function! s:funcs.get_api_info() |
||||
let names = coc#api#func_names() |
||||
return [1, {'functions': map(names, '{"name": "nvim_".v:val}')}] |
||||
endfunction |
||||
|
||||
function! s:funcs.list_bufs() |
||||
return map(getbufinfo({'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 split(&runtimepath, ',') |
||||
endfunction |
||||
|
||||
function! s:funcs.command_output(cmd) |
||||
return execute(a:cmd) |
||||
endfunction |
||||
|
||||
function! s:funcs.get_current_line() |
||||
return getline('.') |
||||
endfunction |
||||
|
||||
function! s:funcs.set_current_line(line) |
||||
call setline('.', a:line) |
||||
endfunction |
||||
|
||||
function! s:funcs.del_current_line(line) |
||||
execute 'normal! dd' |
||||
endfunction |
||||
|
||||
function! s:funcs.get_var(var) |
||||
return get(g:, a:var, v:null) |
||||
endfunction |
||||
|
||||
function! s:funcs.get_vvar(var) |
||||
return get(v:, a:var, v:null) |
||||
endfunction |
||||
|
||||
function! s:funcs.get_option(name) |
||||
return eval('&'.a:name) |
||||
endfunction |
||||
|
||||
function! s:funcs.get_current_buf() |
||||
return bufnr('%') |
||||
endfunction |
||||
|
||||
function! s:funcs.get_current_win() |
||||
return win_getid() |
||||
endfunction |
||||
|
||||
function! s:funcs.get_current_tabpage() |
||||
return tabpagenr() |
||||
endfunction |
||||
|
||||
function! s:funcs.list_tabpages() |
||||
return range(1, tabpagenr('$')) |
||||
endfunction |
||||
|
||||
function! s:funcs.get_mode() |
||||
return {'blocking': v:false, 'mode': mode()} |
||||
endfunction |
||||
|
||||
function! s:funcs.strwidth(str) |
||||
return strwidth(a:str) |
||||
endfunction |
||||
|
||||
function! s:funcs.out_write(str) |
||||
echon a:str |
||||
endfunction |
||||
|
||||
function! s:funcs.err_write(str) |
||||
echoerr a:str |
||||
endfunction |
||||
|
||||
function! s:funcs.err_writeln(str) |
||||
echoerr a:str |
||||
endfunction |
||||
|
||||
function! s:funcs.create_namespace(name) abort |
||||
if empty(a:name) |
||||
let id = s:namespace_id |
||||
let s:namespace_id = s:namespace_id + 1 |
||||
return id |
||||
endif |
||||
let id = get(s:namespace_cache, a:name, 0) |
||||
if !id |
||||
let id = s:namespace_id |
||||
let s:namespace_id = s:namespace_id + 1 |
||||
let s:namespace_cache[a:name] = id |
||||
endif |
||||
return id |
||||
endfunction |
||||
" }} |
||||
|
||||
" buffer methods {{ |
||||
function! s:funcs.buf_set_option(bufnr, name, val) |
||||
let val = a:val |
||||
if val is v:true |
||||
let val = 1 |
||||
elseif val is v:false |
||||
let val = 0 |
||||
endif |
||||
return setbufvar(a:bufnr, '&'.a:name, val) |
||||
endfunction |
||||
|
||||
function! s:funcs.buf_get_changedtick(bufnr) |
||||
return getbufvar(a:bufnr, 'changedtick') |
||||
endfunction |
||||
|
||||
function! s:funcs.buf_is_valid(bufnr) |
||||
return bufloaded(a:bufnr) ? v:true : v:false |
||||
endfunction |
||||
|
||||
function! s:funcs.buf_get_mark(bufnr, name) |
||||
let nr = bufnr('%') |
||||
if a:bufnr != 0 || a:bufnr != nr |
||||
throw 'buf_get_mark support current buffer only' |
||||
endif |
||||
return [line("'" . a:name), col("'" . a:name)] |
||||
endfunction |
||||
|
||||
function! s:funcs.buf_add_highlight(bufnr, srcId, hlGroup, line, colStart, colEnd) abort |
||||
if !has('textprop') || !has('patch-8.1.1719') |
||||
return |
||||
endif |
||||
let bufnr = a:bufnr == 0 ? bufnr('%') : a:bufnr |
||||
let type = 'CocHighlight'.a:hlGroup |
||||
if empty(prop_type_get(type)) |
||||
call prop_type_add(type, {'highlight': a:hlGroup, 'combine': 1}) |
||||
endif |
||||
let total = strlen(getbufline(bufnr, a:line + 1)[0]) |
||||
let end = a:colEnd |
||||
if end == -1 |
||||
let end = total |
||||
else |
||||
let end = min([end, total]) |
||||
endif |
||||
if end <= a:colStart |
||||
return |
||||
endif |
||||
let srcId = a:srcId |
||||
if srcId == 0 |
||||
while v:true |
||||
let srcId = srcId + 1 |
||||
if empty(prop_find({'id': s:prop_offset + srcId, 'lnum' : 1})) |
||||
break |
||||
endif |
||||
endwhile |
||||
" generate srcId |
||||
endif |
||||
let id = srcId == -1 ? 0 : s:prop_offset + srcId |
||||
try |
||||
call prop_add(a:line + 1, a:colStart + 1, {'length': end - a:colStart, 'bufnr': bufnr, 'type': type, 'id': id}) |
||||
catch /^Vim\%((\a\+)\)\=:E967/ |
||||
" ignore 967 |
||||
endtry |
||||
let g:i = srcId |
||||
if a:srcId == 0 |
||||
" return generated srcId |
||||
return srcId |
||||
endif |
||||
endfunction |
||||
|
||||
function! s:funcs.buf_clear_namespace(bufnr, srcId, startLine, endLine) abort |
||||
if !has('textprop') || !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 + 1 |
||||
if a:srcId == -1 |
||||
call prop_clear(start, end, {'bufnr' : bufnr}) |
||||
else |
||||
try |
||||
call prop_remove({'bufnr': bufnr, 'all': 1, 'id': s:prop_offset + a:srcId}, start, end) |
||||
catch /^Vim\%((\a\+)\)\=:E968/ |
||||
" ignore 968 |
||||
endtry |
||||
endif |
||||
endfunction |
||||
|
||||
function! s:funcs.buf_line_count(bufnr) abort |
||||
return s:buf_line_count(a:bufnr) |
||||
endfunction |
||||
|
||||
function! s:funcs.buf_attach(...) |
||||
" not supported |
||||
return 1 |
||||
endfunction |
||||
|
||||
function! s:funcs.buf_detach() |
||||
" not supported |
||||
return 1 |
||||
endfunction |
||||
|
||||
function! s:funcs.buf_get_lines(bufnr, start, end, strict) abort |
||||
let lines = getbufline(a:bufnr, 1, '$') |
||||
let start = a:start < 0 ? a:start + 1 : a:start |
||||
let end = a:end < 0 ? a:end + 1 : a:end |
||||
if a:strict && end > len(lines) |
||||
throw 'line number out of range: '. end |
||||
endif |
||||
return lines[start : end - 1] |
||||
endfunction |
||||
|
||||
function! s:funcs.buf_set_lines(bufnr, start, end, strict, ...) abort |
||||
if !bufloaded(a:bufnr) |
||||
return |
||||
endif |
||||
let replacement = get(a:, 1, []) |
||||
let lineCount = s:buf_line_count(a:bufnr) |
||||
let startLnum = a:start >= 0 ? a:start + 1 : lineCount + a:start + 1 |
||||
let end = a:end >= 0 ? a:end : lineCount + a:end + 1 |
||||
if end == lineCount + 1 |
||||
let end = lineCount |
||||
endif |
||||
let delCount = end - (startLnum - 1) |
||||
let changeBuffer = 0 |
||||
let curr = bufnr('%') |
||||
if a:bufnr != curr && !exists('*setbufline') |
||||
let changeBuffer = 1 |
||||
exe 'buffer '.a:bufnr |
||||
endif |
||||
if a:bufnr == curr || changeBuffer |
||||
" replace |
||||
let storeView = winsaveview() |
||||
if delCount == len(replacement) |
||||
call setline(startLnum, replacement) |
||||
else |
||||
if len(replacement) |
||||
call append(startLnum - 1, replacement) |
||||
endif |
||||
if delCount |
||||
let start = startLnum + len(replacement) |
||||
let saved_reg = @" |
||||
silent execute start . ','.(start + delCount - 1).'d' |
||||
let @" = saved_reg |
||||
endif |
||||
endif |
||||
call winrestview(storeView) |
||||
if changeBuffer |
||||
exe 'buffer '.curr |
||||
endif |
||||
elseif exists('*setbufline') |
||||
" replace |
||||
if delCount == len(replacement) |
||||
" 8.0.1039 |
||||
call setbufline(a:bufnr, startLnum, replacement) |
||||
else |
||||
if len(replacement) |
||||
" 8.10037 |
||||
call appendbufline(a:bufnr, startLnum - 1, replacement) |
||||
endif |
||||
if delCount |
||||
let start = startLnum + len(replacement) |
||||
"8.1.0039 |
||||
silent call deletebufline(a:bufnr, start, start + delCount - 1) |
||||
endif |
||||
endif |
||||
endif |
||||
endfunction |
||||
|
||||
function! s:funcs.buf_set_name(bufnr, name) abort |
||||
let nr = bufnr('%') |
||||
if a:bufnr != nr |
||||
throw 'buf_set_name support current buffer only' |
||||
else |
||||
execute '0f' |
||||
execute 'file '.fnameescape(a:name) |
||||
endif |
||||
endfunction |
||||
|
||||
function! s:funcs.buf_get_var(bufnr, name) |
||||
return getbufvar(a:bufnr, a:name) |
||||
endfunction |
||||
|
||||
function! s:funcs.buf_set_var(bufnr, name, val) |
||||
if !bufloaded(a:bufnr) | return | endif |
||||
call setbufvar(a:bufnr, a:name, a:val) |
||||
endfunction |
||||
|
||||
function! s:funcs.buf_del_var(bufnr, name) |
||||
call setbufvar(a:bufnr, a:name, v:null) |
||||
endfunction |
||||
|
||||
function! s:funcs.buf_get_option(bufnr, name) |
||||
return getbufvar(a:bufnr, '&'.a:name) |
||||
endfunction |
||||
|
||||
function! s:funcs.buf_get_name(bufnr) |
||||
return bufname(a:bufnr) |
||||
endfunction |
||||
" }} |
||||
|
||||
" window methods {{ |
||||
function! s:funcs.win_get_buf(winid) |
||||
return winbufnr(a:winid) |
||||
endfunction |
||||
|
||||
function! s:funcs.win_get_position(win_id) abort |
||||
let [row, col] = win_screenpos(a:win_id) |
||||
if row == 0 && col == 0 |
||||
throw 'Invalid window '.a:win_id |
||||
endif |
||||
return [row - 1, col - 1] |
||||
endfunction |
||||
|
||||
function! s:funcs.win_get_height(win_id) abort |
||||
return winheight(a:win_id) |
||||
endfunction |
||||
|
||||
function! s:funcs.win_get_width(win_id) abort |
||||
return winwidth(a:win_id) |
||||
endfunction |
||||
|
||||
if exists('*win_execute') |
||||
function! s:win_execute(win_id, cmd, ...) abort |
||||
let ref = get(a:000, 0, v:null) |
||||
let cmd = ref is v:null ? a:cmd : 'let ref["out"] = ' . a:cmd |
||||
call win_execute(a:win_id, cmd) |
||||
endfunction |
||||
else |
||||
function! s:win_execute(win_id, cmd, ...) abort |
||||
let ref = get(a:000, 0, v:null) |
||||
let cmd = ref is v:null ? a:cmd : 'let ref["out"] = ' . a:cmd |
||||
let winid = win_getid() |
||||
if winid == a:win_id |
||||
execute cmd |
||||
else |
||||
let goto_status = win_gotoid(a:win_id) |
||||
if !goto_status |
||||
return |
||||
endif |
||||
execute cmd |
||||
call win_gotoid(winid) |
||||
endif |
||||
endfunction |
||||
endif |
||||
|
||||
function! s:funcs.win_get_cursor(win_id) abort |
||||
let ref = {} |
||||
call s:win_execute(a:win_id, "[line('.'), col('.')-1]", ref) |
||||
return ref['out'] |
||||
endfunction |
||||
|
||||
function! s:funcs.win_get_var(win_id, name) abort |
||||
return gettabwinvar(0, a:win_id, a:name) |
||||
endfunction |
||||
|
||||
function! s:funcs.win_set_width(win_id, width) abort |
||||
return s:win_execute(a:win_id, 'vertical resize '.a:width) |
||||
endfunction |
||||
|
||||
function! s:funcs.win_set_buf(win_id, buf_id) abort |
||||
return s:win_execute(a:win_id, 'buffer '.a:buf_id) |
||||
endfunction |
||||
|
||||
function! s:funcs.win_get_option(win_id, name) abort |
||||
return gettabwinvar(0, a:win_id, '&'.a:name) |
||||
endfunction |
||||
|
||||
function! s:funcs.win_set_height(win_id, height) abort |
||||
return s:win_execute(a:win_id, 'resize '.a:height) |
||||
endfunction |
||||
|
||||
function! s:funcs.win_set_option(win_id, name, value) abort |
||||
let val = a:value |
||||
if val is v:true |
||||
let val = 1 |
||||
elseif val is v:false |
||||
let val = 0 |
||||
endif |
||||
call setwinvar(a:win_id, '&'.a:name, val) |
||||
endfunction |
||||
|
||||
function! s:funcs.win_set_var(win_id, name, value) abort |
||||
call setwinvar(a:win_id, a:name, a:value) |
||||
endfunction |
||||
|
||||
function! s:funcs.win_del_var(win_id, name) abort |
||||
call settabwinvar(0, a:win_id, a:name, v:null) |
||||
endfunction |
||||
|
||||
function! s:funcs.win_is_valid(win_id) abort |
||||
let info = getwininfo(a:win_id) |
||||
return !empty(info) |
||||
endfunction |
||||
|
||||
function! s:funcs.win_get_number(win_id) abort |
||||
let info = getwininfo(a:win_id) |
||||
if empty(info) |
||||
throw 'Invalid window id '.a:win_id |
||||
endif |
||||
return info[0]['winnr'] |
||||
endfunction |
||||
|
||||
function! s:funcs.win_set_cursor(win_id, pos) abort |
||||
let [line, col] = a:pos |
||||
call s:win_execute(a:win_id, 'call cursor('.line.','.(col + 1).')') |
||||
endfunction |
||||
|
||||
function! s:funcs.win_close(win_id, ...) abort |
||||
call s:win_execute(a:win_id, 'close!') |
||||
endfunction |
||||
|
||||
function! s:funcs.win_get_tabpage(win_id) abort |
||||
let info = getwininfo(a:win_id) |
||||
if !info |
||||
throw 'Invalid window id '.a:win_id |
||||
endif |
||||
return info[0]['tabnr'] |
||||
endfunction |
||||
" }} |
||||
|
||||
" tabpage methods {{ |
||||
function! s:funcs.tabpage_get_number(id) |
||||
return a:id |
||||
endfunction |
||||
|
||||
function! s:funcs.tabpage_list_wins(tabnr) |
||||
let info = getwininfo() |
||||
return map(filter(info, 'v:val["tabnr"] == a:tabnr'), 'v:val["winid"]') |
||||
endfunction |
||||
|
||||
function! s:funcs.tabpage_get_var(tabnr, name) |
||||
return gettabvar(a:tabnr, a:name, v:null) |
||||
endfunction |
||||
|
||||
function! s:funcs.tabpage_set_var(tabnr, name, value) |
||||
call settabvar(a:tabnr, a:name, a:value) |
||||
endfunction |
||||
|
||||
function! s:funcs.tabpage_del_var(tabnr, name) |
||||
call settabvar(a:tabnr, a:name, v:null) |
||||
endfunction |
||||
|
||||
function! s:funcs.tabpage_is_valid(tabnr) |
||||
let max = tabpagenr('$') |
||||
return a:tabnr <= max |
||||
endfunction |
||||
|
||||
function! s:funcs.tabpage_get_win(tabnr) |
||||
let wnr = tabpagewinnr(a:tabnr) |
||||
return win_getid(wnr, a:tabnr) |
||||
endfunction |
||||
" }} |
||||
|
||||
function! coc#api#func_names() abort |
||||
return keys(s:funcs) |
||||
endfunction |
||||
|
||||
function! coc#api#call(method, args) abort |
||||
let err = v:null |
||||
let res = v:null |
||||
try |
||||
let res = call(s:funcs[a:method], a:args) |
||||
catch /.*/ |
||||
let err = v:exception |
||||
endtry |
||||
return [err, res] |
||||
endfunction |
||||
|
||||
function! coc#api#notify(method, args) abort |
||||
call call(s:funcs[a:method], a:args) |
||||
endfunction |
||||
" vim: set sw=2 ts=2 sts=2 et tw=78 foldmarker={{,}} foldmethod=marker foldlevel=0: |
@ -0,0 +1,340 @@
@@ -0,0 +1,340 @@
|
||||
scriptencoding utf-8 |
||||
let s:root = expand('<sfile>:h:h:h') |
||||
let s:is_vim = !has('nvim') |
||||
let s:is_win = has("win32") || has("win64") |
||||
let s:clients = {} |
||||
|
||||
if get(g:, 'node_client_debug', 0) |
||||
let $NODE_CLIENT_LOG_LEVEL = 'debug' |
||||
if exists('$NODE_CLIENT_LOG_FILE') |
||||
let s:logfile = resolve($NODE_CLIENT_LOG_FILE) |
||||
else |
||||
let s:logfile = tempname() |
||||
let $NODE_CLIENT_LOG_FILE = s:logfile |
||||
endif |
||||
endif |
||||
|
||||
" create a client |
||||
function! coc#client#create(name, command) |
||||
let client = {} |
||||
let client['command'] = a:command |
||||
let client['name'] = a:name |
||||
let client['running'] = 0 |
||||
let client['async_req_id'] = 1 |
||||
let client['async_callbacks'] = {} |
||||
" vim only |
||||
let client['channel'] = v:null |
||||
" neovim only |
||||
let client['chan_id'] = 0 |
||||
let client['start'] = function('s:start', [], client) |
||||
let client['request'] = function('s:request', [], client) |
||||
let client['notify'] = function('s:notify', [], client) |
||||
let client['request_async'] = function('s:request_async', [], client) |
||||
let client['on_async_response'] = function('s:on_async_response', [], client) |
||||
let s:clients[a:name] = client |
||||
return client |
||||
endfunction |
||||
|
||||
function! s:start() dict |
||||
if self.running | return | endif |
||||
if !isdirectory(getcwd()) |
||||
echohl Error | echon '[coc.nvim] Current cwd is not a valid directory.' | echohl None |
||||
return |
||||
endif |
||||
let timeout = string(get(g:, 'coc_channel_timeout', 30)) |
||||
let disable_warning = string(get(g:, 'coc_disable_startup_warning', 0)) |
||||
let tmpdir = fnamemodify(tempname(), ':p:h') |
||||
if s:is_vim |
||||
let options = { |
||||
\ 'in_mode': 'json', |
||||
\ 'out_mode': 'json', |
||||
\ 'err_mode': 'nl', |
||||
\ 'err_cb': {channel, message -> s:on_stderr(self.name, split(message, "\n"))}, |
||||
\ 'exit_cb': {channel, code -> s:on_exit(self.name, code)}, |
||||
\ 'env': { |
||||
\ 'NODE_NO_WARNINGS': '1', |
||||
\ 'VIM_NODE_RPC': '1', |
||||
\ 'COC_NVIM': '1', |
||||
\ 'COC_CHANNEL_TIMEOUT': timeout, |
||||
\ 'COC_NO_WARNINGS': disable_warning, |
||||
\ 'TMPDIR': tmpdir, |
||||
\ } |
||||
\} |
||||
if has("patch-8.1.350") |
||||
let options['noblock'] = 1 |
||||
endif |
||||
let job = job_start(self.command, options) |
||||
let status = job_status(job) |
||||
if status !=# 'run' |
||||
let self.running = 0 |
||||
echohl Error | echom 'Failed to start '.self.name.' service' | echohl None |
||||
return |
||||
endif |
||||
let self['running'] = 1 |
||||
let self['channel'] = job_getchannel(job) |
||||
else |
||||
let original = {'tmpdir': $TMPDIR} |
||||
" env option not work on neovim |
||||
if exists('*setenv') |
||||
let original = { |
||||
\ 'NODE_NO_WARNINGS': getenv('NODE_NO_WARNINGS'), |
||||
\ 'COC_CHANNEL_TIMEOUT': getenv('COC_CHANNEL_TIMEOUT'), |
||||
\ 'COC_NO_WARNINGS': getenv('COC_NO_WARNINGS'), |
||||
\ 'TMPDIR': getenv('TMPDIR'), |
||||
\ } |
||||
call setenv('NODE_NO_WARNINGS', '1') |
||||
call setenv('COC_CHANNEL_TIMEOUT', timeout) |
||||
call setenv('COC_NO_WARNINGS', disable_warning) |
||||
call setenv('TMPDIR', tmpdir) |
||||
else |
||||
let $NODE_NO_WARNINGS = 1 |
||||
let $COC_NO_WARNINGS = disable_warning |
||||
let $TMPDIR = tmpdir |
||||
endif |
||||
let chan_id = jobstart(self.command, { |
||||
\ 'rpc': 1, |
||||
\ 'on_stderr': {channel, msgs -> s:on_stderr(self.name, msgs)}, |
||||
\ 'on_exit': {channel, code -> s:on_exit(self.name, code)}, |
||||
\}) |
||||
if exists('*setenv') |
||||
for key in keys(original) |
||||
call setenv(key, original[key]) |
||||
endfor |
||||
else |
||||
let $TMPDIR = original['tmpdir'] |
||||
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#util#echo_messages('Error', data) |
||||
endfunction |
||||
|
||||
function! s:on_exit(name, code) abort |
||||
if get(g:, 'coc_vim_leaving', 0) | return | endif |
||||
let client = get(s:clients, a:name, v:null) |
||||
if empty(client) | return | endif |
||||
if client['running'] != 1 | return | endif |
||||
let client['running'] = 0 |
||||
let client['chan_id'] = 0 |
||||
let client['channel'] = v:null |
||||
let client['async_req_id'] = 1 |
||||
if a:code != 0 && a:code != 143 |
||||
" could be syntax error |
||||
if a:code == 1 |
||||
call s:check_node() |
||||
endif |
||||
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 |
||||
|
||||
function! s:check_node() abort |
||||
let node = get(g:, 'coc_node_path', $COC_NODE_PATH == '' ? 'node' : $COC_NODE_PATH) |
||||
let output = trim(system(node . ' --version')) |
||||
let ms = matchlist(output, 'v\(\d\+\).\(\d\+\).\(\d\+\)') |
||||
if empty(ms) || str2nr(ms[1]) < 10 || (str2nr(ms[1]) == 10 && str2nr(ms[2]) < 12) |
||||
echohl Error |
||||
echon '[coc.nvim] Node version '.output.' < 10.12.0, please upgrade node.js or use g:coc_node_path variable.' |
||||
echohl None |
||||
endif |
||||
endfunction |
@ -0,0 +1,192 @@
@@ -0,0 +1,192 @@
|
||||
scriptencoding utf-8 |
||||
" 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 |
@ -0,0 +1,152 @@
@@ -0,0 +1,152 @@
|
||||
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#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 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 s:is_vim && 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 |
||||
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 |
||||
|
||||
" 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 not exists. |
||||
endtry |
||||
return |
||||
endif |
||||
if bufnr == a:bufnr |
||||
execute 'silent! '.a:mode.'unmap <buffer> '.a:lhs |
||||
return |
||||
endif |
||||
if exists('*win_execute') |
||||
let winid = coc#compat#buf_win_id(a:bufnr) |
||||
if winid != -1 |
||||
call win_execute(winid, 'silent! '.a:mode.'unmap <buffer> '.a:lhs) |
||||
endif |
||||
endif |
||||
endfunction |
||||
|
||||
" execute command or list of commands in window |
||||
function! coc#compat#execute(winid, command) abort |
||||
if s:is_vim |
||||
if !exists('*win_execute') |
||||
throw 'win_execute function not exists, please upgrade your vim.' |
||||
endif |
||||
if type(a:command) == v:t_string |
||||
keepalt call win_execute(a:winid, a:command) |
||||
elseif type(a:command) == v:t_list |
||||
keepalt call win_execute(a:winid, join(a:command, "\n")) |
||||
endif |
||||
else |
||||
let curr = nvim_get_current_win() |
||||
noa keepalt call nvim_set_current_win(a:winid) |
||||
if type(a:command) == v:t_string |
||||
exec a:command |
||||
elseif type(a:command) == v:t_list |
||||
exec join(a:command, "\n") |
||||
endif |
||||
noa keepalt call nvim_set_current_win(curr) |
||||
endif |
||||
endfunc |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,90 @@
@@ -0,0 +1,90 @@
|
||||
scriptencoding utf-8 |
||||
" Helper methods for viml |
||||
|
||||
" insert inserted to line at position, use ... when result is too long |
||||
" line should only contains character has strwidth equals 1 |
||||
function! coc#helper#str_compose(line, position, inserted) abort |
||||
let width = strwidth(a:line) |
||||
let text = a:inserted |
||||
let res = a:line |
||||
let need_truncate = a:position + strwidth(text) + 1 > width |
||||
if need_truncate |
||||
let remain = width - a:position - 3 |
||||
if remain < 2 |
||||
" use text for full line, use first & end of a:line, ignore position |
||||
let res = strcharpart(a:line, 0, 1) |
||||
let w = strwidth(res) |
||||
for i in range(strchars(text)) |
||||
let c = strcharpart(text, i, 1) |
||||
let a = strwidth(c) |
||||
if w + a <= width - 1 |
||||
let w = w + a |
||||
let res = res.c |
||||
endif |
||||
endfor |
||||
let res = res.strcharpart(a:line, w) |
||||
else |
||||
let res = strcharpart(a:line, 0, a:position) |
||||
let w = strwidth(res) |
||||
for i in range(strchars(text)) |
||||
let c = strcharpart(text, i, 1) |
||||
let a = strwidth(c) |
||||
if w + a <= width - 3 |
||||
let w = w + a |
||||
let res = res.c |
||||
endif |
||||
endfor |
||||
let res = res.'..' |
||||
let w = w + 2 |
||||
let res = res.strcharpart(a:line, w) |
||||
endif |
||||
else |
||||
let first = strcharpart(a:line, 0, a:position) |
||||
let res = first.text.strcharpart(a:line, a:position + strwidth(text)) |
||||
endif |
||||
return res |
||||
endfunction |
||||
|
||||
" Return new dict with keys removed |
||||
function! coc#helper#dict_omit(dict, keys) abort |
||||
let res = {} |
||||
for key in keys(a:dict) |
||||
if index(a:keys, key) == -1 |
||||
let res[key] = a:dict[key] |
||||
endif |
||||
endfor |
||||
return res |
||||
endfunction |
||||
|
||||
" 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 |
@ -0,0 +1,385 @@
@@ -0,0 +1,385 @@
|
||||
scriptencoding utf-8 |
||||
let s:is_vim = !has('nvim') |
||||
let s:clear_match_by_window = has('nvim-0.5.0') || has('patch-8.1.1084') |
||||
let s:namespace_map = {} |
||||
let s:ns_id = 1 |
||||
|
||||
if has('nvim-0.5.0') |
||||
try |
||||
call getmatches(0) |
||||
catch /^Vim\%((\a\+)\)\=:E118/ |
||||
let s:clear_match_by_window = 0 |
||||
endtry |
||||
endif |
||||
|
||||
function! coc#highlight#get_highlights(bufnr, key) abort |
||||
let l:res = [] |
||||
|
||||
if s:is_vim |
||||
let l:lines = len(getbufline(a:bufnr, 1, '$')) |
||||
for l:line in range(l:lines) |
||||
let l:list = prop_list(l:line + 1, {"bufnr": a:bufnr}) |
||||
for l:prop in l:list |
||||
if l:prop["start"] == 0 || l:prop["end"] == 0 |
||||
" multi line tokens are not supported; simply ignore it |
||||
continue |
||||
endif |
||||
|
||||
let l:group = l:prop["type"] |
||||
let l:start = l:prop["col"] - 1 |
||||
let l:end = l:start + l:prop["length"] |
||||
call add(l:res, { |
||||
\ "group": l:group, |
||||
\ "line": l:line, |
||||
\ "startCharacter": l:start, |
||||
\ "endCharacter": l:end |
||||
\ }) |
||||
endfor |
||||
endfor |
||||
else |
||||
let srcId = s:create_namespace(a:key) |
||||
let l:marks = nvim_buf_get_extmarks(a:bufnr, srcId, 0, -1, {"details": v:true}) |
||||
for [_, l:line, l:start, l:details] in l:marks |
||||
call add(l:res, { |
||||
\ "group": l:details["hl_group"], |
||||
\ "line": l:line, |
||||
\ "startCharacter": l:start, |
||||
\ "endCharacter": l:details["end_col"] |
||||
\ }) |
||||
endfor |
||||
endif |
||||
|
||||
return l:res |
||||
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 synmaxcol = getbufvar(a:bufnr, '&synmaxcol', 1000) |
||||
if synmaxcol == 0 |
||||
let synmaxcol = 1000 |
||||
endif |
||||
let synmaxcol = min([synmaxcol, 1000]) |
||||
let srcId = s: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'])) : -1 |
||||
if colStart == colEnd |
||||
continue |
||||
endif |
||||
call coc#highlight#add_highlight(bufnr, srcId, a:hlGroup, lnum - 1, colStart, colEnd) |
||||
endfor |
||||
endfor |
||||
endfunction |
||||
|
||||
function! coc#highlight#add_highlight(bufnr, src_id, hl_group, line, col_start, col_end) abort |
||||
if has('nvim') |
||||
call nvim_buf_add_highlight(a:bufnr, a:src_id, a:hl_group, a:line, a:col_start, a:col_end) |
||||
else |
||||
call coc#api#call('buf_add_highlight', [a:bufnr, a:src_id, a:hl_group, a:line, a:col_start, a:col_end]) |
||||
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 = s: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#call('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 |
||||
" 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 |
||||
call coc#highlight#add_highlight(bufnr, -1, item['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 (1 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 currwin = win_getid() |
||||
let switch = has('nvim') && currwin != a:winid |
||||
if switch |
||||
noa call nvim_set_current_win(a:winid) |
||||
endif |
||||
let defined = [] |
||||
let region_id = 1 |
||||
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 s:execute(a:winid, '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 s:execute(a:winid, 'syntax include @'.toupper(filetype).' syntax/'.filetype.'.vim') |
||||
if has('nvim') |
||||
unlet! b:current_syntax |
||||
elseif exists('*win_execute') |
||||
call win_execute(a:winid, 'unlet! b:current_syntax') |
||||
endif |
||||
call add(defined, filetype) |
||||
endif |
||||
call s:execute(a:winid, 'syntax region CodeBlock'.region_id.' start=/\%'.start.'l/ end=/\%'.end.'l/ contains=@'.toupper(filetype).' keepend') |
||||
let region_id = region_id + 1 |
||||
endif |
||||
endfor |
||||
if switch |
||||
noa call nvim_set_current_win(currwin) |
||||
endif |
||||
endfunction |
||||
|
||||
" Copmpose 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) |
||||
return hlGroup |
||||
endif |
||||
let fg = synIDattr(synIDtrans(hlID(a:fgGroup)), 'fg', 'gui') |
||||
let bg = synIDattr(synIDtrans(hlID(a:bgGroup)), 'bg', 'gui') |
||||
if fg =~# '^#' || bg =~# '^#' |
||||
call s:create_gui_hlgroup(hlGroup, fg, bg, '') |
||||
else |
||||
let fg = synIDattr(synIDtrans(hlID(a:fgGroup)), 'fg', 'cterm') |
||||
let bg = synIDattr(synIDtrans(hlID(a:bgGroup)), 'bg', 'cterm') |
||||
call s:create_cterm_hlgroup(hlGroup, fg, bg, '') |
||||
endif |
||||
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 |
||||
|
||||
" Sets the highlighting for the given group |
||||
function! s:create_gui_hlgroup(group, fg, bg, attr) |
||||
if a:fg != "" |
||||
exec "silent hi " . a:group . " guifg=" . a:fg . " ctermfg=" . coc#color#rgb2term(strpart(a:fg, 1)) |
||||
endif |
||||
if a:bg != "" |
||||
exec "silent hi " . a:group . " guibg=" . a:bg . " ctermbg=" . coc#color#rgb2term(strpart(a:bg, 1)) |
||||
endif |
||||
if a:attr != "" |
||||
exec "silent hi " . a:group . " gui=" . a:attr . " cterm=" . a:attr |
||||
endif |
||||
endfun |
||||
|
||||
function! s:create_cterm_hlgroup(group, fg, bg, attr) abort |
||||
if a:fg != "" |
||||
exec "silent hi " . a:group . " ctermfg=" . a:fg |
||||
endif |
||||
if a:bg != "" |
||||
exec "silent hi " . a:group . " ctermbg=" . a:bg |
||||
endif |
||||
if a:attr != "" |
||||
exec "silent hi " . a:group . " cterm=" . a:attr |
||||
endif |
||||
endfunction |
||||
|
||||
function! s:execute(winid, cmd) abort |
||||
if has('nvim') |
||||
execute 'silent! ' a:cmd |
||||
else |
||||
call win_execute(a:winid, a:cmd, 'silent!') |
||||
endif |
||||
endfunction |
||||
|
||||
function! s: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 |
@ -0,0 +1,343 @@
@@ -0,0 +1,343 @@
|
||||
scriptencoding utf-8 |
||||
let s:is_vim = !has('nvim') |
||||
let s:prefix = '[List Preview]' |
||||
" filetype detect could be slow. |
||||
let s:filetype_map = { |
||||
\ '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'] |
||||
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 |
||||
setl signcolumn=yes |
||||
endif |
||||
return [bufnr('%'), win_getid()] |
||||
endfunction |
||||
|
||||
" close list windows |
||||
function! coc#list#clean_up() abort |
||||
for i in range(1, winnr('$')) |
||||
let bufname = bufname(winbufnr(i)) |
||||
if bufname =~# 'list://' |
||||
execute i.'close!' |
||||
endif |
||||
endfor |
||||
endfunction |
||||
|
||||
function! coc#list#setup(source) |
||||
let b:list_status = {} |
||||
setl buftype=nofile nobuflisted nofen nowrap |
||||
setl norelativenumber bufhidden=wipe cursorline winfixheight |
||||
setl tabstop=1 nolist nocursorcolumn undolevels=-1 |
||||
setl signcolumn=auto |
||||
if has('nvim-0.5.0') || has('patch-8.1.0864') |
||||
setl scrolloff=0 |
||||
endif |
||||
if exists('&cursorlineopt') |
||||
setl cursorlineopt=both |
||||
endif |
||||
setl filetype=list |
||||
syntax case ignore |
||||
let source = a:source[8:] |
||||
let name = toupper(source[0]).source[1:] |
||||
execute 'syntax match Coc'.name.'Line /\v^.*$/' |
||||
nnoremap <silent><nowait><buffer> <esc> <C-w>c |
||||
endfunction |
||||
|
||||
" 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 getwinvar(win, 'previewwindow', 0) |
||||
return win |
||||
endif |
||||
endfor |
||||
endif |
||||
return -1 |
||||
endfunction |
||||
|
||||
function! coc#list#scroll_preview(dir) abort |
||||
let winnr = coc#list#has_preview() |
||||
if !winnr |
||||
return |
||||
endif |
||||
let winid = win_getid(winnr) |
||||
if exists('*win_execute') |
||||
call win_execute(winid, "normal! ".(a:dir ==# 'up' ? "\<C-u>" : "\<C-d>")) |
||||
else |
||||
let id = win_getid() |
||||
noa call win_gotoid(winid) |
||||
execute "normal! ".(a:dir ==# 'up' ? "\<C-u>" : "\<C-d>") |
||||
noa call win_gotoid(id) |
||||
endif |
||||
endfunction |
||||
|
||||
function! coc#list#restore(winid, height) |
||||
if has('nvim') |
||||
if nvim_win_is_valid(a:winid) |
||||
call nvim_win_set_height(a:winid, a:height) |
||||
endif |
||||
else |
||||
if exists('win_execute') |
||||
call win_execute(a:winid, 'noa resize '.a:height, 'silent!') |
||||
redraw |
||||
endif |
||||
endif |
||||
endfunction |
||||
|
||||
function! coc#list#set_height(height) abort |
||||
if winnr('$') == 1| return | endif |
||||
execute 'resize '.a:height |
||||
endfunction |
||||
|
||||
function! coc#list#hide(original, height, winid) abort |
||||
let arr = win_id2tabwin(a:winid) |
||||
" close preview window |
||||
if !empty(arr) && arr[0] != 0 |
||||
silent! pclose! |
||||
let previewwin = coc#list#get_preview(arr[0]) |
||||
call s:close_win(previewwin) |
||||
endif |
||||
if !empty(getwininfo(a:original)) |
||||
call win_gotoid(a:original) |
||||
endif |
||||
if a:winid |
||||
call s:close_win(a:winid) |
||||
endif |
||||
if !empty(a:height) && win_getid() == a:original |
||||
if exists('*nvim_win_set_height') |
||||
call nvim_win_set_height(a:original, a:height) |
||||
elseif win_getid() == a:original |
||||
execute 'resize '.a:height |
||||
endif |
||||
endif |
||||
endfunction |
||||
|
||||
function! s:close_win(winid) abort |
||||
if empty(a:winid) || a:winid == -1 || empty(getwininfo(a:winid)) |
||||
return |
||||
endif |
||||
if s:is_vim |
||||
if exists('*win_execute') |
||||
noa call win_execute(a:winid, 'close!', 'silent!') |
||||
else |
||||
if win_getid() == a:winid |
||||
noa silent! close! |
||||
else |
||||
let winid = win_getid() |
||||
let res = win_gotoid(winid) |
||||
if res |
||||
noa silent! close! |
||||
noa wincmd p |
||||
endif |
||||
endif |
||||
endif |
||||
else |
||||
if nvim_win_is_valid(a:winid) |
||||
silent! noa call nvim_win_close(a:winid, 1) |
||||
endif |
||||
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 |
||||
if s:is_vim && !exists('*win_execute') |
||||
throw 'win_execute function required for preview, please upgrade your vim.' |
||||
return |
||||
endif |
||||
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) |
||||
if bufnr != 0 |
||||
let lines = getbufline(bufnr, 1, '$') |
||||
else |
||||
let lines = [''] |
||||
endif |
||||
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":max([1, lnum - 3])}) |
||||
call setwinvar(winid, '&signcolumn', 'no') |
||||
call setwinvar(winid, '&number', 1) |
||||
call setwinvar(winid, '&cursorline', 0) |
||||
call setwinvar(winid, '&relativenumber', 0) |
||||
call setwinvar(winid, 'previewwindow', 1) |
||||
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":'.max([1, lnum - 3]).'})']) |
||||
endif |
||||
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('coc', {'buffer': bufnr}) |
||||
call coc#compat#execute(winid, 'call clearmatches()') |
||||
if !empty(range) |
||||
call sign_place(1, 'coc', 'CocCurrentLine', bufnr, {'lnum': lnum}) |
||||
call coc#highlight#match_ranges(winid, bufnr, [range], hlGroup, 10) |
||||
endif |
||||
redraw |
||||
endfunction |
||||
|
||||
function! s:get_height(lines, config) abort |
||||
if get(a:config, 'splitRight', 0) || get(a:config, 'position', 'below') == 'tab' |
||||
return 0 |
||||
endif |
||||
let height = min([get(a:config, 'maxHeight', 10), len(a:lines), &lines - &cmdheight - 2]) |
||||
return height |
||||
endfunction |
||||
|
||||
function! s:load_buffer(name) abort |
||||
if exists('*bufadd') && exists('*bufload') |
||||
let bufnr = bufadd(a:name) |
||||
call bufload(bufnr) |
||||
return bufnr |
||||
endif |
||||
return 0 |
||||
endfunction |
@ -0,0 +1,210 @@
@@ -0,0 +1,210 @@
|
||||
scriptencoding utf-8 |
||||
let s:is_vim = !has('nvim') |
||||
let s:activated = 0 |
||||
let s:session_names = [] |
||||
let s:saved_ve = &t_ve |
||||
let s:saved_cursor = &guicursor |
||||
let s:gui = has('gui_running') || has('nvim') |
||||
|
||||
let s:char_map = { |
||||
\ "\<Plug>": '<plug>', |
||||
\ "\<Esc>": '<esc>', |
||||
\ "\<Tab>": '<tab>', |
||||
\ "\<S-Tab>": '<s-tab>', |
||||
\ "\<bs>": '<bs>', |
||||
\ "\<right>": '<right>', |
||||
\ "\<left>": '<left>', |
||||
\ "\<up>": '<up>', |
||||
\ "\<down>": '<down>', |
||||
\ "\<home>": '<home>', |
||||
\ "\<end>": '<end>', |
||||
\ "\<cr>": '<cr>', |
||||
\ "\<PageUp>":'<PageUp>' , |
||||
\ "\<PageDown>":'<PageDown>' , |
||||
\ "\<FocusGained>":'<FocusGained>', |
||||
\ "\<FocusLost>":'<FocusLost>', |
||||
\ "\<ScrollWheelUp>": '<ScrollWheelUp>', |
||||
\ "\<ScrollWheelDown>": '<ScrollWheelDown>', |
||||
\ "\<LeftMouse>": '<LeftMouse>', |
||||
\ "\<LeftDrag>": '<LeftDrag>', |
||||
\ "\<LeftRelease>": '<LeftRelease>', |
||||
\ "\<2-LeftMouse>": '<2-LeftMouse>', |
||||
\ "\<C-a>": '<C-a>', |
||||
\ "\<C-b>": '<C-b>', |
||||
\ "\<C-c>": '<C-c>', |
||||
\ "\<C-d>": '<C-d>', |
||||
\ "\<C-e>": '<C-e>', |
||||
\ "\<C-f>": '<C-f>', |
||||
\ "\<C-g>": '<C-g>', |
||||
\ "\<C-h>": '<C-h>', |
||||
\ "\<C-j>": '<C-j>', |
||||
\ "\<C-k>": '<C-k>', |
||||
\ "\<C-l>": '<C-l>', |
||||
\ "\<C-n>": '<C-n>', |
||||
\ "\<C-o>": '<C-o>', |
||||
\ "\<C-p>": '<C-p>', |
||||
\ "\<C-q>": '<C-q>', |
||||
\ "\<C-r>": '<C-r>', |
||||
\ "\<C-s>": '<C-s>', |
||||
\ "\<C-t>": '<C-t>', |
||||
\ "\<C-u>": '<C-u>', |
||||
\ "\<C-v>": '<C-v>', |
||||
\ "\<C-w>": '<C-w>', |
||||
\ "\<C-x>": '<C-x>', |
||||
\ "\<C-y>": '<C-y>', |
||||
\ "\<C-z>": '<C-z>', |
||||
\ "\<A-a>": '<A-a>', |
||||
\ "\<A-b>": '<A-b>', |
||||
\ "\<A-c>": '<A-c>', |
||||
\ "\<A-d>": '<A-d>', |
||||
\ "\<A-e>": '<A-e>', |
||||
\ "\<A-f>": '<A-f>', |
||||
\ "\<A-g>": '<A-g>', |
||||
\ "\<A-h>": '<A-h>', |
||||
\ "\<A-i>": '<A-i>', |
||||
\ "\<A-j>": '<A-j>', |
||||
\ "\<A-k>": '<A-k>', |
||||
\ "\<A-l>": '<A-l>', |
||||
\ "\<A-m>": '<A-m>', |
||||
\ "\<A-n>": '<A-n>', |
||||
\ "\<A-o>": '<A-o>', |
||||
\ "\<A-p>": '<A-p>', |
||||
\ "\<A-q>": '<A-q>', |
||||
\ "\<A-r>": '<A-r>', |
||||
\ "\<A-s>": '<A-s>', |
||||
\ "\<A-t>": '<A-t>', |
||||
\ "\<A-u>": '<A-u>', |
||||
\ "\<A-v>": '<A-v>', |
||||
\ "\<A-w>": '<A-w>', |
||||
\ "\<A-x>": '<A-x>', |
||||
\ "\<A-y>": '<A-y>', |
||||
\ "\<A-z>": '<A-z>', |
||||
\ } |
||||
|
||||
function! coc#prompt#getc() abort |
||||
let c = getchar() |
||||
return type(c) == type(0) ? nr2char(c) : c |
||||
endfunction |
||||
|
||||
function! coc#prompt#getchar() abort |
||||
let input = coc#prompt#getc() |
||||
if 1 != &iminsert |
||||
return input |
||||
endif |
||||
"a language keymap is activated, so input must be resolved to the mapped values. |
||||
let partial_keymap = mapcheck(input, "l") |
||||
while partial_keymap !=# "" |
||||
let full_keymap = maparg(input, "l") |
||||
if full_keymap ==# "" && len(input) >= 3 "HACK: assume there are no keymaps longer than 3. |
||||
return input |
||||
elseif full_keymap ==# partial_keymap |
||||
return full_keymap |
||||
endif |
||||
let c = coc#prompt#getc() |
||||
if c ==# "\<Esc>" || c ==# "\<CR>" |
||||
"if the short sequence has a valid mapping, return that. |
||||
if !empty(full_keymap) |
||||
return full_keymap |
||||
endif |
||||
return input |
||||
endif |
||||
let input .= c |
||||
let partial_keymap = mapcheck(input, "l") |
||||
endwhile |
||||
return input |
||||
endfunction |
||||
|
||||
function! coc#prompt#start_prompt(session) abort |
||||
let s:session_names = s:filter(s:session_names, a:session) |
||||
call add(s:session_names, a:session) |
||||
if s:activated | return | endif |
||||
if s:is_vim |
||||
call s:start_prompt_vim() |
||||
else |
||||
call s:start_prompt() |
||||
endif |
||||
endfunction |
||||
|
||||
function! s:start_prompt_vim() abort |
||||
call timer_start(10, {-> s:start_prompt()}) |
||||
endfunction |
||||
|
||||
function! s:start_prompt() |
||||
if s:activated | return | endif |
||||
if !get(g:, 'coc_disable_transparent_cursor', 0) |
||||
if s:gui |
||||
if has('nvim-0.5.0') && !empty(s:saved_cursor) |
||||
set guicursor+=a:ver1-CocCursorTransparent/lCursor |
||||
endif |
||||
elseif s:is_vim |
||||
set t_ve= |
||||
endif |
||||
endif |
||||
let s:activated = 1 |
||||
try |
||||
while s:activated |
||||
let ch = coc#prompt#getchar() |
||||
if ch ==# "\<FocusLost>" || ch ==# "\<FocusGained>" || ch ==# "\<CursorHold>" |
||||
continue |
||||
else |
||||
let curr = s:current_session() |
||||
let mapped = get(s:char_map, ch, ch) |
||||
if !empty(curr) |
||||
call coc#rpc#notify('InputChar', [curr, mapped, getcharmod()]) |
||||
endif |
||||
if mapped == '<esc>' |
||||
let s:session_names = [] |
||||
call s:reset() |
||||
break |
||||
endif |
||||
endif |
||||
endwhile |
||||
catch /^Vim:Interrupt$/ |
||||
let s:activated = 0 |
||||
call coc#rpc#notify('InputChar', [s:current_session(), '<esc>']) |
||||
return |
||||
endtry |
||||
let s:activated = 0 |
||||
endfunction |
||||
|
||||
function! coc#prompt#stop_prompt(session) |
||||
let s:session_names = s:filter(s:session_names, a:session) |
||||
if len(s:session_names) |
||||
return |
||||
endif |
||||
if s:activated |
||||
let s:activated = 0 |
||||
call s:reset() |
||||
call feedkeys("\<esc>", 'int') |
||||
endif |
||||
endfunction |
||||
|
||||
function! coc#prompt#activated() abort |
||||
return s:activated |
||||
endfunction |
||||
|
||||
function! s:reset() abort |
||||
if !get(g:, 'coc_disable_transparent_cursor',0) |
||||
" neovim has bug with revert empty &guicursor |
||||
if s:gui && !empty(s:saved_cursor) |
||||
if has('nvim-0.5.0') |
||||
set guicursor+=a:ver1-Cursor/lCursor |
||||
let &guicursor = s:saved_cursor |
||||
endif |
||||
elseif s:is_vim |
||||
let &t_ve = s:saved_ve |
||||
endif |
||||
endif |
||||
echo "" |
||||
endfunction |
||||
|
||||
function! s:current_session() abort |
||||
if empty(s:session_names) |
||||
return v:null |
||||
endif |
||||
return s:session_names[len(s:session_names) - 1] |
||||
endfunction |
||||
|
||||
function! s:filter(list, id) abort |
||||
return filter(copy(a:list), 'v:val !=# a:id') |
||||
endfunction |
@ -0,0 +1,128 @@
@@ -0,0 +1,128 @@
|
||||
scriptencoding utf-8 |
||||
let s:is_win = has("win32") || has("win64") |
||||
let s:client = v:null |
||||
let s:name = 'coc' |
||||
let s:is_vim = !has('nvim') |
||||
|
||||
function! coc#rpc#start_server() |
||||
if get(g:, 'coc_node_env', '') ==# 'test' |
||||
" server already started |
||||
let s:client = coc#client#create(s:name, []) |
||||
let s:client['running'] = 1 |
||||
let s:client['chan_id'] = get(g:, 'coc_node_channel_id', 0) |
||||
call dictwatcheradd(g:, 'coc_node_channel_id', function('s:ChannelSet')) |
||||
return |
||||
endif |
||||
if empty(s:client) |
||||
let cmd = coc#util#job_command() |
||||
if empty(cmd) | return | endif |
||||
let $COC_VIMCONFIG = coc#util#get_config_home() |
||||
let $COC_DATA_HOME = coc#util#get_data_home() |
||||
let s:client = coc#client#create(s:name, cmd) |
||||
endif |
||||
if !coc#client#is_running('coc') |
||||
call s:client['start']() |
||||
endif |
||||
endfunction |
||||
|
||||
function! coc#rpc#started() abort |
||||
return !empty(s:client) |
||||
endfunction |
||||
|
||||
function! coc#rpc#ready() |
||||
if empty(s:client) || s:client['running'] == 0 |
||||
return 0 |
||||
endif |
||||
return 1 |
||||
endfunction |
||||
|
||||
function! s:ChannelSet(dict, key, val) |
||||
let chan_id = get(a:val, 'new', 0) |
||||
if empty(s:client) | return | endif |
||||
let s:client['running'] = 1 |
||||
let s:client['chan_id'] = chan_id |
||||
call dictwatcherdel(g:, 'coc_node_channel_id', function('s:ChannelSet')) |
||||
endfunction |
||||
|
||||
function! coc#rpc#kill() |
||||
let pid = get(g:, 'coc_process_pid', 0) |
||||
if !pid | return | endif |
||||
if s:is_win |
||||
call system('taskkill /PID '.pid) |
||||
else |
||||
call system('kill -9 '.pid) |
||||
endif |
||||
endfunction |
||||
|
||||
function! coc#rpc#get_errors() |
||||
return split(execute('messages'), "\n") |
||||
endfunction |
||||
|
||||
function! coc#rpc#stop() |
||||
if empty(s:client) |
||||
return |
||||
endif |
||||
try |
||||
if s:is_vim |
||||
call job_stop(ch_getjob(s:client['channel']), 'term') |
||||
else |
||||
call jobstop(s:client['chan_id']) |
||||
endif |
||||
catch /.*/ |
||||
" ignore |
||||
endtry |
||||
endfunction |
||||
|
||||
function! coc#rpc#restart() |
||||
if empty(s:client) |
||||
call coc#rpc#start_server() |
||||
else |
||||
call coc#float#close_all() |
||||
call coc#rpc#request('detach', []) |
||||
sleep 100m |
||||
let s:client['command'] = coc#util#job_command() |
||||
call coc#client#restart(s:name) |
||||
echohl MoreMsg | echom 'starting coc.nvim service' | echohl None |
||||
endif |
||||
endfunction |
||||
|
||||
function! coc#rpc#request(method, args) abort |
||||
if !coc#rpc#ready() |
||||
return '' |
||||
endif |
||||
return s:client['request'](a:method, a:args) |
||||
endfunction |
||||
|
||||
function! coc#rpc#notify(method, args) abort |
||||
if !coc#rpc#ready() |
||||
return '' |
||||
endif |
||||
call s:client['notify'](a:method, a:args) |
||||
return '' |
||||
endfunction |
||||
|
||||
function! coc#rpc#request_async(method, args, cb) abort |
||||
if !coc#rpc#ready() |
||||
return cb('coc.nvim service not started.') |
||||
endif |
||||
call s:client['request_async'](a:method, a:args, a:cb) |
||||
endfunction |
||||
|
||||
" receive async response |
||||
function! coc#rpc#async_response(id, resp, isErr) abort |
||||
if empty(s:client) |
||||
return |
||||
endif |
||||
call coc#client#on_response(s:name, a:id, a:resp, a:isErr) |
||||
endfunction |
||||
|
||||
" send async response to server |
||||
function! coc#rpc#async_request(id, method, args) |
||||
let l:Cb = {err, ... -> coc#rpc#notify('nvim_async_response_event', [a:id, err, get(a:000, 0, v:null)])} |
||||
let args = a:args + [l:Cb] |
||||
try |
||||
call call(a:method, args) |
||||
catch /.*/ |
||||
call coc#rpc#notify('nvim_async_response_event', [a:id, v:exception, v:null]) |
||||
endtry |
||||
endfunction |
@ -0,0 +1,69 @@
@@ -0,0 +1,69 @@
|
||||
scriptencoding utf-8 |
||||
let s:is_vim = !has('nvim') |
||||
let s:map_next = 1 |
||||
|
||||
function! coc#snippet#_select_mappings() |
||||
if !get(g:, 'coc_selectmode_mapping', 1) |
||||
return |
||||
endif |
||||
|
||||
redir => mappings |
||||
silent! smap |
||||
redir END |
||||
|
||||
for map in map(filter(split(mappings, '\n'), |
||||
\ "v:val !~# '^s' && v:val !~# '^\\a*\\s*<\\S\\+>'"), |
||||
\ "matchstr(v:val, '^\\a*\\s*\\zs\\S\\+')") |
||||
silent! execute 'sunmap' map |
||||
silent! execute 'sunmap <buffer>' map |
||||
endfor |
||||
|
||||
" same behaviour of ultisnips |
||||
snoremap <silent> <BS> <c-g>c |
||||
snoremap <silent> <DEL> <c-g>c |
||||
snoremap <silent> <c-h> <c-g>c |
||||
snoremap <c-r> <c-g>"_c<c-r> |
||||
endfunction |
||||
|
||||
function! coc#snippet#show_choices(lnum, col, len, values) abort |
||||
let m = mode() |
||||
call cursor(a:lnum, a:col + a:len) |
||||
if m !=# 'i' | startinsert | endif |
||||
call timer_start(20, { -> coc#_do_complete(a:col - 1, a:values, 0)}) |
||||
redraw |
||||
endfunction |
||||
|
||||
function! coc#snippet#enable() |
||||
if get(b:, 'coc_snippet_active', 0) == 1 |
||||
return |
||||
endif |
||||
let b:coc_snippet_active = 1 |
||||
silent! unlet g:coc_selected_text |
||||
call coc#snippet#_select_mappings() |
||||
let nextkey = get(g:, 'coc_snippet_next', '<C-j>') |
||||
let prevkey = get(g:, 'coc_snippet_prev', '<C-k>') |
||||
if maparg(nextkey, 'i') =~# 'expand-jump' |
||||
let s:map_next = 0 |
||||
endif |
||||
if s:map_next |
||||
execute 'inoremap <buffer><nowait><silent>'.nextkey." <C-R>=coc#rpc#request('snippetNext', [])<cr>" |
||||
endif |
||||
execute 'inoremap <buffer><nowait><silent>'.prevkey." <C-R>=coc#rpc#request('snippetPrev', [])<cr>" |
||||
execute 'snoremap <buffer><nowait><silent>'.prevkey." <Esc>:call coc#rpc#request('snippetPrev', [])<cr>" |
||||
execute 'snoremap <buffer><nowait><silent>'.nextkey." <Esc>:call coc#rpc#request('snippetNext', [])<cr>" |
||||
endfunction |
||||
|
||||
function! coc#snippet#disable() |
||||
if get(b:, 'coc_snippet_active', 0) == 0 |
||||
return |
||||
endif |
||||
let b:coc_snippet_active = 0 |
||||
let nextkey = get(g:, 'coc_snippet_next', '<C-j>') |
||||
let prevkey = get(g:, 'coc_snippet_prev', '<C-k>') |
||||
if s:map_next |
||||
silent! execute 'iunmap <buffer> <silent> '.nextkey |
||||
endif |
||||
silent! execute 'iunmap <buffer> <silent> '.prevkey |
||||
silent! execute 'sunmap <buffer> <silent> '.prevkey |
||||
silent! execute 'sunmap <buffer> <silent> '.nextkey |
||||
endfunction |
@ -0,0 +1,175 @@
@@ -0,0 +1,175 @@
|
||||
" ============================================================================ |
||||
" Description: Manage long running tasks. |
||||
" Author: Qiming Zhao <chemzqm@gmail.com> |
||||
" Licence: MIT licence |
||||
" Version: 0.1 |
||||
" Last Modified: Dec 12, 2020 |
||||
" ============================================================================ |
||||
scriptencoding utf-8 |
||||
|
||||
let s:is_vim = !has('nvim') |
||||
let s:running_task = {} |
||||
" neovim emit strings that part of lines. |
||||
let s:out_remain_text = {} |
||||
let s:err_remain_text = {} |
||||
|
||||
function! coc#task#start(id, opts) |
||||
if coc#task#running(a:id) |
||||
call coc#task#stop(a:id) |
||||
endif |
||||
let cmd = [a:opts['cmd']] + get(a:opts, 'args', []) |
||||
let cwd = get(a:opts, 'cwd', getcwd()) |
||||
let env = get(a:opts, 'env', {}) |
||||
" cmd args cwd pty |
||||
if s:is_vim |
||||
let options = { |
||||
\ 'cwd': cwd, |
||||
\ 'err_mode': 'nl', |
||||
\ 'out_mode': 'nl', |
||||
\ 'err_cb': {channel, message -> s:on_stderr(a:id, [message])}, |
||||
\ 'out_cb': {channel, message -> s:on_stdout(a:id, [message])}, |
||||
\ 'exit_cb': {channel, code -> s:on_exit(a:id, code)}, |
||||
\ 'env': env, |
||||
\} |
||||
if has("patch-8.1.350") |
||||
let options['noblock'] = 1 |
||||
endif |
||||
if get(a:opts, 'pty', 0) |
||||
let options['pty'] = 1 |
||||
endif |
||||
let job = job_start(cmd, options) |
||||
let status = job_status(job) |
||||
if status !=# 'run' |
||||
echohl Error | echom 'Failed to start '.a:id.' task' | echohl None |
||||
return v:false |
||||
endif |
||||
let s:running_task[a:id] = job |
||||
else |
||||
let options = { |
||||
\ 'cwd': cwd, |
||||
\ 'on_stderr': {channel, msgs -> s:on_stderr(a:id, msgs)}, |
||||
\ 'on_stdout': {channel, msgs -> s:on_stdout(a:id, msgs)}, |
||||
\ 'on_exit': {channel, code -> s:on_exit(a:id, code)}, |
||||
\ 'detach': get(a:opts, 'detach', 0), |
||||
\} |
||||
let original = {} |
||||
if !empty(env) && exists('*setenv') && exists('*getenv') |
||||
for key in keys(env) |
||||
let original[key] = getenv(key) |
||||
call setenv(key, env[key]) |
||||
endfor |
||||
endif |
||||
if get(a:opts, 'pty', 0) |
||||
let options['pty'] = 1 |
||||
endif |
||||
let chan_id = jobstart(cmd, options) |
||||
if !empty(original) |
||||
for key in keys(original) |
||||
call setenv(key, original[key]) |
||||
endfor |
||||
endif |
||||
if chan_id <= 0 |
||||
echohl Error | echom 'Failed to start '.a:id.' task' | echohl None |
||||
return v:false |
||||
endif |
||||
let s:running_task[a:id] = chan_id |
||||
endif |
||||
return v:true |
||||
endfunction |
||||
|
||||
function! coc#task#stop(id) |
||||
let job = get(s:running_task, a:id, v:null) |
||||
if !job | return | endif |
||||
if s:is_vim |
||||
call job_stop(job, 'term') |
||||
else |
||||
call jobstop(job) |
||||
endif |
||||
sleep 50m |
||||
let running = coc#task#running(a:id) |
||||
if running |
||||
echohl Error | echom 'job '.a:id. ' stop failed.' | echohl None |
||||
endif |
||||
endfunction |
||||
|
||||
function! s:on_exit(id, code) abort |
||||
if get(g:, 'coc_vim_leaving', 0) | return | endif |
||||
if has('nvim') |
||||
let s:out_remain_text[a:id] = '' |
||||
let s:err_remain_text[a:id] = '' |
||||
endif |
||||
if has_key(s:running_task, a:id) |
||||
call remove(s:running_task, a:id) |
||||
endif |
||||
call coc#rpc#notify('TaskExit', [a:id, a:code]) |
||||
endfunction |
||||
|
||||
function! s:on_stderr(id, msgs) |
||||
if get(g:, 'coc_vim_leaving', 0) | return | endif |
||||
if empty(a:msgs) |
||||
return |
||||
endif |
||||
if s:is_vim |
||||
call coc#rpc#notify('TaskStderr', [a:id, a:msgs]) |
||||
else |
||||
let remain = get(s:err_remain_text, a:id, '') |
||||
let eof = (a:msgs == ['']) |
||||
let msgs = copy(a:msgs) |
||||
if len(remain) > 0 |
||||
if msgs[0] == '' |
||||
let msgs[0] = remain |
||||
else |
||||
let msgs[0] = remain . msgs[0] |
||||
endif |
||||
endif |
||||
let last = msgs[len(msgs) - 1] |
||||
let s:err_remain_text[a:id] = len(last) > 0 ? last : '' |
||||
" all lines from 0 to n - 2 |
||||
if len(msgs) > 1 |
||||
call coc#rpc#notify('TaskStderr', [a:id, msgs[:len(msgs)-2]]) |
||||
elseif eof && len(msgs[0]) > 0 |
||||
call coc#rpc#notify('TaskStderr', [a:id, msgs]) |
||||
endif |
||||
endif |
||||
endfunction |
||||
|
||||
function! s:on_stdout(id, msgs) |
||||
if empty(a:msgs) |
||||
return |
||||
endif |
||||
if s:is_vim |
||||
call coc#rpc#notify('TaskStdout', [a:id, a:msgs]) |
||||
else |
||||
let remain = get(s:out_remain_text, a:id, '') |
||||
let eof = (a:msgs == ['']) |
||||
let msgs = copy(a:msgs) |
||||
if len(remain) > 0 |
||||
if msgs[0] == '' |
||||
let msgs[0] = remain |
||||
else |
||||
let msgs[0] = remain . msgs[0] |
||||
endif |
||||
endif |
||||
let last = msgs[len(msgs) - 1] |
||||
let s:out_remain_text[a:id] = len(last) > 0 ? last : '' |
||||
" all lines from 0 to n - 2 |
||||
if len(msgs) > 1 |
||||
call coc#rpc#notify('TaskStdout', [a:id, msgs[:len(msgs)-2]]) |
||||
elseif eof && len(msgs[0]) > 0 |
||||
call coc#rpc#notify('TaskStdout', [a:id, msgs]) |
||||
endif |
||||
endif |
||||
endfunction |
||||
|
||||
function! coc#task#running(id) |
||||
if !has_key(s:running_task, a:id) == 1 |
||||
return v:false |
||||
endif |
||||
let job = s:running_task[a:id] |
||||
if s:is_vim |
||||
let status = job_status(job) |
||||
return status ==# 'run' |
||||
endif |
||||
let [code] = jobwait([job], 10) |
||||
return code == -1 |
||||
endfunction |
@ -0,0 +1,115 @@
@@ -0,0 +1,115 @@
|
||||
scriptencoding utf-8 |
||||
let s:is_vim = !has('nvim') |
||||
let s:channel_map = {} |
||||
let s:is_win = has('win32') || has('win64') |
||||
|
||||
" start terminal, return [bufnr, pid] |
||||
function! coc#terminal#start(cmd, cwd, env) abort |
||||
if s:is_vim && !has('terminal') |
||||
throw 'terminal feature not supported by current vim.' |
||||
endif |
||||
let cwd = empty(a:cwd) ? getcwd() : a:cwd |
||||
execute 'belowright 8new +setl\ buftype=nofile' |
||||
setl winfixheight |
||||
setl norelativenumber |
||||
setl nonumber |
||||
setl bufhidden=hide |
||||
if exists('#User#CocTerminalOpen') |
||||
exe 'doautocmd <nomodeline> User CocTerminalOpen' |
||||
endif |
||||
let bufnr = bufnr('%') |
||||
let env = {} |
||||
let original = {} |
||||
if !empty(a:env) |
||||
" use env option when possible |
||||
if s:is_vim |
||||
let env = copy(a:env) |
||||
elseif exists('*setenv') |
||||
for key in keys(a:env) |
||||
let original[key] = getenv(key) |
||||
call setenv(key, a:env[key]) |
||||
endfor |
||||
endif |
||||
endif |
||||
|
||||
function! s:OnExit(status) closure |
||||
if a:status == 0 |
||||
execute 'silent! bd! '.bufnr |
||||
endif |
||||
endfunction |
||||
|
||||
if has('nvim') |
||||
let job_id = termopen(a:cmd, { |
||||
\ 'cwd': cwd, |
||||
\ 'pty': 1, |
||||
\ 'on_exit': {job, status -> s:OnExit(status)}, |
||||
\ 'env': env, |
||||
\ }) |
||||
if !empty(original) && exists('*setenv') |
||||
for key in keys(original) |
||||
call setenv(key, original[key]) |
||||
endfor |
||||
endif |
||||
if job_id == 0 |
||||
throw 'create terminal job failed' |
||||
endif |
||||
wincmd p |
||||
let s:channel_map[bufnr] = job_id |
||||
return [bufnr, jobpid(job_id)] |
||||
else |
||||
let cmd = s:is_win ? join(a:cmd, ' ') : a:cmd |
||||
let res = term_start(cmd, { |
||||
\ 'cwd': cwd, |
||||
\ 'term_kill': s:is_win ? 'kill' : 'term', |
||||
\ 'term_finish': 'close', |
||||
\ 'exit_cb': {job, status -> s:OnExit(status)}, |
||||
\ 'curwin': 1, |
||||
\ 'env': env, |
||||
\}) |
||||
if res == 0 |
||||
throw 'create terminal job failed' |
||||
endif |
||||
let job = term_getjob(bufnr) |
||||
let s:channel_map[bufnr] = job_getchannel(job) |
||||
wincmd p |
||||
return [bufnr, job_info(job).process] |
||||
endif |
||||
endfunction |
||||
|
||||
function! coc#terminal#send(bufnr, text, add_new_line) abort |
||||
let chan = get(s:channel_map, a:bufnr, v:null) |
||||
if empty(chan) | return| endif |
||||
if has('nvim') |
||||
let lines = split(a:text, '\v\r?\n') |
||||
if a:add_new_line && !empty(lines[len(lines) - 1]) |
||||
if s:is_win |
||||
call add(lines, "\r\n") |
||||
else |
||||
call add(lines, '') |
||||
endif |
||||
endif |
||||
call chansend(chan, lines) |
||||
let winnr = bufwinnr(a:bufnr) |
||||
if winnr != -1 |
||||
exe 'noa '.winnr.'wincmd w' |
||||
exe 'noa normal! G' |
||||
exe 'noa '.wincmd p |
||||
endif |
||||
else |
||||
if !a:add_new_line |
||||
call ch_sendraw(chan, a:text) |
||||
else |
||||
call ch_sendraw(chan, a:text.(s:is_win ? "\r\n" : "\n")) |
||||
endif |
||||
endif |
||||
endfunction |
||||
|
||||
function! coc#terminal#close(bufnr) abort |
||||
if has('nvim') |
||||
let job_id = get(s:channel_map, a:bufnr, 0) |
||||
if !empty(job_id) |
||||
silent! call chanclose(job_id) |
||||
endif |
||||
endif |
||||
exe 'silent! bd! '.a:bufnr |
||||
endfunction |
@ -0,0 +1,960 @@
@@ -0,0 +1,960 @@
|
||||
scriptencoding utf-8 |
||||
let s:root = expand('<sfile>:h:h:h') |
||||
let s:is_win = has('win32') || has('win64') |
||||
let s:is_vim = !has('nvim') |
||||
let s:clear_match_by_id = has('nvim-0.5.0') || has('patch-8.1.1084') |
||||
let s:vim_api_version = 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 |
||||
|
||||
function! coc#util#has_preview() |
||||
for i in range(1, winnr('$')) |
||||
if getwinvar(i, '&previewwindow') |
||||
return i |
||||
endif |
||||
endfor |
||||
return 0 |
||||
endfunction |
||||
|
||||
function! coc#util#api_version() abort |
||||
return s:vim_api_version |
||||
endfunction |
||||
|
||||
" get cursor position |
||||
function! coc#util#cursor() |
||||
return [line('.') - 1, strchars(strpart(getline('.'), 0, col('.') - 1))] |
||||
endfunction |
||||
|
||||
function! coc#util#path_replace_patterns() abort |
||||
if has('win32unix') && exists('g:coc_cygqwin_path_prefixes') |
||||
echohl WarningMsg |
||||
echon 'g:coc_cygqwin_path_prefixes is deprecated, use g:coc_uri_prefix_replace_patterns instead' |
||||
echohl None |
||||
return g:coc_cygqwin_path_prefixes |
||||
endif |
||||
if exists('g:coc_uri_prefix_replace_patterns') |
||||
return g:coc_uri_prefix_replace_patterns |
||||
endif |
||||
return v:null |
||||
endfunction |
||||
|
||||
function! coc#util#version() |
||||
if s:is_vim |
||||
return string(v:versionlong) |
||||
endif |
||||
let c = execute('silent version') |
||||
let lines = split(matchstr(c, 'NVIM v\zs[^\n-]*')) |
||||
return lines[0] |
||||
endfunction |
||||
|
||||
function! coc#util#check_refresh(bufnr) |
||||
if !bufloaded(a:bufnr) |
||||
return 0 |
||||
endif |
||||
if getbufvar(a:bufnr, 'coc_diagnostic_disable', 0) |
||||
return 0 |
||||
endif |
||||
if get(g: , 'EasyMotion_loaded', 0) |
||||
return EasyMotion#is_active() != 1 |
||||
endif |
||||
return 1 |
||||
endfunction |
||||
|
||||
function! coc#util#open_file(cmd, file) |
||||
let file = fnameescape(a:file) |
||||
execute a:cmd .' '.file |
||||
endfunction |
||||
|
||||
function! coc#util#remote_fns(name) |
||||
let fns = ['init', 'complete', 'should_complete', 'refresh', 'get_startcol', 'on_complete', 'on_enter'] |
||||
let res = [] |
||||
for fn in fns |
||||
if exists('*coc#source#'.a:name.'#'.fn) |
||||
call add(res, fn) |
||||
endif |
||||
endfor |
||||
return res |
||||
endfunction |
||||
|
||||
function! coc#util#job_command() |
||||
if (has_key(g:, 'coc_node_path')) |
||||
let node = expand(g:coc_node_path) |
||||
else |
||||
let node = $COC_NODE_PATH == '' ? 'node' : $COC_NODE_PATH |
||||
endif |
||||
if !executable(node) |
||||
echohl Error | echom '[coc.nvim] "'.node.'" is not executable, checkout https://nodejs.org/en/download/' | echohl None |
||||
return |
||||
endif |
||||
if !filereadable(s:root.'/build/index.js') |
||||
echohl Error | echom '[coc.nvim] build/index.js not found, please compile coc.nvim by: npm run build' | echohl None |
||||
return |
||||
endif |
||||
return [node] + get(g:, 'coc_node_args', ['--no-warnings']) + [s:root.'/build/index.js'] |
||||
endfunction |
||||
|
||||
function! coc#util#echo_hover(msg) |
||||
echohl MoreMsg |
||||
echo a:msg |
||||
echohl None |
||||
let g:coc_last_hover_message = a:msg |
||||
endfunction |
||||
|
||||
function! coc#util#execute(cmd) |
||||
silent exe a:cmd |
||||
if &filetype ==# '' |
||||
filetype detect |
||||
endif |
||||
if s:is_vim |
||||
redraw! |
||||
endif |
||||
endfunction |
||||
|
||||
function! coc#util#jump(cmd, filepath, ...) abort |
||||
if a:cmd != 'pedit' |
||||
silent! normal! m' |
||||
endif |
||||
let path = a:filepath |
||||
if (has('win32unix')) |
||||
let path = substitute(a:filepath, '\v\\', '/', 'g') |
||||
endif |
||||
let file = fnamemodify(path, ":~:.") |
||||
if a:cmd == 'pedit' |
||||
let extra = empty(get(a:, 1, [])) ? '' : '+'.(a:1[0] + 1) |
||||
exe 'pedit '.extra.' '.fnameescape(file) |
||||
return |
||||
else |
||||
exe a:cmd.' '.fnameescape(file) |
||||
endif |
||||
if !empty(get(a:, 1, [])) |
||||
let line = getline(a:1[0] + 1) |
||||
" TODO need to use utf16 here |
||||
let col = byteidx(line, a:1[1]) + 1 |
||||
if col == 0 |
||||
let col = 999 |
||||
endif |
||||
call cursor(a:1[0] + 1, col) |
||||
endif |
||||
if &filetype ==# '' |
||||
filetype detect |
||||
endif |
||||
if s:is_vim |
||||
redraw |
||||
endif |
||||
endfunction |
||||
|
||||
function! coc#util#jumpTo(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 |
||||
|
||||
" Position of cursor relative to screen cell |
||||
function! coc#util#cursor_pos() abort |
||||
let nr = winnr() |
||||
let [row, col] = win_screenpos(nr) |
||||
return [row + winline() - 2, col + wincol() - 2] |
||||
endfunction |
||||
|
||||
function! coc#util#echo_messages(hl, msgs) |
||||
if a:hl !~# 'Error' && (mode() !~# '\v^(i|n)$') |
||||
return |
||||
endif |
||||
let msgs = filter(copy(a:msgs), '!empty(v:val)') |
||||
if empty(msgs) |
||||
return |
||||
endif |
||||
execute 'echohl '.a:hl |
||||
echom a:msgs[0] |
||||
redraw |
||||
echo join(msgs, "\n") |
||||
echohl None |
||||
endfunction |
||||
|
||||
function! coc#util#echo_lines(lines) |
||||
echo join(a:lines, "\n") |
||||
endfunction |
||||
|
||||
function! coc#util#timer(method, args) |
||||
call timer_start(0, { -> s:Call(a:method, a:args)}) |
||||
endfunction |
||||
|
||||
function! s:Call(method, args) |
||||
try |
||||
call call(a:method, a:args) |
||||
redraw |
||||
catch /.*/ |
||||
return 0 |
||||
endtry |
||||
endfunction |
||||
|
||||
function! coc#util#get_bufoptions(bufnr, maxFileSize) abort |
||||
if !bufloaded(a:bufnr) | return v:null | endif |
||||
let bufname = bufname(a:bufnr) |
||||
let buftype = getbufvar(a:bufnr, '&buftype') |
||||
let previewwindow = 0 |
||||
let winid = bufwinid(a:bufnr) |
||||
if winid != -1 |
||||
let previewwindow = getwinvar(winid, '&previewwindow', 0) |
||||
endif |
||||
let size = -1 |
||||
if bufnr('%') == a:bufnr |
||||
let size = line2byte(line("$") + 1) |
||||
elseif !empty(bufname) |
||||
let size = getfsize(bufname) |
||||
endif |
||||
let lines = [] |
||||
if getbufvar(a:bufnr, 'coc_enabled', 1) && (buftype == '' || buftype == 'acwrite') && size < a:maxFileSize |
||||
let lines = getbufline(a:bufnr, 1, '$') |
||||
endif |
||||
return { |
||||
\ 'bufname': bufname, |
||||
\ 'size': size, |
||||
\ 'buftype': buftype, |
||||
\ 'winid': winid, |
||||
\ 'previewwindow': previewwindow == 0 ? v:false : v:true, |
||||
\ 'variables': s:variables(a:bufnr), |
||||
\ 'fullpath': empty(bufname) ? '' : fnamemodify(bufname, ':p'), |
||||
\ 'eol': getbufvar(a:bufnr, '&eol'), |
||||
\ 'filetype': getbufvar(a:bufnr, '&filetype'), |
||||
\ 'iskeyword': getbufvar(a:bufnr, '&iskeyword'), |
||||
\ 'changedtick': getbufvar(a:bufnr, 'changedtick'), |
||||
\ 'lines': lines, |
||||
\} |
||||
endfunction |
||||
|
||||
function! s:variables(bufnr) abort |
||||
let info = getbufinfo(a:bufnr) |
||||
let variables = empty(info) ? {} : copy(info[0]['variables']) |
||||
for key in keys(variables) |
||||
if key !~# '\v^coc' |
||||
unlet variables[key] |
||||
endif |
||||
endfor |
||||
return variables |
||||
endfunction |
||||
|
||||
function! coc#util#root_patterns() abort |
||||
return coc#rpc#request('rootPatterns', [bufnr('%')]) |
||||
endfunction |
||||
|
||||
function! coc#util#get_config(key) abort |
||||
return coc#rpc#request('getConfig', [a:key]) |
||||
endfunction |
||||
|
||||
function! coc#util#on_error(msg) abort |
||||
echohl Error | echom '[coc.nvim] '.a:msg | echohl None |
||||
endfunction |
||||
|
||||
function! coc#util#preview_info(info, filetype, ...) abort |
||||
pclose |
||||
keepalt new +setlocal\ previewwindow|setlocal\ buftype=nofile|setlocal\ noswapfile|setlocal\ wrap [Document] |
||||
setl bufhidden=wipe |
||||
setl nobuflisted |
||||
setl nospell |
||||
exe 'setl filetype='.a:filetype |
||||
setl conceallevel=0 |
||||
setl nofoldenable |
||||
for command in a:000 |
||||
execute command |
||||
endfor |
||||
let lines = a:info |
||||
call append(0, lines) |
||||
exe "normal! z" . len(lines) . "\<cr>" |
||||
exe "normal! gg" |
||||
wincmd p |
||||
endfunction |
||||
|
||||
function! coc#util#get_config_home() |
||||
if !empty(get(g:, 'coc_config_home', '')) |
||||
return resolve(expand(g:coc_config_home)) |
||||
endif |
||||
if exists('$VIMCONFIG') |
||||
return resolve($VIMCONFIG) |
||||
endif |
||||
if has('nvim') |
||||
if exists('$XDG_CONFIG_HOME') |
||||
return resolve($XDG_CONFIG_HOME."/nvim") |
||||
endif |
||||
if s:is_win |
||||
return resolve($HOME.'/AppData/Local/nvim') |
||||
endif |
||||
return resolve($HOME.'/.config/nvim') |
||||
else |
||||
if s:is_win |
||||
return resolve($HOME."/vimfiles") |
||||
endif |
||||
return resolve($HOME.'/.vim') |
||||
endif |
||||
endfunction |
||||
|
||||
function! coc#util#get_data_home() |
||||
if !empty(get(g:, 'coc_data_home', '')) |
||||
let dir = resolve(expand(g:coc_data_home)) |
||||
else |
||||
if exists('$XDG_CONFIG_HOME') |
||||
let dir = resolve($XDG_CONFIG_HOME."/coc") |
||||
else |
||||
if s:is_win |
||||
let dir = resolve(expand('~/AppData/Local/coc')) |
||||
else |
||||
let dir = resolve(expand('~/.config/coc')) |
||||
endif |
||||
endif |
||||
endif |
||||
if !isdirectory(dir) |
||||
echohl MoreMsg | echom '[coc.nvim] creating data directory: '.dir | echohl None |
||||
call mkdir(dir, "p", 0755) |
||||
endif |
||||
return dir |
||||
endfunction |
||||
|
||||
function! coc#util#get_input() |
||||
let before = strpart(getline('.'), 0, col('.')-1) |
||||
if len(before) == 0 |
||||
return '' |
||||
endif |
||||
return matchstr(before, '\k*$') |
||||
endfunction |
||||
|
||||
function! coc#util#move_cursor(delta) |
||||
let pos = getcurpos() |
||||
call cursor(pos[1], pos[2] + a:delta) |
||||
endfunction |
||||
|
||||
function! coc#util#get_complete_option() |
||||
let pos = getcurpos() |
||||
let line = getline(pos[1]) |
||||
let input = matchstr(strpart(line, 0, pos[2] - 1), '\k*$') |
||||
let col = pos[2] - strlen(input) |
||||
let synname = synIDattr(synID(pos[1], col, 1), 'name') |
||||
return { |
||||
\ 'word': matchstr(strpart(line, col - 1), '^\k\+'), |
||||
\ 'input': empty(input) ? '' : input, |
||||
\ 'line': line, |
||||
\ 'filetype': &filetype, |
||||
\ 'filepath': expand('%:p'), |
||||
\ 'bufnr': bufnr('%'), |
||||
\ 'linenr': pos[1], |
||||
\ 'colnr' : pos[2], |
||||
\ 'col': col - 1, |
||||
\ 'synname': synname, |
||||
\ 'changedtick': b:changedtick, |
||||
\ 'blacklist': get(b:, 'coc_suggest_blacklist', []), |
||||
\} |
||||
endfunction |
||||
|
||||
function! coc#util#with_callback(method, args, cb) |
||||
function! s:Cb() closure |
||||
try |
||||
let res = call(a:method, a:args) |
||||
call a:cb(v:null, res) |
||||
catch /.*/ |
||||
call a:cb(v:exception) |
||||
endtry |
||||
endfunction |
||||
let timeout = s:is_vim ? 10 : 0 |
||||
call timer_start(timeout, {-> s:Cb() }) |
||||
endfunction |
||||
|
||||
function! coc#util#quickpick(title, items, cb) abort |
||||
if exists('*popup_menu') |
||||
function! s:QuickpickHandler(id, result) closure |
||||
call a:cb(v:null, a:result) |
||||
endfunction |
||||
function! s:QuickpickFilter(id, key) closure |
||||
for i in range(1, len(a:items)) |
||||
if a:key == string(i) |
||||
call popup_close(a:id, i) |
||||
return 1 |
||||
endif |
||||
endfor |
||||
" No shortcut, pass to generic filter |
||||
return popup_filter_menu(a:id, a:key) |
||||
endfunction |
||||
try |
||||
call popup_menu(a:items, { |
||||
\ 'title': a:title, |
||||
\ 'filter': function('s:QuickpickFilter'), |
||||
\ 'callback': function('s:QuickpickHandler'), |
||||
\ }) |
||||
redraw |
||||
catch /.*/ |
||||
call a:cb(v:exception) |
||||
endtry |
||||
else |
||||
let res = inputlist([a:title] + a:items) |
||||
call a:cb(v:null, res) |
||||
endif |
||||
endfunction |
||||
|
||||
function! coc#util#get_syntax_name(lnum, col) |
||||
return synIDattr(synIDtrans(synID(a:lnum,a:col,1)),"name") |
||||
endfunction |
||||
|
||||
function! coc#util#echo_signatures(signatures) abort |
||||
if pumvisible() | return | endif |
||||
echo "" |
||||
for i in range(len(a:signatures)) |
||||
call s:echo_signature(a:signatures[i]) |
||||
if i != len(a:signatures) - 1 |
||||
echon "\n" |
||||
endif |
||||
endfor |
||||
endfunction |
||||
|
||||
function! s:echo_signature(parts) |
||||
for part in a:parts |
||||
let hl = get(part, 'type', 'Normal') |
||||
let text = get(part, 'text', '') |
||||
if !empty(text) |
||||
execute 'echohl '.hl |
||||
execute "echon '".substitute(text, "'", "''", 'g')."'" |
||||
echohl None |
||||
endif |
||||
endfor |
||||
endfunction |
||||
|
||||
function! coc#util#unplace_signs(bufnr, sign_ids) |
||||
if !bufloaded(a:bufnr) | return | endif |
||||
for id in a:sign_ids |
||||
execute 'silent! sign unplace '.id.' buffer='.a:bufnr |
||||
endfor |
||||
endfunction |
||||
|
||||
function! coc#util#setline(lnum, line) |
||||
keepjumps call setline(a:lnum, a:line) |
||||
endfunction |
||||
|
||||
" cmd, cwd |
||||
function! coc#util#open_terminal(opts) abort |
||||
if s:is_vim && !exists('*term_start') |
||||
echohl WarningMsg | echon "Your vim doesn't have terminal support!" | echohl None |
||||
return |
||||
endif |
||||
if get(a:opts, 'position', 'bottom') ==# 'bottom' |
||||
let p = '5new' |
||||
else |
||||
let p = 'vnew' |
||||
endif |
||||
execute 'belowright '.p.' +setl\ buftype=nofile ' |
||||
setl buftype=nofile |
||||
setl winfixheight |
||||
setl norelativenumber |
||||
setl nonumber |
||||
setl bufhidden=wipe |
||||
let cmd = get(a:opts, 'cmd', '') |
||||
let autoclose = get(a:opts, 'autoclose', 1) |
||||
if empty(cmd) |
||||
throw 'command required!' |
||||
endif |
||||
let cwd = get(a:opts, 'cwd', getcwd()) |
||||
let keepfocus = get(a:opts, 'keepfocus', 0) |
||||
let bufnr = bufnr('%') |
||||
let Callback = get(a:opts, 'Callback', v:null) |
||||
|
||||
function! s:OnExit(status) closure |
||||
let content = join(getbufline(bufnr, 1, '$'), "\n") |
||||
if a:status == 0 && autoclose == 1 |
||||
execute 'silent! bd! '.bufnr |
||||
endif |
||||
if !empty(Callback) |
||||
call call(Callback, [a:status, bufnr, content]) |
||||
endif |
||||
endfunction |
||||
|
||||
if has('nvim') |
||||
call termopen(cmd, { |
||||
\ 'cwd': cwd, |
||||
\ 'on_exit': {job, status -> s:OnExit(status)}, |
||||
\}) |
||||
else |
||||
if s:is_win |
||||
let cmd = 'cmd.exe /C "'.cmd.'"' |
||||
endif |
||||
call term_start(cmd, { |
||||
\ 'cwd': cwd, |
||||
\ 'exit_cb': {job, status -> s:OnExit(status)}, |
||||
\ 'curwin': 1, |
||||
\}) |
||||
endif |
||||
if keepfocus |
||||
wincmd p |
||||
endif |
||||
return bufnr |
||||
endfunction |
||||
|
||||
" run command in terminal |
||||
function! coc#util#run_terminal(opts, cb) |
||||
let cmd = get(a:opts, 'cmd', '') |
||||
if empty(cmd) |
||||
return a:cb('command required for terminal') |
||||
endif |
||||
let opts = { |
||||
\ 'cmd': cmd, |
||||
\ 'cwd': get(a:opts, 'cwd', getcwd()), |
||||
\ 'keepfocus': get(a:opts, 'keepfocus', 0), |
||||
\ 'Callback': {status, bufnr, content -> a:cb(v:null, {'success': status == 0 ? v:true : v:false, 'bufnr': bufnr, 'content': content})} |
||||
\} |
||||
call coc#util#open_terminal(opts) |
||||
endfunction |
||||
|
||||
function! coc#util#getpid() |
||||
if !has('win32unix') |
||||
return getpid() |
||||
endif |
||||
let cmd = 'cat /proc/' . getpid() . '/winpid' |
||||
return substitute(system(cmd), '\v\n', '', 'gi') |
||||
endfunction |
||||
|
||||
function! coc#util#vim_info() |
||||
return { |
||||
\ 'apiversion': s:vim_api_version, |
||||
\ 'mode': mode(), |
||||
\ 'floating': has('nvim') && exists('*nvim_open_win') ? v:true : v:false, |
||||
\ 'extensionRoot': coc#util#extension_root(), |
||||
\ 'globalExtensions': get(g:, 'coc_global_extensions', []), |
||||
\ 'config': get(g:, 'coc_user_config', {}), |
||||
\ 'pid': coc#util#getpid(), |
||||
\ 'columns': &columns, |
||||
\ 'lines': &lines, |
||||
\ 'cmdheight': &cmdheight, |
||||
\ 'filetypeMap': get(g:, 'coc_filetype_map', {}), |
||||
\ 'version': coc#util#version(), |
||||
\ 'completeOpt': &completeopt, |
||||
\ 'pumevent': exists('##MenuPopupChanged') || exists('##CompleteChanged'), |
||||
\ 'isVim': has('nvim') ? v:false : v:true, |
||||
\ 'isCygwin': has('win32unix') ? v:true : v:false, |
||||
\ 'isMacvim': has('gui_macvim') ? v:true : v:false, |
||||
\ 'isiTerm': $TERM_PROGRAM ==# "iTerm.app", |
||||
\ 'colorscheme': get(g:, 'colors_name', ''), |
||||
\ 'workspaceFolders': get(g:, 'WorkspaceFolders', v:null), |
||||
\ 'background': &background, |
||||
\ 'runtimepath': &runtimepath, |
||||
\ 'locationlist': get(g:,'coc_enable_locationlist', 1), |
||||
\ 'progpath': v:progpath, |
||||
\ 'guicursor': &guicursor, |
||||
\ 'vimCommands': get(g:, 'coc_vim_commands', []), |
||||
\ 'sign': exists('*sign_place') && exists('*sign_unplace'), |
||||
\ 'textprop': has('textprop') && has('patch-8.1.1719') && !has('nvim') ? v:true : v:false, |
||||
\ 'dialog': has('nvim-0.4.0') || has('patch-8.2.0750') ? v:true : v:false, |
||||
\ 'disabledSources': get(g:, 'coc_sources_disable_map', {}), |
||||
\} |
||||
endfunction |
||||
|
||||
function! coc#util#highlight_options() |
||||
return { |
||||
\ 'colorscheme': get(g:, 'colors_name', ''), |
||||
\ 'background': &background, |
||||
\ 'runtimepath': &runtimepath, |
||||
\} |
||||
endfunction |
||||
|
||||
function! coc#util#set_lines(bufnr, replacement, start, end) abort |
||||
if !s:is_vim |
||||
call nvim_buf_set_lines(a:bufnr, a:start, a:end, 0, a:replacement) |
||||
else |
||||
call coc#api#notify('buf_set_lines', [a:bufnr, a:start, a:end, 0, a:replacement]) |
||||
endif |
||||
return { |
||||
\ 'lines': getbufline(a:bufnr, 1, '$'), |
||||
\ 'changedtick': getbufvar(a:bufnr, 'changedtick') |
||||
\ } |
||||
endfunction |
||||
|
||||
function! coc#util#change_lines(bufnr, list) abort |
||||
if !bufloaded(a:bufnr) | return v:null | endif |
||||
undojoin |
||||
if exists('*setbufline') |
||||
for [lnum, line] in a:list |
||||
call setbufline(a:bufnr, lnum + 1, line) |
||||
endfor |
||||
elseif a:bufnr == bufnr('%') |
||||
for [lnum, line] in a:list |
||||
call setline(lnum + 1, line) |
||||
endfor |
||||
else |
||||
let bufnr = bufnr('%') |
||||
exe 'noa buffer '.a:bufnr |
||||
for [lnum, line] in a:list |
||||
call setline(lnum + 1, line) |
||||
endfor |
||||
exe 'noa buffer '.bufnr |
||||
endif |
||||
return { |
||||
\ 'lines': getbufline(a:bufnr, 1, '$'), |
||||
\ 'changedtick': getbufvar(a:bufnr, 'changedtick') |
||||
\ } |
||||
endfunction |
||||
|
||||
|
||||
" used by vim |
||||
function! coc#util#get_buf_lines(bufnr, changedtick) |
||||
if !bufloaded(a:bufnr) | return '' | endif |
||||
let changedtick = getbufvar(a:bufnr, 'changedtick') |
||||
if changedtick == a:changedtick |
||||
return v:null |
||||
endif |
||||
return { |
||||
\ 'lines': getbufline(a:bufnr, 1, '$'), |
||||
\ 'changedtick': getbufvar(a:bufnr, 'changedtick') |
||||
\ } |
||||
endfunction |
||||
|
||||
" used for TextChangedI with InsertCharPre |
||||
function! coc#util#get_changeinfo() |
||||
return { |
||||
\ 'lnum': line('.'), |
||||
\ 'line': getline('.'), |
||||
\ 'changedtick': b:changedtick, |
||||
\} |
||||
endfunction |
||||
|
||||
" show diff of current buffer |
||||
function! coc#util#diff_content(lines) abort |
||||
let tmpfile = tempname() |
||||
setl foldenable |
||||
call writefile(a:lines, tmpfile) |
||||
let ft = &filetype |
||||
diffthis |
||||
execute 'vs '.tmpfile |
||||
if !empty(ft) |
||||
execute 'setf ' . ft |
||||
endif |
||||
diffthis |
||||
setl foldenable |
||||
endfunction |
||||
|
||||
function! coc#util#clear_signs() |
||||
let buflist = filter(range(1, bufnr('$')), 'buflisted(v:val)') |
||||
for b in buflist |
||||
let signIds = [] |
||||
let lines = split(execute('sign place buffer='.b), "\n") |
||||
for line in lines |
||||
let ms = matchlist(line, 'id=\(\d\+\)\s\+name=Coc') |
||||
if len(ms) > 0 |
||||
call add(signIds, ms[1]) |
||||
endif |
||||
endfor |
||||
call coc#util#unplace_signs(b, signIds) |
||||
endfor |
||||
endfunction |
||||
|
||||
function! coc#util#open_url(url) |
||||
if has('mac') && executable('open') |
||||
call system('open '.a:url) |
||||
return |
||||
endif |
||||
if executable('xdg-open') |
||||
call system('xdg-open '.a:url) |
||||
return |
||||
endif |
||||
call system('cmd /c start "" /b '. substitute(a:url, '&', '^&', 'g')) |
||||
if v:shell_error |
||||
echohl Error | echom 'Failed to open '.a:url | echohl None |
||||
return |
||||
endif |
||||
endfunction |
||||
|
||||
function! coc#util#install() abort |
||||
let yarncmd = get(g:, 'coc_install_yarn_cmd', executable('yarnpkg') ? 'yarnpkg' : 'yarn') |
||||
call coc#util#open_terminal({ |
||||
\ 'cwd': s:root, |
||||
\ 'cmd': yarncmd.' install --frozen-lockfile --ignore-engines', |
||||
\ 'autoclose': 0, |
||||
\ }) |
||||
endfunction |
||||
|
||||
function! coc#util#do_complete(name, opt, cb) abort |
||||
let handler = 'coc#source#'.a:name.'#complete' |
||||
let l:Cb = {res -> a:cb(v:null, res)} |
||||
let args = [a:opt, l:Cb] |
||||
call call(handler, args) |
||||
endfunction |
||||
|
||||
function! coc#util#extension_root() abort |
||||
if get(g:, 'coc_node_env', '') ==# 'test' |
||||
return s:root.'/src/__tests__/extensions' |
||||
endif |
||||
if !empty(get(g:, 'coc_extension_root', '')) |
||||
echohl Error | echon 'g:coc_extension_root not used any more, use g:coc_data_home instead' | echohl None |
||||
endif |
||||
return coc#util#get_data_home().'/extensions' |
||||
endfunction |
||||
|
||||
function! coc#util#update_extensions(...) abort |
||||
let async = get(a:, 1, 0) |
||||
if async |
||||
call coc#rpc#notify('updateExtensions', []) |
||||
else |
||||
call coc#rpc#request('updateExtensions', [v:true]) |
||||
endif |
||||
endfunction |
||||
|
||||
function! coc#util#install_extension(args) abort |
||||
let names = filter(copy(a:args), 'v:val !~# "^-"') |
||||
let isRequest = index(a:args, '-sync') != -1 |
||||
if isRequest |
||||
call coc#rpc#request('installExtensions', names) |
||||
else |
||||
call coc#rpc#notify('installExtensions', names) |
||||
endif |
||||
endfunction |
||||
|
||||
function! coc#util#do_autocmd(name) abort |
||||
if exists('#User#'.a:name) |
||||
exe 'doautocmd <nomodeline> User '.a:name |
||||
endif |
||||
endfunction |
||||
|
||||
function! coc#util#rebuild() |
||||
let dir = coc#util#extension_root() |
||||
if !isdirectory(dir) | return | endif |
||||
call coc#util#open_terminal({ |
||||
\ 'cwd': dir, |
||||
\ 'cmd': 'npm rebuild', |
||||
\ 'keepfocus': 1, |
||||
\}) |
||||
endfunction |
||||
|
||||
" content of first echo line |
||||
function! coc#util#echo_line() |
||||
let str = '' |
||||
let line = &lines - (&cmdheight - 1) |
||||
for i in range(1, &columns - 1) |
||||
let nr = screenchar(line, i) |
||||
let str = str . nr2char(nr) |
||||
endfor |
||||
return str |
||||
endfunction |
||||
|
||||
" [r, g, b] ['255', '255', '255'] |
||||
" return ['65535', '65535', '65535'] or return v:false to cancel |
||||
function! coc#util#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 s: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(s: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 |
||||
|
||||
function! coc#util#iterm_open(dir) |
||||
return s:osascript( |
||||
\ 'if application "iTerm2" is not running', |
||||
\ 'error', |
||||
\ 'end if') && s:osascript( |
||||
\ 'tell application "iTerm2"', |
||||
\ 'tell current window', |
||||
\ 'create tab with default profile', |
||||
\ 'tell current session', |
||||
\ 'write text "cd ' . a:dir . '"', |
||||
\ 'write text "clear"', |
||||
\ 'activate', |
||||
\ 'end tell', |
||||
\ 'end tell', |
||||
\ 'end tell') |
||||
endfunction |
||||
|
||||
function! s:osascript(...) abort |
||||
let args = join(map(copy(a:000), '" -e ".shellescape(v:val)'), '') |
||||
call s:system('osascript'. args) |
||||
return !v:shell_error |
||||
endfunction |
||||
|
||||
function! s:system(cmd) |
||||
let output = system(a:cmd) |
||||
if v:shell_error && output !=# "" |
||||
echohl Error | echom output | echohl None |
||||
return |
||||
endif |
||||
return output |
||||
endfunction |
||||
|
||||
function! coc#util#set_buf_var(bufnr, name, val) abort |
||||
if !bufloaded(a:bufnr) | return | endif |
||||
call setbufvar(a:bufnr, a:name, a:val) |
||||
endfunction |
||||
|
||||
function! coc#util#unmap(bufnr, keys) abort |
||||
if bufnr('%') == a:bufnr |
||||
for key in a:keys |
||||
exe 'silent! nunmap <buffer> '.key |
||||
endfor |
||||
endif |
||||
endfunction |
||||
|
||||
function! coc#util#open_files(files) |
||||
let bufnrs = [] |
||||
" added on latest vim8 |
||||
if exists('*bufadd') && exists('*bufload') |
||||
for file in a:files |
||||
let file = fnamemodify(file, ':.') |
||||
if bufloaded(file) |
||||
call add(bufnrs, bufnr(file)) |
||||
else |
||||
let bufnr = bufadd(file) |
||||
call bufload(file) |
||||
call add(bufnrs, bufnr) |
||||
call setbufvar(bufnr, '&buflisted', 1) |
||||
endif |
||||
endfor |
||||
else |
||||
noa keepalt 1new +setl\ bufhidden=wipe |
||||
for file in a:files |
||||
let file = fnamemodify(file, ':.') |
||||
execute 'noa edit +setl\ bufhidden=hide '.fnameescape(file) |
||||
if &filetype ==# '' |
||||
filetype detect |
||||
endif |
||||
call add(bufnrs, bufnr('%')) |
||||
endfor |
||||
noa close |
||||
endif |
||||
doautocmd BufEnter |
||||
return bufnrs |
||||
endfunction |
||||
|
||||
function! coc#util#refactor_foldlevel(lnum) abort |
||||
if a:lnum <= 2 | return 0 | endif |
||||
let line = getline(a:lnum) |
||||
if line =~# '^\%u3000\s*$' | return 0 | endif |
||||
return 1 |
||||
endfunction |
||||
|
||||
function! coc#util#get_pretext() abort |
||||
return strpart(getline('.'), 0, col('.') - 1) |
||||
endfunction |
||||
|
||||
function! coc#util#refactor_fold_text(lnum) abort |
||||
let range = '' |
||||
let info = get(b:line_infos, a:lnum, []) |
||||
if !empty(info) |
||||
let range = info[0].':'.info[1] |
||||
endif |
||||
return trim(getline(a:lnum)[3:]).' '.range |
||||
endfunction |
||||
|
||||
function! coc#util#set_buf_lines(bufnr, lines) abort |
||||
let res = setbufline(a:bufnr, 1, a:lines) |
||||
if res == 0 |
||||
silent call deletebufline(a:bufnr, len(a:lines) + 1, '$') |
||||
endif |
||||
endfunction |
||||
|
||||
" get tabsize & expandtab option |
||||
function! coc#util#get_format_opts(bufnr) abort |
||||
if a:bufnr && bufloaded(a:bufnr) |
||||
let tabsize = getbufvar(a:bufnr, '&shiftwidth') |
||||
if tabsize == 0 |
||||
let tabsize = getbufvar(a:bufnr, '&tabstop') |
||||
endif |
||||
return [tabsize, getbufvar(a:bufnr, '&expandtab')] |
||||
endif |
||||
let tabsize = &shiftwidth == 0 ? &tabstop : &shiftwidth |
||||
return [tabsize, &expandtab] |
||||
endfunction |
||||
|
||||
function! coc#util#clearmatches(ids, ...) |
||||
let winid = get(a:, 1, win_getid()) |
||||
call coc#highlight#clear_matches(winid, a:ids) |
||||
endfunction |
||||
|
||||
" Character offset of current cursor |
||||
function! coc#util#get_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 |
||||
|
||||
" Make sure window exists |
||||
function! coc#util#win_gotoid(winid) abort |
||||
noa let res = win_gotoid(a:winid) |
||||
if res == 0 |
||||
throw 'Invalid window number' |
||||
endif |
||||
endfunction |
@ -0,0 +1,86 @@
@@ -0,0 +1,86 @@
|
||||
scriptencoding utf-8 |
||||
let s:root = expand('<sfile>:h:h:h') |
||||
|
||||
function! s:checkEnvironment() abort |
||||
let valid = 1 |
||||
if !has('nvim-0.3.0') |
||||
let valid = 0 |
||||
call health#report_error('Neovim version not satisfied, 0.3.0 and above required') |
||||
endif |
||||
let node = get(g:, 'coc_node_path', $COC_NODE_PATH == '' ? 'node' : $COC_NODE_PATH) |
||||
if !executable(node) |
||||
let valid = 0 |
||||
call health#report_error('Executable node.js not found, install node.js from http://nodejs.org/') |
||||
endif |
||||
let output = system(node . ' --version') |
||||
if v:shell_error && output !=# "" |
||||
let valid = 0 |
||||
call health#report_error(output) |
||||
endif |
||||
let ms = matchlist(output, 'v\(\d\+\).\(\d\+\).\(\d\+\)') |
||||
if empty(ms) |
||||
let valid = 0 |
||||
call health#report_error('Unable to detect version of node, make sure your node executable is http://nodejs.org/') |
||||
elseif str2nr(ms[1]) < 12 || (str2nr(ms[1]) == 12 && str2nr(ms[2]) < 12) |
||||
let valid = 0 |
||||
call health#report_warn('Node.js version '.trim(output).' < 12.12.0, please upgrade node.js') |
||||
endif |
||||
if valid |
||||
call health#report_ok('Environment check passed') |
||||
endif |
||||
if has('pythonx') |
||||
try |
||||
silent pyx print("") |
||||
catch /.*/ |
||||
call health#report_warn('pyx command not work, some extensions may fail to work, checkout ":h pythonx"') |
||||
endtry |
||||
endif |
||||
return valid |
||||
endfunction |
||||
|
||||
function! s:checkCommand() |
||||
let file = s:root.'/build/index.js' |
||||
if filereadable(file) |
||||
call health#report_ok('Javascript bundle build/index.js found') |
||||
else |
||||
call health#report_error('Javascript entry not found, please compile coc.nvim by esbuild.') |
||||
endif |
||||
endfunction |
||||
|
||||
function! s:checkAutocmd() |
||||
let cmds = ['CursorHold', 'CursorHoldI', 'CursorMovedI', 'InsertCharPre', 'TextChangedI'] |
||||
for cmd in cmds |
||||
let lines = split(execute('verbose autocmd '.cmd), '\n') |
||||
let n = 0 |
||||
for line in lines |
||||
if line =~# 'CocAction(' && n < len(lines) - 1 |
||||
let next = lines[n + 1] |
||||
let ms = matchlist(next, 'Last set from \(.*\)') |
||||
if !empty(ms) |
||||
call health#report_warn('Use CocActionAsync to replace CocAction for better performance on '.cmd) |
||||
call health#report_warn('Checkout the file '.ms[1]) |
||||
endif |
||||
endif |
||||
let n = n + 1 |
||||
endfor |
||||
endfor |
||||
endfunction |
||||
|
||||
function! s:checkInitailize() abort |
||||
if coc#client#is_running('coc') |
||||
call health#report_ok('Service started') |
||||
return 1 |
||||
endif |
||||
call health#report_error('service could not be initialized', [ |
||||
\ 'Use command ":messages" to get error messages.', |
||||
\ 'Open a issue at https://github.com/neoclide/coc.nvim/issues for feedback.' |
||||
\]) |
||||
return 0 |
||||
endfunction |
||||
|
||||
function! health#coc#check() abort |
||||
call s:checkEnvironment() |
||||
call s:checkCommand() |
||||
call s:checkInitailize() |
||||
call s:checkAutocmd() |
||||
endfunction |
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,50 @@
@@ -0,0 +1,50 @@
|
||||
{ |
||||
"name": "coc.nvim", |
||||
"version": "0.0.80", |
||||
"description": "LSP based intellisense engine for neovim & vim8.", |
||||
"main": "./lib/index.js", |
||||
"engines": { |
||||
"node": ">=8.10.0" |
||||
}, |
||||
"scripts": {}, |
||||
"repository": { |
||||
"type": "git", |
||||
"url": "git+https://github.com/neoclide/coc.nvim.git" |
||||
}, |
||||
"keywords": [ |
||||
"complete", |
||||
"neovim" |
||||
], |
||||
"author": "Qiming Zhao <chemzqm@gmail.com>", |
||||
"license": "MIT", |
||||
"bugs": { |
||||
"url": "https://github.com/neoclide/coc.nvim/issues" |
||||
}, |
||||
"homepage": "https://github.com/neoclide/coc.nvim#readme", |
||||
"jest": { |
||||
"globals": { |
||||
"__TEST__": true |
||||
}, |
||||
"projects": [ |
||||
"<rootDir>" |
||||
], |
||||
"watchman": false, |
||||
"clearMocks": true, |
||||
"globalSetup": "./jest.js", |
||||
"testEnvironment": "node", |
||||
"moduleFileExtensions": [ |
||||
"ts", |
||||
"tsx", |
||||
"json", |
||||
"js" |
||||
], |
||||
"transform": { |
||||
"^.+\\.tsx?$": "ts-jest" |
||||
}, |
||||
"testRegex": "src/__tests__/.*\\.(test|spec)\\.ts$", |
||||
"coverageDirectory": "./coverage/" |
||||
}, |
||||
"devDependencies": {}, |
||||
"dependencies": {} |
||||
} |
||||
|
@ -0,0 +1,520 @@
@@ -0,0 +1,520 @@
|
||||
scriptencoding utf-8 |
||||
if exists('g:did_coc_loaded') || v:version < 800 |
||||
finish |
||||
endif |
||||
|
||||
function! s:checkVersion() abort |
||||
let l:unsupported = 0 |
||||
if get(g:, 'coc_disable_startup_warning', 0) != 1 |
||||
if has('nvim') |
||||
let l:unsupported = !has('nvim-0.3.2') |
||||
else |
||||
let l:unsupported = !has('patch-8.0.1453') |
||||
endif |
||||
|
||||
if l:unsupported == 1 |
||||
echohl Error |
||||
echom "coc.nvim requires at least Vim 8.0.1453 or Neovim 0.3.2, but you're using an older version." |
||||
echom "Please upgrade your (neo)vim." |
||||
echom "You can add this to your vimrc to avoid this message:" |
||||
echom " let g:coc_disable_startup_warning = 1" |
||||
echom "Note that some features may error out or behave incorrectly." |
||||
echom "Please do not report bugs unless you're using at least Vim 8.0.1453 or Neovim 0.3.2." |
||||
echohl None |
||||
sleep 2 |
||||
else |
||||
if !has('nvim-0.4.0') && !has('patch-8.1.1719') |
||||
echohl WarningMsg |
||||
echom "coc.nvim works best on vim >= 8.1.1719 and neovim >= 0.4.0, consider upgrade your vim." |
||||
echom "You can add this to your vimrc to avoid this message:" |
||||
echom " let g:coc_disable_startup_warning = 1" |
||||
echom "Note that some features may behave incorrectly." |
||||
echohl None |
||||
sleep 2 |
||||
endif |
||||
endif |
||||
endif |
||||
endfunction |
||||
|
||||
call s:checkVersion() |
||||
|
||||
let g:did_coc_loaded = 1 |
||||
let g:coc_workspace_initialized = 0 |
||||
let g:coc_service_initialized = 0 |
||||
let s:is_win = has('win32') || has('win64') |
||||
let s:root = expand('<sfile>:h:h') |
||||
let s:is_vim = !has('nvim') |
||||
let s:is_gvim = get(v:, 'progname', '') ==# 'gvim' |
||||
|
||||
if get(g:, 'coc_start_at_startup', 1) && !s:is_gvim |
||||
call coc#rpc#start_server() |
||||
endif |
||||
|
||||
function! CocTagFunc(pattern, flags, info) abort |
||||
if a:flags !=# 'c' |
||||
" use standard tag search |
||||
return v:null |
||||
endif |
||||
return coc#rpc#request('getTagList', []) |
||||
endfunction |
||||
|
||||
function! CocPopupCallback(bufnr, arglist) abort |
||||
if len(a:arglist) == 2 |
||||
if a:arglist[0] == 'confirm' |
||||
call coc#rpc#notify('PromptInsert', [a:arglist[1]]) |
||||
elseif a:arglist[0] == 'exit' |
||||
execute 'silent! bd! '.a:bufnr |
||||
"call coc#rpc#notify('PromptUpdate', [a:arglist[1]]) |
||||
endif |
||||
endif |
||||
endfunction |
||||
|
||||
function! CocAction(name, ...) abort |
||||
if !get(g:, 'coc_service_initialized', 0) |
||||
throw 'coc.nvim not ready when invoke CocAction "'.a:name.'"' |
||||
endif |
||||
return coc#rpc#request(a:name, a:000) |
||||
endfunction |
||||
|
||||
function! CocHasProvider(name) abort |
||||
return coc#rpc#request('hasProvider', [a:name]) |
||||
endfunction |
||||
|
||||
function! CocActionAsync(name, ...) abort |
||||
return s:AsyncRequest(a:name, a:000) |
||||
endfunction |
||||
|
||||
function! CocRequest(...) abort |
||||
return coc#rpc#request('sendRequest', a:000) |
||||
endfunction |
||||
|
||||
function! CocNotify(...) abort |
||||
return coc#rpc#request('sendNotification', a:000) |
||||
endfunction |
||||
|
||||
function! CocRegistNotification(id, method, cb) abort |
||||
call coc#on_notify(a:id, a:method, a:cb) |
||||
endfunction |
||||
|
||||
function! CocLocations(id, method, ...) abort |
||||
let args = [a:id, a:method] + copy(a:000) |
||||
call coc#rpc#request('findLocations', args) |
||||
endfunction |
||||
|
||||
function! CocLocationsAsync(id, method, ...) abort |
||||
let args = [a:id, a:method] + copy(a:000) |
||||
call coc#rpc#notify('findLocations', args) |
||||
endfunction |
||||
|
||||
function! CocRequestAsync(...) |
||||
return s:AsyncRequest('sendRequest', a:000) |
||||
endfunction |
||||
|
||||
function! s:AsyncRequest(name, args) abort |
||||
let Cb = empty(a:args)? v:null : a:args[len(a:args) - 1] |
||||
if type(Cb) == 2 |
||||
if !coc#rpc#ready() |
||||
call Cb('service not started', v:null) |
||||
else |
||||
call coc#rpc#request_async(a:name, a:args[0:-2], Cb) |
||||
endif |
||||
return '' |
||||
endif |
||||
call coc#rpc#notify(a:name, a:args) |
||||
return '' |
||||
endfunction |
||||
|
||||
function! s:CommandList(...) abort |
||||
let list = coc#rpc#request('commandList', a:000) |
||||
return join(list, "\n") |
||||
endfunction |
||||
|
||||
function! s:ExtensionList(...) abort |
||||
let stats = CocAction('extensionStats') |
||||
call filter(stats, 'v:val["isLocal"] == v:false') |
||||
let list = map(stats, 'v:val["id"]') |
||||
return join(list, "\n") |
||||
endfunction |
||||
|
||||
function! s:SearchOptions(...) abort |
||||
let list = ['-e', '--regexp', '-F', '--fixed-strings', '-L', '--follow', |
||||
\ '-g', '--glob', '--hidden', '--no-hidden', '--no-ignore-vcs', |
||||
\ '--word-regexp', '-w', '--smart-case', '-S', '--no-config', |
||||
\ '--line-regexp', '--no-ignore', '-x'] |
||||
return join(list, "\n") |
||||
endfunction |
||||
|
||||
function! s:LoadedExtensions(...) abort |
||||
let list = CocAction('loadedExtensions') |
||||
return join(list, "\n") |
||||
endfunction |
||||
|
||||
function! s:InstallOptions(...)abort |
||||
let list = ['-terminal', '-sync'] |
||||
return join(list, "\n") |
||||
endfunction |
||||
|
||||
function! s:OpenConfig() |
||||
let home = coc#util#get_config_home() |
||||
if !isdirectory(home) |
||||
echohl MoreMsg |
||||
echom 'Config directory "'.home.'" not exists, create? (y/n)' |
||||
echohl None |
||||
let confirm = nr2char(getchar()) |
||||
redraw! |
||||
if !(confirm ==? "y" || confirm ==? "\r") |
||||
return |
||||
else |
||||
call mkdir(home, 'p') |
||||
end |
||||
endif |
||||
execute 'edit '.home.'/coc-settings.json' |
||||
endfunction |
||||
|
||||
function! s:get_color(item, fallback) abort |
||||
let t = type(a:item) |
||||
if t == 1 |
||||
return a:item |
||||
endif |
||||
if t == 4 |
||||
let item = get(a:item, 'gui', {}) |
||||
let color = get(item, &background, a:fallback) |
||||
return type(color) == 1 ? color : a:fallback |
||||
endif |
||||
return a:fallback |
||||
endfunction |
||||
|
||||
function! s:AddAnsiGroups() abort |
||||
let color_map = {} |
||||
let colors = ['#282828', '#cc241d', '#98971a', '#d79921', '#458588', '#b16286', '#689d6a', '#a89984', '#928374'] |
||||
let names = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'grey'] |
||||
for i in range(0, len(names) - 1) |
||||
let name = names[i] |
||||
if exists('g:terminal_ansi_colors') |
||||
let color_map[name] = s:get_color(get(g:terminal_ansi_colors, i, colors[i]), colors[i]) |
||||
else |
||||
let color_map[name] = get(g:, 'terminal_color_'.i, colors[i]) |
||||
endif |
||||
endfor |
||||
try |
||||
for name in keys(color_map) |
||||
let foreground = toupper(name[0]).name[1:] |
||||
let foregroundColor = color_map[name] |
||||
for key in keys(color_map) |
||||
let background = toupper(key[0]).key[1:] |
||||
let backgroundColor = color_map[key] |
||||
exe 'hi default CocList'.foreground.background.' guifg='.foregroundColor.' guibg='.backgroundColor |
||||
endfor |
||||
exe 'hi default CocListFg'.foreground. ' guifg='.foregroundColor. ' ctermfg='.foreground |
||||
exe 'hi default CocListBg'.foreground. ' guibg='.foregroundColor. ' ctermbg='.foreground |
||||
endfor |
||||
catch /.*/ |
||||
" ignore invalid color |
||||
endtry |
||||
endfunction |
||||
|
||||
function! s:CursorRangeFromSelected(type, ...) abort |
||||
" add range by operator |
||||
call coc#rpc#request('cursorsSelect', [bufnr('%'), 'operator', a:type]) |
||||
endfunction |
||||
|
||||
function! s:OpenDiagnostics(...) abort |
||||
let height = get(a:, 1, 0) |
||||
call coc#rpc#request('fillDiagnostics', [bufnr('%')]) |
||||
if height |
||||
execute ':lopen '.height |
||||
else |
||||
lopen |
||||
endif |
||||
endfunction |
||||
|
||||
function! s:Disable() abort |
||||
if get(g:, 'coc_enabled', 0) == 0 |
||||
return |
||||
endif |
||||
augroup coc_nvim |
||||
autocmd! |
||||
augroup end |
||||
call coc#rpc#request('detach', []) |
||||
echohl MoreMsg |
||||
echom '[coc.nvim] Event disabled' |
||||
echohl None |
||||
let g:coc_enabled = 0 |
||||
endfunction |
||||
|
||||
function! s:Autocmd(...) abort |
||||
if !g:coc_workspace_initialized |
||||
return |
||||
endif |
||||
call coc#rpc#notify('CocAutocmd', a:000) |
||||
endfunction |
||||
|
||||
function! s:SyncAutocmd(...) |
||||
if !g:coc_workspace_initialized |
||||
return |
||||
endif |
||||
if g:coc_service_initialized |
||||
call coc#rpc#request('CocAutocmd', a:000) |
||||
else |
||||
call coc#rpc#notify('CocAutocmd', a:000) |
||||
endif |
||||
endfunction |
||||
|
||||
function! s:Enable(initialize) |
||||
if get(g:, 'coc_enabled', 0) == 1 |
||||
return |
||||
endif |
||||
let g:coc_enabled = 1 |
||||
|
||||
augroup coc_nvim |
||||
autocmd! |
||||
|
||||
if exists('##MenuPopupChanged') && exists('*nvim_open_win') |
||||
autocmd MenuPopupChanged * call s:Autocmd('MenuPopupChanged', get(v:, 'event', {}), win_screenpos(winnr())[0] + winline() - 2) |
||||
endif |
||||
if exists('##CompleteChanged') |
||||
autocmd CompleteChanged * call s:Autocmd('MenuPopupChanged', get(v:, 'event', {}), win_screenpos(winnr())[0] + winline() - 2) |
||||
endif |
||||
|
||||
if coc#rpc#started() |
||||
autocmd VimEnter * call coc#rpc#notify('VimEnter', []) |
||||
elseif get(g:, 'coc_start_at_startup', 1) |
||||
autocmd VimEnter * call coc#rpc#start_server() |
||||
endif |
||||
if s:is_vim |
||||
if exists('##DirChanged') |
||||
autocmd DirChanged * call s:Autocmd('DirChanged', getcwd()) |
||||
endif |
||||
if exists('##TerminalOpen') |
||||
autocmd TerminalOpen * call s:Autocmd('TermOpen', +expand('<abuf>')) |
||||
endif |
||||
else |
||||
autocmd DirChanged * call s:Autocmd('DirChanged', get(v:event, 'cwd', '')) |
||||
autocmd TermOpen * call s:Autocmd('TermOpen', +expand('<abuf>')) |
||||
autocmd TermClose * call s:Autocmd('TermClose', +expand('<abuf>')) |
||||
autocmd CursorMoved * call coc#float#nvim_refresh_scrollbar(win_getid()) |
||||
autocmd WinEnter * call coc#float#nvim_win_enter(win_getid()) |
||||
if exists('##WinClosed') |
||||
autocmd WinClosed * call coc#float#close_related(+expand('<afile>')) |
||||
endif |
||||
endif |
||||
if has('nvim-0.4.0') || has('patch-8.1.1719') |
||||
autocmd CursorHold * call coc#float#check_related() |
||||
endif |
||||
autocmd WinLeave * call s:Autocmd('WinLeave', win_getid()) |
||||
autocmd WinEnter * call s:Autocmd('WinEnter', win_getid()) |
||||
autocmd BufWinLeave * call s:Autocmd('BufWinLeave', +expand('<abuf>'), bufwinid(+expand('<abuf>'))) |
||||
autocmd BufWinEnter * call s:Autocmd('BufWinEnter', +expand('<abuf>'), win_getid()) |
||||
autocmd FileType * call s:Autocmd('FileType', expand('<amatch>'), +expand('<abuf>')) |
||||
autocmd CompleteDone * call s:Autocmd('CompleteDone', get(v:, 'completed_item', {})) |
||||
autocmd InsertCharPre * call s:Autocmd('InsertCharPre', v:char) |
||||
if exists('##TextChangedP') |
||||
autocmd TextChangedP * call s:Autocmd('TextChangedP', +expand('<abuf>'), {'lnum': line('.'), 'col': col('.'), 'pre': strpart(getline('.'), 0, col('.') - 1), 'changedtick': b:changedtick}) |
||||
endif |
||||
autocmd TextChangedI * call s:Autocmd('TextChangedI', +expand('<abuf>'), {'lnum': line('.'), 'col': col('.'), 'pre': strpart(getline('.'), 0, col('.') - 1), 'changedtick': b:changedtick}) |
||||
autocmd InsertLeave * call s:Autocmd('InsertLeave', +expand('<abuf>')) |
||||
autocmd InsertEnter * call s:Autocmd('InsertEnter', +expand('<abuf>')) |
||||
autocmd BufHidden * call s:Autocmd('BufHidden', +expand('<abuf>')) |
||||
autocmd BufEnter * call s:Autocmd('BufEnter', +expand('<abuf>')) |
||||
autocmd TextChanged * call s:Autocmd('TextChanged', +expand('<abuf>'), getbufvar(+expand('<abuf>'), 'changedtick')) |
||||
autocmd BufWritePost * call s:Autocmd('BufWritePost', +expand('<abuf>')) |
||||
autocmd CursorMoved * call s:Autocmd('CursorMoved', +expand('<abuf>'), [line('.'), col('.')]) |
||||
autocmd CursorMovedI * call s:Autocmd('CursorMovedI', +expand('<abuf>'), [line('.'), col('.')]) |
||||
autocmd CursorHold * call s:Autocmd('CursorHold', +expand('<abuf>')) |
||||
autocmd CursorHoldI * call s:Autocmd('CursorHoldI', +expand('<abuf>')) |
||||
autocmd BufNewFile,BufReadPost * call s:Autocmd('BufCreate', +expand('<abuf>')) |
||||
autocmd BufUnload * call s:Autocmd('BufUnload', +expand('<abuf>')) |
||||
autocmd BufWritePre * call s:SyncAutocmd('BufWritePre', +expand('<abuf>')) |
||||
autocmd FocusGained * if mode() !~# '^c' | call s:Autocmd('FocusGained') | endif |
||||
autocmd FocusLost * call s:Autocmd('FocusLost') |
||||
autocmd VimResized * call s:Autocmd('VimResized', &columns, &lines) |
||||
autocmd VimLeavePre * let g:coc_vim_leaving = 1 |
||||
autocmd BufReadCmd,FileReadCmd,SourceCmd list://* call coc#list#setup(expand('<amatch>')) |
||||
autocmd BufWriteCmd __coc_refactor__* :call coc#rpc#notify('saveRefactor', [+expand('<abuf>')]) |
||||
autocmd ColorScheme * call s:Hi() |
||||
augroup end |
||||
if a:initialize == 0 |
||||
call coc#rpc#request('attach', []) |
||||
echohl MoreMsg |
||||
echom '[coc.nvim] Event enabled' |
||||
echohl None |
||||
endif |
||||
endfunction |
||||
|
||||
function! s:Hi() abort |
||||
hi default CocErrorSign ctermfg=Red guifg=#ff0000 guibg=NONE |
||||
hi default CocWarningSign ctermfg=Brown guifg=#ff922b guibg=NONE |
||||
hi default CocInfoSign ctermfg=Yellow guifg=#fab005 guibg=NONE |
||||
hi default CocHintSign ctermfg=Blue guifg=#15aabf guibg=NONE |
||||
hi default CocSelectedText ctermfg=Red guifg=#fb4934 guibg=NONE |
||||
hi default CocCodeLens ctermfg=Gray guifg=#999999 guibg=NONE |
||||
hi default CocUnderline cterm=underline gui=underline |
||||
hi default CocBold term=bold cterm=bold gui=bold |
||||
hi default CocItalic term=italic cterm=italic gui=italic |
||||
if s:is_vim || has('nvim-0.4.0') |
||||
hi default CocStrikeThrough guifg=#989898 ctermfg=gray cterm=strikethrough gui=strikethrough |
||||
else |
||||
hi default CocStrikeThrough guifg=#989898 ctermfg=gray |
||||
endif |
||||
hi default CocFadeOut guifg=#928374 ctermfg=245 |
||||
hi default CocMarkdownLink ctermfg=Blue guifg=#15aabf guibg=NONE |
||||
hi default link CocMarkdownCode markdownCode |
||||
hi default link CocMarkdownHeader markdownH1 |
||||
hi default link CocMenuSel PmenuSel |
||||
hi default link CocErrorFloat CocErrorSign |
||||
hi default link CocWarningFloat CocWarningSign |
||||
hi default link CocInfoFloat CocInfoSign |
||||
hi default link CocHintFloat CocHintSign |
||||
hi default link CocErrorHighlight CocUnderline |
||||
hi default link CocWarningHighlight CocUnderline |
||||
hi default link CocInfoHighlight CocUnderline |
||||
hi default link CocHintHighlight CocUnderline |
||||
hi default link CocListMode ModeMsg |
||||
hi default link CocListPath Comment |
||||
hi default link CocHighlightText CursorColumn |
||||
hi default link CocHoverRange Search |
||||
hi default link CocCursorRange Search |
||||
hi default link CocHighlightRead CocHighlightText |
||||
hi default link CocHighlightWrite CocHighlightText |
||||
if has('nvim') |
||||
hi default link CocFloating NormalFloat |
||||
else |
||||
hi default link CocFloating Pmenu |
||||
endif |
||||
if !exists('*sign_getdefined') || empty(sign_getdefined('CocCurrentLine')) |
||||
sign define CocCurrentLine linehl=CocMenuSel |
||||
endif |
||||
if has('nvim-0.5.0') |
||||
hi default CocCursorTransparent gui=strikethrough blend=100 |
||||
endif |
||||
|
||||
if has('nvim') |
||||
let names = ['Error', 'Warning', 'Info', 'Hint'] |
||||
for name in names |
||||
if !hlexists('Coc'.name.'VirtualText') |
||||
exe 'hi default link Coc'.name.'VirtualText Coc'.name.'Sign' |
||||
endif |
||||
endfor |
||||
endif |
||||
call s:AddAnsiGroups() |
||||
endfunction |
||||
|
||||
function! s:FormatFromSelected(type) |
||||
call CocActionAsync('formatSelected', a:type) |
||||
endfunction |
||||
|
||||
function! s:CodeActionFromSelected(type) |
||||
call CocActionAsync('codeAction', a:type) |
||||
endfunction |
||||
|
||||
function! s:ShowInfo() |
||||
if coc#rpc#ready() |
||||
call coc#rpc#notify('showInfo', []) |
||||
else |
||||
let lines = [] |
||||
echomsg 'coc.nvim service not started, checking environment...' |
||||
let node = get(g:, 'coc_node_path', $COC_NODE_PATH == '' ? 'node' : $COC_NODE_PATH) |
||||
if !executable(node) |
||||
call add(lines, 'Error: '.node.' is not executable!') |
||||
else |
||||
let output = trim(system(node . ' --version')) |
||||
let ms = matchlist(output, 'v\(\d\+\).\(\d\+\).\(\d\+\)') |
||||
if empty(ms) || str2nr(ms[1]) < 12 || (str2nr(ms[1]) == 12 && str2nr(ms[2]) < 12) |
||||
call add(lines, 'Error: Node version '.output.' < 12.12.0, please upgrade node.js') |
||||
endif |
||||
endif |
||||
" check bundle |
||||
let file = s:root.'/build/index.js' |
||||
if !filereadable(file) |
||||
call add(lines, 'Error: javascript bundle not found, please compile code of coc.nvim by esbuild.') |
||||
endif |
||||
if !empty(lines) |
||||
belowright vnew |
||||
setl filetype=nofile |
||||
call setline(1, lines) |
||||
else |
||||
if get(g:, 'coc_start_at_startup',1) |
||||
echohl MoreMsg | echon 'Service stopped for some unknown reason, try :CocStart' | echohl None |
||||
else |
||||
echohl MoreMsg | echon 'Start on startup is disabled, try :CocStart' | echohl None |
||||
endif |
||||
endif |
||||
endif |
||||
endfunction |
||||
|
||||
command! -nargs=? CocDiagnostics :call s:OpenDiagnostics(<f-args>) |
||||
command! -nargs=0 CocInfo :call s:ShowInfo() |
||||
command! -nargs=0 CocOpenLog :call coc#rpc#notify('openLog', []) |
||||
command! -nargs=0 CocDisable :call s:Disable() |
||||
command! -nargs=0 CocEnable :call s:Enable(0) |
||||
command! -nargs=0 CocConfig :call s:OpenConfig() |
||||
command! -nargs=0 CocLocalConfig :call coc#rpc#notify('openLocalConfig', []) |
||||
command! -nargs=0 CocRestart :call coc#rpc#restart() |
||||
command! -nargs=0 CocStart :call coc#rpc#start_server() |
||||
command! -nargs=0 CocRebuild :call coc#util#rebuild() |
||||
command! -nargs=1 -complete=custom,s:LoadedExtensions CocWatch :call coc#rpc#notify('watchExtension', [<f-args>]) |
||||
command! -nargs=+ -complete=custom,s:SearchOptions CocSearch :call coc#rpc#notify('search', [<f-args>]) |
||||
command! -nargs=+ -complete=custom,s:ExtensionList CocUninstall :call CocActionAsync('uninstallExtension', <f-args>) |
||||
command! -nargs=* -complete=custom,s:CommandList -range CocCommand :call coc#rpc#notify('runCommand', [<f-args>]) |
||||
command! -nargs=* -complete=custom,coc#list#options CocList :call coc#rpc#notify('openList', [<f-args>]) |
||||
command! -nargs=? -complete=custom,coc#list#names CocListResume :call coc#rpc#notify('listResume', [<f-args>]) |
||||
command! -nargs=0 -complete=custom,coc#list#names CocListCancel :call coc#rpc#notify('listCancel', []) |
||||
command! -nargs=? -complete=custom,coc#list#names CocPrev :call coc#rpc#notify('listPrev', [<f-args>]) |
||||
command! -nargs=? -complete=custom,coc#list#names CocNext :call coc#rpc#notify('listNext', [<f-args>]) |
||||
command! -nargs=? -complete=custom,coc#list#names CocFirst :call coc#rpc#notify('listFirst', [<f-args>]) |
||||
command! -nargs=? -complete=custom,coc#list#names CocLast :call coc#rpc#notify('listLast', [<f-args>]) |
||||
command! -nargs=* -range CocAction :call coc#rpc#notify('codeActionRange', [<line1>, <line2>, <f-args>]) |
||||
command! -nargs=* -range CocFix :call coc#rpc#notify('codeActionRange', [<line1>, <line2>, 'quickfix']) |
||||
command! -nargs=0 CocUpdate :call coc#util#update_extensions(1) |
||||
command! -nargs=0 -bar CocUpdateSync :call coc#util#update_extensions() |
||||
command! -nargs=* -bar -complete=custom,s:InstallOptions CocInstall :call coc#util#install_extension([<f-args>]) |
||||
|
||||
call s:Enable(1) |
||||
call s:Hi() |
||||
|
||||
vnoremap <silent> <Plug>(coc-range-select) :<C-u>call CocActionAsync('rangeSelect', visualmode(), v:true)<CR> |
||||
vnoremap <silent> <Plug>(coc-range-select-backward) :<C-u>call CocActionAsync('rangeSelect', visualmode(), v:false)<CR> |
||||
nnoremap <Plug>(coc-range-select) :<C-u>call CocActionAsync('rangeSelect', '', v:true)<CR> |
||||
nnoremap <Plug>(coc-codelens-action) :<C-u>call CocActionAsync('codeLensAction')<CR> |
||||
vnoremap <silent> <Plug>(coc-format-selected) :<C-u>call CocActionAsync('formatSelected', visualmode())<CR> |
||||
vnoremap <silent> <Plug>(coc-codeaction-selected) :<C-u>call CocActionAsync('codeAction', visualmode())<CR> |
||||
nnoremap <Plug>(coc-codeaction-selected) :<C-u>set operatorfunc=<SID>CodeActionFromSelected<CR>g@ |
||||
nnoremap <Plug>(coc-codeaction) :<C-u>call CocActionAsync('codeAction', '')<CR> |
||||
nnoremap <Plug>(coc-codeaction-line) :<C-u>call CocActionAsync('codeAction', 'line')<CR> |
||||
nnoremap <Plug>(coc-codeaction-cursor) :<C-u>call CocActionAsync('codeAction', 'cursor')<CR> |
||||
nnoremap <silent> <Plug>(coc-rename) :<C-u>call CocActionAsync('rename')<CR> |
||||
nnoremap <silent> <Plug>(coc-format-selected) :<C-u>set operatorfunc=<SID>FormatFromSelected<CR>g@ |
||||
nnoremap <silent> <Plug>(coc-format) :<C-u>call CocActionAsync('format')<CR> |
||||
nnoremap <silent> <Plug>(coc-diagnostic-info) :<C-u>call CocActionAsync('diagnosticInfo')<CR> |
||||
nnoremap <silent> <Plug>(coc-diagnostic-next) :<C-u>call CocActionAsync('diagnosticNext')<CR> |
||||
nnoremap <silent> <Plug>(coc-diagnostic-prev) :<C-u>call CocActionAsync('diagnosticPrevious')<CR> |
||||
nnoremap <silent> <Plug>(coc-diagnostic-next-error) :<C-u>call CocActionAsync('diagnosticNext', 'error')<CR> |
||||
nnoremap <silent> <Plug>(coc-diagnostic-prev-error) :<C-u>call CocActionAsync('diagnosticPrevious', 'error')<CR> |
||||
nnoremap <silent> <Plug>(coc-definition) :<C-u>call CocActionAsync('jumpDefinition')<CR> |
||||
nnoremap <silent> <Plug>(coc-declaration) :<C-u>call CocActionAsync('jumpDeclaration')<CR> |
||||
nnoremap <silent> <Plug>(coc-implementation) :<C-u>call CocActionAsync('jumpImplementation')<CR> |
||||
nnoremap <silent> <Plug>(coc-type-definition) :<C-u>call CocActionAsync('jumpTypeDefinition')<CR> |
||||
nnoremap <silent> <Plug>(coc-references) :<C-u>call CocActionAsync('jumpReferences')<CR> |
||||
nnoremap <silent> <Plug>(coc-references-used) :<C-u>call CocActionAsync('jumpUsed')<CR> |
||||
nnoremap <silent> <Plug>(coc-openlink) :<C-u>call CocActionAsync('openLink')<CR> |
||||
nnoremap <silent> <Plug>(coc-fix-current) :<C-u>call CocActionAsync('doQuickfix')<CR> |
||||
nnoremap <silent> <Plug>(coc-float-hide) :<C-u>call coc#float#close_all()<CR> |
||||
nnoremap <silent> <Plug>(coc-float-jump) :<c-u>call coc#float#jump()<cr> |
||||
nnoremap <silent> <Plug>(coc-command-repeat) :<C-u>call CocAction('repeatCommand')<CR> |
||||
nnoremap <silent> <Plug>(coc-refactor) :<C-u>call CocActionAsync('refactor')<CR> |
||||
inoremap <silent> <Plug>CocRefresh <C-r>=coc#_complete()<CR> |
||||
|
||||
nnoremap <silent> <Plug>(coc-cursors-operator) :<C-u>set operatorfunc=<SID>CursorRangeFromSelected<CR>g@ |
||||
vnoremap <silent> <Plug>(coc-cursors-range) :<C-u>call coc#rpc#request('cursorsSelect', [bufnr('%'), 'range', visualmode()])<CR> |
||||
nnoremap <silent> <Plug>(coc-cursors-word) :<C-u>call coc#rpc#request('cursorsSelect', [bufnr('%'), 'word', 'n'])<CR> |
||||
nnoremap <silent> <Plug>(coc-cursors-position) :<C-u>call coc#rpc#request('cursorsSelect', [bufnr('%'), 'position', 'n'])<CR> |
||||
|
||||
vnoremap <silent> <Plug>(coc-funcobj-i) :<C-U>call coc#rpc#request('selectSymbolRange', [v:true, visualmode(), ['Method', 'Function']])<CR> |
||||
vnoremap <silent> <Plug>(coc-funcobj-a) :<C-U>call coc#rpc#request('selectSymbolRange', [v:false, visualmode(), ['Method', 'Function']])<CR> |
||||
onoremap <silent> <Plug>(coc-funcobj-i) :<C-U>call coc#rpc#request('selectSymbolRange', [v:true, '', ['Method', 'Function']])<CR> |
||||
onoremap <silent> <Plug>(coc-funcobj-a) :<C-U>call coc#rpc#request('selectSymbolRange', [v:false, '', ['Method', 'Function']])<CR> |
||||
|
||||
vnoremap <silent> <Plug>(coc-classobj-i) :<C-U>call coc#rpc#request('selectSymbolRange', [v:true, visualmode(), ['Interface', 'Struct', 'Class']])<CR> |
||||
vnoremap <silent> <Plug>(coc-classobj-a) :<C-U>call coc#rpc#request('selectSymbolRange', [v:false, visualmode(), ['Interface', 'Struct', 'Class']])<CR> |
||||
onoremap <silent> <Plug>(coc-classobj-i) :<C-U>call coc#rpc#request('selectSymbolRange', [v:true, '', ['Interface', 'Struct', 'Class']])<CR> |
||||
onoremap <silent> <Plug>(coc-classobj-a) :<C-U>call coc#rpc#request('selectSymbolRange', [v:false, '', ['Interface', 'Struct', 'Class']])<CR> |
Loading…
Reference in new issue