aboutsummaryrefslogtreecommitdiff
path: root/.config/nvim/plugged/nerdtree-git-plugin/nerdtree_plugin
diff options
context:
space:
mode:
authorMarvin Borner2020-03-16 23:33:42 +0100
committerMarvin Borner2020-03-16 23:33:42 +0100
commit0e9ddbb0bf0cd34500155ea4b03de2e2a38d8ab2 (patch)
tree719da1c7fe5dabb872fe9ff1582c39b55ccd488e /.config/nvim/plugged/nerdtree-git-plugin/nerdtree_plugin
parente5d38956336ab1be954bdbd12808c5f98f8bd925 (diff)
Well I'm using Arch again
Diffstat (limited to '.config/nvim/plugged/nerdtree-git-plugin/nerdtree_plugin')
-rw-r--r--.config/nvim/plugged/nerdtree-git-plugin/nerdtree_plugin/git_status.vim360
1 files changed, 360 insertions, 0 deletions
diff --git a/.config/nvim/plugged/nerdtree-git-plugin/nerdtree_plugin/git_status.vim b/.config/nvim/plugged/nerdtree-git-plugin/nerdtree_plugin/git_status.vim
new file mode 100644
index 0000000..af7eb55
--- /dev/null
+++ b/.config/nvim/plugged/nerdtree-git-plugin/nerdtree_plugin/git_status.vim
@@ -0,0 +1,360 @@
+" ============================================================================
+" File: git_status.vim
+" Description: plugin for NERD Tree that provides git status support
+" Maintainer: Xuyuan Pang <xuyuanp at gmail dot com>
+" Last Change: 4 Apr 2014
+" License: This program is free software. It comes without any warranty,
+" to the extent permitted by applicable law. You can redistribute
+" it and/or modify it under the terms of the Do What The Fuck You
+" Want To Public License, Version 2, as published by Sam Hocevar.
+" See http://sam.zoy.org/wtfpl/COPYING for more details.
+" ============================================================================
+if exists('g:loaded_nerdtree_git_status')
+ finish
+endif
+let g:loaded_nerdtree_git_status = 1
+
+if !exists('g:NERDTreeShowGitStatus')
+ let g:NERDTreeShowGitStatus = 1
+endif
+
+if g:NERDTreeShowGitStatus == 0
+ finish
+endif
+
+if !exists('g:NERDTreeMapNextHunk')
+ let g:NERDTreeMapNextHunk = ']c'
+endif
+
+if !exists('g:NERDTreeMapPrevHunk')
+ let g:NERDTreeMapPrevHunk = '[c'
+endif
+
+if !exists('g:NERDTreeUpdateOnWrite')
+ let g:NERDTreeUpdateOnWrite = 1
+endif
+
+if !exists('g:NERDTreeUpdateOnCursorHold')
+ let g:NERDTreeUpdateOnCursorHold = 1
+endif
+
+if !exists('g:NERDTreeShowIgnoredStatus')
+ let g:NERDTreeShowIgnoredStatus = 0
+endif
+
+if !exists('s:NERDTreeIndicatorMap')
+ let s:NERDTreeIndicatorMap = {
+ \ 'Modified' : '✹',
+ \ 'Staged' : '✚',
+ \ 'Untracked' : '✭',
+ \ 'Renamed' : '➜',
+ \ 'Unmerged' : '═',
+ \ 'Deleted' : '✖',
+ \ 'Dirty' : '✗',
+ \ 'Clean' : '✔︎',
+ \ 'Ignored' : '☒',
+ \ 'Unknown' : '?'
+ \ }
+endif
+
+
+function! NERDTreeGitStatusRefreshListener(event)
+ if !exists('b:NOT_A_GIT_REPOSITORY')
+ call g:NERDTreeGitStatusRefresh()
+ endif
+ let l:path = a:event.subject
+ let l:flag = g:NERDTreeGetGitStatusPrefix(l:path)
+ call l:path.flagSet.clearFlags('git')
+ if l:flag !=# ''
+ call l:path.flagSet.addFlag('git', l:flag)
+ endif
+endfunction
+
+" FUNCTION: g:NERDTreeGitStatusRefresh() {{{2
+" refresh cached git status
+function! g:NERDTreeGitStatusRefresh()
+ let b:NERDTreeCachedGitFileStatus = {}
+ let b:NERDTreeCachedGitDirtyDir = {}
+ let b:NOT_A_GIT_REPOSITORY = 1
+
+ let l:root = fnamemodify(b:NERDTree.root.path.str(), ':p:gs?\\?/?:S')
+ let l:gitcmd = 'git -c color.status=false -C ' . l:root . ' status -s'
+ if g:NERDTreeShowIgnoredStatus
+ let l:gitcmd = l:gitcmd . ' --ignored'
+ endif
+ if exists('g:NERDTreeGitStatusIgnoreSubmodules')
+ let l:gitcmd = l:gitcmd . ' --ignore-submodules'
+ if g:NERDTreeGitStatusIgnoreSubmodules ==# 'all' || g:NERDTreeGitStatusIgnoreSubmodules ==# 'dirty' || g:NERDTreeGitStatusIgnoreSubmodules ==# 'untracked'
+ let l:gitcmd = l:gitcmd . '=' . g:NERDTreeGitStatusIgnoreSubmodules
+ endif
+ endif
+ let l:statusesStr = system(l:gitcmd)
+ let l:statusesSplit = split(l:statusesStr, '\n')
+ if l:statusesSplit != [] && l:statusesSplit[0] =~# 'fatal:.*'
+ let l:statusesSplit = []
+ return
+ endif
+ let b:NOT_A_GIT_REPOSITORY = 0
+
+ for l:statusLine in l:statusesSplit
+ " cache git status of files
+ let l:pathStr = substitute(l:statusLine, '...', '', '')
+ let l:pathSplit = split(l:pathStr, ' -> ')
+ if len(l:pathSplit) == 2
+ call s:NERDTreeCacheDirtyDir(l:pathSplit[0])
+ let l:pathStr = l:pathSplit[1]
+ else
+ let l:pathStr = l:pathSplit[0]
+ endif
+ let l:pathStr = s:NERDTreeTrimDoubleQuotes(l:pathStr)
+ if l:pathStr =~# '\.\./.*'
+ continue
+ endif
+ let l:statusKey = s:NERDTreeGetFileGitStatusKey(l:statusLine[0], l:statusLine[1])
+ let b:NERDTreeCachedGitFileStatus[fnameescape(l:pathStr)] = l:statusKey
+
+ if l:statusKey == 'Ignored'
+ if isdirectory(l:pathStr)
+ let b:NERDTreeCachedGitDirtyDir[fnameescape(l:pathStr)] = l:statusKey
+ endif
+ else
+ call s:NERDTreeCacheDirtyDir(l:pathStr)
+ endif
+ endfor
+endfunction
+
+function! s:NERDTreeCacheDirtyDir(pathStr)
+ " cache dirty dir
+ let l:dirtyPath = s:NERDTreeTrimDoubleQuotes(a:pathStr)
+ if l:dirtyPath =~# '\.\./.*'
+ return
+ endif
+ let l:dirtyPath = substitute(l:dirtyPath, '/[^/]*$', '/', '')
+ while l:dirtyPath =~# '.\+/.*' && has_key(b:NERDTreeCachedGitDirtyDir, fnameescape(l:dirtyPath)) == 0
+ let b:NERDTreeCachedGitDirtyDir[fnameescape(l:dirtyPath)] = 'Dirty'
+ let l:dirtyPath = substitute(l:dirtyPath, '/[^/]*/$', '/', '')
+ endwhile
+endfunction
+
+function! s:NERDTreeTrimDoubleQuotes(pathStr)
+ let l:toReturn = substitute(a:pathStr, '^"', '', '')
+ let l:toReturn = substitute(l:toReturn, '"$', '', '')
+ return l:toReturn
+endfunction
+
+" FUNCTION: g:NERDTreeGetGitStatusPrefix(path) {{{2
+" return the indicator of the path
+" Args: path
+let s:GitStatusCacheTimeExpiry = 2
+let s:GitStatusCacheTime = 0
+function! g:NERDTreeGetGitStatusPrefix(path)
+ if localtime() - s:GitStatusCacheTime > s:GitStatusCacheTimeExpiry
+ let s:GitStatusCacheTime = localtime()
+ call g:NERDTreeGitStatusRefresh()
+ endif
+ let l:pathStr = a:path.str()
+ let l:cwd = b:NERDTree.root.path.str() . a:path.Slash()
+ if nerdtree#runningWindows()
+ let l:pathStr = a:path.WinToUnixPath(l:pathStr)
+ let l:cwd = a:path.WinToUnixPath(l:cwd)
+ endif
+ let l:cwd = substitute(l:cwd, '\~', '\\~', 'g')
+ let l:pathStr = substitute(l:pathStr, l:cwd, '', '')
+ let l:statusKey = ''
+ if a:path.isDirectory
+ let l:statusKey = get(b:NERDTreeCachedGitDirtyDir, fnameescape(l:pathStr . '/'), '')
+ else
+ let l:statusKey = get(b:NERDTreeCachedGitFileStatus, fnameescape(l:pathStr), '')
+ endif
+ return s:NERDTreeGetIndicator(l:statusKey)
+endfunction
+
+" FUNCTION: s:NERDTreeGetCWDGitStatus() {{{2
+" return the indicator of cwd
+function! g:NERDTreeGetCWDGitStatus()
+ if b:NOT_A_GIT_REPOSITORY
+ return ''
+ elseif b:NERDTreeCachedGitDirtyDir == {} && b:NERDTreeCachedGitFileStatus == {}
+ return s:NERDTreeGetIndicator('Clean')
+ endif
+ return s:NERDTreeGetIndicator('Dirty')
+endfunction
+
+function! s:NERDTreeGetIndicator(statusKey)
+ if exists('g:NERDTreeIndicatorMapCustom')
+ let l:indicator = get(g:NERDTreeIndicatorMapCustom, a:statusKey, '')
+ if l:indicator !=# ''
+ return l:indicator
+ endif
+ endif
+ let l:indicator = get(s:NERDTreeIndicatorMap, a:statusKey, '')
+ if l:indicator !=# ''
+ return l:indicator
+ endif
+ return ''
+endfunction
+
+function! s:NERDTreeGetFileGitStatusKey(us, them)
+ if a:us ==# '?' && a:them ==# '?'
+ return 'Untracked'
+ elseif a:us ==# ' ' && a:them ==# 'M'
+ return 'Modified'
+ elseif a:us =~# '[MAC]'
+ return 'Staged'
+ elseif a:us ==# 'R'
+ return 'Renamed'
+ elseif a:us ==# 'U' || a:them ==# 'U' || a:us ==# 'A' && a:them ==# 'A' || a:us ==# 'D' && a:them ==# 'D'
+ return 'Unmerged'
+ elseif a:them ==# 'D'
+ return 'Deleted'
+ elseif a:us ==# '!'
+ return 'Ignored'
+ else
+ return 'Unknown'
+ endif
+endfunction
+
+" FUNCTION: s:jumpToNextHunk(node) {{{2
+function! s:jumpToNextHunk(node)
+ let l:position = search('\[[^{RO}].*\]', '')
+ if l:position
+ call nerdtree#echo('Jump to next hunk ')
+ endif
+endfunction
+
+" FUNCTION: s:jumpToPrevHunk(node) {{{2
+function! s:jumpToPrevHunk(node)
+ let l:position = search('\[[^{RO}].*\]', 'b')
+ if l:position
+ call nerdtree#echo('Jump to prev hunk ')
+ endif
+endfunction
+
+" Function: s:SID() {{{2
+function s:SID()
+ if !exists('s:sid')
+ let s:sid = matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze_SID$')
+ endif
+ return s:sid
+endfun
+
+" FUNCTION: s:NERDTreeGitStatusKeyMapping {{{2
+function! s:NERDTreeGitStatusKeyMapping()
+ let l:s = '<SNR>' . s:SID() . '_'
+
+ call NERDTreeAddKeyMap({
+ \ 'key': g:NERDTreeMapNextHunk,
+ \ 'scope': 'Node',
+ \ 'callback': l:s.'jumpToNextHunk',
+ \ 'quickhelpText': 'Jump to next git hunk' })
+
+ call NERDTreeAddKeyMap({
+ \ 'key': g:NERDTreeMapPrevHunk,
+ \ 'scope': 'Node',
+ \ 'callback': l:s.'jumpToPrevHunk',
+ \ 'quickhelpText': 'Jump to prev git hunk' })
+
+endfunction
+
+augroup nerdtreegitplugin
+ autocmd CursorHold * silent! call s:CursorHoldUpdate()
+augroup END
+" FUNCTION: s:CursorHoldUpdate() {{{2
+function! s:CursorHoldUpdate()
+ if g:NERDTreeUpdateOnCursorHold != 1
+ return
+ endif
+
+ if !g:NERDTree.IsOpen()
+ return
+ endif
+
+ " Do not update when a special buffer is selected
+ if !empty(&l:buftype)
+ return
+ endif
+
+ let l:winnr = winnr()
+ let l:altwinnr = winnr('#')
+
+ call g:NERDTree.CursorToTreeWin()
+ call b:NERDTree.root.refreshFlags()
+ call NERDTreeRender()
+
+ exec l:altwinnr . 'wincmd w'
+ exec l:winnr . 'wincmd w'
+endfunction
+
+augroup nerdtreegitplugin
+ autocmd BufWritePost * call s:FileUpdate(expand('%:p'))
+augroup END
+" FUNCTION: s:FileUpdate(fname) {{{2
+function! s:FileUpdate(fname)
+ if g:NERDTreeUpdateOnWrite != 1
+ return
+ endif
+
+ if !g:NERDTree.IsOpen()
+ return
+ endif
+
+ let l:winnr = winnr()
+ let l:altwinnr = winnr('#')
+
+ call g:NERDTree.CursorToTreeWin()
+ let l:node = b:NERDTree.root.findNode(g:NERDTreePath.New(a:fname))
+ if l:node == {}
+ return
+ endif
+ call l:node.refreshFlags()
+ let l:node = l:node.parent
+ while !empty(l:node)
+ call l:node.refreshDirFlags()
+ let l:node = l:node.parent
+ endwhile
+
+ call NERDTreeRender()
+
+ exec l:altwinnr . 'wincmd w'
+ exec l:winnr . 'wincmd w'
+endfunction
+
+augroup AddHighlighting
+ autocmd FileType nerdtree call s:AddHighlighting()
+augroup END
+function! s:AddHighlighting()
+ let l:synmap = {
+ \ 'NERDTreeGitStatusModified' : s:NERDTreeGetIndicator('Modified'),
+ \ 'NERDTreeGitStatusStaged' : s:NERDTreeGetIndicator('Staged'),
+ \ 'NERDTreeGitStatusUntracked' : s:NERDTreeGetIndicator('Untracked'),
+ \ 'NERDTreeGitStatusRenamed' : s:NERDTreeGetIndicator('Renamed'),
+ \ 'NERDTreeGitStatusIgnored' : s:NERDTreeGetIndicator('Ignored'),
+ \ 'NERDTreeGitStatusDirDirty' : s:NERDTreeGetIndicator('Dirty'),
+ \ 'NERDTreeGitStatusDirClean' : s:NERDTreeGetIndicator('Clean')
+ \ }
+
+ for l:name in keys(l:synmap)
+ exec 'syn match ' . l:name . ' #' . escape(l:synmap[l:name], '~') . '# containedin=NERDTreeFlags'
+ endfor
+
+ hi def link NERDTreeGitStatusModified Special
+ hi def link NERDTreeGitStatusStaged Function
+ hi def link NERDTreeGitStatusRenamed Title
+ hi def link NERDTreeGitStatusUnmerged Label
+ hi def link NERDTreeGitStatusUntracked Comment
+ hi def link NERDTreeGitStatusDirDirty Tag
+ hi def link NERDTreeGitStatusDirClean DiffAdd
+ " TODO: use diff color
+ hi def link NERDTreeGitStatusIgnored DiffAdd
+endfunction
+
+function! s:SetupListeners()
+ call g:NERDTreePathNotifier.AddListener('init', 'NERDTreeGitStatusRefreshListener')
+ call g:NERDTreePathNotifier.AddListener('refresh', 'NERDTreeGitStatusRefreshListener')
+ call g:NERDTreePathNotifier.AddListener('refreshFlags', 'NERDTreeGitStatusRefreshListener')
+endfunction
+
+if g:NERDTreeShowGitStatus && executable('git')
+ call s:NERDTreeGitStatusKeyMapping()
+ call s:SetupListeners()
+endif