Mercurial > vim-lawrencium
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 |