diff 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
line wrap: on
line diff
--- a/plugin/lawrencium.vim	Sat Nov 09 13:20:17 2013 -0800
+++ b/plugin/lawrencium.vim	Sun Feb 16 16:00:16 2014 -0800
@@ -243,6 +243,19 @@
     endif
 endfunction
 
+" Clean up all the 'HG:' lines from a commit message, and see if there's
+" any message left (Mercurial does this automatically, usually, but
+" apparently not when you feed it a log file...).
+function! s:clean_commit_file(log_file) abort
+    let l:lines = readfile(a:log_file)
+    call filter(l:lines, "v:val !~# '\\v^HG:'")
+    if len(filter(copy(l:lines), "v:val !~# '\\v^\\s*$'")) == 0
+        return 0
+    endif
+    call writefile(l:lines, a:log_file)
+    return 1
+endfunction
+
 " }}}
 
 " Mercurial Repository Object {{{
@@ -548,7 +561,10 @@
     else
         call a:repo.ReadCommandOutput('status', a:full_path)
     endif
+    setlocal nomodified
     setlocal filetype=hgstatus
+    setlocal bufhidden=delete
+    setlocal buftype=nofile
 endfunction
 
 " Log (`hg log`)
@@ -595,13 +611,38 @@
     call a:repo.ReadCommandOutput('annotate', '-c', '-n', '-u', '-d', '-q', a:full_path)
 endfunction
 
+" MQ series
+function! s:read_lawrencium_qseries(repo, path_parts, full_path) abort
+    let l:names = split(a:repo.RunCommand('qseries'), '\n')
+    let l:head = split(a:repo.RunCommand('qapplied', '-s'), '\n')
+    let l:tail = split(a:repo.RunCommand('qunapplied', '-s'), '\n')
+
+    let l:idx = 0
+    let l:curbuffer = bufname('%')
+    for line in l:head
+        call setbufvar(l:curbuffer, 'lawrencium_patchname_' . (l:idx + 1), l:names[l:idx])
+        call append(l:idx, "*" . line)
+        let l:idx = l:idx + 1
+    endfor
+    for line in l:tail
+        call setbufvar(l:curbuffer, 'lawrencium_patchname_' . (l:idx + 1), l:names[l:idx])
+        call append(l:idx, line)
+        let l:idx = l:idx + 1
+    endfor
+    set filetype=hgqseries
+endfunction
+
 " Generic read
 let s:lawrencium_file_readers = {
             \'rev': function('s:read_lawrencium_rev'),
             \'log': function('s:read_lawrencium_log'),
             \'diff': function('s:read_lawrencium_diff'),
             \'status': function('s:read_lawrencium_status'),
-            \'annotate': function('s:read_lawrencium_annotate')
+            \'annotate': function('s:read_lawrencium_annotate'),
+            \'qseries': function('s:read_lawrencium_qseries')
+            \}
+let s:lawrencium_file_customoptions = {
+            \'status': 1
             \}
 
 function! s:ReadLawrenciumFile(path) abort
@@ -621,10 +662,12 @@
     call LawrenciumFileReader(l:repo, l:path_parts, l:full_path)
 
     " Setup the new buffer.
-    setlocal readonly
-    setlocal nomodified
-    setlocal bufhidden=delete
-    setlocal buftype=nofile
+    if !has_key(s:lawrencium_file_customoptions, l:path_parts['action'])
+        setlocal readonly
+        setlocal nomodified
+        setlocal bufhidden=delete
+        setlocal buftype=nofile
+    endif
     goto
 
     " Remember the repo it belongs to and make
@@ -1290,16 +1333,12 @@
 
     call s:trace("Committing with log file: " . a:log_file)
 
-    " Clean up all the 'HG:' lines from the commit message, and see if there's
-    " any message left (Mercurial does this automatically, usually, but
-    " apparently not when you feed it a log file...).
-    let l:lines = readfile(a:log_file)
-    call filter(l:lines, "v:val !~# '\\v^HG:'")
-    if len(filter(copy(l:lines), "v:val !~# '\\v^\\s*$'")) == 0
+    " Clean all the 'HG: ' lines.
+    let l:is_valid = s:clean_commit_file(a:log_file)
+    if !l:is_valid
         call s:error("abort: Empty commit message")
         return
     endif
