Commits

Ludovic Chabant committed 85e39bd Merge

Lots of changes that should have gone in other commits (ugh):
- merged changes from @soliman
- removed the bang edit command setting. The preview windows is not really
well suited for some things, so it's been replaced with a normal split
window for `Hg!` and `Hgstatus`.
- officialized `Hglog`.
- fixed some problems on Windows.

Comments (0)

Files changed (2)

doc/lawrencium.txt

 1.  Introduction            |lawrencium-intro|
 2.  Commands                |lawrencium-commands|
 3.  Status Window           |lawrencium-status-window|
-4.  Global Settings         |lawrencium-global-settings|
+4.  Log Window              |lawrencium-log-window|
+5.  Global Settings         |lawrencium-global-settings|
 
 
 =============================================================================
 
                                                 *:Hg!*
 :Hg! {args}             Like |:Hg|, but the output of the command is placed in
-                        a temp file and edited in the |preview-window|, unless
-                        the |lawrencium_hg_bang_edit_command| global setting
-                        specifies that another type of window or buffer should
-                        be used.
+                        a temp file and edited in a split window.
 
                         Once the output is open in a buffer, Lawrencium will
                         try to set the file type according to the Mercurial
 :Hgedit! {file}         |:edit!| {file} relative to the root of the repository.
 
                                                 *:Hgstatus*
-:Hgstatus               Shows the output of 'hg status' in the
-                        |preview-window|. Some extra-commands, along with some
-                        default mappins, are available in this window. See
+:Hgstatus               Shows the output of 'hg status' in a split window.
+                        Some extra-commands, along with some default mappings,
+                        are available in this window. See
                         |lawrencium-status-window|.
 
                                                 *:Hgdiff*
                         given to prevent a .orig backup file from being
                         created.
 
+                                                *:Hglog*
+:Hglog
+                        Opens the history (log) for the currently edited file
+                        in a split window. Some extra-commands, along with 
+                        some default mappings, are available in this window.
+                        See |lawrencium-log-window|.
+
+                                                *:Hglog_f*
+:Hglog {file}           Same as |:Hglog|, but opens the log for the specified
+                        file instead of the currently edited file.
+
 
 =============================================================================
 3.  Status Window                               *lawrencium-status-window*
 
                                                 *:Hgstatusedit*
 :Hgstatusedit           Open the file mentioned on the current line.
-                        Mapped to <cr>.
+                        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>.
+                        Mapped to <CTRL-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>.
+                        Mapped to <CTRL-D>.
 
                                                 *:Hgstatusvdiff*
 :Hgstatusvdiff          Similar to |:Hgstatusdiff|, but use a vertical split.
                         Similar to running |:Hgvdiff| on that file.
-                        Mapped to <C-V>.
+                        Mapped to <CTRL-V>.
 
                                                 *:Hgstatuscommit*
 :Hgstatuscommit         Runs |:Hgcommit| on the files currently mentioned in
                         option means you can delete lines from the buffer
                         until the remaining filenames are those you want to
                         commit.
-                        Mapped to <C-S>.
+                        Mapped to <CTRL-S>.
 
                                                 *:Hgstatusvcommit*
 :Hgstatusvcommit        Similar to |:Hgstatuscommit|, but use a vertical
                                                 *:Hgstatusrefresh*
 :Hgstatusrefresh        Refreshes the status window by running `hg status`
                         again.
-                        Mapped to <C-R>.
+                        Mapped to <CTRL-R>.
 
                                                 *:Hgstatusqnew*
 :Hgstatusqnew {patch} {message}.
 
 
 =============================================================================
-4.  Global Settings                             *lawrencium-global-settings*
+4.  Log Window                                  *lawrencium-log-window*
+                        
+The `hg log` 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.
+
+                                                *:Hglogrevedit*
+:Hglogrevedit           Looks at the revision specified on the current line,
+                        and opens that revision for edit in the previous
+                        window (although as a read-only buffer).
+                        Mapped to |<CR>|
+
+                                                *lawrencium-log-mappings*
+A few other mappings are available in the log window:
+
+    q                   Quit the log window.
+
+
+
+=============================================================================
+5.  Global Settings                             *lawrencium-global-settings*
 
 The following global settings can be defined in your |vimrc| to change the
 default behaviour of Lawrencium.
                         keyboard shortcuts.
                         Defaults to `1`.
 
