2018-03-31 10:56:26 -04:00
|
|
|
function! gitgutter#utility#supports_overscore_sign()
|
2018-06-14 06:31:12 -04:00
|
|
|
if gitgutter#utility#windows()
|
2018-03-31 10:56:26 -04:00
|
|
|
return &encoding ==? 'utf-8'
|
|
|
|
else
|
|
|
|
return &termencoding ==? &encoding || &termencoding == ''
|
|
|
|
endif
|
|
|
|
endfunction
|
2016-11-22 03:36:31 -05:00
|
|
|
|
2017-04-01 07:22:06 -04:00
|
|
|
function! gitgutter#utility#setbufvar(buffer, varname, val)
|
|
|
|
let dict = get(getbufvar(a:buffer, ''), 'gitgutter', {})
|
2018-03-31 10:56:26 -04:00
|
|
|
let needs_setting = empty(dict)
|
2017-04-01 07:22:06 -04:00
|
|
|
let dict[a:varname] = a:val
|
2018-03-31 10:56:26 -04:00
|
|
|
if needs_setting
|
2018-06-14 06:31:12 -04:00
|
|
|
call setbufvar(+a:buffer, 'gitgutter', dict)
|
2018-03-31 10:56:26 -04:00
|
|
|
endif
|
2017-04-01 07:22:06 -04:00
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! gitgutter#utility#getbufvar(buffer, varname, ...)
|
|
|
|
let dict = get(getbufvar(a:buffer, ''), 'gitgutter', {})
|
|
|
|
if has_key(dict, a:varname)
|
|
|
|
return dict[a:varname]
|
|
|
|
else
|
|
|
|
if a:0
|
|
|
|
return a:1
|
|
|
|
endif
|
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
2016-11-22 03:36:31 -05:00
|
|
|
function! gitgutter#utility#warn(message) abort
|
|
|
|
echohl WarningMsg
|
|
|
|
echo 'vim-gitgutter: ' . a:message
|
|
|
|
echohl None
|
|
|
|
let v:warningmsg = a:message
|
|
|
|
endfunction
|
|
|
|
|
2018-03-31 10:56:26 -04:00
|
|
|
function! gitgutter#utility#warn_once(bufnr, message, key) abort
|
|
|
|
if empty(gitgutter#utility#getbufvar(a:bufnr, a:key))
|
|
|
|
call gitgutter#utility#setbufvar(a:bufnr, a:key, '1')
|
2016-11-22 03:36:31 -05:00
|
|
|
echohl WarningMsg
|
2018-03-31 10:56:26 -04:00
|
|
|
redraw | echom 'vim-gitgutter: ' . a:message
|
2016-11-22 03:36:31 -05:00
|
|
|
echohl None
|
|
|
|
let v:warningmsg = a:message
|
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
" Returns truthy when the buffer's file should be processed; and falsey when it shouldn't.
|
|
|
|
" This function does not and should not make any system calls.
|
2018-03-31 10:56:26 -04:00
|
|
|
function! gitgutter#utility#is_active(bufnr) abort
|
2016-11-22 03:36:31 -05:00
|
|
|
return g:gitgutter_enabled &&
|
|
|
|
\ !pumvisible() &&
|
2018-03-31 10:56:26 -04:00
|
|
|
\ s:is_file_buffer(a:bufnr) &&
|
|
|
|
\ s:exists_file(a:bufnr) &&
|
|
|
|
\ s:not_git_dir(a:bufnr)
|
2016-11-22 03:36:31 -05:00
|
|
|
endfunction
|
|
|
|
|
2018-03-31 10:56:26 -04:00
|
|
|
function! s:not_git_dir(bufnr) abort
|
|
|
|
return s:dir(a:bufnr) !~ '[/\\]\.git\($\|[/\\]\)'
|
2016-11-22 03:36:31 -05:00
|
|
|
endfunction
|
|
|
|
|
2018-03-31 10:56:26 -04:00
|
|
|
function! s:is_file_buffer(bufnr) abort
|
|
|
|
return empty(getbufvar(a:bufnr, '&buftype'))
|
2016-11-22 03:36:31 -05:00
|
|
|
endfunction
|
|
|
|
|
2018-03-31 10:56:26 -04:00
|
|
|
" From tpope/vim-fugitive
|
|
|
|
function! s:winshell()
|
|
|
|
return &shell =~? 'cmd' || exists('+shellslash') && !&shellslash
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
" From tpope/vim-fugitive
|
2016-11-22 03:36:31 -05:00
|
|
|
function! gitgutter#utility#shellescape(arg) abort
|
|
|
|
if a:arg =~ '^[A-Za-z0-9_/.-]\+$'
|
|
|
|
return a:arg
|
2018-03-31 10:56:26 -04:00
|
|
|
elseif s:winshell()
|
2016-11-22 03:36:31 -05:00
|
|
|
return '"' . substitute(substitute(a:arg, '"', '""', 'g'), '%', '"%"', 'g') . '"'
|
|
|
|
else
|
|
|
|
return shellescape(a:arg)
|
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
2018-03-31 10:56:26 -04:00
|
|
|
function! gitgutter#utility#file(bufnr)
|
|
|
|
return s:abs_path(a:bufnr, 1)
|
2016-11-22 03:36:31 -05:00
|
|
|
endfunction
|
|
|
|
|
2018-03-31 10:56:26 -04:00
|
|
|
" Not shellescaped
|
|
|
|
function! gitgutter#utility#extension(bufnr) abort
|
|
|
|
return fnamemodify(s:abs_path(a:bufnr, 0), ':e')
|
2016-11-22 03:36:31 -05:00
|
|
|
endfunction
|
|
|
|
|
2018-03-31 10:56:26 -04:00
|
|
|
function! gitgutter#utility#system(cmd, ...) abort
|
|
|
|
call gitgutter#debug#log(a:cmd, a:000)
|
2016-11-22 03:36:31 -05:00
|
|
|
|
2018-03-31 10:56:26 -04:00
|
|
|
call s:use_known_shell()
|
|
|
|
silent let output = (a:0 == 0) ? system(a:cmd) : system(a:cmd, a:1)
|
|
|
|
call s:restore_shell()
|
2016-11-22 03:36:31 -05:00
|
|
|
|
2018-03-31 10:56:26 -04:00
|
|
|
return output
|
2016-11-22 03:36:31 -05:00
|
|
|
endfunction
|
|
|
|
|
2018-03-31 10:56:26 -04:00
|
|
|
" Path of file relative to repo root.
|
|
|
|
"
|
|
|
|
" * empty string - not set
|
|
|
|
" * non-empty string - path
|
|
|
|
" * -1 - pending
|
|
|
|
" * -2 - not tracked by git
|
|
|
|
function! gitgutter#utility#repo_path(bufnr, shellesc) abort
|
|
|
|
let p = gitgutter#utility#getbufvar(a:bufnr, 'path')
|
|
|
|
return a:shellesc ? gitgutter#utility#shellescape(p) : p
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! gitgutter#utility#set_repo_path(bufnr) abort
|
|
|
|
" Values of path:
|
|
|
|
" * non-empty string - path
|
|
|
|
" * -1 - pending
|
|
|
|
" * -2 - not tracked by git
|
|
|
|
|
|
|
|
call gitgutter#utility#setbufvar(a:bufnr, 'path', -1)
|
2018-06-14 06:31:12 -04:00
|
|
|
let cmd = gitgutter#utility#cd_cmd(a:bufnr, g:gitgutter_git_executable.' ls-files --error-unmatch --full-name -- '.gitgutter#utility#shellescape(s:filename(a:bufnr)))
|
2018-03-31 10:56:26 -04:00
|
|
|
|
|
|
|
if g:gitgutter_async && gitgutter#async#available()
|
|
|
|
if has('lambda')
|
|
|
|
call gitgutter#async#execute(cmd, a:bufnr, {
|
|
|
|
\ 'out': {bufnr, path -> gitgutter#utility#setbufvar(bufnr, 'path', s:strip_trailing_new_line(path))},
|
|
|
|
\ 'err': {bufnr -> gitgutter#utility#setbufvar(bufnr, 'path', -2)},
|
|
|
|
\ })
|
2016-11-22 03:36:31 -05:00
|
|
|
else
|
2018-03-31 10:56:26 -04:00
|
|
|
if has('nvim') && !has('nvim-0.2.0')
|
|
|
|
call gitgutter#async#execute(cmd, a:bufnr, {
|
|
|
|
\ 'out': function('s:set_path'),
|
|
|
|
\ 'err': function('s:not_tracked_by_git')
|
|
|
|
\ })
|
|
|
|
else
|
|
|
|
call gitgutter#async#execute(cmd, a:bufnr, {
|
|
|
|
\ 'out': function('s:set_path'),
|
|
|
|
\ 'err': function('s:set_path', [-2])
|
|
|
|
\ })
|
|
|
|
endif
|
|
|
|
endif
|
|
|
|
else
|
|
|
|
let path = gitgutter#utility#system(cmd)
|
|
|
|
if v:shell_error
|
|
|
|
call gitgutter#utility#setbufvar(a:bufnr, 'path', -2)
|
|
|
|
else
|
|
|
|
call gitgutter#utility#setbufvar(a:bufnr, 'path', s:strip_trailing_new_line(path))
|
2016-11-22 03:36:31 -05:00
|
|
|
endif
|
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
2018-03-31 10:56:26 -04:00
|
|
|
if has('nvim') && !has('nvim-0.2.0')
|
|
|
|
function! s:not_tracked_by_git(bufnr)
|
|
|
|
call s:set_path(a:bufnr, -2)
|
|
|
|
endfunction
|
|
|
|
endif
|
2016-11-22 03:36:31 -05:00
|
|
|
|
2018-03-31 10:56:26 -04:00
|
|
|
function! s:set_path(bufnr, path)
|
|
|
|
if a:bufnr == -2
|
|
|
|
let [bufnr, path] = [a:path, a:bufnr]
|
|
|
|
call gitgutter#utility#setbufvar(bufnr, 'path', path)
|
2016-11-22 03:36:31 -05:00
|
|
|
else
|
2018-03-31 10:56:26 -04:00
|
|
|
call gitgutter#utility#setbufvar(a:bufnr, 'path', s:strip_trailing_new_line(a:path))
|
2016-11-22 03:36:31 -05:00
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
2018-03-31 10:56:26 -04:00
|
|
|
function! gitgutter#utility#cd_cmd(bufnr, cmd) abort
|
2018-06-14 06:31:12 -04:00
|
|
|
let cd = s:unc_path(a:bufnr) ? 'pushd' : (gitgutter#utility#windows() ? 'cd /d' : 'cd')
|
2018-03-31 10:56:26 -04:00
|
|
|
return cd.' '.s:dir(a:bufnr).' && '.a:cmd
|
2016-11-22 03:36:31 -05:00
|
|
|
endfunction
|
|
|
|
|
2018-03-31 10:56:26 -04:00
|
|
|
function! s:unc_path(bufnr)
|
|
|
|
return s:abs_path(a:bufnr, 0) =~ '^\\\\'
|
2016-11-22 03:36:31 -05:00
|
|
|
endfunction
|
|
|
|
|
2018-03-31 10:56:26 -04:00
|
|
|
function! s:use_known_shell() abort
|
|
|
|
if has('unix') && &shell !=# 'sh'
|
|
|
|
let [s:shell, s:shellcmdflag, s:shellredir] = [&shell, &shellcmdflag, &shellredir]
|
|
|
|
let &shell = 'sh'
|
|
|
|
set shellcmdflag=-c shellredir=>%s\ 2>&1
|
2016-11-22 03:36:31 -05:00
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
2018-03-31 10:56:26 -04:00
|
|
|
function! s:restore_shell() abort
|
|
|
|
if has('unix') && exists('s:shell')
|
|
|
|
let [&shell, &shellcmdflag, &shellredir] = [s:shell, s:shellcmdflag, s:shellredir]
|
|
|
|
endif
|
2016-11-22 03:36:31 -05:00
|
|
|
endfunction
|
|
|
|
|
2018-03-31 10:56:26 -04:00
|
|
|
function! s:abs_path(bufnr, shellesc)
|
|
|
|
let p = resolve(expand('#'.a:bufnr.':p'))
|
|
|
|
return a:shellesc ? gitgutter#utility#shellescape(p) : p
|
2016-11-22 03:36:31 -05:00
|
|
|
endfunction
|
|
|
|
|
2018-03-31 10:56:26 -04:00
|
|
|
function! s:dir(bufnr) abort
|
|
|
|
return gitgutter#utility#shellescape(fnamemodify(s:abs_path(a:bufnr, 0), ':h'))
|
2016-11-22 03:36:31 -05:00
|
|
|
endfunction
|
|
|
|
|
2018-03-31 10:56:26 -04:00
|
|
|
" Not shellescaped.
|
|
|
|
function! s:filename(bufnr) abort
|
|
|
|
return fnamemodify(s:abs_path(a:bufnr, 0), ':t')
|
2016-11-22 03:36:31 -05:00
|
|
|
endfunction
|
|
|
|
|
2018-03-31 10:56:26 -04:00
|
|
|
function! s:exists_file(bufnr) abort
|
|
|
|
return filereadable(s:abs_path(a:bufnr, 0))
|
2016-11-22 03:36:31 -05:00
|
|
|
endfunction
|
|
|
|
|
2018-03-31 10:56:26 -04:00
|
|
|
function! s:strip_trailing_new_line(line) abort
|
|
|
|
return substitute(a:line, '\n$', '', '')
|
|
|
|
endfunction
|
|
|
|
|
2018-06-14 06:31:12 -04:00
|
|
|
function! gitgutter#utility#windows()
|
2018-03-31 10:56:26 -04:00
|
|
|
return has('win64') || has('win32') || has('win16')
|
2016-11-22 03:36:31 -05:00
|
|
|
endfunction
|