vis: implement :set cursorline
[vis.git] / lexers / wsf.lua
blobfc024b2dad732cc4afd2c5e25004b5e5fc324542
1 -- Copyright 2006-2015 Mitchell mitchell.att.foicica.com. See LICENSE.
2 -- WSF LPeg lexer (based on XML).
3 -- Contributed by Jeff Stone.
5 local l = require('lexer')
6 local token, word_match = l.token, l.word_match
7 local P, R, S, V = lpeg.P, lpeg.R, lpeg.S, lpeg.V
9 local M = {_NAME = 'wsf'}
11 -- Whitespace.
12 local ws = token(l.WHITESPACE, l.space^1)
14 -- Comments.
15 local comment = token(l.COMMENT, '<!--' * (l.any - '-->')^0 * P('-->')^-1)
17 -- Strings.
18 local sq_str = l.delimited_range("'", false, true)
19 local dq_str = l.delimited_range('"', false, true)
20 local string = #S('\'"') * l.last_char_includes('=') *
21 token(l.STRING, sq_str + dq_str)
23 local in_tag = P(function(input, index)
24 local before = input:sub(1, index - 1)
25 local s, e = before:find('<[^>]-$'), before:find('>[^<]-$')
26 if s and e then return s > e and index or nil end
27 if s then return index end
28 return input:find('^[^<]->', index) and index or nil
29 end)
31 -- Numbers.
32 local number = #l.digit * l.last_char_includes('=') *
33 token(l.NUMBER, l.digit^1 * P('%')^-1) * in_tag
35 local alpha = R('az', 'AZ', '\127\255')
36 local word_char = l.alnum + S('_-:.??')
37 local identifier = (l.alpha + S('_-:.??')) * word_char^0
39 -- Elements.
40 local element = token('element', '<' * P('/')^-1 * identifier)
42 -- Attributes.
43 local attribute = token('attribute', identifier) * #(l.space^0 * '=')
45 -- Closing tags.
46 local tag_close = token('element', P('/')^-1 * '>')
48 -- Equals.
49 local equals = token(l.OPERATOR, '=') * in_tag
51 -- Entities.
52 local entity = token('entity', '&' * word_match{
53 'lt', 'gt', 'amp', 'apos', 'quot'
54 } * ';')
56 M._rules = {
57 {'whitespace', ws},
58 {'comment', comment},
59 {'element', element},
60 {'tag_close', tag_close},
61 {'attribute', attribute},
62 {'equals', equals},
63 {'string', string},
64 {'number', number},
65 {'entity', entity}
68 M._tokenstyles = {
69 element = l.STYLE_KEYWORD,
70 attribute = l.STYLE_TYPE,
71 entity = l.STYLE_OPERATOR
74 M._foldsymbols = {
75 _patterns = {'</?', '/>', '<!%-%-', '%-%->'},
76 element = {['<'] = 1, ['/>'] = -1, ['</'] = -1},
77 [l.COMMENT] = {['<!--'] = 1, ['-->'] = -1},
80 -- Finally, add JavaScript and VBScript as embedded languages
82 -- Tags that start embedded languages.
83 M.embed_start_tag = element *
84 (ws^1 * attribute * ws^0 * equals * ws^0 * string)^0 *
85 ws^0 * tag_close
86 M.embed_end_tag = element * tag_close
88 -- Embedded JavaScript.
89 local js = l.load('javascript')
90 local js_start_rule = #(P('<script') * (P(function(input, index)
91 if input:find('^%s+language%s*=%s*(["\'])[jJ][ava]*[sS]cript%1', index) then
92 return index
93 end
94 end) + '>')) * M.embed_start_tag -- <script language="javascript">
95 local js_end_rule = #('</script' * ws^0 * '>') * M.embed_end_tag -- </script>
96 l.embed_lexer(M, js, js_start_rule, js_end_rule)
98 -- Embedded VBScript.
99 local vbs = l.load('vbscript')
100 local vbs_start_rule = #(P('<script') * (P(function(input, index)
101 if input:find('^%s+language%s*=%s*(["\'])[vV][bB][sS]cript%1', index) then
102 return index
104 end) + '>')) * M.embed_start_tag -- <script language="vbscript">
105 local vbs_end_rule = #('</script' * ws^0 * '>') * M.embed_end_tag -- </script>
106 l.embed_lexer(M, vbs, vbs_start_rule, vbs_end_rule)
108 return M