Support expanding inline diffs in :Gstatus
This commit is contained in:
parent
51abc6a1bb
commit
d948ec3376
@ -1481,6 +1481,12 @@ function! fugitive#BufReadStatus() abort
|
||||
endfor
|
||||
endif
|
||||
|
||||
let b:fugitive_diff = {
|
||||
\ 'Staged': split(system(fugitive#Prepare('diff', '--no-ext-diff', '--no-prefix', '--cached', '--')), "\n"),
|
||||
\ 'Unstaged': split(system(fugitive#Prepare('diff', '--no-ext-diff', '--no-prefix', '--')), "\n")}
|
||||
let expanded = get(b:, 'fugitive_expanded', {'Staged': {}, 'Unstaged': {}})
|
||||
let b:fugitive_expanded = {'Staged': {}, 'Unstaged': {}}
|
||||
|
||||
silent keepjumps %delete_
|
||||
|
||||
call s:AddHeader('Head', head)
|
||||
@ -1490,7 +1496,9 @@ function! fugitive#BufReadStatus() abort
|
||||
endif
|
||||
call s:AddSection('Rebasing ' . rebasing_head, rebasing)
|
||||
call s:AddSection('Unstaged', unstaged)
|
||||
let unstaged_end = len(unstaged) ? line('$') : 0
|
||||
call s:AddSection('Staged', staged)
|
||||
let staged_end = len(staged) ? line('$') : 0
|
||||
call s:AddSection('Unpushed to ' . push, unpushed)
|
||||
call s:AddSection('Unpulled from ' . pull, unpulled)
|
||||
|
||||
@ -1522,6 +1530,14 @@ function! fugitive#BufReadStatus() abort
|
||||
nnoremap <buffer> <silent> cw :<C-U>Gcommit --amend --only<CR>
|
||||
nnoremap <buffer> <silent> cva :<C-U>Gcommit -v --amend<CR>
|
||||
nnoremap <buffer> <silent> cvc :<C-U>Gcommit -v<CR>
|
||||
nnoremap <buffer> <silent> a :<C-U>execute <SID>StageInline('toggle',line('.'),v:count)<CR>
|
||||
nnoremap <buffer> <silent> i :<C-U>execute <SID>StageInline('toggle',line('.'),v:count)<CR>
|
||||
exe 'nnoremap <buffer> <silent>' nowait "= :<C-U>execute <SID>StageInline('toggle',line('.'),v:count)<CR>"
|
||||
exe 'nnoremap <buffer> <silent>' nowait "< :<C-U>execute <SID>StageInline('show', line('.'),v:count)<CR>"
|
||||
exe 'nnoremap <buffer> <silent>' nowait "> :<C-U>execute <SID>StageInline('hide', line('.'),v:count)<CR>"
|
||||
exe 'xnoremap <buffer> <silent>' nowait "= :<C-U>execute <SID>StageInline('toggle',line(\"'<\"),line(\"'>\")-line(\"'<\")+1)<CR>"
|
||||
exe 'xnoremap <buffer> <silent>' nowait "< :<C-U>execute <SID>StageInline('show', line(\"'<\"),line(\"'>\")-line(\"'<\")+1)<CR>"
|
||||
exe 'xnoremap <buffer> <silent>' nowait "> :<C-U>execute <SID>StageInline('hide', line(\"'<\"),line(\"'>\")-line(\"'<\")+1)<CR>"
|
||||
nnoremap <buffer> <silent> D :<C-U>execute <SID>StageDiff('Gdiff')<CR>
|
||||
nnoremap <buffer> <silent> dd :<C-U>execute <SID>StageDiff('Gdiff')<CR>
|
||||
nnoremap <buffer> <silent> dh :<C-U>execute <SID>StageDiff('Gsdiff')<CR>
|
||||
@ -1537,9 +1553,20 @@ function! fugitive#BufReadStatus() abort
|
||||
nnoremap <buffer> <silent> R :<C-U>exe <SID>ReloadStatus()<CR>
|
||||
nnoremap <buffer> <silent> U :<C-U>echoerr 'Changed to g<Bar>'<CR>
|
||||
nnoremap <buffer> <silent> g<Bar> :<C-U>execute <SID>StageUndo()<CR>
|
||||
nnoremap <buffer> . : <C-R>=<SID>fnameescape(<SID>StatusCfile())<CR><Home>
|
||||
nnoremap <buffer> . : <C-R>=<SID>fnameescape(get(<SID>StatusCfile(),0,''))<CR><Home>
|
||||
nnoremap <buffer> <silent> g? :help fugitive-:Gstatus<CR>
|
||||
nnoremap <buffer> <silent> <F1> :help fugitive-:Gstatus<CR>
|
||||
|
||||
for [lnum, section] in [[staged_end, 'Staged'], [unstaged_end, 'Unstaged']]
|
||||
while len(getline(lnum))
|
||||
let filename = matchstr(getline(lnum), '^[A-Z?] \zs.*')
|
||||
if has_key(expanded[section], filename)
|
||||
call s:StageInline('show', lnum)
|
||||
endif
|
||||
let lnum -= 1
|
||||
endwhile
|
||||
endfor
|
||||
|
||||
return ''
|
||||
catch /^fugitive:/
|
||||
return 'echoerr v:errmsg'
|
||||
@ -1867,10 +1894,71 @@ function! s:Status(bang, count, mods) abort
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
function! s:ReloadStatus() abort
|
||||
let pos = getpos('.')
|
||||
function! s:StageSeek(info, fallback) abort
|
||||
let info = a:info
|
||||
if empty(info.section)
|
||||
return a:fallback
|
||||
endif
|
||||
let line = search('^' . info.section, 'wn')
|
||||
if !line
|
||||
for section in get({'Staged': ['Unstaged'], 'Unstaged': ['Staged']}, info.section, [])
|
||||
let line = search('^' . section, 'wn')
|
||||
if line
|
||||
return line + (info.index > 0 ? 1 : 0)
|
||||
endif
|
||||
endfor
|
||||
return 1
|
||||
endif
|
||||
let i = 0
|
||||
while len(getline(line))
|
||||
let filename = matchstr(getline(line), '^[A-Z?] \zs.*')
|
||||
if len(filename) &&
|
||||
\ ((info.filename[-1:-1] ==# '/' && filename[0 : len(info.filename) - 1] ==# info.filename) ||
|
||||
\ (filename[-1:-1] ==# '/' && filename ==# info.filename[0 : len(filename) - 1]) ||
|
||||
\ filename ==# info.filename)
|
||||
if info.offset < 0
|
||||
return line
|
||||
else
|
||||
if getline(line+1) !~# '^@'
|
||||
exe s:StageInline('show', line)
|
||||
endif
|
||||
if getline(line+1) !~# '^@'
|
||||
return line
|
||||
endif
|
||||
let type = info.sigil ==# '-' ? '-' : '+'
|
||||
let offset = -1
|
||||
while offset < info.offset
|
||||
let line += 1
|
||||
if getline(line) =~# '^@'
|
||||
let offset = +matchstr(getline(line), type . '\zs\d\+') - 1
|
||||
elseif getline(line) =~# '^[ ' . type . ']'
|
||||
let offset += 1
|
||||
elseif getline(line) !~# '^[ @+-]'
|
||||
return line - 1
|
||||
endif
|
||||
endwhile
|
||||
return line
|
||||
endif
|
||||
endif
|
||||
let commit = matchstr(getline(line), '^\%(\%(\x\x\x\)\@!\l\+\s\+\)\=\zs[0-9a-f]\+')
|
||||
if len(commit) && commit ==# info.commit
|
||||
return line
|
||||
endif
|
||||
if i ==# info.index
|
||||
let backup = line
|
||||
endif
|
||||
let i += getline(line) !~# '^[ @+-]'
|
||||
let line += 1
|
||||
endwhile
|
||||
return exists('backup') ? backup : line - 1
|
||||
endfunction
|
||||
|
||||
function! s:ReloadStatus(...) abort
|
||||
let original_lnum = a:0 ? a:1 : line('.')
|
||||
let info = s:StageInfo(original_lnum)
|
||||
call fugitive#BufReadStatus()
|
||||
call setpos('.', pos)
|
||||
exe s:StageSeek(info, original_lnum)
|
||||
normal! 0
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
@ -1910,28 +1998,44 @@ endfunction
|
||||
|
||||
function! s:StageInfo(...) abort
|
||||
let lnum = a:0 ? a:1 : line('.')
|
||||
let sigil = matchstr(getline('.'), '^[ @+-]')
|
||||
let offset = -1
|
||||
if getline(lnum) =~# '^[ @+-]'
|
||||
let type = sigil ==# '-' ? '-' : '+'
|
||||
while lnum > 0 && getline(lnum) !~# '^@'
|
||||
if getline(lnum) =~# '^[ '.type.']'
|
||||
let offset += 1
|
||||
endif
|
||||
let lnum -= 1
|
||||
endwhile
|
||||
let offset += matchstr(getline(lnum), type.'\zs\d\+')
|
||||
while getline(lnum) =~# '^[ @+-]'
|
||||
let lnum -= 1
|
||||
endwhile
|
||||
endif
|
||||
let slnum = lnum + 1
|
||||
let section = ''
|
||||
let index = 0
|
||||
while len(getline(slnum - 1)) && empty(section)
|
||||
let slnum -= 1
|
||||
let section = matchstr(getline(slnum), '^\u\l\+\ze.* (\d\+)$')
|
||||
if empty(section) && getline(slnum) !~# '^[ @+-]'
|
||||
let index += 1
|
||||
endif
|
||||
endwhile
|
||||
return {'section': section,
|
||||
\ 'heading': getline(slnum),
|
||||
\ 'sigil': sigil,
|
||||
\ 'offset': offset,
|
||||
\ 'filename': matchstr(getline(lnum), '^[A-Z?] \zs.*'),
|
||||
\ 'commit': matchstr(getline(lnum), '^\%(\%(\x\x\x\)\@!\l\+\s\+\)\=\zs[0-9a-f]\{4,\}\ze '),
|
||||
\ 'status': matchstr(getline(lnum), '^[A-Z?]\ze \|^\%(\x\x\x\)\@!\l\+\ze [0-9a-f]'),
|
||||
\ 'index': lnum - slnum}
|
||||
endfunction
|
||||
|
||||
function! s:StageFileSection(lnum) abort
|
||||
let info = s:StageInfo(a:lnum)
|
||||
return [info.filename, info.section]
|
||||
\ 'index': index}
|
||||
endfunction
|
||||
|
||||
function! s:StageNext(count) abort
|
||||
for i in range(a:count)
|
||||
call search('^[A-Z?] .\|^[0-9a-f]\{4,\} ','W')
|
||||
call search('^[A-Z?] .\|^[0-9a-f]\{4,\} \|^@','W')
|
||||
endfor
|
||||
return '.'
|
||||
endfunction
|
||||
@ -1941,35 +2045,15 @@ function! s:StagePrevious(count) abort
|
||||
return 'CtrlP '.fnameescape(s:Tree())
|
||||
else
|
||||
for i in range(a:count)
|
||||
call search('^[A-Z?] .\|^[0-9a-f]\{4,\} ','Wbe')
|
||||
call search('^[A-Z?] .\|^[0-9a-f]\{4,\} \|^@','Wbe')
|
||||
endfor
|
||||
return '.'
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:StageReloadSeek(target,lnum1,lnum2) abort
|
||||
let jump = a:target
|
||||
let target = s:StageFileSection(a:lnum2 + 1)
|
||||
if empty(target[0])
|
||||
let target = s:StageFileSection(a:lnum1 - 1)
|
||||
endif
|
||||
if empty(target[0])
|
||||
let target = a:target
|
||||
endif
|
||||
call s:ReloadStatus()
|
||||
1
|
||||
redraw
|
||||
let lnum = 0
|
||||
while lnum < line('$')
|
||||
let lnum += 1
|
||||
let file = getline(lnum)[2:-1]
|
||||
if (target[0][-1:-1] ==# '/' && file[0 : len(target[0]) - 1] ==# target[0]) ||
|
||||
\ (file[-1:-1] ==# '/' && file ==# target[0][0 : len(file) - 1]) ||
|
||||
\ file ==# target[0]
|
||||
exe lnum
|
||||
return ''
|
||||
endif
|
||||
endwhile
|
||||
exe s:ReloadStatus(a:lnum1)
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
function! s:StageUndo() abort
|
||||
@ -1995,28 +2079,108 @@ function! s:StageUndo() abort
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:StageInline(mode, ...) abort
|
||||
let lnum1 = a:0 ? a:1 : line('.')
|
||||
let lnum = lnum1 + 1
|
||||
if a:0 > 1 && a:2 == 0
|
||||
let info = s:StageInfo(lnum - 1)
|
||||
if empty(info.filename) && len(info.section)
|
||||
while len(getline(lnum))
|
||||
let lnum += 1
|
||||
endwhile
|
||||
endif
|
||||
elseif a:0 > 1
|
||||
let lnum += a:2 - 1
|
||||
endif
|
||||
while lnum > lnum1
|
||||
let lnum -= 1
|
||||
while lnum > 0 && getline(lnum) =~# '^[ @+-]'
|
||||
let lnum -= 1
|
||||
endwhile
|
||||
let info = s:StageInfo(lnum)
|
||||
if !has_key(b:fugitive_diff, info.section)
|
||||
continue
|
||||
endif
|
||||
if getline(lnum + 1) =~# '^[ @+-]'
|
||||
let lnum2 = lnum + 1
|
||||
while getline(lnum2 + 1) =~# '^[ @+-]'
|
||||
let lnum2 += 1
|
||||
endwhile
|
||||
if a:mode !=# 'show'
|
||||
setlocal modifiable noreadonly
|
||||
exe 'silent keepjumps ' . (lnum + 1) . ',' . lnum2 . 'delete _'
|
||||
call remove(b:fugitive_expanded[info.section], info.filename)
|
||||
setlocal nomodifiable readonly nomodified
|
||||
endif
|
||||
continue
|
||||
endif
|
||||
if !has_key(b:fugitive_diff, info.section) || info.status !~# '^[ADM]$' || a:mode ==# 'hide'
|
||||
continue
|
||||
endif
|
||||
let mode = ''
|
||||
let diff = []
|
||||
let index = 0
|
||||
let start = -1
|
||||
for line in b:fugitive_diff[info.section]
|
||||
if mode ==# 'await' && line[0] ==# '@'
|
||||
let mode = 'capture'
|
||||
endif
|
||||
if line[0] ==# 'd'
|
||||
if len(diff)
|
||||
break
|
||||
endif
|
||||
let start = index
|
||||
let mode = 'head'
|
||||
elseif mode ==# 'head' && line ==# '--- ' . info.filename
|
||||
let mode = 'await'
|
||||
elseif mode ==# 'head' && line ==# '+++ ' . info.filename
|
||||
let mode = 'await'
|
||||
elseif mode ==# 'capture'
|
||||
call add(diff, line)
|
||||
elseif line[0] ==# '@'
|
||||
let mode = ''
|
||||
endif
|
||||
let index += 1
|
||||
endfor
|
||||
if len(diff)
|
||||
setlocal modifiable noreadonly
|
||||
silent call append(lnum, diff)
|
||||
let b:fugitive_expanded[info.section][info.filename] = [start, len(diff)]
|
||||
setlocal nomodifiable readonly nomodified
|
||||
endif
|
||||
endwhile
|
||||
return lnum
|
||||
endfunction
|
||||
|
||||
function! s:StageDiff(diff) abort
|
||||
let [filename, section] = s:StageFileSection(line('.'))
|
||||
if filename ==# '' && section ==# 'Staged'
|
||||
let lnum = line('.')
|
||||
let info = s:StageInfo(lnum)
|
||||
let prefix = info.offset > 0 ? '+' . info.offset : ''
|
||||
if empty(info.filename) && info.section ==# 'Staged'
|
||||
return 'Git! diff --no-ext-diff --cached'
|
||||
elseif filename ==# ''
|
||||
elseif empty(info.filename)
|
||||
return 'Git! diff --no-ext-diff'
|
||||
elseif filename =~# ' -> '
|
||||
let [old, new] = split(filename,' -> ')
|
||||
execute 'Gedit '.s:fnameescape(':0:'.new)
|
||||
elseif info.filename =~# ' -> '
|
||||
let [old, new] = split(info.filename,' -> ')
|
||||
execute 'Gedit' . prefix s:fnameescape(':0:'.new)
|
||||
return a:diff.' HEAD:'.s:fnameescape(old)
|
||||
elseif section ==# 'Staged'
|
||||
execute 'Gedit '.s:fnameescape(':0:'.filename)
|
||||
return a:diff.' -'
|
||||
elseif info.section ==# 'Staged' && info.sigil ==# '-'
|
||||
execute 'Gedit' prefix s:fnameescape('@:'.info.filename)
|
||||
return a:diff.'! :0'
|
||||
elseif info.section ==# 'Staged'
|
||||
execute 'Gedit' prefix s:fnameescape(':0:'.info.filename)
|
||||
return a:diff . (info.sigil ==# '+' ? '!' : '') . ' -'
|
||||
elseif info.sigil ==# '-'
|
||||
execute 'Gedit' prefix s:fnameescape(':0:'.info.filename)
|
||||
return a:diff . '!'
|
||||
else
|
||||
execute 'Gedit '.s:fnameescape(':(top)'.filename)
|
||||
return a:diff
|
||||
execute 'Gedit' prefix s:fnameescape(':(top)'.info.filename)
|
||||
return a:diff . (info.sigil ==# '+' ? '!' : '')
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:StageDiffEdit() abort
|
||||
let info = s:StageInfo(line('.'))
|
||||
let [filename, section] = s:StageFileSection(line('.'))
|
||||
let arg = (empty(info.filename) ? '.' : info.filename)
|
||||
if info.section ==# 'Staged'
|
||||
return 'Git! diff --no-ext-diff --cached '.s:shellesc(arg)
|
||||
@ -2029,7 +2193,7 @@ function! s:StageDiffEdit() abort
|
||||
call search('^Staged','W')
|
||||
endif
|
||||
else
|
||||
call s:StageReloadSeek([filename, 'Staged'], line('.'), line('.'))
|
||||
call s:StageReloadSeek([info.filename, 'Staged'], line('.'), line('.'))
|
||||
endif
|
||||
return ''
|
||||
else
|
||||
@ -2107,24 +2271,21 @@ function! s:StagePatch(lnum1,lnum2) abort
|
||||
let reset = []
|
||||
|
||||
for lnum in range(a:lnum1,a:lnum2)
|
||||
let [filename, section] = s:StageFileSection(lnum)
|
||||
if empty(filename) && section ==# 'Staged'
|
||||
let info = s:StageInfo(lnum)
|
||||
if empty(info.filename) && info.section ==# 'Staged'
|
||||
return 'Git reset --patch'
|
||||
elseif empty(filename) && section ==# 'Unstaged'
|
||||
elseif empty(info.filename) && info.section ==# 'Unstaged'
|
||||
return 'Git add --patch'
|
||||
elseif filename ==# ''
|
||||
elseif info.filename ==# ''
|
||||
continue
|
||||
endif
|
||||
if !exists('first_filename')
|
||||
let first_filename = filename
|
||||
endif
|
||||
execute lnum
|
||||
if filename =~ ' -> '
|
||||
let reset += [split(filename,' -> ')[1]]
|
||||
elseif section ==# 'Staged'
|
||||
let reset += [filename]
|
||||
elseif getline(lnum) !~# '^.\=\tdeleted:'
|
||||
let add += [filename]
|
||||
if info.filename =~ ' -> '
|
||||
let reset += [split(info.filename,' -> ')[1]]
|
||||
elseif info.section ==# 'Staged'
|
||||
let reset += [info.filename]
|
||||
elseif info.status !~# '^D'
|
||||
let add += [info.filename]
|
||||
endif
|
||||
endfor
|
||||
try
|
||||
@ -2134,16 +2295,10 @@ function! s:StagePatch(lnum1,lnum2) abort
|
||||
if !empty(reset)
|
||||
execute "Git reset --patch -- ".join(map(reset,'s:shellesc(v:val)'))
|
||||
endif
|
||||
if exists('first_filename')
|
||||
silent! edit!
|
||||
1
|
||||
redraw
|
||||
call search('^[A-Z?] \V'.first_filename.'\$','W')
|
||||
endif
|
||||
catch /^fugitive:/
|
||||
return 'echoerr v:errmsg'
|
||||
endtry
|
||||
return 'checktime'
|
||||
return s:ReloadStatus()
|
||||
endfunction
|
||||
|
||||
" Section: :Gcommit
|
||||
@ -3801,22 +3956,29 @@ endfunction
|
||||
function! s:StatusCfile(...) abort
|
||||
let tree = FugitiveTreeForGitDir(b:git_dir)
|
||||
let lead = s:cpath(tree, getcwd()) ? './' : tree . '/'
|
||||
let info = s:StageInfo()
|
||||
let line = getline('.')
|
||||
if line =~# '^\S '
|
||||
return lead . line[2:-1]
|
||||
elseif line =~# '^[0-9a-f]\{4,\}\s'
|
||||
return matchstr(line, '^\S\+')
|
||||
elseif line =~# '^\l\+\s\+[0-9a-f]\{4,\}\s'
|
||||
return matchstr(line, '^\l\+\s\+\zs\S\+')
|
||||
if len(info.sigil) && len(info.section) && len(info.filename)
|
||||
if info.section ==# 'Unstaged' && info.sigil !=# '-'
|
||||
return [lead . info.filename, info.offset, 'normal!zv']
|
||||
elseif info.section ==# 'Staged' && info.sigil ==# '-'
|
||||
return ['@:' . info.filename, info.offset, 'normal!zv']
|
||||
else
|
||||
return [':0:' . info.filename, info.offset, 'normal!zv']
|
||||
endif
|
||||
elseif len(info.filename)
|
||||
return [lead . info.filename]
|
||||
elseif len(info.commit)
|
||||
return [info.commit]
|
||||
elseif line =~# '^\%(Head\|Merge\|Rebase\|Upstream\|Pull\|Push\): '
|
||||
return matchstr(line, ' \zs.*')
|
||||
return [matchstr(line, ' \zs.*')]
|
||||
else
|
||||
return ''
|
||||
return ['']
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! fugitive#StatusCfile() abort
|
||||
let file = s:Generate(s:StatusCfile())
|
||||
let file = s:Generate(s:StatusCfile()[0])
|
||||
return empty(file) ? fugitive#Cfile() : s:fnameescape(file)
|
||||
endfunction
|
||||
|
||||
@ -4003,7 +4165,7 @@ endfunction
|
||||
|
||||
function! s:GF(mode) abort
|
||||
try
|
||||
let results = &filetype ==# 'fugitive' ? [s:StatusCfile()] : &filetype ==# 'gitcommit' ? [s:MessageCfile()] : s:cfile()
|
||||
let results = &filetype ==# 'fugitive' ? s:StatusCfile() : &filetype ==# 'gitcommit' ? [s:MessageCfile()] : s:cfile()
|
||||
catch /^fugitive:/
|
||||
return 'echoerr v:errmsg'
|
||||
endtry
|
||||
|
@ -49,6 +49,9 @@ that are part of Git repositories).
|
||||
cf |:Gcommit| --fixup=
|
||||
cs |:Gcommit| --squash=
|
||||
cA |:Gcommit| --edit --squash=
|
||||
= toggle inline diff
|
||||
< show inline diff
|
||||
> hide inline diff
|
||||
D |:Gdiff|
|
||||
ds |:Gsdiff|
|
||||
dp |:Git!| diff (p for patch; use :Gw to apply)
|
||||
|
@ -22,7 +22,7 @@ syn match FugitiveSymbolicRef /\.\@!\%(\.\.\@!\|[^[:space:][:cntrl:]\:.]\)\+\.\@
|
||||
syn match fugitiveHash /^\x\{4,\}\>/ contained containedin=fugitiveSection
|
||||
syn match fugitiveHash /\<\x\{4,\}\>/ contained
|
||||
|
||||
syn region fugitiveHunk start=/^\%(@@ -\)\@=/ end=/^\%(diff --\%(git\|cc\|combined\) \|@@\|$\)\@=/ contains=@fugitiveDiff containedin=fugitiveSection fold
|
||||
syn region fugitiveHunk start=/^\%(@@ -\)\@=/ end=/^\%([A-Za-z?@]\|$\)\@=/ contains=@fugitiveDiff containedin=fugitiveSection fold
|
||||
|
||||
hi def link fugitiveHeader Label
|
||||
hi def link fugitiveHeading PreProc
|
||||
|
Loading…
Reference in New Issue
Block a user