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.

196 lines
7.3 KiB

  1. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  2. // Distributed under an MIT license: http://codemirror.net/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: none
  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(ch == ";") {
  67. stream.skipToEnd();
  68. return "comment";
  69. }
  70. // context
  71. if(ch == '[') {
  72. stream.skipTo(']');
  73. stream.eat(']');
  74. return "header";
  75. }
  76. // string
  77. if(ch == '"') {
  78. stream.skipTo('"');
  79. return "string";
  80. }
  81. if(ch == "'") {
  82. stream.skipTo("'");
  83. return "string-2";
  84. }
  85. // dialplan commands
  86. if(ch == '#') {
  87. stream.eatWhile(/\w/);
  88. cur = stream.current();
  89. if(dpcmd.indexOf(cur) !== -1) {
  90. stream.skipToEnd();
  91. return "strong";
  92. }
  93. }
  94. // application args
  95. if(ch == '$'){
  96. var ch1 = stream.peek();
  97. if(ch1 == '{'){
  98. stream.skipTo('}');
  99. stream.eat('}');
  100. return "variable-3";
  101. }
  102. }
  103. // extension
  104. stream.eatWhile(/\w/);
  105. cur = stream.current();
  106. if(atoms.indexOf(cur) !== -1) {
  107. state.extenStart = true;
  108. switch(cur) {
  109. case 'same': state.extenSame = true; break;
  110. case 'include':
  111. case 'switch':
  112. case 'ignorepat':
  113. state.extenInclude = true;break;
  114. default:break;
  115. }
  116. return "atom";
  117. }
  118. }
  119. return {
  120. startState: function() {
  121. return {
  122. extenStart: false,
  123. extenSame: false,
  124. extenInclude: false,
  125. extenExten: false,
  126. extenPriority: false,
  127. extenApplication: false
  128. };
  129. },
  130. token: function(stream, state) {
  131. var cur = '';
  132. if(stream.eatSpace()) return null;
  133. // extension started
  134. if(state.extenStart){
  135. stream.eatWhile(/[^\s]/);
  136. cur = stream.current();
  137. if(/^=>?$/.test(cur)){
  138. state.extenExten = true;
  139. state.extenStart = false;
  140. return "strong";
  141. } else {
  142. state.extenStart = false;
  143. stream.skipToEnd();
  144. return "error";
  145. }
  146. } else if(state.extenExten) {
  147. // set exten and priority
  148. state.extenExten = false;
  149. state.extenPriority = true;
  150. stream.eatWhile(/[^,]/);
  151. if(state.extenInclude) {
  152. stream.skipToEnd();
  153. state.extenPriority = false;
  154. state.extenInclude = false;
  155. }
  156. if(state.extenSame) {
  157. state.extenPriority = false;
  158. state.extenSame = false;
  159. state.extenApplication = true;
  160. }
  161. return "tag";
  162. } else if(state.extenPriority) {
  163. state.extenPriority = false;
  164. state.extenApplication = true;
  165. stream.next(); // get comma
  166. if(state.extenSame) return null;
  167. stream.eatWhile(/[^,]/);
  168. return "number";
  169. } else if(state.extenApplication) {
  170. stream.eatWhile(/,/);
  171. cur = stream.current();
  172. if(cur === ',') return null;
  173. stream.eatWhile(/\w/);
  174. cur = stream.current().toLowerCase();
  175. state.extenApplication = false;
  176. if(apps.indexOf(cur) !== -1){
  177. return "def strong";
  178. }
  179. } else{
  180. return basicToken(stream,state);
  181. }
  182. return null;
  183. }
  184. };
  185. });
  186. CodeMirror.defineMIME("text/x-asterisk", "asterisk");
  187. });