blob: 9a1474f5efd920fc0c6a7bf45f5777684760ad77 [file] [log] [blame]
Bram Moolenaar4770d092006-01-12 23:22:24 +00001" Vim completion script
2" Language: All languages, uses existing syntax highlighting rules
Bram Moolenaar6dfc28b2010-02-11 14:19:15 +01003" Maintainer: David Fishburn <dfishburn dot vim at gmail dot com>
Bram Moolenaar97d62492012-11-15 21:28:22 +01004" Version: 10.0
5" Last Change: 2012 Oct 20
Bram Moolenaar97e8f352006-05-06 21:40:45 +00006" Usage: For detailed help, ":help ft-syntax-omni"
Bram Moolenaar4770d092006-01-12 23:22:24 +00007
Bram Moolenaar6dfc28b2010-02-11 14:19:15 +01008" History
Bram Moolenaar40af4e32010-07-29 22:33:18 +02009"
Bram Moolenaar97d62492012-11-15 21:28:22 +010010" Version 10.0
11" Cycle through all the character ranges specified in the
12" iskeyword option and build a list of valid word separators.
13" Prior to this change, only actual characters were used,
14" where for example ASCII "45" == "-". If "45" were used
15" in iskeyword the hyphen would not be picked up.
16" This introduces a new option, since the character ranges
17" specified could be multibyte:
18" let g:omni_syntax_use_single_byte = 1
19" This by default will only allow single byte ASCII
20" characters to be added and an additional check to ensure
21" the charater is printable (see documentation for isprint).
22"
23" Version 9.0
24" Add the check for cpo.
25"
Bram Moolenaarf1568ec2011-12-14 21:17:39 +010026" Version 8.0
27" Updated SyntaxCSyntaxGroupItems()
28" - Some additional syntax items were also allowed
29" on nextgroup= lines which were ignored by default.
30" Now these lines are processed independently.
31"
Bram Moolenaar40af4e32010-07-29 22:33:18 +020032" Version 7.0
33" Updated syntaxcomplete#OmniSyntaxList()
34" - Looking up the syntax groups defined from a syntax file
35" looked for only 1 format of {filetype}GroupName, but some
36" syntax writers use this format as well:
37" {b:current_syntax}GroupName
38" OmniSyntaxList() will now check for both if the first
39" method does not find a match.
40"
41" Version 6.0
42" Added syntaxcomplete#OmniSyntaxList()
43" - Allows other plugins to use this for their own
44" purposes.
45" - It will return a List of all syntax items for the
46" syntax group name passed in.
47" - XPTemplate for SQL will use this function via the
48" sqlcomplete plugin to populate a Choose box.
49"
Bram Moolenaar6dfc28b2010-02-11 14:19:15 +010050" Version 5.0
Bram Moolenaar40af4e32010-07-29 22:33:18 +020051" Updated SyntaxCSyntaxGroupItems()
52" - When processing a list of syntax groups, the final group
53" was missed in function SyntaxCSyntaxGroupItems.
Bram Moolenaar6dfc28b2010-02-11 14:19:15 +010054"
Bram Moolenaar4770d092006-01-12 23:22:24 +000055" Set completion with CTRL-X CTRL-O to autoloaded function.
Bram Moolenaarc15ef302006-03-19 22:11:16 +000056" This check is in place in case this script is
57" sourced directly instead of using the autoload feature.
Bram Moolenaarc06ac342006-03-02 22:43:39 +000058if exists('+omnifunc')
Bram Moolenaarc15ef302006-03-19 22:11:16 +000059 " Do not set the option if already set since this
60 " results in an E117 warning.
61 if &omnifunc == ""
62 setlocal omnifunc=syntaxcomplete#Complete
63 endif
Bram Moolenaar4770d092006-01-12 23:22:24 +000064endif
65
66if exists('g:loaded_syntax_completion')
67 finish
68endif
Bram Moolenaar97d62492012-11-15 21:28:22 +010069let g:loaded_syntax_completion = 100
70
71" Turn on support for line continuations when creating the script
72let s:cpo_save = &cpo
73set cpo&vim
Bram Moolenaar97e8f352006-05-06 21:40:45 +000074
75" Set ignorecase to the ftplugin standard
Bram Moolenaar9964e462007-05-05 17:54:07 +000076" This is the default setting, but if you define a buffer local
77" variable you can override this on a per filetype.
Bram Moolenaar97e8f352006-05-06 21:40:45 +000078if !exists('g:omni_syntax_ignorecase')
79 let g:omni_syntax_ignorecase = &ignorecase
80endif
Bram Moolenaar4770d092006-01-12 23:22:24 +000081
Bram Moolenaar9964e462007-05-05 17:54:07 +000082" Indicates whether we should use the iskeyword option to determine
83" how to split words.
84" This is the default setting, but if you define a buffer local
85" variable you can override this on a per filetype.
86if !exists('g:omni_syntax_use_iskeyword')
87 let g:omni_syntax_use_iskeyword = 1
88endif
89
Bram Moolenaar97d62492012-11-15 21:28:22 +010090" When using iskeyword, this setting controls whether the characters
91" should be limited to single byte characters.
92if !exists('g:omni_syntax_use_single_byte')
93 let g:omni_syntax_use_single_byte = 1
94endif
95
96" When using iskeyword, this setting controls whether the characters
97" should be limited to single byte characters.
98if !exists('g:omni_syntax_use_iskeyword_numeric')
99 let g:omni_syntax_use_iskeyword_numeric = 1
100endif
101
Bram Moolenaar9964e462007-05-05 17:54:07 +0000102" Only display items in the completion window that are at least
103" this many characters in length.
104" This is the default setting, but if you define a buffer local
105" variable you can override this on a per filetype.
106if !exists('g:omni_syntax_minimum_length')
107 let g:omni_syntax_minimum_length = 0
108endif
109
Bram Moolenaar4770d092006-01-12 23:22:24 +0000110" This script will build a completion list based on the syntax
111" elements defined by the files in $VIMRUNTIME/syntax.
Bram Moolenaar4770d092006-01-12 23:22:24 +0000112let s:syn_remove_words = 'match,matchgroup=,contains,'.
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100113 \ 'links to,start=,end='
114 " \ 'links to,start=,end=,nextgroup='
Bram Moolenaar4770d092006-01-12 23:22:24 +0000115
116let s:cache_name = []
117let s:cache_list = []
Bram Moolenaarc15ef302006-03-19 22:11:16 +0000118let s:prepended = ''
Bram Moolenaar4770d092006-01-12 23:22:24 +0000119
120" This function is used for the 'omnifunc' option.
121function! syntaxcomplete#Complete(findstart, base)
122
Bram Moolenaar9964e462007-05-05 17:54:07 +0000123 " Only display items in the completion window that are at least
124 " this many characters in length
125 if !exists('b:omni_syntax_ignorecase')
126 if exists('g:omni_syntax_ignorecase')
127 let b:omni_syntax_ignorecase = g:omni_syntax_ignorecase
128 else
129 let b:omni_syntax_ignorecase = &ignorecase
130 endif
131 endif
132
Bram Moolenaar4770d092006-01-12 23:22:24 +0000133 if a:findstart
134 " Locate the start of the item, including "."
135 let line = getline('.')
136 let start = col('.') - 1
137 let lastword = -1
138 while start > 0
Bram Moolenaar9964e462007-05-05 17:54:07 +0000139 " if line[start - 1] =~ '\S'
140 " let start -= 1
141 " elseif line[start - 1] =~ '\.'
142 if line[start - 1] =~ '\k'
Bram Moolenaar4770d092006-01-12 23:22:24 +0000143 let start -= 1
Bram Moolenaar9964e462007-05-05 17:54:07 +0000144 let lastword = a:findstart
Bram Moolenaar4770d092006-01-12 23:22:24 +0000145 else
146 break
147 endif
148 endwhile
149
150 " Return the column of the last word, which is going to be changed.
151 " Remember the text that comes before it in s:prepended.
152 if lastword == -1
153 let s:prepended = ''
154 return start
155 endif
Bram Moolenaar9964e462007-05-05 17:54:07 +0000156 let s:prepended = strpart(line, start, (col('.') - 1) - start)
157 return start
Bram Moolenaar4770d092006-01-12 23:22:24 +0000158 endif
159
Bram Moolenaar9964e462007-05-05 17:54:07 +0000160 " let base = s:prepended . a:base
161 let base = s:prepended
Bram Moolenaar4770d092006-01-12 23:22:24 +0000162
Bram Moolenaar97e8f352006-05-06 21:40:45 +0000163 let filetype = substitute(&filetype, '\.', '_', 'g')
164 let list_idx = index(s:cache_name, filetype, 0, &ignorecase)
Bram Moolenaar4770d092006-01-12 23:22:24 +0000165 if list_idx > -1
166 let compl_list = s:cache_list[list_idx]
167 else
Bram Moolenaar97e8f352006-05-06 21:40:45 +0000168 let compl_list = OmniSyntaxList()
169 let s:cache_name = add( s:cache_name, filetype )
170 let s:cache_list = add( s:cache_list, compl_list )
Bram Moolenaar4770d092006-01-12 23:22:24 +0000171 endif
172
173 " Return list of matches.
174
Bram Moolenaar9964e462007-05-05 17:54:07 +0000175 if base != ''
176 " let compstr = join(compl_list, ' ')
177 " let expr = (b:omni_syntax_ignorecase==0?'\C':'').'\<\%('.base.'\)\@!\w\+\s*'
178 " let compstr = substitute(compstr, expr, '', 'g')
179 " let compl_list = split(compstr, '\s\+')
180
181 " Filter the list based on the first few characters the user
182 " entered
183 let expr = 'v:val '.(g:omni_syntax_ignorecase==1?'=~?':'=~#')." '^".escape(base, '\\/.*$^~[]').".*'"
184 let compl_list = filter(deepcopy(compl_list), expr)
Bram Moolenaar4770d092006-01-12 23:22:24 +0000185 endif
186
187 return compl_list
188endfunc
189
Bram Moolenaar40af4e32010-07-29 22:33:18 +0200190function! syntaxcomplete#OmniSyntaxList(...)
191 if a:0 > 0
192 let parms = []
193 if 3 == type(a:1)
194 let parms = a:1
195 elseif 1 == type(a:1)
196 let parms = split(a:1, ',')
197 endif
198 return OmniSyntaxList( parms )
199 else
200 return OmniSyntaxList()
201 endif
202endfunc
203
204function! OmniSyntaxList(...)
205 let list_parms = []
206 if a:0 > 0
207 if 3 == type(a:1)
208 let list_parms = a:1
209 elseif 1 == type(a:1)
210 let list_parms = split(a:1, ',')
211 endif
212 endif
213
Bram Moolenaar97e8f352006-05-06 21:40:45 +0000214 " Default to returning a dictionary, if use_dictionary is set to 0
215 " a list will be returned.
216 " let use_dictionary = 1
217 " if a:0 > 0 && a:1 != ''
218 " let use_dictionary = a:1
219 " endif
220
Bram Moolenaar9964e462007-05-05 17:54:07 +0000221 " Only display items in the completion window that are at least
222 " this many characters in length
223 if !exists('b:omni_syntax_use_iskeyword')
224 if exists('g:omni_syntax_use_iskeyword')
225 let b:omni_syntax_use_iskeyword = g:omni_syntax_use_iskeyword
226 else
227 let b:omni_syntax_use_iskeyword = 1
228 endif
229 endif
230
231 " Only display items in the completion window that are at least
232 " this many characters in length
233 if !exists('b:omni_syntax_minimum_length')
234 if exists('g:omni_syntax_minimum_length')
235 let b:omni_syntax_minimum_length = g:omni_syntax_minimum_length
236 else
237 let b:omni_syntax_minimum_length = 0
238 endif
239 endif
240
Bram Moolenaar4770d092006-01-12 23:22:24 +0000241 let saveL = @l
Bram Moolenaar40af4e32010-07-29 22:33:18 +0200242 let filetype = substitute(&filetype, '\.', '_', 'g')
Bram Moolenaar4770d092006-01-12 23:22:24 +0000243
Bram Moolenaar40af4e32010-07-29 22:33:18 +0200244 if empty(list_parms)
245 " Default the include group to include the requested syntax group
246 let syntax_group_include_{filetype} = ''
247 " Check if there are any overrides specified for this filetype
248 if exists('g:omni_syntax_group_include_'.filetype)
249 let syntax_group_include_{filetype} =
250 \ substitute( g:omni_syntax_group_include_{filetype},'\s\+','','g')
251 let list_parms = split(g:omni_syntax_group_include_{filetype}, ',')
252 if syntax_group_include_{filetype} =~ '\w'
253 let syntax_group_include_{filetype} =
254 \ substitute( syntax_group_include_{filetype},
255 \ '\s*,\s*', '\\|', 'g'
256 \ )
257 endif
258 endif
259 else
260 " A specific list was provided, use it
261 endif
262
Bram Moolenaar4770d092006-01-12 23:22:24 +0000263 " Loop through all the syntax groupnames, and build a
264 " syntax file which contains these names. This can
265 " work generically for any filetype that does not already
266 " have a plugin defined.
267 " This ASSUMES the syntax groupname BEGINS with the name
Bram Moolenaarc06ac342006-03-02 22:43:39 +0000268 " of the filetype. From my casual viewing of the vim7\syntax
Bram Moolenaar40af4e32010-07-29 22:33:18 +0200269 " directory this is true for almost all syntax definitions.
270 " As an example, the SQL syntax groups have this pattern:
271 " sqlType
272 " sqlOperators
273 " sqlKeyword ...
Bram Moolenaar4770d092006-01-12 23:22:24 +0000274 redir @l
Bram Moolenaar40af4e32010-07-29 22:33:18 +0200275 silent! exec 'syntax list '.join(list_parms)
Bram Moolenaar4770d092006-01-12 23:22:24 +0000276 redir END
277
Bram Moolenaarc06ac342006-03-02 22:43:39 +0000278 let syntax_full = "\n".@l
Bram Moolenaar4770d092006-01-12 23:22:24 +0000279 let @l = saveL
280
Bram Moolenaarc06ac342006-03-02 22:43:39 +0000281 if syntax_full =~ 'E28'
282 \ || syntax_full =~ 'E411'
283 \ || syntax_full =~ 'E415'
284 \ || syntax_full =~ 'No Syntax items'
285 return []
Bram Moolenaar4770d092006-01-12 23:22:24 +0000286 endif
287
Bram Moolenaar97e8f352006-05-06 21:40:45 +0000288 let filetype = substitute(&filetype, '\.', '_', 'g')
289
Bram Moolenaar40af4e32010-07-29 22:33:18 +0200290 let list_exclude_groups = []
291 if a:0 > 0
292 " Do nothing since we have specific a specific list of groups
293 else
294 " Default the exclude group to nothing
295 let syntax_group_exclude_{filetype} = ''
296 " Check if there are any overrides specified for this filetype
297 if exists('g:omni_syntax_group_exclude_'.filetype)
298 let syntax_group_exclude_{filetype} =
299 \ substitute( g:omni_syntax_group_exclude_{filetype},'\s\+','','g')
300 let list_exclude_groups = split(g:omni_syntax_group_exclude_{filetype}, ',')
301 if syntax_group_exclude_{filetype} =~ '\w'
302 let syntax_group_exclude_{filetype} =
303 \ substitute( syntax_group_exclude_{filetype},
304 \ '\s*,\s*', '\\|', 'g'
305 \ )
306 endif
Bram Moolenaarc06ac342006-03-02 22:43:39 +0000307 endif
308 endif
309
Bram Moolenaar97e8f352006-05-06 21:40:45 +0000310 " Sometimes filetypes can be composite names, like c.doxygen
311 " Loop through each individual part looking for the syntax
312 " items specific to each individual filetype.
Bram Moolenaar4770d092006-01-12 23:22:24 +0000313 let syn_list = ''
Bram Moolenaar97e8f352006-05-06 21:40:45 +0000314 let ftindex = 0
315 let ftindex = match(&filetype, '\w\+', ftindex)
Bram Moolenaar4770d092006-01-12 23:22:24 +0000316
Bram Moolenaar97e8f352006-05-06 21:40:45 +0000317 while ftindex > -1
318 let ft_part_name = matchstr( &filetype, '\w\+', ftindex )
Bram Moolenaar4770d092006-01-12 23:22:24 +0000319
Bram Moolenaar97e8f352006-05-06 21:40:45 +0000320 " Syntax rules can contain items for more than just the current
321 " filetype. They can contain additional items added by the user
322 " via autocmds or their vimrc.
323 " Some syntax files can be combined (html, php, jsp).
324 " We want only items that begin with the filetype we are interested in.
325 let next_group_regex = '\n' .
326 \ '\zs'.ft_part_name.'\w\+\ze'.
327 \ '\s\+xxx\s\+'
328 let index = 0
329 let index = match(syntax_full, next_group_regex, index)
330
Bram Moolenaar40af4e32010-07-29 22:33:18 +0200331 if index == -1 && exists('b:current_syntax') && ft_part_name != b:current_syntax
332 " There appears to be two standards when writing syntax files.
333 " Either items begin as:
334 " syn keyword {filetype}Keyword values ...
335 " let b:current_syntax = "sql"
336 " let b:current_syntax = "sqlanywhere"
337 " Or
338 " syn keyword {syntax_filename}Keyword values ...
339 " let b:current_syntax = "mysql"
340 " So, we will make the format of finding the syntax group names
341 " a bit more flexible and look for both if the first fails to
342 " find a match.
343 let next_group_regex = '\n' .
344 \ '\zs'.b:current_syntax.'\w\+\ze'.
345 \ '\s\+xxx\s\+'
346 let index = 0
347 let index = match(syntax_full, next_group_regex, index)
348 endif
349
Bram Moolenaar97e8f352006-05-06 21:40:45 +0000350 while index > -1
351 let group_name = matchstr( syntax_full, '\w\+', index )
352
353 let get_syn_list = 1
Bram Moolenaar40af4e32010-07-29 22:33:18 +0200354 for exclude_group_name in list_exclude_groups
355 if '\<'.exclude_group_name.'\>' =~ '\<'.group_name.'\>'
356 let get_syn_list = 0
357 endif
358 endfor
359
360 " This code is no longer needed in version 6.0 since we have
361 " augmented the syntax list command to only retrieve the syntax
362 " groups we are interested in.
363 "
364 " if get_syn_list == 1
365 " if syntax_group_include_{filetype} != ''
366 " if '\<'.syntax_group_include_{filetype}.'\>' !~ '\<'.group_name.'\>'
Bram Moolenaar97e8f352006-05-06 21:40:45 +0000367 " let get_syn_list = 0
368 " endif
369 " endif
Bram Moolenaar97e8f352006-05-06 21:40:45 +0000370 " endif
Bram Moolenaar4770d092006-01-12 23:22:24 +0000371
Bram Moolenaar97e8f352006-05-06 21:40:45 +0000372 if get_syn_list == 1
373 " Pass in the full syntax listing, plus the group name we
374 " are interested in.
375 let extra_syn_list = s:SyntaxCSyntaxGroupItems(group_name, syntax_full)
Bram Moolenaar97e8f352006-05-06 21:40:45 +0000376 let syn_list = syn_list . extra_syn_list . "\n"
377 endif
378
379 let index = index + strlen(group_name)
380 let index = match(syntax_full, next_group_regex, index)
381 endwhile
382
383 let ftindex = ftindex + len(ft_part_name)
384 let ftindex = match( &filetype, '\w\+', ftindex )
Bram Moolenaar4770d092006-01-12 23:22:24 +0000385 endwhile
386
Bram Moolenaarc06ac342006-03-02 22:43:39 +0000387 " Convert the string to a List and sort it.
388 let compl_list = sort(split(syn_list))
389
390 if &filetype == 'vim'
391 let short_compl_list = []
392 for i in range(len(compl_list))
393 if i == len(compl_list)-1
394 let next = i
395 else
396 let next = i + 1
397 endif
398 if compl_list[next] !~ '^'.compl_list[i].'.$'
399 let short_compl_list += [compl_list[i]]
400 endif
401 endfor
402
403 return short_compl_list
404 else
405 return compl_list
406 endif
Bram Moolenaar4770d092006-01-12 23:22:24 +0000407endfunction
408
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000409function! s:SyntaxCSyntaxGroupItems( group_name, syntax_full )
Bram Moolenaar4770d092006-01-12 23:22:24 +0000410
Bram Moolenaarc06ac342006-03-02 22:43:39 +0000411 let syn_list = ""
412
413 " From the full syntax listing, strip out the portion for the
414 " request group.
415 " Query:
416 " \n - must begin with a newline
417 " a:group_name - the group name we are interested in
418 " \s\+xxx\s\+ - group names are always followed by xxx
419 " \zs - start the match
420 " .\{-} - everything ...
421 " \ze - end the match
Bram Moolenaar6dfc28b2010-02-11 14:19:15 +0100422 " \( - start a group or 2 potential matches
Bram Moolenaarc06ac342006-03-02 22:43:39 +0000423 " \n\w - at the first newline starting with a character
Bram Moolenaar6dfc28b2010-02-11 14:19:15 +0100424 " \| - 2nd potential match
425 " \%$ - matches end of the file or string
426 " \) - end a group
Bram Moolenaarc06ac342006-03-02 22:43:39 +0000427 let syntax_group = matchstr(a:syntax_full,
Bram Moolenaar6dfc28b2010-02-11 14:19:15 +0100428 \ "\n".a:group_name.'\s\+xxx\s\+\zs.\{-}\ze\(\n\w\|\%$\)'
Bram Moolenaar97e8f352006-05-06 21:40:45 +0000429 \ )
Bram Moolenaarc06ac342006-03-02 22:43:39 +0000430
431 if syntax_group != ""
Bram Moolenaar4770d092006-01-12 23:22:24 +0000432 " let syn_list = substitute( @l, '^.*xxx\s*\%(contained\s*\)\?', "", '' )
Bram Moolenaarc06ac342006-03-02 22:43:39 +0000433 " let syn_list = substitute( @l, '^.*xxx\s*', "", '' )
Bram Moolenaar4770d092006-01-12 23:22:24 +0000434
435 " We only want the words for the lines begining with
436 " containedin, but there could be other items.
437
438 " Tried to remove all lines that do not begin with contained
439 " but this does not work in all cases since you can have
440 " contained nextgroup=...
441 " So this will strip off the ending of lines with known
442 " keywords.
Bram Moolenaar97e8f352006-05-06 21:40:45 +0000443 let syn_list = substitute(
444 \ syntax_group, '\<\('.
445 \ substitute(
446 \ escape(s:syn_remove_words, '\\/.*$^~[]')
447 \ , ',', '\\|', 'g'
448 \ ).
449 \ '\).\{-}\%($\|'."\n".'\)'
450 \ , "\n", 'g'
451 \ )
Bram Moolenaar4770d092006-01-12 23:22:24 +0000452
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100453 " Now strip off the newline + blank space + contained.
454 " Also include lines with nextgroup=@someName skip_key_words syntax_element
Bram Moolenaar97e8f352006-05-06 21:40:45 +0000455 let syn_list = substitute(
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100456 \ syn_list, '\%(^\|\n\)\@<=\s*\<\(contained\|nextgroup=\)'
457 \ , "", 'g'
458 \ )
459
460 " This can leave lines like this
461 " =@vimMenuList skipwhite onoremenu
462 " Strip the special option keywords first
463 " :h :syn-skipwhite*
464 let syn_list = substitute(
465 \ syn_list, '\<\(skipwhite\|skipnl\|skipempty\)\>'
466 \ , "", 'g'
467 \ )
468
469 " Now remove the remainder of the nextgroup=@someName lines
470 let syn_list = substitute(
471 \ syn_list, '\%(^\|\n\)\@<=\s*\(@\w\+\)'
Bram Moolenaar97e8f352006-05-06 21:40:45 +0000472 \ , "", 'g'
473 \ )
Bram Moolenaar4770d092006-01-12 23:22:24 +0000474
Bram Moolenaar9964e462007-05-05 17:54:07 +0000475 if b:omni_syntax_use_iskeyword == 0
476 " There are a number of items which have non-word characters in
477 " them, *'T_F1'*. vim.vim is one such file.
478 " This will replace non-word characters with spaces.
479 let syn_list = substitute( syn_list, '[^0-9A-Za-z_ ]', ' ', 'g' )
480 else
Bram Moolenaar97d62492012-11-15 21:28:22 +0100481 if g:omni_syntax_use_iskeyword_numeric == 1
482 " iskeyword can contain value like this
483 " 38,42,43,45,47-58,60-62,64-90,97-122,_,+,-,*,/,%,<,=,>,:,$,?,!,@-@,94
484 " Numeric values convert to their ASCII equivalent using the
485 " nr2char() function.
486 " & 38
487 " * 42
488 " + 43
489 " - 45
490 " ^ 94
491 " Iterate through all numeric specifications and convert those
492 " to their ascii equivalent ensuring the character is printable.
493 " If so, add it to the list.
494 let accepted_chars = ''
495 for item in split(&iskeyword, ',')
496 if item =~ '-'
497 " This is a character range (ie 47-58),
498 " cycle through each character within the range
499 let [b:start, b:end] = split(item, '-')
500 for range_item in range( b:start, b:end )
501 if range_item <= 127 || g:omni_syntax_use_single_byte == 0
502 if nr2char(range_item) =~ '\p'
503 let accepted_chars = accepted_chars . nr2char(range_item)
504 endif
505 endif
506 endfor
507 elseif item =~ '^\d\+$'
508 " Only numeric, translate to a character
509 if item < 127 || g:omni_syntax_use_single_byte == 0
510 if nr2char(item) =~ '\p'
511 let accepted_chars = accepted_chars . nr2char(item)
512 endif
513 endif
514 else
515 if char2nr(item) < 127 || g:omni_syntax_use_single_byte == 0
516 if item =~ '\p'
517 let accepted_chars = accepted_chars . item
518 endif
519 endif
520 endif
521 endfor
522 " Escape special regex characters
523 let accepted_chars = escape(accepted_chars, '\\/.*$^~[]' )
524 " Remove all characters that are not acceptable
525 let syn_list = substitute( syn_list, '[^A-Za-z'.accepted_chars.']', ' ', 'g' )
526 else
527 let accept_chars = ','.&iskeyword.','
528 " Remove all character ranges
529 " let accept_chars = substitute(accept_chars, ',[^,]\+-[^,]\+,', ',', 'g')
530 let accept_chars = substitute(accept_chars, ',\@<=[^,]\+-[^,]\+,', '', 'g')
531 " Remove all numeric specifications
532 " let accept_chars = substitute(accept_chars, ',\d\{-},', ',', 'g')
533 let accept_chars = substitute(accept_chars, ',\@<=\d\{-},', '', 'g')
534 " Remove all commas
535 let accept_chars = substitute(accept_chars, ',', '', 'g')
536 " Escape special regex characters
537 let accept_chars = escape(accept_chars, '\\/.*$^~[]' )
538 " Remove all characters that are not acceptable
539 let syn_list = substitute( syn_list, '[^0-9A-Za-z_'.accept_chars.']', ' ', 'g' )
540 endif
Bram Moolenaar9964e462007-05-05 17:54:07 +0000541 endif
542
543 if b:omni_syntax_minimum_length > 0
544 " If the user specified a minimum length, enforce it
545 let syn_list = substitute(' '.syn_list.' ', ' \S\{,'.b:omni_syntax_minimum_length.'}\ze ', ' ', 'g')
546 endif
Bram Moolenaar4770d092006-01-12 23:22:24 +0000547 else
548 let syn_list = ''
549 endif
550
Bram Moolenaar4770d092006-01-12 23:22:24 +0000551 return syn_list
552endfunction
Bram Moolenaar97d62492012-11-15 21:28:22 +0100553
554function! OmniSyntaxShowChars(spec)
555 let result = []
556 for item in split(a:spec, ',')
557 if len(item) > 1
558 if item == '@-@'
559 call add(result, char2nr(item))
560 else
561 call extend(result, call('range', split(item, '-')))
562 endif
563 else
564 if item == '@' " assume this is [A-Za-z]
565 for [c1, c2] in [['A', 'Z'], ['a', 'z']]
566 call extend(result, range(char2nr(c1), char2nr(c2)))
567 endfor
568 else
569 call add(result, char2nr(item))
570 endif
571 endif
572 endfor
573 return join(map(result, 'nr2char(v:val)'), ', ')
574endfunction
575let &cpo = s:cpo_save
576unlet s:cpo_save