From 70b91d47c37c73f7c0945237b3d2cd0120153156 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Mon, 10 Nov 2014 07:18:35 -0500 Subject: [PATCH] feature(edit) ace v1.1.8 --- json/modules.json | 4 +- lib/client/edit/ace.js | 373 ++-- lib/client/edit/ext-beautify.js | 1 - lib/client/edit/ext-chromevox.js | 1 - lib/client/edit/ext-elastic_tabstops_lite.js | 1 - lib/client/edit/ext-emmet.js | 116 +- lib/client/edit/ext-keybinding_menu.js | 28 +- lib/client/edit/ext-language_tools.js | 118 +- lib/client/edit/ext-linking.js | 1 - lib/client/edit/ext-modelist.js | 5 +- lib/client/edit/ext-old_ie.js | 25 +- lib/client/edit/ext-searchbox.js | 25 +- lib/client/edit/ext-settings_menu.js | 11 +- lib/client/edit/ext-spellcheck.js | 1 - lib/client/edit/ext-split.js | 1 - lib/client/edit/ext-static_highlight.js | 1 - lib/client/edit/ext-statusbar.js | 6 +- lib/client/edit/ext-textarea.js | 1 - lib/client/edit/ext-themelist.js | 1 - lib/client/edit/ext-whitespace.js | 1 - lib/client/edit/keybinding-emacs.js | 211 +- lib/client/edit/mode-autohotkey.js | 2 +- lib/client/edit/mode-c_cpp.js | 46 +- lib/client/edit/mode-coffee.js | 2 +- lib/client/edit/mode-coldfusion.js | 86 +- lib/client/edit/mode-csharp.js | 22 +- lib/client/edit/mode-css.js | 4 +- lib/client/edit/mode-curly.js | 86 +- lib/client/edit/mode-d.js | 20 +- lib/client/edit/mode-dart.js | 46 +- lib/client/edit/mode-django.js | 86 +- lib/client/edit/mode-dockerfile.js | 6 +- lib/client/edit/mode-dot.js | 18 +- lib/client/edit/mode-ejs.js | 153 +- lib/client/edit/mode-forth.js | 2 +- lib/client/edit/mode-ftl.js | 30 +- lib/client/edit/mode-gitignore.js | 1 + lib/client/edit/mode-glsl.js | 46 +- lib/client/edit/mode-golang.js | 22 +- lib/client/edit/mode-groovy.js | 34 +- lib/client/edit/mode-haml.js | 67 +- lib/client/edit/mode-handlebars.js | 106 +- lib/client/edit/mode-haxe.js | 22 +- lib/client/edit/mode-html.js | 86 +- lib/client/edit/mode-html_ruby.js | 153 +- lib/client/edit/mode-jack.js | 4 +- lib/client/edit/mode-jade.js | 32 +- lib/client/edit/mode-java.js | 34 +- lib/client/edit/mode-javascript.js | 34 +- lib/client/edit/mode-json.js | 4 +- lib/client/edit/mode-jsoniq.js | 1882 +---------------- lib/client/edit/mode-jsp.js | 34 +- lib/client/edit/mode-jsx.js | 22 +- lib/client/edit/mode-less.js | 4 +- lib/client/edit/mode-liquid.js | 30 +- lib/client/edit/mode-logiql.js | 4 +- lib/client/edit/mode-lsl.js | 4 +- lib/client/edit/mode-luapage.js | 86 +- lib/client/edit/mode-markdown.js | 86 +- lib/client/edit/mode-mel.js | 4 +- lib/client/edit/mode-mysql.js | 18 +- lib/client/edit/mode-nix.js | 46 +- lib/client/edit/mode-objectivec.js | 42 +- lib/client/edit/mode-pgsql.js | 30 +- lib/client/edit/mode-php.js | 1170 +++++++++- lib/client/edit/mode-powershell.js | 4 +- lib/client/edit/mode-protobuf.js | 46 +- lib/client/edit/mode-rhtml.js | 86 +- lib/client/edit/mode-ruby.js | 71 +- lib/client/edit/mode-rust.js | 39 +- lib/client/edit/mode-scad.js | 22 +- lib/client/edit/mode-scala.js | 34 +- lib/client/edit/mode-scss.js | 4 +- lib/client/edit/mode-sh.js | 4 +- lib/client/edit/mode-sjs.js | 34 +- lib/client/edit/mode-smarty.js | 86 +- lib/client/edit/mode-soy_template.js | 88 +- lib/client/edit/mode-stylus.js | 5 +- lib/client/edit/mode-svg.js | 86 +- lib/client/edit/mode-textile.js | 1 + lib/client/edit/mode-twig.js | 86 +- lib/client/edit/mode-typescript.js | 34 +- lib/client/edit/mode-vala.js | 4 +- lib/client/edit/mode-velocity.js | 86 +- lib/client/edit/mode-xml.js | 52 +- lib/client/edit/mode-xquery.js | 1882 +---------------- lib/client/edit/theme-cobalt.js | 2 +- lib/client/edit/theme-idle_fingers.js | 2 +- .../edit/theme-tomorrow_night_bright.js | 4 +- lib/client/edit/worker-coffee.js | 20 +- lib/client/edit/worker-css.js | 20 +- lib/client/edit/worker-html.js | 20 +- lib/client/edit/worker-javascript.js | 20 +- lib/client/edit/worker-json.js | 23 +- lib/client/edit/worker-lua.js | 20 +- lib/client/edit/worker-php.js | 20 +- lib/client/edit/worker-xquery.js | 20 +- 97 files changed, 3808 insertions(+), 4765 deletions(-) diff --git a/json/modules.json b/json/modules.json index 977d9c54..d3ab77cb 100644 --- a/json/modules.json +++ b/json/modules.json @@ -22,8 +22,8 @@ "remote": "//cdn.socket.io/socket.io-{{ version }}.js" }, { "name": "ace", - "version": "1.1.7", - "date": "20.09.2014", + "version": "1.1.8", + "date": "08.11.14", "local": "/lib/client/edit/ace.js", "remote": "//cdn.jsdelivr.net/ace/{{ version }}/noconflict/ace.js" }, { diff --git a/lib/client/edit/ace.js b/lib/client/edit/ace.js index 73bcb27e..f6d4453e 100644 --- a/lib/client/edit/ace.js +++ b/lib/client/edit/ace.js @@ -3,7 +3,7 @@ * * Copyright (c) 2010, Ajax.org B.V. * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright @@ -14,7 +14,7 @@ * * Neither the name of Ajax.org B.V. nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -65,7 +65,7 @@ var _define = function(module, deps, payload) { _define.modules = {}; _define.payloads = {}; } - + _define.payloads[module] = payload; _define.modules[module] = null; }; @@ -160,7 +160,7 @@ var lookup = function(parentId, moduleName) { function exportAce(ns) { var require = function(module, callback) { return _require("", module, callback); - }; + }; var root = global; if (ns) { @@ -1324,6 +1324,9 @@ var Keys = (function() { } })(); + ret.KEY_MODS[0] = ""; + ret.KEY_MODS[-1] = "input"; + return ret; })(); oop.mixin(exports, Keys); @@ -1831,7 +1834,6 @@ exports.getMatchOffsets = function(string, regExp) { return matches; }; exports.deferredCall = function(fcn) { - var timer = null; var callback = function() { timer = null; @@ -1937,13 +1939,13 @@ var TextInput = function(parentNode, host) { var isSelectionEmpty = true; try { var isFocused = document.activeElement === text; } catch(e) {} - event.addListener(text, "blur", function() { - host.onBlur(); + event.addListener(text, "blur", function(e) { + host.onBlur(e); isFocused = false; }); - event.addListener(text, "focus", function() { + event.addListener(text, "focus", function(e) { isFocused = true; - host.onFocus(); + host.onFocus(e); resetSelection(); }); this.focus = function() { text.focus(); }; @@ -3966,8 +3968,16 @@ var KeyBinding = function(editor) { this.getKeyboardHandler = function() { return this.$handlers[this.$handlers.length - 1]; }; + + this.getStatusText = function() { + var data = this.$data; + var editor = data.editor; + return this.$handlers.map(function(h) { + return h.getStatusText && h.getStatusText(editor, data) || ""; + }).filter(Boolean).join(" "); + }; - this.$callKeyboardHandlers = function (hashId, keyString, keyCode, e) { + this.$callKeyboardHandlers = function(hashId, keyString, keyCode, e) { var toExecute; var success = false; var commands = this.$editor.commands; @@ -4859,7 +4869,7 @@ exports.Selection = Selection; ace.define("ace/tokenizer",["require","exports","module"], function(require, exports, module) { "use strict"; -var MAX_TOKEN_COUNT = 1000; +var MAX_TOKEN_COUNT = 2000; var Tokenizer = function(rules) { this.states = rules; @@ -4890,9 +4900,11 @@ var Tokenizer = function(rules) { if (rule.token.length == 1 || matchcount == 1) { rule.token = rule.token[0]; } else if (matchcount - 1 != rule.token.length) { - throw new Error("number of classes and regexp groups in '" + - rule.token + "'\n'" + rule.regex + "' doesn't match\n" - + (matchcount - 1) + "!=" + rule.token.length); + this.reportError("number of classes and regexp groups doesn't match", { + rule: rule, + groupCount: matchcount - 1 + }); + rule.token = rule.token[0]; } else { rule.tokenArray = rule.token; rule.token = null; @@ -5043,6 +5055,7 @@ var Tokenizer = function(rules) { var match, tokens = []; var lastIndex = 0; + var matchAttempts = 0; var token = {type: null, value: ""}; @@ -5083,7 +5096,7 @@ var Tokenizer = function(rules) { state = this.states[currentState]; if (!state) { - window.console && console.error && console.error(currentState, "doesn't exist"); + this.reportError("state doesn't exist", currentState); currentState = "start"; state = this.states[currentState]; } @@ -5096,7 +5109,7 @@ var Tokenizer = function(rules) { } if (value) { - if (typeof type == "string") { + if (typeof type === "string") { if ((!rule || rule.merge !== false) && token.type === type) { token.value += value; } else { @@ -5118,7 +5131,13 @@ var Tokenizer = function(rules) { lastIndex = index; - if (tokens.length > MAX_TOKEN_COUNT) { + if (matchAttempts++ > MAX_TOKEN_COUNT) { + if (matchAttempts > 2 * line.length) { + this.reportError("infinite loop with in ace tokenizer", { + startState: startState, + line: line + }); + } while (lastIndex < line.length) { if (token.type) tokens.push(token); @@ -5145,7 +5164,14 @@ var Tokenizer = function(rules) { state : stack.length ? stack : currentState }; }; - + + this.reportError = function(msg, data) { + var e = new Error(msg); + e.data = data; + if (typeof console == "object" && console.error) + console.error(e); + setTimeout(function() { throw e; }); + }; }).call(Tokenizer.prototype); exports.Tokenizer = Tokenizer; @@ -7334,12 +7360,11 @@ function Folding() { if (startFold && endFold == startFold) return startFold.addSubFold(fold); - if ( - (startFold && !startFold.range.isStart(startRow, startColumn)) - || (endFold && !endFold.range.isEnd(endRow, endColumn)) - ) { - throw new Error("A fold can't intersect already existing fold" + fold.range + startFold.range); - } + if (startFold && !startFold.range.isStart(startRow, startColumn)) + this.removeFold(startFold); + + if (endFold && !endFold.range.isEnd(endRow, endColumn)) + this.removeFold(endFold); var folds = this.getFoldsInRange(fold.range); if (folds.length > 0) { this.removeFolds(folds); @@ -8992,7 +9017,7 @@ var EditSession = function(text, mode) { } }; this.adjustWrapLimit = function(desiredLimit, $printMargin) { - var limits = this.$wrapLimitRange + var limits = this.$wrapLimitRange; if (limits.max < 0) limits = {min: $printMargin, max: $printMargin}; var wrapLimit = this.$constrainWrapLimit(desiredLimit, limits.min, limits.max); @@ -9092,7 +9117,7 @@ var EditSession = function(text, mode) { var foldLine = this.getFoldLine(firstRow); var idx = 0; if (foldLine) { - var cmp = foldLine.range.compareInside(start.row, start.column) + var cmp = foldLine.range.compareInside(start.row, start.column); if (cmp == 0) { foldLine = foldLine.split(start.row, start.column); if (foldLine) { @@ -9438,7 +9463,7 @@ var EditSession = function(text, mode) { return { row: maxRow, column: this.getLine(maxRow).length - } + }; } else { line = this.getLine(docRow); foldLine = null; @@ -9941,7 +9966,7 @@ var Search = function() { if (options.wholeWord) needle = "\\b" + needle + "\\b"; - var modifier = options.caseSensitive ? "g" : "gi"; + var modifier = options.caseSensitive ? "gm" : "gmi"; options.$isMultiLine = !$disableFakeMultiline && /[\n\r]/.test(needle); if (options.$isMultiLine) @@ -10036,35 +10061,25 @@ ace.define("ace/keyboard/hash_handler",["require","exports","module","ace/lib/ke var keyUtil = require("../lib/keys"); var useragent = require("../lib/useragent"); +var KEY_MODS = keyUtil.KEY_MODS; function HashHandler(config, platform) { this.platform = platform || (useragent.isMac ? "mac" : "win"); this.commands = {}; this.commandKeyBinding = {}; - if (this.__defineGetter__ && this.__defineSetter__ && typeof console != "undefined" && console.error) { - var warned = false; - var warn = function() { - if (!warned) { - warned = true; - console.error("commmandKeyBinding has too many m's. use commandKeyBinding"); - } - }; - this.__defineGetter__("commmandKeyBinding", function() { - warn(); - return this.commandKeyBinding; - }); - this.__defineSetter__("commmandKeyBinding", function(val) { - warn(); - return this.commandKeyBinding = val; - }); - } else { - this.commmandKeyBinding = this.commandKeyBinding; - } - this.addCommands(config); -}; + this.$singleCommand = true; +} + +function MultiHashHandler(config, platform) { + HashHandler.call(this, config, platform); + this.$singleCommand = false; +} + +MultiHashHandler.prototype = HashHandler.prototype; (function() { + this.addCommand = function(command) { if (this.commands[command.name]) @@ -10076,34 +10091,73 @@ function HashHandler(config, platform) { this._buildKeyHash(command); }; - this.removeCommand = function(command) { - var name = (typeof command === 'string' ? command : command.name); + this.removeCommand = function(command, keepCommand) { + var name = command && (typeof command === 'string' ? command : command.name); command = this.commands[name]; - delete this.commands[name]; + if (!keepCommand) + delete this.commands[name]; var ckb = this.commandKeyBinding; - for (var hashId in ckb) { - for (var key in ckb[hashId]) { - if (ckb[hashId][key] == command) - delete ckb[hashId][key]; + for (var keyId in ckb) { + var cmdGroup = ckb[keyId]; + if (cmdGroup == command) { + delete ckb[keyId]; + } else if (Array.isArray(cmdGroup)) { + var i = cmdGroup.indexOf(command); + if (i != -1) { + cmdGroup.splice(i, 1); + if (cmdGroup.length == 1) + ckb[keyId] = cmdGroup[0]; + } } } }; - this.bindKey = function(key, command) { - if(!key) + this.bindKey = function(key, command, asDefault) { + if (typeof key == "object") + key = key[this.platform]; + if (!key) return; - if (typeof command == "function") { - this.addCommand({exec: command, bindKey: key, name: command.name || key}); - return; - } - - var ckb = this.commandKeyBinding; + if (typeof command == "function") + return this.addCommand({exec: command, bindKey: key, name: command.name || key}); + key.split("|").forEach(function(keyPart) { - var binding = this.parseKeys(keyPart, command); - var hashId = binding.hashId; - (ckb[hashId] || (ckb[hashId] = {}))[binding.key] = command; + var chain = ""; + if (keyPart.indexOf(" ") != -1) { + var parts = keyPart.split(/\s+/); + keyPart = parts.pop(); + parts.forEach(function(keyPart) { + var binding = this.parseKeys(keyPart); + var id = KEY_MODS[binding.hashId] + binding.key; + chain += (chain ? " " : "") + id; + this._addCommandToBinding(chain, "chainKeys"); + }, this); + chain += " "; + } + var binding = this.parseKeys(keyPart); + var id = KEY_MODS[binding.hashId] + binding.key; + this._addCommandToBinding(chain + id, command, asDefault); }, this); }; + + this._addCommandToBinding = function(keyId, command, asDefault) { + var ckb = this.commandKeyBinding, i; + if (!command) { + delete ckb[keyId]; + } else if (!ckb[keyId] || this.$singleCommand) { + ckb[keyId] = command; + } else { + if (!Array.isArray(ckb[keyId])) { + ckb[keyId] = [ckb[keyId]]; + } else if ((i = ckb[keyId].indexOf(command)) != -1) { + ckb[keyId].splice(i, 1); + } + + if (asDefault || command.isDefault) + ckb[keyId].unshift(command); + else + ckb[keyId].push(command); + } + }; this.addCommands = function(commands) { commands && Object.keys(commands).forEach(function(name) { @@ -10140,17 +10194,9 @@ function HashHandler(config, platform) { }; this._buildKeyHash = function(command) { - var binding = command.bindKey; - if (!binding) - return; - - var key = typeof binding == "string" ? binding: binding[this.platform]; - this.bindKey(key, command); + this.bindKey(command.bindKey, command); }; this.parseKeys = function(keys) { - if (keys.indexOf(" ") != -1) - keys = keys.split(/\s+/).pop(); - var parts = keys.toLowerCase().split(/[\-\+]([\-\+])?/).filter(function(x){return x}); var key = parts.pop(); @@ -10167,7 +10213,7 @@ function HashHandler(config, platform) { var modifier = keyUtil.KEY_MODS[parts[i]]; if (modifier == null) { if (typeof console != "undefined") - console.error("invalid modifier " + parts[i] + " in " + keys); + console.error("invalid modifier " + parts[i] + " in " + keys); return false; } hashId |= modifier; @@ -10176,44 +10222,66 @@ function HashHandler(config, platform) { }; this.findKeyCommand = function findKeyCommand(hashId, keyString) { - var ckbr = this.commandKeyBinding; - return ckbr[hashId] && ckbr[hashId][keyString]; + var key = KEY_MODS[hashId] + keyString; + return this.commandKeyBinding[key]; }; this.handleKeyboard = function(data, hashId, keyString, keyCode) { - return { - command: this.findKeyCommand(hashId, keyString) - }; + var key = KEY_MODS[hashId] + keyString; + var command = this.commandKeyBinding[key]; + if (data.$keyChain) { + data.$keyChain += " " + key; + command = this.commandKeyBinding[data.$keyChain] || command; + } + + if (command) { + if (command == "chainKeys" || command[command.length - 1] == "chainKeys") { + data.$keyChain = data.$keyChain || key; + return {command: "null"}; + } + } + + if (data.$keyChain && keyCode > 0) + data.$keyChain = ""; + return {command: command}; }; -}).call(HashHandler.prototype) +}).call(HashHandler.prototype); exports.HashHandler = HashHandler; +exports.MultiHashHandler = MultiHashHandler; }); ace.define("ace/commands/command_manager",["require","exports","module","ace/lib/oop","ace/keyboard/hash_handler","ace/lib/event_emitter"], function(require, exports, module) { "use strict"; var oop = require("../lib/oop"); -var HashHandler = require("../keyboard/hash_handler").HashHandler; +var MultiHashHandler = require("../keyboard/hash_handler").MultiHashHandler; var EventEmitter = require("../lib/event_emitter").EventEmitter; var CommandManager = function(platform, commands) { - HashHandler.call(this, commands, platform); + MultiHashHandler.call(this, commands, platform); this.byName = this.commands; this.setDefaultHandler("exec", function(e) { return e.command.exec(e.editor, e.args || {}); }); }; -oop.inherits(CommandManager, HashHandler); +oop.inherits(CommandManager, MultiHashHandler); (function() { oop.implement(this, EventEmitter); this.exec = function(command, editor, args) { - if (typeof command === 'string') + if (Array.isArray(command)) { + for (var i = command.length; i--; ) { + if (this.exec(command[i], editor, args)) return true; + } + return false; + } + + if (typeof command === "string") command = this.commands[command]; if (!command) @@ -10223,10 +10291,10 @@ oop.inherits(CommandManager, HashHandler); return false; var e = {editor: editor, command: command, args: args}; - var retvalue = this._emit("exec", e); + e.returnValue = this._emit("exec", e); this._signal("afterExec", e); - return retvalue === false ? false : true; + return e.returnValue === false ? false : true; }; this.toggleRecording = function(editor) { @@ -11022,30 +11090,8 @@ var Editor = function(renderer, session) { function last(a) {return a[a.length - 1]} this.selections = []; - this.commands.on("exec", function(e) { - this.startOperation(e); - - var command = e.command; - if (command.aceCommandGroup == "fileJump") { - var prev = this.prevOp; - if (!prev || prev.command.aceCommandGroup != "fileJump") { - this.lastFileJumpPos = last(this.selections); - } - } else { - this.lastFileJumpPos = null; - } - }.bind(this), true); - - this.commands.on("afterExec", function(e) { - var command = e.command; - - if (command.aceCommandGroup == "fileJump") { - if (this.lastFileJumpPos && !this.curOp.selectionChanged) { - this.selection.fromJSON(this.lastFileJumpPos); - } - } - this.endOperation(e); - }.bind(this), true); + this.commands.on("exec", this.startOperation.bind(this), true); + this.commands.on("afterExec", this.endOperation.bind(this), true); this.$opResetTimer = lang.delayedCall(this.endOperation.bind(this)); @@ -11079,19 +11125,15 @@ var Editor = function(renderer, session) { args: commadEvent.args, scrollTop: this.renderer.scrollTop }; - - var command = this.curOp.command; - if (command && command.scrollIntoView) - this.$blockScrolling++; - - this.selections.push(this.selection.toJSON()); }; - this.endOperation = function() { + this.endOperation = function(e) { if (this.curOp) { + if (e && e.returnValue === false) + return this.curOp = null; + var command = this.curOp.command; if (command && command.scrollIntoView) { - this.$blockScrolling--; switch (command.scrollIntoView) { case "center": this.renderer.scrollCursorIntoView(null, 0.5); @@ -11153,19 +11195,19 @@ var Editor = function(renderer, session) { else if (mergeableCommands.indexOf(e.command.name) !== -1) this.sequenceStartTime = Date.now(); }; - this.setKeyboardHandler = function(keyboardHandler) { - if (!keyboardHandler) { - this.keyBinding.setKeyboardHandler(null); - } else if (typeof keyboardHandler === "string") { + this.setKeyboardHandler = function(keyboardHandler, cb) { + if (keyboardHandler && typeof keyboardHandler === "string") { this.$keybindingId = keyboardHandler; var _self = this; config.loadModule(["keybinding", keyboardHandler], function(module) { if (_self.$keybindingId == keyboardHandler) _self.keyBinding.setKeyboardHandler(module && module.handler); + cb && cb(); }); } else { this.$keybindingId = null; this.keyBinding.setKeyboardHandler(keyboardHandler); + cb && cb(); } }; this.getKeyboardHandler = function() { @@ -11431,21 +11473,21 @@ var Editor = function(renderer, session) { this.blur = function() { this.textInput.blur(); }; - this.onFocus = function() { + this.onFocus = function(e) { if (this.$isFocused) return; this.$isFocused = true; this.renderer.showCursor(); this.renderer.visualizeFocus(); - this._emit("focus"); + this._emit("focus", e); }; - this.onBlur = function() { + this.onBlur = function(e) { if (!this.$isFocused) return; this.$isFocused = false; this.renderer.hideCursor(); this.renderer.visualizeBlur(); - this._emit("blur"); + this._emit("blur", e); }; this.$cursorChange = function() { @@ -11631,9 +11673,8 @@ var Editor = function(renderer, session) { this.insert(e.text, true); }; - this.execCommand = function(command, args) { - this.commands.exec(command, this, args); + return this.commands.exec(command, this, args); }; this.insert = function(text, pasted) { var session = this.session; @@ -12663,7 +12704,9 @@ var Editor = function(renderer, session) { rect = self.renderer.container.getBoundingClientRect(); }); var onAfterRender = this.renderer.on("afterRender", function() { - if (shouldScroll && rect && self.isFocused()) { + if (shouldScroll && rect && (self.isFocused() + || self.searchBox && self.searchBox.isFocused()) + ) { var renderer = self.renderer; var pos = renderer.$cursorLayer.$pixelPos; var config = renderer.layerConfig; @@ -15377,23 +15420,24 @@ var VirtualRenderer = function(container, theme) { this.scrollBarH.setVisible(horizScroll); } - if (!this.$maxLines && this.$scrollPastEnd) { - maxHeight += (size.scrollerHeight - this.lineHeight) * this.$scrollPastEnd; - } - - var vScroll = !hideScrollbars && (this.$vScrollBarAlwaysVisible || - size.scrollerHeight - maxHeight < 0); - var vScrollChanged = this.$vScroll !== vScroll; - if (vScrollChanged) { - this.$vScroll = vScroll; - this.scrollBarV.setVisible(vScroll); - } + var scrollPastEnd = !this.$maxLines && this.$scrollPastEnd + ? (size.scrollerHeight - this.lineHeight) * this.$scrollPastEnd + : 0; + maxHeight += scrollPastEnd; this.session.setScrollTop(Math.max(-this.scrollMargin.top, Math.min(this.scrollTop, maxHeight - size.scrollerHeight + this.scrollMargin.bottom))); this.session.setScrollLeft(Math.max(-this.scrollMargin.left, Math.min(this.scrollLeft, longestLine + 2 * this.$padding - size.scrollerWidth + this.scrollMargin.right))); + + var vScroll = !hideScrollbars && (this.$vScrollBarAlwaysVisible || + size.scrollerHeight - maxHeight + scrollPastEnd < 0 || this.scrollTop); + var vScrollChanged = this.$vScroll !== vScroll; + if (vScrollChanged) { + this.$vScroll = vScroll; + this.scrollBarV.setVisible(vScroll); + } var lineCount = Math.ceil(minHeight / this.lineHeight) - 1; var firstRow = Math.max(0, Math.round((this.scrollTop - offset) / this.lineHeight)); @@ -16005,14 +16049,9 @@ var WorkerClient = function(topLevelNamespaces, mod, classname, workerUrl) { this.onMessage = function(e) { var msg = e.data; switch(msg.type) { - case "log": - window.console && console.log && console.log.apply(console, msg.data); - break; - case "event": this._signal(msg.name, {data: msg.data}); break; - case "call": var callback = this.callbacks[msg.id]; if (callback) { @@ -16020,8 +16059,18 @@ var WorkerClient = function(topLevelNamespaces, mod, classname, workerUrl) { delete this.callbacks[msg.id]; } break; + case "error": + this.reportError(msg.data); + break; + case "log": + window.console && console.log && console.log.apply(console, msg.data); + break; } }; + + this.reportError = function(err) { + window.console && console.error && console.error(err); + }; this.$normalizePath = function(path) { return net.qualifyURL(path); @@ -16032,7 +16081,8 @@ var WorkerClient = function(topLevelNamespaces, mod, classname, workerUrl) { this.deltaQueue = null; this.$worker.terminate(); this.$worker = null; - this.$doc.removeEventListener("change", this.changeListener); + if (this.$doc) + this.$doc.off("change", this.changeListener); this.$doc = null; }; @@ -17642,9 +17692,10 @@ function LineWidgets(session) { this.renderWidgets = this.renderWidgets.bind(this); this.measureWidgets = this.measureWidgets.bind(this); this.session._changedWidgets = []; - this.detach = this.detach.bind(this); + this.$onChangeEditor = this.$onChangeEditor.bind(this); this.session.on("change", this.updateOnChange); + this.session.on("changeEditor", this.$onChangeEditor); } (function() { @@ -17670,8 +17721,12 @@ function LineWidgets(session) { return screenRows; }; + this.$onChangeEditor = function(e) { + this.attach(e.editor); + }; + this.attach = function(editor) { - if (editor.widgetManager && editor.widgetManager != this) + if (editor && editor.widgetManager && editor.widgetManager != this) editor.widgetManager.detach(); if (this.editor == editor) @@ -17680,21 +17735,16 @@ function LineWidgets(session) { this.detach(); this.editor = editor; - this.editor.on("changeSession", this.detach); - - editor.widgetManager = this; - - editor.renderer.on("beforeRender", this.measureWidgets); - editor.renderer.on("afterRender", this.renderWidgets); + if (editor) { + editor.widgetManager = this; + editor.renderer.on("beforeRender", this.measureWidgets); + editor.renderer.on("afterRender", this.renderWidgets); + } }; this.detach = function(e) { - if (e && e.session == this.session) - return; // sometimes attach can be called before setSession var editor = this.editor; if (!editor) return; - - editor.off("changeSession", this.detach); this.editor = null; editor.widgetManager = null; @@ -18142,7 +18192,6 @@ exports.createEditSession = function(text, mode) { exports.EditSession = EditSession; exports.UndoManager = UndoManager; }); -; (function() { ace.require(["ace/ace"], function(a) { a && a.config.init(true); diff --git a/lib/client/edit/ext-beautify.js b/lib/client/edit/ext-beautify.js index d965d505..ba499b77 100644 --- a/lib/client/edit/ext-beautify.js +++ b/lib/client/edit/ext-beautify.js @@ -328,7 +328,6 @@ exports.commands = [{ }] }); -; (function() { ace.require(["ace/ext/beautify"], function() {}); })(); diff --git a/lib/client/edit/ext-chromevox.js b/lib/client/edit/ext-chromevox.js index eb01b149..0e07babd 100644 --- a/lib/client/edit/ext-chromevox.js +++ b/lib/client/edit/ext-chromevox.js @@ -535,7 +535,6 @@ require('../config').defineOptions(Editor.prototype, 'editor', { }); }); -; (function() { ace.require(["ace/ext/chromevox"], function() {}); })(); diff --git a/lib/client/edit/ext-elastic_tabstops_lite.js b/lib/client/edit/ext-elastic_tabstops_lite.js index d9d62ba8..00fe84a4 100644 --- a/lib/client/edit/ext-elastic_tabstops_lite.js +++ b/lib/client/edit/ext-elastic_tabstops_lite.js @@ -269,7 +269,6 @@ require("../config").defineOptions(Editor.prototype, "editor", { }); }); -; (function() { ace.require(["ace/ext/elastic_tabstops_lite"], function() {}); })(); diff --git a/lib/client/edit/ext-emmet.js b/lib/client/edit/ext-emmet.js index f5c868f7..a33b1ae6 100644 --- a/lib/client/edit/ext-emmet.js +++ b/lib/client/edit/ext-emmet.js @@ -901,21 +901,13 @@ var Editor = require("./editor").Editor; }); -ace.define("ace/ext/emmet",["require","exports","module","ace/keyboard/hash_handler","ace/editor","ace/snippets","ace/range","resources","resources","range","tabStops","resources","utils","actions","ace/config"], function(require, exports, module) { +ace.define("ace/ext/emmet",["require","exports","module","ace/keyboard/hash_handler","ace/editor","ace/snippets","ace/range","resources","resources","range","tabStops","resources","utils","actions","ace/config","ace/config"], function(require, exports, module) { "use strict"; var HashHandler = require("ace/keyboard/hash_handler").HashHandler; var Editor = require("ace/editor").Editor; var snippetManager = require("ace/snippets").snippetManager; var Range = require("ace/range").Range; -var emmet; - -Editor.prototype.indexToPosition = function(index) { - return this.session.doc.indexToPosition(index); -}; - -Editor.prototype.positionToIndex = function(pos) { - return this.session.doc.positionToIndex(pos); -}; +var emmet, emmetPath; function AceEmmetEditor() {} AceEmmetEditor.prototype = { @@ -930,21 +922,24 @@ AceEmmetEditor.prototype = { }, getSelectionRange: function() { var range = this.ace.getSelectionRange(); + var doc = this.ace.session.doc; return { - start: this.ace.positionToIndex(range.start), - end: this.ace.positionToIndex(range.end) + start: doc.positionToIndex(range.start), + end: doc.positionToIndex(range.end) }; }, createSelection: function(start, end) { + var doc = this.ace.session.doc; this.ace.selection.setRange({ - start: this.ace.indexToPosition(start), - end: this.ace.indexToPosition(end) + start: doc.indexToPosition(start), + end: doc.indexToPosition(end) }); }, getCurrentLineRange: function() { - var row = this.ace.getCursorPosition().row; - var lineLength = this.ace.session.getLine(row).length; - var index = this.ace.positionToIndex({row: row, column: 0}); + var ace = this.ace; + var row = ace.getCursorPosition().row; + var lineLength = ace.session.getLine(row).length; + var index = ace.session.doc.positionToIndex({row: row, column: 0}); return { start: index, end: index + lineLength @@ -952,10 +947,10 @@ AceEmmetEditor.prototype = { }, getCaretPos: function(){ var pos = this.ace.getCursorPosition(); - return this.ace.positionToIndex(pos); + return this.ace.session.doc.positionToIndex(pos); }, setCaretPos: function(index){ - var pos = this.ace.indexToPosition(index); + var pos = this.ace.session.doc.indexToPosition(index); this.ace.selection.moveToPosition(pos); }, getCurrentLine: function() { @@ -969,13 +964,14 @@ AceEmmetEditor.prototype = { start = 0; var editor = this.ace; - var range = Range.fromPoints(editor.indexToPosition(start), editor.indexToPosition(end)); + var doc = editor.session.doc; + var range = Range.fromPoints(doc.indexToPosition(start), doc.indexToPosition(end)); editor.session.remove(range); range.end = range.start; value = this.$updateTabstops(value); - snippetManager.insertSnippet(editor, value) + snippetManager.insertSnippet(editor, value); }, getContent: function(){ return this.ace.getValue(); @@ -1049,7 +1045,7 @@ AceEmmetEditor.prototype = { lastZero = range.create(data.start, result); } - return result + return result; }, escape: function(ch) { if (ch == '$') return '\\$'; @@ -1100,28 +1096,33 @@ var keymap = { var editorProxy = new AceEmmetEditor(); exports.commands = new HashHandler(); exports.runEmmetCommand = function(editor) { - editorProxy.setupContext(editor); - if (editorProxy.getSyntax() == "php") - return false; - var actions = emmet.require("actions"); - - if (this.action == "expand_abbreviation_with_tab") { - if (!editor.selection.isEmpty()) - return false; - } - - if (this.action == "wrap_with_abbreviation") { - return setTimeout(function() { - actions.run("wrap_with_abbreviation", editorProxy); - }, 0); - } - try { + editorProxy.setupContext(editor); + if (editorProxy.getSyntax() == "php") + return false; + var actions = emmet.require("actions"); + + if (this.action == "expand_abbreviation_with_tab") { + if (!editor.selection.isEmpty()) + return false; + } + + if (this.action == "wrap_with_abbreviation") { + return setTimeout(function() { + actions.run("wrap_with_abbreviation", editorProxy); + }, 0); + } + + var pos = editor.selection.lead; + var token = editor.session.getTokenAt(pos.row, pos.column); + if (token && /\btag\b/.test(token.type)) + return false; + var result = actions.run(this.action, editorProxy); } catch(e) { editor._signal("changeStatus", typeof e == "string" ? e : e.message); console.log(e); - result = false + result = false; } return result; }; @@ -1136,21 +1137,35 @@ for (var command in keymap) { }); } +exports.updateCommands = function(editor, enabled) { + if (enabled) { + editor.keyBinding.addKeyboardHandler(exports.commands); + } else { + editor.keyBinding.removeKeyboardHandler(exports.commands); + } +}; + +exports.isSupportedMode = function(modeId) { + return modeId && /css|less|scss|sass|stylus|html|php|twig|ejs/.test(modeId); +}; + var onChangeMode = function(e, target) { var editor = target; if (!editor) return; - var modeId = editor.session.$modeId; - var enabled = modeId && /css|less|scss|sass|stylus|html|php/.test(modeId); + var enabled = exports.isSupportedMode(editor.session.$modeId); if (e.enableEmmet === false) enabled = false; - if (enabled) - editor.keyBinding.addKeyboardHandler(exports.commands); - else - editor.keyBinding.removeKeyboardHandler(exports.commands); + if (enabled) { + if (typeof emmetPath == "string") { + require("ace/config").loadModule(emmetPath, function() { + emmetPath = null; + }); + } + } + exports.updateCommands(editor, enabled); }; - exports.AceEmmetEditor = AceEmmetEditor; require("ace/config").defineOptions(Editor.prototype, "editor", { enableEmmet: { @@ -1162,10 +1177,13 @@ require("ace/config").defineOptions(Editor.prototype, "editor", { } }); - -exports.setCore = function(e) {emmet = e;}; +exports.setCore = function(e) { + if (typeof e == "string") + emmetPath = e; + else + emmet = e; +}; }); -; (function() { ace.require(["ace/ext/emmet"], function() {}); })(); diff --git a/lib/client/edit/ext-keybinding_menu.js b/lib/client/edit/ext-keybinding_menu.js index 03da558d..b6cfd2b4 100644 --- a/lib/client/edit/ext-keybinding_menu.js +++ b/lib/client/edit/ext-keybinding_menu.js @@ -109,29 +109,20 @@ module.exports.getEditorKeybordShortcuts = function(editor) { editor.keyBinding.$handlers.forEach(function(handler) { var ckb = handler.commandKeyBinding; for (var i in ckb) { - var modifier = parseInt(i); - if (modifier == -1) { - modifier = ""; - } else if(isNaN(modifier)) { - modifier = i; - } else { - modifier = "" + - (modifier & KEY_MODS.command ? "Cmd-" : "") + - (modifier & KEY_MODS.ctrl ? "Ctrl-" : "") + - (modifier & KEY_MODS.alt ? "Alt-" : "") + - (modifier & KEY_MODS.shift ? "Shift-" : ""); - } - for (var key in ckb[i]) { - var command = ckb[i][key] + var key = i.replace(/(^|-)\w/g, function(x) { return x.toUpperCase(); }); + var commands = ckb[i]; + if (!Array.isArray(commands)) + commands = [commands]; + commands.forEach(function(command) { if (typeof command != "string") command = command.name if (commandMap[command]) { - commandMap[command].key += "|" + modifier + key; + commandMap[command].key += "|" + key; } else { - commandMap[command] = {key: modifier+key, command: command}; + commandMap[command] = {key: key, command: command}; keybindings.push(commandMap[command]); - } - } + } + }); } }); return keybindings; @@ -173,7 +164,6 @@ ace.define("ace/ext/keybinding_menu",["require","exports","module","ace/editor", }; }); -; (function() { ace.require(["ace/ext/keybinding_menu"], function() {}); })(); diff --git a/lib/client/edit/ext-language_tools.js b/lib/client/edit/ext-language_tools.js index c6a167ad..129bd9e8 100644 --- a/lib/client/edit/ext-language_tools.js +++ b/lib/client/edit/ext-language_tools.js @@ -1251,7 +1251,7 @@ exports.retrieveFollowingIdentifier = function(text, pos, regex) { }); -ace.define("ace/autocomplete",["require","exports","module","ace/keyboard/hash_handler","ace/autocomplete/popup","ace/autocomplete/util","ace/lib/event","ace/lib/lang","ace/snippets"], function(require, exports, module) { +ace.define("ace/autocomplete",["require","exports","module","ace/keyboard/hash_handler","ace/autocomplete/popup","ace/autocomplete/util","ace/lib/event","ace/lib/lang","ace/lib/dom","ace/snippets"], function(require, exports, module) { "use strict"; var HashHandler = require("./keyboard/hash_handler").HashHandler; @@ -1259,6 +1259,7 @@ var AcePopup = require("./autocomplete/popup").AcePopup; var util = require("./autocomplete/util"); var event = require("./lib/event"); var lang = require("./lib/lang"); +var dom = require("./lib/dom"); var snippetManager = require("./snippets").snippetManager; var Autocomplete = function() { @@ -1275,6 +1276,8 @@ var Autocomplete = function() { this.changeTimer = lang.delayedCall(function() { this.updateCompletions(true); }.bind(this)); + + this.tooltipTimer = lang.delayedCall(this.updateDocTooltip.bind(this), 50); }; (function() { @@ -1287,6 +1290,14 @@ var Autocomplete = function() { e.stop(); }.bind(this)); this.popup.focus = this.editor.focus.bind(this.editor); + this.popup.on("show", this.tooltipTimer.bind(null, null)); + this.popup.on("select", this.tooltipTimer.bind(null, null)); + this.popup.on("changeHoverMarker", this.tooltipTimer.bind(null, null)); + return this.popup; + }; + + this.getPopup = function() { + return this.popup || this.$init(); }; this.openPopup = function(editor, prefix, keepPopupPosition) { @@ -1324,6 +1335,7 @@ var Autocomplete = function() { this.editor.off("mousedown", this.mousedownListener); this.editor.off("mousewheel", this.mousewheelListener); this.changeTimer.cancel(); + this.hideDocTooltip(); if (this.popup && this.popup.isOpen) { this.gatherCompletionsId += 1; @@ -1347,10 +1359,15 @@ var Autocomplete = function() { this.detach(); }; - this.blurListener = function() { + this.blurListener = function(e) { var el = document.activeElement; - if (el != this.editor.textInput.getElement() && el.parentNode != this.popup.container) + var text = this.editor.textInput.getElement() + if (el != text && el.parentNode != this.popup.container + && el != this.tooltipNode && e.relatedTarget != this.tooltipNode + && e.relatedTarget != text + ) { this.detach(); + } }; this.mousedownListener = function(e) { @@ -1382,7 +1399,7 @@ var Autocomplete = function() { return false; if (data.completer && data.completer.insertMatch) { - data.completer.insertMatch(this.editor); + data.completer.insertMatch(this.editor, data); } else { if (this.completions.filterText) { var ranges = this.editor.selection.getAllRanges(); @@ -1399,6 +1416,7 @@ var Autocomplete = function() { this.detach(); }; + this.commands = { "Up": function(editor) { editor.completer.goTo("up"); }, "Down": function(editor) { editor.completer.goTo("down"); }, @@ -1519,6 +1537,73 @@ var Autocomplete = function() { this.cancelContextMenu = function() { this.editor.$mouseHandler.cancelContextMenu(); }; + + this.updateDocTooltip = function() { + var popup = this.popup; + var all = popup.data; + var selected = all && (all[popup.getHoveredRow()] || all[popup.getRow()]); + var doc = null; + if (!selected || !this.editor || !this.popup.isOpen) + return this.hideDocTooltip(); + this.editor.completers.some(function(completer) { + if (completer.getDocTooltip) + doc = completer.getDocTooltip(selected); + return doc; + }); + if (!doc) + doc = selected; + + if (typeof doc == "string") + doc = {docText: doc} + if (!doc || !(doc.docHTML || doc.docText)) + return this.hideDocTooltip(); + this.showDocTooltip(doc); + }; + + this.showDocTooltip = function(item) { + if (!this.tooltipNode) { + this.tooltipNode = dom.createElement("div"); + this.tooltipNode.className = "ace_tooltip ace_doc-tooltip"; + this.tooltipNode.style.margin = 0; + this.tooltipNode.style.pointerEvents = "auto"; + this.tooltipNode.tabIndex = -1; + this.tooltipNode.onblur = this.blurListener.bind(this); + } + + var tooltipNode = this.tooltipNode; + if (item.docHTML) { + tooltipNode.innerHTML = item.docHTML; + } else if (item.docText) { + tooltipNode.textContent = item.docText; + } + + if (!tooltipNode.parentNode) + document.body.appendChild(tooltipNode); + var popup = this.popup; + var rect = popup.container.getBoundingClientRect(); + tooltipNode.style.top = popup.container.style.top; + tooltipNode.style.bottom = popup.container.style.bottom; + + if (window.innerWidth - rect.right < 320) { + tooltipNode.style.right = window.innerWidth - rect.left + "px"; + tooltipNode.style.left = ""; + } else { + tooltipNode.style.left = (rect.right + 1) + "px"; + tooltipNode.style.right = ""; + } + tooltipNode.style.display = "block"; + }; + + this.hideDocTooltip = function() { + this.tooltipTimer.cancel(); + if (!this.tooltipNode) return; + var el = this.tooltipNode; + if (!this.editor.isFocused() && document.activeElement == el) + this.editor.focus(); + this.tooltipNode = null; + if (el.parentNode) + el.parentNode.removeChild(el); + }; }).call(Autocomplete.prototype); @@ -1646,17 +1731,21 @@ ace.define("ace/autocomplete/text_completer",["require","exports","module","ace/ }; }); -ace.define("ace/ext/language_tools",["require","exports","module","ace/snippets","ace/autocomplete","ace/config","ace/autocomplete/util","ace/autocomplete/text_completer","ace/editor","ace/config"], function(require, exports, module) { +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"; var snippetManager = require("../snippets").snippetManager; var Autocomplete = require("../autocomplete").Autocomplete; var config = require("../config"); +var lang = require("../lib/lang"); var util = require("../autocomplete/util"); var textCompleter = require("../autocomplete/text_completer"); var keyWordCompleter = { getCompletions: function(editor, session, pos, prefix, callback) { + if (session.$mode.completer) { + return session.$mode.completer.getCompletions(editor, session, pos, prefix, callback); + } var state = editor.session.getState(pos.row); var completions = session.$mode.getCompletions(state, session, pos, prefix); callback(null, completions); @@ -1677,15 +1766,27 @@ var snippetCompleter = { completions.push({ caption: caption, snippet: s.content, - meta: s.tabTrigger && !s.name ? s.tabTrigger + "\u21E5 " : "snippet" + meta: s.tabTrigger && !s.name ? s.tabTrigger + "\u21E5 " : "snippet", + type: "snippet" }); } }, this); callback(null, completions); + }, + getDocTooltip: function(item) { + if (item.type == "snippet" && !item.docHTML) { + item.docHTML = [ + "", lang.escapeHTML(item.caption), "", "
", + lang.escapeHTML(item.snippet) + ].join(""); + } } }; var completers = [snippetCompleter, textCompleter, keyWordCompleter]; +exports.setCompleters = function(val) { + completers = val || []; +}; exports.addCompleter = function(completer) { completers.push(completer); }; @@ -1696,9 +1797,7 @@ exports.snippetCompleter = snippetCompleter; var expandSnippet = { name: "expandSnippet", exec: function(editor) { - var success = snippetManager.expandWithTab(editor); - if (!success) - editor.execCommand("indent"); + return snippetManager.expandWithTab(editor); }, bindKey: "Tab" }; @@ -1814,7 +1913,6 @@ require("../config").defineOptions(Editor.prototype, "editor", { } }); }); -; (function() { ace.require(["ace/ext/language_tools"], function() {}); })(); diff --git a/lib/client/edit/ext-linking.js b/lib/client/edit/ext-linking.js index a1f79743..c6ad15df 100644 --- a/lib/client/edit/ext-linking.js +++ b/lib/client/edit/ext-linking.js @@ -46,7 +46,6 @@ function onClick(e) { } }); -; (function() { ace.require(["ace/ext/linking"], function() {}); })(); diff --git a/lib/client/edit/ext-modelist.js b/lib/client/edit/ext-modelist.js index 3dfd241e..7a69e839 100644 --- a/lib/client/edit/ext-modelist.js +++ b/lib/client/edit/ext-modelist.js @@ -57,8 +57,12 @@ var supportedModes = { Diff: ["diff|patch"], Dockerfile: ["^Dockerfile"], Dot: ["dot"], + Dummy: ["dummy"], + DummySyntax: ["dummy"], Eiffel: ["e"], EJS: ["ejs"], + Elixir: ["ex|exs"], + Elm: ["elm"], Erlang: ["erl|hrl"], Forth: ["frt|fs|ldr"], FTL: ["ftl"], @@ -176,7 +180,6 @@ module.exports = { }; }); -; (function() { ace.require(["ace/ext/modelist"], function() {}); })(); diff --git a/lib/client/edit/ext-old_ie.js b/lib/client/edit/ext-old_ie.js index 36297068..d84d3ace 100644 --- a/lib/client/edit/ext-old_ie.js +++ b/lib/client/edit/ext-old_ie.js @@ -9,7 +9,7 @@ var searchboxCss = "\ background-color: #ddd;\ border: 1px solid #cbcbcb;\ border-top: 0 none;\ -max-width: 297px;\ +max-width: 325px;\ overflow: hidden;\ margin: 0;\ padding: 4px;\ @@ -158,6 +158,7 @@ var html = '\
\ \ @@ -278,6 +279,11 @@ var SearchBox = function(editor, range, showReplaceForm) { sb.replace(); sb.findPrev(); }, + "Alt-Return": function(sb) { + if (sb.activeInput == sb.replaceInput) + sb.replaceAll(); + sb.findAll(); + }, "Tab": function(sb) { (sb.activeInput == sb.replaceInput ? sb.searchInput : sb.replaceInput).focus(); } @@ -337,6 +343,18 @@ var SearchBox = function(editor, range, showReplaceForm) { this.findPrev = function() { this.find(true, true); }; + this.findAll = function(){ + var range = this.editor.findAll(this.searchInput.value, { + regExp: this.regExpOption.checked, + caseSensitive: this.caseSensitiveOption.checked, + wholeWord: this.wholeWordOption.checked + }); + var noMatch = !range && this.searchInput.value; + dom.setCssClass(this.searchBox, "ace_nomatch", noMatch); + this.editor._emit("findSearchBox", { match: !noMatch }); + this.highlight(); + this.hide(); + }; this.replace = function() { if (!this.editor.getReadOnly()) this.editor.replace(this.replaceInput.value); @@ -371,6 +389,10 @@ var SearchBox = function(editor, range, showReplaceForm) { this.editor.keyBinding.addKeyboardHandler(this.$closeSearchBarKb); }; + this.isFocused = function() { + var el = document.activeElement; + return el == this.searchInput || el == this.replaceInput; + } }).call(SearchBox.prototype); exports.SearchBox = SearchBox; @@ -466,7 +488,6 @@ patch( useragent.isOldIE = true; }); -; (function() { ace.require(["ace/ext/old_ie"], function() {}); })(); diff --git a/lib/client/edit/ext-searchbox.js b/lib/client/edit/ext-searchbox.js index 14528480..b4e4c0e0 100644 --- a/lib/client/edit/ext-searchbox.js +++ b/lib/client/edit/ext-searchbox.js @@ -9,7 +9,7 @@ var searchboxCss = "\ background-color: #ddd;\ border: 1px solid #cbcbcb;\ border-top: 0 none;\ -max-width: 297px;\ +max-width: 325px;\ overflow: hidden;\ margin: 0;\ padding: 4px;\ @@ -158,6 +158,7 @@ var html = '\
\ \ @@ -278,6 +279,11 @@ var SearchBox = function(editor, range, showReplaceForm) { sb.replace(); sb.findPrev(); }, + "Alt-Return": function(sb) { + if (sb.activeInput == sb.replaceInput) + sb.replaceAll(); + sb.findAll(); + }, "Tab": function(sb) { (sb.activeInput == sb.replaceInput ? sb.searchInput : sb.replaceInput).focus(); } @@ -337,6 +343,18 @@ var SearchBox = function(editor, range, showReplaceForm) { this.findPrev = function() { this.find(true, true); }; + this.findAll = function(){ + var range = this.editor.findAll(this.searchInput.value, { + regExp: this.regExpOption.checked, + caseSensitive: this.caseSensitiveOption.checked, + wholeWord: this.wholeWordOption.checked + }); + var noMatch = !range && this.searchInput.value; + dom.setCssClass(this.searchBox, "ace_nomatch", noMatch); + this.editor._emit("findSearchBox", { match: !noMatch }); + this.highlight(); + this.hide(); + }; this.replace = function() { if (!this.editor.getReadOnly()) this.editor.replace(this.replaceInput.value); @@ -371,6 +389,10 @@ var SearchBox = function(editor, range, showReplaceForm) { this.editor.keyBinding.addKeyboardHandler(this.$closeSearchBarKb); }; + this.isFocused = function() { + var el = document.activeElement; + return el == this.searchInput || el == this.replaceInput; + } }).call(SearchBox.prototype); exports.SearchBox = SearchBox; @@ -381,7 +403,6 @@ exports.Search = function(editor, isReplace) { }; }); -; (function() { ace.require(["ace/ext/searchbox"], function() {}); })(); diff --git a/lib/client/edit/ext-settings_menu.js b/lib/client/edit/ext-settings_menu.js index b085e37e..9c1c50aa 100644 --- a/lib/client/edit/ext-settings_menu.js +++ b/lib/client/edit/ext-settings_menu.js @@ -113,8 +113,12 @@ var supportedModes = { Diff: ["diff|patch"], Dockerfile: ["^Dockerfile"], Dot: ["dot"], + Dummy: ["dummy"], + DummySyntax: ["dummy"], Eiffel: ["e"], EJS: ["ejs"], + Elixir: ["ex|exs"], + Elm: ["elm"], Erlang: ["erl|hrl"], Forth: ["frt|fs|ldr"], FTL: ["ftl"], @@ -404,6 +408,12 @@ module.exports.generateSettingsMenu = function generateSettingsMenu (editor) { elements.forEach(function(element) { topmenu.appendChild(element); }); + + var el = topmenu.appendChild(document.createElement('div')); + var version = "1.1.7"; + el.style.padding = "1em"; + el.textContent = "Ace version " + version; + return topmenu; } function createNewEntry(obj, clss, item, val) { @@ -620,7 +630,6 @@ module.exports.init = function(editor) { }; }; }); -; (function() { ace.require(["ace/ext/settings_menu"], function() {}); })(); diff --git a/lib/client/edit/ext-spellcheck.js b/lib/client/edit/ext-spellcheck.js index c47d99e7..8d3b5f6c 100644 --- a/lib/client/edit/ext-spellcheck.js +++ b/lib/client/edit/ext-spellcheck.js @@ -65,7 +65,6 @@ require("../config").defineOptions(Editor.prototype, "editor", { }); }); -; (function() { ace.require(["ace/ext/spellcheck"], function() {}); })(); diff --git a/lib/client/edit/ext-split.js b/lib/client/edit/ext-split.js index df5ecf11..29dd20ef 100644 --- a/lib/client/edit/ext-split.js +++ b/lib/client/edit/ext-split.js @@ -240,7 +240,6 @@ ace.define("ace/ext/split",["require","exports","module","ace/split"], function( module.exports = require("../split"); }); -; (function() { ace.require(["ace/ext/split"], function() {}); })(); diff --git a/lib/client/edit/ext-static_highlight.js b/lib/client/edit/ext-static_highlight.js index 67a8e66a..9ba06a81 100644 --- a/lib/client/edit/ext-static_highlight.js +++ b/lib/client/edit/ext-static_highlight.js @@ -148,7 +148,6 @@ highlight.renderSync = function(input, mode, theme, lineStart, disableGutter) { module.exports = highlight; module.exports.highlight =highlight; }); -; (function() { ace.require(["ace/ext/static_highlight"], function() {}); })(); diff --git a/lib/client/edit/ext-statusbar.js b/lib/client/edit/ext-statusbar.js index 8797f657..d369b166 100644 --- a/lib/client/edit/ext-statusbar.js +++ b/lib/client/edit/ext-statusbar.js @@ -27,9 +27,8 @@ var StatusBar = function(editor, parentNode) { str && status.push(str, separator || "|"); } - if (editor.$vimModeHandler) - add(editor.$vimModeHandler.getStatusText()); - else if (editor.commands.recording) + add(editor.keyBinding.getStatusText(editor)); + if (editor.commands.recording) add("REC"); var c = editor.selection.lead; @@ -46,7 +45,6 @@ var StatusBar = function(editor, parentNode) { exports.StatusBar = StatusBar; }); -; (function() { ace.require(["ace/ext/statusbar"], function() {}); })(); diff --git a/lib/client/edit/ext-textarea.js b/lib/client/edit/ext-textarea.js index ba264f9b..6309fbb4 100644 --- a/lib/client/edit/ext-textarea.js +++ b/lib/client/edit/ext-textarea.js @@ -626,7 +626,6 @@ exports.defaultOptions = { }; }); -; (function() { ace.require(["ace/ext/textarea"], function() {}); })(); diff --git a/lib/client/edit/ext-themelist.js b/lib/client/edit/ext-themelist.js index 539ac59f..b1b03925 100644 --- a/lib/client/edit/ext-themelist.js +++ b/lib/client/edit/ext-themelist.js @@ -52,7 +52,6 @@ exports.themes = themeData.map(function(data) { }); }); -; (function() { ace.require(["ace/ext/themelist"], function() {}); })(); diff --git a/lib/client/edit/ext-whitespace.js b/lib/client/edit/ext-whitespace.js index 01136534..45561ffb 100644 --- a/lib/client/edit/ext-whitespace.js +++ b/lib/client/edit/ext-whitespace.js @@ -175,7 +175,6 @@ exports.commands = [{ }]; }); -; (function() { ace.require(["ace/ext/whitespace"], function() {}); })(); diff --git a/lib/client/edit/keybinding-emacs.js b/lib/client/edit/keybinding-emacs.js index 084d8a8b..2bbc0d69 100644 --- a/lib/client/edit/keybinding-emacs.js +++ b/lib/client/edit/keybinding-emacs.js @@ -315,6 +315,28 @@ exports.iSearchCommands = [{ exec: function(iSearch) { iSearch.$editor.execCommand('recenterTopBottom'); }, readOnly: true, isIncrementalSearchCommand: true +}, { + name: 'selectAllMatches', + bindKey: 'Ctrl-space', + exec: function(iSearch) { + var ed = iSearch.$editor, + hl = ed.session.$isearchHighlight, + ranges = hl && hl.cache ? hl.cache + .reduce(function(ranges, ea) { + return ranges.concat(ea ? ea : []); }, []) : []; + iSearch.deactivate(false); + ranges.forEach(ed.selection.addRange.bind(ed.selection)); + }, + readOnly: true, + isIncrementalSearchCommand: true +}, { + name: 'searchAsRegExp', + bindKey: 'Alt-r', + exec: function(iSearch) { + iSearch.convertNeedleToRegExp(); + }, + readOnly: true, + isIncrementalSearchCommand: true }]; function IncrementalSearchKeyboardHandler(iSearch) { @@ -378,6 +400,30 @@ function IncrementalSearch() { oop.inherits(IncrementalSearch, Search); +function isRegExp(obj) { + return obj instanceof RegExp; +} + +function regExpToObject(re) { + var string = String(re), + start = string.indexOf('/'), + flagStart = string.lastIndexOf('/'); + return { + expression: string.slice(start+1, flagStart), + flags: string.slice(flagStart+1) + } +} + +function stringToRegExp(string, flags) { + try { + return new RegExp(string, flags); + } catch (e) { return string; } +} + +function objectToRegExp(obj) { + return stringToRegExp(obj.expression, obj.flags); +} + ;(function() { this.activate = function(ed, backwards) { @@ -444,10 +490,12 @@ oop.inherits(IncrementalSearch, Search); }; options.start = this.$currentPos; var session = this.$editor.session, - found = this.find(session); + found = this.find(session), + shouldSelect = this.$editor.emacsMark ? + !!this.$editor.emacsMark() : !this.$editor.selection.isEmpty(); if (found) { if (options.backwards) found = Range.fromPoints(found.end, found.start); - this.$editor.moveCursorToPosition(found.end); + this.$editor.selection.setRange(Range.fromPoints(shouldSelect ? this.$startPos : found.end, found.end)); if (moveToNext) this.$currentPos = found.end; this.highlight(options.re) } @@ -459,13 +507,21 @@ oop.inherits(IncrementalSearch, Search); this.addString = function(s) { return this.highlightAndFindWithNeedle(false, function(needle) { - return needle + s; + if (!isRegExp(needle)) + return needle + s; + var reObj = regExpToObject(needle); + reObj.expression += s; + return objectToRegExp(reObj); }); } this.removeChar = function(c) { return this.highlightAndFindWithNeedle(false, function(needle) { - return needle.length > 0 ? needle.substring(0, needle.length-1) : needle; + if (!isRegExp(needle)) + return needle.substring(0, needle.length-1); + var reObj = regExpToObject(needle); + reObj.expression = reObj.expression.substring(0, reObj.expression.length-1); + return objectToRegExp(reObj); }); } @@ -488,6 +544,18 @@ oop.inherits(IncrementalSearch, Search); this.addString(text); } + this.convertNeedleToRegExp = function() { + return this.highlightAndFindWithNeedle(false, function(needle) { + return isRegExp(needle) ? needle : stringToRegExp(needle, 'ig'); + }); + } + + this.convertNeedleToString = function() { + return this.highlightAndFindWithNeedle(false, function(needle) { + return isRegExp(needle) ? regExpToObject(needle).expression : needle; + }); + } + this.statusMessage = function(found) { var options = this.$options, msg = ''; msg += options.backwards ? 'reverse-' : ''; @@ -590,7 +658,7 @@ exports.handler.attach = function(editor) { initialized = true; dom.importCssString('\ .emacs-mode .ace_cursor{\ - border: 2px rgba(50,250,50,0.8) solid!important;\ + border: 1px rgba(50,250,50,0.8) solid!important;\ -moz-box-sizing: border-box!important;\ -webkit-box-sizing: border-box!important;\ box-sizing: border-box!important;\ @@ -648,6 +716,22 @@ exports.handler.attach = function(editor) { return this.session.$emacsMark || this.session.$emacsMarkRing.slice(-1)[0]; }; + editor.emacsMarkForSelection = function(replacement) { + var sel = this.selection, + multiRangeLength = this.multiSelect ? + this.multiSelect.getAllRanges().length : 1, + selIndex = sel.index || 0, + markRing = this.session.$emacsMarkRing, + markIndex = markRing.length - (multiRangeLength - selIndex), + lastMark = markRing[markIndex] || sel.anchor; + if (replacement) { + markRing.splice(markIndex, 1, + "row" in replacement && "column" in replacement ? + replacement : undefined); + } + return lastMark; + } + editor.on("click", $resetMarkMode); editor.on("changeSession", $kbSessionChange); editor.renderer.screenToTextCoordinates = screenToTextBlockCoordinates; @@ -669,6 +753,7 @@ exports.handler.detach = function(editor) { editor.commands.removeCommands(commands); editor.removeEventListener('copy', this.onCopy); editor.removeEventListener('paste', this.onPaste); + editor.$emacsModeHandler = null; }; var $kbSessionChange = function(e) { @@ -710,7 +795,7 @@ exports.handler.onCopy = function(e, editor) { if (editor.$handlesEmacsOnCopy) return; editor.$handlesEmacsOnCopy = true; exports.handler.commands.killRingSave.exec(editor); - delete editor.$handlesEmacsOnCopy; + editor.$handlesEmacsOnCopy = false; }; exports.handler.onPaste = function(e, editor) { @@ -718,6 +803,8 @@ exports.handler.onPaste = function(e, editor) { }; exports.handler.bindKey = function(key, command) { + if (typeof key == "object") + key = key[this.platform]; if (!key) return; @@ -735,10 +822,20 @@ exports.handler.bindKey = function(key, command) { }, this); }; +exports.handler.getStatusText = function(editor, data) { + var str = ""; + if (data.count) + str += data.count; + if (data.keyChain) + str += " " + data.keyChain + return str; +}; + exports.handler.handleKeyboard = function(data, hashId, key, keyCode) { if (keyCode === -1) return undefined; var editor = data.editor; + editor._signal("changeStatus"); if (hashId == -1) { editor.pushEmacsMark(); if (data.count) { @@ -748,20 +845,15 @@ exports.handler.handleKeyboard = function(data, hashId, key, keyCode) { } } - if (key == "\x00") return undefined; - var modifier = eMods[hashId]; - if (modifier == "c-" || data.universalArgument) { - var prevCount = String(data.count || 0); + if (modifier == "c-" || data.count) { var count = parseInt(key[key.length - 1]); if (typeof count === 'number' && !isNaN(count)) { - data.count = parseInt(prevCount + count); + data.count = Math.max(data.count, 0) || 0; + data.count = 10 * data.count + count; return {command: "null"}; - } else if (data.universalArgument) { - data.count = 4; } } - data.universalArgument = false; if (modifier) key = modifier + key; if (data.keyChain) key = data.keyChain += " " + key; var command = this.commandKeyBinding[key]; @@ -770,7 +862,7 @@ exports.handler.handleKeyboard = function(data, hashId, key, keyCode) { if (command === "null") return {command: "null"}; if (command === "universalArgument") { - data.universalArgument = true; + data.count = -4; return {command: "null"}; } var args; @@ -809,7 +901,8 @@ exports.handler.handleKeyboard = function(data, hashId, key, keyCode) { exec: function(editor, args) { for (var i = 0; i < count; i++) command.exec(editor, args); - } + }, + multiSelectAction: command.multiSelectAction } }; } else { @@ -915,53 +1008,56 @@ exports.handler.addCommands({ }, setMark: { exec: function(editor, args) { + if (args && args.count) { - var mark = editor.popEmacsMark(); - mark && editor.selection.moveCursorToPosition(mark); + if (editor.inMultiSelectMode) editor.forEachSelection(moveToMark); + else moveToMark(); + moveToMark(); return; } var mark = editor.emacsMark(), - transientMarkModeActive = true; - if (transientMarkModeActive && (mark || !editor.selection.isEmpty())) { - editor.pushEmacsMark(); - editor.clearSelection(); + ranges = editor.selection.getAllRanges(), + rangePositions = ranges.map(function(r) { return {row: r.start.row, column: r.start.column}; }), + transientMarkModeActive = true, + hasNoSelection = ranges.every(function(range) { return range.isEmpty(); }); + if (transientMarkModeActive && (mark || !hasNoSelection)) { + if (editor.inMultiSelectMode) editor.forEachSelection({exec: editor.clearSelection.bind(editor)}) + else editor.clearSelection(); + if (mark) editor.pushEmacsMark(null); return; } - if (mark) { - var cp = editor.getCursorPosition(); - if (editor.selection.isEmpty() && - mark.row == cp.row && mark.column == cp.column) { - editor.pushEmacsMark(); - return; - } + if (!mark) { + rangePositions.forEach(function(pos) { editor.pushEmacsMark(pos); }); + editor.setEmacsMark(rangePositions[rangePositions.length-1]); + return; } - mark = editor.getCursorPosition(); - editor.setEmacsMark(mark); - editor.selection.setSelectionAnchor(mark.row, mark.column); + + function moveToMark() { + var mark = editor.popEmacsMark(); + mark && editor.moveCursorToPosition(mark); + } + }, readOnly: true, - handlesCount: true, - multiSelectAction: "forEach" + handlesCount: true }, exchangePointAndMark: { - exec: function(editor, args) { + exec: function exchangePointAndMark$exec(editor, args) { var sel = editor.selection; - if (args.count) { - var pos = editor.getCursorPosition(); + if (!args.count && !sel.isEmpty()) { // just invert selection + sel.setSelectionRange(sel.getRange(), !sel.isBackwards()); + return; + } + + if (args.count) { // replace mark and point + var pos = {row: sel.lead.row, column: sel.lead.column}; sel.clearSelection(); - sel.moveCursorToPosition(editor.popEmacsMark()); - editor.pushEmacsMark(pos); - return; + sel.moveCursorToPosition(editor.emacsMarkForSelection(pos)); + } else { // create selection to last mark + sel.selectToPosition(editor.emacsMarkForSelection()); } - var lastMark = editor.getLastEmacsMark(); - var range = sel.getRange(); - if (range.isEmpty()) { - sel.selectToPosition(lastMark); - return; - } - sel.setSelectionRange(range, !sel.isBackwards()); }, readOnly: true, handlesCount: true, @@ -1009,6 +1105,7 @@ exports.handler.addCommands({ if (editor.keyBinding.$data.lastCommand != "yank") return; editor.undo(); + editor.session.$emacsMarkRing.pop(); // also undo recording mark editor.onPaste(exports.killRing.rotate()); editor.keyBinding.$data.lastCommand = "yank"; }, @@ -1022,12 +1119,23 @@ exports.handler.addCommands({ }, killRingSave: { exec: function(editor) { + + editor.$handlesEmacsOnCopy = true; + var marks = editor.session.$emacsMarkRing.slice(), + deselectedMarks = []; exports.killRing.add(editor.getCopyText()); + setTimeout(function() { - var sel = editor.selection, - range = sel.getRange(); - editor.pushEmacsMark(sel.isBackwards() ? range.end : range.start); - sel.clearSelection(); + function deselect() { + var sel = editor.selection, range = sel.getRange(), + pos = sel.isBackwards() ? range.end : range.start; + deselectedMarks.push({row: pos.row, column: pos.column}); + sel.clearSelection(); + } + editor.$handlesEmacsOnCopy = false; + if (editor.inMultiSelectMode) editor.forEachSelection({exec: deselect}); + else deselect(); + editor.session.$emacsMarkRing = marks.concat(deselectedMarks.reverse()); }, 0); }, readOnly: true @@ -1035,6 +1143,7 @@ exports.handler.addCommands({ keyboardQuit: function(editor) { editor.selection.clearSelection(); editor.setEmacsMark(null); + editor.keyBinding.$data.count = null; }, focusCommandLine: function(editor, arg) { if (editor.showCommandLine) diff --git a/lib/client/edit/mode-autohotkey.js b/lib/client/edit/mode-autohotkey.js index 9550e676..986d0437 100644 --- a/lib/client/edit/mode-autohotkey.js +++ b/lib/client/edit/mode-autohotkey.js @@ -180,7 +180,7 @@ var Mode = function() { oop.inherits(Mode, TextMode); (function() { - this.lineCommentStart = "/\\*"; + this.lineCommentStart = ";"; this.blockComment = {start: "/*", end: "*/"}; this.$id = "ace/mode/autohotkey"; }).call(Mode.prototype); diff --git a/lib/client/edit/mode-c_cpp.js b/lib/client/edit/mode-c_cpp.js index 03d0eb5c..5e8a4ee0 100644 --- a/lib/client/edit/mode-c_cpp.js +++ b/lib/client/edit/mode-c_cpp.js @@ -5,22 +5,28 @@ var oop = require("../lib/oop"); var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; var DocCommentHighlightRules = function() { - this.$rules = { "start" : [ { token : "comment.doc.tag", regex : "@[\\w\\d_]+" // TODO: fix email addresses - }, { - token : "comment.doc.tag", - regex : "\\bTODO\\b" - }, { - defaultToken : "comment.doc" + }, + DocCommentHighlightRules.getTagRule(), + { + defaultToken : "comment.doc", + caseInsensitive: true }] }; }; oop.inherits(DocCommentHighlightRules, TextHighlightRules); +DocCommentHighlightRules.getTagRule = function(start) { + return { + token : "comment.doc.tag.storage.type", + regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b" + }; +} + DocCommentHighlightRules.getStartRule = function(start) { return { token : "comment.doc", // doc comment @@ -89,11 +95,12 @@ var c_cppHighlightRules = function() { var identifierRe = "[a-zA-Z\\$_\u00a1-\uffff][a-zA-Z\d\\$_\u00a1-\uffff]*\\b"; - this.$rules = { + this.$rules = { "start" : [ { token : "comment", - regex : "\\/\\/.*$" + regex : "//", + next : "singleLineComment" }, DocCommentHighlightRules.getStartRule("doc-start"), { @@ -160,14 +167,26 @@ var c_cppHighlightRules = function() { regex : ".+" } ], + "singleLineComment" : [ + { + token : "comment", + regex : /\\$/, + next : "singleLineComment" + }, { + token : "comment", + regex : /$/, + next : "start" + }, { + defaultToken: "comment" + } + ], "qqstring" : [ { token : "string", regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"', next : "start" }, { - token : "string", - regex : '.+' + defaultToken : "string" } ], "qstring" : [ @@ -176,8 +195,7 @@ var c_cppHighlightRules = function() { regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'", next : "start" }, { - token : "string", - regex : '.+' + defaultToken : "string" } ], "directive" : [ @@ -275,11 +293,11 @@ var SAFE_INSERT_BEFORE_TOKENS = ["text", "paren.rparen", "punctuation.operator", "comment"]; var context; -var contextCache = {} +var contextCache = {}; var initContext = function(editor) { var id = -1; if (editor.multiSelect) { - id = editor.selection.id; + id = editor.selection.index; if (contextCache.rangeCount != editor.multiSelect.rangeCount) contextCache = {rangeCount: editor.multiSelect.rangeCount}; } diff --git a/lib/client/edit/mode-coffee.js b/lib/client/edit/mode-coffee.js index a04262dd..43da83ea 100644 --- a/lib/client/edit/mode-coffee.js +++ b/lib/client/edit/mode-coffee.js @@ -112,7 +112,7 @@ ace.define("ace/mode/coffee_highlight_rules",["require","exports","module","ace/ } if (val == "}" && stack.length) { stack.shift(); - this.next = stack.shift(); + this.next = stack.shift() || ""; if (this.next.indexOf("string") != -1) return "paren.string"; } diff --git a/lib/client/edit/mode-coldfusion.js b/lib/client/edit/mode-coldfusion.js index 6458306b..1d32095f 100644 --- a/lib/client/edit/mode-coldfusion.js +++ b/lib/client/edit/mode-coldfusion.js @@ -5,22 +5,28 @@ var oop = require("../lib/oop"); var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; var DocCommentHighlightRules = function() { - this.$rules = { "start" : [ { token : "comment.doc.tag", regex : "@[\\w\\d_]+" // TODO: fix email addresses - }, { - token : "comment.doc.tag", - regex : "\\bTODO\\b" - }, { - defaultToken : "comment.doc" + }, + DocCommentHighlightRules.getTagRule(), + { + defaultToken : "comment.doc", + caseInsensitive: true }] }; }; oop.inherits(DocCommentHighlightRules, TextHighlightRules); +DocCommentHighlightRules.getTagRule = function(start) { + return { + token : "comment.doc.tag.storage.type", + regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b" + }; +} + DocCommentHighlightRules.getStartRule = function(start) { return { token : "comment.doc", // doc comment @@ -292,20 +298,24 @@ var JavaScriptHighlightRules = function(options) { } ], "comment_regex_allowed" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "\\*\\/", next : "start"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "comment" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "\\*\\/", next : "no_regex"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "line_comment_regex_allowed" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "$|^", next : "start"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "line_comment" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "$|^", next : "no_regex"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "qqstring" : [ { @@ -444,11 +454,11 @@ var SAFE_INSERT_BEFORE_TOKENS = ["text", "paren.rparen", "punctuation.operator", "comment"]; var context; -var contextCache = {} +var contextCache = {}; var initContext = function(editor) { var id = -1; if (editor.multiSelect) { - id = editor.selection.id; + id = editor.selection.index; if (contextCache.rangeCount != editor.multiSelect.rangeCount) contextCache = {rangeCount: editor.multiSelect.rangeCount}; } @@ -1554,12 +1564,13 @@ oop.inherits(HtmlHighlightRules, XmlHighlightRules); exports.HtmlHighlightRules = HtmlHighlightRules; }); -ace.define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator"], function(require, exports, module) { +ace.define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"], function(require, exports, module) { "use strict"; var oop = require("../../lib/oop"); var Behaviour = require("../behaviour").Behaviour; var TokenIterator = require("../../token_iterator").TokenIterator; +var lang = require("../../lib/lang"); function is(token, type) { return token.type.lastIndexOf(type + ".xml") > -1; @@ -1657,29 +1668,56 @@ var XmlBehaviour = function () { return; return { - text: '>' + '', + text: ">" + "", selection: [1, 1] }; } }); - this.add('autoindent', 'insertion', function (state, action, editor, session, text) { + this.add("autoindent", "insertion", function (state, action, editor, session, text) { if (text == "\n") { var cursor = editor.getCursorPosition(); var line = session.getLine(cursor.row); - var rightChars = line.substring(cursor.column, cursor.column + 2); - if (rightChars == ' -1; @@ -1657,29 +1668,56 @@ var XmlBehaviour = function () { return; return { - text: '>' + '', + text: ">" + "", selection: [1, 1] }; } }); - this.add('autoindent', 'insertion', function (state, action, editor, session, text) { + this.add("autoindent", "insertion", function (state, action, editor, session, text) { if (text == "\n") { var cursor = editor.getCursorPosition(); var line = session.getLine(cursor.row); - var rightChars = line.substring(cursor.column, cursor.column + 2); - if (rightChars == ' -1; @@ -1657,29 +1668,56 @@ var XmlBehaviour = function () { return; return { - text: '>' + '', + text: ">" + "", selection: [1, 1] }; } }); - this.add('autoindent', 'insertion', function (state, action, editor, session, text) { + this.add("autoindent", "insertion", function (state, action, editor, session, text) { if (text == "\n") { var cursor = editor.getCursorPosition(); var line = session.getLine(cursor.row); - var rightChars = line.substring(cursor.column, cursor.column + 2); - if (rightChars == ' -1; @@ -1657,29 +1668,56 @@ var XmlBehaviour = function () { return; return { - text: '>' + '', + text: ">" + "", selection: [1, 1] }; } }); - this.add('autoindent', 'insertion', function (state, action, editor, session, text) { + this.add("autoindent", "insertion", function (state, action, editor, session, text) { if (text == "\n") { var cursor = editor.getCursorPosition(); var line = session.getLine(cursor.row); - var rightChars = line.substring(cursor.column, cursor.column + 2); - if (rightChars == ' -1; @@ -1657,29 +1668,56 @@ var XmlBehaviour = function () { return; return { - text: '>' + '', + text: ">" + "", selection: [1, 1] }; } }); - this.add('autoindent', 'insertion', function (state, action, editor, session, text) { + this.add("autoindent", "insertion", function (state, action, editor, session, text) { if (text == "\n") { var cursor = editor.getCursorPosition(); var line = session.getLine(cursor.row); - var rightChars = line.substring(cursor.column, cursor.column + 2); - if (rightChars == ' -1; @@ -1657,29 +1668,56 @@ var XmlBehaviour = function () { return; return { - text: '>' + '', + text: ">" + "", selection: [1, 1] }; } }); - this.add('autoindent', 'insertion', function (state, action, editor, session, text) { + this.add("autoindent", "insertion", function (state, action, editor, session, text) { if (text == "\n") { var cursor = editor.getCursorPosition(); var line = session.getLine(cursor.row); - var rightChars = line.substring(cursor.column, cursor.column + 2); - if (rightChars == ' -1; @@ -1937,29 +2009,56 @@ var XmlBehaviour = function () { return; return { - text: '>' + '', + text: ">" + "", selection: [1, 1] }; } }); - this.add('autoindent', 'insertion', function (state, action, editor, session, text) { + this.add("autoindent", "insertion", function (state, action, editor, session, text) { if (text == "\n") { var cursor = editor.getCursorPosition(); var line = session.getLine(cursor.row); - var rightChars = line.substring(cursor.column, cursor.column + 2); - if (rightChars == ' -1; @@ -2530,29 +2531,56 @@ var XmlBehaviour = function () { return; return { - text: '>' + '', + text: ">" + "", selection: [1, 1] }; } }); - this.add('autoindent', 'insertion', function (state, action, editor, session, text) { + this.add("autoindent", "insertion", function (state, action, editor, session, text) { if (text == "\n") { var cursor = editor.getCursorPosition(); var line = session.getLine(cursor.row); - var rightChars = line.substring(cursor.column, cursor.column + 2); - if (rightChars == ' "a"}; - } - } - - return [val]; - }}, - {regex: /}/, onMatch: function(val, state, stack) { - return [stack.length ? stack.shift() : val]; - }}, - {regex: /\$(?:\d+|\w+)/, onMatch: TabstopToken}, - {regex: /\$\{[\dA-Z_a-z]+/, onMatch: function(str, state, stack) { - var t = TabstopToken(str.substr(1), state, stack); - stack.unshift(t[0]); - return t; - }, next: "snippetVar"}, - {regex: /\n/, token: "newline", merge: false} - ], - snippetVar: [ - {regex: "\\|" + escape("\\|") + "*\\|", onMatch: function(val, state, stack) { - stack[0].choices = val.slice(1, -1).split(","); - }, next: "start"}, - {regex: "/(" + escape("/") + "+)/(?:(" + escape("/") + "*)/)(\\w*):?", - onMatch: function(val, state, stack) { - var ts = stack[0]; - ts.fmtString = val; - - val = this.splitRegex.exec(val); - ts.guard = val[1]; - ts.fmt = val[2]; - ts.flag = val[3]; - return ""; - }, next: "start"}, - {regex: "`" + escape("`") + "*`", onMatch: function(val, state, stack) { - stack[0].code = val.splice(1, -1); - return ""; - }, next: "start"}, - {regex: "\\?", onMatch: function(val, state, stack) { - if (stack[0]) - stack[0].expectIf = true; - }, next: "start"}, - {regex: "([^:}\\\\]|\\\\.)*:?", token: "", next: "start"} - ], - formatString: [ - {regex: "/(" + escape("/") + "+)/", token: "regex"}, - {regex: "", onMatch: function(val, state, stack) { - stack.inFormatString = true; - }, next: "start"} - ] - }); - SnippetManager.prototype.getTokenizer = function() { - return SnippetManager.$tokenizer; - }; - return SnippetManager.$tokenizer; - }; - - this.tokenizeTmSnippet = function(str, startState) { - return this.getTokenizer().getLineTokens(str, startState).tokens.map(function(x) { - return x.value || x; - }); - }; - - this.$getDefaultValue = function(editor, name) { - if (/^[A-Z]\d+$/.test(name)) { - var i = name.substr(1); - return (this.variables[name[0] + "__"] || {})[i]; - } - if (/^\d+$/.test(name)) { - return (this.variables.__ || {})[name]; - } - name = name.replace(/^TM_/, ""); - - if (!editor) - return; - var s = editor.session; - switch(name) { - case "CURRENT_WORD": - var r = s.getWordRange(); - case "SELECTION": - case "SELECTED_TEXT": - return s.getTextRange(r); - case "CURRENT_LINE": - return s.getLine(editor.getCursorPosition().row); - case "PREV_LINE": // not possible in textmate - return s.getLine(editor.getCursorPosition().row - 1); - case "LINE_INDEX": - return editor.getCursorPosition().column; - case "LINE_NUMBER": - return editor.getCursorPosition().row + 1; - case "SOFT_TABS": - return s.getUseSoftTabs() ? "YES" : "NO"; - case "TAB_SIZE": - return s.getTabSize(); - case "FILENAME": - case "FILEPATH": - return ""; - case "FULLNAME": - return "Ace"; - } - }; - this.variables = {}; - this.getVariableValue = function(editor, varName) { - if (this.variables.hasOwnProperty(varName)) - return this.variables[varName](editor, varName) || ""; - return this.$getDefaultValue(editor, varName) || ""; - }; - this.tmStrFormat = function(str, ch, editor) { - var flag = ch.flag || ""; - var re = ch.guard; - re = new RegExp(re, flag.replace(/[^gi]/, "")); - var fmtTokens = this.tokenizeTmSnippet(ch.fmt, "formatString"); - var _self = this; - var formatted = str.replace(re, function() { - _self.variables.__ = arguments; - var fmtParts = _self.resolveVariables(fmtTokens, editor); - var gChangeCase = "E"; - for (var i = 0; i < fmtParts.length; i++) { - var ch = fmtParts[i]; - if (typeof ch == "object") { - fmtParts[i] = ""; - if (ch.changeCase && ch.local) { - var next = fmtParts[i + 1]; - if (next && typeof next == "string") { - if (ch.changeCase == "u") - fmtParts[i] = next[0].toUpperCase(); - else - fmtParts[i] = next[0].toLowerCase(); - fmtParts[i + 1] = next.substr(1); - } - } else if (ch.changeCase) { - gChangeCase = ch.changeCase; - } - } else if (gChangeCase == "U") { - fmtParts[i] = ch.toUpperCase(); - } else if (gChangeCase == "L") { - fmtParts[i] = ch.toLowerCase(); - } - } - return fmtParts.join(""); - }); - this.variables.__ = null; - return formatted; - }; - - this.resolveVariables = function(snippet, editor) { - var result = []; - for (var i = 0; i < snippet.length; i++) { - var ch = snippet[i]; - if (typeof ch == "string") { - result.push(ch); - } else if (typeof ch != "object") { - continue; - } else if (ch.skip) { - gotoNext(ch); - } else if (ch.processed < i) { - continue; - } else if (ch.text) { - var value = this.getVariableValue(editor, ch.text); - if (value && ch.fmtString) - value = this.tmStrFormat(value, ch); - ch.processed = i; - if (ch.expectIf == null) { - if (value) { - result.push(value); - gotoNext(ch); - } - } else { - if (value) { - ch.skip = ch.elseBranch; - } else - gotoNext(ch); - } - } else if (ch.tabstopId != null) { - result.push(ch); - } else if (ch.changeCase != null) { - result.push(ch); - } - } - function gotoNext(ch) { - var i1 = snippet.indexOf(ch, i + 1); - if (i1 != -1) - i = i1; - } - return result; - }; - - this.insertSnippetForSelection = function(editor, snippetText) { - var cursor = editor.getCursorPosition(); - var line = editor.session.getLine(cursor.row); - var tabString = editor.session.getTabString(); - var indentString = line.match(/^\s*/)[0]; - - if (cursor.column < indentString.length) - indentString = indentString.slice(0, cursor.column); - - var tokens = this.tokenizeTmSnippet(snippetText); - tokens = this.resolveVariables(tokens, editor); - tokens = tokens.map(function(x) { - if (x == "\n") - return x + indentString; - if (typeof x == "string") - return x.replace(/\t/g, tabString); - return x; - }); - var tabstops = []; - tokens.forEach(function(p, i) { - if (typeof p != "object") - return; - var id = p.tabstopId; - var ts = tabstops[id]; - if (!ts) { - ts = tabstops[id] = []; - ts.index = id; - ts.value = ""; - } - if (ts.indexOf(p) !== -1) - return; - ts.push(p); - var i1 = tokens.indexOf(p, i + 1); - if (i1 === -1) - return; - - var value = tokens.slice(i + 1, i1); - var isNested = value.some(function(t) {return typeof t === "object"}); - if (isNested && !ts.value) { - ts.value = value; - } else if (value.length && (!ts.value || typeof ts.value !== "string")) { - ts.value = value.join(""); - } - }); - tabstops.forEach(function(ts) {ts.length = 0}); - var expanding = {}; - function copyValue(val) { - var copy = []; - for (var i = 0; i < val.length; i++) { - var p = val[i]; - if (typeof p == "object") { - if (expanding[p.tabstopId]) - continue; - var j = val.lastIndexOf(p, i - 1); - p = copy[j] || {tabstopId: p.tabstopId}; - } - copy[i] = p; - } - return copy; - } - for (var i = 0; i < tokens.length; i++) { - var p = tokens[i]; - if (typeof p != "object") - continue; - var id = p.tabstopId; - var i1 = tokens.indexOf(p, i + 1); - if (expanding[id]) { - if (expanding[id] === p) - expanding[id] = null; - continue; - } - - var ts = tabstops[id]; - var arg = typeof ts.value == "string" ? [ts.value] : copyValue(ts.value); - arg.unshift(i + 1, Math.max(0, i1 - i)); - arg.push(p); - expanding[id] = p; - tokens.splice.apply(tokens, arg); - - if (ts.indexOf(p) === -1) - ts.push(p); - } - var row = 0, column = 0; - var text = ""; - tokens.forEach(function(t) { - if (typeof t === "string") { - if (t[0] === "\n"){ - column = t.length - 1; - row ++; - } else - column += t.length; - text += t; - } else { - if (!t.start) - t.start = {row: row, column: column}; - else - t.end = {row: row, column: column}; - } - }); - var range = editor.getSelectionRange(); - var end = editor.session.replace(range, text); - - var tabstopManager = new TabstopManager(editor); - var selectionId = editor.inVirtualSelectionMode && editor.selection.index; - tabstopManager.addTabstops(tabstops, range.start, end, selectionId); - }; - - this.insertSnippet = function(editor, snippetText) { - var self = this; - if (editor.inVirtualSelectionMode) - return self.insertSnippetForSelection(editor, snippetText); - - editor.forEachSelection(function() { - self.insertSnippetForSelection(editor, snippetText); - }, null, {keepOrder: true}); - - if (editor.tabstopManager) - editor.tabstopManager.tabNext(); - }; - - this.$getScope = function(editor) { - var scope = editor.session.$mode.$id || ""; - scope = scope.split("/").pop(); - if (scope === "html" || scope === "php") { - if (scope === "php" && !editor.session.$mode.inlinePhp) - scope = "html"; - var c = editor.getCursorPosition(); - var state = editor.session.getState(c.row); - if (typeof state === "object") { - state = state[0]; - } - if (state.substring) { - if (state.substring(0, 3) == "js-") - scope = "javascript"; - else if (state.substring(0, 4) == "css-") - scope = "css"; - else if (state.substring(0, 4) == "php-") - scope = "php"; - } - } - - return scope; - }; - - this.getActiveScopes = function(editor) { - var scope = this.$getScope(editor); - var scopes = [scope]; - var snippetMap = this.snippetMap; - if (snippetMap[scope] && snippetMap[scope].includeScopes) { - scopes.push.apply(scopes, snippetMap[scope].includeScopes); - } - scopes.push("_"); - return scopes; - }; - - this.expandWithTab = function(editor, options) { - var self = this; - var result = editor.forEachSelection(function() { - return self.expandSnippetForSelection(editor, options); - }, null, {keepOrder: true}); - if (result && editor.tabstopManager) - editor.tabstopManager.tabNext(); - return result; - }; - - this.expandSnippetForSelection = function(editor, options) { - var cursor = editor.getCursorPosition(); - var line = editor.session.getLine(cursor.row); - var before = line.substring(0, cursor.column); - var after = line.substr(cursor.column); - - var snippetMap = this.snippetMap; - var snippet; - this.getActiveScopes(editor).some(function(scope) { - var snippets = snippetMap[scope]; - if (snippets) - snippet = this.findMatchingSnippet(snippets, before, after); - return !!snippet; - }, this); - if (!snippet) - return false; - if (options && options.dryRun) - return true; - editor.session.doc.removeInLine(cursor.row, - cursor.column - snippet.replaceBefore.length, - cursor.column + snippet.replaceAfter.length - ); - - this.variables.M__ = snippet.matchBefore; - this.variables.T__ = snippet.matchAfter; - this.insertSnippetForSelection(editor, snippet.content); - - this.variables.M__ = this.variables.T__ = null; - return true; - }; - - this.findMatchingSnippet = function(snippetList, before, after) { - for (var i = snippetList.length; i--;) { - var s = snippetList[i]; - if (s.startRe && !s.startRe.test(before)) - continue; - if (s.endRe && !s.endRe.test(after)) - continue; - if (!s.startRe && !s.endRe) - continue; - - s.matchBefore = s.startRe ? s.startRe.exec(before) : [""]; - s.matchAfter = s.endRe ? s.endRe.exec(after) : [""]; - s.replaceBefore = s.triggerRe ? s.triggerRe.exec(before)[0] : ""; - s.replaceAfter = s.endTriggerRe ? s.endTriggerRe.exec(after)[0] : ""; - return s; - } - }; - - this.snippetMap = {}; - this.snippetNameMap = {}; - this.register = function(snippets, scope) { - var snippetMap = this.snippetMap; - var snippetNameMap = this.snippetNameMap; - var self = this; - - if (!snippets) - snippets = []; - - function wrapRegexp(src) { - if (src && !/^\^?\(.*\)\$?$|^\\b$/.test(src)) - src = "(?:" + src + ")"; - - return src || ""; - } - function guardedRegexp(re, guard, opening) { - re = wrapRegexp(re); - guard = wrapRegexp(guard); - if (opening) { - re = guard + re; - if (re && re[re.length - 1] != "$") - re = re + "$"; - } else { - re = re + guard; - if (re && re[0] != "^") - re = "^" + re; - } - return new RegExp(re); - } - - function addSnippet(s) { - if (!s.scope) - s.scope = scope || "_"; - scope = s.scope; - if (!snippetMap[scope]) { - snippetMap[scope] = []; - snippetNameMap[scope] = {}; - } - - var map = snippetNameMap[scope]; - if (s.name) { - var old = map[s.name]; - if (old) - self.unregister(old); - map[s.name] = s; - } - snippetMap[scope].push(s); - - if (s.tabTrigger && !s.trigger) { - if (!s.guard && /^\w/.test(s.tabTrigger)) - s.guard = "\\b"; - s.trigger = lang.escapeRegExp(s.tabTrigger); - } - - s.startRe = guardedRegexp(s.trigger, s.guard, true); - s.triggerRe = new RegExp(s.trigger, "", true); - - s.endRe = guardedRegexp(s.endTrigger, s.endGuard, true); - s.endTriggerRe = new RegExp(s.endTrigger, "", true); - } - - if (snippets && snippets.content) - addSnippet(snippets); - else if (Array.isArray(snippets)) - snippets.forEach(addSnippet); - - this._signal("registerSnippets", {scope: scope}); - }; - this.unregister = function(snippets, scope) { - var snippetMap = this.snippetMap; - var snippetNameMap = this.snippetNameMap; - - function removeSnippet(s) { - var nameMap = snippetNameMap[s.scope||scope]; - if (nameMap && nameMap[s.name]) { - delete nameMap[s.name]; - var map = snippetMap[s.scope||scope]; - var i = map && map.indexOf(s); - if (i >= 0) - map.splice(i, 1); - } - } - if (snippets.content) - removeSnippet(snippets); - else if (Array.isArray(snippets)) - snippets.forEach(removeSnippet); - }; - this.parseSnippetFile = function(str) { - str = str.replace(/\r/g, ""); - var list = [], snippet = {}; - var re = /^#.*|^({[\s\S]*})\s*$|^(\S+) (.*)$|^((?:\n*\t.*)+)/gm; - var m; - while (m = re.exec(str)) { - if (m[1]) { - try { - snippet = JSON.parse(m[1]); - list.push(snippet); - } catch (e) {} - } if (m[4]) { - snippet.content = m[4].replace(/^\t/gm, ""); - list.push(snippet); - snippet = {}; - } else { - var key = m[2], val = m[3]; - if (key == "regex") { - var guardRe = /\/((?:[^\/\\]|\\.)*)|$/g; - snippet.guard = guardRe.exec(val)[1]; - snippet.trigger = guardRe.exec(val)[1]; - snippet.endTrigger = guardRe.exec(val)[1]; - snippet.endGuard = guardRe.exec(val)[1]; - } else if (key == "snippet") { - snippet.tabTrigger = val.match(/^\S*/)[0]; - if (!snippet.name) - snippet.name = val; - } else { - snippet[key] = val; - } - } - } - return list; - }; - this.getSnippetByName = function(name, editor) { - var snippetMap = this.snippetNameMap; - var snippet; - this.getActiveScopes(editor).some(function(scope) { - var snippets = snippetMap[scope]; - if (snippets) - snippet = snippets[name]; - return !!snippet; - }, this); - return snippet; - }; - -}).call(SnippetManager.prototype); - - -var TabstopManager = function(editor) { - if (editor.tabstopManager) - return editor.tabstopManager; - editor.tabstopManager = this; - this.$onChange = this.onChange.bind(this); - this.$onChangeSelection = lang.delayedCall(this.onChangeSelection.bind(this)).schedule; - this.$onChangeSession = this.onChangeSession.bind(this); - this.$onAfterExec = this.onAfterExec.bind(this); - this.attach(editor); -}; -(function() { - this.attach = function(editor) { - this.index = 0; - this.ranges = []; - this.tabstops = []; - this.$openTabstops = null; - this.selectedTabstop = null; - - this.editor = editor; - this.editor.on("change", this.$onChange); - this.editor.on("changeSelection", this.$onChangeSelection); - this.editor.on("changeSession", this.$onChangeSession); - this.editor.commands.on("afterExec", this.$onAfterExec); - this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler); - }; - this.detach = function() { - this.tabstops.forEach(this.removeTabstopMarkers, this); - this.ranges = null; - this.tabstops = null; - this.selectedTabstop = null; - this.editor.removeListener("change", this.$onChange); - this.editor.removeListener("changeSelection", this.$onChangeSelection); - this.editor.removeListener("changeSession", this.$onChangeSession); - this.editor.commands.removeListener("afterExec", this.$onAfterExec); - this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler); - this.editor.tabstopManager = null; - this.editor = null; - }; - - this.onChange = function(e) { - var changeRange = e.data.range; - var isRemove = e.data.action[0] == "r"; - var start = changeRange.start; - var end = changeRange.end; - var startRow = start.row; - var endRow = end.row; - var lineDif = endRow - startRow; - var colDiff = end.column - start.column; - - if (isRemove) { - lineDif = -lineDif; - colDiff = -colDiff; - } - if (!this.$inChange && isRemove) { - var ts = this.selectedTabstop; - var changedOutside = ts && !ts.some(function(r) { - return comparePoints(r.start, start) <= 0 && comparePoints(r.end, end) >= 0; - }); - if (changedOutside) - return this.detach(); - } - var ranges = this.ranges; - for (var i = 0; i < ranges.length; i++) { - var r = ranges[i]; - if (r.end.row < start.row) - continue; - - if (isRemove && comparePoints(start, r.start) < 0 && comparePoints(end, r.end) > 0) { - this.removeRange(r); - i--; - continue; - } - - if (r.start.row == startRow && r.start.column > start.column) - r.start.column += colDiff; - if (r.end.row == startRow && r.end.column >= start.column) - r.end.column += colDiff; - if (r.start.row >= startRow) - r.start.row += lineDif; - if (r.end.row >= startRow) - r.end.row += lineDif; - - if (comparePoints(r.start, r.end) > 0) - this.removeRange(r); - } - if (!ranges.length) - this.detach(); - }; - this.updateLinkedFields = function() { - var ts = this.selectedTabstop; - if (!ts || !ts.hasLinkedRanges) - return; - this.$inChange = true; - var session = this.editor.session; - var text = session.getTextRange(ts.firstNonLinked); - for (var i = ts.length; i--;) { - var range = ts[i]; - if (!range.linked) - continue; - var fmt = exports.snippetManager.tmStrFormat(text, range.original); - session.replace(range, fmt); - } - this.$inChange = false; - }; - this.onAfterExec = function(e) { - if (e.command && !e.command.readOnly) - this.updateLinkedFields(); - }; - this.onChangeSelection = function() { - if (!this.editor) - return; - var lead = this.editor.selection.lead; - var anchor = this.editor.selection.anchor; - var isEmpty = this.editor.selection.isEmpty(); - for (var i = this.ranges.length; i--;) { - if (this.ranges[i].linked) - continue; - var containsLead = this.ranges[i].contains(lead.row, lead.column); - var containsAnchor = isEmpty || this.ranges[i].contains(anchor.row, anchor.column); - if (containsLead && containsAnchor) - return; - } - this.detach(); - }; - this.onChangeSession = function() { - this.detach(); - }; - this.tabNext = function(dir) { - var max = this.tabstops.length; - var index = this.index + (dir || 1); - index = Math.min(Math.max(index, 1), max); - if (index == max) - index = 0; - this.selectTabstop(index); - if (index === 0) - this.detach(); - }; - this.selectTabstop = function(index) { - this.$openTabstops = null; - var ts = this.tabstops[this.index]; - if (ts) - this.addTabstopMarkers(ts); - this.index = index; - ts = this.tabstops[this.index]; - if (!ts || !ts.length) - return; - - this.selectedTabstop = ts; - if (!this.editor.inVirtualSelectionMode) { - var sel = this.editor.multiSelect; - sel.toSingleRange(ts.firstNonLinked.clone()); - for (var i = ts.length; i--;) { - if (ts.hasLinkedRanges && ts[i].linked) - continue; - sel.addRange(ts[i].clone(), true); - } - if (sel.ranges[0]) - sel.addRange(sel.ranges[0].clone()); - } else { - this.editor.selection.setRange(ts.firstNonLinked); - } - - this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler); - }; - this.addTabstops = function(tabstops, start, end) { - if (!this.$openTabstops) - this.$openTabstops = []; - if (!tabstops[0]) { - var p = Range.fromPoints(end, end); - moveRelative(p.start, start); - moveRelative(p.end, start); - tabstops[0] = [p]; - tabstops[0].index = 0; - } - - var i = this.index; - var arg = [i + 1, 0]; - var ranges = this.ranges; - tabstops.forEach(function(ts, index) { - var dest = this.$openTabstops[index] || ts; - - for (var i = ts.length; i--;) { - var p = ts[i]; - var range = Range.fromPoints(p.start, p.end || p.start); - movePoint(range.start, start); - movePoint(range.end, start); - range.original = p; - range.tabstop = dest; - ranges.push(range); - if (dest != ts) - dest.unshift(range); - else - dest[i] = range; - if (p.fmtString) { - range.linked = true; - dest.hasLinkedRanges = true; - } else if (!dest.firstNonLinked) - dest.firstNonLinked = range; - } - if (!dest.firstNonLinked) - dest.hasLinkedRanges = false; - if (dest === ts) { - arg.push(dest); - this.$openTabstops[index] = dest; - } - this.addTabstopMarkers(dest); - }, this); - - if (arg.length > 2) { - if (this.tabstops.length) - arg.push(arg.splice(2, 1)[0]); - this.tabstops.splice.apply(this.tabstops, arg); - } - }; - - this.addTabstopMarkers = function(ts) { - var session = this.editor.session; - ts.forEach(function(range) { - if (!range.markerId) - range.markerId = session.addMarker(range, "ace_snippet-marker", "text"); - }); - }; - this.removeTabstopMarkers = function(ts) { - var session = this.editor.session; - ts.forEach(function(range) { - session.removeMarker(range.markerId); - range.markerId = null; - }); - }; - this.removeRange = function(range) { - var i = range.tabstop.indexOf(range); - range.tabstop.splice(i, 1); - i = this.ranges.indexOf(range); - this.ranges.splice(i, 1); - this.editor.session.removeMarker(range.markerId); - if (!range.tabstop.length) { - i = this.tabstops.indexOf(range.tabstop); - if (i != -1) - this.tabstops.splice(i, 1); - if (!this.tabstops.length) - this.detach(); - } - }; - - this.keyboardHandler = new HashHandler(); - this.keyboardHandler.bindKeys({ - "Tab": function(ed) { - if (exports.snippetManager && exports.snippetManager.expandWithTab(ed)) { - return; - } - - ed.tabstopManager.tabNext(1); - }, - "Shift-Tab": function(ed) { - ed.tabstopManager.tabNext(-1); - }, - "Esc": function(ed) { - ed.tabstopManager.detach(); - }, - "Return": function(ed) { - return false; - } - }); -}).call(TabstopManager.prototype); - - - -var changeTracker = {}; -changeTracker.onChange = Anchor.prototype.onChange; -changeTracker.setPosition = function(row, column) { - this.pos.row = row; - this.pos.column = column; -}; -changeTracker.update = function(pos, delta, $insertRight) { - this.$insertRight = $insertRight; - this.pos = pos; - this.onChange(delta); -}; - -var movePoint = function(point, diff) { - if (point.row == 0) - point.column += diff.column; - point.row += diff.row; -}; - -var moveRelative = function(point, start) { - if (point.row == start.row) - point.column -= start.column; - point.row -= start.row; -}; - - -require("./lib/dom").importCssString("\ -.ace_snippet-marker {\ - -moz-box-sizing: border-box;\ - box-sizing: border-box;\ - background: rgba(194, 193, 208, 0.09);\ - border: 1px dotted rgba(211, 208, 235, 0.62);\ - position: absolute;\ -}"); - -exports.snippetManager = new SnippetManager(); - - -var Editor = require("./editor").Editor; -(function() { - this.insertSnippet = function(content, options) { - return exports.snippetManager.insertSnippet(this, content, options); - }; - this.expandSnippet = function(options) { - return exports.snippetManager.expandWithTab(this, options); - }; -}).call(Editor.prototype); - -}); - -ace.define("ace/autocomplete/popup",["require","exports","module","ace/edit_session","ace/virtual_renderer","ace/editor","ace/range","ace/lib/event","ace/lib/lang","ace/lib/dom"], function(require, exports, module) { -"use strict"; - -var EditSession = require("../edit_session").EditSession; -var Renderer = require("../virtual_renderer").VirtualRenderer; -var Editor = require("../editor").Editor; -var Range = require("../range").Range; -var event = require("../lib/event"); -var lang = require("../lib/lang"); -var dom = require("../lib/dom"); - -var $singleLineEditor = function(el) { - var renderer = new Renderer(el); - - renderer.$maxLines = 4; - - var editor = new Editor(renderer); - - editor.setHighlightActiveLine(false); - editor.setShowPrintMargin(false); - editor.renderer.setShowGutter(false); - editor.renderer.setHighlightGutterLine(false); - - editor.$mouseHandler.$focusWaitTimout = 0; - editor.$highlightTagPending = true; - - return editor; -}; - -var AcePopup = function(parentNode) { - var el = dom.createElement("div"); - var popup = new $singleLineEditor(el); - - if (parentNode) - parentNode.appendChild(el); - el.style.display = "none"; - popup.renderer.content.style.cursor = "default"; - popup.renderer.setStyle("ace_autocomplete"); - - popup.setOption("displayIndentGuides", false); - popup.setOption("dragDelay", 150); - - var noop = function(){}; - - popup.focus = noop; - popup.$isFocused = true; - - popup.renderer.$cursorLayer.restartTimer = noop; - popup.renderer.$cursorLayer.element.style.opacity = 0; - - popup.renderer.$maxLines = 8; - popup.renderer.$keepTextAreaAtCursor = false; - - popup.setHighlightActiveLine(false); - popup.session.highlight(""); - popup.session.$searchHighlight.clazz = "ace_highlight-marker"; - - popup.on("mousedown", function(e) { - var pos = e.getDocumentPosition(); - popup.selection.moveToPosition(pos); - selectionMarker.start.row = selectionMarker.end.row = pos.row; - e.stop(); - }); - - var lastMouseEvent; - var hoverMarker = new Range(-1,0,-1,Infinity); - var selectionMarker = new Range(-1,0,-1,Infinity); - selectionMarker.id = popup.session.addMarker(selectionMarker, "ace_active-line", "fullLine"); - popup.setSelectOnHover = function(val) { - if (!val) { - hoverMarker.id = popup.session.addMarker(hoverMarker, "ace_line-hover", "fullLine"); - } else if (hoverMarker.id) { - popup.session.removeMarker(hoverMarker.id); - hoverMarker.id = null; - } - }; - popup.setSelectOnHover(false); - popup.on("mousemove", function(e) { - if (!lastMouseEvent) { - lastMouseEvent = e; - return; - } - if (lastMouseEvent.x == e.x && lastMouseEvent.y == e.y) { - return; - } - lastMouseEvent = e; - lastMouseEvent.scrollTop = popup.renderer.scrollTop; - var row = lastMouseEvent.getDocumentPosition().row; - if (hoverMarker.start.row != row) { - if (!hoverMarker.id) - popup.setRow(row); - setHoverMarker(row); - } - }); - popup.renderer.on("beforeRender", function() { - if (lastMouseEvent && hoverMarker.start.row != -1) { - lastMouseEvent.$pos = null; - var row = lastMouseEvent.getDocumentPosition().row; - if (!hoverMarker.id) - popup.setRow(row); - setHoverMarker(row, true); - } - }); - popup.renderer.on("afterRender", function() { - var row = popup.getRow(); - var t = popup.renderer.$textLayer; - var selected = t.element.childNodes[row - t.config.firstRow]; - if (selected == t.selectedNode) - return; - if (t.selectedNode) - dom.removeCssClass(t.selectedNode, "ace_selected"); - t.selectedNode = selected; - if (selected) - dom.addCssClass(selected, "ace_selected"); - }); - var hideHoverMarker = function() { setHoverMarker(-1) }; - var setHoverMarker = function(row, suppressRedraw) { - if (row !== hoverMarker.start.row) { - hoverMarker.start.row = hoverMarker.end.row = row; - if (!suppressRedraw) - popup.session._emit("changeBackMarker"); - popup._emit("changeHoverMarker"); - } - }; - popup.getHoveredRow = function() { - return hoverMarker.start.row; - }; - - event.addListener(popup.container, "mouseout", hideHoverMarker); - popup.on("hide", hideHoverMarker); - popup.on("changeSelection", hideHoverMarker); - - popup.session.doc.getLength = function() { - return popup.data.length; - }; - popup.session.doc.getLine = function(i) { - var data = popup.data[i]; - if (typeof data == "string") - return data; - return (data && data.value) || ""; - }; - - var bgTokenizer = popup.session.bgTokenizer; - bgTokenizer.$tokenizeRow = function(row) { - var data = popup.data[row]; - var tokens = []; - if (!data) - return tokens; - if (typeof data == "string") - data = {value: data}; - if (!data.caption) - data.caption = data.value || data.name; - - var last = -1; - var flag, c; - for (var i = 0; i < data.caption.length; i++) { - c = data.caption[i]; - flag = data.matchMask & (1 << i) ? 1 : 0; - if (last !== flag) { - tokens.push({type: data.className || "" + ( flag ? "completion-highlight" : ""), value: c}); - last = flag; - } else { - tokens[tokens.length - 1].value += c; - } - } - - if (data.meta) { - var maxW = popup.renderer.$size.scrollerWidth / popup.renderer.layerConfig.characterWidth; - if (data.meta.length + data.caption.length < maxW - 2) - tokens.push({type: "rightAlignedText", value: data.meta}); - } - return tokens; - }; - bgTokenizer.$updateOnChange = noop; - bgTokenizer.start = noop; - - popup.session.$computeWidth = function() { - return this.screenWidth = 0; - }; - popup.isOpen = false; - popup.isTopdown = false; - - popup.data = []; - popup.setData = function(list) { - popup.data = list || []; - popup.setValue(lang.stringRepeat("\n", list.length), -1); - popup.setRow(0); - }; - popup.getData = function(row) { - return popup.data[row]; - }; - - popup.getRow = function() { - return selectionMarker.start.row; - }; - popup.setRow = function(line) { - line = Math.max(-1, Math.min(this.data.length, line)); - if (selectionMarker.start.row != line) { - popup.selection.clearSelection(); - selectionMarker.start.row = selectionMarker.end.row = line || 0; - popup.session._emit("changeBackMarker"); - popup.moveCursorTo(line || 0, 0); - if (popup.isOpen) - popup._signal("select"); - } - }; - - popup.on("changeSelection", function() { - if (popup.isOpen) - popup.setRow(popup.selection.lead.row); - }); - - popup.hide = function() { - this.container.style.display = "none"; - this._signal("hide"); - popup.isOpen = false; - }; - popup.show = function(pos, lineHeight, topdownOnly) { - var el = this.container; - var screenHeight = window.innerHeight; - var screenWidth = window.innerWidth; - var renderer = this.renderer; - var maxH = renderer.$maxLines * lineHeight * 1.4; - var top = pos.top + this.$borderSize; - if (top + maxH > screenHeight - lineHeight && !topdownOnly) { - el.style.top = ""; - el.style.bottom = screenHeight - top + "px"; - popup.isTopdown = false; - } else { - top += lineHeight; - el.style.top = top + "px"; - el.style.bottom = ""; - popup.isTopdown = true; - } - - el.style.display = ""; - this.renderer.$textLayer.checkForSizeChanges(); - - var left = pos.left; - if (left + el.offsetWidth > screenWidth) - left = screenWidth - el.offsetWidth; - - el.style.left = left + "px"; - - this._signal("show"); - lastMouseEvent = null; - popup.isOpen = true; - }; - - popup.getTextLeftOffset = function() { - return this.$borderSize + this.renderer.$padding + this.$imageSize; - }; - - popup.$imageSize = 0; - popup.$borderSize = 1; - - return popup; -}; - -dom.importCssString("\ -.ace_editor.ace_autocomplete .ace_marker-layer .ace_active-line {\ - background-color: #CAD6FA;\ - z-index: 1;\ -}\ -.ace_editor.ace_autocomplete .ace_line-hover {\ - border: 1px solid #abbffe;\ - margin-top: -1px;\ - background: rgba(233,233,253,0.4);\ -}\ -.ace_editor.ace_autocomplete .ace_line-hover {\ - position: absolute;\ - z-index: 2;\ -}\ -.ace_editor.ace_autocomplete .ace_scroller {\ - background: none;\ - border: none;\ - box-shadow: none;\ -}\ -.ace_rightAlignedText {\ - color: gray;\ - display: inline-block;\ - position: absolute;\ - right: 4px;\ - text-align: right;\ - z-index: -1;\ -}\ -.ace_editor.ace_autocomplete .ace_completion-highlight{\ - color: #000;\ - text-shadow: 0 0 0.01em;\ -}\ -.ace_editor.ace_autocomplete {\ - width: 280px;\ - z-index: 200000;\ - background: #fbfbfb;\ - color: #444;\ - border: 1px lightgray solid;\ - position: fixed;\ - box-shadow: 2px 3px 5px rgba(0,0,0,.2);\ - line-height: 1.4;\ -}"); - -exports.AcePopup = AcePopup; - -}); - -ace.define("ace/autocomplete/util",["require","exports","module"], function(require, exports, module) { -"use strict"; - -exports.parForEach = function(array, fn, callback) { - var completed = 0; - var arLength = array.length; - if (arLength === 0) - callback(); - for (var i = 0; i < arLength; i++) { - fn(array[i], function(result, err) { - completed++; - if (completed === arLength) - callback(result, err); - }); - } -}; - -var ID_REGEX = /[a-zA-Z_0-9\$\-\u00A2-\uFFFF]/; - -exports.retrievePrecedingIdentifier = function(text, pos, regex) { - regex = regex || ID_REGEX; - var buf = []; - for (var i = pos-1; i >= 0; i--) { - if (regex.test(text[i])) - buf.push(text[i]); - else - break; - } - return buf.reverse().join(""); -}; - -exports.retrieveFollowingIdentifier = function(text, pos, regex) { - regex = regex || ID_REGEX; - var buf = []; - for (var i = pos; i < text.length; i++) { - if (regex.test(text[i])) - buf.push(text[i]); - else - break; - } - return buf; -}; - -}); - -ace.define("ace/autocomplete",["require","exports","module","ace/keyboard/hash_handler","ace/autocomplete/popup","ace/autocomplete/util","ace/lib/event","ace/lib/lang","ace/snippets"], function(require, exports, module) { -"use strict"; - -var HashHandler = require("./keyboard/hash_handler").HashHandler; -var AcePopup = require("./autocomplete/popup").AcePopup; -var util = require("./autocomplete/util"); -var event = require("./lib/event"); -var lang = require("./lib/lang"); -var snippetManager = require("./snippets").snippetManager; - -var Autocomplete = function() { - this.autoInsert = true; - this.autoSelect = true; - this.keyboardHandler = new HashHandler(); - this.keyboardHandler.bindKeys(this.commands); - - this.blurListener = this.blurListener.bind(this); - this.changeListener = this.changeListener.bind(this); - this.mousedownListener = this.mousedownListener.bind(this); - this.mousewheelListener = this.mousewheelListener.bind(this); - - this.changeTimer = lang.delayedCall(function() { - this.updateCompletions(true); - }.bind(this)); -}; - -(function() { - this.gatherCompletionsId = 0; - - this.$init = function() { - this.popup = new AcePopup(document.body || document.documentElement); - this.popup.on("click", function(e) { - this.insertMatch(); - e.stop(); - }.bind(this)); - this.popup.focus = this.editor.focus.bind(this.editor); - }; - - this.openPopup = function(editor, prefix, keepPopupPosition) { - if (!this.popup) - this.$init(); - - this.popup.setData(this.completions.filtered); - - var renderer = editor.renderer; - this.popup.setRow(this.autoSelect ? 0 : -1); - if (!keepPopupPosition) { - this.popup.setTheme(editor.getTheme()); - this.popup.setFontSize(editor.getFontSize()); - - var lineHeight = renderer.layerConfig.lineHeight; - - var pos = renderer.$cursorLayer.getPixelPosition(this.base, true); - pos.left -= this.popup.getTextLeftOffset(); - - var rect = editor.container.getBoundingClientRect(); - pos.top += rect.top - renderer.layerConfig.offset; - pos.left += rect.left - editor.renderer.scrollLeft; - pos.left += renderer.$gutterLayer.gutterWidth; - - this.popup.show(pos, lineHeight); - } else if (keepPopupPosition && !prefix) { - this.detach(); - } - }; - - this.detach = function() { - this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler); - this.editor.off("changeSelection", this.changeListener); - this.editor.off("blur", this.blurListener); - this.editor.off("mousedown", this.mousedownListener); - this.editor.off("mousewheel", this.mousewheelListener); - this.changeTimer.cancel(); - - if (this.popup && this.popup.isOpen) { - this.gatherCompletionsId += 1; - this.popup.hide(); - } - - if (this.base) - this.base.detach(); - this.activated = false; - this.completions = this.base = null; - }; - - this.changeListener = function(e) { - var cursor = this.editor.selection.lead; - if (cursor.row != this.base.row || cursor.column < this.base.column) { - this.detach(); - } - if (this.activated) - this.changeTimer.schedule(); - else - this.detach(); - }; - - this.blurListener = function() { - var el = document.activeElement; - if (el != this.editor.textInput.getElement() && el.parentNode != this.popup.container) - this.detach(); - }; - - this.mousedownListener = function(e) { - this.detach(); - }; - - this.mousewheelListener = function(e) { - this.detach(); - }; - - this.goTo = function(where) { - var row = this.popup.getRow(); - var max = this.popup.session.getLength() - 1; - - switch(where) { - case "up": row = row <= 0 ? max : row - 1; break; - case "down": row = row >= max ? -1 : row + 1; break; - case "start": row = 0; break; - case "end": row = max; break; - } - - this.popup.setRow(row); - }; - - this.insertMatch = function(data) { - if (!data) - data = this.popup.getData(this.popup.getRow()); - if (!data) - return false; - - if (data.completer && data.completer.insertMatch) { - data.completer.insertMatch(this.editor); - } else { - if (this.completions.filterText) { - var ranges = this.editor.selection.getAllRanges(); - for (var i = 0, range; range = ranges[i]; i++) { - range.start.column -= this.completions.filterText.length; - this.editor.session.remove(range); - } - } - if (data.snippet) - snippetManager.insertSnippet(this.editor, data.snippet); - else - this.editor.execCommand("insertstring", data.value || data); - } - this.detach(); - }; - - this.commands = { - "Up": function(editor) { editor.completer.goTo("up"); }, - "Down": function(editor) { editor.completer.goTo("down"); }, - "Ctrl-Up|Ctrl-Home": function(editor) { editor.completer.goTo("start"); }, - "Ctrl-Down|Ctrl-End": function(editor) { editor.completer.goTo("end"); }, - - "Esc": function(editor) { editor.completer.detach(); }, - "Space": function(editor) { editor.completer.detach(); editor.insert(" ");}, - "Return": function(editor) { return editor.completer.insertMatch(); }, - "Shift-Return": function(editor) { editor.completer.insertMatch(true); }, - "Tab": function(editor) { - var result = editor.completer.insertMatch(); - if (!result && !editor.tabstopManager) - editor.completer.goTo("down"); - else - return result; - }, - - "PageUp": function(editor) { editor.completer.popup.gotoPageUp(); }, - "PageDown": function(editor) { editor.completer.popup.gotoPageDown(); } - }; - - this.gatherCompletions = function(editor, callback) { - var session = editor.getSession(); - var pos = editor.getCursorPosition(); - - var line = session.getLine(pos.row); - var prefix = util.retrievePrecedingIdentifier(line, pos.column); - - this.base = session.doc.createAnchor(pos.row, pos.column - prefix.length); - this.base.$insertRight = true; - - var matches = []; - var total = editor.completers.length; - editor.completers.forEach(function(completer, i) { - completer.getCompletions(editor, session, pos, prefix, function(err, results) { - if (!err) - matches = matches.concat(results); - var pos = editor.getCursorPosition(); - var line = session.getLine(pos.row); - callback(null, { - prefix: util.retrievePrecedingIdentifier(line, pos.column, results[0] && results[0].identifierRegex), - matches: matches, - finished: (--total === 0) - }); - }); - }); - return true; - }; - - this.showPopup = function(editor) { - if (this.editor) - this.detach(); - - this.activated = true; - - this.editor = editor; - if (editor.completer != this) { - if (editor.completer) - editor.completer.detach(); - editor.completer = this; - } - - editor.keyBinding.addKeyboardHandler(this.keyboardHandler); - editor.on("changeSelection", this.changeListener); - editor.on("blur", this.blurListener); - editor.on("mousedown", this.mousedownListener); - editor.on("mousewheel", this.mousewheelListener); - - this.updateCompletions(); - }; - - this.updateCompletions = function(keepPopupPosition) { - if (keepPopupPosition && this.base && this.completions) { - var pos = this.editor.getCursorPosition(); - var prefix = this.editor.session.getTextRange({start: this.base, end: pos}); - if (prefix == this.completions.filterText) - return; - this.completions.setFilter(prefix); - if (!this.completions.filtered.length) - return this.detach(); - if (this.completions.filtered.length == 1 - && this.completions.filtered[0].value == prefix - && !this.completions.filtered[0].snippet) - return this.detach(); - this.openPopup(this.editor, prefix, keepPopupPosition); - return; - } - var _id = this.gatherCompletionsId; - this.gatherCompletions(this.editor, function(err, results) { - var detachIfFinished = function() { - if (!results.finished) return; - return this.detach(); - }.bind(this); - - var prefix = results.prefix; - var matches = results && results.matches; - - if (!matches || !matches.length) - return detachIfFinished(); - if (prefix.indexOf(results.prefix) !== 0 || _id != this.gatherCompletionsId) - return; - - this.completions = new FilteredList(matches); - this.completions.setFilter(prefix); - var filtered = this.completions.filtered; - if (!filtered.length) - return detachIfFinished(); - if (filtered.length == 1 && filtered[0].value == prefix && !filtered[0].snippet) - return detachIfFinished(); - if (this.autoInsert && filtered.length == 1 && results.finished) - return this.insertMatch(filtered[0]); - - this.openPopup(this.editor, prefix, keepPopupPosition); - }.bind(this)); - }; - - this.cancelContextMenu = function() { - this.editor.$mouseHandler.cancelContextMenu(); - }; - -}).call(Autocomplete.prototype); - -Autocomplete.startCommand = { - name: "startAutocomplete", - exec: function(editor) { - if (!editor.completer) - editor.completer = new Autocomplete(); - editor.completer.autoInsert = - editor.completer.autoSelect = true; - editor.completer.showPopup(editor); - editor.completer.cancelContextMenu(); - }, - bindKey: "Ctrl-Space|Ctrl-Shift-Space|Alt-Space" -}; - -var FilteredList = function(array, filterText, mutateData) { - this.all = array; - this.filtered = array; - this.filterText = filterText || ""; -}; -(function(){ - this.setFilter = function(str) { - if (str.length > this.filterText && str.lastIndexOf(this.filterText, 0) === 0) - var matches = this.filtered; - else - var matches = this.all; - - this.filterText = str; - matches = this.filterCompletions(matches, this.filterText); - matches = matches.sort(function(a, b) { - return b.exactMatch - a.exactMatch || b.score - a.score; - }); - var prev = null; - matches = matches.filter(function(item){ - var caption = item.snippet || item.caption || item.value; - if (caption === prev) return false; - prev = caption; - return true; - }); - - this.filtered = matches; - }; - this.filterCompletions = function(items, needle) { - var results = []; - var upper = needle.toUpperCase(); - var lower = needle.toLowerCase(); - loop: for (var i = 0, item; item = items[i]; i++) { - var caption = item.value || item.caption || item.snippet; - if (!caption) continue; - var lastIndex = -1; - var matchMask = 0; - var penalty = 0; - var index, distance; - for (var j = 0; j < needle.length; j++) { - var i1 = caption.indexOf(lower[j], lastIndex + 1); - var i2 = caption.indexOf(upper[j], lastIndex + 1); - index = (i1 >= 0) ? ((i2 < 0 || i1 < i2) ? i1 : i2) : i2; - if (index < 0) - continue loop; - distance = index - lastIndex - 1; - if (distance > 0) { - if (lastIndex === -1) - penalty += 10; - penalty += distance; - } - matchMask = matchMask | (1 << index); - lastIndex = index; - } - item.matchMask = matchMask; - item.exactMatch = penalty ? 0 : 1; - item.score = (item.score || 0) - penalty; - results.push(item); - } - return results; - }; -}).call(FilteredList.prototype); - -exports.Autocomplete = Autocomplete; -exports.FilteredList = FilteredList; - -}); - -ace.define("ace/autocomplete/text_completer",["require","exports","module","ace/range"], function(require, exports, module) { - var Range = require("../range").Range; - - var splitRegex = /[^a-zA-Z_0-9\$\-\u00C0-\u1FFF\u2C00-\uD7FF\w]+/; - - function getWordIndex(doc, pos) { - var textBefore = doc.getTextRange(Range.fromPoints({row: 0, column:0}, pos)); - return textBefore.split(splitRegex).length - 1; - } - function wordDistance(doc, pos) { - var prefixPos = getWordIndex(doc, pos); - var words = doc.getValue().split(splitRegex); - var wordScores = Object.create(null); - - var currentWord = words[prefixPos]; - - words.forEach(function(word, idx) { - if (!word || word === currentWord) return; - - var distance = Math.abs(prefixPos - idx); - var score = words.length - distance; - if (wordScores[word]) { - wordScores[word] = Math.max(score, wordScores[word]); - } else { - wordScores[word] = score; - } - }); - return wordScores; - } - - exports.getCompletions = function(editor, session, pos, prefix, callback) { - var wordScore = wordDistance(session, pos, prefix); - var wordList = Object.keys(wordScore); - callback(null, wordList.map(function(word) { - return { - caption: word, - value: word, - score: wordScore[word], - meta: "local" - }; - })); - }; -}); - -ace.define("ace/ext/language_tools",["require","exports","module","ace/snippets","ace/autocomplete","ace/config","ace/autocomplete/util","ace/autocomplete/text_completer","ace/editor","ace/config"], function(require, exports, module) { -"use strict"; - -var snippetManager = require("../snippets").snippetManager; -var Autocomplete = require("../autocomplete").Autocomplete; -var config = require("../config"); -var util = require("../autocomplete/util"); - -var textCompleter = require("../autocomplete/text_completer"); -var keyWordCompleter = { - getCompletions: function(editor, session, pos, prefix, callback) { - var state = editor.session.getState(pos.row); - var completions = session.$mode.getCompletions(state, session, pos, prefix); - callback(null, completions); - } -}; - -var snippetCompleter = { - getCompletions: function(editor, session, pos, prefix, callback) { - var snippetMap = snippetManager.snippetMap; - var completions = []; - snippetManager.getActiveScopes(editor).forEach(function(scope) { - var snippets = snippetMap[scope] || []; - for (var i = snippets.length; i--;) { - var s = snippets[i]; - var caption = s.name || s.tabTrigger; - if (!caption) - continue; - completions.push({ - caption: caption, - snippet: s.content, - meta: s.tabTrigger && !s.name ? s.tabTrigger + "\u21E5 " : "snippet" - }); - } - }, this); - callback(null, completions); - } -}; - -var completers = [snippetCompleter, textCompleter, keyWordCompleter]; -exports.addCompleter = function(completer) { - completers.push(completer); -}; -exports.textCompleter = textCompleter; -exports.keyWordCompleter = keyWordCompleter; -exports.snippetCompleter = snippetCompleter; - -var expandSnippet = { - name: "expandSnippet", - exec: function(editor) { - var success = snippetManager.expandWithTab(editor); - if (!success) - editor.execCommand("indent"); - }, - bindKey: "Tab" -}; - -var onChangeMode = function(e, editor) { - loadSnippetsForMode(editor.session.$mode); -}; - -var loadSnippetsForMode = function(mode) { - var id = mode.$id; - if (!snippetManager.files) - snippetManager.files = {}; - loadSnippetFile(id); - if (mode.modes) - mode.modes.forEach(loadSnippetsForMode); -}; - -var loadSnippetFile = function(id) { - if (!id || snippetManager.files[id]) - return; - var snippetFilePath = id.replace("mode", "snippets"); - snippetManager.files[id] = {}; - config.loadModule(snippetFilePath, function(m) { - if (m) { - snippetManager.files[id] = m; - if (!m.snippets && m.snippetText) - m.snippets = snippetManager.parseSnippetFile(m.snippetText); - snippetManager.register(m.snippets || [], m.scope); - if (m.includeScopes) { - snippetManager.snippetMap[m.scope].includeScopes = m.includeScopes; - m.includeScopes.forEach(function(x) { - loadSnippetFile("ace/mode/" + x); - }); - } - } - }); -}; - -function getCompletionPrefix(editor) { - var pos = editor.getCursorPosition(); - var line = editor.session.getLine(pos.row); - var prefix = util.retrievePrecedingIdentifier(line, pos.column); - editor.completers.forEach(function(completer) { - if (completer.identifierRegexps) { - completer.identifierRegexps.forEach(function(identifierRegex) { - if (!prefix && identifierRegex) - prefix = util.retrievePrecedingIdentifier(line, pos.column, identifierRegex); - }); - } - }); - return prefix; -} - -var doLiveAutocomplete = function(e) { - var editor = e.editor; - var text = e.args || ""; - var hasCompleter = editor.completer && editor.completer.activated; - if (e.command.name === "backspace") { - if (hasCompleter && !getCompletionPrefix(editor)) - editor.completer.detach(); - } - else if (e.command.name === "insertstring") { - var prefix = getCompletionPrefix(editor); - if (prefix && !hasCompleter) { - if (!editor.completer) { - editor.completer = new Autocomplete(); - } - editor.completer.autoSelect = false; - editor.completer.autoInsert = false; - editor.completer.showPopup(editor); - } - } -}; - -var Editor = require("../editor").Editor; -require("../config").defineOptions(Editor.prototype, "editor", { - enableBasicAutocompletion: { - set: function(val) { - if (val) { - if (!this.completers) - this.completers = Array.isArray(val)? val: completers; - this.commands.addCommand(Autocomplete.startCommand); - } else { - this.commands.removeCommand(Autocomplete.startCommand); - } - }, - value: false - }, - enableLiveAutocompletion: { - set: function(val) { - if (val) { - if (!this.completers) - this.completers = Array.isArray(val)? val: completers; - this.commands.on('afterExec', doLiveAutocomplete); - } else { - this.commands.removeListener('afterExec', doLiveAutocomplete); - } - }, - value: false - }, - enableSnippets: { - set: function(val) { - if (val) { - this.commands.addCommand(expandSnippet); - this.on("changeMode", onChangeMode); - onChangeMode(null, this); - } else { - this.commands.removeCommand(expandSnippet); - this.off("changeMode", onChangeMode); - } - }, - value: false - } -}); -}); - -ace.define("ace/mode/jsoniq",["require","exports","module","ace/worker/worker_client","ace/lib/oop","ace/mode/text","ace/mode/text_highlight_rules","ace/mode/xquery/jsoniq_lexer","ace/range","ace/mode/behaviour/xquery","ace/mode/folding/cstyle","ace/anchor","ace/ext/language_tools"], function(require, exports, module) { +ace.define("ace/mode/jsoniq",["require","exports","module","ace/worker/worker_client","ace/lib/oop","ace/mode/text","ace/mode/text_highlight_rules","ace/mode/xquery/jsoniq_lexer","ace/range","ace/mode/behaviour/xquery","ace/mode/folding/cstyle","ace/anchor"], function(require, exports, module) { "use strict"; var WorkerClient = require("../worker/worker_client").WorkerClient; @@ -4548,7 +2759,6 @@ var Range = require("../range").Range; var XQueryBehaviour = require("./behaviour/xquery").XQueryBehaviour; var CStyleFoldMode = require("./folding/cstyle").FoldMode; var Anchor = require("../anchor").Anchor; -var LanguageTools = require("../ext/language_tools"); var Mode = function() { this.$tokenizer = new JSONiqLexer(); @@ -4561,14 +2771,16 @@ oop.inherits(Mode, TextMode); (function() { - LanguageTools.addCompleter({ + this.completer = { getCompletions: function(editor, session, pos, prefix, callback) { + if (!session.$worker) + return callback(); session.$worker.emit("complete", { data: { pos: pos, prefix: prefix } }); session.$worker.on("complete", function(e){ callback(null, e.data); }); } - }); + }; this.getNextLineIndent = function(state, line, tab) { var indent = this.$getIndent(line); diff --git a/lib/client/edit/mode-jsp.js b/lib/client/edit/mode-jsp.js index f1ac2c27..17161fe4 100644 --- a/lib/client/edit/mode-jsp.js +++ b/lib/client/edit/mode-jsp.js @@ -149,22 +149,28 @@ var oop = require("../lib/oop"); var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; var DocCommentHighlightRules = function() { - this.$rules = { "start" : [ { token : "comment.doc.tag", regex : "@[\\w\\d_]+" // TODO: fix email addresses - }, { - token : "comment.doc.tag", - regex : "\\bTODO\\b" - }, { - defaultToken : "comment.doc" + }, + DocCommentHighlightRules.getTagRule(), + { + defaultToken : "comment.doc", + caseInsensitive: true }] }; }; oop.inherits(DocCommentHighlightRules, TextHighlightRules); +DocCommentHighlightRules.getTagRule = function(start) { + return { + token : "comment.doc.tag.storage.type", + regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b" + }; +} + DocCommentHighlightRules.getStartRule = function(start) { return { token : "comment.doc", // doc comment @@ -436,20 +442,24 @@ var JavaScriptHighlightRules = function(options) { } ], "comment_regex_allowed" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "\\*\\/", next : "start"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "comment" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "\\*\\/", next : "no_regex"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "line_comment_regex_allowed" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "$|^", next : "start"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "line_comment" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "$|^", next : "no_regex"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "qqstring" : [ { @@ -1064,11 +1074,11 @@ var SAFE_INSERT_BEFORE_TOKENS = ["text", "paren.rparen", "punctuation.operator", "comment"]; var context; -var contextCache = {} +var contextCache = {}; var initContext = function(editor) { var id = -1; if (editor.multiSelect) { - id = editor.selection.id; + id = editor.selection.index; if (contextCache.rangeCount != editor.multiSelect.rangeCount) contextCache = {rangeCount: editor.multiSelect.rangeCount}; } diff --git a/lib/client/edit/mode-jsx.js b/lib/client/edit/mode-jsx.js index 573abb14..7c558b00 100644 --- a/lib/client/edit/mode-jsx.js +++ b/lib/client/edit/mode-jsx.js @@ -5,22 +5,28 @@ var oop = require("../lib/oop"); var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; var DocCommentHighlightRules = function() { - this.$rules = { "start" : [ { token : "comment.doc.tag", regex : "@[\\w\\d_]+" // TODO: fix email addresses - }, { - token : "comment.doc.tag", - regex : "\\bTODO\\b" - }, { - defaultToken : "comment.doc" + }, + DocCommentHighlightRules.getTagRule(), + { + defaultToken : "comment.doc", + caseInsensitive: true }] }; }; oop.inherits(DocCommentHighlightRules, TextHighlightRules); +DocCommentHighlightRules.getTagRule = function(start) { + return { + token : "comment.doc.tag.storage.type", + regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b" + }; +} + DocCommentHighlightRules.getStartRule = function(start) { return { token : "comment.doc", // doc comment @@ -215,11 +221,11 @@ var SAFE_INSERT_BEFORE_TOKENS = ["text", "paren.rparen", "punctuation.operator", "comment"]; var context; -var contextCache = {} +var contextCache = {}; var initContext = function(editor) { var id = -1; if (editor.multiSelect) { - id = editor.selection.id; + id = editor.selection.index; if (contextCache.rangeCount != editor.multiSelect.rangeCount) contextCache = {rangeCount: editor.multiSelect.rangeCount}; } diff --git a/lib/client/edit/mode-less.js b/lib/client/edit/mode-less.js index 7eff8b49..5872d97a 100644 --- a/lib/client/edit/mode-less.js +++ b/lib/client/edit/mode-less.js @@ -281,11 +281,11 @@ var SAFE_INSERT_BEFORE_TOKENS = ["text", "paren.rparen", "punctuation.operator", "comment"]; var context; -var contextCache = {} +var contextCache = {}; var initContext = function(editor) { var id = -1; if (editor.multiSelect) { - id = editor.selection.id; + id = editor.selection.index; if (contextCache.rangeCount != editor.multiSelect.rangeCount) contextCache = {rangeCount: editor.multiSelect.rangeCount}; } diff --git a/lib/client/edit/mode-liquid.js b/lib/client/edit/mode-liquid.js index d30988fe..b1b7d4aa 100644 --- a/lib/client/edit/mode-liquid.js +++ b/lib/client/edit/mode-liquid.js @@ -149,22 +149,28 @@ var oop = require("../lib/oop"); var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; var DocCommentHighlightRules = function() { - this.$rules = { "start" : [ { token : "comment.doc.tag", regex : "@[\\w\\d_]+" // TODO: fix email addresses - }, { - token : "comment.doc.tag", - regex : "\\bTODO\\b" - }, { - defaultToken : "comment.doc" + }, + DocCommentHighlightRules.getTagRule(), + { + defaultToken : "comment.doc", + caseInsensitive: true }] }; }; oop.inherits(DocCommentHighlightRules, TextHighlightRules); +DocCommentHighlightRules.getTagRule = function(start) { + return { + token : "comment.doc.tag.storage.type", + regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b" + }; +} + DocCommentHighlightRules.getStartRule = function(start) { return { token : "comment.doc", // doc comment @@ -436,20 +442,24 @@ var JavaScriptHighlightRules = function(options) { } ], "comment_regex_allowed" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "\\*\\/", next : "start"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "comment" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "\\*\\/", next : "no_regex"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "line_comment_regex_allowed" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "$|^", next : "start"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "line_comment" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "$|^", next : "no_regex"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "qqstring" : [ { diff --git a/lib/client/edit/mode-logiql.js b/lib/client/edit/mode-logiql.js index 10e6ce65..eb4f7eab 100644 --- a/lib/client/edit/mode-logiql.js +++ b/lib/client/edit/mode-logiql.js @@ -173,11 +173,11 @@ var SAFE_INSERT_BEFORE_TOKENS = ["text", "paren.rparen", "punctuation.operator", "comment"]; var context; -var contextCache = {} +var contextCache = {}; var initContext = function(editor) { var id = -1; if (editor.multiSelect) { - id = editor.selection.id; + id = editor.selection.index; if (contextCache.rangeCount != editor.multiSelect.rangeCount) contextCache = {rangeCount: editor.multiSelect.rangeCount}; } diff --git a/lib/client/edit/mode-lsl.js b/lib/client/edit/mode-lsl.js index 7578a86d..853f7d16 100644 --- a/lib/client/edit/mode-lsl.js +++ b/lib/client/edit/mode-lsl.js @@ -146,11 +146,11 @@ var SAFE_INSERT_BEFORE_TOKENS = ["text", "paren.rparen", "punctuation.operator", "comment"]; var context; -var contextCache = {} +var contextCache = {}; var initContext = function(editor) { var id = -1; if (editor.multiSelect) { - id = editor.selection.id; + id = editor.selection.index; if (contextCache.rangeCount != editor.multiSelect.rangeCount) contextCache = {rangeCount: editor.multiSelect.rangeCount}; } diff --git a/lib/client/edit/mode-luapage.js b/lib/client/edit/mode-luapage.js index aa7adeea..faa89cd3 100644 --- a/lib/client/edit/mode-luapage.js +++ b/lib/client/edit/mode-luapage.js @@ -5,22 +5,28 @@ var oop = require("../lib/oop"); var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; var DocCommentHighlightRules = function() { - this.$rules = { "start" : [ { token : "comment.doc.tag", regex : "@[\\w\\d_]+" // TODO: fix email addresses - }, { - token : "comment.doc.tag", - regex : "\\bTODO\\b" - }, { - defaultToken : "comment.doc" + }, + DocCommentHighlightRules.getTagRule(), + { + defaultToken : "comment.doc", + caseInsensitive: true }] }; }; oop.inherits(DocCommentHighlightRules, TextHighlightRules); +DocCommentHighlightRules.getTagRule = function(start) { + return { + token : "comment.doc.tag.storage.type", + regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b" + }; +} + DocCommentHighlightRules.getStartRule = function(start) { return { token : "comment.doc", // doc comment @@ -292,20 +298,24 @@ var JavaScriptHighlightRules = function(options) { } ], "comment_regex_allowed" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "\\*\\/", next : "start"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "comment" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "\\*\\/", next : "no_regex"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "line_comment_regex_allowed" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "$|^", next : "start"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "line_comment" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "$|^", next : "no_regex"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "qqstring" : [ { @@ -444,11 +454,11 @@ var SAFE_INSERT_BEFORE_TOKENS = ["text", "paren.rparen", "punctuation.operator", "comment"]; var context; -var contextCache = {} +var contextCache = {}; var initContext = function(editor) { var id = -1; if (editor.multiSelect) { - id = editor.selection.id; + id = editor.selection.index; if (contextCache.rangeCount != editor.multiSelect.rangeCount) contextCache = {rangeCount: editor.multiSelect.rangeCount}; } @@ -1554,12 +1564,13 @@ oop.inherits(HtmlHighlightRules, XmlHighlightRules); exports.HtmlHighlightRules = HtmlHighlightRules; }); -ace.define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator"], function(require, exports, module) { +ace.define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"], function(require, exports, module) { "use strict"; var oop = require("../../lib/oop"); var Behaviour = require("../behaviour").Behaviour; var TokenIterator = require("../../token_iterator").TokenIterator; +var lang = require("../../lib/lang"); function is(token, type) { return token.type.lastIndexOf(type + ".xml") > -1; @@ -1657,29 +1668,56 @@ var XmlBehaviour = function () { return; return { - text: '>' + '', + text: ">" + "", selection: [1, 1] }; } }); - this.add('autoindent', 'insertion', function (state, action, editor, session, text) { + this.add("autoindent", "insertion", function (state, action, editor, session, text) { if (text == "\n") { var cursor = editor.getCursorPosition(); var line = session.getLine(cursor.row); - var rightChars = line.substring(cursor.column, cursor.column + 2); - if (rightChars == ' -1; @@ -1283,29 +1294,56 @@ var XmlBehaviour = function () { return; return { - text: '>' + '', + text: ">" + "", selection: [1, 1] }; } }); - this.add('autoindent', 'insertion', function (state, action, editor, session, text) { + this.add("autoindent", "insertion", function (state, action, editor, session, text) { if (text == "\n") { var cursor = editor.getCursorPosition(); var line = session.getLine(cursor.row); - var rightChars = line.substring(cursor.column, cursor.column + 2); - if (rightChars == ' -1; +} + +var XmlBehaviour = function () { + + this.add("string_dquotes", "insertion", function (state, action, editor, session, text) { + if (text == '"' || text == "'") { + var quote = text; + var selected = session.doc.getTextRange(editor.getSelectionRange()); + if (selected !== "" && selected !== "'" && selected != '"' && editor.getWrapBehavioursEnabled()) { + return { + text: quote + selected + quote, + selection: false + }; + } + + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + var iterator = new TokenIterator(session, cursor.row, cursor.column); + var token = iterator.getCurrentToken(); + + if (rightChar == quote && (is(token, "attribute-value") || is(token, "string"))) { + return { + text: "", + selection: [1, 1] + }; + } + + if (!token) + token = iterator.stepBackward(); + + if (!token) + return; + + while (is(token, "tag-whitespace") || is(token, "whitespace")) { + token = iterator.stepBackward(); + } + var rightSpace = !rightChar || rightChar.match(/\s/); + if (is(token, "attribute-equals") && (rightSpace || rightChar == '>') || (is(token, "decl-attribute-equals") && (rightSpace || rightChar == '?'))) { + return { + text: quote + quote, + selection: [1, 1] + }; + } + } + }); + + this.add("string_dquotes", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && (selected == '"' || selected == "'")) { + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == selected) { + range.end.column++; + return range; + } + } + }); + + this.add("autoclosing", "insertion", function (state, action, editor, session, text) { + if (text == '>') { + var position = editor.getCursorPosition(); + var iterator = new TokenIterator(session, position.row, position.column); + var token = iterator.getCurrentToken() || iterator.stepBackward(); + if (!token || !(is(token, "tag-name") || is(token, "tag-whitespace") || is(token, "attribute-name") || is(token, "attribute-equals") || is(token, "attribute-value"))) + return; + if (is(token, "reference.attribute-value")) + return; + if (is(token, "attribute-value")) { + var firstChar = token.value.charAt(0); + if (firstChar == '"' || firstChar == "'") { + var lastChar = token.value.charAt(token.value.length - 1); + var tokenEnd = iterator.getCurrentTokenColumn() + token.value.length; + if (tokenEnd > position.column || tokenEnd == position.column && firstChar != lastChar) + return; + } + } + while (!is(token, "tag-name")) { + token = iterator.stepBackward(); + } + + var tokenRow = iterator.getCurrentTokenRow(); + var tokenColumn = iterator.getCurrentTokenColumn(); + if (is(iterator.stepBackward(), "end-tag-open")) + return; + + var element = token.value; + if (tokenRow == position.row) + element = element.substring(0, position.column - tokenColumn); + + if (this.voidElements.hasOwnProperty(element.toLowerCase())) + return; + + return { + text: ">" + "", + selection: [1, 1] + }; + } + }); + + this.add("autoindent", "insertion", function (state, action, editor, session, text) { + if (text == "\n") { + var cursor = editor.getCursorPosition(); + var line = session.getLine(cursor.row); + var iterator = new TokenIterator(session, cursor.row, cursor.column); + var token = iterator.getCurrentToken(); + + if (token && token.type.indexOf("tag-close") !== -1) { + while (token && token.type.indexOf("tag-name") === -1) { + token = iterator.stepBackward(); + } + + if (!token) { + return; + } + + var tag = token.value; + var row = iterator.getCurrentTokenRow(); + token = iterator.stepBackward(); + if (!token || token.type.indexOf("end-tag") !== -1) { + return; + } + + if (this.voidElements && !this.voidElements[tag]) { + var nextToken = session.getTokenAt(cursor.row, cursor.column+1); + var line = session.getLine(row); + var nextIndent = this.$getIndent(line); + var indent = nextIndent + session.getTabString(); + + if (nextToken && nextToken.value === " -1; +} + +(function() { + + this.getFoldWidget = function(session, foldStyle, row) { + var tag = this._getFirstTagInLine(session, row); + + if (!tag) + return ""; + + if (tag.closing || (!tag.tagName && tag.selfClosing)) + return foldStyle == "markbeginend" ? "end" : ""; + + if (!tag.tagName || tag.selfClosing || this.voidElements.hasOwnProperty(tag.tagName.toLowerCase())) + return ""; + + if (this._findEndTagInLine(session, row, tag.tagName, tag.end.column)) + return ""; + + return "start"; + }; + this._getFirstTagInLine = function(session, row) { + var tokens = session.getTokens(row); + var tag = new Tag(); + + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; + if (is(token, "tag-open")) { + tag.end.column = tag.start.column + token.value.length; + tag.closing = is(token, "end-tag-open"); + token = tokens[++i]; + if (!token) + return null; + tag.tagName = token.value; + tag.end.column += token.value.length; + for (i++; i < tokens.length; i++) { + token = tokens[i]; + tag.end.column += token.value.length; + if (is(token, "tag-close")) { + tag.selfClosing = token.value == '/>'; + break; + } + } + return tag; + } else if (is(token, "tag-close")) { + tag.selfClosing = token.value == '/>'; + return tag; + } + tag.start.column += token.value.length; + } + + return null; + }; + + this._findEndTagInLine = function(session, row, tagName, startColumn) { + var tokens = session.getTokens(row); + var column = 0; + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; + column += token.value.length; + if (column < startColumn) + continue; + if (is(token, "end-tag-open")) { + token = tokens[i + 1]; + if (token && token.value == tagName) + return true; + } + } + return false; + }; + this._readTagForward = function(iterator) { + var token = iterator.getCurrentToken(); + if (!token) + return null; + + var tag = new Tag(); + do { + if (is(token, "tag-open")) { + tag.closing = is(token, "end-tag-open"); + tag.start.row = iterator.getCurrentTokenRow(); + tag.start.column = iterator.getCurrentTokenColumn(); + } else if (is(token, "tag-name")) { + tag.tagName = token.value; + } else if (is(token, "tag-close")) { + tag.selfClosing = token.value == "/>"; + tag.end.row = iterator.getCurrentTokenRow(); + tag.end.column = iterator.getCurrentTokenColumn() + token.value.length; + iterator.stepForward(); + return tag; + } + } while(token = iterator.stepForward()); + + return null; + }; + + this._readTagBackward = function(iterator) { + var token = iterator.getCurrentToken(); + if (!token) + return null; + + var tag = new Tag(); + do { + if (is(token, "tag-open")) { + tag.closing = is(token, "end-tag-open"); + tag.start.row = iterator.getCurrentTokenRow(); + tag.start.column = iterator.getCurrentTokenColumn(); + iterator.stepBackward(); + return tag; + } else if (is(token, "tag-name")) { + tag.tagName = token.value; + } else if (is(token, "tag-close")) { + tag.selfClosing = token.value == "/>"; + tag.end.row = iterator.getCurrentTokenRow(); + tag.end.column = iterator.getCurrentTokenColumn() + token.value.length; + } + } while(token = iterator.stepBackward()); + + return null; + }; + + this._pop = function(stack, tag) { + while (stack.length) { + + var top = stack[stack.length-1]; + if (!tag || top.tagName == tag.tagName) { + return stack.pop(); + } + else if (this.optionalEndTags.hasOwnProperty(tag.tagName)) { + return; + } + else if (this.optionalEndTags.hasOwnProperty(top.tagName)) { + stack.pop(); + continue; + } else { + return null; + } + } + }; + + this.getFoldWidgetRange = function(session, foldStyle, row) { + var firstTag = this._getFirstTagInLine(session, row); + + if (!firstTag) + return null; + + var isBackward = firstTag.closing || firstTag.selfClosing; + var stack = []; + var tag; + + if (!isBackward) { + var iterator = new TokenIterator(session, row, firstTag.start.column); + var start = { + row: row, + column: firstTag.start.column + firstTag.tagName.length + 2 + }; + while (tag = this._readTagForward(iterator)) { + if (tag.selfClosing) { + if (!stack.length) { + tag.start.column += tag.tagName.length + 2; + tag.end.column -= 2; + return Range.fromPoints(tag.start, tag.end); + } else + continue; + } + + if (tag.closing) { + this._pop(stack, tag); + if (stack.length == 0) + return Range.fromPoints(start, tag.start); + } + else { + stack.push(tag); + } + } + } + else { + var iterator = new TokenIterator(session, row, firstTag.end.column); + var end = { + row: row, + column: firstTag.start.column + }; + + while (tag = this._readTagBackward(iterator)) { + if (tag.selfClosing) { + if (!stack.length) { + tag.start.column += tag.tagName.length + 2; + tag.end.column -= 2; + return Range.fromPoints(tag.start, tag.end); + } else + continue; + } + + if (!tag.closing) { + this._pop(stack, tag); + if (stack.length == 0) { + tag.start.column += tag.tagName.length + 2; + return Range.fromPoints(tag.start, end); + } + } + else { + stack.push(tag); + } + } + } + + }; + +}).call(FoldMode.prototype); + +}); + +ace.define("ace/mode/folding/html",["require","exports","module","ace/lib/oop","ace/mode/folding/mixed","ace/mode/folding/xml","ace/mode/folding/cstyle"], function(require, exports, module) { +"use strict"; + +var oop = require("../../lib/oop"); +var MixedFoldMode = require("./mixed").FoldMode; +var XmlFoldMode = require("./xml").FoldMode; +var CStyleFoldMode = require("./cstyle").FoldMode; + +var FoldMode = exports.FoldMode = function(voidElements, optionalTags) { + MixedFoldMode.call(this, new XmlFoldMode(voidElements, optionalTags), { + "js-": new CStyleFoldMode(), + "css-": new CStyleFoldMode() + }); +}; + +oop.inherits(FoldMode, MixedFoldMode); + +}); + +ace.define("ace/mode/html_completions",["require","exports","module","ace/token_iterator"], function(require, exports, module) { +"use strict"; + +var TokenIterator = require("../token_iterator").TokenIterator; + +var commonAttributes = [ + "accesskey", + "class", + "contenteditable", + "contextmenu", + "dir", + "draggable", + "dropzone", + "hidden", + "id", + "inert", + "itemid", + "itemprop", + "itemref", + "itemscope", + "itemtype", + "lang", + "spellcheck", + "style", + "tabindex", + "title", + "translate" +]; + +var eventAttributes = [ + "onabort", + "onblur", + "oncancel", + "oncanplay", + "oncanplaythrough", + "onchange", + "onclick", + "onclose", + "oncontextmenu", + "oncuechange", + "ondblclick", + "ondrag", + "ondragend", + "ondragenter", + "ondragleave", + "ondragover", + "ondragstart", + "ondrop", + "ondurationchange", + "onemptied", + "onended", + "onerror", + "onfocus", + "oninput", + "oninvalid", + "onkeydown", + "onkeypress", + "onkeyup", + "onload", + "onloadeddata", + "onloadedmetadata", + "onloadstart", + "onmousedown", + "onmousemove", + "onmouseout", + "onmouseover", + "onmouseup", + "onmousewheel", + "onpause", + "onplay", + "onplaying", + "onprogress", + "onratechange", + "onreset", + "onscroll", + "onseeked", + "onseeking", + "onselect", + "onshow", + "onstalled", + "onsubmit", + "onsuspend", + "ontimeupdate", + "onvolumechange", + "onwaiting" +]; + +var globalAttributes = commonAttributes.concat(eventAttributes); + +var attributeMap = { + "html": ["manifest"], + "head": [], + "title": [], + "base": ["href", "target"], + "link": ["href", "hreflang", "rel", "media", "type", "sizes"], + "meta": ["http-equiv", "name", "content", "charset"], + "style": ["type", "media", "scoped"], + "script": ["charset", "type", "src", "defer", "async"], + "noscript": ["href"], + "body": ["onafterprint", "onbeforeprint", "onbeforeunload", "onhashchange", "onmessage", "onoffline", "onpopstate", "onredo", "onresize", "onstorage", "onundo", "onunload"], + "section": [], + "nav": [], + "article": ["pubdate"], + "aside": [], + "h1": [], + "h2": [], + "h3": [], + "h4": [], + "h5": [], + "h6": [], + "header": [], + "footer": [], + "address": [], + "main": [], + "p": [], + "hr": [], + "pre": [], + "blockquote": ["cite"], + "ol": ["start", "reversed"], + "ul": [], + "li": ["value"], + "dl": [], + "dt": [], + "dd": [], + "figure": [], + "figcaption": [], + "div": [], + "a": ["href", "target", "ping", "rel", "media", "hreflang", "type"], + "em": [], + "strong": [], + "small": [], + "s": [], + "cite": [], + "q": ["cite"], + "dfn": [], + "abbr": [], + "data": [], + "time": ["datetime"], + "code": [], + "var": [], + "samp": [], + "kbd": [], + "sub": [], + "sup": [], + "i": [], + "b": [], + "u": [], + "mark": [], + "ruby": [], + "rt": [], + "rp": [], + "bdi": [], + "bdo": [], + "span": [], + "br": [], + "wbr": [], + "ins": ["cite", "datetime"], + "del": ["cite", "datetime"], + "img": ["alt", "src", "height", "width", "usemap", "ismap"], + "iframe": ["name", "src", "height", "width", "sandbox", "seamless"], + "embed": ["src", "height", "width", "type"], + "object": ["param", "data", "type", "height" , "width", "usemap", "name", "form", "classid"], + "param": ["name", "value"], + "video": ["src", "autobuffer", "autoplay", "loop", "controls", "width", "height", "poster"], + "audio": ["src", "autobuffer", "autoplay", "loop", "controls"], + "source": ["src", "type", "media"], + "track": ["kind", "src", "srclang", "label", "default"], + "canvas": ["width", "height"], + "map": ["name"], + "area": ["shape", "coords", "href", "hreflang", "alt", "target", "media", "rel", "ping", "type"], + "svg": [], + "math": [], + "table": ["summary"], + "caption": [], + "colgroup": ["span"], + "col": ["span"], + "tbody": [], + "thead": [], + "tfoot": [], + "tr": [], + "td": ["headers", "rowspan", "colspan"], + "th": ["headers", "rowspan", "colspan", "scope"], + "form": ["accept-charset", "action", "autocomplete", "enctype", "method", "name", "novalidate", "target"], + "fieldset": ["disabled", "form", "name"], + "legend": [], + "label": ["form", "for"], + "input": ["type", "accept", "alt", "autocomplete", "checked", "disabled", "form", "formaction", "formenctype", "formmethod", "formnovalidate", "formtarget", "height", "list", "max", "maxlength", "min", "multiple", "pattern", "placeholder", "readonly", "required", "size", "src", "step", "width", "files", "value"], + "button": ["autofocus", "disabled", "form", "formaction", "formenctype", "formmethod", "formnovalidate", "formtarget", "name", "value", "type"], + "select": ["autofocus", "disabled", "form", "multiple", "name", "size"], + "datalist": [], + "optgroup": ["disabled", "label"], + "option": ["disabled", "selected", "label", "value"], + "textarea": ["autofocus", "disabled", "form", "maxlength", "name", "placeholder", "readonly", "required", "rows", "cols", "wrap"], + "keygen": ["autofocus", "challenge", "disabled", "form", "keytype", "name"], + "output": ["for", "form", "name"], + "progress": ["value", "max"], + "meter": ["value", "min", "max", "low", "high", "optimum"], + "details": ["open"], + "summary": [], + "command": ["type", "label", "icon", "disabled", "checked", "radiogroup", "command"], + "menu": ["type", "label"], + "dialog": ["open"] +}; + +var elements = Object.keys(attributeMap); + +function is(token, type) { + return token.type.lastIndexOf(type + ".xml") > -1; +} + +function findTagName(session, pos) { + var iterator = new TokenIterator(session, pos.row, pos.column); + var token = iterator.getCurrentToken(); + while (token && !is(token, "tag-name")){ + token = iterator.stepBackward(); + } + if (token) + return token.value; +} + +var HtmlCompletions = function() { + +}; + +(function() { + + this.getCompletions = function(state, session, pos, prefix) { + var token = session.getTokenAt(pos.row, pos.column); + + if (!token) + return []; + if (is(token, "tag-name") || is(token, "tag-open") || is(token, "end-tag-open")) + return this.getTagCompletions(state, session, pos, prefix); + if (is(token, "tag-whitespace") || is(token, "attribute-name")) + return this.getAttributeCompetions(state, session, pos, prefix); + + return []; + }; + + this.getTagCompletions = function(state, session, pos, prefix) { + return elements.map(function(element){ + return { + value: element, + meta: "tag", + score: Number.MAX_VALUE + }; + }); + }; + + this.getAttributeCompetions = function(state, session, pos, prefix) { + var tagName = findTagName(session, pos); + if (!tagName) + return []; + var attributes = globalAttributes; + if (tagName in attributeMap) { + attributes = attributes.concat(attributeMap[tagName]); + } + return attributes.map(function(attribute){ + return { + caption: attribute, + snippet: attribute + '="$0"', + meta: "attribute", + score: Number.MAX_VALUE + }; + }); + }; + +}).call(HtmlCompletions.prototype); + +exports.HtmlCompletions = HtmlCompletions; +}); + +ace.define("ace/mode/html",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text","ace/mode/javascript","ace/mode/css","ace/mode/html_highlight_rules","ace/mode/behaviour/xml","ace/mode/folding/html","ace/mode/html_completions","ace/worker/worker_client"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var lang = require("../lib/lang"); +var TextMode = require("./text").Mode; +var JavaScriptMode = require("./javascript").Mode; +var CssMode = require("./css").Mode; +var HtmlHighlightRules = require("./html_highlight_rules").HtmlHighlightRules; +var XmlBehaviour = require("./behaviour/xml").XmlBehaviour; +var HtmlFoldMode = require("./folding/html").FoldMode; +var HtmlCompletions = require("./html_completions").HtmlCompletions; +var WorkerClient = require("../worker/worker_client").WorkerClient; +var voidElements = ["area", "base", "br", "col", "embed", "hr", "img", "input", "keygen", "link", "meta", "menuitem", "param", "source", "track", "wbr"]; +var optionalEndTags = ["li", "dt", "dd", "p", "rt", "rp", "optgroup", "option", "colgroup", "td", "th"]; + +var Mode = function(options) { + this.fragmentContext = options && options.fragmentContext; + this.HighlightRules = HtmlHighlightRules; + this.$behaviour = new XmlBehaviour(); + this.$completer = new HtmlCompletions(); + + this.createModeDelegates({ + "js-": JavaScriptMode, + "css-": CssMode + }); + + this.foldingRules = new HtmlFoldMode(this.voidElements, lang.arrayToMap(optionalEndTags)); +}; +oop.inherits(Mode, TextMode); + +(function() { + + this.blockComment = {start: ""}; + + this.voidElements = lang.arrayToMap(voidElements); + + this.getNextLineIndent = function(state, line, tab) { + return this.$getIndent(line); + }; + + this.checkOutdent = function(state, line, input) { + return false; + }; + + this.getCompletions = function(state, session, pos, prefix) { + return this.$completer.getCompletions(state, session, pos, prefix); + }; + + this.createWorker = function(session) { + if (this.constructor != Mode) + return; + var worker = new WorkerClient(["ace"], "ace/mode/html_worker", "Worker"); + worker.attachToDocument(session.getDocument()); + + if (this.fragmentContext) + worker.call("setOptions", [{context: this.fragmentContext}]); + + worker.on("error", function(e) { + session.setAnnotations(e.data); + }); + + worker.on("terminate", function() { + session.clearAnnotations(); + }); + + return worker; + }; + + this.$id = "ace/mode/html"; +}).call(Mode.prototype); + +exports.Mode = Mode; +}); + +ace.define("ace/mode/php",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/php_highlight_rules","ace/mode/php_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle","ace/unicode","ace/mode/html","ace/mode/javascript","ace/mode/css"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextMode = require("./text").Mode; +var PhpHighlightRules = require("./php_highlight_rules").PhpHighlightRules; +var PhpLangHighlightRules = require("./php_highlight_rules").PhpLangHighlightRules; +var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent; +var Range = require("../range").Range; +var WorkerClient = require("../worker/worker_client").WorkerClient; +var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour; +var CStyleFoldMode = require("./folding/cstyle").FoldMode; +var unicode = require("../unicode"); +var HtmlMode = require("./html").Mode; +var JavaScriptMode = require("./javascript").Mode; +var CssMode = require("./css").Mode; + +var PhpMode = function(opts) { + this.HighlightRules = PhpLangHighlightRules; + this.$outdent = new MatchingBraceOutdent(); + this.$behaviour = new CstyleBehaviour(); + this.foldingRules = new CStyleFoldMode(); +}; +oop.inherits(PhpMode, TextMode); + +(function() { + + this.getNextLineIndent = function(state, line, tab) { + var indent = this.$getIndent(line); + + var tokenizedLine = this.getTokenizer().getLineTokens(line, state); + var tokens = tokenizedLine.tokens; + var endState = tokenizedLine.state; + + if (tokens.length && tokens[tokens.length-1].type == "comment") { + return indent; + } + + if (state == "start") { + var match = line.match(/^.*[\{\(\[\:]\s*$/); + if (match) { + indent += tab; + } + } else if (state == "doc-start") { + if (endState != "doc-start") { + return ""; + } + var match = line.match(/^\s*(\/?)\*/); + if (match) { + if (match[1]) { + indent += " "; + } + indent += "* "; + } + } + + return indent; + }; + + this.checkOutdent = function(state, line, input) { + return this.$outdent.checkOutdent(line, input); + }; + + this.autoOutdent = function(state, doc, row) { + this.$outdent.autoOutdent(doc, row); + }; + + this.$id = "ace/mode/php-inline"; +}).call(PhpMode.prototype); + +var Mode = function(opts) { + if (opts && opts.inline) { + PhpMode.call(this); + return; + } + HtmlMode.call(this); + this.HighlightRules = PhpHighlightRules; + this.createModeDelegates({ + "js-": JavaScriptMode, + "css-": CssMode, + "php-": PhpMode + }); +}; +oop.inherits(Mode, HtmlMode); + +(function() { + + this.tokenRe = new RegExp("^[" + + unicode.packages.L + + unicode.packages.Mn + unicode.packages.Mc + + unicode.packages.Nd + + unicode.packages.Pc + "\_]+", "g" + ); + + this.nonTokenRe = new RegExp("^(?:[^" + + unicode.packages.L + + unicode.packages.Mn + unicode.packages.Mc + + unicode.packages.Nd + + unicode.packages.Pc + "\_]|\s])+", "g" + ); + + + this.lineCommentStart = ["//", "#"]; + this.blockComment = {start: "/*", end: "*/"}; + this.createWorker = function(session) { var worker = new WorkerClient(["ace"], "ace/mode/php_worker", "PhpWorker"); worker.attachToDocument(session.getDocument()); - + if (this.inlinePhp) worker.call("setOptions", [{inline: true}]); diff --git a/lib/client/edit/mode-powershell.js b/lib/client/edit/mode-powershell.js index b79c529c..4a29cbe1 100644 --- a/lib/client/edit/mode-powershell.js +++ b/lib/client/edit/mode-powershell.js @@ -193,11 +193,11 @@ var SAFE_INSERT_BEFORE_TOKENS = ["text", "paren.rparen", "punctuation.operator", "comment"]; var context; -var contextCache = {} +var contextCache = {}; var initContext = function(editor) { var id = -1; if (editor.multiSelect) { - id = editor.selection.id; + id = editor.selection.index; if (contextCache.rangeCount != editor.multiSelect.rangeCount) contextCache = {rangeCount: editor.multiSelect.rangeCount}; } diff --git a/lib/client/edit/mode-protobuf.js b/lib/client/edit/mode-protobuf.js index d629589f..05bfa9cf 100644 --- a/lib/client/edit/mode-protobuf.js +++ b/lib/client/edit/mode-protobuf.js @@ -5,22 +5,28 @@ var oop = require("../lib/oop"); var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; var DocCommentHighlightRules = function() { - this.$rules = { "start" : [ { token : "comment.doc.tag", regex : "@[\\w\\d_]+" // TODO: fix email addresses - }, { - token : "comment.doc.tag", - regex : "\\bTODO\\b" - }, { - defaultToken : "comment.doc" + }, + DocCommentHighlightRules.getTagRule(), + { + defaultToken : "comment.doc", + caseInsensitive: true }] }; }; oop.inherits(DocCommentHighlightRules, TextHighlightRules); +DocCommentHighlightRules.getTagRule = function(start) { + return { + token : "comment.doc.tag.storage.type", + regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b" + }; +} + DocCommentHighlightRules.getStartRule = function(start) { return { token : "comment.doc", // doc comment @@ -89,11 +95,12 @@ var c_cppHighlightRules = function() { var identifierRe = "[a-zA-Z\\$_\u00a1-\uffff][a-zA-Z\d\\$_\u00a1-\uffff]*\\b"; - this.$rules = { + this.$rules = { "start" : [ { token : "comment", - regex : "\\/\\/.*$" + regex : "//", + next : "singleLineComment" }, DocCommentHighlightRules.getStartRule("doc-start"), { @@ -160,14 +167,26 @@ var c_cppHighlightRules = function() { regex : ".+" } ], + "singleLineComment" : [ + { + token : "comment", + regex : /\\$/, + next : "singleLineComment" + }, { + token : "comment", + regex : /$/, + next : "start" + }, { + defaultToken: "comment" + } + ], "qqstring" : [ { token : "string", regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"', next : "start" }, { - token : "string", - regex : '.+' + defaultToken : "string" } ], "qstring" : [ @@ -176,8 +195,7 @@ var c_cppHighlightRules = function() { regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'", next : "start" }, { - token : "string", - regex : '.+' + defaultToken : "string" } ], "directive" : [ @@ -275,11 +293,11 @@ var SAFE_INSERT_BEFORE_TOKENS = ["text", "paren.rparen", "punctuation.operator", "comment"]; var context; -var contextCache = {} +var contextCache = {}; var initContext = function(editor) { var id = -1; if (editor.multiSelect) { - id = editor.selection.id; + id = editor.selection.index; if (contextCache.rangeCount != editor.multiSelect.rangeCount) contextCache = {rangeCount: editor.multiSelect.rangeCount}; } diff --git a/lib/client/edit/mode-rhtml.js b/lib/client/edit/mode-rhtml.js index bcd3f753..786bd009 100644 --- a/lib/client/edit/mode-rhtml.js +++ b/lib/client/edit/mode-rhtml.js @@ -5,22 +5,28 @@ var oop = require("../lib/oop"); var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; var DocCommentHighlightRules = function() { - this.$rules = { "start" : [ { token : "comment.doc.tag", regex : "@[\\w\\d_]+" // TODO: fix email addresses - }, { - token : "comment.doc.tag", - regex : "\\bTODO\\b" - }, { - defaultToken : "comment.doc" + }, + DocCommentHighlightRules.getTagRule(), + { + defaultToken : "comment.doc", + caseInsensitive: true }] }; }; oop.inherits(DocCommentHighlightRules, TextHighlightRules); +DocCommentHighlightRules.getTagRule = function(start) { + return { + token : "comment.doc.tag.storage.type", + regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b" + }; +} + DocCommentHighlightRules.getStartRule = function(start) { return { token : "comment.doc", // doc comment @@ -292,20 +298,24 @@ var JavaScriptHighlightRules = function(options) { } ], "comment_regex_allowed" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "\\*\\/", next : "start"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "comment" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "\\*\\/", next : "no_regex"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "line_comment_regex_allowed" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "$|^", next : "start"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "line_comment" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "$|^", next : "no_regex"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "qqstring" : [ { @@ -444,11 +454,11 @@ var SAFE_INSERT_BEFORE_TOKENS = ["text", "paren.rparen", "punctuation.operator", "comment"]; var context; -var contextCache = {} +var contextCache = {}; var initContext = function(editor) { var id = -1; if (editor.multiSelect) { - id = editor.selection.id; + id = editor.selection.index; if (contextCache.rangeCount != editor.multiSelect.rangeCount) contextCache = {rangeCount: editor.multiSelect.rangeCount}; } @@ -1554,12 +1564,13 @@ oop.inherits(HtmlHighlightRules, XmlHighlightRules); exports.HtmlHighlightRules = HtmlHighlightRules; }); -ace.define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator"], function(require, exports, module) { +ace.define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"], function(require, exports, module) { "use strict"; var oop = require("../../lib/oop"); var Behaviour = require("../behaviour").Behaviour; var TokenIterator = require("../../token_iterator").TokenIterator; +var lang = require("../../lib/lang"); function is(token, type) { return token.type.lastIndexOf(type + ".xml") > -1; @@ -1657,29 +1668,56 @@ var XmlBehaviour = function () { return; return { - text: '>' + '', + text: ">" + "", selection: [1, 1] }; } }); - this.add('autoindent', 'insertion', function (state, action, editor, session, text) { + this.add("autoindent", "insertion", function (state, action, editor, session, text) { if (text == "\n") { var cursor = editor.getCursorPosition(); var line = session.getLine(cursor.row); - var rightChars = line.substring(cursor.column, cursor.column + 2); - if (rightChars == '= stack[1]) { + if (value.length > stack[1]) + token = "invalid"; + stack.shift(); + stack.shift(); + this.next = stack.shift(); + } else { + this.next = ""; + } + return token; + }, + regex : /"#*/, + next : "start" + }, { + defaultToken : "string.quoted.raw.source.rust" + } + ] + }, { token: 'string.quoted.double.source.rust', regex: '"', push: @@ -64,10 +93,14 @@ var RustHighlightRules = function() { regex: '$', next: 'pop' }, { defaultToken: 'comment.line.double-dash.source.rust' } ] }, - { token: 'comment.block.source.rust', + { token: 'comment.start.block.source.rust', regex: '/\\*', + stateName: 'comment', push: - [ { token: 'comment.block.source.rust', + [ { token: 'comment.start.block.source.rust', + regex: '/\\*', + push: 'comment' }, + { token: 'comment.end.block.source.rust', regex: '\\*/', next: 'pop' }, { defaultToken: 'comment.block.source.rust' } ] } ], @@ -200,7 +233,7 @@ var Mode = function() { oop.inherits(Mode, TextMode); (function() { - this.lineCommentStart = "/\\*"; + this.lineCommentStart = "//"; this.blockComment = {start: "/*", end: "*/"}; this.$id = "ace/mode/rust"; }).call(Mode.prototype); diff --git a/lib/client/edit/mode-scad.js b/lib/client/edit/mode-scad.js index 0119bbde..c954e76f 100644 --- a/lib/client/edit/mode-scad.js +++ b/lib/client/edit/mode-scad.js @@ -5,22 +5,28 @@ var oop = require("../lib/oop"); var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; var DocCommentHighlightRules = function() { - this.$rules = { "start" : [ { token : "comment.doc.tag", regex : "@[\\w\\d_]+" // TODO: fix email addresses - }, { - token : "comment.doc.tag", - regex : "\\bTODO\\b" - }, { - defaultToken : "comment.doc" + }, + DocCommentHighlightRules.getTagRule(), + { + defaultToken : "comment.doc", + caseInsensitive: true }] }; }; oop.inherits(DocCommentHighlightRules, TextHighlightRules); +DocCommentHighlightRules.getTagRule = function(start) { + return { + token : "comment.doc.tag.storage.type", + regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b" + }; +} + DocCommentHighlightRules.getStartRule = function(start) { return { token : "comment.doc", // doc comment @@ -206,11 +212,11 @@ var SAFE_INSERT_BEFORE_TOKENS = ["text", "paren.rparen", "punctuation.operator", "comment"]; var context; -var contextCache = {} +var contextCache = {}; var initContext = function(editor) { var id = -1; if (editor.multiSelect) { - id = editor.selection.id; + id = editor.selection.index; if (contextCache.rangeCount != editor.multiSelect.rangeCount) contextCache = {rangeCount: editor.multiSelect.rangeCount}; } diff --git a/lib/client/edit/mode-scala.js b/lib/client/edit/mode-scala.js index 4c031a52..4a1ce4c8 100644 --- a/lib/client/edit/mode-scala.js +++ b/lib/client/edit/mode-scala.js @@ -5,22 +5,28 @@ var oop = require("../lib/oop"); var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; var DocCommentHighlightRules = function() { - this.$rules = { "start" : [ { token : "comment.doc.tag", regex : "@[\\w\\d_]+" // TODO: fix email addresses - }, { - token : "comment.doc.tag", - regex : "\\bTODO\\b" - }, { - defaultToken : "comment.doc" + }, + DocCommentHighlightRules.getTagRule(), + { + defaultToken : "comment.doc", + caseInsensitive: true }] }; }; oop.inherits(DocCommentHighlightRules, TextHighlightRules); +DocCommentHighlightRules.getTagRule = function(start) { + return { + token : "comment.doc.tag.storage.type", + regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b" + }; +} + DocCommentHighlightRules.getStartRule = function(start) { return { token : "comment.doc", // doc comment @@ -292,20 +298,24 @@ var JavaScriptHighlightRules = function(options) { } ], "comment_regex_allowed" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "\\*\\/", next : "start"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "comment" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "\\*\\/", next : "no_regex"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "line_comment_regex_allowed" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "$|^", next : "start"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "line_comment" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "$|^", next : "no_regex"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "qqstring" : [ { @@ -444,11 +454,11 @@ var SAFE_INSERT_BEFORE_TOKENS = ["text", "paren.rparen", "punctuation.operator", "comment"]; var context; -var contextCache = {} +var contextCache = {}; var initContext = function(editor) { var id = -1; if (editor.multiSelect) { - id = editor.selection.id; + id = editor.selection.index; if (contextCache.rangeCount != editor.multiSelect.rangeCount) contextCache = {rangeCount: editor.multiSelect.rangeCount}; } diff --git a/lib/client/edit/mode-scss.js b/lib/client/edit/mode-scss.js index 82613ef2..1f10c5fd 100644 --- a/lib/client/edit/mode-scss.js +++ b/lib/client/edit/mode-scss.js @@ -306,11 +306,11 @@ var SAFE_INSERT_BEFORE_TOKENS = ["text", "paren.rparen", "punctuation.operator", "comment"]; var context; -var contextCache = {} +var contextCache = {}; var initContext = function(editor) { var id = -1; if (editor.multiSelect) { - id = editor.selection.id; + id = editor.selection.index; if (contextCache.rangeCount != editor.multiSelect.rangeCount) contextCache = {rangeCount: editor.multiSelect.rangeCount}; } diff --git a/lib/client/edit/mode-sh.js b/lib/client/edit/mode-sh.js index b419ab96..48dab1c8 100644 --- a/lib/client/edit/mode-sh.js +++ b/lib/client/edit/mode-sh.js @@ -280,11 +280,11 @@ var SAFE_INSERT_BEFORE_TOKENS = ["text", "paren.rparen", "punctuation.operator", "comment"]; var context; -var contextCache = {} +var contextCache = {}; var initContext = function(editor) { var id = -1; if (editor.multiSelect) { - id = editor.selection.id; + id = editor.selection.index; if (contextCache.rangeCount != editor.multiSelect.rangeCount) contextCache = {rangeCount: editor.multiSelect.rangeCount}; } diff --git a/lib/client/edit/mode-sjs.js b/lib/client/edit/mode-sjs.js index f5434665..cb564747 100644 --- a/lib/client/edit/mode-sjs.js +++ b/lib/client/edit/mode-sjs.js @@ -5,22 +5,28 @@ var oop = require("../lib/oop"); var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; var DocCommentHighlightRules = function() { - this.$rules = { "start" : [ { token : "comment.doc.tag", regex : "@[\\w\\d_]+" // TODO: fix email addresses - }, { - token : "comment.doc.tag", - regex : "\\bTODO\\b" - }, { - defaultToken : "comment.doc" + }, + DocCommentHighlightRules.getTagRule(), + { + defaultToken : "comment.doc", + caseInsensitive: true }] }; }; oop.inherits(DocCommentHighlightRules, TextHighlightRules); +DocCommentHighlightRules.getTagRule = function(start) { + return { + token : "comment.doc.tag.storage.type", + regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b" + }; +} + DocCommentHighlightRules.getStartRule = function(start) { return { token : "comment.doc", // doc comment @@ -292,20 +298,24 @@ var JavaScriptHighlightRules = function(options) { } ], "comment_regex_allowed" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "\\*\\/", next : "start"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "comment" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "\\*\\/", next : "no_regex"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "line_comment_regex_allowed" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "$|^", next : "start"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "line_comment" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "$|^", next : "no_regex"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "qqstring" : [ { @@ -444,11 +454,11 @@ var SAFE_INSERT_BEFORE_TOKENS = ["text", "paren.rparen", "punctuation.operator", "comment"]; var context; -var contextCache = {} +var contextCache = {}; var initContext = function(editor) { var id = -1; if (editor.multiSelect) { - id = editor.selection.id; + id = editor.selection.index; if (contextCache.rangeCount != editor.multiSelect.rangeCount) contextCache = {rangeCount: editor.multiSelect.rangeCount}; } diff --git a/lib/client/edit/mode-smarty.js b/lib/client/edit/mode-smarty.js index 6abe5f6c..1b47d4d7 100644 --- a/lib/client/edit/mode-smarty.js +++ b/lib/client/edit/mode-smarty.js @@ -5,22 +5,28 @@ var oop = require("../lib/oop"); var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; var DocCommentHighlightRules = function() { - this.$rules = { "start" : [ { token : "comment.doc.tag", regex : "@[\\w\\d_]+" // TODO: fix email addresses - }, { - token : "comment.doc.tag", - regex : "\\bTODO\\b" - }, { - defaultToken : "comment.doc" + }, + DocCommentHighlightRules.getTagRule(), + { + defaultToken : "comment.doc", + caseInsensitive: true }] }; }; oop.inherits(DocCommentHighlightRules, TextHighlightRules); +DocCommentHighlightRules.getTagRule = function(start) { + return { + token : "comment.doc.tag.storage.type", + regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b" + }; +} + DocCommentHighlightRules.getStartRule = function(start) { return { token : "comment.doc", // doc comment @@ -292,20 +298,24 @@ var JavaScriptHighlightRules = function(options) { } ], "comment_regex_allowed" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "\\*\\/", next : "start"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "comment" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "\\*\\/", next : "no_regex"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "line_comment_regex_allowed" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "$|^", next : "start"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "line_comment" : [ + DocCommentHighlightRules.getTagRule(), {token : "comment", regex : "$|^", next : "no_regex"}, - {defaultToken : "comment"} + {defaultToken : "comment", caseInsensitive: true} ], "qqstring" : [ { @@ -444,11 +454,11 @@ var SAFE_INSERT_BEFORE_TOKENS = ["text", "paren.rparen", "punctuation.operator", "comment"]; var context; -var contextCache = {} +var contextCache = {}; var initContext = function(editor) { var id = -1; if (editor.multiSelect) { - id = editor.selection.id; + id = editor.selection.index; if (contextCache.rangeCount != editor.multiSelect.rangeCount) contextCache = {rangeCount: editor.multiSelect.rangeCount}; } @@ -1554,12 +1564,13 @@ oop.inherits(HtmlHighlightRules, XmlHighlightRules); exports.HtmlHighlightRules = HtmlHighlightRules; }); -ace.define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator"], function(require, exports, module) { +ace.define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"], function(require, exports, module) { "use strict"; var oop = require("../../lib/oop"); var Behaviour = require("../behaviour").Behaviour; var TokenIterator = require("../../token_iterator").TokenIterator; +var lang = require("../../lib/lang"); function is(token, type) { return token.type.lastIndexOf(type + ".xml") > -1; @@ -1657,29 +1668,56 @@ var XmlBehaviour = function () { return; return { - text: '>' + '', + text: ">" + "", selection: [1, 1] }; } }); - this.add('autoindent', 'insertion', function (state, action, editor, session, text) { + this.add("autoindent", "insertion", function (state, action, editor, session, text) { if (text == "\n") { var cursor = editor.getCursorPosition(); var line = session.getLine(cursor.row); - var rightChars = line.substring(cursor.column, cursor.column + 2); - if (rightChars == ' -1; @@ -1657,29 +1668,56 @@ var XmlBehaviour = function () { return; return { - text: '>' + '', + text: ">" + "", selection: [1, 1] }; } }); - this.add('autoindent', 'insertion', function (state, action, editor, session, text) { + this.add("autoindent", "insertion", function (state, action, editor, session, text) { if (text == "\n") { var cursor = editor.getCursorPosition(); var line = session.getLine(cursor.row); - var rightChars = line.substring(cursor.column, cursor.column + 2); - if (rightChars == ' -1; @@ -311,29 +312,56 @@ var XmlBehaviour = function () { return; return { - text: '>' + '', + text: ">" + "", selection: [1, 1] }; } }); - this.add('autoindent', 'insertion', function (state, action, editor, session, text) { + this.add("autoindent", "insertion", function (state, action, editor, session, text) { if (text == "\n") { var cursor = editor.getCursorPosition(); var line = session.getLine(cursor.row); - var rightChars = line.substring(cursor.column, cursor.column + 2); - if (rightChars == ' -1; @@ -1657,29 +1668,56 @@ var XmlBehaviour = function () { return; return { - text: '>' + '', + text: ">" + "", selection: [1, 1] }; } }); - this.add('autoindent', 'insertion', function (state, action, editor, session, text) { + this.add("autoindent", "insertion", function (state, action, editor, session, text) { if (text == "\n") { var cursor = editor.getCursorPosition(); var line = session.getLine(cursor.row); - var rightChars = line.substring(cursor.column, cursor.column + 2); - if (rightChars == ' -1; @@ -1657,29 +1668,56 @@ var XmlBehaviour = function () { return; return { - text: '>' + '', + text: ">" + "", selection: [1, 1] }; } }); - this.add('autoindent', 'insertion', function (state, action, editor, session, text) { + this.add("autoindent", "insertion", function (state, action, editor, session, text) { if (text == "\n") { var cursor = editor.getCursorPosition(); var line = session.getLine(cursor.row); - var rightChars = line.substring(cursor.column, cursor.column + 2); - if (rightChars == ' -1; @@ -311,29 +312,56 @@ var XmlBehaviour = function () { return; return { - text: '>' + '', + text: ">" + "", selection: [1, 1] }; } }); - this.add('autoindent', 'insertion', function (state, action, editor, session, text) { + this.add("autoindent", "insertion", function (state, action, editor, session, text) { if (text == "\n") { var cursor = editor.getCursorPosition(); var line = session.getLine(cursor.row); - var rightChars = line.substring(cursor.column, cursor.column + 2); - if (rightChars == ' -1; @@ -2529,29 +2530,56 @@ var XmlBehaviour = function () { return; return { - text: '>' + '', + text: ">" + "", selection: [1, 1] }; } }); - this.add('autoindent', 'insertion', function (state, action, editor, session, text) { + this.add("autoindent", "insertion", function (state, action, editor, session, text) { if (text == "\n") { var cursor = editor.getCursorPosition(); var line = session.getLine(cursor.row); - var rightChars = line.substring(cursor.column, cursor.column + 2); - if (rightChars == ' "a"}; - } - } - - return [val]; - }}, - {regex: /}/, onMatch: function(val, state, stack) { - return [stack.length ? stack.shift() : val]; - }}, - {regex: /\$(?:\d+|\w+)/, onMatch: TabstopToken}, - {regex: /\$\{[\dA-Z_a-z]+/, onMatch: function(str, state, stack) { - var t = TabstopToken(str.substr(1), state, stack); - stack.unshift(t[0]); - return t; - }, next: "snippetVar"}, - {regex: /\n/, token: "newline", merge: false} - ], - snippetVar: [ - {regex: "\\|" + escape("\\|") + "*\\|", onMatch: function(val, state, stack) { - stack[0].choices = val.slice(1, -1).split(","); - }, next: "start"}, - {regex: "/(" + escape("/") + "+)/(?:(" + escape("/") + "*)/)(\\w*):?", - onMatch: function(val, state, stack) { - var ts = stack[0]; - ts.fmtString = val; - - val = this.splitRegex.exec(val); - ts.guard = val[1]; - ts.fmt = val[2]; - ts.flag = val[3]; - return ""; - }, next: "start"}, - {regex: "`" + escape("`") + "*`", onMatch: function(val, state, stack) { - stack[0].code = val.splice(1, -1); - return ""; - }, next: "start"}, - {regex: "\\?", onMatch: function(val, state, stack) { - if (stack[0]) - stack[0].expectIf = true; - }, next: "start"}, - {regex: "([^:}\\\\]|\\\\.)*:?", token: "", next: "start"} - ], - formatString: [ - {regex: "/(" + escape("/") + "+)/", token: "regex"}, - {regex: "", onMatch: function(val, state, stack) { - stack.inFormatString = true; - }, next: "start"} - ] - }); - SnippetManager.prototype.getTokenizer = function() { - return SnippetManager.$tokenizer; - }; - return SnippetManager.$tokenizer; - }; - - this.tokenizeTmSnippet = function(str, startState) { - return this.getTokenizer().getLineTokens(str, startState).tokens.map(function(x) { - return x.value || x; - }); - }; - - this.$getDefaultValue = function(editor, name) { - if (/^[A-Z]\d+$/.test(name)) { - var i = name.substr(1); - return (this.variables[name[0] + "__"] || {})[i]; - } - if (/^\d+$/.test(name)) { - return (this.variables.__ || {})[name]; - } - name = name.replace(/^TM_/, ""); - - if (!editor) - return; - var s = editor.session; - switch(name) { - case "CURRENT_WORD": - var r = s.getWordRange(); - case "SELECTION": - case "SELECTED_TEXT": - return s.getTextRange(r); - case "CURRENT_LINE": - return s.getLine(editor.getCursorPosition().row); - case "PREV_LINE": // not possible in textmate - return s.getLine(editor.getCursorPosition().row - 1); - case "LINE_INDEX": - return editor.getCursorPosition().column; - case "LINE_NUMBER": - return editor.getCursorPosition().row + 1; - case "SOFT_TABS": - return s.getUseSoftTabs() ? "YES" : "NO"; - case "TAB_SIZE": - return s.getTabSize(); - case "FILENAME": - case "FILEPATH": - return ""; - case "FULLNAME": - return "Ace"; - } - }; - this.variables = {}; - this.getVariableValue = function(editor, varName) { - if (this.variables.hasOwnProperty(varName)) - return this.variables[varName](editor, varName) || ""; - return this.$getDefaultValue(editor, varName) || ""; - }; - this.tmStrFormat = function(str, ch, editor) { - var flag = ch.flag || ""; - var re = ch.guard; - re = new RegExp(re, flag.replace(/[^gi]/, "")); - var fmtTokens = this.tokenizeTmSnippet(ch.fmt, "formatString"); - var _self = this; - var formatted = str.replace(re, function() { - _self.variables.__ = arguments; - var fmtParts = _self.resolveVariables(fmtTokens, editor); - var gChangeCase = "E"; - for (var i = 0; i < fmtParts.length; i++) { - var ch = fmtParts[i]; - if (typeof ch == "object") { - fmtParts[i] = ""; - if (ch.changeCase && ch.local) { - var next = fmtParts[i + 1]; - if (next && typeof next == "string") { - if (ch.changeCase == "u") - fmtParts[i] = next[0].toUpperCase(); - else - fmtParts[i] = next[0].toLowerCase(); - fmtParts[i + 1] = next.substr(1); - } - } else if (ch.changeCase) { - gChangeCase = ch.changeCase; - } - } else if (gChangeCase == "U") { - fmtParts[i] = ch.toUpperCase(); - } else if (gChangeCase == "L") { - fmtParts[i] = ch.toLowerCase(); - } - } - return fmtParts.join(""); - }); - this.variables.__ = null; - return formatted; - }; - - this.resolveVariables = function(snippet, editor) { - var result = []; - for (var i = 0; i < snippet.length; i++) { - var ch = snippet[i]; - if (typeof ch == "string") { - result.push(ch); - } else if (typeof ch != "object") { - continue; - } else if (ch.skip) { - gotoNext(ch); - } else if (ch.processed < i) { - continue; - } else if (ch.text) { - var value = this.getVariableValue(editor, ch.text); - if (value && ch.fmtString) - value = this.tmStrFormat(value, ch); - ch.processed = i; - if (ch.expectIf == null) { - if (value) { - result.push(value); - gotoNext(ch); - } - } else { - if (value) { - ch.skip = ch.elseBranch; - } else - gotoNext(ch); - } - } else if (ch.tabstopId != null) { - result.push(ch); - } else if (ch.changeCase != null) { - result.push(ch); - } - } - function gotoNext(ch) { - var i1 = snippet.indexOf(ch, i + 1); - if (i1 != -1) - i = i1; - } - return result; - }; - - this.insertSnippetForSelection = function(editor, snippetText) { - var cursor = editor.getCursorPosition(); - var line = editor.session.getLine(cursor.row); - var tabString = editor.session.getTabString(); - var indentString = line.match(/^\s*/)[0]; - - if (cursor.column < indentString.length) - indentString = indentString.slice(0, cursor.column); - - var tokens = this.tokenizeTmSnippet(snippetText); - tokens = this.resolveVariables(tokens, editor); - tokens = tokens.map(function(x) { - if (x == "\n") - return x + indentString; - if (typeof x == "string") - return x.replace(/\t/g, tabString); - return x; - }); - var tabstops = []; - tokens.forEach(function(p, i) { - if (typeof p != "object") - return; - var id = p.tabstopId; - var ts = tabstops[id]; - if (!ts) { - ts = tabstops[id] = []; - ts.index = id; - ts.value = ""; - } - if (ts.indexOf(p) !== -1) - return; - ts.push(p); - var i1 = tokens.indexOf(p, i + 1); - if (i1 === -1) - return; - - var value = tokens.slice(i + 1, i1); - var isNested = value.some(function(t) {return typeof t === "object"}); - if (isNested && !ts.value) { - ts.value = value; - } else if (value.length && (!ts.value || typeof ts.value !== "string")) { - ts.value = value.join(""); - } - }); - tabstops.forEach(function(ts) {ts.length = 0}); - var expanding = {}; - function copyValue(val) { - var copy = []; - for (var i = 0; i < val.length; i++) { - var p = val[i]; - if (typeof p == "object") { - if (expanding[p.tabstopId]) - continue; - var j = val.lastIndexOf(p, i - 1); - p = copy[j] || {tabstopId: p.tabstopId}; - } - copy[i] = p; - } - return copy; - } - for (var i = 0; i < tokens.length; i++) { - var p = tokens[i]; - if (typeof p != "object") - continue; - var id = p.tabstopId; - var i1 = tokens.indexOf(p, i + 1); - if (expanding[id]) { - if (expanding[id] === p) - expanding[id] = null; - continue; - } - - var ts = tabstops[id]; - var arg = typeof ts.value == "string" ? [ts.value] : copyValue(ts.value); - arg.unshift(i + 1, Math.max(0, i1 - i)); - arg.push(p); - expanding[id] = p; - tokens.splice.apply(tokens, arg); - - if (ts.indexOf(p) === -1) - ts.push(p); - } - var row = 0, column = 0; - var text = ""; - tokens.forEach(function(t) { - if (typeof t === "string") { - if (t[0] === "\n"){ - column = t.length - 1; - row ++; - } else - column += t.length; - text += t; - } else { - if (!t.start) - t.start = {row: row, column: column}; - else - t.end = {row: row, column: column}; - } - }); - var range = editor.getSelectionRange(); - var end = editor.session.replace(range, text); - - var tabstopManager = new TabstopManager(editor); - var selectionId = editor.inVirtualSelectionMode && editor.selection.index; - tabstopManager.addTabstops(tabstops, range.start, end, selectionId); - }; - - this.insertSnippet = function(editor, snippetText) { - var self = this; - if (editor.inVirtualSelectionMode) - return self.insertSnippetForSelection(editor, snippetText); - - editor.forEachSelection(function() { - self.insertSnippetForSelection(editor, snippetText); - }, null, {keepOrder: true}); - - if (editor.tabstopManager) - editor.tabstopManager.tabNext(); - }; - - this.$getScope = function(editor) { - var scope = editor.session.$mode.$id || ""; - scope = scope.split("/").pop(); - if (scope === "html" || scope === "php") { - if (scope === "php" && !editor.session.$mode.inlinePhp) - scope = "html"; - var c = editor.getCursorPosition(); - var state = editor.session.getState(c.row); - if (typeof state === "object") { - state = state[0]; - } - if (state.substring) { - if (state.substring(0, 3) == "js-") - scope = "javascript"; - else if (state.substring(0, 4) == "css-") - scope = "css"; - else if (state.substring(0, 4) == "php-") - scope = "php"; - } - } - - return scope; - }; - - this.getActiveScopes = function(editor) { - var scope = this.$getScope(editor); - var scopes = [scope]; - var snippetMap = this.snippetMap; - if (snippetMap[scope] && snippetMap[scope].includeScopes) { - scopes.push.apply(scopes, snippetMap[scope].includeScopes); - } - scopes.push("_"); - return scopes; - }; - - this.expandWithTab = function(editor, options) { - var self = this; - var result = editor.forEachSelection(function() { - return self.expandSnippetForSelection(editor, options); - }, null, {keepOrder: true}); - if (result && editor.tabstopManager) - editor.tabstopManager.tabNext(); - return result; - }; - - this.expandSnippetForSelection = function(editor, options) { - var cursor = editor.getCursorPosition(); - var line = editor.session.getLine(cursor.row); - var before = line.substring(0, cursor.column); - var after = line.substr(cursor.column); - - var snippetMap = this.snippetMap; - var snippet; - this.getActiveScopes(editor).some(function(scope) { - var snippets = snippetMap[scope]; - if (snippets) - snippet = this.findMatchingSnippet(snippets, before, after); - return !!snippet; - }, this); - if (!snippet) - return false; - if (options && options.dryRun) - return true; - editor.session.doc.removeInLine(cursor.row, - cursor.column - snippet.replaceBefore.length, - cursor.column + snippet.replaceAfter.length - ); - - this.variables.M__ = snippet.matchBefore; - this.variables.T__ = snippet.matchAfter; - this.insertSnippetForSelection(editor, snippet.content); - - this.variables.M__ = this.variables.T__ = null; - return true; - }; - - this.findMatchingSnippet = function(snippetList, before, after) { - for (var i = snippetList.length; i--;) { - var s = snippetList[i]; - if (s.startRe && !s.startRe.test(before)) - continue; - if (s.endRe && !s.endRe.test(after)) - continue; - if (!s.startRe && !s.endRe) - continue; - - s.matchBefore = s.startRe ? s.startRe.exec(before) : [""]; - s.matchAfter = s.endRe ? s.endRe.exec(after) : [""]; - s.replaceBefore = s.triggerRe ? s.triggerRe.exec(before)[0] : ""; - s.replaceAfter = s.endTriggerRe ? s.endTriggerRe.exec(after)[0] : ""; - return s; - } - }; - - this.snippetMap = {}; - this.snippetNameMap = {}; - this.register = function(snippets, scope) { - var snippetMap = this.snippetMap; - var snippetNameMap = this.snippetNameMap; - var self = this; - - if (!snippets) - snippets = []; - - function wrapRegexp(src) { - if (src && !/^\^?\(.*\)\$?$|^\\b$/.test(src)) - src = "(?:" + src + ")"; - - return src || ""; - } - function guardedRegexp(re, guard, opening) { - re = wrapRegexp(re); - guard = wrapRegexp(guard); - if (opening) { - re = guard + re; - if (re && re[re.length - 1] != "$") - re = re + "$"; - } else { - re = re + guard; - if (re && re[0] != "^") - re = "^" + re; - } - return new RegExp(re); - } - - function addSnippet(s) { - if (!s.scope) - s.scope = scope || "_"; - scope = s.scope; - if (!snippetMap[scope]) { - snippetMap[scope] = []; - snippetNameMap[scope] = {}; - } - - var map = snippetNameMap[scope]; - if (s.name) { - var old = map[s.name]; - if (old) - self.unregister(old); - map[s.name] = s; - } - snippetMap[scope].push(s); - - if (s.tabTrigger && !s.trigger) { - if (!s.guard && /^\w/.test(s.tabTrigger)) - s.guard = "\\b"; - s.trigger = lang.escapeRegExp(s.tabTrigger); - } - - s.startRe = guardedRegexp(s.trigger, s.guard, true); - s.triggerRe = new RegExp(s.trigger, "", true); - - s.endRe = guardedRegexp(s.endTrigger, s.endGuard, true); - s.endTriggerRe = new RegExp(s.endTrigger, "", true); - } - - if (snippets && snippets.content) - addSnippet(snippets); - else if (Array.isArray(snippets)) - snippets.forEach(addSnippet); - - this._signal("registerSnippets", {scope: scope}); - }; - this.unregister = function(snippets, scope) { - var snippetMap = this.snippetMap; - var snippetNameMap = this.snippetNameMap; - - function removeSnippet(s) { - var nameMap = snippetNameMap[s.scope||scope]; - if (nameMap && nameMap[s.name]) { - delete nameMap[s.name]; - var map = snippetMap[s.scope||scope]; - var i = map && map.indexOf(s); - if (i >= 0) - map.splice(i, 1); - } - } - if (snippets.content) - removeSnippet(snippets); - else if (Array.isArray(snippets)) - snippets.forEach(removeSnippet); - }; - this.parseSnippetFile = function(str) { - str = str.replace(/\r/g, ""); - var list = [], snippet = {}; - var re = /^#.*|^({[\s\S]*})\s*$|^(\S+) (.*)$|^((?:\n*\t.*)+)/gm; - var m; - while (m = re.exec(str)) { - if (m[1]) { - try { - snippet = JSON.parse(m[1]); - list.push(snippet); - } catch (e) {} - } if (m[4]) { - snippet.content = m[4].replace(/^\t/gm, ""); - list.push(snippet); - snippet = {}; - } else { - var key = m[2], val = m[3]; - if (key == "regex") { - var guardRe = /\/((?:[^\/\\]|\\.)*)|$/g; - snippet.guard = guardRe.exec(val)[1]; - snippet.trigger = guardRe.exec(val)[1]; - snippet.endTrigger = guardRe.exec(val)[1]; - snippet.endGuard = guardRe.exec(val)[1]; - } else if (key == "snippet") { - snippet.tabTrigger = val.match(/^\S*/)[0]; - if (!snippet.name) - snippet.name = val; - } else { - snippet[key] = val; - } - } - } - return list; - }; - this.getSnippetByName = function(name, editor) { - var snippetMap = this.snippetNameMap; - var snippet; - this.getActiveScopes(editor).some(function(scope) { - var snippets = snippetMap[scope]; - if (snippets) - snippet = snippets[name]; - return !!snippet; - }, this); - return snippet; - }; - -}).call(SnippetManager.prototype); - - -var TabstopManager = function(editor) { - if (editor.tabstopManager) - return editor.tabstopManager; - editor.tabstopManager = this; - this.$onChange = this.onChange.bind(this); - this.$onChangeSelection = lang.delayedCall(this.onChangeSelection.bind(this)).schedule; - this.$onChangeSession = this.onChangeSession.bind(this); - this.$onAfterExec = this.onAfterExec.bind(this); - this.attach(editor); -}; -(function() { - this.attach = function(editor) { - this.index = 0; - this.ranges = []; - this.tabstops = []; - this.$openTabstops = null; - this.selectedTabstop = null; - - this.editor = editor; - this.editor.on("change", this.$onChange); - this.editor.on("changeSelection", this.$onChangeSelection); - this.editor.on("changeSession", this.$onChangeSession); - this.editor.commands.on("afterExec", this.$onAfterExec); - this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler); - }; - this.detach = function() { - this.tabstops.forEach(this.removeTabstopMarkers, this); - this.ranges = null; - this.tabstops = null; - this.selectedTabstop = null; - this.editor.removeListener("change", this.$onChange); - this.editor.removeListener("changeSelection", this.$onChangeSelection); - this.editor.removeListener("changeSession", this.$onChangeSession); - this.editor.commands.removeListener("afterExec", this.$onAfterExec); - this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler); - this.editor.tabstopManager = null; - this.editor = null; - }; - - this.onChange = function(e) { - var changeRange = e.data.range; - var isRemove = e.data.action[0] == "r"; - var start = changeRange.start; - var end = changeRange.end; - var startRow = start.row; - var endRow = end.row; - var lineDif = endRow - startRow; - var colDiff = end.column - start.column; - - if (isRemove) { - lineDif = -lineDif; - colDiff = -colDiff; - } - if (!this.$inChange && isRemove) { - var ts = this.selectedTabstop; - var changedOutside = ts && !ts.some(function(r) { - return comparePoints(r.start, start) <= 0 && comparePoints(r.end, end) >= 0; - }); - if (changedOutside) - return this.detach(); - } - var ranges = this.ranges; - for (var i = 0; i < ranges.length; i++) { - var r = ranges[i]; - if (r.end.row < start.row) - continue; - - if (isRemove && comparePoints(start, r.start) < 0 && comparePoints(end, r.end) > 0) { - this.removeRange(r); - i--; - continue; - } - - if (r.start.row == startRow && r.start.column > start.column) - r.start.column += colDiff; - if (r.end.row == startRow && r.end.column >= start.column) - r.end.column += colDiff; - if (r.start.row >= startRow) - r.start.row += lineDif; - if (r.end.row >= startRow) - r.end.row += lineDif; - - if (comparePoints(r.start, r.end) > 0) - this.removeRange(r); - } - if (!ranges.length) - this.detach(); - }; - this.updateLinkedFields = function() { - var ts = this.selectedTabstop; - if (!ts || !ts.hasLinkedRanges) - return; - this.$inChange = true; - var session = this.editor.session; - var text = session.getTextRange(ts.firstNonLinked); - for (var i = ts.length; i--;) { - var range = ts[i]; - if (!range.linked) - continue; - var fmt = exports.snippetManager.tmStrFormat(text, range.original); - session.replace(range, fmt); - } - this.$inChange = false; - }; - this.onAfterExec = function(e) { - if (e.command && !e.command.readOnly) - this.updateLinkedFields(); - }; - this.onChangeSelection = function() { - if (!this.editor) - return; - var lead = this.editor.selection.lead; - var anchor = this.editor.selection.anchor; - var isEmpty = this.editor.selection.isEmpty(); - for (var i = this.ranges.length; i--;) { - if (this.ranges[i].linked) - continue; - var containsLead = this.ranges[i].contains(lead.row, lead.column); - var containsAnchor = isEmpty || this.ranges[i].contains(anchor.row, anchor.column); - if (containsLead && containsAnchor) - return; - } - this.detach(); - }; - this.onChangeSession = function() { - this.detach(); - }; - this.tabNext = function(dir) { - var max = this.tabstops.length; - var index = this.index + (dir || 1); - index = Math.min(Math.max(index, 1), max); - if (index == max) - index = 0; - this.selectTabstop(index); - if (index === 0) - this.detach(); - }; - this.selectTabstop = function(index) { - this.$openTabstops = null; - var ts = this.tabstops[this.index]; - if (ts) - this.addTabstopMarkers(ts); - this.index = index; - ts = this.tabstops[this.index]; - if (!ts || !ts.length) - return; - - this.selectedTabstop = ts; - if (!this.editor.inVirtualSelectionMode) { - var sel = this.editor.multiSelect; - sel.toSingleRange(ts.firstNonLinked.clone()); - for (var i = ts.length; i--;) { - if (ts.hasLinkedRanges && ts[i].linked) - continue; - sel.addRange(ts[i].clone(), true); - } - if (sel.ranges[0]) - sel.addRange(sel.ranges[0].clone()); - } else { - this.editor.selection.setRange(ts.firstNonLinked); - } - - this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler); - }; - this.addTabstops = function(tabstops, start, end) { - if (!this.$openTabstops) - this.$openTabstops = []; - if (!tabstops[0]) { - var p = Range.fromPoints(end, end); - moveRelative(p.start, start); - moveRelative(p.end, start); - tabstops[0] = [p]; - tabstops[0].index = 0; - } - - var i = this.index; - var arg = [i + 1, 0]; - var ranges = this.ranges; - tabstops.forEach(function(ts, index) { - var dest = this.$openTabstops[index] || ts; - - for (var i = ts.length; i--;) { - var p = ts[i]; - var range = Range.fromPoints(p.start, p.end || p.start); - movePoint(range.start, start); - movePoint(range.end, start); - range.original = p; - range.tabstop = dest; - ranges.push(range); - if (dest != ts) - dest.unshift(range); - else - dest[i] = range; - if (p.fmtString) { - range.linked = true; - dest.hasLinkedRanges = true; - } else if (!dest.firstNonLinked) - dest.firstNonLinked = range; - } - if (!dest.firstNonLinked) - dest.hasLinkedRanges = false; - if (dest === ts) { - arg.push(dest); - this.$openTabstops[index] = dest; - } - this.addTabstopMarkers(dest); - }, this); - - if (arg.length > 2) { - if (this.tabstops.length) - arg.push(arg.splice(2, 1)[0]); - this.tabstops.splice.apply(this.tabstops, arg); - } - }; - - this.addTabstopMarkers = function(ts) { - var session = this.editor.session; - ts.forEach(function(range) { - if (!range.markerId) - range.markerId = session.addMarker(range, "ace_snippet-marker", "text"); - }); - }; - this.removeTabstopMarkers = function(ts) { - var session = this.editor.session; - ts.forEach(function(range) { - session.removeMarker(range.markerId); - range.markerId = null; - }); - }; - this.removeRange = function(range) { - var i = range.tabstop.indexOf(range); - range.tabstop.splice(i, 1); - i = this.ranges.indexOf(range); - this.ranges.splice(i, 1); - this.editor.session.removeMarker(range.markerId); - if (!range.tabstop.length) { - i = this.tabstops.indexOf(range.tabstop); - if (i != -1) - this.tabstops.splice(i, 1); - if (!this.tabstops.length) - this.detach(); - } - }; - - this.keyboardHandler = new HashHandler(); - this.keyboardHandler.bindKeys({ - "Tab": function(ed) { - if (exports.snippetManager && exports.snippetManager.expandWithTab(ed)) { - return; - } - - ed.tabstopManager.tabNext(1); - }, - "Shift-Tab": function(ed) { - ed.tabstopManager.tabNext(-1); - }, - "Esc": function(ed) { - ed.tabstopManager.detach(); - }, - "Return": function(ed) { - return false; - } - }); -}).call(TabstopManager.prototype); - - - -var changeTracker = {}; -changeTracker.onChange = Anchor.prototype.onChange; -changeTracker.setPosition = function(row, column) { - this.pos.row = row; - this.pos.column = column; -}; -changeTracker.update = function(pos, delta, $insertRight) { - this.$insertRight = $insertRight; - this.pos = pos; - this.onChange(delta); -}; - -var movePoint = function(point, diff) { - if (point.row == 0) - point.column += diff.column; - point.row += diff.row; -}; - -var moveRelative = function(point, start) { - if (point.row == start.row) - point.column -= start.column; - point.row -= start.row; -}; - - -require("./lib/dom").importCssString("\ -.ace_snippet-marker {\ - -moz-box-sizing: border-box;\ - box-sizing: border-box;\ - background: rgba(194, 193, 208, 0.09);\ - border: 1px dotted rgba(211, 208, 235, 0.62);\ - position: absolute;\ -}"); - -exports.snippetManager = new SnippetManager(); - - -var Editor = require("./editor").Editor; -(function() { - this.insertSnippet = function(content, options) { - return exports.snippetManager.insertSnippet(this, content, options); - }; - this.expandSnippet = function(options) { - return exports.snippetManager.expandWithTab(this, options); - }; -}).call(Editor.prototype); - -}); - -ace.define("ace/autocomplete/popup",["require","exports","module","ace/edit_session","ace/virtual_renderer","ace/editor","ace/range","ace/lib/event","ace/lib/lang","ace/lib/dom"], function(require, exports, module) { -"use strict"; - -var EditSession = require("../edit_session").EditSession; -var Renderer = require("../virtual_renderer").VirtualRenderer; -var Editor = require("../editor").Editor; -var Range = require("../range").Range; -var event = require("../lib/event"); -var lang = require("../lib/lang"); -var dom = require("../lib/dom"); - -var $singleLineEditor = function(el) { - var renderer = new Renderer(el); - - renderer.$maxLines = 4; - - var editor = new Editor(renderer); - - editor.setHighlightActiveLine(false); - editor.setShowPrintMargin(false); - editor.renderer.setShowGutter(false); - editor.renderer.setHighlightGutterLine(false); - - editor.$mouseHandler.$focusWaitTimout = 0; - editor.$highlightTagPending = true; - - return editor; -}; - -var AcePopup = function(parentNode) { - var el = dom.createElement("div"); - var popup = new $singleLineEditor(el); - - if (parentNode) - parentNode.appendChild(el); - el.style.display = "none"; - popup.renderer.content.style.cursor = "default"; - popup.renderer.setStyle("ace_autocomplete"); - - popup.setOption("displayIndentGuides", false); - popup.setOption("dragDelay", 150); - - var noop = function(){}; - - popup.focus = noop; - popup.$isFocused = true; - - popup.renderer.$cursorLayer.restartTimer = noop; - popup.renderer.$cursorLayer.element.style.opacity = 0; - - popup.renderer.$maxLines = 8; - popup.renderer.$keepTextAreaAtCursor = false; - - popup.setHighlightActiveLine(false); - popup.session.highlight(""); - popup.session.$searchHighlight.clazz = "ace_highlight-marker"; - - popup.on("mousedown", function(e) { - var pos = e.getDocumentPosition(); - popup.selection.moveToPosition(pos); - selectionMarker.start.row = selectionMarker.end.row = pos.row; - e.stop(); - }); - - var lastMouseEvent; - var hoverMarker = new Range(-1,0,-1,Infinity); - var selectionMarker = new Range(-1,0,-1,Infinity); - selectionMarker.id = popup.session.addMarker(selectionMarker, "ace_active-line", "fullLine"); - popup.setSelectOnHover = function(val) { - if (!val) { - hoverMarker.id = popup.session.addMarker(hoverMarker, "ace_line-hover", "fullLine"); - } else if (hoverMarker.id) { - popup.session.removeMarker(hoverMarker.id); - hoverMarker.id = null; - } - }; - popup.setSelectOnHover(false); - popup.on("mousemove", function(e) { - if (!lastMouseEvent) { - lastMouseEvent = e; - return; - } - if (lastMouseEvent.x == e.x && lastMouseEvent.y == e.y) { - return; - } - lastMouseEvent = e; - lastMouseEvent.scrollTop = popup.renderer.scrollTop; - var row = lastMouseEvent.getDocumentPosition().row; - if (hoverMarker.start.row != row) { - if (!hoverMarker.id) - popup.setRow(row); - setHoverMarker(row); - } - }); - popup.renderer.on("beforeRender", function() { - if (lastMouseEvent && hoverMarker.start.row != -1) { - lastMouseEvent.$pos = null; - var row = lastMouseEvent.getDocumentPosition().row; - if (!hoverMarker.id) - popup.setRow(row); - setHoverMarker(row, true); - } - }); - popup.renderer.on("afterRender", function() { - var row = popup.getRow(); - var t = popup.renderer.$textLayer; - var selected = t.element.childNodes[row - t.config.firstRow]; - if (selected == t.selectedNode) - return; - if (t.selectedNode) - dom.removeCssClass(t.selectedNode, "ace_selected"); - t.selectedNode = selected; - if (selected) - dom.addCssClass(selected, "ace_selected"); - }); - var hideHoverMarker = function() { setHoverMarker(-1) }; - var setHoverMarker = function(row, suppressRedraw) { - if (row !== hoverMarker.start.row) { - hoverMarker.start.row = hoverMarker.end.row = row; - if (!suppressRedraw) - popup.session._emit("changeBackMarker"); - popup._emit("changeHoverMarker"); - } - }; - popup.getHoveredRow = function() { - return hoverMarker.start.row; - }; - - event.addListener(popup.container, "mouseout", hideHoverMarker); - popup.on("hide", hideHoverMarker); - popup.on("changeSelection", hideHoverMarker); - - popup.session.doc.getLength = function() { - return popup.data.length; - }; - popup.session.doc.getLine = function(i) { - var data = popup.data[i]; - if (typeof data == "string") - return data; - return (data && data.value) || ""; - }; - - var bgTokenizer = popup.session.bgTokenizer; - bgTokenizer.$tokenizeRow = function(row) { - var data = popup.data[row]; - var tokens = []; - if (!data) - return tokens; - if (typeof data == "string") - data = {value: data}; - if (!data.caption) - data.caption = data.value || data.name; - - var last = -1; - var flag, c; - for (var i = 0; i < data.caption.length; i++) { - c = data.caption[i]; - flag = data.matchMask & (1 << i) ? 1 : 0; - if (last !== flag) { - tokens.push({type: data.className || "" + ( flag ? "completion-highlight" : ""), value: c}); - last = flag; - } else { - tokens[tokens.length - 1].value += c; - } - } - - if (data.meta) { - var maxW = popup.renderer.$size.scrollerWidth / popup.renderer.layerConfig.characterWidth; - if (data.meta.length + data.caption.length < maxW - 2) - tokens.push({type: "rightAlignedText", value: data.meta}); - } - return tokens; - }; - bgTokenizer.$updateOnChange = noop; - bgTokenizer.start = noop; - - popup.session.$computeWidth = function() { - return this.screenWidth = 0; - }; - popup.isOpen = false; - popup.isTopdown = false; - - popup.data = []; - popup.setData = function(list) { - popup.data = list || []; - popup.setValue(lang.stringRepeat("\n", list.length), -1); - popup.setRow(0); - }; - popup.getData = function(row) { - return popup.data[row]; - }; - - popup.getRow = function() { - return selectionMarker.start.row; - }; - popup.setRow = function(line) { - line = Math.max(-1, Math.min(this.data.length, line)); - if (selectionMarker.start.row != line) { - popup.selection.clearSelection(); - selectionMarker.start.row = selectionMarker.end.row = line || 0; - popup.session._emit("changeBackMarker"); - popup.moveCursorTo(line || 0, 0); - if (popup.isOpen) - popup._signal("select"); - } - }; - - popup.on("changeSelection", function() { - if (popup.isOpen) - popup.setRow(popup.selection.lead.row); - }); - - popup.hide = function() { - this.container.style.display = "none"; - this._signal("hide"); - popup.isOpen = false; - }; - popup.show = function(pos, lineHeight, topdownOnly) { - var el = this.container; - var screenHeight = window.innerHeight; - var screenWidth = window.innerWidth; - var renderer = this.renderer; - var maxH = renderer.$maxLines * lineHeight * 1.4; - var top = pos.top + this.$borderSize; - if (top + maxH > screenHeight - lineHeight && !topdownOnly) { - el.style.top = ""; - el.style.bottom = screenHeight - top + "px"; - popup.isTopdown = false; - } else { - top += lineHeight; - el.style.top = top + "px"; - el.style.bottom = ""; - popup.isTopdown = true; - } - - el.style.display = ""; - this.renderer.$textLayer.checkForSizeChanges(); - - var left = pos.left; - if (left + el.offsetWidth > screenWidth) - left = screenWidth - el.offsetWidth; - - el.style.left = left + "px"; - - this._signal("show"); - lastMouseEvent = null; - popup.isOpen = true; - }; - - popup.getTextLeftOffset = function() { - return this.$borderSize + this.renderer.$padding + this.$imageSize; - }; - - popup.$imageSize = 0; - popup.$borderSize = 1; - - return popup; -}; - -dom.importCssString("\ -.ace_editor.ace_autocomplete .ace_marker-layer .ace_active-line {\ - background-color: #CAD6FA;\ - z-index: 1;\ -}\ -.ace_editor.ace_autocomplete .ace_line-hover {\ - border: 1px solid #abbffe;\ - margin-top: -1px;\ - background: rgba(233,233,253,0.4);\ -}\ -.ace_editor.ace_autocomplete .ace_line-hover {\ - position: absolute;\ - z-index: 2;\ -}\ -.ace_editor.ace_autocomplete .ace_scroller {\ - background: none;\ - border: none;\ - box-shadow: none;\ -}\ -.ace_rightAlignedText {\ - color: gray;\ - display: inline-block;\ - position: absolute;\ - right: 4px;\ - text-align: right;\ - z-index: -1;\ -}\ -.ace_editor.ace_autocomplete .ace_completion-highlight{\ - color: #000;\ - text-shadow: 0 0 0.01em;\ -}\ -.ace_editor.ace_autocomplete {\ - width: 280px;\ - z-index: 200000;\ - background: #fbfbfb;\ - color: #444;\ - border: 1px lightgray solid;\ - position: fixed;\ - box-shadow: 2px 3px 5px rgba(0,0,0,.2);\ - line-height: 1.4;\ -}"); - -exports.AcePopup = AcePopup; - -}); - -ace.define("ace/autocomplete/util",["require","exports","module"], function(require, exports, module) { -"use strict"; - -exports.parForEach = function(array, fn, callback) { - var completed = 0; - var arLength = array.length; - if (arLength === 0) - callback(); - for (var i = 0; i < arLength; i++) { - fn(array[i], function(result, err) { - completed++; - if (completed === arLength) - callback(result, err); - }); - } -}; - -var ID_REGEX = /[a-zA-Z_0-9\$\-\u00A2-\uFFFF]/; - -exports.retrievePrecedingIdentifier = function(text, pos, regex) { - regex = regex || ID_REGEX; - var buf = []; - for (var i = pos-1; i >= 0; i--) { - if (regex.test(text[i])) - buf.push(text[i]); - else - break; - } - return buf.reverse().join(""); -}; - -exports.retrieveFollowingIdentifier = function(text, pos, regex) { - regex = regex || ID_REGEX; - var buf = []; - for (var i = pos; i < text.length; i++) { - if (regex.test(text[i])) - buf.push(text[i]); - else - break; - } - return buf; -}; - -}); - -ace.define("ace/autocomplete",["require","exports","module","ace/keyboard/hash_handler","ace/autocomplete/popup","ace/autocomplete/util","ace/lib/event","ace/lib/lang","ace/snippets"], function(require, exports, module) { -"use strict"; - -var HashHandler = require("./keyboard/hash_handler").HashHandler; -var AcePopup = require("./autocomplete/popup").AcePopup; -var util = require("./autocomplete/util"); -var event = require("./lib/event"); -var lang = require("./lib/lang"); -var snippetManager = require("./snippets").snippetManager; - -var Autocomplete = function() { - this.autoInsert = true; - this.autoSelect = true; - this.keyboardHandler = new HashHandler(); - this.keyboardHandler.bindKeys(this.commands); - - this.blurListener = this.blurListener.bind(this); - this.changeListener = this.changeListener.bind(this); - this.mousedownListener = this.mousedownListener.bind(this); - this.mousewheelListener = this.mousewheelListener.bind(this); - - this.changeTimer = lang.delayedCall(function() { - this.updateCompletions(true); - }.bind(this)); -}; - -(function() { - this.gatherCompletionsId = 0; - - this.$init = function() { - this.popup = new AcePopup(document.body || document.documentElement); - this.popup.on("click", function(e) { - this.insertMatch(); - e.stop(); - }.bind(this)); - this.popup.focus = this.editor.focus.bind(this.editor); - }; - - this.openPopup = function(editor, prefix, keepPopupPosition) { - if (!this.popup) - this.$init(); - - this.popup.setData(this.completions.filtered); - - var renderer = editor.renderer; - this.popup.setRow(this.autoSelect ? 0 : -1); - if (!keepPopupPosition) { - this.popup.setTheme(editor.getTheme()); - this.popup.setFontSize(editor.getFontSize()); - - var lineHeight = renderer.layerConfig.lineHeight; - - var pos = renderer.$cursorLayer.getPixelPosition(this.base, true); - pos.left -= this.popup.getTextLeftOffset(); - - var rect = editor.container.getBoundingClientRect(); - pos.top += rect.top - renderer.layerConfig.offset; - pos.left += rect.left - editor.renderer.scrollLeft; - pos.left += renderer.$gutterLayer.gutterWidth; - - this.popup.show(pos, lineHeight); - } else if (keepPopupPosition && !prefix) { - this.detach(); - } - }; - - this.detach = function() { - this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler); - this.editor.off("changeSelection", this.changeListener); - this.editor.off("blur", this.blurListener); - this.editor.off("mousedown", this.mousedownListener); - this.editor.off("mousewheel", this.mousewheelListener); - this.changeTimer.cancel(); - - if (this.popup && this.popup.isOpen) { - this.gatherCompletionsId += 1; - this.popup.hide(); - } - - if (this.base) - this.base.detach(); - this.activated = false; - this.completions = this.base = null; - }; - - this.changeListener = function(e) { - var cursor = this.editor.selection.lead; - if (cursor.row != this.base.row || cursor.column < this.base.column) { - this.detach(); - } - if (this.activated) - this.changeTimer.schedule(); - else - this.detach(); - }; - - this.blurListener = function() { - var el = document.activeElement; - if (el != this.editor.textInput.getElement() && el.parentNode != this.popup.container) - this.detach(); - }; - - this.mousedownListener = function(e) { - this.detach(); - }; - - this.mousewheelListener = function(e) { - this.detach(); - }; - - this.goTo = function(where) { - var row = this.popup.getRow(); - var max = this.popup.session.getLength() - 1; - - switch(where) { - case "up": row = row <= 0 ? max : row - 1; break; - case "down": row = row >= max ? -1 : row + 1; break; - case "start": row = 0; break; - case "end": row = max; break; - } - - this.popup.setRow(row); - }; - - this.insertMatch = function(data) { - if (!data) - data = this.popup.getData(this.popup.getRow()); - if (!data) - return false; - - if (data.completer && data.completer.insertMatch) { - data.completer.insertMatch(this.editor); - } else { - if (this.completions.filterText) { - var ranges = this.editor.selection.getAllRanges(); - for (var i = 0, range; range = ranges[i]; i++) { - range.start.column -= this.completions.filterText.length; - this.editor.session.remove(range); - } - } - if (data.snippet) - snippetManager.insertSnippet(this.editor, data.snippet); - else - this.editor.execCommand("insertstring", data.value || data); - } - this.detach(); - }; - - this.commands = { - "Up": function(editor) { editor.completer.goTo("up"); }, - "Down": function(editor) { editor.completer.goTo("down"); }, - "Ctrl-Up|Ctrl-Home": function(editor) { editor.completer.goTo("start"); }, - "Ctrl-Down|Ctrl-End": function(editor) { editor.completer.goTo("end"); }, - - "Esc": function(editor) { editor.completer.detach(); }, - "Space": function(editor) { editor.completer.detach(); editor.insert(" ");}, - "Return": function(editor) { return editor.completer.insertMatch(); }, - "Shift-Return": function(editor) { editor.completer.insertMatch(true); }, - "Tab": function(editor) { - var result = editor.completer.insertMatch(); - if (!result && !editor.tabstopManager) - editor.completer.goTo("down"); - else - return result; - }, - - "PageUp": function(editor) { editor.completer.popup.gotoPageUp(); }, - "PageDown": function(editor) { editor.completer.popup.gotoPageDown(); } - }; - - this.gatherCompletions = function(editor, callback) { - var session = editor.getSession(); - var pos = editor.getCursorPosition(); - - var line = session.getLine(pos.row); - var prefix = util.retrievePrecedingIdentifier(line, pos.column); - - this.base = session.doc.createAnchor(pos.row, pos.column - prefix.length); - this.base.$insertRight = true; - - var matches = []; - var total = editor.completers.length; - editor.completers.forEach(function(completer, i) { - completer.getCompletions(editor, session, pos, prefix, function(err, results) { - if (!err) - matches = matches.concat(results); - var pos = editor.getCursorPosition(); - var line = session.getLine(pos.row); - callback(null, { - prefix: util.retrievePrecedingIdentifier(line, pos.column, results[0] && results[0].identifierRegex), - matches: matches, - finished: (--total === 0) - }); - }); - }); - return true; - }; - - this.showPopup = function(editor) { - if (this.editor) - this.detach(); - - this.activated = true; - - this.editor = editor; - if (editor.completer != this) { - if (editor.completer) - editor.completer.detach(); - editor.completer = this; - } - - editor.keyBinding.addKeyboardHandler(this.keyboardHandler); - editor.on("changeSelection", this.changeListener); - editor.on("blur", this.blurListener); - editor.on("mousedown", this.mousedownListener); - editor.on("mousewheel", this.mousewheelListener); - - this.updateCompletions(); - }; - - this.updateCompletions = function(keepPopupPosition) { - if (keepPopupPosition && this.base && this.completions) { - var pos = this.editor.getCursorPosition(); - var prefix = this.editor.session.getTextRange({start: this.base, end: pos}); - if (prefix == this.completions.filterText) - return; - this.completions.setFilter(prefix); - if (!this.completions.filtered.length) - return this.detach(); - if (this.completions.filtered.length == 1 - && this.completions.filtered[0].value == prefix - && !this.completions.filtered[0].snippet) - return this.detach(); - this.openPopup(this.editor, prefix, keepPopupPosition); - return; - } - var _id = this.gatherCompletionsId; - this.gatherCompletions(this.editor, function(err, results) { - var detachIfFinished = function() { - if (!results.finished) return; - return this.detach(); - }.bind(this); - - var prefix = results.prefix; - var matches = results && results.matches; - - if (!matches || !matches.length) - return detachIfFinished(); - if (prefix.indexOf(results.prefix) !== 0 || _id != this.gatherCompletionsId) - return; - - this.completions = new FilteredList(matches); - this.completions.setFilter(prefix); - var filtered = this.completions.filtered; - if (!filtered.length) - return detachIfFinished(); - if (filtered.length == 1 && filtered[0].value == prefix && !filtered[0].snippet) - return detachIfFinished(); - if (this.autoInsert && filtered.length == 1 && results.finished) - return this.insertMatch(filtered[0]); - - this.openPopup(this.editor, prefix, keepPopupPosition); - }.bind(this)); - }; - - this.cancelContextMenu = function() { - this.editor.$mouseHandler.cancelContextMenu(); - }; - -}).call(Autocomplete.prototype); - -Autocomplete.startCommand = { - name: "startAutocomplete", - exec: function(editor) { - if (!editor.completer) - editor.completer = new Autocomplete(); - editor.completer.autoInsert = - editor.completer.autoSelect = true; - editor.completer.showPopup(editor); - editor.completer.cancelContextMenu(); - }, - bindKey: "Ctrl-Space|Ctrl-Shift-Space|Alt-Space" -}; - -var FilteredList = function(array, filterText, mutateData) { - this.all = array; - this.filtered = array; - this.filterText = filterText || ""; -}; -(function(){ - this.setFilter = function(str) { - if (str.length > this.filterText && str.lastIndexOf(this.filterText, 0) === 0) - var matches = this.filtered; - else - var matches = this.all; - - this.filterText = str; - matches = this.filterCompletions(matches, this.filterText); - matches = matches.sort(function(a, b) { - return b.exactMatch - a.exactMatch || b.score - a.score; - }); - var prev = null; - matches = matches.filter(function(item){ - var caption = item.snippet || item.caption || item.value; - if (caption === prev) return false; - prev = caption; - return true; - }); - - this.filtered = matches; - }; - this.filterCompletions = function(items, needle) { - var results = []; - var upper = needle.toUpperCase(); - var lower = needle.toLowerCase(); - loop: for (var i = 0, item; item = items[i]; i++) { - var caption = item.value || item.caption || item.snippet; - if (!caption) continue; - var lastIndex = -1; - var matchMask = 0; - var penalty = 0; - var index, distance; - for (var j = 0; j < needle.length; j++) { - var i1 = caption.indexOf(lower[j], lastIndex + 1); - var i2 = caption.indexOf(upper[j], lastIndex + 1); - index = (i1 >= 0) ? ((i2 < 0 || i1 < i2) ? i1 : i2) : i2; - if (index < 0) - continue loop; - distance = index - lastIndex - 1; - if (distance > 0) { - if (lastIndex === -1) - penalty += 10; - penalty += distance; - } - matchMask = matchMask | (1 << index); - lastIndex = index; - } - item.matchMask = matchMask; - item.exactMatch = penalty ? 0 : 1; - item.score = (item.score || 0) - penalty; - results.push(item); - } - return results; - }; -}).call(FilteredList.prototype); - -exports.Autocomplete = Autocomplete; -exports.FilteredList = FilteredList; - -}); - -ace.define("ace/autocomplete/text_completer",["require","exports","module","ace/range"], function(require, exports, module) { - var Range = require("../range").Range; - - var splitRegex = /[^a-zA-Z_0-9\$\-\u00C0-\u1FFF\u2C00-\uD7FF\w]+/; - - function getWordIndex(doc, pos) { - var textBefore = doc.getTextRange(Range.fromPoints({row: 0, column:0}, pos)); - return textBefore.split(splitRegex).length - 1; - } - function wordDistance(doc, pos) { - var prefixPos = getWordIndex(doc, pos); - var words = doc.getValue().split(splitRegex); - var wordScores = Object.create(null); - - var currentWord = words[prefixPos]; - - words.forEach(function(word, idx) { - if (!word || word === currentWord) return; - - var distance = Math.abs(prefixPos - idx); - var score = words.length - distance; - if (wordScores[word]) { - wordScores[word] = Math.max(score, wordScores[word]); - } else { - wordScores[word] = score; - } - }); - return wordScores; - } - - exports.getCompletions = function(editor, session, pos, prefix, callback) { - var wordScore = wordDistance(session, pos, prefix); - var wordList = Object.keys(wordScore); - callback(null, wordList.map(function(word) { - return { - caption: word, - value: word, - score: wordScore[word], - meta: "local" - }; - })); - }; -}); - -ace.define("ace/ext/language_tools",["require","exports","module","ace/snippets","ace/autocomplete","ace/config","ace/autocomplete/util","ace/autocomplete/text_completer","ace/editor","ace/config"], function(require, exports, module) { -"use strict"; - -var snippetManager = require("../snippets").snippetManager; -var Autocomplete = require("../autocomplete").Autocomplete; -var config = require("../config"); -var util = require("../autocomplete/util"); - -var textCompleter = require("../autocomplete/text_completer"); -var keyWordCompleter = { - getCompletions: function(editor, session, pos, prefix, callback) { - var state = editor.session.getState(pos.row); - var completions = session.$mode.getCompletions(state, session, pos, prefix); - callback(null, completions); - } -}; - -var snippetCompleter = { - getCompletions: function(editor, session, pos, prefix, callback) { - var snippetMap = snippetManager.snippetMap; - var completions = []; - snippetManager.getActiveScopes(editor).forEach(function(scope) { - var snippets = snippetMap[scope] || []; - for (var i = snippets.length; i--;) { - var s = snippets[i]; - var caption = s.name || s.tabTrigger; - if (!caption) - continue; - completions.push({ - caption: caption, - snippet: s.content, - meta: s.tabTrigger && !s.name ? s.tabTrigger + "\u21E5 " : "snippet" - }); - } - }, this); - callback(null, completions); - } -}; - -var completers = [snippetCompleter, textCompleter, keyWordCompleter]; -exports.addCompleter = function(completer) { - completers.push(completer); -}; -exports.textCompleter = textCompleter; -exports.keyWordCompleter = keyWordCompleter; -exports.snippetCompleter = snippetCompleter; - -var expandSnippet = { - name: "expandSnippet", - exec: function(editor) { - var success = snippetManager.expandWithTab(editor); - if (!success) - editor.execCommand("indent"); - }, - bindKey: "Tab" -}; - -var onChangeMode = function(e, editor) { - loadSnippetsForMode(editor.session.$mode); -}; - -var loadSnippetsForMode = function(mode) { - var id = mode.$id; - if (!snippetManager.files) - snippetManager.files = {}; - loadSnippetFile(id); - if (mode.modes) - mode.modes.forEach(loadSnippetsForMode); -}; - -var loadSnippetFile = function(id) { - if (!id || snippetManager.files[id]) - return; - var snippetFilePath = id.replace("mode", "snippets"); - snippetManager.files[id] = {}; - config.loadModule(snippetFilePath, function(m) { - if (m) { - snippetManager.files[id] = m; - if (!m.snippets && m.snippetText) - m.snippets = snippetManager.parseSnippetFile(m.snippetText); - snippetManager.register(m.snippets || [], m.scope); - if (m.includeScopes) { - snippetManager.snippetMap[m.scope].includeScopes = m.includeScopes; - m.includeScopes.forEach(function(x) { - loadSnippetFile("ace/mode/" + x); - }); - } - } - }); -}; - -function getCompletionPrefix(editor) { - var pos = editor.getCursorPosition(); - var line = editor.session.getLine(pos.row); - var prefix = util.retrievePrecedingIdentifier(line, pos.column); - editor.completers.forEach(function(completer) { - if (completer.identifierRegexps) { - completer.identifierRegexps.forEach(function(identifierRegex) { - if (!prefix && identifierRegex) - prefix = util.retrievePrecedingIdentifier(line, pos.column, identifierRegex); - }); - } - }); - return prefix; -} - -var doLiveAutocomplete = function(e) { - var editor = e.editor; - var text = e.args || ""; - var hasCompleter = editor.completer && editor.completer.activated; - if (e.command.name === "backspace") { - if (hasCompleter && !getCompletionPrefix(editor)) - editor.completer.detach(); - } - else if (e.command.name === "insertstring") { - var prefix = getCompletionPrefix(editor); - if (prefix && !hasCompleter) { - if (!editor.completer) { - editor.completer = new Autocomplete(); - } - editor.completer.autoSelect = false; - editor.completer.autoInsert = false; - editor.completer.showPopup(editor); - } - } -}; - -var Editor = require("../editor").Editor; -require("../config").defineOptions(Editor.prototype, "editor", { - enableBasicAutocompletion: { - set: function(val) { - if (val) { - if (!this.completers) - this.completers = Array.isArray(val)? val: completers; - this.commands.addCommand(Autocomplete.startCommand); - } else { - this.commands.removeCommand(Autocomplete.startCommand); - } - }, - value: false - }, - enableLiveAutocompletion: { - set: function(val) { - if (val) { - if (!this.completers) - this.completers = Array.isArray(val)? val: completers; - this.commands.on('afterExec', doLiveAutocomplete); - } else { - this.commands.removeListener('afterExec', doLiveAutocomplete); - } - }, - value: false - }, - enableSnippets: { - set: function(val) { - if (val) { - this.commands.addCommand(expandSnippet); - this.on("changeMode", onChangeMode); - onChangeMode(null, this); - } else { - this.commands.removeCommand(expandSnippet); - this.off("changeMode", onChangeMode); - } - }, - value: false - } -}); -}); - -ace.define("ace/mode/xquery",["require","exports","module","ace/worker/worker_client","ace/lib/oop","ace/mode/text","ace/mode/text_highlight_rules","ace/mode/xquery/xquery_lexer","ace/range","ace/mode/behaviour/xquery","ace/mode/folding/cstyle","ace/anchor","ace/ext/language_tools"], function(require, exports, module) { +ace.define("ace/mode/xquery",["require","exports","module","ace/worker/worker_client","ace/lib/oop","ace/mode/text","ace/mode/text_highlight_rules","ace/mode/xquery/xquery_lexer","ace/range","ace/mode/behaviour/xquery","ace/mode/folding/cstyle","ace/anchor"], function(require, exports, module) { "use strict"; var WorkerClient = require("../worker/worker_client").WorkerClient; @@ -4547,7 +2758,6 @@ var Range = require("../range").Range; var XQueryBehaviour = require("./behaviour/xquery").XQueryBehaviour; var CStyleFoldMode = require("./folding/cstyle").FoldMode; var Anchor = require("../anchor").Anchor; -var LanguageTools = require("../ext/language_tools"); var Mode = function() { this.$tokenizer = new XQueryLexer(); @@ -4559,14 +2769,16 @@ oop.inherits(Mode, TextMode); (function() { - LanguageTools.addCompleter({ + this.completer = { getCompletions: function(editor, session, pos, prefix, callback) { + if (!session.$worker) + return callback(); session.$worker.emit("complete", { data: { pos: pos, prefix: prefix } }); session.$worker.on("complete", function(e){ callback(null, e.data); }); } - }); + }; this.getNextLineIndent = function(state, line, tab) { var indent = this.$getIndent(line); diff --git a/lib/client/edit/theme-cobalt.js b/lib/client/edit/theme-cobalt.js index 396eb017..7078110a 100644 --- a/lib/client/edit/theme-cobalt.js +++ b/lib/client/edit/theme-cobalt.js @@ -4,7 +4,7 @@ exports.isDark = true; exports.cssClass = "ace-cobalt"; exports.cssText = ".ace-cobalt .ace_gutter {\ background: #011e3a;\ -color: #fff\ +color: rgb(128,145,160)\ }\ .ace-cobalt .ace_print-margin {\ width: 1px;\ diff --git a/lib/client/edit/theme-idle_fingers.js b/lib/client/edit/theme-idle_fingers.js index 42df21c7..93f7ad4c 100644 --- a/lib/client/edit/theme-idle_fingers.js +++ b/lib/client/edit/theme-idle_fingers.js @@ -4,7 +4,7 @@ exports.isDark = true; exports.cssClass = "ace-idle-fingers"; exports.cssText = ".ace-idle-fingers .ace_gutter {\ background: #3b3b3b;\ -color: #fff\ +color: rgb(153,153,153)\ }\ .ace-idle-fingers .ace_print-margin {\ width: 1px;\ diff --git a/lib/client/edit/theme-tomorrow_night_bright.js b/lib/client/edit/theme-tomorrow_night_bright.js index 3fca5f39..a5329508 100644 --- a/lib/client/edit/theme-tomorrow_night_bright.js +++ b/lib/client/edit/theme-tomorrow_night_bright.js @@ -36,7 +36,7 @@ border: 1px solid rgb(110, 119, 0);\ border-bottom: 0;\ box-shadow: inset 0 -1px rgb(110, 119, 0);\ margin: -1px 0 0 -1px;\ -background: rgba(255, 235, 0, 0.1);\ +background: rgba(255, 235, 0, 0.1)\ }\ .ace-tomorrow-night-bright .ace_marker-layer .ace_active-line {\ background: #2A2A2A\ @@ -111,7 +111,7 @@ color: #D54E53\ color: #969896\ }\ .ace-tomorrow-night-bright .ace_c9searchresults.ace_keyword {\ -color: #C2C280;\ +color: #C2C280\ }\ .ace-tomorrow-night-bright .ace_indent-guide {\ background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYFBXV/8PAAJoAXX4kT2EAAAAAElFTkSuQmCC) right repeat-y\ diff --git a/lib/client/edit/worker-coffee.js b/lib/client/edit/worker-coffee.js index 9c80abd1..e55e92b6 100644 --- a/lib/client/edit/worker-coffee.js +++ b/lib/client/edit/worker-coffee.js @@ -17,7 +17,13 @@ window.window = window; window.ace = window; window.onerror = function(message, file, line, col, err) { - console.error("Worker " + (err ? err.stack : message)); + postMessage({type: "error", data: { + message: message, + file: file, + line: line, + col: col, + stack: err.stack + }}); }; window.normalizeModule = function(parentId, moduleName) { @@ -84,15 +90,20 @@ window.define = function(id, deps, factory) { deps = []; id = window.require.id; } + + if (typeof factory != "function") { + window.require.modules[id] = { + exports: factory, + initialized: true + }; + return; + } if (!deps.length) // If there is no dependencies, we inject 'require', 'exports' and // 'module' as dependencies, to provide CommonJS compatibility. deps = ['require', 'exports', 'module']; - if (id.indexOf("text!") === 0) - return; - var req = function(childId) { return window.require(id, childId); }; @@ -1198,7 +1209,6 @@ exports.getMatchOffsets = function(string, regExp) { return matches; }; exports.deferredCall = function(fcn) { - var timer = null; var callback = function() { timer = null; diff --git a/lib/client/edit/worker-css.js b/lib/client/edit/worker-css.js index 926966cb..7b069983 100644 --- a/lib/client/edit/worker-css.js +++ b/lib/client/edit/worker-css.js @@ -17,7 +17,13 @@ window.window = window; window.ace = window; window.onerror = function(message, file, line, col, err) { - console.error("Worker " + (err ? err.stack : message)); + postMessage({type: "error", data: { + message: message, + file: file, + line: line, + col: col, + stack: err.stack + }}); }; window.normalizeModule = function(parentId, moduleName) { @@ -84,15 +90,20 @@ window.define = function(id, deps, factory) { deps = []; id = window.require.id; } + + if (typeof factory != "function") { + window.require.modules[id] = { + exports: factory, + initialized: true + }; + return; + } if (!deps.length) // If there is no dependencies, we inject 'require', 'exports' and // 'module' as dependencies, to provide CommonJS compatibility. deps = ['require', 'exports', 'module']; - if (id.indexOf("text!") === 0) - return; - var req = function(childId) { return window.require(id, childId); }; @@ -325,7 +336,6 @@ exports.getMatchOffsets = function(string, regExp) { return matches; }; exports.deferredCall = function(fcn) { - var timer = null; var callback = function() { timer = null; diff --git a/lib/client/edit/worker-html.js b/lib/client/edit/worker-html.js index 4db5c7e5..153ab864 100644 --- a/lib/client/edit/worker-html.js +++ b/lib/client/edit/worker-html.js @@ -17,7 +17,13 @@ window.window = window; window.ace = window; window.onerror = function(message, file, line, col, err) { - console.error("Worker " + (err ? err.stack : message)); + postMessage({type: "error", data: { + message: message, + file: file, + line: line, + col: col, + stack: err.stack + }}); }; window.normalizeModule = function(parentId, moduleName) { @@ -84,15 +90,20 @@ window.define = function(id, deps, factory) { deps = []; id = window.require.id; } + + if (typeof factory != "function") { + window.require.modules[id] = { + exports: factory, + initialized: true + }; + return; + } if (!deps.length) // If there is no dependencies, we inject 'require', 'exports' and // 'module' as dependencies, to provide CommonJS compatibility. deps = ['require', 'exports', 'module']; - if (id.indexOf("text!") === 0) - return; - var req = function(childId) { return window.require(id, childId); }; @@ -325,7 +336,6 @@ exports.getMatchOffsets = function(string, regExp) { return matches; }; exports.deferredCall = function(fcn) { - var timer = null; var callback = function() { timer = null; diff --git a/lib/client/edit/worker-javascript.js b/lib/client/edit/worker-javascript.js index c3f005e8..3a3800b5 100644 --- a/lib/client/edit/worker-javascript.js +++ b/lib/client/edit/worker-javascript.js @@ -17,7 +17,13 @@ window.window = window; window.ace = window; window.onerror = function(message, file, line, col, err) { - console.error("Worker " + (err ? err.stack : message)); + postMessage({type: "error", data: { + message: message, + file: file, + line: line, + col: col, + stack: err.stack + }}); }; window.normalizeModule = function(parentId, moduleName) { @@ -84,15 +90,20 @@ window.define = function(id, deps, factory) { deps = []; id = window.require.id; } + + if (typeof factory != "function") { + window.require.modules[id] = { + exports: factory, + initialized: true + }; + return; + } if (!deps.length) // If there is no dependencies, we inject 'require', 'exports' and // 'module' as dependencies, to provide CommonJS compatibility. deps = ['require', 'exports', 'module']; - if (id.indexOf("text!") === 0) - return; - var req = function(childId) { return window.require(id, childId); }; @@ -1198,7 +1209,6 @@ exports.getMatchOffsets = function(string, regExp) { return matches; }; exports.deferredCall = function(fcn) { - var timer = null; var callback = function() { timer = null; diff --git a/lib/client/edit/worker-json.js b/lib/client/edit/worker-json.js index 280ba6ce..95c76cf7 100644 --- a/lib/client/edit/worker-json.js +++ b/lib/client/edit/worker-json.js @@ -17,7 +17,13 @@ window.window = window; window.ace = window; window.onerror = function(message, file, line, col, err) { - console.error("Worker " + (err ? err.stack : message)); + postMessage({type: "error", data: { + message: message, + file: file, + line: line, + col: col, + stack: err.stack + }}); }; window.normalizeModule = function(parentId, moduleName) { @@ -84,15 +90,20 @@ window.define = function(id, deps, factory) { deps = []; id = window.require.id; } + + if (typeof factory != "function") { + window.require.modules[id] = { + exports: factory, + initialized: true + }; + return; + } if (!deps.length) // If there is no dependencies, we inject 'require', 'exports' and // 'module' as dependencies, to provide CommonJS compatibility. deps = ['require', 'exports', 'module']; - if (id.indexOf("text!") === 0) - return; - var req = function(childId) { return window.require(id, childId); }; @@ -1198,7 +1209,6 @@ exports.getMatchOffsets = function(string, regExp) { return matches; }; exports.deferredCall = function(fcn) { - var timer = null; var callback = function() { timer = null; @@ -1592,7 +1602,8 @@ oop.inherits(JsonWorker, Mirror); var value = this.doc.getValue(); try { - var result = parse(value); + if (value) + parse(value); } catch (e) { var pos = this.doc.indexToPosition(e.at-1); this.sender.emit("error", { diff --git a/lib/client/edit/worker-lua.js b/lib/client/edit/worker-lua.js index 5be0e062..510424b6 100644 --- a/lib/client/edit/worker-lua.js +++ b/lib/client/edit/worker-lua.js @@ -17,7 +17,13 @@ window.window = window; window.ace = window; window.onerror = function(message, file, line, col, err) { - console.error("Worker " + (err ? err.stack : message)); + postMessage({type: "error", data: { + message: message, + file: file, + line: line, + col: col, + stack: err.stack + }}); }; window.normalizeModule = function(parentId, moduleName) { @@ -84,15 +90,20 @@ window.define = function(id, deps, factory) { deps = []; id = window.require.id; } + + if (typeof factory != "function") { + window.require.modules[id] = { + exports: factory, + initialized: true + }; + return; + } if (!deps.length) // If there is no dependencies, we inject 'require', 'exports' and // 'module' as dependencies, to provide CommonJS compatibility. deps = ['require', 'exports', 'module']; - if (id.indexOf("text!") === 0) - return; - var req = function(childId) { return window.require(id, childId); }; @@ -1198,7 +1209,6 @@ exports.getMatchOffsets = function(string, regExp) { return matches; }; exports.deferredCall = function(fcn) { - var timer = null; var callback = function() { timer = null; diff --git a/lib/client/edit/worker-php.js b/lib/client/edit/worker-php.js index 89467a1d..2046ee3f 100644 --- a/lib/client/edit/worker-php.js +++ b/lib/client/edit/worker-php.js @@ -17,7 +17,13 @@ window.window = window; window.ace = window; window.onerror = function(message, file, line, col, err) { - console.error("Worker " + (err ? err.stack : message)); + postMessage({type: "error", data: { + message: message, + file: file, + line: line, + col: col, + stack: err.stack + }}); }; window.normalizeModule = function(parentId, moduleName) { @@ -84,15 +90,20 @@ window.define = function(id, deps, factory) { deps = []; id = window.require.id; } + + if (typeof factory != "function") { + window.require.modules[id] = { + exports: factory, + initialized: true + }; + return; + } if (!deps.length) // If there is no dependencies, we inject 'require', 'exports' and // 'module' as dependencies, to provide CommonJS compatibility. deps = ['require', 'exports', 'module']; - if (id.indexOf("text!") === 0) - return; - var req = function(childId) { return window.require(id, childId); }; @@ -1198,7 +1209,6 @@ exports.getMatchOffsets = function(string, regExp) { return matches; }; exports.deferredCall = function(fcn) { - var timer = null; var callback = function() { timer = null; diff --git a/lib/client/edit/worker-xquery.js b/lib/client/edit/worker-xquery.js index 64f008ce..3d5dfb14 100644 --- a/lib/client/edit/worker-xquery.js +++ b/lib/client/edit/worker-xquery.js @@ -17,7 +17,13 @@ window.window = window; window.ace = window; window.onerror = function(message, file, line, col, err) { - console.error("Worker " + (err ? err.stack : message)); + postMessage({type: "error", data: { + message: message, + file: file, + line: line, + col: col, + stack: err.stack + }}); }; window.normalizeModule = function(parentId, moduleName) { @@ -84,15 +90,20 @@ window.define = function(id, deps, factory) { deps = []; id = window.require.id; } + + if (typeof factory != "function") { + window.require.modules[id] = { + exports: factory, + initialized: true + }; + return; + } if (!deps.length) // If there is no dependencies, we inject 'require', 'exports' and // 'module' as dependencies, to provide CommonJS compatibility. deps = ['require', 'exports', 'module']; - if (id.indexOf("text!") === 0) - return; - var req = function(childId) { return window.require(id, childId); }; @@ -1198,7 +1209,6 @@ exports.getMatchOffsets = function(string, regExp) { return matches; }; exports.deferredCall = function(fcn) { - var timer = null; var callback = function() { timer = null;