1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-02-03 18:00:05 +08:00
SpaceVim/bundle/gina.vim/autoload/gina/util.vim

252 lines
6.5 KiB
VimL

let s:Dict = vital#gina#import('Data.Dict')
let s:File = vital#gina#import('System.File')
let s:String = vital#gina#import('Data.String')
let s:DIRECTION_PATTERN = printf('\<\%%(%s\)\>', join([
\ 'lefta\%[bove]',
\ 'abo\%[veleft]',
\ 'rightb\%[elow]',
\ 'bel\%[owright]',
\ 'to\%[pleft]',
\ 'bo\%[tright]',
\], '\|')
\)
let s:t_list = type([])
let s:timer_syncbind = v:null
let s:timer_diffupdate = v:null
function! gina#util#contain_direction(mods) abort
return a:mods =~# s:DIRECTION_PATTERN
endfunction
function! gina#util#get(obj, key, ...) abort
let val = get(a:obj, a:key, v:null)
return val is# v:null ? get(a:000, 0, '') : val
endfunction
function! gina#util#map(lhs, rhs, ...) abort
let options = extend({
\ 'mode': '',
\ 'noremap': 0,
\ 'buffer': 1,
\ 'nowait': 0,
\ 'silent': 0,
\ 'special': 0,
\ 'script': 0,
\ 'unique': 0,
\ 'expr': 0,
\}, get(a:000, 0, {})
\)
let command = join([
\ options.mode . (options.noremap ? 'noremap' : 'map'),
\ options.buffer ? '<buffer>' : '',
\ options.nowait ? '<nowait>' : '',
\ options.silent ? '<silent>' : '',
\ options.special ? '<special>' : '',
\ options.script ? '<script>' : '',
\ options.unique ? '<unique>' : '',
\ options.expr ? '<expr>' : '',
\ a:lhs, a:rhs
\])
execute command
endfunction
function! gina#util#yank(value) abort
call setreg(v:register, a:value)
endfunction
function! gina#util#open(uri) abort
call s:File.open(a:uri)
endfunction
function! gina#util#filter(arglead, candidates, ...) abort
let hidden_pattern = get(a:000, 0, '')
let pattern = '^' . s:String.escape_pattern(a:arglead)
let candidates = copy(a:candidates)
if empty(a:arglead) && !empty(hidden_pattern)
call filter(candidates, 'v:val !~# hidden_pattern')
endif
call filter(candidates, 'v:val =~# pattern')
return candidates
endfunction
function! gina#util#shellescape(value, ...) abort
if empty(a:value)
return ''
endif
let value = type(a:value) == s:t_list
\ ? join(map(copy(a:value), 'shellescape(v:val)'))
\ : shellescape(a:value)
let prefix = get(a:000, 0, '')
return prefix . value
endfunction
function! gina#util#fnameescape(value, ...) abort
if empty(a:value)
return ''
endif
let value = type(a:value) == s:t_list
\ ? join(map(copy(a:value), 'fnameescape(v:val)'))
\ : fnameescape(a:value)
let prefix = get(a:000, 0, '')
return prefix . value
endfunction
function! gina#util#windo(expr) abort
let winid = win_getid()
try
execute printf('windo %s', a:expr)
finally
call win_gotoid(winid)
endtry
endfunction
function! gina#util#bufdo(expr, ...) abort
let bang = a:0 ? '!' : ''
let winid = win_getid()
try
execute printf('bufdo%s %s', bang, a:expr)
finally
call win_gotoid(winid)
endtry
endfunction
function! gina#util#doautocmd(name, ...) abort
let pattern = get(a:000, 0, '')
let expr = '#' . a:name
let eis = split(&eventignore, ',')
if index(eis, a:name) != -1 || index(eis, 'all') != -1 || !exists(expr)
" the specified event is ignored or does not exists
return
endif
let is_pseudo_required = empty(pattern) && !exists('#' . a:name . '#*')
if is_pseudo_required
" NOTE:
" autocmd XXXXX <pattern> exists but not sure if the current buffer name
" match with the <pattern> so register an empty autocmd to prevent
" 'No matching autocommands' warning
augroup gina_internal_util_doautocmd
autocmd! *
execute printf('autocmd %s * :', a:name)
augroup END
endif
let nomodeline = has('patch-7.4.438') && a:name ==# 'User'
\ ? '<nomodeline> '
\ : ''
try
execute printf('doautocmd %s %s %s', nomodeline, a:name, pattern)
finally
if is_pseudo_required
augroup gina_internal_util_doautocmd
autocmd! *
augroup END
endif
endtry
endfunction
function! gina#util#winwidth(winnr) abort
let width = winwidth(a:winnr)
let width -= &foldcolumn
let width -= s:is_sign_visible(winbufnr(a:winnr)) ? 2 : 0
let width -= (&number || &relativenumber)
\ ? len(string(line('$'))) + 1
\ : 0
return width
endfunction
function! gina#util#syncbind() abort
" NOTE:
" 'syncbind' does not work just after a buffer has opened
" so use timer to delay the command.
silent! call timer_stop(s:timer_syncbind)
let s:timer_syncbind = timer_start(50, function('s:syncbind'))
endfunction
function! gina#util#diffthis() abort
diffthis
augroup gina_internal_util_diffthis_local
autocmd! * <buffer>
autocmd BufReadPost <buffer>
\ if &diff && &foldmethod !=# 'diff' |
\ setlocal foldmethod=diff |
\ endif
augroup END
endfunction
function! gina#util#diffupdate() abort
" NOTE:
" 'diffupdate' does not work just after a buffer has opened
" so use timer to delay the command.
silent! call timer_stop(s:timer_diffupdate)
let s:timer_diffupdate = timer_start(100, function('s:diffupdate', [bufnr('%')]))
endfunction
" Private --------------------------------------------------------------------
function! s:syncbind(...) abort
syncbind
silent! wincmd p
silent! wincmd p
endfunction
function! s:diffoff(update) abort
augroup gina_internal_util_diffthis
autocmd! * <buffer>
augroup END
diffoff
if a:update
call s:diffupdate(bufnr('%'))
endif
endfunction
function! s:diffoff_all() abort
let winid = win_getid()
for winnr in range(1, winnr('$'))
if getwinvar(winnr, '&diff')
call win_gotoid(win_getid(winnr))
call s:diffoff(0)
endif
endfor
call win_gotoid(winid)
call s:diffupdate(bufnr('%'))
endfunction
function! s:diffupdate(bufnr, ...) abort
let winid = bufwinid(a:bufnr)
if winid == -1
return
endif
let winid_saved = win_getid()
try
if winid != winid_saved
call win_gotoid(winid)
endif
diffupdate
syncbind
finally
call win_gotoid(winid_saved)
endtry
endfunction
function! s:diffcount() abort
let indicators = map(
\ range(1, winnr('$')),
\ 'getwinvar(v:val, ''&diff'')'
\)
let indicators = filter(indicators, 'v:val')
return len(indicators)
endfunction
function! s:call_super(cls, method, ...) abort dict
return call(a:cls.__super[a:method], a:000, self)
endfunction
function! s:is_sign_visible(bufnr) abort
if !exists('&signcolumn') || &signcolumn ==# 'auto'
return len(split(execute('sign place buffer=' . a:bufnr), '\r\?\n')) > 1
else
return &signcolumn ==# 'yes'
endif
endfunction