-    call writefile(l:lines, a:log_file)
 
     " Get the repo and commit with the given message.
     let l:repo = s:hg_repo()
@@ -1561,6 +1600,111 @@
 
 " }}}
 
+" Hgqseries {{{
+
+function! s:HgQSeries() abort
+    " Open the MQ series in the preview window and jump to it.
+    let l:repo = s:hg_repo()
+    let l:path = l:repo.GetLawrenciumPath('', 'qseries', '')
+    execute 'pedit ' . l:path
+    wincmd P
+
+    " Make the series buffer a Lawrencium buffer.
+    let b:mercurial_dir = l:repo.root_dir
+    call s:DefineMainCommands()
+
+    " Add some commands and mappings.
+    command! -buffer Hgqseriesgoto                  :call s:HgQSeries_Goto()
+    command! -buffer Hgqserieseditmessage           :call s:HgQSeries_EditMessage()
+    command! -buffer -nargs=+ Hgqseriesrename       :call s:HgQSeries_Rename(<f-args>)
+    if g:lawrencium_define_mappings
+        nnoremap <buffer> <silent> <C-g> :Hgqseriesgoto<cr>
+        nnoremap <buffer> <silent> <C-e> :Hgqserieseditmessage<cr>
+        nnoremap <buffer> <silent> q     :bdelete!<cr>
+    endif
+endfunction
+
+function! s:HgQSeries_GetCurrentPatchName() abort
+    let l:pos = getpos('.')
+    return getbufvar('%', 'lawrencium_patchname_' . l:pos[1])
+endfunction
+
+function! s:HgQSeries_Goto() abort
+    let l:repo = s:hg_repo()
+    let l:patchname = HgQSeries_GetCurrentPatchName()
+    if len(l:patchname) == 0
+        call s:error("No patch to go to here.")
+        return
+    endif
+    call l:repo.RunCommand('qgoto', l:patchname)
+    edit
+endfunction
+
+function! s:HgQSeries_Rename(...) abort
+    let l:repo = s:hg_repo()
+    let l:current_name = HgQSeries_GetCurrentPatchName()
+    if len(l:current_name) == 0
+        call s:error("No patch to rename here.")
+        return
+    endif
+    let l:new_name = '"' . join(a:000, ' ') . '"'
+    call l:repo.RunCommand('qrename', l:current_name, l:new_name)
+    edit
+endfunction
+
+function! s:HgQSeries_EditMessage() abort
+    let l:repo = s:hg_repo()
+    let l:patchname = getbufvar('%', 'lawrencium_patchname_1')
+    if len(l:patchname) == 0
+        call s:error("No patch to edit here.")
+        return
+    endif
+    let l:current = split(l:repo.RunCommand('qheader', l:patchname), '\n')
+
+    " Open a temp file to write the commit message.
+    let l:temp_file = s:tempname('hg-qrefedit-', '.txt')
+    split
+    execute 'edit ' . l:temp_file
+    call append(0, 'HG: Enter the new commit message for patch "' . l:patchname . '" here.\n')
+    call append(0, '')
+    call append(0, l:current)
+    call cursor(1, 1)
+
+    " Make it a temp buffer that will actually change the commit message
+    " when it is saved and closed.
+    let b:mercurial_dir = l:repo.root_dir
+    let b:lawrencium_patchname = l:patchname
+    setlocal bufhidden=delete
+    setlocal filetype=hgcommit
+    autocmd BufDelete <buffer> call s:HgQSeries_EditMessage_Execute(expand('<afile>:p'))
+
+    call s:DefineMainCommands()
+endfunction
+
+function! s:HgQSeries_EditMessage_Execute(log_file) abort
+    if !filereadable(a:log_file)
+        call s:error("abort: Commit message not saved")
+        return
+    endif
+
+    " Clean all the 'HG:' lines.
+    let l:is_valid = s:clean_commit_file(a:log_file)
+    if !l:is_valid
+        call s:error("abort: Empty commit message")
+        return
+    endif
+
+    " Get the repo and edit the given patch.
+    let l:repo = s:hg_repo()
+    let l:hg_args = ['-s', '-l', a:log_file]
+    call l:repo.RunCommand('qref', l:hg_args)
+endfunction
+
+
+call s:AddMainCommand("Hgqseries call s:HgQSeries()")
+
+" }}}
+
 " Autoload Functions {{{
 
 " Prints a summary of the current repo (if any) that's appropriate for