You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ga...@apache.org on 2013/10/30 14:43:35 UTC
[41/52] [partial] Remove unneeded ace files and codemirror
http://git-wip-us.apache.org/repos/asf/couchdb/blob/5b8fb9c3/src/fauxton/assets/js/libs/ace/ext-emmet.js
----------------------------------------------------------------------
diff --git a/src/fauxton/assets/js/libs/ace/ext-emmet.js b/src/fauxton/assets/js/libs/ace/ext-emmet.js
new file mode 100644
index 0000000..a6228a7
--- /dev/null
+++ b/src/fauxton/assets/js/libs/ace/ext-emmet.js
@@ -0,0 +1,1096 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Distributed under the BSD license:
+ *
+ * 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
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * 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
+ * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/ext/emmet', ['require', 'exports', 'module' , 'ace/keyboard/hash_handler', 'ace/editor', 'ace/snippets', 'ace/range', 'ace/config'], function(require, exports, module) {
+
+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);
+};
+function AceEmmetEditor() {}
+
+AceEmmetEditor.prototype = {
+ setupContext: function(editor) {
+ this.ace = editor;
+ this.indentation = editor.session.getTabString();
+ if (!emmet)
+ emmet = window.emmet;
+ emmet.require("resources").setVariable("indentation", this.indentation);
+ this.$syntax = null;
+ this.$syntax = this.getSyntax();
+ },
+ getSelectionRange: function() {
+ var range = this.ace.getSelectionRange();
+ return {
+ start: this.ace.positionToIndex(range.start),
+ end: this.ace.positionToIndex(range.end)
+ };
+ },
+ createSelection: function(start, end) {
+ this.ace.selection.setRange({
+ start: this.ace.indexToPosition(start),
+ end: this.ace.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});
+ return {
+ start: index,
+ end: index + lineLength
+ };
+ },
+ getCaretPos: function(){
+ var pos = this.ace.getCursorPosition();
+ return this.ace.positionToIndex(pos);
+ },
+ setCaretPos: function(index){
+ var pos = this.ace.indexToPosition(index);
+ this.ace.clearSelection();
+ this.ace.selection.moveCursorToPosition(pos);
+ },
+ getCurrentLine: function() {
+ var row = this.ace.getCursorPosition().row;
+ return this.ace.session.getLine(row);
+ },
+ replaceContent: function(value, start, end, noIndent) {
+ if (end == null)
+ end = start == null ? this.getContent().length : start;
+ if (start == null)
+ start = 0;
+
+ var editor = this.ace;
+ var range = Range.fromPoints(editor.indexToPosition(start), editor.indexToPosition(end));
+ editor.session.remove(range);
+
+ range.end = range.start;
+
+ value = this.$updateTabstops(value);
+ snippetManager.insertSnippet(editor, value)
+ },
+ getContent: function(){
+ return this.ace.getValue();
+ },
+ getSyntax: function() {
+ if (this.$syntax)
+ return this.$syntax;
+ var syntax = this.ace.session.$modeId.split("/").pop();
+ if (syntax == "html" || syntax == "php") {
+ var cursor = this.ace.getCursorPosition();
+ var state = this.ace.session.getState(cursor.row);
+ if (typeof state != "string")
+ state = state[0];
+ if (state) {
+ state = state.split("-");
+ if (state.length > 1)
+ syntax = state[0];
+ else if (syntax == "php")
+ syntax = "html";
+ }
+ }
+ return syntax;
+ },
+ getProfileName: function() {
+ switch(this.getSyntax()) {
+ case "css": return "css";
+ case "xml":
+ case "xsl":
+ return "xml";
+ case "html":
+ var profile = emmet.require("resources").getVariable("profile");
+ if (!profile)
+ profile = this.ace.session.getLines(0,2).join("").search(/<!DOCTYPE[^>]+XHTML/i) != -1 ? "xhtml": "html";
+ return profile;
+ }
+ return "xhtml";
+ },
+ prompt: function(title) {
+ return prompt(title);
+ },
+ getSelection: function() {
+ return this.ace.session.getTextRange();
+ },
+ getFilePath: function() {
+ return "";
+ },
+ $updateTabstops: function(value) {
+ var base = 1000;
+ var zeroBase = 0;
+ var lastZero = null;
+ var range = emmet.require('range');
+ var ts = emmet.require('tabStops');
+ var settings = emmet.require('resources').getVocabulary("user");
+ var tabstopOptions = {
+ tabstop: function(data) {
+ var group = parseInt(data.group, 10);
+ var isZero = group === 0;
+ if (isZero)
+ group = ++zeroBase;
+ else
+ group += base;
+
+ var placeholder = data.placeholder;
+ if (placeholder) {
+ placeholder = ts.processText(placeholder, tabstopOptions);
+ }
+
+ var result = '${' + group + (placeholder ? ':' + placeholder : '') + '}';
+
+ if (isZero) {
+ lastZero = range.create(data.start, result);
+ }
+
+ return result
+ },
+ escape: function(ch) {
+ if (ch == '$') return '\\$';
+ if (ch == '\\') return '\\\\';
+ return ch;
+ }
+ };
+
+ value = ts.processText(value, tabstopOptions);
+
+ if (settings.variables['insert_final_tabstop'] && !/\$\{0\}$/.test(value)) {
+ value += '${0}';
+ } else if (lastZero) {
+ value = emmet.require('utils').replaceSubstring(value, '${0}', lastZero);
+ }
+
+ return value;
+ }
+};
+
+
+var keymap = {
+ expand_abbreviation: {"mac": "ctrl+alt+e", "win": "alt+e"},
+ match_pair_outward: {"mac": "ctrl+d", "win": "ctrl+,"},
+ match_pair_inward: {"mac": "ctrl+j", "win": "ctrl+shift+0"},
+ matching_pair: {"mac": "ctrl+alt+j", "win": "alt+j"},
+ next_edit_point: "alt+right",
+ prev_edit_point: "alt+left",
+ toggle_comment: {"mac": "command+/", "win": "ctrl+/"},
+ split_join_tag: {"mac": "shift+command+'", "win": "shift+ctrl+`"},
+ remove_tag: {"mac": "command+'", "win": "shift+ctrl+;"},
+ evaluate_math_expression: {"mac": "shift+command+y", "win": "shift+ctrl+y"},
+ increment_number_by_1: "ctrl+up",
+ decrement_number_by_1: "ctrl+down",
+ increment_number_by_01: "alt+up",
+ decrement_number_by_01: "alt+down",
+ increment_number_by_10: {"mac": "alt+command+up", "win": "shift+alt+up"},
+ decrement_number_by_10: {"mac": "alt+command+down", "win": "shift+alt+down"},
+ select_next_item: {"mac": "shift+command+.", "win": "shift+ctrl+."},
+ select_previous_item: {"mac": "shift+command+,", "win": "shift+ctrl+,"},
+ reflect_css_value: {"mac": "shift+command+r", "win": "shift+ctrl+r"},
+
+ encode_decode_data_url: {"mac": "shift+ctrl+d", "win": "ctrl+'"},
+ expand_abbreviation_with_tab: "Tab",
+ wrap_with_abbreviation: {"mac": "shift+ctrl+a", "win": "shift+ctrl+a"}
+};
+
+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 {
+ var result = actions.run(this.action, editorProxy);
+ } catch(e) {
+ editor._signal("changeStatus", typeof e == "string" ? e : e.message);
+ console.log(e);
+ }
+ return result;
+};
+
+for (var command in keymap) {
+ exports.commands.addCommand({
+ name: "emmet:" + command,
+ action: command,
+ bindKey: keymap[command],
+ exec: exports.runEmmetCommand,
+ multiSelectAction: "forEach"
+ });
+}
+
+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);
+ if (e.enableEmmet === false)
+ enabled = false;
+ if (enabled)
+ editor.keyBinding.addKeyboardHandler(exports.commands);
+ else
+ editor.keyBinding.removeKeyboardHandler(exports.commands);
+};
+
+
+exports.AceEmmetEditor = AceEmmetEditor;
+require("ace/config").defineOptions(Editor.prototype, "editor", {
+ enableEmmet: {
+ set: function(val) {
+ this[val ? "on" : "removeListener"]("changeMode", onChangeMode);
+ onChangeMode({enableEmmet: !!val}, this);
+ },
+ value: true
+ }
+});
+
+
+exports.setCore = function(e) {emmet = e;};
+});
+
+define('ace/snippets', ['require', 'exports', 'module' , 'ace/lib/lang', 'ace/range', 'ace/keyboard/hash_handler', 'ace/tokenizer', 'ace/lib/dom'], function(require, exports, module) {
+
+var lang = require("./lib/lang")
+var Range = require("./range").Range
+var HashHandler = require("./keyboard/hash_handler").HashHandler;
+var Tokenizer = require("./tokenizer").Tokenizer;
+var comparePoints = Range.comparePoints;
+
+var SnippetManager = function() {
+ this.snippetMap = {};
+ this.snippetNameMap = {};
+};
+
+(function() {
+ this.getTokenizer = function() {
+ function TabstopToken(str, _, stack) {
+ str = str.substr(1);
+ if (/^\d+$/.test(str) && !stack.inFormatString)
+ return [{tabstopId: parseInt(str, 10)}];
+ return [{text: str}]
+ }
+ function escape(ch) {
+ return "(?:[^\\\\" + ch + "]|\\\\.)";
+ }
+ SnippetManager.$tokenizer = new Tokenizer({
+ start: [
+ {regex: /:/, onMatch: function(val, state, stack) {
+ if (stack.length && stack[0].expectIf) {
+ stack[0].expectIf = false;
+ stack[0].elseBranch = stack[0];
+ return [stack[0]];
+ }
+ return ":";
+ }},
+ {regex: /\\./, onMatch: function(val, state, stack) {
+ var ch = val[1];
+ if (ch == "}" && stack.length) {
+ val = ch;
+ }else if ("`$\\".indexOf(ch) != -1) {
+ val = ch;
+ } else if (stack.inFormatString) {
+ if (ch == "n")
+ val = "\n";
+ else if (ch == "t")
+ val = "\n";
+ else if ("ulULE".indexOf(ch) != -1) {
+ val = {changeCase: ch, local: ch > "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 "ace.ajax.org";
+ 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.insertSnippet = function(editor, snippetText) {
+ var cursor = editor.getCursorPosition();
+ var line = editor.session.getLine(cursor.row);
+ var indentString = line.match(/^\s*/)[0];
+ var tabString = editor.session.getTabString();
+
+ 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] == 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);
+ tabstopManager.addTabstops(tabstops, range.start, end);
+ tabstopManager.tabNext();
+ };
+
+ this.$getScope = function(editor) {
+ var scope = editor.session.$mode.$id || "";
+ scope = scope.split("/").pop();
+ if (scope === "html" || scope === "php") {
+ if (scope === "php")
+ 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.expandWithTab = function(editor) {
+ 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 scope = this.$getScope(editor);
+ var snippetMap = this.snippetMap;
+ var snippet;
+ [scope, "_"].some(function(scope) {
+ var snippets = snippetMap[scope];
+ if (snippets)
+ snippet = this.findMatchingSnippet(snippets, before, after);
+ return !!snippet;
+ }, this);
+ if (!snippet)
+ return false;
+
+ 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.insertSnippet(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;
+ 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.content)
+ addSnippet(snippets);
+ else if (Array.isArray(snippets))
+ snippets.forEach(addSnippet);
+ };
+ 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 scope = editor && this.$getScope(editor);
+ var snippetMap = this.snippetNameMap;
+ var snippet;
+ [scope, "_"].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 = -1;
+ this.ranges = [];
+ this.tabstops = [];
+ 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.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 (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.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 - 1;
+ var index = this.index + (dir || 1);
+ index = Math.min(Math.max(index, 0), max);
+ this.selectTabstop(index);
+ if (index == max)
+ this.detach();
+ };
+ this.selectTabstop = function(index) {
+ 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);
+ }
+ } else {
+ this.editor.selection.setRange(ts.firstNonLinked);
+ }
+
+ this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler);
+ };
+ this.addTabstops = function(tabstops, start, end) {
+ 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, 0];
+ var ranges = this.ranges;
+ var editor = this.editor;
+ tabstops.forEach(function(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 = ts;
+ ranges.push(range);
+ ts[i] = range;
+ if (p.fmtString) {
+ range.linked = true;
+ ts.hasLinkedRanges = true;
+ } else if (!ts.firstNonLinked)
+ ts.firstNonLinked = range;
+ }
+ if (!ts.firstNonLinked)
+ ts.hasLinkedRanges = false;
+ arg.push(ts);
+ this.addTabstopMarkers(ts);
+ }, this);
+ 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);
+ };
+
+ this.keyboardHandler = new HashHandler();
+ this.keyboardHandler.bindKeys({
+ "Tab": function(ed) {
+ 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 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();
+
+
+});
http://git-wip-us.apache.org/repos/asf/couchdb/blob/5b8fb9c3/src/fauxton/assets/js/libs/ace/ext-keybinding_menu.js
----------------------------------------------------------------------
diff --git a/src/fauxton/assets/js/libs/ace/ext-keybinding_menu.js b/src/fauxton/assets/js/libs/ace/ext-keybinding_menu.js
new file mode 100644
index 0000000..fac6eae
--- /dev/null
+++ b/src/fauxton/assets/js/libs/ace/ext-keybinding_menu.js
@@ -0,0 +1,207 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Distributed under the BSD license:
+ *
+ * Copyright (c) 2013 Matthew Christopher Kastor-Inare III, Atropa Inc. Intl
+ * All rights reserved.
+ *
+ * Contributed to Ajax.org under the BSD license.
+ *
+ * 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
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * 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
+ * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/ext/keybinding_menu', ['require', 'exports', 'module' , 'ace/editor', 'ace/ext/menu_tools/overlay_page', 'ace/ext/menu_tools/get_editor_keyboard_shortcuts'], function(require, exports, module) {
+
+ var Editor = require("ace/editor").Editor;
+ function showKeyboardShortcuts (editor) {
+ if(!document.getElementById('kbshortcutmenu')) {
+ var overlayPage = require('./menu_tools/overlay_page').overlayPage;
+ var getEditorKeybordShortcuts = require('./menu_tools/get_editor_keyboard_shortcuts').getEditorKeybordShortcuts;
+ var kb = getEditorKeybordShortcuts(editor);
+ var el = document.createElement('div');
+ var commands = kb.reduce(function(previous, current) {
+ return previous + '<div class="ace_optionsMenuEntry"><span class="ace_optionsMenuCommand">'
+ + current.command + '</span> : '
+ + '<span class="ace_optionsMenuKey">' + current.key + '</span></div>';
+ }, '');
+
+ el.id = 'kbshortcutmenu';
+ el.innerHTML = '<h1>Keyboard Shortcuts</h1>' + commands + '</div>';
+ overlayPage(editor, el, '0', '0', '0', null);
+ }
+ };
+ module.exports.init = function(editor) {
+ Editor.prototype.showKeyboardShortcuts = function() {
+ showKeyboardShortcuts(this);
+ };
+ editor.commands.addCommands([{
+ name: "showKeyboardShortcuts",
+ bindKey: {win: "Ctrl-Alt-h", mac: "Command-Alt-h"},
+ exec: function(editor, line) {
+ editor.showKeyboardShortcuts();
+ }
+ }]);
+ };
+
+});
+
+define('ace/ext/menu_tools/overlay_page', ['require', 'exports', 'module' , 'ace/lib/dom'], function(require, exports, module) {
+
+var dom = require("../../lib/dom");
+var cssText = "#ace_settingsmenu, #kbshortcutmenu {\
+background-color: #F7F7F7;\
+color: black;\
+box-shadow: -5px 4px 5px rgba(126, 126, 126, 0.55);\
+padding: 1em 0.5em 2em 1em;\
+overflow: auto;\
+position: absolute;\
+margin: 0;\
+bottom: 0;\
+right: 0;\
+top: 0;\
+z-index: 9991;\
+cursor: default;\
+}\
+.ace_dark #ace_settingsmenu, .ace_dark #kbshortcutmenu {\
+box-shadow: -20px 10px 25px rgba(126, 126, 126, 0.25);\
+background-color: rgba(255, 255, 255, 0.6);\
+color: black;\
+}\
+.ace_optionsMenuEntry:hover {\
+background-color: rgba(100, 100, 100, 0.1);\
+-webkit-transition: all 0.5s;\
+transition: all 0.3s\
+}\
+.ace_closeButton {\
+background: rgba(245, 146, 146, 0.5);\
+border: 1px solid #F48A8A;\
+border-radius: 50%;\
+padding: 7px;\
+position: absolute;\
+right: -8px;\
+top: -8px;\
+z-index: 1000;\
+}\
+.ace_closeButton{\
+background: rgba(245, 146, 146, 0.9);\
+}\
+.ace_optionsMenuKey {\
+color: darkslateblue;\
+font-weight: bold;\
+}\
+.ace_optionsMenuCommand {\
+color: darkcyan;\
+font-weight: normal;\
+}";
+dom.importCssString(cssText);
+module.exports.overlayPage = function overlayPage(editor, contentElement, top, right, bottom, left) {
+ top = top ? 'top: ' + top + ';' : '';
+ bottom = bottom ? 'bottom: ' + bottom + ';' : '';
+ right = right ? 'right: ' + right + ';' : '';
+ left = left ? 'left: ' + left + ';' : '';
+
+ var closer = document.createElement('div');
+ var contentContainer = document.createElement('div');
+
+ function documentEscListener(e) {
+ if (e.keyCode === 27) {
+ closer.click();
+ }
+ }
+
+ closer.style.cssText = 'margin: 0; padding: 0; ' +
+ 'position: fixed; top:0; bottom:0; left:0; right:0;' +
+ 'z-index: 9990; ' +
+ 'background-color: rgba(0, 0, 0, 0.3);';
+ closer.addEventListener('click', function() {
+ document.removeEventListener('keydown', documentEscListener);
+ closer.parentNode.removeChild(closer);
+ editor.focus();
+ closer = null;
+ });
+ document.addEventListener('keydown', documentEscListener);
+
+ contentContainer.style.cssText = top + right + bottom + left;
+ contentContainer.addEventListener('click', function(e) {
+ e.stopPropagation();
+ });
+
+ var wrapper = dom.createElement("div");
+ wrapper.style.position = "relative";
+
+ var closeButton = dom.createElement("div");
+ closeButton.className = "ace_closeButton";
+ closeButton.addEventListener('click', function() {
+ closer.click();
+ });
+
+ wrapper.appendChild(closeButton);
+ contentContainer.appendChild(wrapper);
+
+ contentContainer.appendChild(contentElement);
+ closer.appendChild(contentContainer);
+ document.body.appendChild(closer);
+ editor.blur();
+};
+
+});
+
+define('ace/ext/menu_tools/get_editor_keyboard_shortcuts', ['require', 'exports', 'module' , 'ace/lib/keys'], function(require, exports, module) {
+
+var keys = require("../../lib/keys");
+module.exports.getEditorKeybordShortcuts = function(editor) {
+ var KEY_MODS = keys.KEY_MODS;
+ var keybindings = [];
+ var commandMap = {};
+ 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]
+ if (typeof command != "string")
+ command = command.name
+ if (commandMap[command]) {
+ commandMap[command].key += "|" + modifier + key;
+ } else {
+ commandMap[command] = {key: modifier+key, command: command};
+ keybindings.push(commandMap[command]);
+ }
+ }
+ }
+ });
+ return keybindings;
+};
+
+});
\ No newline at end of file