0
|
1 // CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
2 // Distributed under an MIT license: https://codemirror.net/5/LICENSE
|
|
3
|
|
4 /*
|
|
5 * =====================================================================================
|
|
6 *
|
|
7 * Filename: mode/asterisk/asterisk.js
|
|
8 *
|
|
9 * Description: CodeMirror mode for Asterisk dialplan
|
|
10 *
|
|
11 * Created: 05/17/2012 09:20:25 PM
|
|
12 * Revision: 08/05/2019 AstLinux Project: Support block-comments
|
|
13 *
|
|
14 * Author: Stas Kobzar (stas@modulis.ca),
|
|
15 * Company: Modulis.ca Inc.
|
|
16 *
|
|
17 * =====================================================================================
|
|
18 */
|
|
19
|
|
20 (function(mod) {
|
|
21 if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|
22 mod(require("../../lib/codemirror"));
|
|
23 else if (typeof define == "function" && define.amd) // AMD
|
|
24 define(["../../lib/codemirror"], mod);
|
|
25 else // Plain browser env
|
|
26 mod(CodeMirror);
|
|
27 })(function(CodeMirror) {
|
|
28 "use strict";
|
|
29
|
|
30 CodeMirror.defineMode("asterisk", function() {
|
|
31 var atoms = ["exten", "same", "include","ignorepat","switch"],
|
|
32 dpcmd = ["#include","#exec"],
|
|
33 apps = [
|
|
34 "addqueuemember","adsiprog","aelsub","agentlogin","agentmonitoroutgoing","agi",
|
|
35 "alarmreceiver","amd","answer","authenticate","background","backgrounddetect",
|
|
36 "bridge","busy","callcompletioncancel","callcompletionrequest","celgenuserevent",
|
|
37 "changemonitor","chanisavail","channelredirect","chanspy","clearhash","confbridge",
|
|
38 "congestion","continuewhile","controlplayback","dahdiacceptr2call","dahdibarge",
|
|
39 "dahdiras","dahdiscan","dahdisendcallreroutingfacility","dahdisendkeypadfacility",
|
|
40 "datetime","dbdel","dbdeltree","deadagi","dial","dictate","directory","disa",
|
|
41 "dumpchan","eagi","echo","endwhile","exec","execif","execiftime","exitwhile","extenspy",
|
|
42 "externalivr","festival","flash","followme","forkcdr","getcpeid","gosub","gosubif",
|
|
43 "goto","gotoif","gotoiftime","hangup","iax2provision","ices","importvar","incomplete",
|
|
44 "ivrdemo","jabberjoin","jabberleave","jabbersend","jabbersendgroup","jabberstatus",
|
|
45 "jack","log","macro","macroexclusive","macroexit","macroif","mailboxexists","meetme",
|
|
46 "meetmeadmin","meetmechanneladmin","meetmecount","milliwatt","minivmaccmess","minivmdelete",
|
|
47 "minivmgreet","minivmmwi","minivmnotify","minivmrecord","mixmonitor","monitor","morsecode",
|
|
48 "mp3player","mset","musiconhold","nbscat","nocdr","noop","odbc","odbc","odbcfinish",
|
|
49 "originate","ospauth","ospfinish","osplookup","ospnext","page","park","parkandannounce",
|
|
50 "parkedcall","pausemonitor","pausequeuemember","pickup","pickupchan","playback","playtones",
|
|
51 "privacymanager","proceeding","progress","queue","queuelog","raiseexception","read","readexten",
|
|
52 "readfile","receivefax","receivefax","receivefax","record","removequeuemember",
|
|
53 "resetcdr","retrydial","return","ringing","sayalpha","saycountedadj","saycountednoun",
|
|
54 "saycountpl","saydigits","saynumber","sayphonetic","sayunixtime","senddtmf","sendfax",
|
|
55 "sendfax","sendfax","sendimage","sendtext","sendurl","set","setamaflags",
|
|
56 "setcallerpres","setmusiconhold","sipaddheader","sipdtmfmode","sipremoveheader","skel",
|
|
57 "slastation","slatrunk","sms","softhangup","speechactivategrammar","speechbackground",
|
|
58 "speechcreate","speechdeactivategrammar","speechdestroy","speechloadgrammar","speechprocessingsound",
|
|
59 "speechstart","speechunloadgrammar","stackpop","startmusiconhold","stopmixmonitor","stopmonitor",
|
|
60 "stopmusiconhold","stopplaytones","system","testclient","testserver","transfer","tryexec",
|
|
61 "trysystem","unpausemonitor","unpausequeuemember","userevent","verbose","vmauthenticate",
|
|
62 "vmsayname","voicemail","voicemailmain","wait","waitexten","waitfornoise","waitforring",
|
|
63 "waitforsilence","waitmusiconhold","waituntil","while","zapateller"
|
|
64 ];
|
|
65
|
|
66 function basicToken(stream,state){
|
|
67 var cur = '';
|
|
68 var ch = stream.next();
|
|
69 // comment
|
|
70 if (state.blockComment) {
|
|
71 if (ch == "-" && stream.match("-;", true)) {
|
|
72 state.blockComment = false;
|
|
73 } else if (stream.skipTo("--;")) {
|
|
74 stream.next();
|
|
75 stream.next();
|
|
76 stream.next();
|
|
77 state.blockComment = false;
|
|
78 } else {
|
|
79 stream.skipToEnd();
|
|
80 }
|
|
81 return "comment";
|
|
82 }
|
|
83 if(ch == ";") {
|
|
84 if (stream.match("--", true)) {
|
|
85 if (!stream.match("-", false)) { // Except ;--- is not a block comment
|
|
86 state.blockComment = true;
|
|
87 return "comment";
|
|
88 }
|
|
89 }
|
|
90 stream.skipToEnd();
|
|
91 return "comment";
|
|
92 }
|
|
93 // context
|
|
94 if(ch == '[') {
|
|
95 stream.skipTo(']');
|
|
96 stream.eat(']');
|
|
97 return "header";
|
|
98 }
|
|
99 // string
|
|
100 if(ch == '"') {
|
|
101 stream.skipTo('"');
|
|
102 return "string";
|
|
103 }
|
|
104 if(ch == "'") {
|
|
105 stream.skipTo("'");
|
|
106 return "string-2";
|
|
107 }
|
|
108 // dialplan commands
|
|
109 if(ch == '#') {
|
|
110 stream.eatWhile(/\w/);
|
|
111 cur = stream.current();
|
|
112 if(dpcmd.indexOf(cur) !== -1) {
|
|
113 stream.skipToEnd();
|
|
114 return "strong";
|
|
115 }
|
|
116 }
|
|
117 // application args
|
|
118 if(ch == '$'){
|
|
119 var ch1 = stream.peek();
|
|
120 if(ch1 == '{'){
|
|
121 stream.skipTo('}');
|
|
122 stream.eat('}');
|
|
123 return "variable-3";
|
|
124 }
|
|
125 }
|
|
126 // extension
|
|
127 stream.eatWhile(/\w/);
|
|
128 cur = stream.current();
|
|
129 if(atoms.indexOf(cur) !== -1) {
|
|
130 state.extenStart = true;
|
|
131 switch(cur) {
|
|
132 case 'same': state.extenSame = true; break;
|
|
133 case 'include':
|
|
134 case 'switch':
|
|
135 case 'ignorepat':
|
|
136 state.extenInclude = true;break;
|
|
137 default:break;
|
|
138 }
|
|
139 return "atom";
|
|
140 }
|
|
141 }
|
|
142
|
|
143 return {
|
|
144 startState: function() {
|
|
145 return {
|
|
146 blockComment: false,
|
|
147 extenStart: false,
|
|
148 extenSame: false,
|
|
149 extenInclude: false,
|
|
150 extenExten: false,
|
|
151 extenPriority: false,
|
|
152 extenApplication: false
|
|
153 };
|
|
154 },
|
|
155 token: function(stream, state) {
|
|
156
|
|
157 var cur = '';
|
|
158 if(stream.eatSpace()) return null;
|
|
159 // extension started
|
|
160 if(state.extenStart){
|
|
161 stream.eatWhile(/[^\s]/);
|
|
162 cur = stream.current();
|
|
163 if(/^=>?$/.test(cur)){
|
|
164 state.extenExten = true;
|
|
165 state.extenStart = false;
|
|
166 return "strong";
|
|
167 } else {
|
|
168 state.extenStart = false;
|
|
169 stream.skipToEnd();
|
|
170 return "error";
|
|
171 }
|
|
172 } else if(state.extenExten) {
|
|
173 // set exten and priority
|
|
174 state.extenExten = false;
|
|
175 state.extenPriority = true;
|
|
176 stream.eatWhile(/[^,]/);
|
|
177 if(state.extenInclude) {
|
|
178 stream.skipToEnd();
|
|
179 state.extenPriority = false;
|
|
180 state.extenInclude = false;
|
|
181 }
|
|
182 if(state.extenSame) {
|
|
183 state.extenPriority = false;
|
|
184 state.extenSame = false;
|
|
185 state.extenApplication = true;
|
|
186 }
|
|
187 return "tag";
|
|
188 } else if(state.extenPriority) {
|
|
189 state.extenPriority = false;
|
|
190 state.extenApplication = true;
|
|
191 stream.next(); // get comma
|
|
192 if(state.extenSame) return null;
|
|
193 stream.eatWhile(/[^,]/);
|
|
194 return "number";
|
|
195 } else if(state.extenApplication) {
|
|
196 stream.eatWhile(/,/);
|
|
197 cur = stream.current();
|
|
198 if(cur === ',') return null;
|
|
199 stream.eatWhile(/\w/);
|
|
200 cur = stream.current().toLowerCase();
|
|
201 state.extenApplication = false;
|
|
202 if(apps.indexOf(cur) !== -1){
|
|
203 return "def strong";
|
|
204 }
|
|
205 } else{
|
|
206 return basicToken(stream,state);
|
|
207 }
|
|
208
|
|
209 return null;
|
|
210 },
|
|
211
|
|
212 blockCommentStart: ";--",
|
|
213 blockCommentEnd: "--;",
|
|
214 lineComment: ";"
|
|
215 };
|
|
216 });
|
|
217
|
|
218 CodeMirror.defineMIME("text/x-asterisk", "asterisk");
|
|
219
|
|
220 });
|