"============================================================================= " $Id$ " File: plugin/local_vimrc.vim {{{1 " Author: Luc Hermitte " " Version: 1.10 " Created: 09th Apr 2003 " Last Update: 10th Apr 2012 " License: GPLv3 "------------------------------------------------------------------------ " Description: Solution to Yakov Lerner's question on Vim ML {{{2 " Search for a _vimrc_local.vim file in the parents directories and " source it if found. " " Initial Question: " "Is it possible, after sourcing ~/.exrc, to traverse from $HOME down " to cwd, and source .exrc from every directory if present ? " (And if cwd is not under $HOME, just source ~/.exrc). " What do I put into .vimrc to do this ? " " "Example: current dir is ~/a/b/c. Files are sourced in this order: " ~/.exrc, then ~/a/.exrc, ~/a/b/.exrc, ~/a/b/c/.exrc. " No messages if some of .exrc does not exist." " }}}2 "------------------------------------------------------------------------ " Installation: {{{2 " 0- Set g:local_vimrc in your .vimrc if you wish to use filenames other " than '_vimrc_local.vim' " a- Drop this plugin into a {rtp}/plugin/ directory, and install " lh-vim-lib. " b- Define _vimrc_local.vim files into your directories " " Ideally, each foo/bar/_vimrc_local.vim should be defined the same " way as a ftplugin, i.e.: {{{3 " " Global stuff that needs to be updated/override " let g:bar = 'bar' " YES! This is a global variable! " " " Local stuff that needs to be defined once for each buffer " if exists('b:foo_bar_local_vimrc') | finish | endif " let b:foo_bar_local_vimrc = 1 " setlocal xxx " nnoremap foo :call s:Foo() " let b:foo = 'foo' " " " Global stuff that needs to be defined once only => functions " if exists('g:foo_bar_local_vimrc') | finish | endif " let g:foo_bar_local_vimrc = 1 " function s:Foo() " ... " endfunction " c- In order to load the local variable before a skeleton is read, ask " the maintainer of template-file expander pluin to explicitly execute " :SourceLocalVimrc before doing the actual expansion. " " History: {{{2 " v1.10 s:k_version in local_vimrc files is automatically incremented " on saving " v1.9 New command :SourceLocalVimrc in order to explicitly load the " local-vimrc file before creating new files from a template (We " can't just rely on BufNewFile as there is no guaranty " local_vimrc's BufNewFile will be called before the one from the " Template Expander Plugin => it's up to the TEP to call the " function) " v1.8 No more infinite recursion on file in non existent paths. " + patch from cristiklein to support paths with spaces " v1.7 Don't search a local vimrc with remote paths (ftp://, http, ... ) " v1.6 Sometimes root path is Z:\\, which is quite odd " v1.5 The auto-command is moved to the au-group LocalVimrc " v1.4 Stop the recursion when we get to // or \\ (UNC paths) " v1.3 More comments. " Trace of the directories searched when 'verbose' >= 2 " v1.2 Stops at $HOME or at root (/) " v1.1 Uses _vimrc_local.vim " v1.0 Initial solution " TODO: {{{2 " (*) Add option to stop looking at $HOME or elsewhere " ([bg]:lv_stop_at : string, default $HOME) " See also: alternative scripts: #441, #3393, #1860, ... " }}}1 "============================================================================= "============================================================================= " Avoid global reinclusion {{{1 let s:k_version = 109 if exists("g:loaded_local_vimrc") \ && (g:loaded_local_vimrc >= s:k_version) \ && !exists('g:force_reload_local_vimrc') finish endif let g:loaded_local_vimrc_vim = s:k_version let s:cpo_save=&cpo set cpo&vim " Avoid global reinclusion }}}1 "------------------------------------------------------------------------ " Commands {{{1 command! -nargs=0 SourceLocalVimrc call s:Main(expand('%:p')) " Functions {{{1 " Name of the files used {{{2 function! s:LocalVimrcName() return exists('g:local_vimrc') ? g:local_vimrc : '_vimrc_local.vim' endfunction let s:local_vimrc = s:LocalVimrcName() " Value of $HOME -- actually a regex. {{{2 let s:home = substitute($HOME, '/\|\\', '[/\\\\]', 'g') " Regex used to determine when we must stop looking for local-vimrc's {{{2 " Sometimes paths appears as Z:\\ .... let s:re_last_path = '^/\=$\|^[A-Za-z]:[/\\]\+$\|^//$\|^\\\\$'. \ ((s:home != '') ? ('\|^'.s:home.'$') : '') " The main function {{{2 function! s:SourceLocal(path) let up_path = fnamemodify(a:path,':h') if up_path == '.' " likelly a non existant path if ! isdirectory(a:path) call lh#common#warning_msg("[local_vimrc] The current file '".expand('%:p:')."' seems to be in a non-existant directory: '".a:path."'") endif let up_path = getcwd() endif " call confirm('crt='.a:path."\nup=".up_path."\n$HOME=".s:home, '&Ok', 1) " echomsg ('crt='.a:path."\nup=".up_path."\n$HOME=".s:home) if (a:path !~ s:re_last_path) if (up_path !~ s:re_last_path) " Recursive call: first check the parent directory call s:SourceLocal(up_path) elseif filereadable(up_path.'/'.s:local_vimrc) " Terminal condition: try to source the upper(/uppest?) local-vimrc if &verbose >= 2 echo 'Check '.up_path.' for '.s:local_vimrc.' ... found!' endif exe 'source '.escape(up_path.'/'.s:local_vimrc, ' \$,') elseif &verbose >= 2 echo 'Check '.up_path.' for '.s:local_vimrc.' ... none!' endif endif " In all case, try to source the local-vimrc present in the directory " currently considered if filereadable(a:path.'/'.s:local_vimrc) if &verbose >= 2 echo 'Check '.a:path.' for '.s:local_vimrc.' ... found!' endif exe 'source '.escape(a:path.'/'.s:local_vimrc, ' \$,') elseif &verbose >= 2 echo 'Check '.a:path.' for '.s:local_vimrc.' ... none!' endif endfunction function! s:CheckForbiddenPath(path) let ok = a:path !~ '^\(s\=ftp:\|s\=http:\|scp:\|^$\)' return ok endfunction function! s:Main(path) " echomsg 'Sourcing: '.a:path if !s:CheckForbiddenPath(a:path) return else call s:SourceLocal(a:path) endif endfunction " Update s:k_version in local_vimrc files {{{2 function! s:IncrementVersionOnSave() let l = search('let s:k_version', 'n') if l > 0 let nl = substitute(getline(l), '\(let\s\+s:k_version\s*=\s*\)\(\d\+\)\s*$', '\=submatch(1).(1+submatch(2))', '') call setline(l, nl) endif endfunction " Auto-command {{{2 " => automate the loading of local-vimrc's every time we change buffers aug LocalVimrc au! au BufEnter * :call s:Main(expand(':p:h')) exe 'au BufWritePre '.s:local_vimrc . ' call s:IncrementVersionOnSave()' aug END " Functions }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: