comparison plugin/lawrencium.vim @ 71:1fbba48019b5

MQ support: - Added `Hgqseries` command to navigate MQ series. - Ability to go to, rename, and edit the message of a patch. - Wrote documentation. Fixed a bug with the `Hgstatus` being `readonly`.
author Ludovic Chabant <ludovic@chabant.com>
date Sun, 16 Feb 2014 16:00:16 -0800
parents 16e873b2a4a8
children a987094d5ae6
comparison
equal deleted inserted replaced
70:16e873b2a4a8 71:1fbba48019b5
241 call s:trace("Returning to window " . l:cur_winnr) 241 call s:trace("Returning to window " . l:cur_winnr)
242 execute l:cur_winnr . "wincmd w" 242 execute l:cur_winnr . "wincmd w"
243 endif 243 endif
244 endfunction 244 endfunction
245 245
246 " Clean up all the 'HG:' lines from a commit message, and see if there's
247 " any message left (Mercurial does this automatically, usually, but
248 " apparently not when you feed it a log file...).
249 function! s:clean_commit_file(log_file) abort
250 let l:lines = readfile(a:log_file)
251 call filter(l:lines, "v:val !~# '\\v^HG:'")
252 if len(filter(copy(l:lines), "v:val !~# '\\v^\\s*$'")) == 0
253 return 0
254 endif
255 call writefile(l:lines, a:log_file)
256 return 1
257 endfunction
258
246 " }}} 259 " }}}
247 260
248 " Mercurial Repository Object {{{ 261 " Mercurial Repository Object {{{
249 262
250 " Let's define a Mercurial repo 'class' using prototype-based object-oriented 263 " Let's define a Mercurial repo 'class' using prototype-based object-oriented
546 if a:path_parts['path'] == '' 559 if a:path_parts['path'] == ''
547 call a:repo.ReadCommandOutput('status') 560 call a:repo.ReadCommandOutput('status')
548 else 561 else
549 call a:repo.ReadCommandOutput('status', a:full_path) 562 call a:repo.ReadCommandOutput('status', a:full_path)
550 endif 563 endif
564 setlocal nomodified
551 setlocal filetype=hgstatus 565 setlocal filetype=hgstatus
566 setlocal bufhidden=delete
567 setlocal buftype=nofile
552 endfunction 568 endfunction
553 569
554 " Log (`hg log`) 570 " Log (`hg log`)
555 let s:log_style_file = expand("<sfile>:h:h") . "/resources/hg_log.style" 571 let s:log_style_file = expand("<sfile>:h:h") . "/resources/hg_log.style"
556 572
593 " Annotate file 609 " Annotate file
594 function! s:read_lawrencium_annotate(repo, path_parts, full_path) abort 610 function! s:read_lawrencium_annotate(repo, path_parts, full_path) abort
595 call a:repo.ReadCommandOutput('annotate', '-c', '-n', '-u', '-d', '-q', a:full_path) 611 call a:repo.ReadCommandOutput('annotate', '-c', '-n', '-u', '-d', '-q', a:full_path)
596 endfunction 612 endfunction
597 613
614 " MQ series
615 function! s:read_lawrencium_qseries(repo, path_parts, full_path) abort
616 let l:names = split(a:repo.RunCommand('qseries'), '\n')
617 let l:head = split(a:repo.RunCommand('qapplied', '-s'), '\n')
618 let l:tail = split(a:repo.RunCommand('qunapplied', '-s'), '\n')
619
620 let l:idx = 0
621 let l:curbuffer = bufname('%')
622 for line in l:head
623 call setbufvar(l:curbuffer, 'lawrencium_patchname_' . (l:idx + 1), l:names[l:idx])
624 call append(l:idx, "*" . line)
625 let l:idx = l:idx + 1
626 endfor
627 for line in l:tail
628 call setbufvar(l:curbuffer, 'lawrencium_patchname_' . (l:idx + 1), l:names[l:idx])
629 call append(l:idx, line)
630 let l:idx = l:idx + 1
631 endfor
632 set filetype=hgqseries
633 endfunction
634
598 " Generic read 635 " Generic read
599 let s:lawrencium_file_readers = { 636 let s:lawrencium_file_readers = {
600 \'rev': function('s:read_lawrencium_rev'), 637 \'rev': function('s:read_lawrencium_rev'),
601 \'log': function('s:read_lawrencium_log'), 638 \'log': function('s:read_lawrencium_log'),
602 \'diff': function('s:read_lawrencium_diff'), 639 \'diff': function('s:read_lawrencium_diff'),
603 \'status': function('s:read_lawrencium_status'), 640 \'status': function('s:read_lawrencium_status'),
604 \'annotate': function('s:read_lawrencium_annotate') 641 \'annotate': function('s:read_lawrencium_annotate'),
642 \'qseries': function('s:read_lawrencium_qseries')
643 \}
644 let s:lawrencium_file_customoptions = {
645 \'status': 1
605 \} 646 \}
606 647
607 function! s:ReadLawrenciumFile(path) abort 648 function! s:ReadLawrenciumFile(path) abort
608 call s:trace("Reading Lawrencium file: " . a:path) 649 call s:trace("Reading Lawrencium file: " . a:path)
609 let l:path_parts = s:parse_lawrencium_path(a:path) 650 let l:path_parts = s:parse_lawrencium_path(a:path)
619 let l:full_path = l:repo.root_dir . l:path_parts['path'] 660 let l:full_path = l:repo.root_dir . l:path_parts['path']
620 let LawrenciumFileReader = s:lawrencium_file_readers[l:path_parts['action']] 661 let LawrenciumFileReader = s:lawrencium_file_readers[l:path_parts['action']]
621 call LawrenciumFileReader(l:repo, l:path_parts, l:full_path) 662 call LawrenciumFileReader(l:repo, l:path_parts, l:full_path)
622 663
623 " Setup the new buffer. 664 " Setup the new buffer.
624 setlocal readonly 665 if !has_key(s:lawrencium_file_customoptions, l:path_parts['action'])
625 setlocal nomodified 666 setlocal readonly
626 setlocal bufhidden=delete 667 setlocal nomodified
627 setlocal buftype=nofile 668 setlocal bufhidden=delete
669 setlocal buftype=nofile
670 endif
628 goto 671 goto
629 672
630 " Remember the repo it belongs to and make 673 " Remember the repo it belongs to and make
631 " the Lawrencium commands available. 674 " the Lawrencium commands available.
632 let b:mercurial_dir = l:repo.root_dir 675 let b:mercurial_dir = l:repo.root_dir
1288 return 1331 return
1289 endif 1332 endif
1290 1333
1291 call s:trace("Committing with log file: " . a:log_file) 1334 call s:trace("Committing with log file: " . a:log_file)
1292 1335
1293 " Clean up all the 'HG:' lines from the commit message, and see if there's 1336 " Clean all the 'HG: ' lines.
1294 " any message left (Mercurial does this automatically, usually, but 1337 let l:is_valid = s:clean_commit_file(a:log_file)
1295 " apparently not when you feed it a log file...). 1338 if !l:is_valid
1296 let l:lines = readfile(a:log_file)
1297 call filter(l:lines, "v:val !~# '\\v^HG:'")
1298 if len(filter(copy(l:lines), "v:val !~# '\\v^\\s*$'")) == 0
1299 call s:error("abort: Empty commit message") 1339 call s:error("abort: Empty commit message")
1300 return 1340 return
1301 endif 1341 endif
1302 call writefile(l:lines, a:log_file)
1303 1342
1304 " Get the repo and commit with the given message. 1343 " Get the repo and commit with the given message.
1305 let l:repo = s:hg_repo() 1344 let l:repo = s:hg_repo()
1306 let l:hg_args = ['-l', a:log_file] 1345 let l:hg_args = ['-l', a:log_file]
1307 call extend(l:hg_args, b:lawrencium_commit_files) 1346 call extend(l:hg_args, b:lawrencium_commit_files)
1559 1598
1560 call s:AddMainCommand("Hgannotate :call s:HgAnnotate()") 1599 call s:AddMainCommand("Hgannotate :call s:HgAnnotate()")
1561 1600
1562 " }}} 1601 " }}}
1563 1602
1603 " Hgqseries {{{
1604
1605 function! s:HgQSeries() abort
1606 " Open the MQ series in the preview window and jump to it.
1607 let l:repo = s:hg_repo()
1608 let l:path = l:repo.GetLawrenciumPath('', 'qseries', '')
1609 execute 'pedit ' . l:path
1610 wincmd P
1611
1612 " Make the series buffer a Lawrencium buffer.
1613 let b:mercurial_dir = l:repo.root_dir
1614 call s:DefineMainCommands()
1615
1616 " Add some commands and mappings.
1617 command! -buffer Hgqseriesgoto :call s:HgQSeries_Goto()
1618 command! -buffer Hgqserieseditmessage :call s:HgQSeries_EditMessage()
1619 command! -buffer -nargs=+ Hgqseriesrename :call s:HgQSeries_Rename(<f-args>)
1620 if g:lawrencium_define_mappings
1621 nnoremap <buffer> <silent> <C-g> :Hgqseriesgoto<cr>
1622 nnoremap <buffer> <silent> <C-e> :Hgqserieseditmessage<cr>
1623 nnoremap <buffer> <silent> q :bdelete!<cr>
1624 endif
1625 endfunction
1626
1627 function! s:HgQSeries_GetCurrentPatchName() abort
1628 let l:pos = getpos('.')
1629 return getbufvar('%', 'lawrencium_patchname_' . l:pos[1])
1630 endfunction
1631
1632 function! s:HgQSeries_Goto() abort
1633 let l:repo = s:hg_repo()
1634 let l:patchname = HgQSeries_GetCurrentPatchName()
1635 if len(l:patchname) == 0
1636 call s:error("No patch to go to here.")
1637 return
1638 endif
1639 call l:repo.RunCommand('qgoto', l:patchname)
1640 edit
1641 endfunction
1642
1643 function! s:HgQSeries_Rename(...) abort
1644 let l:repo = s:hg_repo()
1645 let l:current_name = HgQSeries_GetCurrentPatchName()
1646 if len(l:current_name) == 0
1647 call s:error("No patch to rename here.")
1648 return
1649 endif
1650 let l:new_name = '"' . join(a:000, ' ') . '"'
1651 call l:repo.RunCommand('qrename', l:current_name, l:new_name)
1652 edit
1653 endfunction
1654
1655 function! s:HgQSeries_EditMessage() abort
1656 let l:repo = s:hg_repo()
1657 let l:patchname = getbufvar('%', 'lawrencium_patchname_1')
1658 if len(l:patchname) == 0
1659 call s:error("No patch to edit here.")
1660 return
1661 endif
1662 let l:current = split(l:repo.RunCommand('qheader', l:patchname), '\n')
1663
1664 " Open a temp file to write the commit message.
1665 let l:temp_file = s:tempname('hg-qrefedit-', '.txt')
1666 split
1667 execute 'edit ' . l:temp_file
1668 call append(0, 'HG: Enter the new commit message for patch "' . l:patchname . '" here.\n')
1669 call append(0, '')
1670 call append(0, l:current)
1671 call cursor(1, 1)
1672
1673 " Make it a temp buffer that will actually change the commit message
1674 " when it is saved and closed.
1675 let b:mercurial_dir = l:repo.root_dir
1676 let b:lawrencium_patchname = l:patchname
1677 setlocal bufhidden=delete
1678 setlocal filetype=hgcommit
1679 autocmd BufDelete <buffer> call s:HgQSeries_EditMessage_Execute(expand('<afile>:p'))
1680
1681 call s:DefineMainCommands()
1682 endfunction
1683
1684 function! s:HgQSeries_EditMessage_Execute(log_file) abort
1685 if !filereadable(a:log_file)
1686 call s:error("abort: Commit message not saved")
1687 return
1688 endif
1689
1690 " Clean all the 'HG:' lines.
1691 let l:is_valid = s:clean_commit_file(a:log_file)
1692 if !l:is_valid
1693 call s:error("abort: Empty commit message")
1694 return
1695 endif
1696
1697 " Get the repo and edit the given patch.
1698 let l:repo = s:hg_repo()
1699 let l:hg_args = ['-s', '-l', a:log_file]
1700 call l:repo.RunCommand('qref', l:hg_args)
1701 endfunction
1702
1703
1704 call s:AddMainCommand("Hgqseries call s:HgQSeries()")
1705
1706 " }}}
1707
1564 " Autoload Functions {{{ 1708 " Autoload Functions {{{
1565 1709
1566 " Prints a summary of the current repo (if any) that's appropriate for 1710 " Prints a summary of the current repo (if any) that's appropriate for
1567 " displaying on the status line. 1711 " displaying on the status line.
1568 function! lawrencium#statusline(...) 1712 function! lawrencium#statusline(...)