-                                                *lawrencium_hg_bang_edit_command*
-g:lawrencium_hg_bang_edit_command
-                        Defines the Vim command to run when using the |:Hg!|
-                        command (with the bang) in order to show the output.
-                        
-                        Defaults to |pedit|, which opens the output of the
-                        command in the |preview-window|. A good alternative
-                        is to use |edit|, to open the output in a normal
-                        buffer.
-
                                                 *lawrencium_hg_commands_file_types*
 g:lawrencium_hg_commands_file_types
                         Defines the |file-types| that Lawrencium should use

plugin/lawrencium.vim

     let g:lawrencium_define_mappings = 1
 endif
 
-if !exists('g:lawrencium_hg_bang_edit_command')
-    let g:lawrencium_hg_bang_edit_command = 'pedit'
-endif
-
 " }}}
 
 " Utility {{{
 " Normalizes the slashes in a path.
 function! s:normalizepath(path)
     if exists('+shellslash') && &shellslash
-        return substitute(a:path, '\\', '/', '')
+        return substitute(a:path, '\v/', '\\', 'g')
     elseif has('win32')
-        return substitute(a:path, '/', '\\', '')
+        return substitute(a:path, '\v/', '\\', 'g')
     else
         return a:path
     endif
 endfunction
 
+" Shell-slashes the path (opposite of `normalizepath`).
+function! s:shellslash(path)
+  if exists('+shellslash') && !&shellslash
+    return substitute(a:path, '\v\\', '/', 'g')
+  else
+    return a:path
+  endif
+endfunction
+
 " Like tempname() but with some control over the filename.
 function! s:tempname(name, ...)
     let l:path = tempname()
 " Given a Lawrencium path (e.g: 'lawrencium:///repo/root_dir@foo/bar/file.py//34'), extract
 " the repository root, relative file path and revision number/changeset ID.
 function! s:parse_lawrencium_path(lawrencium_path)
-    let l:repo_path = a:lawrencium_path
-    if l:repo_path =~? '^lawrencium://'
+    let l:repo_path = s:shellslash(a:lawrencium_path)
+    if l:repo_path =~? '\v^lawrencium://'
         let l:repo_path = strpart(l:repo_path, strlen('lawrencium://'))
     endif
 
     if a:bang
         " Open the output of the command in a temp file.
         let l:temp_file = s:tempname('hg-output-', '.txt')
-        execute g:lawrencium_hg_bang_edit_command . ' ' . l:temp_file
-        wincmd p
+        split
+        execute 'edit ' . l:temp_file
         call append(0, split(l:output, '\n'))
         call cursor(1, 1)
 
         echo "Nothing modified."
     endif
 
-    " Open a new temp buffer in the preview window, jump to it,
+    " Open a new temp buffer in a new window, jump to it,
     " and paste the `hg status` output in there.
     let l:temp_file = s:tempname('hg-status-', '.txt')
-    let l:preview_height = &previewheight
     let l:status_lines = split(l:status_text, '\n')
-    execute "setlocal previewheight=" . (len(l:status_lines) + 1)
-    execute "pedit " . l:temp_file
-    wincmd p
+    split
+    execute "setlocal winfixheight"
+    execute "setlocal winheight=" . (len(l:status_lines) + 1)
+    execute "resize " . (len(l:status_lines) + 1)
+    execute "edit " . l:temp_file
     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.
     setlocal bufhidden=delete
     
         let l:filepath = a:1
     endif
 
-    " Get the repo and get the command.
+    " Get the repo and run the command.
     let l:repo = s:hg_repo()
