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_TagHLRunPythonScript') && (g:plugin_development_mode != 1))
16 throw "Already loaded"
21 let g:loaded_TagHLRunPythonScript = 1
23 let s:python_variant = 'None'
25 " A simply python script that will try to import the print function
26 " and will fail gracefully if the python version is too old. It's
27 " unlikely that the sys.hexversion check will ever fail as if the version
28 " is older than 2.6, the import_check will have failed. I've left it in,
29 " however, in case I ever need to depend on 2.7
30 let s:version_and_future_check =
32 \ " import import_check\n" .
35 \ " vim.command('''let g:taghl_python_version = '%s' ''' % sys.version)\n" .
36 \ " if sys.hexversion < 0x02060000:\n" .
37 \ " raise ValueError('Incorrect python version')\n" .
38 \ " vim.command('let g:taghl_python_operational = 1')\n" .
42 " This script is responsible for finding a means of running the python app.
43 " If vim is compiled with python support (and we can run a simple test
44 " command), use that method. If not, but python is in the path, use it to
45 " run the script. If python is not in path, we'll have to rely on a compiled
50 let path = substitute($PATH, '\\\?;', ',', 'g')
52 let path = substitute($PATH, ':', ',', 'g')
57 function! s:RunShellCommand(args)
63 if stridx(arg, " ") != -1
64 let syscmd .= shellescape(arg)
69 call TagHLDebug(syscmd, "Information")
70 let result = system(syscmd)
75 function! TagHighlight#RunPythonScript#RunGenerator(options)
76 " Will only actually load the options once
77 call TagHighlight#Option#LoadOptions()
79 " This will only search for python the first time or if
80 " the variant priority or forced variant preferences have
82 call TagHighlight#RunPythonScript#FindPython()
84 call TagHLDebug("Using variant: " .s:python_variant, "Information")
86 if index(["if_pyth","if_pyth3"], s:python_variant) != -1
87 let PY = s:python_cmd[0]
88 exe PY 'from module.utilities import TagHighlightOptionDict'
89 exe PY 'from module.worker import RunWithOptions'
90 exe PY 'options = TagHighlightOptionDict()'
91 let handled_options = []
92 " We're using the custom interpreter: create an options object
93 " All options supported by both Vim and the Python script must
94 " have VimOptionMap and CommandLineSwitches keys
95 for option in g:TagHighlightPrivate['PluginOptions']
96 if has_key(option, 'VimOptionMap') &&
97 \ has_key(option, 'CommandLineSwitches') &&
98 \ has_key(a:options, option['VimOptionMap'])
99 " We can handle this one automatically
100 let pyoption = 'options["'.option['Destination'].'"]'
101 if option['Type'] == 'bool'
102 let handled_options += [option['VimOptionMap']]
103 let value = a:options[option['VimOptionMap']]
104 if (value == 1) || (value == 'True')
105 exe PY pyoption '= True'
107 exe PY pyoption '= False'
109 elseif option['Type'] == 'string'
110 let handled_options += [option['VimOptionMap']]
111 exe PY pyoption '= r"""'.a:options[option['VimOptionMap']].'"""'
112 elseif option['Type'] == 'int'
113 let handled_options += [option['VimOptionMap']]
114 exe PY pyoption '= ' . a:options[option['VimOptionMap']]
115 elseif option['Type'] == 'list'
116 let handled_options += [option['VimOptionMap']]
117 exe PY pyoption '= []'
118 for entry in a:options[option['VimOptionMap']]
119 exe PY pyoption '+= [r"""' . entry . '"""]'
124 for check_opt in keys(a:options)
125 if index(handled_options, check_opt) == -1
126 call TagHLDebug("Unhandled run option: " . check_opt, "Information")
129 exe PY 'RunWithOptions(options)'
130 elseif index(["python","compiled"], s:python_variant) != -1
131 let args = s:python_cmd[:]
132 " We're calling the script externally, build a list of arguments
133 for option in g:TagHighlightPrivate['PluginOptions']
134 if has_key(option, 'VimOptionMap') &&
135 \ has_key(option, 'CommandLineSwitches') &&
136 \ has_key(a:options, option['VimOptionMap'])
137 if type(option['CommandLineSwitches']) == type([])
138 let switch = option['CommandLineSwitches'][0]
140 let switch = option['CommandLineSwitches']
142 if switch[:1] == "--"
144 elseif switch[:0] == "-"
147 call TagHLDebug("Invalid configuration for option " . option['VimOptionMap'], "Error")
149 " We can handle this one automatically
150 if option['Type'] == 'bool'
151 if (a:options[option['VimOptionMap']] == 1) || (a:options[option['VimOptionMap']] == 'True')
156 if (((bvalue == 1) && option['Default'] == 'False')
157 \ || ((bvalue == 0) && option['Default'] == 'True'))
160 elseif option['Type'] == 'string'
162 let args += [switch . '=' . a:options[option['VimOptionMap']]]
164 let args += [switch, a:options[option['VimOptionMap']]]
166 elseif option['Type'] == 'int'
168 let args += [switch . '=' . a:options[option['VimOptionMap']]]
170 let args += [switch, a:options[option['VimOptionMap']]]
172 elseif option['Type'] == 'list'
173 for entry in a:options[option['VimOptionMap']]
175 let args += [switch . '=' . entry]
177 let args += [switch, entry]
183 let sysoutput = s:RunShellCommand(args)
185 throw "Tag highlighter: invalid or not implemented python variant"
189 function! TagHighlight#RunPythonScript#FindExeInPath(file)
190 let full_file = a:file
191 if has("win32") || has("win32unix")
193 let full_file = a:file . '.exe.'
196 let short_file = fnamemodify(full_file, ':p:t')
197 let file_exe_list = split(globpath(s:GetPath(), short_file, 1), '\n')
199 if len(file_exe_list) > 0 && executable(file_exe_list[0])
200 let file_exe = file_exe_list[0]
204 "let file_exe = substitute(file_exe, '\\', '/', 'g')
208 function! TagHighlight#RunPythonScript#FindPython()
209 let forced_variant = TagHighlight#Option#GetOption('ForcedPythonVariant')
211 let supported_variants = ['if_pyth3', 'if_pyth', 'python', 'compiled']
212 " Priority of those variants (default is that specified above)
213 let variant_priority = TagHighlight#Option#GetOption('PythonVariantPriority')
215 " If we've run before and nothing has changed, just return
216 if s:python_variant != 'None'
217 if forced_variant == s:stored_forced_variant
218 \ && s:stored_variant_priority == variant_priority
219 \ && s:python_path == TagHighlight#Option#GetOption("PathToPython")
220 return s:python_variant
224 let s:python_variant = 'None'
225 let s:python_version = 'Unknown'
226 let s:python_cmd = []
227 let s:python_path = ""
229 " Make sure that the user specified variant is supported
230 if index(supported_variants, forced_variant) == -1
231 let forced_variant = 'None'
234 let s:stored_forced_variant = forced_variant
235 let s:stored_variant_priority = variant_priority
237 let add_to_py_path = substitute(g:TagHighlightPrivate['PluginPath'], '\\', '/','g')
239 " Make sure that all variants in the priority list are supported
240 call filter(variant_priority, 'index(supported_variants, v:val) != -1')
242 " Try each variant in the priority list until we find one that works
243 for variant in variant_priority
244 if forced_variant == variant || forced_variant == 'None'
245 try " Fix for bug in Vim versions before 7.3-388
246 if variant == 'if_pyth3' && has('python3')
247 " Check whether the python 3 interface works
248 let g:taghl_findpython_testvar = 0
251 exe 'py3 sys.path = ["'.add_to_py_path.'"] + sys.path'
252 let g:taghl_python_operational = 0
253 exe 'py3' s:version_and_future_check
256 if g:taghl_python_operational != 1
257 throw "Python doesn't seem to be working"
259 let s:python_version = g:taghl_python_version
260 unlet g:taghl_python_operational
261 unlet g:taghl_python_version
263 " If we got this far, it should be working
264 let s:python_variant = 'if_pyth3'
265 let s:python_cmd = ['py3']
267 call TagHLDebug("Cannot use python3 interface", "Status")
269 elseif variant == 'if_pyth' && has('python')
270 " Check whether the python 2 interface works
271 let g:taghl_findpython_testvar = 0
274 exe 'py sys.path = ["'.add_to_py_path.'"] + sys.path'
275 let g:taghl_python_operational = 0
276 exe 'py' s:version_and_future_check
279 if g:taghl_python_operational != 1
280 throw "Python doesn't seem to be working"
282 let s:python_version = g:taghl_python_version
283 unlet g:taghl_python_operational
284 unlet g:taghl_python_version
286 " If we got this far, it should be working
287 let s:python_variant = 'if_pyth'
288 let s:python_cmd = ['py']
290 call TagHLDebug("Cannot use python2 interface", "Status")
292 elseif variant == 'python'
293 " Try calling an external python
295 " Has a specific path to python been set?
296 let python_path = TagHighlight#Option#GetOption('PathToPython')
297 if python_path != 'None' && executable(python_path)
298 " We've found python, it's probably usable
299 let s:python_variant = 'python'
300 let s:python_path = python_path
301 let s:python_cmd = [python_path, g:TagHighlightPrivate['PluginPath'] . '/TagHighlight.py']
303 " See if it's in the path
304 let python_path = TagHighlight#RunPythonScript#FindExeInPath('python')
305 if python_path != 'None'
306 let s:python_variant = 'python'
307 let s:python_path = python_path
308 let s:python_cmd = [python_path, g:TagHighlightPrivate['PluginPath'] . '/TagHighlight.py']
312 " Now run some simple test code to make sure it works correctly and
313 " is a reasonable version
314 let result = s:RunShellCommand([s:python_path, g:TagHighlightPrivate['PluginPath'] . '/version_check.py'])
315 let lines = split(result, '\n')
316 let s:python_version = lines[1]
318 let s:python_variant = 'None'
319 let s:python_path = ''
320 let s:python_cmd = []
322 elseif variant == 'compiled'
323 " See if there's a compiled executable version of the
326 let compiled_highlighter = split(globpath(&rtp, "plugin/TagHighlight/Compiled/Win32/TagHighlight.exe", 1), "\n")
327 if len(compiled_highlighter) > 0 && executable(compiled_highlighter[0])
328 let s:python_variant = 'compiled'
329 let s:python_version = 'Compiled Highlighter'
330 let s:python_cmd = [compiled_highlighter[0]]
333 let compiled_highlighter = split(globpath(&rtp, "plugin/TagHighlight/Compiled/Linux/TagHighlight"), "\n")
334 if len(compiled_highlighter) > 0 && executable(compiled_highlighter[0])
335 let s:python_variant = 'compiled'
336 let s:python_version = 'Compiled Highlighter'
337 let s:python_cmd = [compiled_highlighter[0]]
341 catch /^Vim\%((\a\+)\)\=:E83[67]/
342 call TagHLDebug("Attempted to use conflicting pythons in pre-7.3-288 Vim", "Status")
346 if s:python_variant != 'None'
352 if s:python_variant != 'None'
353 call TagHLDebug("Python variant is " . s:python_variant, "Information")
354 call TagHLDebug("Python Command is " . join(s:python_cmd, " "), "Information")
355 call TagHLDebug("Python Path is " . s:python_path, "Information")
356 call TagHLDebug("Python version reported as: " . s:python_version,
359 throw "Tag highlighter: could not find python (2.6+) or the compiled version of the highlighter."
362 return s:python_variant