nvim/pack/acp/start/coc.nvim/autoload/coc/util.vim

1117 lines
30 KiB
VimL

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: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#scroll_preview(dir) abort
let winnr = coc#util#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#util#has_float()
echohl Error | echon 'coc#util#has_float is deprecated, use coc#float#has_float instead' | echohl None
return coc#float#has_float()
endfunction
function! coc#util#float_hide()
echohl Error | echon 'coc#util#float_hide is deprecated, use coc#float#close_all instead' | echohl None
call coc#float#close_all()
endfunction
function! coc#util#float_jump()
echohl Error | echon 'coc#util#float_jump is deprecated, use coc#float#jump instead' | echohl None
endfunction
" close all float/popup window
function! coc#util#close_floats() abort
echohl WarningMsg | echon 'coc#util#close_floats is deprecated, use coc#float#close_all instead' | echohl None
call coc#float#close_all()
endfunction
function! coc#util#close_win(id)
echohl WarningMsg | echon 'coc#util#close_win is deprecated, use coc#float#close instead' | echohl None
call coc#float#close(a:id)
endfunction
function! coc#util#float_scroll(forward)
echohl WarningMsg | echon 'coc#util#close_win is deprecated, use coc#float#scroll instead' | echohl None
call coc#float#scroll(a:forward)
endfunction
" scroll float without exiting insert mode (nvim only)
function! coc#util#float_scroll_i(amount)
let float = coc#float#get_float_win()
if !float | return '' | endif
let buf = nvim_win_get_buf(float)
let buf_height = nvim_buf_line_count(buf)
let win_height = nvim_win_get_height(float)
if buf_height < win_height | return '' | endif
let pos = nvim_win_get_cursor(float)
try
let last_amount = nvim_win_get_var(float, 'coc_float_scroll_last_amount')
catch
let last_amount = 0
endtry
if a:amount > 0
if pos[0] == 1
let pos[0] += a:amount + win_height - 2
elseif last_amount > 0
let pos[0] += a:amount
else
let pos[0] += a:amount + win_height - 3
endif
let pos[0] = pos[0] < buf_height ? pos[0] : buf_height
elseif a:amount < 0
if pos[0] == buf_height
let pos[0] += a:amount - win_height + 2
elseif last_amount < 0
let pos[0] += a:amount
else
let pos[0] += a:amount - win_height + 3
endif
let pos[0] = pos[0] > 1 ? pos[0] : 1
endif
call nvim_win_set_var(float, 'coc_float_scroll_last_amount', a:amount)
call nvim_win_set_cursor(float, pos)
return ''
endfunction
" get cursor position
function! coc#util#cursor()
let pos = getcurpos()
let content = pos[2] == 1 ? '' : getline('.')[0: pos[2] - 2]
return [pos[1] - 1, strchars(content)]
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.'/bin/server.js') && filereadable(s:root.'/src/index.ts') && !get(g:, 'coc_force_bundle', 0)
if !filereadable(s:root.'/lib/attach.js')
echohl Error | echom '[coc.nvim] javascript bundle not found, please try :call coc#util#install()' | echohl None
return
endif
"use javascript from lib
return [node] + get(g:, 'coc_node_args', ['--no-warnings']) + [s:root.'/bin/server.js']
else
if !filereadable(s:root.'/build/index.js')
echohl Error | echom '[coc.nvim] build/index.js not found, reinstall coc.nvim to fix it.' | echohl None
return
endif
return [node] + get(g:, 'coc_node_args', ['--no-warnings']) + [s:root.'/build/index.js']
endif
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
silent! normal! m'
let path = a:filepath
if (has('win32unix'))
let path = substitute(a:filepath, '\v\\', '/', 'g')
endif
let file = fnamemodify(path, ":~:.")
exe a:cmd.' '.fnameescape(file)
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
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) 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
return {
\ 'bufname': bufname,
\ 'size': size,
\ 'eol': getbufvar(a:bufnr, '&eol'),
\ 'buftype': buftype,
\ 'winid': winid,
\ 'previewwindow': previewwindow == 0 ? v:false : v:true,
\ 'variables': s:variables(a:bufnr),
\ 'fullpath': empty(bufname) ? '' : fnamemodify(bufname, ':p'),
\ 'filetype': getbufvar(a:bufnr, '&filetype'),
\ 'iskeyword': getbufvar(a:bufnr, '&iskeyword'),
\ 'changedtick': getbufvar(a:bufnr, 'changedtick'),
\}
endfunction
function! s:variables(bufnr) abort
let info = getbufinfo({'bufnr':a:bufnr, 'variables': 1})
let variables = 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=2
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 pos = getcurpos()
let line = getline('.')
let l:start = pos[2] - 1
while l:start > 0 && line[l:start - 1] =~# '\k'
let l:start -= 1
endwhile
return pos[2] == 1 ? '' : line[l:start : pos[2] - 2]
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 disabled = get(b:, 'coc_suggest_disable', 0)
if disabled | return | endif
let blacklist = get(b:, 'coc_suggest_blacklist', [])
let pos = getcurpos()
let l:start = pos[2] - 1
let line = getline(pos[1])
for char in reverse(split(line[0: l:start - 1], '\zs'))
if l:start > 0 && char =~# '\k'
let l:start = l:start - strlen(char)
else
break
endif
endfor
let input = pos[2] == 1 ? '' : line[l:start : pos[2] - 2]
if !empty(blacklist) && index(blacklist, input) >= 0
return
endif
let synname = synIDattr(synID(pos[1], l:start, 1),"name")
return {
\ 'word': matchstr(line[l:start : ], '^\k\+'),
\ 'input': empty(input) ? '' : input,
\ 'line': line,
\ 'filetype': &filetype,
\ 'filepath': expand('%:p'),
\ 'bufnr': bufnr('%'),
\ 'linenr': pos[1],
\ 'colnr' : pos[2],
\ 'col': l:start,
\ 'synname': synname,
\ 'changedtick': b:changedtick,
\ 'blacklist': 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'),
\ })
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#prompt(title, cb) abort
if exists('*popup_dialog')
function! s:PromptHandler(id, result) closure
call a:cb(v:null, a:result)
endfunction
try
call popup_dialog(a:title. ' (y/n)', #{
\ filter: 'popup_filter_yesno',
\ callback: function('s:PromptHandler'),
\ })
catch /.*/
call a:cb(v:exception)
endtry
elseif !s:is_vim && exists('*confirm')
let choice = confirm(a:title, "&Yes\n&No")
call a:cb(v:null, choice == 1)
else
echohl MoreMsg
echom a:title.' (y/n)'
echohl None
let confirm = nr2char(getchar())
redraw!
if !(confirm ==? "y" || confirm ==? "\r")
echohl Moremsg | echo 'Cancelled.' | echohl None
return 0
call a:cb(v:null, 0)
end
call a:cb(v:null, 1)
endif
endfunction
function! coc#util#prompt_confirm(title)
if exists('*confirm') && !s:is_vim
let choice = confirm(a:title, "&Yes\n&No")
return choice == 1
else
echohl MoreMsg
echom a:title.' (y/n)'
echohl None
let confirm = nr2char(getchar())
redraw!
if !(confirm ==? "y" || confirm ==? "\r")
echohl Moremsg | echo 'Cancelled.' | echohl None
return 0
end
return 1
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 {
\ 'mode': mode(),
\ 'floating': has('nvim') && exists('*nvim_open_win') ? v:true : v:false,
\ 'extensionRoot': coc#util#extension_root(),
\ 'watchExtensions': get(g:, 'coc_watch_extensions', []),
\ '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', []),
\ 'textprop': has('textprop') && has('patch-8.1.1719') && !has('nvim') ? 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
" used by vim
function! coc#util#get_content(bufnr)
if !bufloaded(a:bufnr) | return '' | endif
return {
\ 'content': join(getbufline(a:bufnr, 1, '$'), "\n"),
\ '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
call coc#util#open_terminal({
\ 'cwd': s:root,
\ 'cmd': 'yarn install --frozen-lockfile',
\ '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#change_lines(bufnr, list) abort
if !bufloaded(a:bufnr) | return | endif
if exists('*setbufline')
for [lnum, line] in a:list
call setbufline(a:bufnr, lnum + 1, line)
endfor
elseif a:bufnr == bufnr('%')
for [lnum, line] in a:list
call setline(lnum + 1, line)
endfor
else
let bufnr = bufnr('%')
exe 'noa buffer '.a:bufnr
for [lnum, line] in a:list
call setline(lnum + 1, line)
endfor
exe 'noa buffer '.bufnr
endif
endfunction
function! coc#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
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
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
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#clear_pos_matches(match, ...) abort
let winid = get(a:, 1, win_getid())
if empty(getwininfo(winid))
" not valid
return
endif
if win_getid() == winid
let arr = filter(getmatches(), 'v:val["group"] =~# "'.a:match.'"')
for item in arr
call matchdelete(item['id'])
endfor
elseif s:clear_match_by_id
let arr = filter(getmatches(winid), 'v:val["group"] =~# "'.a:match.'"')
for item in arr
call matchdelete(item['id'], winid)
endfor
endif
endfunction
function! coc#util#clearmatches(ids, ...)
let winid = get(a:, 1, win_getid())
if empty(getwininfo(winid))
return
endif
if win_getid() == winid
for id in a:ids
try
call matchdelete(id)
catch /.*/
" matches have been cleared in other ways,
endtry
endfor
elseif s:clear_match_by_id
for id in a:ids
try
call matchdelete(id, winid)
catch /.*/
" matches have been cleared in other ways,
endtry
endfor
endif
endfunction
" clear document highlights of current window
function! coc#util#clear_highlights(...) abort
let winid = get(a:, 1, win_getid())
if empty(getwininfo(winid))
" not valid
return
endif
if winid == win_getid()
let arr = filter(getmatches(), 'v:val["group"] =~# "^CocHighlight"')
for item in arr
call matchdelete(item['id'])
endfor
elseif s:clear_match_by_id
let arr = filter(getmatches(winid), 'v:val["group"] =~# "^CocHighlight"')
for item in arr
call matchdelete(item['id'], winid)
endfor
endif
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
" Make sure pum is visible
function! coc#util#pumvisible() abort
let visible = pumvisible()
if !visible
throw 'Pum not visible'
endif
endfunction