// CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: https://codemirror.net/LICENSE /* * ===================================================================================== * * Filename: mode/asterisk/asterisk.js * * Description: CodeMirror mode for Asterisk dialplan * * Created: 05/17/2012 09:20:25 PM * Revision: 08/05/2019 AstLinux Project: Support block-comments * * Author: Stas Kobzar (stas@modulis.ca), * Company: Modulis.ca Inc. * * ===================================================================================== */ ;(function (mod) { if (typeof exports == 'object' && typeof module == 'object') // CommonJS mod(require('../../lib/codemirror')) else if (typeof define == 'function' && define.amd) // AMD define(['../../lib/codemirror'], mod) // Plain browser env else mod(CodeMirror) })(function (CodeMirror) { 'use strict' CodeMirror.defineMode('asterisk', function () { var atoms = ['exten', 'same', 'include', 'ignorepat', 'switch'], dpcmd = ['#include', '#exec'], apps = [ 'addqueuemember', 'adsiprog', 'aelsub', 'agentlogin', 'agentmonitoroutgoing', 'agi', 'alarmreceiver', 'amd', 'answer', 'authenticate', 'background', 'backgrounddetect', 'bridge', 'busy', 'callcompletioncancel', 'callcompletionrequest', 'celgenuserevent', 'changemonitor', 'chanisavail', 'channelredirect', 'chanspy', 'clearhash', 'confbridge', 'congestion', 'continuewhile', 'controlplayback', 'dahdiacceptr2call', 'dahdibarge', 'dahdiras', 'dahdiscan', 'dahdisendcallreroutingfacility', 'dahdisendkeypadfacility', 'datetime', 'dbdel', 'dbdeltree', 'deadagi', 'dial', 'dictate', 'directory', 'disa', 'dumpchan', 'eagi', 'echo', 'endwhile', 'exec', 'execif', 'execiftime', 'exitwhile', 'extenspy', 'externalivr', 'festival', 'flash', 'followme', 'forkcdr', 'getcpeid', 'gosub', 'gosubif', 'goto', 'gotoif', 'gotoiftime', 'hangup', 'iax2provision', 'ices', 'importvar', 'incomplete', 'ivrdemo', 'jabberjoin', 'jabberleave', 'jabbersend', 'jabbersendgroup', 'jabberstatus', 'jack', 'log', 'macro', 'macroexclusive', 'macroexit', 'macroif', 'mailboxexists', 'meetme', 'meetmeadmin', 'meetmechanneladmin', 'meetmecount', 'milliwatt', 'minivmaccmess', 'minivmdelete', 'minivmgreet', 'minivmmwi', 'minivmnotify', 'minivmrecord', 'mixmonitor', 'monitor', 'morsecode', 'mp3player', 'mset', 'musiconhold', 'nbscat', 'nocdr', 'noop', 'odbc', 'odbc', 'odbcfinish', 'originate', 'ospauth', 'ospfinish', 'osplookup', 'ospnext', 'page', 'park', 'parkandannounce', 'parkedcall', 'pausemonitor', 'pausequeuemember', 'pickup', 'pickupchan', 'playback', 'playtones', 'privacymanager', 'proceeding', 'progress', 'queue', 'queuelog', 'raiseexception', 'read', 'readexten', 'readfile', 'receivefax', 'receivefax', 'receivefax', 'record', 'removequeuemember', 'resetcdr', 'retrydial', 'return', 'ringing', 'sayalpha', 'saycountedadj', 'saycountednoun', 'saycountpl', 'saydigits', 'saynumber', 'sayphonetic', 'sayunixtime', 'senddtmf', 'sendfax', 'sendfax', 'sendfax', 'sendimage', 'sendtext', 'sendurl', 'set', 'setamaflags', 'setcallerpres', 'setmusiconhold', 'sipaddheader', 'sipdtmfmode', 'sipremoveheader', 'skel', 'slastation', 'slatrunk', 'sms', 'softhangup', 'speechactivategrammar', 'speechbackground', 'speechcreate', 'speechdeactivategrammar', 'speechdestroy', 'speechloadgrammar', 'speechprocessingsound', 'speechstart', 'speechunloadgrammar', 'stackpop', 'startmusiconhold', 'stopmixmonitor', 'stopmonitor', 'stopmusiconhold', 'stopplaytones', 'system', 'testclient', 'testserver', 'transfer', 'tryexec', 'trysystem', 'unpausemonitor', 'unpausequeuemember', 'userevent', 'verbose', 'vmauthenticate', 'vmsayname', 'voicemail', 'voicemailmain', 'wait', 'waitexten', 'waitfornoise', 'waitforring', 'waitforsilence', 'waitmusiconhold', 'waituntil', 'while', 'zapateller', ] function basicToken(stream, state) { var cur = '' var ch = stream.next() // comment if (state.blockComment) { if (ch == '-' && stream.match('-;', true)) { state.blockComment = false } else if (stream.skipTo('--;')) { stream.next() stream.next() stream.next() state.blockComment = false } else { stream.skipToEnd() } return 'comment' } if (ch == ';') { if (stream.match('--', true)) { if (!stream.match('-', false)) { // Except ;--- is not a block comment state.blockComment = true return 'comment' } } stream.skipToEnd() return 'comment' } // context if (ch == '[') { stream.skipTo(']') stream.eat(']') return 'header' } // string if (ch == '"') { stream.skipTo('"') return 'string' } if (ch == "'") { stream.skipTo("'") return 'string-2' } // dialplan commands if (ch == '#') { stream.eatWhile(/\w/) cur = stream.current() if (dpcmd.indexOf(cur) !== -1) { stream.skipToEnd() return 'strong' } } // application args if (ch == '$') { var ch1 = stream.peek() if (ch1 == '{') { stream.skipTo('}') stream.eat('}') return 'variable-3' } } // extension stream.eatWhile(/\w/) cur = stream.current() if (atoms.indexOf(cur) !== -1) { state.extenStart = true switch (cur) { case 'same': state.extenSame = true break case 'include': case 'switch': case 'ignorepat': state.extenInclude = true break default: break } return 'atom' } } return { startState: function () { return { blockComment: false, extenStart: false, extenSame: false, extenInclude: false, extenExten: false, extenPriority: false, extenApplication: false, } }, token: function (stream, state) { var cur = '' if (stream.eatSpace()) return null // extension started if (state.extenStart) { stream.eatWhile(/[^\s]/) cur = stream.current() if (/^=>?$/.test(cur)) { state.extenExten = true state.extenStart = false return 'strong' } else { state.extenStart = false stream.skipToEnd() return 'error' } } else if (state.extenExten) { // set exten and priority state.extenExten = false state.extenPriority = true stream.eatWhile(/[^,]/) if (state.extenInclude) { stream.skipToEnd() state.extenPriority = false state.extenInclude = false } if (state.extenSame) { state.extenPriority = false state.extenSame = false state.extenApplication = true } return 'tag' } else if (state.extenPriority) { state.extenPriority = false state.extenApplication = true stream.next() // get comma if (state.extenSame) return null stream.eatWhile(/[^,]/) return 'number' } else if (state.extenApplication) { stream.eatWhile(/,/) cur = stream.current() if (cur === ',') return null stream.eatWhile(/\w/) cur = stream.current().toLowerCase() state.extenApplication = false if (apps.indexOf(cur) !== -1) { return 'def strong' } } else { return basicToken(stream, state) } return null }, blockCommentStart: ';--', blockCommentEnd: '--;', lineComment: ';', } }) CodeMirror.defineMIME('text/x-asterisk', 'asterisk') })