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/29 16:40:28 UTC

[43/51] [partial] working replacement

http://git-wip-us.apache.org/repos/asf/couchdb/blob/9abd128c/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..6647da4
--- /dev/null
+++ b/src/fauxton/assets/js/libs/ace/ext/emmet.js
@@ -0,0 +1,415 @@
+/* ***** 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(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);
+};
+
+/**
+ * Implementation of {@link IEmmetEditor} interface for Ace
+ */
+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();
+    },
+    /**
+     * Returns character indexes of selected text: object with <code>start</code>
+     * and <code>end</code> properties. If there's no selection, should return
+     * object with <code>start</code> and <code>end</code> properties referring
+     * to current caret position
+     * @return {Object}
+     * @example
+     * var selection = editor.getSelectionRange();
+     * alert(selection.start + ', ' + selection.end);
+     */
+    getSelectionRange: function() {
+        // TODO should start be caret position instead?
+        var range = this.ace.getSelectionRange();
+        return {
+            start: this.ace.positionToIndex(range.start),
+            end: this.ace.positionToIndex(range.end)
+        };
+    },
+
+    /**
+     * Creates selection from <code>start</code> to <code>end</code> character
+     * indexes. If <code>end</code> is ommited, this method should place caret
+     * and <code>start</code> index
+     * @param {Number} start
+     * @param {Number} [end]
+     * @example
+     * editor.createSelection(10, 40);
+     *
+     * //move caret to 15th character
+     * editor.createSelection(15);
+     */
+    createSelection: function(start, end) {
+        this.ace.selection.setRange({
+            start: this.ace.indexToPosition(start),
+            end: this.ace.indexToPosition(end)
+        });
+    },
+
+    /**
+     * Returns current line's start and end indexes as object with <code>start</code>
+     * and <code>end</code> properties
+     * @return {Object}
+     * @example
+     * var range = editor.getCurrentLineRange();
+     * alert(range.start + ', ' + range.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
+        };
+    },
+
+    /**
+     * Returns current caret position
+     * @return {Number|null}
+     */
+    getCaretPos: function(){
+        var pos = this.ace.getCursorPosition();
+        return this.ace.positionToIndex(pos);
+    },
+
+    /**
+     * Set new caret position
+     * @param {Number} index Caret position
+     */
+    setCaretPos: function(index){
+        var pos = this.ace.indexToPosition(index);
+        this.ace.clearSelection();
+        this.ace.selection.moveCursorToPosition(pos);
+    },
+
+    /**
+     * Returns content of current line
+     * @return {String}
+     */
+    getCurrentLine: function() {
+        var row = this.ace.getCursorPosition().row;
+        return this.ace.session.getLine(row);
+    },
+
+    /**
+     * Replace editor's content or it's part (from <code>start</code> to
+     * <code>end</code> index). If <code>value</code> contains
+     * <code>caret_placeholder</code>, the editor will put caret into
+     * this position. If you skip <code>start</code> and <code>end</code>
+     * arguments, the whole target's content will be replaced with
+     * <code>value</code>.
+     *
+     * If you pass <code>start</code> argument only,
+     * the <code>value</code> will be placed at <code>start</code> string
+     * index of current content.
+     *
+     * If you pass <code>start</code> and <code>end</code> arguments,
+     * the corresponding substring of current target's content will be
+     * replaced with <code>value</code>.
+     * @param {String} value Content you want to paste
+     * @param {Number} [start] Start index of editor's content
+     * @param {Number} [end] End index of editor's content
+     * @param {Boolean} [noIndent] Do not auto indent <code>value</code>
+     */
+    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;
+        //editor.selection.setRange(range);
+        
+        value = this.$updateTabstops(value);
+        snippetManager.insertSnippet(editor, value)
+    },
+
+    /**
+     * Returns editor's content
+     * @return {String}
+     */
+    getContent: function(){
+        return this.ace.getValue();
+    },
+
+    /**
+     * Returns current editor's syntax mode
+     * @return {String}
+     */
+    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;
+    },
+
+    /**
+     * Returns current output profile name (@see emmet#setupProfile)
+     * @return {String}
+     */
+    getProfileName: function() {
+        switch(this.getSyntax()) {
+          case "css": return "css";
+          case "xml":
+          case "xsl":
+            return "xml";
+          case "html":
+            var profile = emmet.require("resources").getVariable("profile");
+            // no forced profile, guess from content html or xhtml?
+            if (!profile)
+                profile = this.ace.session.getLines(0,2).join("").search(/<!DOCTYPE[^>]+XHTML/i) != -1 ? "xhtml": "html";
+            return profile;
+        }
+        return "xhtml";
+    },
+
+    /**
+     * Ask user to enter something
+     * @param {String} title Dialog title
+     * @return {String} Entered data
+     * @since 0.65
+     */
+    prompt: function(title) {
+        return prompt(title);
+    },
+
+    /**
+     * Returns current selection
+     * @return {String}
+     * @since 0.65
+     */
+    getSelection: function() {
+        return this.ace.session.getTextRange();
+    },
+
+    /**
+     * Returns current editor's file path
+     * @return {String}
+     * @since 0.65
+     */
+    getFilePath: function() {
+        return "";
+    },
+    
+    // update tabstops: make sure all caret placeholders are unique
+    // by default, abbreviation parser generates all unlinked (un-mirrored)
+    // tabstops as ${0}, so we have upgrade all caret tabstops with unique
+    // positions but make sure that all other tabstops are not linked accidentally
+    // based on https://github.com/sergeche/emmet-sublime/blob/master/editor.js#L119-L171
+    $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) {
+                    // recursively update nested tabstops
+                    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+'"},
+    // update_image_size: {"mac": "shift+ctrl+i", "win": "ctrl+u"},
+    // expand_as_you_type: "ctrl+alt+enter",
+    // wrap_as_you_type: {"mac": "shift+ctrl+g", "win": "shift+ctrl+g"},
+    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") {
+        // without setTimeout prompt doesn't work on firefox
+        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;};
+});
+

