comparison plugin/lawrencium.vim @ 107:6846e12f8ec8

Improvements for the `Hgdiff` family of commands - Only mess up with windows that are part of a specific diff session. - Show the old revision on the left/top, the newer on the right/bottom.
author Ludovic Chabant <ludovic@chabant.com>
date Fri, 15 Aug 2014 17:11:28 -0700
parents 77f77b2c2738
children 497f7a481599
comparison
equal deleted inserted replaced
106:77f77b2c2738 107:6846e12f8ec8
1274 1274
1275 function! s:HgDiff(filename, split, ...) abort 1275 function! s:HgDiff(filename, split, ...) abort
1276 " Default revisions to diff: the working directory (null string) 1276 " Default revisions to diff: the working directory (null string)
1277 " and the parent of the working directory (using Mercurial's revsets syntax). 1277 " and the parent of the working directory (using Mercurial's revsets syntax).
1278 " Otherwise, use the 1 or 2 revisions specified as extra parameters. 1278 " Otherwise, use the 1 or 2 revisions specified as extra parameters.
1279 let l:rev1 = '' 1279 let l:rev1 = 'p1()'
1280 let l:rev2 = 'p1()' 1280 let l:rev2 = ''
1281 if a:0 == 1 1281 if a:0 == 1
1282 if type(a:1) == type([]) 1282 if type(a:1) == type([])
1283 if len(a:1) >= 2 1283 if len(a:1) >= 2
1284 let l:rev1 = a:1[0] 1284 let l:rev1 = a:1[0]
1285 let l:rev2 = a:1[1] 1285 let l:rev2 = a:1[1]
1286 elseif len(a:1) == 1 1286 elseif len(a:1) == 1
1287 let l:rev2 = a:1[0] 1287 let l:rev1 = a:1[0]
1288 endif 1288 endif
1289 else 1289 else
1290 let l:rev2 = a:1 1290 let l:rev1 = a:1
1291 endif 1291 endif
1292 elseif a:0 == 2 1292 elseif a:0 == 2
1293 let l:rev1 = a:1 1293 let l:rev1 = a:1
1294 let l:rev2 = a:2 1294 let l:rev2 = a:2
1295 endif 1295 endif
1296 1296
1297 " Get the current repo, and expand the given filename in case it contains 1297 " Get the current repo, and expand the given filename in case it contains
1298 " fancy filename modifiers. 1298 " fancy filename modifiers.
1299 let l:repo = s:hg_repo() 1299 let l:repo = s:hg_repo()
1300 let l:path = expand(a:filename) 1300 let l:path = expand(a:filename)
1301 let l:diff_id = localtime()
1301 call s:trace("Diff'ing '".l:rev1."' and '".l:rev2."' on file: ".l:path) 1302 call s:trace("Diff'ing '".l:rev1."' and '".l:rev2."' on file: ".l:path)
1302
1303 " We'll keep a list of buffers in this diff, so when one exits, the
1304 " others' 'diff' flag is turned off.
1305 let l:diff_buffers = []
1306 1303
1307 " Get the first file and open it. 1304 " Get the first file and open it.
1308 let l:cleanupbufnr = -1 1305 let l:cleanupbufnr = -1
1309 if l:rev1 == '' 1306 if l:rev1 == ''
1310 if a:split == 2 1307 if a:split == 2
1321 else 1318 else
1322 execute 'edit ' . fnameescape(l:path) 1319 execute 'edit ' . fnameescape(l:path)
1323 endif 1320 endif
1324 endif 1321 endif
1325 " Make it part of the diff group. 1322 " Make it part of the diff group.
1326 call s:HgDiff_DiffThis() 1323 call s:HgDiff_DiffThis(l:diff_id)
1327 else 1324 else
1328 let l:rev_path = l:repo.GetLawrenciumPath(l:path, 'rev', l:rev1) 1325 let l:rev_path = l:repo.GetLawrenciumPath(l:path, 'rev', l:rev1)
1329 if a:split == 2 1326 if a:split == 2
1330 " See comments above about avoiding `tabedit`. 1327 " See comments above about avoiding `tabedit`.
1331 tabnew 1328 tabnew
1332 let l:cleanupbufnr = bufnr('%') 1329 let l:cleanupbufnr = bufnr('%')
1333 endif 1330 endif
1334 execute 'edit ' . fnameescape(l:rev_path) 1331 execute 'edit ' . fnameescape(l:rev_path)
1335 " Make it part of the diff group. 1332 " Make it part of the diff group.
1336 call s:HgDiff_DiffThis() 1333 call s:HgDiff_DiffThis(l:diff_id)
1337 endif 1334 endif
1338 if l:cleanupbufnr >= 0 && bufloaded(l:cleanupbufnr) 1335 if l:cleanupbufnr >= 0 && bufloaded(l:cleanupbufnr)
1339 execute 'bdelete ' . l:cleanupbufnr 1336 execute 'bdelete ' . l:cleanupbufnr
1340 endif 1337 endif
1341 1338
1342 " Get the second file and open it too. 1339 " Get the second file and open it too.
1343 let l:diffsplit = 'diffsplit' 1340 " Don't use `diffsplit` because it will set `&diff` before we get a chance
1341 " to save a bunch of local settings that we will want to restore later.
1342 let l:diffsplit = 'split'
1344 if a:split >= 1 1343 if a:split >= 1
1345 let l:diffsplit = 'vertical diffsplit' 1344 let l:diffsplit = 'vsplit'
1346 endif 1345 endif
1347 if l:rev2 == '' 1346 if l:rev2 == ''
1348 execute l:diffsplit . ' ' . fnameescape(l:path) 1347 execute l:diffsplit . ' ' . fnameescape(l:path)
1349 else 1348 else
1350 let l:rev_path = l:repo.GetLawrenciumPath(l:path, 'rev', l:rev2) 1349 let l:rev_path = l:repo.GetLawrenciumPath(l:path, 'rev', l:rev2)
1351 execute l:diffsplit . ' ' . fnameescape(l:rev_path) 1350 execute l:diffsplit . ' ' . fnameescape(l:rev_path)
1352 endif 1351 endif
1353 endfunction 1352 call s:HgDiff_DiffThis(l:diff_id)
1354 1353 endfunction
1355 function! s:HgDiff_DiffThis() abort 1354
1355 function! s:HgDiff_DiffThis(diff_id) abort
1356 " Store some commands to run when we exit diff mode. 1356 " Store some commands to run when we exit diff mode.
1357 " It's needed because `diffoff` reverts those settings to their default 1357 " It's needed because `diffoff` reverts those settings to their default
1358 " values, instead of their previous ones. 1358 " values, instead of their previous ones.
1359 if !&diff 1359 if &diff
1360 call s:trace('Enabling diff mode on ' . bufname('%')) 1360 call s:throw("Calling diffthis too late on a buffer!")
1361 let w:lawrencium_diffoff = {} 1361 return
1362 let w:lawrencium_diffoff['&diff'] = 0 1362 endif
1363 let w:lawrencium_diffoff['&wrap'] = &l:wrap 1363 call s:trace('Enabling diff mode on ' . bufname('%'))
1364 let w:lawrencium_diffoff['&scrollopt'] = &l:scrollopt 1364 let w:lawrencium_diffoff = {}
1365 let w:lawrencium_diffoff['&scrollbind'] = &l:scrollbind 1365 let w:lawrencium_diffoff['&diff'] = 0
1366 let w:lawrencium_diffoff['&cursorbind'] = &l:cursorbind 1366 let w:lawrencium_diffoff['&wrap'] = &l:wrap
1367 let w:lawrencium_diffoff['&foldmethod'] = &l:foldmethod 1367 let w:lawrencium_diffoff['&scrollopt'] = &l:scrollopt
1368 let w:lawrencium_diffoff['&foldcolumn'] = &l:foldcolumn 1368 let w:lawrencium_diffoff['&scrollbind'] = &l:scrollbind
1369 diffthis 1369 let w:lawrencium_diffoff['&cursorbind'] = &l:cursorbind
1370 endif 1370 let w:lawrencium_diffoff['&foldmethod'] = &l:foldmethod
1371 let w:lawrencium_diffoff['&foldcolumn'] = &l:foldcolumn
1372 let w:lawrencium_diff_id = a:diff_id
1373 diffthis
1374 autocmd BufWinLeave <buffer> call s:HgDiff_CleanUp()
1371 endfunction 1375 endfunction
1372 1376
1373 function! s:HgDiff_DiffOff(...) abort 1377 function! s:HgDiff_DiffOff(...) abort
1374 " Get the window name (given as a paramter, or current window). 1378 " Get the window name (given as a paramter, or current window).
1375 let l:nr = a:0 ? a:1 : winnr() 1379 let l:nr = a:0 ? a:1 : winnr()
1386 call s:trace('Disabling diff mode on ' . l:nr . ' (but no true restore)') 1390 call s:trace('Disabling diff mode on ' . l:nr . ' (but no true restore)')
1387 diffoff 1391 diffoff
1388 endif 1392 endif
1389 endfunction 1393 endfunction
1390 1394
1391 function! s:HgDiff_GetDiffWindows() abort 1395 function! s:HgDiff_GetDiffWindows(diff_id) abort
1392 let l:result = [] 1396 let l:result = []
1393 for nr in range(1, winnr('$')) 1397 for nr in range(1, winnr('$'))
1394 if getwinvar(nr, '&diff') 1398 if getwinvar(nr, '&diff') && getwinvar(nr, 'lawrencium_diff_id') == a:diff_id
1395 call add(l:result, nr) 1399 call add(l:result, nr)
1396 endif 1400 endif
1397 endfor 1401 endfor
1398 return l:result 1402 return l:result
1399 endfunction 1403 endfunction
1400 1404
1401 function! s:HgDiff_CleanUp() abort 1405 function! s:HgDiff_CleanUp() abort
1402 " If we're not leaving a diff window, do nothing. 1406 " If we're not leaving one of our diff window, do nothing.
1403 if !&diff 1407 if !&diff || !exists('w:lawrencium_diff_id')
1404 return 1408 return
1405 endif 1409 endif
1406 1410
1407 " If there will be only one diff window left (plus the one we're leaving), 1411 " If there will be only one diff window left (plus the one we're leaving),
1408 " turn off diff everywhere. 1412 " turn off diff in it and restore its local settings.
1409 let l:nrs = s:HgDiff_GetDiffWindows() 1413 let l:nrs = s:HgDiff_GetDiffWindows(w:lawrencium_diff_id)
1410 if len(l:nrs) <= 2 1414 if len(l:nrs) <= 2
1411 call s:trace('Disabling diff mode in ' . len(l:nrs) . ' windows.') 1415 call s:trace('Disabling diff mode in ' . len(l:nrs) . ' windows.')
1412 for nr in l:nrs 1416 for nr in l:nrs
1413 if getwinvar(nr, '&diff') 1417 if getwinvar(nr, '&diff')
1414 call s:HgDiff_DiffOff(nr) 1418 call s:HgDiff_DiffOff(nr)
1416 endfor 1420 endfor
1417 else 1421 else
1418 call s:trace('Still ' . len(l:nrs) . ' diff windows open.') 1422 call s:trace('Still ' . len(l:nrs) . ' diff windows open.')
1419 endif 1423 endif
1420 endfunction 1424 endfunction
1421
1422 augroup lawrencium_diff
1423 autocmd!
1424 autocmd BufWinLeave * call s:HgDiff_CleanUp()
1425 augroup end
1426 1425
1427 call s:AddMainCommand("-nargs=* Hgdiff :call s:HgDiff('%:p', 0, <f-args>)") 1426 call s:AddMainCommand("-nargs=* Hgdiff :call s:HgDiff('%:p', 0, <f-args>)")
1428 call s:AddMainCommand("-nargs=* Hgvdiff :call s:HgDiff('%:p', 1, <f-args>)") 1427 call s:AddMainCommand("-nargs=* Hgvdiff :call s:HgDiff('%:p', 1, <f-args>)")
1429 call s:AddMainCommand("-nargs=* Hgtabdiff :call s:HgDiff('%:p', 2, <f-args>)") 1428 call s:AddMainCommand("-nargs=* Hgtabdiff :call s:HgDiff('%:p', 2, <f-args>)")
1430 1429
1768 function! s:HgLog_Diff(split, ...) abort 1767 function! s:HgLog_Diff(split, ...) abort
1769 let l:revs = [] 1768 let l:revs = []
1770 if a:0 >= 2 1769 if a:0 >= 2
1771 let l:revs = [a:1, a:2] 1770 let l:revs = [a:1, a:2]
1772 elseif a:0 == 1 1771 elseif a:0 == 1
1773 let l:revs = [a:1, 'p1('.a:1.')'] 1772 let l:revs = ['p1('.a:1.')', a:1]
1774 else 1773 else
1775 let l:sel = s:HgLog_GetSelectedRev() 1774 let l:sel = s:HgLog_GetSelectedRev()
1776 let l:revs = [l:sel, 'p1('.l:sel.')'] 1775 let l:revs = ['p1('.l:sel.')', l:sel]
1777 endif 1776 endif
1778 1777
1779 let l:repo = s:hg_repo() 1778 let l:repo = s:hg_repo()
1780 let l:bufobj = s:buffer_obj() 1779 let l:bufobj = s:buffer_obj()
1781 let l:log_path = s:parse_lawrencium_path(l:bufobj.GetName()) 1780 let l:log_path = s:parse_lawrencium_path(l:bufobj.GetName())