changeset 56:0dbb1fd60f71

Debugging features, better auto-complete, and a bug fix in the hg-repo detection code.
author Ludovic Chabant <ludovic@chabant.com>
date Thu, 08 Dec 2011 12:30:50 -0800
parents a7932e0fa961
children 6494b882dcef
files vim/bundle/lawrencium/plugin/lawrencium.vim
diffstat 1 files changed, 104 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/vim/bundle/lawrencium/plugin/lawrencium.vim	Thu Dec 08 12:29:57 2011 -0800
+++ b/vim/bundle/lawrencium/plugin/lawrencium.vim	Thu Dec 08 12:30:50 2011 -0800
@@ -2,8 +2,14 @@
 " Maintainer:   Ludovic Chabant <http://ludovic.chabant.com>
 " Version:      0.1
 
-if exists('g:loaded_lawrencium') || &cp
-    "  finish
+" 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
 
@@ -15,29 +21,54 @@
     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?[\/]$??')
+    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)
-    while l: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)
@@ -63,16 +94,37 @@
 
 " 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)
+    let l:root_dir = self.root_dir
+    if a:path =~# '^[/\\]'
+        let l:root_dir = s:stripslash(l:root_dir)
     endif
-    return l:path . a:path
+    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(self.root_dir)
+    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)
@@ -106,6 +158,7 @@
 " 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*$/'
@@ -121,7 +174,8 @@
     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('%') . "' with repo : " . expand(b:mercurial_dir))
+        call s:trace("Setting Mercurial commands for buffer '" . bufname('%'))
+        call s:trace("  with repo : " . expand(b:mercurial_dir))
         silent doautocmd User Lawrencium
     endif
 endfunction
@@ -143,8 +197,8 @@
 endfunction
 
 function! s:DefineMainCommands()
-    for command in s:main_commands
-        execute 'command! -buffer '.command
+    for l:command in s:main_commands
+        execute 'command! -buffer ' . l:command
     endfor
 endfunction
 
@@ -179,13 +233,8 @@
 " 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] . "/"')
+    let l:matches = s:hg_repo().Glob(a:ArgLead . '*/')
+    call map(l:matches, 's:normalizepath(v:val)')
     return l:matches
 endfunction
 
@@ -194,8 +243,22 @@
 
 " }}}
 
+" 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 ''
@@ -206,5 +269,27 @@
     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
+
 " }}}