http://git-wip-us.apache.org/repos/asf/couchdb/blob/9abd128c/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..bf8189a
--- /dev/null
+++ b/src/fauxton/assets/js/libs/ace/ext/keybinding_menu.js
@@ -0,0 +1,86 @@
+/* ***** 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 ***** */
+
+/*jslint indent: 4, maxerr: 50, white: true, browser: true, vars: true*/
+/*global define, require */
+
+/**
+ * Show Keyboard Shortcuts
+ * @fileOverview Show Keyboard Shortcuts <br />
+ * Generates a menu which displays the keyboard shortcuts.
+ * @author <a href="mailto:matthewkastor@gmail.com">
+ *  Matthew Christopher Kastor-Inare III </a><br />
+ *  ☭ Hial Atropa!! ☭
+ */
+
+define(function(require, exports, module) {
+    "use strict";
+    var Editor = require("ace/editor").Editor;
+    /**
+     * Generates a menu which displays the keyboard shortcuts.
+     * @author <a href="mailto:matthewkastor@gmail.com">
+     *  Matthew Christopher Kastor-Inare III </a><br />
+     *  ☭ Hial Atropa!! ☭
+     * @param {ace.Editor} editor An instance of the ace editor.
+     */
+    function showKeyboardShortcuts (editor) {
+        // make sure the menu isn't open already.
+        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();
+            }
+        }]);
+    };
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/couchdb/blob/9abd128c/src/fauxton/assets/js/libs/ace/ext/language_tools.js
----------------------------------------------------------------------
diff --git a/src/fauxton/assets/js/libs/ace/ext/language_tools.js b/src/fauxton/assets/js/libs/ace/ext/language_tools.js
new file mode 100644
index 0000000..e5cd8bb
--- /dev/null
+++ b/src/fauxton/assets/js/libs/ace/ext/language_tools.js
@@ -0,0 +1,129 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Distributed under the BSD license:
+ *
+ * Copyright (c) 2012, 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(function(require, exports, module) {
+"use strict";
+
+var snippetManager = require("../snippets").snippetManager;
+var Autocomplete = require("../autocomplete").Autocomplete;
+var config = require("../config");
+
+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 scope = snippetManager.$getScope(editor);
+        var snippetMap = snippetManager.snippetMap;
+        var completions = [];
+        [scope, "_"].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);
+};
+
+var expandSnippet = {
+    name: "expandSnippet",
+    exec: function(editor) {
+        var success = snippetManager.expandWithTab(editor);
+        if (!success)
+            editor.execCommand("indent");
+    },
+    bindKey: "tab"
+}
+
+var onChangeMode = function(e, editor) {
+    var mode = editor.session.$mode;
+    var id = mode.$id
+    if (!snippetManager.files) snippetManager.files = {};
+    if (id && !snippetManager.files[id]) {
+        var snippetFilePath = id.replace("mode", "snippets");
+        config.loadModule(snippetFilePath, function(m) {
+            if (m) {
+                snippetManager.files[id] = m;
+                m.snippets = snippetManager.parseSnippetFile(m.snippetText);
+                snippetManager.register(m.snippets, m.scope);
+            }
+        });
+    }
+};
+
+var Editor = require("../editor").Editor;
+require("../config").defineOptions(Editor.prototype, "editor", {
+    enableBasicAutocompletion: {
+        set: function(val) {
+            if (val) {
+                this.completers = completers
+                this.commands.addCommand(Autocomplete.startCommand);
+            } else {
+                this.commands.removeCommand(Autocomplete.startCommand);
+            }
+        },
+        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
+    }
+});
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/couchdb/blob/9abd128c/src/fauxton/assets/js/libs/ace/ext/menu_tools/add_editor_menu_options.js
----------------------------------------------------------------------
diff --git a/src/fauxton/assets/js/libs/ace/ext/menu_tools/add_editor_menu_options.js b/src/fauxton/assets/js/libs/ace/ext/menu_tools/add_editor_menu_options.js
new file mode 100644
index 0000000..fd56859
--- /dev/null
+++ b/src/fauxton/assets/js/libs/ace/ext/menu_tools/add_editor_menu_options.js
@@ -0,0 +1,103 @@
+/* ***** 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 ***** */
+
+/*jslint indent: 4, maxerr: 50, white: true, browser: true, vars: true*/
+/*global define, require */
+
+/**
+ * Add Editor Menu Options
+ * @fileOverview Add Editor Menu Options <br />
+ * The menu options property needs to be added to the editor
+ *  so that the settings menu can know about options for
+ *  selection elements and track which option is selected.
+ * @author <a href="mailto:matthewkastor@gmail.com">
+ *  Matthew Christopher Kastor-Inare III </a><br />
+ *  ☭ Hial Atropa!! ☭
+ */
+
+define(function(require, exports, module) {
+'use strict';
+
+/**
+ * The menu options property needs to be added to the editor
+ *  so that the settings menu can know about options for
+ *  selection elements and track which option is selected.
+ * @author <a href="mailto:matthewkastor@gmail.com">
+ *  Matthew Christopher Kastor-Inare III </a><br />
+ *  ☭ Hial Atropa!! ☭
+ * @param {ace.Editor} editor An instance of the ace editor.
+ */
+module.exports.addEditorMenuOptions = function addEditorMenuOptions (editor) {
+    var modelist = require('../modelist');
+    var themelist = require('../themelist');
+    editor.menuOptions = {
+        "setNewLineMode" : [{
+            "textContent" : "unix",
+            "value" : "unix"
+        }, {
+            "textContent" : "windows",
+            "value" : "windows"
+        }, {
+            "textContent" : "auto",
+            "value" : "auto"
+        }],
+        "setTheme" : [],
+        "setMode" : [],
+        "setKeyboardHandler": [{
+            "textContent" : "ace",
+            "value" : ""
+        }, {
+            "textContent" : "vim",
+            "value" : "ace/keyboard/vim"
+        }, {
+            "textContent" : "emacs",
+            "value" : "ace/keyboard/emacs"
+        }]
+    };
+
+    editor.menuOptions.setTheme = themelist.themes.map(function(theme) {
+        return {
+            'textContent' : theme.desc,
+            'value' : theme.theme
+        };
+    });
+
+    editor.menuOptions.setMode = modelist.modes.map(function(mode) {
+        return {
+            'textContent' : mode.name,
+            'value' : mode.mode
+        };
+    });
+};
+
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/couchdb/blob/9abd128c/src/fauxton/assets/js/libs/ace/ext/menu_tools/element_generator.js
----------------------------------------------------------------------
diff --git a/src/fauxton/assets/js/libs/ace/ext/menu_tools/element_generator.js b/src/fauxton/assets/js/libs/ace/ext/menu_tools/element_generator.js
new file mode 100644
index 0000000..ec6ba93
--- /dev/null
+++ b/src/fauxton/assets/js/libs/ace/ext/menu_tools/element_generator.js
@@ -0,0 +1,148 @@
+/* ***** 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 ***** */
+
+/*jslint indent: 4, maxerr: 50, white: true, browser: true, vars: true*/
+/*global define, require */
+
+/**
+ * Element Generator
+ * @fileOverview Element Generator <br />
+ * Contains methods for generating elements.
+ * @author <a href="mailto:matthewkastor@gmail.com">
+ *  Matthew Christopher Kastor-Inare III </a><br />
+ *  ☭ Hial Atropa!! ☭
+ */
+
+define(function(require, exports, module) {
+'use strict';
+/**
+ * Creates a DOM option element
+ * @author <a href="mailto:matthewkastor@gmail.com">
+ *  Matthew Christopher Kastor-Inare III </a><br />
+ *  ☭ Hial Atropa!! ☭
+ * @param {object} obj An object containing properties to add to the dom
+ *  element. If one of those properties is named `selected` then it will be
+ *  added as an attribute on the element instead.
+ */
+module.exports.createOption = function createOption (obj) {
+    var attribute;
+    var el = document.createElement('option');
+    for(attribute in obj) {
+        if(obj.hasOwnProperty(attribute)) {
+            if(attribute === 'selected') {
+                el.setAttribute(attribute, obj[attribute]);
+            } else {
+                el[attribute] = obj[attribute];
+            }
+        }
+    }
+    return el;
+};
+/**
+ * Creates a DOM checkbox element.
+ * @author <a href="mailto:matthewkastor@gmail.com">
+ *  Matthew Christopher Kastor-Inare III </a><br />
+ *  ☭ Hial Atropa!! ☭
+ * @param {string} id The id of the element.
+ * @param {boolean} checked Whether or not the element is checked.
+ * @param {string} clss The class of the element.
+ * @returns {DOMElement} Returns a checkbox element reference.
+ */
+module.exports.createCheckbox = function createCheckbox (id, checked, clss) {
+    var el = document.createElement('input');
+    el.setAttribute('type', 'checkbox');
+    el.setAttribute('id', id);
+    el.setAttribute('name', id);
+    el.setAttribute('value', checked);
+    el.setAttribute('class', clss);
+    if(checked) {
+        el.setAttribute('checked', 'checked');
+    }
+    return el;
+};
+/**
+ * Creates a DOM text input element.
+ * @author <a href="mailto:matthewkastor@gmail.com">
+ *  Matthew Christopher Kastor-Inare III </a><br />
+ *  ☭ Hial Atropa!! ☭
+ * @param {string} id The id of the element.
+ * @param {string} value The default value of the input element.
+ * @param {string} clss The class of the element.
+ * @returns {DOMElement} Returns an input element reference.
+ */
+module.exports.createInput = function createInput (id, value, clss) {
+    var el = document.createElement('input');
+    el.setAttribute('type', 'text');
+    el.setAttribute('id', id);
+    el.setAttribute('name', id);
+    el.setAttribute('value', value);
+    el.setAttribute('class', clss);
+    return el;
+};
+/**
+ * Creates a DOM label element.
+ * @author <a href="mailto:matthewkastor@gmail.com">
+ *  Matthew Christopher Kastor-Inare III </a><br />
+ *  ☭ Hial Atropa!! ☭
+ * @param {string} text The label text.
+ * @param {string} labelFor The id of the element being labeled.
+ * @returns {DOMElement} Returns a label element reference.
+ */
+module.exports.createLabel = function createLabel (text, labelFor) {
+    var el = document.createElement('label');
+    el.setAttribute('for', labelFor);
+    el.textContent = text;
+    return el;
+};
+/**
+ * Creates a DOM selection element.
+ * @author <a href="mailto:matthewkastor@gmail.com">
+ *  Matthew Christopher Kastor-Inare III </a><br />
+ *  ☭ Hial Atropa!! ☭
+ * @param {string} id The id of the element.
+ * @param {string} values An array of objects suitable for `createOption`
+ * @param {string} clss The class of the element.
+ * @returns {DOMElement} Returns a selection element reference.
+ * @see ace/ext/element_generator.createOption
+ */
+module.exports.createSelection = function createSelection (id, values, clss) {
+    var el = document.createElement('select');
+    el.setAttribute('id', id);
+    el.setAttribute('name', id);
+    el.setAttribute('class', clss);
+    values.forEach(function(item) {
+        el.appendChild(module.exports.createOption(item));
+    });
+    return el;
+};
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/couchdb/blob/9abd128c/src/fauxton/assets/js/libs/ace/ext/menu_tools/generate_settings_menu.js
----------------------------------------------------------------------
diff --git a/src/fauxton/assets/js/libs/ace/ext/menu_tools/generate_settings_menu.js b/src/fauxton/assets/js/libs/ace/ext/menu_tools/generate_settings_menu.js
new file mode 100644
index 0000000..16d3a76
--- /dev/null
+++ b/src/fauxton/assets/js/libs/ace/ext/menu_tools/generate_settings_menu.js
@@ -0,0 +1,258 @@
+/* ***** 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 ***** */
+
+/*jslint indent: 4, maxerr: 50, white: true, browser: true, vars: true*/
+/*global define*/
+
+/**
+ * Generates the settings menu
+ * @fileOverview Generates the settings menu.
+ * @author <a href="mailto:matthewkastor@gmail.com">
+ *  Matthew Christopher Kastor-Inare III </a><br />
+ *  ☭ Hial Atropa!! ☭
+ */
+
+define(function(require, exports, module) {
+'use strict';
+var egen = require('./element_generator');
+var addEditorMenuOptions = require('./add_editor_menu_options').addEditorMenuOptions;
+var getSetFunctions = require('./get_set_functions').getSetFunctions;
+
+/**
+ * Generates an interactive menu with settings useful to end users.
+ * @author <a href="mailto:matthewkastor@gmail.com">
+ *  Matthew Christopher Kastor-Inare III </a><br />
+ *  ☭ Hial Atropa!! ☭
+ * @param {ace.Editor} editor An instance of the ace editor.
+ */
+module.exports.generateSettingsMenu = function generateSettingsMenu (editor) {
+    /**
+     * container for dom elements that will go in the menu.
+     * @author <a href="mailto:matthewkastor@gmail.com">
+     *  Matthew Christopher Kastor-Inare III </a><br />
+     *  ☭ Hial Atropa!! ☭
+     */
+    var elements = [];
+    /**
+     * Sorts the menu entries (elements var) so they'll appear in alphabetical order
+     *  the sort is performed based on the value of the contains property
+     *  of each element. Since this is an `array.sort` the array is sorted
+     *  in place.
+     * @author <a href="mailto:matthewkastor@gmail.com">
+     *  Matthew Christopher Kastor-Inare III </a><br />
+     *  ☭ Hial Atropa!! ☭
+     */
+    function cleanupElementsList() {
+        elements.sort(function(a, b) {
+            var x = a.getAttribute('contains');
+            var y = b.getAttribute('contains');
+            return x.localeCompare(y);
+        });
+    }
+    /**
+     * Wraps all dom elements contained in the elements var with a single
+     *  div.
+     * @author <a href="mailto:matthewkastor@gmail.com">
+     *  Matthew Christopher Kastor-Inare III </a><br />
+     *  ☭ Hial Atropa!! ☭
+     */
+    function wrapElements() {
+        var topmenu = document.createElement('div');
+        topmenu.setAttribute('id', 'ace_settingsmenu');
+        elements.forEach(function(element) {
+            topmenu.appendChild(element);
+        });
+        return topmenu;
+    }
+    /**
+     * Creates a new menu entry.
+     * @author <a href="mailto:matthewkastor@gmail.com">
+     *  Matthew Christopher Kastor-Inare III </a><br />
+     *  ☭ Hial Atropa!! ☭
+     * @param {object} obj This is a reference to the object containing the
+     *  set function. It is used to set up event listeners for when the
+     *  menu options change.
+     * @param {string} clss Maps to the class of the dom element. This is
+     *  the name of the object containing the set function e.g. `editor`,
+     *  `session`, `renderer`.
+     * @param {string} item  This is the set function name. It maps to the
+     *  id of the dom element (check, select, input) and to the "contains"
+     *  attribute of the div holding both the element and its label.
+     * @param {mixed} val This is the value of the setting. It is mapped to
+     *  the dom element's value, checked, or selected option accordingly.
+     */
+    function createNewEntry(obj, clss, item, val) {
+        var el;
+        var div = document.createElement('div');
+        div.setAttribute('contains', item);
+        div.setAttribute('class', 'ace_optionsMenuEntry');
+        div.setAttribute('style', 'clear: both;');
+
+        div.appendChild(egen.createLabel(
+            item.replace(/^set/, '').replace(/([A-Z])/g, ' $1').trim(),
+            item
+        ));
+
+        if (Array.isArray(val)) {
+            el = egen.createSelection(item, val, clss);
+            el.addEventListener('change', function(e) {
+                try{
+                    editor.menuOptions[e.target.id].forEach(function(x) {
+                        if(x.textContent !== e.target.textContent) {
+                            delete x.selected;
+                        }
+                    });
+                    obj[e.target.id](e.target.value);
+                } catch (err) {
+                    throw new Error(err);
+                }
+            });
+        } else if(typeof val === 'boolean') {
+            el = egen.createCheckbox(item, val, clss);
+            el.addEventListener('change', function(e) {
+                try{
+                    // renderer['setHighlightGutterLine'](true);
+                    obj[e.target.id](!!e.target.checked);
+                } catch (err) {
+                    throw new Error(err);
+                }
+            });
+        } else {
+            // this aids in giving the ability to specify settings through
+            // post and get requests.
+            // /ace_editor.html?setMode=ace/mode/html&setOverwrite=true
+            el = egen.createInput(item, val, clss);
+            el.addEventListener('change', function(e) {
+                try{
+                    if(e.target.value === 'true') {
+                        obj[e.target.id](true);
+                    } else if(e.target.value === 'false') {
+                        obj[e.target.id](false);
+                    } else {
+                        obj[e.target.id](e.target.value);
+                    }
+                } catch (err) {
+                    throw new Error(err);
+                }
+            });
+        }
+        el.style.cssText = 'float:right;';
+        div.appendChild(el);
+        return div;
+    }
+    /**
+     * Generates selection fields for the menu and populates their options
+     *  using information from `editor.menuOptions`
+     * @author <a href="mailto:matthewkastor@gmail.com">
+     *  Matthew Christopher Kastor-Inare III </a><br />
+     *  ☭ Hial Atropa!! ☭
+     * @param {string} item The set function name.
+     * @param {object} esr A reference to the object having the set function.
+     * @param {string} clss The name of the object containing the set function.
+     * @param {string} fn The matching get function's function name.
+     * @returns {DOMElement} Returns a dom element containing a selection
+     *  element populated with options. The option whose value matches that
+     *  returned from `esr[fn]()` will be selected.
+     */
+    function makeDropdown(item, esr, clss, fn) {
+        var val = editor.menuOptions[item];
+        var currentVal = esr[fn]();
+        if (typeof currentVal == 'object')
+            currentVal = currentVal.$id;
+        val.forEach(function(valuex) {
+            if (valuex.value === currentVal)
+                valuex.selected = 'selected';
+        });
+        return createNewEntry(esr, clss, item, val);
+    }
+    /**
+     * Processes the set functions returned from `getSetFunctions`. First it
+     *  checks for menu options defined in `editor.menuOptions`. If no
+     *  options are specified then it checks whether there is a get function
+     *  (replace set with get) for the setting. When either of those
+     *  conditions are met it will attempt to create a new entry for the
+     *  settings menu and push it into the elements array defined above.
+     *  It can only do so for get functions which return
+     *  strings, numbers, and booleans. A special case is written in for
+     *  `getMode` where it looks at the returned objects `$id` property and
+     *  forwards that through instead. Other special cases could be written
+     *  in but that would get a bit ridiculous.
+     * @author <a href="mailto:matthewkastor@gmail.com">
+     *  Matthew Christopher Kastor-Inare III </a><br />
+     *  ☭ Hial Atropa!! ☭
+     * @param {object} setObj An item from the array returned by
+     *  `getSetFunctions`.
+     */
+    function handleSet(setObj) {
+        var item = setObj.functionName;
+        var esr = setObj.parentObj;
+        var clss = setObj.parentName;
+        var val;
+        var fn = item.replace(/^set/, 'get');
+        if(editor.menuOptions[item] !== undefined) {
+            // has options for select element
+            elements.push(makeDropdown(item, esr, clss, fn));
+        } else if(typeof esr[fn] === 'function') {
+            // has get function
+            try {
+                val = esr[fn]();
+                if(typeof val === 'object') {
+                    // setMode takes a string, getMode returns an object
+                    // the $id property of that object is the string
+                    // which may be given to setMode...
+                    val = val.$id;
+                }
+                // the rest of the get functions return strings,
+                // booleans, or numbers.
+                elements.push(
+                    createNewEntry(esr, clss, item, val)
+                );
+            } catch (e) {
+                // if there are errors it is because the element
+                // does not belong in the settings menu
+            }
+        }
+    }
+    addEditorMenuOptions(editor);
+    // gather the set functions
+    getSetFunctions(editor).forEach(function(setObj) {
+        // populate the elements array with good stuff.
+        handleSet(setObj);
+    });
+    // sort the menu entries in the elements list so people can find
+    // the settings in alphabetical order.
+    cleanupElementsList();
+    // dump the entries from the elements list and wrap them up in a div
+    return wrapElements();
+};
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/couchdb/blob/9abd128c/src/fauxton/assets/js/libs/ace/ext/menu_tools/get_editor_keyboard_shortcuts.js
----------------------------------------------------------------------
diff --git a/src/fauxton/assets/js/libs/ace/ext/menu_tools/get_editor_keyboard_shortcuts.js b/src/fauxton/assets/js/libs/ace/ext/menu_tools/get_editor_keyboard_shortcuts.js
new file mode 100644
index 0000000..e412bfb
--- /dev/null
+++ b/src/fauxton/assets/js/libs/ace/ext/menu_tools/get_editor_keyboard_shortcuts.js
@@ -0,0 +1,100 @@
+/* ***** 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 ***** */
+
+/*jslint indent: 4, maxerr: 50, white: true, browser: true, vars: true*/
+/*global define, require */
+
+/**
+ * Get Editor Keyboard Shortcuts
+ * @fileOverview Get Editor Keyboard Shortcuts <br />
+ * Gets a map of keyboard shortcuts to command names for the current platform.
+ * @author <a href="mailto:matthewkastor@gmail.com">
+ *  Matthew Christopher Kastor-Inare III </a><br />
+ *  ☭ Hial Atropa!! ☭
+ */
+
+define(function(require, exports, module) {
+"use strict";
+var keys = require("../../lib/keys");
+
+/**
+ * Gets a map of keyboard shortcuts to command names for the current platform.
+ * @author <a href="mailto:matthewkastor@gmail.com">
+ *  Matthew Christopher Kastor-Inare III </a><br />
+ *  ☭ Hial Atropa!! ☭
+ * @param {ace.Editor} editor An editor instance.
+ * @returns {Array} Returns an array of objects representing the keyboard
+ *  shortcuts for the given editor.
+ * @example
+ * var getKbShortcuts = require('./get_keyboard_shortcuts');
+ * console.log(getKbShortcuts(editor));
+ * // [
+ * //     {'command' : aCommand, 'key' : 'Control-d'},
+ * //     {'command' : aCommand, 'key' : 'Control-d'}
+ * // ]
+ */
+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

http://git-wip-us.apache.org/repos/asf/couchdb/blob/9abd128c/src/fauxton/assets/js/libs/ace/ext/menu_tools/get_set_functions.js
----------------------------------------------------------------------
diff --git a/src/fauxton/assets/js/libs/ace/ext/menu_tools/get_set_functions.js b/src/fauxton/assets/js/libs/ace/ext/menu_tools/get_set_functions.js
new file mode 100644
index 0000000..4cd6550
--- /dev/null
+++ b/src/fauxton/assets/js/libs/ace/ext/menu_tools/get_set_functions.js
@@ -0,0 +1,141 @@
+/* ***** 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 ***** */
+
+/*jslint indent: 4, maxerr: 50, white: true, browser: true, vars: true */
+/*global define*/
+
+/**
+ * Get Set Functions
+ * @fileOverview Get Set Functions <br />
+ * Gets various functions for setting settings.
+ * @author <a href="mailto:matthewkastor@gmail.com">
+ *  Matthew Christopher Kastor-Inare III </a><br />
+ *  ☭ Hial Atropa!! ☭
+ */
+
+define(function(require, exports, module) {
+'use strict';
+/**
+ * Generates a list of set functions for the settings menu.
+ * @author <a href="mailto:matthewkastor@gmail.com">
+ *  Matthew Christopher Kastor-Inare III </a><br />
+ *  ☭ Hial Atropa!! ☭
+ * @param {object} editor The editor instance
+ * @return {array} Returns an array of objects. Each object contains the
+ *  following properties: functionName, parentObj, and parentName. The
+ *  function name will be the name of a method beginning with the string
+ *  `set` which was found. The parent object will be a reference to the
+ *  object having the method matching the function name. The parent name
+ *  will be a string representing the identifier of the parent object e.g.
+ *  `editor`, `session`, or `renderer`.
+ */
+module.exports.getSetFunctions = function getSetFunctions (editor) {
+    /**
+     * Output array. Will hold the objects described above.
+     * @author <a href="mailto:matthewkastor@gmail.com">
+     *  Matthew Christopher Kastor-Inare III </a><br />
+     *  ☭ Hial Atropa!! ☭
+     */
+    var out = [];
+    /**
+     * This object provides a map between the objects which will be
+     *  traversed and the parent name which will appear in the output.
+     * @author <a href="mailto:matthewkastor@gmail.com">
+     *  Matthew Christopher Kastor-Inare III </a><br />
+     *  ☭ Hial Atropa!! ☭
+     */
+    var my = {
+        'editor' : editor,
+        'session' : editor.session,
+        'renderer' : editor.renderer
+    };
+    /**
+     * This array will hold the set function names which have already been
+     *  found so that they are not added to the output multiple times.
+     * @author <a href="mailto:matthewkastor@gmail.com">
+     *  Matthew Christopher Kastor-Inare III </a><br />
+     *  ☭ Hial Atropa!! ☭
+     */
+    var opts = [];
+    /**
+     * This is a list of set functions which will not appear in the settings
+     *  menu. I don't know what to do with setKeyboardHandler. When I tried
+     *  to use it, it didn't appear to be working. Someone who knows better
+     *  could remove it from this list and add it's options to
+     *  add_editor_menu_options.js
+     * @author <a href="mailto:matthewkastor@gmail.com">
+     *  Matthew Christopher Kastor-Inare III </a><br />
+     *  ☭ Hial Atropa!! ☭
+     */
+    var skip = [
+        'setOption',
+        'setUndoManager',
+        'setDocument',
+        'setValue',
+        'setBreakpoints',
+        'setScrollTop',
+        'setScrollLeft',
+        'setSelectionStyle',
+        'setWrapLimitRange'
+    ];
+
+
+    /**
+     * This will search the objects mapped to the `my` variable above. When
+     *  it finds a set function in the object that is not listed in the
+     *  `skip` list or the `opts` list it will push a new object to the
+     *  output array.
+     * @author <a href="mailto:matthewkastor@gmail.com">
+     *  Matthew Christopher Kastor-Inare III </a><br />
+     *  ☭ Hial Atropa!! ☭
+     */
+    ['renderer', 'session', 'editor'].forEach(function(esra) {
+        var esr = my[esra];
+        var clss = esra;
+        for(var fn in esr) {
+            if(skip.indexOf(fn) === -1) {
+                if(/^set/.test(fn) && opts.indexOf(fn) === -1) {
+                    // found set function
+                    opts.push(fn);
+                    out.push({
+                        'functionName' : fn,
+                        'parentObj' : esr,
+                        'parentName' : clss
+                    });
+                }
+            }
+        }
+    });
+    return out;
+};
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/couchdb/blob/9abd128c/src/fauxton/assets/js/libs/ace/ext/menu_tools/overlay_page.js
----------------------------------------------------------------------
diff --git a/src/fauxton/assets/js/libs/ace/ext/menu_tools/overlay_page.js b/src/fauxton/assets/js/libs/ace/ext/menu_tools/overlay_page.js
new file mode 100644
index 0000000..bf985e2
--- /dev/null
+++ b/src/fauxton/assets/js/libs/ace/ext/menu_tools/overlay_page.js
@@ -0,0 +1,116 @@
+/* ***** 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 ***** */
+
+/*jslint indent: 4, maxerr: 50, white: true, browser: true, vars: true*/
+/*global define, require */
+
+/**
+ * Overlay Page
+ * @fileOverview Overlay Page <br />
+ * Generates an overlay for displaying menus. The overlay is an absolutely
+ *  positioned div.
+ * @author <a href="mailto:matthewkastor@gmail.com">
+ *  Matthew Christopher Kastor-Inare III </a><br />
+ *  ☭ Hial Atropa!! ☭
+ */
+
+define(function(require, exports, module) {
+'use strict';
+var dom = require("../../lib/dom");
+var cssText = require("../../requirejs/text!./settings_menu.css");
+dom.importCssString(cssText);
+
+/**
+ * Generates an overlay for displaying menus. The overlay is an absolutely
+ *  positioned div.
+ * @author <a href="mailto:matthewkastor@gmail.com">
+ *  Matthew Christopher Kastor-Inare III </a><br />
+ *  ☭ Hial Atropa!! ☭
+ * @param {DOMElement} contentElement Any element which may be presented inside
+ *  a div.
+ * @param {string|number} top absolute position value.
+ * @param {string|number} right absolute position value.
+ * @param {string|number} bottom absolute position value.
+ * @param {string|number} left absolute position value.
+ */
+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;
+    });
+    // click closer if esc key is pressed
+    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();
+};
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/couchdb/blob/9abd128c/src/fauxton/assets/js/libs/ace/ext/menu_tools/settings_menu.css
----------------------------------------------------------------------
diff --git a/src/fauxton/assets/js/libs/ace/ext/menu_tools/settings_menu.css b/src/fauxton/assets/js/libs/ace/ext/menu_tools/settings_menu.css
new file mode 100644
index 0000000..f8b761c
--- /dev/null
+++ b/src/fauxton/assets/js/libs/ace/ext/menu_tools/settings_menu.css
@@ -0,0 +1,48 @@
+#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;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/couchdb/blob/9abd128c/src/fauxton/assets/js/libs/ace/ext/modelist.js
----------------------------------------------------------------------
diff --git a/src/fauxton/assets/js/libs/ace/ext/modelist.js b/src/fauxton/assets/js/libs/ace/ext/modelist.js
new file mode 100644
index 0000000..88b0218
--- /dev/null
+++ b/src/fauxton/assets/js/libs/ace/ext/modelist.js
@@ -0,0 +1,174 @@
+define(function(require, exports, module) {
+"use strict";
+
+var modes = [];
+/**
+ * Suggests a mode based on the file extension present in the given path
+ * @param {string} path The path to the file
+ * @returns {object} Returns an object containing information about the
+ *  suggested mode.
+ */
+function getModeForPath(path) {
+    var mode = modesByName.text;
+    var fileName = path.split(/[\/\\]/).pop();
+    for (var i = 0; i < modes.length; i++) {
+        if (modes[i].supportsFile(fileName)) {
+            mode = modes[i];
+            break;
+        }
+    }
+    return mode;
+}
+
+var Mode = function(name, caption, extensions) {
+    this.name = name;
+    this.caption = caption;
+    this.mode = "ace/mode/" + name;
+    this.extensions = extensions;
+    if (/\^/.test(extensions)) {
+        var re = extensions.replace(/\|(\^)?/g, function(a, b){
+            return "$|" + (b ? "^" : "^.*\\.");
+        }) + "$";
+    } else {
+        var re = "^.*\\.(" + extensions + ")$";
+    }
+
+    this.extRe = new RegExp(re, "gi");
+};
+
+Mode.prototype.supportsFile = function(filename) {
+    return filename.match(this.extRe);
+};
+
+// todo firstlinematch
+var supportedModes = {
+    ABAP:        ["abap"],
+    ActionScript:["as"],
+    ADA:         ["ada|adb"],
+    AsciiDoc:    ["asciidoc"],
+    Assembly_x86:["asm"],
+    AutoHotKey:  ["ahk"],
+    BatchFile:   ["bat|cmd"],
+    C9Search:    ["c9search_results"],
+    C_Cpp:       ["cpp|c|cc|cxx|h|hh|hpp"],
+    Clojure:     ["clj"],
+    Cobol:       ["CBL|COB"],
+    coffee:      ["coffee|cf|cson|^Cakefile"],
+    ColdFusion:  ["cfm"],
+    CSharp:      ["cs"],
+    CSS:         ["css"],
+    Curly:       ["curly"],
+    D:           ["d|di"],
+    Dart:        ["dart"],
+    Diff:        ["diff|patch"],
+    Dot:         ["dot"],
+    Erlang:      ["erl|hrl"],
+    EJS:         ["ejs"],
+    Forth:       ["frt|fs|ldr"],
+    FTL:         ["ftl"],
+    Glsl:        ["glsl|frag|vert"],
+    golang:      ["go"],
+    Groovy:      ["groovy"],
+    HAML:        ["haml"],
+    Handlebars:  ["hbs|handlebars|tpl|mustache"],
+    Haskell:     ["hs"],
+    haXe:        ["hx"],
+    HTML:        ["html|htm|xhtml"],
+    HTML_Ruby:   ["erb|rhtml|html.erb"],
+    INI:         ["ini|conf|cfg|prefs"],
+    Jack:        ["jack"],
+    Jade:        ["jade"],
+    Java:        ["java"],
+    JavaScript:  ["js|jsm"],
+    JSON:        ["json"],
+    JSONiq:      ["jq"],
+    JSP:         ["jsp"],
+    JSX:         ["jsx"],
+    Julia:       ["jl"],
+    LaTeX:       ["tex|latex|ltx|bib"],
+    LESS:        ["less"],
+    Liquid:      ["liquid"],
+    Lisp:        ["lisp"],
+    LiveScript:  ["ls"],
+    LogiQL:      ["logic|lql"],
+    LSL:         ["lsl"],
+    Lua:         ["lua"],
+    LuaPage:     ["lp"],
+    Lucene:      ["lucene"],
+    Makefile:    ["^Makefile|^GNUmakefile|^makefile|^OCamlMakefile|make"],
+    MATLAB:      ["matlab"],
+    Markdown:    ["md|markdown"],
+    MySQL:       ["mysql"],
+    MUSHCode:    ["mc|mush"],
+    Nix:         ["nix"],
+    ObjectiveC:  ["m|mm"],
+    OCaml:       ["ml|mli"],
+    Pascal:      ["pas|p"],
+    Perl:        ["pl|pm"],
+    pgSQL:       ["pgsql"],
+    PHP:         ["php|phtml"],
+    Powershell:  ["ps1"],
+    Prolog:      ["plg|prolog"],
+    Properties:  ["properties"],
+    Protobuf:    ["proto"],
+    Python:      ["py"],
+    R:           ["r"],
+    RDoc:        ["Rd"],
+    RHTML:       ["Rhtml"],
+    Ruby:        ["rb|ru|gemspec|rake|^Guardfile|^Rakefile|^Gemfile"],
+    Rust:        ["rs"],
+    SASS:        ["sass"],
+    SCAD:        ["scad"],
+    Scala:       ["scala"],
+    Scheme:      ["scm|rkt"],
+    SCSS:        ["scss"],
+    SH:          ["sh|bash|^.bashrc"],
+    SJS:         ["sjs"],
+    Space:       ["space"],
+    snippets:    ["snippets"],
+    Soy_Template:["soy"],
+    SQL:         ["sql"],
+    Stylus:      ["styl|stylus"],
+    SVG:         ["svg"],
+    Tcl:         ["tcl"],
+    Tex:         ["tex"],
+    Text:        ["txt"],
+    Textile:     ["textile"],
+    Toml:        ["toml"],
+    Twig:        ["twig"],
+    Typescript:  ["ts|typescript|str"],
+    VBScript:    ["vbs"],
+    Velocity:    ["vm"],
+    Verilog:     ["v|vh|sv|svh"],
+    XML:         ["xml|rdf|rss|wsdl|xslt|atom|mathml|mml|xul|xbl"],
+    XQuery:      ["xq"],
+    YAML:        ["yaml|yml"]
+};
+
+var nameOverrides = {
+    ObjectiveC: "Objective-C",
+    CSharp: "C#",
+    golang: "Go",
+    C_Cpp: "C/C++",
+    coffee: "CoffeeScript",
+    HTML_Ruby: "HTML (Ruby)",
+    FTL: "FreeMarker"
+};
+var modesByName = {};
+for (var name in supportedModes) {
+    var data = supportedModes[name];
+    var displayName = nameOverrides[name] || name;
+    var filename = name.toLowerCase();
+    var mode = new Mode(filename, displayName, data[0]);
+    modesByName[filename] = mode;
+    modes.push(mode);
+}
+
+module.exports = {
+    getModeForPath: getModeForPath,
+    modes: modes,
+    modesByName: modesByName
+};
+
+});
+

http://git-wip-us.apache.org/repos/asf/couchdb/blob/9abd128c/src/fauxton/assets/js/libs/ace/ext/old_ie.js
----------------------------------------------------------------------
diff --git a/src/fauxton/assets/js/libs/ace/ext/old_ie.js b/src/fauxton/assets/js/libs/ace/ext/old_ie.js
new file mode 100644
index 0000000..ca67888
--- /dev/null
+++ b/src/fauxton/assets/js/libs/ace/ext/old_ie.js
@@ -0,0 +1,108 @@
+/* ***** 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(function(require, exports, module) {
+"use strict";
+var MAX_TOKEN_COUNT = 1000;
+var useragent = require("../lib/useragent");
+var TokenizerModule = require("../tokenizer");
+
+function patch(obj, name, regexp, replacement) {
+    eval("obj['" + name + "']=" + obj[name].toString().replace(
+        regexp, replacement
+    ));
+}
+
+if (useragent.isIE && useragent.isIE < 10 && window.top.document.compatMode === "BackCompat")
+    useragent.isOldIE = true;
+
+if (typeof document != "undefined" && !document.documentElement.querySelector) {    
+    useragent.isOldIE = true;
+    var qs = function(el, selector) {
+        if (selector.charAt(0) == ".") {
+            var classNeme = selector.slice(1);
+        } else {
+            var m = selector.match(/(\w+)=(\w+)/);
+            var attr = m && m[1];
+            var attrVal = m && m[2];
+        }
+        for (var i = 0; i < el.all.length; i++) {
+            var ch = el.all[i];
+            if (classNeme) {
+                if (ch.className.indexOf(classNeme) != -1)
+                    return ch;
+            } else if (attr) {
+                if (ch.getAttribute(attr) == attrVal)
+                    return ch;
+            }
+        }
+    };
+    var sb = require("./searchbox").SearchBox.prototype;
+    patch(
+        sb, "$initElements",
+        /([^\s=]*).querySelector\((".*?")\)/g, 
+        "qs($1, $2)"
+    );
+}
+    
+var compliantExecNpcg = /()??/.exec("")[1] === undefined;
+if (compliantExecNpcg)
+    return;
+var proto = TokenizerModule.Tokenizer.prototype;
+TokenizerModule.Tokenizer_orig = TokenizerModule.Tokenizer;
+proto.getLineTokens_orig = proto.getLineTokens;
+
+patch(
+    TokenizerModule, "Tokenizer",
+    "ruleRegExps.push(adjustedregex);\n", 
+    function(m) {
+        return m + '\
+        if (state[i].next && RegExp(adjustedregex).test(""))\n\
+            rule._qre = RegExp(adjustedregex, "g");\n\
+        ';
+    }
+);
+TokenizerModule.Tokenizer.prototype = proto;
+patch(
+    proto, "getLineTokens",
+    /if \(match\[i \+ 1\] === undefined\)\s*continue;/, 
+    "if (!match[i + 1]) {\n\
+        if (value)continue;\n\
+        var qre = state[mapping[i]]._qre;\n\
+        if (!qre) continue;\n\
+        qre.lastIndex = lastIndex;\n\
+        if (!qre.exec(line) || qre.lastIndex != lastIndex)\n\
+            continue;\n\
+    }"
+);
+
+useragent.isOldIE = true;
+
+});

http://git-wip-us.apache.org/repos/asf/couchdb/blob/9abd128c/src/fauxton/assets/js/libs/ace/ext/old_ie_test.js
----------------------------------------------------------------------
diff --git a/src/fauxton/assets/js/libs/ace/ext/old_ie_test.js b/src/fauxton/assets/js/libs/ace/ext/old_ie_test.js
new file mode 100644
index 0000000..98652e1
--- /dev/null
+++ b/src/fauxton/assets/js/libs/ace/ext/old_ie_test.js
@@ -0,0 +1,77 @@
+/* ***** 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 ***** */
+
+if (typeof process !== "undefined") {
+    require("amd-loader");
+}
+
+define(function(require, exports, module) {
+"use strict";
+
+var assert = require("../test/assertions");
+
+module.exports = {
+    "test: getTokenizer() (smoke test)" : function() {
+        var exec = RegExp.prototype.exec
+        var brokenExec = function(str) {
+            var result = exec.call(this, str);
+            if (result) {
+                for (var i = result.length; i--;)
+                    if (!result[i])
+                        result[i] = "";
+            }
+            return result;
+        }
+        
+        try {
+            // break this to emulate old ie
+            RegExp.prototype.exec = brokenExec;
+            require("./old_ie");
+            var Tokenizer = require("../tokenizer").Tokenizer;
+            var JavaScriptHighlightRules = require("../mode/javascript_highlight_rules").JavaScriptHighlightRules;
+            var tokenizer = new Tokenizer((new JavaScriptHighlightRules).getRules());
+            
+            var tokens = tokenizer.getLineTokens("'juhu'", "start").tokens;
+            assert.equal("string", tokens[0].type);
+        } finally {
+            // restore modified functions
+            RegExp.prototype.exec = exec;
+            var module = require("../tokenizer");
+            module.Tokenizer = module.Tokenizer_orig;
+            module.Tokenizer.prototype.getLineTokens = module.Tokenizer.prototype.getLineTokens_orig;
+        }
+    }
+};
+
+});
+
+if (typeof module !== "undefined" && module === require.main) {
+    require("asyncjs").test.testcase(module.exports).exec()
+}

http://git-wip-us.apache.org/repos/asf/couchdb/blob/9abd128c/src/fauxton/assets/js/libs/ace/ext/searchbox.css
----------------------------------------------------------------------
diff --git a/src/fauxton/assets/js/libs/ace/ext/searchbox.css b/src/fauxton/assets/js/libs/ace/ext/searchbox.css
new file mode 100644
index 0000000..c0f5f28
--- /dev/null
+++ b/src/fauxton/assets/js/libs/ace/ext/searchbox.css
@@ -0,0 +1,157 @@
+
+
+/* ------------------------------------------------------------------------------------------
+ * Editor Search Form
+ * --------------------------------------------------------------------------------------- */
+ .ace_search {
+    background-color: #ddd;
+    border: 1px solid #cbcbcb;
+    border-top: 0 none;
+    max-width: 297px;
+    overflow: hidden;
+    margin: 0;
+    padding: 4px;
+    padding-right: 6px;
+    padding-bottom: 0;
+    position: absolute;
+    top: 0px;
+    z-index: 99;
+}
+.ace_search.left {
+    border-left: 0 none;
+    border-radius: 0px 0px 5px 0px;
+    left: 0;
+}
+.ace_search.right {
+    border-radius: 0px 0px 0px 5px;
+    border-right: 0 none;
+    right: 0;
+}
+
+.ace_search_form, .ace_replace_form {
+    border-radius: 3px;
+    border: 1px solid #cbcbcb;
+    float: left;
+    margin-bottom: 4px;
+    overflow: hidden;
+}
+.ace_search_form.ace_nomatch {
+    outline: 1px solid red;
+}
+
+.ace_search_field {
+    background-color: white;
+    border-right: 1px solid #cbcbcb;
+    border: 0 none;
+    -webkit-box-sizing: border-box;
+       -moz-box-sizing: border-box;
+            box-sizing: border-box;
+    display: block;
+    float: left;
+    height: 22px;
+    outline: 0;
+    padding: 0 7px;
+    width: 214px;
+    margin: 0;
+}
+.ace_searchbtn,
+.ace_replacebtn {
+    background: #fff;
+    border: 0 none;
+    border-left: 1px solid #dcdcdc;
+    cursor: pointer;
+    display: block;
+    float: left;
+    height: 22px;
+    margin: 0;
+    padding: 0;
+    position: relative;
+}
+.ace_searchbtn:last-child,
+.ace_replacebtn:last-child {
+    border-top-right-radius: 3px;
+    border-bottom-right-radius: 3px;
+}
+.ace_searchbtn:disabled {
+    background: none;
+    cursor: default;
+}
+.ace_searchbtn {
+    background-position: 50% 50%;
+    background-repeat: no-repeat;
+    width: 27px;
+}
+.ace_searchbtn.prev {
+    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADFJREFUeNpiSU1NZUAC/6E0I0yACYskCpsJiySKIiY0SUZk40FyTEgCjGgKwTRAgAEAQJUIPCE+qfkAAAAASUVORK5CYII=);    
+}
+.ace_searchbtn.next {
+    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNpiTE1NZQCC/0DMyIAKwGJMUAYDEo3M/s+EpvM/mkKwCQxYjIeLMaELoLMBAgwAU7UJObTKsvAAAAAASUVORK5CYII=);    
+}
+.ace_searchbtn_close {
+    background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAcCAYAAABRVo5BAAAAZ0lEQVR42u2SUQrAMAhDvazn8OjZBilCkYVVxiis8H4CT0VrAJb4WHT3C5xU2a2IQZXJjiQIRMdkEoJ5Q2yMqpfDIo+XY4k6h+YXOyKqTIj5REaxloNAd0xiKmAtsTHqW8sR2W5f7gCu5nWFUpVjZwAAAABJRU5ErkJggg==) no-repeat 50% 0;
+    border-radius: 50%;
+    border: 0 none;
+    color: #656565;
+    cursor: pointer;
+    display: block;
+    float: right;
+    font-family: Arial;
+    font-size: 16px;
+    height: 14px;
+    line-height: 16px;
+    margin: 5px 1px 9px 5px;
+    padding: 0;
+    text-align: center;
+    width: 14px;
+}
+.ace_searchbtn_close:hover {
+    background-color: #656565;
+    background-position: 50% 100%;
+    color: white;
+}
+.ace_replacebtn.prev {
+    width: 54px
+}
+.ace_replacebtn.next {
+    width: 27px
+}
+
+.ace_button {
+    margin-left: 2px;
+    cursor: pointer;
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -o-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+    overflow: hidden;
+    opacity: 0.7;
+    border: 1px solid rgba(100,100,100,0.23);
+    padding: 1px;
+    -moz-box-sizing: border-box;
+    box-sizing:    border-box;
+    color: black;
+}
+
+.ace_button:hover {
+    background-color: #eee;
+    opacity:1;
+}
+.ace_button:active {
+    background-color: #ddd;
+}
+
+.ace_button.checked {
+    border-color: #3399ff;
+    opacity:1;
+}
+
+.ace_search_options{
+    margin-bottom: 3px;
+    text-align: right;
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -o-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+}
\ No newline at end of file