" Author: Eric Van Dewoestine " " License: {{{ " " Copyright (C) 2005 - 2014 Eric Van Dewoestine " " This program is free software: you can redistribute it and/or modify " it under the terms of the GNU General Public License as published by " the Free Software Foundation, either version 3 of the License, or " (at your option) any later version. " " This program is distributed in the hope that it will be useful, " but WITHOUT ANY WARRANTY; without even the implied warranty of " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the " GNU General Public License for more details. " " You should have received a copy of the GNU General Public License " along with this program. If not, see . " " }}} " Script Variables {{{ let s:command_add = '-command history_add -p "" -f ""' let s:command_list = '-command history_list -p "" -f ""' let s:command_revision = \ '-command history_revision -p "" -f "" -r ' let s:command_clear = '-command history_clear -p "" -f ""' " }}} function! eclim#common#history#AddHistory() " {{{ " Adds the current state of the file to the eclipse local history (should be " invoked prior to saving to disk). if !filereadable(expand('%')) || !eclim#project#util#IsCurrentFileInProject(0) return endif let project = eclim#project#util#GetCurrentProjectName() let file = eclim#project#util#GetProjectRelativeFilePath() let command = s:command_add let command = substitute(command, '', project, '') let command = substitute(command, '', file, '') call eclim#Execute(command) endfunction " }}} function! eclim#common#history#History() " {{{ " Opens a temporary buffer with a list of local history revisions. if !eclim#project#util#IsCurrentFileInProject() return endif let project = eclim#project#util#GetCurrentProjectName() let file = eclim#project#util#GetProjectRelativeFilePath() let command = s:command_list let command = substitute(command, '', project, '') let command = substitute(command, '', file, '') let history = eclim#Execute(command) if type(history) != g:LIST_TYPE return endif let lines = [file] let revisions = [0] let indent = eclim#util#GetIndent(1) for rev in history call add(lines, indent . rev.datetime . ' (' . rev.delta . ')') call add(revisions, rev.timestamp) endfor call add(lines, '') call eclim#util#TempWindow('[History]', lines) setlocal modifiable noreadonly if !g:EclimKeepLocalHistory call append(line('$'), \ '" Note: local history is currently disabled: ' . \ 'g:EclimKeepLocalHistory = ' . g:EclimKeepLocalHistory) endif call append(line('$'), '" use ? to view help') setlocal nomodifiable readonly syntax match Comment /^".*/ let b:history_revisions = revisions call s:Syntax() command! -count=1 HistoryDiffNext call s:DiffNextPrev(1, ) command! -count=1 HistoryDiffPrev call s:DiffNextPrev(-1, ) augroup eclim_history_window autocmd! BufWinLeave autocmd BufWinLeave \ delcommand HistoryDiffNext | \ delcommand HistoryDiffPrev augroup END noremap :call View() noremap d :call Diff() noremap r :call Revert() noremap c :call Clear(1) " assign to buffer var to get around weird vim issue passing list containing " a string w/ a '<' in it on execution of mapping. let b:history_help = [ \ ' - view the entry', \ 'd - diff the file with the version under the cursor', \ 'r - revert the file to the version under the cursor', \ 'c - clear the history', \ ':HistoryDiffNext - diff the file with the next version in the history', \ ':HistoryDiffPrev - diff the file with the previous version in the history', \ ] nnoremap ? \ :call eclim#help#BufferHelp(b:history_help, 'vertical', 50) endfunction " }}} function! eclim#common#history#HistoryClear(bang) " {{{ " Clear the history for the current file. if !eclim#project#util#IsCurrentFileInProject() return endif call s:Clear(a:bang == '', expand('%:p')) endfunction " }}} function s:View(...) " {{{ " View the contents of the revision under the cursor. if line('.') == 1 || line('.') > len(b:history_revisions) return endif let current = b:filename let entry = line('.') - 1 let revision = b:history_revisions[entry] if eclim#util#GoToBufferWindow(current) let filetype = &ft let project = eclim#project#util#GetCurrentProjectName() let file = eclim#project#util#GetProjectRelativeFilePath() let command = s:command_revision let command = substitute(command, '', project, '') let command = substitute(command, '', file, '') let command = substitute(command, '', revision, '') let result = eclim#Execute(command) if result == "0" return endif let cmd = len(a:000) > 0 ? a:000[0] : 'split' call eclim#util#GoToBufferWindowOrOpen( \ current . '_' . revision, 'keepalt ' . cmd) setlocal modifiable setlocal noreadonly let temp = tempname() call writefile(split(result, '\n'), temp) try silent 1,$delete _ silent read ++edit `=temp` silent 1,1delete _ finally call delete(temp) endtry exec 'setlocal filetype=' . filetype setlocal nomodified setlocal readonly setlocal nomodifiable setlocal noswapfile setlocal nobuflisted setlocal buftype=nofile setlocal bufhidden=wipe doautocmd BufReadPost call s:HighlightEntry(entry) return 1 else call eclim#util#EchoWarning('Target file is no longer open.') endif endfunction " }}} function s:Diff() " {{{ " Diff the contents of the revision under the cursor against the current " contents. let hist_buf = bufnr('%') let winend = winnr('$') let winnum = 1 while winnum <= winend let bufnr = winbufnr(winnum) if getbufvar(bufnr, 'history_diff') != '' exec bufnr . 'bd' continue endif let winnum += 1 endwhile call eclim#util#GoToBufferWindow(hist_buf) let current = b:filename let orien = g:EclimHistoryDiffOrientation == 'horizontal' ? '' : 'vertical' if s:View(orien . ' below split') let b:history_diff = 1 diffthis augroup history_diff autocmd! BufWinLeave call eclim#util#GoToBufferWindowRegister(current) autocmd BufWinLeave diffoff augroup END call eclim#util#GoToBufferWindow(current) diffthis endif endfunction " }}} function s:DiffNextPrev(dir, count) " {{{ let winnr = winnr() if eclim#util#GoToBufferWindow('[History]') let num = v:count > 0 ? v:count : a:count let cur = exists('b:history_current_entry') ? b:history_current_entry : 0 let index = cur + (a:dir * num) if index < 0 || index > len(b:history_revisions) call eclim#util#EchoError('Operation exceeds history stack range.') exec winnr . 'winc w' return endif call cursor(index + 1, 0) call s:Diff() endif endfunction " }}} function s:Revert() " {{{ " Revert the file to the revision under the cursor. if line('.') == 1 || line('.') > len(b:history_revisions) return endif let current = b:filename let revision = b:history_revisions[line('.') - 1] if eclim#util#GoToBufferWindow(current) let project = eclim#project#util#GetCurrentProjectName() let file = eclim#project#util#GetProjectRelativeFilePath() let command = s:command_revision let command = substitute(command, '', project, '') let command = substitute(command, '', file, '') let command = substitute(command, '', revision, '') let result = eclim#Execute(command) if result == "0" return endif let ff = &ff let temp = tempname() call writefile(split(result, '\n'), temp) try silent 1,$delete _ silent read ++edit `=temp` silent 1,1delete _ finally call delete(temp) endtry if ff != &ff call eclim#util#EchoWarning( \ "Warning: the file format is being reverted from '" . ff . "' to '" . \ &ff . "'. Using vim's undo will not restore the previous format so " . \ "if you choose to undo the reverting of this file, you will need to " . \ "manually set the file format back to " . ff . " (set ff=" . ff . ").") endif endif endfunction " }}} function s:Clear(prompt, ...) " {{{ " Optional args: " filename let response = 1 if a:prompt let response = eclim#util#PromptConfirm( \ 'Clear local history?', g:EclimHighlightInfo) endif if response == 1 let filename = len(a:000) > 0 ? a:000[0] : b:filename let current = eclim#project#util#GetProjectRelativeFilePath(filename) let project = eclim#project#util#GetCurrentProjectName() let command = s:command_clear let command = substitute(command, '', project, '') let command = substitute(command, '', current, '') let result = eclim#Execute(command) if result == "0" return endif if filename != expand('%:p') quit endif call eclim#util#Echo(result) endif endfunction " }}} function! s:Syntax() " {{{ set ft=eclim_history hi link HistoryFile Identifier hi link HistoryCurrentEntry Constant syntax match HistoryFile /.*\%1l.*/ syntax match Comment /^".*/ endfunction " }}} function s:HighlightEntry(index) " {{{ let winnr = winnr() if eclim#util#GoToBufferWindow('[History]') let b:history_current_entry = a:index try " forces reset of syntax call s:Syntax() exec 'syntax match HistoryCurrentEntry /.*\%' . (a:index + 1) . 'l.*/' finally exec winnr . 'winc w' endtry endif endfunction " }}} " vim:ft=vim:fdm=marker