11let s: plugin_name = expand (' <sfile>:t:r' )
22let s: vital_base_dir = expand (' <sfile>:h' )
33let s: project_root = expand (' <sfile>:h:h:h' )
4- let s: is_vital_vim = s: plugin_name is # ' _latest__ '
4+ let s: is_vital_vim = s: plugin_name is # ' vital '
55
66let s: loaded = {}
77let s: cache_sid = {}
@@ -25,11 +25,18 @@ function! vital#{s:plugin_name}#of() abort
2525 return s: new (s: plugin_name )
2626endfunction
2727
28+ function ! vital#{s: plugin_name }#import (... ) abort
29+ if ! exists (' s:V' )
30+ let s: V = s: new (s: plugin_name )
31+ endif
32+ return call (s: V .import , a: 000 , s: V )
33+ endfunction
34+
2835let s: Vital = {}
2936
3037function ! s: new (plugin_name) abort
3138 let base = deepcopy (s: Vital )
32- let base.plugin_name = a: plugin_name
39+ let base._plugin_name = a: plugin_name
3340 return base
3441endfunction
3542
@@ -103,18 +110,10 @@ endfunction
103110let s: Vital .unload = s: _function (' s:unload' )
104111
105112function ! s: exists (name) abort dict
106- let b = exists (printf (' *vital#_%s#%s#import' , self .plugin_name, substitute (a: name , ' \.' , ' #' , ' g' )))
107- if b
108- return b
113+ if a: name !~# ' \v^\u\w*%(\.\u\w*)*$'
114+ throw ' vital: Invalid module name: ' . a: name
109115 endif
110- let name_path = substitute (a: name , ' \.' , ' /' , ' g' )
111- let path = printf (' %s/_%s/%s.vim' , s: vital_base_dir , self .plugin_name, name_path)
112- let b = filereadable (path )
113- if b
114- return b
115- endif
116- let path = printf (' %s/_%s/%s.vim' , s: vital_base_dir , ' _latest__' , name_path)
117- let b = filereadable (path )
116+ return s: _module_path (a: name ) isnot # ' '
118117endfunction
119118let s: Vital .exists = s: _function (' s:exists' )
120119
@@ -125,6 +124,11 @@ function! s:search(pattern) abort dict
125124endfunction
126125let s: Vital .search = s: _function (' s:search' )
127126
127+ function ! s: plugin_name () abort dict
128+ return self ._plugin_name
129+ endfunction
130+ let s: Vital .plugin_name = s: _function (' s:plugin_name' )
131+
128132function ! s: _self_vital_files () abort
129133 let builtin = printf (' %s/__%s__/' , s: vital_base_dir , s: plugin_name )
130134 let installed = printf (' %s/_%s/' , s: vital_base_dir , s: plugin_name )
@@ -178,45 +182,76 @@ let s:Vital._import = s:_function('s:_import')
178182
179183" s:_get_module() returns module object wihch has all script local functions.
180184function ! s: _get_module (name) abort dict
181- try
182- let module = vital#_{self .plugin_name}#{substitute (a: name , ' \.' , ' #' , ' g' )}#import ()
183- catch /E117: Unknown function:/
184- " Retry to support loading self modules.
185- let module = s: _get_builtin_module (a: name )
186- endtry
187- return module
185+ let funcname = s: _import_func_name (self .plugin_name (), a: name )
186+ if s: _exists_autoload_func_with_source (funcname)
187+ return call (funcname, [])
188+ else
189+ return s: _get_builtin_module (a: name )
190+ endif
188191endfunction
189- let s: Vital ._get_module = s: _function (' s:_get_module' )
190192
191193function ! s: _get_builtin_module (name) abort
192194 return s: sid2sfuncs (s: _module_sid (a: name ))
193195endfunction
194196
195- let s: vital_builtin_dir = printf (' autoload/vital/__%s__/' , s: is_vital_vim ? ' *' : s: plugin_name )
197+ if s: is_vital_vim
198+ " For vital.vim, we can use s:_get_builtin_module directly
199+ let s: Vital ._get_module = s: _function (' s:_get_builtin_module' )
200+ else
201+ let s: Vital ._get_module = s: _function (' s:_get_module' )
202+ endif
203+
204+ function ! s: _import_func_name (plugin_name, module_name) abort
205+ return printf (' vital#_%s#%s#import' , a: plugin_name , s: _dot_to_sharp (a: module_name ))
206+ endfunction
196207
197208function ! s: _module_sid (name) abort
198- let module_path = substitute (a: name , ' \.' , ' /' , ' g' ) . ' .vim'
199- let module_rel_path = s: vital_builtin_dir . module_path
200- let path = get (split (globpath (s: _module_sid_base_dir (), module_rel_path, 1 ), " \n " ), 0 , ' ' )
209+ let path = s: _module_path (a: name )
201210 if ! filereadable (path )
202211 throw ' vital: module not found: ' . a: name
203212 endif
204- let p = substitute (' autoload/vital/__\w\+__/' . module_path, ' /' , ' [/\\\\]\\+' , ' g' )
213+ let vital_dir = s: is_vital_vim ? ' __\w\+__' : printf (' _\{1,2}%s\%%(__\)\?' , s: plugin_name )
214+ let base = join ([vital_dir, ' ' ], ' [/\\]\+' )
215+ let p = base . substitute (' ' . a: name , ' \.' , ' [/\\\\]\\+' , ' g' )
205216 let sid = s: _sid (path , p )
206217 if ! sid
207218 call s: _source (path )
208219 let sid = s: _sid (path , p )
209220 if ! sid
210- throw ' vital: cannot get <SID> from path'
221+ throw printf ( ' vital: cannot get <SID> from path: %s ' , path )
211222 endif
212223 endif
213224 return sid
214225endfunction
215226
227+ function ! s: _module_path (name) abort
228+ return get (s: _extract_files (a: name , s: vital_files ()), 0 , ' ' )
229+ endfunction
230+
216231function ! s: _module_sid_base_dir () abort
217232 return s: is_vital_vim ? &rtp : s: project_root
218233endfunction
219234
235+ function ! s: _dot_to_sharp (name) abort
236+ return substitute (a: name , ' \.' , ' #' , ' g' )
237+ endfunction
238+
239+ " It will sources autoload file if a given func is not already defined.
240+ function ! s: _exists_autoload_func_with_source (funcname) abort
241+ if exists (' *' . a: funcname )
242+ " Return true if a given func is already defined
243+ return 1
244+ endif
245+ " source a file which may include a given func definition and try again.
246+ let path = ' autoload/' . substitute (substitute (a: funcname , ' #[^#]*$' , ' .vim' , ' ' ), ' #' , ' /' , ' g' )
247+ call s: _runtime (path )
248+ return exists (' *' . a: funcname )
249+ endfunction
250+
251+ function ! s: _runtime (path ) abort
252+ execute ' runtime' fnameescape (a: path )
253+ endfunction
254+
220255function ! s: _source (path ) abort
221256 execute ' source' fnameescape (a: path )
222257endfunction
297332 if a: list [i ] == # a: list [i - 1 ]
298333 call remove (a: list , i )
299334 endif
300- let i -= 1
335+ let i -= 1
301336 endwhile
302337 return a: list
303338 endfunction
0 commit comments