Mercurial > vim-lawrencium
changeset 48:85e39bdd7089
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.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Thu, 08 Nov 2012 13:58:29 -0800 |
parents | 6a4f5200d8da (diff) edc43c59b3b8 (current diff) |
children | dffb41c2067c |
files | doc/lawrencium.txt plugin/lawrencium.vim |
diffstat | 4 files changed, 266 insertions(+), 36 deletions(-) [+] |
line wrap: on
line diff
--- a/doc/lawrencium.txt Sun Nov 04 16:13:23 2012 +0100 +++ b/doc/lawrencium.txt Thu Nov 08 13:58:29 2012 -0800 @@ -1,6 +1,23 @@ *lawrencium.txt* Mercurial wrapper for VIM + LLLLLLLLLLL ~ + L:::::::::L ~ + L:::::::::L ~ + LL:::::::LL ~ + L:::::L rrrrr rrrrrrrrr ~ + L:::::L r::::rrr:::::::::r ~ + L:::::L r:::::::::::::::::r ~ + L:::::L rr::::::rrrrr::::::r ~ + L:::::L r:::::r r:::::r ~ + L:::::L r:::::r rrrrrrr ~ + L:::::L r:::::r ~ + L:::::L LLLLLLr:::::r ~ + LL:::::::LLLLLLLLL:::::Lr:::::r ~ + L::::::::::::::::::::::Lr:::::r ~ + L::::::::::::::::::::::Lr:::::r ~ + LLLLLLLLLLLLLLLLLLLLLLLLrrrrrrr ~ + LAWRENCIUM REFERENCE MANUAL by Ludovic Chabant @@ -10,6 +27,8 @@ 1. Introduction |lawrencium-intro| 2. Commands |lawrencium-commands| 3. Status Window |lawrencium-status-window| +4. Log Window |lawrencium-log-window| +5. Global Settings |lawrencium-global-settings| ============================================================================= @@ -38,14 +57,18 @@ file belongs to, and it will auto-complete any standard command or option. - Also, unless the `lawrencium_auto_cd` global is set to + Also, unless the |lawrencium_auto_cd| global is set to `0`, it will temporarily set the current directory to be the root of the repository so that auto-completed filenames work out of the box. *:Hg!* :Hg! {args} Like |:Hg|, but the output of the command is placed in - a temp file and edited in the |preview-window|. + 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 + command that was run. See |lawrencium_hg_commands_file_types|. *:Hgcd* :Hgcd[!] {path} |:cd| relative to the root of the repository. @@ -60,9 +83,9 @@ :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* @@ -96,37 +119,48 @@ 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* 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 +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>. + 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 @@ -134,7 +168,7 @@ 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 @@ -144,7 +178,7 @@ *:Hgstatusrefresh* :Hgstatusrefresh Refreshes the status window by running `hg status` again. - Mapped to <C-R>. + Mapped to <CTRL-R>. *:Hgstatusqnew* :Hgstatusqnew {patch} {message}. @@ -167,4 +201,64 @@ q Quit the status window. + +============================================================================= +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. + + *lawrencium_hg_executable* +g:lawrencium_hg_executable + Defines the executable to run when running Mercurial + commands. + Defaults to simply `hg`. + + *lawrencium_auto_cd* +g:lawrencium_auto_cd Specifies whether the current working directory should + be set to the repository's root while running |:Hg| + commands so that auto-completion works magically with + repository relative paths. + Defaults to `1`. + + *lawrencium_define_mappings* +g:lawrencium_define_mappings + Specifies whether Lawrencium should define default + keyboard shortcuts. + Defaults to `1`. + + *lawrencium_hg_commands_file_types* +g:lawrencium_hg_commands_file_types + Defines the |file-types| that Lawrencium should use + when editing the output of |:Hg!| based on the + Mercurial command that was used. + + By default, unless overridden, the following commands + map to the following file types: + + diff diff + graphlog graphlog + + vim:tw=78:et:ft=help:norl:
--- a/plugin/lawrencium.vim Sun Nov 04 16:13:23 2012 +0100 +++ b/plugin/lawrencium.vim Thu Nov 08 13:58:29 2012 -0800 @@ -44,14 +44,23 @@ " 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() @@ -107,8 +116,8 @@ " 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 @@ -313,9 +322,23 @@ if a:bang " Open the output of the command in a temp file. let l:temp_file = s:tempname('hg-output-', '.txt') - execute 'pedit ' . l:temp_file - wincmd P + split + execute 'edit ' . l:temp_file call append(0, split(l:output, '\n')) + call cursor(1, 1) + + " Make it a temp buffer + setlocal bufhidden=delete + setlocal buftype=nofile + + " Try to find a nice syntax to set given the current command. + let l:command_name = s:GetHgCommandName(a:000) + if l:command_name != '' && exists('g:lawrencium_hg_commands_file_types') + let l:file_type = get(g:lawrencium_hg_commands_file_types, l:command_name, '') + if l:file_type != '' + execute 'setlocal ft=' . l:file_type + endif + endif else " Just print out the output of the command. echo l:output @@ -330,6 +353,12 @@ call s:error("Can't find the Mercurial usage file. Auto-completion will be disabled in Lawrencium.") endif +" Include the command file type mappings. +let s:file_type_mappings = expand("<sfile>:h:h") . '/resources/hg_command_file_types.vim' +if filereadable(s:file_type_mappings) + execute "source " . s:file_type_mappings +endif + function! s:CompleteHg(ArgLead, CmdLine, CursorPos) " Don't do anything if the usage file was not sourced. if !exists('g:lawrencium_hg_commands') || !exists('g:lawrencium_hg_options') @@ -351,15 +380,11 @@ " Try completing a command (note that there could be global options before " the command name). if a:CmdLine =~# '\v^Hg\s+(\-[a-zA-Z0-9\-_]+\s+)*[a-zA-Z]+$' - echom " - matched command" return filter(keys(g:lawrencium_hg_commands), "v:val[0:strlen(l:arglead)-1] ==# l:arglead") endif " Try completing a command's options. let l:cmd = matchstr(a:CmdLine, '\v(^Hg\s+(\-[a-zA-Z0-9\-_]+\s+)*)@<=[a-zA-Z]+') - if strlen(l:cmd) > 0 - echom " - matched command option for " . l:cmd . " with : " . l:arglead - endif if strlen(l:cmd) > 0 && l:arglead[0] ==# '-' if has_key(g:lawrencium_hg_commands, l:cmd) " Return both command options and global options together. @@ -376,6 +401,15 @@ return s:ListRepoFiles(a:ArgLead, a:CmdLine, a:CursorPos) endfunction +function! s:GetHgCommandName(args) abort + for l:a in a:args + if stridx(l:a, '-') != 0 + return l:a + endif + endfor + return '' +endfunction + call s:AddMainCommand("-bang -complete=customlist,s:CompleteHg -nargs=* Hg :call s:Hg(<bang>0, <f-args>)") " }}} @@ -390,18 +424,17 @@ 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 @@ -451,7 +484,6 @@ let l:status_text = l:repo.RunCommand('status') " Replace the contents of the current buffer with it, and refresh. - echo "Writing to " . expand('%:p') let l:path = expand('%:p') let l:status_lines = split(l:status_text, '\n') call writefile(l:status_lines, l:path) @@ -889,16 +921,17 @@ 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, '%#\') + 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. @@ -918,8 +951,51 @@ 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(...) @@ -931,7 +1007,11 @@ 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 @@ -961,12 +1041,16 @@ 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 " }}}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/resources/hg_command_file_types.vim Thu Nov 08 13:58:29 2012 -0800 @@ -0,0 +1,9 @@ +" LAWRENCIUM - MERCURIAL COMMANDS FILE TYPES +" +if !exists('g:lawrencium_hg_commands_file_types') + g:lawrencium_hg_commands_file_types = {} +endif + +let g:lawrencium_hg_commands_file_types.diff = 'diff' +let g:lawrencium_hg_commands_file_types.glog = 'hggraphlog' +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/syntax/hggraphlog.vim Thu Nov 08 13:58:29 2012 -0800 @@ -0,0 +1,43 @@ +" Vim syntax file +" Language: hg graphlog output +" Maintainer: Ludovic Chabant <ludovic@chabant.com> +" Filenames: <none> + +if exists("b:current_syntax") + finish +endif + +syn case match + +syn match hggraphlogBranch /^|\(\( .*\)\|$\)/he=s+1 +syn match hggraphlogBranchMerge /^|[\\\/]/ +syn match hggraphlogNode /^o .*/he=s+1 + +syn match hggraphlogBranch2 / |\(\( .*\)\|$\)/he=s+2 contained containedin=hggraphlogBranch,hggraphlogNode +syn match hggraphlogBranch2Merge / |[\\\/]/ contained containedin=hggraphlogBranch +syn match hggraphlogNode2 / o .*/he=s+2 contained containedin=hggraphlogBranch + +syn match hggraphlogBranch3 / | |\(\( .*\)\|$\)/ms=s+3,he=s+4 contained containedin=hggraphlogBranch2,hggraphlogNode2 +syn match hggraphlogBranch3Merge / | |[\\\/]/ms=s+3 contained containedin=hggraphlogBranch2 +syn match hggraphlogNode3 / | o .*/ms=s+3,he=s+4 contained containedin=hggraphlogBranch2 + +syn match hggraphlogBranch4 / | | |\(\( .*\)\|$\)/ms=s+5,he=s+6 contained containedin=hggraphlogBranch3,hggraphlogNode3 +syn match hggraphlogBranch4Merge / | | |[\\\/]/ms=s+5 contained containedin=hggraphlogBranch3 +syn match hggraphlogNode4 / | | o .*/ms=s+5,he=s+6 contained containedin=hggraphlogBranch3 + +syn match hggraphlogHead /^@\s/he=e-1 + +hi def link hggraphlogBranch hlLevel1 +hi def link hggraphlogBranchMerge hlLevel1 +hi def link hggraphlogNode hlLevel1 +hi def link hggraphlogBranch2 hlLevel2 +hi def link hggraphlogBranch2Merge hlLevel2 +hi def link hggraphlogNode2 hlLevel2 +hi def link hggraphlogBranch3 hlLevel3 +hi def link hggraphlogBranch3Merge hlLevel3 +hi def link hggraphlogNode3 hlLevel3 +hi def link hggraphlogBranch4 hlLevel4 +hi def link hggraphlogBranch4Merge hlLevel4 +hi def link hggraphlogNode4 hlLevel4 +hi def link hggraphlogHead PreProc +