Mercurial > vim-lawrencium
changeset 0:0a5b490dc35d
Initial commit
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Thu, 08 Dec 2011 12:40:55 -0800 |
parents | |
children | 9241ae881b9f |
files | doc/lawrencium.txt plugin/lawrencium.vim |
diffstat | 2 files changed, 340 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/lawrencium.txt Thu Dec 08 12:40:55 2011 -0800 @@ -0,0 +1,45 @@ +*lawrencium.txt* Mercurial wrapper for VIM + +Author: Ludovic Chabant <http://ludovic.chabant.com> +License: Same terms as Vim itself (see |license|) + +This plugin is only available if 'compatible' is not set. + +INTRODUCTION *lawrencium* + +When a file from a Mercurial repository is open in a buffer, that buffer gets +new commands defined. + +COMMANDS *lawrencium-commands* + +All commands defined by |lawrencium| are local to each buffer. + + *lawrencium-:Hg* +:Hg [args] Run an arbitrary Mercurial command. Similar to :!hg + [args] but the '--repository' is automatically + specified with the root of the repository the current + file belongs to. + + *lawrencium-:Hg!* +:Hg! [args] Like |:Hg|, but the output of the command is placed in + a temp file and edited in the |preview-window|. + + *lawrencium-:Hgcd* +:Hgcd [directory] |:cd| relative to the root of the repository. + + *lawrencium-:Hglcd* +:Hglcd [directory] |:lcd| relative to the root of the repository. + + *lawrencium-:Hgstatus* +:Hgstatus Shows the output of 'hg status' in the + |preview-window|. + + +ABOUT *lawrencium-about* + +Grab the latest version or report a bug on BitBucket: + +http://bitbucket.org/ludovicchabant/lawrencium + + + vim:tw=78:et:ft=help:norl:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/lawrencium.vim Thu Dec 08 12:40:55 2011 -0800 @@ -0,0 +1,295 @@ +" lawrencium.vim - A Mercurial wrapper +" Maintainer: Ludovic Chabant <http://ludovic.chabant.com> +" Version: 0.1 + +" Globals {{{ + +if !exists('g:lawrencium_debug') + let g:lawrencium_debug = 0 +endif + +if (exists('g:loaded_lawrencium') || &cp) && !g:lawrencium_debug + finish +endif +let g:loaded_lawrencium = 1 + +if !exists('g:lawrencium_hg_executable') + let g:lawrencium_hg_executable = 'hg' +endif + +if !exists('g:lawrencium_trace') + let g:lawrencium_trace = 0 +endif + +if g:lawrencium_debug + echom "Loaded Lawrencium." +endif + +" }}} + +" Utility {{{ + +" Strips the ending slash in a path. +function! s:stripslash(path) + return fnamemodify(a:path, ':s?[/\\]$??') +endfunction + +" Normalizes the slashes in a path. +function! s:normalizepath(path) + if exists('+shellslash') && &shellslash + return substitute(a:path, '\\', '/', '') + elseif has('win32') + return substitute(a:path, '/', '\\', '') + else + return a:path + endif +endfunction + +" Prints a message if debug tracing is enabled. +function! s:trace(message) + if g:lawrencium_trace + let l:message = "lawrencium: " . a:message + echom l:message + endif +endfunction + +" Throw a Lawrencium exception message. +function! s:throw(message) + let v:errmsg = "lawrencium: " . a:message + throw v:errmsg +endfunction + +" Finds the repository root given a path inside that repository. +" Throw an error if not repository is found. +function! s:find_repo_root(path) + let l:path = s:stripslash(a:path) + let l:previous_path = "" + while l:path != l:previous_path + if isdirectory(l:path . '/.hg/store') + return simplify(fnamemodify(l:path, ':p')) + endif + let l:previous_path = l:path + let l:path = fnamemodify(l:path, ':h') + endwhile + call s:throw("No Mercurial repository found above: " . a:path) +endfunction + +" }}} + +" Mercurial Repository {{{ + +" Let's define a Mercurial repo 'class' using prototype-based object-oriented +" programming. +" +" The prototype dictionary. +let s:HgRepo = {} + +" Constructor +function! s:HgRepo.New(path) abort + let l:newRepo = copy(self) + let l:newRepo.root_dir = s:find_repo_root(a:path) + call s:trace("Built new Mercurial repository object at : " . l:newRepo.root_dir) + return l:newRepo +endfunction + +" Gets a full path given a repo-relative path +function! s:HgRepo.GetFullPath(path) abort + let l:root_dir = self.root_dir + if a:path =~# '^[/\\]' + let l:root_dir = s:stripslash(l:root_dir) + endif + return l:root_dir . a:path +endfunction + +" Gets a list of files matching a root-relative pattern. +" If a flag is passed and is TRUE, a slash will be appended to all +" directories. +function! s:HgRepo.Glob(pattern, ...) abort + let l:root_dir = self.root_dir + if (a:pattern =~# '^[/\\]') + let l:root_dir = s:stripslash(l:root_dir) + endif + let l:matches = split(glob(l:root_dir . a:pattern), '\n') + if a:0 && a:1 + for l:idx in range(len(l:matches)) + if !filereadable(l:matches[l:idx]) + let l:matches[l:idx] = l:matches[l:idx] . '/' + endif + endfor + endif + let l:strip_len = len(l:root_dir) + call map(l:matches, 'v:val[l:strip_len : -1]') + return l:matches +endfunction + +" Runs a Mercurial command in the repo +function! s:HgRepo.RunCommand(command, ...) abort + 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, ' ') + call s:trace("Running Mercurial command: " . l:hg_command) + return system(l:hg_command) +endfunction + +" Repo cache map +let s:buffer_repos = {} + +" Get a cached repo +function! s:hg_repo(...) abort + " Use the given path, or the mercurial directory of the current buffer. + if a:0 == 0 + if exists('b:mercurial_dir') + let l:path = b:mercurial_dir + else + let l:path = s:find_repo_root(expand('%:p')) + endif + else + let l:path = a:1 + endif + " Find a cache repo instance, or make a new one. + if has_key(s:buffer_repos, l:path) + return get(s:buffer_repos, l:path) + else + let l:repo = s:HgRepo.New(l:path) + let s:buffer_repos[l:path] = l:repo + return l:repo + endif +endfunction + +" Sets up the current buffer with Lawrencium commands if it contains a file from a Mercurial repo. +" If the file is not in a Mercurial repo, just exit silently. +function! s:setup_buffer_commands() abort + call s:trace("Scanning buffer '" . bufname('%') . "' for Lawrencium setup...") + let l:do_setup = 1 + if exists('b:mercurial_dir') + if b:mercurial_dir =~# '/^\s*$/' + unlet b:mercurial_dir + else + let l:do_setup = 0 + endif + endif + try + let l:repo = s:hg_repo() + catch /^lawrencium\:/ + return + endtry + let b:mercurial_dir = l:repo.root_dir + if exists('b:mercurial_dir') && l:do_setup + call s:trace("Setting Mercurial commands for buffer '" . bufname('%')) + call s:trace(" with repo : " . expand(b:mercurial_dir)) + silent doautocmd User Lawrencium + endif +endfunction + +augroup lawrencium_detect + autocmd! + autocmd BufNewFile,BufReadPost * call s:setup_buffer_commands() + autocmd VimEnter * if expand('<amatch>')==''|call s:setup_buffer_commands()|endif +augroup end + +" }}} + +" Commands {{{ + +let s:main_commands = [] + +function! s:AddMainCommand(command) abort + let s:main_commands += [a:command] +endfunction + +function! s:DefineMainCommands() + for l:command in s:main_commands + execute 'command! -buffer ' . l:command + endfor +endfunction + +augroup lawrencium_main + autocmd! + autocmd User Lawrencium call s:DefineMainCommands() +augroup end + +" }}} + +" HgExecute {{{ + +function! s:HgExecute(...) abort + let l:repo = s:hg_repo() + echo call(l:repo.RunCommand, a:000, l:repo) +endfunction + +call s:AddMainCommand("-nargs=* Hg :execute s:HgExecute(<f-args>)") + +" }}} + +" HgStatus {{{ + +function! s:HgStatus() abort + echo s:hg_repo().RunCommand('status') +endfunction + +call s:AddMainCommand("HgStatus :execute s:HgStatus()") + +" }}} + +" Hgcd, Hglcd {{{ + +function! s:ListRepoDirs(ArgLead, CmdLine, CursorPos) abort + let l:matches = s:hg_repo().Glob(a:ArgLead . '*/') + call map(l:matches, 's:normalizepath(v:val)') + return l:matches +endfunction + +call s:AddMainCommand("-bang -nargs=? -complete=customlist,s:ListRepoDirs Hgcd :cd<bang> `=s:hg_repo().GetFullPath(<q-args>)`") +call s:AddMainCommand("-bang -nargs=? -complete=customlist,s:ListRepoDirs Hglcd :lcd<bang> `=s:hg_repo().GetFullPath(<q-args>)`") + +" }}} + +" Hgedit {{{ + +function! s:ListRepoFiles(ArgLead, CmdLine, CursorPos) abort + let l:matches = s:hg_repo().Glob(a:ArgLead . '*', 1) + call map(l:matches, 's:normalizepath(v:val)') + return l:matches +endfunction + +call s:AddMainCommand("-bang -nargs=? -complete=customlist,s:ListRepoFiles Hgedit :edit<bang> `=s:hg_repo().GetFullPath(<q-args>)`") + +" }}} + +" Autoload Functions {{{ + +" Prints a summary of the current repo (if any) that's appropriate for +" displaying on the status line. +function! lawrencium#statusline(...) + if !exists('b:mercurial_dir') + return '' + endif + let l:summary = s:hg_repo().RunCommand('summary') + let l:parent_rev = matchstr(l:summary, 'parent\: \d+\:[0-9a-f]+') + let l:branch = matchstr(l:summary, 'branch\: [\d\w\-_\.]+') + return l:branch . ', ' . l:parent_rev +endfunction + +" Rescans the current buffer for setting up Mercurial commands. +" Passing '1' as the parameter enables debug traces temporarily. +function! lawrencium#rescan(...) + if exists('b:mercurial_dir') + unlet b:mercurial_dir + endif + if a:0 && a:1 + let l:trace_backup = g:lawrencium_trace + let g:lawrencium_trace = 1 + endif + call s:setup_buffer_commands() + if a:0 && a:1 + let g:lawrencium_trace = l:trace_backup + endif +endfunction + +" Enables/disables the debug trace. +function! lawrencium#debugtrace(...) + let g:lawrencium_trace = (a:0 == 0 || (a:0 && a:1)) + echom "Lawrencium debug trace is now " . (g:lawrencium_trace ? "enabled." : "disabled.") +endfunction + +" }}} +