You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

220 lines
8.0 KiB

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