Install vim74
[msysgit.git] / share / vim / vim74 / autoload / syntaxcomplete.vim
bloba18c3c360c02dfe20da020c2f624cd7a0d6094e8
1 " Vim completion script
2 " Language:    All languages, uses existing syntax highlighting rules
3 " Maintainer:  David Fishburn <dfishburn dot vim at gmail dot com>
4 " Version:     13.0
5 " Last Change: 2013 May 14
6 " Usage:       For detailed help, ":help ft-syntax-omni"
8 " History
10 " Version 13.0
11 "   - Extended the option omni_syntax_group_include_{filetype}
12 "     to accept a comma separated list of regex's rather than
13 "     string.  For example, for the javascript filetype you could
14 "     use:
15 "        let g:omni_syntax_group_include_javascript = 'javascript\w\+,jquery\w\+'
16 "   - Some syntax files (perl.vim) use the match // syntax as a mechanism
17 "     to identify keywords.  This update attempts to parse the
18 "     match syntax and pull out syntax items which are at least
19 "     3 words or more.
21 " Version 12.0
22 "   - It is possible to have '-' as part of iskeyword, when
23 "     checking for character ranges, tighten up the regex.
24 "     E688: More targets than List items.
26 " Version 11.0
27 "   - Corrected which characters required escaping during
28 "     substitution calls.
30 " Version 10.0
31 "   - Cycle through all the character ranges specified in the
32 "     iskeyword option and build a list of valid word separators.
33 "     Prior to this change, only actual characters were used,
34 "     where for example ASCII "45" == "-".  If "45" were used
35 "     in iskeyword the hyphen would not be picked up.
36 "     This introduces a new option, since the character ranges
37 "     specified could be multibyte:
38 "         let g:omni_syntax_use_single_byte = 1
39 "   - This by default will only allow single byte ASCII
40 "     characters to be added and an additional check to ensure
41 "     the charater is printable (see documentation for isprint).
43 " Version 9.0
44 "   - Add the check for cpo.
46 " Version 8.0
47 "   - Updated SyntaxCSyntaxGroupItems()
48 "         - Some additional syntax items were also allowed
49 "           on nextgroup= lines which were ignored by default.
50 "           Now these lines are processed independently.
52 " Version 7.0
53 "   - Updated syntaxcomplete#OmniSyntaxList()
54 "         - Looking up the syntax groups defined from a syntax file
55 "           looked for only 1 format of {filetype}GroupName, but some
56 "           syntax writers use this format as well:
57 "               {b:current_syntax}GroupName
58 "   -       OmniSyntaxList() will now check for both if the first
59 "           method does not find a match.
61 " Version 6.0
62 "   - Added syntaxcomplete#OmniSyntaxList()
63 "         - Allows other plugins to use this for their own
64 "           purposes.
65 "         - It will return a List of all syntax items for the
66 "           syntax group name passed in.
67 "         - XPTemplate for SQL will use this function via the
68 "           sqlcomplete plugin to populate a Choose box.
70 " Version 5.0
71 "   - Updated SyntaxCSyntaxGroupItems()
72 "         - When processing a list of syntax groups, the final group
73 "           was missed in function SyntaxCSyntaxGroupItems.
75 " Set completion with CTRL-X CTRL-O to autoloaded function.
76 " This check is in place in case this script is
77 " sourced directly instead of using the autoload feature.
78 if exists('+omnifunc')
79     " Do not set the option if already set since this
80     " results in an E117 warning.
81     if &omnifunc == ""
82         setlocal omnifunc=syntaxcomplete#Complete
83     endif
84 endif
86 if exists('g:loaded_syntax_completion')
87     finish
88 endif
89 let g:loaded_syntax_completion = 130
91 " Turn on support for line continuations when creating the script
92 let s:cpo_save = &cpo
93 set cpo&vim
95 " Set ignorecase to the ftplugin standard
96 " This is the default setting, but if you define a buffer local
97 " variable you can override this on a per filetype.
98 if !exists('g:omni_syntax_ignorecase')
99     let g:omni_syntax_ignorecase = &ignorecase
100 endif
102 " Indicates whether we should use the iskeyword option to determine
103 " how to split words.
104 " This is the default setting, but if you define a buffer local
105 " variable you can override this on a per filetype.
106 if !exists('g:omni_syntax_use_iskeyword')
107     let g:omni_syntax_use_iskeyword = 1
108 endif
110 " When using iskeyword, this setting controls whether the characters
111 " should be limited to single byte characters.
112 if !exists('g:omni_syntax_use_single_byte')
113     let g:omni_syntax_use_single_byte = 1
114 endif
116 " When using iskeyword, this setting controls whether the characters
117 " should be limited to single byte characters.
118 if !exists('g:omni_syntax_use_iskeyword_numeric')
119     let g:omni_syntax_use_iskeyword_numeric = 1
120 endif
122 " Only display items in the completion window that are at least
123 " this many characters in length.
124 " This is the default setting, but if you define a buffer local
125 " variable you can override this on a per filetype.
126 if !exists('g:omni_syntax_minimum_length')
127     let g:omni_syntax_minimum_length = 0
128 endif
130 " This script will build a completion list based on the syntax
131 " elements defined by the files in $VIMRUNTIME/syntax.
132 " let s:syn_remove_words = 'match,matchgroup=,contains,'.
133 let s:syn_remove_words = 'matchgroup=,contains,'.
134             \ 'links to,start=,end='
135             " \ 'links to,start=,end=,nextgroup='
137 let s:cache_name = []
138 let s:cache_list = []
139 let s:prepended  = ''
141 " This function is used for the 'omnifunc' option.
142 function! syntaxcomplete#Complete(findstart, base)
144     " Only display items in the completion window that are at least
145     " this many characters in length
146     if !exists('b:omni_syntax_ignorecase')
147         if exists('g:omni_syntax_ignorecase')
148             let b:omni_syntax_ignorecase = g:omni_syntax_ignorecase
149         else
150             let b:omni_syntax_ignorecase = &ignorecase
151         endif
152     endif
154     if a:findstart
155         " Locate the start of the item, including "."
156         let line = getline('.')
157         let start = col('.') - 1
158         let lastword = -1
159         while start > 0
160             " if line[start - 1] =~ '\S'
161             "     let start -= 1
162             " elseif line[start - 1] =~ '\.'
163             if line[start - 1] =~ '\k'
164                 let start -= 1
165                 let lastword = a:findstart
166             else
167                 break
168             endif
169         endwhile
171         " Return the column of the last word, which is going to be changed.
172         " Remember the text that comes before it in s:prepended.
173         if lastword == -1
174             let s:prepended = ''
175             return start
176         endif
177         let s:prepended = strpart(line, start, (col('.') - 1) - start)
178         return start
179     endif
181     " let base = s:prepended . a:base
182     let base = s:prepended
184     let filetype = substitute(&filetype, '\.', '_', 'g')
185     let list_idx = index(s:cache_name, filetype, 0, &ignorecase)
186     if list_idx > -1
187         let compl_list = s:cache_list[list_idx]
188     else
189         let compl_list   = OmniSyntaxList()
190         let s:cache_name = add( s:cache_name,  filetype )
191         let s:cache_list = add( s:cache_list,  compl_list )
192     endif
194     " Return list of matches.
196     if base != ''
197         " let compstr    = join(compl_list, ' ')
198         " let expr       = (b:omni_syntax_ignorecase==0?'\C':'').'\<\%('.base.'\)\@!\w\+\s*'
199         " let compstr    = substitute(compstr, expr, '', 'g')
200         " let compl_list = split(compstr, '\s\+')
202         " Filter the list based on the first few characters the user
203         " entered
204         let expr = 'v:val '.(g:omni_syntax_ignorecase==1?'=~?':'=~#')." '^".escape(base, '\\/.*$^~[]').".*'"
205         let compl_list = filter(deepcopy(compl_list), expr)
206     endif
208     return compl_list
209 endfunc
211 function! syntaxcomplete#OmniSyntaxList(...)
212     if a:0 > 0
213         let parms = []
214         if 3 == type(a:1)
215             let parms = a:1
216         elseif 1 == type(a:1)
217             let parms = split(a:1, ',')
218         endif
219         return OmniSyntaxList( parms )
220     else
221         return OmniSyntaxList()
222     endif
223 endfunc
225 function! OmniSyntaxList(...)
226     let list_parms = []
227     if a:0 > 0
228         if 3 == type(a:1)
229             let list_parms = a:1
230         elseif 1 == type(a:1)
231             let list_parms = split(a:1, ',')
232         endif
233     endif
235     " Default to returning a dictionary, if use_dictionary is set to 0
236     " a list will be returned.
237     " let use_dictionary = 1
238     " if a:0 > 0 && a:1 != ''
239     "     let use_dictionary = a:1
240     " endif
242     " Only display items in the completion window that are at least
243     " this many characters in length
244     if !exists('b:omni_syntax_use_iskeyword')
245         if exists('g:omni_syntax_use_iskeyword')
246             let b:omni_syntax_use_iskeyword = g:omni_syntax_use_iskeyword
247         else
248             let b:omni_syntax_use_iskeyword = 1
249         endif
250     endif
252     " Only display items in the completion window that are at least
253     " this many characters in length
254     if !exists('b:omni_syntax_minimum_length')
255         if exists('g:omni_syntax_minimum_length')
256             let b:omni_syntax_minimum_length = g:omni_syntax_minimum_length
257         else
258             let b:omni_syntax_minimum_length = 0
259         endif
260     endif
262     let saveL = @l
263     let filetype = substitute(&filetype, '\.', '_', 'g')
265     if empty(list_parms)
266         " Default the include group to include the requested syntax group
267         let syntax_group_include_{filetype} = ''
268         " Check if there are any overrides specified for this filetype
269         if exists('g:omni_syntax_group_include_'.filetype)
270             let syntax_group_include_{filetype} =
271                         \ substitute( g:omni_syntax_group_include_{filetype},'\s\+','','g')
272             let list_parms = split(g:omni_syntax_group_include_{filetype}, ',')
273             if syntax_group_include_{filetype} =~ '\w'
274                 let syntax_group_include_{filetype} =
275                             \ substitute( syntax_group_include_{filetype},
276                             \ '\s*,\s*', '\\|', 'g'
277                             \ )
278             endif
279         endif
280     else
281         " A specific list was provided, use it
282     endif
284     " Loop through all the syntax groupnames, and build a
285     " syntax file which contains these names.  This can
286     " work generically for any filetype that does not already
287     " have a plugin defined.
288     " This ASSUMES the syntax groupname BEGINS with the name
289     " of the filetype.  From my casual viewing of the vim7\syntax
290     " directory this is true for almost all syntax definitions.
291     " As an example, the SQL syntax groups have this pattern:
292     "     sqlType
293     "     sqlOperators
294     "     sqlKeyword ...
295     if !empty(list_parms) && empty(substitute(join(list_parms), '[a-zA-Z ]', '', 'g'))
296         " If list_parms only includes word characters, use it to limit
297         " the syntax elements.
298         " If using regex syntax list will fail to find those items, so
299         " simply grab the who syntax list.
300         redir @l
301         silent! exec 'syntax list '.join(list_parms)
302         redir END
303     else
304         redir @l
305         silent! exec 'syntax list'
306         redir END
307     endif
309     let syntax_full = "\n".@l
310     let @l = saveL
312     if syntax_full =~ 'E28'
313                 \ || syntax_full =~ 'E411'
314                 \ || syntax_full =~ 'E415'
315                 \ || syntax_full =~ 'No Syntax items'
316         return []
317     endif
319     let filetype = substitute(&filetype, '\.', '_', 'g')
321     let list_exclude_groups = []
322     if a:0 > 0
323         " Do nothing since we have specific a specific list of groups
324     else
325         " Default the exclude group to nothing
326         let syntax_group_exclude_{filetype} = ''
327         " Check if there are any overrides specified for this filetype
328         if exists('g:omni_syntax_group_exclude_'.filetype)
329             let syntax_group_exclude_{filetype} =
330                         \ substitute( g:omni_syntax_group_exclude_{filetype},'\s\+','','g')
331             let list_exclude_groups = split(g:omni_syntax_group_exclude_{filetype}, ',')
332             if syntax_group_exclude_{filetype} =~ '\w'
333                 let syntax_group_exclude_{filetype} =
334                             \ substitute( syntax_group_exclude_{filetype},
335                             \ '\s*,\s*', '\\|', 'g'
336                             \ )
337             endif
338         endif
339     endif
341     if empty(list_parms)
342         let list_parms = [&filetype.'\w\+']
343     endif
345     let syn_list = ''
346     let index    = 0
347     for group_regex in list_parms
348         " Sometimes filetypes can be composite names, like c.doxygen
349         " Loop through each individual part looking for the syntax
350         " items specific to each individual filetype.
351         " let ftindex  = 0
352         " let ftindex  = match(syntax_full, group_regex, ftindex)
354         " while ftindex > -1
355             " let ft_part_name = matchstr( syntax_full, '\w\+', ftindex )
357             " Syntax rules can contain items for more than just the current
358             " filetype.  They can contain additional items added by the user
359             " via autocmds or their vimrc.
360             " Some syntax files can be combined (html, php, jsp).
361             " We want only items that begin with the filetype we are interested in.
362             let next_group_regex = '\n' .
363                         \ '\zs'.group_regex.'\ze'.
364                         \ '\s\+xxx\s\+'
365             let index    = match(syntax_full, next_group_regex, index)
367             " For the matched group name, strip off any of the regex special
368             " characters and see if we get a match with the current syntax
369             if index == -1 && exists('b:current_syntax') && substitute(group_regex, '[^a-zA-Z ]\+.*', '', 'g') !~ '^'.b:current_syntax
370                 " There appears to be two standards when writing syntax files.
371                 " Either items begin as:
372                 "     syn keyword {filetype}Keyword         values ...
373                 "     let b:current_syntax = "sql"
374                 "     let b:current_syntax = "sqlanywhere"
375                 " Or
376                 "     syn keyword {syntax_filename}Keyword  values ...
377                 "     let b:current_syntax = "mysql"
378                 " So, we will make the format of finding the syntax group names
379                 " a bit more flexible and look for both if the first fails to
380                 " find a match.
381                 let next_group_regex = '\n' .
382                             \ '\zs'.b:current_syntax.'\w\+\ze'.
383                             \ '\s\+xxx\s\+'
384                 let index    = 0
385                 let index    = match(syntax_full, next_group_regex, index)
386             endif
388             while index > -1
389                 let group_name = matchstr( syntax_full, '\w\+', index )
391                 let get_syn_list = 1
392                 for exclude_group_name in list_exclude_groups
393                     if '\<'.exclude_group_name.'\>' =~ '\<'.group_name.'\>'
394                         let get_syn_list = 0
395                     endif
396                 endfor
398                 " This code is no longer needed in version 6.0 since we have
399                 " augmented the syntax list command to only retrieve the syntax
400                 " groups we are interested in.
401                 "
402                 " if get_syn_list == 1
403                 "     if syntax_group_include_{filetype} != ''
404                 "         if '\<'.syntax_group_include_{filetype}.'\>' !~ '\<'.group_name.'\>'
405                 "             let get_syn_list = 0
406                 "         endif
407                 "     endif
408                 " endif
410                 if get_syn_list == 1
411                     " Pass in the full syntax listing, plus the group name we
412                     " are interested in.
413                     let extra_syn_list = s:SyntaxCSyntaxGroupItems(group_name, syntax_full)
414                     let syn_list = syn_list . extra_syn_list . "\n"
415                 endif
417                 let index = index + strlen(group_name)
418                 let index = match(syntax_full, next_group_regex, index)
419             endwhile
421             " let ftindex  = ftindex + len(ft_part_name)
422             " let ftindex  = match( syntax_full, group_regex, ftindex )
423         " endwhile
424     endfor
426 "   " Sometimes filetypes can be composite names, like c.doxygen
427 "   " Loop through each individual part looking for the syntax
428 "   " items specific to each individual filetype.
429 "   let syn_list = ''
430 "   let ftindex  = 0
431 "   let ftindex  = match(&filetype, '\w\+', ftindex)
433 "   while ftindex > -1
434 "       let ft_part_name = matchstr( &filetype, '\w\+', ftindex )
436 "       " Syntax rules can contain items for more than just the current
437 "       " filetype.  They can contain additional items added by the user
438 "       " via autocmds or their vimrc.
439 "       " Some syntax files can be combined (html, php, jsp).
440 "       " We want only items that begin with the filetype we are interested in.
441 "       let next_group_regex = '\n' .
442 "                   \ '\zs'.ft_part_name.'\w\+\ze'.
443 "                   \ '\s\+xxx\s\+'
444 "       let index    = 0
445 "       let index    = match(syntax_full, next_group_regex, index)
447 "       if index == -1 && exists('b:current_syntax') && ft_part_name != b:current_syntax
448 "           " There appears to be two standards when writing syntax files.
449 "           " Either items begin as:
450 "           "     syn keyword {filetype}Keyword         values ...
451 "           "     let b:current_syntax = "sql"
452 "           "     let b:current_syntax = "sqlanywhere"
453 "           " Or
454 "           "     syn keyword {syntax_filename}Keyword  values ...
455 "           "     let b:current_syntax = "mysql"
456 "           " So, we will make the format of finding the syntax group names
457 "           " a bit more flexible and look for both if the first fails to
458 "           " find a match.
459 "           let next_group_regex = '\n' .
460 "                       \ '\zs'.b:current_syntax.'\w\+\ze'.
461 "                       \ '\s\+xxx\s\+'
462 "           let index    = 0
463 "           let index    = match(syntax_full, next_group_regex, index)
464 "       endif
466 "       while index > -1
467 "           let group_name = matchstr( syntax_full, '\w\+', index )
469 "           let get_syn_list = 1
470 "           for exclude_group_name in list_exclude_groups
471 "               if '\<'.exclude_group_name.'\>' =~ '\<'.group_name.'\>'
472 "                   let get_syn_list = 0
473 "               endif
474 "           endfor
476 "           " This code is no longer needed in version 6.0 since we have
477 "           " augmented the syntax list command to only retrieve the syntax
478 "           " groups we are interested in.
479 "           "
480 "           " if get_syn_list == 1
481 "           "     if syntax_group_include_{filetype} != ''
482 "           "         if '\<'.syntax_group_include_{filetype}.'\>' !~ '\<'.group_name.'\>'
483 "           "             let get_syn_list = 0
484 "           "         endif
485 "           "     endif
486 "           " endif
488 "           if get_syn_list == 1
489 "               " Pass in the full syntax listing, plus the group name we
490 "               " are interested in.
491 "               let extra_syn_list = s:SyntaxCSyntaxGroupItems(group_name, syntax_full)
492 "               let syn_list = syn_list . extra_syn_list . "\n"
493 "           endif
495 "           let index = index + strlen(group_name)
496 "           let index = match(syntax_full, next_group_regex, index)
497 "       endwhile
499 "       let ftindex  = ftindex + len(ft_part_name)
500 "       let ftindex  = match( &filetype, '\w\+', ftindex )
501 "   endwhile
503     " Convert the string to a List and sort it.
504     let compl_list = sort(split(syn_list))
506     if &filetype == 'vim'
507         let short_compl_list = []
508         for i in range(len(compl_list))
509             if i == len(compl_list)-1
510                 let next = i
511             else
512                 let next = i + 1
513             endif
514             if  compl_list[next] !~ '^'.compl_list[i].'.$'
515                 let short_compl_list += [compl_list[i]]
516             endif
517         endfor
519         return short_compl_list
520     else
521         return compl_list
522     endif
523 endfunction
525 function! s:SyntaxCSyntaxGroupItems( group_name, syntax_full )
527     let syn_list = ""
529     " From the full syntax listing, strip out the portion for the
530     " request group.
531     " Query:
532     "     \n           - must begin with a newline
533     "     a:group_name - the group name we are interested in
534     "     \s\+xxx\s\+  - group names are always followed by xxx
535     "     \zs          - start the match
536     "     .\{-}        - everything ...
537     "     \ze          - end the match
538     "     \(           - start a group or 2 potential matches
539     "     \n\w         - at the first newline starting with a character
540     "     \|           - 2nd potential match
541     "     \%$          - matches end of the file or string
542     "     \)           - end a group
543     let syntax_group = matchstr(a:syntax_full,
544                 \ "\n".a:group_name.'\s\+xxx\s\+\zs.\{-}\ze\(\n\w\|\%$\)'
545                 \ )
547     if syntax_group != ""
548         " let syn_list = substitute( @l, '^.*xxx\s*\%(contained\s*\)\?', "", '' )
549         " let syn_list = substitute( @l, '^.*xxx\s*', "", '' )
551         " We only want the words for the lines begining with
552         " containedin, but there could be other items.
554         " Tried to remove all lines that do not begin with contained
555         " but this does not work in all cases since you can have
556         "    contained nextgroup=...
557         " So this will strip off the ending of lines with known
558         " keywords.
559         let syn_list = substitute(
560                     \    syntax_group, '\<\('.
561                     \    substitute(
562                     \      escape(s:syn_remove_words, '\\/.*$^~[]')
563                     \      , ',', '\\|', 'g'
564                     \    ).
565                     \    '\).\{-}\%($\|'."\n".'\)'
566                     \    , "\n", 'g'
567                     \  )
569         " Attempt to deal with lines using the match syntax
570         " javaScriptDocTags xxx match /@\(param\|argument\|requires\|file\)\>/
571         " Though it can use any types of regex, so this plugin will attempt
572         " to restrict it
573         " 1.  Only use \( or \%( constructs remove all else
574         " 2   Remove and []s
575         " 3.  Account for match //constructs
576         "                       \%(\%(ms\|me\|hs\|he\|rs\|re\|lc\)\S\+\)\?
577         " 4.  Hope for the best
578         "
579         "
580         let syn_list_old = syn_list
581         while syn_list =~ '\<match\>\s\+\/'
582             if syn_list =~ 'perlElseIfError'
583                 let syn_list = syn_list
584             endif
585             " Check if the match has words at least 3 characters long
586             if syn_list =~ '\<match \/\zs.\{-}\<\w\{3,}\>.\{-}\ze\\\@<!\/\%(\%(ms\|me\|hs\|he\|rs\|re\|lc\)\S\+\)\?\s\+'
587                 " Remove everything after / and before the first \(
588                 let syn_list = substitute( syn_list, '\<match \/\zs.\{-}\ze\\%\?(.\{-}\\\@<!\/\%(\%(ms\|me\|hs\|he\|rs\|re\|lc\)\S\+\)\?\s\+', '', 'g' )
589                 " Remove everything after \) and up to the ending /
590                 let syn_list = substitute( syn_list, '\<match \/.\{-}\\)\zs.\{-}\ze\/\%(\%(ms\|me\|hs\|he\|rs\|re\|lc\)\S\+\)\?\s\+', '', 'g' )
592                 " Remove any character classes
593                 " let syn_list = substitute( syn_list, '\<match /\zs.\{-}\[[^]]*\].\{-}\ze\/ ', '', 'g' )
594                 let syn_list = substitute( syn_list, '\%(\<match \/[^/]\{-}\)\@<=\[[^]]*\]\ze.\{-}\\\@<!\/\%(\%(ms\|me\|hs\|he\|rs\|re\|lc\)\S\+\)\?', '', 'g' )
595                 " Remove any words < 3 characters
596                 let syn_list = substitute( syn_list, '\%(\<match \/[^/]\{-}\)\@<=\<\w\{1,2}\>\ze.\{-}\\\@<!\/\%(\%(ms\|me\|hs\|he\|rs\|re\|lc\)\S\+\)\?\s\+', '', 'g' )
597                 " Remove all non-word characters
598                 " let syn_list = substitute( syn_list, '\<match /\zs.\{-}\<\W\+\>.\{-}\ze\/ ', "", 'g' )
599                 " let syn_list = substitute( syn_list, '\%(\<match \/[^/]\{-}\)\@<=\W\+\ze.\{-}\/ ', ' ', 'g' )
600                 " Do this by using the outer substitue() call to gather all
601                 " text between the match /.../ tags.
602                 " The inner substitute() call operates on the text selected
603                 " and replaces all non-word characters.
604                 let syn_list = substitute( syn_list, '\<match \/\zs\(.\{-}\)\ze\\\@<!\/\%(\%(ms\|me\|hs\|he\|rs\|re\|lc\)\S\+\)\?\s\+'
605                             \ , '\=substitute(submatch(1), "\\W\\+", " ", "g")'
606                             \ , 'g' )
607                 " Remove the match / / syntax
608                 let syn_list = substitute( syn_list, '\<match \/\(.\{-}\)\/\%(\%(ms\|me\|hs\|he\|rs\|re\|lc\)\S\+\)\?\s\+', '\1', 'g' )
609             else
610                 " No words long enough, remove the match
611                 " Remove the match syntax
612                 " let syn_list = substitute( syn_list, '\<match \/[^\/]*\/\%(\%(ms\|me\|hs\|he\|rs\|re\|lc\)\S\+\)\?\s\+', '', 'g' )
613                 let syn_list = substitute( syn_list, '\<match \/\%(.\{-}\)\?\/\%(\%(ms\|me\|hs\|he\|rs\|re\|lc\)\S\+\)\?\s\+', '', 'g' )
614             endif
615             if syn_list =~ '\<match\>\s\+\/'
616                 " Problem removing the match / / tags
617                 let syn_list = ''
618             endif
619         endwhile
622         " Now strip off the newline + blank space + contained.
623         " Also include lines with nextgroup=@someName skip_key_words syntax_element
624                     " \    syn_list, '\%(^\|\n\)\@<=\s*\<\(contained\|nextgroup=\)'
625                     " \    syn_list, '\%(^\|\n\)\@<=\s*\<\(contained\|nextgroup=[@a-zA-Z,]*\)'
626         let syn_list = substitute(
627                     \    syn_list, '\<\(contained\|nextgroup=[@a-zA-Z,]*\)'
628                     \    , "", 'g'
629                     \ )
631         " This can leave lines like this
632         "     =@vimMenuList  skipwhite onoremenu
633         " Strip the special option keywords first
634         "     :h :syn-skipwhite*
635         let syn_list = substitute(
636                     \    syn_list, '\<\(skipwhite\|skipnl\|skipempty\)\>'
637                     \    , "", 'g'
638                     \ )
640         " Now remove the remainder of the nextgroup=@someName lines
641         let syn_list = substitute(
642                     \    syn_list, '\%(^\|\n\)\@<=\s*\(@\w\+\)'
643                     \    , "", 'g'
644                     \ )
646         if b:omni_syntax_use_iskeyword == 0
647             " There are a number of items which have non-word characters in
648             " them, *'T_F1'*.  vim.vim is one such file.
649             " This will replace non-word characters with spaces.
650             let syn_list = substitute( syn_list, '[^0-9A-Za-z_ ]', ' ', 'g' )
651         else
652             if g:omni_syntax_use_iskeyword_numeric == 1
653                 " iskeyword can contain value like this
654                 " 38,42,43,45,47-58,60-62,64-90,97-122,_,+,-,*,/,%,<,=,>,:,$,?,!,@-@,94
655                 " Numeric values convert to their ASCII equivalent using the
656                 " nr2char() function.
657                 "     &       38
658                 "     *       42
659                 "     +       43
660                 "     -       45
661                 "     ^       94
662                 " Iterate through all numeric specifications and convert those
663                 " to their ascii equivalent ensuring the character is printable.
664                 " If so, add it to the list.
665                 let accepted_chars = ''
666                 for item in split(&iskeyword, ',')
667                     if item =~ '\d-\d'
668                         " This is a character range (ie 47-58),
669                         " cycle through each character within the range
670                         let [b:start, b:end] = split(item, '-')
671                         for range_item in range( b:start, b:end )
672                             if range_item <= 127 || g:omni_syntax_use_single_byte == 0
673                                 if nr2char(range_item) =~ '\p'
674                                     let accepted_chars = accepted_chars . nr2char(range_item)
675                                 endif
676                             endif
677                         endfor
678                     elseif item =~ '^\d\+$'
679                         " Only numeric, translate to a character
680                         if item < 127 || g:omni_syntax_use_single_byte == 0
681                             if nr2char(item) =~ '\p'
682                                 let accepted_chars = accepted_chars . nr2char(item)
683                             endif
684                         endif
685                     else
686                         if char2nr(item) < 127 || g:omni_syntax_use_single_byte == 0
687                             if item =~ '\p'
688                                 let accepted_chars = accepted_chars . item
689                             endif
690                         endif
691                     endif
692                 endfor
693                 " Escape special regex characters
694                 " Looks like the wrong chars are escaped.  In a collection,
695                 "      :h /[]
696                 "      only `]', `\', `-' and `^' are special:
697                 " let accepted_chars = escape(accepted_chars, '\\/.*$^~[]' )
698                 let accepted_chars = escape(accepted_chars, ']\-^' )
699                 " Remove all characters that are not acceptable
700                 let syn_list = substitute( syn_list, '[^A-Za-z'.accepted_chars.']', ' ', 'g' )
701             else
702                 let accept_chars = ','.&iskeyword.','
703                 " Remove all character ranges
704                 " let accept_chars = substitute(accept_chars, ',[^,]\+-[^,]\+,', ',', 'g')
705                 let accept_chars = substitute(accept_chars, ',\@<=[^,]\+-[^,]\+,', '', 'g')
706                 " Remove all numeric specifications
707                 " let accept_chars = substitute(accept_chars, ',\d\{-},', ',', 'g')
708                 let accept_chars = substitute(accept_chars, ',\@<=\d\{-},', '', 'g')
709                 " Remove all commas
710                 let accept_chars = substitute(accept_chars, ',', '', 'g')
711                 " Escape special regex characters
712                 " Looks like the wrong chars are escaped.  In a collection,
713                 "      :h /[]
714                 "      only `]', `\', `-' and `^' are special:
715                 " let accept_chars = escape(accept_chars, '\\/.*$^~[]' )
716                 let accept_chars = escape(accept_chars, ']\-^' )
717                 " Remove all characters that are not acceptable
718                 let syn_list = substitute( syn_list, '[^0-9A-Za-z_'.accept_chars.']', ' ', 'g' )
719             endif
720         endif
722         if b:omni_syntax_minimum_length > 0
723             " If the user specified a minimum length, enforce it
724             let syn_list = substitute(' '.syn_list.' ', ' \S\{,'.b:omni_syntax_minimum_length.'}\ze ', ' ', 'g')
725         endif
726     else
727         let syn_list = ''
728     endif
730     return syn_list
731 endfunction
733 function! OmniSyntaxShowChars(spec)
734   let result = []
735   for item in split(a:spec, ',')
736     if len(item) > 1
737       if item == '@-@'
738         call add(result, char2nr(item))
739       else
740         call extend(result, call('range', split(item, '-')))
741       endif
742     else
743       if item == '@'  " assume this is [A-Za-z]
744         for [c1, c2] in [['A', 'Z'], ['a', 'z']]
745           call extend(result, range(char2nr(c1), char2nr(c2)))
746         endfor
747       else
748         call add(result, char2nr(item))
749       endif
750     endif
751   endfor
752   return join(map(result, 'nr2char(v:val)'), ', ')
753 endfunction
754 let &cpo = s:cpo_save
755 unlet s:cpo_save