1 " Vim script
  2 " Last Change: July 23, 2010
  3 " Author: Peter Odding
  4 " URL: http://peterodding.com/code/vim/reload/
  5 
  6 let s:script = expand('<sfile>:t')
  7 
  8 " Patterns to match various types of Vim script names. {{{1
  9 
 10 " Enable line continuation.
 11 let s:cpo_save = &cpo
 12 set cpoptions-=C
 13 
 14 if has('win32') || has('win64')
 15   let s:scripttypes = [
 16         \ ['s:reload_plugin', '\c[\\/]plugin[\\/].\{-}\.vim$'],
 17         \ ['s:reload_autoload', '\c[\\/]autoload[\\/].\{-}\.vim$'],
 18         \ ['s:reload_ftplugin', '\c[\\/]ftplugin[\\/][^\\/]\+\.vim$'],
 19         \ ['s:reload_syntax', '\c[\\/]syntax[\\/][^\\/]\+\.vim$'],
 20         \ ['s:reload_indent', '\c[\\/]indent[\\/][^\\/]\+\.vim$'],
 21         \ ['s:reload_colors', '\c[\\/]colors[\\/][^\\/]\+\.vim$']]
 22 else
 23   let s:scripttypes = [
 24         \ ['s:reload_plugin', '\C/plugin/.\{-}\.vim$'],
 25         \ ['s:reload_autoload', '\C/autoload/.\{-}\.vim$'],
 26         \ ['s:reload_ftplugin', '\C/ftplugin/[^/]\+\.vim$'],
 27         \ ['s:reload_syntax', '\C/syntax/[^/]\+\.vim$'],
 28         \ ['s:reload_indent', '\C/indent/[^/]\+\.vim$'],
 29         \ ['s:reload_colors', '\C/colors/[^/]\+\.vim$']]
 30 endif
 31 
 32 " Restore compatibility options
 33 let &cpo = s:cpo_save
 34 unlet s:cpo_save
 35 
 36 if !exists('s:reload_script_active')
 37   function! xolox#reload#script(filename) " {{{1
 38     let s:reload_script_active = 1
 39     let start_time = xolox#timer#start()
 40     if s:script_sourced(a:filename)
 41       let filename = s:unresolve_scriptname(a:filename)
 42       for [callback, pattern] in s:scripttypes
 43         if filename =~ pattern
 44           let args = [start_time, filename, fnamemodify(filename, ':~')]
 45           let result = call(callback, args)
 46           if type(result) == type([])
 47             call call('xolox#timer#stop', result)
 48           endif
 49           unlet result
 50         endif
 51       endfor
 52     endif
 53     unlet s:reload_script_active
 54   endfunction
 55 endif
 56 
 57 function! s:reload_plugin(start_time, filename, friendly_name) " {{{1
 58   call s:reload_message('plug-in', a:friendly_name)
 59   " Clear include guard so full plug-in can be reloaded?
 60   let variable = 'g:loaded_' . fnamemodify(a:filename, ':t:r')
 61   if exists(variable)
 62     execute 'unlet' variable
 63   endif
 64   execute 'source' fnameescape(a:filename)
 65   return ["%s: Reloaded %s plug-in in %s.", s:script, a:friendly_name, a:start_time]
 66 endfunction
 67 
 68 if !exists('s:reload_script_active')
 69   function! s:reload_autoload(start_time, filename, friendly_name) " {{{1
 70     call s:reload_message('auto-load script', a:friendly_name)
 71     execute 'source' fnameescape(a:filename)
 72     return ["%s: Reloaded %s auto-load script in %s.", s:script, a:friendly_name, a:start_time]
 73   endfunction
 74 endif
 75 
 76 function! s:reload_ftplugin(st, fn, hr) " {{{1
 77   return s:reload_buffers(a:st, a:fn, a:hr, 'file type plug-in', 'b:reload_ftplugin')
 78 endfunction
 79 
 80 function! s:reload_syntax(st, fn, hr) " {{{1
 81   return s:reload_buffers(a:st, a:fn, a:hr, 'syntax script', 'b:reload_syntax')
 82 endfunction
 83 
 84 function! s:reload_indent(st, fn, hr) " {{{1
 85   return s:reload_buffers(a:st, a:fn, a:hr, 'indent script', 'b:reload_indent')
 86 endfunction
 87 
 88 function! s:reload_buffers(start_time, filename, friendly_name, script_type, variable)
 89   let type = fnamemodify(a:filename, ':t:r')
 90   " Make sure we can restore the user's context after reloading!
 91   let bufnr_save = bufnr('%')
 92   let view_save = winsaveview()
 93   " Temporarily enable the SwapExists automatic command to prevent the E325
 94   " prompt from rearing its ugly head while reloading (in :bufdo below).
 95   let s:reloading_buffers = 1
 96   call s:reload_message(a:script_type, a:friendly_name)
 97   silent hide bufdo if &ft == type | execute 'let' a:variable '= 1' | endif
 98   call xolox#reload#windows()
 99   " Restore the user's context.
