GPQAPP

Форк
0
202 строки · 7.0 Кб
1
// CodeMirror, copyright (c) by Marijn Haverbeke and others
2
// Distributed under an MIT license: https://codemirror.net/LICENSE
3

4
(function(mod) {
5
  if (typeof exports == "object" && typeof module == "object") // CommonJS
6
    mod(require("../../lib/codemirror"));
7
  else if (typeof define == "function" && define.amd) // AMD
8
    define(["../../lib/codemirror"], mod);
9
  else // Plain browser env
10
    mod(CodeMirror);
11
})(function(CodeMirror) {
12
"use strict";
13

14
CodeMirror.defineMode("velocity", function() {
15
    function parseWords(str) {
16
        var obj = {}, words = str.split(" ");
17
        for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
18
        return obj;
19
    }
20

21
    var keywords = parseWords("#end #else #break #stop #[[ #]] " +
22
                              "#{end} #{else} #{break} #{stop}");
23
    var functions = parseWords("#if #elseif #foreach #set #include #parse #macro #define #evaluate " +
24
                               "#{if} #{elseif} #{foreach} #{set} #{include} #{parse} #{macro} #{define} #{evaluate}");
25
    var specials = parseWords("$foreach.count $foreach.hasNext $foreach.first $foreach.last $foreach.topmost $foreach.parent.count $foreach.parent.hasNext $foreach.parent.first $foreach.parent.last $foreach.parent $velocityCount $!bodyContent $bodyContent");
26
    var isOperatorChar = /[+\-*&%=<>!?:\/|]/;
27

28
    function chain(stream, state, f) {
29
        state.tokenize = f;
30
        return f(stream, state);
31
    }
32
    function tokenBase(stream, state) {
33
        var beforeParams = state.beforeParams;
34
        state.beforeParams = false;
35
        var ch = stream.next();
36
        // start of unparsed string?
37
        if ((ch == "'") && !state.inString && state.inParams) {
38
            state.lastTokenWasBuiltin = false;
39
            return chain(stream, state, tokenString(ch));
40
        }
41
        // start of parsed string?
42
        else if ((ch == '"')) {
43
            state.lastTokenWasBuiltin = false;
44
            if (state.inString) {
45
                state.inString = false;
46
                return "string";
47
            }
48
            else if (state.inParams)
49
                return chain(stream, state, tokenString(ch));
50
        }
51
        // is it one of the special signs []{}().,;? Separator?
52
        else if (/[\[\]{}\(\),;\.]/.test(ch)) {
53
            if (ch == "(" && beforeParams)
54
                state.inParams = true;
55
            else if (ch == ")") {
56
                state.inParams = false;
57
                state.lastTokenWasBuiltin = true;
58
            }
59
            return null;
60
        }
61
        // start of a number value?
62
        else if (/\d/.test(ch)) {
63
            state.lastTokenWasBuiltin = false;
64
            stream.eatWhile(/[\w\.]/);
65
            return "number";
66
        }
67
        // multi line comment?
68
        else if (ch == "#" && stream.eat("*")) {
69
            state.lastTokenWasBuiltin = false;
70
            return chain(stream, state, tokenComment);
71
        }
72
        // unparsed content?
73
        else if (ch == "#" && stream.match(/ *\[ *\[/)) {
74
            state.lastTokenWasBuiltin = false;
75
            return chain(stream, state, tokenUnparsed);
76
        }
77
        // single line comment?
78
        else if (ch == "#" && stream.eat("#")) {
79
            state.lastTokenWasBuiltin = false;
80
            stream.skipToEnd();
81
            return "comment";
82
        }
83
        // variable?
84
        else if (ch == "$") {
85
            stream.eat("!");
86
            stream.eatWhile(/[\w\d\$_\.{}-]/);
87
            // is it one of the specials?
88
            if (specials && specials.propertyIsEnumerable(stream.current())) {
89
                return "keyword";
90
            }
91
            else {
92
                state.lastTokenWasBuiltin = true;
93
                state.beforeParams = true;
94
                return "builtin";
95
            }
96
        }
97
        // is it a operator?
98
        else if (isOperatorChar.test(ch)) {
99
            state.lastTokenWasBuiltin = false;
100
            stream.eatWhile(isOperatorChar);
101
            return "operator";
102
        }
103
        else {
104
            // get the whole word
105
            stream.eatWhile(/[\w\$_{}@]/);
106
            var word = stream.current();
107
            // is it one of the listed keywords?
108
            if (keywords && keywords.propertyIsEnumerable(word))
109
                return "keyword";
110
            // is it one of the listed functions?
111
            if (functions && functions.propertyIsEnumerable(word) ||
112
                    (stream.current().match(/^#@?[a-z0-9_]+ *$/i) && stream.peek()=="(") &&
113
                     !(functions && functions.propertyIsEnumerable(word.toLowerCase()))) {
114
                state.beforeParams = true;
115
                state.lastTokenWasBuiltin = false;
116
                return "keyword";
117
            }
118
            if (state.inString) {
119
                state.lastTokenWasBuiltin = false;
120
                return "string";
121
            }
122
            if (stream.pos > word.length && stream.string.charAt(stream.pos-word.length-1)=="." && state.lastTokenWasBuiltin)
123
                return "builtin";
124
            // default: just a "word"
125
            state.lastTokenWasBuiltin = false;
126
            return null;
127
        }
128
    }
129

130
    function tokenString(quote) {
131
        return function(stream, state) {
132
            var escaped = false, next, end = false;
133
            while ((next = stream.next()) != null) {
134
                if ((next == quote) && !escaped) {
135
                    end = true;
136
                    break;
137
                }
138
                if (quote=='"' && stream.peek() == '$' && !escaped) {
139
                    state.inString = true;
140
                    end = true;
141
                    break;
142
                }
143
                escaped = !escaped && next == "\\";
144
            }
145
            if (end) state.tokenize = tokenBase;
146
            return "string";
147
        };
148
    }
149

150
    function tokenComment(stream, state) {
151
        var maybeEnd = false, ch;
152
        while (ch = stream.next()) {
153
            if (ch == "#" && maybeEnd) {
154
                state.tokenize = tokenBase;
155
                break;
156
            }
157
            maybeEnd = (ch == "*");
158
        }
159
        return "comment";
160
    }
161

162
    function tokenUnparsed(stream, state) {
163
        var maybeEnd = 0, ch;
164
        while (ch = stream.next()) {
165
            if (ch == "#" && maybeEnd == 2) {
166
                state.tokenize = tokenBase;
167
                break;
168
            }
169
            if (ch == "]")
170
                maybeEnd++;
171
            else if (ch != " ")
172
                maybeEnd = 0;
173
        }
174
        return "meta";
175
    }
176
    // Interface
177

178
    return {
179
        startState: function() {
180
            return {
181
                tokenize: tokenBase,
182
                beforeParams: false,
183
                inParams: false,
184
                inString: false,
185
                lastTokenWasBuiltin: false
186
            };
187
        },
188

189
        token: function(stream, state) {
190
            if (stream.eatSpace()) return null;
191
            return state.tokenize(stream, state);
192
        },
193
        blockCommentStart: "#*",
194
        blockCommentEnd: "*#",
195
        lineComment: "##",
196
        fold: "velocity"
197
    };
198
});
199

200
CodeMirror.defineMIME("text/velocity", "velocity");
201

202
});
203

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.