14770d09aSBram Moolenaar" Vim completion script
24770d09aSBram Moolenaar" Language:    All languages, uses existing syntax highlighting rules
36dfc28beSBram Moolenaar" Maintainer:  David Fishburn <dfishburn dot vim at gmail dot com>
4*4c295027SBram Moolenaar" Version:     15.0
5*4c295027SBram Moolenaar" Last Change: 2021 Apr 27
697e8f356SBram Moolenaar" Usage:       For detailed help, ":help ft-syntax-omni"
74770d09aSBram Moolenaar
86dfc28beSBram Moolenaar" History
940af4e39SBram Moolenaar"
10*4c295027SBram Moolenaar" Version 15.0
11*4c295027SBram Moolenaar"   - SyntaxComplete ignored all buffer specific overrides, always used global
12*4c295027SBram Moolenaar"     https://github.com/vim/vim/issues/8153
13*4c295027SBram Moolenaar"
149faec4e3SBram Moolenaar" Version 14.0
159faec4e3SBram Moolenaar"   - Fixed issue with single quotes and is_keyword
169faec4e3SBram Moolenaar"     https://github.com/vim/vim/issues/7463
179faec4e3SBram Moolenaar"
18ad3b366cSBram Moolenaar" Version 13.0
19ad3b366cSBram Moolenaar"   - Extended the option omni_syntax_group_include_{filetype}
20ad3b366cSBram Moolenaar"     to accept a comma separated list of regex's rather than
21ad3b366cSBram Moolenaar"     string.  For example, for the javascript filetype you could
22ad3b366cSBram Moolenaar"     use:
23ad3b366cSBram Moolenaar"        let g:omni_syntax_group_include_javascript = 'javascript\w\+,jquery\w\+'
24ad3b366cSBram Moolenaar"   - Some syntax files (perl.vim) use the match // syntax as a mechanism
25ad3b366cSBram Moolenaar"     to identify keywords.  This update attempts to parse the
26ad3b366cSBram Moolenaar"     match syntax and pull out syntax items which are at least
27ad3b366cSBram Moolenaar"     3 words or more.
28ad3b366cSBram Moolenaar"
29ad3b366cSBram Moolenaar" Version 12.0
30ad3b366cSBram Moolenaar"   - It is possible to have '-' as part of iskeyword, when
31ad3b366cSBram Moolenaar"     checking for character ranges, tighten up the regex.
32ad3b366cSBram Moolenaar"     E688: More targets than List items.
33ad3b366cSBram Moolenaar"
3434feacbcSBram Moolenaar" Version 11.0
35ad3b366cSBram Moolenaar"   - Corrected which characters required escaping during
3634feacbcSBram Moolenaar"     substitution calls.
3734feacbcSBram Moolenaar"
3897d62497SBram Moolenaar" Version 10.0
39ad3b366cSBram Moolenaar"   - Cycle through all the character ranges specified in the
4097d62497SBram Moolenaar"     iskeyword option and build a list of valid word separators.
4197d62497SBram Moolenaar"     Prior to this change, only actual characters were used,
4297d62497SBram Moolenaar"     where for example ASCII "45" == "-".  If "45" were used
4397d62497SBram Moolenaar"     in iskeyword the hyphen would not be picked up.
4497d62497SBram Moolenaar"     This introduces a new option, since the character ranges
4597d62497SBram Moolenaar"     specified could be multibyte:
4697d62497SBram Moolenaar"         let g:omni_syntax_use_single_byte = 1
47ad3b366cSBram Moolenaar"   - This by default will only allow single byte ASCII
4897d62497SBram Moolenaar"     characters to be added and an additional check to ensure
49*4c295027SBram Moolenaar"     the character is printable (see documentation for isprint).
5097d62497SBram Moolenaar"
5197d62497SBram Moolenaar" Version 9.0
52ad3b366cSBram Moolenaar"   - Add the check for cpo.
5397d62497SBram Moolenaar"
54f1568ecaSBram Moolenaar" Version 8.0
55ad3b366cSBram Moolenaar"   - Updated SyntaxCSyntaxGroupItems()
56f1568ecaSBram Moolenaar"         - Some additional syntax items were also allowed
57f1568ecaSBram Moolenaar"           on nextgroup= lines which were ignored by default.
58f1568ecaSBram Moolenaar"           Now these lines are processed independently.
59f1568ecaSBram Moolenaar"
6040af4e39SBram Moolenaar" Version 7.0
61ad3b366cSBram Moolenaar"   - Updated syntaxcomplete#OmniSyntaxList()
6240af4e39SBram Moolenaar"         - Looking up the syntax groups defined from a syntax file
6340af4e39SBram Moolenaar"           looked for only 1 format of {filetype}GroupName, but some
6440af4e39SBram Moolenaar"           syntax writers use this format as well:
6540af4e39SBram Moolenaar"               {b:current_syntax}GroupName
66ad3b366cSBram Moolenaar"   -       OmniSyntaxList() will now check for both if the first
6740af4e39SBram Moolenaar"           method does not find a match.
6840af4e39SBram Moolenaar"
6940af4e39SBram Moolenaar" Version 6.0
70ad3b366cSBram Moolenaar"   - Added syntaxcomplete#OmniSyntaxList()
7140af4e39SBram Moolenaar"         - Allows other plugins to use this for their own
7240af4e39SBram Moolenaar"           purposes.
7340af4e39SBram Moolenaar"         - It will return a List of all syntax items for the
7440af4e39SBram Moolenaar"           syntax group name passed in.
7540af4e39SBram Moolenaar"         - XPTemplate for SQL will use this function via the
7640af4e39SBram Moolenaar"           sqlcomplete plugin to populate a Choose box.
7740af4e39SBram Moolenaar"
786dfc28beSBram Moolenaar" Version 5.0
79ad3b366cSBram Moolenaar"   - Updated SyntaxCSyntaxGroupItems()
8040af4e39SBram Moolenaar"         - When processing a list of syntax groups, the final group
816dfc28beSBram Moolenaar"           was missed in function SyntaxCSyntaxGroupItems.
826dfc28beSBram Moolenaar"
834770d09aSBram Moolenaar" Set completion with CTRL-X CTRL-O to autoloaded function.
84c15ef30cSBram Moolenaar" This check is in place in case this script is
85c15ef30cSBram Moolenaar" sourced directly instead of using the autoload feature.
86c06ac340SBram Moolenaarif exists('+omnifunc')
87c15ef30cSBram Moolenaar    " Do not set the option if already set since this
88c15ef30cSBram Moolenaar    " results in an E117 warning.
89c15ef30cSBram Moolenaar    if &omnifunc == ""
90c06ac340SBram Moolenaar        setlocal omnifunc=syntaxcomplete#Complete
914770d09aSBram Moolenaar    endif
92c15ef30cSBram Moolenaarendif
934770d09aSBram Moolenaar
944770d09aSBram Moolenaarif exists('g:loaded_syntax_completion')
954770d09aSBram Moolenaar    finish
964770d09aSBram Moolenaarendif
97*4c295027SBram Moolenaarlet g:loaded_syntax_completion = 150
9897d62497SBram Moolenaar
9997d62497SBram Moolenaar" Turn on support for line continuations when creating the script
10097d62497SBram Moolenaarlet s:cpo_save = &cpo
10197d62497SBram Moolenaarset cpo&vim
10297e8f356SBram Moolenaar
10397e8f356SBram Moolenaar" Set ignorecase to the ftplugin standard
1049964e468SBram Moolenaar" This is the default setting, but if you define a buffer local
1059964e468SBram Moolenaar" variable you can override this on a per filetype.
10697e8f356SBram Moolenaarif !exists('g:omni_syntax_ignorecase')
10797e8f356SBram Moolenaar    let g:omni_syntax_ignorecase = &ignorecase
10897e8f356SBram Moolenaarendif
1094770d09aSBram Moolenaar
1109964e468SBram Moolenaar" Indicates whether we should use the iskeyword option to determine
1119964e468SBram Moolenaar" how to split words.
1129964e468SBram Moolenaar" This is the default setting, but if you define a buffer local
1139964e468SBram Moolenaar" variable you can override this on a per filetype.
1149964e468SBram Moolenaarif !exists('g:omni_syntax_use_iskeyword')
1159964e468SBram Moolenaar    let g:omni_syntax_use_iskeyword = 1
1169964e468SBram Moolenaarendif
1179964e468SBram Moolenaar
11897d62497SBram Moolenaar" When using iskeyword, this setting controls whether the characters
11997d62497SBram Moolenaar" should be limited to single byte characters.
12097d62497SBram Moolenaarif !exists('g:omni_syntax_use_single_byte')
12197d62497SBram Moolenaar    let g:omni_syntax_use_single_byte = 1
12297d62497SBram Moolenaarendif
12397d62497SBram Moolenaar
12497d62497SBram Moolenaar" When using iskeyword, this setting controls whether the characters
12597d62497SBram Moolenaar" should be limited to single byte characters.
12697d62497SBram Moolenaarif !exists('g:omni_syntax_use_iskeyword_numeric')
12797d62497SBram Moolenaar    let g:omni_syntax_use_iskeyword_numeric = 1
12897d62497SBram Moolenaarendif
12997d62497SBram Moolenaar
1309964e468SBram Moolenaar" Only display items in the completion window that are at least
1319964e468SBram Moolenaar" this many characters in length.
1329964e468SBram Moolenaar" This is the default setting, but if you define a buffer local
1339964e468SBram Moolenaar" variable you can override this on a per filetype.
1349964e468SBram Moolenaarif !exists('g:omni_syntax_minimum_length')
1359964e468SBram Moolenaar    let g:omni_syntax_minimum_length = 0
1369964e468SBram Moolenaarendif
1379964e468SBram Moolenaar
1384770d09aSBram Moolenaar" This script will build a completion list based on the syntax
1394770d09aSBram Moolenaar" elements defined by the files in $VIMRUNTIME/syntax.
140ad3b366cSBram Moolenaar" let s:syn_remove_words = 'match,matchgroup=,contains,'.
141ad3b366cSBram Moolenaarlet s:syn_remove_words = 'matchgroup=,contains,'.
142f1568ecaSBram Moolenaar            \ 'links to,start=,end='
143f1568ecaSBram Moolenaar            " \ 'links to,start=,end=,nextgroup='
1444770d09aSBram Moolenaar
1454770d09aSBram Moolenaarlet s:cache_name = []
1464770d09aSBram Moolenaarlet s:cache_list = []
147c15ef30cSBram Moolenaarlet s:prepended  = ''
1484770d09aSBram Moolenaar
1494770d09aSBram Moolenaar" This function is used for the 'omnifunc' option.
1504770d09aSBram Moolenaarfunction! syntaxcomplete#Complete(findstart, base)
1514770d09aSBram Moolenaar
152*4c295027SBram Moolenaar    " Allow user to override ignorecase per buffer
153*4c295027SBram Moolenaar    let l:omni_syntax_ignorecase = g:omni_syntax_ignorecase
154*4c295027SBram Moolenaar    if exists('b:omni_syntax_ignorecase')
155*4c295027SBram Moolenaar        let l:omni_syntax_ignorecase = b:omni_syntax_ignorecase
1569964e468SBram Moolenaar    endif
1579964e468SBram Moolenaar
1584770d09aSBram Moolenaar    if a:findstart
1594770d09aSBram Moolenaar        " Locate the start of the item, including "."
1604770d09aSBram Moolenaar        let line = getline('.')
1614770d09aSBram Moolenaar        let start = col('.') - 1
1624770d09aSBram Moolenaar        let lastword = -1
1634770d09aSBram Moolenaar        while start > 0
1649964e468SBram Moolenaar            " if line[start - 1] =~ '\S'
1659964e468SBram Moolenaar            "     let start -= 1
1669964e468SBram Moolenaar            " elseif line[start - 1] =~ '\.'
1679964e468SBram Moolenaar            if line[start - 1] =~ '\k'
1684770d09aSBram Moolenaar                let start -= 1
1699964e468SBram Moolenaar                let lastword = a:findstart
1704770d09aSBram Moolenaar            else
1714770d09aSBram Moolenaar                break
1724770d09aSBram Moolenaar            endif
1734770d09aSBram Moolenaar        endwhile
1744770d09aSBram Moolenaar
1754770d09aSBram Moolenaar        " Return the column of the last word, which is going to be changed.
1764770d09aSBram Moolenaar        " Remember the text that comes before it in s:prepended.
1774770d09aSBram Moolenaar        if lastword == -1
1784770d09aSBram Moolenaar            let s:prepended = ''
1794770d09aSBram Moolenaar            return start
1804770d09aSBram Moolenaar        endif
1819964e468SBram Moolenaar        let s:prepended = strpart(line, start, (col('.') - 1) - start)
1829964e468SBram Moolenaar        return start
1834770d09aSBram Moolenaar    endif
1844770d09aSBram Moolenaar
1859964e468SBram Moolenaar    " let base = s:prepended . a:base
1869faec4e3SBram Moolenaar    let base = substitute(s:prepended, "'", "''", 'g')
1874770d09aSBram Moolenaar
18897e8f356SBram Moolenaar    let filetype = substitute(&filetype, '\.', '_', 'g')
18997e8f356SBram Moolenaar    let list_idx = index(s:cache_name, filetype, 0, &ignorecase)
1904770d09aSBram Moolenaar    if list_idx > -1
1914770d09aSBram Moolenaar        let compl_list = s:cache_list[list_idx]
1924770d09aSBram Moolenaar    else
193c06ac340SBram Moolenaar        let compl_list   = OmniSyntaxList()
19497e8f356SBram Moolenaar        let s:cache_name = add( s:cache_name,  filetype )
1954770d09aSBram Moolenaar        let s:cache_list = add( s:cache_list,  compl_list )
1964770d09aSBram Moolenaar    endif
1974770d09aSBram Moolenaar
1984770d09aSBram Moolenaar    " Return list of matches.
1994770d09aSBram Moolenaar
2009964e468SBram Moolenaar    if base != ''
2019964e468SBram Moolenaar        " let compstr    = join(compl_list, ' ')
202*4c295027SBram Moolenaar        " let expr       = (l:omni_syntax_ignorecase==0?'\C':'').'\<\%('.base.'\)\@!\w\+\s*'
2039964e468SBram Moolenaar        " let compstr    = substitute(compstr, expr, '', 'g')
2049964e468SBram Moolenaar        " let compl_list = split(compstr, '\s\+')
2059964e468SBram Moolenaar
2069964e468SBram Moolenaar        " Filter the list based on the first few characters the user
2079964e468SBram Moolenaar        " entered
208*4c295027SBram Moolenaar        let expr = 'v:val '.(l:omni_syntax_ignorecase==1?'=~?':'=~#')." '^".escape(base, '\\/.*$^~[]').".*'"
2099964e468SBram Moolenaar        let compl_list = filter(deepcopy(compl_list), expr)
2104770d09aSBram Moolenaar    endif
2114770d09aSBram Moolenaar
2124770d09aSBram Moolenaar    return compl_list
2134770d09aSBram Moolenaarendfunc
2144770d09aSBram Moolenaar
21540af4e39SBram Moolenaarfunction! syntaxcomplete#OmniSyntaxList(...)
21640af4e39SBram Moolenaar    if a:0 > 0
21740af4e39SBram Moolenaar        let parms = []
21840af4e39SBram Moolenaar        if 3 == type(a:1)
21940af4e39SBram Moolenaar            let parms = a:1
22040af4e39SBram Moolenaar        elseif 1 == type(a:1)
22140af4e39SBram Moolenaar            let parms = split(a:1, ',')
22240af4e39SBram Moolenaar        endif
22340af4e39SBram Moolenaar        return OmniSyntaxList( parms )
22440af4e39SBram Moolenaar    else
22540af4e39SBram Moolenaar        return OmniSyntaxList()
22640af4e39SBram Moolenaar    endif
22740af4e39SBram Moolenaarendfunc
22840af4e39SBram Moolenaar
229*4c295027SBram Moolenaarfunction! syntaxcomplete#OmniSyntaxClearCache()
230*4c295027SBram Moolenaar    let s:cache_name = []
231*4c295027SBram Moolenaar    let s:cache_list = []
232*4c295027SBram Moolenaarendfunction
233*4c295027SBram Moolenaar
234*4c295027SBram Moolenaar" To retrieve all syntax items regardless of syntax group:
235*4c295027SBram Moolenaar"     echo OmniSyntaxList( [] )
236*4c295027SBram Moolenaar"
237*4c295027SBram Moolenaar" To retrieve only the syntax items for the sqlOperator syntax group:
238*4c295027SBram Moolenaar"     echo OmniSyntaxList( ['sqlOperator'] )
239*4c295027SBram Moolenaar"
240*4c295027SBram Moolenaar" To retrieve all syntax items for both the sqlOperator and sqlType groups:
241*4c295027SBram Moolenaar"     echo OmniSyntaxList( ['sqlOperator', 'sqlType'] )
242*4c295027SBram Moolenaar"
243*4c295027SBram Moolenaar" A regular expression can also be used:
244*4c295027SBram Moolenaar"     echo OmniSyntaxList( ['sql\w\+'] )
245*4c295027SBram Moolenaar"
246*4c295027SBram Moolenaar" From within a plugin, you would typically assign the output to a List: >
247*4c295027SBram Moolenaar"     let myKeywords = []
248*4c295027SBram Moolenaar"     let myKeywords = OmniSyntaxList( ['sqlKeyword'] )
24940af4e39SBram Moolenaarfunction! OmniSyntaxList(...)
25040af4e39SBram Moolenaar    let list_parms = []
25140af4e39SBram Moolenaar    if a:0 > 0
25240af4e39SBram Moolenaar        if 3 == type(a:1)
25340af4e39SBram Moolenaar            let list_parms = a:1
25440af4e39SBram Moolenaar        elseif 1 == type(a:1)
25540af4e39SBram Moolenaar            let list_parms = split(a:1, ',')
25640af4e39SBram Moolenaar        endif
25740af4e39SBram Moolenaar    endif
25840af4e39SBram Moolenaar
25997e8f356SBram Moolenaar    " Default to returning a dictionary, if use_dictionary is set to 0
26097e8f356SBram Moolenaar    " a list will be returned.
26197e8f356SBram Moolenaar    " let use_dictionary = 1
26297e8f356SBram Moolenaar    " if a:0 > 0 && a:1 != ''
26397e8f356SBram Moolenaar    "     let use_dictionary = a:1
26497e8f356SBram Moolenaar    " endif
26597e8f356SBram Moolenaar
2664770d09aSBram Moolenaar    let saveL = @l
26740af4e39SBram Moolenaar    let filetype = substitute(&filetype, '\.', '_', 'g')
26840af4e39SBram Moolenaar
26940af4e39SBram Moolenaar    if empty(list_parms)
270*4c295027SBram Moolenaar        " Allow user to override per buffer
271*4c295027SBram Moolenaar        if exists('g:omni_syntax_group_include_'.filetype)
272*4c295027SBram Moolenaar            let l:omni_syntax_group_include_{filetype} = g:omni_syntax_group_include_{filetype}
273*4c295027SBram Moolenaar        endif
274*4c295027SBram Moolenaar        if exists('b:omni_syntax_group_include_'.filetype)
275*4c295027SBram Moolenaar            let l:omni_syntax_group_include_{filetype} = b:omni_syntax_group_include_{filetype}
276*4c295027SBram Moolenaar        endif
277*4c295027SBram Moolenaar
27840af4e39SBram Moolenaar        " Default the include group to include the requested syntax group
27940af4e39SBram Moolenaar        let syntax_group_include_{filetype} = ''
28040af4e39SBram Moolenaar        " Check if there are any overrides specified for this filetype
281*4c295027SBram Moolenaar        if exists('l:omni_syntax_group_include_'.filetype)
28240af4e39SBram Moolenaar            let syntax_group_include_{filetype} =
283*4c295027SBram Moolenaar                        \ substitute( l:omni_syntax_group_include_{filetype},'\s\+','','g')
284*4c295027SBram Moolenaar            let list_parms = split(l:omni_syntax_group_include_{filetype}, ',')
28540af4e39SBram Moolenaar            if syntax_group_include_{filetype} =~ '\w'
28640af4e39SBram Moolenaar                let syntax_group_include_{filetype} =
28740af4e39SBram Moolenaar                            \ substitute( syntax_group_include_{filetype},
28840af4e39SBram Moolenaar                            \ '\s*,\s*', '\\|', 'g'
28940af4e39SBram Moolenaar                            \ )
29040af4e39SBram Moolenaar            endif
29140af4e39SBram Moolenaar        endif
29240af4e39SBram Moolenaar    else
29340af4e39SBram Moolenaar        " A specific list was provided, use it
29440af4e39SBram Moolenaar    endif
2954770d09aSBram Moolenaar
2964770d09aSBram Moolenaar    " Loop through all the syntax groupnames, and build a
2974770d09aSBram Moolenaar    " syntax file which contains these names.  This can
2984770d09aSBram Moolenaar    " work generically for any filetype that does not already
2994770d09aSBram Moolenaar    " have a plugin defined.
3004770d09aSBram Moolenaar    " This ASSUMES the syntax groupname BEGINS with the name
301c06ac340SBram Moolenaar    " of the filetype.  From my casual viewing of the vim7\syntax
30240af4e39SBram Moolenaar    " directory this is true for almost all syntax definitions.
30340af4e39SBram Moolenaar    " As an example, the SQL syntax groups have this pattern:
30440af4e39SBram Moolenaar    "     sqlType
30540af4e39SBram Moolenaar    "     sqlOperators
30640af4e39SBram Moolenaar    "     sqlKeyword ...
307ad3b366cSBram Moolenaar    if !empty(list_parms) && empty(substitute(join(list_parms), '[a-zA-Z ]', '', 'g'))
308ad3b366cSBram Moolenaar        " If list_parms only includes word characters, use it to limit
309ad3b366cSBram Moolenaar        " the syntax elements.
310ad3b366cSBram Moolenaar        " If using regex syntax list will fail to find those items, so
311ad3b366cSBram Moolenaar        " simply grab the who syntax list.
3124770d09aSBram Moolenaar        redir @l
31340af4e39SBram Moolenaar        silent! exec 'syntax list '.join(list_parms)
3144770d09aSBram Moolenaar        redir END
315ad3b366cSBram Moolenaar    else
316ad3b366cSBram Moolenaar        redir @l
317ad3b366cSBram Moolenaar        silent! exec 'syntax list'
318ad3b366cSBram Moolenaar        redir END
319ad3b366cSBram Moolenaar    endif
3204770d09aSBram Moolenaar
321c06ac340SBram Moolenaar    let syntax_full = "\n".@l
3224770d09aSBram Moolenaar    let @l = saveL
3234770d09aSBram Moolenaar
324c06ac340SBram Moolenaar    if syntax_full =~ 'E28'
325c06ac340SBram Moolenaar                \ || syntax_full =~ 'E411'
326c06ac340SBram Moolenaar                \ || syntax_full =~ 'E415'
327c06ac340SBram Moolenaar                \ || syntax_full =~ 'No Syntax items'
328c06ac340SBram Moolenaar        return []
3294770d09aSBram Moolenaar    endif
3304770d09aSBram Moolenaar
33197e8f356SBram Moolenaar    let filetype = substitute(&filetype, '\.', '_', 'g')
33297e8f356SBram Moolenaar
33340af4e39SBram Moolenaar    let list_exclude_groups = []
33440af4e39SBram Moolenaar    if a:0 > 0
33540af4e39SBram Moolenaar        " Do nothing since we have specific a specific list of groups
33640af4e39SBram Moolenaar    else
337c06ac340SBram Moolenaar        " Default the exclude group to nothing
33897e8f356SBram Moolenaar        let syntax_group_exclude_{filetype} = ''
339*4c295027SBram Moolenaar
340*4c295027SBram Moolenaar        " Allow user to override per buffer
34197e8f356SBram Moolenaar        if exists('g:omni_syntax_group_exclude_'.filetype)
342*4c295027SBram Moolenaar            let l:omni_syntax_group_exclude_{filetype} = g:omni_syntax_group_exclude_{filetype}
343*4c295027SBram Moolenaar        endif
344*4c295027SBram Moolenaar        if exists('b:omni_syntax_group_exclude_'.filetype)
345*4c295027SBram Moolenaar            let l:omni_syntax_group_exclude_{filetype} = b:omni_syntax_group_exclude_{filetype}
346*4c295027SBram Moolenaar        endif
347*4c295027SBram Moolenaar
348*4c295027SBram Moolenaar        " Check if there are any overrides specified for this filetype
349*4c295027SBram Moolenaar        if exists('l:omni_syntax_group_exclude_'.filetype)
35097e8f356SBram Moolenaar            let syntax_group_exclude_{filetype} =
351*4c295027SBram Moolenaar                        \ substitute( l:omni_syntax_group_exclude_{filetype},'\s\+','','g')
352*4c295027SBram Moolenaar            let list_exclude_groups = split(l:omni_syntax_group_exclude_{filetype}, ',')
35397e8f356SBram Moolenaar            if syntax_group_exclude_{filetype} =~ '\w'
35497e8f356SBram Moolenaar                let syntax_group_exclude_{filetype} =
35597e8f356SBram Moolenaar                            \ substitute( syntax_group_exclude_{filetype},
356c06ac340SBram Moolenaar                            \ '\s*,\s*', '\\|', 'g'
357c06ac340SBram Moolenaar                            \ )
358c06ac340SBram Moolenaar            endif
359c06ac340SBram Moolenaar        endif
36040af4e39SBram Moolenaar    endif
361c06ac340SBram Moolenaar
362ad3b366cSBram Moolenaar    if empty(list_parms)
363ad3b366cSBram Moolenaar        let list_parms = [&filetype.'\w\+']
364ad3b366cSBram Moolenaar    endif
365ad3b366cSBram Moolenaar
366ad3b366cSBram Moolenaar    let syn_list = ''
367ad3b366cSBram Moolenaar    let index    = 0
368ad3b366cSBram Moolenaar    for group_regex in list_parms
36997e8f356SBram Moolenaar        " Sometimes filetypes can be composite names, like c.doxygen
37097e8f356SBram Moolenaar        " Loop through each individual part looking for the syntax
37197e8f356SBram Moolenaar        " items specific to each individual filetype.
372ad3b366cSBram Moolenaar        " let ftindex  = 0
373ad3b366cSBram Moolenaar        " let ftindex  = match(syntax_full, group_regex, ftindex)
37497e8f356SBram Moolenaar
375ad3b366cSBram Moolenaar        " while ftindex > -1
376ad3b366cSBram Moolenaar            " let ft_part_name = matchstr( syntax_full, '\w\+', ftindex )
37797e8f356SBram Moolenaar
378c06ac340SBram Moolenaar            " Syntax rules can contain items for more than just the current
379c06ac340SBram Moolenaar            " filetype.  They can contain additional items added by the user
380c06ac340SBram Moolenaar            " via autocmds or their vimrc.
381c06ac340SBram Moolenaar            " Some syntax files can be combined (html, php, jsp).
382c06ac340SBram Moolenaar            " We want only items that begin with the filetype we are interested in.
3834770d09aSBram Moolenaar            let next_group_regex = '\n' .
384ad3b366cSBram Moolenaar                        \ '\zs'.group_regex.'\ze'.
385c06ac340SBram Moolenaar                        \ '\s\+xxx\s\+'
386c06ac340SBram Moolenaar            let index    = match(syntax_full, next_group_regex, index)
3874770d09aSBram Moolenaar
388ad3b366cSBram Moolenaar            " For the matched group name, strip off any of the regex special
389ad3b366cSBram Moolenaar            " characters and see if we get a match with the current syntax
390ad3b366cSBram Moolenaar            if index == -1 && exists('b:current_syntax') && substitute(group_regex, '[^a-zA-Z ]\+.*', '', 'g') !~ '^'.b:current_syntax
39140af4e39SBram Moolenaar                " There appears to be two standards when writing syntax files.
39240af4e39SBram Moolenaar                " Either items begin as:
39340af4e39SBram Moolenaar                "     syn keyword {filetype}Keyword         values ...
39440af4e39SBram Moolenaar                "     let b:current_syntax = "sql"
39540af4e39SBram Moolenaar                "     let b:current_syntax = "sqlanywhere"
39640af4e39SBram Moolenaar                " Or
39740af4e39SBram Moolenaar                "     syn keyword {syntax_filename}Keyword  values ...
39840af4e39SBram Moolenaar                "     let b:current_syntax = "mysql"
39940af4e39SBram Moolenaar                " So, we will make the format of finding the syntax group names
40040af4e39SBram Moolenaar                " a bit more flexible and look for both if the first fails to
40140af4e39SBram Moolenaar                " find a match.
40240af4e39SBram Moolenaar                let next_group_regex = '\n' .
40340af4e39SBram Moolenaar                            \ '\zs'.b:current_syntax.'\w\+\ze'.
40440af4e39SBram Moolenaar                            \ '\s\+xxx\s\+'
40540af4e39SBram Moolenaar                let index    = 0
40640af4e39SBram Moolenaar                let index    = match(syntax_full, next_group_regex, index)
40740af4e39SBram Moolenaar            endif
40840af4e39SBram Moolenaar
40997e8f356SBram Moolenaar            while index > -1
410c06ac340SBram Moolenaar                let group_name = matchstr( syntax_full, '\w\+', index )
4114770d09aSBram Moolenaar
412c06ac340SBram Moolenaar                let get_syn_list = 1
41340af4e39SBram Moolenaar                for exclude_group_name in list_exclude_groups
41440af4e39SBram Moolenaar                    if '\<'.exclude_group_name.'\>' =~ '\<'.group_name.'\>'
415c06ac340SBram Moolenaar                        let get_syn_list = 0
416c06ac340SBram Moolenaar                    endif
41740af4e39SBram Moolenaar                endfor
418c06ac340SBram Moolenaar
41940af4e39SBram Moolenaar                " This code is no longer needed in version 6.0 since we have
42040af4e39SBram Moolenaar                " augmented the syntax list command to only retrieve the syntax
42140af4e39SBram Moolenaar                " groups we are interested in.
42240af4e39SBram Moolenaar                "
42340af4e39SBram Moolenaar                " if get_syn_list == 1
42440af4e39SBram Moolenaar                "     if syntax_group_include_{filetype} != ''
42540af4e39SBram Moolenaar                "         if '\<'.syntax_group_include_{filetype}.'\>' !~ '\<'.group_name.'\>'
42640af4e39SBram Moolenaar                "             let get_syn_list = 0
42740af4e39SBram Moolenaar                "         endif
42840af4e39SBram Moolenaar                "     endif
42940af4e39SBram Moolenaar                " endif
430c06ac340SBram Moolenaar
431c06ac340SBram Moolenaar                if get_syn_list == 1
432c06ac340SBram Moolenaar                    " Pass in the full syntax listing, plus the group name we
433c06ac340SBram Moolenaar                    " are interested in.
434e2f98b95SBram Moolenaar                    let extra_syn_list = s:SyntaxCSyntaxGroupItems(group_name, syntax_full)
4354770d09aSBram Moolenaar                    let syn_list = syn_list . extra_syn_list . "\n"
436c06ac340SBram Moolenaar                endif
4374770d09aSBram Moolenaar
4384770d09aSBram Moolenaar                let index = index + strlen(group_name)
439c06ac340SBram Moolenaar                let index = match(syntax_full, next_group_regex, index)
4404770d09aSBram Moolenaar            endwhile
4414770d09aSBram Moolenaar
442ad3b366cSBram Moolenaar            " let ftindex  = ftindex + len(ft_part_name)
443ad3b366cSBram Moolenaar            " let ftindex  = match( syntax_full, group_regex, ftindex )
444ad3b366cSBram Moolenaar        " endwhile
445ad3b366cSBram Moolenaar    endfor
446ad3b366cSBram Moolenaar
447ad3b366cSBram Moolenaar"   " Sometimes filetypes can be composite names, like c.doxygen
448ad3b366cSBram Moolenaar"   " Loop through each individual part looking for the syntax
449ad3b366cSBram Moolenaar"   " items specific to each individual filetype.
450ad3b366cSBram Moolenaar"   let syn_list = ''
451ad3b366cSBram Moolenaar"   let ftindex  = 0
452ad3b366cSBram Moolenaar"   let ftindex  = match(&filetype, '\w\+', ftindex)
453ad3b366cSBram Moolenaar
454ad3b366cSBram Moolenaar"   while ftindex > -1
455ad3b366cSBram Moolenaar"       let ft_part_name = matchstr( &filetype, '\w\+', ftindex )
456ad3b366cSBram Moolenaar
457ad3b366cSBram Moolenaar"       " Syntax rules can contain items for more than just the current
458ad3b366cSBram Moolenaar"       " filetype.  They can contain additional items added by the user
459ad3b366cSBram Moolenaar"       " via autocmds or their vimrc.
460ad3b366cSBram Moolenaar"       " Some syntax files can be combined (html, php, jsp).
461ad3b366cSBram Moolenaar"       " We want only items that begin with the filetype we are interested in.
462ad3b366cSBram Moolenaar"       let next_group_regex = '\n' .
463ad3b366cSBram Moolenaar"                   \ '\zs'.ft_part_name.'\w\+\ze'.
464ad3b366cSBram Moolenaar"                   \ '\s\+xxx\s\+'
465ad3b366cSBram Moolenaar"       let index    = 0
466ad3b366cSBram Moolenaar"       let index    = match(syntax_full, next_group_regex, index)
467ad3b366cSBram Moolenaar
468ad3b366cSBram Moolenaar"       if index == -1 && exists('b:current_syntax') && ft_part_name != b:current_syntax
469ad3b366cSBram Moolenaar"           " There appears to be two standards when writing syntax files.
470ad3b366cSBram Moolenaar"           " Either items begin as:
471ad3b366cSBram Moolenaar"           "     syn keyword {filetype}Keyword         values ...
472ad3b366cSBram Moolenaar"           "     let b:current_syntax = "sql"
473ad3b366cSBram Moolenaar"           "     let b:current_syntax = "sqlanywhere"
474ad3b366cSBram Moolenaar"           " Or
475ad3b366cSBram Moolenaar"           "     syn keyword {syntax_filename}Keyword  values ...
476ad3b366cSBram Moolenaar"           "     let b:current_syntax = "mysql"
477ad3b366cSBram Moolenaar"           " So, we will make the format of finding the syntax group names
478ad3b366cSBram Moolenaar"           " a bit more flexible and look for both if the first fails to
479ad3b366cSBram Moolenaar"           " find a match.
480ad3b366cSBram Moolenaar"           let next_group_regex = '\n' .
481ad3b366cSBram Moolenaar"                       \ '\zs'.b:current_syntax.'\w\+\ze'.
482ad3b366cSBram Moolenaar"                       \ '\s\+xxx\s\+'
483ad3b366cSBram Moolenaar"           let index    = 0
484ad3b366cSBram Moolenaar"           let index    = match(syntax_full, next_group_regex, index)
485ad3b366cSBram Moolenaar"       endif
486ad3b366cSBram Moolenaar
487ad3b366cSBram Moolenaar"       while index > -1
488ad3b366cSBram Moolenaar"           let group_name = matchstr( syntax_full, '\w\+', index )
489ad3b366cSBram Moolenaar
490ad3b366cSBram Moolenaar"           let get_syn_list = 1
491ad3b366cSBram Moolenaar"           for exclude_group_name in list_exclude_groups
492ad3b366cSBram Moolenaar"               if '\<'.exclude_group_name.'\>' =~ '\<'.group_name.'\>'
493ad3b366cSBram Moolenaar"                   let get_syn_list = 0
494ad3b366cSBram Moolenaar"               endif
495ad3b366cSBram Moolenaar"           endfor
496ad3b366cSBram Moolenaar
497ad3b366cSBram Moolenaar"           " This code is no longer needed in version 6.0 since we have
498ad3b366cSBram Moolenaar"           " augmented the syntax list command to only retrieve the syntax
499ad3b366cSBram Moolenaar"           " groups we are interested in.
500ad3b366cSBram Moolenaar"           "
501ad3b366cSBram Moolenaar"           " if get_syn_list == 1
502ad3b366cSBram Moolenaar"           "     if syntax_group_include_{filetype} != ''
503ad3b366cSBram Moolenaar"           "         if '\<'.syntax_group_include_{filetype}.'\>' !~ '\<'.group_name.'\>'
504ad3b366cSBram Moolenaar"           "             let get_syn_list = 0
505ad3b366cSBram Moolenaar"           "         endif
506ad3b366cSBram Moolenaar"           "     endif
507ad3b366cSBram Moolenaar"           " endif
508ad3b366cSBram Moolenaar
509ad3b366cSBram Moolenaar"           if get_syn_list == 1
510ad3b366cSBram Moolenaar"               " Pass in the full syntax listing, plus the group name we
511ad3b366cSBram Moolenaar"               " are interested in.
512ad3b366cSBram Moolenaar"               let extra_syn_list = s:SyntaxCSyntaxGroupItems(group_name, syntax_full)
513ad3b366cSBram Moolenaar"               let syn_list = syn_list . extra_syn_list . "\n"
514ad3b366cSBram Moolenaar"           endif
515ad3b366cSBram Moolenaar
516ad3b366cSBram Moolenaar"           let index = index + strlen(group_name)
517ad3b366cSBram Moolenaar"           let index = match(syntax_full, next_group_regex, index)
518ad3b366cSBram Moolenaar"       endwhile
519ad3b366cSBram Moolenaar
520ad3b366cSBram Moolenaar"       let ftindex  = ftindex + len(ft_part_name)
521ad3b366cSBram Moolenaar"       let ftindex  = match( &filetype, '\w\+', ftindex )
522ad3b366cSBram Moolenaar"   endwhile
52397e8f356SBram Moolenaar
524c06ac340SBram Moolenaar    " Convert the string to a List and sort it.
525c06ac340SBram Moolenaar    let compl_list = sort(split(syn_list))
526c06ac340SBram Moolenaar
527c06ac340SBram Moolenaar    if &filetype == 'vim'
528c06ac340SBram Moolenaar        let short_compl_list = []
529c06ac340SBram Moolenaar        for i in range(len(compl_list))
530c06ac340SBram Moolenaar            if i == len(compl_list)-1
531c06ac340SBram Moolenaar                let next = i
532c06ac340SBram Moolenaar            else
533c06ac340SBram Moolenaar                let next = i + 1
534c06ac340SBram Moolenaar            endif
535c06ac340SBram Moolenaar            if  compl_list[next] !~ '^'.compl_list[i].'.$'
536c06ac340SBram Moolenaar                let short_compl_list += [compl_list[i]]
537c06ac340SBram Moolenaar            endif
538c06ac340SBram Moolenaar        endfor
539c06ac340SBram Moolenaar
540c06ac340SBram Moolenaar        return short_compl_list
541c06ac340SBram Moolenaar    else
542c06ac340SBram Moolenaar        return compl_list
543c06ac340SBram Moolenaar    endif
5444770d09aSBram Moolenaarendfunction
5454770d09aSBram Moolenaar
546e2f98b95SBram Moolenaarfunction! s:SyntaxCSyntaxGroupItems( group_name, syntax_full )
5474770d09aSBram Moolenaar
548*4c295027SBram Moolenaar    " Allow user to override iskeyword per buffer
549*4c295027SBram Moolenaar    let l:omni_syntax_use_iskeyword = g:omni_syntax_use_iskeyword
550*4c295027SBram Moolenaar    if exists('b:omni_syntax_use_iskeyword')
551*4c295027SBram Moolenaar        let l:omni_syntax_use_iskeyword = b:omni_syntax_use_iskeyword
552*4c295027SBram Moolenaar    endif
553*4c295027SBram Moolenaar
554*4c295027SBram Moolenaar    " Allow user to override iskeyword_numeric per buffer
555*4c295027SBram Moolenaar    let l:omni_syntax_use_iskeyword_numeric = g:omni_syntax_use_iskeyword_numeric
556*4c295027SBram Moolenaar    if exists('b:omni_syntax_use_iskeyword_numeric')
557*4c295027SBram Moolenaar        let l:omni_syntax_use_iskeyword_numeric = b:omni_syntax_use_iskeyword_numeric
558*4c295027SBram Moolenaar    endif
559*4c295027SBram Moolenaar
560*4c295027SBram Moolenaar    " Allow user to override iskeyword_numeric per buffer
561*4c295027SBram Moolenaar    let l:omni_syntax_use_single_byte = g:omni_syntax_use_single_byte
562*4c295027SBram Moolenaar    if exists('b:omni_syntax_use_single_byte')
563*4c295027SBram Moolenaar        let l:omni_syntax_use_single_byte = b:omni_syntax_use_single_byte
564*4c295027SBram Moolenaar    endif
565*4c295027SBram Moolenaar
566*4c295027SBram Moolenaar    " Allow user to override minimum_length per buffer
567*4c295027SBram Moolenaar    let l:omni_syntax_minimum_length = g:omni_syntax_minimum_length
568*4c295027SBram Moolenaar    if exists('b:omni_syntax_minimum_length')
569*4c295027SBram Moolenaar        let l:omni_syntax_minimum_length = b:omni_syntax_minimum_length
570*4c295027SBram Moolenaar    endif
571*4c295027SBram Moolenaar
572c06ac340SBram Moolenaar    let syn_list = ""
5734770d09aSBram Moolenaar
574c06ac340SBram Moolenaar    " From the full syntax listing, strip out the portion for the
575c06ac340SBram Moolenaar    " request group.
576c06ac340SBram Moolenaar    " Query:
577c06ac340SBram Moolenaar    "     \n           - must begin with a newline
578c06ac340SBram Moolenaar    "     a:group_name - the group name we are interested in
579c06ac340SBram Moolenaar    "     \s\+xxx\s\+  - group names are always followed by xxx
580c06ac340SBram Moolenaar    "     \zs          - start the match
581c06ac340SBram Moolenaar    "     .\{-}        - everything ...
582c06ac340SBram Moolenaar    "     \ze          - end the match
5836dfc28beSBram Moolenaar    "     \(           - start a group or 2 potential matches
584c06ac340SBram Moolenaar    "     \n\w         - at the first newline starting with a character
5856dfc28beSBram Moolenaar    "     \|           - 2nd potential match
5866dfc28beSBram Moolenaar    "     \%$          - matches end of the file or string
5876dfc28beSBram Moolenaar    "     \)           - end a group
588c06ac340SBram Moolenaar    let syntax_group = matchstr(a:syntax_full,
5896dfc28beSBram Moolenaar                \ "\n".a:group_name.'\s\+xxx\s\+\zs.\{-}\ze\(\n\w\|\%$\)'
590c06ac340SBram Moolenaar                \ )
591c06ac340SBram Moolenaar
592c06ac340SBram Moolenaar    if syntax_group != ""
5934770d09aSBram Moolenaar        " let syn_list = substitute( @l, '^.*xxx\s*\%(contained\s*\)\?', "", '' )
594c06ac340SBram Moolenaar        " let syn_list = substitute( @l, '^.*xxx\s*', "", '' )
5954770d09aSBram Moolenaar
5969faec4e3SBram Moolenaar        " We only want the words for the lines beginning with
5974770d09aSBram Moolenaar        " containedin, but there could be other items.
5984770d09aSBram Moolenaar
5994770d09aSBram Moolenaar        " Tried to remove all lines that do not begin with contained
6004770d09aSBram Moolenaar        " but this does not work in all cases since you can have
6014770d09aSBram Moolenaar        "    contained nextgroup=...
6024770d09aSBram Moolenaar        " So this will strip off the ending of lines with known
6034770d09aSBram Moolenaar        " keywords.
60497e8f356SBram Moolenaar        let syn_list = substitute(
60597e8f356SBram Moolenaar                    \    syntax_group, '\<\('.
6064770d09aSBram Moolenaar                    \    substitute(
6074770d09aSBram Moolenaar                    \      escape(s:syn_remove_words, '\\/.*$^~[]')
60897e8f356SBram Moolenaar                    \      , ',', '\\|', 'g'
60997e8f356SBram Moolenaar                    \    ).
6104770d09aSBram Moolenaar                    \    '\).\{-}\%($\|'."\n".'\)'
61197e8f356SBram Moolenaar                    \    , "\n", 'g'
61297e8f356SBram Moolenaar                    \  )
6134770d09aSBram Moolenaar
614ad3b366cSBram Moolenaar        " Attempt to deal with lines using the match syntax
615ad3b366cSBram Moolenaar        " javaScriptDocTags xxx match /@\(param\|argument\|requires\|file\)\>/
616ad3b366cSBram Moolenaar        " Though it can use any types of regex, so this plugin will attempt
617ad3b366cSBram Moolenaar        " to restrict it
618ad3b366cSBram Moolenaar        " 1.  Only use \( or \%( constructs remove all else
619ad3b366cSBram Moolenaar        " 2   Remove and []s
620ad3b366cSBram Moolenaar        " 3.  Account for match //constructs
621ad3b366cSBram Moolenaar        "                       \%(\%(ms\|me\|hs\|he\|rs\|re\|lc\)\S\+\)\?
622ad3b366cSBram Moolenaar        " 4.  Hope for the best
623ad3b366cSBram Moolenaar        "
624ad3b366cSBram Moolenaar        "
625ad3b366cSBram Moolenaar        let syn_list_old = syn_list
626ad3b366cSBram Moolenaar        while syn_list =~ '\<match\>\s\+\/'
627ad3b366cSBram Moolenaar            if syn_list =~ 'perlElseIfError'
628ad3b366cSBram Moolenaar                let syn_list = syn_list
629ad3b366cSBram Moolenaar            endif
630ad3b366cSBram Moolenaar            " Check if the match has words at least 3 characters long
631ad3b366cSBram Moolenaar            if syn_list =~ '\<match \/\zs.\{-}\<\w\{3,}\>.\{-}\ze\\\@<!\/\%(\%(ms\|me\|hs\|he\|rs\|re\|lc\)\S\+\)\?\s\+'
632ad3b366cSBram Moolenaar                " Remove everything after / and before the first \(
633ad3b366cSBram Moolenaar                let syn_list = substitute( syn_list, '\<match \/\zs.\{-}\ze\\%\?(.\{-}\\\@<!\/\%(\%(ms\|me\|hs\|he\|rs\|re\|lc\)\S\+\)\?\s\+', '', 'g' )
634ad3b366cSBram Moolenaar                " Remove everything after \) and up to the ending /
635ad3b366cSBram Moolenaar                let syn_list = substitute( syn_list, '\<match \/.\{-}\\)\zs.\{-}\ze\/\%(\%(ms\|me\|hs\|he\|rs\|re\|lc\)\S\+\)\?\s\+', '', 'g' )
636ad3b366cSBram Moolenaar
637ad3b366cSBram Moolenaar                " Remove any character classes
638ad3b366cSBram Moolenaar                " let syn_list = substitute( syn_list, '\<match /\zs.\{-}\[[^]]*\].\{-}\ze\/ ', '', 'g' )
639ad3b366cSBram Moolenaar                let syn_list = substitute( syn_list, '\%(\<match \/[^/]\{-}\)\@<=\[[^]]*\]\ze.\{-}\\\@<!\/\%(\%(ms\|me\|hs\|he\|rs\|re\|lc\)\S\+\)\?', '', 'g' )
640ad3b366cSBram Moolenaar                " Remove any words < 3 characters
641ad3b366cSBram Moolenaar                let syn_list = substitute( syn_list, '\%(\<match \/[^/]\{-}\)\@<=\<\w\{1,2}\>\ze.\{-}\\\@<!\/\%(\%(ms\|me\|hs\|he\|rs\|re\|lc\)\S\+\)\?\s\+', '', 'g' )
642ad3b366cSBram Moolenaar                " Remove all non-word characters
643ad3b366cSBram Moolenaar                " let syn_list = substitute( syn_list, '\<match /\zs.\{-}\<\W\+\>.\{-}\ze\/ ', "", 'g' )
644ad3b366cSBram Moolenaar                " let syn_list = substitute( syn_list, '\%(\<match \/[^/]\{-}\)\@<=\W\+\ze.\{-}\/ ', ' ', 'g' )
64556c860c3SBram Moolenaar                " Do this by using the outer substitute() call to gather all
646ad3b366cSBram Moolenaar                " text between the match /.../ tags.
647ad3b366cSBram Moolenaar                " The inner substitute() call operates on the text selected
648ad3b366cSBram Moolenaar                " and replaces all non-word characters.
649ad3b366cSBram Moolenaar                let syn_list = substitute( syn_list, '\<match \/\zs\(.\{-}\)\ze\\\@<!\/\%(\%(ms\|me\|hs\|he\|rs\|re\|lc\)\S\+\)\?\s\+'
650ad3b366cSBram Moolenaar                            \ , '\=substitute(submatch(1), "\\W\\+", " ", "g")'
651ad3b366cSBram Moolenaar                            \ , 'g' )
652ad3b366cSBram Moolenaar                " Remove the match / / syntax
653ad3b366cSBram Moolenaar                let syn_list = substitute( syn_list, '\<match \/\(.\{-}\)\/\%(\%(ms\|me\|hs\|he\|rs\|re\|lc\)\S\+\)\?\s\+', '\1', 'g' )
654ad3b366cSBram Moolenaar            else
655ad3b366cSBram Moolenaar                " No words long enough, remove the match
656ad3b366cSBram Moolenaar                " Remove the match syntax
657ad3b366cSBram Moolenaar                " let syn_list = substitute( syn_list, '\<match \/[^\/]*\/\%(\%(ms\|me\|hs\|he\|rs\|re\|lc\)\S\+\)\?\s\+', '', 'g' )
658ad3b366cSBram Moolenaar                let syn_list = substitute( syn_list, '\<match \/\%(.\{-}\)\?\/\%(\%(ms\|me\|hs\|he\|rs\|re\|lc\)\S\+\)\?\s\+', '', 'g' )
659ad3b366cSBram Moolenaar            endif
660ad3b366cSBram Moolenaar            if syn_list =~ '\<match\>\s\+\/'
661ad3b366cSBram Moolenaar                " Problem removing the match / / tags
662ad3b366cSBram Moolenaar                let syn_list = ''
663ad3b366cSBram Moolenaar            endif
664ad3b366cSBram Moolenaar        endwhile
665ad3b366cSBram Moolenaar
666ad3b366cSBram Moolenaar
667f1568ecaSBram Moolenaar        " Now strip off the newline + blank space + contained.
668f1568ecaSBram Moolenaar        " Also include lines with nextgroup=@someName skip_key_words syntax_element
669ad3b366cSBram Moolenaar                    " \    syn_list, '\%(^\|\n\)\@<=\s*\<\(contained\|nextgroup=\)'
670ad3b366cSBram Moolenaar                    " \    syn_list, '\%(^\|\n\)\@<=\s*\<\(contained\|nextgroup=[@a-zA-Z,]*\)'
67197e8f356SBram Moolenaar        let syn_list = substitute(
672ad3b366cSBram Moolenaar                    \    syn_list, '\<\(contained\|nextgroup=[@a-zA-Z,]*\)'
673f1568ecaSBram Moolenaar                    \    , "", 'g'
674f1568ecaSBram Moolenaar                    \ )
675f1568ecaSBram Moolenaar
676f1568ecaSBram Moolenaar        " This can leave lines like this
677f1568ecaSBram Moolenaar        "     =@vimMenuList  skipwhite onoremenu
678f1568ecaSBram Moolenaar        " Strip the special option keywords first
679f1568ecaSBram Moolenaar        "     :h :syn-skipwhite*
680f1568ecaSBram Moolenaar        let syn_list = substitute(
681f1568ecaSBram Moolenaar                    \    syn_list, '\<\(skipwhite\|skipnl\|skipempty\)\>'
682f1568ecaSBram Moolenaar                    \    , "", 'g'
683f1568ecaSBram Moolenaar                    \ )
684f1568ecaSBram Moolenaar
685f1568ecaSBram Moolenaar        " Now remove the remainder of the nextgroup=@someName lines
686f1568ecaSBram Moolenaar        let syn_list = substitute(
687f1568ecaSBram Moolenaar                    \    syn_list, '\%(^\|\n\)\@<=\s*\(@\w\+\)'
68897e8f356SBram Moolenaar                    \    , "", 'g'
68997e8f356SBram Moolenaar                    \ )
6904770d09aSBram Moolenaar
691*4c295027SBram Moolenaar        if l:omni_syntax_use_iskeyword == 0
6924770d09aSBram Moolenaar            " There are a number of items which have non-word characters in
6934770d09aSBram Moolenaar            " them, *'T_F1'*.  vim.vim is one such file.
6944770d09aSBram Moolenaar            " This will replace non-word characters with spaces.
695*4c295027SBram Moolenaar            "   setlocal filetype=forth
696*4c295027SBram Moolenaar            "   let g:omni_syntax_use_iskeyword = 1
697*4c295027SBram Moolenaar            "   let g:omni_syntax_use_iskeyword_numeric = 1
698*4c295027SBram Moolenaar            " You will see entries like
699*4c295027SBram Moolenaar            "   #>>
700*4c295027SBram Moolenaar            "   (.local)
701*4c295027SBram Moolenaar            " These were found doing a grep in vim82\syntax
702*4c295027SBram Moolenaar            "   grep iskeyword *
703*4c295027SBram Moolenaar            "   forth.vim:setlocal iskeyword=!,@,33-35,%,$,38-64,A-Z,91-96,a-z,123-126,128-255
7044770d09aSBram Moolenaar            let syn_list = substitute( syn_list, '[^0-9A-Za-z_ ]', ' ', 'g' )
7054770d09aSBram Moolenaar        else
706*4c295027SBram Moolenaar            if l:omni_syntax_use_iskeyword_numeric == 1
70797d62497SBram Moolenaar                " iskeyword can contain value like this
70897d62497SBram Moolenaar                " 38,42,43,45,47-58,60-62,64-90,97-122,_,+,-,*,/,%,<,=,>,:,$,?,!,@-@,94
70997d62497SBram Moolenaar                " Numeric values convert to their ASCII equivalent using the
71097d62497SBram Moolenaar                " nr2char() function.
71197d62497SBram Moolenaar                "     &       38
71297d62497SBram Moolenaar                "     *       42
71397d62497SBram Moolenaar                "     +       43
71497d62497SBram Moolenaar                "     -       45
71597d62497SBram Moolenaar                "     ^       94
71697d62497SBram Moolenaar                " Iterate through all numeric specifications and convert those
71797d62497SBram Moolenaar                " to their ascii equivalent ensuring the character is printable.
71897d62497SBram Moolenaar                " If so, add it to the list.
71997d62497SBram Moolenaar                let accepted_chars = ''
72097d62497SBram Moolenaar                for item in split(&iskeyword, ',')
721ad3b366cSBram Moolenaar                    if item =~ '\d-\d'
72297d62497SBram Moolenaar                        " This is a character range (ie 47-58),
72397d62497SBram Moolenaar                        " cycle through each character within the range
72497d62497SBram Moolenaar                        let [b:start, b:end] = split(item, '-')
72597d62497SBram Moolenaar                        for range_item in range( b:start, b:end )
726*4c295027SBram Moolenaar                            if range_item <= 127 || l:omni_syntax_use_single_byte == 0
72797d62497SBram Moolenaar                                if nr2char(range_item) =~ '\p'
72897d62497SBram Moolenaar                                    let accepted_chars = accepted_chars . nr2char(range_item)
72997d62497SBram Moolenaar                                endif
73097d62497SBram Moolenaar                            endif
73197d62497SBram Moolenaar                        endfor
73297d62497SBram Moolenaar                    elseif item =~ '^\d\+$'
73397d62497SBram Moolenaar                        " Only numeric, translate to a character
734*4c295027SBram Moolenaar                        if item < 127 || l:omni_syntax_use_single_byte == 0
73597d62497SBram Moolenaar                            if nr2char(item) =~ '\p'
73697d62497SBram Moolenaar                                let accepted_chars = accepted_chars . nr2char(item)
73797d62497SBram Moolenaar                            endif
73897d62497SBram Moolenaar                        endif
73997d62497SBram Moolenaar                    else
740*4c295027SBram Moolenaar                        if char2nr(item) < 127 || l:omni_syntax_use_single_byte == 0
74197d62497SBram Moolenaar                            if item =~ '\p'
74297d62497SBram Moolenaar                                let accepted_chars = accepted_chars . item
74397d62497SBram Moolenaar                            endif
74497d62497SBram Moolenaar                        endif
74597d62497SBram Moolenaar                    endif
74697d62497SBram Moolenaar                endfor
74797d62497SBram Moolenaar                " Escape special regex characters
74834feacbcSBram Moolenaar                " Looks like the wrong chars are escaped.  In a collection,
74934feacbcSBram Moolenaar                "      :h /[]
75034feacbcSBram Moolenaar                "      only `]', `\', `-' and `^' are special:
75134feacbcSBram Moolenaar                " let accepted_chars = escape(accepted_chars, '\\/.*$^~[]' )
75234feacbcSBram Moolenaar                let accepted_chars = escape(accepted_chars, ']\-^' )
75397d62497SBram Moolenaar                " Remove all characters that are not acceptable
75497d62497SBram Moolenaar                let syn_list = substitute( syn_list, '[^A-Za-z'.accepted_chars.']', ' ', 'g' )
75597d62497SBram Moolenaar            else
7569964e468SBram Moolenaar                let accept_chars = ','.&iskeyword.','
7579964e468SBram Moolenaar                " Remove all character ranges
7583577c6faSBram Moolenaar                " let accept_chars = substitute(accept_chars, ',[^,]\+-[^,]\+,', ',', 'g')
7593577c6faSBram Moolenaar                let accept_chars = substitute(accept_chars, ',\@<=[^,]\+-[^,]\+,', '', 'g')
7609964e468SBram Moolenaar                " Remove all numeric specifications
7613577c6faSBram Moolenaar                " let accept_chars = substitute(accept_chars, ',\d\{-},', ',', 'g')
7623577c6faSBram Moolenaar                let accept_chars = substitute(accept_chars, ',\@<=\d\{-},', '', 'g')
7639964e468SBram Moolenaar                " Remove all commas
7649964e468SBram Moolenaar                let accept_chars = substitute(accept_chars, ',', '', 'g')
7659964e468SBram Moolenaar                " Escape special regex characters
76634feacbcSBram Moolenaar                " Looks like the wrong chars are escaped.  In a collection,
76734feacbcSBram Moolenaar                "      :h /[]
76834feacbcSBram Moolenaar                "      only `]', `\', `-' and `^' are special:
76934feacbcSBram Moolenaar                " let accept_chars = escape(accept_chars, '\\/.*$^~[]' )
77034feacbcSBram Moolenaar                let accept_chars = escape(accept_chars, ']\-^' )
7719964e468SBram Moolenaar                " Remove all characters that are not acceptable
7729964e468SBram Moolenaar                let syn_list = substitute( syn_list, '[^0-9A-Za-z_'.accept_chars.']', ' ', 'g' )
7739964e468SBram Moolenaar            endif
77497d62497SBram Moolenaar        endif
7759964e468SBram Moolenaar
776*4c295027SBram Moolenaar        if l:omni_syntax_minimum_length > 0
7779964e468SBram Moolenaar            " If the user specified a minimum length, enforce it
778*4c295027SBram Moolenaar            let syn_list = substitute(' '.syn_list.' ', ' \S\{,'.l:omni_syntax_minimum_length.'}\ze ', ' ', 'g')
7799964e468SBram Moolenaar        endif
7809964e468SBram Moolenaar    else
7814770d09aSBram Moolenaar        let syn_list = ''
7824770d09aSBram Moolenaar    endif
7834770d09aSBram Moolenaar
7844770d09aSBram Moolenaar    return syn_list
7854770d09aSBram Moolenaarendfunction
78697d62497SBram Moolenaar
78797d62497SBram Moolenaarfunction! OmniSyntaxShowChars(spec)
78897d62497SBram Moolenaar  let result = []
78997d62497SBram Moolenaar  for item in split(a:spec, ',')
79097d62497SBram Moolenaar    if len(item) > 1
79197d62497SBram Moolenaar      if item == '@-@'
79297d62497SBram Moolenaar        call add(result, char2nr(item))
79397d62497SBram Moolenaar      else
79497d62497SBram Moolenaar        call extend(result, call('range', split(item, '-')))
79597d62497SBram Moolenaar      endif
79697d62497SBram Moolenaar    else
79797d62497SBram Moolenaar      if item == '@'  " assume this is [A-Za-z]
79897d62497SBram Moolenaar        for [c1, c2] in [['A', 'Z'], ['a', 'z']]
79997d62497SBram Moolenaar          call extend(result, range(char2nr(c1), char2nr(c2)))
80097d62497SBram Moolenaar        endfor
80197d62497SBram Moolenaar      else
80297d62497SBram Moolenaar        call add(result, char2nr(item))
80397d62497SBram Moolenaar      endif
80497d62497SBram Moolenaar    endif
80597d62497SBram Moolenaar  endfor
80697d62497SBram Moolenaar  return join(map(result, 'nr2char(v:val)'), ', ')
80797d62497SBram Moolenaarendfunction
808*4c295027SBram Moolenaar
80997d62497SBram Moolenaarlet &cpo = s:cpo_save
81097d62497SBram Moolenaarunlet s:cpo_save
811