Mercurial > vim-lawrencium
view autoload/lawrencium.vim @ 139:065625e1bb31
Split plugin file into multiple extensions.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Mon, 13 Jun 2016 09:32:34 -0700 |
parents | |
children | 4d5f4233b04e |
line wrap: on
line source
" Path Utility {{{ " Strips the ending slash in a path. function! lawrencium#stripslash(path) return fnamemodify(a:path, ':s?[/\\]$??') endfunction " Returns whether a path is absolute. function! lawrencium#isabspath(path) return a:path =~# '\v^(\w\:)?[/\\]' endfunction " Normalizes the slashes in a path. function! lawrencium#normalizepath(path) if exists('+shellslash') && &shellslash return substitute(a:path, '\v/', '\\', 'g') elseif has('win32') return substitute(a:path, '\v/', '\\', 'g') else return a:path endif endfunction " Shell-slashes the path (opposite of `normalizepath`). function! lawrencium#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! lawrencium#tempname(name, ...) let l:path = tempname() let l:result = fnamemodify(l:path, ':h') . '/' . a:name . fnamemodify(l:path, ':t') if a:0 > 0 let l:result = l:result . a:1 endif return l:result endfunction " Delete a temporary file if it exists. function! lawrencium#clean_tempfile(path) if filewritable(a:path) call lawrencium#trace("Cleaning up temporary file: " . a:path) call delete(a:path) endif endfunction " }}} " Logging {{{ " Prints a message if debug tracing is enabled. function! lawrencium#trace(message, ...) if g:lawrencium_trace || (a:0 && a:1) let l:message = "lawrencium: " . a:message echom l:message endif endfunction " Prints an error message with 'lawrencium error' prefixed to it. function! lawrencium#error(message) echom "lawrencium error: " . a:message endfunction " Throw a Lawrencium exception message. function! lawrencium#throw(message) let v:errmsg = "lawrencium: " . a:message throw v:errmsg endfunction " }}} " Repositories {{{ " Finds the repository root given a path inside that repository. " Throw an error if not repository is found. function! lawrencium#find_repo_root(path) let l:path = lawrencium#stripslash(a:path) let l:previous_path = "" while l:path != l:previous_path if isdirectory(l:path . '/.hg') return lawrencium#normalizepath(simplify(fnamemodify(l:path, ':p'))) endif let l:previous_path = l:path let l:path = fnamemodify(l:path, ':h') endwhile call lawrencium#throw("No Mercurial repository found above: " . a:path) endfunction " Given a Lawrencium path (e.g: 'lawrencium:///repo/root_dir//foo/bar/file.py//rev=34'), extract " the repository root, relative file path and revision number/changeset ID. " " If a second argument exists, it must be: " - `relative`: to make the file path relative to the repository root. " - `absolute`: to make the file path absolute. " function! lawrencium#parse_lawrencium_path(lawrencium_path, ...) let l:repo_path = lawrencium#shellslash(a:lawrencium_path) let l:repo_path = substitute(l:repo_path, '\\ ', ' ', 'g') if l:repo_path =~? '\v^lawrencium://' let l:repo_path = strpart(l:repo_path, strlen('lawrencium://')) endif let l:root_dir = '' let l:at_idx = stridx(l:repo_path, '//') if l:at_idx >= 0 let l:root_dir = strpart(l:repo_path, 0, l:at_idx) let l:repo_path = strpart(l:repo_path, l:at_idx + 2) endif let l:value = '' let l:action = '' let l:actionidx = stridx(l:repo_path, '//') if l:actionidx >= 0 let l:action = strpart(l:repo_path, l:actionidx + 2) let l:repo_path = strpart(l:repo_path, 0, l:actionidx) let l:equalidx = stridx(l:action, '=') if l:equalidx >= 0 let l:value = strpart(l:action, l:equalidx + 1) let l:action = strpart(l:action, 0, l:equalidx) endif endif if a:0 > 0 execute 'cd! ' . fnameescape(l:root_dir) if a:1 == 'relative' let l:repo_path = fnamemodify(l:repo_path, ':.') elseif a:1 == 'absolute' let l:repo_path = fnamemodify(l:repo_path, ':p') endif execute 'cd! -' endif let l:result = { 'root': l:root_dir, 'path': l:repo_path, 'action': l:action, 'value': l:value } return l:result endfunction " Clean up all the 'HG:' lines from a commit message, and see if there's " any message left (Mercurial does this automatically, usually, but " apparently not when you feed it a log file...). function! lawrencium#clean_commit_file(log_file) abort let l:lines = readfile(a:log_file) call filter(l:lines, "v:val !~# '\\v^HG:'") if len(filter(copy(l:lines), "v:val !~# '\\v^\\s*$'")) == 0 return 0 endif call writefile(l:lines, a:log_file) return 1 endfunction " }}} " Vim Utility {{{ " Finds a window whose displayed buffer has a given variable " set to the given value. function! lawrencium#find_buffer_window(varname, varvalue) abort for wnr in range(1, winnr('$')) let l:bnr = winbufnr(wnr) if getbufvar(l:bnr, a:varname) == a:varvalue return l:wnr endif endfor return -1 endfunction " Opens a buffer in a way that makes it easy to delete it later: " - if the about-to-be previous buffer doesn't have a given variable, " just open the new buffer. " - if the about-to-be previous buffer has a given variable, open the " new buffer with the `keepalt` option to make it so that the " actual previous buffer (returned by things like `bufname('#')`) " is the original buffer that was there before the first deletable " buffer was opened. function! lawrencium#edit_deletable_buffer(varname, varvalue, path) abort let l:edit_cmd = 'edit ' if getbufvar('%', a:varname) != '' let l:edit_cmd = 'keepalt edit ' endif execute l:edit_cmd . fnameescape(a:path) call setbufvar('%', a:varname, a:varvalue) endfunction " Deletes all buffers that have a given variable set to a given value. " For each buffer, if it is not shown in any window, it will be just deleted. " If it is shown in a window, that window will be switched to the alternate " buffer before the buffer is deleted, unless the `lawrencium_quit_on_delete` " variable is set to `1`, in which case the window is closed too. function! lawrencium#delete_dependency_buffers(varname, varvalue) abort let l:cur_winnr = winnr() for bnr in range(1, bufnr('$')) if getbufvar(bnr, a:varname) == a:varvalue " Delete this buffer if it is not shown in any window. " Otherwise, display the alternate buffer before deleting " it so the window is not closed. let l:bwnr = bufwinnr(bnr) if l:bwnr < 0 || getbufvar(bnr, 'lawrencium_quit_on_delete') == 1 if bufloaded(l:bnr) call lawrencium#trace("Deleting dependency buffer " . bnr) execute "bdelete! " . bnr else call lawrencium#trace("Dependency buffer " . bnr . " is already unladed.") endif else execute l:bwnr . "wincmd w" " TODO: better handle case where there's no previous/alternate buffer? let l:prev_bnr = bufnr('#') if l:prev_bnr > 0 && bufloaded(l:prev_bnr) execute "buffer " . l:prev_bnr if bufloaded(l:bnr) call lawrencium#trace("Deleting dependency buffer " . bnr . " after switching to " . l:prev_bnr . " in window " . l:bwnr) execute "bdelete! " . bnr else call lawrencium#trace("Dependency buffer " . bnr . " is unladed after switching to " . l:prev_bnr) endif else call lawrencium#trace("Deleting dependency buffer " . bnr . " and window.") bdelete! endif endif endif endfor if l:cur_winnr != winnr() call lawrencium#trace("Returning to window " . l:cur_winnr) execute l:cur_winnr . "wincmd w" endif endfunction " }}} " Mercurial Repository Object {{{ " 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 = lawrencium#find_repo_root(a:path) call lawrencium#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 lawrencium#isabspath(a:path) call lawrencium#throw("Expected relative path, got absolute path: " . a:path) endif return lawrencium#normalizepath(l:root_dir . a:path) endfunction " Gets a repo-relative path given any path. function! s:HgRepo.GetRelativePath(path) abort execute 'lcd! ' . fnameescape(self.root_dir) let l:relative_path = fnamemodify(a:path, ':.') execute 'lcd! -' return l:relative_path endfunction " Gets, and optionally creates, a temp folder for some operation in the `.hg` " directory. function! s:HgRepo.GetTempDir(path, ...) abort let l:tmp_dir = self.GetFullPath('.hg/lawrencium/' . a:path) if !isdirectory(l:tmp_dir) if a:0 > 0 && !a:1 return '' endif call mkdir(l:tmp_dir, 'p') endif return l:tmp_dir 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 =~# '\v^[/\\]') let l:root_dir = lawrencium#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 " Gets a full Mercurial command. function! s:HgRepo.GetCommand(command, ...) abort " If there's only one argument, and it's a list, then use that as the " argument list. let l:arg_list = a:000 if a:0 == 1 && type(a:1) == type([]) let l:arg_list = a:1 endif let l:prev_shellslash = &shellslash setlocal noshellslash let l:hg_command = g:lawrencium_hg_executable . ' --repository ' . shellescape(lawrencium#stripslash(self.root_dir)) let l:hg_command = l:hg_command . ' ' . a:command for l:arg in l:arg_list let l:hg_command = l:hg_command . ' ' . shellescape(l:arg) endfor if l:prev_shellslash setlocal shellslash endif return l:hg_command endfunction " Runs a Mercurial command in the repo. function! s:HgRepo.RunCommand(command, ...) abort let l:all_args = [1, a:command] + a:000 return call(self['RunCommandEx'], l:all_args, self) endfunction function! s:HgRepo.RunCommandEx(plain_mode, command, ...) abort let l:prev_hgplain = $HGPLAIN if a:plain_mode let $HGPLAIN = 'true' endif let l:all_args = [a:command] + a:000 let l:hg_command = call(self['GetCommand'], l:all_args, self) call lawrencium#trace("Running Mercurial command: " . l:hg_command) let l:cmd_out = system(l:hg_command) if a:plain_mode let $HGPLAIN = l:prev_hgplain endif return l:cmd_out endfunction " Runs a Mercurial command in the repo and reads its output into the current " buffer. function! s:HgRepo.ReadCommandOutput(command, ...) abort function! s:PutOutputIntoBuffer(command_line) let l:was_buffer_empty = (line('$') == 1 && getline(1) == '') execute '0read!' . escape(a:command_line, '%#\') if l:was_buffer_empty " (Always true?) " '0read' inserts before the cursor, leaving a blank line which " needs to be deleted... but if there are folds in this thing, we " must open them all first otherwise we could delete the whole " contents of the last fold (since Vim may close them all by " default). normal! zRG"_dd endif endfunction let l:all_args = [a:command] + a:000 let l:hg_command = call(self['GetCommand'], l:all_args, self) call lawrencium#trace("Running Mercurial command: " . l:hg_command) call s:PutOutputIntoBuffer(l:hg_command) endfunction " Build a Lawrencium path for the given file and action. " By default, the given path will be made relative to the repository root, " unless '0' is passed as the 4th argument. function! s:HgRepo.GetLawrenciumPath(path, action, value, ...) abort let l:path = a:path if a:0 == 0 || !a:1 let l:path = self.GetRelativePath(a:path) endif let l:path = fnameescape(l:path) let l:result = 'lawrencium://' . lawrencium#stripslash(self.root_dir) . '//' . l:path if a:action !=? '' let l:result = l:result . '//' . a:action if a:value !=? '' let l:result = l:result . '=' . a:value endif endif return l:result endfunction " Repo cache map. let s:buffer_repos = {} " Get a cached repo. function! lawrencium#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 = lawrencium#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 " }}} " Buffer Object {{{ " The prototype dictionary. let s:Buffer = {} " Constructor. function! s:Buffer.New(number) dict abort let l:newBuffer = copy(self) let l:newBuffer.nr = a:number let l:newBuffer.var_backup = {} let l:newBuffer.cmd_names = {} let l:newBuffer.on_delete = [] let l:newBuffer.on_winleave = [] let l:newBuffer.on_unload = [] execute 'augroup lawrencium_buffer_' . a:number execute ' autocmd!' execute ' autocmd BufDelete <buffer=' . a:number . '> call s:buffer_on_delete(' . a:number . ')' execute 'augroup end' call lawrencium#trace("Built new buffer object for buffer: " . a:number) return l:newBuffer endfunction function! s:Buffer.GetName(...) dict abort let l:name = bufname(self.nr) if a:0 > 0 let l:name = fnamemodify(l:name, a:1) endif return l:name endfunction function! s:Buffer.GetVar(var) dict abort return getbufvar(self.nr, a:var) endfunction function! s:Buffer.SetVar(var, value) dict abort if !has_key(self.var_backup, a:var) let self.var_backup[a:var] = getbufvar(self.nr, a:var) endif return setbufvar(self.nr, a:var, a:value) endfunction function! s:Buffer.RestoreVars() dict abort for key in keys(self.var_backup) setbufvar(self.nr, key, self.var_backup[key]) endfor endfunction function! s:Buffer.DefineCommand(name, ...) dict abort if a:0 == 0 call lawrencium#throw("Not enough parameters for s:Buffer.DefineCommands()") endif if a:0 == 1 let l:flags = '' let l:cmd = a:1 else let l:flags = a:1 let l:cmd = a:2 endif if has_key(self.cmd_names, a:name) call lawrencium#throw("Command '".a:name."' is already defined in buffer ".self.nr) endif if bufnr('%') != self.nr call lawrencium#throw("You must move to buffer ".self.nr."first before defining local commands") endif let self.cmd_names[a:name] = 1 let l:real_flags = '' if type(l:flags) == type('') let l:real_flags = l:flags endif execute 'command -buffer '.l:real_flags.' '.a:name.' '.l:cmd endfunction function! s:Buffer.DeleteCommand(name) dict abort if !has_key(self.cmd_names, a:name) call lawrencium#throw("Command '".a:name."' has not been defined in buffer ".self.nr) endif if bufnr('%') != self.nr call lawrencium#throw("You must move to buffer ".self.nr."first before deleting local commands") endif execute 'delcommand '.a:name call remove(self.cmd_names, a:name) endfunction function! s:Buffer.DeleteCommands() dict abort if bufnr('%') != self.nr call lawrencium#throw("You must move to buffer ".self.nr."first before deleting local commands") endif for name in keys(self.cmd_names) execute 'delcommand '.name endfor let self.cmd_names = {} endfunction function! s:Buffer.MoveToFirstWindow() dict abort let l:win_nr = bufwinnr(self.nr) if l:win_nr < 0 if a:0 > 0 && a:1 == 0 return 0 endif call lawrencium#throw("No windows currently showing buffer ".self.nr) endif execute l:win_nr.'wincmd w' return 1 endfunction function! s:Buffer.OnDelete(cmd) dict abort call lawrencium#trace("Adding BufDelete callback for buffer " . self.nr . ": " . a:cmd) call add(self.on_delete, a:cmd) endfunction function! s:Buffer.OnWinLeave(cmd) dict abort if len(self.on_winleave) == 0 call lawrencium#trace("Adding BufWinLeave auto-command on buffer " . self.nr) execute 'augroup lawrencium_buffer_' . self.nr . '_winleave' execute ' autocmd!' execute ' autocmd BufWinLeave <buffer=' . self.nr . '> call s:buffer_on_winleave(' . self.nr .')' execute 'augroup end' endif call lawrencium#trace("Adding BufWinLeave callback for buffer " . self.nr . ": " . a:cmd) call add(self.on_winleave, a:cmd) endfunction function! s:Buffer.OnUnload(cmd) dict abort if len(self.on_unload) == 0 call lawrencium#trace("Adding BufUnload auto-command on buffer " . self.nr) execute 'augroup lawrencium_buffer_' . self.nr . '_unload' execute ' autocmd!' execute ' autocmd BufUnload <buffer=' . self.nr . '> call s:buffer_on_unload(' . self.nr . ')' execute 'augroup end' endif call lawrencium#trace("Adding BufUnload callback for buffer " . self.nr . ": " . a:cmd) call add(self.on_unload, a:cmd) endfunction let s:buffer_objects = {} " Get a buffer instance for the specified buffer number, or the " current buffer if nothing is specified. function! lawrencium#buffer_obj(...) abort let l:bufnr = a:0 ? a:1 : bufnr('%') if !has_key(s:buffer_objects, l:bufnr) let s:buffer_objects[l:bufnr] = s:Buffer.New(l:bufnr) endif return s:buffer_objects[l:bufnr] endfunction " Execute all the "on delete" callbacks. function! s:buffer_on_delete(number) abort let l:bufobj = s:buffer_objects[a:number] call lawrencium#trace("Calling BufDelete callbacks on buffer " . l:bufobj.nr) for cmd in l:bufobj.on_delete call lawrencium#trace(" [" . cmd . "]") execute cmd endfor call lawrencium#trace("Deleted buffer object " . l:bufobj.nr) call remove(s:buffer_objects, l:bufobj.nr) execute 'augroup lawrencium_buffer_' . l:bufobj.nr execute ' autocmd!' execute 'augroup end' endfunction " Execute all the "on winleave" callbacks. function! s:buffer_on_winleave(number) abort let l:bufobj = s:buffer_objects[a:number] call lawrencium#trace("Calling BufWinLeave callbacks on buffer " . l:bufobj.nr) for cmd in l:bufobj.on_winleave call lawrencium#trace(" [" . cmd . "]") execute cmd endfor execute 'augroup lawrencium_buffer_' . l:bufobj.nr . '_winleave' execute ' autocmd!' execute 'augroup end' endfunction " Execute all the "on unload" callbacks. function! s:buffer_on_unload(number) abort let l:bufobj = s:buffer_objects[a:number] call lawrencium#trace("Calling BufUnload callbacks on buffer " . l:bufobj.nr) for cmd in l:bufobj.on_unload call lawrencium#trace(" [" . cmd . "]") execute cmd endfor execute 'augroup lawrencium_buffer_' . l:bufobj.nr . '_unload' execute ' autocmd!' execute 'augroup end' endfunction " }}} " Buffer Commands Management {{{ " Store the commands for Lawrencium-enabled buffers so that we can add them in " batch when we need to. let s:main_commands = [] function! lawrencium#add_command(command) abort let s:main_commands += [a:command] endfunction function! lawrencium#define_commands() for l:command in s:main_commands execute 'command! -buffer ' . l:command endfor endfunction augroup lawrencium_main autocmd! autocmd User Lawrencium call lawrencium#define_commands() augroup end " 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! lawrencium#setup_buffer_commands() abort call lawrencium#trace("Scanning buffer '" . bufname('%') . "' for Lawrencium setup...") let l:do_setup = 1 if exists('b:mercurial_dir') if b:mercurial_dir =~# '\v^\s*$' unlet b:mercurial_dir else let l:do_setup = 0 endif endif try let l:repo = lawrencium#hg_repo() catch /^lawrencium\:/ return endtry let b:mercurial_dir = l:repo.root_dir if exists('b:mercurial_dir') && l:do_setup call lawrencium#trace("Setting Mercurial commands for buffer '" . bufname('%')) call lawrencium#trace(" with repo : " . expand(b:mercurial_dir)) silent doautocmd User Lawrencium endif endfunction " }}} " Commands Auto-Complete {{{ " Auto-complete function for commands that take repo-relative file paths. function! lawrencium#list_repo_files(ArgLead, CmdLine, CursorPos) abort let l:matches = lawrencium#hg_repo().Glob(a:ArgLead . '*', 1) call map(l:matches, 'lawrencium#normalizepath(v:val)') return l:matches endfunction " Auto-complete function for commands that take repo-relative directory paths. function! lawrencium#list_repo_dirs(ArgLead, CmdLine, CursorPos) abort let l:matches = lawrencium#hg_repo().Glob(a:ArgLead . '*/') call map(l:matches, 'lawrencium#normalizepath(v:val)') return l:matches endfunction " }}} " Lawrencium Files {{{ " Generic read let s:lawrencium_file_readers = {} let s:lawrencium_file_customoptions = {} function! lawrencium#add_reader(action, callback, ...) abort if has_key(s:lawrencium_file_readers, a:action) call lawrencium#throw("Lawrencium file '".a:action."' has alredy been registered.") endif let s:lawrencium_file_readers[a:action] = function(a:callback) if a:0 && a:1 let s:lawrencium_file_customoptions[a:action] = 1 endif endfunction function! lawrencium#read_lawrencium_file(path) abort call lawrencium#trace("Reading Lawrencium file: " . a:path) let l:path_parts = lawrencium#parse_lawrencium_path(a:path) if l:path_parts['root'] == '' call lawrencium#throw("Can't get repository root from: " . a:path) endif if !has_key(s:lawrencium_file_readers, l:path_parts['action']) call lawrencium#throw("No registered reader for action: " . l:path_parts['action']) endif " Call the registered reader. let l:repo = lawrencium#hg_repo(l:path_parts['root']) let l:full_path = l:repo.root_dir . l:path_parts['path'] let LawrenciumFileReader = s:lawrencium_file_readers[l:path_parts['action']] call LawrenciumFileReader(l:repo, l:path_parts, l:full_path) " Setup the new buffer. if !has_key(s:lawrencium_file_customoptions, l:path_parts['action']) setlocal readonly setlocal nomodified setlocal bufhidden=delete setlocal buftype=nofile endif goto " Remember the real Lawrencium path, because Vim can fuck up the slashes " on Windows. let b:lawrencium_path = a:path " Remember the repo it belongs to and make " the Lawrencium commands available. let b:mercurial_dir = l:repo.root_dir call lawrencium#define_commands() return '' endfunction function! lawrencium#write_lawrencium_file(path) abort call lawrencium#trace("Writing Lawrencium file: " . a:path) endfunction " }}} " Statusline {{{ " 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:repo = lawrencium#hg_repo() let l:prefix = (a:0 > 0 ? a:1 : '') let l:suffix = (a:0 > 1 ? a:2 : '') let l:branch = 'default' let l:branch_file = l:repo.GetFullPath('.hg/branch') if filereadable(l:branch_file) let l:branch = readfile(l:branch_file)[0] endif let l:bookmarks = '' let l:bookmarks_file = l:repo.GetFullPath('.hg/bookmarks.current') if filereadable(l:bookmarks_file) let l:bookmarks = join(readfile(l:bookmarks_file), ', ') endif let l:line = l:prefix . l:branch if strlen(l:bookmarks) > 0 let l:line = l:line . ' - ' . l:bookmarks endif let l:line = l:line . l:suffix return l:line endfunction " }}} " Miscellaneous User Functions {{{ " 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 lawrencium#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 " }}} " Setup {{{ function! lawrencium#init() abort let s:builtin_exts = [ \'lawrencium#addremove', \'lawrencium#annotate', \'lawrencium#cat', \'lawrencium#commit', \'lawrencium#diff', \'lawrencium#hg', \'lawrencium#log', \'lawrencium#mq', \'lawrencium#record', \'lawrencium#revert', \'lawrencium#status', \'lawrencium#vimutils' \] let s:user_exts = copy(g:lawrencium_extensions) let s:exts = s:builtin_exts + s:user_exts for ext in s:exts call lawrencium#trace("Initializing Lawrencium extension " . ext) execute ('call ' . ext . '#init()') endfor endfunction " }}}