diff --git a/git.vim b/git.vim new file mode 100644 index 0000000..1de23a2 --- /dev/null +++ b/git.vim @@ -0,0 +1,191 @@ +" ┌─────────────────┐ +" └─┬─┬───┬─┬───┬─┬─┘ +" │ │ │ │ │ │ +" │ │ │ │ │ │ +" ┌─┴─┴───┴─┴───┴─┴─┐ +" ┌┘ Git Stuff └┐ +" └───────────────────┘ + +function! s:gitroot() + let s:ret = substitute(system('git rev-parse --show-toplevel'), '\n\_.*', '', '') + if v:shell_error + throw s:ret + else + return s:ret + end +endf + +function! s:git_history() + if exists("b:git_history") + if b:git_history[0]+10 > localtime() + return b:git_history[1] + end + end + + if exists("b:git_original_file") " Is this already a file@revision buffer? + let l:fname = b:git_original_file + else + let l:fname = substitute(expand("%"), "\\\\", "/", "g") + end + let l:commits = system('git log --format="%h" '.l:fname) + let l:hist = split(l:commits, "\n") + let b:git_history = [localtime(), l:hist] + + return l:hist +endfun + +function! s:git_first() + if &modified + echo "Save your changes first!" + return + end + let l:history = s:git_history() + call s:file_at_revision(get(l:history, -1)) +endfun + +function! s:git_last() + if &modified + echo "Save your changes first!" + return + end + let l:history = s:git_history() + call s:file_at_revision(get(l:history, 1, "HEAD")) +endfun + +function! s:git_info() + if !exists("b:git_revision_hash") || !exists("b:git_original_file") + echo "Not a file@revision buffer!" + return + end + echo system("git show --no-patch ".b:git_revision_hash) +endfun + +function! s:git_next() + if !exists("b:git_revision_hash") || !exists("b:git_original_file") + echo "Error 01: Not a file@revision buffer!" + return + end + let l:history = s:git_history() + let l:idx = index(l:history, b:git_revision_hash) + if l:idx == -1 + echo "Error 02" + return + end + let l:new_revision = get(l:history, l:idx-1, "LAST") + if l:new_revision=="LAST" + echo "Already at latest revision! ".l:new_revision + return + else + call s:file_at_revision(l:new_revision) + end +endfun + +function! s:git_prev() + if !exists("b:git_revision_hash") || !exists("b:git_original_file") + let l:new_revision = s:git_history()[0] + else + let l:history = s:git_history() + let l:idx = index(l:history, b:git_revision_hash) + if l:idx == -1 + echo "Error 03: cannot find revision ".b:git_revision_hash + return + end + let l:new_revision = get(l:history, l:idx+1, "FIRST") + end + if l:new_revision=="FIRST" + echo "Already at earliest revision! ".l:new_revision + return + else + call s:file_at_revision(l:new_revision) + end +endfun + +function! s:file_at_revision(rev) + let l:pos = getpos(".") + if exists("b:git_original_file") " Is this already a file@revision buffer? + let l:fname = b:git_original_file + let l:ftail = fnamemodify(b:git_original_file, ":t") + else + let l:fname = expand("%") + let l:ftail = expand("%:t") + end + let l:fname = substitute(l:fname, "\\\\", "/", "g") + let l:ftype = &filetype + + ene! + set modifiable + silent exec "file ".l:ftail."@".a:rev + exec "r!git show ".a:rev.":".l:fname + 1,1del + let l:pos[0] = bufnr('.') + call setpos('.', l:pos) + setl nomodifiable + setl buftype=nofile + setl bufhidden=delete + let &filetype = l:ftype + + let b:git_original_file = l:fname + let b:git_revision_hash = a:rev +endfun + +function! s:git_diff(...) + if a:0 + vert bot split + call s:file_at_revision(a:1) + diffthis + au BufUnload diffoff! + exec "normal \\" + diffthis + call s:git_info() + else + if exists("b:git_revision_hash") + call s:git_diff(get(s:git_history(), index(s:git_history(), b:git_revision_hash)+1, "NIL")) + else + call s:git_diff(get(s:git_history(), 0, "HEAD")) + end + end +endfun + +function! s:git_blame() + let l:name = expand('%') + let l:line = getpos('.')[1] + let l:char = getpos('.')[2]+59 + let l:type = &filetype + enew + set modifiable + let &filetype = l:type + set buftype=nofile + set bufhidden=delete + set nowrap + silent exec "file Blame: ".l:name + keepjumps exec 'r !git blame '.l:name + keepjumps 0,0del " + set nomodifiable + keepjumps call setpos('.', [0, l:line, l:char, 0]) +endfun + +command! Blame try + \| call s:gitroot() | call git_blame() + \| catch | echo 'Not a git repo!' + \| endtry +command! GitNext try + \| call s:gitroot() | call git_next() | call s:git_info() + \| catch | echo 'Not a git repo!' + \| endtry +command! GitPrev call git_prev() | call s:git_info() +command! GitFirst call git_first() | call s:git_info() +command! GitLast call git_last() | call s:git_info() +command! GitInfo call git_info() +command! -nargs=1 GitCheckout call file_at_revision() +command! -nargs=? GitCompare try + \| call s:gitroot() | call git_diff() + \| catch | echo 'Not a git repo!' + \| endtry +command! Uncommited try + \| call s:gitroot() | call git_diff() + \| catch | echo 'Not a git repo!' + \| endtry +command! GitRoot try + \| echo gitroot() + \| catch | echo 'Not a git repository' + \| endtry diff --git a/vimrc b/vimrc index 2c6a2d2..559ec37 100644 --- a/vimrc +++ b/vimrc @@ -1,6 +1,8 @@ " vim: set bufhidden=delete list noexpandtab :miv " "!!! makes use of marker ' +let s:root = expand(':p:h') + set nocompatible """""""""""""""" @@ -368,197 +370,7 @@ command! -nargs=* Hex call hex() command! -range=% LuaCompile ,w !luac -l -p - -" ┌─────────────────┐ -" └─┬─┬───┬─┬───┬─┬─┘ -" │ │ │ │ │ │ -" │ │ │ │ │ │ -" ┌─┴─┴───┴─┴───┴─┴─┐ -" ┌┘ Git Stuff └┐ -" └───────────────────┘ - -function! s:gitroot() - let s:ret = substitute(system('git rev-parse --show-toplevel'), '\n\_.*', '', '') - if v:shell_error - throw s:ret - else - return s:ret - end -endf - -function! s:git_history() - if exists("b:git_history") - if b:git_history[0]+10 > localtime() - return b:git_history[1] - end - end - - if exists("b:git_original_file") " Is this already a file@revision buffer? - let l:fname = b:git_original_file - else - let l:fname = substitute(expand("%"), "\\\\", "/", "g") - end - let l:commits = system('git log --format="%h" '.l:fname) - let l:hist = split(l:commits, "\n") - let b:git_history = [localtime(), l:hist] - - return l:hist -endfun - -function! s:git_first() - if &modified - echo "Save your changes first!" - return - end - let l:history = s:git_history() - call s:file_at_revision(get(l:history, -1)) -endfun - -function! s:git_last() - if &modified - echo "Save your changes first!" - return - end - let l:history = s:git_history() - call s:file_at_revision(get(l:history, 1, "HEAD")) -endfun - -function! s:git_info() - if !exists("b:git_revision_hash") || !exists("b:git_original_file") - echo "Not a file@revision buffer!" - return - end - echo system("git show --no-patch ".b:git_revision_hash) -endfun - -function! s:git_next() - if !exists("b:git_revision_hash") || !exists("b:git_original_file") - echo "Error 01: Not a file@revision buffer!" - return - end - let l:history = s:git_history() - let l:idx = index(l:history, b:git_revision_hash) - if l:idx == -1 - echo "Error 02" - return - end - let l:new_revision = get(l:history, l:idx-1, "LAST") - if l:new_revision=="LAST" - echo "Already at latest revision! ".l:new_revision - return - else - call s:file_at_revision(l:new_revision) - end -endfun - -function! s:git_prev() - if !exists("b:git_revision_hash") || !exists("b:git_original_file") - let l:new_revision = s:git_history()[0] - else - let l:history = s:git_history() - let l:idx = index(l:history, b:git_revision_hash) - if l:idx == -1 - echo "Error 03: cannot find revision ".b:git_revision_hash - return - end - let l:new_revision = get(l:history, l:idx+1, "FIRST") - end - if l:new_revision=="FIRST" - echo "Already at earliest revision! ".l:new_revision - return - else - call s:file_at_revision(l:new_revision) - end -endfun - -function! s:file_at_revision(rev) - let l:pos = getpos(".") - if exists("b:git_original_file") " Is this already a file@revision buffer? - let l:fname = b:git_original_file - let l:ftail = fnamemodify(b:git_original_file, ":t") - else - let l:fname = expand("%") - let l:ftail = expand("%:t") - end - let l:fname = substitute(l:fname, "\\\\", "/", "g") - let l:ftype = &filetype - - ene! - set modifiable - silent exec "file ".l:ftail."@".a:rev - exec "r!git show ".a:rev.":".l:fname - 1,1del - let l:pos[0] = bufnr('.') - call setpos('.', l:pos) - setl nomodifiable - setl buftype=nofile - setl bufhidden=delete - let &filetype = l:ftype - - let b:git_original_file = l:fname - let b:git_revision_hash = a:rev -endfun - -function! s:git_diff(...) - if a:0 - vert bot split - call s:file_at_revision(a:1) - diffthis - au BufUnload diffoff! - exec "normal \\" - diffthis - call s:git_info() - else - if exists("b:git_revision_hash") - call s:git_diff(get(s:git_history(), index(s:git_history(), b:git_revision_hash)+1, "NIL")) - else - call s:git_diff(get(s:git_history(), 0, "HEAD")) - end - end -endfun - -function! s:git_blame() - let l:name = expand('%') - let l:line = getpos('.')[1] - let l:char = getpos('.')[2]+59 - let l:type = &filetype - enew - set modifiable - let &filetype = l:type - set buftype=nofile - set bufhidden=delete - set nowrap - silent exec "file Blame: ".l:name - keepjumps exec 'r !git blame '.l:name - keepjumps 0,0del " - set nomodifiable - keepjumps call setpos('.', [0, l:line, l:char, 0]) -endfun - -command! Blame try - \| call s:gitroot() | call git_blame() - \| catch | echo 'Not a git repo!' - \| endtry -command! GitNext try - \| call s:gitroot() | call git_next() | call s:git_info() - \| catch | echo 'Not a git repo!' - \| endtry -command! GitPrev call git_prev() | call s:git_info() -command! GitFirst call git_first() | call s:git_info() -command! GitLast call git_last() | call s:git_info() -command! GitInfo call git_info() -command! -nargs=1 GitCheckout call file_at_revision() -command! -nargs=? GitCompare try - \| call s:gitroot() | call git_diff() - \| catch | echo 'Not a git repo!' - \| endtry -command! Uncommited try - \| call s:gitroot() | call git_diff() - \| catch | echo 'Not a git repo!' - \| endtry -command! GitRoot try - \| echo gitroot() - \| catch | echo 'Not a git repository' - \| endtry +exec 'so '.s:root.'/git.vim' " === FILE STUFF ===