changeset 31:3a0f7bb6ea64

Hgstatus window improvements and bug fixes: - `addremove` command replaces `add`, and can run on a selection range. - Lawrencium commands are available (along with in the diff windows). - Default mappings are optional. - Updated documentation.
author Ludovic Chabant <ludovic@chabant.com>
date Sun, 25 Dec 2011 22:40:30 -0800
parents 1ce59d5aa5e9
children 799c7b57e19a
files doc/lawrencium.txt plugin/lawrencium.vim
diffstat 2 files changed, 126 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/doc/lawrencium.txt	Tue Dec 20 16:16:52 2011 -0800
+++ b/doc/lawrencium.txt	Sun Dec 25 22:40:30 2011 -0800
@@ -9,6 +9,7 @@
 
 1.  Introduction            |lawrencium-intro|
 2.  Commands                |lawrencium-commands|
+3.  Status Window           |lawrencium-status-window|
 
 
 =============================================================================
@@ -55,13 +56,9 @@
 
                                                 *:Hgstatus*
 :Hgstatus               Shows the output of 'hg status' in the
-                        |preview-window|.
-                        You can navigate to the next/previous file with <C-N> 
-                        and <C-P>, open a file with <cr>, diff the local file
-                        with the parent revision with <C-D> and <C-V>,
-                        depending on whether you want a horizontal or vertical
-                        split window, add an untracked file with <C-A>, and
-                        refresh the window with <C-R>.
+                        |preview-window|. Some extra-commands, along with some
+                        default mappins, are available in this window. See
+                        |lawrencium-status-window|.
 
                                                 *:Hgdiff*
 :Hgdiff                 Diffs the current file against its parent revision.
@@ -87,5 +84,48 @@
 
 
 
+=============================================================================
+3.  Status Window                               *lawrencium-status-window*
+
+The `hg status` window opened by Lawrencium has a few special commands 
+defined in it. Also, unless the global `lawrencium_define_mappings` is set to
+`0`, some commands are mapped to keyboard shortcuts, as detailed in the
+following descriptions.
+
+
+                                                *:Hgstatusedit*
+:Hgstatusedit           Open the file mentioned on the current line.
+                        Mapped to <cr>.
+
+                                                *:Hgstatusaddremove*
+:Hgstatusaddremove      Run `hg addremove` on the file mentioned on the
+                        current line, or on the lines currently selected in
+                        visual selection mode (see |visual-start|).
+                        Mapped to <C-A>.
+
+                                                *:Hgstatusdiff*
+:Hgstatusdiff           Open a diff window on the file mentioned on the
+                        current line, between the working directory version
+                        and the parent revision version. Similar to running
+                        |:Hgdiff| on that file.
+                        Mapped to <C-D>.
+
+                                                *:Hgstatusvdiff*
+:Hgstatusvdiff          Similar to |:Hgstatusdiff|, but use a vertical split.
+                        Similar to running |:Hgvdiff| on that file.
+                        Mapped to <C-V>.
+
+                                                *:Hgstatusrefresh*
+:Hgstatusrefresh        Refreshes the status window by running `hg status`
+                        again.
+                        Mapped to <C-R>.
+
+                                                *lawrencium-status-mappings*
+A few other mappings are available in the status window:
+
+   <C-N>                Jump to the next filename.
+   <C-P>                Jump to the previous filename.
+   q                    Quit the status window.
+
 
  vim:tw=78:et:ft=help:norl:
--- a/plugin/lawrencium.vim	Tue Dec 20 16:16:52 2011 -0800
+++ b/plugin/lawrencium.vim	Sun Dec 25 22:40:30 2011 -0800
@@ -24,6 +24,10 @@
     let g:lawrencium_trace = 0
 endif
 
+if !exists('g:lawrencium_define_mappings')
+    let g:lawrencium_define_mappings = 1
+endif
+
 " }}}
 
 " Utility {{{
@@ -138,8 +142,14 @@
 
 " Runs a Mercurial command in the repo
 function! s:HgRepo.RunCommand(command, ...) abort