-    let l:log_command = l:repo.GetCommand('log', l:filepath, '--template', '"{rev}\t{desc|firstline}\n"')
+    let l:output = l:repo.RunCommand('log', l:filepath, '--template', '"{rev}\t{desc|firstline}\n"')
 
     " Open a new temp buffer in the preview window, jump to it,
     " and paste the `hg log` output in there.
     let l:temp_file = s:tempname('hg-log-', '.txt')
     execute "pedit " . l:temp_file
-    wincmd p
-    execute "read !" . escape(l:log_command, '%#\')
+    wincmd P
+    call append(0, split(l:output, '\n'))
+    call cursor(1, 1)
 
     " Setup the buffer correctly: readonly, and with the correct repo linked
     " to it, and deleted on close.
         nnoremap <buffer> <silent> q     :bdelete!<cr>
     endif
 
-    " Make sure the file is deleted with the buffer.
-    autocmd BufDelete <buffer> call s:clean_tempfile(expand('<afile>:p'))
+    " Clean up when the log buffer is deleted.
+    autocmd BufDelete <buffer> call s:HgLog_Delete(expand('<afile>:p'))
+endfunction
+
+function! s:HgLog_Delete(path)
+    let l:orignr = winnr()
+    let l:origpath = b:mercurial_logged_file
+    " Delete any other buffer opened by this log.
+    " (buffers with Lawrencium paths that match this repo and filename)
+    for nr in range(1, winnr('$'))
+        let l:br = winbufnr(nr)
+        let l:bpath = bufname(l:br)
+        let l:bpath_comps = s:parse_lawrencium_path(l:bpath)
+        if l:bpath_comps['root'] != ''
+            let l:bpath_root = s:normalizepath(l:bpath_comps['root'])
+            let l:bpath_path = s:normalizepath(l:bpath_comps['path'])
+            if l:bpath_root == b:mercurial_dir && l:bpath_path == b:mercurial_logged_file
+                " Go to that window and switch to the previous buffer
+                " from the buffer with the file revision.
+                " Just switching away should delete the buffer since it
+                " has `bufhidden=delete`.
+                echom "Found buffer in window: ".nr
+                execute nr . 'wincmd w'
+                let l:altbufname = s:shellslash(bufname('#'))
+                if l:altbufname =~# '\v^lawrencium://'
+                    " This is a special Lawrencium buffer... it could be
+                    " a previously shown revision of the file opened with
+                    " this very `Hglog`, which we don't want to switch to.
+                    " Let's just default to editing the original file
+                    " again... not sure what else to do here.
+                    execute 'edit ' . l:origpath
+                else
+                    bprevious
+                endif
+            endif
+        endif
+    endfor
+    " Restore the current window if we switched away.
+    let l:curnr = winnr()
+    if l:curnr != l:orignr
+        execute l:orignr . 'wincmd w'
+    endif
+    
+    " Delete the temp file if it was created somehow.
+    call s:clean_tempfile(a:path)
 endfunction
 
 function! s:HgLog_FileRevEdit(...)
         let l:rev = s:HgLog_GetSelectedRev()
     endif
     let l:path = 'lawrencium://' . b:mercurial_dir . '@' . b:mercurial_logged_file . '//' . l:rev
+    let l:path = fnameescape(l:path)
+    wincmd p
     execute 'edit ' . l:path
+    setlocal bufhidden=delete
+    setlocal buftype=nofile
 endfunction
 
 function! s:HgLog_GetSelectedRev() abort
     else
         execute 'read !' . escape(l:repo.GetCommand('cat', '-r', l:comps['rev'], l:comps['path']), '%#\')
     endif
+    setlocal readonly
+    setlocal nomodifiable
+    setlocal nomodified
+    setlocal bufhidden=delete
     return ''
 endfunction
 
 augroup lawrencium_files
   autocmd!
-  autocmd BufReadCmd  lawrencium://**//[0-9a-f][0-9a-f]* exe s:ReadFileRevision(expand('<amatch>'))
+  autocmd BufReadCmd  lawrencium://**//[0-9a-f]* exe s:ReadFileRevision(expand('<amatch>'))
 augroup END
 
 " }}}