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
13 " ---------------------------------------------------------------------
15 if &cp || v:version < 700 || (exists('g:loaded_TagHLFind') && (g:plugin_development_mode != 1))
16 throw "Already loaded"
21 let g:loaded_TagHLFind = 1
23 " Tools for finding files. When generating the tags and types file, we need
24 " to decide where to place it. If the user has configured the mode in which
25 " everything is based on the current directory (which works well with the
26 " project plugin), the current directory is what we use. If the user wants to
27 " search up for a tags file, we can look for an existing tags file and stop
28 " when we find one, starting either from the current directory or source
29 " directory. If we don't, either use the current directory or the source file
30 " directory (configuration).
32 " It should also be possible to place the tags file in a remote location and
33 " use either the current directory, source directory or explicitly set
34 " directory for the base of the scan.
38 " [gb]:TagHighlightSettings:
39 " DefaultDirModePriority:[Explicit,UpFromCurrent,UpFromFile,CurrentDirectory,FileDirectory]
40 " TagFileDirModePriority:["Default"] or as above
41 " TypesFileDirModePriority:As tag file
42 " ConfigFileDirModePriority:As tag file
43 " DefaultDirModeSearchWildcard:'' (look for tags file) or something specific (*.uvopt)?
44 " MaxDirSearchLevels: (integer)
48 " [gb]:TagHighlightSettings:
49 " TagFileDirectory:str (NONE)
50 " TagFileName:str (tags)
51 " TypesFileDirectory:str (NONE)
52 " TypesPrefix:str (types)
53 " ProjectConfigFileName:str (taghl_config.txt)
54 " ProjectConfigFileDirectory:str (NONE)
56 function! TagHighlight#Find#LocateFile(which, suffix)
57 call TagHLDebug("Locating file " . a:which . " with suffix " . a:suffix, 'Information')
59 " a:which is 'TAGS', 'TYPES', 'CONFIG'
60 let default_priority = TagHighlight#Option#GetOption('DefaultDirModePriority')
61 call TagHLDebug("Priority: " . string(default_priority), "Information")
62 let default_search_wildcards = TagHighlight#Option#GetOption('DefaultDirModeSearchWildcards')
65 let file = expand('<afile>')
67 let file = expand('%')
71 " Suffix is ignored here
72 let filename = TagHighlight#Option#GetOption('TagFileName')
73 let search_priority = TagHighlight#Option#GetOption('TagFileDirModePriority')
74 let explicit_location = TagHighlight#Option#GetOption('TagFileDirectory')
75 let search_wildcards = TagHighlight#Option#GetOption('TagFileSearchWildcards')
76 elseif a:which == 'TYPES'
77 let filename = TagHighlight#Option#GetOption('TypesFilePrefix') . '_' .
79 \ TagHighlight#Option#GetOption('TypesFileExtension')
80 let search_priority = TagHighlight#Option#GetOption('TypesFileDirModePriority')
81 let explicit_location = TagHighlight#Option#GetOption('TypesFileDirectory')
82 let search_wildcards = TagHighlight#Option#GetOption('TypesFileSearchWildcards')
83 elseif a:which == 'CONFIG'
84 " Suffix is ignored here
85 let filename = TagHighlight#Option#GetOption('ProjectConfigFileName')
86 let search_priority = TagHighlight#Option#GetOption('ProjectConfigFileDirModePriority')
87 let explicit_location = TagHighlight#Option#GetOption('ProjectConfigFileDirectory')
88 let search_wildcards = TagHighlight#Option#GetOption('ProjectConfigFileSearchWildcards')
90 throw "Unrecognised file"
93 if search_wildcards[0] == 'Default'
94 let search_wildcards = default_search_wildcards
97 if search_priority[0] == 'Default'
98 let search_priority = default_priority
101 " Ensure there's no trailing slash on 'explicit location'
102 if explicit_location[len(explicit_location)-1] == '/'
103 let explicit_location = explicit_location[:len(explicit_location)-2]
106 " Result contains 'Found','FullPath','Directory','Filename','Exists']
109 for search_mode in search_priority
110 if search_mode == 'Explicit' && explicit_location != 'None'
111 " Use explicit location, overriding everything else
112 call TagHLDebug('Using explicit location', 'Information')
113 let result['Directory'] = explicit_location
114 let result['Filename'] = filename
115 elseif search_mode == 'UpFromCurrent'
116 " Start in the current directory and search up
117 let dir = fnamemodify('.',':p:h')
118 let result = s:ScanUp(dir, search_wildcards)
119 if has_key(result, 'Directory')
120 call TagHLDebug('Found location with UpFromCurrent', 'Information')
121 let result['Filename'] = filename
123 elseif search_mode == 'UpFromFile'
124 " Start in the directory containing the current file and search up
125 let dir = fnamemodify(file,':p:h')
126 let result = s:ScanUp(dir, search_wildcards)
127 if has_key(result, 'Directory')
128 call TagHLDebug('Found location with UpFromFile', 'Information')
129 let result['Filename'] = filename
131 elseif search_mode == 'CurrentDirectory'
132 call TagHLDebug('Using current directory: ' . fnamemodify('.', ':p:h'), 'Information')
133 let result['Directory'] = fnamemodify('.',':p:h')
134 let result['Filename'] = filename
135 elseif search_mode == 'FileDirectory'
136 call TagHLDebug('Using file directory: ' . fnamemodify(file, ':p:h'), 'Information')
137 let result['Directory'] = fnamemodify(file,':p:h')
138 let result['Filename'] = filename
140 if has_key(result, 'Directory')
141 let result['FullPath'] = result['Directory'] . '/' . result['Filename']
142 let result['Found'] = 1
143 call TagHLDebug('Found file location: ' . result['FullPath'], 'Information')
144 if filereadable(result['FullPath'])
145 call TagHLDebug('File exists', 'Information')
146 let result['Exists'] = 1
149 let expansion = split(glob(result['FullPath'], 1), '\n')
150 let wildcard_match = 0
151 if len(expansion) > 0
152 for entry in expansion
153 if filereadable(entry)
154 let result['FullPath'] = entry
155 let result['Exists'] = 1
156 let wildcard_match = 1
162 if wildcard_match == 0
163 call TagHLDebug('File does not exist', 'Information')
164 let result['Exists'] = 0
171 if ! has_key(result, 'Directory')
172 call TagHLDebug("Couldn't find path", 'Warning')
173 let result = {'Found': 0, 'Exists': 0}
179 function! s:ScanUp(dir, wildcards)
181 let max_levels = TagHighlight#Option#GetOption('MaxDirSearchLevels')
187 call TagHLDebug("Searching up from " . a:dir . " for " . string(a:wildcards), 'Information')
189 " new_dir != dir check looks for the root directory
192 let new_dir = fnamemodify(dir, ':h')
194 call TagHLDebug("Trying " . dir, "Information")
195 for wildcard in a:wildcards
196 let glob_pattern = dir
197 if glob_pattern[len(glob_pattern)-1] != '/'
198 let glob_pattern .= '/'
200 let glob_pattern .= wildcard
201 let glob_result = split(glob(glob_pattern), "\n")
202 if len(glob_result) > 0
209 call TagHLDebug("Found match: " . dir . " (" . glob_pattern . ")", "Information")
210 let result['Directory'] = dir
214 call TagHLDebug("Wildcard matches were not readable (directory?)", "Information")
222 " Check for recursion limit
224 if (max_levels > 0) && (levels >= max_levels)
225 call TagHLDebug("Hit recursion limit", "Information")
230 " Must have reached root directory
231 call TagHLDebug("Reached root directory and stopped", "Information")