bgneal@7: " ============================================================================= bgneal@7: " File: autoload/ctrlp/undo.vim bgneal@7: " Description: Undo extension bgneal@7: " Author: Kien Nguyen bgneal@7: " ============================================================================= bgneal@7: bgneal@7: " Init {{{1 bgneal@7: if ( exists('g:loaded_ctrlp_undo') && g:loaded_ctrlp_undo ) bgneal@7: fini bgneal@7: en bgneal@7: let g:loaded_ctrlp_undo = 1 bgneal@7: bgneal@7: cal add(g:ctrlp_ext_vars, { bgneal@7: \ 'init': 'ctrlp#undo#init()', bgneal@7: \ 'accept': 'ctrlp#undo#accept', bgneal@7: \ 'lname': 'undo', bgneal@7: \ 'sname': 'udo', bgneal@7: \ 'enter': 'ctrlp#undo#enter()', bgneal@7: \ 'exit': 'ctrlp#undo#exit()', bgneal@7: \ 'type': 'line', bgneal@7: \ 'sort': 0, bgneal@7: \ 'nolim': 1, bgneal@7: \ }) bgneal@7: bgneal@7: let s:id = g:ctrlp_builtins + len(g:ctrlp_ext_vars) bgneal@7: bgneal@7: let s:text = map(['second', 'seconds', 'minutes', 'hours', 'days', 'weeks', bgneal@7: \ 'months', 'years'], '" ".v:val." ago"') bgneal@7: " Utilities {{{1 bgneal@7: fu! s:getundo() bgneal@7: if exists('*undotree') bgneal@7: \ && ( v:version > 703 || ( v:version == 703 && has('patch005') ) ) bgneal@7: retu [1, undotree()] bgneal@7: el bgneal@7: redi => result bgneal@7: sil! undol bgneal@7: redi END bgneal@7: retu [0, split(result, "\n")[1:]] bgneal@7: en bgneal@7: endf bgneal@7: bgneal@7: fu! s:flatten(tree, cur) bgneal@7: let flatdict = {} bgneal@7: for each in a:tree bgneal@7: let saved = has_key(each, 'save') ? 'saved' : '' bgneal@7: let current = each['seq'] == a:cur ? 'current' : '' bgneal@7: cal extend(flatdict, { each['seq'] : [each['time'], saved, current] }) bgneal@7: if has_key(each, 'alt') bgneal@7: cal extend(flatdict, s:flatten(each['alt'], a:cur)) bgneal@7: en bgneal@7: endfo bgneal@7: retu flatdict bgneal@7: endf bgneal@7: bgneal@7: fu! s:elapsed(nr) bgneal@7: let [text, time] = [s:text, localtime() - a:nr] bgneal@7: let mins = time / 60 bgneal@7: let hrs = time / 3600 bgneal@7: let days = time / 86400 bgneal@7: let wks = time / 604800 bgneal@7: let mons = time / 2592000 bgneal@7: let yrs = time / 31536000 bgneal@7: if yrs > 1 bgneal@7: retu yrs.text[7] bgneal@7: elsei mons > 1 bgneal@7: retu mons.text[6] bgneal@7: elsei wks > 1 bgneal@7: retu wks.text[5] bgneal@7: elsei days > 1 bgneal@7: retu days.text[4] bgneal@7: elsei hrs > 1 bgneal@7: retu hrs.text[3] bgneal@7: elsei mins > 1 bgneal@7: retu mins.text[2] bgneal@7: elsei time == 1 bgneal@7: retu time.text[0] bgneal@7: elsei time < 120 bgneal@7: retu time.text[1] bgneal@7: en bgneal@7: endf bgneal@7: bgneal@7: fu! s:syntax() bgneal@7: if ctrlp#nosy() | retu | en bgneal@7: for [ke, va] in items({'T': 'Directory', 'Br': 'Comment', 'Nr': 'String', bgneal@7: \ 'Sv': 'Comment', 'Po': 'Title'}) bgneal@7: cal ctrlp#hicheck('CtrlPUndo'.ke, va) bgneal@7: endfo bgneal@7: sy match CtrlPUndoT '\v\d+ \zs[^ ]+\ze|\d+:\d+:\d+' bgneal@7: sy match CtrlPUndoBr '\[\|\]' bgneal@7: sy match CtrlPUndoNr '\[\d\+\]' contains=CtrlPUndoBr bgneal@7: sy match CtrlPUndoSv 'saved' bgneal@7: sy match CtrlPUndoPo 'current' bgneal@7: endf bgneal@7: bgneal@7: fu! s:dict2list(dict) bgneal@7: for ke in keys(a:dict) bgneal@7: let a:dict[ke][0] = s:elapsed(a:dict[ke][0]) bgneal@7: endfo bgneal@7: retu map(keys(a:dict), 'eval(''[v:val, a:dict[v:val]]'')') bgneal@7: endf bgneal@7: bgneal@7: fu! s:compval(...) bgneal@7: retu a:2[0] - a:1[0] bgneal@7: endf bgneal@7: bgneal@7: fu! s:format(...) bgneal@7: let saved = !empty(a:1[1][1]) ? ' '.a:1[1][1] : '' bgneal@7: let current = !empty(a:1[1][2]) ? ' '.a:1[1][2] : '' bgneal@7: retu a:1[1][0].' ['.a:1[0].']'.saved.current bgneal@7: endf bgneal@7: bgneal@7: fu! s:formatul(...) bgneal@7: let parts = matchlist(a:1, bgneal@7: \ '\v^\s+(\d+)\s+\d+\s+([^ ]+\s?[^ ]+|\d+\s\w+\s\w+)(\s*\d*)$') bgneal@7: retu parts == [] ? '----' bgneal@7: \ : parts[2].' ['.parts[1].']'.( parts[3] != '' ? ' saved' : '' ) bgneal@7: endf bgneal@7: " Public {{{1 bgneal@7: fu! ctrlp#undo#init() bgneal@7: let entries = s:undos[0] ? s:undos[1]['entries'] : s:undos[1] bgneal@7: if empty(entries) | retu [] | en bgneal@7: if !exists('s:lines') bgneal@7: if s:undos[0] bgneal@7: let entries = s:dict2list(s:flatten(entries, s:undos[1]['seq_cur'])) bgneal@7: let s:lines = map(sort(entries, 's:compval'), 's:format(v:val)') bgneal@7: el bgneal@7: let s:lines = map(reverse(entries), 's:formatul(v:val)') bgneal@7: en bgneal@7: en bgneal@7: cal s:syntax() bgneal@7: retu s:lines bgneal@7: endf bgneal@7: bgneal@7: fu! ctrlp#undo#accept(mode, str) bgneal@7: let undon = matchstr(a:str, '\[\zs\d\+\ze\]') bgneal@7: if empty(undon) | retu | en bgneal@7: cal ctrlp#exit() bgneal@7: exe 'u' undon bgneal@7: endf bgneal@7: bgneal@7: fu! ctrlp#undo#id() bgneal@7: retu s:id bgneal@7: endf bgneal@7: bgneal@7: fu! ctrlp#undo#enter() bgneal@7: let s:undos = s:getundo() bgneal@7: endf bgneal@7: bgneal@7: fu! ctrlp#undo#exit() bgneal@7: unl! s:lines bgneal@7: endf bgneal@7: "}}} bgneal@7: bgneal@7: " vim:fen:fdm=marker:fmr={{{,}}}:fdl=0:fdc=1:ts=2:sw=2:sts=2