ext-language_tools-ec14926a.js 91 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296
  1. ace.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){"use strict";
  2. var dom = require("./lib/dom");
  3. var oop = require("./lib/oop");
  4. var EventEmitter = require("./lib/event_emitter").EventEmitter;
  5. var lang = require("./lib/lang");
  6. var Range = require("./range").Range;
  7. var RangeList = require("./range_list").RangeList;
  8. var HashHandler = require("./keyboard/hash_handler").HashHandler;
  9. var Tokenizer = require("./tokenizer").Tokenizer;
  10. var clipboard = require("./clipboard");
  11. var VARIABLES = {
  12. CURRENT_WORD: function (editor) {
  13. return editor.session.getTextRange(editor.session.getWordRange());
  14. },
  15. SELECTION: function (editor, name, indentation) {
  16. var text = editor.session.getTextRange();
  17. if (indentation)
  18. return text.replace(/\n\r?([ \t]*\S)/g, "\n" + indentation + "$1");
  19. return text;
  20. },
  21. CURRENT_LINE: function (editor) {
  22. return editor.session.getLine(editor.getCursorPosition().row);
  23. },
  24. PREV_LINE: function (editor) {
  25. return editor.session.getLine(editor.getCursorPosition().row - 1);
  26. },
  27. LINE_INDEX: function (editor) {
  28. return editor.getCursorPosition().row;
  29. },
  30. LINE_NUMBER: function (editor) {
  31. return editor.getCursorPosition().row + 1;
  32. },
  33. SOFT_TABS: function (editor) {
  34. return editor.session.getUseSoftTabs() ? "YES" : "NO";
  35. },
  36. TAB_SIZE: function (editor) {
  37. return editor.session.getTabSize();
  38. },
  39. CLIPBOARD: function (editor) {
  40. return clipboard.getText && clipboard.getText();
  41. },
  42. FILENAME: function (editor) {
  43. return /[^/\\]*$/.exec(this.FILEPATH(editor))[0];
  44. },
  45. FILENAME_BASE: function (editor) {
  46. return /[^/\\]*$/.exec(this.FILEPATH(editor))[0].replace(/\.[^.]*$/, "");
  47. },
  48. DIRECTORY: function (editor) {
  49. return this.FILEPATH(editor).replace(/[^/\\]*$/, "");
  50. },
  51. FILEPATH: function (editor) { return "/not implemented.txt"; },
  52. WORKSPACE_NAME: function () { return "Unknown"; },
  53. FULLNAME: function () { return "Unknown"; },
  54. BLOCK_COMMENT_START: function (editor) {
  55. var mode = editor.session.$mode || {};
  56. return mode.blockComment && mode.blockComment.start || "";
  57. },
  58. BLOCK_COMMENT_END: function (editor) {
  59. var mode = editor.session.$mode || {};
  60. return mode.blockComment && mode.blockComment.end || "";
  61. },
  62. LINE_COMMENT: function (editor) {
  63. var mode = editor.session.$mode || {};
  64. return mode.lineCommentStart || "";
  65. },
  66. CURRENT_YEAR: date.bind(null, { year: "numeric" }),
  67. CURRENT_YEAR_SHORT: date.bind(null, { year: "2-digit" }),
  68. CURRENT_MONTH: date.bind(null, { month: "numeric" }),
  69. CURRENT_MONTH_NAME: date.bind(null, { month: "long" }),
  70. CURRENT_MONTH_NAME_SHORT: date.bind(null, { month: "short" }),
  71. CURRENT_DATE: date.bind(null, { day: "2-digit" }),
  72. CURRENT_DAY_NAME: date.bind(null, { weekday: "long" }),
  73. CURRENT_DAY_NAME_SHORT: date.bind(null, { weekday: "short" }),
  74. CURRENT_HOUR: date.bind(null, { hour: "2-digit", hour12: false }),
  75. CURRENT_MINUTE: date.bind(null, { minute: "2-digit" }),
  76. CURRENT_SECOND: date.bind(null, { second: "2-digit" })
  77. };
  78. VARIABLES.SELECTED_TEXT = VARIABLES.SELECTION;
  79. function date(dateFormat) {
  80. var str = new Date().toLocaleString("en-us", dateFormat);
  81. return str.length == 1 ? "0" + str : str;
  82. }
  83. var SnippetManager = function () {
  84. this.snippetMap = {};
  85. this.snippetNameMap = {};
  86. };
  87. (function () {
  88. oop.implement(this, EventEmitter);
  89. this.getTokenizer = function () {
  90. return SnippetManager.$tokenizer || this.createTokenizer();
  91. };
  92. this.createTokenizer = function () {
  93. function TabstopToken(str) {
  94. str = str.substr(1);
  95. if (/^\d+$/.test(str))
  96. return [{ tabstopId: parseInt(str, 10) }];
  97. return [{ text: str }];
  98. }
  99. function escape(ch) {
  100. return "(?:[^\\\\" + ch + "]|\\\\.)";
  101. }
  102. var formatMatcher = {
  103. regex: "/(" + escape("/") + "+)/",
  104. onMatch: function (val, state, stack) {
  105. var ts = stack[0];
  106. ts.fmtString = true;
  107. ts.guard = val.slice(1, -1);
  108. ts.flag = "";
  109. return "";
  110. },
  111. next: "formatString"
  112. };
  113. SnippetManager.$tokenizer = new Tokenizer({
  114. start: [
  115. { regex: /\\./, onMatch: function (val, state, stack) {
  116. var ch = val[1];
  117. if (ch == "}" && stack.length) {
  118. val = ch;
  119. }
  120. else if ("`$\\".indexOf(ch) != -1) {
  121. val = ch;
  122. }
  123. return [val];
  124. } },
  125. { regex: /}/, onMatch: function (val, state, stack) {
  126. return [stack.length ? stack.shift() : val];
  127. } },
  128. { regex: /\$(?:\d+|\w+)/, onMatch: TabstopToken },
  129. { regex: /\$\{[\dA-Z_a-z]+/, onMatch: function (str, state, stack) {
  130. var t = TabstopToken(str.substr(1));
  131. stack.unshift(t[0]);
  132. return t;
  133. }, next: "snippetVar" },
  134. { regex: /\n/, token: "newline", merge: false }
  135. ],
  136. snippetVar: [
  137. { regex: "\\|" + escape("\\|") + "*\\|", onMatch: function (val, state, stack) {
  138. var choices = val.slice(1, -1).replace(/\\[,|\\]|,/g, function (operator) {
  139. return operator.length == 2 ? operator[1] : "\x00";
  140. }).split("\x00").map(function (value) {
  141. return { value: value };
  142. });
  143. stack[0].choices = choices;
  144. return [choices[0]];
  145. }, next: "start" },
  146. formatMatcher,
  147. { regex: "([^:}\\\\]|\\\\.)*:?", token: "", next: "start" }
  148. ],
  149. formatString: [
  150. { regex: /:/, onMatch: function (val, state, stack) {
  151. if (stack.length && stack[0].expectElse) {
  152. stack[0].expectElse = false;
  153. stack[0].ifEnd = { elseEnd: stack[0] };
  154. return [stack[0].ifEnd];
  155. }
  156. return ":";
  157. } },
  158. { regex: /\\./, onMatch: function (val, state, stack) {
  159. var ch = val[1];
  160. if (ch == "}" && stack.length)
  161. val = ch;
  162. else if ("`$\\".indexOf(ch) != -1)
  163. val = ch;
  164. else if (ch == "n")
  165. val = "\n";
  166. else if (ch == "t")
  167. val = "\t";
  168. else if ("ulULE".indexOf(ch) != -1)
  169. val = { changeCase: ch, local: ch > "a" };
  170. return [val];
  171. } },
  172. { regex: "/\\w*}", onMatch: function (val, state, stack) {
  173. var next = stack.shift();
  174. if (next)
  175. next.flag = val.slice(1, -1);
  176. this.next = next && next.tabstopId ? "start" : "";
  177. return [next || val];
  178. }, next: "start" },
  179. { regex: /\$(?:\d+|\w+)/, onMatch: function (val, state, stack) {
  180. return [{ text: val.slice(1) }];
  181. } },
  182. { regex: /\${\w+/, onMatch: function (val, state, stack) {
  183. var token = { text: val.slice(2) };
  184. stack.unshift(token);
  185. return [token];
  186. }, next: "formatStringVar" },
  187. { regex: /\n/, token: "newline", merge: false },
  188. { regex: /}/, onMatch: function (val, state, stack) {
  189. var next = stack.shift();
  190. this.next = next && next.tabstopId ? "start" : "";
  191. return [next || val];
  192. }, next: "start" }
  193. ],
  194. formatStringVar: [
  195. { regex: /:\/\w+}/, onMatch: function (val, state, stack) {
  196. var ts = stack[0];
  197. ts.formatFunction = val.slice(2, -1);
  198. return [stack.shift()];
  199. }, next: "formatString" },
  200. formatMatcher,
  201. { regex: /:[\?\-+]?/, onMatch: function (val, state, stack) {
  202. if (val[1] == "+")
  203. stack[0].ifEnd = stack[0];
  204. if (val[1] == "?")
  205. stack[0].expectElse = true;
  206. }, next: "formatString" },
  207. { regex: "([^:}\\\\]|\\\\.)*:?", token: "", next: "formatString" }
  208. ]
  209. });
  210. return SnippetManager.$tokenizer;
  211. };
  212. this.tokenizeTmSnippet = function (str, startState) {
  213. return this.getTokenizer().getLineTokens(str, startState).tokens.map(function (x) {
  214. return x.value || x;
  215. });
  216. };
  217. this.getVariableValue = function (editor, name, indentation) {
  218. if (/^\d+$/.test(name))
  219. return (this.variables.__ || {})[name] || "";
  220. if (/^[A-Z]\d+$/.test(name))
  221. return (this.variables[name[0] + "__"] || {})[name.substr(1)] || "";
  222. name = name.replace(/^TM_/, "");
  223. if (!this.variables.hasOwnProperty(name))
  224. return "";
  225. var value = this.variables[name];
  226. if (typeof value == "function")
  227. value = this.variables[name](editor, name, indentation);
  228. return value == null ? "" : value;
  229. };
  230. this.variables = VARIABLES;
  231. this.tmStrFormat = function (str, ch, editor) {
  232. if (!ch.fmt)
  233. return str;
  234. var flag = ch.flag || "";
  235. var re = ch.guard;
  236. re = new RegExp(re, flag.replace(/[^gim]/g, ""));
  237. var fmtTokens = typeof ch.fmt == "string" ? this.tokenizeTmSnippet(ch.fmt, "formatString") : ch.fmt;
  238. var _self = this;
  239. var formatted = str.replace(re, function () {
  240. var oldArgs = _self.variables.__;
  241. _self.variables.__ = [].slice.call(arguments);
  242. var fmtParts = _self.resolveVariables(fmtTokens, editor);
  243. var gChangeCase = "E";
  244. for (var i = 0; i < fmtParts.length; i++) {
  245. var ch = fmtParts[i];
  246. if (typeof ch == "object") {
  247. fmtParts[i] = "";
  248. if (ch.changeCase && ch.local) {
  249. var next = fmtParts[i + 1];
  250. if (next && typeof next == "string") {
  251. if (ch.changeCase == "u")
  252. fmtParts[i] = next[0].toUpperCase();
  253. else
  254. fmtParts[i] = next[0].toLowerCase();
  255. fmtParts[i + 1] = next.substr(1);
  256. }
  257. }
  258. else if (ch.changeCase) {
  259. gChangeCase = ch.changeCase;
  260. }
  261. }
  262. else if (gChangeCase == "U") {
  263. fmtParts[i] = ch.toUpperCase();
  264. }
  265. else if (gChangeCase == "L") {
  266. fmtParts[i] = ch.toLowerCase();
  267. }
  268. }
  269. _self.variables.__ = oldArgs;
  270. return fmtParts.join("");
  271. });
  272. return formatted;
  273. };
  274. this.tmFormatFunction = function (str, ch, editor) {
  275. if (ch.formatFunction == "upcase")
  276. return str.toUpperCase();
  277. if (ch.formatFunction == "downcase")
  278. return str.toLowerCase();
  279. return str;
  280. };
  281. this.resolveVariables = function (snippet, editor) {
  282. var result = [];
  283. var indentation = "";
  284. var afterNewLine = true;
  285. for (var i = 0; i < snippet.length; i++) {
  286. var ch = snippet[i];
  287. if (typeof ch == "string") {
  288. result.push(ch);
  289. if (ch == "\n") {
  290. afterNewLine = true;
  291. indentation = "";
  292. }
  293. else if (afterNewLine) {
  294. indentation = /^\t*/.exec(ch)[0];
  295. afterNewLine = /\S/.test(ch);
  296. }
  297. continue;
  298. }
  299. if (!ch)
  300. continue;
  301. afterNewLine = false;
  302. if (ch.fmtString) {
  303. var j = snippet.indexOf(ch, i + 1);
  304. if (j == -1)
  305. j = snippet.length;
  306. ch.fmt = snippet.slice(i + 1, j);
  307. i = j;
  308. }
  309. if (ch.text) {
  310. var value = this.getVariableValue(editor, ch.text, indentation) + "";
  311. if (ch.fmtString)
  312. value = this.tmStrFormat(value, ch, editor);
  313. if (ch.formatFunction)
  314. value = this.tmFormatFunction(value, ch, editor);
  315. if (value && !ch.ifEnd) {
  316. result.push(value);
  317. gotoNext(ch);
  318. }
  319. else if (!value && ch.ifEnd) {
  320. gotoNext(ch.ifEnd);
  321. }
  322. }
  323. else if (ch.elseEnd) {
  324. gotoNext(ch.elseEnd);
  325. }
  326. else if (ch.tabstopId != null) {
  327. result.push(ch);
  328. }
  329. else if (ch.changeCase != null) {
  330. result.push(ch);
  331. }
  332. }
  333. function gotoNext(ch) {
  334. var i1 = snippet.indexOf(ch, i + 1);
  335. if (i1 != -1)
  336. i = i1;
  337. }
  338. return result;
  339. };
  340. var processSnippetText = function (editor, snippetText, options) {
  341. if (options === void 0) { options = {}; }
  342. var cursor = editor.getCursorPosition();
  343. var line = editor.session.getLine(cursor.row);
  344. var tabString = editor.session.getTabString();
  345. var indentString = line.match(/^\s*/)[0];
  346. if (cursor.column < indentString.length)
  347. indentString = indentString.slice(0, cursor.column);
  348. snippetText = snippetText.replace(/\r/g, "");
  349. var tokens = this.tokenizeTmSnippet(snippetText);
  350. tokens = this.resolveVariables(tokens, editor);
  351. tokens = tokens.map(function (x) {
  352. if (x == "\n" && !options.excludeExtraIndent)
  353. return x + indentString;
  354. if (typeof x == "string")
  355. return x.replace(/\t/g, tabString);
  356. return x;
  357. });
  358. var tabstops = [];
  359. tokens.forEach(function (p, i) {
  360. if (typeof p != "object")
  361. return;
  362. var id = p.tabstopId;
  363. var ts = tabstops[id];
  364. if (!ts) {
  365. ts = tabstops[id] = [];
  366. ts.index = id;
  367. ts.value = "";
  368. ts.parents = {};
  369. }
  370. if (ts.indexOf(p) !== -1)
  371. return;
  372. if (p.choices && !ts.choices)
  373. ts.choices = p.choices;
  374. ts.push(p);
  375. var i1 = tokens.indexOf(p, i + 1);
  376. if (i1 === -1)
  377. return;
  378. var value = tokens.slice(i + 1, i1);
  379. var isNested = value.some(function (t) { return typeof t === "object"; });
  380. if (isNested && !ts.value) {
  381. ts.value = value;
  382. }
  383. else if (value.length && (!ts.value || typeof ts.value !== "string")) {
  384. ts.value = value.join("");
  385. }
  386. });
  387. tabstops.forEach(function (ts) { ts.length = 0; });
  388. var expanding = {};
  389. function copyValue(val) {
  390. var copy = [];
  391. for (var i = 0; i < val.length; i++) {
  392. var p = val[i];
  393. if (typeof p == "object") {
  394. if (expanding[p.tabstopId])
  395. continue;
  396. var j = val.lastIndexOf(p, i - 1);
  397. p = copy[j] || { tabstopId: p.tabstopId };
  398. }
  399. copy[i] = p;
  400. }
  401. return copy;
  402. }
  403. for (var i = 0; i < tokens.length; i++) {
  404. var p = tokens[i];
  405. if (typeof p != "object")
  406. continue;
  407. var id = p.tabstopId;
  408. var ts = tabstops[id];
  409. var i1 = tokens.indexOf(p, i + 1);
  410. if (expanding[id]) {
  411. if (expanding[id] === p) {
  412. delete expanding[id];
  413. Object.keys(expanding).forEach(function (parentId) {
  414. ts.parents[parentId] = true;
  415. });
  416. }
  417. continue;
  418. }
  419. expanding[id] = p;
  420. var value = ts.value;
  421. if (typeof value !== "string")
  422. value = copyValue(value);
  423. else if (p.fmt)
  424. value = this.tmStrFormat(value, p, editor);
  425. tokens.splice.apply(tokens, [i + 1, Math.max(0, i1 - i)].concat(value, p));
  426. if (ts.indexOf(p) === -1)
  427. ts.push(p);
  428. }
  429. var row = 0, column = 0;
  430. var text = "";
  431. tokens.forEach(function (t) {
  432. if (typeof t === "string") {
  433. var lines = t.split("\n");
  434. if (lines.length > 1) {
  435. column = lines[lines.length - 1].length;
  436. row += lines.length - 1;
  437. }
  438. else
  439. column += t.length;
  440. text += t;
  441. }
  442. else if (t) {
  443. if (!t.start)
  444. t.start = { row: row, column: column };
  445. else
  446. t.end = { row: row, column: column };
  447. }
  448. });
  449. return {
  450. text: text,
  451. tabstops: tabstops,
  452. tokens: tokens
  453. };
  454. };
  455. this.getDisplayTextForSnippet = function (editor, snippetText) {
  456. var processedSnippet = processSnippetText.call(this, editor, snippetText);
  457. return processedSnippet.text;
  458. };
  459. this.insertSnippetForSelection = function (editor, snippetText, options) {
  460. if (options === void 0) { options = {}; }
  461. var processedSnippet = processSnippetText.call(this, editor, snippetText, options);
  462. var range = editor.getSelectionRange();
  463. if (options.range && options.range.compareRange(range) === 0) {
  464. range = options.range;
  465. }
  466. var end = editor.session.replace(range, processedSnippet.text);
  467. var tabstopManager = new TabstopManager(editor);
  468. var selectionId = editor.inVirtualSelectionMode && editor.selection.index;
  469. tabstopManager.addTabstops(processedSnippet.tabstops, range.start, end, selectionId);
  470. };
  471. this.insertSnippet = function (editor, snippetText, options) {
  472. if (options === void 0) { options = {}; }
  473. var self = this;
  474. if (options.range && !(options.range instanceof Range))
  475. options.range = Range.fromPoints(options.range.start, options.range.end);
  476. if (editor.inVirtualSelectionMode)
  477. return self.insertSnippetForSelection(editor, snippetText, options);
  478. editor.forEachSelection(function () {
  479. self.insertSnippetForSelection(editor, snippetText, options);
  480. }, null, { keepOrder: true });
  481. if (editor.tabstopManager)
  482. editor.tabstopManager.tabNext();
  483. };
  484. this.$getScope = function (editor) {
  485. var scope = editor.session.$mode.$id || "";
  486. scope = scope.split("/").pop();
  487. if (scope === "html" || scope === "php") {
  488. if (scope === "php" && !editor.session.$mode.inlinePhp)
  489. scope = "html";
  490. var c = editor.getCursorPosition();
  491. var state = editor.session.getState(c.row);
  492. if (typeof state === "object") {
  493. state = state[0];
  494. }
  495. if (state.substring) {
  496. if (state.substring(0, 3) == "js-")
  497. scope = "javascript";
  498. else if (state.substring(0, 4) == "css-")
  499. scope = "css";
  500. else if (state.substring(0, 4) == "php-")
  501. scope = "php";
  502. }
  503. }
  504. return scope;
  505. };
  506. this.getActiveScopes = function (editor) {
  507. var scope = this.$getScope(editor);
  508. var scopes = [scope];
  509. var snippetMap = this.snippetMap;
  510. if (snippetMap[scope] && snippetMap[scope].includeScopes) {
  511. scopes.push.apply(scopes, snippetMap[scope].includeScopes);
  512. }
  513. scopes.push("_");
  514. return scopes;
  515. };
  516. this.expandWithTab = function (editor, options) {
  517. var self = this;
  518. var result = editor.forEachSelection(function () {
  519. return self.expandSnippetForSelection(editor, options);
  520. }, null, { keepOrder: true });
  521. if (result && editor.tabstopManager)
  522. editor.tabstopManager.tabNext();
  523. return result;
  524. };
  525. this.expandSnippetForSelection = function (editor, options) {
  526. var cursor = editor.getCursorPosition();
  527. var line = editor.session.getLine(cursor.row);
  528. var before = line.substring(0, cursor.column);
  529. var after = line.substr(cursor.column);
  530. var snippetMap = this.snippetMap;
  531. var snippet;
  532. this.getActiveScopes(editor).some(function (scope) {
  533. var snippets = snippetMap[scope];
  534. if (snippets)
  535. snippet = this.findMatchingSnippet(snippets, before, after);
  536. return !!snippet;
  537. }, this);
  538. if (!snippet)
  539. return false;
  540. if (options && options.dryRun)
  541. return true;
  542. editor.session.doc.removeInLine(cursor.row, cursor.column - snippet.replaceBefore.length, cursor.column + snippet.replaceAfter.length);
  543. this.variables.M__ = snippet.matchBefore;
  544. this.variables.T__ = snippet.matchAfter;
  545. this.insertSnippetForSelection(editor, snippet.content);
  546. this.variables.M__ = this.variables.T__ = null;
  547. return true;
  548. };
  549. this.findMatchingSnippet = function (snippetList, before, after) {
  550. for (var i = snippetList.length; i--;) {
  551. var s = snippetList[i];
  552. if (s.startRe && !s.startRe.test(before))
  553. continue;
  554. if (s.endRe && !s.endRe.test(after))
  555. continue;
  556. if (!s.startRe && !s.endRe)
  557. continue;
  558. s.matchBefore = s.startRe ? s.startRe.exec(before) : [""];
  559. s.matchAfter = s.endRe ? s.endRe.exec(after) : [""];
  560. s.replaceBefore = s.triggerRe ? s.triggerRe.exec(before)[0] : "";
  561. s.replaceAfter = s.endTriggerRe ? s.endTriggerRe.exec(after)[0] : "";
  562. return s;
  563. }
  564. };
  565. this.snippetMap = {};
  566. this.snippetNameMap = {};
  567. this.register = function (snippets, scope) {
  568. var snippetMap = this.snippetMap;
  569. var snippetNameMap = this.snippetNameMap;
  570. var self = this;
  571. if (!snippets)
  572. snippets = [];
  573. function wrapRegexp(src) {
  574. if (src && !/^\^?\(.*\)\$?$|^\\b$/.test(src))
  575. src = "(?:" + src + ")";
  576. return src || "";
  577. }
  578. function guardedRegexp(re, guard, opening) {
  579. re = wrapRegexp(re);
  580. guard = wrapRegexp(guard);
  581. if (opening) {
  582. re = guard + re;
  583. if (re && re[re.length - 1] != "$")
  584. re = re + "$";
  585. }
  586. else {
  587. re = re + guard;
  588. if (re && re[0] != "^")
  589. re = "^" + re;
  590. }
  591. return new RegExp(re);
  592. }
  593. function addSnippet(s) {
  594. if (!s.scope)
  595. s.scope = scope || "_";
  596. scope = s.scope;
  597. if (!snippetMap[scope]) {
  598. snippetMap[scope] = [];
  599. snippetNameMap[scope] = {};
  600. }
  601. var map = snippetNameMap[scope];
  602. if (s.name) {
  603. var old = map[s.name];
  604. if (old)
  605. self.unregister(old);
  606. map[s.name] = s;
  607. }
  608. snippetMap[scope].push(s);
  609. if (s.prefix)
  610. s.tabTrigger = s.prefix;
  611. if (!s.content && s.body)
  612. s.content = Array.isArray(s.body) ? s.body.join("\n") : s.body;
  613. if (s.tabTrigger && !s.trigger) {
  614. if (!s.guard && /^\w/.test(s.tabTrigger))
  615. s.guard = "\\b";
  616. s.trigger = lang.escapeRegExp(s.tabTrigger);
  617. }
  618. if (!s.trigger && !s.guard && !s.endTrigger && !s.endGuard)
  619. return;
  620. s.startRe = guardedRegexp(s.trigger, s.guard, true);
  621. s.triggerRe = new RegExp(s.trigger);
  622. s.endRe = guardedRegexp(s.endTrigger, s.endGuard, true);
  623. s.endTriggerRe = new RegExp(s.endTrigger);
  624. }
  625. if (Array.isArray(snippets)) {
  626. snippets.forEach(addSnippet);
  627. }
  628. else {
  629. Object.keys(snippets).forEach(function (key) {
  630. addSnippet(snippets[key]);
  631. });
  632. }
  633. this._signal("registerSnippets", { scope: scope });
  634. };
  635. this.unregister = function (snippets, scope) {
  636. var snippetMap = this.snippetMap;
  637. var snippetNameMap = this.snippetNameMap;
  638. function removeSnippet(s) {
  639. var nameMap = snippetNameMap[s.scope || scope];
  640. if (nameMap && nameMap[s.name]) {
  641. delete nameMap[s.name];
  642. var map = snippetMap[s.scope || scope];
  643. var i = map && map.indexOf(s);
  644. if (i >= 0)
  645. map.splice(i, 1);
  646. }
  647. }
  648. if (snippets.content)
  649. removeSnippet(snippets);
  650. else if (Array.isArray(snippets))
  651. snippets.forEach(removeSnippet);
  652. };
  653. this.parseSnippetFile = function (str) {
  654. str = str.replace(/\r/g, "");
  655. var list = [], snippet = {};
  656. var re = /^#.*|^({[\s\S]*})\s*$|^(\S+) (.*)$|^((?:\n*\t.*)+)/gm;
  657. var m;
  658. while (m = re.exec(str)) {
  659. if (m[1]) {
  660. try {
  661. snippet = JSON.parse(m[1]);
  662. list.push(snippet);
  663. }
  664. catch (e) { }
  665. }
  666. if (m[4]) {
  667. snippet.content = m[4].replace(/^\t/gm, "");
  668. list.push(snippet);
  669. snippet = {};
  670. }
  671. else {
  672. var key = m[2], val = m[3];
  673. if (key == "regex") {
  674. var guardRe = /\/((?:[^\/\\]|\\.)*)|$/g;
  675. snippet.guard = guardRe.exec(val)[1];
  676. snippet.trigger = guardRe.exec(val)[1];
  677. snippet.endTrigger = guardRe.exec(val)[1];
  678. snippet.endGuard = guardRe.exec(val)[1];
  679. }
  680. else if (key == "snippet") {
  681. snippet.tabTrigger = val.match(/^\S*/)[0];
  682. if (!snippet.name)
  683. snippet.name = val;
  684. }
  685. else if (key) {
  686. snippet[key] = val;
  687. }
  688. }
  689. }
  690. return list;
  691. };
  692. this.getSnippetByName = function (name, editor) {
  693. var snippetMap = this.snippetNameMap;
  694. var snippet;
  695. this.getActiveScopes(editor).some(function (scope) {
  696. var snippets = snippetMap[scope];
  697. if (snippets)
  698. snippet = snippets[name];
  699. return !!snippet;
  700. }, this);
  701. return snippet;
  702. };
  703. }).call(SnippetManager.prototype);
  704. var TabstopManager = function (editor) {
  705. if (editor.tabstopManager)
  706. return editor.tabstopManager;
  707. editor.tabstopManager = this;
  708. this.$onChange = this.onChange.bind(this);
  709. this.$onChangeSelection = lang.delayedCall(this.onChangeSelection.bind(this)).schedule;
  710. this.$onChangeSession = this.onChangeSession.bind(this);
  711. this.$onAfterExec = this.onAfterExec.bind(this);
  712. this.attach(editor);
  713. };
  714. (function () {
  715. this.attach = function (editor) {
  716. this.index = 0;
  717. this.ranges = [];
  718. this.tabstops = [];
  719. this.$openTabstops = null;
  720. this.selectedTabstop = null;
  721. this.editor = editor;
  722. this.editor.on("change", this.$onChange);
  723. this.editor.on("changeSelection", this.$onChangeSelection);
  724. this.editor.on("changeSession", this.$onChangeSession);
  725. this.editor.commands.on("afterExec", this.$onAfterExec);
  726. this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler);
  727. };
  728. this.detach = function () {
  729. this.tabstops.forEach(this.removeTabstopMarkers, this);
  730. this.ranges = null;
  731. this.tabstops = null;
  732. this.selectedTabstop = null;
  733. this.editor.removeListener("change", this.$onChange);
  734. this.editor.removeListener("changeSelection", this.$onChangeSelection);
  735. this.editor.removeListener("changeSession", this.$onChangeSession);
  736. this.editor.commands.removeListener("afterExec", this.$onAfterExec);
  737. this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler);
  738. this.editor.tabstopManager = null;
  739. this.editor = null;
  740. };
  741. this.onChange = function (delta) {
  742. var isRemove = delta.action[0] == "r";
  743. var selectedTabstop = this.selectedTabstop || {};
  744. var parents = selectedTabstop.parents || {};
  745. var tabstops = (this.tabstops || []).slice();
  746. for (var i = 0; i < tabstops.length; i++) {
  747. var ts = tabstops[i];
  748. var active = ts == selectedTabstop || parents[ts.index];
  749. ts.rangeList.$bias = active ? 0 : 1;
  750. if (delta.action == "remove" && ts !== selectedTabstop) {
  751. var parentActive = ts.parents && ts.parents[selectedTabstop.index];
  752. var startIndex = ts.rangeList.pointIndex(delta.start, parentActive);
  753. startIndex = startIndex < 0 ? -startIndex - 1 : startIndex + 1;
  754. var endIndex = ts.rangeList.pointIndex(delta.end, parentActive);
  755. endIndex = endIndex < 0 ? -endIndex - 1 : endIndex - 1;
  756. var toRemove = ts.rangeList.ranges.slice(startIndex, endIndex);
  757. for (var j = 0; j < toRemove.length; j++)
  758. this.removeRange(toRemove[j]);
  759. }
  760. ts.rangeList.$onChange(delta);
  761. }
  762. var session = this.editor.session;
  763. if (!this.$inChange && isRemove && session.getLength() == 1 && !session.getValue())
  764. this.detach();
  765. };
  766. this.updateLinkedFields = function () {
  767. var ts = this.selectedTabstop;
  768. if (!ts || !ts.hasLinkedRanges || !ts.firstNonLinked)
  769. return;
  770. this.$inChange = true;
  771. var session = this.editor.session;
  772. var text = session.getTextRange(ts.firstNonLinked);
  773. for (var i = 0; i < ts.length; i++) {
  774. var range = ts[i];
  775. if (!range.linked)
  776. continue;
  777. var original = range.original;
  778. var fmt = exports.snippetManager.tmStrFormat(text, original, this.editor);
  779. session.replace(range, fmt);
  780. }
  781. this.$inChange = false;
  782. };
  783. this.onAfterExec = function (e) {
  784. if (e.command && !e.command.readOnly)
  785. this.updateLinkedFields();
  786. };
  787. this.onChangeSelection = function () {
  788. if (!this.editor)
  789. return;
  790. var lead = this.editor.selection.lead;
  791. var anchor = this.editor.selection.anchor;
  792. var isEmpty = this.editor.selection.isEmpty();
  793. for (var i = 0; i < this.ranges.length; i++) {
  794. if (this.ranges[i].linked)
  795. continue;
  796. var containsLead = this.ranges[i].contains(lead.row, lead.column);
  797. var containsAnchor = isEmpty || this.ranges[i].contains(anchor.row, anchor.column);
  798. if (containsLead && containsAnchor)
  799. return;
  800. }
  801. this.detach();
  802. };
  803. this.onChangeSession = function () {
  804. this.detach();
  805. };
  806. this.tabNext = function (dir) {
  807. var max = this.tabstops.length;
  808. var index = this.index + (dir || 1);
  809. index = Math.min(Math.max(index, 1), max);
  810. if (index == max)
  811. index = 0;
  812. this.selectTabstop(index);
  813. if (index === 0)
  814. this.detach();
  815. };
  816. this.selectTabstop = function (index) {
  817. this.$openTabstops = null;
  818. var ts = this.tabstops[this.index];
  819. if (ts)
  820. this.addTabstopMarkers(ts);
  821. this.index = index;
  822. ts = this.tabstops[this.index];
  823. if (!ts || !ts.length)
  824. return;
  825. this.selectedTabstop = ts;
  826. var range = ts.firstNonLinked || ts;
  827. if (ts.choices)
  828. range.cursor = range.start;
  829. if (!this.editor.inVirtualSelectionMode) {
  830. var sel = this.editor.multiSelect;
  831. sel.toSingleRange(range);
  832. for (var i = 0; i < ts.length; i++) {
  833. if (ts.hasLinkedRanges && ts[i].linked)
  834. continue;
  835. sel.addRange(ts[i].clone(), true);
  836. }
  837. }
  838. else {
  839. this.editor.selection.fromOrientedRange(range);
  840. }
  841. this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler);
  842. if (this.selectedTabstop && this.selectedTabstop.choices)
  843. this.editor.execCommand("startAutocomplete", { matches: this.selectedTabstop.choices });
  844. };
  845. this.addTabstops = function (tabstops, start, end) {
  846. var useLink = this.useLink || !this.editor.getOption("enableMultiselect");
  847. if (!this.$openTabstops)
  848. this.$openTabstops = [];
  849. if (!tabstops[0]) {
  850. var p = Range.fromPoints(end, end);
  851. moveRelative(p.start, start);
  852. moveRelative(p.end, start);
  853. tabstops[0] = [p];
  854. tabstops[0].index = 0;
  855. }
  856. var i = this.index;
  857. var arg = [i + 1, 0];
  858. var ranges = this.ranges;
  859. tabstops.forEach(function (ts, index) {
  860. var dest = this.$openTabstops[index] || ts;
  861. for (var i = 0; i < ts.length; i++) {
  862. var p = ts[i];
  863. var range = Range.fromPoints(p.start, p.end || p.start);
  864. movePoint(range.start, start);
  865. movePoint(range.end, start);
  866. range.original = p;
  867. range.tabstop = dest;
  868. ranges.push(range);
  869. if (dest != ts)
  870. dest.unshift(range);
  871. else
  872. dest[i] = range;
  873. if (p.fmtString || (dest.firstNonLinked && useLink)) {
  874. range.linked = true;
  875. dest.hasLinkedRanges = true;
  876. }
  877. else if (!dest.firstNonLinked)
  878. dest.firstNonLinked = range;
  879. }
  880. if (!dest.firstNonLinked)
  881. dest.hasLinkedRanges = false;
  882. if (dest === ts) {
  883. arg.push(dest);
  884. this.$openTabstops[index] = dest;
  885. }
  886. this.addTabstopMarkers(dest);
  887. dest.rangeList = dest.rangeList || new RangeList();
  888. dest.rangeList.$bias = 0;
  889. dest.rangeList.addList(dest);
  890. }, this);
  891. if (arg.length > 2) {
  892. if (this.tabstops.length)
  893. arg.push(arg.splice(2, 1)[0]);
  894. this.tabstops.splice.apply(this.tabstops, arg);
  895. }
  896. };
  897. this.addTabstopMarkers = function (ts) {
  898. var session = this.editor.session;
  899. ts.forEach(function (range) {
  900. if (!range.markerId)
  901. range.markerId = session.addMarker(range, "ace_snippet-marker", "text");
  902. });
  903. };
  904. this.removeTabstopMarkers = function (ts) {
  905. var session = this.editor.session;
  906. ts.forEach(function (range) {
  907. session.removeMarker(range.markerId);
  908. range.markerId = null;
  909. });
  910. };
  911. this.removeRange = function (range) {
  912. var i = range.tabstop.indexOf(range);
  913. if (i != -1)
  914. range.tabstop.splice(i, 1);
  915. i = this.ranges.indexOf(range);
  916. if (i != -1)
  917. this.ranges.splice(i, 1);
  918. i = range.tabstop.rangeList.ranges.indexOf(range);
  919. if (i != -1)
  920. range.tabstop.splice(i, 1);
  921. this.editor.session.removeMarker(range.markerId);
  922. if (!range.tabstop.length) {
  923. i = this.tabstops.indexOf(range.tabstop);
  924. if (i != -1)
  925. this.tabstops.splice(i, 1);
  926. if (!this.tabstops.length)
  927. this.detach();
  928. }
  929. };
  930. this.keyboardHandler = new HashHandler();
  931. this.keyboardHandler.bindKeys({
  932. "Tab": function (editor) {
  933. if (exports.snippetManager && exports.snippetManager.expandWithTab(editor))
  934. return;
  935. editor.tabstopManager.tabNext(1);
  936. editor.renderer.scrollCursorIntoView();
  937. },
  938. "Shift-Tab": function (editor) {
  939. editor.tabstopManager.tabNext(-1);
  940. editor.renderer.scrollCursorIntoView();
  941. },
  942. "Esc": function (editor) {
  943. editor.tabstopManager.detach();
  944. }
  945. });
  946. }).call(TabstopManager.prototype);
  947. var movePoint = function (point, diff) {
  948. if (point.row == 0)
  949. point.column += diff.column;
  950. point.row += diff.row;
  951. };
  952. var moveRelative = function (point, start) {
  953. if (point.row == start.row)
  954. point.column -= start.column;
  955. point.row -= start.row;
  956. };
  957. dom.importCssString("\n.ace_snippet-marker {\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n background: rgba(194, 193, 208, 0.09);\n border: 1px dotted rgba(211, 208, 235, 0.62);\n position: absolute;\n}", "snippets.css", false);
  958. exports.snippetManager = new SnippetManager();
  959. var Editor = require("./editor").Editor;
  960. (function () {
  961. this.insertSnippet = function (content, options) {
  962. return exports.snippetManager.insertSnippet(this, content, options);
  963. };
  964. this.expandSnippet = function (options) {
  965. return exports.snippetManager.expandWithTab(this, options);
  966. };
  967. }).call(Editor.prototype);
  968. });
  969. ace.define("ace/autocomplete/popup",["require","exports","module","ace/virtual_renderer","ace/editor","ace/range","ace/lib/event","ace/lib/lang","ace/lib/dom","ace/config"], function(require, exports, module){"use strict";
  970. var Renderer = require("../virtual_renderer").VirtualRenderer;
  971. var Editor = require("../editor").Editor;
  972. var Range = require("../range").Range;
  973. var event = require("../lib/event");
  974. var lang = require("../lib/lang");
  975. var dom = require("../lib/dom");
  976. var nls = require("../config").nls;
  977. var getAriaId = function (index) {
  978. return "suggest-aria-id:".concat(index);
  979. };
  980. var $singleLineEditor = function (el) {
  981. var renderer = new Renderer(el);
  982. renderer.$maxLines = 4;
  983. var editor = new Editor(renderer);
  984. editor.setHighlightActiveLine(false);
  985. editor.setShowPrintMargin(false);
  986. editor.renderer.setShowGutter(false);
  987. editor.renderer.setHighlightGutterLine(false);
  988. editor.$mouseHandler.$focusTimeout = 0;
  989. editor.$highlightTagPending = true;
  990. return editor;
  991. };
  992. var AcePopup = /** @class */ (function () {
  993. function AcePopup(parentNode) {
  994. var el = dom.createElement("div");
  995. var popup = new $singleLineEditor(el);
  996. if (parentNode) {
  997. parentNode.appendChild(el);
  998. }
  999. el.style.display = "none";
  1000. popup.renderer.content.style.cursor = "default";
  1001. popup.renderer.setStyle("ace_autocomplete");
  1002. popup.renderer.container.setAttribute("role", "listbox");
  1003. popup.renderer.container.setAttribute("aria-label", nls("Autocomplete suggestions"));
  1004. popup.setOption("displayIndentGuides", false);
  1005. popup.setOption("dragDelay", 150);
  1006. var noop = function () { };
  1007. popup.focus = noop;
  1008. popup.$isFocused = true;
  1009. popup.renderer.$cursorLayer.restartTimer = noop;
  1010. popup.renderer.$cursorLayer.element.style.opacity = 0;
  1011. popup.renderer.$maxLines = 8;
  1012. popup.renderer.$keepTextAreaAtCursor = false;
  1013. popup.setHighlightActiveLine(false);
  1014. popup.session.highlight("");
  1015. popup.session.$searchHighlight.clazz = "ace_highlight-marker";
  1016. popup.on("mousedown", function (e) {
  1017. var pos = e.getDocumentPosition();
  1018. popup.selection.moveToPosition(pos);
  1019. selectionMarker.start.row = selectionMarker.end.row = pos.row;
  1020. e.stop();
  1021. });
  1022. var lastMouseEvent;
  1023. var hoverMarker = new Range(-1, 0, -1, Infinity);
  1024. var selectionMarker = new Range(-1, 0, -1, Infinity);
  1025. selectionMarker.id = popup.session.addMarker(selectionMarker, "ace_active-line", "fullLine");
  1026. popup.setSelectOnHover = function (val) {
  1027. if (!val) {
  1028. hoverMarker.id = popup.session.addMarker(hoverMarker, "ace_line-hover", "fullLine");
  1029. }
  1030. else if (hoverMarker.id) {
  1031. popup.session.removeMarker(hoverMarker.id);
  1032. hoverMarker.id = null;
  1033. }
  1034. };
  1035. popup.setSelectOnHover(false);
  1036. popup.on("mousemove", function (e) {
  1037. if (!lastMouseEvent) {
  1038. lastMouseEvent = e;
  1039. return;
  1040. }
  1041. if (lastMouseEvent.x == e.x && lastMouseEvent.y == e.y) {
  1042. return;
  1043. }
  1044. lastMouseEvent = e;
  1045. lastMouseEvent.scrollTop = popup.renderer.scrollTop;
  1046. var row = lastMouseEvent.getDocumentPosition().row;
  1047. if (hoverMarker.start.row != row) {
  1048. if (!hoverMarker.id)
  1049. popup.setRow(row);
  1050. setHoverMarker(row);
  1051. }
  1052. });
  1053. popup.renderer.on("beforeRender", function () {
  1054. if (lastMouseEvent && hoverMarker.start.row != -1) {
  1055. lastMouseEvent.$pos = null;
  1056. var row = lastMouseEvent.getDocumentPosition().row;
  1057. if (!hoverMarker.id)
  1058. popup.setRow(row);
  1059. setHoverMarker(row, true);
  1060. }
  1061. });
  1062. popup.renderer.on("afterRender", function () {
  1063. var row = popup.getRow();
  1064. var t = popup.renderer.$textLayer;
  1065. var selected = t.element.childNodes[row - t.config.firstRow];
  1066. var el = document.activeElement; // Active element is textarea of main editor
  1067. if (selected !== t.selectedNode && t.selectedNode) {
  1068. dom.removeCssClass(t.selectedNode, "ace_selected");
  1069. el.removeAttribute("aria-activedescendant");
  1070. t.selectedNode.removeAttribute("id");
  1071. }
  1072. t.selectedNode = selected;
  1073. if (selected) {
  1074. dom.addCssClass(selected, "ace_selected");
  1075. var ariaId = getAriaId(row);
  1076. selected.id = ariaId;
  1077. popup.renderer.container.setAttribute("aria-activedescendant", ariaId);
  1078. el.setAttribute("aria-activedescendant", ariaId);
  1079. selected.setAttribute("role", "option");
  1080. selected.setAttribute("aria-label", popup.getData(row).value);
  1081. selected.setAttribute("aria-setsize", popup.data.length);
  1082. selected.setAttribute("aria-posinset", row);
  1083. }
  1084. });
  1085. var hideHoverMarker = function () { setHoverMarker(-1); };
  1086. var setHoverMarker = function (row, suppressRedraw) {
  1087. if (row !== hoverMarker.start.row) {
  1088. hoverMarker.start.row = hoverMarker.end.row = row;
  1089. if (!suppressRedraw)
  1090. popup.session._emit("changeBackMarker");
  1091. popup._emit("changeHoverMarker");
  1092. }
  1093. };
  1094. popup.getHoveredRow = function () {
  1095. return hoverMarker.start.row;
  1096. };
  1097. event.addListener(popup.container, "mouseout", hideHoverMarker);
  1098. popup.on("hide", hideHoverMarker);
  1099. popup.on("changeSelection", hideHoverMarker);
  1100. popup.session.doc.getLength = function () {
  1101. return popup.data.length;
  1102. };
  1103. popup.session.doc.getLine = function (i) {
  1104. var data = popup.data[i];
  1105. if (typeof data == "string")
  1106. return data;
  1107. return (data && data.value) || "";
  1108. };
  1109. var bgTokenizer = popup.session.bgTokenizer;
  1110. bgTokenizer.$tokenizeRow = function (row) {
  1111. var data = popup.data[row];
  1112. var tokens = [];
  1113. if (!data)
  1114. return tokens;
  1115. if (typeof data == "string")
  1116. data = { value: data };
  1117. var caption = data.caption || data.value || data.name;
  1118. function addToken(value, className) {
  1119. value && tokens.push({
  1120. type: (data.className || "") + (className || ""),
  1121. value: value
  1122. });
  1123. }
  1124. var lower = caption.toLowerCase();
  1125. var filterText = (popup.filterText || "").toLowerCase();
  1126. var lastIndex = 0;
  1127. var lastI = 0;
  1128. for (var i = 0; i <= filterText.length; i++) {
  1129. if (i != lastI && (data.matchMask & (1 << i) || i == filterText.length)) {
  1130. var sub = filterText.slice(lastI, i);
  1131. lastI = i;
  1132. var index = lower.indexOf(sub, lastIndex);
  1133. if (index == -1)
  1134. continue;
  1135. addToken(caption.slice(lastIndex, index), "");
  1136. lastIndex = index + sub.length;
  1137. addToken(caption.slice(index, lastIndex), "completion-highlight");
  1138. }
  1139. }
  1140. addToken(caption.slice(lastIndex, caption.length), "");
  1141. tokens.push({ type: "completion-spacer", value: " " });
  1142. if (data.meta)
  1143. tokens.push({ type: "completion-meta", value: data.meta });
  1144. if (data.message)
  1145. tokens.push({ type: "completion-message", value: data.message });
  1146. return tokens;
  1147. };
  1148. bgTokenizer.$updateOnChange = noop;
  1149. bgTokenizer.start = noop;
  1150. popup.session.$computeWidth = function () {
  1151. return this.screenWidth = 0;
  1152. };
  1153. popup.isOpen = false;
  1154. popup.isTopdown = false;
  1155. popup.autoSelect = true;
  1156. popup.filterText = "";
  1157. popup.data = [];
  1158. popup.setData = function (list, filterText) {
  1159. popup.filterText = filterText || "";
  1160. popup.setValue(lang.stringRepeat("\n", list.length), -1);
  1161. popup.data = list || [];
  1162. popup.setRow(0);
  1163. };
  1164. popup.getData = function (row) {
  1165. return popup.data[row];
  1166. };
  1167. popup.getRow = function () {
  1168. return selectionMarker.start.row;
  1169. };
  1170. popup.setRow = function (line) {
  1171. line = Math.max(this.autoSelect ? 0 : -1, Math.min(this.data.length - 1, line));
  1172. if (selectionMarker.start.row != line) {
  1173. popup.selection.clearSelection();
  1174. selectionMarker.start.row = selectionMarker.end.row = line || 0;
  1175. popup.session._emit("changeBackMarker");
  1176. popup.moveCursorTo(line || 0, 0);
  1177. if (popup.isOpen)
  1178. popup._signal("select");
  1179. }
  1180. };
  1181. popup.on("changeSelection", function () {
  1182. if (popup.isOpen)
  1183. popup.setRow(popup.selection.lead.row);
  1184. popup.renderer.scrollCursorIntoView();
  1185. });
  1186. popup.hide = function () {
  1187. this.container.style.display = "none";
  1188. popup.anchorPos = null;
  1189. popup.anchor = null;
  1190. if (popup.isOpen) {
  1191. popup.isOpen = false;
  1192. this._signal("hide");
  1193. }
  1194. };
  1195. popup.tryShow = function (pos, lineHeight, anchor, forceShow) {
  1196. if (!forceShow && popup.isOpen && popup.anchorPos && popup.anchor &&
  1197. popup.anchorPos.top === pos.top && popup.anchorPos.left === pos.left &&
  1198. popup.anchor === anchor) {
  1199. return true;
  1200. }
  1201. var el = this.container;
  1202. var screenHeight = window.innerHeight;
  1203. var screenWidth = window.innerWidth;
  1204. var renderer = this.renderer;
  1205. var maxH = renderer.$maxLines * lineHeight * 1.4;
  1206. var dims = { top: 0, bottom: 0, left: 0 };
  1207. var spaceBelow = screenHeight - pos.top - 3 * this.$borderSize - lineHeight;
  1208. var spaceAbove = pos.top - 3 * this.$borderSize;
  1209. if (!anchor) {
  1210. if (spaceAbove <= spaceBelow || spaceBelow >= maxH) {
  1211. anchor = "bottom";
  1212. }
  1213. else {
  1214. anchor = "top";
  1215. }
  1216. }
  1217. if (anchor === "top") {
  1218. dims.bottom = pos.top - this.$borderSize;
  1219. dims.top = dims.bottom - maxH;
  1220. }
  1221. else if (anchor === "bottom") {
  1222. dims.top = pos.top + lineHeight + this.$borderSize;
  1223. dims.bottom = dims.top + maxH;
  1224. }
  1225. var fitsX = dims.top >= 0 && dims.bottom <= screenHeight;
  1226. if (!forceShow && !fitsX) {
  1227. return false;
  1228. }
  1229. if (!fitsX) {
  1230. if (anchor === "top") {
  1231. renderer.$maxPixelHeight = spaceAbove;
  1232. }
  1233. else {
  1234. renderer.$maxPixelHeight = spaceBelow;
  1235. }
  1236. }
  1237. else {
  1238. renderer.$maxPixelHeight = null;
  1239. }
  1240. if (anchor === "top") {
  1241. el.style.top = "";
  1242. el.style.bottom = (screenHeight - dims.bottom) + "px";
  1243. popup.isTopdown = false;
  1244. }
  1245. else {
  1246. el.style.top = dims.top + "px";
  1247. el.style.bottom = "";
  1248. popup.isTopdown = true;
  1249. }
  1250. el.style.display = "";
  1251. var left = pos.left;
  1252. if (left + el.offsetWidth > screenWidth)
  1253. left = screenWidth - el.offsetWidth;
  1254. el.style.left = left + "px";
  1255. el.style.right = "";
  1256. if (!popup.isOpen) {
  1257. popup.isOpen = true;
  1258. this._signal("show");
  1259. lastMouseEvent = null;
  1260. }
  1261. popup.anchorPos = pos;
  1262. popup.anchor = anchor;
  1263. return true;
  1264. };
  1265. popup.show = function (pos, lineHeight, topdownOnly) {
  1266. this.tryShow(pos, lineHeight, topdownOnly ? "bottom" : undefined, true);
  1267. };
  1268. popup.goTo = function (where) {
  1269. var row = this.getRow();
  1270. var max = this.session.getLength() - 1;
  1271. switch (where) {
  1272. case "up":
  1273. row = row <= 0 ? max : row - 1;
  1274. break;
  1275. case "down":
  1276. row = row >= max ? -1 : row + 1;
  1277. break;
  1278. case "start":
  1279. row = 0;
  1280. break;
  1281. case "end":
  1282. row = max;
  1283. break;
  1284. }
  1285. this.setRow(row);
  1286. };
  1287. popup.getTextLeftOffset = function () {
  1288. return this.$borderSize + this.renderer.$padding + this.$imageSize;
  1289. };
  1290. popup.$imageSize = 0;
  1291. popup.$borderSize = 1;
  1292. return popup;
  1293. }
  1294. return AcePopup;
  1295. }());
  1296. dom.importCssString("\n.ace_editor.ace_autocomplete .ace_marker-layer .ace_active-line {\n background-color: #CAD6FA;\n z-index: 1;\n}\n.ace_dark.ace_editor.ace_autocomplete .ace_marker-layer .ace_active-line {\n background-color: #3a674e;\n}\n.ace_editor.ace_autocomplete .ace_line-hover {\n border: 1px solid #abbffe;\n margin-top: -1px;\n background: rgba(233,233,253,0.4);\n position: absolute;\n z-index: 2;\n}\n.ace_dark.ace_editor.ace_autocomplete .ace_line-hover {\n border: 1px solid rgba(109, 150, 13, 0.8);\n background: rgba(58, 103, 78, 0.62);\n}\n.ace_completion-meta {\n opacity: 0.5;\n margin: 0 0.9em;\n}\n.ace_completion-message {\n color: blue;\n}\n.ace_editor.ace_autocomplete .ace_completion-highlight{\n color: #2d69c7;\n}\n.ace_dark.ace_editor.ace_autocomplete .ace_completion-highlight{\n color: #93ca12;\n}\n.ace_editor.ace_autocomplete {\n width: 300px;\n z-index: 200000;\n border: 1px lightgray solid;\n position: fixed;\n box-shadow: 2px 3px 5px rgba(0,0,0,.2);\n line-height: 1.4;\n background: #fefefe;\n color: #111;\n}\n.ace_dark.ace_editor.ace_autocomplete {\n border: 1px #484747 solid;\n box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.51);\n line-height: 1.4;\n background: #25282c;\n color: #c1c1c1;\n}\n.ace_autocomplete_right .ace_text-layer {\n width: calc(100% - 8px);\n}\n.ace_autocomplete_right .ace_line {\n display: flex;\n}\n.ace_autocomplete_right .ace_completion-spacer {\n flex: 1;\n}\n", "autocompletion.css", false);
  1297. exports.AcePopup = AcePopup;
  1298. exports.$singleLineEditor = $singleLineEditor;
  1299. exports.getAriaId = getAriaId;
  1300. });
  1301. ace.define("ace/autocomplete/inline",["require","exports","module","ace/snippets"], function(require, exports, module){"use strict";
  1302. var snippetManager = require("../snippets").snippetManager;
  1303. var AceInline = /** @class */ (function () {
  1304. function AceInline() {
  1305. this.editor = null;
  1306. }
  1307. AceInline.prototype.show = function (editor, completion, prefix) {
  1308. prefix = prefix || "";
  1309. if (editor && this.editor && this.editor !== editor) {
  1310. this.hide();
  1311. this.editor = null;
  1312. }
  1313. if (!editor || !completion) {
  1314. return false;
  1315. }
  1316. var displayText = completion.snippet ? snippetManager.getDisplayTextForSnippet(editor, completion.snippet) : completion.value;
  1317. if (!displayText || !displayText.startsWith(prefix)) {
  1318. return false;
  1319. }
  1320. this.editor = editor;
  1321. displayText = displayText.slice(prefix.length);
  1322. if (displayText === "") {
  1323. editor.removeGhostText();
  1324. }
  1325. else {
  1326. editor.setGhostText(displayText);
  1327. }
  1328. return true;
  1329. };
  1330. AceInline.prototype.isOpen = function () {
  1331. if (!this.editor) {
  1332. return false;
  1333. }
  1334. return !!this.editor.renderer.$ghostText;
  1335. };
  1336. AceInline.prototype.hide = function () {
  1337. if (!this.editor) {
  1338. return false;
  1339. }
  1340. this.editor.removeGhostText();
  1341. return true;
  1342. };
  1343. AceInline.prototype.destroy = function () {
  1344. this.hide();
  1345. this.editor = null;
  1346. };
  1347. return AceInline;
  1348. }());
  1349. exports.AceInline = AceInline;
  1350. });
  1351. ace.define("ace/autocomplete/util",["require","exports","module"], function(require, exports, module){"use strict";
  1352. exports.parForEach = function (array, fn, callback) {
  1353. var completed = 0;
  1354. var arLength = array.length;
  1355. if (arLength === 0)
  1356. callback();
  1357. for (var i = 0; i < arLength; i++) {
  1358. fn(array[i], function (result, err) {
  1359. completed++;
  1360. if (completed === arLength)
  1361. callback(result, err);
  1362. });
  1363. }
  1364. };
  1365. var ID_REGEX = /[a-zA-Z_0-9\$\-\u00A2-\u2000\u2070-\uFFFF]/;
  1366. exports.retrievePrecedingIdentifier = function (text, pos, regex) {
  1367. regex = regex || ID_REGEX;
  1368. var buf = [];
  1369. for (var i = pos - 1; i >= 0; i--) {
  1370. if (regex.test(text[i]))
  1371. buf.push(text[i]);
  1372. else
  1373. break;
  1374. }
  1375. return buf.reverse().join("");
  1376. };
  1377. exports.retrieveFollowingIdentifier = function (text, pos, regex) {
  1378. regex = regex || ID_REGEX;
  1379. var buf = [];
  1380. for (var i = pos; i < text.length; i++) {
  1381. if (regex.test(text[i]))
  1382. buf.push(text[i]);
  1383. else
  1384. break;
  1385. }
  1386. return buf;
  1387. };
  1388. exports.getCompletionPrefix = function (editor) {
  1389. var pos = editor.getCursorPosition();
  1390. var line = editor.session.getLine(pos.row);
  1391. var prefix;
  1392. editor.completers.forEach(function (completer) {
  1393. if (completer.identifierRegexps) {
  1394. completer.identifierRegexps.forEach(function (identifierRegex) {
  1395. if (!prefix && identifierRegex)
  1396. prefix = this.retrievePrecedingIdentifier(line, pos.column, identifierRegex);
  1397. }.bind(this));
  1398. }
  1399. }.bind(this));
  1400. return prefix || this.retrievePrecedingIdentifier(line, pos.column);
  1401. };
  1402. exports.triggerAutocomplete = function (editor) {
  1403. var pos = editor.getCursorPosition();
  1404. var line = editor.session.getLine(pos.row);
  1405. var column = (pos.column === 0) ? 0 : pos.column - 1;
  1406. var previousChar = line[column];
  1407. return editor.completers.some(function (el) {
  1408. if (el.triggerCharacters && Array.isArray(el.triggerCharacters)) {
  1409. return el.triggerCharacters.includes(previousChar);
  1410. }
  1411. });
  1412. };
  1413. });
  1414. ace.define("ace/autocomplete",["require","exports","module","ace/keyboard/hash_handler","ace/autocomplete/popup","ace/autocomplete/inline","ace/autocomplete/popup","ace/autocomplete/util","ace/lib/lang","ace/lib/dom","ace/snippets","ace/config"], function(require, exports, module){"use strict";
  1415. var HashHandler = require("./keyboard/hash_handler").HashHandler;
  1416. var AcePopup = require("./autocomplete/popup").AcePopup;
  1417. var AceInline = require("./autocomplete/inline").AceInline;
  1418. var getAriaId = require("./autocomplete/popup").getAriaId;
  1419. var util = require("./autocomplete/util");
  1420. var lang = require("./lib/lang");
  1421. var dom = require("./lib/dom");
  1422. var snippetManager = require("./snippets").snippetManager;
  1423. var config = require("./config");
  1424. var destroyCompleter = function (e, editor) {
  1425. editor.completer && editor.completer.destroy();
  1426. };
  1427. var Autocomplete = /** @class */ (function () {
  1428. function Autocomplete() {
  1429. this.autoInsert = false;
  1430. this.autoSelect = true;
  1431. this.autoShown = false;
  1432. this.exactMatch = false;
  1433. this.inlineEnabled = false;
  1434. this.keyboardHandler = new HashHandler();
  1435. this.keyboardHandler.bindKeys(this.commands);
  1436. this.parentNode = null;
  1437. this.blurListener = this.blurListener.bind(this);
  1438. this.changeListener = this.changeListener.bind(this);
  1439. this.mousedownListener = this.mousedownListener.bind(this);
  1440. this.mousewheelListener = this.mousewheelListener.bind(this);
  1441. this.changeTimer = lang.delayedCall(function () {
  1442. this.updateCompletions(true);
  1443. }.bind(this));
  1444. this.tooltipTimer = lang.delayedCall(this.updateDocTooltip.bind(this), 50);
  1445. }
  1446. Autocomplete.prototype.$init = function () {
  1447. this.popup = new AcePopup(this.parentNode || document.body || document.documentElement);
  1448. this.popup.on("click", function (e) {
  1449. this.insertMatch();
  1450. e.stop();
  1451. }.bind(this));
  1452. this.popup.focus = this.editor.focus.bind(this.editor);
  1453. this.popup.on("show", this.$onPopupChange.bind(this));
  1454. this.popup.on("hide", this.$onHidePopup.bind(this));
  1455. this.popup.on("select", this.$onPopupChange.bind(this));
  1456. this.popup.on("changeHoverMarker", this.tooltipTimer.bind(null, null));
  1457. return this.popup;
  1458. };
  1459. Autocomplete.prototype.$initInline = function () {
  1460. if (!this.inlineEnabled || this.inlineRenderer)
  1461. return;
  1462. this.inlineRenderer = new AceInline();
  1463. return this.inlineRenderer;
  1464. };
  1465. Autocomplete.prototype.getPopup = function () {
  1466. return this.popup || this.$init();
  1467. };
  1468. Autocomplete.prototype.$onHidePopup = function () {
  1469. if (this.inlineRenderer) {
  1470. this.inlineRenderer.hide();
  1471. }
  1472. this.hideDocTooltip();
  1473. };
  1474. Autocomplete.prototype.$onPopupChange = function (hide) {
  1475. if (this.inlineRenderer && this.inlineEnabled) {
  1476. var completion = hide ? null : this.popup.getData(this.popup.getRow());
  1477. var prefix = util.getCompletionPrefix(this.editor);
  1478. if (!this.inlineRenderer.show(this.editor, completion, prefix)) {
  1479. this.inlineRenderer.hide();
  1480. }
  1481. this.$updatePopupPosition();
  1482. }
  1483. this.tooltipTimer.call(null, null);
  1484. };
  1485. Autocomplete.prototype.$updatePopupPosition = function () {
  1486. var editor = this.editor;
  1487. var renderer = editor.renderer;
  1488. var lineHeight = renderer.layerConfig.lineHeight;
  1489. var pos = renderer.$cursorLayer.getPixelPosition(this.base, true);
  1490. pos.left -= this.popup.getTextLeftOffset();
  1491. var rect = editor.container.getBoundingClientRect();
  1492. pos.top += rect.top - renderer.layerConfig.offset;
  1493. pos.left += rect.left - editor.renderer.scrollLeft;
  1494. pos.left += renderer.gutterWidth;
  1495. var posGhostText = {
  1496. top: pos.top,
  1497. left: pos.left
  1498. };
  1499. if (renderer.$ghostText && renderer.$ghostTextWidget) {
  1500. if (this.base.row === renderer.$ghostText.position.row) {
  1501. posGhostText.top += renderer.$ghostTextWidget.el.offsetHeight;
  1502. }
  1503. }
  1504. if (this.popup.tryShow(posGhostText, lineHeight, "bottom")) {
  1505. return;
  1506. }
  1507. if (this.popup.tryShow(pos, lineHeight, "top")) {
  1508. return;
  1509. }
  1510. this.popup.show(pos, lineHeight);
  1511. };
  1512. Autocomplete.prototype.openPopup = function (editor, prefix, keepPopupPosition) {
  1513. if (!this.popup)
  1514. this.$init();
  1515. if (this.inlineEnabled && !this.inlineRenderer)
  1516. this.$initInline();
  1517. this.popup.autoSelect = this.autoSelect;
  1518. this.popup.setData(this.completions.filtered, this.completions.filterText);
  1519. if (this.editor.textInput.setAriaOptions) {
  1520. this.editor.textInput.setAriaOptions({
  1521. activeDescendant: getAriaId(this.popup.getRow()),
  1522. inline: this.inlineEnabled
  1523. });
  1524. }
  1525. editor.keyBinding.addKeyboardHandler(this.keyboardHandler);
  1526. this.popup.setRow(this.autoSelect ? 0 : -1);
  1527. if (!keepPopupPosition) {
  1528. this.popup.setTheme(editor.getTheme());
  1529. this.popup.setFontSize(editor.getFontSize());
  1530. this.$updatePopupPosition();
  1531. if (this.tooltipNode) {
  1532. this.updateDocTooltip();
  1533. }
  1534. }
  1535. else if (keepPopupPosition && !prefix) {
  1536. this.detach();
  1537. }
  1538. this.changeTimer.cancel();
  1539. };
  1540. Autocomplete.prototype.detach = function () {
  1541. if (this.editor) {
  1542. this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler);
  1543. this.editor.off("changeSelection", this.changeListener);
  1544. this.editor.off("blur", this.blurListener);
  1545. this.editor.off("mousedown", this.mousedownListener);
  1546. this.editor.off("mousewheel", this.mousewheelListener);
  1547. }
  1548. this.changeTimer.cancel();
  1549. this.hideDocTooltip();
  1550. if (this.completionProvider) {
  1551. this.completionProvider.detach();
  1552. }
  1553. if (this.popup && this.popup.isOpen)
  1554. this.popup.hide();
  1555. if (this.base)
  1556. this.base.detach();
  1557. this.activated = false;
  1558. this.completionProvider = this.completions = this.base = null;
  1559. };
  1560. Autocomplete.prototype.changeListener = function (e) {
  1561. var cursor = this.editor.selection.lead;
  1562. if (cursor.row != this.base.row || cursor.column < this.base.column) {
  1563. this.detach();
  1564. }
  1565. if (this.activated)
  1566. this.changeTimer.schedule();
  1567. else
  1568. this.detach();
  1569. };
  1570. Autocomplete.prototype.blurListener = function (e) {
  1571. var el = document.activeElement;
  1572. var text = this.editor.textInput.getElement();
  1573. var fromTooltip = e.relatedTarget && this.tooltipNode && this.tooltipNode.contains(e.relatedTarget);
  1574. var container = this.popup && this.popup.container;
  1575. if (el != text && el.parentNode != container && !fromTooltip
  1576. && el != this.tooltipNode && e.relatedTarget != text) {
  1577. this.detach();
  1578. }
  1579. };
  1580. Autocomplete.prototype.mousedownListener = function (e) {
  1581. this.detach();
  1582. };
  1583. Autocomplete.prototype.mousewheelListener = function (e) {
  1584. this.detach();
  1585. };
  1586. Autocomplete.prototype.goTo = function (where) {
  1587. this.popup.goTo(where);
  1588. };
  1589. Autocomplete.prototype.insertMatch = function (data, options) {
  1590. if (!data)
  1591. data = this.popup.getData(this.popup.getRow());
  1592. if (!data)
  1593. return false;
  1594. if (data.value === "") // Explicitly given nothing to insert, e.g. "No suggestion state"
  1595. return this.detach();
  1596. var completions = this.completions;
  1597. var result = this.getCompletionProvider().insertMatch(this.editor, data, completions.filterText, options);
  1598. if (this.completions == completions)
  1599. this.detach();
  1600. return result;
  1601. };
  1602. Autocomplete.prototype.showPopup = function (editor, options) {
  1603. if (this.editor)
  1604. this.detach();
  1605. this.activated = true;
  1606. this.editor = editor;
  1607. if (editor.completer != this) {
  1608. if (editor.completer)
  1609. editor.completer.detach();
  1610. editor.completer = this;
  1611. }
  1612. editor.on("changeSelection", this.changeListener);
  1613. editor.on("blur", this.blurListener);
  1614. editor.on("mousedown", this.mousedownListener);
  1615. editor.on("mousewheel", this.mousewheelListener);
  1616. this.updateCompletions(false, options);
  1617. };
  1618. Autocomplete.prototype.getCompletionProvider = function () {
  1619. if (!this.completionProvider)
  1620. this.completionProvider = new CompletionProvider();
  1621. return this.completionProvider;
  1622. };
  1623. Autocomplete.prototype.gatherCompletions = function (editor, callback) {
  1624. return this.getCompletionProvider().gatherCompletions(editor, callback);
  1625. };
  1626. Autocomplete.prototype.updateCompletions = function (keepPopupPosition, options) {
  1627. if (keepPopupPosition && this.base && this.completions) {
  1628. var pos = this.editor.getCursorPosition();
  1629. var prefix = this.editor.session.getTextRange({ start: this.base, end: pos });
  1630. if (prefix == this.completions.filterText)
  1631. return;
  1632. this.completions.setFilter(prefix);
  1633. if (!this.completions.filtered.length)
  1634. return this.detach();
  1635. if (this.completions.filtered.length == 1
  1636. && this.completions.filtered[0].value == prefix
  1637. && !this.completions.filtered[0].snippet)
  1638. return this.detach();
  1639. this.openPopup(this.editor, prefix, keepPopupPosition);
  1640. return;
  1641. }
  1642. if (options && options.matches) {
  1643. var pos = this.editor.getSelectionRange().start;
  1644. this.base = this.editor.session.doc.createAnchor(pos.row, pos.column);
  1645. this.base.$insertRight = true;
  1646. this.completions = new FilteredList(options.matches);
  1647. return this.openPopup(this.editor, "", keepPopupPosition);
  1648. }
  1649. var session = this.editor.getSession();
  1650. var pos = this.editor.getCursorPosition();
  1651. var prefix = util.getCompletionPrefix(this.editor);
  1652. this.base = session.doc.createAnchor(pos.row, pos.column - prefix.length);
  1653. this.base.$insertRight = true;
  1654. var completionOptions = { exactMatch: this.exactMatch };
  1655. this.getCompletionProvider().provideCompletions(this.editor, completionOptions, function (err, completions, finished) {
  1656. var filtered = completions.filtered;
  1657. var prefix = util.getCompletionPrefix(this.editor);
  1658. if (finished) {
  1659. if (!filtered.length) {
  1660. var emptyMessage = !this.autoShown && this.emptyMessage;
  1661. if (typeof emptyMessage == "function")
  1662. emptyMessage = this.emptyMessage(prefix);
  1663. if (emptyMessage) {
  1664. var completionsForEmpty = [{
  1665. caption: this.emptyMessage(prefix),
  1666. value: ""
  1667. }];
  1668. this.completions = new FilteredList(completionsForEmpty);
  1669. this.openPopup(this.editor, prefix, keepPopupPosition);
  1670. return;
  1671. }
  1672. return this.detach();
  1673. }
  1674. if (filtered.length == 1 && filtered[0].value == prefix && !filtered[0].snippet)
  1675. return this.detach();
  1676. if (this.autoInsert && !this.autoShown && filtered.length == 1)
  1677. return this.insertMatch(filtered[0]);
  1678. }
  1679. this.completions = completions;
  1680. this.openPopup(this.editor, prefix, keepPopupPosition);
  1681. }.bind(this));
  1682. };
  1683. Autocomplete.prototype.cancelContextMenu = function () {
  1684. this.editor.$mouseHandler.cancelContextMenu();
  1685. };
  1686. Autocomplete.prototype.updateDocTooltip = function () {
  1687. var popup = this.popup;
  1688. var all = popup.data;
  1689. var selected = all && (all[popup.getHoveredRow()] || all[popup.getRow()]);
  1690. var doc = null;
  1691. if (!selected || !this.editor || !this.popup.isOpen)
  1692. return this.hideDocTooltip();
  1693. var completersLength = this.editor.completers.length;
  1694. for (var i = 0; i < completersLength; i++) {
  1695. var completer = this.editor.completers[i];
  1696. if (completer.getDocTooltip && selected.completerId === completer.id) {
  1697. doc = completer.getDocTooltip(selected);
  1698. break;
  1699. }
  1700. }
  1701. if (!doc && typeof selected != "string")
  1702. doc = selected;
  1703. if (typeof doc == "string")
  1704. doc = { docText: doc };
  1705. if (!doc || !(doc.docHTML || doc.docText))
  1706. return this.hideDocTooltip();
  1707. this.showDocTooltip(doc);
  1708. };
  1709. Autocomplete.prototype.showDocTooltip = function (item) {
  1710. if (!this.tooltipNode) {
  1711. this.tooltipNode = dom.createElement("div");
  1712. this.tooltipNode.style.margin = 0;
  1713. this.tooltipNode.style.pointerEvents = "auto";
  1714. this.tooltipNode.tabIndex = -1;
  1715. this.tooltipNode.onblur = this.blurListener.bind(this);
  1716. this.tooltipNode.onclick = this.onTooltipClick.bind(this);
  1717. }
  1718. var theme = this.editor.renderer.theme;
  1719. this.tooltipNode.className = "ace_tooltip ace_doc-tooltip " +
  1720. (theme.isDark ? "ace_dark " : "") + (theme.cssClass || "");
  1721. var tooltipNode = this.tooltipNode;
  1722. if (item.docHTML) {
  1723. tooltipNode.innerHTML = item.docHTML;
  1724. }
  1725. else if (item.docText) {
  1726. tooltipNode.textContent = item.docText;
  1727. }
  1728. if (!tooltipNode.parentNode)
  1729. this.popup.container.appendChild(this.tooltipNode);
  1730. var popup = this.popup;
  1731. var rect = popup.container.getBoundingClientRect();
  1732. tooltipNode.style.top = popup.container.style.top;
  1733. tooltipNode.style.bottom = popup.container.style.bottom;
  1734. tooltipNode.style.display = "block";
  1735. if (window.innerWidth - rect.right < 320) {
  1736. if (rect.left < 320) {
  1737. if (popup.isTopdown) {
  1738. tooltipNode.style.top = rect.bottom + "px";
  1739. tooltipNode.style.left = rect.left + "px";
  1740. tooltipNode.style.right = "";
  1741. tooltipNode.style.bottom = "";
  1742. }
  1743. else {
  1744. tooltipNode.style.top = popup.container.offsetTop - tooltipNode.offsetHeight + "px";
  1745. tooltipNode.style.left = rect.left + "px";
  1746. tooltipNode.style.right = "";
  1747. tooltipNode.style.bottom = "";
  1748. }
  1749. }
  1750. else {
  1751. tooltipNode.style.right = window.innerWidth - rect.left + "px";
  1752. tooltipNode.style.left = "";
  1753. }
  1754. }
  1755. else {
  1756. tooltipNode.style.left = (rect.right + 1) + "px";
  1757. tooltipNode.style.right = "";
  1758. }
  1759. };
  1760. Autocomplete.prototype.hideDocTooltip = function () {
  1761. this.tooltipTimer.cancel();
  1762. if (!this.tooltipNode)
  1763. return;
  1764. var el = this.tooltipNode;
  1765. if (!this.editor.isFocused() && document.activeElement == el)
  1766. this.editor.focus();
  1767. this.tooltipNode = null;
  1768. if (el.parentNode)
  1769. el.parentNode.removeChild(el);
  1770. };
  1771. Autocomplete.prototype.onTooltipClick = function (e) {
  1772. var a = e.target;
  1773. while (a && a != this.tooltipNode) {
  1774. if (a.nodeName == "A" && a.href) {
  1775. a.rel = "noreferrer";
  1776. a.target = "_blank";
  1777. break;
  1778. }
  1779. a = a.parentNode;
  1780. }
  1781. };
  1782. Autocomplete.prototype.destroy = function () {
  1783. this.detach();
  1784. if (this.popup) {
  1785. this.popup.destroy();
  1786. var el = this.popup.container;
  1787. if (el && el.parentNode)
  1788. el.parentNode.removeChild(el);
  1789. }
  1790. if (this.editor && this.editor.completer == this) {
  1791. this.editor.off("destroy", destroyCompleter);
  1792. this.editor.completer = null;
  1793. }
  1794. this.inlineRenderer = this.popup = this.editor = null;
  1795. };
  1796. return Autocomplete;
  1797. }());
  1798. Autocomplete.prototype.commands = {
  1799. "Up": function (editor) { editor.completer.goTo("up"); },
  1800. "Down": function (editor) { editor.completer.goTo("down"); },
  1801. "Ctrl-Up|Ctrl-Home": function (editor) { editor.completer.goTo("start"); },
  1802. "Ctrl-Down|Ctrl-End": function (editor) { editor.completer.goTo("end"); },
  1803. "Esc": function (editor) { editor.completer.detach(); },
  1804. "Return": function (editor) { return editor.completer.insertMatch(); },
  1805. "Shift-Return": function (editor) { editor.completer.insertMatch(null, { deleteSuffix: true }); },
  1806. "Tab": function (editor) {
  1807. var result = editor.completer.insertMatch();
  1808. if (!result && !editor.tabstopManager)
  1809. editor.completer.goTo("down");
  1810. else
  1811. return result;
  1812. },
  1813. "PageUp": function (editor) { editor.completer.popup.gotoPageUp(); },
  1814. "PageDown": function (editor) { editor.completer.popup.gotoPageDown(); }
  1815. };
  1816. Autocomplete.for = function (editor) {
  1817. if (editor.completer instanceof Autocomplete) {
  1818. return editor.completer;
  1819. }
  1820. if (editor.completer) {
  1821. editor.completer.destroy();
  1822. editor.completer = null;
  1823. }
  1824. if (config.get("sharedPopups")) {
  1825. if (!Autocomplete.$sharedInstance)
  1826. Autocomplete.$sharedInstance = new Autocomplete();
  1827. editor.completer = Autocomplete.$sharedInstance;
  1828. }
  1829. else {
  1830. editor.completer = new Autocomplete();
  1831. editor.once("destroy", destroyCompleter);
  1832. }
  1833. return editor.completer;
  1834. };
  1835. Autocomplete.startCommand = {
  1836. name: "startAutocomplete",
  1837. exec: function (editor, options) {
  1838. var completer = Autocomplete.for(editor);
  1839. completer.autoInsert = false;
  1840. completer.autoSelect = true;
  1841. completer.autoShown = false;
  1842. completer.showPopup(editor, options);
  1843. completer.cancelContextMenu();
  1844. },
  1845. bindKey: "Ctrl-Space|Ctrl-Shift-Space|Alt-Space"
  1846. };
  1847. var CompletionProvider = /** @class */ (function () {
  1848. function CompletionProvider() {
  1849. this.active = true;
  1850. }
  1851. CompletionProvider.prototype.insertByIndex = function (editor, index, options) {
  1852. if (!this.completions || !this.completions.filtered) {
  1853. return false;
  1854. }
  1855. return this.insertMatch(editor, this.completions.filtered[index], options);
  1856. };
  1857. CompletionProvider.prototype.insertMatch = function (editor, data, options) {
  1858. if (!data)
  1859. return false;
  1860. editor.startOperation({ command: { name: "insertMatch" } });
  1861. if (data.completer && data.completer.insertMatch) {
  1862. data.completer.insertMatch(editor, data);
  1863. }
  1864. else {
  1865. if (!this.completions)
  1866. return false;
  1867. if (this.completions.filterText) {
  1868. var ranges;
  1869. if (editor.selection.getAllRanges) {
  1870. ranges = editor.selection.getAllRanges();
  1871. }
  1872. else {
  1873. ranges = [editor.getSelectionRange()];
  1874. }
  1875. for (var i = 0, range; range = ranges[i]; i++) {
  1876. range.start.column -= this.completions.filterText.length;
  1877. editor.session.remove(range);
  1878. }
  1879. }
  1880. if (data.snippet)
  1881. snippetManager.insertSnippet(editor, data.snippet, { range: data.range });
  1882. else {
  1883. this.$insertString(editor, data);
  1884. }
  1885. if (data.command && data.command === "startAutocomplete") {
  1886. editor.execCommand(data.command);
  1887. }
  1888. }
  1889. editor.endOperation();
  1890. return true;
  1891. };
  1892. CompletionProvider.prototype.$insertString = function (editor, data) {
  1893. var text = data.value || data;
  1894. if (data.range) {
  1895. if (editor.inVirtualSelectionMode) {
  1896. return editor.session.replace(data.range, text);
  1897. }
  1898. editor.forEachSelection(function () {
  1899. var range = editor.getSelectionRange();
  1900. if (data.range.compareRange(range) === 0) {
  1901. editor.session.replace(data.range, text);
  1902. }
  1903. else {
  1904. editor.insert(text);
  1905. }
  1906. }, null, { keepOrder: true });
  1907. }
  1908. else {
  1909. editor.execCommand("insertstring", text);
  1910. }
  1911. };
  1912. CompletionProvider.prototype.gatherCompletions = function (editor, callback) {
  1913. var session = editor.getSession();
  1914. var pos = editor.getCursorPosition();
  1915. var prefix = util.getCompletionPrefix(editor);
  1916. var matches = [];
  1917. var total = editor.completers.length;
  1918. editor.completers.forEach(function (completer, i) {
  1919. completer.getCompletions(editor, session, pos, prefix, function (err, results) {
  1920. if (!err && results)
  1921. matches = matches.concat(results);
  1922. callback(null, {
  1923. prefix: util.getCompletionPrefix(editor),
  1924. matches: matches,
  1925. finished: (--total === 0)
  1926. });
  1927. });
  1928. });
  1929. return true;
  1930. };
  1931. CompletionProvider.prototype.provideCompletions = function (editor, options, callback) {
  1932. var processResults = function (results) {
  1933. var prefix = results.prefix;
  1934. var matches = results.matches;
  1935. this.completions = new FilteredList(matches);
  1936. if (options.exactMatch)
  1937. this.completions.exactMatch = true;
  1938. if (options.ignoreCaption)
  1939. this.completions.ignoreCaption = true;
  1940. this.completions.setFilter(prefix);
  1941. if (results.finished || this.completions.filtered.length)
  1942. callback(null, this.completions, results.finished);
  1943. }.bind(this);
  1944. var isImmediate = true;
  1945. var immediateResults = null;
  1946. this.gatherCompletions(editor, function (err, results) {
  1947. if (!this.active) {
  1948. return;
  1949. }
  1950. if (err) {
  1951. callback(err, [], true);
  1952. this.detach();
  1953. }
  1954. var prefix = results.prefix;
  1955. if (prefix.indexOf(results.prefix) !== 0)
  1956. return;
  1957. if (isImmediate) {
  1958. immediateResults = results;
  1959. return;
  1960. }
  1961. processResults(results);
  1962. }.bind(this));
  1963. isImmediate = false;
  1964. if (immediateResults) {
  1965. var results = immediateResults;
  1966. immediateResults = null;
  1967. processResults(results);
  1968. }
  1969. };
  1970. CompletionProvider.prototype.detach = function () {
  1971. this.active = false;
  1972. };
  1973. return CompletionProvider;
  1974. }());
  1975. var FilteredList = /** @class */ (function () {
  1976. function FilteredList(array, filterText) {
  1977. this.all = array;
  1978. this.filtered = array;
  1979. this.filterText = filterText || "";
  1980. this.exactMatch = false;
  1981. this.ignoreCaption = false;
  1982. }
  1983. FilteredList.prototype.setFilter = function (str) {
  1984. if (str.length > this.filterText && str.lastIndexOf(this.filterText, 0) === 0)
  1985. var matches = this.filtered;
  1986. else
  1987. var matches = this.all;
  1988. this.filterText = str;
  1989. matches = this.filterCompletions(matches, this.filterText);
  1990. matches = matches.sort(function (a, b) {
  1991. return b.exactMatch - a.exactMatch || b.$score - a.$score
  1992. || (a.caption || a.value).localeCompare(b.caption || b.value);
  1993. });
  1994. var prev = null;
  1995. matches = matches.filter(function (item) {
  1996. var caption = item.snippet || item.caption || item.value;
  1997. if (caption === prev)
  1998. return false;
  1999. prev = caption;
  2000. return true;
  2001. });
  2002. this.filtered = matches;
  2003. };
  2004. FilteredList.prototype.filterCompletions = function (items, needle) {
  2005. var results = [];
  2006. var upper = needle.toUpperCase();
  2007. var lower = needle.toLowerCase();
  2008. loop: for (var i = 0, item; item = items[i]; i++) {
  2009. var caption = (!this.ignoreCaption && item.caption) || item.value || item.snippet;
  2010. if (!caption)
  2011. continue;
  2012. var lastIndex = -1;
  2013. var matchMask = 0;
  2014. var penalty = 0;
  2015. var index, distance;
  2016. if (this.exactMatch) {
  2017. if (needle !== caption.substr(0, needle.length))
  2018. continue loop;
  2019. }
  2020. else {
  2021. var fullMatchIndex = caption.toLowerCase().indexOf(lower);
  2022. if (fullMatchIndex > -1) {
  2023. penalty = fullMatchIndex;
  2024. }
  2025. else {
  2026. for (var j = 0; j < needle.length; j++) {
  2027. var i1 = caption.indexOf(lower[j], lastIndex + 1);
  2028. var i2 = caption.indexOf(upper[j], lastIndex + 1);
  2029. index = (i1 >= 0) ? ((i2 < 0 || i1 < i2) ? i1 : i2) : i2;
  2030. if (index < 0)
  2031. continue loop;
  2032. distance = index - lastIndex - 1;
  2033. if (distance > 0) {
  2034. if (lastIndex === -1)
  2035. penalty += 10;
  2036. penalty += distance;
  2037. matchMask = matchMask | (1 << j);
  2038. }
  2039. lastIndex = index;
  2040. }
  2041. }
  2042. }
  2043. item.matchMask = matchMask;
  2044. item.exactMatch = penalty ? 0 : 1;
  2045. item.$score = (item.score || 0) - penalty;
  2046. results.push(item);
  2047. }
  2048. return results;
  2049. };
  2050. return FilteredList;
  2051. }());
  2052. exports.Autocomplete = Autocomplete;
  2053. exports.CompletionProvider = CompletionProvider;
  2054. exports.FilteredList = FilteredList;
  2055. });
  2056. ace.define("ace/autocomplete/text_completer",["require","exports","module","ace/range"], function(require, exports, module){var Range = require("../range").Range;
  2057. var splitRegex = /[^a-zA-Z_0-9\$\-\u00C0-\u1FFF\u2C00-\uD7FF\w]+/;
  2058. function getWordIndex(doc, pos) {
  2059. var textBefore = doc.getTextRange(Range.fromPoints({
  2060. row: 0,
  2061. column: 0
  2062. }, pos));
  2063. return textBefore.split(splitRegex).length - 1;
  2064. }
  2065. function wordDistance(doc, pos) {
  2066. var prefixPos = getWordIndex(doc, pos);
  2067. var words = doc.getValue().split(splitRegex);
  2068. var wordScores = Object.create(null);
  2069. var currentWord = words[prefixPos];
  2070. words.forEach(function (word, idx) {
  2071. if (!word || word === currentWord)
  2072. return;
  2073. var distance = Math.abs(prefixPos - idx);
  2074. var score = words.length - distance;
  2075. if (wordScores[word]) {
  2076. wordScores[word] = Math.max(score, wordScores[word]);
  2077. }
  2078. else {
  2079. wordScores[word] = score;
  2080. }
  2081. });
  2082. return wordScores;
  2083. }
  2084. exports.getCompletions = function (editor, session, pos, prefix, callback) {
  2085. var wordScore = wordDistance(session, pos);
  2086. var wordList = Object.keys(wordScore);
  2087. callback(null, wordList.map(function (word) {
  2088. return {
  2089. caption: word,
  2090. value: word,
  2091. score: wordScore[word],
  2092. meta: "local"
  2093. };
  2094. }));
  2095. };
  2096. });
  2097. ace.define("ace/ext/language_tools",["require","exports","module","ace/snippets","ace/autocomplete","ace/config","ace/lib/lang","ace/autocomplete/util","ace/autocomplete/text_completer","ace/editor","ace/config"], function(require, exports, module){"use strict";
  2098. var snippetManager = require("../snippets").snippetManager;
  2099. var Autocomplete = require("../autocomplete").Autocomplete;
  2100. var config = require("../config");
  2101. var lang = require("../lib/lang");
  2102. var util = require("../autocomplete/util");
  2103. var textCompleter = require("../autocomplete/text_completer");
  2104. var keyWordCompleter = {
  2105. getCompletions: function (editor, session, pos, prefix, callback) {
  2106. if (session.$mode.completer) {
  2107. return session.$mode.completer.getCompletions(editor, session, pos, prefix, callback);
  2108. }
  2109. var state = editor.session.getState(pos.row);
  2110. var completions = session.$mode.getCompletions(state, session, pos, prefix);
  2111. completions = completions.map(function (el) {
  2112. el.completerId = keyWordCompleter.id;
  2113. return el;
  2114. });
  2115. callback(null, completions);
  2116. },
  2117. id: "keywordCompleter"
  2118. };
  2119. var transformSnippetTooltip = function (str) {
  2120. var record = {};
  2121. return str.replace(/\${(\d+)(:(.*?))?}/g, function (_, p1, p2, p3) {
  2122. return (record[p1] = p3 || '');
  2123. }).replace(/\$(\d+?)/g, function (_, p1) {
  2124. return record[p1];
  2125. });
  2126. };
  2127. var snippetCompleter = {
  2128. getCompletions: function (editor, session, pos, prefix, callback) {
  2129. var scopes = [];
  2130. var token = session.getTokenAt(pos.row, pos.column);
  2131. if (token && token.type.match(/(tag-name|tag-open|tag-whitespace|attribute-name|attribute-value)\.xml$/))
  2132. scopes.push('html-tag');
  2133. else
  2134. scopes = snippetManager.getActiveScopes(editor);
  2135. var snippetMap = snippetManager.snippetMap;
  2136. var completions = [];
  2137. scopes.forEach(function (scope) {
  2138. var snippets = snippetMap[scope] || [];
  2139. for (var i = snippets.length; i--;) {
  2140. var s = snippets[i];
  2141. var caption = s.name || s.tabTrigger;
  2142. if (!caption)
  2143. continue;
  2144. completions.push({
  2145. caption: caption,
  2146. snippet: s.content,
  2147. meta: s.tabTrigger && !s.name ? s.tabTrigger + "\u21E5 " : "snippet",
  2148. completerId: snippetCompleter.id
  2149. });
  2150. }
  2151. }, this);
  2152. callback(null, completions);
  2153. },
  2154. getDocTooltip: function (item) {
  2155. if (item.snippet && !item.docHTML) {
  2156. item.docHTML = [
  2157. "<b>", lang.escapeHTML(item.caption), "</b>", "<hr></hr>",
  2158. lang.escapeHTML(transformSnippetTooltip(item.snippet))
  2159. ].join("");
  2160. }
  2161. },
  2162. id: "snippetCompleter"
  2163. };
  2164. var completers = [snippetCompleter, textCompleter, keyWordCompleter];
  2165. exports.setCompleters = function (val) {
  2166. completers.length = 0;
  2167. if (val)
  2168. completers.push.apply(completers, val);
  2169. };
  2170. exports.addCompleter = function (completer) {
  2171. completers.push(completer);
  2172. };
  2173. exports.textCompleter = textCompleter;
  2174. exports.keyWordCompleter = keyWordCompleter;
  2175. exports.snippetCompleter = snippetCompleter;
  2176. var expandSnippet = {
  2177. name: "expandSnippet",
  2178. exec: function (editor) {
  2179. return snippetManager.expandWithTab(editor);
  2180. },
  2181. bindKey: "Tab"
  2182. };
  2183. var onChangeMode = function (e, editor) {
  2184. loadSnippetsForMode(editor.session.$mode);
  2185. };
  2186. var loadSnippetsForMode = function (mode) {
  2187. if (typeof mode == "string")
  2188. mode = config.$modes[mode];
  2189. if (!mode)
  2190. return;
  2191. if (!snippetManager.files)
  2192. snippetManager.files = {};
  2193. loadSnippetFile(mode.$id, mode.snippetFileId);
  2194. if (mode.modes)
  2195. mode.modes.forEach(loadSnippetsForMode);
  2196. };
  2197. var loadSnippetFile = function (id, snippetFilePath) {
  2198. if (!snippetFilePath || !id || snippetManager.files[id])
  2199. return;
  2200. snippetManager.files[id] = {};
  2201. config.loadModule(snippetFilePath, function (m) {
  2202. if (!m)
  2203. return;
  2204. snippetManager.files[id] = m;
  2205. if (!m.snippets && m.snippetText)
  2206. m.snippets = snippetManager.parseSnippetFile(m.snippetText);
  2207. snippetManager.register(m.snippets || [], m.scope);
  2208. if (m.includeScopes) {
  2209. snippetManager.snippetMap[m.scope].includeScopes = m.includeScopes;
  2210. m.includeScopes.forEach(function (x) {
  2211. loadSnippetsForMode("ace/mode/" + x);
  2212. });
  2213. }
  2214. });
  2215. };
  2216. var doLiveAutocomplete = function (e) {
  2217. var editor = e.editor;
  2218. var hasCompleter = editor.completer && editor.completer.activated;
  2219. if (e.command.name === "backspace") {
  2220. if (hasCompleter && !util.getCompletionPrefix(editor))
  2221. editor.completer.detach();
  2222. }
  2223. else if (e.command.name === "insertstring") {
  2224. var prefix = util.getCompletionPrefix(editor);
  2225. var triggerAutocomplete = util.triggerAutocomplete(editor);
  2226. if ((prefix || triggerAutocomplete) && !hasCompleter) {
  2227. var completer = Autocomplete.for(editor);
  2228. completer.autoShown = true;
  2229. completer.showPopup(editor);
  2230. }
  2231. }
  2232. };
  2233. var Editor = require("../editor").Editor;
  2234. require("../config").defineOptions(Editor.prototype, "editor", {
  2235. enableBasicAutocompletion: {
  2236. set: function (val) {
  2237. if (val) {
  2238. if (!this.completers)
  2239. this.completers = Array.isArray(val) ? val : completers;
  2240. this.commands.addCommand(Autocomplete.startCommand);
  2241. }
  2242. else {
  2243. this.commands.removeCommand(Autocomplete.startCommand);
  2244. }
  2245. },
  2246. value: false
  2247. },
  2248. enableLiveAutocompletion: {
  2249. set: function (val) {
  2250. if (val) {
  2251. if (!this.completers)
  2252. this.completers = Array.isArray(val) ? val : completers;
  2253. this.commands.on('afterExec', doLiveAutocomplete);
  2254. }
  2255. else {
  2256. this.commands.removeListener('afterExec', doLiveAutocomplete);
  2257. }
  2258. },
  2259. value: false
  2260. },
  2261. enableSnippets: {
  2262. set: function (val) {
  2263. if (val) {
  2264. this.commands.addCommand(expandSnippet);
  2265. this.on("changeMode", onChangeMode);
  2266. onChangeMode(null, this);
  2267. }
  2268. else {
  2269. this.commands.removeCommand(expandSnippet);
  2270. this.off("changeMode", onChangeMode);
  2271. }
  2272. },
  2273. value: false
  2274. }
  2275. });
  2276. }); (function() {
  2277. ace.require(["ace/ext/language_tools"], function(m) {
  2278. if (typeof module == "object" && typeof exports == "object" && module) {
  2279. module.exports = m;
  2280. }
  2281. });
  2282. })();