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