corrade-nucleus-nucleons – Blame information for rev 6
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
2 | office | 1 | ace.define("ace/snippets",["require","exports","module","ace/lib/oop","ace/lib/event_emitter","ace/lib/lang","ace/range","ace/anchor","ace/keyboard/hash_handler","ace/tokenizer","ace/lib/dom","ace/editor"], function(require, exports, module) { |
2 | "use strict"; |
||
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 Anchor = require("./anchor").Anchor; |
||
8 | var HashHandler = require("./keyboard/hash_handler").HashHandler; |
||
9 | var Tokenizer = require("./tokenizer").Tokenizer; |
||
10 | var comparePoints = Range.comparePoints; |
||
11 | |||
12 | var SnippetManager = function() { |
||
13 | this.snippetMap = {}; |
||
14 | this.snippetNameMap = {}; |
||
15 | }; |
||
16 | |||
17 | (function() { |
||
18 | oop.implement(this, EventEmitter); |
||
19 | |||
20 | this.getTokenizer = function() { |
||
21 | function TabstopToken(str, _, stack) { |
||
22 | str = str.substr(1); |
||
23 | if (/^\d+$/.test(str) && !stack.inFormatString) |
||
24 | return [{tabstopId: parseInt(str, 10)}]; |
||
25 | return [{text: str}]; |
||
26 | } |
||
27 | function escape(ch) { |
||
28 | return "(?:[^\\\\" + ch + "]|\\\\.)"; |
||
29 | } |
||
30 | SnippetManager.$tokenizer = new Tokenizer({ |
||
31 | start: [ |
||
32 | {regex: /:/, onMatch: function(val, state, stack) { |
||
33 | if (stack.length && stack[0].expectIf) { |
||
34 | stack[0].expectIf = false; |
||
35 | stack[0].elseBranch = stack[0]; |
||
36 | return [stack[0]]; |
||
37 | } |
||
38 | return ":"; |
||
39 | }}, |
||
40 | {regex: /\\./, onMatch: function(val, state, stack) { |
||
41 | var ch = val[1]; |
||
42 | if (ch == "}" && stack.length) { |
||
43 | val = ch; |
||
44 | }else if ("`$\\".indexOf(ch) != -1) { |
||
45 | val = ch; |
||
46 | } else if (stack.inFormatString) { |
||
47 | if (ch == "n") |
||
48 | val = "\n"; |
||
49 | else if (ch == "t") |
||
50 | val = "\n"; |
||
51 | else if ("ulULE".indexOf(ch) != -1) { |
||
52 | val = {changeCase: ch, local: ch > "a"}; |
||
53 | } |
||
54 | } |
||
55 | |||
56 | return [val]; |
||
57 | }}, |
||
58 | {regex: /}/, onMatch: function(val, state, stack) { |
||
59 | return [stack.length ? stack.shift() : val]; |
||
60 | }}, |
||
61 | {regex: /\$(?:\d+|\w+)/, onMatch: TabstopToken}, |
||
62 | {regex: /\$\{[\dA-Z_a-z]+/, onMatch: function(str, state, stack) { |
||
63 | var t = TabstopToken(str.substr(1), state, stack); |
||
64 | stack.unshift(t[0]); |
||
65 | return t; |
||
66 | }, next: "snippetVar"}, |
||
67 | {regex: /\n/, token: "newline", merge: false} |
||
68 | ], |
||
69 | snippetVar: [ |
||
70 | {regex: "\\|" + escape("\\|") + "*\\|", onMatch: function(val, state, stack) { |
||
71 | stack[0].choices = val.slice(1, -1).split(","); |
||
72 | }, next: "start"}, |
||
73 | {regex: "/(" + escape("/") + "+)/(?:(" + escape("/") + "*)/)(\\w*):?", |
||
74 | onMatch: function(val, state, stack) { |
||
75 | var ts = stack[0]; |
||
76 | ts.fmtString = val; |
||
77 | |||
78 | val = this.splitRegex.exec(val); |
||
79 | ts.guard = val[1]; |
||
80 | ts.fmt = val[2]; |
||
81 | ts.flag = val[3]; |
||
82 | return ""; |
||
83 | }, next: "start"}, |
||
84 | {regex: "`" + escape("`") + "*`", onMatch: function(val, state, stack) { |
||
85 | stack[0].code = val.splice(1, -1); |
||
86 | return ""; |
||
87 | }, next: "start"}, |
||
88 | {regex: "\\?", onMatch: function(val, state, stack) { |
||
89 | if (stack[0]) |
||
90 | stack[0].expectIf = true; |
||
91 | }, next: "start"}, |
||
92 | {regex: "([^:}\\\\]|\\\\.)*:?", token: "", next: "start"} |
||
93 | ], |
||
94 | formatString: [ |
||
95 | {regex: "/(" + escape("/") + "+)/", token: "regex"}, |
||
96 | {regex: "", onMatch: function(val, state, stack) { |
||
97 | stack.inFormatString = true; |
||
98 | }, next: "start"} |
||
99 | ] |
||
100 | }); |
||
101 | SnippetManager.prototype.getTokenizer = function() { |
||
102 | return SnippetManager.$tokenizer; |
||
103 | }; |
||
104 | return SnippetManager.$tokenizer; |
||
105 | }; |
||
106 | |||
107 | this.tokenizeTmSnippet = function(str, startState) { |
||
108 | return this.getTokenizer().getLineTokens(str, startState).tokens.map(function(x) { |
||
109 | return x.value || x; |
||
110 | }); |
||
111 | }; |
||
112 | |||
113 | this.$getDefaultValue = function(editor, name) { |
||
114 | if (/^[A-Z]\d+$/.test(name)) { |
||
115 | var i = name.substr(1); |
||
116 | return (this.variables[name[0] + "__"] || {})[i]; |
||
117 | } |
||
118 | if (/^\d+$/.test(name)) { |
||
119 | return (this.variables.__ || {})[name]; |
||
120 | } |
||
121 | name = name.replace(/^TM_/, ""); |
||
122 | |||
123 | if (!editor) |
||
124 | return; |
||
125 | var s = editor.session; |
||
126 | switch(name) { |
||
127 | case "CURRENT_WORD": |
||
128 | var r = s.getWordRange(); |
||
129 | case "SELECTION": |
||
130 | case "SELECTED_TEXT": |
||
131 | return s.getTextRange(r); |
||
132 | case "CURRENT_LINE": |
||
133 | return s.getLine(editor.getCursorPosition().row); |
||
134 | case "PREV_LINE": // not possible in textmate |
||
135 | return s.getLine(editor.getCursorPosition().row - 1); |
||
136 | case "LINE_INDEX": |
||
137 | return editor.getCursorPosition().column; |
||
138 | case "LINE_NUMBER": |
||
139 | return editor.getCursorPosition().row + 1; |
||
140 | case "SOFT_TABS": |
||
141 | return s.getUseSoftTabs() ? "YES" : "NO"; |
||
142 | case "TAB_SIZE": |
||
143 | return s.getTabSize(); |
||
144 | case "FILENAME": |
||
145 | case "FILEPATH": |
||
146 | return ""; |
||
147 | case "FULLNAME": |
||
148 | return "Ace"; |
||
149 | } |
||
150 | }; |
||
151 | this.variables = {}; |
||
152 | this.getVariableValue = function(editor, varName) { |
||
153 | if (this.variables.hasOwnProperty(varName)) |
||
154 | return this.variables[varName](editor, varName) || ""; |
||
155 | return this.$getDefaultValue(editor, varName) || ""; |
||
156 | }; |
||
157 | this.tmStrFormat = function(str, ch, editor) { |
||
158 | var flag = ch.flag || ""; |
||
159 | var re = ch.guard; |
||
160 | re = new RegExp(re, flag.replace(/[^gi]/, "")); |
||
161 | var fmtTokens = this.tokenizeTmSnippet(ch.fmt, "formatString"); |
||
162 | var _self = this; |
||
163 | var formatted = str.replace(re, function() { |
||
164 | _self.variables.__ = arguments; |
||
165 | var fmtParts = _self.resolveVariables(fmtTokens, editor); |
||
166 | var gChangeCase = "E"; |
||
167 | for (var i = 0; i < fmtParts.length; i++) { |
||
168 | var ch = fmtParts[i]; |
||
169 | if (typeof ch == "object") { |
||
170 | fmtParts[i] = ""; |
||
171 | if (ch.changeCase && ch.local) { |
||
172 | var next = fmtParts[i + 1]; |
||
173 | if (next && typeof next == "string") { |
||
174 | if (ch.changeCase == "u") |
||
175 | fmtParts[i] = next[0].toUpperCase(); |
||
176 | else |
||
177 | fmtParts[i] = next[0].toLowerCase(); |
||
178 | fmtParts[i + 1] = next.substr(1); |
||
179 | } |
||
180 | } else if (ch.changeCase) { |
||
181 | gChangeCase = ch.changeCase; |
||
182 | } |
||
183 | } else if (gChangeCase == "U") { |
||
184 | fmtParts[i] = ch.toUpperCase(); |
||
185 | } else if (gChangeCase == "L") { |
||
186 | fmtParts[i] = ch.toLowerCase(); |
||
187 | } |
||
188 | } |
||
189 | return fmtParts.join(""); |
||
190 | }); |
||
191 | this.variables.__ = null; |
||
192 | return formatted; |
||
193 | }; |
||
194 | |||
195 | this.resolveVariables = function(snippet, editor) { |
||
196 | var result = []; |
||
197 | for (var i = 0; i < snippet.length; i++) { |
||
198 | var ch = snippet[i]; |
||
199 | if (typeof ch == "string") { |
||
200 | result.push(ch); |
||
201 | } else if (typeof ch != "object") { |
||
202 | continue; |
||
203 | } else if (ch.skip) { |
||
204 | gotoNext(ch); |
||
205 | } else if (ch.processed < i) { |
||
206 | continue; |
||
207 | } else if (ch.text) { |
||
208 | var value = this.getVariableValue(editor, ch.text); |
||
209 | if (value && ch.fmtString) |
||
210 | value = this.tmStrFormat(value, ch); |
||
211 | ch.processed = i; |
||
212 | if (ch.expectIf == null) { |
||
213 | if (value) { |
||
214 | result.push(value); |
||
215 | gotoNext(ch); |
||
216 | } |
||
217 | } else { |
||
218 | if (value) { |
||
219 | ch.skip = ch.elseBranch; |
||
220 | } else |
||
221 | gotoNext(ch); |
||
222 | } |
||
223 | } else if (ch.tabstopId != null) { |
||
224 | result.push(ch); |
||
225 | } else if (ch.changeCase != null) { |
||
226 | result.push(ch); |
||
227 | } |
||
228 | } |
||
229 | function gotoNext(ch) { |
||
230 | var i1 = snippet.indexOf(ch, i + 1); |
||
231 | if (i1 != -1) |
||
232 | i = i1; |
||
233 | } |
||
234 | return result; |
||
235 | }; |
||
236 | |||
237 | this.insertSnippetForSelection = function(editor, snippetText) { |
||
238 | var cursor = editor.getCursorPosition(); |
||
239 | var line = editor.session.getLine(cursor.row); |
||
240 | var tabString = editor.session.getTabString(); |
||
241 | var indentString = line.match(/^\s*/)[0]; |
||
242 | |||
243 | if (cursor.column < indentString.length) |
||
244 | indentString = indentString.slice(0, cursor.column); |
||
245 | |||
246 | snippetText = snippetText.replace(/\r/g, ""); |
||
247 | var tokens = this.tokenizeTmSnippet(snippetText); |
||
248 | tokens = this.resolveVariables(tokens, editor); |
||
249 | tokens = tokens.map(function(x) { |
||
250 | if (x == "\n") |
||
251 | return x + indentString; |
||
252 | if (typeof x == "string") |
||
253 | return x.replace(/\t/g, tabString); |
||
254 | return x; |
||
255 | }); |
||
256 | var tabstops = []; |
||
257 | tokens.forEach(function(p, i) { |
||
258 | if (typeof p != "object") |
||
259 | return; |
||
260 | var id = p.tabstopId; |
||
261 | var ts = tabstops[id]; |
||
262 | if (!ts) { |
||
263 | ts = tabstops[id] = []; |
||
264 | ts.index = id; |
||
265 | ts.value = ""; |
||
266 | } |
||
267 | if (ts.indexOf(p) !== -1) |
||
268 | return; |
||
269 | ts.push(p); |
||
270 | var i1 = tokens.indexOf(p, i + 1); |
||
271 | if (i1 === -1) |
||
272 | return; |
||
273 | |||
274 | var value = tokens.slice(i + 1, i1); |
||
275 | var isNested = value.some(function(t) {return typeof t === "object"}); |
||
276 | if (isNested && !ts.value) { |
||
277 | ts.value = value; |
||
278 | } else if (value.length && (!ts.value || typeof ts.value !== "string")) { |
||
279 | ts.value = value.join(""); |
||
280 | } |
||
281 | }); |
||
282 | tabstops.forEach(function(ts) {ts.length = 0}); |
||
283 | var expanding = {}; |
||
284 | function copyValue(val) { |
||
285 | var copy = []; |
||
286 | for (var i = 0; i < val.length; i++) { |
||
287 | var p = val[i]; |
||
288 | if (typeof p == "object") { |
||
289 | if (expanding[p.tabstopId]) |
||
290 | continue; |
||
291 | var j = val.lastIndexOf(p, i - 1); |
||
292 | p = copy[j] || {tabstopId: p.tabstopId}; |
||
293 | } |
||
294 | copy[i] = p; |
||
295 | } |
||
296 | return copy; |
||
297 | } |
||
298 | for (var i = 0; i < tokens.length; i++) { |
||
299 | var p = tokens[i]; |
||
300 | if (typeof p != "object") |
||
301 | continue; |
||
302 | var id = p.tabstopId; |
||
303 | var i1 = tokens.indexOf(p, i + 1); |
||
304 | if (expanding[id]) { |
||
305 | if (expanding[id] === p) |
||
306 | expanding[id] = null; |
||
307 | continue; |
||
308 | } |
||
309 | |||
310 | var ts = tabstops[id]; |
||
311 | var arg = typeof ts.value == "string" ? [ts.value] : copyValue(ts.value); |
||
312 | arg.unshift(i + 1, Math.max(0, i1 - i)); |
||
313 | arg.push(p); |
||
314 | expanding[id] = p; |
||
315 | tokens.splice.apply(tokens, arg); |
||
316 | |||
317 | if (ts.indexOf(p) === -1) |
||
318 | ts.push(p); |
||
319 | } |
||
320 | var row = 0, column = 0; |
||
321 | var text = ""; |
||
322 | tokens.forEach(function(t) { |
||
323 | if (typeof t === "string") { |
||
324 | var lines = t.split("\n"); |
||
325 | if (lines.length > 1){ |
||
326 | column = lines[lines.length - 1].length; |
||
327 | row += lines.length - 1; |
||
328 | } else |
||
329 | column += t.length; |
||
330 | text += t; |
||
331 | } else { |
||
332 | if (!t.start) |
||
333 | t.start = {row: row, column: column}; |
||
334 | else |
||
335 | t.end = {row: row, column: column}; |
||
336 | } |
||
337 | }); |
||
338 | var range = editor.getSelectionRange(); |
||
339 | var end = editor.session.replace(range, text); |
||
340 | |||
341 | var tabstopManager = new TabstopManager(editor); |
||
342 | var selectionId = editor.inVirtualSelectionMode && editor.selection.index; |
||
343 | tabstopManager.addTabstops(tabstops, range.start, end, selectionId); |
||
344 | }; |
||
345 | |||
346 | this.insertSnippet = function(editor, snippetText) { |
||
347 | var self = this; |
||
348 | if (editor.inVirtualSelectionMode) |
||
349 | return self.insertSnippetForSelection(editor, snippetText); |
||
350 | |||
351 | editor.forEachSelection(function() { |
||
352 | self.insertSnippetForSelection(editor, snippetText); |
||
353 | }, null, {keepOrder: true}); |
||
354 | |||
355 | if (editor.tabstopManager) |
||
356 | editor.tabstopManager.tabNext(); |
||
357 | }; |
||
358 | |||
359 | this.$getScope = function(editor) { |
||
360 | var scope = editor.session.$mode.$id || ""; |
||
361 | scope = scope.split("/").pop(); |
||
362 | if (scope === "html" || scope === "php") { |
||
363 | if (scope === "php" && !editor.session.$mode.inlinePhp) |
||
364 | scope = "html"; |
||
365 | var c = editor.getCursorPosition(); |
||
366 | var state = editor.session.getState(c.row); |
||
367 | if (typeof state === "object") { |
||
368 | state = state[0]; |
||
369 | } |
||
370 | if (state.substring) { |
||
371 | if (state.substring(0, 3) == "js-") |
||
372 | scope = "javascript"; |
||
373 | else if (state.substring(0, 4) == "css-") |
||
374 | scope = "css"; |
||
375 | else if (state.substring(0, 4) == "php-") |
||
376 | scope = "php"; |
||
377 | } |
||
378 | } |
||
379 | |||
380 | return scope; |
||
381 | }; |
||
382 | |||
383 | this.getActiveScopes = function(editor) { |
||
384 | var scope = this.$getScope(editor); |
||
385 | var scopes = [scope]; |
||
386 | var snippetMap = this.snippetMap; |
||
387 | if (snippetMap[scope] && snippetMap[scope].includeScopes) { |
||
388 | scopes.push.apply(scopes, snippetMap[scope].includeScopes); |
||
389 | } |
||
390 | scopes.push("_"); |
||
391 | return scopes; |
||
392 | }; |
||
393 | |||
394 | this.expandWithTab = function(editor, options) { |
||
395 | var self = this; |
||
396 | var result = editor.forEachSelection(function() { |
||
397 | return self.expandSnippetForSelection(editor, options); |
||
398 | }, null, {keepOrder: true}); |
||
399 | if (result && editor.tabstopManager) |
||
400 | editor.tabstopManager.tabNext(); |
||
401 | return result; |
||
402 | }; |
||
403 | |||
404 | this.expandSnippetForSelection = function(editor, options) { |
||
405 | var cursor = editor.getCursorPosition(); |
||
406 | var line = editor.session.getLine(cursor.row); |
||
407 | var before = line.substring(0, cursor.column); |
||
408 | var after = line.substr(cursor.column); |
||
409 | |||
410 | var snippetMap = this.snippetMap; |
||
411 | var snippet; |
||
412 | this.getActiveScopes(editor).some(function(scope) { |
||
413 | var snippets = snippetMap[scope]; |
||
414 | if (snippets) |
||
415 | snippet = this.findMatchingSnippet(snippets, before, after); |
||
416 | return !!snippet; |
||
417 | }, this); |
||
418 | if (!snippet) |
||
419 | return false; |
||
420 | if (options && options.dryRun) |
||
421 | return true; |
||
422 | editor.session.doc.removeInLine(cursor.row, |
||
423 | cursor.column - snippet.replaceBefore.length, |
||
424 | cursor.column + snippet.replaceAfter.length |
||
425 | ); |
||
426 | |||
427 | this.variables.M__ = snippet.matchBefore; |
||
428 | this.variables.T__ = snippet.matchAfter; |
||
429 | this.insertSnippetForSelection(editor, snippet.content); |
||
430 | |||
431 | this.variables.M__ = this.variables.T__ = null; |
||
432 | return true; |
||
433 | }; |
||
434 | |||
435 | this.findMatchingSnippet = function(snippetList, before, after) { |
||
436 | for (var i = snippetList.length; i--;) { |
||
437 | var s = snippetList[i]; |
||
438 | if (s.startRe && !s.startRe.test(before)) |
||
439 | continue; |
||
440 | if (s.endRe && !s.endRe.test(after)) |
||
441 | continue; |
||
442 | if (!s.startRe && !s.endRe) |
||
443 | continue; |
||
444 | |||
445 | s.matchBefore = s.startRe ? s.startRe.exec(before) : [""]; |
||
446 | s.matchAfter = s.endRe ? s.endRe.exec(after) : [""]; |
||
447 | s.replaceBefore = s.triggerRe ? s.triggerRe.exec(before)[0] : ""; |
||
448 | s.replaceAfter = s.endTriggerRe ? s.endTriggerRe.exec(after)[0] : ""; |
||
449 | return s; |
||
450 | } |
||
451 | }; |
||
452 | |||
453 | this.snippetMap = {}; |
||
454 | this.snippetNameMap = {}; |
||
455 | this.register = function(snippets, scope) { |
||
456 | var snippetMap = this.snippetMap; |
||
457 | var snippetNameMap = this.snippetNameMap; |
||
458 | var self = this; |
||
459 | |||
460 | if (!snippets) |
||
461 | snippets = []; |
||
462 | |||
463 | function wrapRegexp(src) { |
||
464 | if (src && !/^\^?\(.*\)\$?$|^\\b$/.test(src)) |
||
465 | src = "(?:" + src + ")"; |
||
466 | |||
467 | return src || ""; |
||
468 | } |
||
469 | function guardedRegexp(re, guard, opening) { |
||
470 | re = wrapRegexp(re); |
||
471 | guard = wrapRegexp(guard); |
||
472 | if (opening) { |
||
473 | re = guard + re; |
||
474 | if (re && re[re.length - 1] != "$") |
||
475 | re = re + "$"; |
||
476 | } else { |
||
477 | re = re + guard; |
||
478 | if (re && re[0] != "^") |
||
479 | re = "^" + re; |
||
480 | } |
||
481 | return new RegExp(re); |
||
482 | } |
||
483 | |||
484 | function addSnippet(s) { |
||
485 | if (!s.scope) |
||
486 | s.scope = scope || "_"; |
||
487 | scope = s.scope; |
||
488 | if (!snippetMap[scope]) { |
||
489 | snippetMap[scope] = []; |
||
490 | snippetNameMap[scope] = {}; |
||
491 | } |
||
492 | |||
493 | var map = snippetNameMap[scope]; |
||
494 | if (s.name) { |
||
495 | var old = map[s.name]; |
||
496 | if (old) |
||
497 | self.unregister(old); |
||
498 | map[s.name] = s; |
||
499 | } |
||
500 | snippetMap[scope].push(s); |
||
501 | |||
502 | if (s.tabTrigger && !s.trigger) { |
||
503 | if (!s.guard && /^\w/.test(s.tabTrigger)) |
||
504 | s.guard = "\\b"; |
||
505 | s.trigger = lang.escapeRegExp(s.tabTrigger); |
||
506 | } |
||
507 | |||
508 | if (!s.trigger && !s.guard && !s.endTrigger && !s.endGuard) |
||
509 | return; |
||
510 | |||
511 | s.startRe = guardedRegexp(s.trigger, s.guard, true); |
||
512 | s.triggerRe = new RegExp(s.trigger, "", true); |
||
513 | |||
514 | s.endRe = guardedRegexp(s.endTrigger, s.endGuard, true); |
||
515 | s.endTriggerRe = new RegExp(s.endTrigger, "", true); |
||
516 | } |
||
517 | |||
518 | if (snippets && snippets.content) |
||
519 | addSnippet(snippets); |
||
520 | else if (Array.isArray(snippets)) |
||
521 | snippets.forEach(addSnippet); |
||
522 | |||
523 | this._signal("registerSnippets", {scope: scope}); |
||
524 | }; |
||
525 | this.unregister = function(snippets, scope) { |
||
526 | var snippetMap = this.snippetMap; |
||
527 | var snippetNameMap = this.snippetNameMap; |
||
528 | |||
529 | function removeSnippet(s) { |
||
530 | var nameMap = snippetNameMap[s.scope||scope]; |
||
531 | if (nameMap && nameMap[s.name]) { |
||
532 | delete nameMap[s.name]; |
||
533 | var map = snippetMap[s.scope||scope]; |
||
534 | var i = map && map.indexOf(s); |
||
535 | if (i >= 0) |
||
536 | map.splice(i, 1); |
||
537 | } |
||
538 | } |
||
539 | if (snippets.content) |
||
540 | removeSnippet(snippets); |
||
541 | else if (Array.isArray(snippets)) |
||
542 | snippets.forEach(removeSnippet); |
||
543 | }; |
||
544 | this.parseSnippetFile = function(str) { |
||
545 | str = str.replace(/\r/g, ""); |
||
546 | var list = [], snippet = {}; |
||
547 | var re = /^#.*|^({[\s\S]*})\s*$|^(\S+) (.*)$|^((?:\n*\t.*)+)/gm; |
||
548 | var m; |
||
549 | while (m = re.exec(str)) { |
||
550 | if (m[1]) { |
||
551 | try { |
||
552 | snippet = JSON.parse(m[1]); |
||
553 | list.push(snippet); |
||
554 | } catch (e) {} |
||
555 | } if (m[4]) { |
||
556 | snippet.content = m[4].replace(/^\t/gm, ""); |
||
557 | list.push(snippet); |
||
558 | snippet = {}; |
||
559 | } else { |
||
560 | var key = m[2], val = m[3]; |
||
561 | if (key == "regex") { |
||
562 | var guardRe = /\/((?:[^\/\\]|\\.)*)|$/g; |
||
563 | snippet.guard = guardRe.exec(val)[1]; |
||
564 | snippet.trigger = guardRe.exec(val)[1]; |
||
565 | snippet.endTrigger = guardRe.exec(val)[1]; |
||
566 | snippet.endGuard = guardRe.exec(val)[1]; |
||
567 | } else if (key == "snippet") { |
||
568 | snippet.tabTrigger = val.match(/^\S*/)[0]; |
||
569 | if (!snippet.name) |
||
570 | snippet.name = val; |
||
571 | } else { |
||
572 | snippet[key] = val; |
||
573 | } |
||
574 | } |
||
575 | } |
||
576 | return list; |
||
577 | }; |
||
578 | this.getSnippetByName = function(name, editor) { |
||
579 | var snippetMap = this.snippetNameMap; |
||
580 | var snippet; |
||
581 | this.getActiveScopes(editor).some(function(scope) { |
||
582 | var snippets = snippetMap[scope]; |
||
583 | if (snippets) |
||
584 | snippet = snippets[name]; |
||
585 | return !!snippet; |
||
586 | }, this); |
||
587 | return snippet; |
||
588 | }; |
||
589 | |||
590 | }).call(SnippetManager.prototype); |
||
591 | |||
592 | |||
593 | var TabstopManager = function(editor) { |
||
594 | if (editor.tabstopManager) |
||
595 | return editor.tabstopManager; |
||
596 | editor.tabstopManager = this; |
||
597 | this.$onChange = this.onChange.bind(this); |
||
598 | this.$onChangeSelection = lang.delayedCall(this.onChangeSelection.bind(this)).schedule; |
||
599 | this.$onChangeSession = this.onChangeSession.bind(this); |
||
600 | this.$onAfterExec = this.onAfterExec.bind(this); |
||
601 | this.attach(editor); |
||
602 | }; |
||
603 | (function() { |
||
604 | this.attach = function(editor) { |
||
605 | this.index = 0; |
||
606 | this.ranges = []; |
||
607 | this.tabstops = []; |
||
608 | this.$openTabstops = null; |
||
609 | this.selectedTabstop = null; |
||
610 | |||
611 | this.editor = editor; |
||
612 | this.editor.on("change", this.$onChange); |
||
613 | this.editor.on("changeSelection", this.$onChangeSelection); |
||
614 | this.editor.on("changeSession", this.$onChangeSession); |
||
615 | this.editor.commands.on("afterExec", this.$onAfterExec); |
||
616 | this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler); |
||
617 | }; |
||
618 | this.detach = function() { |
||
619 | this.tabstops.forEach(this.removeTabstopMarkers, this); |
||
620 | this.ranges = null; |
||
621 | this.tabstops = null; |
||
622 | this.selectedTabstop = null; |
||
623 | this.editor.removeListener("change", this.$onChange); |
||
624 | this.editor.removeListener("changeSelection", this.$onChangeSelection); |
||
625 | this.editor.removeListener("changeSession", this.$onChangeSession); |
||
626 | this.editor.commands.removeListener("afterExec", this.$onAfterExec); |
||
627 | this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler); |
||
628 | this.editor.tabstopManager = null; |
||
629 | this.editor = null; |
||
630 | }; |
||
631 | |||
632 | this.onChange = function(delta) { |
||
633 | var changeRange = delta; |
||
634 | var isRemove = delta.action[0] == "r"; |
||
635 | var start = delta.start; |
||
636 | var end = delta.end; |
||
637 | var startRow = start.row; |
||
638 | var endRow = end.row; |
||
639 | var lineDif = endRow - startRow; |
||
640 | var colDiff = end.column - start.column; |
||
641 | |||
642 | if (isRemove) { |
||
643 | lineDif = -lineDif; |
||
644 | colDiff = -colDiff; |
||
645 | } |
||
646 | if (!this.$inChange && isRemove) { |
||
647 | var ts = this.selectedTabstop; |
||
648 | var changedOutside = ts && !ts.some(function(r) { |
||
649 | return comparePoints(r.start, start) <= 0 && comparePoints(r.end, end) >= 0; |
||
650 | }); |
||
651 | if (changedOutside) |
||
652 | return this.detach(); |
||
653 | } |
||
654 | var ranges = this.ranges; |
||
655 | for (var i = 0; i < ranges.length; i++) { |
||
656 | var r = ranges[i]; |
||
657 | if (r.end.row < start.row) |
||
658 | continue; |
||
659 | |||
660 | if (isRemove && comparePoints(start, r.start) < 0 && comparePoints(end, r.end) > 0) { |
||
661 | this.removeRange(r); |
||
662 | i--; |
||
663 | continue; |
||
664 | } |
||
665 | |||
666 | if (r.start.row == startRow && r.start.column > start.column) |
||
667 | r.start.column += colDiff; |
||
668 | if (r.end.row == startRow && r.end.column >= start.column) |
||
669 | r.end.column += colDiff; |
||
670 | if (r.start.row >= startRow) |
||
671 | r.start.row += lineDif; |
||
672 | if (r.end.row >= startRow) |
||
673 | r.end.row += lineDif; |
||
674 | |||
675 | if (comparePoints(r.start, r.end) > 0) |
||
676 | this.removeRange(r); |
||
677 | } |
||
678 | if (!ranges.length) |
||
679 | this.detach(); |
||
680 | }; |
||
681 | this.updateLinkedFields = function() { |
||
682 | var ts = this.selectedTabstop; |
||
683 | if (!ts || !ts.hasLinkedRanges) |
||
684 | return; |
||
685 | this.$inChange = true; |
||
686 | var session = this.editor.session; |
||
687 | var text = session.getTextRange(ts.firstNonLinked); |
||
688 | for (var i = ts.length; i--;) { |
||
689 | var range = ts[i]; |
||
690 | if (!range.linked) |
||
691 | continue; |
||
692 | var fmt = exports.snippetManager.tmStrFormat(text, range.original); |
||
693 | session.replace(range, fmt); |
||
694 | } |
||
695 | this.$inChange = false; |
||
696 | }; |
||
697 | this.onAfterExec = function(e) { |
||
698 | if (e.command && !e.command.readOnly) |
||
699 | this.updateLinkedFields(); |
||
700 | }; |
||
701 | this.onChangeSelection = function() { |
||
702 | if (!this.editor) |
||
703 | return; |
||
704 | var lead = this.editor.selection.lead; |
||
705 | var anchor = this.editor.selection.anchor; |
||
706 | var isEmpty = this.editor.selection.isEmpty(); |
||
707 | for (var i = this.ranges.length; i--;) { |
||
708 | if (this.ranges[i].linked) |
||
709 | continue; |
||
710 | var containsLead = this.ranges[i].contains(lead.row, lead.column); |
||
711 | var containsAnchor = isEmpty || this.ranges[i].contains(anchor.row, anchor.column); |
||
712 | if (containsLead && containsAnchor) |
||
713 | return; |
||
714 | } |
||
715 | this.detach(); |
||
716 | }; |
||
717 | this.onChangeSession = function() { |
||
718 | this.detach(); |
||
719 | }; |
||
720 | this.tabNext = function(dir) { |
||
721 | var max = this.tabstops.length; |
||
722 | var index = this.index + (dir || 1); |
||
723 | index = Math.min(Math.max(index, 1), max); |
||
724 | if (index == max) |
||
725 | index = 0; |
||
726 | this.selectTabstop(index); |
||
727 | if (index === 0) |
||
728 | this.detach(); |
||
729 | }; |
||
730 | this.selectTabstop = function(index) { |
||
731 | this.$openTabstops = null; |
||
732 | var ts = this.tabstops[this.index]; |
||
733 | if (ts) |
||
734 | this.addTabstopMarkers(ts); |
||
735 | this.index = index; |
||
736 | ts = this.tabstops[this.index]; |
||
737 | if (!ts || !ts.length) |
||
738 | return; |
||
739 | |||
740 | this.selectedTabstop = ts; |
||
741 | if (!this.editor.inVirtualSelectionMode) { |
||
742 | var sel = this.editor.multiSelect; |
||
743 | sel.toSingleRange(ts.firstNonLinked.clone()); |
||
744 | for (var i = ts.length; i--;) { |
||
745 | if (ts.hasLinkedRanges && ts[i].linked) |
||
746 | continue; |
||
747 | sel.addRange(ts[i].clone(), true); |
||
748 | } |
||
749 | if (sel.ranges[0]) |
||
750 | sel.addRange(sel.ranges[0].clone()); |
||
751 | } else { |
||
752 | this.editor.selection.setRange(ts.firstNonLinked); |
||
753 | } |
||
754 | |||
755 | this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler); |
||
756 | }; |
||
757 | this.addTabstops = function(tabstops, start, end) { |
||
758 | if (!this.$openTabstops) |
||
759 | this.$openTabstops = []; |
||
760 | if (!tabstops[0]) { |
||
761 | var p = Range.fromPoints(end, end); |
||
762 | moveRelative(p.start, start); |
||
763 | moveRelative(p.end, start); |
||
764 | tabstops[0] = [p]; |
||
765 | tabstops[0].index = 0; |
||
766 | } |
||
767 | |||
768 | var i = this.index; |
||
769 | var arg = [i + 1, 0]; |
||
770 | var ranges = this.ranges; |
||
771 | tabstops.forEach(function(ts, index) { |
||
772 | var dest = this.$openTabstops[index] || ts; |
||
773 | |||
774 | for (var i = ts.length; i--;) { |
||
775 | var p = ts[i]; |
||
776 | var range = Range.fromPoints(p.start, p.end || p.start); |
||
777 | movePoint(range.start, start); |
||
778 | movePoint(range.end, start); |
||
779 | range.original = p; |
||
780 | range.tabstop = dest; |
||
781 | ranges.push(range); |
||
782 | if (dest != ts) |
||
783 | dest.unshift(range); |
||
784 | else |
||
785 | dest[i] = range; |
||
786 | if (p.fmtString) { |
||
787 | range.linked = true; |
||
788 | dest.hasLinkedRanges = true; |
||
789 | } else if (!dest.firstNonLinked) |
||
790 | dest.firstNonLinked = range; |
||
791 | } |
||
792 | if (!dest.firstNonLinked) |
||
793 | dest.hasLinkedRanges = false; |
||
794 | if (dest === ts) { |
||
795 | arg.push(dest); |
||
796 | this.$openTabstops[index] = dest; |
||
797 | } |
||
798 | this.addTabstopMarkers(dest); |
||
799 | }, this); |
||
800 | |||
801 | if (arg.length > 2) { |
||
802 | if (this.tabstops.length) |
||
803 | arg.push(arg.splice(2, 1)[0]); |
||
804 | this.tabstops.splice.apply(this.tabstops, arg); |
||
805 | } |
||
806 | }; |
||
807 | |||
808 | this.addTabstopMarkers = function(ts) { |
||
809 | var session = this.editor.session; |
||
810 | ts.forEach(function(range) { |
||
811 | if (!range.markerId) |
||
812 | range.markerId = session.addMarker(range, "ace_snippet-marker", "text"); |
||
813 | }); |
||
814 | }; |
||
815 | this.removeTabstopMarkers = function(ts) { |
||
816 | var session = this.editor.session; |
||
817 | ts.forEach(function(range) { |
||
818 | session.removeMarker(range.markerId); |
||
819 | range.markerId = null; |
||
820 | }); |
||
821 | }; |
||
822 | this.removeRange = function(range) { |
||
823 | var i = range.tabstop.indexOf(range); |
||
824 | range.tabstop.splice(i, 1); |
||
825 | i = this.ranges.indexOf(range); |
||
826 | this.ranges.splice(i, 1); |
||
827 | this.editor.session.removeMarker(range.markerId); |
||
828 | if (!range.tabstop.length) { |
||
829 | i = this.tabstops.indexOf(range.tabstop); |
||
830 | if (i != -1) |
||
831 | this.tabstops.splice(i, 1); |
||
832 | if (!this.tabstops.length) |
||
833 | this.detach(); |
||
834 | } |
||
835 | }; |
||
836 | |||
837 | this.keyboardHandler = new HashHandler(); |
||
838 | this.keyboardHandler.bindKeys({ |
||
839 | "Tab": function(ed) { |
||
840 | if (exports.snippetManager && exports.snippetManager.expandWithTab(ed)) { |
||
841 | return; |
||
842 | } |
||
843 | |||
844 | ed.tabstopManager.tabNext(1); |
||
845 | }, |
||
846 | "Shift-Tab": function(ed) { |
||
847 | ed.tabstopManager.tabNext(-1); |
||
848 | }, |
||
849 | "Esc": function(ed) { |
||
850 | ed.tabstopManager.detach(); |
||
851 | }, |
||
852 | "Return": function(ed) { |
||
853 | return false; |
||
854 | } |
||
855 | }); |
||
856 | }).call(TabstopManager.prototype); |
||
857 | |||
858 | |||
859 | |||
860 | var changeTracker = {}; |
||
861 | changeTracker.onChange = Anchor.prototype.onChange; |
||
862 | changeTracker.setPosition = function(row, column) { |
||
863 | this.pos.row = row; |
||
864 | this.pos.column = column; |
||
865 | }; |
||
866 | changeTracker.update = function(pos, delta, $insertRight) { |
||
867 | this.$insertRight = $insertRight; |
||
868 | this.pos = pos; |
||
869 | this.onChange(delta); |
||
870 | }; |
||
871 | |||
872 | var movePoint = function(point, diff) { |
||
873 | if (point.row == 0) |
||
874 | point.column += diff.column; |
||
875 | point.row += diff.row; |
||
876 | }; |
||
877 | |||
878 | var moveRelative = function(point, start) { |
||
879 | if (point.row == start.row) |
||
880 | point.column -= start.column; |
||
881 | point.row -= start.row; |
||
882 | }; |
||
883 | |||
884 | |||
885 | require("./lib/dom").importCssString("\ |
||
886 | .ace_snippet-marker {\ |
||
887 | -moz-box-sizing: border-box;\ |
||
888 | box-sizing: border-box;\ |
||
889 | background: rgba(194, 193, 208, 0.09);\ |
||
890 | border: 1px dotted rgba(211, 208, 235, 0.62);\ |
||
891 | position: absolute;\ |
||
892 | }"); |
||
893 | |||
894 | exports.snippetManager = new SnippetManager(); |
||
895 | |||
896 | |||
897 | var Editor = require("./editor").Editor; |
||
898 | (function() { |
||
899 | this.insertSnippet = function(content, options) { |
||
900 | return exports.snippetManager.insertSnippet(this, content, options); |
||
901 | }; |
||
902 | this.expandSnippet = function(options) { |
||
903 | return exports.snippetManager.expandWithTab(this, options); |
||
904 | }; |
||
905 | }).call(Editor.prototype); |
||
906 | |||
907 | }); |
||
908 | |||
909 | ace.define("ace/ext/emmet",["require","exports","module","ace/keyboard/hash_handler","ace/editor","ace/snippets","ace/range","resources","resources","tabStops","resources","utils","actions","ace/config","ace/config"], function(require, exports, module) { |
||
910 | "use strict"; |
||
911 | var HashHandler = require("ace/keyboard/hash_handler").HashHandler; |
||
912 | var Editor = require("ace/editor").Editor; |
||
913 | var snippetManager = require("ace/snippets").snippetManager; |
||
914 | var Range = require("ace/range").Range; |
||
915 | var emmet, emmetPath; |
||
916 | function AceEmmetEditor() {} |
||
917 | |||
918 | AceEmmetEditor.prototype = { |
||
919 | setupContext: function(editor) { |
||
920 | this.ace = editor; |
||
921 | this.indentation = editor.session.getTabString(); |
||
922 | if (!emmet) |
||
923 | emmet = window.emmet; |
||
924 | var resources = emmet.resources || emmet.require("resources"); |
||
925 | resources.setVariable("indentation", this.indentation); |
||
926 | this.$syntax = null; |
||
927 | this.$syntax = this.getSyntax(); |
||
928 | }, |
||
929 | getSelectionRange: function() { |
||
930 | var range = this.ace.getSelectionRange(); |
||
931 | var doc = this.ace.session.doc; |
||
932 | return { |
||
933 | start: doc.positionToIndex(range.start), |
||
934 | end: doc.positionToIndex(range.end) |
||
935 | }; |
||
936 | }, |
||
937 | createSelection: function(start, end) { |
||
938 | var doc = this.ace.session.doc; |
||
939 | this.ace.selection.setRange({ |
||
940 | start: doc.indexToPosition(start), |
||
941 | end: doc.indexToPosition(end) |
||
942 | }); |
||
943 | }, |
||
944 | getCurrentLineRange: function() { |
||
945 | var ace = this.ace; |
||
946 | var row = ace.getCursorPosition().row; |
||
947 | var lineLength = ace.session.getLine(row).length; |
||
948 | var index = ace.session.doc.positionToIndex({row: row, column: 0}); |
||
949 | return { |
||
950 | start: index, |
||
951 | end: index + lineLength |
||
952 | }; |
||
953 | }, |
||
954 | getCaretPos: function(){ |
||
955 | var pos = this.ace.getCursorPosition(); |
||
956 | return this.ace.session.doc.positionToIndex(pos); |
||
957 | }, |
||
958 | setCaretPos: function(index){ |
||
959 | var pos = this.ace.session.doc.indexToPosition(index); |
||
960 | this.ace.selection.moveToPosition(pos); |
||
961 | }, |
||
962 | getCurrentLine: function() { |
||
963 | var row = this.ace.getCursorPosition().row; |
||
964 | return this.ace.session.getLine(row); |
||
965 | }, |
||
966 | replaceContent: function(value, start, end, noIndent) { |
||
967 | if (end == null) |
||
968 | end = start == null ? this.getContent().length : start; |
||
969 | if (start == null) |
||
970 | start = 0; |
||
971 | |||
972 | var editor = this.ace; |
||
973 | var doc = editor.session.doc; |
||
974 | var range = Range.fromPoints(doc.indexToPosition(start), doc.indexToPosition(end)); |
||
975 | editor.session.remove(range); |
||
976 | |||
977 | range.end = range.start; |
||
978 | |||
979 | value = this.$updateTabstops(value); |
||
980 | snippetManager.insertSnippet(editor, value); |
||
981 | }, |
||
982 | getContent: function(){ |
||
983 | return this.ace.getValue(); |
||
984 | }, |
||
985 | getSyntax: function() { |
||
986 | if (this.$syntax) |
||
987 | return this.$syntax; |
||
988 | var syntax = this.ace.session.$modeId.split("/").pop(); |
||
989 | if (syntax == "html" || syntax == "php") { |
||
990 | var cursor = this.ace.getCursorPosition(); |
||
991 | var state = this.ace.session.getState(cursor.row); |
||
992 | if (typeof state != "string") |
||
993 | state = state[0]; |
||
994 | if (state) { |
||
995 | state = state.split("-"); |
||
996 | if (state.length > 1) |
||
997 | syntax = state[0]; |
||
998 | else if (syntax == "php") |
||
999 | syntax = "html"; |
||
1000 | } |
||
1001 | } |
||
1002 | return syntax; |
||
1003 | }, |
||
1004 | getProfileName: function() { |
||
1005 | var resources = emmet.resources || emmet.require("resources"); |
||
1006 | switch (this.getSyntax()) { |
||
1007 | case "css": return "css"; |
||
1008 | case "xml": |
||
1009 | case "xsl": |
||
1010 | return "xml"; |
||
1011 | case "html": |
||
1012 | var profile = resources.getVariable("profile"); |
||
1013 | if (!profile) |
||
1014 | profile = this.ace.session.getLines(0,2).join("").search(/]+XHTML/i) != -1 ? "xhtml": "html";!DOCTYPE[^> |
||
1015 | return profile;!DOCTYPE[^> |
||
1016 | default:!DOCTYPE[^> |
||
1017 | var mode = this.ace.session.$mode;!DOCTYPE[^> |
||
1018 | return mode.emmetConfig && mode.emmetConfig.profile || "xhtml";!DOCTYPE[^> |
||
1019 | }!DOCTYPE[^> |
||
1020 | },!DOCTYPE[^> |
||
1021 | prompt: function(title) {!DOCTYPE[^> |
||
1022 | return prompt(title);!DOCTYPE[^> |
||
1023 | },!DOCTYPE[^> |
||
1024 | getSelection: function() {!DOCTYPE[^> |
||
1025 | return this.ace.session.getTextRange();!DOCTYPE[^> |
||
1026 | },!DOCTYPE[^> |
||
1027 | getFilePath: function() {!DOCTYPE[^> |
||
1028 | return "";!DOCTYPE[^> |
||
1029 | },!DOCTYPE[^> |
||
1030 | $updateTabstops: function(value) {!DOCTYPE[^> |
||
1031 | var base = 1000;!DOCTYPE[^> |
||
1032 | var zeroBase = 0;!DOCTYPE[^> |
||
1033 | var lastZero = null;!DOCTYPE[^> |
||
1034 | var ts = emmet.tabStops || emmet.require('tabStops');!DOCTYPE[^> |
||
1035 | var resources = emmet.resources || emmet.require("resources");!DOCTYPE[^> |
||
1036 | var settings = resources.getVocabulary("user");!DOCTYPE[^> |
||
1037 | var tabstopOptions = {!DOCTYPE[^> |
||
1038 | tabstop: function(data) {!DOCTYPE[^> |
||
1039 | var group = parseInt(data.group, 10);!DOCTYPE[^> |
||
1040 | var isZero = group === 0;!DOCTYPE[^> |
||
1041 | if (isZero)!DOCTYPE[^> |
||
1042 | group = ++zeroBase;!DOCTYPE[^> |
||
1043 | else!DOCTYPE[^> |
||
1044 | group += base;!DOCTYPE[^> |
||
1045 | |||
1046 | var placeholder = data.placeholder;!DOCTYPE[^> |
||
1047 | if (placeholder) {!DOCTYPE[^> |
||
1048 | placeholder = ts.processText(placeholder, tabstopOptions);!DOCTYPE[^> |
||
1049 | }!DOCTYPE[^> |
||
1050 | |||
1051 | var result = '${' + group + (placeholder ? ':' + placeholder : '') + '}';!DOCTYPE[^> |
||
1052 | |||
1053 | if (isZero) {!DOCTYPE[^> |
||
1054 | lastZero = [data.start, result];!DOCTYPE[^> |
||
1055 | }!DOCTYPE[^> |
||
1056 | |||
1057 | return result;!DOCTYPE[^> |
||
1058 | },!DOCTYPE[^> |
||
1059 | escape: function(ch) {!DOCTYPE[^> |
||
1060 | if (ch == '$') return '\\$';!DOCTYPE[^> |
||
1061 | if (ch == '\\') return '\\\\';!DOCTYPE[^> |
||
1062 | return ch;!DOCTYPE[^> |
||
1063 | }!DOCTYPE[^> |
||
1064 | };!DOCTYPE[^> |
||
1065 | |||
1066 | value = ts.processText(value, tabstopOptions);!DOCTYPE[^> |
||
1067 | |||
1068 | if (settings.variables['insert_final_tabstop'] && !/\$\{0\}$/.test(value)) {!DOCTYPE[^> |
||
1069 | value += '${0}';!DOCTYPE[^> |
||
1070 | } else if (lastZero) {!DOCTYPE[^> |
||
1071 | var common = emmet.utils ? emmet.utils.common : emmet.require('utils');!DOCTYPE[^> |
||
1072 | value = common.replaceSubstring(value, '${0}', lastZero[0], lastZero[1]);!DOCTYPE[^> |
||
1073 | }!DOCTYPE[^> |
||
1074 | |||
1075 | return value;!DOCTYPE[^> |
||
1076 | }!DOCTYPE[^> |
||
1077 | };!DOCTYPE[^> |
||
1078 | |||
1079 | |||
1080 | var keymap = {!DOCTYPE[^> |
||
1081 | expand_abbreviation: {"mac": "ctrl+alt+e", "win": "alt+e"},!DOCTYPE[^> |
||
1082 | match_pair_outward: {"mac": "ctrl+d", "win": "ctrl+,"},!DOCTYPE[^> |
||
1083 | match_pair_inward: {"mac": "ctrl+j", "win": "ctrl+shift+0"},!DOCTYPE[^> |
||
1084 | matching_pair: {"mac": "ctrl+alt+j", "win": "alt+j"},!DOCTYPE[^> |
||
1085 | next_edit_point: "alt+right",!DOCTYPE[^> |
||
1086 | prev_edit_point: "alt+left",!DOCTYPE[^> |
||
1087 | toggle_comment: {"mac": "command+/", "win": "ctrl+/"},!DOCTYPE[^> |
||
1088 | split_join_tag: {"mac": "shift+command+'", "win": "shift+ctrl+`"},!DOCTYPE[^> |
||
1089 | remove_tag: {"mac": "command+'", "win": "shift+ctrl+;"},!DOCTYPE[^> |
||
1090 | evaluate_math_expression: {"mac": "shift+command+y", "win": "shift+ctrl+y"},!DOCTYPE[^> |
||
1091 | increment_number_by_1: "ctrl+up",!DOCTYPE[^> |
||
1092 | decrement_number_by_1: "ctrl+down",!DOCTYPE[^> |
||
1093 | increment_number_by_01: "alt+up",!DOCTYPE[^> |
||
1094 | decrement_number_by_01: "alt+down",!DOCTYPE[^> |
||
1095 | increment_number_by_10: {"mac": "alt+command+up", "win": "shift+alt+up"},!DOCTYPE[^> |
||
1096 | decrement_number_by_10: {"mac": "alt+command+down", "win": "shift+alt+down"},!DOCTYPE[^> |
||
1097 | select_next_item: {"mac": "shift+command+.", "win": "shift+ctrl+."},!DOCTYPE[^> |
||
1098 | select_previous_item: {"mac": "shift+command+,", "win": "shift+ctrl+,"},!DOCTYPE[^> |
||
1099 | reflect_css_value: {"mac": "shift+command+r", "win": "shift+ctrl+r"},!DOCTYPE[^> |
||
1100 | |||
1101 | encode_decode_data_url: {"mac": "shift+ctrl+d", "win": "ctrl+'"},!DOCTYPE[^> |
||
1102 | expand_abbreviation_with_tab: "Tab",!DOCTYPE[^> |
||
1103 | wrap_with_abbreviation: {"mac": "shift+ctrl+a", "win": "shift+ctrl+a"}!DOCTYPE[^> |
||
1104 | };!DOCTYPE[^> |
||
1105 | |||
1106 | var editorProxy = new AceEmmetEditor();!DOCTYPE[^> |
||
1107 | exports.commands = new HashHandler();!DOCTYPE[^> |
||
1108 | exports.runEmmetCommand = function runEmmetCommand(editor) {!DOCTYPE[^> |
||
1109 | try {!DOCTYPE[^> |
||
1110 | editorProxy.setupContext(editor);!DOCTYPE[^> |
||
1111 | var actions = emmet.actions || emmet.require("actions");!DOCTYPE[^> |
||
1112 | |||
1113 | if (this.action == "expand_abbreviation_with_tab") {!DOCTYPE[^> |
||
1114 | if (!editor.selection.isEmpty())!DOCTYPE[^> |
||
1115 | return false;!DOCTYPE[^> |
||
1116 | var pos = editor.selection.lead;!DOCTYPE[^> |
||
1117 | var token = editor.session.getTokenAt(pos.row, pos.column);!DOCTYPE[^> |
||
1118 | if (token && /\btag\b/.test(token.type))!DOCTYPE[^> |
||
1119 | return false;!DOCTYPE[^> |
||
1120 | }!DOCTYPE[^> |
||
1121 | |||
1122 | if (this.action == "wrap_with_abbreviation") {!DOCTYPE[^> |
||
1123 | return setTimeout(function() {!DOCTYPE[^> |
||
1124 | actions.run("wrap_with_abbreviation", editorProxy);!DOCTYPE[^> |
||
1125 | }, 0);!DOCTYPE[^> |
||
1126 | }!DOCTYPE[^> |
||
1127 | |||
1128 | var result = actions.run(this.action, editorProxy);!DOCTYPE[^> |
||
1129 | } catch(e) {!DOCTYPE[^> |
||
1130 | if (!emmet) {!DOCTYPE[^> |
||
1131 | load(runEmmetCommand.bind(this, editor));!DOCTYPE[^> |
||
1132 | return true;!DOCTYPE[^> |
||
1133 | }!DOCTYPE[^> |
||
1134 | editor._signal("changeStatus", typeof e == "string" ? e : e.message);!DOCTYPE[^> |
||
1135 | console.log(e);!DOCTYPE[^> |
||
1136 | result = false;!DOCTYPE[^> |
||
1137 | }!DOCTYPE[^> |
||
1138 | return result;!DOCTYPE[^> |
||
1139 | };!DOCTYPE[^> |
||
1140 | |||
1141 | for (var command in keymap) {!DOCTYPE[^> |
||
1142 | exports.commands.addCommand({!DOCTYPE[^> |
||
1143 | name: "emmet:" + command,!DOCTYPE[^> |
||
1144 | action: command,!DOCTYPE[^> |
||
1145 | bindKey: keymap[command],!DOCTYPE[^> |
||
1146 | exec: exports.runEmmetCommand,!DOCTYPE[^> |
||
1147 | multiSelectAction: "forEach"!DOCTYPE[^> |
||
1148 | });!DOCTYPE[^> |
||
1149 | }!DOCTYPE[^> |
||
1150 | |||
1151 | exports.updateCommands = function(editor, enabled) {!DOCTYPE[^> |
||
1152 | if (enabled) {!DOCTYPE[^> |
||
1153 | editor.keyBinding.addKeyboardHandler(exports.commands);!DOCTYPE[^> |
||
1154 | } else {!DOCTYPE[^> |
||
1155 | editor.keyBinding.removeKeyboardHandler(exports.commands);!DOCTYPE[^> |
||
1156 | }!DOCTYPE[^> |
||
1157 | };!DOCTYPE[^> |
||
1158 | |||
1159 | exports.isSupportedMode = function(mode) {!DOCTYPE[^> |
||
1160 | if (!mode) return false;!DOCTYPE[^> |
||
1161 | if (mode.emmetConfig) return true;!DOCTYPE[^> |
||
1162 | var id = mode.$id || mode;!DOCTYPE[^> |
||
1163 | return /css|less|scss|sass|stylus|html|php|twig|ejs|handlebars/.test(id);!DOCTYPE[^> |
||
1164 | };!DOCTYPE[^> |
||
1165 | |||
1166 | exports.isAvailable = function(editor, command) {!DOCTYPE[^> |
||
1167 | if (/(evaluate_math_expression|expand_abbreviation)$/.test(command))!DOCTYPE[^> |
||
1168 | return true;!DOCTYPE[^> |
||
1169 | var mode = editor.session.$mode;!DOCTYPE[^> |
||
1170 | var isSupported = exports.isSupportedMode(mode);!DOCTYPE[^> |
||
1171 | if (isSupported && mode.$modes) {!DOCTYPE[^> |
||
1172 | try {!DOCTYPE[^> |
||
1173 | editorProxy.setupContext(editor);!DOCTYPE[^> |
||
1174 | if (/js|php/.test(editorProxy.getSyntax()))!DOCTYPE[^> |
||
1175 | isSupported = false;!DOCTYPE[^> |
||
1176 | } catch(e) {}!DOCTYPE[^> |
||
1177 | }!DOCTYPE[^> |
||
1178 | return isSupported;!DOCTYPE[^> |
||
1179 | }!DOCTYPE[^> |
||
1180 | |||
1181 | var onChangeMode = function(e, target) {!DOCTYPE[^> |
||
1182 | var editor = target;!DOCTYPE[^> |
||
1183 | if (!editor)!DOCTYPE[^> |
||
1184 | return;!DOCTYPE[^> |
||
1185 | var enabled = exports.isSupportedMode(editor.session.$mode);!DOCTYPE[^> |
||
1186 | if (e.enableEmmet === false)!DOCTYPE[^> |
||
1187 | enabled = false;!DOCTYPE[^> |
||
1188 | if (enabled)!DOCTYPE[^> |
||
1189 | load();!DOCTYPE[^> |
||
1190 | exports.updateCommands(editor, enabled);!DOCTYPE[^> |
||
1191 | };!DOCTYPE[^> |
||
1192 | |||
1193 | var load = function(cb) {!DOCTYPE[^> |
||
1194 | if (typeof emmetPath == "string") {!DOCTYPE[^> |
||
1195 | require("ace/config").loadModule(emmetPath, function() {!DOCTYPE[^> |
||
1196 | emmetPath = null;!DOCTYPE[^> |
||
1197 | cb && cb();!DOCTYPE[^> |
||
1198 | });!DOCTYPE[^> |
||
1199 | }!DOCTYPE[^> |
||
1200 | };!DOCTYPE[^> |
||
1201 | |||
1202 | exports.AceEmmetEditor = AceEmmetEditor;!DOCTYPE[^> |
||
1203 | require("ace/config").defineOptions(Editor.prototype, "editor", {!DOCTYPE[^> |
||
1204 | enableEmmet: {!DOCTYPE[^> |
||
1205 | set: function(val) {!DOCTYPE[^> |
||
1206 | this[val ? "on" : "removeListener"]("changeMode", onChangeMode);!DOCTYPE[^> |
||
1207 | onChangeMode({enableEmmet: !!val}, this);!DOCTYPE[^> |
||
1208 | },!DOCTYPE[^> |
||
1209 | value: true!DOCTYPE[^> |
||
1210 | }!DOCTYPE[^> |
||
1211 | });!DOCTYPE[^> |
||
1212 | |||
1213 | exports.setCore = function(e) {!DOCTYPE[^> |
||
1214 | if (typeof e == "string")!DOCTYPE[^> |
||
1215 | emmetPath = e;!DOCTYPE[^> |
||
1216 | else!DOCTYPE[^> |
||
1217 | emmet = e;!DOCTYPE[^> |
||
1218 | };!DOCTYPE[^> |
||
1219 | });!DOCTYPE[^> |
||
1220 | (function() {!DOCTYPE[^> |
||
1221 | ace.require(["ace/ext/emmet"], function() {});!DOCTYPE[^> |
||
1222 | })();!DOCTYPE[^> |
||
1223 |