8ecbab00bbd8a99bd4c2d8bab28eedf1a6d15996
[stack/conf/vim.git] / addons / TagHighlight / autoload / TagHighlight / Libraries.vim
1 " Tag Highlighter:
2 "   Author:  A. S. Budden <abudden _at_ gmail _dot_ com>
3 " Copyright: Copyright (C) 2009-2011 A. S. Budden
4 "            Permission is hereby granted to use and distribute this code,
5 "            with or without modifications, provided that this copyright
6 "            notice is copied with it. Like anything else that's free,
7 "            the TagHighlight plugin is provided *as is* and comes with no
8 "            warranty of any kind, either expressed or implied. By using
9 "            this plugin, you agree that in no event will the copyright
10 "            holder be liable for any damages resulting from the use
11 "            of this software.
12
13 " ---------------------------------------------------------------------
14 try
15         if &cp || v:version < 700 || (exists('g:loaded_TagHLLibraries') && (g:plugin_development_mode != 1))
16                 throw "Already loaded"
17         endif
18 catch
19         finish
20 endtry
21 let g:loaded_TagHLLibraries = 1
22
23 function! TagHighlight#Libraries#LoadLibraries()
24         if has_key(g:TagHighlightPrivate,'Libraries')
25                 " Already loaded
26                 return
27         endif
28         call TagHLDebug("Loading standard library information", "Information")
29
30         let g:TagHighlightPrivate['LibraryPath'] = g:TagHighlightPrivate['PluginPath'] . '/standard_libraries'
31         let g:TagHighlightPrivate['Libraries'] = {}
32         let library_config_files = split(glob(g:TagHighlightPrivate['LibraryPath'] . '/*/library_types.txt'), '\n')
33
34         let required_keys = ["LibraryName","TypesFiles","CheckMode","TypesSuffixes"]
35         for library_config in library_config_files
36                 call TagHLDebug("Loading information for " . library_config, "Information")
37                 let skip = 0
38                 let library_details = TagHighlight#LoadDataFile#LoadFile(library_config)
39                 for key in required_keys
40                         if ! has_key(library_details, key)
41                                 call TagHLDebug("Could not load library from " . library_config, "Warning")
42                                 let skip = 1
43                                 break
44                         endif
45                 endfor
46                 if skip
47                         continue
48                 endif
49                 " Config looks valid; check fields that should be lists are:
50                 let list_keys = ["TypesFiles","TypesSuffixes","MatchREs"]
51                 for key in list_keys
52                         if has_key(library_details,key) && type(library_details[key]) == type('')
53                                 let value = library_details[key]
54                                 unlet library_details[key]
55                                 let library_details[key] = [value]
56                         endif
57                 endfor
58                 " Store the absolute path to the all types files
59                 let library_details['TypesFileFullPaths'] = []
60                 for types_file in library_details['TypesFiles']
61                         let library_details['TypesFileFullPaths'] += [fnamemodify(library_config, ':p:h') . '/' . types_file]
62                 endfor
63
64                 " Handle some defaults
65                 if ! has_key(library_details,'MatchREs')
66                         " Default matcher will never match on any file
67                         let library_details['MatchREs'] = ['.\%^']
68                 endif
69                 if ! has_key(library_details, 'CustomFunction')
70                         " Default custom function will always return 'Skip'
71                         let library_details['CustomFunction'] = 'TagHighlight#Libraries#NeverMatch'
72                 endif
73                 if ! has_key(library_details, 'MatchLines')
74                         " Just use a suitable default value
75                         let library_details['MatchLines'] = 30
76                 endif
77                 
78                 call TagHLDebug("Loaded library: " . string(library_details), "Information")
79                 let g:TagHighlightPrivate['Libraries'][library_details['LibraryName']] = library_details
80         endfor
81 endfunction
82
83 function! TagHighlight#Libraries#FindUserLibraries()
84         " Open any explicitly configured libraries
85         call TagHLDebug("Searching for user libraries", "Information")
86         let user_library_dir = TagHighlight#Option#GetOption('UserLibraryDir')
87         let user_libraries = TagHighlight#Option#GetOption('UserLibraries')
88
89         call TagHLDebug("Library Dir: " . user_library_dir, "Information")
90         call TagHLDebug("Library List: " . string(user_libraries), "Information")
91
92         let libraries_to_load = []
93
94         for library in user_libraries
95                 " If it looks like an absolute path, just load it
96                 if (library[1] == ':' || library['0'] == '/') && filereadable(library)
97                         call TagHLDebug("User library is absolute path: " . library, "Information")
98                         let libraries_to_load +=
99                                                 \ [{
100                                                 \     'Name': 'User Library',
101                                                 \     'Filename': fnamemodify(library, ':t'),
102                                                 \     'Path': fnamemodify(library, '%:p'),
103                                                 \ }]
104                 " Otherwise, try appending to the library dir
105                 elseif filereadable(user_library_dir . '/' . library)
106                         call TagHLDebug("User library is relative path: " . library, "Information")
107                         let library_path = user_library_dir . '/' . library
108                         let libraries_to_load +=
109                                                 \ [{
110                                                 \     'Name': 'User Library',
111                                                 \     'Filename': fnamemodify(library_path, ':t'),
112                                                 \     'Path': fnamemodify(library_path, '%:p'),
113                                                 \ }]
114                 else
115                         call TagHLDebug("Cannot load user library " . library, "Error")
116                 endif
117         endfor
118         return libraries_to_load
119 endfunction
120
121 function! TagHighlight#Libraries#FindLibraryFiles(suffix)
122         " Should only actually read the libraries once
123         call TagHLDebug("Finding library files for current file with suffix " . a:suffix, "Information")
124         call TagHighlight#Libraries#LoadLibraries()
125
126         let libraries_to_load = []
127         let forced_standard_libraries = TagHighlight#Option#GetOption('ForcedStandardLibraries')
128
129         if TagHighlight#Option#GetOption('DisableStandardLibraries')
130                 call TagHLDebug("Standard library loading disabled", "Information")
131                 return []
132         endif
133
134         for library in values(g:TagHighlightPrivate['Libraries'])
135                 call TagHLDebug("Checking " . library['LibraryName'], "Information")
136                 let load = 0
137                 if index(library['TypesSuffixes'], a:suffix) != -1
138                         " Suffix is in the list of acceptable ones
139                         if index(forced_standard_libraries, library['LibraryName']) != -1
140                                 call TagHLDebug("Library(".library['LibraryName']."): Forced", "Information")
141                                 let load = 1
142                         elseif library['CheckMode'] == 'Always'
143                                 call TagHLDebug("Library(".library['LibraryName']."): Always", "Information")
144                                 let load = 1
145                         elseif library['CheckMode'] == 'MatchStart'
146                                 call TagHLDebug("Library(".library['LibraryName']."): Checking MatchStart", "Information")
147                                 for matcher in library['MatchREs']
148                                         call cursor(1,1)
149                                         if search(matcher, 'nc',library['MatchLines'])
150                                                 call TagHLDebug("Library(".library['LibraryName']."): Match!", "Information")
151                                                 let load = 1
152                                                 break
153                                         endif
154                                 endfor
155                         elseif library['CheckMode'] == 'MatchEnd'
156                                 call TagHLDebug("Library(".library['LibraryName']."): Checking MatchEnd", "Information")
157                                 for matcher in library['MatchREs']
158                                         call cursor(1000000,1000000)
159                                         if search(matcher, 'ncb', library['MatchLines'])
160                                                 call TagHLDebug("Library(".library['LibraryName']."): Match!", "Information")
161                                                 let load = 1
162                                                 break
163                                         endif
164                                 endfor
165                         elseif library['CheckMode'] == 'Custom'
166                                 call TagHLDebug("Library(".library['LibraryName']."): Custom (".library['CustomFunction'].")", "Information")
167                                 " The hope is that this won't really ever be used, but
168                                 " call the function and check that it returns the right
169                                 " kind of thing (takes suffix as parameter)
170                                 exe 'let result = ' . library['CustomFunction'] . '(' . a:suffix . ')'
171                                 if result == 'Load'
172                                         call TagHLDebug("Custom result: Load", "Information")
173                                         let load = 1
174                                 elseif result == 'Skip'
175                                         call TagHLDebug("Custom result: Skip", "Information")
176                                         " Pass
177                                 else
178                                         call TagHLDebug("Misconfigured library: custom function has invalid return value", "Critical")
179                                 endif
180                         endif
181                 endif
182                 if load
183                         for full_path in library['TypesFileFullPaths']
184                                 let libraries_to_load += 
185                                                         \ [{
186                                                         \     'Name': library['LibraryName'],
187                                                         \     'Filename': fnamemodify(full_path, ':t'),
188                                                         \     'Path': full_path,
189                                                         \ }]
190                         endfor
191                 else
192                         call TagHLDebug("No match:" . library['LibraryName'], "Information")
193                 endif
194         endfor
195
196         return libraries_to_load
197 endfunction
198
199 function! TagHighlight#Libraries#NeverMatch()
200         return 'Skip'
201 endfunction