+    " If there's only one argument, and it's a list, then use that as the
+    " argument list.
+    let l:arg_list = a:000
+    if a:0 == 1 && type(a:1) == type([])
+        let l:arg_list = a:1
+    endif
     let l:hg_command = g:lawrencium_hg_executable . ' --repository ' . shellescape(s:stripslash(self.root_dir))
-    let l:hg_command = l:hg_command . ' ' . a:command . ' ' . join(a:000, ' ')
+    let l:hg_command = l:hg_command . ' ' . a:command . ' ' . join(l:arg_list, ' ')
     call s:trace("Running Mercurial command: " . l:hg_command)
     return system(l:hg_command)
 endfunction
@@ -337,6 +347,7 @@
     execute "pedit " . l:temp_file
     wincmd p
     call append(0, l:status_lines)
+    call cursor(1, 1)
     " Make it a nice size. 
     execute "setlocal previewheight=" . l:preview_height
     " Make sure it's deleted when we exit the window.
@@ -345,21 +356,33 @@
     " Setup the buffer correctly: readonly, and with the correct repo linked
     " to it.
     let b:mercurial_dir = l:repo.root_dir
-    setlocal buftype=nofile
     setlocal nomodified
     setlocal nomodifiable
     setlocal readonly
+    setlocal buftype=nofile
     setlocal syntax=hgstatus
-    
+
+    " Make commands available.
+    call s:DefineMainCommands()
+
+    " Add some nice commands.
+    command! -buffer        Hgstatusedit      :call s:HgStatus_FileEdit()
+    command! -buffer -range Hgstatusaddremove :call s:HgStatus_AddRemove(<line1>, <line2>)
+    command! -buffer        Hgstatusdiff      :call s:HgStatus_Diff(0)
+    command! -buffer        Hgstatusvdiff     :call s:HgStatus_Diff(1)
+    command! -buffer        Hgstatusrefresh   :call s:HgStatus_Refresh()
+
     " Add some handy mappings.
-    nnoremap <buffer> <silent> <C-N> :call search('^[MARC\!\?I ]\s.', 'We')<cr>
-    nnoremap <buffer> <silent> <C-P> :call search('^[MARC\!\?I ]\s.','Wbe')<cr>
-    nnoremap <buffer> <silent> <cr>  :call <SID>HgStatus_FileEdit()<cr>
-    nnoremap <buffer> <silent> <C-D> :call <SID>HgStatus_FileDiff(0)<cr>
-    nnoremap <buffer> <silent> <C-V> :call <SID>HgStatus_FileDiff(1)<cr>
-    nnoremap <buffer> <silent> <C-A> :call <SID>HgStatus_FileAdd()<cr>
-    nnoremap <buffer> <silent> <C-R> :call <SID>HgStatus_Refresh()<cr>
-    nnoremap <buffer> <silent> q     :bdelete<cr>
+    if g:lawrencium_define_mappings
+        nnoremap <buffer> <silent> <cr>  :Hgstatusedit<cr>
+        nnoremap <buffer> <silent> <C-N> :call search('^[MARC\!\?I ]\s.', 'We')<cr>
+        nnoremap <buffer> <silent> <C-P> :call search('^[MARC\!\?I ]\s.', 'Wbe')<cr>
+        nnoremap <buffer> <silent> <C-D> :Hgstatusdiff<cr>
+        nnoremap <buffer> <silent> <C-V> :Hgstatusvdiff<cr>
+        nnoremap <buffer> <silent> <C-A> :Hgstatusaddremove<cr>
+        nnoremap <buffer> <silent> <C-R> :Hgstatusrefresh<cr>
+        nnoremap <buffer> <silent> q     :bdelete!<cr>
+    endif
 
     " Make sure the file is deleted with the buffer.
     autocmd BufDelete <buffer> call s:HgStatus_CleanUp(expand('<afile>:p'))
@@ -389,7 +412,7 @@
 
 function! s:HgStatus_FileEdit() abort
     " Get the path of the file the cursor is on.
-    let l:filename = s:HgStatus_GetSelectedPath()
+    let l:filename = s:HgStatus_GetSelectedFile()
    
     " If the file is already open in a window, jump to that window.
     " Otherwise, jump to the previous window and open it there.
