comparison plugin/lawrencium.vim @ 65:e8f252a7ed9e

Made the `Hglog` window use Lawrencium buffers: - Added support for `hg log` with Lawrencium paths. - Fixed some bugs with `delete_dependency_buffers`. Miscellaneous: - Added support for `BufWinLeave` and `BufUnload` on buffer objects. - Added some comments.
author Ludovic Chabant <ludovic@chabant.com>
date Sat, 24 Nov 2012 08:50:30 -0800
parents e75ecde434d7
children 75e9d909758a
comparison
equal deleted inserted replaced
64:e75ecde434d7 65:e8f252a7ed9e
196 endif 196 endif
197 execute l:edit_cmd . fnameescape(a:path) 197 execute l:edit_cmd . fnameescape(a:path)
198 call setbufvar('%', a:varname, a:varvalue) 198 call setbufvar('%', a:varname, a:varvalue)
199 endfunction 199 endfunction
200 200
201 " Deletes all buffers that have a given variable set to a given value.
202 " For each buffer, if it is not shown in any window, it will be just deleted.
203 " If it is shown in a window, that window will be switched to the alternate
204 " buffer before the buffer is deleted, unless the `lawrencium_quit_on_delete`
205 " variable is set to `1`, in which case the window is closed too.
201 function! s:delete_dependency_buffers(varname, varvalue) abort 206 function! s:delete_dependency_buffers(varname, varvalue) abort
202 let l:cur_winnr = winnr() 207 let l:cur_winnr = winnr()
203 for bnr in range(1, bufnr('$')) 208 for bnr in range(1, bufnr('$'))
204 if getbufvar(bnr, a:varname) == a:varvalue 209 if getbufvar(bnr, a:varname) == a:varvalue
205 " Delete this buffer if it is not shown in any window. 210 " Delete this buffer if it is not shown in any window.
214 call s:trace("Dependency buffer " . bnr . " is already unladed.") 219 call s:trace("Dependency buffer " . bnr . " is already unladed.")
215 endif 220 endif
216 else 221 else
217 execute l:bwnr . "wincmd w" 222 execute l:bwnr . "wincmd w"
218 " TODO: better handle case where there's no previous/alternate buffer? 223 " TODO: better handle case where there's no previous/alternate buffer?
219 if bufnr('#') > 0 && bufloaded(bufnr('#')) 224 let l:prev_bnr = bufnr('#')
220 bprevious 225 if l:prev_bnr > 0 && bufloaded(l:prev_bnr)
226 execute "buffer " . l:prev_bnr
221 if bufloaded(l:bnr) 227 if bufloaded(l:bnr)
222 call s:trace("Deleting dependency buffer " . bnr . " after buffer switching.") 228 call s:trace("Deleting dependency buffer " . bnr . " after switching to " . l:prev_bnr . " in window " . l:bwnr)
223 execute "bdelete! " . bnr 229 execute "bdelete! " . bnr
224 else 230 else
225 call s:trace("Dependency buffer " . bnr . " is unladed after buffer switching.") 231 call s:trace("Dependency buffer " . bnr . " is unladed after switching to " . l:prev_bnr)
226 endif 232 endif
227 else 233 else
228 call s:trace("Deleting dependency buffer " . bnr . " and window.") 234 call s:trace("Deleting dependency buffer " . bnr . " and window.")
229 bdelete! 235 bdelete!
230 endif 236 endif
231 endif 237 endif
232 endif 238 endif
233 endfor 239 endfor
234 if l:cur_winnr != winnr() 240 if l:cur_winnr != winnr()
241 call s:trace("Returning to window " . l:cur_winnr)
235 execute l:cur_winnr . "wincmd w" 242 execute l:cur_winnr . "wincmd w"
236 endif 243 endif
237 endfunction 244 endfunction
238 245
239 " }}} 246 " }}}
407 let l:newBuffer = copy(self) 414 let l:newBuffer = copy(self)
408 let l:newBuffer.nr = a:number 415 let l:newBuffer.nr = a:number
409 let l:newBuffer.var_backup = {} 416 let l:newBuffer.var_backup = {}
410 let l:newBuffer.on_delete = [] 417 let l:newBuffer.on_delete = []
411 let l:newBuffer.on_winleave = [] 418 let l:newBuffer.on_winleave = []
419 let l:newBuffer.on_unload = []
412 execute 'augroup lawrencium_buffer_' . a:number 420 execute 'augroup lawrencium_buffer_' . a:number
413 execute ' autocmd!' 421 execute ' autocmd!'
414 execute ' autocmd BufDelete <buffer=' . a:number . '> call s:buffer_on_delete(' . a:number . ')' 422 execute ' autocmd BufDelete <buffer=' . a:number . '> call s:buffer_on_delete(' . a:number . ')'
415 execute 'augroup end' 423 execute 'augroup end'
416 call s:trace("Built new buffer object for buffer: " . a:number) 424 call s:trace("Built new buffer object for buffer: " . a:number)
440 endfunction 448 endfunction
441 449
442 function! s:Buffer.OnWinLeave(cmd) dict abort 450 function! s:Buffer.OnWinLeave(cmd) dict abort
443 if len(self.on_winleave) == 0 451 if len(self.on_winleave) == 0
444 call s:trace("Adding BufWinLeave auto-command on buffer " . self.nr) 452 call s:trace("Adding BufWinLeave auto-command on buffer " . self.nr)
445 execute 'autocmd BufWinLeave <buffer=' . self.nr . '> call s:buffer_on_winleave(' . self.nr .')' 453 execute 'augroup lawrencium_buffer_' . self.nr . '_winleave'
454 execute ' autocmd!'
455 execute ' autocmd BufWinLeave <buffer=' . self.nr . '> call s:buffer_on_winleave(' . self.nr .')'
456 execute 'augroup end'
446 endif 457 endif
447 call s:trace("Adding BufWinLeave callback for buffer " . self.nr . ": " . a:cmd) 458 call s:trace("Adding BufWinLeave callback for buffer " . self.nr . ": " . a:cmd)
448 call add(self.on_winleave, a:cmd) 459 call add(self.on_winleave, a:cmd)
460 endfunction
461
462 function! s:Buffer.OnUnload(cmd) dict abort
463 if len(self.on_unload) == 0
464 call s:trace("Adding BufUnload auto-command on buffer " . self.nr)
465 execute 'augroup lawrencium_buffer_' . self.nr . '_unload'
466 execute ' autocmd!'
467 execute ' autocmd BufUnload <buffer=' . self.nr . '> call s:buffer_on_unload(' . self.nr . ')'
468 execute 'augroup end'
469 endif
470 call s:trace("Adding BufUnload callback for buffer " . self.nr . ": " . a:cmd)
471 call add(self.on_unload, a:cmd)
449 endfunction 472 endfunction
450 473
451 let s:buffer_objects = {} 474 let s:buffer_objects = {}
452 475
453 " Get a buffer instance for the specified buffer number, or the 476 " Get a buffer instance for the specified buffer number, or the
481 call s:trace("Calling BufWinLeave callbacks on buffer " . l:bufobj.nr) 504 call s:trace("Calling BufWinLeave callbacks on buffer " . l:bufobj.nr)
482 for cmd in l:bufobj.on_winleave 505 for cmd in l:bufobj.on_winleave
483 call s:trace(" [" . cmd . "]") 506 call s:trace(" [" . cmd . "]")
484 execute cmd 507 execute cmd
485 endfor 508 endfor
509 execute 'augroup lawrencium_buffer_' . l:bufobj.nr . '_winleave'
510 execute ' autocmd!'
511 execute 'augroup end'
512 endfunction
513
514 " Execute all the "on unload" callbacks.
515 function! s:buffer_on_unload(number) abort
516 let l:bufobj = s:buffer_objects[a:number]
517 call s:trace("Calling BufUnload callbacks on buffer " . l:bufobj.nr)
518 for cmd in l:bufobj.on_unload
519 call s:trace(" [" . cmd . "]")
520 execute cmd
521 endfor
522 execute 'augroup lawrencium_buffer_' . l:bufobj.nr . '_unload'
523 execute ' autocmd!'
524 execute 'augroup end'
486 endfunction 525 endfunction
487 526
488 " }}} 527 " }}}
489 528
490 " Buffer Commands Management {{{ 529 " Buffer Commands Management {{{
1154 1193
1155 " }}} 1194 " }}}
1156 1195
1157 " Hglog, Hgrepolog {{{ 1196 " Hglog, Hgrepolog {{{
1158 1197
1159 let s:log_style_file = expand("<sfile>:h:h") . "/resources/hg_log.style"
1160
1161 function! s:HgLog(is_file, ...) abort 1198 function! s:HgLog(is_file, ...) abort
1162 " Get the file or directory to get the log from, or figure out 1199 " Get the file or directory to get the log from, or figure out
1163 " some nice defaults (the current file, or the whole repository). 1200 " some nice defaults (the current file, or the whole repository).
1164 if a:is_file 1201 if a:is_file
1165 let l:log_path = expand('%:p') 1202 let l:path = expand('%:p')
1166 else 1203 else
1167 let l:log_path = '.' 1204 let l:path = ''
1168 endif
1169
1170 " If the file or directory is specified, get the absolute path.
1171 let l:repo = s:hg_repo()
1172 if a:0 == 1
1173 let l:log_path = l:repo.GetFullPath(a:1)
1174 endif
1175
1176 " Run the command.
1177 if l:log_path == '.'
1178 let l:output = l:repo.RunCommand('log', '--style', shellescape(s:log_style_file))
1179 else
1180 let l:output = l:repo.RunCommand('log', '--style', shellescape(s:log_style_file), l:log_path)
1181 endif 1205 endif
1182 1206
1183 " Remember the file that opened this log. 1207 " Remember the file that opened this log.
1184 let l:original_path = expand('%:p') 1208 let l:original_path = expand('%:p')
1185 1209
1186 " Open a new temp buffer in the preview window, jump to it, 1210 " Get the Lawrencium path for this `hg log`.
1187 " and paste the `hg log` output in there. 1211 let l:repo = s:hg_repo()
1188 let l:temp_file = s:tempname('hg-log-', '.txt') 1212 let l:log_path = l:repo.GetLawrenciumPath(l:path, 'log', '')
1189 execute "pedit " . l:temp_file 1213
1214 " Open it in a preview window and jump to it.
1215 execute 'pedit ' . l:log_path
1190 wincmd P 1216 wincmd P
1191 call append(0, split(l:output, '\n'))
1192 call cursor(1, 1)
1193
1194 " Setup the buffer correctly: readonly, and with the correct repo linked
1195 " to it, and deleted on close.
1196 let b:mercurial_dir = l:repo.root_dir
1197 let b:lawrencium_logged_path = l:repo.GetRelativePath(l:log_path)
1198 let b:lawrencium_original_path = l:original_path
1199 setlocal bufhidden=delete
1200 setlocal buftype=nofile
1201 setlocal filetype=hglog
1202
1203 " Make commands available.
1204 call s:DefineMainCommands()
1205 1217
1206 " Add some other nice commands and mappings. 1218 " Add some other nice commands and mappings.
1207 command! -buffer -nargs=* Hglogdiff :call s:HgLog_Diff(<f-args>) 1219 command! -buffer -nargs=* Hglogdiff :call s:HgLog_Diff(<f-args>)
1208 if a:is_file 1220 if a:is_file
1221 let b:lawrencium_logged_path = l:repo.GetRelativePath(l:path)
1209 command! -buffer -nargs=? Hglogrevedit :call s:HgLog_FileRevEdit(<f-args>) 1222 command! -buffer -nargs=? Hglogrevedit :call s:HgLog_FileRevEdit(<f-args>)
1210 endif 1223 endif
1211 1224
1212 if g:lawrencium_define_mappings 1225 if g:lawrencium_define_mappings
1213 nnoremap <buffer> <silent> <cr> :Hglogdiff<cr> 1226 nnoremap <buffer> <silent> <cr> :Hglogdiff<cr>
1217 endif 1230 endif
1218 endif 1231 endif
1219 1232
1220 " Clean up when the log buffer is deleted. 1233 " Clean up when the log buffer is deleted.
1221 let l:bufobj = s:buffer_obj() 1234 let l:bufobj = s:buffer_obj()
1222 call l:bufobj.OnDelete('call s:HgLog_Delete(' . l:bufobj.nr . ', "' . fnameescape(l:temp_file) . '")') 1235 call l:bufobj.OnDelete('call s:HgLog_Delete(' . l:bufobj.nr . ')')
1223 endfunction 1236 endfunction
1224 1237
1225 function! s:HgLog_Delete(bufnr, path) 1238 function! s:HgLog_Delete(bufnr)
1226 if g:lawrencium_auto_close_buffers 1239 if g:lawrencium_auto_close_buffers
1227 call s:delete_dependency_buffers('lawrencium_diff_for', a:bufnr) 1240 call s:delete_dependency_buffers('lawrencium_diff_for', a:bufnr)
1228 call s:delete_dependency_buffers('lawrencium_rev_for', a:bufnr) 1241 call s:delete_dependency_buffers('lawrencium_rev_for', a:bufnr)
1229 endif 1242 endif
1230 " Delete the temp file if it was created somehow.
1231 call s:clean_tempfile(a:path)
1232 endfunction 1243 endfunction
1233 1244
1234 function! s:HgLog_FileRevEdit(...) 1245 function! s:HgLog_FileRevEdit(...)
1235 if a:0 > 0 1246 if a:0 > 0
1236 " Revision was given manually. 1247 " Revision was given manually.
1405 1416
1406 " }}} 1417 " }}}
1407 1418
1408 " Lawrencium files {{{ 1419 " Lawrencium files {{{
1409 1420
1421 let s:log_style_file = expand("<sfile>:h:h") . "/resources/hg_log.style"
1422
1410 function! s:ReadLawrenciumFile(path) abort 1423 function! s:ReadLawrenciumFile(path) abort
1411 call s:trace("Reading Lawrencium file '" . a:path) 1424 call s:trace("Reading Lawrencium file '" . a:path)
1412 let l:comps = s:parse_lawrencium_path(a:path) 1425 let l:comps = s:parse_lawrencium_path(a:path)
1413 if l:comps['root'] == '' 1426 if l:comps['root'] == ''
1414 call s:throw("Can't get repository root from: " . a:path) 1427 call s:throw("Can't get repository root from: " . a:path)
1429 call l:repo.ReadCommandOutput('status') 1442 call l:repo.ReadCommandOutput('status')
1430 else 1443 else
1431 call l:repo.ReadCommandOutput('status', l:full_path) 1444 call l:repo.ReadCommandOutput('status', l:full_path)
1432 endif 1445 endif
1433 setlocal filetype=hgstatus 1446 setlocal filetype=hgstatus
1447 elseif l:comps['action'] == 'log'
1448 " Log (`hg log`)
1449 if l:comps['path'] == ''
1450 call l:repo.ReadCommandOutput('log', '--style', shellescape(s:log_style_file))
1451 else
1452 call l:repo.ReadCommandOutput('log', '--style', shellescape(s:log_style_file), l:full_path)
1453 endif
1454 setlocal filetype=hglog
1434 elseif l:comps['action'] == 'diff' 1455 elseif l:comps['action'] == 'diff'
1435 " Diff revisions (`hg diff`) 1456 " Diff revisions (`hg diff`)
1436 let l:diffargs = [] 1457 let l:diffargs = []
1437 let l:commaidx = stridx(l:comps['value'], ',') 1458 let l:commaidx = stridx(l:comps['value'], ',')
1438 if l:commaidx > 0 1459 if l:commaidx > 0