ext-prompt.js 96 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806
  1. define("ace/ext/menu_tools/get_editor_keyboard_shortcuts",["require","exports","module","ace/lib/keys"], function(require, exports, module) {
  2. "use strict";
  3. var keys = require("../../lib/keys");
  4. module.exports.getEditorKeybordShortcuts = function(editor) {
  5. var KEY_MODS = keys.KEY_MODS;
  6. var keybindings = [];
  7. var commandMap = {};
  8. editor.keyBinding.$handlers.forEach(function(handler) {
  9. var ckb = handler.commandKeyBinding;
  10. for (var i in ckb) {
  11. var key = i.replace(/(^|-)\w/g, function(x) { return x.toUpperCase(); });
  12. var commands = ckb[i];
  13. if (!Array.isArray(commands))
  14. commands = [commands];
  15. commands.forEach(function(command) {
  16. if (typeof command != "string")
  17. command = command.name;
  18. if (commandMap[command]) {
  19. commandMap[command].key += "|" + key;
  20. } else {
  21. commandMap[command] = {key: key, command: command};
  22. keybindings.push(commandMap[command]);
  23. }
  24. });
  25. }
  26. });
  27. return keybindings;
  28. };
  29. });
  30. define("ace/autocomplete/popup",["require","exports","module","ace/virtual_renderer","ace/editor","ace/range","ace/lib/event","ace/lib/lang","ace/lib/dom"], function(require, exports, module) {
  31. "use strict";
  32. var Renderer = require("../virtual_renderer").VirtualRenderer;
  33. var Editor = require("../editor").Editor;
  34. var Range = require("../range").Range;
  35. var event = require("../lib/event");
  36. var lang = require("../lib/lang");
  37. var dom = require("../lib/dom");
  38. var $singleLineEditor = function(el) {
  39. var renderer = new Renderer(el);
  40. renderer.$maxLines = 4;
  41. var editor = new Editor(renderer);
  42. editor.setHighlightActiveLine(false);
  43. editor.setShowPrintMargin(false);
  44. editor.renderer.setShowGutter(false);
  45. editor.renderer.setHighlightGutterLine(false);
  46. editor.$mouseHandler.$focusTimeout = 0;
  47. editor.$highlightTagPending = true;
  48. return editor;
  49. };
  50. var AcePopup = function(parentNode) {
  51. var el = dom.createElement("div");
  52. var popup = new $singleLineEditor(el);
  53. if (parentNode)
  54. parentNode.appendChild(el);
  55. el.style.display = "none";
  56. popup.renderer.content.style.cursor = "default";
  57. popup.renderer.setStyle("ace_autocomplete");
  58. popup.setOption("displayIndentGuides", false);
  59. popup.setOption("dragDelay", 150);
  60. var noop = function(){};
  61. popup.focus = noop;
  62. popup.$isFocused = true;
  63. popup.renderer.$cursorLayer.restartTimer = noop;
  64. popup.renderer.$cursorLayer.element.style.opacity = 0;
  65. popup.renderer.$maxLines = 8;
  66. popup.renderer.$keepTextAreaAtCursor = false;
  67. popup.setHighlightActiveLine(false);
  68. popup.session.highlight("");
  69. popup.session.$searchHighlight.clazz = "ace_highlight-marker";
  70. popup.on("mousedown", function(e) {
  71. var pos = e.getDocumentPosition();
  72. popup.selection.moveToPosition(pos);
  73. selectionMarker.start.row = selectionMarker.end.row = pos.row;
  74. e.stop();
  75. });
  76. var lastMouseEvent;
  77. var hoverMarker = new Range(-1,0,-1,Infinity);
  78. var selectionMarker = new Range(-1,0,-1,Infinity);
  79. selectionMarker.id = popup.session.addMarker(selectionMarker, "ace_active-line", "fullLine");
  80. popup.setSelectOnHover = function(val) {
  81. if (!val) {
  82. hoverMarker.id = popup.session.addMarker(hoverMarker, "ace_line-hover", "fullLine");
  83. } else if (hoverMarker.id) {
  84. popup.session.removeMarker(hoverMarker.id);
  85. hoverMarker.id = null;
  86. }
  87. };
  88. popup.setSelectOnHover(false);
  89. popup.on("mousemove", function(e) {
  90. if (!lastMouseEvent) {
  91. lastMouseEvent = e;
  92. return;
  93. }
  94. if (lastMouseEvent.x == e.x && lastMouseEvent.y == e.y) {
  95. return;
  96. }
  97. lastMouseEvent = e;
  98. lastMouseEvent.scrollTop = popup.renderer.scrollTop;
  99. var row = lastMouseEvent.getDocumentPosition().row;
  100. if (hoverMarker.start.row != row) {
  101. if (!hoverMarker.id)
  102. popup.setRow(row);
  103. setHoverMarker(row);
  104. }
  105. });
  106. popup.renderer.on("beforeRender", function() {
  107. if (lastMouseEvent && hoverMarker.start.row != -1) {
  108. lastMouseEvent.$pos = null;
  109. var row = lastMouseEvent.getDocumentPosition().row;
  110. if (!hoverMarker.id)
  111. popup.setRow(row);
  112. setHoverMarker(row, true);
  113. }
  114. });
  115. popup.renderer.on("afterRender", function() {
  116. var row = popup.getRow();
  117. var t = popup.renderer.$textLayer;
  118. var selected = t.element.childNodes[row - t.config.firstRow];
  119. if (selected !== t.selectedNode && t.selectedNode)
  120. dom.removeCssClass(t.selectedNode, "ace_selected");
  121. t.selectedNode = selected;
  122. if (selected)
  123. dom.addCssClass(selected, "ace_selected");
  124. });
  125. var hideHoverMarker = function() { setHoverMarker(-1); };
  126. var setHoverMarker = function(row, suppressRedraw) {
  127. if (row !== hoverMarker.start.row) {
  128. hoverMarker.start.row = hoverMarker.end.row = row;
  129. if (!suppressRedraw)
  130. popup.session._emit("changeBackMarker");
  131. popup._emit("changeHoverMarker");
  132. }
  133. };
  134. popup.getHoveredRow = function() {
  135. return hoverMarker.start.row;
  136. };
  137. event.addListener(popup.container, "mouseout", hideHoverMarker);
  138. popup.on("hide", hideHoverMarker);
  139. popup.on("changeSelection", hideHoverMarker);
  140. popup.session.doc.getLength = function() {
  141. return popup.data.length;
  142. };
  143. popup.session.doc.getLine = function(i) {
  144. var data = popup.data[i];
  145. if (typeof data == "string")
  146. return data;
  147. return (data && data.value) || "";
  148. };
  149. var bgTokenizer = popup.session.bgTokenizer;
  150. bgTokenizer.$tokenizeRow = function(row) {
  151. var data = popup.data[row];
  152. var tokens = [];
  153. if (!data)
  154. return tokens;
  155. if (typeof data == "string")
  156. data = {value: data};
  157. var caption = data.caption || data.value || data.name;
  158. function addToken(value, className) {
  159. value && tokens.push({
  160. type: (data.className || "") + (className || ""),
  161. value: value
  162. });
  163. }
  164. var lower = caption.toLowerCase();
  165. var filterText = (popup.filterText || "").toLowerCase();
  166. var lastIndex = 0;
  167. var lastI = 0;
  168. for (var i = 0; i <= filterText.length; i++) {
  169. if (i != lastI && (data.matchMask & (1 << i) || i == filterText.length)) {
  170. var sub = filterText.slice(lastI, i);
  171. lastI = i;
  172. var index = lower.indexOf(sub, lastIndex);
  173. if (index == -1) continue;
  174. addToken(caption.slice(lastIndex, index), "");
  175. lastIndex = index + sub.length;
  176. addToken(caption.slice(index, lastIndex), "completion-highlight");
  177. }
  178. }
  179. addToken(caption.slice(lastIndex, caption.length), "");
  180. if (data.meta)
  181. tokens.push({type: "completion-meta", value: data.meta});
  182. if (data.message)
  183. tokens.push({type: "completion-message", value: data.message});
  184. return tokens;
  185. };
  186. bgTokenizer.$updateOnChange = noop;
  187. bgTokenizer.start = noop;
  188. popup.session.$computeWidth = function() {
  189. return this.screenWidth = 0;
  190. };
  191. popup.isOpen = false;
  192. popup.isTopdown = false;
  193. popup.autoSelect = true;
  194. popup.filterText = "";
  195. popup.data = [];
  196. popup.setData = function(list, filterText) {
  197. popup.filterText = filterText || "";
  198. popup.setValue(lang.stringRepeat("\n", list.length), -1);
  199. popup.data = list || [];
  200. popup.setRow(0);
  201. };
  202. popup.getData = function(row) {
  203. return popup.data[row];
  204. };
  205. popup.getRow = function() {
  206. return selectionMarker.start.row;
  207. };
  208. popup.setRow = function(line) {
  209. line = Math.max(this.autoSelect ? 0 : -1, Math.min(this.data.length, line));
  210. if (selectionMarker.start.row != line) {
  211. popup.selection.clearSelection();
  212. selectionMarker.start.row = selectionMarker.end.row = line || 0;
  213. popup.session._emit("changeBackMarker");
  214. popup.moveCursorTo(line || 0, 0);
  215. if (popup.isOpen)
  216. popup._signal("select");
  217. }
  218. };
  219. popup.on("changeSelection", function() {
  220. if (popup.isOpen)
  221. popup.setRow(popup.selection.lead.row);
  222. popup.renderer.scrollCursorIntoView();
  223. });
  224. popup.hide = function() {
  225. this.container.style.display = "none";
  226. this._signal("hide");
  227. popup.isOpen = false;
  228. };
  229. popup.show = function(pos, lineHeight, topdownOnly) {
  230. var el = this.container;
  231. var screenHeight = window.innerHeight;
  232. var screenWidth = window.innerWidth;
  233. var renderer = this.renderer;
  234. var maxH = renderer.$maxLines * lineHeight * 1.4;
  235. var top = pos.top + this.$borderSize;
  236. var allowTopdown = top > screenHeight / 2 && !topdownOnly;
  237. if (allowTopdown && top + lineHeight + maxH > screenHeight) {
  238. renderer.$maxPixelHeight = top - 2 * this.$borderSize;
  239. el.style.top = "";
  240. el.style.bottom = screenHeight - top + "px";
  241. popup.isTopdown = false;
  242. } else {
  243. top += lineHeight;
  244. renderer.$maxPixelHeight = screenHeight - top - 0.2 * lineHeight;
  245. el.style.top = top + "px";
  246. el.style.bottom = "";
  247. popup.isTopdown = true;
  248. }
  249. el.style.display = "";
  250. var left = pos.left;
  251. if (left + el.offsetWidth > screenWidth)
  252. left = screenWidth - el.offsetWidth;
  253. el.style.left = left + "px";
  254. this._signal("show");
  255. lastMouseEvent = null;
  256. popup.isOpen = true;
  257. };
  258. popup.goTo = function(where) {
  259. var row = this.getRow();
  260. var max = this.session.getLength() - 1;
  261. switch(where) {
  262. case "up": row = row <= 0 ? max : row - 1; break;
  263. case "down": row = row >= max ? -1 : row + 1; break;
  264. case "start": row = 0; break;
  265. case "end": row = max; break;
  266. }
  267. this.setRow(row);
  268. };
  269. popup.getTextLeftOffset = function() {
  270. return this.$borderSize + this.renderer.$padding + this.$imageSize;
  271. };
  272. popup.$imageSize = 0;
  273. popup.$borderSize = 1;
  274. return popup;
  275. };
  276. dom.importCssString("\
  277. .ace_editor.ace_autocomplete .ace_marker-layer .ace_active-line {\
  278. background-color: #CAD6FA;\
  279. z-index: 1;\
  280. }\
  281. .ace_dark.ace_editor.ace_autocomplete .ace_marker-layer .ace_active-line {\
  282. background-color: #3a674e;\
  283. }\
  284. .ace_editor.ace_autocomplete .ace_line-hover {\
  285. border: 1px solid #abbffe;\
  286. margin-top: -1px;\
  287. background: rgba(233,233,253,0.4);\
  288. position: absolute;\
  289. z-index: 2;\
  290. }\
  291. .ace_dark.ace_editor.ace_autocomplete .ace_line-hover {\
  292. border: 1px solid rgba(109, 150, 13, 0.8);\
  293. background: rgba(58, 103, 78, 0.62);\
  294. }\
  295. .ace_completion-meta {\
  296. opacity: 0.5;\
  297. margin: 0.9em;\
  298. }\
  299. .ace_completion-message {\
  300. color: blue;\
  301. }\
  302. .ace_editor.ace_autocomplete .ace_completion-highlight{\
  303. color: #2d69c7;\
  304. }\
  305. .ace_dark.ace_editor.ace_autocomplete .ace_completion-highlight{\
  306. color: #93ca12;\
  307. }\
  308. .ace_editor.ace_autocomplete {\
  309. width: 300px;\
  310. z-index: 200000;\
  311. border: 1px lightgray solid;\
  312. position: fixed;\
  313. box-shadow: 2px 3px 5px rgba(0,0,0,.2);\
  314. line-height: 1.4;\
  315. background: #fefefe;\
  316. color: #111;\
  317. }\
  318. .ace_dark.ace_editor.ace_autocomplete {\
  319. border: 1px #484747 solid;\
  320. box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.51);\
  321. line-height: 1.4;\
  322. background: #25282c;\
  323. color: #c1c1c1;\
  324. }", "autocompletion.css", false);
  325. exports.AcePopup = AcePopup;
  326. exports.$singleLineEditor = $singleLineEditor;
  327. });
  328. define("ace/autocomplete/util",["require","exports","module"], function(require, exports, module) {
  329. "use strict";
  330. exports.parForEach = function(array, fn, callback) {
  331. var completed = 0;
  332. var arLength = array.length;
  333. if (arLength === 0)
  334. callback();
  335. for (var i = 0; i < arLength; i++) {
  336. fn(array[i], function(result, err) {
  337. completed++;
  338. if (completed === arLength)
  339. callback(result, err);
  340. });
  341. }
  342. };
  343. var ID_REGEX = /[a-zA-Z_0-9\$\-\u00A2-\u2000\u2070-\uFFFF]/;
  344. exports.retrievePrecedingIdentifier = function(text, pos, regex) {
  345. regex = regex || ID_REGEX;
  346. var buf = [];
  347. for (var i = pos-1; i >= 0; i--) {
  348. if (regex.test(text[i]))
  349. buf.push(text[i]);
  350. else
  351. break;
  352. }
  353. return buf.reverse().join("");
  354. };
  355. exports.retrieveFollowingIdentifier = function(text, pos, regex) {
  356. regex = regex || ID_REGEX;
  357. var buf = [];
  358. for (var i = pos; i < text.length; i++) {
  359. if (regex.test(text[i]))
  360. buf.push(text[i]);
  361. else
  362. break;
  363. }
  364. return buf;
  365. };
  366. exports.getCompletionPrefix = function (editor) {
  367. var pos = editor.getCursorPosition();
  368. var line = editor.session.getLine(pos.row);
  369. var prefix;
  370. editor.completers.forEach(function(completer) {
  371. if (completer.identifierRegexps) {
  372. completer.identifierRegexps.forEach(function(identifierRegex) {
  373. if (!prefix && identifierRegex)
  374. prefix = this.retrievePrecedingIdentifier(line, pos.column, identifierRegex);
  375. }.bind(this));
  376. }
  377. }.bind(this));
  378. return prefix || this.retrievePrecedingIdentifier(line, pos.column);
  379. };
  380. });
  381. define("ace/snippets",["require","exports","module","ace/lib/dom","ace/lib/oop","ace/lib/event_emitter","ace/lib/lang","ace/range","ace/range_list","ace/keyboard/hash_handler","ace/tokenizer","ace/clipboard","ace/editor"], function(require, exports, module) {
  382. "use strict";
  383. var dom = require("./lib/dom");
  384. var oop = require("./lib/oop");
  385. var EventEmitter = require("./lib/event_emitter").EventEmitter;
  386. var lang = require("./lib/lang");
  387. var Range = require("./range").Range;
  388. var RangeList = require("./range_list").RangeList;
  389. var HashHandler = require("./keyboard/hash_handler").HashHandler;
  390. var Tokenizer = require("./tokenizer").Tokenizer;
  391. var clipboard = require("./clipboard");
  392. var VARIABLES = {
  393. CURRENT_WORD: function(editor) {
  394. return editor.session.getTextRange(editor.session.getWordRange());
  395. },
  396. SELECTION: function(editor, name, indentation) {
  397. var text = editor.session.getTextRange();
  398. if (indentation)
  399. return text.replace(/\n\r?([ \t]*\S)/g, "\n" + indentation + "$1");
  400. return text;
  401. },
  402. CURRENT_LINE: function(editor) {
  403. return editor.session.getLine(editor.getCursorPosition().row);
  404. },
  405. PREV_LINE: function(editor) {
  406. return editor.session.getLine(editor.getCursorPosition().row - 1);
  407. },
  408. LINE_INDEX: function(editor) {
  409. return editor.getCursorPosition().row;
  410. },
  411. LINE_NUMBER: function(editor) {
  412. return editor.getCursorPosition().row + 1;
  413. },
  414. SOFT_TABS: function(editor) {
  415. return editor.session.getUseSoftTabs() ? "YES" : "NO";
  416. },
  417. TAB_SIZE: function(editor) {
  418. return editor.session.getTabSize();
  419. },
  420. CLIPBOARD: function(editor) {
  421. return clipboard.getText && clipboard.getText();
  422. },
  423. FILENAME: function(editor) {
  424. return /[^/\\]*$/.exec(this.FILEPATH(editor))[0];
  425. },
  426. FILENAME_BASE: function(editor) {
  427. return /[^/\\]*$/.exec(this.FILEPATH(editor))[0].replace(/\.[^.]*$/, "");
  428. },
  429. DIRECTORY: function(editor) {
  430. return this.FILEPATH(editor).replace(/[^/\\]*$/, "");
  431. },
  432. FILEPATH: function(editor) { return "/not implemented.txt"; },
  433. WORKSPACE_NAME: function() { return "Unknown"; },
  434. FULLNAME: function() { return "Unknown"; },
  435. BLOCK_COMMENT_START: function(editor) {
  436. var mode = editor.session.$mode || {};
  437. return mode.blockComment && mode.blockComment.start || "";
  438. },
  439. BLOCK_COMMENT_END: function(editor) {
  440. var mode = editor.session.$mode || {};
  441. return mode.blockComment && mode.blockComment.end || "";
  442. },
  443. LINE_COMMENT: function(editor) {
  444. var mode = editor.session.$mode || {};
  445. return mode.lineCommentStart || "";
  446. },
  447. CURRENT_YEAR: date.bind(null, {year: "numeric"}),
  448. CURRENT_YEAR_SHORT: date.bind(null, {year: "2-digit"}),
  449. CURRENT_MONTH: date.bind(null, {month: "numeric"}),
  450. CURRENT_MONTH_NAME: date.bind(null, {month: "long"}),
  451. CURRENT_MONTH_NAME_SHORT: date.bind(null, {month: "short"}),
  452. CURRENT_DATE: date.bind(null, {day: "2-digit"}),
  453. CURRENT_DAY_NAME: date.bind(null, {weekday: "long"}),
  454. CURRENT_DAY_NAME_SHORT: date.bind(null, {weekday: "short"}),
  455. CURRENT_HOUR: date.bind(null, {hour: "2-digit", hour12: false}),
  456. CURRENT_MINUTE: date.bind(null, {minute: "2-digit"}),
  457. CURRENT_SECOND: date.bind(null, {second: "2-digit"})
  458. };
  459. VARIABLES.SELECTED_TEXT = VARIABLES.SELECTION;
  460. function date(dateFormat) {
  461. var str = new Date().toLocaleString("en-us", dateFormat);
  462. return str.length == 1 ? "0" + str : str;
  463. }
  464. var SnippetManager = function() {
  465. this.snippetMap = {};
  466. this.snippetNameMap = {};
  467. };
  468. (function() {
  469. oop.implement(this, EventEmitter);
  470. this.getTokenizer = function() {
  471. return SnippetManager.$tokenizer || this.createTokenizer();
  472. };
  473. this.createTokenizer = function() {
  474. function TabstopToken(str) {
  475. str = str.substr(1);
  476. if (/^\d+$/.test(str))
  477. return [{tabstopId: parseInt(str, 10)}];
  478. return [{text: str}];
  479. }
  480. function escape(ch) {
  481. return "(?:[^\\\\" + ch + "]|\\\\.)";
  482. }
  483. var formatMatcher = {
  484. regex: "/(" + escape("/") + "+)/",
  485. onMatch: function(val, state, stack) {
  486. var ts = stack[0];
  487. ts.fmtString = true;
  488. ts.guard = val.slice(1, -1);
  489. ts.flag = "";
  490. return "";
  491. },
  492. next: "formatString"
  493. };
  494. SnippetManager.$tokenizer = new Tokenizer({
  495. start: [
  496. {regex: /\\./, onMatch: function(val, state, stack) {
  497. var ch = val[1];
  498. if (ch == "}" && stack.length) {
  499. val = ch;
  500. } else if ("`$\\".indexOf(ch) != -1) {
  501. val = ch;
  502. }
  503. return [val];
  504. }},
  505. {regex: /}/, onMatch: function(val, state, stack) {
  506. return [stack.length ? stack.shift() : val];
  507. }},
  508. {regex: /\$(?:\d+|\w+)/, onMatch: TabstopToken},
  509. {regex: /\$\{[\dA-Z_a-z]+/, onMatch: function(str, state, stack) {
  510. var t = TabstopToken(str.substr(1));
  511. stack.unshift(t[0]);
  512. return t;
  513. }, next: "snippetVar"},
  514. {regex: /\n/, token: "newline", merge: false}
  515. ],
  516. snippetVar: [
  517. {regex: "\\|" + escape("\\|") + "*\\|", onMatch: function(val, state, stack) {
  518. var choices = val.slice(1, -1).replace(/\\[,|\\]|,/g, function(operator) {
  519. return operator.length == 2 ? operator[1] : "\x00";
  520. }).split("\x00").map(function(value){
  521. return {value: value};
  522. });
  523. stack[0].choices = choices;
  524. return [choices[0]];
  525. }, next: "start"},
  526. formatMatcher,
  527. {regex: "([^:}\\\\]|\\\\.)*:?", token: "", next: "start"}
  528. ],
  529. formatString: [
  530. {regex: /:/, onMatch: function(val, state, stack) {
  531. if (stack.length && stack[0].expectElse) {
  532. stack[0].expectElse = false;
  533. stack[0].ifEnd = {elseEnd: stack[0]};
  534. return [stack[0].ifEnd];
  535. }
  536. return ":";
  537. }},
  538. {regex: /\\./, onMatch: function(val, state, stack) {
  539. var ch = val[1];
  540. if (ch == "}" && stack.length)
  541. val = ch;
  542. else if ("`$\\".indexOf(ch) != -1)
  543. val = ch;
  544. else if (ch == "n")
  545. val = "\n";
  546. else if (ch == "t")
  547. val = "\t";
  548. else if ("ulULE".indexOf(ch) != -1)
  549. val = {changeCase: ch, local: ch > "a"};
  550. return [val];
  551. }},
  552. {regex: "/\\w*}", onMatch: function(val, state, stack) {
  553. var next = stack.shift();
  554. if (next)
  555. next.flag = val.slice(1, -1);
  556. this.next = next && next.tabstopId ? "start" : "";
  557. return [next || val];
  558. }, next: "start"},
  559. {regex: /\$(?:\d+|\w+)/, onMatch: function(val, state, stack) {
  560. return [{text: val.slice(1)}];
  561. }},
  562. {regex: /\${\w+/, onMatch: function(val, state, stack) {
  563. var token = {text: val.slice(2)};
  564. stack.unshift(token);
  565. return [token];
  566. }, next: "formatStringVar"},
  567. {regex: /\n/, token: "newline", merge: false},
  568. {regex: /}/, onMatch: function(val, state, stack) {
  569. var next = stack.shift();
  570. this.next = next && next.tabstopId ? "start" : "";
  571. return [next || val];
  572. }, next: "start"}
  573. ],
  574. formatStringVar: [
  575. {regex: /:\/\w+}/, onMatch: function(val, state, stack) {
  576. var ts = stack[0];
  577. ts.formatFunction = val.slice(2, -1);
  578. return [stack.shift()];
  579. }, next: "formatString"},
  580. formatMatcher,
  581. {regex: /:[\?\-+]?/, onMatch: function(val, state, stack) {
  582. if (val[1] == "+")
  583. stack[0].ifEnd = stack[0];
  584. if (val[1] == "?")
  585. stack[0].expectElse = true;
  586. }, next: "formatString"},
  587. {regex: "([^:}\\\\]|\\\\.)*:?", token: "", next: "formatString"}
  588. ]
  589. });
  590. return SnippetManager.$tokenizer;
  591. };
  592. this.tokenizeTmSnippet = function(str, startState) {
  593. return this.getTokenizer().getLineTokens(str, startState).tokens.map(function(x) {
  594. return x.value || x;
  595. });
  596. };
  597. this.getVariableValue = function(editor, name, indentation) {
  598. if (/^\d+$/.test(name))
  599. return (this.variables.__ || {})[name] || "";
  600. if (/^[A-Z]\d+$/.test(name))
  601. return (this.variables[name[0] + "__"] || {})[name.substr(1)] || "";
  602. name = name.replace(/^TM_/, "");
  603. if (!this.variables.hasOwnProperty(name))
  604. return "";
  605. var value = this.variables[name];
  606. if (typeof value == "function")
  607. value = this.variables[name](editor, name, indentation);
  608. return value == null ? "" : value;
  609. };
  610. this.variables = VARIABLES;
  611. this.tmStrFormat = function(str, ch, editor) {
  612. if (!ch.fmt) return str;
  613. var flag = ch.flag || "";
  614. var re = ch.guard;
  615. re = new RegExp(re, flag.replace(/[^gim]/g, ""));
  616. var fmtTokens = typeof ch.fmt == "string" ? this.tokenizeTmSnippet(ch.fmt, "formatString") : ch.fmt;
  617. var _self = this;
  618. var formatted = str.replace(re, function() {
  619. var oldArgs = _self.variables.__;
  620. _self.variables.__ = [].slice.call(arguments);
  621. var fmtParts = _self.resolveVariables(fmtTokens, editor);
  622. var gChangeCase = "E";
  623. for (var i = 0; i < fmtParts.length; i++) {
  624. var ch = fmtParts[i];
  625. if (typeof ch == "object") {
  626. fmtParts[i] = "";
  627. if (ch.changeCase && ch.local) {
  628. var next = fmtParts[i + 1];
  629. if (next && typeof next == "string") {
  630. if (ch.changeCase == "u")
  631. fmtParts[i] = next[0].toUpperCase();
  632. else
  633. fmtParts[i] = next[0].toLowerCase();
  634. fmtParts[i + 1] = next.substr(1);
  635. }
  636. } else if (ch.changeCase) {
  637. gChangeCase = ch.changeCase;
  638. }
  639. } else if (gChangeCase == "U") {
  640. fmtParts[i] = ch.toUpperCase();
  641. } else if (gChangeCase == "L") {
  642. fmtParts[i] = ch.toLowerCase();
  643. }
  644. }
  645. _self.variables.__ = oldArgs;
  646. return fmtParts.join("");
  647. });
  648. return formatted;
  649. };
  650. this.tmFormatFunction = function(str, ch, editor) {
  651. if (ch.formatFunction == "upcase")
  652. return str.toUpperCase();
  653. if (ch.formatFunction == "downcase")
  654. return str.toLowerCase();
  655. return str;
  656. };
  657. this.resolveVariables = function(snippet, editor) {
  658. var result = [];
  659. var indentation = "";
  660. var afterNewLine = true;
  661. for (var i = 0; i < snippet.length; i++) {
  662. var ch = snippet[i];
  663. if (typeof ch == "string") {
  664. result.push(ch);
  665. if (ch == "\n") {
  666. afterNewLine = true;
  667. indentation = "";
  668. }
  669. else if (afterNewLine) {
  670. indentation = /^\t*/.exec(ch)[0];
  671. afterNewLine = /\S/.test(ch);
  672. }
  673. continue;
  674. }
  675. if (!ch) continue;
  676. afterNewLine = false;
  677. if (ch.fmtString) {
  678. var j = snippet.indexOf(ch, i + 1);
  679. if (j == -1) j = snippet.length;
  680. ch.fmt = snippet.slice(i + 1, j);
  681. i = j;
  682. }
  683. if (ch.text) {
  684. var value = this.getVariableValue(editor, ch.text, indentation) + "";
  685. if (ch.fmtString)
  686. value = this.tmStrFormat(value, ch, editor);
  687. if (ch.formatFunction)
  688. value = this.tmFormatFunction(value, ch, editor);
  689. if (value && !ch.ifEnd) {
  690. result.push(value);
  691. gotoNext(ch);
  692. } else if (!value && ch.ifEnd) {
  693. gotoNext(ch.ifEnd);
  694. }
  695. } else if (ch.elseEnd) {
  696. gotoNext(ch.elseEnd);
  697. } else if (ch.tabstopId != null) {
  698. result.push(ch);
  699. } else if (ch.changeCase != null) {
  700. result.push(ch);
  701. }
  702. }
  703. function gotoNext(ch) {
  704. var i1 = snippet.indexOf(ch, i + 1);
  705. if (i1 != -1)
  706. i = i1;
  707. }
  708. return result;
  709. };
  710. this.insertSnippetForSelection = function(editor, snippetText) {
  711. var cursor = editor.getCursorPosition();
  712. var line = editor.session.getLine(cursor.row);
  713. var tabString = editor.session.getTabString();
  714. var indentString = line.match(/^\s*/)[0];
  715. if (cursor.column < indentString.length)
  716. indentString = indentString.slice(0, cursor.column);
  717. snippetText = snippetText.replace(/\r/g, "");
  718. var tokens = this.tokenizeTmSnippet(snippetText);
  719. tokens = this.resolveVariables(tokens, editor);
  720. tokens = tokens.map(function(x) {
  721. if (x == "\n")
  722. return x + indentString;
  723. if (typeof x == "string")
  724. return x.replace(/\t/g, tabString);
  725. return x;
  726. });
  727. var tabstops = [];
  728. tokens.forEach(function(p, i) {
  729. if (typeof p != "object")
  730. return;
  731. var id = p.tabstopId;
  732. var ts = tabstops[id];
  733. if (!ts) {
  734. ts = tabstops[id] = [];
  735. ts.index = id;
  736. ts.value = "";
  737. ts.parents = {};
  738. }
  739. if (ts.indexOf(p) !== -1)
  740. return;
  741. if (p.choices && !ts.choices)
  742. ts.choices = p.choices;
  743. ts.push(p);
  744. var i1 = tokens.indexOf(p, i + 1);
  745. if (i1 === -1)
  746. return;
  747. var value = tokens.slice(i + 1, i1);
  748. var isNested = value.some(function(t) {return typeof t === "object";});
  749. if (isNested && !ts.value) {
  750. ts.value = value;
  751. } else if (value.length && (!ts.value || typeof ts.value !== "string")) {
  752. ts.value = value.join("");
  753. }
  754. });
  755. tabstops.forEach(function(ts) {ts.length = 0;});
  756. var expanding = {};
  757. function copyValue(val) {
  758. var copy = [];
  759. for (var i = 0; i < val.length; i++) {
  760. var p = val[i];
  761. if (typeof p == "object") {
  762. if (expanding[p.tabstopId])
  763. continue;
  764. var j = val.lastIndexOf(p, i - 1);
  765. p = copy[j] || {tabstopId: p.tabstopId};
  766. }
  767. copy[i] = p;
  768. }
  769. return copy;
  770. }
  771. for (var i = 0; i < tokens.length; i++) {
  772. var p = tokens[i];
  773. if (typeof p != "object")
  774. continue;
  775. var id = p.tabstopId;
  776. var ts = tabstops[id];
  777. var i1 = tokens.indexOf(p, i + 1);
  778. if (expanding[id]) {
  779. if (expanding[id] === p) {
  780. delete expanding[id];
  781. Object.keys(expanding).forEach(function(parentId) {
  782. ts.parents[parentId] = true;
  783. });
  784. }
  785. continue;
  786. }
  787. expanding[id] = p;
  788. var value = ts.value;
  789. if (typeof value !== "string")
  790. value = copyValue(value);
  791. else if (p.fmt)
  792. value = this.tmStrFormat(value, p, editor);
  793. tokens.splice.apply(tokens, [i + 1, Math.max(0, i1 - i)].concat(value, p));
  794. if (ts.indexOf(p) === -1)
  795. ts.push(p);
  796. }
  797. var row = 0, column = 0;
  798. var text = "";
  799. tokens.forEach(function(t) {
  800. if (typeof t === "string") {
  801. var lines = t.split("\n");
  802. if (lines.length > 1){
  803. column = lines[lines.length - 1].length;
  804. row += lines.length - 1;
  805. } else
  806. column += t.length;
  807. text += t;
  808. } else if (t) {
  809. if (!t.start)
  810. t.start = {row: row, column: column};
  811. else
  812. t.end = {row: row, column: column};
  813. }
  814. });
  815. var range = editor.getSelectionRange();
  816. var end = editor.session.replace(range, text);
  817. var tabstopManager = new TabstopManager(editor);
  818. var selectionId = editor.inVirtualSelectionMode && editor.selection.index;
  819. tabstopManager.addTabstops(tabstops, range.start, end, selectionId);
  820. };
  821. this.insertSnippet = function(editor, snippetText) {
  822. var self = this;
  823. if (editor.inVirtualSelectionMode)
  824. return self.insertSnippetForSelection(editor, snippetText);
  825. editor.forEachSelection(function() {
  826. self.insertSnippetForSelection(editor, snippetText);
  827. }, null, {keepOrder: true});
  828. if (editor.tabstopManager)
  829. editor.tabstopManager.tabNext();
  830. };
  831. this.$getScope = function(editor) {
  832. var scope = editor.session.$mode.$id || "";
  833. scope = scope.split("/").pop();
  834. if (scope === "html" || scope === "php") {
  835. if (scope === "php" && !editor.session.$mode.inlinePhp)
  836. scope = "html";
  837. var c = editor.getCursorPosition();
  838. var state = editor.session.getState(c.row);
  839. if (typeof state === "object") {
  840. state = state[0];
  841. }
  842. if (state.substring) {
  843. if (state.substring(0, 3) == "js-")
  844. scope = "javascript";
  845. else if (state.substring(0, 4) == "css-")
  846. scope = "css";
  847. else if (state.substring(0, 4) == "php-")
  848. scope = "php";
  849. }
  850. }
  851. return scope;
  852. };
  853. this.getActiveScopes = function(editor) {
  854. var scope = this.$getScope(editor);
  855. var scopes = [scope];
  856. var snippetMap = this.snippetMap;
  857. if (snippetMap[scope] && snippetMap[scope].includeScopes) {
  858. scopes.push.apply(scopes, snippetMap[scope].includeScopes);
  859. }
  860. scopes.push("_");
  861. return scopes;
  862. };
  863. this.expandWithTab = function(editor, options) {
  864. var self = this;
  865. var result = editor.forEachSelection(function() {
  866. return self.expandSnippetForSelection(editor, options);
  867. }, null, {keepOrder: true});
  868. if (result && editor.tabstopManager)
  869. editor.tabstopManager.tabNext();
  870. return result;
  871. };
  872. this.expandSnippetForSelection = function(editor, options) {
  873. var cursor = editor.getCursorPosition();
  874. var line = editor.session.getLine(cursor.row);
  875. var before = line.substring(0, cursor.column);
  876. var after = line.substr(cursor.column);
  877. var snippetMap = this.snippetMap;
  878. var snippet;
  879. this.getActiveScopes(editor).some(function(scope) {
  880. var snippets = snippetMap[scope];
  881. if (snippets)
  882. snippet = this.findMatchingSnippet(snippets, before, after);
  883. return !!snippet;
  884. }, this);
  885. if (!snippet)
  886. return false;
  887. if (options && options.dryRun)
  888. return true;
  889. editor.session.doc.removeInLine(cursor.row,
  890. cursor.column - snippet.replaceBefore.length,
  891. cursor.column + snippet.replaceAfter.length
  892. );
  893. this.variables.M__ = snippet.matchBefore;
  894. this.variables.T__ = snippet.matchAfter;
  895. this.insertSnippetForSelection(editor, snippet.content);
  896. this.variables.M__ = this.variables.T__ = null;
  897. return true;
  898. };
  899. this.findMatchingSnippet = function(snippetList, before, after) {
  900. for (var i = snippetList.length; i--;) {
  901. var s = snippetList[i];
  902. if (s.startRe && !s.startRe.test(before))
  903. continue;
  904. if (s.endRe && !s.endRe.test(after))
  905. continue;
  906. if (!s.startRe && !s.endRe)
  907. continue;
  908. s.matchBefore = s.startRe ? s.startRe.exec(before) : [""];
  909. s.matchAfter = s.endRe ? s.endRe.exec(after) : [""];
  910. s.replaceBefore = s.triggerRe ? s.triggerRe.exec(before)[0] : "";
  911. s.replaceAfter = s.endTriggerRe ? s.endTriggerRe.exec(after)[0] : "";
  912. return s;
  913. }
  914. };
  915. this.snippetMap = {};
  916. this.snippetNameMap = {};
  917. this.register = function(snippets, scope) {
  918. var snippetMap = this.snippetMap;
  919. var snippetNameMap = this.snippetNameMap;
  920. var self = this;
  921. if (!snippets)
  922. snippets = [];
  923. function wrapRegexp(src) {
  924. if (src && !/^\^?\(.*\)\$?$|^\\b$/.test(src))
  925. src = "(?:" + src + ")";
  926. return src || "";
  927. }
  928. function guardedRegexp(re, guard, opening) {
  929. re = wrapRegexp(re);
  930. guard = wrapRegexp(guard);
  931. if (opening) {
  932. re = guard + re;
  933. if (re && re[re.length - 1] != "$")
  934. re = re + "$";
  935. } else {
  936. re = re + guard;
  937. if (re && re[0] != "^")
  938. re = "^" + re;
  939. }
  940. return new RegExp(re);
  941. }
  942. function addSnippet(s) {
  943. if (!s.scope)
  944. s.scope = scope || "_";
  945. scope = s.scope;
  946. if (!snippetMap[scope]) {
  947. snippetMap[scope] = [];
  948. snippetNameMap[scope] = {};
  949. }
  950. var map = snippetNameMap[scope];
  951. if (s.name) {
  952. var old = map[s.name];
  953. if (old)
  954. self.unregister(old);
  955. map[s.name] = s;
  956. }
  957. snippetMap[scope].push(s);
  958. if (s.prefix)
  959. s.tabTrigger = s.prefix;
  960. if (!s.content && s.body)
  961. s.content = Array.isArray(s.body) ? s.body.join("\n") : s.body;
  962. if (s.tabTrigger && !s.trigger) {
  963. if (!s.guard && /^\w/.test(s.tabTrigger))
  964. s.guard = "\\b";
  965. s.trigger = lang.escapeRegExp(s.tabTrigger);
  966. }
  967. if (!s.trigger && !s.guard && !s.endTrigger && !s.endGuard)
  968. return;
  969. s.startRe = guardedRegexp(s.trigger, s.guard, true);
  970. s.triggerRe = new RegExp(s.trigger);
  971. s.endRe = guardedRegexp(s.endTrigger, s.endGuard, true);
  972. s.endTriggerRe = new RegExp(s.endTrigger);
  973. }
  974. if (Array.isArray(snippets)) {
  975. snippets.forEach(addSnippet);
  976. } else {
  977. Object.keys(snippets).forEach(function(key) {
  978. addSnippet(snippets[key]);
  979. });
  980. }
  981. this._signal("registerSnippets", {scope: scope});
  982. };
  983. this.unregister = function(snippets, scope) {
  984. var snippetMap = this.snippetMap;
  985. var snippetNameMap = this.snippetNameMap;
  986. function removeSnippet(s) {
  987. var nameMap = snippetNameMap[s.scope||scope];
  988. if (nameMap && nameMap[s.name]) {
  989. delete nameMap[s.name];
  990. var map = snippetMap[s.scope||scope];
  991. var i = map && map.indexOf(s);
  992. if (i >= 0)
  993. map.splice(i, 1);
  994. }
  995. }
  996. if (snippets.content)
  997. removeSnippet(snippets);
  998. else if (Array.isArray(snippets))
  999. snippets.forEach(removeSnippet);
  1000. };
  1001. this.parseSnippetFile = function(str) {
  1002. str = str.replace(/\r/g, "");
  1003. var list = [], snippet = {};
  1004. var re = /^#.*|^({[\s\S]*})\s*$|^(\S+) (.*)$|^((?:\n*\t.*)+)/gm;
  1005. var m;
  1006. while (m = re.exec(str)) {
  1007. if (m[1]) {
  1008. try {
  1009. snippet = JSON.parse(m[1]);
  1010. list.push(snippet);
  1011. } catch (e) {}
  1012. } if (m[4]) {
  1013. snippet.content = m[4].replace(/^\t/gm, "");
  1014. list.push(snippet);
  1015. snippet = {};
  1016. } else {
  1017. var key = m[2], val = m[3];
  1018. if (key == "regex") {
  1019. var guardRe = /\/((?:[^\/\\]|\\.)*)|$/g;
  1020. snippet.guard = guardRe.exec(val)[1];
  1021. snippet.trigger = guardRe.exec(val)[1];
  1022. snippet.endTrigger = guardRe.exec(val)[1];
  1023. snippet.endGuard = guardRe.exec(val)[1];
  1024. } else if (key == "snippet") {
  1025. snippet.tabTrigger = val.match(/^\S*/)[0];
  1026. if (!snippet.name)
  1027. snippet.name = val;
  1028. } else if (key) {
  1029. snippet[key] = val;
  1030. }
  1031. }
  1032. }
  1033. return list;
  1034. };
  1035. this.getSnippetByName = function(name, editor) {
  1036. var snippetMap = this.snippetNameMap;
  1037. var snippet;
  1038. this.getActiveScopes(editor).some(function(scope) {
  1039. var snippets = snippetMap[scope];
  1040. if (snippets)
  1041. snippet = snippets[name];
  1042. return !!snippet;
  1043. }, this);
  1044. return snippet;
  1045. };
  1046. }).call(SnippetManager.prototype);
  1047. var TabstopManager = function(editor) {
  1048. if (editor.tabstopManager)
  1049. return editor.tabstopManager;
  1050. editor.tabstopManager = this;
  1051. this.$onChange = this.onChange.bind(this);
  1052. this.$onChangeSelection = lang.delayedCall(this.onChangeSelection.bind(this)).schedule;
  1053. this.$onChangeSession = this.onChangeSession.bind(this);
  1054. this.$onAfterExec = this.onAfterExec.bind(this);
  1055. this.attach(editor);
  1056. };
  1057. (function() {
  1058. this.attach = function(editor) {
  1059. this.index = 0;
  1060. this.ranges = [];
  1061. this.tabstops = [];
  1062. this.$openTabstops = null;
  1063. this.selectedTabstop = null;
  1064. this.editor = editor;
  1065. this.editor.on("change", this.$onChange);
  1066. this.editor.on("changeSelection", this.$onChangeSelection);
  1067. this.editor.on("changeSession", this.$onChangeSession);
  1068. this.editor.commands.on("afterExec", this.$onAfterExec);
  1069. this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler);
  1070. };
  1071. this.detach = function() {
  1072. this.tabstops.forEach(this.removeTabstopMarkers, this);
  1073. this.ranges = null;
  1074. this.tabstops = null;
  1075. this.selectedTabstop = null;
  1076. this.editor.removeListener("change", this.$onChange);
  1077. this.editor.removeListener("changeSelection", this.$onChangeSelection);
  1078. this.editor.removeListener("changeSession", this.$onChangeSession);
  1079. this.editor.commands.removeListener("afterExec", this.$onAfterExec);
  1080. this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler);
  1081. this.editor.tabstopManager = null;
  1082. this.editor = null;
  1083. };
  1084. this.onChange = function(delta) {
  1085. var isRemove = delta.action[0] == "r";
  1086. var selectedTabstop = this.selectedTabstop || {};
  1087. var parents = selectedTabstop.parents || {};
  1088. var tabstops = (this.tabstops || []).slice();
  1089. for (var i = 0; i < tabstops.length; i++) {
  1090. var ts = tabstops[i];
  1091. var active = ts == selectedTabstop || parents[ts.index];
  1092. ts.rangeList.$bias = active ? 0 : 1;
  1093. if (delta.action == "remove" && ts !== selectedTabstop) {
  1094. var parentActive = ts.parents && ts.parents[selectedTabstop.index];
  1095. var startIndex = ts.rangeList.pointIndex(delta.start, parentActive);
  1096. startIndex = startIndex < 0 ? -startIndex - 1 : startIndex + 1;
  1097. var endIndex = ts.rangeList.pointIndex(delta.end, parentActive);
  1098. endIndex = endIndex < 0 ? -endIndex - 1 : endIndex - 1;
  1099. var toRemove = ts.rangeList.ranges.slice(startIndex, endIndex);
  1100. for (var j = 0; j < toRemove.length; j++)
  1101. this.removeRange(toRemove[j]);
  1102. }
  1103. ts.rangeList.$onChange(delta);
  1104. }
  1105. var session = this.editor.session;
  1106. if (!this.$inChange && isRemove && session.getLength() == 1 && !session.getValue())
  1107. this.detach();
  1108. };
  1109. this.updateLinkedFields = function() {
  1110. var ts = this.selectedTabstop;
  1111. if (!ts || !ts.hasLinkedRanges || !ts.firstNonLinked)
  1112. return;
  1113. this.$inChange = true;
  1114. var session = this.editor.session;
  1115. var text = session.getTextRange(ts.firstNonLinked);
  1116. for (var i = 0; i < ts.length; i++) {
  1117. var range = ts[i];
  1118. if (!range.linked)
  1119. continue;
  1120. var original = range.original;
  1121. var fmt = exports.snippetManager.tmStrFormat(text, original, this.editor);
  1122. session.replace(range, fmt);
  1123. }
  1124. this.$inChange = false;
  1125. };
  1126. this.onAfterExec = function(e) {
  1127. if (e.command && !e.command.readOnly)
  1128. this.updateLinkedFields();
  1129. };
  1130. this.onChangeSelection = function() {
  1131. if (!this.editor)
  1132. return;
  1133. var lead = this.editor.selection.lead;
  1134. var anchor = this.editor.selection.anchor;
  1135. var isEmpty = this.editor.selection.isEmpty();
  1136. for (var i = 0; i < this.ranges.length; i++) {
  1137. if (this.ranges[i].linked)
  1138. continue;
  1139. var containsLead = this.ranges[i].contains(lead.row, lead.column);
  1140. var containsAnchor = isEmpty || this.ranges[i].contains(anchor.row, anchor.column);
  1141. if (containsLead && containsAnchor)
  1142. return;
  1143. }
  1144. this.detach();
  1145. };
  1146. this.onChangeSession = function() {
  1147. this.detach();
  1148. };
  1149. this.tabNext = function(dir) {
  1150. var max = this.tabstops.length;
  1151. var index = this.index + (dir || 1);
  1152. index = Math.min(Math.max(index, 1), max);
  1153. if (index == max)
  1154. index = 0;
  1155. this.selectTabstop(index);
  1156. if (index === 0)
  1157. this.detach();
  1158. };
  1159. this.selectTabstop = function(index) {
  1160. this.$openTabstops = null;
  1161. var ts = this.tabstops[this.index];
  1162. if (ts)
  1163. this.addTabstopMarkers(ts);
  1164. this.index = index;
  1165. ts = this.tabstops[this.index];
  1166. if (!ts || !ts.length)
  1167. return;
  1168. this.selectedTabstop = ts;
  1169. var range = ts.firstNonLinked || ts;
  1170. if (ts.choices) range.cursor = range.start;
  1171. if (!this.editor.inVirtualSelectionMode) {
  1172. var sel = this.editor.multiSelect;
  1173. sel.toSingleRange(range);
  1174. for (var i = 0; i < ts.length; i++) {
  1175. if (ts.hasLinkedRanges && ts[i].linked)
  1176. continue;
  1177. sel.addRange(ts[i].clone(), true);
  1178. }
  1179. } else {
  1180. this.editor.selection.fromOrientedRange(range);
  1181. }
  1182. this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler);
  1183. if (this.selectedTabstop && this.selectedTabstop.choices)
  1184. this.editor.execCommand("startAutocomplete", {matches: this.selectedTabstop.choices});
  1185. };
  1186. this.addTabstops = function(tabstops, start, end) {
  1187. var useLink = this.useLink || !this.editor.getOption("enableMultiselect");
  1188. if (!this.$openTabstops)
  1189. this.$openTabstops = [];
  1190. if (!tabstops[0]) {
  1191. var p = Range.fromPoints(end, end);
  1192. moveRelative(p.start, start);
  1193. moveRelative(p.end, start);
  1194. tabstops[0] = [p];
  1195. tabstops[0].index = 0;
  1196. }
  1197. var i = this.index;
  1198. var arg = [i + 1, 0];
  1199. var ranges = this.ranges;
  1200. tabstops.forEach(function(ts, index) {
  1201. var dest = this.$openTabstops[index] || ts;
  1202. for (var i = 0; i < ts.length; i++) {
  1203. var p = ts[i];
  1204. var range = Range.fromPoints(p.start, p.end || p.start);
  1205. movePoint(range.start, start);
  1206. movePoint(range.end, start);
  1207. range.original = p;
  1208. range.tabstop = dest;
  1209. ranges.push(range);
  1210. if (dest != ts)
  1211. dest.unshift(range);
  1212. else
  1213. dest[i] = range;
  1214. if (p.fmtString || (dest.firstNonLinked && useLink)) {
  1215. range.linked = true;
  1216. dest.hasLinkedRanges = true;
  1217. } else if (!dest.firstNonLinked)
  1218. dest.firstNonLinked = range;
  1219. }
  1220. if (!dest.firstNonLinked)
  1221. dest.hasLinkedRanges = false;
  1222. if (dest === ts) {
  1223. arg.push(dest);
  1224. this.$openTabstops[index] = dest;
  1225. }
  1226. this.addTabstopMarkers(dest);
  1227. dest.rangeList = dest.rangeList || new RangeList();
  1228. dest.rangeList.$bias = 0;
  1229. dest.rangeList.addList(dest);
  1230. }, this);
  1231. if (arg.length > 2) {
  1232. if (this.tabstops.length)
  1233. arg.push(arg.splice(2, 1)[0]);
  1234. this.tabstops.splice.apply(this.tabstops, arg);
  1235. }
  1236. };
  1237. this.addTabstopMarkers = function(ts) {
  1238. var session = this.editor.session;
  1239. ts.forEach(function(range) {
  1240. if (!range.markerId)
  1241. range.markerId = session.addMarker(range, "ace_snippet-marker", "text");
  1242. });
  1243. };
  1244. this.removeTabstopMarkers = function(ts) {
  1245. var session = this.editor.session;
  1246. ts.forEach(function(range) {
  1247. session.removeMarker(range.markerId);
  1248. range.markerId = null;
  1249. });
  1250. };
  1251. this.removeRange = function(range) {
  1252. var i = range.tabstop.indexOf(range);
  1253. if (i != -1) range.tabstop.splice(i, 1);
  1254. i = this.ranges.indexOf(range);
  1255. if (i != -1) this.ranges.splice(i, 1);
  1256. i = range.tabstop.rangeList.ranges.indexOf(range);
  1257. if (i != -1) range.tabstop.splice(i, 1);
  1258. this.editor.session.removeMarker(range.markerId);
  1259. if (!range.tabstop.length) {
  1260. i = this.tabstops.indexOf(range.tabstop);
  1261. if (i != -1)
  1262. this.tabstops.splice(i, 1);
  1263. if (!this.tabstops.length)
  1264. this.detach();
  1265. }
  1266. };
  1267. this.keyboardHandler = new HashHandler();
  1268. this.keyboardHandler.bindKeys({
  1269. "Tab": function(editor) {
  1270. if (exports.snippetManager && exports.snippetManager.expandWithTab(editor))
  1271. return;
  1272. editor.tabstopManager.tabNext(1);
  1273. editor.renderer.scrollCursorIntoView();
  1274. },
  1275. "Shift-Tab": function(editor) {
  1276. editor.tabstopManager.tabNext(-1);
  1277. editor.renderer.scrollCursorIntoView();
  1278. },
  1279. "Esc": function(editor) {
  1280. editor.tabstopManager.detach();
  1281. }
  1282. });
  1283. }).call(TabstopManager.prototype);
  1284. var movePoint = function(point, diff) {
  1285. if (point.row == 0)
  1286. point.column += diff.column;
  1287. point.row += diff.row;
  1288. };
  1289. var moveRelative = function(point, start) {
  1290. if (point.row == start.row)
  1291. point.column -= start.column;
  1292. point.row -= start.row;
  1293. };
  1294. dom.importCssString("\
  1295. .ace_snippet-marker {\
  1296. -moz-box-sizing: border-box;\
  1297. box-sizing: border-box;\
  1298. background: rgba(194, 193, 208, 0.09);\
  1299. border: 1px dotted rgba(211, 208, 235, 0.62);\
  1300. position: absolute;\
  1301. }", "snippets.css", false);
  1302. exports.snippetManager = new SnippetManager();
  1303. var Editor = require("./editor").Editor;
  1304. (function() {
  1305. this.insertSnippet = function(content, options) {
  1306. return exports.snippetManager.insertSnippet(this, content, options);
  1307. };
  1308. this.expandSnippet = function(options) {
  1309. return exports.snippetManager.expandWithTab(this, options);
  1310. };
  1311. }).call(Editor.prototype);
  1312. });
  1313. define("ace/autocomplete",["require","exports","module","ace/keyboard/hash_handler","ace/autocomplete/popup","ace/autocomplete/util","ace/lib/lang","ace/lib/dom","ace/snippets","ace/config"], function(require, exports, module) {
  1314. "use strict";
  1315. var HashHandler = require("./keyboard/hash_handler").HashHandler;
  1316. var AcePopup = require("./autocomplete/popup").AcePopup;
  1317. var util = require("./autocomplete/util");
  1318. var lang = require("./lib/lang");
  1319. var dom = require("./lib/dom");
  1320. var snippetManager = require("./snippets").snippetManager;
  1321. var config = require("./config");
  1322. var Autocomplete = function() {
  1323. this.autoInsert = false;
  1324. this.autoSelect = true;
  1325. this.exactMatch = false;
  1326. this.gatherCompletionsId = 0;
  1327. this.keyboardHandler = new HashHandler();
  1328. this.keyboardHandler.bindKeys(this.commands);
  1329. this.blurListener = this.blurListener.bind(this);
  1330. this.changeListener = this.changeListener.bind(this);
  1331. this.mousedownListener = this.mousedownListener.bind(this);
  1332. this.mousewheelListener = this.mousewheelListener.bind(this);
  1333. this.changeTimer = lang.delayedCall(function() {
  1334. this.updateCompletions(true);
  1335. }.bind(this));
  1336. this.tooltipTimer = lang.delayedCall(this.updateDocTooltip.bind(this), 50);
  1337. };
  1338. (function() {
  1339. this.$init = function() {
  1340. this.popup = new AcePopup(document.body || document.documentElement);
  1341. this.popup.on("click", function(e) {
  1342. this.insertMatch();
  1343. e.stop();
  1344. }.bind(this));
  1345. this.popup.focus = this.editor.focus.bind(this.editor);
  1346. this.popup.on("show", this.tooltipTimer.bind(null, null));
  1347. this.popup.on("select", this.tooltipTimer.bind(null, null));
  1348. this.popup.on("changeHoverMarker", this.tooltipTimer.bind(null, null));
  1349. return this.popup;
  1350. };
  1351. this.getPopup = function() {
  1352. return this.popup || this.$init();
  1353. };
  1354. this.openPopup = function(editor, prefix, keepPopupPosition) {
  1355. if (!this.popup)
  1356. this.$init();
  1357. this.popup.autoSelect = this.autoSelect;
  1358. this.popup.setData(this.completions.filtered, this.completions.filterText);
  1359. editor.keyBinding.addKeyboardHandler(this.keyboardHandler);
  1360. var renderer = editor.renderer;
  1361. this.popup.setRow(this.autoSelect ? 0 : -1);
  1362. if (!keepPopupPosition) {
  1363. this.popup.setTheme(editor.getTheme());
  1364. this.popup.setFontSize(editor.getFontSize());
  1365. var lineHeight = renderer.layerConfig.lineHeight;
  1366. var pos = renderer.$cursorLayer.getPixelPosition(this.base, true);
  1367. pos.left -= this.popup.getTextLeftOffset();
  1368. var rect = editor.container.getBoundingClientRect();
  1369. pos.top += rect.top - renderer.layerConfig.offset;
  1370. pos.left += rect.left - editor.renderer.scrollLeft;
  1371. pos.left += renderer.gutterWidth;
  1372. this.popup.show(pos, lineHeight);
  1373. } else if (keepPopupPosition && !prefix) {
  1374. this.detach();
  1375. }
  1376. this.changeTimer.cancel();
  1377. };
  1378. this.detach = function() {
  1379. this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler);
  1380. this.editor.off("changeSelection", this.changeListener);
  1381. this.editor.off("blur", this.blurListener);
  1382. this.editor.off("mousedown", this.mousedownListener);
  1383. this.editor.off("mousewheel", this.mousewheelListener);
  1384. this.changeTimer.cancel();
  1385. this.hideDocTooltip();
  1386. this.gatherCompletionsId += 1;
  1387. if (this.popup && this.popup.isOpen)
  1388. this.popup.hide();
  1389. if (this.base)
  1390. this.base.detach();
  1391. this.activated = false;
  1392. this.completions = this.base = null;
  1393. };
  1394. this.changeListener = function(e) {
  1395. var cursor = this.editor.selection.lead;
  1396. if (cursor.row != this.base.row || cursor.column < this.base.column) {
  1397. this.detach();
  1398. }
  1399. if (this.activated)
  1400. this.changeTimer.schedule();
  1401. else
  1402. this.detach();
  1403. };
  1404. this.blurListener = function(e) {
  1405. var el = document.activeElement;
  1406. var text = this.editor.textInput.getElement();
  1407. var fromTooltip = e.relatedTarget && this.tooltipNode && this.tooltipNode.contains(e.relatedTarget);
  1408. var container = this.popup && this.popup.container;
  1409. if (el != text && el.parentNode != container && !fromTooltip
  1410. && el != this.tooltipNode && e.relatedTarget != text
  1411. ) {
  1412. this.detach();
  1413. }
  1414. };
  1415. this.mousedownListener = function(e) {
  1416. this.detach();
  1417. };
  1418. this.mousewheelListener = function(e) {
  1419. this.detach();
  1420. };
  1421. this.goTo = function(where) {
  1422. this.popup.goTo(where);
  1423. };
  1424. this.insertMatch = function(data, options) {
  1425. if (!data)
  1426. data = this.popup.getData(this.popup.getRow());
  1427. if (!data)
  1428. return false;
  1429. var completions = this.completions;
  1430. this.editor.startOperation({command: {name: "insertMatch"}});
  1431. if (data.completer && data.completer.insertMatch) {
  1432. data.completer.insertMatch(this.editor, data);
  1433. } else {
  1434. if (completions.filterText) {
  1435. var ranges = this.editor.selection.getAllRanges();
  1436. for (var i = 0, range; range = ranges[i]; i++) {
  1437. range.start.column -= completions.filterText.length;
  1438. this.editor.session.remove(range);
  1439. }
  1440. }
  1441. if (data.snippet)
  1442. snippetManager.insertSnippet(this.editor, data.snippet);
  1443. else
  1444. this.editor.execCommand("insertstring", data.value || data);
  1445. }
  1446. if (this.completions == completions)
  1447. this.detach();
  1448. this.editor.endOperation();
  1449. };
  1450. this.commands = {
  1451. "Up": function(editor) { editor.completer.goTo("up"); },
  1452. "Down": function(editor) { editor.completer.goTo("down"); },
  1453. "Ctrl-Up|Ctrl-Home": function(editor) { editor.completer.goTo("start"); },
  1454. "Ctrl-Down|Ctrl-End": function(editor) { editor.completer.goTo("end"); },
  1455. "Esc": function(editor) { editor.completer.detach(); },
  1456. "Return": function(editor) { return editor.completer.insertMatch(); },
  1457. "Shift-Return": function(editor) { editor.completer.insertMatch(null, {deleteSuffix: true}); },
  1458. "Tab": function(editor) {
  1459. var result = editor.completer.insertMatch();
  1460. if (!result && !editor.tabstopManager)
  1461. editor.completer.goTo("down");
  1462. else
  1463. return result;
  1464. },
  1465. "PageUp": function(editor) { editor.completer.popup.gotoPageUp(); },
  1466. "PageDown": function(editor) { editor.completer.popup.gotoPageDown(); }
  1467. };
  1468. this.gatherCompletions = function(editor, callback) {
  1469. var session = editor.getSession();
  1470. var pos = editor.getCursorPosition();
  1471. var prefix = util.getCompletionPrefix(editor);
  1472. this.base = session.doc.createAnchor(pos.row, pos.column - prefix.length);
  1473. this.base.$insertRight = true;
  1474. var matches = [];
  1475. var total = editor.completers.length;
  1476. editor.completers.forEach(function(completer, i) {
  1477. completer.getCompletions(editor, session, pos, prefix, function(err, results) {
  1478. if (!err && results)
  1479. matches = matches.concat(results);
  1480. callback(null, {
  1481. prefix: util.getCompletionPrefix(editor),
  1482. matches: matches,
  1483. finished: (--total === 0)
  1484. });
  1485. });
  1486. });
  1487. return true;
  1488. };
  1489. this.showPopup = function(editor, options) {
  1490. if (this.editor)
  1491. this.detach();
  1492. this.activated = true;
  1493. this.editor = editor;
  1494. if (editor.completer != this) {
  1495. if (editor.completer)
  1496. editor.completer.detach();
  1497. editor.completer = this;
  1498. }
  1499. editor.on("changeSelection", this.changeListener);
  1500. editor.on("blur", this.blurListener);
  1501. editor.on("mousedown", this.mousedownListener);
  1502. editor.on("mousewheel", this.mousewheelListener);
  1503. this.updateCompletions(false, options);
  1504. };
  1505. this.updateCompletions = function(keepPopupPosition, options) {
  1506. if (keepPopupPosition && this.base && this.completions) {
  1507. var pos = this.editor.getCursorPosition();
  1508. var prefix = this.editor.session.getTextRange({start: this.base, end: pos});
  1509. if (prefix == this.completions.filterText)
  1510. return;
  1511. this.completions.setFilter(prefix);
  1512. if (!this.completions.filtered.length)
  1513. return this.detach();
  1514. if (this.completions.filtered.length == 1
  1515. && this.completions.filtered[0].value == prefix
  1516. && !this.completions.filtered[0].snippet)
  1517. return this.detach();
  1518. this.openPopup(this.editor, prefix, keepPopupPosition);
  1519. return;
  1520. }
  1521. if (options && options.matches) {
  1522. var pos = this.editor.getSelectionRange().start;
  1523. this.base = this.editor.session.doc.createAnchor(pos.row, pos.column);
  1524. this.base.$insertRight = true;
  1525. this.completions = new FilteredList(options.matches);
  1526. return this.openPopup(this.editor, "", keepPopupPosition);
  1527. }
  1528. var _id = this.gatherCompletionsId;
  1529. var detachIfFinished = function(results) {
  1530. if (!results.finished) return;
  1531. return this.detach();
  1532. }.bind(this);
  1533. var processResults = function(results) {
  1534. var prefix = results.prefix;
  1535. var matches = results.matches;
  1536. this.completions = new FilteredList(matches);
  1537. if (this.exactMatch)
  1538. this.completions.exactMatch = true;
  1539. this.completions.setFilter(prefix);
  1540. var filtered = this.completions.filtered;
  1541. if (!filtered.length)
  1542. return detachIfFinished(results);
  1543. if (filtered.length == 1 && filtered[0].value == prefix && !filtered[0].snippet)
  1544. return detachIfFinished(results);
  1545. if (this.autoInsert && filtered.length == 1 && results.finished)
  1546. return this.insertMatch(filtered[0]);
  1547. this.openPopup(this.editor, prefix, keepPopupPosition);
  1548. }.bind(this);
  1549. var isImmediate = true;
  1550. var immediateResults = null;
  1551. this.gatherCompletions(this.editor, function(err, results) {
  1552. var prefix = results.prefix;
  1553. var matches = results && results.matches;
  1554. if (!matches || !matches.length)
  1555. return detachIfFinished(results);
  1556. if (prefix.indexOf(results.prefix) !== 0 || _id != this.gatherCompletionsId)
  1557. return;
  1558. if (isImmediate) {
  1559. immediateResults = results;
  1560. return;
  1561. }
  1562. processResults(results);
  1563. }.bind(this));
  1564. isImmediate = false;
  1565. if (immediateResults) {
  1566. var results = immediateResults;
  1567. immediateResults = null;
  1568. processResults(results);
  1569. }
  1570. };
  1571. this.cancelContextMenu = function() {
  1572. this.editor.$mouseHandler.cancelContextMenu();
  1573. };
  1574. this.updateDocTooltip = function() {
  1575. var popup = this.popup;
  1576. var all = popup.data;
  1577. var selected = all && (all[popup.getHoveredRow()] || all[popup.getRow()]);
  1578. var doc = null;
  1579. if (!selected || !this.editor || !this.popup.isOpen)
  1580. return this.hideDocTooltip();
  1581. this.editor.completers.some(function(completer) {
  1582. if (completer.getDocTooltip)
  1583. doc = completer.getDocTooltip(selected);
  1584. return doc;
  1585. });
  1586. if (!doc && typeof selected != "string")
  1587. doc = selected;
  1588. if (typeof doc == "string")
  1589. doc = {docText: doc};
  1590. if (!doc || !(doc.docHTML || doc.docText))
  1591. return this.hideDocTooltip();
  1592. this.showDocTooltip(doc);
  1593. };
  1594. this.showDocTooltip = function(item) {
  1595. if (!this.tooltipNode) {
  1596. this.tooltipNode = dom.createElement("div");
  1597. this.tooltipNode.className = "ace_tooltip ace_doc-tooltip";
  1598. this.tooltipNode.style.margin = 0;
  1599. this.tooltipNode.style.pointerEvents = "auto";
  1600. this.tooltipNode.tabIndex = -1;
  1601. this.tooltipNode.onblur = this.blurListener.bind(this);
  1602. this.tooltipNode.onclick = this.onTooltipClick.bind(this);
  1603. }
  1604. var tooltipNode = this.tooltipNode;
  1605. if (item.docHTML) {
  1606. tooltipNode.innerHTML = item.docHTML;
  1607. } else if (item.docText) {
  1608. tooltipNode.textContent = item.docText;
  1609. }
  1610. if (!tooltipNode.parentNode)
  1611. document.body.appendChild(tooltipNode);
  1612. var popup = this.popup;
  1613. var rect = popup.container.getBoundingClientRect();
  1614. tooltipNode.style.top = popup.container.style.top;
  1615. tooltipNode.style.bottom = popup.container.style.bottom;
  1616. tooltipNode.style.display = "block";
  1617. if (window.innerWidth - rect.right < 320) {
  1618. if (rect.left < 320) {
  1619. if(popup.isTopdown) {
  1620. tooltipNode.style.top = rect.bottom + "px";
  1621. tooltipNode.style.left = rect.left + "px";
  1622. tooltipNode.style.right = "";
  1623. tooltipNode.style.bottom = "";
  1624. } else {
  1625. tooltipNode.style.top = popup.container.offsetTop - tooltipNode.offsetHeight + "px";
  1626. tooltipNode.style.left = rect.left + "px";
  1627. tooltipNode.style.right = "";
  1628. tooltipNode.style.bottom = "";
  1629. }
  1630. } else {
  1631. tooltipNode.style.right = window.innerWidth - rect.left + "px";
  1632. tooltipNode.style.left = "";
  1633. }
  1634. } else {
  1635. tooltipNode.style.left = (rect.right + 1) + "px";
  1636. tooltipNode.style.right = "";
  1637. }
  1638. };
  1639. this.hideDocTooltip = function() {
  1640. this.tooltipTimer.cancel();
  1641. if (!this.tooltipNode) return;
  1642. var el = this.tooltipNode;
  1643. if (!this.editor.isFocused() && document.activeElement == el)
  1644. this.editor.focus();
  1645. this.tooltipNode = null;
  1646. if (el.parentNode)
  1647. el.parentNode.removeChild(el);
  1648. };
  1649. this.onTooltipClick = function(e) {
  1650. var a = e.target;
  1651. while (a && a != this.tooltipNode) {
  1652. if (a.nodeName == "A" && a.href) {
  1653. a.rel = "noreferrer";
  1654. a.target = "_blank";
  1655. break;
  1656. }
  1657. a = a.parentNode;
  1658. }
  1659. };
  1660. this.destroy = function() {
  1661. this.detach();
  1662. if (this.popup) {
  1663. this.popup.destroy();
  1664. var el = this.popup.container;
  1665. if (el && el.parentNode)
  1666. el.parentNode.removeChild(el);
  1667. }
  1668. if (this.editor && this.editor.completer == this)
  1669. this.editor.completer == null;
  1670. this.popup = null;
  1671. };
  1672. }).call(Autocomplete.prototype);
  1673. Autocomplete.for = function(editor) {
  1674. if (editor.completer) {
  1675. return editor.completer;
  1676. }
  1677. if (config.get("sharedPopups")) {
  1678. if (!Autocomplete.$shared)
  1679. Autocomplete.$sharedInstance = new Autocomplete();
  1680. editor.completer = Autocomplete.$sharedInstance;
  1681. } else {
  1682. editor.completer = new Autocomplete();
  1683. editor.once("destroy", function(e, editor) {
  1684. editor.completer.destroy();
  1685. });
  1686. }
  1687. return editor.completer;
  1688. };
  1689. Autocomplete.startCommand = {
  1690. name: "startAutocomplete",
  1691. exec: function(editor, options) {
  1692. var completer = Autocomplete.for(editor);
  1693. completer.autoInsert = false;
  1694. completer.autoSelect = true;
  1695. completer.showPopup(editor, options);
  1696. completer.cancelContextMenu();
  1697. },
  1698. bindKey: "Ctrl-Space|Ctrl-Shift-Space|Alt-Space"
  1699. };
  1700. var FilteredList = function(array, filterText) {
  1701. this.all = array;
  1702. this.filtered = array;
  1703. this.filterText = filterText || "";
  1704. this.exactMatch = false;
  1705. };
  1706. (function(){
  1707. this.setFilter = function(str) {
  1708. if (str.length > this.filterText && str.lastIndexOf(this.filterText, 0) === 0)
  1709. var matches = this.filtered;
  1710. else
  1711. var matches = this.all;
  1712. this.filterText = str;
  1713. matches = this.filterCompletions(matches, this.filterText);
  1714. matches = matches.sort(function(a, b) {
  1715. return b.exactMatch - a.exactMatch || b.$score - a.$score
  1716. || (a.caption || a.value).localeCompare(b.caption || b.value);
  1717. });
  1718. var prev = null;
  1719. matches = matches.filter(function(item){
  1720. var caption = item.snippet || item.caption || item.value;
  1721. if (caption === prev) return false;
  1722. prev = caption;
  1723. return true;
  1724. });
  1725. this.filtered = matches;
  1726. };
  1727. this.filterCompletions = function(items, needle) {
  1728. var results = [];
  1729. var upper = needle.toUpperCase();
  1730. var lower = needle.toLowerCase();
  1731. loop: for (var i = 0, item; item = items[i]; i++) {
  1732. var caption = item.caption || item.value || item.snippet;
  1733. if (!caption) continue;
  1734. var lastIndex = -1;
  1735. var matchMask = 0;
  1736. var penalty = 0;
  1737. var index, distance;
  1738. if (this.exactMatch) {
  1739. if (needle !== caption.substr(0, needle.length))
  1740. continue loop;
  1741. } else {
  1742. var fullMatchIndex = caption.toLowerCase().indexOf(lower);
  1743. if (fullMatchIndex > -1) {
  1744. penalty = fullMatchIndex;
  1745. } else {
  1746. for (var j = 0; j < needle.length; j++) {
  1747. var i1 = caption.indexOf(lower[j], lastIndex + 1);
  1748. var i2 = caption.indexOf(upper[j], lastIndex + 1);
  1749. index = (i1 >= 0) ? ((i2 < 0 || i1 < i2) ? i1 : i2) : i2;
  1750. if (index < 0)
  1751. continue loop;
  1752. distance = index - lastIndex - 1;
  1753. if (distance > 0) {
  1754. if (lastIndex === -1)
  1755. penalty += 10;
  1756. penalty += distance;
  1757. matchMask = matchMask | (1 << j);
  1758. }
  1759. lastIndex = index;
  1760. }
  1761. }
  1762. }
  1763. item.matchMask = matchMask;
  1764. item.exactMatch = penalty ? 0 : 1;
  1765. item.$score = (item.score || 0) - penalty;
  1766. results.push(item);
  1767. }
  1768. return results;
  1769. };
  1770. }).call(FilteredList.prototype);
  1771. exports.Autocomplete = Autocomplete;
  1772. exports.FilteredList = FilteredList;
  1773. });
  1774. define("ace/ext/menu_tools/overlay_page",["require","exports","module","ace/lib/dom"], function(require, exports, module) {
  1775. 'use strict';
  1776. var dom = require("../../lib/dom");
  1777. var cssText = "#ace_settingsmenu, #kbshortcutmenu {\
  1778. background-color: #F7F7F7;\
  1779. color: black;\
  1780. box-shadow: -5px 4px 5px rgba(126, 126, 126, 0.55);\
  1781. padding: 1em 0.5em 2em 1em;\
  1782. overflow: auto;\
  1783. position: absolute;\
  1784. margin: 0;\
  1785. bottom: 0;\
  1786. right: 0;\
  1787. top: 0;\
  1788. z-index: 9991;\
  1789. cursor: default;\
  1790. }\
  1791. .ace_dark #ace_settingsmenu, .ace_dark #kbshortcutmenu {\
  1792. box-shadow: -20px 10px 25px rgba(126, 126, 126, 0.25);\
  1793. background-color: rgba(255, 255, 255, 0.6);\
  1794. color: black;\
  1795. }\
  1796. .ace_optionsMenuEntry:hover {\
  1797. background-color: rgba(100, 100, 100, 0.1);\
  1798. transition: all 0.3s\
  1799. }\
  1800. .ace_closeButton {\
  1801. background: rgba(245, 146, 146, 0.5);\
  1802. border: 1px solid #F48A8A;\
  1803. border-radius: 50%;\
  1804. padding: 7px;\
  1805. position: absolute;\
  1806. right: -8px;\
  1807. top: -8px;\
  1808. z-index: 100000;\
  1809. }\
  1810. .ace_closeButton{\
  1811. background: rgba(245, 146, 146, 0.9);\
  1812. }\
  1813. .ace_optionsMenuKey {\
  1814. color: darkslateblue;\
  1815. font-weight: bold;\
  1816. }\
  1817. .ace_optionsMenuCommand {\
  1818. color: darkcyan;\
  1819. font-weight: normal;\
  1820. }\
  1821. .ace_optionsMenuEntry input, .ace_optionsMenuEntry button {\
  1822. vertical-align: middle;\
  1823. }\
  1824. .ace_optionsMenuEntry button[ace_selected_button=true] {\
  1825. background: #e7e7e7;\
  1826. box-shadow: 1px 0px 2px 0px #adadad inset;\
  1827. border-color: #adadad;\
  1828. }\
  1829. .ace_optionsMenuEntry button {\
  1830. background: white;\
  1831. border: 1px solid lightgray;\
  1832. margin: 0px;\
  1833. }\
  1834. .ace_optionsMenuEntry button:hover{\
  1835. background: #f0f0f0;\
  1836. }";
  1837. dom.importCssString(cssText, "settings_menu.css", false);
  1838. module.exports.overlayPage = function overlayPage(editor, contentElement, callback) {
  1839. var closer = document.createElement('div');
  1840. var ignoreFocusOut = false;
  1841. function documentEscListener(e) {
  1842. if (e.keyCode === 27) {
  1843. close();
  1844. }
  1845. }
  1846. function close() {
  1847. if (!closer) return;
  1848. document.removeEventListener('keydown', documentEscListener);
  1849. closer.parentNode.removeChild(closer);
  1850. if (editor) {
  1851. editor.focus();
  1852. }
  1853. closer = null;
  1854. callback && callback();
  1855. }
  1856. function setIgnoreFocusOut(ignore) {
  1857. ignoreFocusOut = ignore;
  1858. if (ignore) {
  1859. closer.style.pointerEvents = "none";
  1860. contentElement.style.pointerEvents = "auto";
  1861. }
  1862. }
  1863. closer.style.cssText = 'margin: 0; padding: 0; ' +
  1864. 'position: fixed; top:0; bottom:0; left:0; right:0;' +
  1865. 'z-index: 9990; ' +
  1866. (editor ? 'background-color: rgba(0, 0, 0, 0.3);' : '');
  1867. closer.addEventListener('click', function(e) {
  1868. if (!ignoreFocusOut) {
  1869. close();
  1870. }
  1871. });
  1872. document.addEventListener('keydown', documentEscListener);
  1873. contentElement.addEventListener('click', function (e) {
  1874. e.stopPropagation();
  1875. });
  1876. closer.appendChild(contentElement);
  1877. document.body.appendChild(closer);
  1878. if (editor) {
  1879. editor.blur();
  1880. }
  1881. return {
  1882. close: close,
  1883. setIgnoreFocusOut: setIgnoreFocusOut
  1884. };
  1885. };
  1886. });
  1887. define("ace/ext/modelist",["require","exports","module"], function(require, exports, module) {
  1888. "use strict";
  1889. var modes = [];
  1890. function getModeForPath(path) {
  1891. var mode = modesByName.text;
  1892. var fileName = path.split(/[\/\\]/).pop();
  1893. for (var i = 0; i < modes.length; i++) {
  1894. if (modes[i].supportsFile(fileName)) {
  1895. mode = modes[i];
  1896. break;
  1897. }
  1898. }
  1899. return mode;
  1900. }
  1901. var Mode = function(name, caption, extensions) {
  1902. this.name = name;
  1903. this.caption = caption;
  1904. this.mode = "ace/mode/" + name;
  1905. this.extensions = extensions;
  1906. var re;
  1907. if (/\^/.test(extensions)) {
  1908. re = extensions.replace(/\|(\^)?/g, function(a, b){
  1909. return "$|" + (b ? "^" : "^.*\\.");
  1910. }) + "$";
  1911. } else {
  1912. re = "^.*\\.(" + extensions + ")$";
  1913. }
  1914. this.extRe = new RegExp(re, "gi");
  1915. };
  1916. Mode.prototype.supportsFile = function(filename) {
  1917. return filename.match(this.extRe);
  1918. };
  1919. var supportedModes = {
  1920. ABAP: ["abap"],
  1921. ABC: ["abc"],
  1922. ActionScript:["as"],
  1923. ADA: ["ada|adb"],
  1924. Alda: ["alda"],
  1925. Apache_Conf: ["^htaccess|^htgroups|^htpasswd|^conf|htaccess|htgroups|htpasswd"],
  1926. Apex: ["apex|cls|trigger|tgr"],
  1927. AQL: ["aql"],
  1928. AsciiDoc: ["asciidoc|adoc"],
  1929. ASL: ["dsl|asl|asl.json"],
  1930. Assembly_x86:["asm|a"],
  1931. AutoHotKey: ["ahk"],
  1932. BatchFile: ["bat|cmd"],
  1933. C_Cpp: ["cpp|c|cc|cxx|h|hh|hpp|ino"],
  1934. C9Search: ["c9search_results"],
  1935. Cirru: ["cirru|cr"],
  1936. Clojure: ["clj|cljs"],
  1937. Cobol: ["CBL|COB"],
  1938. coffee: ["coffee|cf|cson|^Cakefile"],
  1939. ColdFusion: ["cfm"],
  1940. Crystal: ["cr"],
  1941. CSharp: ["cs"],
  1942. Csound_Document: ["csd"],
  1943. Csound_Orchestra: ["orc"],
  1944. Csound_Score: ["sco"],
  1945. CSS: ["css"],
  1946. Curly: ["curly"],
  1947. D: ["d|di"],
  1948. Dart: ["dart"],
  1949. Diff: ["diff|patch"],
  1950. Dockerfile: ["^Dockerfile"],
  1951. Dot: ["dot"],
  1952. Drools: ["drl"],
  1953. Edifact: ["edi"],
  1954. Eiffel: ["e|ge"],
  1955. EJS: ["ejs"],
  1956. Elixir: ["ex|exs"],
  1957. Elm: ["elm"],
  1958. Erlang: ["erl|hrl"],
  1959. Forth: ["frt|fs|ldr|fth|4th"],
  1960. Fortran: ["f|f90"],
  1961. FSharp: ["fsi|fs|ml|mli|fsx|fsscript"],
  1962. FSL: ["fsl"],
  1963. FTL: ["ftl"],
  1964. Gcode: ["gcode"],
  1965. Gherkin: ["feature"],
  1966. Gitignore: ["^.gitignore"],
  1967. Glsl: ["glsl|frag|vert"],
  1968. Gobstones: ["gbs"],
  1969. golang: ["go"],
  1970. GraphQLSchema: ["gql"],
  1971. Groovy: ["groovy"],
  1972. HAML: ["haml"],
  1973. Handlebars: ["hbs|handlebars|tpl|mustache"],
  1974. Haskell: ["hs"],
  1975. Haskell_Cabal: ["cabal"],
  1976. haXe: ["hx"],
  1977. Hjson: ["hjson"],
  1978. HTML: ["html|htm|xhtml|vue|we|wpy"],
  1979. HTML_Elixir: ["eex|html.eex"],
  1980. HTML_Ruby: ["erb|rhtml|html.erb"],
  1981. INI: ["ini|conf|cfg|prefs"],
  1982. Io: ["io"],
  1983. Jack: ["jack"],
  1984. Jade: ["jade|pug"],
  1985. Java: ["java"],
  1986. JavaScript: ["js|jsm|jsx"],
  1987. JSON: ["json"],
  1988. JSON5: ["json5"],
  1989. JSONiq: ["jq"],
  1990. JSP: ["jsp"],
  1991. JSSM: ["jssm|jssm_state"],
  1992. JSX: ["jsx"],
  1993. Julia: ["jl"],
  1994. Kotlin: ["kt|kts"],
  1995. LaTeX: ["tex|latex|ltx|bib"],
  1996. Latte: ["latte"],
  1997. LESS: ["less"],
  1998. Liquid: ["liquid"],
  1999. Lisp: ["lisp"],
  2000. LiveScript: ["ls"],
  2001. LogiQL: ["logic|lql"],
  2002. LSL: ["lsl"],
  2003. Lua: ["lua"],
  2004. LuaPage: ["lp"],
  2005. Lucene: ["lucene"],
  2006. Makefile: ["^Makefile|^GNUmakefile|^makefile|^OCamlMakefile|make"],
  2007. Markdown: ["md|markdown"],
  2008. Mask: ["mask"],
  2009. MATLAB: ["matlab"],
  2010. Maze: ["mz"],
  2011. MediaWiki: ["wiki|mediawiki"],
  2012. MEL: ["mel"],
  2013. MIPS: ["s|asm"],
  2014. MIXAL: ["mixal"],
  2015. MUSHCode: ["mc|mush"],
  2016. MySQL: ["mysql"],
  2017. Nginx: ["nginx|conf"],
  2018. Nim: ["nim"],
  2019. Nix: ["nix"],
  2020. NSIS: ["nsi|nsh"],
  2021. Nunjucks: ["nunjucks|nunjs|nj|njk"],
  2022. ObjectiveC: ["m|mm"],
  2023. OCaml: ["ml|mli"],
  2024. Pascal: ["pas|p"],
  2025. Perl: ["pl|pm"],
  2026. pgSQL: ["pgsql"],
  2027. PHP: ["php|inc|phtml|shtml|php3|php4|php5|phps|phpt|aw|ctp|module"],
  2028. PHP_Laravel_blade: ["blade.php"],
  2029. Pig: ["pig"],
  2030. Powershell: ["ps1"],
  2031. Praat: ["praat|praatscript|psc|proc"],
  2032. Prisma: ["prisma"],
  2033. Prolog: ["plg|prolog"],
  2034. Properties: ["properties"],
  2035. Protobuf: ["proto"],
  2036. Puppet: ["epp|pp"],
  2037. Python: ["py"],
  2038. QML: ["qml"],
  2039. R: ["r"],
  2040. Raku: ["raku|rakumod|rakutest|p6|pl6|pm6"],
  2041. Razor: ["cshtml|asp"],
  2042. RDoc: ["Rd"],
  2043. Red: ["red|reds"],
  2044. RHTML: ["Rhtml"],
  2045. RST: ["rst"],
  2046. Ruby: ["rb|ru|gemspec|rake|^Guardfile|^Rakefile|^Gemfile"],
  2047. Rust: ["rs"],
  2048. SASS: ["sass"],
  2049. SCAD: ["scad"],
  2050. Scala: ["scala|sbt"],
  2051. Scheme: ["scm|sm|rkt|oak|scheme"],
  2052. Scrypt: ["scrypt"],
  2053. SCSS: ["scss"],
  2054. SH: ["sh|bash|^.bashrc"],
  2055. SJS: ["sjs"],
  2056. Slim: ["slim|skim"],
  2057. Smarty: ["smarty|tpl"],
  2058. Smithy: ["smithy"],
  2059. snippets: ["snippets"],
  2060. Soy_Template:["soy"],
  2061. Space: ["space"],
  2062. SQL: ["sql"],
  2063. SQLServer: ["sqlserver"],
  2064. Stylus: ["styl|stylus"],
  2065. SVG: ["svg"],
  2066. Swift: ["swift"],
  2067. Tcl: ["tcl"],
  2068. Terraform: ["tf", "tfvars", "terragrunt"],
  2069. Tex: ["tex"],
  2070. Text: ["txt"],
  2071. Textile: ["textile"],
  2072. Toml: ["toml"],
  2073. TSX: ["tsx"],
  2074. Twig: ["twig|swig"],
  2075. Typescript: ["ts|typescript|str"],
  2076. Vala: ["vala"],
  2077. VBScript: ["vbs|vb"],
  2078. Velocity: ["vm"],
  2079. Verilog: ["v|vh|sv|svh"],
  2080. VHDL: ["vhd|vhdl"],
  2081. Visualforce: ["vfp|component|page"],
  2082. Wollok: ["wlk|wpgm|wtest"],
  2083. XML: ["xml|rdf|rss|wsdl|xslt|atom|mathml|mml|xul|xbl|xaml"],
  2084. XQuery: ["xq"],
  2085. YAML: ["yaml|yml"],
  2086. Zeek: ["zeek|bro"],
  2087. Django: ["html"]
  2088. };
  2089. var nameOverrides = {
  2090. ObjectiveC: "Objective-C",
  2091. CSharp: "C#",
  2092. golang: "Go",
  2093. C_Cpp: "C and C++",
  2094. Csound_Document: "Csound Document",
  2095. Csound_Orchestra: "Csound",
  2096. Csound_Score: "Csound Score",
  2097. coffee: "CoffeeScript",
  2098. HTML_Ruby: "HTML (Ruby)",
  2099. HTML_Elixir: "HTML (Elixir)",
  2100. FTL: "FreeMarker",
  2101. PHP_Laravel_blade: "PHP (Blade Template)",
  2102. Perl6: "Perl 6",
  2103. AutoHotKey: "AutoHotkey / AutoIt"
  2104. };
  2105. var modesByName = {};
  2106. for (var name in supportedModes) {
  2107. var data = supportedModes[name];
  2108. var displayName = (nameOverrides[name] || name).replace(/_/g, " ");
  2109. var filename = name.toLowerCase();
  2110. var mode = new Mode(filename, displayName, data[0]);
  2111. modesByName[filename] = mode;
  2112. modes.push(mode);
  2113. }
  2114. module.exports = {
  2115. getModeForPath: getModeForPath,
  2116. modes: modes,
  2117. modesByName: modesByName
  2118. };
  2119. });
  2120. define("ace/ext/prompt",["require","exports","module","ace/range","ace/lib/dom","ace/ext/menu_tools/get_editor_keyboard_shortcuts","ace/autocomplete","ace/autocomplete/popup","ace/autocomplete/popup","ace/undomanager","ace/tokenizer","ace/ext/menu_tools/overlay_page","ace/ext/modelist"], function(require, exports, module) {
  2121. "use strict";
  2122. var Range = require("../range").Range;
  2123. var dom = require("../lib/dom");
  2124. var shortcuts = require("../ext/menu_tools/get_editor_keyboard_shortcuts");
  2125. var FilteredList= require("../autocomplete").FilteredList;
  2126. var AcePopup = require('../autocomplete/popup').AcePopup;
  2127. var $singleLineEditor = require('../autocomplete/popup').$singleLineEditor;
  2128. var UndoManager = require("../undomanager").UndoManager;
  2129. var Tokenizer = require("../tokenizer").Tokenizer;
  2130. var overlayPage = require("./menu_tools/overlay_page").overlayPage;
  2131. var modelist = require("./modelist");
  2132. var openPrompt;
  2133. function prompt(editor, message, options, callback) {
  2134. if (typeof message == "object") {
  2135. return prompt(editor, "", message, options);
  2136. }
  2137. if (openPrompt) {
  2138. var lastPrompt = openPrompt;
  2139. editor = lastPrompt.editor;
  2140. lastPrompt.close();
  2141. if (lastPrompt.name && lastPrompt.name == options.name)
  2142. return;
  2143. }
  2144. if (options.$type)
  2145. return prompt[options.$type](editor, callback);
  2146. var cmdLine = $singleLineEditor();
  2147. cmdLine.session.setUndoManager(new UndoManager());
  2148. var el = dom.buildDom(["div", {class: "ace_prompt_container" + (options.hasDescription ? " input-box-with-description" : "")}]);
  2149. var overlay = overlayPage(editor, el, done);
  2150. el.appendChild(cmdLine.container);
  2151. if (editor) {
  2152. editor.cmdLine = cmdLine;
  2153. cmdLine.setOption("fontSize", editor.getOption("fontSize"));
  2154. }
  2155. if (message) {
  2156. cmdLine.setValue(message, 1);
  2157. }
  2158. if (options.selection) {
  2159. cmdLine.selection.setRange({
  2160. start: cmdLine.session.doc.indexToPosition(options.selection[0]),
  2161. end: cmdLine.session.doc.indexToPosition(options.selection[1])
  2162. });
  2163. }
  2164. if (options.getCompletions) {
  2165. var popup = new AcePopup();
  2166. popup.renderer.setStyle("ace_autocomplete_inline");
  2167. popup.container.style.display = "block";
  2168. popup.container.style.maxWidth = "600px";
  2169. popup.container.style.width = "100%";
  2170. popup.container.style.marginTop = "3px";
  2171. popup.renderer.setScrollMargin(2, 2, 0, 0);
  2172. popup.autoSelect = false;
  2173. popup.renderer.$maxLines = 15;
  2174. popup.setRow(-1);
  2175. popup.on("click", function(e) {
  2176. var data = popup.getData(popup.getRow());
  2177. if (!data.error) {
  2178. cmdLine.setValue(data.value || data.name || data);
  2179. accept();
  2180. e.stop();
  2181. }
  2182. });
  2183. el.appendChild(popup.container);
  2184. updateCompletions();
  2185. }
  2186. if (options.$rules) {
  2187. var tokenizer = new Tokenizer(options.$rules);
  2188. cmdLine.session.bgTokenizer.setTokenizer(tokenizer);
  2189. }
  2190. if (options.placeholder) {
  2191. cmdLine.setOption("placeholder", options.placeholder);
  2192. }
  2193. if (options.hasDescription) {
  2194. var promptTextContainer = dom.buildDom(["div", {class: "ace_prompt_text_container"}]);
  2195. dom.buildDom(options.prompt || "Press 'Enter' to confirm or 'Escape' to cancel", promptTextContainer);
  2196. el.appendChild(promptTextContainer);
  2197. }
  2198. overlay.setIgnoreFocusOut(options.ignoreFocusOut);
  2199. function accept() {
  2200. var val;
  2201. if (popup && popup.getCursorPosition().row > 0) {
  2202. val = valueFromRecentList();
  2203. } else {
  2204. val = cmdLine.getValue();
  2205. }
  2206. var curData = popup ? popup.getData(popup.getRow()) : val;
  2207. if (curData && !curData.error) {
  2208. done();
  2209. options.onAccept && options.onAccept({
  2210. value: val,
  2211. item: curData
  2212. }, cmdLine);
  2213. }
  2214. }
  2215. var keys = {
  2216. "Enter": accept,
  2217. "Esc|Shift-Esc": function() {
  2218. options.onCancel && options.onCancel(cmdLine.getValue(), cmdLine);
  2219. done();
  2220. }
  2221. };
  2222. if (popup) {
  2223. Object.assign(keys, {
  2224. "Up": function(editor) { popup.goTo("up"); valueFromRecentList();},
  2225. "Down": function(editor) { popup.goTo("down"); valueFromRecentList();},
  2226. "Ctrl-Up|Ctrl-Home": function(editor) { popup.goTo("start"); valueFromRecentList();},
  2227. "Ctrl-Down|Ctrl-End": function(editor) { popup.goTo("end"); valueFromRecentList();},
  2228. "Tab": function(editor) {
  2229. popup.goTo("down"); valueFromRecentList();
  2230. },
  2231. "PageUp": function(editor) { popup.gotoPageUp(); valueFromRecentList();},
  2232. "PageDown": function(editor) { popup.gotoPageDown(); valueFromRecentList();}
  2233. });
  2234. }
  2235. cmdLine.commands.bindKeys(keys);
  2236. function done() {
  2237. overlay.close();
  2238. callback && callback();
  2239. openPrompt = null;
  2240. }
  2241. cmdLine.on("input", function() {
  2242. options.onInput && options.onInput();
  2243. updateCompletions();
  2244. });
  2245. function updateCompletions() {
  2246. if (options.getCompletions) {
  2247. var prefix;
  2248. if (options.getPrefix) {
  2249. prefix = options.getPrefix(cmdLine);
  2250. }
  2251. var completions = options.getCompletions(cmdLine);
  2252. popup.setData(completions, prefix);
  2253. popup.resize(true);
  2254. }
  2255. }
  2256. function valueFromRecentList() {
  2257. var current = popup.getData(popup.getRow());
  2258. if (current && !current.error)
  2259. return current.value || current.caption || current;
  2260. }
  2261. cmdLine.resize(true);
  2262. if (popup) {
  2263. popup.resize(true);
  2264. }
  2265. cmdLine.focus();
  2266. openPrompt = {
  2267. close: done,
  2268. name: options.name,
  2269. editor: editor
  2270. };
  2271. }
  2272. prompt.gotoLine = function(editor, callback) {
  2273. function stringifySelection(selection) {
  2274. if (!Array.isArray(selection))
  2275. selection = [selection];
  2276. return selection.map(function(r) {
  2277. var cursor = r.isBackwards ? r.start: r.end;
  2278. var anchor = r.isBackwards ? r.end: r.start;
  2279. var row = anchor.row;
  2280. var s = (row + 1) + ":" + anchor.column;
  2281. if (anchor.row == cursor.row) {
  2282. if (anchor.column != cursor.column)
  2283. s += ">" + ":" + cursor.column;
  2284. } else {
  2285. s += ">" + (cursor.row + 1) + ":" + cursor.column;
  2286. }
  2287. return s;
  2288. }).reverse().join(", ");
  2289. }
  2290. prompt(editor, ":" + stringifySelection(editor.selection.toJSON()), {
  2291. name: "gotoLine",
  2292. selection: [1, Number.MAX_VALUE],
  2293. onAccept: function(data) {
  2294. var value = data.value;
  2295. var _history = prompt.gotoLine._history;
  2296. if (!_history)
  2297. prompt.gotoLine._history = _history = [];
  2298. if (_history.indexOf(value) != -1)
  2299. _history.splice(_history.indexOf(value), 1);
  2300. _history.unshift(value);
  2301. if (_history.length > 20) _history.length = 20;
  2302. var pos = editor.getCursorPosition();
  2303. var ranges = [];
  2304. value.replace(/^:/, "").split(/,/).map(function(str) {
  2305. var parts = str.split(/([<>:+-]|c?\d+)|[^c\d<>:+-]+/).filter(Boolean);
  2306. var i = 0;
  2307. function readPosition() {
  2308. var c = parts[i++];
  2309. if (!c) return;
  2310. if (c[0] == "c") {
  2311. var index = parseInt(c.slice(1)) || 0;
  2312. return editor.session.doc.indexToPosition(index);
  2313. }
  2314. var row = pos.row;
  2315. var column = 0;
  2316. if (/\d/.test(c)) {
  2317. row = parseInt(c) - 1;
  2318. c = parts[i++];
  2319. }
  2320. if (c == ":") {
  2321. c = parts[i++];
  2322. if (/\d/.test(c)) {
  2323. column = parseInt(c) || 0;
  2324. }
  2325. }
  2326. return {row: row, column: column};
  2327. }
  2328. pos = readPosition();
  2329. var range = Range.fromPoints(pos, pos);
  2330. if (parts[i] == ">") {
  2331. i++;
  2332. range.end = readPosition();
  2333. }
  2334. else if (parts[i] == "<") {
  2335. i++;
  2336. range.start = readPosition();
  2337. }
  2338. ranges.unshift(range);
  2339. });
  2340. editor.selection.fromJSON(ranges);
  2341. var scrollTop = editor.renderer.scrollTop;
  2342. editor.renderer.scrollSelectionIntoView(
  2343. editor.selection.anchor,
  2344. editor.selection.cursor,
  2345. 0.5
  2346. );
  2347. editor.renderer.animateScrolling(scrollTop);
  2348. },
  2349. history: function() {
  2350. var undoManager = editor.session.getUndoManager();
  2351. if (!prompt.gotoLine._history)
  2352. return [];
  2353. return prompt.gotoLine._history;
  2354. },
  2355. getCompletions: function(cmdLine) {
  2356. var value = cmdLine.getValue();
  2357. var m = value.replace(/^:/, "").split(":");
  2358. var row = Math.min(parseInt(m[0]) || 1, editor.session.getLength()) - 1;
  2359. var line = editor.session.getLine(row);
  2360. var current = value + " " + line;
  2361. return [current].concat(this.history());
  2362. },
  2363. $rules: {
  2364. start: [{
  2365. regex: /\d+/,
  2366. token: "string"
  2367. }, {
  2368. regex: /[:,><+\-c]/,
  2369. token: "keyword"
  2370. }]
  2371. }
  2372. });
  2373. };
  2374. prompt.commands = function(editor, callback) {
  2375. function normalizeName(name) {
  2376. return (name || "").replace(/^./, function(x) {
  2377. return x.toUpperCase(x);
  2378. }).replace(/[a-z][A-Z]/g, function(x) {
  2379. return x[0] + " " + x[1].toLowerCase(x);
  2380. });
  2381. }
  2382. function getEditorCommandsByName(excludeCommands) {
  2383. var commandsByName = [];
  2384. var commandMap = {};
  2385. editor.keyBinding.$handlers.forEach(function(handler) {
  2386. var platform = handler.platform;
  2387. var cbn = handler.byName;
  2388. for (var i in cbn) {
  2389. var key = cbn[i].bindKey;
  2390. if (typeof key !== "string") {
  2391. key = key && key[platform] || "";
  2392. }
  2393. var commands = cbn[i];
  2394. var description = commands.description || normalizeName(commands.name);
  2395. if (!Array.isArray(commands))
  2396. commands = [commands];
  2397. commands.forEach(function(command) {
  2398. if (typeof command != "string")
  2399. command = command.name;
  2400. var needle = excludeCommands.find(function(el) {
  2401. return el === command;
  2402. });
  2403. if (!needle) {
  2404. if (commandMap[command]) {
  2405. commandMap[command].key += "|" + key;
  2406. } else {
  2407. commandMap[command] = {key: key, command: command, description: description};
  2408. commandsByName.push(commandMap[command]);
  2409. }
  2410. }
  2411. });
  2412. }
  2413. });
  2414. return commandsByName;
  2415. }
  2416. var excludeCommandsList = ["insertstring", "inserttext", "setIndentation", "paste"];
  2417. var shortcutsArray = getEditorCommandsByName(excludeCommandsList);
  2418. shortcutsArray = shortcutsArray.map(function(item) {
  2419. return {value: item.description, meta: item.key, command: item.command};
  2420. });
  2421. prompt(editor, "", {
  2422. name: "commands",
  2423. selection: [0, Number.MAX_VALUE],
  2424. maxHistoryCount: 5,
  2425. onAccept: function(data) {
  2426. if (data.item) {
  2427. var commandName = data.item.command;
  2428. this.addToHistory(data.item);
  2429. editor.execCommand(commandName);
  2430. }
  2431. },
  2432. addToHistory: function(item) {
  2433. var history = this.history();
  2434. history.unshift(item);
  2435. delete item.message;
  2436. for (var i = 1; i < history.length; i++) {
  2437. if (history[i]["command"] == item.command ) {
  2438. history.splice(i, 1);
  2439. break;
  2440. }
  2441. }
  2442. if (this.maxHistoryCount > 0 && history.length > this.maxHistoryCount) {
  2443. history.splice(history.length - 1, 1);
  2444. }
  2445. prompt.commands.history = history;
  2446. },
  2447. history: function() {
  2448. return prompt.commands.history || [];
  2449. },
  2450. getPrefix: function(cmdLine) {
  2451. var currentPos = cmdLine.getCursorPosition();
  2452. var filterValue = cmdLine.getValue();
  2453. return filterValue.substring(0, currentPos.column);
  2454. },
  2455. getCompletions: function(cmdLine) {
  2456. function getFilteredCompletions(commands, prefix) {
  2457. var resultCommands = JSON.parse(JSON.stringify(commands));
  2458. var filtered = new FilteredList(resultCommands);
  2459. return filtered.filterCompletions(resultCommands, prefix);
  2460. }
  2461. function getUniqueCommandList(commands, usedCommands) {
  2462. if (!usedCommands || !usedCommands.length) {
  2463. return commands;
  2464. }
  2465. var excludeCommands = [];
  2466. usedCommands.forEach(function(item) {
  2467. excludeCommands.push(item.command);
  2468. });
  2469. var resultCommands = [];
  2470. commands.forEach(function(item) {
  2471. if (excludeCommands.indexOf(item.command) === -1) {
  2472. resultCommands.push(item);
  2473. }
  2474. });
  2475. return resultCommands;
  2476. }
  2477. var prefix = this.getPrefix(cmdLine);
  2478. var recentlyUsedCommands = getFilteredCompletions(this.history(), prefix);
  2479. var otherCommands = getUniqueCommandList(shortcutsArray, recentlyUsedCommands);
  2480. otherCommands = getFilteredCompletions(otherCommands, prefix);
  2481. if (recentlyUsedCommands.length && otherCommands.length) {
  2482. recentlyUsedCommands[0]["message"] = " Recently used";
  2483. otherCommands[0]["message"] = " Other commands";
  2484. }
  2485. var completions = recentlyUsedCommands.concat(otherCommands);
  2486. return completions.length > 0 ? completions : [{
  2487. value: "No matching commands",
  2488. error: 1
  2489. }];
  2490. }
  2491. });
  2492. };
  2493. prompt.modes = function(editor, callback) {
  2494. var modesArray = modelist.modes;
  2495. modesArray = modesArray.map(function(item) {
  2496. return {value: item.caption, mode: item.name};
  2497. });
  2498. prompt(editor, "", {
  2499. name: "modes",
  2500. selection: [0, Number.MAX_VALUE],
  2501. onAccept: function(data) {
  2502. if (data.item) {
  2503. var modeName = "ace/mode/" + data.item.mode;
  2504. editor.session.setMode(modeName);
  2505. }
  2506. },
  2507. getPrefix: function(cmdLine) {
  2508. var currentPos = cmdLine.getCursorPosition();
  2509. var filterValue = cmdLine.getValue();
  2510. return filterValue.substring(0, currentPos.column);
  2511. },
  2512. getCompletions: function(cmdLine) {
  2513. function getFilteredCompletions(modes, prefix) {
  2514. var resultCommands = JSON.parse(JSON.stringify(modes));
  2515. var filtered = new FilteredList(resultCommands);
  2516. return filtered.filterCompletions(resultCommands, prefix);
  2517. }
  2518. var prefix = this.getPrefix(cmdLine);
  2519. var completions = getFilteredCompletions(modesArray, prefix);
  2520. return completions.length > 0 ? completions : [{
  2521. "caption": "No mode matching",
  2522. "value": "No mode matching",
  2523. "error": 1
  2524. }];
  2525. }
  2526. });
  2527. };
  2528. dom.importCssString(".ace_prompt_container {\
  2529. max-width: 600px;\
  2530. width: 100%;\
  2531. margin: 20px auto;\
  2532. padding: 3px;\
  2533. background: white;\
  2534. border-radius: 2px;\
  2535. box-shadow: 0px 2px 3px 0px #555;\
  2536. }", "promtp.css", false);
  2537. exports.prompt = prompt;
  2538. }); (function() {
  2539. window.require(["ace/ext/prompt"], function(m) {
  2540. if (typeof module == "object" && typeof exports == "object" && module) {
  2541. module.exports = m;
  2542. }
  2543. });
  2544. })();