@@ -405,40 +428,59 @@
     execute 'edit ' . l:filename
 endfunction
 
-function! s:HgStatus_FileAdd() abort
-    " Get the path of the file the cursor is on, and its status.
-    let l:filename = s:HgStatus_GetSelectedPath()
-    let l:status = s:HgStatus_GetSelectedStatus()
-    if l:status !=# '?'
-        call s:error("Not an untracked file: " . l:filename)
+function! s:HgStatus_AddRemove(linestart, lineend) abort
+    " Get the selected filenames.
+    let l:filenames = s:HgStatus_GetSelectedFiles(a:linestart, a:lineend, ['!', '?'])
+    if len(l:filenames) == 0
+        call s:error("No files to add or remove in selection or current line.")
     endif
 
-    " Add the file.
+    " Run `addremove` on those paths.
     let l:repo = s:hg_repo()
-    call l:repo.RunCommand('add', l:filename)
+    call l:repo.RunCommand('addremove', l:filenames)
 
     " Refresh the status window.
     call s:HgStatus_Refresh()
 endfunction
 
-function! s:HgStatus_FileDiff(vertical) abort
+function! s:HgStatus_Diff(vertical) abort
     " Open the file and run `Hgdiff` on it.
     call s:HgStatus_FileEdit()
     call s:HgDiff('%:p', a:vertical)
 endfunction
 
-function! s:HgStatus_GetSelectedPath() abort
-    let l:repo = s:hg_repo()
-    let l:line = getline('.')
-    " Yay, awesome, Vim's regex syntax is fucked up like shit, especially for
-    " look-aheads and look-behinds. See for yourself:
-    let l:filename = matchstr(l:line, '\v(^[MARC\!\?I ]\s)@<=.*')
-    let l:filename = l:repo.GetFullPath(l:filename)
-    return l:filename
+function! s:HgStatus_GetSelectedFile() abort
+    let l:filenames = s:HgStatus_GetSelectedFiles()
+    return l:filenames[0]
 endfunction
 
-function! s:HgStatus_GetSelectedStatus() abort
-    let l:line = getline('.')
+function! s:HgStatus_GetSelectedFiles(...) abort
+    if a:0 >= 2
+        let l:lines = getline(a:1, a:2)
+    else
+        let l:lines = []
+        call add(l:lines, getline('.'))
+    endif
+    let l:filenames = []
+    let l:repo = s:hg_repo()
+    for line in l:lines
+        if a:0 >= 3
+            let l:status = s:HgStatus_GetFileStatus(line)
+            if index(a:3, l:status) < 0
+                continue
+            endif
+        endif
+        " Yay, awesome, Vim's regex syntax is fucked up like shit, especially for
+        " look-aheads and look-behinds. See for yourself:
+        let l:filename = matchstr(l:line, '\v(^[MARC\!\?I ]\s)@<=.*')
+        let l:filename = l:repo.GetFullPath(l:filename)
+        call add(l:filenames, l:filename)
+    endfor
+    return l:filenames
+endfunction
+
+function! s:HgStatus_GetFileStatus(...) abort
+    let l:line = a:0 ? a:1 : getline('.')
     return matchstr(l:line, '\v^[MARC\!\?I ]')
 endfunction
 
@@ -512,6 +554,8 @@
         let b:mercurial_dir = l:repo.root_dir
         " Make sure it's deleted when we move away from it.
         setlocal bufhidden=delete
+        " Make commands available.
+        call s:DefineMainCommands()
     endif
 
     " Get the second file and open it too.
@@ -529,6 +573,8 @@
         let b:mercurial_dir = l:repo.root_dir
         " Make sure it's deleted when we move away from it.
         setlocal bufhidden=delete
+        " Make commands available.
+        call s:DefineMainCommands()
     endif
 endfunction
 
@@ -633,6 +679,8 @@
     else
         autocmd BufDelete <buffer> call s:HgCommit_Execute(expand('<afile>:p'), 1)
     endif
+    " Make commands available.
+    call s:DefineMainCommands()
 endfunction
 
 let s:hg_status_messages = {