changeset 51:a6bc310e7015

First version of lawrencium plugin.
author Ludovic Chabant <ludovic@chabant.com>
date Wed, 07 Dec 2011 23:32:39 -0800
parents 30c36bc04926
children 05fd225bd1a0
files vim/bundle/lawrencium/doc/lawrencium.txt vim/bundle/lawrencium/plugin/lawrencium.vim
diffstat 2 files changed, 247 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/bundle/lawrencium/doc/lawrencium.txt	Wed Dec 07 23:32:39 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/vim/bundle/lawrencium/plugin/lawrencium.vim	Wed Dec 07 23:32:39 2011 -0800
@@ -0,0 +1,202 @@
+" lawrencium.vim - A Mercurial wrapper
+" Maintainer:   Ludovic Chabant <http://ludovic.chabant.com>
+" Version:      0.1
+
+if exists('g:loaded_lawrencium') || &cp
+    "  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
+
+" Utility {{{
+
+function! s:stripslash(path)
+    return fnamemodify(a:path, ':s?[\/]$??')
+endfunction
+
+function! s:trace(message)
+   if g:lawrencium_trace 
+       let l:message = "lawrencium: " . a:message
+   endif
+endfunction
+
+function! s:throw(message)
+    let v:errmsg = "lawrencium: " . a:message
+    throw v:errmsg
+endfunction
+
+function! s:find_repo_root(path)
+    let l:path = s:stripslash(a:path)
+    while l:path != ""
+        if isdirectory(l:path . '/.hg/store')
+            return simplify(fnamemodify(l:path, ':p'))
+        endif
+        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
+
+" Sets up the current buffer with local variables
+function! s:HgRepo.SetupBuffer() abort
+    if exists('b:mercurial_dir') && (b:mercurial_dir =~# '/^\s*$/')
+        unlet b:mercurial_dir
+    endif
+    if !exists('b:mercurial_dir')
+        let b:mercurial_dir = self.root_dir
+    endif
+    if exists('b:mercurial_dir')
+        call s:trace("Setting Mercurial directory to : " . expand(b:mercurial_dir))
+        silent doautocmd User Lawrencium
+    endif
+endfunction
+
+" Gets a full path given a repo-relative path
+function! s:HgRepo.GetFullPath(path) abort
+    let l:path = self.root_dir
+    if a:path =~# '^/'
+        let l:path = s:stripslash(self.root_dir)
+    endif
+    return l:path . a:path
+endfunction
+
+" Runs a Mercurial command in the repo
+function! s:HgRepo.RunCommand(command, ...) abort
+    let l:hg_command = g:lawrencium_hg_executable . ' --repository ' . shellescape(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'))
+            let b:mercurial_dir = l:path
+        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
+
+augroup lawrencium_detect
+    autocmd!
+"    autocmd BufNewFile,BufReadPost *     call s:DetectMercurialRepository(expand('<amatch>:p'))
+"    autocmd VimEnter               *     if expand('<amatch>')==''|call s:DetectMercurialRepository(getcwd())|endif
+augroup end
+
+" }}}
+
+" Commands {{{
+
+let s:main_commands = []
+
+function! s:AddMainCommand(command) abort
+    let s:main_commands += [a:command]
+endfunction
+
+function! s:DefineMainCommands()
+    for command in s:main_commands
+        execute 'command! -buffer '.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:root_dir = s:hg_repo().root_dir
+    if (a:ArgLead =~# '^/')
+        let l:root_dir = s:stripslash(l:root_dir)
+    endif
+    let l:matches = split(glob(l:root_dir . a:ArgLead . '*'), '\n')
+    let l:strip_len = len(l:root_dir)
+    call map(l:matches, 'v:val[l:strip_len : -1] . "/"')
+    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>)`")
+
+" }}}
+
+" Autoload Functions {{{
+
+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
+
+" }}}
+