100   silent execute 'buffer' bufnr_save
101   call winrestview(view_save)
102   " Disable the SwapExists automatic command.
103   unlet s:reloading_buffers
104   return ["%s: Reloaded %s %s in %s.", s:script, a:script_type, a:friendly_name, a:start_time]
105 endfunction
106 
107 function! xolox#reload#open_readonly() " {{{1
108   if exists('s:reloading_buffers')
109     let v:swapchoice = 'o'
110   endif
111 endfunction
112 
113 function! xolox#reload#windows() " {{{1
114   let window = winnr()
115   try
116     windo call s:reload_window()
117   finally
118     execute window . 'wincmd w'
119   endtry
120 endfunction
121 
122 function! s:reload_window()
123   if exists('b:reload_ftplugin')
124     unlet! b:reload_ftplugin b:did_ftplugin
125     let &filetype = &filetype
126   endif
127   if exists('b:reload_syntax')
128     unlet! b:reload_syntax b:current_syntax
129     let &syntax = &syntax
130   endif
131   if exists('b:reload_indent')
132     unlet! b:reload_indent b:did_indent
133     let &filetype = &filetype
134   endif
135 endfunction
136 
137 function! s:reload_colors(start_time, filename, friendly_name) " {{{1
138   let colorscheme = fnamemodify(a:filename, ':t:r')
139   if exists('g:colors_name') && g:colors_name == colorscheme
140     call s:reload_message('color scheme', a:friendly_name)
141     let escaped = fnameescape(colorscheme)
142     execute 'colorscheme' escaped
143     execute 'doautocmd colorscheme' escaped
144     return ["%s: Reloaded %s color scheme in %s.", s:script, a:friendly_name, a:start_time]
145   endif
146 endfunction
147 
148 " Miscellaneous functions. {{{1
149 
150 let s:loaded_scripts = {}
151 
152 function! s:script_sourced(filename) " {{{2
153   call s:parse_scriptnames()
154   return has_key(s:loaded_scripts, resolve(a:filename))
155 endfunction
156 
157 function! s:unresolve_scriptname(filename) " {{{2
158   call s:parse_scriptnames()
159   return get(s:loaded_scripts, resolve(a:filename), a:filename)
160 endfunction
161 
162 function! s:parse_scriptnames() " {{{2
163   let listing = ''
164   redir => listing
165   silent scriptnames
166   redir END
167   let lines = split(listing, "\n")
168   let num_loaded = len(s:loaded_scripts)
169   if len(lines) > num_loaded
170     for line in lines[num_loaded : -1]
171       let filename = matchstr(line, '^\s*\d\+:\s\+\zs.\+$')
172       let s:loaded_scripts[resolve(filename)] = filename
173     endfor
174   endif
175 endfunction
176 
177 function! s:reload_message(scripttype, scriptname) " {{{2
178   call xolox#message('%s: Reloading %s %s', s:script, a:scripttype, a:scriptname)
179 endfunction
180 
181 " vim: ts=2 sw=2 et