Просмотр исходного кода

Update Ace and fix autocomplete

James Allen 12 лет назад
Родитель
Сommit
16e382bef2
100 измененных файлов с 12728 добавлено и 22343 удалено
  1. 3 3
      services/web/app/coffee/Features/Project/ProjectController.coffee
  2. 7 10
      services/web/public/coffee/ide/editor/directives/aceEditor.coffee
  3. 54 37
      services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee
  4. 1 1
      services/web/public/coffee/ide/editor/directives/aceEditor/highlights/HighlightsManager.coffee
  5. 1 1
      services/web/public/coffee/ide/editor/directives/aceEditor/spell-check/SpellCheckManager.coffee
  6. 1 3
      services/web/public/coffee/ide/editor/directives/aceEditor/undo/UndoManager.coffee
  7. 5366 4
      services/web/public/js/ace/ace.js
  8. 0 242
      services/web/public/js/ace/anchor.js
  9. 0 188
      services/web/public/js/ace/anchor_test.js
  10. 0 351
      services/web/public/js/ace/autocomplete.js
  11. 0 332
      services/web/public/js/ace/autocomplete/popup.js
  12. 0 78
      services/web/public/js/ace/autocomplete/text_completer.js
  13. 0 74
      services/web/public/js/ace/autocomplete/util.js
  14. 0 255
      services/web/public/js/ace/background_tokenizer.js
  15. 0 85
      services/web/public/js/ace/background_tokenizer_test.js
  16. 0 112
      services/web/public/js/ace/commands/command_manager.js
  17. 0 199
      services/web/public/js/ace/commands/command_manager_test.js
  18. 0 542
      services/web/public/js/ace/commands/default_commands.js
  19. 0 180
      services/web/public/js/ace/commands/incremental_search_commands.js
  20. 0 97
      services/web/public/js/ace/commands/multi_select_commands.js
  21. 0 110
      services/web/public/js/ace/commands/occur_commands.js
  22. 0 295
      services/web/public/js/ace/config.js
  23. 0 128
      services/web/public/js/ace/config_test.js
  24. BIN
      services/web/public/js/ace/css/codefolding-fold-button-states.png
  25. 0 85
      services/web/public/js/ace/css/editor.css
  26. BIN
      services/web/public/js/ace/css/expand-marker.png
  27. 0 642
      services/web/public/js/ace/document.js
  28. 0 306
      services/web/public/js/ace/document_test.js
  29. 0 2541
      services/web/public/js/ace/edit_session.js
  30. 0 219
      services/web/public/js/ace/edit_session/bracket_match.js
  31. 0 140
      services/web/public/js/ace/edit_session/fold.js
  32. 0 268
      services/web/public/js/ace/edit_session/fold_line.js
  33. 0 846
      services/web/public/js/ace/edit_session/folding.js
  34. 0 1075
      services/web/public/js/ace/edit_session_test.js
  35. 0 2444
      services/web/public/js/ace/editor.js
  36. 0 188
      services/web/public/js/ace/editor_change_document_test.js
  37. 0 223
      services/web/public/js/ace/editor_highlight_selected_word_test.js
  38. 0 164
      services/web/public/js/ace/editor_navigation_test.js
  39. 0 557
      services/web/public/js/ace/editor_text_edit_test.js
  40. 335 0
      services/web/public/js/ace/ext-beautify.js
  41. 6 444
      services/web/public/js/ace/ext-chromevox.js
  42. 7 50
      services/web/public/js/ace/ext-elastic_tabstops_lite.js
  43. 417 93
      services/web/public/js/ace/ext-emmet.js
  44. 6 0
      services/web/public/js/ace/ext-error_marker.js
  45. 180 0
      services/web/public/js/ace/ext-keybinding_menu.js
  46. 1822 0
      services/web/public/js/ace/ext-language_tools.js
  47. 53 0
      services/web/public/js/ace/ext-linking.js
  48. 14 11
      services/web/public/js/ace/ext-modelist.js
  49. 478 0
      services/web/public/js/ace/ext-old_ie.js
  50. 154 47
      services/web/public/js/ace/ext-searchbox.js
  51. 622 0
      services/web/public/js/ace/ext-settings_menu.js
  52. 6 3
      services/web/public/js/ace/ext-spellcheck.js
  53. 12 138
      services/web/public/js/ace/ext-split.js
  54. 36 69
      services/web/public/js/ace/ext-static_highlight.js
  55. 7 3
      services/web/public/js/ace/ext-statusbar.js
  56. 242 168
      services/web/public/js/ace/ext-textarea.js
  57. 59 0
      services/web/public/js/ace/ext-themelist.js
  58. 11 44
      services/web/public/js/ace/ext-whitespace.js
  59. 0 415
      services/web/public/js/ace/ext/emmet.js
  60. 0 86
      services/web/public/js/ace/ext/keybinding_menu.js
  61. 0 129
      services/web/public/js/ace/ext/language_tools.js
  62. 0 103
      services/web/public/js/ace/ext/menu_tools/add_editor_menu_options.js
  63. 0 148
      services/web/public/js/ace/ext/menu_tools/element_generator.js
  64. 0 258
      services/web/public/js/ace/ext/menu_tools/generate_settings_menu.js
  65. 0 100
      services/web/public/js/ace/ext/menu_tools/get_editor_keyboard_shortcuts.js
  66. 0 141
      services/web/public/js/ace/ext/menu_tools/get_set_functions.js
  67. 0 116
      services/web/public/js/ace/ext/menu_tools/overlay_page.js
  68. 0 48
      services/web/public/js/ace/ext/menu_tools/settings_menu.css
  69. 0 108
      services/web/public/js/ace/ext/old_ie.js
  70. 0 77
      services/web/public/js/ace/ext/old_ie_test.js
  71. 0 158
      services/web/public/js/ace/ext/searchbox.css
  72. 0 76
      services/web/public/js/ace/ext/settings_menu.js
  73. 0 40
      services/web/public/js/ace/ext/split.js
  74. 0 32
      services/web/public/js/ace/ext/static.css
  75. 0 96
      services/web/public/js/ace/ext/static_highlight_test.js
  76. 0 101
      services/web/public/js/ace/ext/themelist.js
  77. 0 259
      services/web/public/js/ace/incremental_search.js
  78. 0 208
      services/web/public/js/ace/incremental_search_test.js
  79. 1070 0
      services/web/public/js/ace/keybinding-emacs.js
  80. 1758 0
      services/web/public/js/ace/keybinding-vim.js
  81. 0 599
      services/web/public/js/ace/keyboard/emacs.js
  82. 0 73
      services/web/public/js/ace/keyboard/emacs_test.js
  83. 0 198
      services/web/public/js/ace/keyboard/hash_handler.js
  84. 0 136
      services/web/public/js/ace/keyboard/keybinding.js
  85. 0 69
      services/web/public/js/ace/keyboard/keybinding_test.js
  86. 0 249
      services/web/public/js/ace/keyboard/state_handler.js
  87. 0 505
      services/web/public/js/ace/keyboard/textinput.js
  88. 0 195
      services/web/public/js/ace/keyboard/vim.js
  89. 0 613
      services/web/public/js/ace/keyboard/vim/commands.js
  90. 0 94
      services/web/public/js/ace/keyboard/vim/maps/aliases.js
  91. 0 664
      services/web/public/js/ace/keyboard/vim/maps/motions.js
  92. 0 195
      services/web/public/js/ace/keyboard/vim/maps/operators.js
  93. 0 134
      services/web/public/js/ace/keyboard/vim/maps/util.js
  94. 0 42
      services/web/public/js/ace/keyboard/vim/registers.js
  95. 0 217
      services/web/public/js/ace/layer/cursor.js
  96. 0 272
      services/web/public/js/ace/layer/gutter.js
  97. 0 218
      services/web/public/js/ace/layer/marker.js
  98. 0 667
      services/web/public/js/ace/layer/text.js
  99. 0 126
      services/web/public/js/ace/layer/text_test.js
  100. 0 283
      services/web/public/js/ace/lib/dom.js

+ 3 - 3
services/web/app/coffee/Features/Project/ProjectController.coffee

@@ -290,9 +290,9 @@ defaultSettingsForAnonymousUser = (user_id)->
 
 THEME_LIST = []
 do generateThemeList = () ->
-	files = fs.readdirSync __dirname + '/../../../../public/js/ace/theme'
+	files = fs.readdirSync __dirname + '/../../../../public/js/ace'
 	for file in files
-		if file.slice(-2) == "js"
-			cleanName = file.slice(0,-3)
+		if file.slice(-2) == "js" and file.match(/^theme-/)
+			cleanName = file.slice(0,-3).slice(6)
 			THEME_LIST.push cleanName
 

+ 7 - 10
services/web/public/coffee/ide/editor/directives/aceEditor.coffee

@@ -6,12 +6,7 @@ define [
 	"ide/editor/directives/aceEditor/spell-check/SpellCheckManager"
 	"ide/editor/directives/aceEditor/highlights/HighlightsManager"
 	"ide/editor/directives/aceEditor/cursor-position/CursorPositionManager"
-	"ace/keyboard/vim"
-	"ace/keyboard/emacs"
-	"ace/mode/latex"
-	"ace/edit_session"
 ], (App, Ace, UndoManager, AutoCompleteManager, SpellCheckManager, HighlightsManager, CursorPositionManager) ->
-	LatexMode = require("ace/mode/latex").Mode
 	EditSession = require('ace/edit_session').EditSession
 
 	App.directive "aceEditor", ["$timeout", ($timeout) ->
@@ -43,6 +38,8 @@ define [
 						@$originalApply(fn);
 
 				editor = Ace.edit(element.find(".ace-editor-body")[0])
+				window.editors ||= []
+				window.editors.push editor
 
 				scope.name = attrs.aceEditor
 
@@ -74,10 +71,10 @@ define [
 					editor.setShowPrintMargin(value)
 
 				scope.$watch "keybindings", (value) ->
-					Vim = require("ace/keyboard/vim").handler
-					Emacs = require("ace/keyboard/emacs").handler
-					keybindings = vim: Vim, emacs: Emacs
-					editor.setKeyboardHandler(keybindings[value])
+					if value in ["vim", "emacs"]
+						editor.setKeyboardHandler("ace/keyboard/#{value}")
+					else
+						editor.setKeyboardHandler(null)
 
 				scope.$watch "fontSize", (value) ->
 					element.find(".ace_editor, .ace_content").css({
@@ -109,7 +106,7 @@ define [
 				resetSession = () ->
 					session = editor.getSession()
 					session.setUseWrapMode(true)
-					session.setMode(new LatexMode())
+					session.setMode("ace/mode/latex")
 					session.setAnnotations scope.annotations
 
 				attachToAce = (sharejs_doc) ->

+ 54 - 37
services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee

@@ -1,23 +1,10 @@
 define [
 	"ide/editor/directives/aceEditor/auto-complete/SuggestionManager"
 	"ide/editor/directives/aceEditor/auto-complete/Snippets"
-	"ace/autocomplete/util"
-	"ace/autocomplete"
-	"ace/range"
-	"ace/ext/language_tools"
-], (SuggestionManager, Snippets, Util, AutoComplete) ->
-	Range = require("ace/range").Range
-	Autocomplete = AutoComplete.Autocomplete
-
-	Util.retrievePrecedingIdentifier = (text, pos, regex) ->
-		currentLineOffset = 0
-		for i in [(pos-1)..0]
-			if text[i] == "\n"
-				currentLineOffset = i + 1
-				break
-		currentLine = text.slice(currentLineOffset, pos)
-		fragment = getLastCommandFragment(currentLine) or ""
-		return fragment
+	"ace/ace"
+	"ace/ext-language_tools"
+], (SuggestionManager, Snippets, Ace) ->
+	Range = Ace.require("ace/range").Range
 
 	getLastCommandFragment = (lineUpToCursor) ->
 		if m = lineUpToCursor.match(/(\\[^\\ ]+)$/)
@@ -29,21 +16,7 @@ define [
 		constructor: (@$scope, @editor) ->
 			@suggestionManager = new SuggestionManager()
 
-			if !Autocomplete::_insertMatch?
-				# Only override this once since it's global but we may create multiple
-				# autocomplete handlers
-				Autocomplete::_insertMatch = Autocomplete::insertMatch
-				Autocomplete::insertMatch = (data) ->
-					pos = editor.getCursorPosition()
-					range = new Range(pos.row, pos.column, pos.row, pos.column + 1)
-					nextChar = editor.session.getTextRange(range)
-
-					# If we are in \begin{it|}, then we need to remove the trailing }
-					# since it will be adding in with the autocomplete of \begin{item}...
-					if this.completions.filterText.match(/^\\begin\{/) and nextChar == "}"
-						editor.session.remove(range)
-					
-					Autocomplete::_insertMatch.call this, data
+			@monkeyPatchAutocomplete()	
 
 			@$scope.$watch "autoComplete", (autocomplete) =>
 				if autocomplete
@@ -51,14 +24,14 @@ define [
 				else
 					@disable()
 
-
 			@editor.on "changeSession", (e) =>
 				@bindToSession(e.session)
 
 		enable: () ->
 			@editor.setOptions({
 				enableBasicAutocompletion: true,
-				enableSnippets: true
+				enableSnippets: true,
+				enableLiveAutocompletion: false
 			})
 			
 			SnippetCompleter =
@@ -87,6 +60,50 @@ define [
 					commandFragment = getLastCommandFragment(lineUpToCursor)
 
 					if commandFragment? and commandFragment.length > 2
-					 	setTimeout () =>
-					 		@editor.execCommand("startAutocomplete")
-					 	, 0
+						setTimeout () =>
+							@editor.execCommand("startAutocomplete")
+						, 0
+
+		monkeyPatchAutocomplete: () ->
+			Autocomplete = require("ace/autocomplete").Autocomplete
+			Util = require("ace/autocomplete/util")
+			editor = @editor
+
+			if !Autocomplete::_insertMatch?
+				# Only override this once since it's global but we may create multiple
+				# autocomplete handlers
+				Autocomplete::_insertMatch = Autocomplete::insertMatch
+				Autocomplete::insertMatch = (data) ->
+					pos = editor.getCursorPosition()
+					range = new Range(pos.row, pos.column, pos.row, pos.column + 1)
+					nextChar = editor.session.getTextRange(range)
+
+					# If we are in \begin{it|}, then we need to remove the trailing }
+					# since it will be adding in with the autocomplete of \begin{item}...
+					if this.completions.filterText.match(/^\\begin\{/) and nextChar == "}"
+						editor.session.remove(range)
+					
+					Autocomplete::_insertMatch.call this, data
+
+				# Overwrite this to set autoInsert = false
+				Autocomplete.startCommand = {
+					name: "startAutocomplete",
+					exec: (editor) ->
+						if (!editor.completer)
+							editor.completer = new Autocomplete()
+						editor.completer.autoInsert = false
+						editor.completer.autoSelect = true
+						editor.completer.showPopup(editor)
+						editor.completer.cancelContextMenu()
+					bindKey: "Ctrl-Space|Ctrl-Shift-Space|Alt-Space"
+				}
+
+			Util.retrievePrecedingIdentifier = (text, pos, regex) ->
+				currentLineOffset = 0
+				for i in [(pos-1)..0]
+					if text[i] == "\n"
+						currentLineOffset = i + 1
+						break
+				currentLine = text.slice(currentLineOffset, pos)
+				fragment = getLastCommandFragment(currentLine) or ""
+				return fragment

+ 1 - 1
services/web/public/coffee/ide/editor/directives/aceEditor/highlights/HighlightsManager.coffee

@@ -1,5 +1,5 @@
 define [
-	"ace/range"
+	"ace/ace"
 ], () ->
 	Range = require("ace/range").Range
 

+ 1 - 1
services/web/public/coffee/ide/editor/directives/aceEditor/spell-check/SpellCheckManager.coffee

@@ -1,6 +1,6 @@
 define [
 	"ide/editor/directives/aceEditor/spell-check/HighlightedWordManager"
-	"ace/range"
+	"ace/ace"
 ], (HighlightedWordManager) ->
 	Range = require("ace/range").Range
 

+ 1 - 3
services/web/public/coffee/ide/editor/directives/aceEditor/undo/UndoManager.coffee

@@ -1,7 +1,5 @@
 define [
-	"ace/range"
-	"ace/edit_session"
-	"ace/document"
+	"ace/ace"
 ], () ->
 	Range = require("ace/range").Range
 	EditSession = require("ace/edit_session").EditSession

Разница между файлами не показана из-за своего большого размера
+ 5366 - 4
services/web/public/js/ace/ace.js


+ 0 - 242
services/web/public/js/ace/anchor.js

@@ -1,242 +0,0 @@
-/* ***** 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 oop = require("./lib/oop");
-var EventEmitter = require("./lib/event_emitter").EventEmitter;
-
-/**
- *
- * Defines the floating pointer in the document. Whenever text is inserted or deleted before the cursor, the position of the cursor is updated.
- *
- * @class Anchor
- **/
-
-/**
- * Creates a new `Anchor` and associates it with a document.
- *
- * @param {Document} doc The document to associate with the anchor
- * @param {Number} row The starting row position
- * @param {Number} column The starting column position
- *
- * @constructor
- **/
-
-var Anchor = exports.Anchor = function(doc, row, column) {
-    this.$onChange = this.onChange.bind(this);
-    this.attach(doc);
-    
-    if (typeof column == "undefined")
-        this.setPosition(row.row, row.column);
-    else
-        this.setPosition(row, column);
-};
-
-(function() {
-
-    oop.implement(this, EventEmitter);
-
-    /**
-     * Returns an object identifying the `row` and `column` position of the current anchor.
-     * @returns {Object}
-     **/
-    this.getPosition = function() {
-        return this.$clipPositionToDocument(this.row, this.column);
-    };
-
-    /**
-     *
-     * Returns the current document.
-     * @returns {Document}
-     **/
-    this.getDocument = function() {
-        return this.document;
-    };
-
-    /**
-     * experimental: allows anchor to stick to the next on the left
-     */
-    this.$insertRight = false;
-    /**
-     * Fires whenever the anchor position changes.
-     *
-     * Both of these objects have a `row` and `column` property corresponding to the position.
-     *
-     * Events that can trigger this function include [[Anchor.setPosition `setPosition()`]].
-     *
-     * @event change
-     * @param {Object} e  An object containing information about the anchor position. It has two properties:
-     *  - `old`: An object describing the old Anchor position
-     *  - `value`: An object describing the new Anchor position
-     *
-     **/
-    this.onChange = function(e) {
-        var delta = e.data;
-        var range = delta.range;
-
-        if (range.start.row == range.end.row && range.start.row != this.row)
-            return;
-
-        if (range.start.row > this.row)
-            return;
-
-        if (range.start.row == this.row && range.start.column > this.column)
-            return;
-
-        var row = this.row;
-        var column = this.column;
-        var start = range.start;
-        var end = range.end;
-
-        if (delta.action === "insertText") {
-            if (start.row === row && start.column <= column) {
-                if (start.column === column && this.$insertRight) {
-                    // do nothing
-                } else if (start.row === end.row) {
-                    column += end.column - start.column;
-                } else {
-                    column -= start.column;
-                    row += end.row - start.row;
-                }
-            } else if (start.row !== end.row && start.row < row) {
-                row += end.row - start.row;
-            }
-        } else if (delta.action === "insertLines") {
-            if (start.row <= row) {
-                row += end.row - start.row;
-            }
-        } else if (delta.action === "removeText") {
-            if (start.row === row && start.column < column) {
-                if (end.column >= column)
-                    column = start.column;
-                else
-                    column = Math.max(0, column - (end.column - start.column));
-
-            } else if (start.row !== end.row && start.row < row) {
-                if (end.row === row)
-                    column = Math.max(0, column - end.column) + start.column;
-                row -= (end.row - start.row);
-            } else if (end.row === row) {
-                row -= end.row - start.row;
-                column = Math.max(0, column - end.column) + start.column;
-            }
-        } else if (delta.action == "removeLines") {
-            if (start.row <= row) {
-                if (end.row <= row)
-                    row -= end.row - start.row;
-                else {
-                    row = start.row;
-                    column = 0;
-                }
-            }
-        }
-
-        this.setPosition(row, column, true);
-    };
-
-    /**
-     * Sets the anchor position to the specified row and column. If `noClip` is `true`, the position is not clipped.
-     * @param {Number} row The row index to move the anchor to
-     * @param {Number} column The column index to move the anchor to
-     * @param {Boolean} noClip Identifies if you want the position to be clipped
-     *
-     **/
-    this.setPosition = function(row, column, noClip) {
-        var pos;
-        if (noClip) {
-            pos = {
-                row: row,
-                column: column
-            };
-        } else {
-            pos = this.$clipPositionToDocument(row, column);
-        }
-
-        if (this.row == pos.row && this.column == pos.column)
-            return;
-
-        var old = {
-            row: this.row,
-            column: this.column
-        };
-
-        this.row = pos.row;
-        this.column = pos.column;
-        this._emit("change", {
-            old: old,
-            value: pos
-        });
-    };
-
-    /**
-     * When called, the `'change'` event listener is removed.
-     *
-     **/
-    this.detach = function() {
-        this.document.removeEventListener("change", this.$onChange);
-    };
-    this.attach = function(doc) {
-        this.document = doc || this.document;
-        this.document.on("change", this.$onChange);
-    };
-
-    /**
-     * Clips the anchor position to the specified row and column.
-     * @param {Number} row The row index to clip the anchor to
-     * @param {Number} column The column index to clip the anchor to
-     *
-     **/
-    this.$clipPositionToDocument = function(row, column) {
-        var pos = {};
-
-        if (row >= this.document.getLength()) {
-            pos.row = Math.max(0, this.document.getLength() - 1);
-            pos.column = this.document.getLine(pos.row).length;
-        }
-        else if (row < 0) {
-            pos.row = 0;
-            pos.column = 0;
-        }
-        else {
-            pos.row = row;
-            pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column));
-        }
-
-        if (column < 0)
-            pos.column = 0;
-
-        return pos;
-    };
-
-}).call(Anchor.prototype);
-
-});

+ 0 - 188
services/web/public/js/ace/anchor_test.js

@@ -1,188 +0,0 @@
-/* ***** 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 Document = require("./document").Document;
-var Anchor = require("./anchor").Anchor;
-var Range = require("./range").Range;
-var assert = require("./test/assertions");
-
-module.exports = {
-
-    "test create anchor" : function() {
-        var doc = new Document("juhu");
-        var anchor = new Anchor(doc, 0, 0);
-        
-        assert.position(anchor.getPosition(), 0, 0);
-        assert.equal(anchor.getDocument(), doc);
-    },
-    
-    "test insert text in same row before cursor should move anchor column": function() {
-        var doc = new Document("juhu\nkinners");
-        var anchor = new Anchor(doc, 1, 4);
-        
-        doc.insert({row: 1, column: 1}, "123");
-        assert.position(anchor.getPosition(), 1, 7);
-    },
-    
-    "test insert lines before cursor should move anchor row": function() {
-        var doc = new Document("juhu\nkinners");
-        var anchor = new Anchor(doc, 1, 4);
-        
-        doc.insertLines(1, ["123", "456"]);
-        assert.position(anchor.getPosition(), 3, 4);    
-    },
-    
-    "test insert new line before cursor should move anchor column": function() {
-        var doc = new Document("juhu\nkinners");
-        var anchor = new Anchor(doc, 1, 4);
-        
-        doc.insertNewLine({row: 0, column: 0});
-        assert.position(anchor.getPosition(), 2, 4);    
-    },
-    
-    "test insert new line in anchor line before anchor should move anchor column and row": function() {
-        var doc = new Document("juhu\nkinners");
-        var anchor = new Anchor(doc, 1, 4);
-        
-        doc.insertNewLine({row: 1, column: 2});
-        assert.position(anchor.getPosition(), 2, 2);
-    },
-    
-    "test delete text in anchor line before anchor should move anchor column": function() {
-        var doc = new Document("juhu\nkinners");
-        var anchor = new Anchor(doc, 1, 4);
-        
-        doc.remove(new Range(1, 1, 1, 3));
-        assert.position(anchor.getPosition(), 1, 2);
-    },
-    
-    "test remove range which contains the anchor should move the anchor to the start of the range": function() {
-        var doc = new Document("juhu\nkinners");
-        var anchor = new Anchor(doc, 0, 3);
-        
-        doc.remove(new Range(0, 1, 1, 3));
-        assert.position(anchor.getPosition(), 0, 1);
-    },
-    
-    "test delete character before the anchor should have no effect": function() {
-        var doc = new Document("juhu\nkinners");
-        var anchor = new Anchor(doc, 1, 4);
-        
-        doc.remove(new Range(1, 4, 1, 5));
-        assert.position(anchor.getPosition(), 1, 4);
-    },
-    
-    "test delete lines in anchor line before anchor should move anchor row": function() {
-        var doc = new Document("juhu\n1\n2\nkinners");
-        var anchor = new Anchor(doc, 3, 4);
-        
-        doc.removeLines(1, 2);
-        assert.position(anchor.getPosition(), 1, 4);
-    },
-    
-    "test remove new line before the cursor": function() {
-        var doc = new Document("juhu\nkinners");
-        var anchor = new Anchor(doc, 1, 4);
-        
-        doc.removeNewLine(0);
-        assert.position(anchor.getPosition(), 0, 8);
-    },
-    
-    "test delete range which contains the anchor should move anchor to the end of the range": function() {
-        var doc = new Document("juhu\nkinners");
-        var anchor = new Anchor(doc, 1, 4);
-        
-        doc.remove(new Range(0, 2, 1, 2));
-        assert.position(anchor.getPosition(), 0, 4);
-    },
-    
-    "test delete line which contains the anchor should move anchor to the end of the range": function() {
-        var doc = new Document("juhu\nkinners\n123");
-        var anchor = new Anchor(doc, 1, 5);
-        
-        doc.removeLines(1, 1);
-        assert.position(anchor.getPosition(), 1, 0);
-    },
-    
-    "test remove after the anchor should have no effect": function() {
-        var doc = new Document("juhu\nkinners\n123");
-        var anchor = new Anchor(doc, 1, 2);
-        
-        doc.remove(new Range(1, 4, 2, 2));
-        assert.position(anchor.getPosition(), 1, 2);
-    },
-    
-    "test anchor changes triggered by document changes should emit change event": function(next) {
-        var doc = new Document("juhu\nkinners\n123");
-        var anchor = new Anchor(doc, 1, 5);
-        
-        anchor.on("change", function(e) {
-            assert.position(anchor.getPosition(), 0, 0);
-            next();
-        });
-        
-        doc.remove(new Range(0, 0, 2, 1));
-    },
-    
-    "test only fire change event if position changes": function() {
-        var doc = new Document("juhu\nkinners\n123");
-        var anchor = new Anchor(doc, 1, 5);
-        
-        anchor.on("change", function(e) {
-            assert.fail();
-        });
-        
-        doc.remove(new Range(2, 0, 2, 1));
-    },
-    
-    "test insert/remove lines at the end of the document": function() {
-        var doc = new Document("juhu\nkinners\n123");
-        var anchor = new Anchor(doc, 2, 4);
-        
-        doc.removeLines(0, 3);
-        assert.position(anchor.getPosition(), 0, 0);
-        doc.insertLines(0, ["a", "b", "c"]);        
-        assert.position(anchor.getPosition(), 3, 0);
-        assert.equal(doc.getValue(), "a\nb\nc\n");
-    }
-};
-
-});
-
-if (typeof module !== "undefined" && module === require.main) {
-    require("asyncjs").test.testcase(module.exports).exec()
-}

+ 0 - 351
services/web/public/js/ace/autocomplete.js

@@ -1,351 +0,0 @@
-/* ***** 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 HashHandler = require("./keyboard/hash_handler").HashHandler;
-var AcePopup = require("./autocomplete/popup").AcePopup;
-var util = require("./autocomplete/util");
-var event = require("./lib/event");
-var lang = require("./lib/lang");
-var snippetManager = require("./snippets").snippetManager;
-
-var Autocomplete = function() {
-    this.keyboardHandler = new HashHandler();
-    this.keyboardHandler.bindKeys(this.commands);
-
-    this.blurListener = this.blurListener.bind(this);
-    this.changeListener = this.changeListener.bind(this);
-    this.mousedownListener = this.mousedownListener.bind(this);
-    this.mousewheelListener = this.mousewheelListener.bind(this);
-    
-    this.changeTimer = lang.delayedCall(function() {
-        this.updateCompletions(true);
-    }.bind(this))
-};
-
-(function() {
-    this.$init = function() {
-        this.popup = new AcePopup(document.body || document.documentElement);
-        this.popup.on("click", function(e) {
-            this.insertMatch();
-            e.stop();
-        }.bind(this));
-    };
-
-    this.openPopup = function(editor, prefix, keepPopupPosition) {
-        if (!this.popup)
-            this.$init();
-
-        this.popup.setData(this.completions.filtered);
-
-        var renderer = editor.renderer;
-        if (!keepPopupPosition) {
-            this.popup.setRow(0);
-            this.popup.setFontSize(editor.getFontSize());
-
-            var lineHeight = renderer.layerConfig.lineHeight;
-            
-            var pos = renderer.$cursorLayer.getPixelPosition(this.base, true);            
-            pos.left -= this.popup.getTextLeftOffset();
-            
-            var rect = editor.container.getBoundingClientRect();
-            pos.top += rect.top - renderer.layerConfig.offset;
-            pos.left += rect.left - editor.renderer.scrollLeft;
-            pos.left += renderer.$gutterLayer.gutterWidth;
-
-            this.popup.show(pos, lineHeight);
-        }
-    };
-
-    this.detach = function() {
-        this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler);
-        this.editor.off("changeSelection", this.changeListener);
-        this.editor.off("blur", this.changeListener);
-        this.editor.off("mousedown", this.mousedownListener);
-        this.editor.off("mousewheel", this.mousewheelListener);
-        this.changeTimer.cancel();
-        
-        if (this.popup)
-            this.popup.hide();
-
-        this.activated = false;
-        this.completions = this.base = null;
-    };
-
-    this.changeListener = function(e) {
-        var cursor = this.editor.selection.lead;
-        if (cursor.row != this.base.row || cursor.column < this.base.column) {
-            this.detach();
-        }
-        if (this.activated)
-            this.changeTimer.schedule();
-        else
-            this.detach();
-    };
-
-    this.blurListener = function() {
-        if (document.activeElement != this.editor.textInput.getElement())
-            this.detach();
-    };
-
-    this.mousedownListener = function(e) {
-        this.detach();
-    };
-
-    this.mousewheelListener = function(e) {
-        this.detach();
-    };
-
-    this.goTo = function(where) {
-        var row = this.popup.getRow();
-        var max = this.popup.session.getLength() - 1;
-
-        switch(where) {
-            case "up": row = row < 0 ? max : row - 1; break;
-            case "down": row = row >= max ? -1 : row + 1; break;
-            case "start": row = 0; break;
-            case "end": row = max; break;
-        }
-
-        this.popup.setRow(row);
-    };
-
-    this.insertMatch = function(data) {
-        if (!data)
-            data = this.popup.getData(this.popup.getRow());
-        if (!data)
-            return false;
-        if (data.completer && data.completer.insertMatch) {
-            data.completer.insertMatch(this.editor);
-        } else {
-            if (this.completions.filterText) {
-                var ranges = this.editor.selection.getAllRanges();
-                for (var i = 0, range; range = ranges[i]; i++) {
-                    range.start.column -= this.completions.filterText.length;
-                    this.editor.session.remove(range);
-                }
-            }
-            if (data.snippet)
-                snippetManager.insertSnippet(this.editor, data.snippet);
-            else
-                this.editor.execCommand("insertstring", data.value || data);
-        }
-        this.detach();
-    };
-
-    this.commands = {
-        "Up": function(editor) { editor.completer.goTo("up"); },
-        "Down": function(editor) { editor.completer.goTo("down"); },
-        "Ctrl-Up|Ctrl-Home": function(editor) { editor.completer.goTo("start"); },
-        "Ctrl-Down|Ctrl-End": function(editor) { editor.completer.goTo("end"); },
-
-        "Esc": function(editor) { editor.completer.detach(); },
-        "Space": function(editor) { editor.completer.detach(); editor.insert(" ");},
-        "Return": function(editor) { editor.completer.insertMatch(); },
-        "Shift-Return": function(editor) { editor.completer.insertMatch(true); },
-        "Tab": function(editor) { editor.completer.insertMatch(); },
-
-        "PageUp": function(editor) { editor.completer.popup.gotoPageUp(); },
-        "PageDown": function(editor) { editor.completer.popup.gotoPageDown(); }
-    };
-
-    this.gatherCompletions = function(editor, callback) {
-        var session = editor.getSession();
-        var pos = editor.getCursorPosition();
-        
-        var line = session.getLine(pos.row);
-        var prefix = util.retrievePrecedingIdentifier(line, pos.column);
-        
-        this.base = editor.getCursorPosition();
-        this.base.column -= prefix.length;
-
-        var matches = [];
-        util.parForEach(editor.completers, function(completer, next) {
-            completer.getCompletions(editor, session, pos, prefix, function(err, results) {
-                if (!err)
-                    matches = matches.concat(results);
-                next();
-            });
-        }, function() {
-            callback(null, {
-                prefix: prefix,
-                matches: matches
-            });
-        });
-        return true;
-    };
-
-    this.showPopup = function(editor) {
-        if (this.editor)
-            this.detach();
-        
-        this.activated = true;
-
-        this.editor = editor;
-        if (editor.completer != this) {
-            if (editor.completer)
-                editor.completer.detach();
-            editor.completer = this;
-        }
-
-        editor.keyBinding.addKeyboardHandler(this.keyboardHandler);
-        editor.on("changeSelection", this.changeListener);
-        editor.on("blur", this.blurListener);
-        editor.on("mousedown", this.mousedownListener);
-        editor.on("mousewheel", this.mousewheelListener);
-        
-        this.updateCompletions();
-    };
-    
-    this.updateCompletions = function(keepPopupPosition) {
-        if (keepPopupPosition && this.base && this.completions) {
-            var pos = this.editor.getCursorPosition();
-            var prefix = this.editor.session.getTextRange({start: this.base, end: pos});
-            if (prefix == this.completions.filterText)
-                return;
-            this.completions.setFilter(prefix);
-            if (!this.completions.filtered.length)
-                return this.detach();
-            this.openPopup(this.editor, prefix, keepPopupPosition);
-            return;
-        }
-        this.gatherCompletions(this.editor, function(err, results) {
-            var matches = results && results.matches;
-            if (!matches || !matches.length)
-                return this.detach();
-            // TODO reenable this when we have proper change tracking 
-            // if (matches.length == 1)
-            //     return this.insertMatch(matches[0]);
-
-            this.completions = new FilteredList(matches);
-            this.completions.setFilter(results.prefix);
-            if (!this.completions.filtered.length)
-                return this.detach();
-            this.openPopup(this.editor, results.prefix, keepPopupPosition);
-        }.bind(this));
-    };
-
-    this.cancelContextMenu = function() {
-        var stop = function(e) {
-            this.editor.off("nativecontextmenu", stop);
-            if (e && e.domEvent)
-                event.stopEvent(e.domEvent);
-        }.bind(this);
-        setTimeout(stop, 10);
-        this.editor.on("nativecontextmenu", stop);
-    };
-
-}).call(Autocomplete.prototype);
-
-Autocomplete.startCommand = {
-    name: "startAutocomplete",
-    exec: function(editor) {
-        if (!editor.completer)
-            editor.completer = new Autocomplete();
-        editor.completer.showPopup(editor);
-        // needed for firefox on mac
-        editor.completer.cancelContextMenu();
-    },
-    bindKey: "Ctrl-Space|Ctrl-Shift-Space|Alt-Space"
-};
-
-var FilteredList = function(array, filterText, mutateData) {
-    this.all = array;
-    this.filtered = array;
-    this.filterText = filterText || "";
-};
-(function(){
-    this.setFilter = function(str) {
-        if (str.length > this.filterText && str.lastIndexOf(this.filterText, 0) === 0)
-            var matches = this.filtered;
-        else
-            var matches = this.all;
-
-        this.filterText = str;
-        matches = this.filterCompletions(matches, this.filterText);
-        matches = matches.sort(function(a, b) {
-            return b.exactMatch - a.exactMatch || b.score - a.score;
-        });
-        
-        // make unique
-        var prev = null;
-        matches = matches.filter(function(item){
-            var caption = item.value || item.caption || item.snippet; 
-            if (caption === prev) return false;
-            prev = caption;
-            return true;
-        });
-        
-        this.filtered = matches;
-    };
-    this.filterCompletions = function(items, needle) {
-        var results = [];
-        var upper = needle.toUpperCase();
-        var lower = needle.toLowerCase();
-        loop: for (var i = 0, item; item = items[i]; i++) {
-            var caption = item.value || item.caption || item.snippet;
-            if (!caption) continue;
-            var lastIndex = -1;
-            var matchMask = 0;
-            var penalty = 0;
-            var index, distance;
-            // caption char iteration is faster in Chrome but slower in Firefox, so lets use indexOf
-            for (var j = 0; j < needle.length; j++) {
-                // TODO add penalty on case mismatch
-                var i1 = caption.indexOf(lower[j], lastIndex + 1);
-                var i2 = caption.indexOf(upper[j], lastIndex + 1);
-                index = (i1 >= 0) ? ((i2 < 0 || i1 < i2) ? i1 : i2) : i2;
-                if (index < 0)
-                    continue loop;
-                distance = index - lastIndex - 1;
-                if (distance > 0) {
-                    // first char mismatch should be more sensitive
-                    if (lastIndex === -1)
-                        penalty += 10;
-                    penalty += distance;
-                }
-                matchMask = matchMask | (1 << index);
-                lastIndex = index;
-            }
-            item.matchMask = matchMask;
-            item.exactMatch = penalty ? 0 : 1;
-            item.score = (item.score || 0) - penalty;
-            results.push(item);
-        }
-        return results;
-    };
-}).call(FilteredList.prototype);
-
-exports.Autocomplete = Autocomplete;
-exports.FilteredList = FilteredList;
-
-});

+ 0 - 332
services/web/public/js/ace/autocomplete/popup.js

@@ -1,332 +0,0 @@
-/* ***** 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 EditSession = require("../edit_session").EditSession;
-var Renderer = require("../virtual_renderer").VirtualRenderer;
-var Editor = require("../editor").Editor;
-var Range = require("../range").Range;
-var event = require("../lib/event");
-var lang = require("../lib/lang");
-var dom = require("../lib/dom");
-
-var $singleLineEditor = function(el) {
-    var renderer = new Renderer(el);
-
-    renderer.$maxLines = 4;
-    
-    var editor = new Editor(renderer);
-
-    editor.setHighlightActiveLine(false);
-    editor.setShowPrintMargin(false);
-    editor.renderer.setShowGutter(false);
-    editor.renderer.setHighlightGutterLine(false);
-
-    editor.$mouseHandler.$focusWaitTimout = 0;
-
-    return editor;
-};
-
-var AcePopup = function(parentNode) {
-    var el = dom.createElement("div");
-    var popup = new $singleLineEditor(el);
-    
-    if (parentNode)
-        parentNode.appendChild(el);
-    el.style.display = "none";
-    popup.renderer.content.style.cursor = "default";
-    popup.renderer.setStyle("ace_autocomplete");
-    
-    popup.setOption("displayIndentGuides", false);
-
-    var noop = function(){};
-
-    popup.focus = noop;
-    popup.$isFocused = true;
-
-    popup.renderer.$cursorLayer.restartTimer = noop;
-    popup.renderer.$cursorLayer.element.style.opacity = 0;
-
-    popup.renderer.$maxLines = 8;
-    popup.renderer.$keepTextAreaAtCursor = false;
-
-    popup.setHighlightActiveLine(false);
-    // set default highlight color
-    popup.session.highlight("");
-    popup.session.$searchHighlight.clazz = "ace_highlight-marker";
-
-    popup.on("mousedown", function(e) {
-        var pos = e.getDocumentPosition();
-        popup.moveCursorToPosition(pos);
-        popup.selection.clearSelection();
-        selectionMarker.start.row = selectionMarker.end.row = pos.row;
-        e.stop();
-    });
-
-    var lastMouseEvent;
-    var hoverMarker = new Range(-1,0,-1,Infinity);
-    var selectionMarker = new Range(-1,0,-1,Infinity);
-    selectionMarker.id = popup.session.addMarker(selectionMarker, "ace_active-line", "fullLine");
-    popup.setSelectOnHover = function(val) {
-        if (!val) {
-            hoverMarker.id = popup.session.addMarker(hoverMarker, "ace_line-hover", "fullLine");
-        } else if (hoverMarker.id) {
-            popup.session.removeMarker(hoverMarker.id);
-            hoverMarker.id = null;
-        }
-    }
-    popup.setSelectOnHover(false);
-    popup.on("mousemove", function(e) {
-        if (!lastMouseEvent) {
-            lastMouseEvent = e;
-            return;
-        }
-        if (lastMouseEvent.x == e.x && lastMouseEvent.y == e.y) {
-            return;
-        }
-        lastMouseEvent = e;
-        lastMouseEvent.scrollTop = popup.renderer.scrollTop;
-        var row = lastMouseEvent.getDocumentPosition().row;
-        if (hoverMarker.start.row != row) {
-            if (!hoverMarker.id)
-                popup.setRow(row);
-            setHoverMarker(row);
-        }
-    });
-    popup.renderer.on("beforeRender", function() {
-        if (lastMouseEvent && hoverMarker.start.row != -1) {
-            lastMouseEvent.$pos = null;
-            var row = lastMouseEvent.getDocumentPosition().row;
-            if (!hoverMarker.id)
-                popup.setRow(row);
-            setHoverMarker(row, true);
-        }
-    });
-    popup.renderer.on("afterRender", function() {
-        var row = popup.getRow();
-        var t = popup.renderer.$textLayer;
-        var selected = t.element.childNodes[row - t.config.firstRow];
-        if (selected == t.selectedNode)
-            return;
-        if (t.selectedNode)
-            dom.removeCssClass(t.selectedNode, "ace_selected");
-        t.selectedNode = selected;
-        if (selected)
-            dom.addCssClass(selected, "ace_selected");
-    });
-    var hideHoverMarker = function() { setHoverMarker(-1) };
-    var setHoverMarker = function(row, suppressRedraw) {
-        if (row !== hoverMarker.start.row) {
-            hoverMarker.start.row = hoverMarker.end.row = row;
-            if (!suppressRedraw)
-                popup.session._emit("changeBackMarker");
-            popup._emit("changeHoverMarker");
-        }
-    };
-    popup.getHoveredRow = function() {
-        return hoverMarker.start.row;
-    };
-    
-    event.addListener(popup.container, "mouseout", hideHoverMarker);
-    popup.on("hide", hideHoverMarker);
-    popup.on("changeSelection", hideHoverMarker);
-    
-    popup.session.doc.getLength = function() {
-        return popup.data.length;
-    };
-    popup.session.doc.getLine = function(i) {
-        var data = popup.data[i];
-        if (typeof data == "string")
-            return data;
-        return (data && data.value) || "";
-    };
-
-    var bgTokenizer = popup.session.bgTokenizer;
-    bgTokenizer.$tokenizeRow = function(i) {
-        var data = popup.data[i];
-        var tokens = [];
-        if (!data)
-            return tokens;
-        if (typeof data == "string")
-            data = {value: data};
-        if (!data.caption)
-            data.caption = data.value;
-
-        var last = -1;
-        var flag, c;
-        for (var i = 0; i < data.caption.length; i++) {
-            c = data.caption[i];
-            flag = data.matchMask & (1 << i) ? 1 : 0;
-            if (last !== flag) {
-                tokens.push({type: data.className || "" + ( flag ? "completion-highlight" : ""), value: c});
-                last = flag;
-            } else {
-                tokens[tokens.length - 1].value += c;
-            }
-        }
-
-        if (data.meta) {
-            var maxW = popup.renderer.$size.scrollerWidth / popup.renderer.layerConfig.characterWidth;
-            if (data.meta.length + data.caption.length < maxW - 2)
-                tokens.push({type: "rightAlignedText", value: data.meta});
-        }
-        return tokens;
-    };
-    bgTokenizer.$updateOnChange = noop;
-    bgTokenizer.start = noop;
-    
-    popup.session.$computeWidth = function() {
-        return this.screenWidth = 0;
-    }
-
-    // public
-    popup.isOpen = false;
-    popup.isTopdown = false;
-    
-    popup.data = [];
-    popup.setData = function(list) {
-        popup.data = list || [];
-        popup.setValue(lang.stringRepeat("\n", list.length), -1);
-        popup.setRow(0);
-    };
-    popup.getData = function(row) {
-        return popup.data[row];
-    };
-
-    popup.getRow = function() {
-        return selectionMarker.start.row;
-    };
-    popup.setRow = function(line) {
-        line = Math.max(-1, Math.min(this.data.length, line));
-        if (selectionMarker.start.row != line) {
-            popup.selection.clearSelection();
-            selectionMarker.start.row = selectionMarker.end.row = line || 0;
-            popup.session._emit("changeBackMarker");
-            popup.moveCursorTo(line || 0, 0);
-            if (popup.isOpen)
-                popup._signal("select");
-        }
-    };
-    
-    popup.on("changeSelection", function() {
-        if (popup.isOpen)
-            popup.setRow(popup.selection.lead.row);
-    });
-
-    popup.hide = function() {
-        this.container.style.display = "none";
-        this._signal("hide");
-        popup.isOpen = false;
-    };
-    popup.show = function(pos, lineHeight, topdownOnly) {
-        var el = this.container;
-        var screenHeight = window.innerHeight;
-        var screenWidth = window.innerWidth;
-        var renderer = this.renderer;
-        // var maxLines = Math.min(renderer.$maxLines, this.session.getLength());
-        var maxH = renderer.$maxLines * lineHeight * 1.4;
-        var top = pos.top + this.$borderSize;
-        if (top + maxH > screenHeight - lineHeight && !topdownOnly) {
-            el.style.top = "";
-            el.style.bottom = screenHeight - top + "px";
-            popup.isTopdown = false;
-        } else {
-            top += lineHeight;
-            el.style.top = top + "px";
-            el.style.bottom = "";
-            popup.isTopdown = true;
-        }
-
-        el.style.display = "";
-        this.renderer.$textLayer.checkForSizeChanges();
-        
-        var left = pos.left;
-        if (left + el.offsetWidth > screenWidth)
-            left = screenWidth - el.offsetWidth;
-            
-        el.style.left = left + "px";
-        
-        this._signal("show");
-        lastMouseEvent = null;
-        popup.isOpen = true;
-    };
-    
-    popup.getTextLeftOffset = function() {
-        return this.$borderSize + this.renderer.$padding + this.$imageSize;
-    };
-    
-    popup.$imageSize = 0;
-    popup.$borderSize = 1;
-
-    return popup;
-};
-
-dom.importCssString("\
-.ace_autocomplete.ace-tm .ace_marker-layer .ace_active-line {\
-    background-color: #CAD6FA;\
-    z-index: 1;\
-}\
-.ace_autocomplete.ace-tm .ace_line-hover {\
-    border: 1px solid #abbffe;\
-    margin-top: -1px;\
-    background: rgba(233,233,253,0.4);\
-}\
-.ace_autocomplete .ace_line-hover {\
-    position: absolute;\
-    z-index: 2;\
-}\
-.ace_rightAlignedText {\
-    color: gray;\
-    display: inline-block;\
-    position: absolute;\
-    right: 4px;\
-    text-align: right;\
-    z-index: -1;\
-}\
-.ace_autocomplete .ace_completion-highlight{\
-    color: #000;\
-    text-shadow: 0 0 0.01em;\
-}\
-.ace_autocomplete {\
-    width: 280px;\
-    z-index: 200000;\
-    background: #fbfbfb;\
-    color: #444;\
-    border: 1px lightgray solid;\
-    position: fixed;\
-    box-shadow: 2px 3px 5px rgba(0,0,0,.2);\
-    line-height: 1.4;\
-}");
-
-exports.AcePopup = AcePopup;
-
-});

+ 0 - 78
services/web/public/js/ace/autocomplete/text_completer.js

@@ -1,78 +0,0 @@
-/* ***** 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) {
-    var Range = require("ace/range").Range;
-    
-    var splitRegex = /[^a-zA-Z_0-9\$\-]+/;
-
-    function getWordIndex(doc, pos) {
-        var textBefore = doc.getTextRange(Range.fromPoints({row: 0, column:0}, pos));
-        return textBefore.split(splitRegex).length - 1;
-    }
-
-    /**
-     * Does a distance analysis of the word `prefix` at position `pos` in `doc`.
-     * @return Map
-     */
-    function wordDistance(doc, pos) {
-        var prefixPos = getWordIndex(doc, pos);
-        var words = doc.getValue().split(splitRegex);
-        var wordScores = Object.create(null);
-        
-        var currentWord = words[prefixPos];
-
-        words.forEach(function(word, idx) {
-            if (!word || word === currentWord) return;
-
-            var distance = Math.abs(prefixPos - idx);
-            var score = words.length - distance;
-            if (wordScores[word]) {
-                wordScores[word] = Math.max(score, wordScores[word]);
-            } else {
-                wordScores[word] = score;
-            }
-        });
-        return wordScores;
-    }
-
-    exports.getCompletions = function(editor, session, pos, prefix, callback) {
-        var wordScore = wordDistance(session, pos, prefix);
-        var wordList = Object.keys(wordScore);
-        callback(null, wordList.map(function(word) {
-            return {
-                name: word,
-                value: word,
-                score: wordScore[word],
-                meta: "local"
-            };
-        }));
-    };
-});

+ 0 - 74
services/web/public/js/ace/autocomplete/util.js

@@ -1,74 +0,0 @@
-/* ***** 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";
-
-exports.parForEach = function(array, fn, callback) {
-    var completed = 0;
-    var arLength = array.length;
-    if (arLength === 0)
-        callback();
-    for (var i = 0; i < arLength; i++) {
-        fn(array[i], function(result, err) {
-            completed++;
-            if (completed === arLength)
-                callback(result, err);
-        });
-    }
-}
-
-var ID_REGEX = /[a-zA-Z_0-9\$-]/;
-
-exports.retrievePrecedingIdentifier = function(text, pos, regex) {
-    regex = regex || ID_REGEX;
-    var buf = [];
-    for (var i = pos-1; i >= 0; i--) {
-        if (regex.test(text[i]))
-            buf.push(text[i]);
-        else
-            break;
-    }
-    return buf.reverse().join("");
-}
-
-exports.retrieveFollowingIdentifier = function(text, pos, regex) {
-    regex = regex || ID_REGEX;
-    var buf = [];
-    for (var i = pos; i < text.length; i++) {
-        if (regex.test(text[i]))
-            buf.push(text[i]);
-        else
-            break;
-    }
-    return buf;
-}
-
-});

+ 0 - 255
services/web/public/js/ace/background_tokenizer.js

@@ -1,255 +0,0 @@
-/* ***** 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 oop = require("./lib/oop");
-var EventEmitter = require("./lib/event_emitter").EventEmitter;
-
-
-/**
- * 
- *
- * Tokenizes the current [[Document `Document`]] in the background, and caches the tokenized rows for future use. 
- * 
- * If a certain row is changed, everything below that row is re-tokenized.
- *
- * @class BackgroundTokenizer
- **/
-
-/**
- * Creates a new `BackgroundTokenizer` object.
- * @param {Tokenizer} tokenizer The tokenizer to use
- * @param {Editor} editor The editor to associate with
- *
- * 
- * 
- * @constructor
- **/
-
-var BackgroundTokenizer = function(tokenizer, editor) {
-    this.running = false;
-    this.lines = [];
-    this.states = [];
-    this.currentLine = 0;
-    this.tokenizer = tokenizer;
-
-    var self = this;
-
-    this.$worker = function() {
-        if (!self.running) { return; }
-
-        var workerStart = new Date();
-        var currentLine = self.currentLine;
-        var endLine = -1;
-        var doc = self.doc;
-
-        while (self.lines[currentLine])
-            currentLine++;
-
-        var startLine = currentLine;
-
-        var len = doc.getLength();
-        var processedLines = 0;
-        self.running = false;
-        while (currentLine < len) {
-            self.$tokenizeRow(currentLine);
-            endLine = currentLine;
-            do {
-                currentLine++;
-            } while (self.lines[currentLine]);
-
-            // only check every 5 lines
-            processedLines ++;
-            if ((processedLines % 5 == 0) && (new Date() - workerStart) > 20) {                
-                self.running = setTimeout(self.$worker, 20);
-                self.currentLine = currentLine;
-                return;
-            }
-        }
-        self.currentLine = currentLine;
-        
-        if (startLine <= endLine)
-            self.fireUpdateEvent(startLine, endLine);
-    };
-};
-
-(function(){
-
-    oop.implement(this, EventEmitter);
-
-    /**
-     * Sets a new tokenizer for this object.
-     *
-     * @param {Tokenizer} tokenizer The new tokenizer to use
-     *
-     **/
-    this.setTokenizer = function(tokenizer) {
-        this.tokenizer = tokenizer;
-        this.lines = [];
-        this.states = [];
-
-        this.start(0);
-    };
-
-    /**
-     * Sets a new document to associate with this object.
-     * @param {Document} doc The new document to associate with
-     **/
-    this.setDocument = function(doc) {
-        this.doc = doc;
-        this.lines = [];
-        this.states = [];
-
-        this.stop();
-    };
-
-     /**
-     * Fires whenever the background tokeniziers between a range of rows are going to be updated.
-     * 
-     * @event update
-     * @param {Object} e An object containing two properties, `first` and `last`, which indicate the rows of the region being updated.
-     *
-     **/
-    /**
-     * Emits the `'update'` event. `firstRow` and `lastRow` are used to define the boundaries of the region to be updated.
-     * @param {Number} firstRow The starting row region
-     * @param {Number} lastRow The final row region
-     *
-     **/
-    this.fireUpdateEvent = function(firstRow, lastRow) {
-        var data = {
-            first: firstRow,
-            last: lastRow
-        };
-        this._emit("update", {data: data});
-    };
-
-    /**
-     * Starts tokenizing at the row indicated.
-     *
-     * @param {Number} startRow The row to start at
-     *
-     **/
-    this.start = function(startRow) {
-        this.currentLine = Math.min(startRow || 0, this.currentLine, this.doc.getLength());
-
-        // remove all cached items below this line
-        this.lines.splice(this.currentLine, this.lines.length);
-        this.states.splice(this.currentLine, this.states.length);
-
-        this.stop();
-        // pretty long delay to prevent the tokenizer from interfering with the user
-        this.running = setTimeout(this.$worker, 700);
-    };
-    
-    this.scheduleStart = function() {
-        if (!this.running)
-            this.running = setTimeout(this.$worker, 700);
-    }
-
-    this.$updateOnChange = function(delta) {
-        var range = delta.range;
-        var startRow = range.start.row;
-        var len = range.end.row - startRow;
-
-        if (len === 0) {
-            this.lines[startRow] = null;
-        } else if (delta.action == "removeText" || delta.action == "removeLines") {
-            this.lines.splice(startRow, len + 1, null);
-            this.states.splice(startRow, len + 1, null);
-        } else {
-            var args = Array(len + 1);
-            args.unshift(startRow, 1);
-            this.lines.splice.apply(this.lines, args);
-            this.states.splice.apply(this.states, args);
-        }
-
-        this.currentLine = Math.min(startRow, this.currentLine, this.doc.getLength());
-
-        this.stop();
-    };
-
-    /**
-     * Stops tokenizing.
-     *
-     **/
-    this.stop = function() {
-        if (this.running)
-            clearTimeout(this.running);
-        this.running = false;
-    };
-
-    /**
-     * Gives list of tokens of the row. (tokens are cached)
-     * 
-     * @param {Number} row The row to get tokens at
-     *
-     * 
-     *
-     **/
-    this.getTokens = function(row) {
-        return this.lines[row] || this.$tokenizeRow(row);
-    };
-
-    /**
-     * [Returns the state of tokenization at the end of a row.]{: #BackgroundTokenizer.getState}
-     *
-     * @param {Number} row The row to get state at
-     **/
-    this.getState = function(row) {
-        if (this.currentLine == row)
-            this.$tokenizeRow(row);
-        return this.states[row] || "start";
-    };
-
-    this.$tokenizeRow = function(row) {
-        var line = this.doc.getLine(row);
-        var state = this.states[row - 1];
-
-        var data = this.tokenizer.getLineTokens(line, state, row);
-
-        if (this.states[row] + "" !== data.state + "") {
-            this.states[row] = data.state;
-            this.lines[row + 1] = null;
-            if (this.currentLine > row + 1)
-                this.currentLine = row + 1;
-        } else if (this.currentLine == row) {
-            this.currentLine = row + 1;
-        }
-
-        return this.lines[row] = data.tokens;
-    };
-
-}).call(BackgroundTokenizer.prototype);
-
-exports.BackgroundTokenizer = BackgroundTokenizer;
-});

+ 0 - 85
services/web/public/js/ace/background_tokenizer_test.js

@@ -1,85 +0,0 @@
-/* ***** 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 EditSession = require("./edit_session").EditSession;
-var JavaScriptMode = require("./mode/javascript").Mode;
-var Range = require("./range").Range;
-var assert = require("./test/assertions");
-
-function forceTokenize(session){
-    for (var i = 0, l = session.getLength(); i < l; i++)
-        session.getTokens(i)
-}
-
-function testStates(session, states) {
-    for (var i = 0, l = session.getLength(); i < l; i++)
-        assert.equal(session.bgTokenizer.states[i], states[i])
-    assert.ok(l == states.length)
-}
-
-module.exports = {
-
-    "test background tokenizer update on session change" : function() {
-        var doc = new EditSession([
-            "/*",
-            "*/",
-            "var juhu"
-        ]);
-        doc.setMode("./mode/javascript")  
-        
-        forceTokenize(doc)
-        testStates(doc, ["comment_regex_allowed", "start", "no_regex"])
-        
-        doc.remove(new Range(0,2,1,2))
-        testStates(doc, [null, "no_regex"])
-        
-        forceTokenize(doc)
-        testStates(doc, ["comment_regex_allowed", "comment_regex_allowed"])
-        
-        doc.insert({row:0, column:2}, "\n*/")
-        testStates(doc, [undefined, undefined, "comment_regex_allowed"])
-        
-        forceTokenize(doc)
-        testStates(doc, ["comment_regex_allowed", "start", "no_regex"])
-    }
-};
-
-});
-
-if (typeof module !== "undefined" && module === require.main) {
-    require("asyncjs").test.testcase(module.exports).exec()
-}

+ 0 - 112
services/web/public/js/ace/commands/command_manager.js

@@ -1,112 +0,0 @@
-define(function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var HashHandler = require("../keyboard/hash_handler").HashHandler;
-var EventEmitter = require("../lib/event_emitter").EventEmitter;
-
-/**
- * @class CommandManager
- *
- *
- **/
-
-/**
- * new CommandManager(platform, commands)
- * @param {String} platform Identifier for the platform; must be either `'mac'` or `'win'`
- * @param {Array} commands A list of commands
- *
- **/
-
-var CommandManager = function(platform, commands) {
-    HashHandler.call(this, commands, platform);
-    this.byName = this.commands;
-    this.setDefaultHandler("exec", function(e) {
-        return e.command.exec(e.editor, e.args || {});
-    });
-};
-
-oop.inherits(CommandManager, HashHandler);
-
-(function() {
-
-    oop.implement(this, EventEmitter);
-
-    this.exec = function(command, editor, args) {
-        if (typeof command === 'string')
-            command = this.commands[command];
-
-        if (!command)
-            return false;
-
-        if (editor && editor.$readOnly && !command.readOnly)
-            return false;
-
-        var e = {editor: editor, command: command, args: args};
-        var retvalue = this._emit("exec", e);
-        this._signal("afterExec", e);
-
-        return retvalue === false ? false : true;
-    };
-
-    this.toggleRecording = function(editor) {
-        if (this.$inReplay)
-            return;
-
-        editor && editor._emit("changeStatus");
-        if (this.recording) {
-            this.macro.pop();
-            this.removeEventListener("exec", this.$addCommandToMacro);
-
-            if (!this.macro.length)
-                this.macro = this.oldMacro;
-
-            return this.recording = false;
-        }
-        if (!this.$addCommandToMacro) {
-            this.$addCommandToMacro = function(e) {
-                this.macro.push([e.command, e.args]);
-            }.bind(this);
-        }
-
-        this.oldMacro = this.macro;
-        this.macro = [];
-        this.on("exec", this.$addCommandToMacro);
-        return this.recording = true;
-    };
-
-    this.replay = function(editor) {
-        if (this.$inReplay || !this.macro)
-            return;
-
-        if (this.recording)
-            return this.toggleRecording(editor);
-
-        try {
-            this.$inReplay = true;
-            this.macro.forEach(function(x) {
-                if (typeof x == "string")
-                    this.exec(x, editor);
-                else
-                    this.exec(x[0], editor, x[1]);
-            }, this);
-        } finally {
-            this.$inReplay = false;
-        }
-    };
-
-    this.trimMacro = function(m) {
-        return m.map(function(x){
-            if (typeof x[0] != "string")
-                x[0] = x[0].name;
-            if (!x[1])
-                x = x[0];
-            return x;
-        });
-    };
-
-}).call(CommandManager.prototype);
-
-exports.CommandManager = CommandManager;
-
-});

+ 0 - 199
services/web/public/js/ace/commands/command_manager_test.js

@@ -1,199 +0,0 @@
-/* ***** 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 CommandManager = require("./command_manager").CommandManager;
-var keys = require("../lib/keys");
-var assert = require("../test/assertions");
-
-module.exports = {
-
-    setUp: function() {
-        this.command = {
-            name: "gotoline",
-            bindKey: {
-                mac: "Command-L",
-                win: "Ctrl-L"
-            },
-            called: false,
-            exec: function(editor) { this.called = true; }
-        };
-
-        this.cm = new CommandManager("mac", [this.command]);
-    },
-
-    "test: register command": function() {
-        this.cm.exec("gotoline");
-        assert.ok(this.command.called);
-    },
-
-    "test: mac hotkeys": function() {
-        var command = this.cm.findKeyCommand(keys.KEY_MODS.command, "l");
-        assert.equal(command, this.command);
-
-        var command = this.cm.findKeyCommand(keys.KEY_MODS.ctrl, "l");
-        assert.equal(command, undefined);
-    },
-
-    "test: win hotkeys": function() {
-        var cm = new CommandManager("win", [this.command]);
-
-        var command = cm.findKeyCommand(keys.KEY_MODS.command, "l");
-        assert.equal(command, undefined);
-
-        var command = cm.findKeyCommand(keys.KEY_MODS.ctrl, "l");
-        assert.equal(command, this.command);
-    },
-
-    "test: remove command by object": function() {
-        this.cm.removeCommand(this.command);
-
-        this.cm.exec("gotoline");
-        assert.ok(!this.command.called);
-
-        var command = this.cm.findKeyCommand(keys.KEY_MODS.command, "l");
-        assert.equal(command, null);
-    },
-
-    "test: remove command by name": function() {
-        this.cm.removeCommand("gotoline");
-
-        this.cm.exec("gotoline");
-        assert.ok(!this.command.called);
-
-        var command = this.cm.findKeyCommand(keys.KEY_MODS.command, "l");
-        assert.equal(command, null);
-    },
-
-    "test: adding a new command with the same name as an existing one should remove the old one first": function() {
-        var command = {
-            name: "gotoline",
-            bindKey: {
-                mac: "Command-L",
-                win: "Ctrl-L"
-            },
-            called: false,
-            exec: function(editor) { this.called = true; }
-        };
-        this.cm.addCommand(command);
-
-        this.cm.exec("gotoline");
-        assert.ok(command.called);
-        assert.ok(!this.command.called);
-
-        assert.equal(this.cm.findKeyCommand(keys.KEY_MODS.command, "l"), command);
-    },
-
-    "test: adding commands and recording a macro": function() {
-        var called = "";
-        this.cm.addCommands({
-            togglerecording: function(editor) {
-                editor.cm.toggleRecording(editor);
-            },
-            replay: function(editor) {
-                editor.cm.replay();
-            },
-            cm1: function(editor, arg) {
-                called += "1" + (arg || "");
-            },
-            cm2: function(editor) {
-                called += "2";
-            }
-        });
-        
-        
-        var statusUpdateEmitted = false;
-        this._emit = function() {statusUpdateEmitted = true};
-
-        this.cm.exec("togglerecording", this);
-        assert.ok(this.cm.recording);
-        assert.ok(statusUpdateEmitted);
-
-        this.cm.exec("cm1", this, "-");
-        this.cm.exec("cm2");
-        this.cm.exec("replay", this);
-        assert.ok(!this.cm.recording);
-        assert.equal(called, "1-2");
-
-        called = "";
-        this.cm.exec("replay", this);
-        assert.equal(called, "1-2");
-    },
-
-    "test: bindkeys": function() {
-        this.cm.bindKeys({
-            "Ctrl-L|Command-C": "cm1",
-            "Ctrl-R": "cm2"
-        });
-
-        var command = this.cm.findKeyCommand(keys.KEY_MODS.command, "c");
-        assert.equal(command, "cm1");
-
-        var command = this.cm.findKeyCommand(keys.KEY_MODS.ctrl, "r");
-        assert.equal(command, "cm2");
-
-        this.cm.bindKeys({
-            "Ctrl-R": null
-        });
-
-        var command = this.cm.findKeyCommand(keys.KEY_MODS.ctrl, "r");
-        assert.equal(command, null);
-    },
-
-    "test: binding keys without modifiers": function() {
-        this.cm.bindKeys({
-            "R": "cm1",
-            "Shift-r": "cm2",
-            "Return": "cm4",
-            "Enter": "cm3"
-        });
-
-        var command = this.cm.findKeyCommand(-1, "r");
-        assert.equal(command, "cm1");
-
-        var command = this.cm.findKeyCommand(-1, "R");
-        assert.equal(command, "cm2");
-
-        var command = this.cm.findKeyCommand(0, "return");
-        assert.equal(command, "cm3");
-    }
-};
-
-});
-
-if (typeof module !== "undefined" && module === require.main) {
-    require("asyncjs").test.testcase(module.exports).exec();
-}

+ 0 - 542
services/web/public/js/ace/commands/default_commands.js

@@ -1,542 +0,0 @@
-/* ***** 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 lang = require("../lib/lang");
-var config = require("../config");
-
-function bindKey(win, mac) {
-    return {win: win, mac: mac};
-}
-
-/*
-    multiSelectAction: "forEach"|"forEachLine"|function|undefined,
-    scrollIntoView: true|"cursor"|"center"|"selectionPart"
-*/
-exports.commands = [{
-    name: "showSettingsMenu",
-    bindKey: bindKey("Ctrl-,", "Command-,"),
-    exec: function(editor) {
-        config.loadModule("ace/ext/settings_menu", function(module) {
-            module.init(editor);
-            editor.showSettingsMenu();
-        });
-    },
-    readOnly: true
-}, {
-    name: "selectall",
-    bindKey: bindKey("Ctrl-A", "Command-A"),
-    exec: function(editor) { editor.selectAll(); },
-    readOnly: true
-}, {
-    name: "centerselection",
-    bindKey: bindKey(null, "Ctrl-L"),
-    exec: function(editor) { editor.centerSelection(); },
-    readOnly: true
-}, {
-    name: "gotoline",
-    bindKey: bindKey("Ctrl-L", "Command-L"),
-    exec: function(editor) {
-        var line = parseInt(prompt("Enter line number:"), 10);
-        if (!isNaN(line)) {
-            editor.gotoLine(line);
-        }
-    },
-    readOnly: true
-}, {
-    name: "fold",
-    bindKey: bindKey("Alt-L|Ctrl-F1", "Command-Alt-L|Command-F1"),
-    exec: function(editor) { editor.session.toggleFold(false); },
-    scrollIntoView: "center",
-    readOnly: true
-}, {
-    name: "unfold",
-    bindKey: bindKey("Alt-Shift-L|Ctrl-Shift-F1", "Command-Alt-Shift-L|Command-Shift-F1"),
-    exec: function(editor) { editor.session.toggleFold(true); },
-    scrollIntoView: "center",
-    readOnly: true
-}, {
-    name: "toggleFoldWidget",
-    bindKey: bindKey("F2", "F2"),
-    exec: function(editor) { editor.session.toggleFoldWidget(); },
-    scrollIntoView: "center",
-    readOnly: true
-}, {
-    name: "toggleParentFoldWidget",
-    bindKey: bindKey("Alt-F2", "Alt-F2"),
-    exec: function(editor) { editor.session.toggleFoldWidget(true); },
-    scrollIntoView: "center",
-    readOnly: true
-}, {
-    name: "foldall",
-    bindKey: bindKey("Ctrl-Alt-0", "Ctrl-Command-Option-0"),
-    exec: function(editor) { editor.session.foldAll(); },
-    scrollIntoView: "center",
-    readOnly: true
-}, {
-    name: "foldOther",
-    bindKey: bindKey("Alt-0", "Command-Option-0"),
-    exec: function(editor) { 
-        editor.session.foldAll();
-        editor.session.unfold(editor.selection.getAllRanges());
-    },
-    scrollIntoView: "center",
-    readOnly: true
-}, {
-    name: "unfoldall",
-    bindKey: bindKey("Alt-Shift-0", "Command-Option-Shift-0"),
-    exec: function(editor) { editor.session.unfold(); },
-    scrollIntoView: "center",
-    readOnly: true
-}, {
-    name: "findnext",
-    bindKey: bindKey("Ctrl-K", "Command-G"),
-    exec: function(editor) { editor.findNext(); },
-    readOnly: true
-}, {
-    name: "findprevious",
-    bindKey: bindKey("Ctrl-Shift-K", "Command-Shift-G"),
-    exec: function(editor) { editor.findPrevious(); },
-    readOnly: true
-}, {
-    name: "selectOrFindNext",
-    bindKey: bindKey("ALt-K", "Ctrl-G"),
-    exec: function(editor) {
-        if (editor.selection.isEmpty())
-            editor.selection.selectWord();
-        else
-            editor.findNext(); 
-    },
-    readOnly: true
-}, {
-    name: "selectOrFindPrevious",
-    bindKey: bindKey("Alt-Shift-K", "Ctrl-Shift-G"),
-    exec: function(editor) { 
-        if (editor.selection.isEmpty())
-            editor.selection.selectWord();
-        else
-            editor.findPrevious();
-    },
-    readOnly: true
-}, {
-    name: "find",
-    bindKey: bindKey("Ctrl-F", "Command-F"),
-    exec: function(editor) {
-        config.loadModule("ace/ext/searchbox", function(e) {e.Search(editor)});
-    },
-    readOnly: true
-}, {
-    name: "overwrite",
-    bindKey: "Insert",
-    exec: function(editor) { editor.toggleOverwrite(); },
-    readOnly: true
-}, {
-    name: "selecttostart",
-    bindKey: bindKey("Ctrl-Shift-Home", "Command-Shift-Up"),
-    exec: function(editor) { editor.getSelection().selectFileStart(); },
-    multiSelectAction: "forEach",
-    readOnly: true,
-    aceCommandGroup: "fileJump"
-}, {
-    name: "gotostart",
-    bindKey: bindKey("Ctrl-Home", "Command-Home|Command-Up"),
-    exec: function(editor) { editor.navigateFileStart(); },
-    multiSelectAction: "forEach",
-    readOnly: true,
-    aceCommandGroup: "fileJump"
-}, {
-    name: "selectup",
-    bindKey: bindKey("Shift-Up", "Shift-Up"),
-    exec: function(editor) { editor.getSelection().selectUp(); },
-    multiSelectAction: "forEach",
-    readOnly: true
-}, {
-    name: "golineup",
-    bindKey: bindKey("Up", "Up|Ctrl-P"),
-    exec: function(editor, args) { editor.navigateUp(args.times); },
-    multiSelectAction: "forEach",
-    readOnly: true
-}, {
-    name: "selecttoend",
-    bindKey: bindKey("Ctrl-Shift-End", "Command-Shift-Down"),
-    exec: function(editor) { editor.getSelection().selectFileEnd(); },
-    multiSelectAction: "forEach",
-    readOnly: true,
-    aceCommandGroup: "fileJump"
-}, {
-    name: "gotoend",
-    bindKey: bindKey("Ctrl-End", "Command-End|Command-Down"),
-    exec: function(editor) { editor.navigateFileEnd(); },
-    multiSelectAction: "forEach",
-    readOnly: true,
-    aceCommandGroup: "fileJump"
-}, {
-    name: "selectdown",
-    bindKey: bindKey("Shift-Down", "Shift-Down"),
-    exec: function(editor) { editor.getSelection().selectDown(); },
-    multiSelectAction: "forEach",
-    readOnly: true
-}, {
-    name: "golinedown",
-    bindKey: bindKey("Down", "Down|Ctrl-N"),
-    exec: function(editor, args) { editor.navigateDown(args.times); },
-    multiSelectAction: "forEach",
-    readOnly: true
-}, {
-    name: "selectwordleft",
-    bindKey: bindKey("Ctrl-Shift-Left", "Option-Shift-Left"),
-    exec: function(editor) { editor.getSelection().selectWordLeft(); },
-    multiSelectAction: "forEach",
-    readOnly: true
-}, {
-    name: "gotowordleft",
-    bindKey: bindKey("Ctrl-Left", "Option-Left"),
-    exec: function(editor) { editor.navigateWordLeft(); },
-    multiSelectAction: "forEach",
-    readOnly: true
-}, {
-    name: "selecttolinestart",
-    bindKey: bindKey("Alt-Shift-Left", "Command-Shift-Left"),
-    exec: function(editor) { editor.getSelection().selectLineStart(); },
-    multiSelectAction: "forEach",
-    readOnly: true
-}, {
-    name: "gotolinestart",
-    bindKey: bindKey("Alt-Left|Home", "Command-Left|Home|Ctrl-A"),
-    exec: function(editor) { editor.navigateLineStart(); },
-    multiSelectAction: "forEach",
-    readOnly: true
-}, {
-    name: "selectleft",
-    bindKey: bindKey("Shift-Left", "Shift-Left"),
-    exec: function(editor) { editor.getSelection().selectLeft(); },
-    multiSelectAction: "forEach",
-    readOnly: true
-}, {
-    name: "gotoleft",
-    bindKey: bindKey("Left", "Left|Ctrl-B"),
-    exec: function(editor, args) { editor.navigateLeft(args.times); },
-    multiSelectAction: "forEach",
-    readOnly: true
-}, {
-    name: "selectwordright",
-    bindKey: bindKey("Ctrl-Shift-Right", "Option-Shift-Right"),
-    exec: function(editor) { editor.getSelection().selectWordRight(); },
-    multiSelectAction: "forEach",
-    readOnly: true
-}, {
-    name: "gotowordright",
-    bindKey: bindKey("Ctrl-Right", "Option-Right"),
-    exec: function(editor) { editor.navigateWordRight(); },
-    multiSelectAction: "forEach",
-    readOnly: true
-}, {
-    name: "selecttolineend",
-    bindKey: bindKey("Alt-Shift-Right", "Command-Shift-Right"),
-    exec: function(editor) { editor.getSelection().selectLineEnd(); },
-    multiSelectAction: "forEach",
-    readOnly: true
-}, {
-    name: "gotolineend",
-    bindKey: bindKey("Alt-Right|End", "Command-Right|End|Ctrl-E"),
-    exec: function(editor) { editor.navigateLineEnd(); },
-    multiSelectAction: "forEach",
-    readOnly: true
-}, {
-    name: "selectright",
-    bindKey: bindKey("Shift-Right", "Shift-Right"),
-    exec: function(editor) { editor.getSelection().selectRight(); },
-    multiSelectAction: "forEach",
-    readOnly: true
-}, {
-    name: "gotoright",
-    bindKey: bindKey("Right", "Right|Ctrl-F"),
-    exec: function(editor, args) { editor.navigateRight(args.times); },
-    multiSelectAction: "forEach",
-    readOnly: true
-}, {
-    name: "selectpagedown",
-    bindKey: "Shift-PageDown",
-    exec: function(editor) { editor.selectPageDown(); },
-    readOnly: true
-}, {
-    name: "pagedown",
-    bindKey: bindKey(null, "Option-PageDown"),
-    exec: function(editor) { editor.scrollPageDown(); },
-    readOnly: true
-}, {
-    name: "gotopagedown",
-    bindKey: bindKey("PageDown", "PageDown|Ctrl-V"),
-    exec: function(editor) { editor.gotoPageDown(); },
-    readOnly: true
-}, {
-    name: "selectpageup",
-    bindKey: "Shift-PageUp",
-    exec: function(editor) { editor.selectPageUp(); },
-    readOnly: true
-}, {
-    name: "pageup",
-    bindKey: bindKey(null, "Option-PageUp"),
-    exec: function(editor) { editor.scrollPageUp(); },
-    readOnly: true
-}, {
-    name: "gotopageup",
-    bindKey: "PageUp",
-    exec: function(editor) { editor.gotoPageUp(); },
-    readOnly: true
-}, {
-    name: "scrollup",
-    bindKey: bindKey("Ctrl-Up", null),
-    exec: function(e) { e.renderer.scrollBy(0, -2 * e.renderer.layerConfig.lineHeight); },
-    readOnly: true
-}, {
-    name: "scrolldown",
-    bindKey: bindKey("Ctrl-Down", null),
-    exec: function(e) { e.renderer.scrollBy(0, 2 * e.renderer.layerConfig.lineHeight); },
-    readOnly: true
-}, {
-    name: "selectlinestart",
-    bindKey: "Shift-Home",
-    exec: function(editor) { editor.getSelection().selectLineStart(); },
-    multiSelectAction: "forEach",
-    readOnly: true
-}, {
-    name: "selectlineend",
-    bindKey: "Shift-End",
-    exec: function(editor) { editor.getSelection().selectLineEnd(); },
-    multiSelectAction: "forEach",
-    readOnly: true
-}, {
-    name: "togglerecording",
-    bindKey: bindKey("Ctrl-Alt-E", "Command-Option-E"),
-    exec: function(editor) { editor.commands.toggleRecording(editor); },
-    readOnly: true
-}, {
-    name: "replaymacro",
-    bindKey: bindKey("Ctrl-Shift-E", "Command-Shift-E"),
-    exec: function(editor) { editor.commands.replay(editor); },
-    readOnly: true
-}, {
-    name: "jumptomatching",
-    bindKey: bindKey("Ctrl-P", "Ctrl-Shift-P"),
-    exec: function(editor) { editor.jumpToMatching(); },
-    multiSelectAction: "forEach",
-    readOnly: true
-}, {
-    name: "selecttomatching",
-    bindKey: bindKey("Ctrl-Shift-P", null),
-    exec: function(editor) { editor.jumpToMatching(true); },
-    multiSelectAction: "forEach",
-    readOnly: true
-}, 
-
-// commands disabled in readOnly mode
-{
-    name: "cut",
-    exec: function(editor) {
-        var range = editor.getSelectionRange();
-        editor._emit("cut", range);
-
-        if (!editor.selection.isEmpty()) {
-            editor.session.remove(range);
-            editor.clearSelection();
-        }
-    },
-    multiSelectAction: "forEach"
-}, {
-    name: "removeline",
-    bindKey: bindKey("Ctrl-D", "Command-D"),
-    exec: function(editor) { editor.removeLines(); },
-    multiSelectAction: "forEachLine"
-}, {
-    name: "duplicateSelection",
-    bindKey: bindKey("Ctrl-Shift-D", "Command-Shift-D"),
-    exec: function(editor) { editor.duplicateSelection(); },
-    multiSelectAction: "forEach"
-}, {
-    name: "sortlines",
-    bindKey: bindKey("Ctrl-Alt-S", "Command-Alt-S"),
-    exec: function(editor) { editor.sortLines(); },
-    multiSelectAction: "forEachLine"
-}, {
-    name: "togglecomment",
-    bindKey: bindKey("Ctrl-/", "Command-/"),
-    exec: function(editor) { editor.toggleCommentLines(); },
-    multiSelectAction: "forEachLine",
-    scrollIntoView: "selectionPart"
-}, {
-    name: "toggleBlockComment",
-    bindKey: bindKey("Ctrl-Shift-/", "Command-Shift-/"),
-    exec: function(editor) { editor.toggleBlockComment(); },
-    multiSelectAction: "forEach"
-}, {
-    name: "modifyNumberUp",
-    bindKey: bindKey("Ctrl-Shift-Up", "Alt-Shift-Up"),
-    exec: function(editor) { editor.modifyNumber(1); },
-    multiSelectAction: "forEach"
-}, {
-    name: "modifyNumberDown",
-    bindKey: bindKey("Ctrl-Shift-Down", "Alt-Shift-Down"),
-    exec: function(editor) { editor.modifyNumber(-1); },
-    multiSelectAction: "forEach"
-}, {
-    name: "replace",
-    bindKey: bindKey("Ctrl-H", "Command-Option-F"),
-    exec: function(editor) {
-        config.loadModule("ace/ext/searchbox", function(e) {e.Search(editor, true)});
-    }
-}, {
-    name: "undo",
-    bindKey: bindKey("Ctrl-Z", "Command-Z"),
-    exec: function(editor) { editor.undo(); }
-}, {
-    name: "redo",
-    bindKey: bindKey("Ctrl-Shift-Z|Ctrl-Y", "Command-Shift-Z|Command-Y"),
-    exec: function(editor) { editor.redo(); }
-}, {
-    name: "copylinesup",
-    bindKey: bindKey("Alt-Shift-Up", "Command-Option-Up"),
-    exec: function(editor) { editor.copyLinesUp(); }
-}, {
-    name: "movelinesup",
-    bindKey: bindKey("Alt-Up", "Option-Up"),
-    exec: function(editor) { editor.moveLinesUp(); }
-}, {
-    name: "copylinesdown",
-    bindKey: bindKey("Alt-Shift-Down", "Command-Option-Down"),
-    exec: function(editor) { editor.copyLinesDown(); }
-}, {
-    name: "movelinesdown",
-    bindKey: bindKey("Alt-Down", "Option-Down"),
-    exec: function(editor) { editor.moveLinesDown(); }
-}, {
-    name: "del",
-    bindKey: bindKey("Delete", "Delete|Ctrl-D|Shift-Delete"),
-    exec: function(editor) { editor.remove("right"); },
-    multiSelectAction: "forEach"
-}, {
-    name: "backspace",
-    bindKey: bindKey(
-        "Shift-Backspace|Backspace",
-        "Ctrl-Backspace|Shift-Backspace|Backspace|Ctrl-H"
-    ),
-    exec: function(editor) { editor.remove("left"); },
-    multiSelectAction: "forEach"
-}, {
-    name: "cut_or_delete",
-    bindKey: bindKey("Shift-Delete", null),
-    exec: function(editor) { 
-        if (editor.selection.isEmpty()) {
-            editor.remove("left");
-        } else {
-            return false;
-        }
-    },
-    multiSelectAction: "forEach"
-}, {
-    name: "removetolinestart",
-    bindKey: bindKey("Alt-Backspace", "Command-Backspace"),
-    exec: function(editor) { editor.removeToLineStart(); },
-    multiSelectAction: "forEach"
-}, {
-    name: "removetolineend",
-    bindKey: bindKey("Alt-Delete", "Ctrl-K"),
-    exec: function(editor) { editor.removeToLineEnd(); },
-    multiSelectAction: "forEach"
-}, {
-    name: "removewordleft",
-    bindKey: bindKey("Ctrl-Backspace", "Alt-Backspace|Ctrl-Alt-Backspace"),
-    exec: function(editor) { editor.removeWordLeft(); },
-    multiSelectAction: "forEach"
-}, {
-    name: "removewordright",
-    bindKey: bindKey("Ctrl-Delete", "Alt-Delete"),
-    exec: function(editor) { editor.removeWordRight(); },
-    multiSelectAction: "forEach"
-}, {
-    name: "outdent",
-    bindKey: bindKey("Shift-Tab", "Shift-Tab"),
-    exec: function(editor) { editor.blockOutdent(); },
-    multiSelectAction: "forEach",
-    scrollIntoView: "selectionPart"
-}, {
-    name: "indent",
-    bindKey: bindKey("Tab", "Tab"),
-    exec: function(editor) { editor.indent(); },
-    multiSelectAction: "forEach",
-    scrollIntoView: "selectionPart"
-}, {
-    name: "blockoutdent",
-    bindKey: bindKey("Ctrl-[", "Ctrl-["),
-    exec: function(editor) { editor.blockOutdent(); },
-    multiSelectAction: "forEachLine",
-    scrollIntoView: "selectionPart"
-}, {
-    name: "blockindent",
-    bindKey: bindKey("Ctrl-]", "Ctrl-]"),
-    exec: function(editor) { editor.blockIndent(); },
-    multiSelectAction: "forEachLine",
-    scrollIntoView: "selectionPart"
-}, {
-    name: "insertstring",
-    exec: function(editor, str) { editor.insert(str); },
-    multiSelectAction: "forEach",
-    scrollIntoView: "cursor"
-}, {
-    name: "inserttext",
-    exec: function(editor, args) {
-        editor.insert(lang.stringRepeat(args.text  || "", args.times || 1));
-    },
-    multiSelectAction: "forEach"
-}, {
-    name: "splitline",
-    bindKey: bindKey(null, "Ctrl-O"),
-    exec: function(editor) { editor.splitLine(); },
-    multiSelectAction: "forEach"
-}, {
-    name: "transposeletters",
-    bindKey: bindKey("Ctrl-T", "Ctrl-T"),
-    exec: function(editor) { editor.transposeLetters(); },
-    multiSelectAction: function(editor) {editor.transposeSelections(1); }
-}, {
-    name: "touppercase",
-    bindKey: bindKey("Ctrl-U", "Ctrl-U"),
-    exec: function(editor) { editor.toUpperCase(); },
-    multiSelectAction: "forEach"
-}, {
-    name: "tolowercase",
-    bindKey: bindKey("Ctrl-Shift-U", "Ctrl-Shift-U"),
-    exec: function(editor) { editor.toLowerCase(); },
-    multiSelectAction: "forEach"
-}];
-
-});

+ 0 - 180
services/web/public/js/ace/commands/incremental_search_commands.js

@@ -1,180 +0,0 @@
-/* ***** 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) {
-
-var config = require("../config");
-var oop = require("../lib/oop");
-var HashHandler = require("../keyboard/hash_handler").HashHandler;
-var occurStartCommand = require("./occur_commands").occurStartCommand;
-
-// These commands can be installed in a normal key handler to start iSearch:
-exports.iSearchStartCommands = [{
-    name: "iSearch",
-    bindKey: {win: "Ctrl-F", mac: "Command-F"},
-    exec: function(editor, options) {
-        config.loadModule(["core", "ace/incremental_search"], function(e) {
-            var iSearch = e.iSearch = e.iSearch || new e.IncrementalSearch();
-            iSearch.activate(editor, options.backwards);
-            if (options.jumpToFirstMatch) iSearch.next(options);
-        });
-    },
-    readOnly: true
-}, {
-    name: "iSearchBackwards",
-    exec: function(editor, jumpToNext) { editor.execCommand('iSearch', {backwards: true}); },
-    readOnly: true
-}, {
-    name: "iSearchAndGo",
-    bindKey: {win: "Ctrl-K", mac: "Command-G"},
-    exec: function(editor, jumpToNext) { editor.execCommand('iSearch', {jumpToFirstMatch: true, useCurrentOrPrevSearch: true}); },
-    readOnly: true
-}, {
-    name: "iSearchBackwardsAndGo",
-    bindKey: {win: "Ctrl-Shift-K", mac: "Command-Shift-G"},
-    exec: function(editor) { editor.execCommand('iSearch', {jumpToFirstMatch: true, backwards: true, useCurrentOrPrevSearch: true}); },
-    readOnly: true
-}];
-
-// These commands are only available when incremental search mode is active:
-exports.iSearchCommands = [{
-    name: "restartSearch",
-    bindKey: {win: "Ctrl-F", mac: "Command-F"},
-    exec: function(iSearch) {
-        iSearch.cancelSearch(true);
-    },
-    readOnly: true,
-    isIncrementalSearchCommand: true
-}, {
-    name: "searchForward",
-    bindKey: {win: "Ctrl-S|Ctrl-K", mac: "Ctrl-S|Command-G"},
-    exec: function(iSearch, options) {
-        options.useCurrentOrPrevSearch = true;
-        iSearch.next(options);
-    },
-    readOnly: true,
-    isIncrementalSearchCommand: true
-}, {
-    name: "searchBackward",
-    bindKey: {win: "Ctrl-R|Ctrl-Shift-K", mac: "Ctrl-R|Command-Shift-G"},
-    exec: function(iSearch, options) {
-        options.useCurrentOrPrevSearch = true;
-        options.backwards = true;
-        iSearch.next(options);
-    },
-    readOnly: true,
-    isIncrementalSearchCommand: true
-}, {
-    name: "extendSearchTerm",
-    exec: function(iSearch, string) {
-        iSearch.addChar(string);
-    },
-    readOnly: true,
-    isIncrementalSearchCommand: true
-}, {
-    name: "extendSearchTermSpace",
-    bindKey: "space",
-    exec: function(iSearch) { iSearch.addChar(' '); },
-    readOnly: true,
-    isIncrementalSearchCommand: true
-}, {
-    name: "shrinkSearchTerm",
-    bindKey: "backspace",
-    exec: function(iSearch) {
-        iSearch.removeChar();
-    },
-    readOnly: true,
-    isIncrementalSearchCommand: true
-}, {
-    name: 'confirmSearch',
-    bindKey: 'return',
-    exec: function(iSearch) { iSearch.deactivate(); },
-    readOnly: true,
-    isIncrementalSearchCommand: true
-}, {
-    name: 'cancelSearch',
-    bindKey: 'esc|Ctrl-G',
-    exec: function(iSearch) { iSearch.deactivate(true); },
-    readOnly: true,
-    isIncrementalSearchCommand: true
-}, {
-    name: 'occurisearch',
-    bindKey: 'Ctrl-O',
-    exec: function(iSearch) {
-        var options = oop.mixin({}, iSearch.$options);
-        iSearch.deactivate();
-        occurStartCommand.exec(iSearch.$editor, options);
-    },
-    readOnly: true,
-    isIncrementalSearchCommand: true
-}];
-
-function IncrementalSearchKeyboardHandler(iSearch) {
-    this.$iSearch = iSearch;
-}
-
-oop.inherits(IncrementalSearchKeyboardHandler, HashHandler);
-
-;(function() {
-
-    this.attach = function(editor) {
-        var iSearch = this.$iSearch;
-        HashHandler.call(this, exports.iSearchCommands, editor.commands.platform);
-        this.$commandExecHandler = editor.commands.addEventListener('exec', function(e) {
-            if (!e.command.isIncrementalSearchCommand) return undefined;
-            e.stopPropagation();
-            e.preventDefault();
-            return e.command.exec(iSearch, e.args || {});
-        });
-    }
-
-    this.detach = function(editor) {
-        if (!this.$commandExecHandler) return;
-        editor.commands.removeEventListener('exec', this.$commandExecHandler);
-        delete this.$commandExecHandler;
-    }
-
-    var handleKeyboard$super = this.handleKeyboard;
-    this.handleKeyboard = function(data, hashId, key, keyCode) {
-        var cmd = handleKeyboard$super.call(this, data, hashId, key, keyCode);
-        if (cmd.command) { return cmd; }
-        if (hashId == -1) {
-            var extendCmd = this.commands.extendSearchTerm;
-            if (extendCmd) { return {command: extendCmd, args: key}; }
-        }
-        return {command: "null", passEvent: hashId == 0 || hashId == 4};
-    }
-
-}).call(IncrementalSearchKeyboardHandler.prototype);
-
-
-exports.IncrementalSearchKeyboardHandler = IncrementalSearchKeyboardHandler;
-
-});

+ 0 - 97
services/web/public/js/ace/commands/multi_select_commands.js

@@ -1,97 +0,0 @@
-/* ***** 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) {
-
-// commands to enter multiselect mode
-exports.defaultCommands = [{
-    name: "addCursorAbove",
-    exec: function(editor) { editor.selectMoreLines(-1); },
-    bindKey: {win: "Ctrl-Alt-Up", mac: "Ctrl-Alt-Up"},
-    readonly: true
-}, {
-    name: "addCursorBelow",
-    exec: function(editor) { editor.selectMoreLines(1); },
-    bindKey: {win: "Ctrl-Alt-Down", mac: "Ctrl-Alt-Down"},
-    readonly: true
-}, {
-    name: "addCursorAboveSkipCurrent",
-    exec: function(editor) { editor.selectMoreLines(-1, true); },
-    bindKey: {win: "Ctrl-Alt-Shift-Up", mac: "Ctrl-Alt-Shift-Up"},
-    readonly: true
-}, {
-    name: "addCursorBelowSkipCurrent",
-    exec: function(editor) { editor.selectMoreLines(1, true); },
-    bindKey: {win: "Ctrl-Alt-Shift-Down", mac: "Ctrl-Alt-Shift-Down"},
-    readonly: true
-}, {
-    name: "selectMoreBefore",
-    exec: function(editor) { editor.selectMore(-1); },
-    bindKey: {win: "Ctrl-Alt-Left", mac: "Ctrl-Alt-Left"},
-    readonly: true
-}, {
-    name: "selectMoreAfter",
-    exec: function(editor) { editor.selectMore(1); },
-    bindKey: {win: "Ctrl-Alt-Right", mac: "Ctrl-Alt-Right"},
-    readonly: true
-}, {
-    name: "selectNextBefore",
-    exec: function(editor) { editor.selectMore(-1, true); },
-    bindKey: {win: "Ctrl-Alt-Shift-Left", mac: "Ctrl-Alt-Shift-Left"},
-    readonly: true
-}, {
-    name: "selectNextAfter",
-    exec: function(editor) { editor.selectMore(1, true); },
-    bindKey: {win: "Ctrl-Alt-Shift-Right", mac: "Ctrl-Alt-Shift-Right"},
-    readonly: true
-}, {
-    name: "splitIntoLines",
-    exec: function(editor) { editor.multiSelect.splitIntoLines(); },
-    bindKey: {win: "Ctrl-Alt-L", mac: "Ctrl-Alt-L"},
-    readonly: true
-}, {
-    name: "alignCursors",
-    exec: function(editor) { editor.alignCursors(); },
-    bindKey: {win: "Ctrl-Alt-A", mac: "Ctrl-Alt-A"}
-}];
-
-// commands active only in multiselect mode
-exports.multiSelectCommands = [{
-    name: "singleSelection",
-    bindKey: "esc",
-    exec: function(editor) { editor.exitMultiSelectMode(); },
-    readonly: true,
-    isAvailable: function(editor) {return editor && editor.inMultiSelectMode}
-}];
-
-var HashHandler = require("../keyboard/hash_handler").HashHandler;
-exports.keyboardHandler = new HashHandler(exports.multiSelectCommands);
-
-});

+ 0 - 110
services/web/public/js/ace/commands/occur_commands.js

@@ -1,110 +0,0 @@
-/* ***** 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) {
-
-var config = require("../config"),
-    Occur = require("../occur").Occur;
-
-// These commands can be installed in a normal command handler to start occur:
-var occurStartCommand = {
-    name: "occur",
-    exec: function(editor, options) {
-        var alreadyInOccur = !!editor.session.$occur;
-        var occurSessionActive = new Occur().enter(editor, options);
-        if (occurSessionActive && !alreadyInOccur)
-            OccurKeyboardHandler.installIn(editor);
-    },
-    readOnly: true
-};
-
-var occurCommands = [{
-    name: "occurexit",
-    bindKey: 'esc|Ctrl-G',
-    exec: function(editor) {
-        var occur = editor.session.$occur;
-        if (!occur) return;
-        occur.exit(editor, {});
-        if (!editor.session.$occur) OccurKeyboardHandler.uninstallFrom(editor);
-    },
-    readOnly: true
-}, {
-    name: "occuraccept",
-    bindKey: 'enter',
-    exec: function(editor) {
-        var occur = editor.session.$occur;
-        if (!occur) return;
-        occur.exit(editor, {translatePosition: true});
-        if (!editor.session.$occur) OccurKeyboardHandler.uninstallFrom(editor);
-    },
-    readOnly: true
-}];
-
-var HashHandler = require("../keyboard/hash_handler").HashHandler;
-var oop = require("../lib/oop");
-
-
-function OccurKeyboardHandler() {}
-
-oop.inherits(OccurKeyboardHandler, HashHandler);
-
-;(function() {
-
-    this.isOccurHandler = true;
-
-    this.attach = function(editor) {
-        HashHandler.call(this, occurCommands, editor.commands.platform);
-        this.$editor = editor;
-    }
-
-    var handleKeyboard$super = this.handleKeyboard;
-    this.handleKeyboard = function(data, hashId, key, keyCode) {
-        var cmd = handleKeyboard$super.call(this, data, hashId, key, keyCode);
-        return (cmd && cmd.command) ? cmd : undefined;
-    }
-
-}).call(OccurKeyboardHandler.prototype);
-
-OccurKeyboardHandler.installIn = function(editor) {
-    var handler = new this();
-    editor.keyBinding.addKeyboardHandler(handler);
-    editor.commands.addCommands(occurCommands);
-}
-
-OccurKeyboardHandler.uninstallFrom = function(editor) {
-    editor.commands.removeCommands(occurCommands);
-    var handler = editor.getKeyboardHandler();
-    if (handler.isOccurHandler)
-        editor.keyBinding.removeKeyboardHandler(handler);
-}
-
-exports.occurStartCommand = occurStartCommand;
-
-});

+ 0 - 295
services/web/public/js/ace/config.js

@@ -1,295 +0,0 @@
-/* ***** 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) {
-"no use strict";
-
-var lang = require("./lib/lang");
-var oop = require("./lib/oop");
-var net = require("./lib/net");
-var EventEmitter = require("./lib/event_emitter").EventEmitter;
-
-var global = (function() {
-    return this;
-})();
-
-var options = {
-    packaged: false,
-    workerPath: null,
-    modePath: null,
-    themePath: null,
-    basePath: "",
-    suffix: ".js",
-    $moduleUrls: {}
-};
-
-exports.get = function(key) {
-    if (!options.hasOwnProperty(key))
-        throw new Error("Unknown config key: " + key);
-
-    return options[key];
-};
-
-exports.set = function(key, value) {
-    if (!options.hasOwnProperty(key))
-        throw new Error("Unknown config key: " + key);
-
-    options[key] = value;
-};
-
-exports.all = function() {
-    return lang.copyObject(options);
-};
-
-// module loading
-oop.implement(exports, EventEmitter);
-
-exports.moduleUrl = function(name, component) {
-    if (options.$moduleUrls[name])
-        return options.$moduleUrls[name];
-
-    var parts = name.split("/");
-    component = component || parts[parts.length - 2] || "";
-    
-    // todo make this configurable or get rid of '-'
-    var sep = component == "snippets" ? "/" : "-";
-    var base = parts[parts.length - 1];    
-    if (sep == "-") {
-        var re = new RegExp("^" + component + "[\\-_]|[\\-_]" + component + "$", "g");
-        base = base.replace(re, "");
-    }
-
-    if ((!base || base == component) && parts.length > 1)
-        base = parts[parts.length - 2];
-    var path = options[component + "Path"];
-    if (path == null) {
-        path = options.basePath;
-    } else if (sep == "/") {
-        component = sep = "";
-    }
-    if (path && path.slice(-1) != "/")
-        path += "/";
-    return path + component + sep + base + this.get("suffix");
-};
-
-exports.setModuleUrl = function(name, subst) {
-    return options.$moduleUrls[name] = subst;
-};
-
-exports.$loading = {};
-exports.loadModule = function(moduleName, onLoad) {
-    var module, moduleType;
-    if (Array.isArray(moduleName)) {
-        moduleType = moduleName[0];
-        moduleName = moduleName[1];
-    }
-
-    try {
-        module = require(moduleName);
-    } catch (e) {}
-    // require(moduleName) can return empty object if called after require([moduleName], callback)
-    if (module && !exports.$loading[moduleName])
-        return onLoad && onLoad(module);
-
-    if (!exports.$loading[moduleName])
-        exports.$loading[moduleName] = [];
-
-    exports.$loading[moduleName].push(onLoad);
-
-    if (exports.$loading[moduleName].length > 1)
-        return;
-
-    var afterLoad = function() {
-        require([moduleName], function(module) {
-            exports._emit("load.module", {name: moduleName, module: module});
-            var listeners = exports.$loading[moduleName];
-            exports.$loading[moduleName] = null;
-            listeners.forEach(function(onLoad) {
-                onLoad && onLoad(module);
-            });
-        });
-    };
-
-    if (!exports.get("packaged"))
-        return afterLoad();
-    net.loadScript(exports.moduleUrl(moduleName, moduleType), afterLoad);
-};
-
-
-// initialization
-exports.init = function() {
-    options.packaged = require.packaged || module.packaged || (global.define && define.packaged);
-
-    if (!global.document)
-        return "";
-
-    var scriptOptions = {};
-    var scriptUrl = "";
-
-    var scripts = document.getElementsByTagName("script");
-    for (var i=0; i<scripts.length; i++) {
-        var script = scripts[i];
-
-        var src = script.src || script.getAttribute("src");
-        if (!src)
-            continue;
-
-        var attributes = script.attributes;
-        for (var j=0, l=attributes.length; j < l; j++) {
-            var attr = attributes[j];
-            if (attr.name.indexOf("data-ace-") === 0) {
-                scriptOptions[deHyphenate(attr.name.replace(/^data-ace-/, ""))] = attr.value;
-            }
-        }
-
-        var m = src.match(/^(.*)\/ace(\-\w+)?\.js(\?|$)/);
-        if (m)
-            scriptUrl = m[1];
-    }
-
-    if (scriptUrl) {
-        scriptOptions.base = scriptOptions.base || scriptUrl;
-        scriptOptions.packaged = true;
-    }
-
-    scriptOptions.basePath = scriptOptions.base;
-    scriptOptions.workerPath = scriptOptions.workerPath || scriptOptions.base;
-    scriptOptions.modePath = scriptOptions.modePath || scriptOptions.base;
-    scriptOptions.themePath = scriptOptions.themePath || scriptOptions.base;
-    delete scriptOptions.base;
-
-    for (var key in scriptOptions)
-        if (typeof scriptOptions[key] !== "undefined")
-            exports.set(key, scriptOptions[key]);
-};
-
-function deHyphenate(str) {
-    return str.replace(/-(.)/g, function(m, m1) { return m1.toUpperCase(); });
-}
-
-var optionsProvider = {
-    setOptions: function(optList) {
-        Object.keys(optList).forEach(function(key) {
-            this.setOption(key, optList[key]);
-        }, this);
-    },
-    getOptions: function(optionNames) {
-        var result = {};
-        if (!optionNames) {
-            optionNames = Object.keys(this.$options);
-        } else if (!Array.isArray(optionNames)) {
-            result = optionNames;
-            optionNames = Object.keys(result);
-        }
-        optionNames.forEach(function(key) {
-            result[key] = this.getOption(key);
-        }, this);
-        return result;
-    },
-    setOption: function(name, value) {
-        if (this["$" + name] === value)
-            return;
-        var opt = this.$options[name];
-        if (!opt) {
-            if (typeof console != "undefined" && console.warn)
-                console.warn('misspelled option "' + name + '"');
-            return undefined;
-        }
-        if (opt.forwardTo)
-            return this[opt.forwardTo] && this[opt.forwardTo].setOption(name, value);
-
-        if (!opt.handlesSet)
-            this["$" + name] = value;
-        if (opt && opt.set)
-            opt.set.call(this, value);
-    },
-    getOption: function(name) {
-        var opt = this.$options[name];
-        if (!opt) {
-            if (typeof console != "undefined" && console.warn)
-                console.warn('misspelled option "' + name + '"');
-            return undefined;
-        }
-        if (opt.forwardTo)
-            return this[opt.forwardTo] && this[opt.forwardTo].getOption(name);
-        return opt && opt.get ? opt.get.call(this) : this["$" + name];
-    }
-};
-
-var defaultOptions = {};
-/*
- * option {name, value, initialValue, setterName, set, get }
- */
-exports.defineOptions = function(obj, path, options) {
-    if (!obj.$options)
-        defaultOptions[path] = obj.$options = {};
-
-    Object.keys(options).forEach(function(key) {
-        var opt = options[key];
-        if (typeof opt == "string")
-            opt = {forwardTo: opt};
-
-        opt.name || (opt.name = key);
-        obj.$options[opt.name] = opt;
-        if ("initialValue" in opt)
-            obj["$" + opt.name] = opt.initialValue;
-    });
-
-    // implement option provider interface
-    oop.implement(obj, optionsProvider);
-
-    return this;
-};
-
-exports.resetOptions = function(obj) {
-    Object.keys(obj.$options).forEach(function(key) {
-        var opt = obj.$options[key];
-        if ("value" in opt)
-            obj.setOption(key, opt.value);
-    });
-};
-
-exports.setDefaultValue = function(path, name, value) {
-    var opts = defaultOptions[path] || (defaultOptions[path] = {});
-    if (opts[name]) {
-        if (opts.forwardTo)
-            exports.setDefaultValue(opts.forwardTo, name, value);
-        else
-            opts[name].value = value;
-    }
-};
-
-exports.setDefaultValues = function(path, optionHash) {
-    Object.keys(optionHash).forEach(function(key) {
-        exports.setDefaultValue(path, key, optionHash[key]);
-    });
-};
-
-});

+ 0 - 128
services/web/public/js/ace/config_test.js

@@ -1,128 +0,0 @@
-/* ***** 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 config = require("./config");
-var assert = require("./test/assertions");
-
-module.exports = {
-
-    "test: path resolution" : function() {
-        config.set("packaged", "true");
-        var url = config.moduleUrl("kr_theme", "theme");
-        assert.equal(url, "theme-kr.js");
-        
-        config.set("basePath", "a/b");
-        url = config.moduleUrl("m/theme", "theme");
-        assert.equal(url, "a/b/theme-m.js");
-        
-        url = config.moduleUrl("m/theme", "ext");
-        assert.equal(url, "a/b/ext-theme.js");
-        
-        config.set("workerPath", "c/");
-        url = config.moduleUrl("foo/1", "worker");
-        assert.equal(url, "c/worker-1.js");
-        
-        config.setModuleUrl("foo/1", "a/b1.js");
-        url = config.moduleUrl("foo/1", "theme");
-        assert.equal(url, "a/b1.js");
-        
-        url = config.moduleUrl("snippets/js");
-        assert.equal(url, "a/b/snippets/js.js");
-        
-        config.setModuleUrl("snippets/js", "_.js");
-        url = config.moduleUrl("snippets/js");
-        assert.equal(url, "_.js");
-        
-        url = config.moduleUrl("ace/ext/textarea");
-        assert.equal(url, "a/b/ext-textarea.js");
-        
-        assert.equal();
-    },
-    "test: define options" : function() {
-        var o = {};
-        config.defineOptions(o, "test_object", {
-            opt1: {
-                set: function(val) {
-                    this.x = val;
-                },
-                value: 7,
-            },
-            initialValue: {
-                set: function(val) {
-                    this.x = val;
-                },
-                initialValue: 8,
-            },
-            opt2: {
-                get: function(val) {
-                    return this.x;
-                }
-            },
-            forwarded: "model"
-        });
-        o.model = {};
-        config.defineOptions(o.model, "model", {
-            forwarded: {value: 1}
-        });
-        
-        config.resetOptions(o);
-        config.resetOptions(o.model);
-        assert.equal(o.getOption("opt1"), 7);
-        assert.equal(o.getOption("opt2"), 7);
-        o.setOption("opt1", 8);
-        assert.equal(o.getOption("opt1"), 8);
-        assert.equal(o.getOption("opt2"), 8);
-        
-        assert.equal(o.getOption("forwarded"), 1);
-        
-        assert.equal(o.getOption("new"), undefined);
-        o.setOption("new", 0);
-        assert.equal(o.getOption("new"), undefined);
-        
-
-        assert.equal(o.getOption("initialValue"), 8);
-        o.setOption("initialValue", 7);
-        assert.equal(o.getOption("opt2"), 7);
-
-    }
-};
-
-});
-
-if (typeof module !== "undefined" && module === require.main) {
-    require("asyncjs").test.testcase(module.exports).exec()
-}

BIN
services/web/public/js/ace/css/codefolding-fold-button-states.png


Разница между файлами не показана из-за своего большого размера
+ 0 - 85
services/web/public/js/ace/css/editor.css


BIN
services/web/public/js/ace/css/expand-marker.png


+ 0 - 642
services/web/public/js/ace/document.js

@@ -1,642 +0,0 @@
-/* ***** 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 oop = require("./lib/oop");
-var EventEmitter = require("./lib/event_emitter").EventEmitter;
-var Range = require("./range").Range;
-var Anchor = require("./anchor").Anchor;
-
-/**
- * Contains the text of the document. Document can be attached to several [[EditSession `EditSession`]]s. 
- *
- * At its core, `Document`s are just an array of strings, with each row in the document matching up to the array index.
- *
- * @class Document
- **/
-
- /**
- *
- * Creates a new `Document`. If `text` is included, the `Document` contains those strings; otherwise, it's empty.
- * @param {String | Array} text The starting text
- * @constructor
- **/
-
-var Document = function(text) {
-    this.$lines = [];
-
-    // There has to be one line at least in the document. If you pass an empty
-    // string to the insert function, nothing will happen. Workaround.
-    if (text.length == 0) {
-        this.$lines = [""];
-    } else if (Array.isArray(text)) {
-        this._insertLines(0, text);
-    } else {
-        this.insert({row: 0, column:0}, text);
-    }
-};
-
-(function() {
-
-    oop.implement(this, EventEmitter);
-
-    /**
-    * Replaces all the lines in the current `Document` with the value of `text`.
-    *
-    * @param {String} text The text to use
-    **/
-    this.setValue = function(text) {
-        var len = this.getLength();
-        this.remove(new Range(0, 0, len, this.getLine(len-1).length));
-        this.insert({row: 0, column:0}, text);
-    };
-
-    /**
-    * Returns all the lines in the document as a single string, joined by the new line character.
-    **/
-    this.getValue = function() {
-        return this.getAllLines().join(this.getNewLineCharacter());
-    };
-
-    /** 
-    * Creates a new `Anchor` to define a floating point in the document.
-    * @param {Number} row The row number to use
-    * @param {Number} column The column number to use
-    *
-    **/
-    this.createAnchor = function(row, column) {
-        return new Anchor(this, row, column);
-    };
-
-    /** 
-    * Splits a string of text on any newline (`\n`) or carriage-return ('\r') characters.
-    *
-    * @method $split
-    * @param {String} text The text to work with
-    * @returns {String} A String array, with each index containing a piece of the original `text` string.
-    *
-    **/
-
-    // check for IE split bug
-    if ("aaa".split(/a/).length == 0)
-        this.$split = function(text) {
-            return text.replace(/\r\n|\r/g, "\n").split("\n");
-        }
-    else
-        this.$split = function(text) {
-            return text.split(/\r\n|\r|\n/);
-        };
-
-
-    this.$detectNewLine = function(text) {
-        var match = text.match(/^.*?(\r\n|\r|\n)/m);
-        this.$autoNewLine = match ? match[1] : "\n";
-    };
-
-    /**
-    * Returns the newline character that's being used, depending on the value of `newLineMode`. 
-    * @returns {String} If `newLineMode == windows`, `\r\n` is returned.  
-    *  If `newLineMode == unix`, `\n` is returned.  
-    *  If `newLineMode == auto`, the value of `autoNewLine` is returned.
-    *
-    **/
-    this.getNewLineCharacter = function() {
-        switch (this.$newLineMode) {
-          case "windows":
-            return "\r\n";
-          case "unix":
-            return "\n";
-          default:
-            return this.$autoNewLine;
-        }
-    };
-
-    this.$autoNewLine = "\n";
-    this.$newLineMode = "auto";
-    /**
-     * [Sets the new line mode.]{: #Document.setNewLineMode.desc}
-     * @param {String} newLineMode [The newline mode to use; can be either `windows`, `unix`, or `auto`]{: #Document.setNewLineMode.param}
-     *
-     **/
-    this.setNewLineMode = function(newLineMode) {
-        if (this.$newLineMode === newLineMode)
-            return;
-
-        this.$newLineMode = newLineMode;
-    };
-
-    /**
-    * [Returns the type of newlines being used; either `windows`, `unix`, or `auto`]{: #Document.getNewLineMode}
-    * @returns {String}
-    **/
-    this.getNewLineMode = function() {
-        return this.$newLineMode;
-    };
-
-    /**
-    * Returns `true` if `text` is a newline character (either `\r\n`, `\r`, or `\n`).
-    * @param {String} text The text to check
-    *
-    **/
-    this.isNewLine = function(text) {
-        return (text == "\r\n" || text == "\r" || text == "\n");
-    };
-
-    /**
-    * Returns a verbatim copy of the given line as it is in the document
-    * @param {Number} row The row index to retrieve
-    *
-    **/
-    this.getLine = function(row) {
-        return this.$lines[row] || "";
-    };
-
-    /**
-    * Returns an array of strings of the rows between `firstRow` and `lastRow`. This function is inclusive of `lastRow`.
-    * @param {Number} firstRow The first row index to retrieve
-    * @param {Number} lastRow The final row index to retrieve
-    *
-    **/
-    this.getLines = function(firstRow, lastRow) {
-        return this.$lines.slice(firstRow, lastRow + 1);
-    };
-
-    /**
-    * Returns all lines in the document as string array.
-    **/
-    this.getAllLines = function() {
-        return this.getLines(0, this.getLength());
-    };
-
-    /**
-    * Returns the number of rows in the document.
-    **/
-    this.getLength = function() {
-        return this.$lines.length;
-    };
-
-    /**
-    * [Given a range within the document, this function returns all the text within that range as a single string.]{: #Document.getTextRange.desc}
-    * @param {Range} range The range to work with
-    * 
-    * @returns {String}
-    **/
-    this.getTextRange = function(range) {
-        if (range.start.row == range.end.row) {
-            return this.getLine(range.start.row)
-                .substring(range.start.column, range.end.column);
-        }
-        var lines = this.getLines(range.start.row, range.end.row);
-        lines[0] = (lines[0] || "").substring(range.start.column);
-        var l = lines.length - 1;
-        if (range.end.row - range.start.row == l)
-            lines[l] = lines[l].substring(0, range.end.column);
-        return lines.join(this.getNewLineCharacter());
-    };
-
-    this.$clipPosition = function(position) {
-        var length = this.getLength();
-        if (position.row >= length) {
-            position.row = Math.max(0, length - 1);
-            position.column = this.getLine(length-1).length;
-        } else if (position.row < 0)
-            position.row = 0;
-        return position;
-    };
-
-    /**
-    * Inserts a block of `text` at the indicated `position`.
-    * @param {Object} position The position to start inserting at; it's an object that looks like `{ row: row, column: column}`
-    * @param {String} text A chunk of text to insert
-    * @returns {Object} The position ({row, column}) of the last line of `text`. If the length of `text` is 0, this function simply returns `position`. 
-    *
-    **/
-    this.insert = function(position, text) {
-        if (!text || text.length === 0)
-            return position;
-
-        position = this.$clipPosition(position);
-
-        // only detect new lines if the document has no line break yet
-        if (this.getLength() <= 1)
-            this.$detectNewLine(text);
-
-        var lines = this.$split(text);
-        var firstLine = lines.splice(0, 1)[0];
-        var lastLine = lines.length == 0 ? null : lines.splice(lines.length - 1, 1)[0];
-
-        position = this.insertInLine(position, firstLine);
-        if (lastLine !== null) {
-            position = this.insertNewLine(position); // terminate first line
-            position = this._insertLines(position.row, lines);
-            position = this.insertInLine(position, lastLine || "");
-        }
-        return position;
-    };
-
-    /**
-     * Fires whenever the document changes.
-     *
-     * Several methods trigger different `"change"` events. Below is a list of each action type, followed by each property that's also available:
-     *
-     *  * `"insertLines"` (emitted by [[Document.insertLines]])
-     *    * `range`: the [[Range]] of the change within the document
-     *    * `lines`: the lines in the document that are changing
-     *  * `"insertText"` (emitted by [[Document.insertNewLine]])
-     *    * `range`: the [[Range]] of the change within the document
-     *    * `text`: the text that's being added
-     *  * `"removeLines"` (emitted by [[Document.insertLines]])
-     *    * `range`: the [[Range]] of the change within the document
-     *    * `lines`: the lines in the document that were removed
-     *    * `nl`: the new line character (as defined by [[Document.getNewLineCharacter]])
-     *  * `"removeText"` (emitted by [[Document.removeInLine]] and [[Document.removeNewLine]])
-     *    * `range`: the [[Range]] of the change within the document
-     *    * `text`: the text that's being removed
-     *
-     * @event change
-     * @param {Object} e Contains at least one property called `"action"`. `"action"` indicates the action that triggered the change. Each action also has a set of additional properties.
-     *
-     **/
-    /**
-    * Inserts the elements in `lines` into the document, starting at the row index given by `row`. This method also triggers the `'change'` event.
-    * @param {Number} row The index of the row to insert at
-    * @param {Array} lines An array of strings
-    * @returns {Object} Contains the final row and column, like this:  
-    *   ```
-    *   {row: endRow, column: 0}
-    *   ```  
-    *   If `lines` is empty, this function returns an object containing the current row, and column, like this:  
-    *   ``` 
-    *   {row: row, column: 0}
-    *   ```
-    *
-    **/
-    this.insertLines = function(row, lines) {
-        if (row >= this.getLength())
-            return this.insert({row: row, column: 0}, "\n" + lines.join("\n"));
-        return this._insertLines(Math.max(row, 0), lines);
-    };
-    this._insertLines = function(row, lines) {
-        if (lines.length == 0)
-            return {row: row, column: 0};
-
-        // apply doesn't work for big arrays (smallest threshold is on safari 0xFFFF)
-        // to circumvent that we have to break huge inserts into smaller chunks here
-        if (lines.length > 0xFFFF) {
-            var end = this._insertLines(row, lines.slice(0xFFFF));
-            lines = lines.slice(0, 0xFFFF);
-        }
-
-        var args = [row, 0];
-        args.push.apply(args, lines);
-        this.$lines.splice.apply(this.$lines, args);
-
-        var range = new Range(row, 0, row + lines.length, 0);
-        var delta = {
-            action: "insertLines",
-            range: range,
-            lines: lines
-        };
-        this._emit("change", { data: delta });
-        return end || range.end;
-    };
-
-    /**
-    * Inserts a new line into the document at the current row's `position`. This method also triggers the `'change'` event. 
-    * @param {Object} position The position to insert at
-    * @returns {Object} Returns an object containing the final row and column, like this:<br/>
-    *    ```
-    *    {row: endRow, column: 0}
-    *    ```
-    *
-    **/
-    this.insertNewLine = function(position) {
-        position = this.$clipPosition(position);
-        var line = this.$lines[position.row] || "";
-
-        this.$lines[position.row] = line.substring(0, position.column);
-        this.$lines.splice(position.row + 1, 0, line.substring(position.column, line.length));
-
-        var end = {
-            row : position.row + 1,
-            column : 0
-        };
-
-        var delta = {
-            action: "insertText",
-            range: Range.fromPoints(position, end),
-            text: this.getNewLineCharacter()
-        };
-        this._emit("change", { data: delta });
-
-        return end;
-    };
-
-    /**
-    * Inserts `text` into the `position` at the current row. This method also triggers the `'change'` event.
-    * @param {Object} position The position to insert at; it's an object that looks like `{ row: row, column: column}`
-    * @param {String} text A chunk of text
-    * @returns {Object} Returns an object containing the final row and column, like this:  
-    *     ```
-    *     {row: endRow, column: 0}
-    *     ```
-    *
-    **/
-    this.insertInLine = function(position, text) {
-        if (text.length == 0)
-            return position;
-
-        var line = this.$lines[position.row] || "";
-
-        this.$lines[position.row] = line.substring(0, position.column) + text
-                + line.substring(position.column);
-
-        var end = {
-            row : position.row,
-            column : position.column + text.length
-        };
-
-        var delta = {
-            action: "insertText",
-            range: Range.fromPoints(position, end),
-            text: text
-        };
-        this._emit("change", { data: delta });
-
-        return end;
-    };
-
-    /**
-    * Removes the `range` from the document.
-    * @param {Range} range A specified Range to remove
-    * @returns {Object} Returns the new `start` property of the range, which contains `startRow` and `startColumn`. If `range` is empty, this function returns the unmodified value of `range.start`.
-    *
-    **/
-    this.remove = function(range) {
-        if (!range instanceof Range)
-            range = Range.fromPoints(range.start, range.end);
-        // clip to document
-        range.start = this.$clipPosition(range.start);
-        range.end = this.$clipPosition(range.end);
-
-        if (range.isEmpty())
-            return range.start;
-
-        var firstRow = range.start.row;
-        var lastRow = range.end.row;
-
-        if (range.isMultiLine()) {
-            var firstFullRow = range.start.column == 0 ? firstRow : firstRow + 1;
-            var lastFullRow = lastRow - 1;
-
-            if (range.end.column > 0)
-                this.removeInLine(lastRow, 0, range.end.column);
-
-            if (lastFullRow >= firstFullRow)
-                this._removeLines(firstFullRow, lastFullRow);
-
-            if (firstFullRow != firstRow) {
-                this.removeInLine(firstRow, range.start.column, this.getLine(firstRow).length);
-                this.removeNewLine(range.start.row);
-            }
-        }
-        else {
-            this.removeInLine(firstRow, range.start.column, range.end.column);
-        }
-        return range.start;
-    };
-
-    /**
-    * Removes the specified columns from the `row`. This method also triggers the `'change'` event.
-    * @param {Number} row The row to remove from
-    * @param {Number} startColumn The column to start removing at 
-    * @param {Number} endColumn The column to stop removing at
-    * @returns {Object} Returns an object containing `startRow` and `startColumn`, indicating the new row and column values.<br/>If `startColumn` is equal to `endColumn`, this function returns nothing.
-    *
-    **/
-    this.removeInLine = function(row, startColumn, endColumn) {
-        if (startColumn == endColumn)
-            return;
-
-        var range = new Range(row, startColumn, row, endColumn);
-        var line = this.getLine(row);
-        var removed = line.substring(startColumn, endColumn);
-        var newLine = line.substring(0, startColumn) + line.substring(endColumn, line.length);
-        this.$lines.splice(row, 1, newLine);
-
-        var delta = {
-            action: "removeText",
-            range: range,
-            text: removed
-        };
-        this._emit("change", { data: delta });
-        return range.start;
-    };
-
-    /**
-    * Removes a range of full lines. This method also triggers the `'change'` event.
-    * @param {Number} firstRow The first row to be removed
-    * @param {Number} lastRow The last row to be removed
-    * @returns {[String]} Returns all the removed lines.
-    *
-    **/
-    this.removeLines = function(firstRow, lastRow) {
-        if (firstRow < 0 || lastRow >= this.getLength())
-            return this.remove(new Range(firstRow, 0, lastRow + 1, 0));
-        return this._removeLines(firstRow, lastRow);
-    };
-
-    this._removeLines = function(firstRow, lastRow) {
-        var range = new Range(firstRow, 0, lastRow + 1, 0);
-        var removed = this.$lines.splice(firstRow, lastRow - firstRow + 1);
-
-        var delta = {
-            action: "removeLines",
-            range: range,
-            nl: this.getNewLineCharacter(),
-            lines: removed
-        };
-        this._emit("change", { data: delta });
-        return removed;
-    };
-
-    /**
-    * Removes the new line between `row` and the row immediately following it. This method also triggers the `'change'` event.
-    * @param {Number} row The row to check
-    *
-    **/
-    this.removeNewLine = function(row) {
-        var firstLine = this.getLine(row);
-        var secondLine = this.getLine(row+1);
-
-        var range = new Range(row, firstLine.length, row+1, 0);
-        var line = firstLine + secondLine;
-
-        this.$lines.splice(row, 2, line);
-
-        var delta = {
-            action: "removeText",
-            range: range,
-            text: this.getNewLineCharacter()
-        };
-        this._emit("change", { data: delta });
-    };
-
-    /**
-    * Replaces a range in the document with the new `text`.
-    * @param {Range} range A specified Range to replace
-    * @param {String} text The new text to use as a replacement
-    * @returns {Object} Returns an object containing the final row and column, like this:
-    *     {row: endRow, column: 0}
-    * If the text and range are empty, this function returns an object containing the current `range.start` value.
-    * If the text is the exact same as what currently exists, this function returns an object containing the current `range.end` value.
-    *
-    **/
-    this.replace = function(range, text) {
-        if (!range instanceof Range)
-            range = Range.fromPoints(range.start, range.end);
-        if (text.length == 0 && range.isEmpty())
-            return range.start;
-
-        // Shortcut: If the text we want to insert is the same as it is already
-        // in the document, we don't have to replace anything.
-        if (text == this.getTextRange(range))
-            return range.end;
-
-        this.remove(range);
-        if (text) {
-            var end = this.insert(range.start, text);
-        }
-        else {
-            end = range.start;
-        }
-
-        return end;
-    };
-
-    /**
-    * Applies all the changes previously accumulated. These can be either `'includeText'`, `'insertLines'`, `'removeText'`, and `'removeLines'`.
-    **/
-    this.applyDeltas = function(deltas) {
-        for (var i=0; i<deltas.length; i++) {
-            var delta = deltas[i];
-            var range = Range.fromPoints(delta.range.start, delta.range.end);
-
-            if (delta.action == "insertLines")
-                this.insertLines(range.start.row, delta.lines);
-            else if (delta.action == "insertText")
-                this.insert(range.start, delta.text);
-            else if (delta.action == "removeLines")
-                this._removeLines(range.start.row, range.end.row - 1);
-            else if (delta.action == "removeText")
-                this.remove(range);
-        }
-    };
-
-    /**
-    * Reverts any changes previously applied. These can be either `'includeText'`, `'insertLines'`, `'removeText'`, and `'removeLines'`.
-    **/
-    this.revertDeltas = function(deltas) {
-        for (var i=deltas.length-1; i>=0; i--) {
-            var delta = deltas[i];
-
-            var range = Range.fromPoints(delta.range.start, delta.range.end);
-
-            if (delta.action == "insertLines")
-                this._removeLines(range.start.row, range.end.row - 1);
-            else if (delta.action == "insertText")
-                this.remove(range);
-            else if (delta.action == "removeLines")
-                this._insertLines(range.start.row, delta.lines);
-            else if (delta.action == "removeText")
-                this.insert(range.start, delta.text);
-        }
-    };
-
-    /**
-     * Converts an index position in a document to a `{row, column}` object.
-     *
-     * Index refers to the "absolute position" of a character in the document. For example:
-     *
-     * ```javascript
-     * var x = 0; // 10 characters, plus one for newline
-     * var y = -1;
-     * ```
-     * 
-     * Here, `y` is an index 15: 11 characters for the first row, and 5 characters until `y` in the second.
-     *
-     * @param {Number} index An index to convert
-     * @param {Number} startRow=0 The row from which to start the conversion
-     * @returns {Object} A `{row, column}` object of the `index` position
-     */
-    this.indexToPosition = function(index, startRow) {
-        var lines = this.$lines || this.getAllLines();
-        var newlineLength = this.getNewLineCharacter().length;
-        for (var i = startRow || 0, l = lines.length; i < l; i++) {
-            index -= lines[i].length + newlineLength;
-            if (index < 0)
-                return {row: i, column: index + lines[i].length + newlineLength};
-        }
-        return {row: l-1, column: lines[l-1].length};
-    };
-
-    /**
-     * Converts the `{row, column}` position in a document to the character's index.
-     *
-     * Index refers to the "absolute position" of a character in the document. For example:
-     *
-     * ```javascript
-     * var x = 0; // 10 characters, plus one for newline
-     * var y = -1;
-     * ```
-     * 
-     * Here, `y` is an index 15: 11 characters for the first row, and 5 characters until `y` in the second.
-     *
-     * @param {Object} pos The `{row, column}` to convert
-     * @param {Number} startRow=0 The row from which to start the conversion
-     * @returns {Number} The index position in the document
-     */
-    this.positionToIndex = function(pos, startRow) {
-        var lines = this.$lines || this.getAllLines();
-        var newlineLength = this.getNewLineCharacter().length;
-        var index = 0;
-        var row = Math.min(pos.row, lines.length);
-        for (var i = startRow || 0; i < row; ++i)
-            index += lines[i].length + newlineLength;
-
-        return index + pos.column;
-    };
-
-}).call(Document.prototype);
-
-exports.Document = Document;
-});

+ 0 - 306
services/web/public/js/ace/document_test.js

@@ -1,306 +0,0 @@
-/* ***** 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");
-    require("./test/mockdom");
-}
-
-define(function(require, exports, module) {
-"use strict";
-
-var Document = require("./document").Document;
-var Range = require("./range").Range;
-var assert = require("./test/assertions");
-
-module.exports = {
-
-    "test: insert text in line" : function() {
-        var doc = new Document(["12", "34"]);
-
-        var deltas = [];
-        doc.on("change", function(e) { deltas.push(e.data); });
-
-        doc.insert({row: 0, column: 1}, "juhu");
-        assert.equal(doc.getValue(), ["1juhu2", "34"].join("\n"));
-
-        var d = deltas.concat();
-        doc.revertDeltas(d);
-        assert.equal(doc.getValue(), ["12", "34"].join("\n"));
-
-        doc.applyDeltas(d);
-        assert.equal(doc.getValue(), ["1juhu2", "34"].join("\n"));
-    },
-
-    "test: insert new line" : function() {
-        var doc = new Document(["12", "34"]);
-
-        var deltas = [];
-        doc.on("change", function(e) { deltas.push(e.data); });
-
-        doc.insertNewLine({row: 0, column: 1});
-        assert.equal(doc.getValue(), ["1", "2", "34"].join("\n"));
-
-        var d = deltas.concat();
-        doc.revertDeltas(d);
-        assert.equal(doc.getValue(), ["12", "34"].join("\n"));
-
-        doc.applyDeltas(d);
-        assert.equal(doc.getValue(), ["1", "2", "34"].join("\n"));
-    },
-
-    "test: insert lines at the beginning" : function() {
-        var doc = new Document(["12", "34"]);
-
-        var deltas = [];
-        doc.on("change", function(e) { deltas.push(e.data); });
-
-        doc.insertLines(0, ["aa", "bb"]);
-        assert.equal(doc.getValue(), ["aa", "bb", "12", "34"].join("\n"));
-
-        var d = deltas.concat();
-        doc.revertDeltas(d);
-        assert.equal(doc.getValue(), ["12", "34"].join("\n"));
-
-        doc.applyDeltas(d);
-        assert.equal(doc.getValue(), ["aa", "bb", "12", "34"].join("\n"));
-    },
-
-    "test: insert lines at the end" : function() {
-        var doc = new Document(["12", "34"]);
-
-        var deltas = [];
-        doc.on("change", function(e) { deltas.push(e.data); });
-
-        doc.insertLines(2, ["aa", "bb"]);
-        assert.equal(doc.getValue(), ["12", "34", "aa", "bb"].join("\n"));
-    },
-
-    "test: insert lines in the middle" : function() {
-        var doc = new Document(["12", "34"]);
-
-        var deltas = [];
-        doc.on("change", function(e) { deltas.push(e.data); });
-
-        doc.insertLines(1, ["aa", "bb"]);
-        assert.equal(doc.getValue(), ["12", "aa", "bb", "34"].join("\n"));
-
-        var d = deltas.concat();
-        doc.revertDeltas(d);
-        assert.equal(doc.getValue(), ["12", "34"].join("\n"));
-
-        doc.applyDeltas(d);
-        assert.equal(doc.getValue(), ["12", "aa", "bb", "34"].join("\n"));
-    },
-
-    "test: insert multi line string at the start" : function() {
-        var doc = new Document(["12", "34"]);
-
-        var deltas = [];
-        doc.on("change", function(e) { deltas.push(e.data); });
-
-        doc.insert({row: 0, column: 0}, "aa\nbb\ncc");
-        assert.equal(doc.getValue(), ["aa", "bb", "cc12", "34"].join("\n"));
-
-        var d = deltas.concat();
-        doc.revertDeltas(d);
-        assert.equal(doc.getValue(), ["12", "34"].join("\n"));
-
-        doc.applyDeltas(d);
-        assert.equal(doc.getValue(), ["aa", "bb", "cc12", "34"].join("\n"));
-    },
-
-    "test: insert multi line string at the end" : function() {
-        var doc = new Document(["12", "34"]);
-
-        var deltas = [];
-        doc.on("change", function(e) { deltas.push(e.data); });
-
-        doc.insert({row: 2, column: 0}, "aa\nbb\ncc");
-        assert.equal(doc.getValue(), ["12", "34aa", "bb", "cc"].join("\n"));
-
-        var d = deltas.concat();
-        doc.revertDeltas(d);
-        assert.equal(doc.getValue(), ["12", "34"].join("\n"));
-
-        doc.applyDeltas(d);
-        assert.equal(doc.getValue(), ["12", "34aa", "bb", "cc"].join("\n"));
-    },
-
-    "test: insert multi line string in the middle" : function() {
-        var doc = new Document(["12", "34"]);
-
-        var deltas = [];
-        doc.on("change", function(e) { deltas.push(e.data); });
-
-        doc.insert({row: 0, column: 1}, "aa\nbb\ncc");
-        assert.equal(doc.getValue(), ["1aa", "bb", "cc2", "34"].join("\n"));
-
-        var d = deltas.concat();
-        doc.revertDeltas(d);
-        assert.equal(doc.getValue(), ["12", "34"].join("\n"));
-
-        doc.applyDeltas(d);
-        assert.equal(doc.getValue(), ["1aa", "bb", "cc2", "34"].join("\n"));
-    },
-
-    "test: delete in line" : function() {
-        var doc = new Document(["1234", "5678"]);
-
-        var deltas = [];
-        doc.on("change", function(e) { deltas.push(e.data); });
-
-        doc.remove(new Range(0, 1, 0, 3));
-        assert.equal(doc.getValue(), ["14", "5678"].join("\n"));
-
-        var d = deltas.concat();
-        doc.revertDeltas(d);
-        assert.equal(doc.getValue(), ["1234", "5678"].join("\n"));
-
-        doc.applyDeltas(d);
-        assert.equal(doc.getValue(), ["14", "5678"].join("\n"));
-    },
-
-    "test: delete new line" : function() {
-        var doc = new Document(["1234", "5678"]);
-
-        var deltas = [];
-        doc.on("change", function(e) { deltas.push(e.data); });
-
-        doc.remove(new Range(0, 4, 1, 0));
-        assert.equal(doc.getValue(), ["12345678"].join("\n"));
-
-        var d = deltas.concat();
-        doc.revertDeltas(d);
-        assert.equal(doc.getValue(), ["1234", "5678"].join("\n"));
-
-        doc.applyDeltas(d);
-        assert.equal(doc.getValue(), ["12345678"].join("\n"));
-    },
-
-    "test: delete multi line range line" : function() {
-        var doc = new Document(["1234", "5678", "abcd"]);
-
-        var deltas = [];
-        doc.on("change", function(e) { deltas.push(e.data); });
-
-        doc.remove(new Range(0, 2, 2, 2));
-        assert.equal(doc.getValue(), ["12cd"].join("\n"));
-
-        var d = deltas.concat();
-        doc.revertDeltas(d);
-        assert.equal(doc.getValue(), ["1234", "5678", "abcd"].join("\n"));
-
-        doc.applyDeltas(d);
-        assert.equal(doc.getValue(), ["12cd"].join("\n"));
-    },
-
-    "test: delete full lines" : function() {
-        var doc = new Document(["1234", "5678", "abcd"]);
-
-        var deltas = [];
-        doc.on("change", function(e) { deltas.push(e.data); });
-
-        doc.remove(new Range(1, 0, 3, 0));
-        assert.equal(doc.getValue(), ["1234", ""].join("\n"));
-    },
-
-    "test: remove lines should return the removed lines" : function() {
-        var doc = new Document(["1234", "5678", "abcd"]);
-
-        var removed = doc.removeLines(1, 2);
-        assert.equal(removed.join("\n"), ["5678", "abcd"].join("\n"));
-    },
-
-    "test: should handle unix style new lines" : function() {
-        var doc = new Document(["1", "2", "3"]);
-        assert.equal(doc.getValue(), ["1", "2", "3"].join("\n"));
-    },
-
-    "test: should handle windows style new lines" : function() {
-        var doc = new Document(["1", "2", "3"].join("\r\n"));
-
-        doc.setNewLineMode("unix");
-        assert.equal(doc.getValue(), ["1", "2", "3"].join("\n"));
-    },
-
-    "test: set new line mode to 'windows' should use '\\r\\n' as new lines": function() {
-        var doc = new Document(["1", "2", "3"].join("\n"));
-        doc.setNewLineMode("windows");
-        assert.equal(doc.getValue(), ["1", "2", "3"].join("\r\n"));
-    },
-
-    "test: set new line mode to 'unix' should use '\\n' as new lines": function() {
-        var doc = new Document(["1", "2", "3"].join("\r\n"));
-
-        doc.setNewLineMode("unix");
-        assert.equal(doc.getValue(), ["1", "2", "3"].join("\n"));
-    },
-
-    "test: set new line mode to 'auto' should detect the incoming nl type": function() {
-        var doc = new Document(["1", "2", "3"].join("\n"));
-
-        doc.setNewLineMode("auto");
-        assert.equal(doc.getValue(), ["1", "2", "3"].join("\n"));
-
-        var doc = new Document(["1", "2", "3"].join("\r\n"));
-
-        doc.setNewLineMode("auto");
-        assert.equal(doc.getValue(), ["1", "2", "3"].join("\r\n"));
-
-        doc.replace(new Range(0, 0, 2, 1), ["4", "5", "6"].join("\n"));
-        assert.equal(["4", "5", "6"].join("\n"), doc.getValue());
-    },
-
-    "test: set value": function() {
-        var doc = new Document("1");
-        assert.equal("1", doc.getValue());
-
-        doc.setValue(doc.getValue());
-        assert.equal("1", doc.getValue());
-
-        var doc = new Document("1\n2");
-        assert.equal("1\n2", doc.getValue());
-
-        doc.setValue(doc.getValue());
-        assert.equal("1\n2", doc.getValue());
-    },
-
-    "test: empty document has to contain one line": function() {
-        var doc = new Document("");
-        assert.equal(doc.$lines.length, 1);
-    }
-};
-
-});
-
-if (typeof module !== "undefined" && module === require.main) {
-    require("asyncjs").test.testcase(module.exports).exec()
-}

+ 0 - 2541
services/web/public/js/ace/edit_session.js

@@ -1,2541 +0,0 @@
-/* ***** 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 oop = require("./lib/oop");
-var lang = require("./lib/lang");
-var config = require("./config");
-var EventEmitter = require("./lib/event_emitter").EventEmitter;
-var Selection = require("./selection").Selection;
-var TextMode = require("./mode/text").Mode;
-var Range = require("./range").Range;
-var Document = require("./document").Document;
-var BackgroundTokenizer = require("./background_tokenizer").BackgroundTokenizer;
-var SearchHighlight = require("./search_highlight").SearchHighlight;
-
-/**
- * Stores all the data about [[Editor `Editor`]] state providing easy way to change editors state.
- *
- * `EditSession` can be attached to only one [[Document `Document`]]. Same `Document` can be attached to several `EditSession`s.
- * @class EditSession
- **/
-
-//{ events
-/**
- *
- * Emitted when the document changes.
- * @event change
- * @param {Object} e An object containing a `delta` of information about the change.
- **/
-/**
- * Emitted when the tab size changes, via [[EditSession.setTabSize]].
- *
- * @event changeTabSize
- **/
-/**
- * Emitted when the ability to overwrite text changes, via [[EditSession.setOverwrite]].
- *
- * @event changeOverwrite
- **/
-/**
- * Emitted when the gutter changes, either by setting or removing breakpoints, or when the gutter decorations change.
- *
- * @event changeBreakpoint
- **/
-/**
- * Emitted when a front marker changes.
- *
- * @event changeFrontMarker
- **/
-/**
- * Emitted when a back marker changes.
- *
- * @event changeBackMarker
- **/
-/**
- * Emitted when an annotation changes, like through [[EditSession.setAnnotations]].
- *
- * @event changeAnnotation
- **/
-/**
- * Emitted when a background tokenizer asynchronously processes new rows.
- * @event tokenizerUpdate
- *
- * @param {Object} e An object containing one property, `"data"`, that contains information about the changing rows
- *
- **/
-/**
- * Emitted when the current mode changes.
- *
- * @event changeMode
- *
- **/
-/**
- * Emitted when the wrap mode changes.
- *
- * @event changeWrapMode
- *
- **/
-/**
- * Emitted when the wrapping limit changes.
- *
- * @event changeWrapLimit
- *
- **/
-/**
- * Emitted when a code fold is added or removed.
- *
- * @event changeFold
- *
- **/
- /**
- * Emitted when the scroll top changes.
- * @event changeScrollTop
- *
- * @param {Number} scrollTop The new scroll top value
- **/
-/**
- * Emitted when the scroll left changes.
- * @event changeScrollLeft
- *
- * @param {Number} scrollLeft The new scroll left value
- **/
-//}
-
-/**
- *
- * Sets up a new `EditSession` and associates it with the given `Document` and `TextMode`.
- * @param {Document | String} text [If `text` is a `Document`, it associates the `EditSession` with it. Otherwise, a new `Document` is created, with the initial text]{: #textParam}
- * @param {TextMode} mode [The inital language mode to use for the document]{: #modeParam}
- *
- * @constructor
- **/
-
-var EditSession = function(text, mode) {
-    this.$breakpoints = [];
-    this.$decorations = [];
-    this.$frontMarkers = {};
-    this.$backMarkers = {};
-    this.$markerId = 1;
-    this.$undoSelect = true;
-
-    this.$foldData = [];
-    this.$foldData.toString = function() {
-        return this.join("\n");
-    }
-    this.on("changeFold", this.onChangeFold.bind(this));
-    this.$onChange = this.onChange.bind(this);
-
-    if (typeof text != "object" || !text.getLine)
-        text = new Document(text);
-
-    this.setDocument(text);
-    this.selection = new Selection(this);
-
-    config.resetOptions(this);
-    this.setMode(mode);
-    config._emit("session", this);
-};
-
-
-(function() {
-
-    oop.implement(this, EventEmitter);
-
-    /**
-     * Sets the `EditSession` to point to a new `Document`. If a `BackgroundTokenizer` exists, it also points to `doc`.
-     *
-     * @param {Document} doc The new `Document` to use
-     *
-     **/
-    this.setDocument = function(doc) {
-        if (this.doc)
-            this.doc.removeListener("change", this.$onChange);
-
-        this.doc = doc;
-        doc.on("change", this.$onChange);
-
-        if (this.bgTokenizer)
-            this.bgTokenizer.setDocument(this.getDocument());
-
-        this.resetCaches();
-    };
-
-    /**
-     * Returns the `Document` associated with this session.
-     * @return {Document}
-     **/
-    this.getDocument = function() {
-        return this.doc;
-    };
-
-    /**
-     * @param {Number} row The row to work with
-     *
-     **/
-    this.$resetRowCache = function(docRow) {
-        if (!docRow) {
-            this.$docRowCache = [];
-            this.$screenRowCache = [];
-            return;
-        }
-        var l = this.$docRowCache.length;
-        var i = this.$getRowCacheIndex(this.$docRowCache, docRow) + 1;
-        if (l > i) {
-            this.$docRowCache.splice(i, l);
-            this.$screenRowCache.splice(i, l);
-        }
-    };
-
-    this.$getRowCacheIndex = function(cacheArray, val) {
-        var low = 0;
-        var hi = cacheArray.length - 1;
-
-        while (low <= hi) {
-            var mid = (low + hi) >> 1;
-            var c = cacheArray[mid];
-
-            if (val > c)
-                low = mid + 1;
-            else if (val < c)
-                hi = mid - 1;
-            else
-                return mid;
-        }
-
-        return low -1;
-    };
-
-    this.resetCaches = function() {
-        this.$modified = true;
-        this.$wrapData = [];
-        this.$rowLengthCache = [];
-        this.$resetRowCache(0);
-        if (this.bgTokenizer)
-            this.bgTokenizer.start(0);
-    };
-
-    this.onChangeFold = function(e) {
-        var fold = e.data;
-        this.$resetRowCache(fold.start.row);
-    };
-
-    this.onChange = function(e) {
-        var delta = e.data;
-        this.$modified = true;
-
-        this.$resetRowCache(delta.range.start.row);
-
-        var removedFolds = this.$updateInternalDataOnChange(e);
-        if (!this.$fromUndo && this.$undoManager && !delta.ignore) {
-            this.$deltasDoc.push(delta);
-            if (removedFolds && removedFolds.length != 0) {
-                this.$deltasFold.push({
-                    action: "removeFolds",
-                    folds:  removedFolds
-                });
-            }
-
-            this.$informUndoManager.schedule();
-        }
-
-        this.bgTokenizer.$updateOnChange(delta);
-        this._emit("change", e);
-    };
-
-    /**
-    * Sets the session text.
-    * @param {String} text The new text to place
-    *
-    *
-    *
-    **/
-    this.setValue = function(text) {
-        this.doc.setValue(text);
-        this.selection.moveCursorTo(0, 0);
-        this.selection.clearSelection();
-
-        this.$resetRowCache(0);
-        this.$deltas = [];
-        this.$deltasDoc = [];
-        this.$deltasFold = [];
-        this.getUndoManager().reset();
-    };
-
-    /**
-    * Returns the current [[Document `Document`]] as a string.
-    * @method toString
-    * @returns {String}
-    * @alias EditSession.getValue
-    *
-    **/
-
-    /**
-    * Returns the current [[Document `Document`]] as a string.
-    * @method getValue
-    * @returns {String}
-    * @alias EditSession.toString
-    **/
-    this.getValue =
-    this.toString = function() {
-        return this.doc.getValue();
-    };
-
-    /**
-    * Returns the string of the current selection.
-    **/
-    this.getSelection = function() {
-        return this.selection;
-    };
-
-    /**
-     * {:BackgroundTokenizer.getState}
-     * @param {Number} row The row to start at
-     *
-     * @related BackgroundTokenizer.getState
-     **/
-    this.getState = function(row) {
-        return this.bgTokenizer.getState(row);
-    };
-
-    /**
-     * Starts tokenizing at the row indicated. Returns a list of objects of the tokenized rows.
-     * @param {Number} row The row to start at
-     *
-     *
-     *
-     **/
-    this.getTokens = function(row) {
-        return this.bgTokenizer.getTokens(row);
-    };
-
-    /**
-    * Returns an object indicating the token at the current row. The object has two properties: `index` and `start`.
-    * @param {Number} row The row number to retrieve from
-    * @param {Number} column The column number to retrieve from
-    *
-    *
-    **/
-    this.getTokenAt = function(row, column) {
-        var tokens = this.bgTokenizer.getTokens(row);
-        var token, c = 0;
-        if (column == null) {
-            i = tokens.length - 1;
-            c = this.getLine(row).length;
-        } else {
-            for (var i = 0; i < tokens.length; i++) {
-                c += tokens[i].value.length;
-                if (c >= column)
-                    break;
-            }
-        }
-        token = tokens[i];
-        if (!token)
-            return null;
-        token.index = i;
-        token.start = c - token.value.length;
-        return token;
-    };
-
-    /**
-    * Sets the undo manager.
-    * @param {UndoManager} undoManager The new undo manager
-    *
-    *
-    **/
-    this.setUndoManager = function(undoManager) {
-        this.$undoManager = undoManager;
-        this.$deltas = [];
-        this.$deltasDoc = [];
-        this.$deltasFold = [];
-
-        if (this.$informUndoManager)
-            this.$informUndoManager.cancel();
-
-        if (undoManager) {
-            var self = this;
-
-            this.$syncInformUndoManager = function() {
-                self.$informUndoManager.cancel();
-
-                if (self.$deltasFold.length) {
-                    self.$deltas.push({
-                        group: "fold",
-                        deltas: self.$deltasFold
-                    });
-                    self.$deltasFold = [];
-                }
-
-                if (self.$deltasDoc.length) {
-                    self.$deltas.push({
-                        group: "doc",
-                        deltas: self.$deltasDoc
-                    });
-                    self.$deltasDoc = [];
-                }
-
-                if (self.$deltas.length > 0) {
-                    undoManager.execute({
-                        action: "aceupdate",
-                        args: [self.$deltas, self],
-                        merge: self.mergeUndoDeltas
-                    });
-                }
-                self.mergeUndoDeltas = false;
-                self.$deltas = [];
-            }
-            this.$informUndoManager = lang.delayedCall(this.$syncInformUndoManager);
-        }
-    };
-
-    /**
-     * starts a new group in undo history
-     **/
-    this.markUndoGroup = function() {
-        if (this.$syncInformUndoManager)
-            this.$syncInformUndoManager();
-    };
-    
-    this.$defaultUndoManager = {
-        undo: function() {},
-        redo: function() {},
-        reset: function() {}
-    };
-
-    /**
-    * Returns the current undo manager.
-    **/
-    this.getUndoManager = function() {
-        return this.$undoManager || this.$defaultUndoManager;
-    };
-
-    /**
-    * Returns the current value for tabs. If the user is using soft tabs, this will be a series of spaces (defined by [[EditSession.getTabSize `getTabSize()`]]); otherwise it's simply `'\t'`.
-    **/
-    this.getTabString = function() {
-        if (this.getUseSoftTabs()) {
-            return lang.stringRepeat(" ", this.getTabSize());
-        } else {
-            return "\t";
-        }
-    };
-
-    /**
-    /**
-    * Pass `true` to enable the use of soft tabs. Soft tabs means you're using spaces instead of the tab character (`'\t'`).
-    * @param {Boolean} useSoftTabs Value indicating whether or not to use soft tabs
-    **/
-    this.setUseSoftTabs = function(val) {
-        this.setOption("useSoftTabs", val);
-    };
-    /**
-    * Returns `true` if soft tabs are being used, `false` otherwise.
-    * @returns {Boolean}
-    **/
-    this.getUseSoftTabs = function() {
-        // todo might need more general way for changing settings from mode, but this is ok for now
-        return this.$useSoftTabs && !this.$mode.$indentWithTabs;
-    };
-    /**
-    * Set the number of spaces that define a soft tab; for example, passing in `4` transforms the soft tabs to be equivalent to four spaces. This function also emits the `changeTabSize` event.
-    * @param {Number} tabSize The new tab size
-    **/
-    this.setTabSize = function(tabSize) {
-        this.setOption("tabSize", tabSize)
-    };
-    /**
-    * Returns the current tab size.
-    **/
-    this.getTabSize = function() {
-        return this.$tabSize;
-    };
-
-    /**
-    * Returns `true` if the character at the position is a soft tab.
-    * @param {Object} position The position to check
-    *
-    *
-    **/
-    this.isTabStop = function(position) {
-        return this.$useSoftTabs && (position.column % this.$tabSize == 0);
-    };
-
-    this.$overwrite = false;
-    /**
-    * Pass in `true` to enable overwrites in your session, or `false` to disable.
-    *
-    * If overwrites is enabled, any text you enter will type over any text after it. If the value of `overwrite` changes, this function also emites the `changeOverwrite` event.
-    *
-    * @param {Boolean} overwrite Defines wheter or not to set overwrites
-    *
-    *
-    **/
-    this.setOverwrite = function(overwrite) {
-        this.setOption("overwrite", overwrite)
-    };
-
-    /**
-    * Returns `true` if overwrites are enabled; `false` otherwise.
-    **/
-    this.getOverwrite = function() {
-        return this.$overwrite;
-    };
-
-    /**
-    * Sets the value of overwrite to the opposite of whatever it currently is.
-    **/
-    this.toggleOverwrite = function() {
-        this.setOverwrite(!this.$overwrite);
-    };
-
-    /**
-    * Adds `className` to the `row`, to be used for CSS stylings and whatnot.
-    * @param {Number} row The row number
-    * @param {String} className The class to add
-    *
-    *
-    **/
-    this.addGutterDecoration = function(row, className) {
-        if (!this.$decorations[row])
-            this.$decorations[row] = "";
-        this.$decorations[row] += " " + className;
-        this._emit("changeBreakpoint", {});
-    };
-
-    /**
-    * Removes `className` from the `row`.
-    * @param {Number} row The row number
-    * @param {String} className The class to add
-    *
-    *
-    **/
-    this.removeGutterDecoration = function(row, className) {
-        this.$decorations[row] = (this.$decorations[row] || "").replace(" " + className, "");
-        this._emit("changeBreakpoint", {});
-    };
-
-    /**
-    * Returns an array of numbers, indicating which rows have breakpoints.
-    * @returns {[Number]}
-    **/
-    this.getBreakpoints = function() {
-        return this.$breakpoints;
-    };
-
-    /**
-    * Sets a breakpoint on every row number given by `rows`. This function also emites the `'changeBreakpoint'` event.
-    * @param {Array} rows An array of row indices
-    *
-    *
-    *
-    **/
-    this.setBreakpoints = function(rows) {
-        this.$breakpoints = [];
-        for (var i=0; i<rows.length; i++) {
-            this.$breakpoints[rows[i]] = "ace_breakpoint";
-        }
-        this._emit("changeBreakpoint", {});
-    };
-
-    /**
-    * Removes all breakpoints on the rows. This function also emites the `'changeBreakpoint'` event.
-    **/
-    this.clearBreakpoints = function() {
-        this.$breakpoints = [];
-        this._emit("changeBreakpoint", {});
-    };
-
-    /**
-    * Sets a breakpoint on the row number given by `rows`. This function also emites the `'changeBreakpoint'` event.
-    * @param {Number} row A row index
-    * @param {String} className Class of the breakpoint
-    *
-    *
-    **/
-    this.setBreakpoint = function(row, className) {
-        if (className === undefined)
-            className = "ace_breakpoint";
-        if (className)
-            this.$breakpoints[row] = className;
-        else
-            delete this.$breakpoints[row];
-        this._emit("changeBreakpoint", {});
-    };
-
-    /**
-    * Removes a breakpoint on the row number given by `rows`. This function also emites the `'changeBreakpoint'` event.
-    * @param {Number} row A row index
-    *
-    *
-    **/
-    this.clearBreakpoint = function(row) {
-        delete this.$breakpoints[row];
-        this._emit("changeBreakpoint", {});
-    };
-
-    /**
-    * Adds a new marker to the given `Range`. If `inFront` is `true`, a front marker is defined, and the `'changeFrontMarker'` event fires; otherwise, the `'changeBackMarker'` event fires.
-    * @param {Range} range Define the range of the marker
-    * @param {String} clazz Set the CSS class for the marker
-    * @param {Function | String} type Identify the type of the marker
-    * @param {Boolean} inFront Set to `true` to establish a front marker
-    *
-    *
-    * @return {Number} The new marker id
-    **/
-    this.addMarker = function(range, clazz, type, inFront) {
-        var id = this.$markerId++;
-
-        var marker = {
-            range : range,
-            type : type || "line",
-            renderer: typeof type == "function" ? type : null,
-            clazz : clazz,
-            inFront: !!inFront,
-            id: id
-        }
-
-        if (inFront) {
-            this.$frontMarkers[id] = marker;
-            this._emit("changeFrontMarker")
-        } else {
-            this.$backMarkers[id] = marker;
-            this._emit("changeBackMarker")
-        }
-
-        return id;
-    };
-
-    /**
-     * Adds a dynamic marker to the session.
-     * @param {Object} marker object with update method
-     * @param {Boolean} inFront Set to `true` to establish a front marker
-     *
-     *
-     * @return {Object} The added marker
-     **/
-    this.addDynamicMarker = function(marker, inFront) {
-        if (!marker.update)
-            return;
-        var id = this.$markerId++;
-        marker.id = id;
-        marker.inFront = !!inFront;
-
-        if (inFront) {
-            this.$frontMarkers[id] = marker;
-            this._emit("changeFrontMarker")
-        } else {
-            this.$backMarkers[id] = marker;
-            this._emit("changeBackMarker")
-        }
-
-        return marker;
-    };
-
-    /**
-    * Removes the marker with the specified ID. If this marker was in front, the `'changeFrontMarker'` event is emitted. If the marker was in the back, the `'changeBackMarker'` event is emitted.
-    * @param {Number} markerId A number representing a marker
-    *
-    *
-    *
-    **/
-    this.removeMarker = function(markerId) {
-        var marker = this.$frontMarkers[markerId] || this.$backMarkers[markerId];
-        if (!marker)
-            return;
-
-        var markers = marker.inFront ? this.$frontMarkers : this.$backMarkers;
-        if (marker) {
-            delete (markers[markerId]);
-            this._emit(marker.inFront ? "changeFrontMarker" : "changeBackMarker");
-        }
-    };
-
-    /**
-    * Returns an array containing the IDs of all the markers, either front or back.
-    * @param {Boolean} inFront If `true`, indicates you only want front markers; `false` indicates only back markers
-    *
-    * @returns {Array}
-    **/
-    this.getMarkers = function(inFront) {
-        return inFront ? this.$frontMarkers : this.$backMarkers;
-    };
-
-    this.highlight = function(re) {
-        if (!this.$searchHighlight) {
-            var highlight = new SearchHighlight(null, "ace_selected-word", "text");
-            this.$searchHighlight = this.addDynamicMarker(highlight);
-        }
-        this.$searchHighlight.setRegexp(re);
-    }
-
-    // experimental
-    this.highlightLines = function(startRow, endRow, clazz, inFront) {
-        if (typeof endRow != "number") {
-            clazz = endRow;
-            endRow = startRow;
-        }
-        if (!clazz)
-            clazz = "ace_step";
-
-        var range = new Range(startRow, 0, endRow, Infinity);
-        range.id = this.addMarker(range, clazz, "fullLine", inFront);
-        return range;
-    };
-
-    /*
-     * Error:
-     *  {
-     *    row: 12,
-     *    column: 2, //can be undefined
-     *    text: "Missing argument",
-     *    type: "error" // or "warning" or "info"
-     *  }
-     */
-    /**
-    * Sets annotations for the `EditSession`. This functions emits the `'changeAnnotation'` event.
-    * @param {Array} annotations A list of annotations
-    *
-    **/
-    this.setAnnotations = function(annotations) {
-        this.$annotations = annotations;
-        this._emit("changeAnnotation", {});
-    };
-
-    /**
-    * Returns the annotations for the `EditSession`.
-    * @returns {Array}
-    **/
-    this.getAnnotations = function() {
-        return this.$annotations || [];
-    };
-
-    /**
-    * Clears all the annotations for this session. This function also triggers the `'changeAnnotation'` event.
-    **/
-    this.clearAnnotations = function() {
-        this.setAnnotations([]);
-    };
-
-    /**
-    * If `text` contains either the newline (`\n`) or carriage-return ('\r') characters, `$autoNewLine` stores that value.
-    * @param {String} text A block of text
-    *
-    *
-    **/
-    this.$detectNewLine = function(text) {
-        var match = text.match(/^.*?(\r?\n)/m);
-        if (match) {
-            this.$autoNewLine = match[1];
-        } else {
-            this.$autoNewLine = "\n";
-        }
-    };
-
-    /**
-    * Given a starting row and column, this method returns the `Range` of the first word boundary it finds.
-    * @param {Number} row The row to start at
-    * @param {Number} column The column to start at
-    *
-    * @returns {Range}
-    **/
-    this.getWordRange = function(row, column) {
-        var line = this.getLine(row);
-
-        var inToken = false;
-        if (column > 0)
-            inToken = !!line.charAt(column - 1).match(this.tokenRe);
-
-        if (!inToken)
-            inToken = !!line.charAt(column).match(this.tokenRe);
-
-        if (inToken)
-            var re = this.tokenRe;
-        else if (/^\s+$/.test(line.slice(column-1, column+1)))
-            var re = /\s/;
-        else
-            var re = this.nonTokenRe;
-
-        var start = column;
-        if (start > 0) {
-            do {
-                start--;
-            }
-            while (start >= 0 && line.charAt(start).match(re));
-            start++;
-        }
-
-        var end = column;
-        while (end < line.length && line.charAt(end).match(re)) {
-            end++;
-        }
-
-        return new Range(row, start, row, end);
-    };
-
-    /**
-    * Gets the range of a word, including its right whitespace.
-    * @param {Number} row The row number to start from
-    * @param {Number} column The column number to start from
-    *
-    * @return {Range}
-    **/
-    this.getAWordRange = function(row, column) {
-        var wordRange = this.getWordRange(row, column);
-        var line = this.getLine(wordRange.end.row);
-
-        while (line.charAt(wordRange.end.column).match(/[ \t]/)) {
-            wordRange.end.column += 1;
-        }
-        return wordRange;
-    };
-
-    /**
-    * {:Document.setNewLineMode.desc}
-    * @param {String} newLineMode {:Document.setNewLineMode.param}
-    *
-    *
-    * @related Document.setNewLineMode
-    **/
-    this.setNewLineMode = function(newLineMode) {
-        this.doc.setNewLineMode(newLineMode);
-    };
-
-    /**
-    *
-    * Returns the current new line mode.
-    * @returns {String}
-    * @related Document.getNewLineMode
-    **/
-    this.getNewLineMode = function() {
-        return this.doc.getNewLineMode();
-    };
-
-    /**
-    * Identifies if you want to use a worker for the `EditSession`.
-    * @param {Boolean} useWorker Set to `true` to use a worker
-    *
-    **/
-    this.setUseWorker = function(useWorker) { this.setOption("useWorker", useWorker); };
-
-    /**
-    * Returns `true` if workers are being used.
-    **/
-    this.getUseWorker = function() { return this.$useWorker; };
-
-    /**
-    * Reloads all the tokens on the current session. This function calls [[BackgroundTokenizer.start `BackgroundTokenizer.start ()`]] to all the rows; it also emits the `'tokenizerUpdate'` event.
-    **/
-    this.onReloadTokenizer = function(e) {
-        var rows = e.data;
-        this.bgTokenizer.start(rows.first);
-        this._emit("tokenizerUpdate", e);
-    };
-
-    this.$modes = {};
-
-    /**
-    * Sets a new text mode for the `EditSession`. This method also emits the `'changeMode'` event. If a [[BackgroundTokenizer `BackgroundTokenizer`]] is set, the `'tokenizerUpdate'` event is also emitted.
-    * @param {TextMode} mode Set a new text mode
-    * @param {cb} optional callback
-    *
-    **/
-    this.$mode = null;
-    this.$modeId = null;
-    this.setMode = function(mode, cb) {
-        if (mode && typeof mode === "object") {
-            if (mode.getTokenizer)
-                return this.$onChangeMode(mode);
-            var options = mode;
-            var path = options.path;
-        } else {
-            path = mode || "ace/mode/text";
-        }
-
-        // this is needed if ace isn't on require path (e.g tests in node)
-        if (!this.$modes["ace/mode/text"])
-            this.$modes["ace/mode/text"] = new TextMode();
-
-        if (this.$modes[path] && !options) {
-            this.$onChangeMode(this.$modes[path]);
-            cb && cb();
-            return;
-        }
-        // load on demand
-        this.$modeId = path;
-        config.loadModule(["mode", path], function(m) {
-            if (this.$modeId !== path)
-                return cb && cb();
-            if (this.$modes[path] && !options)
-                return this.$onChangeMode(this.$modes[path]);
-            if (m && m.Mode) {
-                m = new m.Mode(options);
-                if (!options) {
-                    this.$modes[path] = m;
-                    m.$id = path;
-                }
-                this.$onChangeMode(m);
-                cb && cb();
-            }
-        }.bind(this));
-
-        // set mode to text until loading is finished
-        if (!this.$mode)
-            this.$onChangeMode(this.$modes["ace/mode/text"], true);
-    };
-
-    this.$onChangeMode = function(mode, $isPlaceholder) {
-        if (!$isPlaceholder)
-            this.$modeId = mode.$id;
-        if (this.$mode === mode) 
-            return;
-
-        this.$mode = mode;
-
-        this.$stopWorker();
-
-        if (this.$useWorker)
-            this.$startWorker();
-
-        var tokenizer = mode.getTokenizer();
-
-        if(tokenizer.addEventListener !== undefined) {
-            var onReloadTokenizer = this.onReloadTokenizer.bind(this);
-            tokenizer.addEventListener("update", onReloadTokenizer);
-        }
-
-        if (!this.bgTokenizer) {
-            this.bgTokenizer = new BackgroundTokenizer(tokenizer);
-            var _self = this;
-            this.bgTokenizer.addEventListener("update", function(e) {
-                _self._emit("tokenizerUpdate", e);
-            });
-        } else {
-            this.bgTokenizer.setTokenizer(tokenizer);
-        }
-
-        this.bgTokenizer.setDocument(this.getDocument());
-
-        this.tokenRe = mode.tokenRe;
-        this.nonTokenRe = mode.nonTokenRe;
-
-        
-        if (!$isPlaceholder) {
-            this.$options.wrapMethod.set.call(this, this.$wrapMethod);
-            this.$setFolding(mode.foldingRules);
-            this.bgTokenizer.start(0);
-            this._emit("changeMode");
-        }
-    };
-
-
-    this.$stopWorker = function() {
-        if (this.$worker)
-            this.$worker.terminate();
-
-        this.$worker = null;
-    };
-
-    this.$startWorker = function() {
-        if (typeof Worker !== "undefined" && !require.noWorker) {
-            try {
-                this.$worker = this.$mode.createWorker(this);
-            } catch (e) {
-                console.log("Could not load worker");
-                console.log(e);
-                this.$worker = null;
-            }
-        }
-        else
-            this.$worker = null;
-    };
-
-    /**
-    * Returns the current text mode.
-    * @returns {TextMode} The current text mode
-    **/
-    this.getMode = function() {
-        return this.$mode;
-    };
-
-    this.$scrollTop = 0;
-    /**
-    * This function sets the scroll top value. It also emits the `'changeScrollTop'` event.
-    * @param {Number} scrollTop The new scroll top value
-    *
-    **/
-    this.setScrollTop = function(scrollTop) {
-        // TODO: should we force integer lineheight instead? scrollTop = Math.round(scrollTop); 
-        if (this.$scrollTop === scrollTop || isNaN(scrollTop))
-            return;
-
-        this.$scrollTop = scrollTop;
-        this._signal("changeScrollTop", scrollTop);
-    };
-
-    /**
-    * [Returns the value of the distance between the top of the editor and the topmost part of the visible content.]{: #EditSession.getScrollTop}
-    * @returns {Number}
-    **/
-    this.getScrollTop = function() {
-        return this.$scrollTop;
-    };
-
-    this.$scrollLeft = 0;
-    /**
-    * [Sets the value of the distance between the left of the editor and the leftmost part of the visible content.]{: #EditSession.setScrollLeft}
-    **/
-    this.setScrollLeft = function(scrollLeft) {
-        // scrollLeft = Math.round(scrollLeft);
-        if (this.$scrollLeft === scrollLeft || isNaN(scrollLeft))
-            return;
-
-        this.$scrollLeft = scrollLeft;
-        this._signal("changeScrollLeft", scrollLeft);
-    };
-
-    /**
-    * [Returns the value of the distance between the left of the editor and the leftmost part of the visible content.]{: #EditSession.getScrollLeft}
-    * @returns {Number}
-    **/
-    this.getScrollLeft = function() {
-        return this.$scrollLeft;
-    };
-
-    /**
-    * Returns the width of the screen.
-    * @returns {Number}
-    **/
-    this.getScreenWidth = function() {
-        this.$computeWidth();
-        if (this.lineWidgets) 
-            return Math.max(this.getLineWidgetMaxWidth(), this.screenWidth);
-        return this.screenWidth;
-    };
-    
-    this.getLineWidgetMaxWidth = function() {
-        if (this.lineWidgetsWidth != null) return this.lineWidgetsWidth
-        var width = 0;
-        this.lineWidgets.forEach(function(w) {
-            if (w && w.screenWidth > width)
-                width = w.screenWidth;
-        });
-        return this.lineWidgetWidth = width;
-    }
-
-    this.$computeWidth = function(force) {
-        if (this.$modified || force) {
-            this.$modified = false;
-
-            if (this.$useWrapMode)
-                return this.screenWidth = this.$wrapLimit;
-
-            var lines = this.doc.getAllLines();
-            var cache = this.$rowLengthCache;
-            var longestScreenLine = 0;
-            var foldIndex = 0;
-            var foldLine = this.$foldData[foldIndex];
-            var foldStart = foldLine ? foldLine.start.row : Infinity;
-            var len = lines.length;
-
-            for (var i = 0; i < len; i++) {
-                if (i > foldStart) {
-                    i = foldLine.end.row + 1;
-                    if (i >= len)
-                        break;
-                    foldLine = this.$foldData[foldIndex++];
-                    foldStart = foldLine ? foldLine.start.row : Infinity;
-                }
-
-                if (cache[i] == null)
-                    cache[i] = this.$getStringScreenWidth(lines[i])[0];
-
-                if (cache[i] > longestScreenLine)
-                    longestScreenLine = cache[i];
-            }
-            this.screenWidth = longestScreenLine;
-        }
-    };
-
-    /**
-     * Returns a verbatim copy of the given line as it is in the document
-     * @param {Number} row The row to retrieve from
-     *
-    *
-     * @returns {String}
-    *
-    **/
-    this.getLine = function(row) {
-        return this.doc.getLine(row);
-    };
-
-    /**
-     * Returns an array of strings of the rows between `firstRow` and `lastRow`. This function is inclusive of `lastRow`.
-     * @param {Number} firstRow The first row index to retrieve
-     * @param {Number} lastRow The final row index to retrieve
-     *
-     * @returns {[String]}
-     *
-     **/
-    this.getLines = function(firstRow, lastRow) {
-        return this.doc.getLines(firstRow, lastRow);
-    };
-
-    /**
-     * Returns the number of rows in the document.
-     * @returns {Number}
-     **/
-    this.getLength = function() {
-        return this.doc.getLength();
-    };
-
-    /**
-     * {:Document.getTextRange.desc}
-     * @param {Range} range The range to work with
-     *
-     * @returns {String}
-     **/
-    this.getTextRange = function(range) {
-        return this.doc.getTextRange(range || this.selection.getRange());
-    };
-
-    /**
-     * Inserts a block of `text` and the indicated `position`.
-     * @param {Object} position The position {row, column} to start inserting at
-     * @param {String} text A chunk of text to insert
-     * @returns {Object} The position of the last line of `text`. If the length of `text` is 0, this function simply returns `position`.
-     *
-     *
-     **/
-    this.insert = function(position, text) {
-        return this.doc.insert(position, text);
-    };
-
-    /**
-     * Removes the `range` from the document.
-     * @param {Range} range A specified Range to remove
-     * @returns {Object} The new `start` property of the range, which contains `startRow` and `startColumn`. If `range` is empty, this function returns the unmodified value of `range.start`.
-     *
-     * @related Document.remove
-     *
-     **/
-    this.remove = function(range) {
-        return this.doc.remove(range);
-    };
-
-    /**
-     * Reverts previous changes to your document.
-     * @param {Array} deltas An array of previous changes
-     * @param {Boolean} dontSelect [If `true`, doesn't select the range of where the change occured]{: #dontSelect}
-    *
-     *
-     * @returns {Range}
-    **/
-    this.undoChanges = function(deltas, dontSelect) {
-        if (!deltas.length)
-            return;
-
-        this.$fromUndo = true;
-        var lastUndoRange = null;
-        for (var i = deltas.length - 1; i != -1; i--) {
-            var delta = deltas[i];
-            if (delta.group == "doc") {
-                this.doc.revertDeltas(delta.deltas);
-                lastUndoRange =
-                    this.$getUndoSelection(delta.deltas, true, lastUndoRange);
-            } else {
-                delta.deltas.forEach(function(foldDelta) {
-                    this.addFolds(foldDelta.folds);
-                }, this);
-            }
-        }
-        this.$fromUndo = false;
-        lastUndoRange &&
-            this.$undoSelect &&
-            !dontSelect &&
-            this.selection.setSelectionRange(lastUndoRange);
-        return lastUndoRange;
-    };
-
-    /**
-     * Re-implements a previously undone change to your document.
-     * @param {Array} deltas An array of previous changes
-     * @param {Boolean} dontSelect {:dontSelect}
-     *
-    *
-     * @returns {Range}
-    **/
-    this.redoChanges = function(deltas, dontSelect) {
-        if (!deltas.length)
-            return;
-
-        this.$fromUndo = true;
-        var lastUndoRange = null;
-        for (var i = 0; i < deltas.length; i++) {
-            var delta = deltas[i];
-            if (delta.group == "doc") {
-                this.doc.applyDeltas(delta.deltas);
-                lastUndoRange =
-                    this.$getUndoSelection(delta.deltas, false, lastUndoRange);
-            }
-        }
-        this.$fromUndo = false;
-        lastUndoRange &&
-            this.$undoSelect &&
-            !dontSelect &&
-            this.selection.setSelectionRange(lastUndoRange);
-        return lastUndoRange;
-    };
-
-    /**
-     * Enables or disables highlighting of the range where an undo occured.
-     * @param {Boolean} enable If `true`, selects the range of the reinserted change
-    *
-    **/
-    this.setUndoSelect = function(enable) {
-        this.$undoSelect = enable;
-    };
-
-    this.$getUndoSelection = function(deltas, isUndo, lastUndoRange) {
-        function isInsert(delta) {
-            var insert =
-                delta.action === "insertText" || delta.action === "insertLines";
-            return isUndo ? !insert : insert;
-        }
-
-        var delta = deltas[0];
-        var range, point;
-        var lastDeltaIsInsert = false;
-        if (isInsert(delta)) {
-            range = Range.fromPoints(delta.range.start, delta.range.end);
-            lastDeltaIsInsert = true;
-        } else {
-            range = Range.fromPoints(delta.range.start, delta.range.start);
-            lastDeltaIsInsert = false;
-        }
-
-        for (var i = 1; i < deltas.length; i++) {
-            delta = deltas[i];
-            if (isInsert(delta)) {
-                point = delta.range.start;
-                if (range.compare(point.row, point.column) == -1) {
-                    range.setStart(delta.range.start);
-                }
-                point = delta.range.end;
-                if (range.compare(point.row, point.column) == 1) {
-                    range.setEnd(delta.range.end);
-                }
-                lastDeltaIsInsert = true;
-            } else {
-                point = delta.range.start;
-                if (range.compare(point.row, point.column) == -1) {
-                    range =
-                        Range.fromPoints(delta.range.start, delta.range.start);
-                }
-                lastDeltaIsInsert = false;
-            }
-        }
-
-        // Check if this range and the last undo range has something in common.
-        // If true, merge the ranges.
-        if (lastUndoRange != null) {
-            if (Range.comparePoints(lastUndoRange.start, range.start) == 0) {
-                lastUndoRange.start.column += range.end.column - range.start.column;
-                lastUndoRange.end.column += range.end.column - range.start.column;
-            }
-
-            var cmp = lastUndoRange.compareRange(range);
-            if (cmp == 1) {
-                range.setStart(lastUndoRange.start);
-            } else if (cmp == -1) {
-                range.setEnd(lastUndoRange.end);
-            }
-        }
-
-        return range;
-    };
-
-    /**
-    * Replaces a range in the document with the new `text`.
-    *
-    * @param {Range} range A specified Range to replace
-    * @param {String} text The new text to use as a replacement
-    * @returns {Object} An object containing the final row and column, like this:
-    * ```
-    * {row: endRow, column: 0}
-    * ```
-    * If the text and range are empty, this function returns an object containing the current `range.start` value.
-    * If the text is the exact same as what currently exists, this function returns an object containing the current `range.end` value.
-    *
-    *
-    *
-    * @related Document.replace
-    *
-    *
-    **/
-    this.replace = function(range, text) {
-        return this.doc.replace(range, text);
-    };
-
-    /**
-    * Moves a range of text from the given range to the given position. `toPosition` is an object that looks like this:
-     *  ```json
-    *    { row: newRowLocation, column: newColumnLocation }
-     *  ```
-     * @param {Range} fromRange The range of text you want moved within the document
-     * @param {Object} toPosition The location (row and column) where you want to move the text to
-     * @returns {Range} The new range where the text was moved to.
-    *
-    *
-    *
-    **/
-    this.moveText = function(fromRange, toPosition, copy) {
-        var text = this.getTextRange(fromRange);
-        var folds = this.getFoldsInRange(fromRange);
-
-        var toRange = Range.fromPoints(toPosition, toPosition);
-        if (!copy) {
-            this.remove(fromRange);
-            var rowDiff = fromRange.start.row - fromRange.end.row;
-            var collDiff = rowDiff ? -fromRange.end.column : fromRange.start.column - fromRange.end.column;
-            if (collDiff) {
-                if (toRange.start.row == fromRange.end.row && toRange.start.column > fromRange.end.column)
-                    toRange.start.column += collDiff;
-                if (toRange.end.row == fromRange.end.row && toRange.end.column > fromRange.end.column)
-                    toRange.end.column += collDiff;
-            }
-            if (rowDiff && toRange.start.row >= fromRange.end.row) {
-                toRange.start.row += rowDiff;
-                toRange.end.row += rowDiff;
-            }
-        }
-
-        toRange.end = this.insert(toRange.start, text);
-        if (folds.length) {
-            var oldStart = fromRange.start;
-            var newStart = toRange.start;
-            var rowDiff = newStart.row - oldStart.row;
-            var collDiff = newStart.column - oldStart.column;
-            this.addFolds(folds.map(function(x) {
-                x = x.clone();
-                if (x.start.row == oldStart.row)
-                    x.start.column += collDiff;
-                if (x.end.row == oldStart.row)
-                    x.end.column += collDiff;
-                x.start.row += rowDiff;
-                x.end.row += rowDiff;
-                return x;
-            }));
-        }
-
-        return toRange;
-    };
-
-    /**
-    * Indents all the rows, from `startRow` to `endRow` (inclusive), by prefixing each row with the token in `indentString`.
-    *
-    * If `indentString` contains the `'\t'` character, it's replaced by whatever is defined by [[EditSession.getTabString `getTabString()`]].
-    * @param {Number} startRow Starting row
-    * @param {Number} endRow Ending row
-    * @param {String} indentString The indent token
-    *
-    *
-    **/
-    this.indentRows = function(startRow, endRow, indentString) {
-        indentString = indentString.replace(/\t/g, this.getTabString());
-        for (var row=startRow; row<=endRow; row++)
-            this.insert({row: row, column:0}, indentString);
-    };
-
-    /**
-    * Outdents all the rows defined by the `start` and `end` properties of `range`.
-    * @param {Range} range A range of rows
-    *
-    *
-    **/
-    this.outdentRows = function (range) {
-        var rowRange = range.collapseRows();
-        var deleteRange = new Range(0, 0, 0, 0);
-        var size = this.getTabSize();
-
-        for (var i = rowRange.start.row; i <= rowRange.end.row; ++i) {
-            var line = this.getLine(i);
-
-            deleteRange.start.row = i;
-            deleteRange.end.row = i;
-            for (var j = 0; j < size; ++j)
-                if (line.charAt(j) != ' ')
-                    break;
-            if (j < size && line.charAt(j) == '\t') {
-                deleteRange.start.column = j;
-                deleteRange.end.column = j + 1;
-            } else {
-                deleteRange.start.column = 0;
-                deleteRange.end.column = j;
-            }
-            this.remove(deleteRange);
-        }
-    };
-
-    this.$moveLines = function(firstRow, lastRow, dir) {
-        firstRow = this.getRowFoldStart(firstRow);
-        lastRow = this.getRowFoldEnd(lastRow);
-        if (dir < 0) {
-            var row = this.getRowFoldStart(firstRow + dir);
-            if (row < 0) return 0;
-            var diff = row-firstRow;
-        } else if (dir > 0) {
-            var row = this.getRowFoldEnd(lastRow + dir);
-            if (row > this.doc.getLength()-1) return 0;
-            var diff = row-lastRow;
-        } else {
-            firstRow = this.$clipRowToDocument(firstRow);
-            lastRow = this.$clipRowToDocument(lastRow);
-            var diff = lastRow - firstRow + 1;
-        }
-
-        var range = new Range(firstRow, 0, lastRow, Number.MAX_VALUE);
-        var folds = this.getFoldsInRange(range).map(function(x){
-            x = x.clone();
-            x.start.row += diff;
-            x.end.row += diff;
-            return x;
-        });
-
-        var lines = dir == 0
-            ? this.doc.getLines(firstRow, lastRow)
-            : this.doc.removeLines(firstRow, lastRow);
-        this.doc.insertLines(firstRow+diff, lines);
-        folds.length && this.addFolds(folds);
-        return diff;
-    };
-    /**
-    * Shifts all the lines in the document up one, starting from `firstRow` and ending at `lastRow`.
-    * @param {Number} firstRow The starting row to move up
-    * @param {Number} lastRow The final row to move up
-    * @returns {Number} If `firstRow` is less-than or equal to 0, this function returns 0. Otherwise, on success, it returns -1.
-    *
-    * @related Document.insertLines
-    *
-    **/
-    this.moveLinesUp = function(firstRow, lastRow) {
-        return this.$moveLines(firstRow, lastRow, -1);
-    };
-
-    /**
-    * Shifts all the lines in the document down one, starting from `firstRow` and ending at `lastRow`.
-    * @param {Number} firstRow The starting row to move down
-    * @param {Number} lastRow The final row to move down
-    * @returns {Number} If `firstRow` is less-than or equal to 0, this function returns 0. Otherwise, on success, it returns -1.
-    *
-    * @related Document.insertLines
-    **/
-    this.moveLinesDown = function(firstRow, lastRow) {
-        return this.$moveLines(firstRow, lastRow, 1);
-    };
-
-    /**
-    * Duplicates all the text between `firstRow` and `lastRow`.
-    * @param {Number} firstRow The starting row to duplicate
-    * @param {Number} lastRow The final row to duplicate
-    * @returns {Number} Returns the number of new rows added; in other words, `lastRow - firstRow + 1`.
-    *
-    *
-    **/
-    this.duplicateLines = function(firstRow, lastRow) {
-        return this.$moveLines(firstRow, lastRow, 0);
-    };
-
-
-    this.$clipRowToDocument = function(row) {
-        return Math.max(0, Math.min(row, this.doc.getLength()-1));
-    };
-
-    this.$clipColumnToRow = function(row, column) {
-        if (column < 0)
-            return 0;
-        return Math.min(this.doc.getLine(row).length, column);
-    };
-
-
-    this.$clipPositionToDocument = function(row, column) {
-        column = Math.max(0, column);
-
-        if (row < 0) {
-            row = 0;
-            column = 0;
-        } else {
-            var len = this.doc.getLength();
-            if (row >= len) {
-                row = len - 1;
-                column = this.doc.getLine(len-1).length;
-            } else {
-                column = Math.min(this.doc.getLine(row).length, column);
-            }
-        }
-
-        return {
-            row: row,
-            column: column
-        };
-    };
-
-    this.$clipRangeToDocument = function(range) {
-        if (range.start.row < 0) {
-            range.start.row = 0;
-            range.start.column = 0;
-        } else {
-            range.start.column = this.$clipColumnToRow(
-                range.start.row,
-                range.start.column
-            );
-        }
-
-        var len = this.doc.getLength() - 1;
-        if (range.end.row > len) {
-            range.end.row = len;
-            range.end.column = this.doc.getLine(len).length;
-        } else {
-            range.end.column = this.$clipColumnToRow(
-                range.end.row,
-                range.end.column
-            );
-        }
-        return range;
-    };
-
-    // WRAPMODE
-    this.$wrapLimit = 80;
-    this.$useWrapMode = false;
-    this.$wrapLimitRange = {
-        min : null,
-        max : null
-    };
-
-    /**
-     * Sets whether or not line wrapping is enabled. If `useWrapMode` is different than the current value, the `'changeWrapMode'` event is emitted.
-     * @param {Boolean} useWrapMode Enable (or disable) wrap mode
-     *
-    *
-    **/
-    this.setUseWrapMode = function(useWrapMode) {
-        if (useWrapMode != this.$useWrapMode) {
-            this.$useWrapMode = useWrapMode;
-            this.$modified = true;
-            this.$resetRowCache(0);
-
-            // If wrapMode is activaed, the wrapData array has to be initialized.
-            if (useWrapMode) {
-                var len = this.getLength();
-                this.$wrapData = [];
-                for (var i = 0; i < len; i++) {
-                    this.$wrapData.push([]);
-                }
-                this.$updateWrapData(0, len - 1);
-            }
-
-            this._emit("changeWrapMode");
-        }
-    };
-
-    /**
-    * Returns `true` if wrap mode is being used; `false` otherwise.
-    * @returns {Boolean}
-    **/
-    this.getUseWrapMode = function() {
-        return this.$useWrapMode;
-    };
-
-    // Allow the wrap limit to move freely between min and max. Either
-    // parameter can be null to allow the wrap limit to be unconstrained
-    // in that direction. Or set both parameters to the same number to pin
-    // the limit to that value.
-    /**
-     * Sets the boundaries of wrap. Either value can be `null` to have an unconstrained wrap, or, they can be the same number to pin the limit. If the wrap limits for `min` or `max` are different, this method also emits the `'changeWrapMode'` event.
-     * @param {Number} min The minimum wrap value (the left side wrap)
-     * @param {Number} max The maximum wrap value (the right side wrap)
-     *
-    *
-    **/
-    this.setWrapLimitRange = function(min, max) {
-        if (this.$wrapLimitRange.min !== min || this.$wrapLimitRange.max !== max) {
-            this.$wrapLimitRange = {
-                min: min,
-                max: max
-            };
-            this.$modified = true;
-            // This will force a recalculation of the wrap limit
-            this._emit("changeWrapMode");
-        }
-    };
-
-    /**
-    * This should generally only be called by the renderer when a resize is detected.
-    * @param {Number} desiredLimit The new wrap limit
-    * @returns {Boolean}
-    *
-    * @private
-    **/
-    this.adjustWrapLimit = function(desiredLimit, $printMargin) {
-        var limits = this.$wrapLimitRange
-        if (limits.max < 0)
-            limits = {min: $printMargin, max: $printMargin};
-        var wrapLimit = this.$constrainWrapLimit(desiredLimit, limits.min, limits.max);
-        if (wrapLimit != this.$wrapLimit && wrapLimit > 1) {
-            this.$wrapLimit = wrapLimit;
-            this.$modified = true;
-            if (this.$useWrapMode) {
-                this.$updateWrapData(0, this.getLength() - 1);
-                this.$resetRowCache(0);
-                this._emit("changeWrapLimit");
-            }
-            return true;
-        }
-        return false;
-    };
-
-    this.$constrainWrapLimit = function(wrapLimit, min, max) {
-        if (min)
-            wrapLimit = Math.max(min, wrapLimit);
-
-        if (max)
-            wrapLimit = Math.min(max, wrapLimit);
-
-        return wrapLimit;
-    };
-
-    /**
-    * Returns the value of wrap limit.
-    * @returns {Number} The wrap limit.
-    **/
-    this.getWrapLimit = function() {
-        return this.$wrapLimit;
-    };
-    
-    /**
-     * Sets the line length for soft wrap in the editor. Lines will break
-     *  at a minimum of the given length minus 20 chars and at a maximum
-     *  of the given number of chars.
-     * @param {number} limit The maximum line length in chars, for soft wrapping lines.
-     */
-    this.setWrapLimit = function (limit) {
-        this.setWrapLimitRange(limit, limit);
-    };
-    
-    /**
-    * Returns an object that defines the minimum and maximum of the wrap limit; it looks something like this:
-    *
-    *     { min: wrapLimitRange_min, max: wrapLimitRange_max }
-    *
-    * @returns {Object}
-    **/
-    this.getWrapLimitRange = function() {
-        // Avoid unexpected mutation by returning a copy
-        return {
-            min : this.$wrapLimitRange.min,
-            max : this.$wrapLimitRange.max
-        };
-    };
-
-    this.$updateInternalDataOnChange = function(e) {
-        var useWrapMode = this.$useWrapMode;
-        var len;
-        var action = e.data.action;
-        var firstRow = e.data.range.start.row;
-        var lastRow = e.data.range.end.row;
-        var start = e.data.range.start;
-        var end = e.data.range.end;
-        var removedFolds = null;
-
-        if (action.indexOf("Lines") != -1) {
-            if (action == "insertLines") {
-                lastRow = firstRow + (e.data.lines.length);
-            } else {
-                lastRow = firstRow;
-            }
-            len = e.data.lines ? e.data.lines.length : lastRow - firstRow;
-        } else {
-            len = lastRow - firstRow;
-        }
-
-        this.$updating = true;
-        if (len != 0) {
-            if (action.indexOf("remove") != -1) {
-                this[useWrapMode ? "$wrapData" : "$rowLengthCache"].splice(firstRow, len);
-
-                var foldLines = this.$foldData;
-                removedFolds = this.getFoldsInRange(e.data.range);
-                this.removeFolds(removedFolds);
-
-                var foldLine = this.getFoldLine(end.row);
-                var idx = 0;
-                if (foldLine) {
-                    foldLine.addRemoveChars(end.row, end.column, start.column - end.column);
-                    foldLine.shiftRow(-len);
-
-                    var foldLineBefore = this.getFoldLine(firstRow);
-                    if (foldLineBefore && foldLineBefore !== foldLine) {
-                        foldLineBefore.merge(foldLine);
-                        foldLine = foldLineBefore;
-                    }
-                    idx = foldLines.indexOf(foldLine) + 1;
-                }
-
-                for (idx; idx < foldLines.length; idx++) {
-                    var foldLine = foldLines[idx];
-                    if (foldLine.start.row >= end.row) {
-                        foldLine.shiftRow(-len);
-                    }
-                }
-
-                lastRow = firstRow;
-            } else {
-                var args;
-                if (useWrapMode) {
-                    args = [firstRow, 0];
-                    for (var i = 0; i < len; i++) args.push([]);
-                    this.$wrapData.splice.apply(this.$wrapData, args);
-                } else {
-                    args = Array(len);
-                    args.unshift(firstRow, 0);
-                    this.$rowLengthCache.splice.apply(this.$rowLengthCache, args);
-                }
-
-                // If some new line is added inside of a foldLine, then split
-                // the fold line up.
-                var foldLines = this.$foldData;
-                var foldLine = this.getFoldLine(firstRow);
-                var idx = 0;
-                if (foldLine) {
-                    var cmp = foldLine.range.compareInside(start.row, start.column)
-                    // Inside of the foldLine range. Need to split stuff up.
-                    if (cmp == 0) {
-                        foldLine = foldLine.split(start.row, start.column);
-                        foldLine.shiftRow(len);
-                        foldLine.addRemoveChars(
-                            lastRow, 0, end.column - start.column);
-                    } else
-                    // Infront of the foldLine but same row. Need to shift column.
-                    if (cmp == -1) {
-                        foldLine.addRemoveChars(firstRow, 0, end.column - start.column);
-                        foldLine.shiftRow(len);
-                    }
-                    // Nothing to do if the insert is after the foldLine.
-                    idx = foldLines.indexOf(foldLine) + 1;
-                }
-
-                for (idx; idx < foldLines.length; idx++) {
-                    var foldLine = foldLines[idx];
-                    if (foldLine.start.row >= firstRow) {
-                        foldLine.shiftRow(len);
-                    }
-                }
-            }
-        } else {
-            // Realign folds. E.g. if you add some new chars before a fold, the
-            // fold should "move" to the right.
-            len = Math.abs(e.data.range.start.column - e.data.range.end.column);
-            if (action.indexOf("remove") != -1) {
-                // Get all the folds in the change range and remove them.
-                removedFolds = this.getFoldsInRange(e.data.range);
-                this.removeFolds(removedFolds);
-
-                len = -len;
-            }
-            var foldLine = this.getFoldLine(firstRow);
-            if (foldLine) {
-                foldLine.addRemoveChars(firstRow, start.column, len);
-            }
-        }
-
-        if (useWrapMode && this.$wrapData.length != this.doc.getLength()) {
-            console.error("doc.getLength() and $wrapData.length have to be the same!");
-        }
-        this.$updating = false;
-
-        if (useWrapMode)
-            this.$updateWrapData(firstRow, lastRow);
-        else
-            this.$updateRowLengthCache(firstRow, lastRow);
-
-        return removedFolds;
-    };
-
-    this.$updateRowLengthCache = function(firstRow, lastRow, b) {
-        this.$rowLengthCache[firstRow] = null;
-        this.$rowLengthCache[lastRow] = null;
-    };
-
-    this.$updateWrapData = function(firstRow, lastRow) {
-        var lines = this.doc.getAllLines();
-        var tabSize = this.getTabSize();
-        var wrapData = this.$wrapData;
-        var wrapLimit = this.$wrapLimit;
-        var tokens;
-        var foldLine;
-
-        var row = firstRow;
-        lastRow = Math.min(lastRow, lines.length - 1);
-        while (row <= lastRow) {
-            foldLine = this.getFoldLine(row, foldLine);
-            if (!foldLine) {
-                tokens = this.$getDisplayTokens(lines[row]);
-                wrapData[row] = this.$computeWrapSplits(tokens, wrapLimit, tabSize);
-                row ++;
-            } else {
-                tokens = [];
-                foldLine.walk(function(placeholder, row, column, lastColumn) {
-                        var walkTokens;
-                        if (placeholder != null) {
-                            walkTokens = this.$getDisplayTokens(
-                                            placeholder, tokens.length);
-                            walkTokens[0] = PLACEHOLDER_START;
-                            for (var i = 1; i < walkTokens.length; i++) {
-                                walkTokens[i] = PLACEHOLDER_BODY;
-                            }
-                        } else {
-                            walkTokens = this.$getDisplayTokens(
-                                lines[row].substring(lastColumn, column),
-                                tokens.length);
-                        }
-                        tokens = tokens.concat(walkTokens);
-                    }.bind(this),
-                    foldLine.end.row,
-                    lines[foldLine.end.row].length + 1
-                );
-
-                wrapData[foldLine.start.row]
-                    = this.$computeWrapSplits(tokens, wrapLimit, tabSize);
-                row = foldLine.end.row + 1;
-            }
-        }
-    };
-
-    // "Tokens"
-    var CHAR = 1,
-        CHAR_EXT = 2,
-        PLACEHOLDER_START = 3,
-        PLACEHOLDER_BODY =  4,
-        PUNCTUATION = 9,
-        SPACE = 10,
-        TAB = 11,
-        TAB_SPACE = 12;
-
-
-    this.$computeWrapSplits = function(tokens, wrapLimit) {
-        if (tokens.length == 0) {
-            return [];
-        }
-
-        var splits = [];
-        var displayLength = tokens.length;
-        var lastSplit = 0, lastDocSplit = 0;
-
-        var isCode = this.$wrapAsCode;
-
-        function addSplit(screenPos) {
-            var displayed = tokens.slice(lastSplit, screenPos);
-
-            // The document size is the current size - the extra width for tabs
-            // and multipleWidth characters.
-            var len = displayed.length;
-            displayed.join("").
-                // Get all the TAB_SPACEs.
-                replace(/12/g, function() {
-                    len -= 1;
-                }).
-                // Get all the CHAR_EXT/multipleWidth characters.
-                replace(/2/g, function() {
-                    len -= 1;
-                });
-
-            lastDocSplit += len;
-            splits.push(lastDocSplit);
-            lastSplit = screenPos;
-        }
-
-        while (displayLength - lastSplit > wrapLimit) {
-            // This is, where the split should be.
-            var split = lastSplit + wrapLimit;
-
-            // If there is a space or tab at this split position, then making
-            // a split is simple.
-            if (tokens[split - 1] >= SPACE && tokens[split] >= SPACE) {
-                /* disabled see https://github.com/ajaxorg/ace/issues/1186
-                // Include all following spaces + tabs in this split as well.
-                while (tokens[split] >= SPACE) {
-                    split ++;
-                } */
-                addSplit(split);
-                continue;
-            }
-
-            // === ELSE ===
-            // Check if split is inside of a placeholder. Placeholder are
-            // not splitable. Therefore, seek the beginning of the placeholder
-            // and try to place the split beofre the placeholder's start.
-            if (tokens[split] == PLACEHOLDER_START || tokens[split] == PLACEHOLDER_BODY) {
-                // Seek the start of the placeholder and do the split
-                // before the placeholder. By definition there always
-                // a PLACEHOLDER_START between split and lastSplit.
-                for (split; split != lastSplit - 1; split--) {
-                    if (tokens[split] == PLACEHOLDER_START) {
-                        // split++; << No incremental here as we want to
-                        //  have the position before the Placeholder.
-                        break;
-                    }
-                }
-
-                // If the PLACEHOLDER_START is not the index of the
-                // last split, then we can do the split
-                if (split > lastSplit) {
-                    addSplit(split);
-                    continue;
-                }
-
-                // If the PLACEHOLDER_START IS the index of the last
-                // split, then we have to place the split after the
-                // placeholder. So, let's seek for the end of the placeholder.
-                split = lastSplit + wrapLimit;
-                for (split; split < tokens.length; split++) {
-                    if (tokens[split] != PLACEHOLDER_BODY) {
-                        break;
-                    }
-                }
-
-                // If spilt == tokens.length, then the placeholder is the last
-                // thing in the line and adding a new split doesn't make sense.
-                if (split == tokens.length) {
-                    break;  // Breaks the while-loop.
-                }
-
-                // Finally, add the split...
-                addSplit(split);
-                continue;
-            }
-
-            // === ELSE ===
-            // Search for the first non space/tab/placeholder/punctuation token backwards.
-            var minSplit = Math.max(split - (isCode ? 10 : wrapLimit-(wrapLimit>>2)), lastSplit - 1);
-            while (split > minSplit && tokens[split] < PLACEHOLDER_START) {
-                split --;
-            }
-            if (isCode) {
-                while (split > minSplit && tokens[split] < PLACEHOLDER_START) {
-                    split --;
-                }
-                while (split > minSplit && tokens[split] == PUNCTUATION) {
-                    split --;
-                }
-            } else {
-                while (split > minSplit && tokens[split] < SPACE) {
-                    split --;
-                }
-            }
-            // If we found one, then add the split.
-            if (split > minSplit) {
-                addSplit(++split);
-                continue;
-            }
-
-            // === ELSE ===
-            split = lastSplit + wrapLimit;
-            // The split is inside of a CHAR or CHAR_EXT token and no space
-            // around -> force a split.
-            addSplit(split);
-        }
-        return splits;
-    };
-
-    /**
-    * Given a string, returns an array of the display characters, including tabs and spaces.
-    * @param {String} str The string to check
-    * @param {Number} offset The value to start at
-    *
-    *
-    **/
-    this.$getDisplayTokens = function(str, offset) {
-        var arr = [];
-        var tabSize;
-        offset = offset || 0;
-
-        for (var i = 0; i < str.length; i++) {
-            var c = str.charCodeAt(i);
-            // Tab
-            if (c == 9) {
-                tabSize = this.getScreenTabSize(arr.length + offset);
-                arr.push(TAB);
-                for (var n = 1; n < tabSize; n++) {
-                    arr.push(TAB_SPACE);
-                }
-            }
-            // Space
-            else if (c == 32) {
-                arr.push(SPACE);
-            } else if((c > 39 && c < 48) || (c > 57 && c < 64)) {
-                arr.push(PUNCTUATION);
-            }
-            // full width characters
-            else if (c >= 0x1100 && isFullWidth(c)) {
-                arr.push(CHAR, CHAR_EXT);
-            } else {
-                arr.push(CHAR);
-            }
-        }
-        return arr;
-    };
-
-    /**
-     * Calculates the width of the string `str` on the screen while assuming that the string starts at the first column on the screen.
-    * @param {String} str The string to calculate the screen width of
-    * @param {Number} maxScreenColumn
-    * @param {Number} screenColumn
-    * @returns {[Number]} Returns an `int[]` array with two elements:<br/>
-    * The first position indicates the number of columns for `str` on screen.<br/>
-    * The second value contains the position of the document column that this function read until.
-    *
-    *
-    *
-    *
-    **/
-    this.$getStringScreenWidth = function(str, maxScreenColumn, screenColumn) {
-        if (maxScreenColumn == 0)
-            return [0, 0];
-        if (maxScreenColumn == null)
-            maxScreenColumn = Infinity;
-        screenColumn = screenColumn || 0;
-
-        var c, column;
-        for (column = 0; column < str.length; column++) {
-            c = str.charCodeAt(column);
-            // tab
-            if (c == 9) {
-                screenColumn += this.getScreenTabSize(screenColumn);
-            }
-            // full width characters
-            else if (c >= 0x1100 && isFullWidth(c)) {
-                screenColumn += 2;
-            } else {
-                screenColumn += 1;
-            }
-            if (screenColumn > maxScreenColumn) {
-                break;
-            }
-        }
-
-        return [screenColumn, column];
-    };
-
-    this.lineWidgets = null;
-    /**
-    * Returns number of screenrows in a wrapped line.
-    * @param {Number} row The row number to check
-    *
-    * @returns {Number}
-    **/
-    this.getRowLength = function(row) {
-        if (this.lineWidgets)
-            var h = this.lineWidgets[row] && this.lineWidgets[row].rowCount || 0;
-        else 
-            h = 0
-        if (!this.$useWrapMode || !this.$wrapData[row]) {
-            return 1 + h;
-        } else {
-            return this.$wrapData[row].length + 1 + h;
-        }
-    };
-    this.getRowLineCount = function(row) {
-        if (!this.$useWrapMode || !this.$wrapData[row]) {
-            return 1;
-        } else {
-            return this.$wrapData[row].length + 1;
-        }
-    };
-
-    /**
-     * Returns the position (on screen) for the last character in the provided screen row.
-     * @param {Number} screenRow The screen row to check
-     * @returns {Number}
-     *
-     * @related EditSession.documentToScreenColumn
-    **/
-    this.getScreenLastRowColumn = function(screenRow) {
-        var pos = this.screenToDocumentPosition(screenRow, Number.MAX_VALUE);
-        return this.documentToScreenColumn(pos.row, pos.column);
-    };
-
-    /**
-    * For the given document row and column, this returns the column position of the last screen row.
-    * @param {Number} docRow
-    *
-    * @param {Number} docColumn
-    **/
-    this.getDocumentLastRowColumn = function(docRow, docColumn) {
-        var screenRow = this.documentToScreenRow(docRow, docColumn);
-        return this.getScreenLastRowColumn(screenRow);
-    };
-
-    /**
-    * For the given document row and column, this returns the document position of the last row.
-    * @param {Number} docRow
-    * @param {Number} docColumn
-    *
-    *
-    **/
-    this.getDocumentLastRowColumnPosition = function(docRow, docColumn) {
-        var screenRow = this.documentToScreenRow(docRow, docColumn);
-        return this.screenToDocumentPosition(screenRow, Number.MAX_VALUE / 10);
-    };
-
-    /**
-    * For the given row, this returns the split data.
-    * @returns {String}
-    **/
-    this.getRowSplitData = function(row) {
-        if (!this.$useWrapMode) {
-            return undefined;
-        } else {
-            return this.$wrapData[row];
-        }
-    };
-
-    /**
-    * The distance to the next tab stop at the specified screen column.
-    * @param {Number} screenColumn The screen column to check
-    *
-    *
-    * @returns {Number}
-    **/
-    this.getScreenTabSize = function(screenColumn) {
-        return this.$tabSize - screenColumn % this.$tabSize;
-    };
-
-
-    this.screenToDocumentRow = function(screenRow, screenColumn) {
-        return this.screenToDocumentPosition(screenRow, screenColumn).row;
-    };
-
-
-    this.screenToDocumentColumn = function(screenRow, screenColumn) {
-        return this.screenToDocumentPosition(screenRow, screenColumn).column;
-    };
-
-    /**
-    * Converts characters coordinates on the screen to characters coordinates within the document. [This takes into account code folding, word wrap, tab size, and any other visual modifications.]{: #conversionConsiderations}
-    * @param {Number} screenRow The screen row to check
-    * @param {Number} screenColumn The screen column to check
-    * @returns {Object} The object returned has two properties: `row` and `column`.
-    *
-    *
-    * @related EditSession.documentToScreenPosition
-    *
-    **/
-    this.screenToDocumentPosition = function(screenRow, screenColumn) {
-        if (screenRow < 0)
-            return {row: 0, column: 0};
-
-        var line;
-        var docRow = 0;
-        var docColumn = 0;
-        var column;
-        var row = 0;
-        var rowLength = 0;
-
-        var rowCache = this.$screenRowCache;
-        var i = this.$getRowCacheIndex(rowCache, screenRow);
-        var l = rowCache.length;
-        if (l && i >= 0) {
-            var row = rowCache[i];
-            var docRow = this.$docRowCache[i];
-            var doCache = screenRow > rowCache[l - 1];
-        } else {
-            var doCache = !l;
-        }
-
-        var maxRow = this.getLength() - 1;
-        var foldLine = this.getNextFoldLine(docRow);
-        var foldStart = foldLine ? foldLine.start.row : Infinity;
-
-        while (row <= screenRow) {
-            rowLength = this.getRowLength(docRow);
-            if (row + rowLength > screenRow || docRow >= maxRow) {
-                break;
-            } else {
-                row += rowLength;
-                docRow++;
-                if (docRow > foldStart) {
-                    docRow = foldLine.end.row+1;
-                    foldLine = this.getNextFoldLine(docRow, foldLine);
-                    foldStart = foldLine ? foldLine.start.row : Infinity;
-                }
-            }
-
-            if (doCache) {
-                this.$docRowCache.push(docRow);
-                this.$screenRowCache.push(row);
-            }
-        }
-
-        if (foldLine && foldLine.start.row <= docRow) {
-            line = this.getFoldDisplayLine(foldLine);
-            docRow = foldLine.start.row;
-        } else if (row + rowLength <= screenRow || docRow > maxRow) {
-            // clip at the end of the document
-            return {
-                row: maxRow,
-                column: this.getLine(maxRow).length
-            }
-        } else {
-            line = this.getLine(docRow);
-            foldLine = null;
-        }
-
-        if (this.$useWrapMode) {
-            var splits = this.$wrapData[docRow];
-            if (splits) {
-                var splitIndex = Math.floor(screenRow - row);
-                column = splits[splitIndex];
-                if(splitIndex > 0 && splits.length) {
-                    docColumn = splits[splitIndex - 1] || splits[splits.length - 1];
-                    line = line.substring(docColumn);
-                }
-            }
-        }
-
-        docColumn += this.$getStringScreenWidth(line, screenColumn)[1];
-
-        // We remove one character at the end so that the docColumn
-        // position returned is not associated to the next row on the screen.
-        if (this.$useWrapMode && docColumn >= column)
-            docColumn = column - 1;
-
-        if (foldLine)
-            return foldLine.idxToPosition(docColumn);
-
-        return {row: docRow, column: docColumn};
-    };
-
-    /**
-    * Converts document coordinates to screen coordinates. {:conversionConsiderations}
-    * @param {Number} docRow The document row to check
-    * @param {Number} docColumn The document column to check
-    * @returns {Object} The object returned by this method has two properties: `row` and `column`.
-    *
-    *
-    * @related EditSession.screenToDocumentPosition
-    *
-    **/
-    this.documentToScreenPosition = function(docRow, docColumn) {
-        // Normalize the passed in arguments.
-        if (typeof docColumn === "undefined")
-            var pos = this.$clipPositionToDocument(docRow.row, docRow.column);
-        else
-            pos = this.$clipPositionToDocument(docRow, docColumn);
-
-        docRow = pos.row;
-        docColumn = pos.column;
-
-        var screenRow = 0;
-        var foldStartRow = null;
-        var fold = null;
-
-        // Clamp the docRow position in case it's inside of a folded block.
-        fold = this.getFoldAt(docRow, docColumn, 1);
-        if (fold) {
-            docRow = fold.start.row;
-            docColumn = fold.start.column;
-        }
-
-        var rowEnd, row = 0;
-
-
-        var rowCache = this.$docRowCache;
-        var i = this.$getRowCacheIndex(rowCache, docRow);
-        var l = rowCache.length;
-        if (l && i >= 0) {
-            var row = rowCache[i];
-            var screenRow = this.$screenRowCache[i];
-            var doCache = docRow > rowCache[l - 1];
-        } else {
-            var doCache = !l;
-        }
-
-        var foldLine = this.getNextFoldLine(row);
-        var foldStart = foldLine ?foldLine.start.row :Infinity;
-
-        while (row < docRow) {
-            if (row >= foldStart) {
-                rowEnd = foldLine.end.row + 1;
-                if (rowEnd > docRow)
-                    break;
-                foldLine = this.getNextFoldLine(rowEnd, foldLine);
-                foldStart = foldLine ?foldLine.start.row :Infinity;
-            }
-            else {
-                rowEnd = row + 1;
-            }
-
-            screenRow += this.getRowLength(row);
-            row = rowEnd;
-
-            if (doCache) {
-                this.$docRowCache.push(row);
-                this.$screenRowCache.push(screenRow);
-            }
-        }
-
-        // Calculate the text line that is displayed in docRow on the screen.
-        var textLine = "";
-        // Check if the final row we want to reach is inside of a fold.
-        if (foldLine && row >= foldStart) {
-            textLine = this.getFoldDisplayLine(foldLine, docRow, docColumn);
-            foldStartRow = foldLine.start.row;
-        } else {
-            textLine = this.getLine(docRow).substring(0, docColumn);
-            foldStartRow = docRow;
-        }
-        // Clamp textLine if in wrapMode.
-        if (this.$useWrapMode) {
-            var wrapRow = this.$wrapData[foldStartRow];
-            var screenRowOffset = 0;
-            while (textLine.length >= wrapRow[screenRowOffset]) {
-                screenRow ++;
-                screenRowOffset++;
-            }
-            textLine = textLine.substring(
-                wrapRow[screenRowOffset - 1] || 0, textLine.length
-            );
-        }
-
-        return {
-            row: screenRow,
-            column: this.$getStringScreenWidth(textLine)[0]
-        };
-    };
-
-    /**
-    * For the given document row and column, returns the screen column.
-    * @param {Number} row
-    * @param {Number} docColumn
-    * @returns {Number}
-    *
-    **/
-    this.documentToScreenColumn = function(row, docColumn) {
-        return this.documentToScreenPosition(row, docColumn).column;
-    };
-
-    /**
-    * For the given document row and column, returns the screen row.
-    * @param {Number} docRow
-    * @param {Number} docColumn
-    *
-    *
-    **/
-    this.documentToScreenRow = function(docRow, docColumn) {
-        return this.documentToScreenPosition(docRow, docColumn).row;
-    };
-
-    /**
-    * Returns the length of the screen.
-    * @returns {Number}
-    **/
-    this.getScreenLength = function() {
-        var screenRows = 0;
-        var fold = null;
-        if (!this.$useWrapMode) {
-            screenRows = this.getLength();
-
-            // Remove the folded lines again.
-            var foldData = this.$foldData;
-            for (var i = 0; i < foldData.length; i++) {
-                fold = foldData[i];
-                screenRows -= fold.end.row - fold.start.row;
-            }
-        } else {
-            var lastRow = this.$wrapData.length;
-            var row = 0, i = 0;
-            var fold = this.$foldData[i++];
-            var foldStart = fold ? fold.start.row :Infinity;
-
-            while (row < lastRow) {
-                screenRows += this.$wrapData[row].length + 1;
-                row ++;
-                if (row > foldStart) {
-                    row = fold.end.row+1;
-                    fold = this.$foldData[i++];
-                    foldStart = fold ?fold.start.row :Infinity;
-                }
-            }
-        }
-
-        // todo
-        if (this.lineWidgets)
-            screenRows += this.$getWidgetScreenLength();
-
-        return screenRows;
-    };
-
-    // For every keystroke this gets called once per char in the whole doc!!
-    // Wouldn't hurt to make it a bit faster for c >= 0x1100
-
-    /**
-     * @private
-     *
-     */
-    function isFullWidth(c) {
-        if (c < 0x1100)
-            return false;
-        return c >= 0x1100 && c <= 0x115F ||
-               c >= 0x11A3 && c <= 0x11A7 ||
-               c >= 0x11FA && c <= 0x11FF ||
-               c >= 0x2329 && c <= 0x232A ||
-               c >= 0x2E80 && c <= 0x2E99 ||
-               c >= 0x2E9B && c <= 0x2EF3 ||
-               c >= 0x2F00 && c <= 0x2FD5 ||
-               c >= 0x2FF0 && c <= 0x2FFB ||
-               c >= 0x3000 && c <= 0x303E ||
-               c >= 0x3041 && c <= 0x3096 ||
-               c >= 0x3099 && c <= 0x30FF ||
-               c >= 0x3105 && c <= 0x312D ||
-               c >= 0x3131 && c <= 0x318E ||
-               c >= 0x3190 && c <= 0x31BA ||
-               c >= 0x31C0 && c <= 0x31E3 ||
-               c >= 0x31F0 && c <= 0x321E ||
-               c >= 0x3220 && c <= 0x3247 ||
-               c >= 0x3250 && c <= 0x32FE ||
-               c >= 0x3300 && c <= 0x4DBF ||
-               c >= 0x4E00 && c <= 0xA48C ||
-               c >= 0xA490 && c <= 0xA4C6 ||
-               c >= 0xA960 && c <= 0xA97C ||
-               c >= 0xAC00 && c <= 0xD7A3 ||
-               c >= 0xD7B0 && c <= 0xD7C6 ||
-               c >= 0xD7CB && c <= 0xD7FB ||
-               c >= 0xF900 && c <= 0xFAFF ||
-               c >= 0xFE10 && c <= 0xFE19 ||
-               c >= 0xFE30 && c <= 0xFE52 ||
-               c >= 0xFE54 && c <= 0xFE66 ||
-               c >= 0xFE68 && c <= 0xFE6B ||
-               c >= 0xFF01 && c <= 0xFF60 ||
-               c >= 0xFFE0 && c <= 0xFFE6;
-    };
-
-}).call(EditSession.prototype);
-
-require("./edit_session/folding").Folding.call(EditSession.prototype);
-require("./edit_session/bracket_match").BracketMatch.call(EditSession.prototype);
-
-
-config.defineOptions(EditSession.prototype, "session", {
-    wrap: {
-        set: function(value) {
-            if (!value || value == "off")
-                value = false;
-            else if (value == "free")
-                value = true;
-            else if (value == "printMargin")
-                value = -1;
-            else if (typeof value == "string")
-                value = parseInt(value, 10) || false;
-
-            if (this.$wrap == value)
-                return;
-            if (!value) {
-                this.setUseWrapMode(false);
-            } else {
-                var col = typeof value == "number" ? value : null;
-                this.setWrapLimitRange(col, col);
-                this.setUseWrapMode(true);
-            }
-            this.$wrap = value;
-        },
-        get: function() {
-            return this.getUseWrapMode() ? this.getWrapLimitRange().min || "free" : "off";
-        },
-        handlesSet: true
-    },    
-    wrapMethod: {
-        // code|text|auto
-        set: function(val) {
-            val = val == "auto"
-                ? this.$mode.type != "text"
-                : val != "text";
-            if (val != this.$wrapAsCode) {
-                this.$wrapAsCode = val;
-                if (this.$useWrapMode) {
-                    this.$modified = true;
-                    this.$resetRowCache(0);
-                    this.$updateWrapData(0, this.getLength() - 1);
-                }
-            }
-        },
-        initialValue: "auto"
-    },
-    firstLineNumber: {
-        set: function() {this._emit("changeBreakpoint");},
-        initialValue: 1
-    },
-    useWorker: {
-        set: function(useWorker) {
-            this.$useWorker = useWorker;
-
-            this.$stopWorker();
-            if (useWorker)
-                this.$startWorker();
-        },
-        initialValue: true
-    },
-    useSoftTabs: {initialValue: true},
-    tabSize: {
-        set: function(tabSize) {
-            if (isNaN(tabSize) || this.$tabSize === tabSize) return;
-
-            this.$modified = true;
-            this.$rowLengthCache = [];
-            this.$tabSize = tabSize;
-            this._emit("changeTabSize");
-        },
-        initialValue: 4,
-        handlesSet: true
-    },
-    overwrite: {
-        set: function(val) {this._emit("changeOverwrite");},
-        initialValue: false
-    },
-    newLineMode: {
-        set: function(val) {this.doc.setNewLineMode(val)},
-        get: function() {return this.doc.getNewLineMode()},
-        handlesSet: true
-    }
-});
-
-exports.EditSession = EditSession;
-});

+ 0 - 219
services/web/public/js/ace/edit_session/bracket_match.js

@@ -1,219 +0,0 @@
-/* ***** 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 TokenIterator = require("../token_iterator").TokenIterator;
-var Range = require("../range").Range;
-
-
-function BracketMatch() {
-
-    this.findMatchingBracket = function(position, chr) {
-        if (position.column == 0) return null;
-
-        var charBeforeCursor = chr || this.getLine(position.row).charAt(position.column-1);
-        if (charBeforeCursor == "") return null;
-
-        var match = charBeforeCursor.match(/([\(\[\{])|([\)\]\}])/);
-        if (!match)
-            return null;
-
-        if (match[1])
-            return this.$findClosingBracket(match[1], position);
-        else
-            return this.$findOpeningBracket(match[2], position);
-    };
-    
-    this.getBracketRange = function(pos) {
-        var line = this.getLine(pos.row);
-        var before = true, range;
-
-        var chr = line.charAt(pos.column-1);
-        var match = chr && chr.match(/([\(\[\{])|([\)\]\}])/);
-        if (!match) {
-            chr = line.charAt(pos.column);
-            pos = {row: pos.row, column: pos.column + 1};
-            match = chr && chr.match(/([\(\[\{])|([\)\]\}])/);
-            before = false;
-        }
-        if (!match)
-            return null;
-
-        if (match[1]) {
-            var bracketPos = this.$findClosingBracket(match[1], pos);
-            if (!bracketPos)
-                return null;
-            range = Range.fromPoints(pos, bracketPos);
-            if (!before) {
-                range.end.column++;
-                range.start.column--;
-            }
-            range.cursor = range.end;
-        } else {
-            var bracketPos = this.$findOpeningBracket(match[2], pos);
-            if (!bracketPos)
-                return null;
-            range = Range.fromPoints(bracketPos, pos);
-            if (!before) {
-                range.start.column++;
-                range.end.column--;
-            }
-            range.cursor = range.start;
-        }
-        
-        return range;
-    };
-
-    this.$brackets = {
-        ")": "(",
-        "(": ")",
-        "]": "[",
-        "[": "]",
-        "{": "}",
-        "}": "{"
-    };
-
-    this.$findOpeningBracket = function(bracket, position, typeRe) {
-        var openBracket = this.$brackets[bracket];
-        var depth = 1;
-
-        var iterator = new TokenIterator(this, position.row, position.column);
-        var token = iterator.getCurrentToken();
-        if (!token)
-            token = iterator.stepForward();
-        if (!token)
-            return;
-        
-         if (!typeRe){
-            typeRe = new RegExp(
-                "(\\.?" +
-                token.type.replace(".", "\\.").replace("rparen", ".paren")
-                + ")+"
-            );
-        }
-        
-        // Start searching in token, just before the character at position.column
-        var valueIndex = position.column - iterator.getCurrentTokenColumn() - 2;
-        var value = token.value;
-        
-        while (true) {
-        
-            while (valueIndex >= 0) {
-                var chr = value.charAt(valueIndex);
-                if (chr == openBracket) {
-                    depth -= 1;
-                    if (depth == 0) {
-                        return {row: iterator.getCurrentTokenRow(),
-                            column: valueIndex + iterator.getCurrentTokenColumn()};
-                    }
-                }
-                else if (chr == bracket) {
-                    depth += 1;
-                }
-                valueIndex -= 1;
-            }
-
-            // Scan backward through the document, looking for the next token
-            // whose type matches typeRe
-            do {
-                token = iterator.stepBackward();
-            } while (token && !typeRe.test(token.type));
-
-            if (token == null)
-                break;
-                
-            value = token.value;
-            valueIndex = value.length - 1;
-        }
-        
-        return null;
-    };
-
-    this.$findClosingBracket = function(bracket, position, typeRe) {
-        var closingBracket = this.$brackets[bracket];
-        var depth = 1;
-
-        var iterator = new TokenIterator(this, position.row, position.column);
-        var token = iterator.getCurrentToken();
-        if (!token)
-            token = iterator.stepForward();
-        if (!token)
-            return;
-
-        if (!typeRe){
-            typeRe = new RegExp(
-                "(\\.?" +
-                token.type.replace(".", "\\.").replace("lparen", ".paren")
-                + ")+"
-            );
-        }
-
-        // Start searching in token, after the character at position.column
-        var valueIndex = position.column - iterator.getCurrentTokenColumn();
-
-        while (true) {
-
-            var value = token.value;
-            var valueLength = value.length;
-            while (valueIndex < valueLength) {
-                var chr = value.charAt(valueIndex);
-                if (chr == closingBracket) {
-                    depth -= 1;
-                    if (depth == 0) {
-                        return {row: iterator.getCurrentTokenRow(),
-                            column: valueIndex + iterator.getCurrentTokenColumn()};
-                    }
-                }
-                else if (chr == bracket) {
-                    depth += 1;
-                }
-                valueIndex += 1;
-            }
-
-            // Scan forward through the document, looking for the next token
-            // whose type matches typeRe
-            do {
-                token = iterator.stepForward();
-            } while (token && !typeRe.test(token.type));
-
-            if (token == null)
-                break;
-
-            valueIndex = 0;
-        }
-        
-        return null;
-    };
-}
-exports.BracketMatch = BracketMatch;
-
-});

+ 0 - 140
services/web/public/js/ace/edit_session/fold.js

@@ -1,140 +0,0 @@
-/* ***** 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 Range = require("../range").Range;
-var RangeList = require("../range_list").RangeList;
-var oop = require("../lib/oop")
-/*
- * Simple fold-data struct.
- **/
-var Fold = exports.Fold = function(range, placeholder) {
-    this.foldLine = null;
-    this.placeholder = placeholder;
-    this.range = range;
-    this.start = range.start;
-    this.end = range.end;
-
-    this.sameRow = range.start.row == range.end.row;
-    this.subFolds = this.ranges = [];
-};
-
-oop.inherits(Fold, RangeList);
-
-(function() {
-
-    this.toString = function() {
-        return '"' + this.placeholder + '" ' + this.range.toString();
-    };
-
-    this.setFoldLine = function(foldLine) {
-        this.foldLine = foldLine;
-        this.subFolds.forEach(function(fold) {
-            fold.setFoldLine(foldLine);
-        });
-    };
-
-    this.clone = function() {
-        var range = this.range.clone();
-        var fold = new Fold(range, this.placeholder);
-        this.subFolds.forEach(function(subFold) {
-            fold.subFolds.push(subFold.clone());
-        });
-        fold.collapseChildren = this.collapseChildren;
-        return fold;
-    };
-
-    this.addSubFold = function(fold) {
-        if (this.range.isEqual(fold))
-            return;
-
-        if (!this.range.containsRange(fold))
-            throw new Error("A fold can't intersect already existing fold" + fold.range + this.range);
-
-        // transform fold to local coordinates
-        consumeRange(fold, this.start);
-
-        var row = fold.start.row, column = fold.start.column;
-        for (var i = 0, cmp = -1; i < this.subFolds.length; i++) {
-            cmp = this.subFolds[i].range.compare(row, column);
-            if (cmp != 1)
-                break;
-        }
-        var afterStart = this.subFolds[i];
-
-        if (cmp == 0)
-            return afterStart.addSubFold(fold);
-
-        // cmp == -1
-        var row = fold.range.end.row, column = fold.range.end.column;
-        for (var j = i, cmp = -1; j < this.subFolds.length; j++) {
-            cmp = this.subFolds[j].range.compare(row, column);
-            if (cmp != 1)
-                break;
-        }
-        var afterEnd = this.subFolds[j];
-
-        if (cmp == 0)
-            throw new Error("A fold can't intersect already existing fold" + fold.range + this.range);
-
-        var consumedFolds = this.subFolds.splice(i, j - i, fold);
-        fold.setFoldLine(this.foldLine);
-
-        return fold;
-    };
-    
-    this.restoreRange = function(range) {
-        return restoreRange(range, this.start);
-    };
-
-}).call(Fold.prototype);
-
-function consumePoint(point, anchor) {
-    point.row -= anchor.row;
-    if (point.row == 0)
-        point.column -= anchor.column;
-}
-function consumeRange(range, anchor) {
-    consumePoint(range.start, anchor);
-    consumePoint(range.end, anchor);
-}
-function restorePoint(point, anchor) {
-    if (point.row == 0)
-        point.column += anchor.column;
-    point.row += anchor.row;
-}
-function restoreRange(range, anchor) {
-    restorePoint(range.start, anchor);
-    restorePoint(range.end, anchor);
-}
-
-});

+ 0 - 268
services/web/public/js/ace/edit_session/fold_line.js

@@ -1,268 +0,0 @@
-/* ***** 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 Range = require("../range").Range;
-
-/*
- * If an array is passed in, the folds are expected to be sorted already.
- */
-function FoldLine(foldData, folds) {
-    this.foldData = foldData;
-    if (Array.isArray(folds)) {
-        this.folds = folds;
-    } else {
-        folds = this.folds = [ folds ];
-    }
-
-    var last = folds[folds.length - 1]
-    this.range = new Range(folds[0].start.row, folds[0].start.column,
-                           last.end.row, last.end.column);
-    this.start = this.range.start;
-    this.end   = this.range.end;
-
-    this.folds.forEach(function(fold) {
-        fold.setFoldLine(this);
-    }, this);
-}
-
-(function() {
-    /*
-     * Note: This doesn't update wrapData!
-     */
-    this.shiftRow = function(shift) {
-        this.start.row += shift;
-        this.end.row += shift;
-        this.folds.forEach(function(fold) {
-            fold.start.row += shift;
-            fold.end.row += shift;
-        });
-    }
-
-    this.addFold = function(fold) {
-        if (fold.sameRow) {
-            if (fold.start.row < this.startRow || fold.endRow > this.endRow) {
-                throw new Error("Can't add a fold to this FoldLine as it has no connection");
-            }
-            this.folds.push(fold);
-            this.folds.sort(function(a, b) {
-                return -a.range.compareEnd(b.start.row, b.start.column);
-            });
-            if (this.range.compareEnd(fold.start.row, fold.start.column) > 0) {
-                this.end.row = fold.end.row;
-                this.end.column =  fold.end.column;
-            } else if (this.range.compareStart(fold.end.row, fold.end.column) < 0) {
-                this.start.row = fold.start.row;
-                this.start.column = fold.start.column;
-            }
-        } else if (fold.start.row == this.end.row) {
-            this.folds.push(fold);
-            this.end.row = fold.end.row;
-            this.end.column = fold.end.column;
-        } else if (fold.end.row == this.start.row) {
-            this.folds.unshift(fold);
-            this.start.row = fold.start.row;
-            this.start.column = fold.start.column;
-        } else {
-            throw new Error("Trying to add fold to FoldRow that doesn't have a matching row");
-        }
-        fold.foldLine = this;
-    }
-
-    this.containsRow = function(row) {
-        return row >= this.start.row && row <= this.end.row;
-    }
-
-    this.walk = function(callback, endRow, endColumn) {
-        var lastEnd = 0,
-            folds = this.folds,
-            fold,
-            comp, stop, isNewRow = true;
-
-        if (endRow == null) {
-            endRow = this.end.row;
-            endColumn = this.end.column;
-        }
-
-        for (var i = 0; i < folds.length; i++) {
-            fold = folds[i];
-
-            comp = fold.range.compareStart(endRow, endColumn);
-            // This fold is after the endRow/Column.
-            if (comp == -1) {
-                callback(null, endRow, endColumn, lastEnd, isNewRow);
-                return;
-            }
-
-            stop = callback(null, fold.start.row, fold.start.column, lastEnd, isNewRow);
-            stop = !stop && callback(fold.placeholder, fold.start.row, fold.start.column, lastEnd);
-
-            // If the user requested to stop the walk or endRow/endColumn is
-            // inside of this fold (comp == 0), then end here.
-            if (stop || comp == 0) {
-                return;
-            }
-
-            // Note the new lastEnd might not be on the same line. However,
-            // it's the callback's job to recognize this.
-            isNewRow = !fold.sameRow;
-            lastEnd = fold.end.column;
-        }
-        callback(null, endRow, endColumn, lastEnd, isNewRow);
-    }
-
-    this.getNextFoldTo = function(row, column) {
-        var fold, cmp;
-        for (var i = 0; i < this.folds.length; i++) {
-            fold = this.folds[i];
-            cmp = fold.range.compareEnd(row, column);
-            if (cmp == -1) {
-                return {
-                    fold: fold,
-                    kind: "after"
-                };
-            } else if (cmp == 0) {
-                return {
-                    fold: fold,
-                    kind: "inside"
-                }
-            }
-        }
-        return null;
-    }
-
-    this.addRemoveChars = function(row, column, len) {
-        var ret = this.getNextFoldTo(row, column),
-            fold, folds;
-        if (ret) {
-            fold = ret.fold;
-            if (ret.kind == "inside"
-                && fold.start.column != column
-                && fold.start.row != row)
-            {
-                //throwing here breaks whole editor
-                //TODO: properly handle this
-                window.console && window.console.log(row, column, fold);
-            } else if (fold.start.row == row) {
-                folds = this.folds;
-                var i = folds.indexOf(fold);
-                if (i == 0) {
-                    this.start.column += len;
-                }
-                for (i; i < folds.length; i++) {
-                    fold = folds[i];
-                    fold.start.column += len;
-                    if (!fold.sameRow) {
-                        return;
-                    }
-                    fold.end.column += len;
-                }
-                this.end.column += len;
-            }
-        }
-    }
-
-    this.split = function(row, column) {
-        var fold = this.getNextFoldTo(row, column).fold;
-        var folds = this.folds;
-        var foldData = this.foldData;
-
-        if (!fold)
-            return null;
-
-        var i = folds.indexOf(fold);
-        var foldBefore = folds[i - 1];
-        this.end.row = foldBefore.end.row;
-        this.end.column = foldBefore.end.column;
-
-        // Remove the folds after row/column and create a new FoldLine
-        // containing these removed folds.
-        folds = folds.splice(i, folds.length - i);
-
-        var newFoldLine = new FoldLine(foldData, folds);
-        foldData.splice(foldData.indexOf(this) + 1, 0, newFoldLine);
-        return newFoldLine;
-    }
-
-    this.merge = function(foldLineNext) {
-        var folds = foldLineNext.folds;
-        for (var i = 0; i < folds.length; i++) {
-            this.addFold(folds[i]);
-        }
-        // Remove the foldLineNext - no longer needed, as
-        // it's merged now with foldLineNext.
-        var foldData = this.foldData;
-        foldData.splice(foldData.indexOf(foldLineNext), 1);
-    }
-
-    this.toString = function() {
-        var ret = [this.range.toString() + ": [" ];
-
-        this.folds.forEach(function(fold) {
-            ret.push("  " + fold.toString());
-        });
-        ret.push("]")
-        return ret.join("\n");
-    }
-
-    this.idxToPosition = function(idx) {
-        var lastFoldEndColumn = 0;
-        var fold;
-
-        for (var i = 0; i < this.folds.length; i++) {
-            var fold = this.folds[i];
-
-            idx -= fold.start.column - lastFoldEndColumn;
-            if (idx < 0) {
-                return {
-                    row: fold.start.row,
-                    column: fold.start.column + idx
-                };
-            }
-
-            idx -= fold.placeholder.length;
-            if (idx < 0) {
-                return fold.start;
-            }
-
-            lastFoldEndColumn = fold.end.column;
-        }
-
-        return {
-            row: this.end.row,
-            column: this.end.column + idx
-        };
-    }
-}).call(FoldLine.prototype);
-
-exports.FoldLine = FoldLine;
-});

+ 0 - 846
services/web/public/js/ace/edit_session/folding.js

@@ -1,846 +0,0 @@
-/* ***** 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 Range = require("../range").Range;
-var FoldLine = require("./fold_line").FoldLine;
-var Fold = require("./fold").Fold;
-var TokenIterator = require("../token_iterator").TokenIterator;
-
-function Folding() {
-    /*
-     * Looks up a fold at a given row/column. Possible values for side:
-     *   -1: ignore a fold if fold.start = row/column
-     *   +1: ignore a fold if fold.end = row/column
-     */
-    this.getFoldAt = function(row, column, side) {
-        var foldLine = this.getFoldLine(row);
-        if (!foldLine)
-            return null;
-
-        var folds = foldLine.folds;
-        for (var i = 0; i < folds.length; i++) {
-            var fold = folds[i];
-            if (fold.range.contains(row, column)) {
-                if (side == 1 && fold.range.isEnd(row, column)) {
-                    continue;
-                } else if (side == -1 && fold.range.isStart(row, column)) {
-                    continue;
-                }
-                return fold;
-            }
-        }
-    };
-
-    /*
-     * Returns all folds in the given range. Note, that this will return folds
-     *
-     */
-    this.getFoldsInRange = function(range) {
-        var start = range.start;
-        var end = range.end;
-        var foldLines = this.$foldData;
-        var foundFolds = [];
-
-        start.column += 1;
-        end.column -= 1;
-
-        for (var i = 0; i < foldLines.length; i++) {
-            var cmp = foldLines[i].range.compareRange(range);
-            if (cmp == 2) {
-                // Range is before foldLine. No intersection. This means,
-                // there might be other foldLines that intersect.
-                continue;
-            }
-            else if (cmp == -2) {
-                // Range is after foldLine. There can't be any other foldLines then,
-                // so let's give up.
-                break;
-            }
-
-            var folds = foldLines[i].folds;
-            for (var j = 0; j < folds.length; j++) {
-                var fold = folds[j];
-                cmp = fold.range.compareRange(range);
-                if (cmp == -2) {
-                    break;
-                } else if (cmp == 2) {
-                    continue;
-                } else
-                // WTF-state: Can happen due to -1/+1 to start/end column.
-                if (cmp == 42) {
-                    break;
-                }
-                foundFolds.push(fold);
-            }
-        }
-        start.column -= 1;
-        end.column += 1;
-
-        return foundFolds;
-    };
-
-    this.getFoldsInRangeList = function(ranges) {
-        if (Array.isArray(ranges)) {
-            var folds = [];
-            ranges.forEach(function(range) {
-                folds = folds.concat(this.getFoldsInRange(range));
-            }, this);
-        } else {
-            var folds = this.getFoldsInRange(ranges);
-        }
-        return folds;
-    }
-    
-    /*
-     * Returns all folds in the document
-     */
-    this.getAllFolds = function() {
-        var folds = [];
-        var foldLines = this.$foldData;
-        
-        for (var i = 0; i < foldLines.length; i++)
-            for (var j = 0; j < foldLines[i].folds.length; j++)
-                folds.push(foldLines[i].folds[j]);
-
-        return folds;
-    };
-
-    /*
-     * Returns the string between folds at the given position.
-     * E.g.
-     *  foo<fold>b|ar<fold>wolrd -> "bar"
-     *  foo<fold>bar<fold>wol|rd -> "world"
-     *  foo<fold>bar<fo|ld>wolrd -> <null>
-     *
-     * where | means the position of row/column
-     *
-     * The trim option determs if the return string should be trimed according
-     * to the "side" passed with the trim value:
-     *
-     * E.g.
-     *  foo<fold>b|ar<fold>wolrd -trim=-1> "b"
-     *  foo<fold>bar<fold>wol|rd -trim=+1> "rld"
-     *  fo|o<fold>bar<fold>wolrd -trim=00> "foo"
-     */
-    this.getFoldStringAt = function(row, column, trim, foldLine) {
-        foldLine = foldLine || this.getFoldLine(row);
-        if (!foldLine)
-            return null;
-
-        var lastFold = {
-            end: { column: 0 }
-        };
-        // TODO: Refactor to use getNextFoldTo function.
-        var str, fold;
-        for (var i = 0; i < foldLine.folds.length; i++) {
-            fold = foldLine.folds[i];
-            var cmp = fold.range.compareEnd(row, column);
-            if (cmp == -1) {
-                str = this
-                    .getLine(fold.start.row)
-                    .substring(lastFold.end.column, fold.start.column);
-                break;
-            }
-            else if (cmp === 0) {
-                return null;
-            }
-            lastFold = fold;
-        }
-        if (!str)
-            str = this.getLine(fold.start.row).substring(lastFold.end.column);
-
-        if (trim == -1)
-            return str.substring(0, column - lastFold.end.column);
-        else if (trim == 1)
-            return str.substring(column - lastFold.end.column);
-        else
-            return str;
-    };
-
-    this.getFoldLine = function(docRow, startFoldLine) {
-        var foldData = this.$foldData;
-        var i = 0;
-        if (startFoldLine)
-            i = foldData.indexOf(startFoldLine);
-        if (i == -1)
-            i = 0;
-        for (i; i < foldData.length; i++) {
-            var foldLine = foldData[i];
-            if (foldLine.start.row <= docRow && foldLine.end.row >= docRow) {
-                return foldLine;
-            } else if (foldLine.end.row > docRow) {
-                return null;
-            }
-        }
-        return null;
-    };
-
-    // returns the fold which starts after or contains docRow
-    this.getNextFoldLine = function(docRow, startFoldLine) {
-        var foldData = this.$foldData;
-        var i = 0;
-        if (startFoldLine)
-            i = foldData.indexOf(startFoldLine);
-        if (i == -1)
-            i = 0;
-        for (i; i < foldData.length; i++) {
-            var foldLine = foldData[i];
-            if (foldLine.end.row >= docRow) {
-                return foldLine;
-            }
-        }
-        return null;
-    };
-
-    this.getFoldedRowCount = function(first, last) {
-        var foldData = this.$foldData, rowCount = last-first+1;
-        for (var i = 0; i < foldData.length; i++) {
-            var foldLine = foldData[i],
-                end = foldLine.end.row,
-                start = foldLine.start.row;
-            if (end >= last) {
-                if(start < last) {
-                    if(start >= first)
-                        rowCount -= last-start;
-                    else
-                        rowCount = 0;//in one fold
-                }
-                break;
-            } else if(end >= first){
-                if (start >= first) //fold inside range
-                    rowCount -=  end-start;
-                else
-                    rowCount -=  end-first+1;
-            }
-        }
-        return rowCount;
-    };
-
-    this.$addFoldLine = function(foldLine) {
-        this.$foldData.push(foldLine);
-        this.$foldData.sort(function(a, b) {
-            return a.start.row - b.start.row;
-        });
-        return foldLine;
-    };
-
-    /**
-     * Adds a new fold.
-     *
-     * @returns
-     *      The new created Fold object or an existing fold object in case the
-     *      passed in range fits an existing fold exactly.
-     */
-    this.addFold = function(placeholder, range) {
-        var foldData = this.$foldData;
-        var added = false;
-        var fold;
-        
-        if (placeholder instanceof Fold)
-            fold = placeholder;
-        else {
-            fold = new Fold(range, placeholder);
-            fold.collapseChildren = range.collapseChildren;
-        }
-        this.$clipRangeToDocument(fold.range);
-
-        var startRow = fold.start.row;
-        var startColumn = fold.start.column;
-        var endRow = fold.end.row;
-        var endColumn = fold.end.column;
-
-        // --- Some checking ---
-        if (!(startRow < endRow || 
-            startRow == endRow && startColumn <= endColumn - 2))
-            throw new Error("The range has to be at least 2 characters width");
-
-        var startFold = this.getFoldAt(startRow, startColumn, 1);
-        var endFold = this.getFoldAt(endRow, endColumn, -1);
-        if (startFold && endFold == startFold)
-            return startFold.addSubFold(fold);
-
-        if (
-            (startFold && !startFold.range.isStart(startRow, startColumn))
-            || (endFold && !endFold.range.isEnd(endRow, endColumn))
-        ) {
-            throw new Error("A fold can't intersect already existing fold" + fold.range + startFold.range);
-        }
-
-        // Check if there are folds in the range we create the new fold for.
-        var folds = this.getFoldsInRange(fold.range);
-        if (folds.length > 0) {
-            // Remove the folds from fold data.
-            this.removeFolds(folds);
-            // Add the removed folds as subfolds on the new fold.
-            folds.forEach(function(subFold) {
-                fold.addSubFold(subFold);
-            });
-        }
-
-        for (var i = 0; i < foldData.length; i++) {
-            var foldLine = foldData[i];
-            if (endRow == foldLine.start.row) {
-                foldLine.addFold(fold);
-                added = true;
-                break;
-            } else if (startRow == foldLine.end.row) {
-                foldLine.addFold(fold);
-                added = true;
-                if (!fold.sameRow) {
-                    // Check if we might have to merge two FoldLines.
-                    var foldLineNext = foldData[i + 1];
-                    if (foldLineNext && foldLineNext.start.row == endRow) {
-                        // We need to merge!
-                        foldLine.merge(foldLineNext);
-                        break;
-                    }
-                }
-                break;
-            } else if (endRow <= foldLine.start.row) {
-                break;
-            }
-        }
-
-        if (!added)
-            foldLine = this.$addFoldLine(new FoldLine(this.$foldData, fold));
-
-        if (this.$useWrapMode)
-            this.$updateWrapData(foldLine.start.row, foldLine.start.row);
-        else
-            this.$updateRowLengthCache(foldLine.start.row, foldLine.start.row);
-
-        // Notify that fold data has changed.
-        this.$modified = true;
-        this._emit("changeFold", { data: fold, action: "add" });
-
-        return fold;
-    };
-
-    this.addFolds = function(folds) {
-        folds.forEach(function(fold) {
-            this.addFold(fold);
-        }, this);
-    };
-
-    this.removeFold = function(fold) {
-        var foldLine = fold.foldLine;
-        var startRow = foldLine.start.row;
-        var endRow = foldLine.end.row;
-
-        var foldLines = this.$foldData;
-        var folds = foldLine.folds;
-        // Simple case where there is only one fold in the FoldLine such that
-        // the entire fold line can get removed directly.
-        if (folds.length == 1) {
-            foldLines.splice(foldLines.indexOf(foldLine), 1);
-        } else
-        // If the fold is the last fold of the foldLine, just remove it.
-        if (foldLine.range.isEnd(fold.end.row, fold.end.column)) {
-            folds.pop();
-            foldLine.end.row = folds[folds.length - 1].end.row;
-            foldLine.end.column = folds[folds.length - 1].end.column;
-        } else
-        // If the fold is the first fold of the foldLine, just remove it.
-        if (foldLine.range.isStart(fold.start.row, fold.start.column)) {
-            folds.shift();
-            foldLine.start.row = folds[0].start.row;
-            foldLine.start.column = folds[0].start.column;
-        } else
-        // We know there are more then 2 folds and the fold is not at the edge.
-        // This means, the fold is somewhere in between.
-        //
-        // If the fold is in one row, we just can remove it.
-        if (fold.sameRow) {
-            folds.splice(folds.indexOf(fold), 1);
-        } else
-        // The fold goes over more then one row. This means remvoing this fold
-        // will cause the fold line to get splitted up. newFoldLine is the second part
-        {
-            var newFoldLine = foldLine.split(fold.start.row, fold.start.column);
-            folds = newFoldLine.folds;
-            folds.shift();
-            newFoldLine.start.row = folds[0].start.row;
-            newFoldLine.start.column = folds[0].start.column;
-        }
-
-        if (!this.$updating) {
-            if (this.$useWrapMode)
-                this.$updateWrapData(startRow, endRow);
-            else
-                this.$updateRowLengthCache(startRow, endRow);
-        }
-        
-        // Notify that fold data has changed.
-        this.$modified = true;
-        this._emit("changeFold", { data: fold, action: "remove" });
-    };
-
-    this.removeFolds = function(folds) {
-        // We need to clone the folds array passed in as it might be the folds
-        // array of a fold line and as we call this.removeFold(fold), folds
-        // are removed from folds and changes the current index.
-        var cloneFolds = [];
-        for (var i = 0; i < folds.length; i++) {
-            cloneFolds.push(folds[i]);
-        }
-
-        cloneFolds.forEach(function(fold) {
-            this.removeFold(fold);
-        }, this);
-        this.$modified = true;
-    };
-
-    this.expandFold = function(fold) {
-        this.removeFold(fold);
-        fold.subFolds.forEach(function(subFold) {
-            fold.restoreRange(subFold);
-            this.addFold(subFold);
-        }, this);
-        if (fold.collapseChildren > 0) {
-            this.foldAll(fold.start.row+1, fold.end.row, fold.collapseChildren-1);
-        }
-        fold.subFolds = [];
-    };
-
-    this.expandFolds = function(folds) {
-        folds.forEach(function(fold) {
-            this.expandFold(fold);
-        }, this);
-    };
-
-    this.unfold = function(location, expandInner) {
-        var range, folds;
-        if (location == null) {
-            range = new Range(0, 0, this.getLength(), 0);
-            expandInner = true;
-        } else if (typeof location == "number")
-            range = new Range(location, 0, location, this.getLine(location).length);
-        else if ("row" in location)
-            range = Range.fromPoints(location, location);
-        else
-            range = location;
-        
-        folds = this.getFoldsInRangeList(range);
-        if (expandInner) {
-            this.removeFolds(folds);
-        } else {
-            // TODO: might need to remove and add folds in one go instead of using
-            // expandFolds several times.
-            while (folds.length) {
-                this.expandFolds(folds);
-                folds = this.getFoldsInRangeList(range);
-            }
-        }
-    };
-
-    /*
-     * Checks if a given documentRow is folded. This is true if there are some
-     * folded parts such that some parts of the line is still visible.
-     **/
-    this.isRowFolded = function(docRow, startFoldRow) {
-        return !!this.getFoldLine(docRow, startFoldRow);
-    };
-
-    this.getRowFoldEnd = function(docRow, startFoldRow) {
-        var foldLine = this.getFoldLine(docRow, startFoldRow);
-        return foldLine ? foldLine.end.row : docRow;
-    };
-
-    this.getRowFoldStart = function(docRow, startFoldRow) {
-        var foldLine = this.getFoldLine(docRow, startFoldRow);
-        return foldLine ? foldLine.start.row : docRow;
-    };
-
-    this.getFoldDisplayLine = function(foldLine, endRow, endColumn, startRow, startColumn) {
-        if (startRow == null) {
-            startRow = foldLine.start.row;
-            startColumn = 0;
-        }
-
-        if (endRow == null) {
-            endRow = foldLine.end.row;
-            endColumn = this.getLine(endRow).length;
-        }
-
-        // Build the textline using the FoldLine walker.
-        var doc = this.doc;
-        var textLine = "";
-
-        foldLine.walk(function(placeholder, row, column, lastColumn) {
-            if (row < startRow)
-                return;
-            if (row == startRow) {
-                if (column < startColumn)
-                    return;
-                lastColumn = Math.max(startColumn, lastColumn);
-            }
-
-            if (placeholder != null) {
-                textLine += placeholder;
-            } else {
-                textLine += doc.getLine(row).substring(lastColumn, column);
-            }
-        }, endRow, endColumn);
-        return textLine;
-    };
-
-    this.getDisplayLine = function(row, endColumn, startRow, startColumn) {
-        var foldLine = this.getFoldLine(row);
-
-        if (!foldLine) {
-            var line;
-            line = this.doc.getLine(row);
-            return line.substring(startColumn || 0, endColumn || line.length);
-        } else {
-            return this.getFoldDisplayLine(
-                foldLine, row, endColumn, startRow, startColumn);
-        }
-    };
-
-    this.$cloneFoldData = function() {
-        var fd = [];
-        fd = this.$foldData.map(function(foldLine) {
-            var folds = foldLine.folds.map(function(fold) {
-                return fold.clone();
-            });
-            return new FoldLine(fd, folds);
-        });
-
-        return fd;
-    };
-
-    this.toggleFold = function(tryToUnfold) {
-        var selection = this.selection;
-        var range = selection.getRange();
-        var fold;
-        var bracketPos;
-
-        if (range.isEmpty()) {
-            var cursor = range.start;
-            fold = this.getFoldAt(cursor.row, cursor.column);
-
-            if (fold) {
-                this.expandFold(fold);
-                return;
-            } else if (bracketPos = this.findMatchingBracket(cursor)) {
-                if (range.comparePoint(bracketPos) == 1) {
-                    range.end = bracketPos;
-                } else {
-                    range.start = bracketPos;
-                    range.start.column++;
-                    range.end.column--;
-                }
-            } else if (bracketPos = this.findMatchingBracket({row: cursor.row, column: cursor.column + 1})) {
-                if (range.comparePoint(bracketPos) == 1)
-                    range.end = bracketPos;
-                else
-                    range.start = bracketPos;
-
-                range.start.column++;
-            } else {
-                range = this.getCommentFoldRange(cursor.row, cursor.column) || range;
-            }
-        } else {
-            var folds = this.getFoldsInRange(range);
-            if (tryToUnfold && folds.length) {
-                this.expandFolds(folds);
-                return;
-            } else if (folds.length == 1 ) {
-                fold = folds[0];
-            }
-        }
-
-        if (!fold)
-            fold = this.getFoldAt(range.start.row, range.start.column);
-
-        if (fold && fold.range.toString() == range.toString()) {
-            this.expandFold(fold);
-            return;
-        }
-
-        var placeholder = "...";
-        if (!range.isMultiLine()) {
-            placeholder = this.getTextRange(range);
-            if(placeholder.length < 4)
-                return;
-            placeholder = placeholder.trim().substring(0, 2) + "..";
-        }
-
-        this.addFold(placeholder, range);
-    };
-
-    this.getCommentFoldRange = function(row, column, dir) {
-        var iterator = new TokenIterator(this, row, column);
-        var token = iterator.getCurrentToken();
-        if (token && /^comment|string/.test(token.type)) {
-            var range = new Range();
-            var re = new RegExp(token.type.replace(/\..*/, "\\."));
-            if (dir != 1) {
-                do {
-                    token = iterator.stepBackward();
-                } while(token && re.test(token.type));
-                iterator.stepForward();
-            }
-            
-            range.start.row = iterator.getCurrentTokenRow();
-            range.start.column = iterator.getCurrentTokenColumn() + 2;
-
-            iterator = new TokenIterator(this, row, column);
-            
-            if (dir != -1) {
-                do {
-                    token = iterator.stepForward();
-                } while(token && re.test(token.type));
-                token = iterator.stepBackward();
-            } else
-                token = iterator.getCurrentToken();
-
-            range.end.row = iterator.getCurrentTokenRow();
-            range.end.column = iterator.getCurrentTokenColumn() + token.value.length - 2;
-            return range;
-        }
-    };
-
-    this.foldAll = function(startRow, endRow, depth) {
-        if (depth == undefined)
-            depth = 100000; // JSON.stringify doesn't hanle Infinity
-        var foldWidgets = this.foldWidgets;
-        if (!foldWidgets)
-            return; // mode doesn't support folding
-        endRow = endRow || this.getLength();
-        startRow = startRow || 0;
-        for (var row = startRow; row < endRow; row++) {
-            if (foldWidgets[row] == null)
-                foldWidgets[row] = this.getFoldWidget(row);
-            if (foldWidgets[row] != "start")
-                continue;
-
-            var range = this.getFoldWidgetRange(row);
-            // sometimes range can be incompatible with existing fold
-            // TODO change addFold to return null istead of throwing
-            if (range && range.isMultiLine()
-                && range.end.row <= endRow
-                && range.start.row >= startRow
-            ) {
-                row = range.end.row;
-                try {
-                    // addFold can change the range
-                    var fold = this.addFold("...", range);
-                    if (fold)
-                        fold.collapseChildren = depth;
-                } catch(e) {}
-            }
-        }
-    };
-    
-    // structured folding
-    this.$foldStyles = {
-        "manual": 1,
-        "markbegin": 1,
-        "markbeginend": 1
-    };
-    this.$foldStyle = "markbegin";
-    this.setFoldStyle = function(style) {
-        if (!this.$foldStyles[style])
-            throw new Error("invalid fold style: " + style + "[" + Object.keys(this.$foldStyles).join(", ") + "]");
-        
-        if (this.$foldStyle == style)
-            return;
-
-        this.$foldStyle = style;
-        
-        if (style == "manual")
-            this.unfold();
-        
-        // reset folding
-        var mode = this.$foldMode;
-        this.$setFolding(null);
-        this.$setFolding(mode);
-    };
-
-    this.$setFolding = function(foldMode) {
-        if (this.$foldMode == foldMode)
-            return;
-            
-        this.$foldMode = foldMode;
-        
-        this.removeListener('change', this.$updateFoldWidgets);
-        this._emit("changeAnnotation");
-        
-        if (!foldMode || this.$foldStyle == "manual") {
-            this.foldWidgets = null;
-            return;
-        }
-        
-        this.foldWidgets = [];
-        this.getFoldWidget = foldMode.getFoldWidget.bind(foldMode, this, this.$foldStyle);
-        this.getFoldWidgetRange = foldMode.getFoldWidgetRange.bind(foldMode, this, this.$foldStyle);
-        
-        this.$updateFoldWidgets = this.updateFoldWidgets.bind(this);
-        this.on('change', this.$updateFoldWidgets);
-        
-    };
-
-    this.getParentFoldRangeData = function (row, ignoreCurrent) {
-        var fw = this.foldWidgets;
-        if (!fw || (ignoreCurrent && fw[row]))
-            return {};
-
-        var i = row - 1, firstRange;
-        while (i >= 0) {
-            var c = fw[i];
-            if (c == null)
-                c = fw[i] = this.getFoldWidget(i);
-
-            if (c == "start") {
-                var range = this.getFoldWidgetRange(i);
-                if (!firstRange)
-                    firstRange = range;
-                if (range && range.end.row >= row)
-                    break;
-            }
-            i--;
-        }
-
-        return {
-            range: i !== -1 && range,
-            firstRange: firstRange
-        };
-    }
-
-    this.onFoldWidgetClick = function(row, e) {
-        e = e.domEvent;
-        var options = {
-            children: e.shiftKey,
-            all: e.ctrlKey || e.metaKey,
-            siblings: e.altKey
-        };
-        
-        var range = this.$toggleFoldWidget(row, options);
-        if (!range)
-            (e.target || e.srcElement).className += " ace_invalid";
-    };
-    
-    this.$toggleFoldWidget = function(row, options) {
-        if (!this.getFoldWidget)
-            return;
-        var type = this.getFoldWidget(row);
-        var line = this.getLine(row);
-
-        var dir = type === "end" ? -1 : 1;
-        var fold = this.getFoldAt(row, dir === -1 ? 0 : line.length, dir);
-
-        if (fold) {
-            if (options.children || options.all)
-                this.removeFold(fold);
-            else
-                this.expandFold(fold);
-            return;
-        }
-
-        var range = this.getFoldWidgetRange(row, true);
-        // sometimes singleline folds can be missed by the code above
-        if (range && !range.isMultiLine()) {
-            fold = this.getFoldAt(range.start.row, range.start.column, 1);
-            if (fold && range.isEqual(fold.range)) {
-                this.removeFold(fold);
-                return;
-            }
-        }
-        
-        if (options.siblings) {
-            var data = this.getParentFoldRangeData(row);
-            if (data.range) {
-                var startRow = data.range.start.row + 1;
-                var endRow = data.range.end.row;
-            }
-            this.foldAll(startRow, endRow, options.all ? 10000 : 0);
-        } else if (options.children) {
-            endRow = range ? range.end.row : this.getLength();
-            this.foldAll(row + 1, range.end.row, options.all ? 10000 : 0);
-        } else if (range) {
-            if (options.all) 
-                range.collapseChildren = 10000;
-            this.addFold("...", range);
-        }
-        
-        return range;
-    };
-    
-    
-    
-    this.toggleFoldWidget = function(toggleParent) {
-        var row = this.selection.getCursor().row;
-        row = this.getRowFoldStart(row);
-        var range = this.$toggleFoldWidget(row, {});
-        
-        if (range)
-            return;
-        // handle toggleParent
-        var data = this.getParentFoldRangeData(row, true);
-        range = data.range || data.firstRange;
-        
-        if (range) {
-            row = range.start.row;
-            var fold = this.getFoldAt(row, this.getLine(row).length, 1);
-
-            if (fold) {
-                this.removeFold(fold);
-            } else {
-                this.addFold("...", range);
-            }
-        }
-    };
-
-    this.updateFoldWidgets = function(e) {
-        var delta = e.data;
-        var range = delta.range;
-        var firstRow = range.start.row;
-        var len = range.end.row - firstRow;
-
-        if (len === 0) {
-            this.foldWidgets[firstRow] = null;
-        } else if (delta.action == "removeText" || delta.action == "removeLines") {
-            this.foldWidgets.splice(firstRow, len + 1, null);
-        } else {
-            var args = Array(len + 1);
-            args.unshift(firstRow, 1);
-            this.foldWidgets.splice.apply(this.foldWidgets, args);
-        }
-    };
-
-}
-
-exports.Folding = Folding;
-
-});

+ 0 - 1075
services/web/public/js/ace/edit_session_test.js

@@ -1,1075 +0,0 @@
-/* ***** 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");
-    require("./test/mockdom");
-}
-
-define(function(require, exports, module) {
-"use strict";
-
-var lang = require("./lib/lang");
-var EditSession = require("./edit_session").EditSession;
-var Editor = require("./editor").Editor;
-var UndoManager = require("./undomanager").UndoManager;
-var MockRenderer = require("./test/mockrenderer").MockRenderer;
-var Range = require("./range").Range;
-var assert = require("./test/assertions");
-var JavaScriptMode = require("./mode/javascript").Mode;
-
-function createFoldTestSession() {
-    var lines = [
-        "function foo(items) {",
-        "    for (var i=0; i<items.length; i++) {",
-        "        alert(items[i] + \"juhu\");",
-        "    }    // Real Tab.",
-        "}"
-    ];
-    var session = new EditSession(lines.join("\n"));
-    session.setUndoManager(new UndoManager());
-    session.addFold("args...", new Range(0, 13, 0, 18));
-    session.addFold("foo...", new Range(1, 10, 2, 10));
-    session.addFold("bar...", new Range(2, 20, 2, 25));
-    return session;
-}
-
-function assertArray(a, b) {
-    assert.equal(a+"", b+"");
-    assert.ok(a.length == b.length);
-    for (var i = 0; i < a.length; i++) {
-        assert.equal(a[i], b[i]);
-    }
-}
-
-module.exports = {
-
-   "test: find matching opening bracket in Text mode" : function() {
-        var session = new EditSession(["(()(", "())))"]);
-
-        assert.position(session.findMatchingBracket({row: 0, column: 3}), 0, 1);
-        assert.position(session.findMatchingBracket({row: 1, column: 2}), 1, 0);
-        assert.position(session.findMatchingBracket({row: 1, column: 3}), 0, 3);
-        assert.position(session.findMatchingBracket({row: 1, column: 4}), 0, 0);
-        assert.equal(session.findMatchingBracket({row: 1, column: 5}), null);
-    },
-
-    "test: find matching closing bracket in Text mode" : function() {
-        var session = new EditSession(["(()(", "())))"]);
-
-        assert.position(session.findMatchingBracket({row: 1, column: 1}), 1, 1);
-        assert.position(session.findMatchingBracket({row: 1, column: 1}), 1, 1);
-        assert.position(session.findMatchingBracket({row: 0, column: 4}), 1, 2);
-        assert.position(session.findMatchingBracket({row: 0, column: 2}), 0, 2);
-        assert.position(session.findMatchingBracket({row: 0, column: 1}), 1, 3);
-        assert.equal(session.findMatchingBracket({row: 0, column: 0}), null);
-    },
-
-    "test: find matching opening bracket in JavaScript mode" : function() {
-        var lines = [
-            "function foo() {",
-            "    var str = \"{ foo()\";",
-            "    if (debug) {",
-            "        // write str (a string) to the console",
-            "        console.log(str);",
-            "    }",
-            "    str += \" bar() }\";",
-            "}"
-        ];
-        var session = new EditSession(lines.join("\n"), new JavaScriptMode());
-
-        assert.position(session.findMatchingBracket({row: 0, column: 14}), 0, 12);
-        assert.position(session.findMatchingBracket({row: 7, column: 1}), 0, 15);
-        assert.position(session.findMatchingBracket({row: 6, column: 20}), 1, 15);
-        assert.position(session.findMatchingBracket({row: 1, column: 22}), 1, 20);
-        assert.position(session.findMatchingBracket({row: 3, column: 31}), 3, 21);
-        assert.position(session.findMatchingBracket({row: 4, column: 24}), 4, 19);
-        assert.equal(session.findMatchingBracket({row: 0, column: 1}), null);
-    },
-
-    "test: find matching closing bracket in JavaScript mode" : function() {
-        var lines = [
-            "function foo() {",
-            "    var str = \"{ foo()\";",
-            "    if (debug) {",
-            "        // write str (a string) to the console",
-            "        console.log(str);",
-            "    }",
-            "    str += \" bar() }\";",
-            "}"
-        ];
-        var session = new EditSession(lines.join("\n"), new JavaScriptMode());
-
-        assert.position(session.findMatchingBracket({row: 0, column: 13}), 0, 13);
-        assert.position(session.findMatchingBracket({row: 0, column: 16}), 7, 0);
-        assert.position(session.findMatchingBracket({row: 1, column: 16}), 6, 19);
-        assert.position(session.findMatchingBracket({row: 1, column: 21}), 1, 21);
-        assert.position(session.findMatchingBracket({row: 3, column: 22}), 3, 30);
-        assert.position(session.findMatchingBracket({row: 4, column: 20}), 4, 23);
-    },
-
-    "test: handle unbalanced brackets in JavaScript mode" : function() {
-        var lines = [
-            "function foo() {",
-            "    var str = \"{ foo()\";",
-            "    if (debug) {",
-            "        // write str a string) to the console",
-            "        console.log(str);",
-            "    ",
-            "    str += \" bar() \";",
-            "}"
-        ];
-        var session = new EditSession(lines.join("\n"), new JavaScriptMode());
-
-        assert.equal(session.findMatchingBracket({row: 0, column: 16}), null);
-        assert.equal(session.findMatchingBracket({row: 3, column: 30}), null);
-        assert.equal(session.findMatchingBracket({row: 1, column: 16}), null);
-    },
-
-    "test: match different bracket types" : function() {
-        var session = new EditSession(["({[", ")]}"]);
-
-        assert.position(session.findMatchingBracket({row: 0, column: 1}), 1, 0);
-        assert.position(session.findMatchingBracket({row: 0, column: 2}), 1, 2);
-        assert.position(session.findMatchingBracket({row: 0, column: 3}), 1, 1);
-
-        assert.position(session.findMatchingBracket({row: 1, column: 1}), 0, 0);
-        assert.position(session.findMatchingBracket({row: 1, column: 2}), 0, 2);
-        assert.position(session.findMatchingBracket({row: 1, column: 3}), 0, 1);
-    },
-
-    "test: move lines down" : function() {
-        var session = new EditSession(["a1", "a2", "a3", "a4"]);
-
-        session.moveLinesDown(0, 1);
-        assert.equal(session.getValue(), ["a3", "a1", "a2", "a4"].join("\n"));
-
-        session.moveLinesDown(1, 2);
-        assert.equal(session.getValue(), ["a3", "a4", "a1", "a2"].join("\n"));
-
-        session.moveLinesDown(2, 3);
-        assert.equal(session.getValue(), ["a3", "a4", "a1", "a2"].join("\n"));
-
-        session.moveLinesDown(2, 2);
-        assert.equal(session.getValue(), ["a3", "a4", "a2", "a1"].join("\n"));
-    },
-
-    "test: move lines up" : function() {
-        var session = new EditSession(["a1", "a2", "a3", "a4"]);
-
-        session.moveLinesUp(2, 3);
-        assert.equal(session.getValue(), ["a1", "a3", "a4", "a2"].join("\n"));
-
-        session.moveLinesUp(1, 2);
-        assert.equal(session.getValue(), ["a3", "a4", "a1", "a2"].join("\n"));
-
-        session.moveLinesUp(0, 1);
-        assert.equal(session.getValue(), ["a3", "a4", "a1", "a2"].join("\n"));
-
-        session.moveLinesUp(2, 2);
-        assert.equal(session.getValue(), ["a3", "a1", "a4", "a2"].join("\n"));
-    },
-
-    "test: duplicate lines" : function() {
-        var session = new EditSession(["1", "2", "3", "4"]);
-
-        session.duplicateLines(1, 2);
-        assert.equal(session.getValue(), ["1", "2", "3", "2", "3", "4"].join("\n"));
-    },
-
-    "test: duplicate last line" : function() {
-        var session = new EditSession(["1", "2", "3"]);
-
-        session.duplicateLines(2, 2);
-        assert.equal(session.getValue(), ["1", "2", "3", "3"].join("\n"));
-    },
-
-    "test: duplicate first line" : function() {
-        var session = new EditSession(["1", "2", "3"]);
-
-        session.duplicateLines(0, 0);
-        assert.equal(session.getValue(), ["1", "1", "2", "3"].join("\n"));
-    },
-
-    "test: getScreenLastRowColumn": function() {
-        var session = new EditSession([
-            "juhu",
-            "12\t\t34",
-            "ぁぁa"
-        ]);
-
-        assert.equal(session.getScreenLastRowColumn(0), 4);
-        assert.equal(session.getScreenLastRowColumn(1), 10);
-        assert.equal(session.getScreenLastRowColumn(2), 5);
-    },
-
-    "test: convert document to screen coordinates" : function() {
-        var session = new EditSession("01234\t567890\t1234");
-        session.setTabSize(4);
-
-        assert.equal(session.documentToScreenColumn(0, 0), 0);
-        assert.equal(session.documentToScreenColumn(0, 4), 4);
-        assert.equal(session.documentToScreenColumn(0, 5), 5);
-        assert.equal(session.documentToScreenColumn(0, 6), 8);
-        assert.equal(session.documentToScreenColumn(0, 12), 14);
-        assert.equal(session.documentToScreenColumn(0, 13), 16);
-
-        session.setTabSize(2);
-
-        assert.equal(session.documentToScreenColumn(0, 0), 0);
-        assert.equal(session.documentToScreenColumn(0, 4), 4);
-        assert.equal(session.documentToScreenColumn(0, 5), 5);
-        assert.equal(session.documentToScreenColumn(0, 6), 6);
-        assert.equal(session.documentToScreenColumn(0, 7), 7);
-        assert.equal(session.documentToScreenColumn(0, 12), 12);
-        assert.equal(session.documentToScreenColumn(0, 13), 14);
-    },
-
-    "test: convert document to screen coordinates with leading tabs": function() {
-        var session = new EditSession("\t\t123");
-        session.setTabSize(4);
-
-        assert.equal(session.documentToScreenColumn(0, 0), 0);
-        assert.equal(session.documentToScreenColumn(0, 1), 4);
-        assert.equal(session.documentToScreenColumn(0, 2), 8);
-        assert.equal(session.documentToScreenColumn(0, 3), 9);
-    },
-
-    "test: documentToScreen without soft wrap": function() {
-        var session = new EditSession([
-            "juhu",
-            "12\t\t34",
-            "ぁぁa"
-        ]);
-
-        assert.position(session.documentToScreenPosition(0, 3), 0, 3);
-        assert.position(session.documentToScreenPosition(1, 3), 1, 4);
-        assert.position(session.documentToScreenPosition(1, 4), 1, 8);
-        assert.position(session.documentToScreenPosition(2, 2), 2, 4);
-    },
-
-    "test: documentToScreen with soft wrap": function() {
-        var session = new EditSession(["foo bar foo bar"]);
-        session.setUseWrapMode(true);
-        session.setWrapLimitRange(12, 12);
-        session.adjustWrapLimit(80);
-
-        assert.position(session.documentToScreenPosition(0, 11), 0, 11);
-        assert.position(session.documentToScreenPosition(0, 12), 1, 0);
-    },
-
-    "test: documentToScreen with soft wrap and multibyte characters": function() {
-        var session = new EditSession(["ぁぁa"]);
-        session.setUseWrapMode(true);
-        session.setWrapLimitRange(2, 2);
-        session.adjustWrapLimit(80);
-
-        assert.position(session.documentToScreenPosition(0, 1), 1, 0);
-        assert.position(session.documentToScreenPosition(0, 2), 2, 0);
-        assert.position(session.documentToScreenPosition(0, 4), 2, 1);
-    },
-
-    "test: documentToScreen should clip position to the document boundaries": function() {
-        var session = new EditSession("foo bar\njuhu kinners");
-
-        assert.position(session.documentToScreenPosition(-1, 4), 0, 0);
-        assert.position(session.documentToScreenPosition(3, 0), 1, 12);
-    },
-
-    "test: convert screen to document coordinates" : function() {
-        var session = new EditSession("01234\t567890\t1234");
-        session.setTabSize(4);
-
-        assert.equal(session.screenToDocumentColumn(0, 0), 0);
-        assert.equal(session.screenToDocumentColumn(0, 4), 4);
-        assert.equal(session.screenToDocumentColumn(0, 5), 5);
-        assert.equal(session.screenToDocumentColumn(0, 6), 5);
-        assert.equal(session.screenToDocumentColumn(0, 7), 5);
-        assert.equal(session.screenToDocumentColumn(0, 8), 6);
-        assert.equal(session.screenToDocumentColumn(0, 9), 7);
-        assert.equal(session.screenToDocumentColumn(0, 15), 12);
-        assert.equal(session.screenToDocumentColumn(0, 19), 16);
-
-        session.setTabSize(2);
-
-        assert.equal(session.screenToDocumentColumn(0, 0), 0);
-        assert.equal(session.screenToDocumentColumn(0, 4), 4);
-        assert.equal(session.screenToDocumentColumn(0, 5), 5);
-        assert.equal(session.screenToDocumentColumn(0, 6), 6);
-        assert.equal(session.screenToDocumentColumn(0, 12), 12);
-        assert.equal(session.screenToDocumentColumn(0, 13), 12);
-        assert.equal(session.screenToDocumentColumn(0, 14), 13);
-    },
-
-    "test: screenToDocument with soft wrap": function() {
-        var session = new EditSession(["foo bar foo bar"]);
-        session.setUseWrapMode(true);
-        session.setWrapLimitRange(12, 12);
-        session.adjustWrapLimit(80);
-
-        assert.position(session.screenToDocumentPosition(1, 0), 0, 12);
-        assert.position(session.screenToDocumentPosition(0, 11), 0, 11);
-        // Check if the position is clamped the right way.
-        assert.position(session.screenToDocumentPosition(0, 12), 0, 11);
-        assert.position(session.screenToDocumentPosition(0, 20), 0, 11);
-    },
-
-    "test: screenToDocument with soft wrap and multi byte characters": function() {
-        var session = new EditSession(["ぁ a"]);
-        session.setUseWrapMode(true);
-        session.adjustWrapLimit(80);
-
-        assert.position(session.screenToDocumentPosition(0, 1), 0, 0);
-        assert.position(session.screenToDocumentPosition(0, 2), 0, 1);
-        assert.position(session.screenToDocumentPosition(0, 3), 0, 2);
-        assert.position(session.screenToDocumentPosition(0, 4), 0, 3);
-        assert.position(session.screenToDocumentPosition(0, 5), 0, 3);
-    },
-
-    "test: screenToDocument should clip position to the document boundaries": function() {
-        var session = new EditSession("foo bar\njuhu kinners");
-
-        assert.position(session.screenToDocumentPosition(-1, 4), 0, 0);
-        assert.position(session.screenToDocumentPosition(0, -1), 0, 0);
-        assert.position(session.screenToDocumentPosition(0, 30), 0, 7);
-        assert.position(session.screenToDocumentPosition(2, 4), 1, 12);
-        assert.position(session.screenToDocumentPosition(1, 30), 1, 12);
-        assert.position(session.screenToDocumentPosition(20, 50), 1, 12);
-        assert.position(session.screenToDocumentPosition(20, 5), 1, 12);
-
-        // and the same for folded rows
-        session.addFold("...", new Range(0,1,1,3));
-        assert.position(session.screenToDocumentPosition(1, 2), 1, 12);
-        // for wrapped rows
-        session.setUseWrapMode(true);
-        session.setWrapLimitRange(5,5);
-        assert.position(session.screenToDocumentPosition(4, 1), 1, 12);
-    },
-
-    "test: wrapLine split function" : function() {
-        function computeAndAssert(line, assertEqual, wrapLimit, tabSize) {
-            wrapLimit = wrapLimit || 12;
-            tabSize = tabSize || 4;
-            line = lang.stringTrimRight(line);
-            var tokens = EditSession.prototype.$getDisplayTokens(line);
-            var splits = EditSession.prototype.$computeWrapSplits(tokens, wrapLimit, tabSize);
-            // console.log("String:", line, "Result:", splits, "Expected:", assertEqual);
-            assert.ok(splits.length == assertEqual.length);
-            for (var i = 0; i < splits.length; i++) {
-                assert.ok(splits[i] == assertEqual[i]);
-            }
-        }
-        
-        EditSession.prototype.$wrapAsCode = true;
-        // Basic splitting.
-        computeAndAssert("foo bar foo bar", [ 12 ]);
-        computeAndAssert("foo bar f   bar", [ 12 ]);
-        computeAndAssert("foo bar f     r", [ 12 ]); // 14 if we enable 
-        computeAndAssert("foo bar foo bar foo bara foo", [12, 25]);
-
-        // Don't split if there is only whitespaces/tabs at the end of the line.
-        computeAndAssert("foo foo foo \t \t", [ ]);
-
-        // If there is no space to split, force split.
-        computeAndAssert("foooooooooooooo", [ 12 ]);
-        computeAndAssert("fooooooooooooooooooooooooooo", [12, 24]);
-        computeAndAssert("foo bar fooooooooooobooooooo", [8,  20]);
-
-        // Basic splitting + tabs.
-        computeAndAssert("foo \t\tbar", [ 6 ]);
-        computeAndAssert("foo \t \tbar", [ 7 ]);
-
-        // Ignore spaces/tabs at beginning of split.
-        computeAndAssert("foo \t \t   \t \t bar", [ 7 ]); // 14
-
-        // Test wrapping for asian characters.
-        computeAndAssert("ぁぁ", [1], 2);
-        computeAndAssert(" ぁぁ", [1, 2], 2);
-        computeAndAssert(" ぁ\tぁ", [1, 3], 2);
-        computeAndAssert(" ぁぁ\tぁ", [1, 4], 4);
-
-        // Test wrapping for punctuation.
-        computeAndAssert(" ab.c;ef++", [1, 3, 5, 7, 8], 2);
-        computeAndAssert(" a.b", [1, 2, 3], 1);
-        computeAndAssert("#>>", [1, 2], 1);
-        
-        // Test wrapping for punctuation in
-        EditSession.prototype.$wrapAsCode = false;
-        computeAndAssert("ab cde, Juhu kinners", [3, 8, 13, 19], 6);
-    },
-
-    "test get longest line" : function() {
-        var session = new EditSession(["12"]);
-        session.setTabSize(4);
-        assert.equal(session.getScreenWidth(), 2);
-
-        session.doc.insertNewLine({row: 0, column: Infinity});
-        session.doc.insertLines(1, ["123"]);
-        assert.equal(session.getScreenWidth(), 3);
-
-        session.doc.insertNewLine({row: 0, column: Infinity});
-        session.doc.insertLines(1, ["\t\t"]);
-
-        assert.equal(session.getScreenWidth(), 8);
-
-        session.setTabSize(2);
-        assert.equal(session.getScreenWidth(), 4);
-    },
-
-    "test getDisplayString": function() {
-        var session = new EditSession(["12"]);
-        session.setTabSize(4);
-
-        assert.equal(session.$getDisplayTokens("\t").length, 4);
-        assert.equal(session.$getDisplayTokens("abc").length, 3);
-        assert.equal(session.$getDisplayTokens("abc\t").length, 4);
-    },
-
-    "test issue 83": function() {
-        var session = new EditSession("");
-        var editor = new Editor(new MockRenderer(), session);
-        var document = session.getDocument();
-
-        session.setUseWrapMode(true);
-
-        document.insertLines(0, ["a", "b"]);
-        document.insertLines(2, ["c", "d"]);
-        document.removeLines(1, 2);
-    },
-
-    "test wrapMode init has to create wrapData array": function() {
-        var session = new EditSession("foo bar\nfoo bar");
-        var editor = new Editor(new MockRenderer(), session);
-        var document = session.getDocument();
-
-        session.setUseWrapMode(true);
-        session.setWrapLimitRange(3, 3);
-        session.adjustWrapLimit(80);
-
-        // Test if wrapData is there and was computed.
-        assert.equal(session.$wrapData.length, 2);
-        assert.equal(session.$wrapData[0].length, 1);
-        assert.equal(session.$wrapData[1].length, 1);
-    },
-
-    "test first line blank with wrap": function() {
-        var session = new EditSession("\nfoo");
-        session.setUseWrapMode(true);
-        assert.equal(session.doc.getValue(), ["", "foo"].join("\n"));
-    },
-
-    "test first line blank with wrap 2" : function() {
-        var session = new EditSession("");
-        session.setUseWrapMode(true);
-        session.setValue("\nfoo");
-
-        assert.equal(session.doc.getValue(), ["", "foo"].join("\n"));
-    },
-
-    "test fold getFoldDisplayLine": function() {
-        var session = createFoldTestSession();
-        function assertDisplayLine(foldLine, str) {
-            var line = session.getLine(foldLine.end.row);
-            var displayLine =
-                session.getFoldDisplayLine(foldLine, foldLine.end.row, line.length);
-            assert.equal(displayLine, str);
-        }
-
-        assertDisplayLine(session.$foldData[0], "function foo(args...) {")
-        assertDisplayLine(session.$foldData[1], "    for (vfoo...ert(items[bar...\"juhu\");");
-    },
-
-    "test foldLine idxToPosition": function() {
-        var session = createFoldTestSession();
-
-        function assertIdx2Pos(foldLineIdx, idx, row, column) {
-            var foldLine = session.$foldData[foldLineIdx];
-            assert.position(foldLine.idxToPosition(idx), row, column);
-        }
-
-//        "function foo(items) {",
-//        "    for (var i=0; i<items.length; i++) {",
-//        "        alert(items[i] + \"juhu\");",
-//        "    }    // Real Tab.",
-//        "}"
-
-        assertIdx2Pos(0, 12, 0, 12);
-        assertIdx2Pos(0, 13, 0, 13);
-        assertIdx2Pos(0, 14, 0, 13);
-        assertIdx2Pos(0, 19, 0, 13);
-        assertIdx2Pos(0, 20, 0, 18);
-
-        assertIdx2Pos(1, 10, 1, 10);
-        assertIdx2Pos(1, 11, 1, 10);
-        assertIdx2Pos(1, 15, 1, 10);
-        assertIdx2Pos(1, 16, 2, 10);
-        assertIdx2Pos(1, 26, 2, 20);
-        assertIdx2Pos(1, 27, 2, 20);
-        assertIdx2Pos(1, 32, 2, 25);
-    },
-
-    "test fold documentToScreen": function() {
-        var session = createFoldTestSession();
-        function assertDoc2Screen(docRow, docCol, screenRow, screenCol) {
-            assert.position(
-                session.documentToScreenPosition(docRow, docCol),
-                screenRow, screenCol
-            );
-        }
-
-        // One fold ending in the same row.
-        assertDoc2Screen(0,  0, 0, 0);
-        assertDoc2Screen(0, 13, 0, 13);
-        assertDoc2Screen(0, 14, 0, 13);
-        assertDoc2Screen(0, 17, 0, 13);
-        assertDoc2Screen(0, 18, 0, 20);
-
-        // Fold ending on some other row.
-        assertDoc2Screen(1,  0, 1, 0);
-        assertDoc2Screen(1, 10, 1, 10);
-        assertDoc2Screen(1, 11, 1, 10);
-        assertDoc2Screen(1, 99, 1, 10);
-
-        assertDoc2Screen(2,  0, 1, 10);
-        assertDoc2Screen(2,  9, 1, 10);
-        assertDoc2Screen(2, 10, 1, 16);
-        assertDoc2Screen(2, 11, 1, 17);
-
-        // Fold in the same row with fold over more then one row in the same row.
-        assertDoc2Screen(2, 19, 1, 25);
-        assertDoc2Screen(2, 20, 1, 26);
-        assertDoc2Screen(2, 21, 1, 26);
-
-        assertDoc2Screen(2, 24, 1, 26);
-        assertDoc2Screen(2, 25, 1, 32);
-        assertDoc2Screen(2, 26, 1, 33);
-        assertDoc2Screen(2, 99, 1, 40);
-
-        // Test one position after the folds. Should be all like normal.
-        assertDoc2Screen(3,  0, 2,  0);
-    },
-
-    "test fold screenToDocument": function() {
-        var session = createFoldTestSession();
-        function assertScreen2Doc(docRow, docCol, screenRow, screenCol) {
-            assert.position(
-                session.screenToDocumentPosition(screenRow, screenCol),
-                docRow, docCol
-            );
-        }
-
-        // One fold ending in the same row.
-        assertScreen2Doc(0,  0, 0, 0);
-        assertScreen2Doc(0, 13, 0, 13);
-        assertScreen2Doc(0, 13, 0, 14);
-        assertScreen2Doc(0, 18, 0, 20);
-        assertScreen2Doc(0, 19, 0, 21);
-
-        // Fold ending on some other row.
-        assertScreen2Doc(1,  0, 1, 0);
-        assertScreen2Doc(1, 10, 1, 10);
-        assertScreen2Doc(1, 10, 1, 11);
-
-        assertScreen2Doc(1, 10, 1, 15);
-        assertScreen2Doc(2, 10, 1, 16);
-        assertScreen2Doc(2, 11, 1, 17);
-
-        // Fold in the same row with fold over more then one row in the same row.
-        assertScreen2Doc(2, 19, 1, 25);
-        assertScreen2Doc(2, 20, 1, 26);
-        assertScreen2Doc(2, 20, 1, 27);
-
-        assertScreen2Doc(2, 20, 1, 31);
-        assertScreen2Doc(2, 25, 1, 32);
-        assertScreen2Doc(2, 26, 1, 33);
-        assertScreen2Doc(2, 33, 1, 99);
-
-        // Test one position after the folds. Should be all like normal.
-        assertScreen2Doc(3,  0, 2,  0);
-    },
-
-    "test getFoldsInRange()": function() {
-        var session = createFoldTestSession();
-        var foldLines = session.$foldData;
-        var folds = foldLines[0].folds.concat(foldLines[1].folds);
-
-        function test(startRow, startColumn, endColumn, endRow, folds) {
-            var r = new Range(startRow, startColumn, endColumn, endRow);
-            var retFolds = session.getFoldsInRange(r);
-
-            assert.ok(retFolds.length == folds.length);
-            for (var i = 0; i < retFolds.length; i++) {
-                assert.equal(retFolds[i].range + "", folds[i].range + "");
-            }
-        }
-
-        test(0, 0, 0, 13,  [ ]);
-        test(0, 0, 0, 14,  [ folds[0] ]);
-        test(0, 0, 0, 18,  [ folds[0] ]);
-        test(0, 0, 1, 10,  [ folds[0] ]);
-        test(0, 0, 1, 11,  [ folds[0], folds[1] ]);
-        test(0, 18, 1, 11, [ folds[1] ]);
-        test(2, 0,  2, 13, [ folds[1] ]);
-        test(2, 10, 2, 20, [ ]);
-        test(2, 10, 2, 11, [ ]);
-        test(2, 19, 2, 20, [ ]);
-    },
-
-    "test fold one-line text insert": function() {
-        // These are mostly test for the FoldLine.addRemoveChars function.
-        var session = createFoldTestSession();
-        var undoManager = session.getUndoManager();
-        var foldLines = session.$foldData;
-
-        function insert(row, column, text) {
-            session.insert({row: row, column: column}, text);
-
-            // Force the session to store all changes made to the document NOW
-            // on the undoManager's queue. Otherwise we can't undo in separate
-            // steps later.
-            session.$syncInformUndoManager();
-        }
-
-        var foldLine, fold, folds;
-        // First line.
-        foldLine = session.$foldData[0];
-        fold = foldLine.folds[0];
-
-        insert(0, 0, "0");
-        assert.range(foldLine.range, 0, 14, 0, 19);
-        assert.range(fold.range,     0, 14, 0, 19);
-        insert(0, 14, "1");
-        assert.range(foldLine.range, 0, 15, 0, 20);
-        assert.range(fold.range,     0, 15, 0, 20);
-        insert(0, 20, "2");
-        assert.range(foldLine.range, 0, 15, 0, 20);
-        assert.range(fold.range,     0, 15, 0, 20);
-
-        // Second line.
-        foldLine = session.$foldData[1];
-        folds = foldLine.folds;
-
-        insert(1, 0, "3");
-        assert.range(foldLine.range, 1, 11, 2, 25);
-        assert.range(folds[0].range, 1, 11, 2, 10);
-        assert.range(folds[1].range, 2, 20, 2, 25);
-
-        insert(1, 11, "4");
-        assert.range(foldLine.range, 1, 12, 2, 25);
-        assert.range(folds[0].range, 1, 12, 2, 10);
-        assert.range(folds[1].range, 2, 20, 2, 25);
-
-        insert(2, 10, "5");
-        assert.range(foldLine.range, 1, 12, 2, 26);
-        assert.range(folds[0].range, 1, 12, 2, 10);
-        assert.range(folds[1].range, 2, 21, 2, 26);
-
-        insert(2, 21, "6");
-        assert.range(foldLine.range, 1, 12, 2, 27);
-        assert.range(folds[0].range, 1, 12, 2, 10);
-        assert.range(folds[1].range, 2, 22, 2, 27);
-
-        insert(2, 27, "7");
-        assert.range(foldLine.range, 1, 12, 2, 27);
-        assert.range(folds[0].range, 1, 12, 2, 10);
-        assert.range(folds[1].range, 2, 22, 2, 27);
-
-        // UNDO = REMOVE
-        undoManager.undo(); // 6
-        assert.range(foldLine.range, 1, 12, 2, 27);
-        assert.range(folds[0].range, 1, 12, 2, 10);
-        assert.range(folds[1].range, 2, 22, 2, 27);
-
-        undoManager.undo(); // 5
-        assert.range(foldLine.range, 1, 12, 2, 26);
-        assert.range(folds[0].range, 1, 12, 2, 10);
-        assert.range(folds[1].range, 2, 21, 2, 26);
-
-        undoManager.undo(); // 4
-        assert.range(foldLine.range, 1, 12, 2, 25);
-        assert.range(folds[0].range, 1, 12, 2, 10);
-        assert.range(folds[1].range, 2, 20, 2, 25);
-
-        undoManager.undo(); // 3
-        assert.range(foldLine.range, 1, 11, 2, 25);
-        assert.range(folds[0].range, 1, 11, 2, 10);
-        assert.range(folds[1].range, 2, 20, 2, 25);
-
-        undoManager.undo(); // Beginning first line.
-        assert.equal(foldLines.length, 2);
-        assert.range(foldLines[0].range, 0, 15, 0, 20);
-        assert.range(foldLines[1].range, 1, 10, 2, 25);
-
-        foldLine = session.$foldData[0];
-        fold = foldLine.folds[0];
-
-        undoManager.undo(); // 2
-        assert.range(foldLine.range, 0, 15, 0, 20);
-        assert.range(fold.range,     0, 15, 0, 20);
-
-        undoManager.undo(); // 1
-        assert.range(foldLine.range, 0, 14, 0, 19);
-        assert.range(fold.range,     0, 14, 0, 19);
-
-        undoManager.undo(); // 0
-        assert.range(foldLine.range, 0, 13, 0, 18);
-        assert.range(fold.range,     0, 13, 0, 18);
-    },
-
-    "test fold multi-line insert/remove": function() {
-        var session = createFoldTestSession(),
-            undoManager = session.getUndoManager(),
-            foldLines = session.$foldData;
-        function insert(row, column, text) {
-            session.insert({row: row, column: column}, text);
-            // Force the session to store all changes made to the document NOW
-            // on the undoManager's queue. Otherwise we can't undo in separate
-            // steps later.
-            session.$syncInformUndoManager();
-        }
-
-        var foldLines = session.$foldData, foldLine, fold, folds;
-
-        insert(0, 0, "\nfo0");
-        assert.equal(foldLines.length, 2);
-        assert.range(foldLines[0].range, 1, 16, 1, 21);
-        assert.range(foldLines[1].range, 2, 10, 3, 25);
-
-        insert(2, 0, "\nba1");
-        assert.equal(foldLines.length, 2);
-        assert.range(foldLines[0].range, 1, 16, 1, 21);
-        assert.range(foldLines[1].range, 3, 13, 4, 25);
-
-        insert(3, 10, "\nfo2");
-        assert.equal(foldLines.length, 2);
-        assert.range(foldLines[0].range, 1, 16, 1, 21);
-        assert.range(foldLines[1].range, 4,  6, 5, 25);
-
-        insert(5, 10, "\nba3");
-        assert.equal(foldLines.length, 3);
-        assert.range(foldLines[0].range, 1, 16, 1, 21);
-        assert.range(foldLines[1].range, 4,  6, 5, 10);
-        assert.range(foldLines[2].range, 6, 13, 6, 18);
-
-        insert(6, 18, "\nfo4");
-        assert.equal(foldLines.length, 3);
-        assert.range(foldLines[0].range, 1, 16, 1, 21);
-        assert.range(foldLines[1].range, 4,  6, 5, 10);
-        assert.range(foldLines[2].range, 6, 13, 6, 18);
-
-        undoManager.undo(); // 3
-        assert.equal(foldLines.length, 3);
-        assert.range(foldLines[0].range, 1, 16, 1, 21);
-        assert.range(foldLines[1].range, 4,  6, 5, 10);
-        assert.range(foldLines[2].range, 6, 13, 6, 18);
-
-        undoManager.undo(); // 2
-        assert.equal(foldLines.length, 2);
-        assert.range(foldLines[0].range, 1, 16, 1, 21);
-        assert.range(foldLines[1].range, 4,  6, 5, 25);
-
-        undoManager.undo(); // 1
-        assert.equal(foldLines.length, 2);
-        assert.range(foldLines[0].range, 1, 16, 1, 21);
-        assert.range(foldLines[1].range, 3, 13, 4, 25);
-
-        undoManager.undo(); // 0
-        assert.equal(foldLines.length, 2);
-        assert.range(foldLines[0].range, 1, 16, 1, 21);
-        assert.range(foldLines[1].range, 2, 10, 3, 25);
-
-        undoManager.undo(); // Beginning
-        assert.equal(foldLines.length, 2);
-        assert.range(foldLines[0].range, 0, 13, 0, 18);
-        assert.range(foldLines[1].range, 1, 10, 2, 25);
-        // TODO: Add test for inseration inside of folds.
-    },
-
-    "test fold wrap data compution": function() {
-        function assertWrap(line0, line1, line2) {
-            line0 && assertArray(wrapData[0], line0);
-            line1 && assertArray(wrapData[1], line1);
-            line2 && assertArray(wrapData[2], line2);
-        }
-
-        function removeFoldAssertWrap(docRow, docColumn, line0, line1, line2) {
-            session.removeFold(session.getFoldAt(docRow, docColumn));
-            assertWrap(line0, line1, line2);
-        }
-
-        var lines = [
-            "foo bar foo bar",
-            "foo bar foo bar",
-            "foo bar foo bar"
-        ];
-
-        var session = new EditSession(lines.join("\n"));
-        session.setUseWrapMode(true);
-        session.$wrapLimit = 7;
-        session.$updateWrapData(0, 2);
-        var wrapData = session.$wrapData;
-
-        // Do a simple assertion without folds to check basic functionallity.
-        assertWrap([8], [8], [8]);
-
-        // --- Do in line folding ---
-
-        // Adding a fold. The split position is inside of the fold. As placeholder
-        // are not splitable, the split should be before the split.
-        session.addFold("woot", new Range(0, 4, 0, 15));
-        assertWrap([4], [8], [8]);
-
-        // Remove the fold again which should reset the wrapData.
-        removeFoldAssertWrap(0, 4, [8], [8], [8]);
-
-        session.addFold("woot", new Range(0, 6, 0, 9));
-        assertWrap([6, 13], [8], [8]);
-        removeFoldAssertWrap(0, 6, [8], [8], [8]);
-
-        // The fold fits into the wrap limit - no split expected.
-        session.addFold("woot", new Range(0, 3, 0, 15));
-        assertWrap([], [8], [8]);
-        removeFoldAssertWrap(0, 4, [8], [8], [8]);
-
-        // Fold after split position should be all fine.
-        session.addFold("woot", new Range(0, 8, 0, 15));
-        assertWrap([8], [8], [8]);
-        removeFoldAssertWrap(0, 8, [8], [8], [8]);
-
-        // Fold's placeholder is far too long for wrapSplit.
-        session.addFold("woot0123456789", new Range(0, 8, 0, 15));
-        assertWrap([8], [8], [8]);
-        removeFoldAssertWrap(0, 8, [8], [8], [8]);
-
-        // Fold's placeholder is far too long for wrapSplit
-        // + content at the end of the line
-        session.addFold("woot0123456789", new Range(0, 6, 0, 8));
-        assertWrap([6, 20], [8], [8]);
-        removeFoldAssertWrap(0, 8, [8], [8], [8]);
-
-        session.addFold("woot0123456789", new Range(0, 6, 0, 8));
-        session.addFold("woot0123456789", new Range(0, 8, 0, 10));
-        assertWrap([6, 20, 34], [8], [8]);
-        session.removeFold(session.getFoldAt(0, 7));
-        removeFoldAssertWrap(0, 8, [8], [8], [8]);
-
-        session.addFold("woot0123456789", new Range(0, 7, 0, 9));
-        session.addFold("woot0123456789", new Range(0, 13, 0, 15));
-        assertWrap([7, 21, 25], [8], [8]);
-        session.removeFold(session.getFoldAt(0, 7));
-        removeFoldAssertWrap(0, 14, [8], [8], [8]);
-
-        // --- Do some multiline folding ---
-
-        // Add a fold over two lines. Note, that the wrapData[1] stays the
-        // same. This is an implementation detail and expected behavior.
-        session.addFold("woot", new Range(0, 8, 1, 15));
-        assertWrap([8], [8 /* See comments */], [8]);
-        removeFoldAssertWrap(0, 8, [8], [8], [8]);
-
-        session.addFold("woot", new Range(0, 9, 1, 11));
-        assertWrap([8, 14], [8 /* See comments */], [8]);
-        removeFoldAssertWrap(0, 9, [8], [8], [8]);
-
-        session.addFold("woot", new Range(0, 9, 1, 15));
-        assertWrap([8], [8 /* See comments */], [8]);
-        removeFoldAssertWrap(0, 9, [8], [8], [8]);
-
-        return session;
-    },
-    
-    "test delete fold with wrap enabled": function() {
-        var session = new EditSession("");
-        session.setValue([
-            "This is some placeholder text that will be folded inline.",
-            "This is some placeholder text that will be folded inline.",
-            "More text.",
-            "<p>The cursor in this paragraph text will be offset by 1 row.<p>",
-            "<p>Everything after this will be offset as well due to the folds in the row before too.</p>"
-        ].join("\n"));
-        session.addFold('...', new Range(0, 8, 0, 42));
-        session.addFold('...', new Range(1, 8, 1, 42));
-        session.addFold('...', new Range(3, 7, 3, 51));
-        session.setOption("wrap", 40);
-        session.remove(new Range(0,0, 2, 5));
-        // needed because adjustWrapLimit is called async from renderer
-        session.adjustWrapLimit(80);
-        
-        assert.equal(session.$wrapData + "", [[], [], [40, 76]] + "");
-    },
-        
-    "test add fold": function() {
-        var session = createFoldTestSession();
-        var fold;
-
-        function tryAddFold(placeholder, range, shouldFail) {
-            var fail = false;
-            try {
-                fold = session.addFold(placeholder, range);
-            } catch (e) {
-                fail = true;
-            }
-            if (fail != shouldFail) {
-                throw new Error("Expected to get an exception");
-            }
-        }
-
-        tryAddFold("foo", new Range(0, 13, 0, 17), false);
-        tryAddFold("foo", new Range(0, 14, 0, 18), true);
-        tryAddFold("foo", new Range(0, 13, 0, 18), false);
-        assert.equal(session.$foldData[0].folds.length, 1);
-
-        tryAddFold("f", new Range(0, 13, 0, 18), false);
-        tryAddFold("foo", new Range(0, 18, 0, 21), false);
-        assert.equal(session.$foldData[0].folds.length, 2);
-        session.removeFold(fold);
-
-        tryAddFold("foo", new Range(0, 18, 0, 22), false);
-        tryAddFold("foo", new Range(0, 18, 0, 19), true);
-        tryAddFold("foo", new Range(0, 22, 1, 10), false);
-    },
-
-    "test add subfolds": function() {
-        var session = createFoldTestSession();
-        var fold, oldFold;
-        var foldData = session.$foldData;
-
-        oldFold = foldData[0].folds[0];
-
-        fold = session.addFold("fold0", new Range(0, 10, 0, 21));
-        assert.equal(foldData[0].folds.length, 1);
-        assert.equal(fold.subFolds.length, 1);
-        assert.equal(fold.subFolds[0], oldFold);
-
-        session.expandFold(fold);
-        assert.equal(foldData[0].folds.length, 1);
-        assert.equal(foldData[0].folds[0], oldFold);
-        assert.equal(fold.subFolds.length, 0);
-
-        fold = session.addFold("fold0", new Range(0, 13, 2, 10));
-        assert.equal(foldData.length, 1);
-        assert.equal(fold.subFolds.length, 2);
-        assert.equal(fold.subFolds[0], oldFold);
-
-        session.expandFold(fold);
-        assert.equal(foldData.length, 2);
-        assert.equal(foldData[0].folds.length, 1);
-        assert.equal(foldData[0].folds[0], oldFold);
-        assert.equal(fold.subFolds.length, 0);
-
-        session.unfold(null, true);
-        fold = session.addFold("fold0", new Range(0, 0, 0, 21));
-        session.addFold("fold0", new Range(0, 1, 0, 5));
-        session.addFold("fold0", new Range(0, 6, 0, 8));
-        assert.equal(fold.subFolds.length, 2);
-    },
-
-    "test row cache": function() {
-        var session = createFoldTestSession();
-
-        session.screenToDocumentPosition(2,3);
-        assertArray(session.$docRowCache, [1,3]);
-        assertArray(session.$screenRowCache, [1,2]);
-
-        session.screenToDocumentPosition(5,3);
-        assertArray(session.$docRowCache, [1,3,4]);
-        assertArray(session.$screenRowCache, [1,2,3]);
-
-        session.screenToDocumentPosition(0,3);
-        assertArray(session.$docRowCache, [1,3,4]);
-        assertArray(session.$screenRowCache, [1,2,3]);
-
-        var pos = session.screenToDocumentPosition(0,0);
-        assert.equal(pos.row, 0);
-        assertArray(session.$docRowCache, [1,3,4]);
-        assertArray(session.$screenRowCache, [1,2,3]);
-        
-        session.screenToDocumentPosition(1,0);
-        assertArray(session.$docRowCache, [1,3,4]);
-        assertArray(session.$screenRowCache, [1,2,3]);
-
-        session.$resetRowCache();
-        assertArray(session.$docRowCache, []);
-        assertArray(session.$screenRowCache, []);
-        
-        session.screenToDocumentPosition(1,3);
-        assertArray(session.$docRowCache, [1]);
-        assertArray(session.$screenRowCache, [1]);
-       
-        session.screenToDocumentPosition(5,3);
-        assertArray(session.$docRowCache, [1,3,4]);
-        assertArray(session.$screenRowCache, [1,2,3]);
-        
-        session = new EditSession(new Array(30).join("\n"));
-        session.documentToScreenPosition(2,0);
-        session.documentToScreenPosition(2,0);
-        assertArray(session.$docRowCache, [1,2]);
-        assertArray(session.$screenRowCache, [1,2]);
-    },
-
-    "test annotations": function() {
-        var session = new EditSession([]),
-            annotation = {row: 0, type: 'info', text: "This is a test."};
-
-        session.clearAnnotations();
-        assertArray(session.getAnnotations(), []);
-        session.setAnnotations([annotation]);
-        assertArray(session.getAnnotations(), [annotation]);
-    },
-    
-    "test: mode loading" : function(next) {
-        if (!require.undef) {
-            console.log("Skipping test: This test only runs in the browser");
-            next();
-            return;
-        }
-        var session = new EditSession([]);
-        session.setMode("ace/mode/javascript");
-        assert.equal(session.$modeid, "ace/mode/javascript");
-        session.on("changeMode", function() {
-            assert.equal(session.$modeid, "ace/mode/javascript");
-        });
-        session.setMode("ace/mode/sh", function(mode) {
-            assert.ok(!mode);
-        });
-        setTimeout(function() {
-            session.setMode("ace/mode/javascript", function(mode) {
-                session.setMode("ace/mode/javascript");
-                assert.equal(session.$modeid, "ace/mode/javascript");
-                next();
-            });
-        }, 0);
-    }
-};
-});
-
-if (typeof module !== "undefined" && module === require.main) {
-    require("asyncjs").test.testcase(module.exports).exec();
-}

+ 0 - 2444
services/web/public/js/ace/editor.js

@@ -1,2444 +0,0 @@
-/* ***** 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";
-
-require("./lib/fixoldbrowsers");
-
-var oop = require("./lib/oop");
-var dom = require("./lib/dom");
-var lang = require("./lib/lang");
-var useragent = require("./lib/useragent");
-var TextInput = require("./keyboard/textinput").TextInput;
-var MouseHandler = require("./mouse/mouse_handler").MouseHandler;
-var FoldHandler = require("./mouse/fold_handler").FoldHandler;
-var KeyBinding = require("./keyboard/keybinding").KeyBinding;
-var EditSession = require("./edit_session").EditSession;
-var Search = require("./search").Search;
-var Range = require("./range").Range;
-var EventEmitter = require("./lib/event_emitter").EventEmitter;
-var CommandManager = require("./commands/command_manager").CommandManager;
-var defaultCommands = require("./commands/default_commands").commands;
-var config = require("./config");
-
-/**
- * The main entry point into the Ace functionality.
- *
- * The `Editor` manages the [[EditSession]] (which manages [[Document]]s), as well as the [[VirtualRenderer]], which draws everything to the screen.
- *
- * Event sessions dealing with the mouse and keyboard are bubbled up from `Document` to the `Editor`, which decides what to do with them.
- * @class Editor
- **/
-
-/**
- * Creates a new `Editor` object.
- *
- * @param {VirtualRenderer} renderer Associated `VirtualRenderer` that draws everything
- * @param {EditSession} session The `EditSession` to refer to
- *
- *
- * @constructor
- **/
-var Editor = function(renderer, session) {
-    var container = renderer.getContainerElement();
-    this.container = container;
-    this.renderer = renderer;
-
-    this.commands = new CommandManager(useragent.isMac ? "mac" : "win", defaultCommands);
-    this.textInput  = new TextInput(renderer.getTextAreaContainer(), this);
-    this.renderer.textarea = this.textInput.getElement();
-    this.keyBinding = new KeyBinding(this);
-
-    // TODO detect touch event support
-    this.$mouseHandler = new MouseHandler(this);
-    new FoldHandler(this);
-
-    this.$blockScrolling = 0;
-    this.$search = new Search().set({
-        wrap: true
-    });
-
-    this.$historyTracker = this.$historyTracker.bind(this);
-    this.commands.on("exec", this.$historyTracker);
-
-    this.$initOperationListeners();
-    
-    this._$emitInputEvent = lang.delayedCall(function() {
-        this._signal("input", {});
-        this.session.bgTokenizer && this.session.bgTokenizer.scheduleStart();
-    }.bind(this));
-    
-    this.on("change", function(_, _self) {
-        _self._$emitInputEvent.schedule(31);
-    });
-
-    this.setSession(session || new EditSession(""));
-    config.resetOptions(this);
-    config._emit("editor", this);
-};
-
-(function(){
-
-    oop.implement(this, EventEmitter);
-
-    this.$initOperationListeners = function() {
-        function last(a) {return a[a.length - 1]}
-
-        this.selections = [];
-        this.commands.on("exec", function(e) {
-            this.startOperation(e);
-
-            var command = e.command;
-            if (command.aceCommandGroup == "fileJump") {
-                var prev = this.prevOp;
-                if (!prev || prev.command.aceCommandGroup != "fileJump") {
-                    this.lastFileJumpPos = last(this.selections);
-                }
-            } else {
-                this.lastFileJumpPos = null;
-            }
-        }.bind(this), true);
-
-        this.commands.on("afterExec", function(e) {
-            var command = e.command;
-
-            if (command.aceCommandGroup == "fileJump") {
-                if (this.lastFileJumpPos && !this.curOp.selectionChanged) {
-                    this.selection.fromJSON(this.lastFileJumpPos);
-                    return;
-                }
-            }
-            this.endOperation(e);
-        }.bind(this), true);
-
-        this.$opResetTimer = lang.delayedCall(this.endOperation.bind(this));
-
-        this.on("change", function() {
-            this.curOp || this.startOperation();
-            this.curOp.docChanged = true;
-        }.bind(this), true);
-
-        this.on("changeSelection", function() {
-            this.curOp || this.startOperation();
-            this.curOp.selectionChanged = true;
-        }.bind(this), true);
-    };
-
-    this.curOp = null;
-    this.prevOp = {};
-    this.startOperation = function(commadEvent) {
-        if (this.curOp) {
-            if (!commadEvent || this.curOp.command)
-                return;
-            this.prevOp = this.curOp;
-        }
-        if (!commadEvent) {
-            this.previousCommand = null;
-            commadEvent = {};
-        }
-
-        this.$opResetTimer.schedule();
-        this.curOp = {
-            command: commadEvent.command || {},
-            args: commadEvent.args
-        };
-        
-        var command = this.curOp.command;
-        if (command && command.scrollIntoView)
-            this.$blockScrolling++;
-
-        this.selections.push(this.selection.toJSON());
-    };
-
-    this.endOperation = function() {
-        if (this.curOp) {
-            var command = this.curOp.command;
-            if (command && command.scrollIntoView) {
-                this.$blockScrolling--;
-                switch (command.scrollIntoView) {
-                    case "center":
-                        this.renderer.scrollCursorIntoView(null, 0.5);
-                        break;
-                    case "cursor":
-                        this.renderer.scrollCursorIntoView();
-                        break;
-                    case "selectionPart":
-                        this.renderer.scrollCursorIntoView();
-                        break;
-                    default:
-                        break;
-                }
-            }
-            this.prevOp = this.curOp;
-            this.curOp = null;
-        }
-    };
-
-    this.$historyTracker = function(e) {
-        if (!this.$mergeUndoDeltas)
-            return;
-
-
-        var prev = this.prevOp;
-        var mergeableCommands = ["backspace", "del", "insertstring"];
-        // previous command was the same
-        var shouldMerge = prev.command && (e.command.name == prev.command.name);
-        if (e.command.name == "insertstring") {
-            var text = e.args;
-            if (this.mergeNextCommand === undefined)
-                this.mergeNextCommand = true;
-
-            shouldMerge = shouldMerge
-                && this.mergeNextCommand // previous command allows to coalesce with
-                && (!/\s/.test(text) || /\s/.test(prev.args)); // previous insertion was of same type
-
-            this.mergeNextCommand = true;
-        } else {
-            shouldMerge = shouldMerge
-                && mergeableCommands.indexOf(e.command.name) !== -1; // the command is mergeable
-        }
-
-        if (
-            this.$mergeUndoDeltas != "always"
-            && Date.now() - this.sequenceStartTime > 2000
-        ) {
-            shouldMerge = false; // the sequence is too long
-        }
-
-        if (shouldMerge)
-            this.session.mergeUndoDeltas = true;
-        else if (mergeableCommands.indexOf(e.command.name) !== -1)
-            this.sequenceStartTime = Date.now();
-    };
-
-    /**
-     * Sets a new key handler, such as "vim" or "windows".
-     * @param {String} keyboardHandler The new key handler
-     *
-     *
-     **/
-    this.setKeyboardHandler = function(keyboardHandler) {
-        if (!keyboardHandler) {
-            this.keyBinding.setKeyboardHandler(null);
-        } else if (typeof keyboardHandler == "string") {
-            this.$keybindingId = keyboardHandler;
-            var _self = this;
-            config.loadModule(["keybinding", keyboardHandler], function(module) {
-                if (_self.$keybindingId == keyboardHandler)
-                    _self.keyBinding.setKeyboardHandler(module && module.handler);
-            });
-        } else {
-            this.$keybindingId = null;
-            this.keyBinding.setKeyboardHandler(keyboardHandler);
-        }
-    };
-
-    /**
-     * Returns the keyboard handler, such as "vim" or "windows".
-     *
-     * @returns {String}
-     *
-     **/
-    this.getKeyboardHandler = function() {
-        return this.keyBinding.getKeyboardHandler();
-    };
-
-
-    /**
-     * Emitted whenever the [[EditSession]] changes.
-     * @event changeSession
-     * @param {Object} e An object with two properties, `oldSession` and `session`, that represent the old and new [[EditSession]]s.
-     *
-     *
-     **/
-    /**
-     * Sets a new editsession to use. This method also emits the `'changeSession'` event.
-     * @param {EditSession} session The new session to use
-     *
-     *
-     **/
-    this.setSession = function(session) {
-        if (this.session == session)
-            return;
-
-        if (this.session) {
-            var oldSession = this.session;
-            this.session.removeEventListener("change", this.$onDocumentChange);
-            this.session.removeEventListener("changeMode", this.$onChangeMode);
-            this.session.removeEventListener("tokenizerUpdate", this.$onTokenizerUpdate);
-            this.session.removeEventListener("changeTabSize", this.$onChangeTabSize);
-            this.session.removeEventListener("changeWrapLimit", this.$onChangeWrapLimit);
-            this.session.removeEventListener("changeWrapMode", this.$onChangeWrapMode);
-            this.session.removeEventListener("onChangeFold", this.$onChangeFold);
-            this.session.removeEventListener("changeFrontMarker", this.$onChangeFrontMarker);
-            this.session.removeEventListener("changeBackMarker", this.$onChangeBackMarker);
-            this.session.removeEventListener("changeBreakpoint", this.$onChangeBreakpoint);
-            this.session.removeEventListener("changeAnnotation", this.$onChangeAnnotation);
-            this.session.removeEventListener("changeOverwrite", this.$onCursorChange);
-            this.session.removeEventListener("changeScrollTop", this.$onScrollTopChange);
-            this.session.removeEventListener("changeScrollLeft", this.$onScrollLeftChange);
-
-            var selection = this.session.getSelection();
-            selection.removeEventListener("changeCursor", this.$onCursorChange);
-            selection.removeEventListener("changeSelection", this.$onSelectionChange);
-        }
-
-        this.session = session;
-
-        this.$onDocumentChange = this.onDocumentChange.bind(this);
-        session.addEventListener("change", this.$onDocumentChange);
-        this.renderer.setSession(session);
-
-        this.$onChangeMode = this.onChangeMode.bind(this);
-        session.addEventListener("changeMode", this.$onChangeMode);
-
-        this.$onTokenizerUpdate = this.onTokenizerUpdate.bind(this);
-        session.addEventListener("tokenizerUpdate", this.$onTokenizerUpdate);
-
-        this.$onChangeTabSize = this.renderer.onChangeTabSize.bind(this.renderer);
-        session.addEventListener("changeTabSize", this.$onChangeTabSize);
-
-        this.$onChangeWrapLimit = this.onChangeWrapLimit.bind(this);
-        session.addEventListener("changeWrapLimit", this.$onChangeWrapLimit);
-
-        this.$onChangeWrapMode = this.onChangeWrapMode.bind(this);
-        session.addEventListener("changeWrapMode", this.$onChangeWrapMode);
-
-        this.$onChangeFold = this.onChangeFold.bind(this);
-        session.addEventListener("changeFold", this.$onChangeFold);
-
-        this.$onChangeFrontMarker = this.onChangeFrontMarker.bind(this);
-        this.session.addEventListener("changeFrontMarker", this.$onChangeFrontMarker);
-
-        this.$onChangeBackMarker = this.onChangeBackMarker.bind(this);
-        this.session.addEventListener("changeBackMarker", this.$onChangeBackMarker);
-
-        this.$onChangeBreakpoint = this.onChangeBreakpoint.bind(this);
-        this.session.addEventListener("changeBreakpoint", this.$onChangeBreakpoint);
-
-        this.$onChangeAnnotation = this.onChangeAnnotation.bind(this);
-        this.session.addEventListener("changeAnnotation", this.$onChangeAnnotation);
-
-        this.$onCursorChange = this.onCursorChange.bind(this);
-        this.session.addEventListener("changeOverwrite", this.$onCursorChange);
-
-        this.$onScrollTopChange = this.onScrollTopChange.bind(this);
-        this.session.addEventListener("changeScrollTop", this.$onScrollTopChange);
-
-        this.$onScrollLeftChange = this.onScrollLeftChange.bind(this);
-        this.session.addEventListener("changeScrollLeft", this.$onScrollLeftChange);
-
-        this.selection = session.getSelection();
-        this.selection.addEventListener("changeCursor", this.$onCursorChange);
-
-        this.$onSelectionChange = this.onSelectionChange.bind(this);
-        this.selection.addEventListener("changeSelection", this.$onSelectionChange);
-
-        this.onChangeMode();
-
-        this.$blockScrolling += 1;
-        this.onCursorChange();
-        this.$blockScrolling -= 1;
-
-        this.onScrollTopChange();
-        this.onScrollLeftChange();
-        this.onSelectionChange();
-        this.onChangeFrontMarker();
-        this.onChangeBackMarker();
-        this.onChangeBreakpoint();
-        this.onChangeAnnotation();
-        this.session.getUseWrapMode() && this.renderer.adjustWrapLimit();
-        this.renderer.updateFull();
-
-        this._emit("changeSession", {
-            session: session,
-            oldSession: oldSession
-        });
-    };
-
-    /**
-     * Returns the current session being used.
-     * @returns {EditSession}
-     **/
-    this.getSession = function() {
-        return this.session;
-    };
-
-    /**
-     * Sets the current document to `val`.
-     * @param {String} val The new value to set for the document
-     * @param {Number} cursorPos Where to set the new value. `undefined` or 0 is selectAll, -1 is at the document start, and 1 is at the end
-     *
-     * @returns {String} The current document value
-     * @related Document.setValue
-     **/
-    this.setValue = function(val, cursorPos) {
-        this.session.doc.setValue(val);
-
-        if (!cursorPos)
-            this.selectAll();
-        else if (cursorPos == 1)
-            this.navigateFileEnd();
-        else if (cursorPos == -1)
-            this.navigateFileStart();
-
-        return val;
-    };
-
-    /**
-     * Returns the current session's content.
-     *
-     * @returns {String}
-     * @related EditSession.getValue
-     **/
-    this.getValue = function() {
-        return this.session.getValue();
-    };
-
-    /**
-     *
-     * Returns the currently highlighted selection.
-     * @returns {String} The highlighted selection
-     **/
-    this.getSelection = function() {
-        return this.selection;
-    };
-
-    /**
-     * {:VirtualRenderer.onResize}
-     * @param {Boolean} force If `true`, recomputes the size, even if the height and width haven't changed
-     *
-     *
-     * @related VirtualRenderer.onResize
-     **/
-    this.resize = function(force) {
-        this.renderer.onResize(force);
-    };
-
-    /**
-     * {:VirtualRenderer.setTheme}
-     * @param {String} theme The path to a theme
-     *
-     *
-     **/
-    this.setTheme = function(theme) {
-        this.renderer.setTheme(theme);
-    };
-
-    /**
-     * {:VirtualRenderer.getTheme}
-     *
-     * @returns {String} The set theme
-     * @related VirtualRenderer.getTheme
-     **/
-    this.getTheme = function() {
-        return this.renderer.getTheme();
-    };
-
-    /**
-     * {:VirtualRenderer.setStyle}
-     * @param {String} style A class name
-     *
-     *
-     * @related VirtualRenderer.setStyle
-     **/
-    this.setStyle = function(style) {
-        this.renderer.setStyle(style);
-    };
-
-    /**
-     * {:VirtualRenderer.unsetStyle}
-     * @related VirtualRenderer.unsetStyle
-     **/
-    this.unsetStyle = function(style) {
-        this.renderer.unsetStyle(style);
-    };
-
-    /**
-     * Gets the current font size of the editor text.
-     */
-    this.getFontSize = function () {
-        return this.getOption("fontSize") ||
-           dom.computedStyle(this.container, "fontSize");
-    };
-
-    /**
-     * Set a new font size (in pixels) for the editor text.
-     * @param {String} size A font size ( _e.g._ "12px")
-     *
-     *
-     **/
-    this.setFontSize = function(size) {
-        this.setOption("fontSize", size);
-    };
-
-    this.$highlightBrackets = function() {
-        if (this.session.$bracketHighlight) {
-            this.session.removeMarker(this.session.$bracketHighlight);
-            this.session.$bracketHighlight = null;
-        }
-
-        if (this.$highlightPending) {
-            return;
-        }
-
-        // perform highlight async to not block the browser during navigation
-        var self = this;
-        this.$highlightPending = true;
-        setTimeout(function() {
-            self.$highlightPending = false;
-
-            var pos = self.session.findMatchingBracket(self.getCursorPosition());
-            if (pos) {
-                var range = new Range(pos.row, pos.column, pos.row, pos.column+1);
-            } else if (self.session.$mode.getMatching) {
-                var range = self.session.$mode.getMatching(self.session);
-            }
-            if (range)
-                self.session.$bracketHighlight = self.session.addMarker(range, "ace_bracket", "text");
-        }, 50);
-    };
-
-    /**
-     *
-     * Brings the current `textInput` into focus.
-     **/
-    this.focus = function() {
-        // Safari needs the timeout
-        // iOS and Firefox need it called immediately
-        // to be on the save side we do both
-        var _self = this;
-        setTimeout(function() {
-            _self.textInput.focus();
-        });
-        this.textInput.focus();
-    };
-
-    /**
-     * Returns `true` if the current `textInput` is in focus.
-     * @return {Boolean}
-     **/
-    this.isFocused = function() {
-        return this.textInput.isFocused();
-    };
-
-    /**
-     *
-     * Blurs the current `textInput`.
-     **/
-    this.blur = function() {
-        this.textInput.blur();
-    };
-
-    /**
-     * Emitted once the editor comes into focus.
-     * @event focus
-     *
-     *
-     **/
-    this.onFocus = function() {
-        if (this.$isFocused)
-            return;
-        this.$isFocused = true;
-        this.renderer.showCursor();
-        this.renderer.visualizeFocus();
-        this._emit("focus");
-    };
-
-    /**
-     * Emitted once the editor has been blurred.
-     * @event blur
-     *
-     *
-     **/
-    this.onBlur = function() {
-        if (!this.$isFocused)
-            return;
-        this.$isFocused = false;
-        this.renderer.hideCursor();
-        this.renderer.visualizeBlur();
-        this._emit("blur");
-    };
-
-    this.$cursorChange = function() {
-        this.renderer.updateCursor();
-    };
-
-    /**
-     * Emitted whenever the document is changed.
-     * @event change
-     * @param {Object} e Contains a single property, `data`, which has the delta of changes
-     *
-     *
-     *
-     **/
-    this.onDocumentChange = function(e) {
-        var delta = e.data;
-        var range = delta.range;
-        var lastRow;
-
-        if (range.start.row == range.end.row && delta.action != "insertLines" && delta.action != "removeLines")
-            lastRow = range.end.row;
-        else
-            lastRow = Infinity;
-        this.renderer.updateLines(range.start.row, lastRow);
-
-        this._emit("change", e);
-
-        // update cursor because tab characters can influence the cursor position
-        this.$cursorChange();
-    };
-
-    this.onTokenizerUpdate = function(e) {
-        var rows = e.data;
-        this.renderer.updateLines(rows.first, rows.last);
-    };
-
-
-    this.onScrollTopChange = function() {
-        this.renderer.scrollToY(this.session.getScrollTop());
-    };
-
-    this.onScrollLeftChange = function() {
-        this.renderer.scrollToX(this.session.getScrollLeft());
-    };
-
-    /**
-     * Emitted when the selection changes.
-     *
-     **/
-    this.onCursorChange = function() {
-        this.$cursorChange();
-
-        if (!this.$blockScrolling) {
-            this.renderer.scrollCursorIntoView();
-        }
-
-        this.$highlightBrackets();
-        this.$updateHighlightActiveLine();
-        this._emit("changeSelection");
-    };
-
-    this.$updateHighlightActiveLine = function() {
-        var session = this.getSession();
-
-        var highlight;
-        if (this.$highlightActiveLine) {
-            if ((this.$selectionStyle != "line" || !this.selection.isMultiLine()))
-                highlight = this.getCursorPosition();
-            if (this.renderer.$maxLines && this.session.getLength() === 1)
-                highlight = false;
-        }
-
-        if (session.$highlightLineMarker && !highlight) {
-            session.removeMarker(session.$highlightLineMarker.id);
-            session.$highlightLineMarker = null;
-        } else if (!session.$highlightLineMarker && highlight) {
-            var range = new Range(highlight.row, highlight.column, highlight.row, Infinity);
-            range.id = session.addMarker(range, "ace_active-line", "screenLine");
-            session.$highlightLineMarker = range;
-        } else if (highlight) {
-            session.$highlightLineMarker.start.row = highlight.row;
-            session.$highlightLineMarker.end.row = highlight.row;
-            session.$highlightLineMarker.start.column = highlight.column;
-            session._emit("changeBackMarker");
-        }
-    };
-
-    this.onSelectionChange = function(e) {
-        var session = this.session;
-
-        if (session.$selectionMarker) {
-            session.removeMarker(session.$selectionMarker);
-        }
-        session.$selectionMarker = null;
-
-        if (!this.selection.isEmpty()) {
-            var range = this.selection.getRange();
-            var style = this.getSelectionStyle();
-            session.$selectionMarker = session.addMarker(range, "ace_selection", style);
-        } else {
-            this.$updateHighlightActiveLine();
-        }
-
-        var re = this.$highlightSelectedWord && this.$getSelectionHighLightRegexp();
-        this.session.highlight(re);
-
-        this._emit("changeSelection");
-    };
-
-    this.$getSelectionHighLightRegexp = function() {
-        var session = this.session;
-
-        var selection = this.getSelectionRange();
-        if (selection.isEmpty() || selection.isMultiLine())
-            return;
-
-        var startOuter = selection.start.column - 1;
-        var endOuter = selection.end.column + 1;
-        var line = session.getLine(selection.start.row);
-        var lineCols = line.length;
-        var needle = line.substring(Math.max(startOuter, 0),
-                                    Math.min(endOuter, lineCols));
-
-        // Make sure the outer characters are not part of the word.
-        if ((startOuter >= 0 && /^[\w\d]/.test(needle)) ||
-            (endOuter <= lineCols && /[\w\d]$/.test(needle)))
-            return;
-
-        needle = line.substring(selection.start.column, selection.end.column);
-        if (!/^[\w\d]+$/.test(needle))
-            return;
-
-        var re = this.$search.$assembleRegExp({
-            wholeWord: true,
-            caseSensitive: true,
-            needle: needle
-        });
-
-        return re;
-    };
-
-
-    this.onChangeFrontMarker = function() {
-        this.renderer.updateFrontMarkers();
-    };
-
-    this.onChangeBackMarker = function() {
-        this.renderer.updateBackMarkers();
-    };
-
-
-    this.onChangeBreakpoint = function() {
-        this.renderer.updateBreakpoints();
-    };
-
-    this.onChangeAnnotation = function() {
-        this.renderer.setAnnotations(this.session.getAnnotations());
-    };
-
-
-    this.onChangeMode = function(e) {
-        this.renderer.updateText();
-        this._emit("changeMode", e);
-    };
-
-
-    this.onChangeWrapLimit = function() {
-        this.renderer.updateFull();
-    };
-
-    this.onChangeWrapMode = function() {
-        this.renderer.onResize(true);
-    };
-
-
-    this.onChangeFold = function() {
-        // Update the active line marker as due to folding changes the current
-        // line range on the screen might have changed.
-        this.$updateHighlightActiveLine();
-        // TODO: This might be too much updating. Okay for now.
-        this.renderer.updateFull();
-    };
-
-    
-    /**
-     * Returns the string of text currently highlighted.
-     * @returns {String}
-     **/
-    this.getSelectedText = function() {
-        return this.session.getTextRange(this.getSelectionRange());
-    };
-    
-    /**
-     * Emitted when text is copied.
-     * @event copy
-     * @param {String} text The copied text
-     *
-     **/
-    /**
-     * Returns the string of text currently highlighted.
-     * @returns {String}
-     * @deprecated Use getSelectedText instead.
-     **/
-    this.getCopyText = function() {
-        var text = this.getSelectedText();
-        this._signal("copy", text);
-        return text;
-    };
-
-    /**
-     * Called whenever a text "copy" happens.
-     **/
-    this.onCopy = function() {
-        this.commands.exec("copy", this);
-    };
-
-    /**
-     * Called whenever a text "cut" happens.
-     **/
-    this.onCut = function() {
-        this.commands.exec("cut", this);
-    };
-
-    /**
-     * Emitted when text is pasted.
-     * @event paste
-     * @param {String} text The pasted text
-     *
-     *
-     **/
-    /**
-     * Called whenever a text "paste" happens.
-     * @param {String} text The pasted text
-     *
-     *
-     **/
-    this.onPaste = function(text) {
-        // todo this should change when paste becomes a command
-        if (this.$readOnly)
-            return;
-        this._emit("paste", text);
-        this.insert(text);
-    };
-
-
-    this.execCommand = function(command, args) {
-        this.commands.exec(command, this, args);
-    };
-
-    /**
-     * Inserts `text` into wherever the cursor is pointing.
-     * @param {String} text The new text to add
-     *
-     *
-     **/
-    this.insert = function(text) {
-        var session = this.session;
-        var mode = session.getMode();
-        var cursor = this.getCursorPosition();
-
-        if (this.getBehavioursEnabled()) {
-            // Get a transform if the current mode wants one.
-            var transform = mode.transformAction(session.getState(cursor.row), 'insertion', this, session, text);
-            if (transform) {
-                if (text !== transform.text) {
-                    this.session.mergeUndoDeltas = false;
-                    this.$mergeNextCommand = false;
-                }
-                text = transform.text;
-
-            }
-        }
-        
-        if (text == "\t")
-            text = this.session.getTabString();
-
-        // remove selected text
-        if (!this.selection.isEmpty()) {
-            var range = this.getSelectionRange();
-            cursor = this.session.remove(range);
-            this.clearSelection();
-        }
-        else if (this.session.getOverwrite()) {
-            var range = new Range.fromPoints(cursor, cursor);
-            range.end.column += text.length;
-            this.session.remove(range);
-        }
-
-        if (text == "\n" || text == "\r\n") {
-            var line = session.getLine(cursor.row)
-            if (cursor.column > line.search(/\S|$/)) {
-                var d = line.substr(cursor.column).search(/\S|$/);
-                session.doc.removeInLine(cursor.row, cursor.column, cursor.column + d);
-            }
-        }
-        this.clearSelection();
-
-        var start = cursor.column;
-        var lineState = session.getState(cursor.row);
-        var line = session.getLine(cursor.row);
-        var shouldOutdent = mode.checkOutdent(lineState, line, text);
-        var end = session.insert(cursor, text);
-
-        if (transform && transform.selection) {
-            if (transform.selection.length == 2) { // Transform relative to the current column
-                this.selection.setSelectionRange(
-                    new Range(cursor.row, start + transform.selection[0],
-                              cursor.row, start + transform.selection[1]));
-            } else { // Transform relative to the current row.
-                this.selection.setSelectionRange(
-                    new Range(cursor.row + transform.selection[0],
-                              transform.selection[1],
-                              cursor.row + transform.selection[2],
-                              transform.selection[3]));
-            }
-        }
-
-        if (session.getDocument().isNewLine(text)) {
-            var lineIndent = mode.getNextLineIndent(lineState, line.slice(0, cursor.column), session.getTabString());
-
-            session.insert({row: cursor.row+1, column: 0}, lineIndent);
-        }
-        if (shouldOutdent)
-            mode.autoOutdent(lineState, session, cursor.row);
-    };
-
-    this.onTextInput = function(text) {
-        this.keyBinding.onTextInput(text);
-    };
-
-    this.onCommandKey = function(e, hashId, keyCode) {
-        this.keyBinding.onCommandKey(e, hashId, keyCode);
-    };
-
-    /**
-     * Pass in `true` to enable overwrites in your session, or `false` to disable. If overwrites is enabled, any text you enter will type over any text after it. If the value of `overwrite` changes, this function also emites the `changeOverwrite` event.
-     * @param {Boolean} overwrite Defines wheter or not to set overwrites
-     *
-     *
-     * @related EditSession.setOverwrite
-     **/
-    this.setOverwrite = function(overwrite) {
-        this.session.setOverwrite(overwrite);
-    };
-
-    /**
-     * Returns `true` if overwrites are enabled; `false` otherwise.
-     * @returns {Boolean}
-     * @related EditSession.getOverwrite
-     **/
-    this.getOverwrite = function() {
-        return this.session.getOverwrite();
-    };
-
-    /**
-     * Sets the value of overwrite to the opposite of whatever it currently is.
-     * @related EditSession.toggleOverwrite
-     **/
-    this.toggleOverwrite = function() {
-        this.session.toggleOverwrite();
-    };
-
-    /**
-     * Sets how fast the mouse scrolling should do.
-     * @param {Number} speed A value indicating the new speed (in milliseconds)
-     **/
-    this.setScrollSpeed = function(speed) {
-        this.setOption("scrollSpeed", speed);
-    };
-
-    /**
-     * Returns the value indicating how fast the mouse scroll speed is (in milliseconds).
-     * @returns {Number}
-     **/
-    this.getScrollSpeed = function() {
-        return this.getOption("scrollSpeed");
-    };
-
-    /**
-     * Sets the delay (in milliseconds) of the mouse drag.
-     * @param {Number} dragDelay A value indicating the new delay
-     **/
-    this.setDragDelay = function(dragDelay) {
-        this.setOption("dragDelay", dragDelay);
-    };
-
-    /**
-     * Returns the current mouse drag delay.
-     * @returns {Number}
-     **/
-    this.getDragDelay = function() {
-        return this.getOption("dragDelay");
-    };
-
-    /**
-     * Emitted when the selection style changes, via [[Editor.setSelectionStyle]].
-     * @event changeSelectionStyle
-     * @param {Object} data Contains one property, `data`, which indicates the new selection style
-     **/
-    /**
-     * Draw selection markers spanning whole line, or only over selected text. Default value is "line"
-     * @param {String} style The new selection style "line"|"text"
-     *
-     **/
-    this.setSelectionStyle = function(val) {
-        this.setOption("selectionStyle", val);
-    };
-
-    /**
-     * Returns the current selection style.
-     * @returns {String}
-     **/
-    this.getSelectionStyle = function() {
-        return this.getOption("selectionStyle");
-    };
-
-    /**
-     * Determines whether or not the current line should be highlighted.
-     * @param {Boolean} shouldHighlight Set to `true` to highlight the current line
-     **/
-    this.setHighlightActiveLine = function(shouldHighlight) {
-        this.setOption("highlightActiveLine", shouldHighlight);
-    };
-    /**
-     * Returns `true` if current lines are always highlighted.
-     * @return {Boolean}
-     **/
-    this.getHighlightActiveLine = function() {
-        return this.getOption("highlightActiveLine");
-    };
-    this.setHighlightGutterLine = function(shouldHighlight) {
-        this.setOption("highlightGutterLine", shouldHighlight);
-    };
-
-    this.getHighlightGutterLine = function() {
-        return this.getOption("highlightGutterLine");
-    };
-    /**
-     * Determines if the currently selected word should be highlighted.
-     * @param {Boolean} shouldHighlight Set to `true` to highlight the currently selected word
-     *
-     **/
-    this.setHighlightSelectedWord = function(shouldHighlight) {
-        this.setOption("highlightSelectedWord", shouldHighlight);
-    };
-
-    /**
-     * Returns `true` if currently highlighted words are to be highlighted.
-     * @returns {Boolean}
-     **/
-    this.getHighlightSelectedWord = function() {
-        return this.$highlightSelectedWord;
-    };
-
-    this.setAnimatedScroll = function(shouldAnimate){
-        this.renderer.setAnimatedScroll(shouldAnimate);
-    };
-
-    this.getAnimatedScroll = function(){
-        return this.renderer.getAnimatedScroll();
-    };
-
-    /**
-     * If `showInvisibles` is set to `true`, invisible characters&mdash;like spaces or new lines&mdash;are show in the editor.
-     * @param {Boolean} showInvisibles Specifies whether or not to show invisible characters
-     *
-     **/
-    this.setShowInvisibles = function(showInvisibles) {
-        this.renderer.setShowInvisibles(showInvisibles);
-    };
-
-    /**
-     * Returns `true` if invisible characters are being shown.
-     * @returns {Boolean}
-     **/
-    this.getShowInvisibles = function() {
-        return this.renderer.getShowInvisibles();
-    };
-
-    this.setDisplayIndentGuides = function(display) {
-        this.renderer.setDisplayIndentGuides(display);
-    };
-
-    this.getDisplayIndentGuides = function() {
-        return this.renderer.getDisplayIndentGuides();
-    };
-
-    /**
-     * If `showPrintMargin` is set to `true`, the print margin is shown in the editor.
-     * @param {Boolean} showPrintMargin Specifies whether or not to show the print margin
-     *
-     **/
-    this.setShowPrintMargin = function(showPrintMargin) {
-        this.renderer.setShowPrintMargin(showPrintMargin);
-    };
-
-    /**
-     * Returns `true` if the print margin is being shown.
-     * @returns {Boolean}
-     **/
-    this.getShowPrintMargin = function() {
-        return this.renderer.getShowPrintMargin();
-    };
-
-    /**
-     * Sets the column defining where the print margin should be.
-     * @param {Number} showPrintMargin Specifies the new print margin
-     *
-     **/
-    this.setPrintMarginColumn = function(showPrintMargin) {
-        this.renderer.setPrintMarginColumn(showPrintMargin);
-    };
-
-    /**
-     * Returns the column number of where the print margin is.
-     * @returns {Number}
-     **/
-    this.getPrintMarginColumn = function() {
-        return this.renderer.getPrintMarginColumn();
-    };
-
-    /**
-     * If `readOnly` is true, then the editor is set to read-only mode, and none of the content can change.
-     * @param {Boolean} readOnly Specifies whether the editor can be modified or not
-     *
-     **/
-    this.setReadOnly = function(readOnly) {
-        this.setOption("readOnly", readOnly);
-    };
-
-    /**
-     * Returns `true` if the editor is set to read-only mode.
-     * @returns {Boolean}
-     **/
-    this.getReadOnly = function() {
-        return this.getOption("readOnly");
-    };
-
-    /**
-     * Specifies whether to use behaviors or not. ["Behaviors" in this case is the auto-pairing of special characters, like quotation marks, parenthesis, or brackets.]{: #BehaviorsDef}
-     * @param {Boolean} enabled Enables or disables behaviors
-     *
-     **/
-    this.setBehavioursEnabled = function (enabled) {
-        this.setOption("behavioursEnabled", enabled);
-    };
-
-    /**
-     * Returns `true` if the behaviors are currently enabled. {:BehaviorsDef}
-     *
-     * @returns {Boolean}
-     **/
-    this.getBehavioursEnabled = function () {
-        return this.getOption("behavioursEnabled");
-    };
-
-    /**
-     * Specifies whether to use wrapping behaviors or not, i.e. automatically wrapping the selection with characters such as brackets
-     * when such a character is typed in.
-     * @param {Boolean} enabled Enables or disables wrapping behaviors
-     *
-     **/
-    this.setWrapBehavioursEnabled = function (enabled) {
-        this.setOption("wrapBehavioursEnabled", enabled);
-    };
-
-    /**
-     * Returns `true` if the wrapping behaviors are currently enabled.
-     **/
-    this.getWrapBehavioursEnabled = function () {
-        return this.getOption("wrapBehavioursEnabled");
-    };
-
-    /**
-     * Indicates whether the fold widgets should be shown or not.
-     * @param {Boolean} show Specifies whether the fold widgets are shown
-     **/
-    this.setShowFoldWidgets = function(show) {
-        this.setOption("showFoldWidgets", show);
-
-    };
-    /**
-     * Returns `true` if the fold widgets are shown.
-     * @return {Boolean}
-     **/
-    this.getShowFoldWidgets = function() {
-        return this.getOption("showFoldWidgets");
-    };
-
-    this.setFadeFoldWidgets = function(fade) {
-        this.setOption("fadeFoldWidgets", fade);
-    };
-
-    this.getFadeFoldWidgets = function() {
-        return this.getOption("fadeFoldWidgets");
-    };
-
-    /**
-     * Removes words of text from the editor. A "word" is defined as a string of characters bookended by whitespace.
-     * @param {String} dir The direction of the deletion to occur, either "left" or "right"
-     *
-     **/
-    this.remove = function(dir) {
-        if (this.selection.isEmpty()){
-            if (dir == "left")
-                this.selection.selectLeft();
-            else
-                this.selection.selectRight();
-        }
-
-        var range = this.getSelectionRange();
-        if (this.getBehavioursEnabled()) {
-            var session = this.session;
-            var state = session.getState(range.start.row);
-            var new_range = session.getMode().transformAction(state, 'deletion', this, session, range);
-
-            if (range.end.column == 0) {
-                var text = session.getTextRange(range);
-                if (text[text.length - 1] == "\n") {
-                    var line = session.getLine(range.end.row);
-                    if (/^\s+$/.test(line)) {
-                        range.end.column = line.length;
-                    }
-                }
-            }
-            if (new_range)
-                range = new_range;
-        }
-
-        this.session.remove(range);
-        this.clearSelection();
-    };
-
-    /**
-     * Removes the word directly to the right of the current selection.
-     **/
-    this.removeWordRight = function() {
-        if (this.selection.isEmpty())
-            this.selection.selectWordRight();
-
-        this.session.remove(this.getSelectionRange());
-        this.clearSelection();
-    };
-
-    /**
-     * Removes the word directly to the left of the current selection.
-     **/
-    this.removeWordLeft = function() {
-        if (this.selection.isEmpty())
-            this.selection.selectWordLeft();
-
-        this.session.remove(this.getSelectionRange());
-        this.clearSelection();
-    };
-
-    /**
-     * Removes all the words to the left of the current selection, until the start of the line.
-     **/
-    this.removeToLineStart = function() {
-        if (this.selection.isEmpty())
-            this.selection.selectLineStart();
-
-        this.session.remove(this.getSelectionRange());
-        this.clearSelection();
-    };
-
-    /**
-     * Removes all the words to the right of the current selection, until the end of the line.
-     **/
-    this.removeToLineEnd = function() {
-        if (this.selection.isEmpty())
-            this.selection.selectLineEnd();
-
-        var range = this.getSelectionRange();
-        if (range.start.column == range.end.column && range.start.row == range.end.row) {
-            range.end.column = 0;
-            range.end.row++;
-        }
-
-        this.session.remove(range);
-        this.clearSelection();
-    };
-
-    /**
-     * Splits the line at the current selection (by inserting an `'\n'`).
-     **/
-    this.splitLine = function() {
-        if (!this.selection.isEmpty()) {
-            this.session.remove(this.getSelectionRange());
-            this.clearSelection();
-        }
-
-        var cursor = this.getCursorPosition();
-        this.insert("\n");
-        this.moveCursorToPosition(cursor);
-    };
-
-    /**
-     * Transposes current line.
-     **/
-    this.transposeLetters = function() {
-        if (!this.selection.isEmpty()) {
-            return;
-        }
-
-        var cursor = this.getCursorPosition();
-        var column = cursor.column;
-        if (column === 0)
-            return;
-
-        var line = this.session.getLine(cursor.row);
-        var swap, range;
-        if (column < line.length) {
-            swap = line.charAt(column) + line.charAt(column-1);
-            range = new Range(cursor.row, column-1, cursor.row, column+1);
-        }
-        else {
-            swap = line.charAt(column-1) + line.charAt(column-2);
-            range = new Range(cursor.row, column-2, cursor.row, column);
-        }
-        this.session.replace(range, swap);
-    };
-
-    /**
-     * Converts the current selection entirely into lowercase.
-     **/
-    this.toLowerCase = function() {
-        var originalRange = this.getSelectionRange();
-        if (this.selection.isEmpty()) {
-            this.selection.selectWord();
-        }
-
-        var range = this.getSelectionRange();
-        var text = this.session.getTextRange(range);
-        this.session.replace(range, text.toLowerCase());
-        this.selection.setSelectionRange(originalRange);
-    };
-
-    /**
-     * Converts the current selection entirely into uppercase.
-     **/
-    this.toUpperCase = function() {
-        var originalRange = this.getSelectionRange();
-        if (this.selection.isEmpty()) {
-            this.selection.selectWord();
-        }
-
-        var range = this.getSelectionRange();
-        var text = this.session.getTextRange(range);
-        this.session.replace(range, text.toUpperCase());
-        this.selection.setSelectionRange(originalRange);
-    };
-
-    /**
-     * Inserts an indentation into the current cursor position or indents the selected lines.
-     *
-     * @related EditSession.indentRows
-     **/
-    this.indent = function() {
-        var session = this.session;
-        var range = this.getSelectionRange();
-
-        if (range.start.row < range.end.row) {
-            var rows = this.$getSelectedRows();
-            session.indentRows(rows.first, rows.last, "\t");
-            return;
-        } else if (range.start.column < range.end.column) {
-            var text = session.getTextRange(range);
-            if (!/^\s+$/.test(text)) {
-                var rows = this.$getSelectedRows();
-                session.indentRows(rows.first, rows.last, "\t");
-                return;
-            }
-        }
-        
-        var line = session.getLine(range.start.row)
-        var position = range.start;
-        var size = session.getTabSize();
-        var column = session.documentToScreenColumn(position.row, position.column);
-
-        if (this.session.getUseSoftTabs()) {
-            var count = (size - column % size);
-            var indentString = lang.stringRepeat(" ", count);
-        } else {
-            var count = column % size;
-            while (line[range.start.column] == " " && count) {
-                range.start.column--;
-                count--;
-            }
-            this.selection.setSelectionRange(range);
-            indentString = "\t";
-        }
-        return this.insert(indentString);
-    };
-
-    /**
-     * Indents the current line.
-     * @related EditSession.indentRows
-     **/
-    this.blockIndent = function() {
-        var rows = this.$getSelectedRows();
-        this.session.indentRows(rows.first, rows.last, "\t");
-    };
-
-    /**
-     * Outdents the current line.
-     * @related EditSession.outdentRows
-     **/
-    this.blockOutdent = function() {
-        var selection = this.session.getSelection();
-        this.session.outdentRows(selection.getRange());
-    };
-
-    // TODO: move out of core when we have good mechanism for managing extensions
-    this.sortLines = function() {
-        var rows = this.$getSelectedRows();
-        var session = this.session;
-
-        var lines = [];
-        for (i = rows.first; i <= rows.last; i++)
-            lines.push(session.getLine(i));
-
-        lines.sort(function(a, b) {
-            if (a.toLowerCase() < b.toLowerCase()) return -1;
-            if (a.toLowerCase() > b.toLowerCase()) return 1;
-            return 0;
-        });
-
-        var deleteRange = new Range(0, 0, 0, 0);
-        for (var i = rows.first; i <= rows.last; i++) {
-            var line = session.getLine(i);
-            deleteRange.start.row = i;
-            deleteRange.end.row = i;
-            deleteRange.end.column = line.length;
-            session.replace(deleteRange, lines[i-rows.first]);
-        }
-    };
-
-    /**
-     * Given the currently selected range, this function either comments all the lines, or uncomments all of them.
-     **/
-    this.toggleCommentLines = function() {
-        var state = this.session.getState(this.getCursorPosition().row);
-        var rows = this.$getSelectedRows();
-        this.session.getMode().toggleCommentLines(state, this.session, rows.first, rows.last);
-    };
-
-    this.toggleBlockComment = function() {
-        var cursor = this.getCursorPosition();
-        var state = this.session.getState(cursor.row);
-        var range = this.getSelectionRange();
-        this.session.getMode().toggleBlockComment(state, this.session, range, cursor);
-    };
-
-    /**
-     * Works like [[EditSession.getTokenAt]], except it returns a number.
-     * @returns {Number}
-     **/
-    this.getNumberAt = function(row, column) {
-        var _numberRx = /[\-]?[0-9]+(?:\.[0-9]+)?/g;
-        _numberRx.lastIndex = 0;
-
-        var s = this.session.getLine(row);
-        while (_numberRx.lastIndex < column) {
-            var m = _numberRx.exec(s);
-            if(m.index <= column && m.index+m[0].length >= column){
-                var number = {
-                    value: m[0],
-                    start: m.index,
-                    end: m.index+m[0].length
-                };
-                return number;
-            }
-        }
-        return null;
-    };
-
-    /**
-     * If the character before the cursor is a number, this functions changes its value by `amount`.
-     * @param {Number} amount The value to change the numeral by (can be negative to decrease value)
-     *
-     **/
-    this.modifyNumber = function(amount) {
-        var row = this.selection.getCursor().row;
-        var column = this.selection.getCursor().column;
-
-        // get the char before the cursor
-        var charRange = new Range(row, column-1, row, column);
-
-        var c = this.session.getTextRange(charRange);
-        // if the char is a digit
-        if (!isNaN(parseFloat(c)) && isFinite(c)) {
-            // get the whole number the digit is part of
-            var nr = this.getNumberAt(row, column);
-            // if number found
-            if (nr) {
-                var fp = nr.value.indexOf(".") >= 0 ? nr.start + nr.value.indexOf(".") + 1 : nr.end;
-                var decimals = nr.start + nr.value.length - fp;
-
-                var t = parseFloat(nr.value);
-                t *= Math.pow(10, decimals);
-
-
-                if(fp !== nr.end && column < fp){
-                    amount *= Math.pow(10, nr.end - column - 1);
-                } else {
-                    amount *= Math.pow(10, nr.end - column);
-                }
-
-                t += amount;
-                t /= Math.pow(10, decimals);
-                var nnr = t.toFixed(decimals);
-
-                //update number
-                var replaceRange = new Range(row, nr.start, row, nr.end);
-                this.session.replace(replaceRange, nnr);
-
-                //reposition the cursor
-                this.moveCursorTo(row, Math.max(nr.start +1, column + nnr.length - nr.value.length));
-
-            }
-        }
-    };
-
-    /**
-     * Removes all the lines in the current selection
-     * @related EditSession.remove
-     **/
-    this.removeLines = function() {
-        var rows = this.$getSelectedRows();
-        var range;
-        if (rows.first === 0 || rows.last+1 < this.session.getLength())
-            range = new Range(rows.first, 0, rows.last+1, 0);
-        else
-            range = new Range(
-                rows.first-1, this.session.getLine(rows.first-1).length,
-                rows.last, this.session.getLine(rows.last).length
-            );
-        this.session.remove(range);
-        this.clearSelection();
-    };
-
-    this.duplicateSelection = function() {
-        var sel = this.selection;
-        var doc = this.session;
-        var range = sel.getRange();
-        var reverse = sel.isBackwards();
-        if (range.isEmpty()) {
-            var row = range.start.row;
-            doc.duplicateLines(row, row);
-        } else {
-            var point = reverse ? range.start : range.end;
-            var endPoint = doc.insert(point, doc.getTextRange(range), false);
-            range.start = point;
-            range.end = endPoint;
-
-            sel.setSelectionRange(range, reverse);
-        }
-    };
-
-    /**
-     * Shifts all the selected lines down one row.
-     *
-     * @returns {Number} On success, it returns -1.
-     * @related EditSession.moveLinesUp
-     **/
-    this.moveLinesDown = function() {
-        this.$moveLines(function(firstRow, lastRow) {
-            return this.session.moveLinesDown(firstRow, lastRow);
-        });
-    };
-
-    /**
-     * Shifts all the selected lines up one row.
-     * @returns {Number} On success, it returns -1.
-     * @related EditSession.moveLinesDown
-     **/
-    this.moveLinesUp = function() {
-        this.$moveLines(function(firstRow, lastRow) {
-            return this.session.moveLinesUp(firstRow, lastRow);
-        });
-    };
-
-    /**
-     * Moves a range of text from the given range to the given position. `toPosition` is an object that looks like this:
-     * ```json
-     *    { row: newRowLocation, column: newColumnLocation }
-     * ```
-     * @param {Range} fromRange The range of text you want moved within the document
-     * @param {Object} toPosition The location (row and column) where you want to move the text to
-     *
-     * @returns {Range} The new range where the text was moved to.
-     * @related EditSession.moveText
-     **/
-    this.moveText = function(range, toPosition, copy) {
-        return this.session.moveText(range, toPosition, copy);
-    };
-
-    /**
-     * Copies all the selected lines up one row.
-     * @returns {Number} On success, returns 0.
-     *
-     **/
-    this.copyLinesUp = function() {
-        this.$moveLines(function(firstRow, lastRow) {
-            this.session.duplicateLines(firstRow, lastRow);
-            return 0;
-        });
-    };
-
-    /**
-     * Copies all the selected lines down one row.
-     * @returns {Number} On success, returns the number of new rows added; in other words, `lastRow - firstRow + 1`.
-     * @related EditSession.duplicateLines
-     *
-     **/
-    this.copyLinesDown = function() {
-        this.$moveLines(function(firstRow, lastRow) {
-            return this.session.duplicateLines(firstRow, lastRow);
-        });
-    };
-
-    /**
-     * Executes a specific function, which can be anything that manipulates selected lines, such as copying them, duplicating them, or shifting them.
-     * @param {Function} mover A method to call on each selected row
-     *
-     *
-     **/
-    this.$moveLines = function(mover) {
-        var selection = this.selection;
-        if (!selection.inMultiSelectMode || this.inVirtualSelectionMode) {
-            var range = selection.toOrientedRange();
-            var rows = this.$getSelectedRows(range);
-            var linesMoved = mover.call(this, rows.first, rows.last);
-            range.moveBy(linesMoved, 0);
-            selection.fromOrientedRange(range);
-        } else {
-            var ranges = selection.rangeList.ranges;
-            selection.rangeList.detach(this.session);
-
-            for (var i = ranges.length; i--; ) {
-                var rangeIndex = i;
-                var rows = ranges[i].collapseRows();
-                var last = rows.end.row;
-                var first = rows.start.row;
-                while (i--) {
-                    var rows = ranges[i].collapseRows();
-                    if (first - rows.end.row <= 1)
-                        first = rows.end.row;
-                    else
-                        break;
-                }
-                i++;
-
-                var linesMoved = mover.call(this, first, last);
-                while (rangeIndex >= i) {
-                    ranges[rangeIndex].moveBy(linesMoved, 0);
-                    rangeIndex--;
-                }
-            }
-            selection.fromOrientedRange(selection.ranges[0]);
-            selection.rangeList.attach(this.session);
-        }
-    };
-
-    /**
-     * Returns an object indicating the currently selected rows. The object looks like this:
-     *
-     * ```json
-     * { first: range.start.row, last: range.end.row }
-     * ```
-     *
-     * @returns {Object}
-     **/
-    this.$getSelectedRows = function() {
-        var range = this.getSelectionRange().collapseRows();
-
-        return {
-            first: this.session.getRowFoldStart(range.start.row),
-            last: this.session.getRowFoldEnd(range.end.row)
-        };
-    };
-
-    this.onCompositionStart = function(text) {
-        this.renderer.showComposition(this.getCursorPosition());
-    };
-
-    this.onCompositionUpdate = function(text) {
-        this.renderer.setCompositionText(text);
-    };
-
-    this.onCompositionEnd = function() {
-        this.renderer.hideComposition();
-    };
-
-    /**
-     * {:VirtualRenderer.getFirstVisibleRow}
-     *
-     * @returns {Number}
-     * @related VirtualRenderer.getFirstVisibleRow
-     **/
-    this.getFirstVisibleRow = function() {
-        return this.renderer.getFirstVisibleRow();
-    };
-
-    /**
-     * {:VirtualRenderer.getLastVisibleRow}
-     *
-     * @returns {Number}
-     * @related VirtualRenderer.getLastVisibleRow
-     **/
-    this.getLastVisibleRow = function() {
-        return this.renderer.getLastVisibleRow();
-    };
-
-    /**
-     * Indicates if the row is currently visible on the screen.
-     * @param {Number} row The row to check
-     *
-     * @returns {Boolean}
-     **/
-    this.isRowVisible = function(row) {
-        return (row >= this.getFirstVisibleRow() && row <= this.getLastVisibleRow());
-    };
-
-    /**
-     * Indicates if the entire row is currently visible on the screen.
-     * @param {Number} row The row to check
-     *
-     *
-     * @returns {Boolean}
-     **/
-    this.isRowFullyVisible = function(row) {
-        return (row >= this.renderer.getFirstFullyVisibleRow() && row <= this.renderer.getLastFullyVisibleRow());
-    };
-
-    /**
-     * Returns the number of currently visibile rows.
-     * @returns {Number}
-     **/
-    this.$getVisibleRowCount = function() {
-        return this.renderer.getScrollBottomRow() - this.renderer.getScrollTopRow() + 1;
-    };
-
-    this.$moveByPage = function(dir, select) {
-        var renderer = this.renderer;
-        var config = this.renderer.layerConfig;
-        var rows = dir * Math.floor(config.height / config.lineHeight);
-
-        this.$blockScrolling++;
-        if (select == true) {
-            this.selection.$moveSelection(function(){
-                this.moveCursorBy(rows, 0);
-            });
-        } else if (select == false) {
-            this.selection.moveCursorBy(rows, 0);
-            this.selection.clearSelection();
-        }
-        this.$blockScrolling--;
-
-        var scrollTop = renderer.scrollTop;
-
-        renderer.scrollBy(0, rows * config.lineHeight);
-        if (select != null)
-            renderer.scrollCursorIntoView(null, 0.5);
-
-        renderer.animateScrolling(scrollTop);
-    };
-
-    /**
-     * Selects the text from the current position of the document until where a "page down" finishes.
-     **/
-    this.selectPageDown = function() {
-        this.$moveByPage(1, true);
-    };
-
-    /**
-     * Selects the text from the current position of the document until where a "page up" finishes.
-     **/
-    this.selectPageUp = function() {
-        this.$moveByPage(-1, true);
-    };
-
-    /**
-     * Shifts the document to wherever "page down" is, as well as moving the cursor position.
-     **/
-    this.gotoPageDown = function() {
-       this.$moveByPage(1, false);
-    };
-
-    /**
-     * Shifts the document to wherever "page up" is, as well as moving the cursor position.
-     **/
-    this.gotoPageUp = function() {
-        this.$moveByPage(-1, false);
-    };
-
-    /**
-     * Scrolls the document to wherever "page down" is, without changing the cursor position.
-     **/
-    this.scrollPageDown = function() {
-        this.$moveByPage(1);
-    };
-
-    /**
-     * Scrolls the document to wherever "page up" is, without changing the cursor position.
-     **/
-    this.scrollPageUp = function() {
-        this.$moveByPage(-1);
-    };
-
-    /**
-     * Moves the editor to the specified row.
-     * @related VirtualRenderer.scrollToRow
-     **/
-    this.scrollToRow = function(row) {
-        this.renderer.scrollToRow(row);
-    };
-
-    /**
-     * Scrolls to a line. If `center` is `true`, it puts the line in middle of screen (or attempts to).
-     * @param {Number} line The line to scroll to
-     * @param {Boolean} center If `true`
-     * @param {Boolean} animate If `true` animates scrolling
-     * @param {Function} callback Function to be called when the animation has finished
-     *
-     *
-     * @related VirtualRenderer.scrollToLine
-     **/
-    this.scrollToLine = function(line, center, animate, callback) {
-        this.renderer.scrollToLine(line, center, animate, callback);
-    };
-
-    /**
-     * Attempts to center the current selection on the screen.
-     **/
-    this.centerSelection = function() {
-        var range = this.getSelectionRange();
-        var pos = {
-            row: Math.floor(range.start.row + (range.end.row - range.start.row) / 2),
-            column: Math.floor(range.start.column + (range.end.column - range.start.column) / 2)
-        };
-        this.renderer.alignCursor(pos, 0.5);
-    };
-
-    /**
-     * Gets the current position of the cursor.
-     * @returns {Object} An object that looks something like this:
-     *
-     * ```json
-     * { row: currRow, column: currCol }
-     * ```
-     *
-     * @related Selection.getCursor
-     **/
-    this.getCursorPosition = function() {
-        return this.selection.getCursor();
-    };
-
-    /**
-     * Returns the screen position of the cursor.
-     * @returns {Number}
-     * @related EditSession.documentToScreenPosition
-     **/
-    this.getCursorPositionScreen = function() {
-        return this.session.documentToScreenPosition(this.getCursorPosition());
-    };
-
-    /**
-     * {:Selection.getRange}
-     * @returns {Range}
-     * @related Selection.getRange
-     **/
-    this.getSelectionRange = function() {
-        return this.selection.getRange();
-    };
-
-
-    /**
-     * Selects all the text in editor.
-     * @related Selection.selectAll
-     **/
-    this.selectAll = function() {
-        this.$blockScrolling += 1;
-        this.selection.selectAll();
-        this.$blockScrolling -= 1;
-    };
-
-    /**
-     * {:Selection.clearSelection}
-     * @related Selection.clearSelection
-     **/
-    this.clearSelection = function() {
-        this.selection.clearSelection();
-    };
-
-    /**
-     * Moves the cursor to the specified row and column. Note that this does not de-select the current selection.
-     * @param {Number} row The new row number
-     * @param {Number} column The new column number
-     *
-     *
-     * @related Selection.moveCursorTo
-     **/
-    this.moveCursorTo = function(row, column) {
-        this.selection.moveCursorTo(row, column);
-    };
-
-    /**
-     * Moves the cursor to the position indicated by `pos.row` and `pos.column`.
-     * @param {Object} pos An object with two properties, row and column
-     *
-     *
-     * @related Selection.moveCursorToPosition
-     **/
-    this.moveCursorToPosition = function(pos) {
-        this.selection.moveCursorToPosition(pos);
-    };
-
-    /**
-     * Moves the cursor's row and column to the next matching bracket.
-     *
-     **/
-    this.jumpToMatching = function(select) {
-        var cursor = this.getCursorPosition();
-
-        var range = this.session.getBracketRange(cursor);
-        if (!range) {
-            range = this.find({
-                needle: /[{}()\[\]]/g,
-                preventScroll:true,
-                start: {row: cursor.row, column: cursor.column - 1}
-            });
-            if (!range)
-                return;
-            var pos = range.start;
-            if (pos.row == cursor.row && Math.abs(pos.column - cursor.column) < 2)
-                range = this.session.getBracketRange(pos);
-        }
-
-        pos = range && range.cursor || pos;
-        if (pos) {
-            if (select) {
-                if (range && range.isEqual(this.getSelectionRange()))
-                    this.clearSelection();
-                else
-                    this.selection.selectTo(pos.row, pos.column);
-            } else {
-                this.clearSelection();
-                this.moveCursorTo(pos.row, pos.column);
-            }
-        }
-    };
-
-    /**
-     * Moves the cursor to the specified line number, and also into the indiciated column.
-     * @param {Number} lineNumber The line number to go to
-     * @param {Number} column A column number to go to
-     * @param {Boolean} animate If `true` animates scolling
-     *
-     **/
-    this.gotoLine = function(lineNumber, column, animate) {
-        this.selection.clearSelection();
-        this.session.unfold({row: lineNumber - 1, column: column || 0});
-
-        this.$blockScrolling += 1;
-        // todo: find a way to automatically exit multiselect mode
-        this.exitMultiSelectMode && this.exitMultiSelectMode();
-        this.moveCursorTo(lineNumber - 1, column || 0);
-        this.$blockScrolling -= 1;
-
-        if (!this.isRowFullyVisible(lineNumber - 1))
-            this.scrollToLine(lineNumber - 1, true, animate);
-    };
-
-    /**
-     * Moves the cursor to the specified row and column. Note that this does de-select the current selection.
-     * @param {Number} row The new row number
-     * @param {Number} column The new column number
-     *
-     *
-     * @related Editor.moveCursorTo
-     **/
-    this.navigateTo = function(row, column) {
-        this.clearSelection();
-        this.moveCursorTo(row, column);
-    };
-
-    /**
-     * Moves the cursor up in the document the specified number of times. Note that this does de-select the current selection.
-     * @param {Number} times The number of times to change navigation
-     *
-     *
-     **/
-    this.navigateUp = function(times) {
-        if (this.selection.isMultiLine() && !this.selection.isBackwards()) {
-            var selectionStart = this.selection.anchor.getPosition();
-            return this.moveCursorToPosition(selectionStart);
-        }
-        this.selection.clearSelection();
-        times = times || 1;
-        this.selection.moveCursorBy(-times, 0);
-    };
-
-    /**
-     * Moves the cursor down in the document the specified number of times. Note that this does de-select the current selection.
-     * @param {Number} times The number of times to change navigation
-     *
-     *
-     **/
-    this.navigateDown = function(times) {
-        if (this.selection.isMultiLine() && this.selection.isBackwards()) {
-            var selectionEnd = this.selection.anchor.getPosition();
-            return this.moveCursorToPosition(selectionEnd);
-        }
-        this.selection.clearSelection();
-        times = times || 1;
-        this.selection.moveCursorBy(times, 0);
-    };
-
-    /**
-     * Moves the cursor left in the document the specified number of times. Note that this does de-select the current selection.
-     * @param {Number} times The number of times to change navigation
-     *
-     *
-     **/
-    this.navigateLeft = function(times) {
-        if (!this.selection.isEmpty()) {
-            var selectionStart = this.getSelectionRange().start;
-            this.moveCursorToPosition(selectionStart);
-        }
-        else {
-            times = times || 1;
-            while (times--) {
-                this.selection.moveCursorLeft();
-            }
-        }
-        this.clearSelection();
-    };
-
-    /**
-     * Moves the cursor right in the document the specified number of times. Note that this does de-select the current selection.
-     * @param {Number} times The number of times to change navigation
-     *
-     *
-     **/
-    this.navigateRight = function(times) {
-        if (!this.selection.isEmpty()) {
-            var selectionEnd = this.getSelectionRange().end;
-            this.moveCursorToPosition(selectionEnd);
-        }
-        else {
-            times = times || 1;
-            while (times--) {
-                this.selection.moveCursorRight();
-            }
-        }
-        this.clearSelection();
-    };
-
-    /**
-     *
-     * Moves the cursor to the start of the current line. Note that this does de-select the current selection.
-     **/
-    this.navigateLineStart = function() {
-        this.selection.moveCursorLineStart();
-        this.clearSelection();
-    };
-
-    /**
-     *
-     * Moves the cursor to the end of the current line. Note that this does de-select the current selection.
-     **/
-    this.navigateLineEnd = function() {
-        this.selection.moveCursorLineEnd();
-        this.clearSelection();
-    };
-
-    /**
-     *
-     * Moves the cursor to the end of the current file. Note that this does de-select the current selection.
-     **/
-    this.navigateFileEnd = function() {
-        var scrollTop = this.renderer.scrollTop;
-        this.selection.moveCursorFileEnd();
-        this.clearSelection();
-        this.renderer.animateScrolling(scrollTop);
-    };
-
-    /**
-     *
-     * Moves the cursor to the start of the current file. Note that this does de-select the current selection.
-     **/
-    this.navigateFileStart = function() {
-        var scrollTop = this.renderer.scrollTop;
-        this.selection.moveCursorFileStart();
-        this.clearSelection();
-        this.renderer.animateScrolling(scrollTop);
-    };
-
-    /**
-     *
-     * Moves the cursor to the word immediately to the right of the current position. Note that this does de-select the current selection.
-     **/
-    this.navigateWordRight = function() {
-        this.selection.moveCursorWordRight();
-        this.clearSelection();
-    };
-
-    /**
-     *
-     * Moves the cursor to the word immediately to the left of the current position. Note that this does de-select the current selection.
-     **/
-    this.navigateWordLeft = function() {
-        this.selection.moveCursorWordLeft();
-        this.clearSelection();
-    };
-
-    /**
-     * Replaces the first occurance of `options.needle` with the value in `replacement`.
-     * @param {String} replacement The text to replace with
-     * @param {Object} options The [[Search `Search`]] options to use
-     *
-     *
-     **/
-    this.replace = function(replacement, options) {
-        if (options)
-            this.$search.set(options);
-
-        var range = this.$search.find(this.session);
-        var replaced = 0;
-        if (!range)
-            return replaced;
-
-        if (this.$tryReplace(range, replacement)) {
-            replaced = 1;
-        }
-        if (range !== null) {
-            this.selection.setSelectionRange(range);
-            this.renderer.scrollSelectionIntoView(range.start, range.end);
-        }
-
-        return replaced;
-    };
-
-    /**
-     * Replaces all occurances of `options.needle` with the value in `replacement`.
-     * @param {String} replacement The text to replace with
-     * @param {Object} options The [[Search `Search`]] options to use
-     *
-     *
-     **/
-    this.replaceAll = function(replacement, options) {
-        if (options) {
-            this.$search.set(options);
-        }
-
-        var ranges = this.$search.findAll(this.session);
-        var replaced = 0;
-        if (!ranges.length)
-            return replaced;
-
-        this.$blockScrolling += 1;
-
-        var selection = this.getSelectionRange();
-        this.clearSelection();
-        this.selection.moveCursorTo(0, 0);
-
-        for (var i = ranges.length - 1; i >= 0; --i) {
-            if(this.$tryReplace(ranges[i], replacement)) {
-                replaced++;
-            }
-        }
-
-        this.selection.setSelectionRange(selection);
-        this.$blockScrolling -= 1;
-
-        return replaced;
-    };
-
-    this.$tryReplace = function(range, replacement) {
-        var input = this.session.getTextRange(range);
-        replacement = this.$search.replace(input, replacement);
-        if (replacement !== null) {
-            range.end = this.session.replace(range, replacement);
-            return range;
-        } else {
-            return null;
-        }
-    };
-
-    /**
-     * {:Search.getOptions} For more information on `options`, see [[Search `Search`]].
-     * @related Search.getOptions
-     * @returns {Object}
-     **/
-    this.getLastSearchOptions = function() {
-        return this.$search.getOptions();
-    };
-
-    /**
-     * Attempts to find `needle` within the document. For more information on `options`, see [[Search `Search`]].
-     * @param {String} needle The text to search for (optional)
-     * @param {Object} options An object defining various search properties
-     * @param {Boolean} animate If `true` animate scrolling
-     *
-     *
-     * @related Search.find
-     **/
-    this.find = function(needle, options, animate) {
-        if (!options)
-            options = {};
-
-        if (typeof needle == "string" || needle instanceof RegExp)
-            options.needle = needle;
-        else if (typeof needle == "object")
-            oop.mixin(options, needle);
-
-        var range = this.selection.getRange();
-        if (options.needle == null) {
-            needle = this.session.getTextRange(range)
-                || this.$search.$options.needle;
-            if (!needle) {
-                range = this.session.getWordRange(range.start.row, range.start.column);
-                needle = this.session.getTextRange(range);
-            }
-            this.$search.set({needle: needle});
-        }
-
-        this.$search.set(options);
-        if (!options.start)
-            this.$search.set({start: range});
-
-        var newRange = this.$search.find(this.session);
-        if (options.preventScroll)
-            return newRange;
-        if (newRange) {
-            this.revealRange(newRange, animate);
-            return newRange;
-        }
-        // clear selection if nothing is found
-        if (options.backwards)
-            range.start = range.end;
-        else
-            range.end = range.start;
-        this.selection.setRange(range);
-    };
-
-    /**
-     * Performs another search for `needle` in the document. For more information on `options`, see [[Search `Search`]].
-     * @param {Object} options search options
-     * @param {Boolean} animate If `true` animate scrolling
-     *
-     *
-     * @related Editor.find
-     **/
-    this.findNext = function(options, animate) {
-        this.find({skipCurrent: true, backwards: false}, options, animate);
-    };
-
-    /**
-     * Performs a search for `needle` backwards. For more information on `options`, see [[Search `Search`]].
-     * @param {Object} options search options
-     * @param {Boolean} animate If `true` animate scrolling
-     *
-     *
-     * @related Editor.find
-     **/
-    this.findPrevious = function(options, animate) {
-        this.find(options, {skipCurrent: true, backwards: true}, animate);
-    };
-
-    this.revealRange = function(range, animate) {
-        this.$blockScrolling += 1;
-        this.session.unfold(range);
-        this.selection.setSelectionRange(range);
-        this.$blockScrolling -= 1;
-
-        var scrollTop = this.renderer.scrollTop;
-        this.renderer.scrollSelectionIntoView(range.start, range.end, 0.5);
-        if (animate != false)
-            this.renderer.animateScrolling(scrollTop);
-    };
-
-    /**
-     * {:UndoManager.undo}
-     * @related UndoManager.undo
-     **/
-    this.undo = function() {
-        this.$blockScrolling++;
-        this.session.getUndoManager().undo();
-        this.$blockScrolling--;
-        this.renderer.scrollCursorIntoView(null, 0.5);
-    };
-
-    /**
-     * {:UndoManager.redo}
-     * @related UndoManager.redo
-     **/
-    this.redo = function() {
-        this.$blockScrolling++;
-        this.session.getUndoManager().redo();
-        this.$blockScrolling--;
-        this.renderer.scrollCursorIntoView(null, 0.5);
-    };
-
-    /**
-     *
-     * Cleans up the entire editor.
-     **/
-    this.destroy = function() {
-        this.renderer.destroy();
-        this._emit("destroy", this);
-    };
-
-    /**
-     * Enables automatic scrolling of the cursor into view when editor itself is inside scrollable element
-     * @param {Boolean} enable default true
-     **/
-    this.setAutoScrollEditorIntoView = function(enable) {
-        if (enable === false)
-            return;
-        var rect;
-        var self = this;
-        var shouldScroll = false;
-        if (!this.$scrollAnchor)
-            this.$scrollAnchor = document.createElement("div");
-        var scrollAnchor = this.$scrollAnchor;
-        scrollAnchor.style.cssText = "position:absolute";
-        this.container.insertBefore(scrollAnchor, this.container.firstChild);
-        var onChangeSelection = this.on("changeSelection", function() {
-            shouldScroll = true;
-        });
-        // needed to not trigger sync reflow
-        var onBeforeRender = this.renderer.on("beforeRender", function() {
-            if (shouldScroll)
-                rect = self.renderer.container.getBoundingClientRect();
-        });
-        var onAfterRender = this.renderer.on("afterRender", function() {
-            if (shouldScroll && rect && self.isFocused()) {
-                var renderer = self.renderer;
-                var pos = renderer.$cursorLayer.$pixelPos;
-                var config = renderer.layerConfig;
-                var top = pos.top - config.offset;
-                if (pos.top >= 0 && top + rect.top < 0) {
-                    shouldScroll = true;
-                } else if (pos.top < config.height &&
-                    pos.top + rect.top + config.lineHeight > window.innerHeight) {
-                    shouldScroll = false;
-                } else {
-                    shouldScroll = null;
-                }
-                if (shouldScroll != null) {
-                    scrollAnchor.style.top = top + "px";
-                    scrollAnchor.style.left = pos.left + "px";
-                    scrollAnchor.style.height = config.lineHeight + "px";
-                    scrollAnchor.scrollIntoView(shouldScroll);
-                }
-                shouldScroll = rect = null;
-            }
-        });
-        this.setAutoScrollEditorIntoView = function(enable) {
-            if (enable === true)
-                return;
-            delete this.setAutoScrollEditorIntoView;
-            this.removeEventListener("changeSelection", onChangeSelection);
-            this.renderer.removeEventListener("afterRender", onAfterRender);
-            this.renderer.removeEventListener("beforeRender", onBeforeRender);
-        };
-    };
-
-
-    this.$resetCursorStyle = function() {
-        var style = this.$cursorStyle || "ace";
-        var cursorLayer = this.renderer.$cursorLayer;
-        if (!cursorLayer)
-            return;
-        cursorLayer.setSmoothBlinking(style == "smooth");
-        cursorLayer.isBlinking = !this.$readOnly && style != "wide";
-    };
-
-}).call(Editor.prototype);
-
-
-
-config.defineOptions(Editor.prototype, "editor", {
-    selectionStyle: {
-        set: function(style) {
-            this.onSelectionChange();
-            this._emit("changeSelectionStyle", {data: style});
-        },
-        initialValue: "line"
-    },
-    highlightActiveLine: {
-        set: function() {this.$updateHighlightActiveLine();},
-        initialValue: true
-    },
-    highlightSelectedWord: {
-        set: function(shouldHighlight) {this.$onSelectionChange();},
-        initialValue: true
-    },
-    readOnly: {
-        set: function(readOnly) {
-            this.textInput.setReadOnly(readOnly); 
-            this.$resetCursorStyle(); 
-        },
-        initialValue: false
-    },
-    cursorStyle: {
-        set: function(val) { this.$resetCursorStyle(); },
-        values: ["ace", "slim", "smooth", "wide"],
-        initialValue: "ace"
-    },
-    mergeUndoDeltas: {
-        values: [false, true, "always"],
-        initialValue: true
-    },
-    behavioursEnabled: {initialValue: true},
-    wrapBehavioursEnabled: {initialValue: true},
-
-    hScrollBarAlwaysVisible: "renderer",
-    vScrollBarAlwaysVisible: "renderer",
-    highlightGutterLine: "renderer",
-    animatedScroll: "renderer",
-    showInvisibles: "renderer",
-    showPrintMargin: "renderer",
-    printMarginColumn: "renderer",
-    printMargin: "renderer",
-    fadeFoldWidgets: "renderer",
-    showFoldWidgets: "renderer",
-    showGutter: "renderer",
-    displayIndentGuides: "renderer",
-    fontSize: "renderer",
-    fontFamily: "renderer",
-    maxLines: "renderer",
-    minLines: "renderer",
-    scrollPastEnd: "renderer",
-    fixedWidthGutter: "renderer",
-
-    scrollSpeed: "$mouseHandler",
-    dragDelay: "$mouseHandler",
-    dragEnabled: "$mouseHandler",
-    focusTimout: "$mouseHandler",
-
-    firstLineNumber: "session",
-    overwrite: "session",
-    newLineMode: "session",
-    useWorker: "session",
-    useSoftTabs: "session",
-    tabSize: "session",
-    wrap: "session",
-    foldStyle: "session"
-});
-
-exports.Editor = Editor;
-});

+ 0 - 188
services/web/public/js/ace/editor_change_document_test.js

@@ -1,188 +0,0 @@
-/* ***** 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");
-    require("./test/mockdom");
-}
-
-define(function(require, exports, module) {
-"use strict";
-
-var EditSession = require("./edit_session").EditSession;
-var Editor = require("./editor").Editor;
-var Text = require("./mode/text").Mode;
-var JavaScriptMode = require("./mode/javascript").Mode;
-var CssMode = require("./mode/css").Mode;
-var HtmlMode = require("./mode/html").Mode;
-var MockRenderer = require("./test/mockrenderer").MockRenderer;
-var assert = require("./test/assertions");
-
-module.exports = {
-
-    setUp : function(next) {
-        this.session1 = new EditSession(["abc", "def"]);
-        this.session2 = new EditSession(["ghi", "jkl"]);
-        
-        
-        this.editor = new Editor(new MockRenderer());
-        next();
-    },
-
-    "test: change document" : function() {
-        this.editor.setSession(this.session1);
-        assert.equal(this.editor.getSession(), this.session1);
-
-        this.editor.setSession(this.session2);
-        assert.equal(this.editor.getSession(), this.session2);
-    },
-
-    "test: only changes to the new document should have effect" : function() {
-        var called = false;
-        this.editor.onDocumentChange = function() {
-            called = true;
-        };
-
-        this.editor.setSession(this.session1);
-        this.editor.setSession(this.session2);
-
-        this.session1.duplicateLines(0, 0);
-        assert.notOk(called);
-
-        this.session2.duplicateLines(0, 0);
-        assert.ok(called);
-    },
-
-    "test: should use cursor of new document" : function() {
-        this.session1.getSelection().moveCursorTo(0, 1);
-        this.session2.getSelection().moveCursorTo(1, 0);
-
-        this.editor.setSession(this.session1);
-        assert.position(this.editor.getCursorPosition(), 0, 1);
-
-        this.editor.setSession(this.session2);
-        assert.position(this.editor.getCursorPosition(), 1, 0);
-    },
-
-    "test: only changing the cursor of the new doc should not have an effect" : function() {
-        this.editor.onCursorChange = function() {
-            called = true;
-        };
-
-        this.editor.setSession(this.session1);
-        this.editor.setSession(this.session2);
-        assert.position(this.editor.getCursorPosition(), 0, 0);
-
-        var called = false;
-        this.session1.getSelection().moveCursorTo(0, 1);
-        assert.position(this.editor.getCursorPosition(), 0, 0);
-        assert.notOk(called);
-
-        this.session2.getSelection().moveCursorTo(1, 1);
-        assert.position(this.editor.getCursorPosition(), 1, 1);
-        assert.ok(called);
-    },
-
-    "test: should use selection of new document" : function() {
-        this.session1.getSelection().selectTo(0, 1);
-        this.session2.getSelection().selectTo(1, 0);
-
-        this.editor.setSession(this.session1);
-        assert.position(this.editor.getSelection().getSelectionLead(), 0, 1);
-
-        this.editor.setSession(this.session2);
-        assert.position(this.editor.getSelection().getSelectionLead(), 1, 0);
-    },
-
-    "test: only changing the selection of the new doc should not have an effect" : function() {
-        this.editor.onSelectionChange = function() {
-            called = true;
-        };
-
-        this.editor.setSession(this.session1);
-        this.editor.setSession(this.session2);
-        assert.position(this.editor.getSelection().getSelectionLead(), 0, 0);
-
-        var called = false;
-        this.session1.getSelection().selectTo(0, 1);
-        assert.position(this.editor.getSelection().getSelectionLead(), 0, 0);
-        assert.notOk(called);
-
-        this.session2.getSelection().selectTo(1, 1);
-        assert.position(this.editor.getSelection().getSelectionLead(), 1, 1);
-        assert.ok(called);
-    },
-
-    "test: should use mode of new document" : function() {
-        this.editor.onChangeMode = function() {
-            called = true;
-        };
-        this.editor.setSession(this.session1);
-        this.editor.setSession(this.session2);
-
-        var called = false;
-        this.session1.setMode(new Text());
-        assert.notOk(called);
-
-        this.session2.setMode(new JavaScriptMode());
-        assert.ok(called);
-    },
-    
-    "test: should use stop worker of old document" : function(next) {
-        var self = this;
-        
-        // 1. Open an editor and set the session to CssMode
-        self.editor.setSession(self.session1);
-        self.session1.setMode(new CssMode());
-        
-        // 2. Add a line or two of valid CSS.
-        self.session1.setValue("DIV { color: red; }");
-        
-        // 3. Clear the session value.
-        self.session1.setValue("");
-        
-        // 4. Set the session to HtmlMode
-        self.session1.setMode(new HtmlMode());
-
-        // 5. Try to type valid HTML
-        self.session1.insert({row: 0, column: 0}, "<html></html>");
-        
-        setTimeout(function() {
-            assert.equal(Object.keys(self.session1.getAnnotations()).length, 0);
-            next();
-        }, 600);
-    }
-};
-
-});
-
-if (typeof module !== "undefined" && module === require.main) {
-    require("asyncjs").test.testcase(module.exports).exec()
-}

+ 0 - 223
services/web/public/js/ace/editor_highlight_selected_word_test.js

@@ -1,223 +0,0 @@
-/* ***** 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");
-    require("./test/mockdom");
-}
-
-define(function(require, exports, module) {
-"use strict";
-
-var EditSession = require("./edit_session").EditSession;
-var Editor = require("./editor").Editor;
-var MockRenderer = require("./test/mockrenderer").MockRenderer;
-var assert = require("./test/assertions");
-
-var lipsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " +
-             "Mauris at arcu mi, eu lobortis mauris. Quisque ut libero eget " +
-             "diam congue vehicula. Quisque ut odio ut mi aliquam tincidunt. " +
-             "Duis lacinia aliquam lorem eget eleifend. Morbi eget felis mi. " +
-             "Duis quam ligula, consequat vitae convallis volutpat, blandit " +
-             "nec neque. Nulla facilisi. Etiam suscipit lorem ac justo " +
-             "sollicitudin tristique. Phasellus ut posuere nunc. Aliquam " +
-             "scelerisque mollis felis non gravida. Vestibulum lacus sem, " +
-             "posuere non bibendum id, luctus non dolor. Aenean id metus " +
-             "lorem, vel dapibus est. Donec gravida feugiat augue nec " +
-             "accumsan.Lorem ipsum dolor sit amet, consectetur adipiscing " +
-             "elit. Nulla vulputate, velit vitae tincidunt congue, nunc " +
-             "augue accumsan velit, eu consequat turpis lectus ac orci. " +
-             "Pellentesque ornare dolor feugiat dui auctor eu varius nulla " +
-             "fermentum. Sed aliquam odio at velit lacinia vel fermentum " +
-             "felis sodales. In dignissim magna eget nunc lobortis non " +
-             "fringilla nibh ullamcorper. Donec facilisis malesuada elit " +
-             "at egestas. Etiam bibendum, diam vitae tempor aliquet, dui " +
-             "libero vehicula odio, eget bibendum mauris velit eu lorem.\n" +
-             "consectetur";
-
-function callHighlighterUpdate(session, firstRow, lastRow) {
-    var rangeCount = 0;
-    var  mockMarkerLayer = { drawSingleLineMarker: function() {rangeCount++;} }
-    session.$searchHighlight.update([], mockMarkerLayer, session, {
-        firstRow: firstRow,
-        lastRow: lastRow
-    });
-    return rangeCount;
-}
-
-module.exports = {
-    setUp: function(next) {
-        this.session = new EditSession(lipsum);
-        this.editor = new Editor(new MockRenderer(), this.session);
-        this.selection = this.session.getSelection();
-        this.search = this.editor.$search;
-        next();
-    },
-
-    "test: highlight selected words by default": function() {
-        assert.equal(this.editor.getHighlightSelectedWord(), true);
-    },
-
-    "test: highlight a word": function() {
-        this.editor.moveCursorTo(0, 9);
-        this.selection.selectWord();
-
-        var highlighter = this.editor.session.$searchHighlight;
-        assert.ok(highlighter != null);
-
-        var range = this.selection.getRange();
-        assert.equal(this.session.getTextRange(range), "ipsum");
-        assert.equal(highlighter.cache.length, 0);
-        assert.equal(callHighlighterUpdate(this.session, 0, 0), 2);
-    },
-
-    "test: highlight a word and clear highlight": function() {
-        this.editor.moveCursorTo(0, 8);
-        this.selection.selectWord();
-
-        var range = this.selection.getRange();
-        assert.equal(this.session.getTextRange(range), "ipsum");
-        assert.equal(callHighlighterUpdate(this.session, 0, 0), 2);
-
-        this.session.highlight("");
-        assert.equal(this.session.$searchHighlight.cache.length, 0);
-        assert.equal(callHighlighterUpdate(this.session, 0, 0), 0);
-    },
-
-    "test: highlight another word": function() {
-        this.selection.moveCursorTo(0, 14);
-        this.selection.selectWord();
-
-        var range = this.selection.getRange();
-        assert.equal(this.session.getTextRange(range), "dolor");
-        assert.equal(callHighlighterUpdate(this.session, 0, 0), 4);
-    },
-
-    "test: no selection, no highlight": function() {
-        this.selection.clearSelection();
-        assert.equal(callHighlighterUpdate(this.session, 0, 0), 0);
-    },
-
-    "test: select a word, no highlight": function() {
-        this.selection.moveCursorTo(0, 14);
-        this.selection.selectWord();
-
-        this.editor.setHighlightSelectedWord(false);
-
-        var range = this.selection.getRange();
-        assert.equal(this.session.getTextRange(range), "dolor");
-        assert.equal(callHighlighterUpdate(this.session, 0, 0), 0);
-    },
-
-    "test: select a word with no matches": function() {
-        this.editor.setHighlightSelectedWord(true);
-
-        var currentOptions = this.search.getOptions();
-        var newOptions = {
-            wrap: true,
-            wholeWord: true,
-            caseSensitive: true,
-            needle: "Mauris"
-        };
-        this.search.set(newOptions);
-
-        var match = this.search.find(this.session);
-        assert.notEqual(match, null, "found a match for 'Mauris'");
-
-        this.search.set(currentOptions);
-
-        this.selection.setSelectionRange(match);
-
-        assert.equal(this.session.getTextRange(match), "Mauris");
-        assert.equal(callHighlighterUpdate(this.session, 0, 0), 1);
-    },
-
-    "test: partial word selection 1": function() {
-        this.selection.moveCursorTo(0, 14);
-        this.selection.selectWord();
-        this.selection.selectLeft();
-
-        var range = this.selection.getRange();
-        assert.equal(this.session.getTextRange(range), "dolo");
-        assert.equal(callHighlighterUpdate(this.session, 0, 0), 0);
-    },
-
-    "test: partial word selection 2": function() {
-        this.selection.moveCursorTo(0, 13);
-        this.selection.selectWord();
-        this.selection.selectRight();
-
-        var range = this.selection.getRange();
-        assert.equal(this.session.getTextRange(range), "dolor ");
-        assert.equal(callHighlighterUpdate(this.session, 0, 0), 0);
-    },
-
-    "test: partial word selection 3": function() {
-        this.selection.moveCursorTo(0, 14);
-        this.selection.selectWord();
-        this.selection.selectLeft();
-        this.selection.shiftSelection(1);
-
-        var range = this.selection.getRange();
-        assert.equal(this.session.getTextRange(range), "olor");
-        assert.equal(callHighlighterUpdate(this.session, 0, 0), 0);
-    },
-
-    "test: select last word": function() {
-        this.selection.moveCursorTo(0, 1);
-
-        var currentOptions = this.search.getOptions();
-        var newOptions = {
-            wrap: true,
-            wholeWord: true,
-            caseSensitive: true,
-            backwards: true,
-            needle: "consectetur"
-        };
-        this.search.set(newOptions);
-
-        var match = this.search.find(this.session);
-        assert.notEqual(match, null, "found a match for 'consectetur'");
-        assert.position(match.start, 1, 0);
-
-        this.search.set(currentOptions);
-
-        this.selection.setSelectionRange(match);
-
-        assert.equal(this.session.getTextRange(match), "consectetur");
-        assert.equal(callHighlighterUpdate(this.session, 0, 1), 3);
-    }
-};
-
-});
-
-if (typeof module !== "undefined" && module === require.main) {
-    require("asyncjs").test.testcase(module.exports).exec();
-}

+ 0 - 164
services/web/public/js/ace/editor_navigation_test.js

@@ -1,164 +0,0 @@
-/* ***** 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");
-    require("./test/mockdom");
-}
-
-define(function(require, exports, module) {
-"use strict";
-
-var EditSession = require("./edit_session").EditSession;
-var Editor = require("./editor").Editor;
-var MockRenderer = require("./test/mockrenderer").MockRenderer;
-var assert = require("./test/assertions");
-
-module.exports = {
-    createEditSession : function(rows, cols) {
-        var line = new Array(cols + 1).join("a");
-        var text = new Array(rows).join(line + "\n") + line;
-        return new EditSession(text);
-    },
-
-    "test: navigate to end of file should scroll the last line into view" : function() {
-        var doc = this.createEditSession(200, 10);
-        var editor = new Editor(new MockRenderer(), doc);
-
-        editor.navigateFileEnd();
-        var cursor = editor.getCursorPosition();
-
-        assert.ok(editor.getFirstVisibleRow() <= cursor.row);
-        assert.ok(editor.getLastVisibleRow() >= cursor.row);
-    },
-
-    "test: navigate to start of file should scroll the first row into view" : function() {
-        var doc = this.createEditSession(200, 10);
-        var editor = new Editor(new MockRenderer(), doc);
-
-        editor.moveCursorTo(editor.getLastVisibleRow() + 20);
-        editor.navigateFileStart();
-
-        assert.equal(editor.getFirstVisibleRow(), 0);
-    },
-
-    "test: goto hidden line should scroll the line into the middle of the viewport" : function() {
-        var editor = new Editor(new MockRenderer(), this.createEditSession(200, 5));
-
-        editor.navigateTo(0, 0);
-        editor.gotoLine(101);
-        assert.position(editor.getCursorPosition(), 100, 0);
-        assert.equal(editor.getFirstVisibleRow(), 89);
-
-        editor.navigateTo(100, 0);
-        editor.gotoLine(11);
-        assert.position(editor.getCursorPosition(), 10, 0);
-        assert.equal(editor.getFirstVisibleRow(), 0);
-
-        editor.navigateTo(100, 0);
-        editor.gotoLine(6);
-        assert.position(editor.getCursorPosition(), 5, 0);
-        assert.equal(0, editor.getFirstVisibleRow(), 0);
-
-        editor.navigateTo(100, 0);
-        editor.gotoLine(1);
-        assert.position(editor.getCursorPosition(), 0, 0);
-        assert.equal(editor.getFirstVisibleRow(), 0);
-
-        editor.navigateTo(0, 0);
-        editor.gotoLine(191);
-        assert.position(editor.getCursorPosition(), 190, 0);
-        assert.equal(editor.getFirstVisibleRow(), 179);
-
-        editor.navigateTo(0, 0);
-        editor.gotoLine(196);
-        assert.position(editor.getCursorPosition(), 195, 0);
-        assert.equal(editor.getFirstVisibleRow(), 180);
-    },
-
-    "test: goto visible line should only move the cursor and not scroll": function() {
-        var editor = new Editor(new MockRenderer(), this.createEditSession(200, 5));
-
-        editor.navigateTo(0, 0);
-        editor.gotoLine(12);
-        assert.position(editor.getCursorPosition(), 11, 0);
-        assert.equal(editor.getFirstVisibleRow(), 0);
-
-        editor.navigateTo(30, 0);
-        editor.gotoLine(33);
-        assert.position(editor.getCursorPosition(), 32, 0);
-        assert.equal(editor.getFirstVisibleRow(), 30);
-    },
-
-    "test: navigate from the end of a long line down to a short line and back should maintain the curser column": function() {
-        var editor = new Editor(new MockRenderer(), new EditSession(["123456", "1"]));
-
-        editor.navigateTo(0, 6);
-        assert.position(editor.getCursorPosition(), 0, 6);
-
-        editor.navigateDown();
-        assert.position(editor.getCursorPosition(), 1, 1);
-
-        editor.navigateUp();
-        assert.position(editor.getCursorPosition(), 0, 6);
-    },
-
-    "test: reset desired column on navigate left or right": function() {
-        var editor = new Editor(new MockRenderer(), new EditSession(["123456", "12"]));
-
-        editor.navigateTo(0, 6);
-        assert.position(editor.getCursorPosition(), 0, 6);
-
-        editor.navigateDown();
-        assert.position(editor.getCursorPosition(), 1, 2);
-
-        editor.navigateLeft();
-        assert.position(editor.getCursorPosition(), 1, 1);
-
-        editor.navigateUp();
-        assert.position(editor.getCursorPosition(), 0, 1);
-    },
-    
-    "test: typing text should update the desired column": function() {
-        var editor = new Editor(new MockRenderer(), new EditSession(["1234", "1234567890"]));
-
-        editor.navigateTo(0, 3);
-        editor.insert("juhu");
-        
-        editor.navigateDown();
-        assert.position(editor.getCursorPosition(), 1, 7);
-    }
-};
-
-});
-
-if (typeof module !== "undefined" && module === require.main) {
-    require("asyncjs").test.testcase(module.exports).exec()
-}

+ 0 - 557
services/web/public/js/ace/editor_text_edit_test.js

@@ -1,557 +0,0 @@
-/* ***** 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");
-    require("./test/mockdom");
-}
-
-define(function(require, exports, module) {
-"use strict";
-
-var EditSession = require("./edit_session").EditSession;
-var Editor = require("./editor").Editor;
-var JavaScriptMode = require("./mode/javascript").Mode;
-var UndoManager = require("./undomanager").UndoManager;
-var MockRenderer = require("./test/mockrenderer").MockRenderer;
-var assert = require("./test/assertions");
-var whitespace = require("./ext/whitespace");
-
-module.exports = {
-    "test: delete line from the middle" : function() {
-        var session = new EditSession(["a", "b", "c", "d"].join("\n"));
-        var editor = new Editor(new MockRenderer(), session);
-
-        editor.moveCursorTo(1, 1);
-        editor.removeLines();
-
-        assert.equal(session.toString(), "a\nc\nd");
-        assert.position(editor.getCursorPosition(), 1, 0);
-
-        editor.removeLines();
-
-        assert.equal(session.toString(), "a\nd");
-        assert.position(editor.getCursorPosition(), 1, 0);
-
-        editor.removeLines();
-
-        assert.equal(session.toString(), "a");
-        assert.position(editor.getCursorPosition(), 0, 1);
-
-        editor.removeLines();
-
-        assert.equal(session.toString(), "");
-        assert.position(editor.getCursorPosition(), 0, 0);
-    },
-
-    "test: delete multiple selected lines" : function() {
-        var session = new EditSession(["a", "b", "c", "d"].join("\n"));
-        var editor = new Editor(new MockRenderer(), session);
-
-        editor.moveCursorTo(1, 1);
-        editor.getSelection().selectDown();
-
-        editor.removeLines();
-        assert.equal(session.toString(), "a\nd");
-        assert.position(editor.getCursorPosition(), 1, 0);
-    },
-
-    "test: delete first line" : function() {
-        var session = new EditSession(["a", "b", "c"].join("\n"));
-        var editor = new Editor(new MockRenderer(), session);
-
-        editor.removeLines();
-
-        assert.equal(session.toString(), "b\nc");
-        assert.position(editor.getCursorPosition(), 0, 0);
-    },
-
-    "test: delete last should also delete the new line of the previous line" : function() {
-        var session = new EditSession(["a", "b", "c", ""].join("\n"));
-        var editor = new Editor(new MockRenderer(), session);
-
-        editor.moveCursorTo(3, 0);
-
-        editor.removeLines();
-        assert.equal(session.toString(), "a\nb\nc");
-        assert.position(editor.getCursorPosition(), 2, 1);
-
-        editor.removeLines();
-        assert.equal(session.toString(), "a\nb");
-        assert.position(editor.getCursorPosition(), 1, 1);
-    },
-
-    "test: indent block" : function() {
-        var session = new EditSession(["a12345", "b12345", "c12345"].join("\n"));
-        var editor = new Editor(new MockRenderer(), session);
-
-        editor.moveCursorTo(1, 3);
-        editor.getSelection().selectDown();
-
-        editor.indent();
-
-        assert.equal(["a12345", "    b12345", "    c12345"].join("\n"), session.toString());
-
-        assert.position(editor.getCursorPosition(), 2, 7);
-
-        var range = editor.getSelectionRange();
-        assert.position(range.start, 1, 7);
-        assert.position(range.end, 2, 7);
-    },
-
-    "test: indent selected lines" : function() {
-        var session = new EditSession(["a12345", "b12345", "c12345"].join("\n"));
-        var editor = new Editor(new MockRenderer(), session);
-
-        editor.moveCursorTo(1, 0);
-        editor.getSelection().selectDown();
-
-        editor.indent();
-        assert.equal(["a12345", "    b12345", "c12345"].join("\n"), session.toString());
-    },
-
-    "test: no auto indent if cursor is before the {" : function() {
-        var session = new EditSession("{", new JavaScriptMode());
-        var editor = new Editor(new MockRenderer(), session);
-
-        editor.moveCursorTo(0, 0);
-        editor.onTextInput("\n");
-        assert.equal(["", "{"].join("\n"), session.toString());
-    },
-    
-    "test: outdent block" : function() {
-        var session = new EditSession(["        a12345", "    b12345", "        c12345"].join("\n"));
-        var editor = new Editor(new MockRenderer(), session);
-
-        editor.moveCursorTo(0, 5);
-        editor.getSelection().selectDown();
-        editor.getSelection().selectDown();
-
-        editor.blockOutdent();
-        assert.equal(session.toString(), ["    a12345", "b12345", "    c12345"].join("\n"));
-
-        assert.position(editor.getCursorPosition(), 2, 1);
-
-        var range = editor.getSelectionRange();
-        assert.position(range.start, 0, 1);
-        assert.position(range.end, 2, 1);
-
-        editor.blockOutdent();
-        assert.equal(session.toString(), ["a12345", "b12345", "c12345"].join("\n"));
-
-        var range = editor.getSelectionRange();
-        assert.position(range.start, 0, 0);
-        assert.position(range.end, 2, 0);
-    },
-
-    "test: outent without a selection should update cursor" : function() {
-        var session = new EditSession("        12");
-        var editor = new Editor(new MockRenderer(), session);
-
-        editor.moveCursorTo(0, 3);
-        editor.blockOutdent("  ");
-
-        assert.equal(session.toString(), "    12");
-        assert.position(editor.getCursorPosition(), 0, 0);
-    },
-
-    "test: comment lines should perserve selection" : function() {
-        var session = new EditSession(["  abc", "cde"].join("\n"), new JavaScriptMode());
-        var editor = new Editor(new MockRenderer(), session);
-        whitespace.detectIndentation(session);
-        
-        editor.moveCursorTo(0, 2);
-        editor.getSelection().selectDown();
-        editor.toggleCommentLines();
-
-        assert.equal(["//   abc", "// cde"].join("\n"), session.toString());
-
-        var selection = editor.getSelectionRange();
-        assert.position(selection.start, 0, 5);
-        assert.position(selection.end, 1, 5);
-    },
-
-    "test: uncomment lines should perserve selection" : function() {
-        var session = new EditSession(["//   abc", "//cde"].join("\n"), new JavaScriptMode());
-        var editor = new Editor(new MockRenderer(), session);
-        session.setTabSize(2);
-
-        editor.moveCursorTo(0, 1);
-        editor.getSelection().selectDown();
-        editor.getSelection().selectRight();
-        editor.getSelection().selectRight();
-
-        editor.toggleCommentLines();
-
-        assert.equal(["  abc", "cde"].join("\n"), session.toString());
-        assert.range(editor.getSelectionRange(), 0, 0, 1, 1);
-    },
-
-    "test: toggle comment lines twice should return the original text" : function() {
-        var session = new EditSession(["  abc", "cde", "fg"], new JavaScriptMode());
-        var editor = new Editor(new MockRenderer(), session);
-
-        editor.moveCursorTo(0, 0);
-        editor.getSelection().selectDown();
-        editor.getSelection().selectDown();
-
-        editor.toggleCommentLines();
-        editor.toggleCommentLines();
-
-        assert.equal(["  abc", "cde", "fg"].join("\n"), session.toString());
-    },
-
-
-    "test: comment lines - if the selection end is at the line start it should stay there": function() {
-        //select down
-        var session = new EditSession(["abc", "cde"].join("\n"), new JavaScriptMode());
-        var editor = new Editor(new MockRenderer(), session);
-
-        editor.moveCursorTo(0, 0);
-        editor.getSelection().selectDown();
-
-        editor.toggleCommentLines();
-        assert.range(editor.getSelectionRange(), 0, 3, 1, 0);
-
-        // select up
-        var session = new EditSession(["abc", "cde"].join("\n"), new JavaScriptMode());
-        var editor = new Editor(new MockRenderer(), session);
-
-        editor.moveCursorTo(1, 0);
-        editor.getSelection().selectUp();
-
-        editor.toggleCommentLines();
-        assert.range(editor.getSelectionRange(), 0, 3, 1, 0);
-    },
-
-    "test: move lines down should keep selection on moved lines" : function() {
-        var session = new EditSession(["11", "22", "33", "44"].join("\n"));
-        var editor = new Editor(new MockRenderer(), session);
-
-        editor.moveCursorTo(0, 1);
-        editor.getSelection().selectDown();
-
-        editor.moveLinesDown();
-        assert.equal(["33", "11", "22", "44"].join("\n"), session.toString());
-        assert.position(editor.getCursorPosition(), 2, 1);
-        assert.position(editor.getSelection().getSelectionAnchor(), 1, 1);
-        assert.position(editor.getSelection().getSelectionLead(), 2, 1);
-
-        editor.moveLinesDown();
-        assert.equal(["33", "44", "11", "22"].join("\n"), session.toString());
-        assert.position(editor.getCursorPosition(), 3, 1);
-        assert.position(editor.getSelection().getSelectionAnchor(), 2, 1);
-        assert.position(editor.getSelection().getSelectionLead(), 3, 1);
-
-        // moving again should have no effect
-        editor.moveLinesDown();
-        assert.equal(["33", "44", "11", "22"].join("\n"), session.toString());
-        assert.position(editor.getCursorPosition(), 3, 1);
-        assert.position(editor.getSelection().getSelectionAnchor(), 2, 1);
-        assert.position(editor.getSelection().getSelectionLead(), 3, 1);
-    },
-
-    "test: move lines up should keep selection on moved lines" : function() {
-        var session = new EditSession(["11", "22", "33", "44"].join("\n"));
-        var editor = new Editor(new MockRenderer(), session);
-
-        editor.moveCursorTo(2, 1);
-        editor.getSelection().selectDown();
-
-        editor.moveLinesUp();
-        assert.equal(session.toString(), ["11", "33", "44", "22"].join("\n"));
-        assert.position(editor.getCursorPosition(), 2, 1);
-        assert.position(editor.getSelection().getSelectionAnchor(), 1, 1);
-        assert.position(editor.getSelection().getSelectionLead(), 2, 1);
-
-        editor.moveLinesUp();
-        assert.equal(session.toString(), ["33", "44", "11", "22"].join("\n"));
-        assert.position(editor.getCursorPosition(), 1, 1);
-        assert.position(editor.getSelection().getSelectionAnchor(), 0, 1);
-        assert.position(editor.getSelection().getSelectionLead(), 1, 1);
-    },
-
-    "test: move line without active selection should not move cursor relative to the moved line" : function() {
-        var session = new EditSession(["11", "22", "33", "44"].join("\n"));
-        var editor = new Editor(new MockRenderer(), session);
-
-        editor.moveCursorTo(1, 1);
-        editor.clearSelection();
-
-        editor.moveLinesDown();
-        assert.equal(["11", "33", "22", "44"].join("\n"), session.toString());
-        assert.position(editor.getCursorPosition(), 2, 1);
-
-        editor.clearSelection();
-
-        editor.moveLinesUp();
-        assert.equal(["11", "22", "33", "44"].join("\n"), session.toString());
-        assert.position(editor.getCursorPosition(), 1, 1);
-    },
-
-    "test: copy lines down should keep selection" : function() {
-        var session = new EditSession(["11", "22", "33", "44"].join("\n"));
-        var editor = new Editor(new MockRenderer(), session);
-
-        editor.moveCursorTo(1, 1);
-        editor.getSelection().selectDown();
-
-        editor.copyLinesDown();
-        assert.equal(["11", "22", "33", "22", "33", "44"].join("\n"), session.toString());
-
-        assert.position(editor.getCursorPosition(), 4, 1);
-        assert.position(editor.getSelection().getSelectionAnchor(), 3, 1);
-        assert.position(editor.getSelection().getSelectionLead(), 4, 1);
-    },
-
-    "test: copy lines up should keep selection" : function() {
-        var session = new EditSession(["11", "22", "33", "44"].join("\n"));
-        var editor = new Editor(new MockRenderer(), session);
-
-        editor.moveCursorTo(1, 1);
-        editor.getSelection().selectDown();
-
-        editor.copyLinesUp();
-        assert.equal(["11", "22", "33", "22", "33", "44"].join("\n"), session.toString());
-
-        assert.position(editor.getCursorPosition(), 2, 1);
-        assert.position(editor.getSelection().getSelectionAnchor(), 1, 1);
-        assert.position(editor.getSelection().getSelectionLead(), 2, 1);
-    },
-
-    "test: input a tab with soft tab should convert it to spaces" : function() {
-        var session = new EditSession("");
-        var editor = new Editor(new MockRenderer(), session);
-
-        session.setTabSize(2);
-        session.setUseSoftTabs(true);
-
-        editor.onTextInput("\t");
-        assert.equal(session.toString(), "  ");
-
-        session.setTabSize(5);
-        editor.onTextInput("\t");
-        assert.equal(session.toString(), "       ");
-    },
-
-    "test: input tab without soft tabs should keep the tab character" : function() {
-        var session = new EditSession("");
-        var editor = new Editor(new MockRenderer(), session);
-
-        session.setUseSoftTabs(false);
-
-        editor.onTextInput("\t");
-        assert.equal(session.toString(), "\t");
-    },
-
-    "test: undo/redo for delete line" : function() {
-        var session = new EditSession(["111", "222", "333"]);
-        var undoManager = new UndoManager();
-        session.setUndoManager(undoManager);
-
-        var initialText = session.toString();
-        var editor = new Editor(new MockRenderer(), session);
-
-        editor.removeLines();
-        var step1 = session.toString();
-        assert.equal(step1, "222\n333");
-        session.$syncInformUndoManager();
-
-        editor.removeLines();
-        var step2 = session.toString();
-        assert.equal(step2, "333");
-        session.$syncInformUndoManager();
-
-        editor.removeLines();
-        var step3 = session.toString();
-        assert.equal(step3, "");
-        session.$syncInformUndoManager();
-
-        undoManager.undo();
-        session.$syncInformUndoManager();
-        assert.equal(session.toString(), step2);
-
-        undoManager.undo();
-        session.$syncInformUndoManager();
-        assert.equal(session.toString(), step1);
-
-        undoManager.undo();
-        session.$syncInformUndoManager();
-        assert.equal(session.toString(), initialText);
-
-        undoManager.undo();
-        session.$syncInformUndoManager();
-        assert.equal(session.toString(), initialText);
-    },
-
-    "test: remove left should remove character left of the cursor" : function() {
-        var session = new EditSession(["123", "456"]);
-
-        var editor = new Editor(new MockRenderer(), session);
-        editor.moveCursorTo(1, 1);
-        editor.remove("left");
-        assert.equal(session.toString(), "123\n56");
-    },
-
-    "test: remove left should remove line break if cursor is at line start" : function() {
-        var session = new EditSession(["123", "456"]);
-
-        var editor = new Editor(new MockRenderer(), session);
-        editor.moveCursorTo(1, 0);
-        editor.remove("left");
-        assert.equal(session.toString(), "123456");
-    },
-
-    "test: remove left should remove tabsize spaces if cursor is on a tab stop and preceeded by spaces" : function() {
-        var session = new EditSession(["123", "        456"]);
-        session.setUseSoftTabs(true);
-        session.setTabSize(4);
-
-        var editor = new Editor(new MockRenderer(), session);
-        editor.moveCursorTo(1, 8);
-        editor.remove("left");
-        assert.equal(session.toString(), "123\n    456");
-    },
-    
-    "test: transpose at line start should be a noop": function() {
-        var session = new EditSession(["123", "4567", "89"]);
-        
-        var editor = new Editor(new MockRenderer(), session);
-        editor.moveCursorTo(1, 0);
-        editor.transposeLetters();
-        
-        assert.equal(session.getValue(), ["123", "4567", "89"].join("\n"));
-    },
-    
-    "test: transpose in line should swap the charaters before and after the cursor": function() {
-        var session = new EditSession(["123", "4567", "89"]);
-        
-        var editor = new Editor(new MockRenderer(), session);
-        editor.moveCursorTo(1, 2);
-        editor.transposeLetters();
-        
-        assert.equal(session.getValue(), ["123", "4657", "89"].join("\n"));
-    },
-    
-    "test: transpose at line end should swap the last two characters": function() {
-        var session = new EditSession(["123", "4567", "89"]);
-        
-        var editor = new Editor(new MockRenderer(), session);
-        editor.moveCursorTo(1, 4);
-        editor.transposeLetters();
-        
-        assert.equal(session.getValue(), ["123", "4576", "89"].join("\n"));
-    },
-    
-    "test: transpose with non empty selection should be a noop": function() {
-        var session = new EditSession(["123", "4567", "89"]);
-        
-        var editor = new Editor(new MockRenderer(), session);
-        editor.moveCursorTo(1, 1);
-        editor.getSelection().selectRight();
-        editor.transposeLetters();
-        
-        assert.equal(session.getValue(), ["123", "4567", "89"].join("\n"));
-    },
-    
-    "test: transpose should move the cursor behind the last swapped character": function() {
-        var session = new EditSession(["123", "4567", "89"]);
-        
-        var editor = new Editor(new MockRenderer(), session);
-        editor.moveCursorTo(1, 2);
-        editor.transposeLetters();
-        assert.position(editor.getCursorPosition(), 1, 3);
-    },
-    
-    "test: remove to line end": function() {
-        var session = new EditSession(["123", "4567", "89"]);
-        
-        var editor = new Editor(new MockRenderer(), session);
-        editor.moveCursorTo(1, 2);
-        editor.removeToLineEnd();
-        assert.equal(session.getValue(), ["123", "45", "89"].join("\n"));
-    },
-    
-    "test: remove to line end at line end should remove the new line": function() {
-        var session = new EditSession(["123", "4567", "89"]);
-        
-        var editor = new Editor(new MockRenderer(), session);
-        editor.moveCursorTo(1, 4);
-        editor.removeToLineEnd();
-        assert.position(editor.getCursorPosition(), 1, 4);
-        assert.equal(session.getValue(), ["123", "456789"].join("\n"));
-    },
-
-    "test: transform selection to uppercase": function() {
-        var session = new EditSession(["ajax", "dot", "org"]);
-
-        var editor = new Editor(new MockRenderer(), session);
-        editor.moveCursorTo(1, 0);
-        editor.getSelection().selectLineEnd();
-        editor.toUpperCase()
-        assert.equal(session.getValue(), ["ajax", "DOT", "org"].join("\n"));
-    },
-
-    "test: transform word to uppercase": function() {
-        var session = new EditSession(["ajax", "dot", "org"]);
-
-        var editor = new Editor(new MockRenderer(), session);
-        editor.moveCursorTo(1, 0);
-        editor.toUpperCase()
-        assert.equal(session.getValue(), ["ajax", "DOT", "org"].join("\n"));
-        assert.position(editor.getCursorPosition(), 1, 0);
-    },
-
-    "test: transform selection to lowercase": function() {
-        var session = new EditSession(["AJAX", "DOT", "ORG"]);
-
-        var editor = new Editor(new MockRenderer(), session);
-        editor.moveCursorTo(1, 0);
-        editor.getSelection().selectLineEnd();
-        editor.toLowerCase()
-        assert.equal(session.getValue(), ["AJAX", "dot", "ORG"].join("\n"));
-    },
-
-    "test: transform word to lowercase": function() {
-        var session = new EditSession(["AJAX", "DOT", "ORG"]);
-
-        var editor = new Editor(new MockRenderer(), session);
-        editor.moveCursorTo(1, 0);
-        editor.toLowerCase()
-        assert.equal(session.getValue(), ["AJAX", "dot", "ORG"].join("\n"));
-        assert.position(editor.getCursorPosition(), 1, 0);
-    }
-};
-
-});
-
-if (typeof module !== "undefined" && module === require.main) {
-    require("asyncjs").test.testcase(module.exports).exec()
-}

+ 335 - 0
services/web/public/js/ace/ext-beautify.js

@@ -0,0 +1,335 @@
+define("ace/ext/beautify/php_rules",["require","exports","module","ace/token_iterator"], function(require, exports, module) {
+"use strict";
+var TokenIterator = require("ace/token_iterator").TokenIterator;
+exports.newLines = [{
+    type: 'support.php_tag',
+    value: '<?php'
+}, {
+    type: 'support.php_tag',
+    value: '<?'
+}, {
+    type: 'support.php_tag',
+    value: '?>'
+}, {
+    type: 'paren.lparen',
+    value: '{',
+    indent: true
+}, {
+    type: 'paren.rparen',
+    breakBefore: true,
+    value: '}',
+    indent: false
+}, {
+    type: 'paren.rparen',
+    breakBefore: true,
+    value: '})',
+    indent: false,
+    dontBreak: true
+}, {
+    type: 'comment'
+}, {
+    type: 'text',
+    value: ';'
+}, {
+    type: 'text',
+    value: ':',
+    context: 'php'
+}, {
+    type: 'keyword',
+    value: 'case',
+    indent: true,
+    dontBreak: true
+}, {
+    type: 'keyword',
+    value: 'default',
+    indent: true,
+    dontBreak: true
+}, {
+    type: 'keyword',
+    value: 'break',
+    indent: false,
+    dontBreak: true
+}, {
+    type: 'punctuation.doctype.end',
+    value: '>'
+}, {
+    type: 'meta.tag.punctuation.end',
+    value: '>'
+}, {
+    type: 'meta.tag.punctuation.begin',
+    value: '<',
+    blockTag: true,
+    indent: true,
+    dontBreak: true
+}, {
+    type: 'meta.tag.punctuation.begin',
+    value: '</',
+    indent: false,
+    breakBefore: true,
+    dontBreak: true
+}, {
+    type: 'punctuation.operator',
+    value: ';'
+}];
+
+exports.spaces = [{
+    type: 'xml-pe',
+    prepend: true
+},{
+    type: 'entity.other.attribute-name',
+    prepend: true
+}, {
+    type: 'storage.type',
+    value: 'var',
+    append: true
+}, {
+    type: 'storage.type',
+    value: 'function',
+    append: true
+}, {
+    type: 'keyword.operator',
+    value: '='
+}, {
+    type: 'keyword',
+    value: 'as',
+    prepend: true,
+    append: true
+}, {
+    type: 'keyword',
+    value: 'function',
+    append: true
+}, {
+    type: 'support.function',
+    next: /[^\(]/,
+    append: true
+}, {
+    type: 'keyword',
+    value: 'or',
+    append: true,
+    prepend: true
+}, {
+    type: 'keyword',
+    value: 'and',
+    append: true,
+    prepend: true
+}, {
+    type: 'keyword',
+    value: 'case',
+    append: true
+}, {
+    type: 'keyword.operator',
+    value: '||',
+    append: true,
+    prepend: true
+}, {
+    type: 'keyword.operator',
+    value: '&&',
+    append: true,
+    prepend: true
+}];
+exports.singleTags = ['!doctype','area','base','br','hr','input','img','link','meta'];
+
+exports.transform = function(iterator, maxPos, context) {
+    var token = iterator.getCurrentToken();
+    
+    var newLines = exports.newLines;
+    var spaces = exports.spaces;
+    var singleTags = exports.singleTags;
+
+    var code = '';
+    
+    var indentation = 0;
+    var dontBreak = false;
+    var tag;
+    var lastTag;
+    var lastToken = {};
+    var nextTag;
+    var nextToken = {};
+    var breakAdded = false;
+    var value = '';
+
+    while (token!==null) {
+        console.log(token);
+
+        if( !token ){
+            token = iterator.stepForward();
+            continue;
+        }
+        if( token.type == 'support.php_tag' && token.value != '?>' ){
+            context = 'php';
+        }
+        else if( token.type == 'support.php_tag' && token.value == '?>' ){
+            context = 'html';
+        }
+        else if( token.type == 'meta.tag.name.style' && context != 'css' ){
+            context = 'css';
+        }
+        else if( token.type == 'meta.tag.name.style' && context == 'css' ){
+            context = 'html';
+        }
+        else if( token.type == 'meta.tag.name.script' && context != 'js' ){
+            context = 'js';
+        }
+        else if( token.type == 'meta.tag.name.script' && context == 'js' ){
+            context = 'html';
+        }
+
+        nextToken = iterator.stepForward();
+        if (nextToken && nextToken.type.indexOf('meta.tag.name') == 0) {
+            nextTag = nextToken.value;
+        }
+        if ( lastToken.type == 'support.php_tag' && lastToken.value == '<?=') {
+            dontBreak = true;
+        }
+        if (token.type == 'meta.tag.name') {
+            token.value = token.value.toLowerCase();
+        }
+        if (token.type == 'text') {
+            token.value = token.value.trim();
+        }
+        if (!token.value) {
+            token = nextToken;
+            continue;
+        }
+        value = token.value;
+        for (var i in spaces) {
+            if (
+                token.type == spaces[i].type &&
+                (!spaces[i].value || token.value == spaces[i].value) &&
+                (
+                    nextToken &&
+                    (!spaces[i].next || spaces[i].next.test(nextToken.value))
+                )
+            ) {
+                if (spaces[i].prepend) {
+                    value = ' ' + token.value;
+                }
+
+                if (spaces[i].append) {
+                    value += ' ';
+                }
+            }
+        }
+        if (token.type.indexOf('meta.tag.name') == 0) {
+            tag = token.value;
+        }
+        breakAdded = false;
+        for (i in newLines) {
+            if (
+                token.type == newLines[i].type &&
+                (
+                    !newLines[i].value ||
+                    token.value == newLines[i].value
+                ) &&
+                (
+                    !newLines[i].blockTag ||
+                    singleTags.indexOf(nextTag) === -1
+                ) &&
+                (
+                    !newLines[i].context ||
+                    newLines[i].context === context
+                )
+            ) {
+                if (newLines[i].indent === false) {
+                    indentation--;
+                }
+
+                if (
+                    newLines[i].breakBefore &&
+                    ( !newLines[i].prev || newLines[i].prev.test(lastToken.value) )
+                ) {
+                    code += "\n";
+                    breakAdded = true;
+                    for (i = 0; i < indentation; i++) {
+                        code += "\t";
+                    }
+                }
+
+                break;
+            }
+        }
+
+        if (dontBreak===false) {
+            for (i in newLines) {
+                if (
+                    lastToken.type == newLines[i].type &&
+                    (
+                        !newLines[i].value || lastToken.value == newLines[i].value
+                    ) &&
+                    (
+                        !newLines[i].blockTag ||
+                        singleTags.indexOf(tag) === -1
+                    ) &&
+                    (
+                        !newLines[i].context ||
+                        newLines[i].context === context
+                    )
+                ) {
+                    if (newLines[i].indent === true) {
+                        indentation++;
+                    }
+
+                    if (!newLines[i].dontBreak  && !breakAdded) {
+                        code += "\n";
+                        for (i = 0; i < indentation; i++) {
+                            code += "\t";
+                        }
+                    }
+
+                    break;
+                }
+            }
+        }
+
+        code += value;
+        if ( lastToken.type == 'support.php_tag' && lastToken.value == '?>' ) {
+            dontBreak = false;
+        }
+        lastTag = tag;
+
+        lastToken = token;
+
+        token = nextToken;
+
+        if (token===null) {
+            break;
+        }
+    }
+    
+    return code;
+};
+
+
+
+});
+
+define("ace/ext/beautify",["require","exports","module","ace/token_iterator","ace/ext/beautify/php_rules"], function(require, exports, module) {
+"use strict";
+var TokenIterator = require("ace/token_iterator").TokenIterator;
+
+var phpTransform = require("./beautify/php_rules").transform;
+
+exports.beautify = function(session) {
+    var iterator = new TokenIterator(session, 0, 0);
+    var token = iterator.getCurrentToken();
+
+    var context = session.$modeId.split("/").pop();
+
+    var code = phpTransform(iterator, context);
+    session.doc.setValue(code);
+};
+
+exports.commands = [{
+    name: "beautify",
+    exec: function(editor) {
+        exports.beautify(editor.session);
+    },
+    bindKey: "Ctrl-Shift-B"
+}]
+
+});
+;
+                (function() {
+                    window.require(["ace/ext/beautify"], function() {});
+                })();
+            

+ 6 - 444
services/web/public/js/ace/ext/chromevox.js → services/web/public/js/ace/ext-chromevox.js

@@ -1,125 +1,46 @@
-define(function(require, exports, module) {
-
-/* ChromeVox Ace namespace. */
+define("ace/ext/chromevox",["require","exports","module","ace/editor","ace/config"], function(require, exports, module) {
 var cvoxAce = {};
-
-/* Typedefs for Closure compiler. */
-/**
- * @typedef {{
-    rate: number,
-    pitch: number,
-    volume: number,
-    relativePitch: number,
-    punctuationEcho: string
-   }}
- */
-/* TODO(peterxiao): Export this typedef through cvox.Api. */
 cvoxAce.SpeechProperty;
-
-/**
- * @typedef {{
- *   row: number,
- *   column: number
- * }}
- */
 cvoxAce.Cursor;
-
-/**
- * @typedef {{
-    type: string,
-    value: string
-   }}
- }
- */
 cvoxAce.Token;
-
-/**
- * These are errors and information that Ace will display in the gutter.
- * @typedef {{
-    row: number,
-    column: number,
-    value: string
-   }}
- }
- */
 cvoxAce.Annotation;
-
-/* Speech Properties. */
-/**
- * Speech property for speaking constant tokens.
- * @type {cvoxAce.SpeechProperty}
- */
 var CONSTANT_PROP = {
   'rate': 0.8,
   'pitch': 0.4,
   'volume': 0.9
 };
-
-/**
- * Default speech property for speaking tokens.
- * @type {cvoxAce.SpeechProperty}
- */
 var DEFAULT_PROP = {
   'rate': 1,
   'pitch': 0.5,
   'volume': 0.9
 };
-
-/**
- * Speech property for speaking entity tokens.
- * @type {cvoxAce.SpeechProperty}
- */
 var ENTITY_PROP = {
   'rate': 0.8,
   'pitch': 0.8,
   'volume': 0.9
 };
-
-/**
- * Speech property for speaking keywords.
- * @type {cvoxAce.SpeechProperty}
- */
 var KEYWORD_PROP = {
   'rate': 0.8,
   'pitch': 0.3,
   'volume': 0.9
 };
-
-/**
- * Speech property for speaking storage tokens.
- * @type {cvoxAce.SpeechProperty}
- */
 var STORAGE_PROP = {
   'rate': 0.8,
   'pitch': 0.7,
   'volume': 0.9
 };
-
-/**
- * Speech property for speaking variable tokens.
- * @type {cvoxAce.SpeechProperty}
- */
 var VARIABLE_PROP = {
   'rate': 0.8,
   'pitch': 0.8,
   'volume': 0.9
 };
-
-/**
- * Speech property for speaking deleted text.
- * @type {cvoxAce.SpeechProperty}
- */
 var DELETED_PROP = {
   'punctuationEcho': 'none',
   'relativePitch': -0.6
 };
-
-/* Constants for Earcons. */
 var ERROR_EARCON = 'ALERT_NONMODAL';
 var MODE_SWITCH_EARCON = 'ALERT_MODAL';
 var NO_MATCH_EARCON = 'INVALID_KEYPRESS';
-
-/* Constants for vim state. */
 var INSERT_MODE_STATE = 'insertMode';
 var COMMAND_MODE_STATE = 'start';
 
@@ -133,10 +54,6 @@ var REPLACE_LIST = [
     newSubstr: ' colon '
   }
 ];
-
-/**
- * Context menu commands.
- */
 var Command = {
   SPEAK_ANNOT: 'annots',
   SPEAK_ALL_ANNOTS: 'all_annots',
@@ -146,104 +63,30 @@ var Command = {
   TOGGLE_DISPLACEMENT: 'toggle_displacement',
   FOCUS_TEXT: 'focus_text'
 };
-
-/**
- * Key prefix for each shortcut.
- */
 var KEY_PREFIX = 'CONTROL + SHIFT ';
-
-/* Globals. */
 cvoxAce.editor = null;
-/**
- * Last cursor position.
- * @type {cvoxAce.Cursor}
- */
 var lastCursor = null;
-
-/**
- * Table of annotations.
- * @typedef {!Object.<number, Object<number, cvoxAce.Annotation>>}
- */
 var annotTable = {};
-
-/**
- * Whether to speak character, word, and then line. This allows blind users
- * to know the location of the cursor when they change lines.
- * @typedef {boolean}
- */
 var shouldSpeakRowLocation = false;
-
-/**
- * Whether to speak displacement.
- * @typedef {boolean}
- */
 var shouldSpeakDisplacement = false;
-
-/**
- * Whether text was changed to cause a cursor change event.
- * @typedef {boolean}
- */
 var changed = false;
-
-/**
- * Current state vim is in.
- */
 var vimState = null;
-
-/**
- * Mapping from key code to shortcut.
- */
 var keyCodeToShortcutMap = {};
-
-/**
- * Mapping from command to shortcut.
- */
 var cmdToShortcutMap = {};
-
-/**
- * Get shortcut string from keyCode.
- * @param {number} keyCode Key code of shortcut.
- * @return {string} String representation of shortcut.
- */
 var getKeyShortcutString = function(keyCode) {
   return KEY_PREFIX + String.fromCharCode(keyCode);
 };
-
-/**
- * Return if in vim mode.
- * @return {boolean} True if in Vim mode.
- */
 var isVimMode = function() {
   var keyboardHandler = cvoxAce.editor.keyBinding.getKeyboardHandler();
   return keyboardHandler.$id === 'ace/keyboard/vim';
 };
-
-/**
- * Gets the current token.
- * @param {!cvoxAce.Cursor} cursor Current position of the cursor.
- * @return {!cvoxAce.Token} Token at the current position.
- */
 var getCurrentToken = function(cursor) {
   return cvoxAce.editor.getSession().getTokenAt(cursor.row, cursor.column + 1);
 };
-
-/**
- * Gets the current line the cursor is under.
- * @param {!cvoxAce.Cursor} cursor Current cursor position.
- */
 var getCurrentLine = function(cursor) {
   return cvoxAce.editor.getSession().getLine(cursor.row);
 };
-
-/**
- * Event handler for row changes. When the user changes rows we want to speak
- * the line so the user can work on this line. If shouldSpeakRowLocation is on
- * then we speak the character, then the row, then the line so the user knows
- * where the cursor is.
- * @param {!cvoxAce.Cursor} currCursor Current cursor position.
- */
 var onRowChange = function(currCursor) {
-  /* Notify that this line has an annotation. */
   if (annotTable[currCursor.row]) {
     cvox.Api.playEarcon(ERROR_EARCON);
   }
@@ -256,28 +99,16 @@ var onRowChange = function(currCursor) {
     speakLine(currCursor.row, 0);
   }
 };
-
-/**
- * Returns whether the cursor is at the beginning of a word. A word is
- * a grouping of alphanumeric characters including underscores.
- * @param {!cvoxAce.Cursor} cursor Current cursor position.
- * @return {boolean} Whether there is word.
- */
 var isWord = function(cursor) {
   var line = getCurrentLine(cursor);
   var lineSuffix = line.substr(cursor.column - 1);
   if (cursor.column === 0) {
     lineSuffix = ' ' + line;
   }
-  /* Use regex to tell if the suffix is at the start of a new word. */
   var firstWordRegExp = /^\W(\w+)/;
   var words = firstWordRegExp.exec(lineSuffix);
   return words !== null;
 };
-
-/**
- * A mapping of syntax type to speech properties / expanding rules.
- */
 var rules = {
   'constant': {
     prop: CONSTANT_PROP
@@ -316,20 +147,9 @@ var rules = {
     ]
   }
 };
-
-/**
- * Default rule to be used.
- */
 var DEFAULT_RULE = {
   prop: DEFAULT_RULE
 };
-
-/**
- * Expands substrings to how they are read based on the given rules.
- * @param {string} value Text to be expanded.
- * @param {Array.<Object>} replaceRules Rules to determine expansion.
- * @return {string} New expanded value.
- */
 var expand = function(value, replaceRules) {
   var newValue = value;
   for (var i = 0; i < replaceRules.length; i++) {
@@ -339,16 +159,7 @@ var expand = function(value, replaceRules) {
   }
   return newValue;
 };
-
-/**
- * Merges tokens from start inclusive to end exclusive.
- * @param {Array.<cvoxAce.Token>} Tokens to be merged.
- * @param {number} start Start index inclusive.
- * @param {number} end End index exclusive.
- * @return {cvoxAce.Token} Merged token.
- */
 var mergeTokens = function(tokens, start, end) {
-  /* Different type of token found! Merge all previous like tokens. */
   var newToken = {};
   newToken.value = '';
   newToken.type = tokens[start].type;
@@ -357,12 +168,6 @@ var mergeTokens = function(tokens, start, end) {
   }
   return newToken;
 };
-
-/**
- * Merges tokens that use the same speech properties.
- * @param {Array.<cvoxAce.Token>} tokens Tokens to be merged.
- * @return {Array.<cvoxAce.Token>} Merged tokens.
- */
 var mergeLikeTokens = function(tokens) {
   if (tokens.length <= 1) {
     return tokens;
@@ -380,23 +185,11 @@ var mergeLikeTokens = function(tokens) {
   newTokens.push(mergeTokens(tokens, lastLikeIndex, tokens.length));
   return newTokens;
 };
-
-/**
- * Returns if given row is a whitespace row.
- * @param {number} row Row.
- * @return {boolean} True if row is whitespaces.
- */
 var isRowWhiteSpace = function(row) {
   var line = cvoxAce.editor.getSession().getLine(row);
   var whiteSpaceRegexp = /^\s*$/;
   return whiteSpaceRegexp.exec(line) !== null;
 };
-
-/**
- * Speak the line with syntax properties.
- * @param {number} row Row to speak.
- * @param {number} queue Queue mode to speak.
- */
 var speakLine = function(row, queue) {
   var tokens = cvoxAce.editor.getSession().getTokens(row);
   if (tokens.length === 0 || isRowWhiteSpace(row)) {
@@ -405,41 +198,19 @@ var speakLine = function(row, queue) {
   }
   tokens = mergeLikeTokens(tokens);
   var firstToken = tokens[0];
-  /* Filter out first token. */
   tokens = tokens.filter(function(token) {
     return token !== firstToken;
   });
-  /* Speak first token separately to flush if queue. */
   speakToken_(firstToken, queue);
-  /* Speak rest of tokens. */
   tokens.forEach(speakTokenQueue);
 };
-
-/**
- * Speak the token based on the syntax of the token, flushing.
- * @param {!cvoxAce.Token} token Token to speak.
- * @param {number} queue Queue mode.
- */
 var speakTokenFlush = function(token) {
   speakToken_(token, 0);
 };
-
-/**
- * Speak the token based on the syntax of the token, queueing.
- * @param {!cvoxAce.Token} token Token to speak.
- * @param {number} queue Queue mode.
- */
 var speakTokenQueue = function(token) {
   speakToken_(token, 1);
 };
-
-/**
- * @param {!cvoxAce.Token} token Token to speak.
- * Get the token speech property.
- */
 var getTokenRule = function(token) {
-  /* Types are period delimited. In this case, we only syntax speak the outer
-   * most type of token. */
   if (!token || !token.type) {
     return;
   }
@@ -454,13 +225,6 @@ var getTokenRule = function(token) {
   }
   return rule;
 };
-
-/**
- * Speak the token based on the syntax of the token.
- * @private
- * @param {!cvoxAce.Token} token Token to speak.
- * @param {number} queue Queue mode.
- */
 var speakToken_ = function(token, queue) {
   var rule = getTokenRule(token);
   var value = expand(token.value, REPLACE_LIST);
@@ -469,45 +233,19 @@ var speakToken_ = function(token, queue) {
   }
   cvox.Api.speak(value, queue, rule.prop);
 };
-
-/**
- * Speaks the character under the cursor. This is queued.
- * @param {!cvoxAce.Cursor} cursor Current cursor position.
- * @return {string} Character.
- */
 var speakChar = function(cursor) {
   var line = getCurrentLine(cursor);
   cvox.Api.speak(line[cursor.column], 1);
 };
-
-/**
- * Speaks the jump from lastCursor to currCursor. This function assumes the
- * jump takes place on the current line.
- * @param {!cvoxAce.Cursor} lastCursor Previous cursor position.
- * @param {!cvoxAce.Cursor} currCursor Current cursor position.
- */
 var speakDisplacement = function(lastCursor, currCursor) {
   var line = getCurrentLine(currCursor);
-
-  /* Get the text that we jumped past. */
   var displace = line.substring(lastCursor.column, currCursor.column);
-
-  /* Speak out loud spaces. */
   displace = displace.replace(/ /g, ' space ');
   cvox.Api.speak(displace);
 };
-
-/**
- * Speaks the word if the cursor jumped to a new word or to the beginning
- * of the line. Otherwise speak the charactor.
- * @param {!cvoxAce.Cursor} lastCursor Previous cursor position.
- * @param {!cvoxAce.Cursor} currCursor Current cursor position.
- */
 var speakCharOrWordOrLine = function(lastCursor, currCursor) {
-  /* Say word only if jump. */
   if (Math.abs(lastCursor.column - currCursor.column) !== 1) {
     var currLineLength = getCurrentLine(currCursor).length;
-    /* Speak line if jumping to beginning or end of line. */
     if (currCursor.column === 0 || currCursor.column === currLineLength) {
       speakLine(currCursor.row, 0);
       return;
@@ -520,15 +258,6 @@ var speakCharOrWordOrLine = function(lastCursor, currCursor) {
   }
   speakChar(currCursor);
 };
-
-/**
- * Event handler for column changes. If shouldSpeakDisplacement is on, then
- * we just speak displacements in row changes. Otherwise, we either speak
- * the character for single character movements, the word when jumping to the
- * next word, or the entire line if jumping to beginning or end of the line.
- * @param {!cvoxAce.Cursor} lastCursor Previous cursor position.
- * @param {!cvoxAce.Cursor} currCursor Current cursor position.
- */
 var onColumnChange = function(lastCursor, currCursor) {
   if (!cvoxAce.editor.selection.isEmpty()) {
     speakDisplacement(lastCursor, currCursor);
@@ -540,15 +269,7 @@ var onColumnChange = function(lastCursor, currCursor) {
     speakCharOrWordOrLine(lastCursor, currCursor);
   }
 };
-
-/**
- * Event handler for cursor changes. Classify cursor changes as either row or
- * column changes, then delegate accordingly.
- * @param {!Event} evt The event.
- */
 var onCursorChange = function(evt) {
-  /* Do not speak if cursor change was a result of text insertion. We want to
-   * speak the text that was inserted and not where the cursor lands. */
   if (changed) {
     changed = false;
     return;
@@ -561,54 +282,29 @@ var onCursorChange = function(evt) {
   }
   lastCursor = currCursor;
 };
-
-/**
- * Event handler for selection changes.
- * @param {!Event} evt The event.
- */
 var onSelectionChange = function(evt) {
-  /* Assumes that when selection changes to empty, the user has unselected. */
   if (cvoxAce.editor.selection.isEmpty()) {
     cvox.Api.speak('unselected');
   }
 };
-
-/**
- * Event handler for source changes. We want auditory feedback for inserting
- * and deleting text.
- * @param {!Event} evt The event.
- */
 var onChange = function(evt) {
   var data = evt.data;
   switch (data.action) {
   case 'removeText':
     cvox.Api.speak(data.text, 0, DELETED_PROP);
-    /* Let the future cursor change event know it's from text change. */
     changed = true;
     break;
   case 'insertText':
     cvox.Api.speak(data.text, 0);
-    /* Let the future cursor change event know it's from text change. */
     changed = true;
     break;
   }
 };
-
-/**
- * Returns whether or not the annotation is new.
- * @param {!cvoxAce.Annotation} annot Annotation in question.
- * @return {boolean} Whether annot is new.
- */
 var isNewAnnotation = function(annot) {
   var row = annot.row;
   var col = annot.column;
   return !annotTable[row] || !annotTable[row][col];
 };
-
-/**
- * Populates the annotation table.
- * @param {!Array.<cvoxAce.Annotation>} annotations Array of annotations.
- */
 var populateAnnotations = function(annotations) {
   annotTable = {};
   for (var i = 0; i < annotations.length; i++) {
@@ -621,12 +317,6 @@ var populateAnnotations = function(annotations) {
     annotTable[row][col] = annotation;
   }
 };
-
-/**
- * Event handler for annotation changes. We want to notify the user when an
- * a new annotation appears.
- * @param {!Event} evt Event.
- */
 var onAnnotationChange = function(evt) {
   var annotations = cvoxAce.editor.getSession().getAnnotations();
   var newAnnotations = annotations.filter(isNewAnnotation);
@@ -635,58 +325,29 @@ var onAnnotationChange = function(evt) {
   }
   populateAnnotations(annotations);
 };
-
-/**
- * Speak annotation.
- * @param {!cvoxAce.Annotation} annot Annotation to speak.
- */
 var speakAnnot = function(annot) {
   var annotText = annot.type + ' ' + annot.text + ' on ' +
       rowColToString(annot.row, annot.column);
   annotText = annotText.replace(';', 'semicolon');
   cvox.Api.speak(annotText, 1);
 };
-
-/**
- * Speak annotations in a row.
- * @param {number} row Row of annotations to speak.
- */
 var speakAnnotsByRow = function(row) {
   var annots = annotTable[row];
   for (var col in annots) {
     speakAnnot(annots[col]);
   }
 };
-
-/**
- * Get a string representation of a row and column.
- * @param {boolean} row Zero indexed row.
- * @param {boolean} col Zero indexed column.
- * @return {string} Row and column to be spoken.
- */
 var rowColToString = function(row, col) {
   return 'row ' + (row + 1) + ' column ' + (col + 1);
 };
-
-/**
- * Speaks the row and column.
- */
 var speakCurrRowAndCol = function() {
   cvox.Api.speak(rowColToString(lastCursor.row, lastCursor.column));
 };
-
-/**
- * Speaks all annotations.
- */
 var speakAllAnnots = function() {
   for (var row in annotTable) {
     speakAnnotsByRow(row);
   }
 };
-
-/**
- * Speak the vim mode. If no vim mode, this function does nothing.
- */
 var speakMode = function() {
   if (!isVimMode()) {
     return;
@@ -700,38 +361,22 @@ var speakMode = function() {
     break;
   }
 };
-
-/**
- * Toggle speak location.
- */
 var toggleSpeakRowLocation = function() {
   shouldSpeakRowLocation = !shouldSpeakRowLocation;
-  /* Auditory feedback of the change. */
   if (shouldSpeakRowLocation) {
     cvox.Api.speak('Speak location on row change enabled.');
   } else {
     cvox.Api.speak('Speak location on row change disabled.');
   }
 };
-
-/**
- * Toggle speak displacement.
- */
 var toggleSpeakDisplacement = function() {
   shouldSpeakDisplacement = !shouldSpeakDisplacement;
-  /* Auditory feedback of the change. */
   if (shouldSpeakDisplacement) {
     cvox.Api.speak('Speak displacement on column changes.');
   } else {
     cvox.Api.speak('Speak current character or word on column changes.');
   }
 };
-
-/**
- * Event handler for key down events. Gets the right shortcut from the map,
- * and calls the associated function.
- * @param {!Event} evt Keyboard event.
- */
 var onKeyDown = function(evt) {
   if (evt.ctrlKey && evt.shiftKey) {
     var shortcut = keyCodeToShortcutMap[evt.keyCode];
@@ -740,59 +385,34 @@ var onKeyDown = function(evt) {
     }
   }
 };
-
-/**
- * Event handler for status change events. Auditory feedback of changing
- * between vim states.
- * @param {!Event} evt Change status event.
- * @param {!Object} editor Editor state.
- */
 var onChangeStatus = function(evt, editor) {
   if (!isVimMode()) {
     return;
   }
   var state = editor.keyBinding.$data.state;
   if (state === vimState) {
-    /* State hasn't changed, do nothing. */
     return;
   }
   switch (state) {
   case INSERT_MODE_STATE:
     cvox.Api.playEarcon(MODE_SWITCH_EARCON);
-    /* When in insert mode, we want to speak out keys as feedback. */
     cvox.Api.setKeyEcho(true);
     break;
   case COMMAND_MODE_STATE:
     cvox.Api.playEarcon(MODE_SWITCH_EARCON);
-    /* When in command mode, we want don't speak out keys because those keys
-    * are not being inserted in the document. */
     cvox.Api.setKeyEcho(false);
     break;
   }
   vimState = state;
 };
-
-/**
- * Handles context menu events. This is a ChromeVox feature where hitting
- * the shortcut ChromeVox + comma will open up a search bar where you can
- * type in various commands. All keyboard shortcuts are also commands that
- * can be invoked. This handles the event that ChromeVox sends to the page.
- * @param {Event} evt Event received.
- */
 var contextMenuHandler = function(evt) {
   var cmd = evt.detail['customCommand'];
   var shortcut = cmdToShortcutMap[cmd];
   if (shortcut) {
     shortcut.func();
-    /* ChromeVox will bring focus to an element near the cursor instead of the
-     * text input. */
     cvoxAce.editor.focus();
   }
 };
-
-/**
- * Initialize the ChromeVox context menu.
- */
 var initContextMenu = function() {
   var ACTIONS = SHORTCUTS.map(function(shortcut) {
     return {
@@ -800,44 +420,22 @@ var initContextMenu = function() {
       cmd: shortcut.cmd
     };
   });
-
-  /* Attach ContextMenuActions. */
   var body = document.querySelector('body');
   body.setAttribute('contextMenuActions', JSON.stringify(ACTIONS));
-
-  /* Listen for ContextMenu events. */
   body.addEventListener('ATCustomEvent', contextMenuHandler, true);
 };
-
-/**
- * Event handler for find events. When there is a match, we want to speak the
- * line we are now at. Otherwise, we want to notify the user there was no
- * match
- * @param {!Event} evt The event.
- */
 var onFindSearchbox = function(evt) {
   if (evt.match) {
-    /* There is still a match! Speak the line. */
     speakLine(lastCursor.row, 0);
   } else {
-    /* No match, give auditory feedback! */
     cvox.Api.playEarcon(NO_MATCH_EARCON);
   }
 };
-
-/**
- * Focus to text input.
- */
 var focus = function() {
   cvoxAce.editor.focus();
 };
-
-/**
- * Shortcut definitions.
- */
 var SHORTCUTS = [
   {
-    /* 1 key. */
     keyCode: 49,
     func: function() {
       speakAnnotsByRow(lastCursor.row);
@@ -846,56 +444,44 @@ var SHORTCUTS = [
     desc: 'Speak annotations on line'
   },
   {
-    /* 2 key. */
     keyCode: 50,
     func: speakAllAnnots,
     cmd: Command.SPEAK_ALL_ANNOTS,
     desc: 'Speak all annotations'
   },
   {
-    /* 3 key. */
     keyCode: 51,
     func: speakMode,
     cmd: Command.SPEAK_MODE,
     desc: 'Speak Vim mode'
   },
   {
-    /* 4 key. */
     keyCode: 52,
     func: toggleSpeakRowLocation,
     cmd: Command.TOGGLE_LOCATION,
     desc: 'Toggle speak row location'
   },
   {
-    /* 5 key. */
     keyCode: 53,
     func: speakCurrRowAndCol,
     cmd: Command.SPEAK_ROW_COL,
     desc: 'Speak row and column'
   },
   {
-    /* 6 key. */
     keyCode: 54,
     func: toggleSpeakDisplacement,
     cmd: Command.TOGGLE_DISPLACEMENT,
     desc: 'Toggle speak displacement'
   },
   {
-    /* 7 key. */
     keyCode: 55,
     func: focus,
     cmd: Command.FOCUS_TEXT,
     desc: 'Focus text'
   }
 ];
-
-/**
- * Event handler for focus events.
- */
 var onFocus = function() {
   cvoxAce.editor = editor;
-
-  /* Set up listeners. */
   editor.getSession().selection.on('changeCursor', onCursorChange);
   editor.getSession().selection.on('changeSelection', onSelectionChange);
   editor.getSession().on('change', onChange);
@@ -906,53 +492,24 @@ var onFocus = function() {
 
   lastCursor = editor.selection.getCursor();
 };
-
-/**
- * Initialize the theme.
- * @param {Object} editor Editor to use.
- */
 var init = function(editor) {
   onFocus();
-
-  /* Construct maps. */
   SHORTCUTS.forEach(function(shortcut) {
     keyCodeToShortcutMap[shortcut.keyCode] = shortcut;
     cmdToShortcutMap[shortcut.cmd] = shortcut;
   });
 
   editor.on('focus', onFocus);
-
-  /* Assume we start in command mode if vim. */
   if (isVimMode()) {
     cvox.Api.setKeyEcho(false);
   }
   initContextMenu();
 };
-
-/**
- * Returns if cvox exists, and the api exists.
- * @return {boolean} Whether not Cvox Api exists.
- */
 function cvoxApiExists() {
   return (typeof(cvox) !== 'undefined') && cvox && cvox.Api;
 }
-
-/**
- * Number of tries for Cvox loading.
- * @type {number}
- */
 var tries = 0;
-
-/**
- * Max number of tries to watch for Cvox loading.
- * @type {number}
- */
 var MAX_TRIES = 15;
-
-/**
- * Check for ChromeVox load.
- * @param {Object} editor Editor to use.
- */
 function watchForCvoxLoad(editor) {
   if (cvoxApiExists()) {
     init(editor);
@@ -978,3 +535,8 @@ require('../config').defineOptions(Editor.prototype, 'editor', {
 });
 
 });
+;
+                (function() {
+                    window.require(["ace/ext/chromevox"], function() {});
+                })();
+            

+ 7 - 50
services/web/public/js/ace/ext/elastic_tabstops_lite.js → services/web/public/js/ace/ext-elastic_tabstops_lite.js

@@ -1,34 +1,4 @@
-/* ***** 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) {
+define("ace/ext/elastic_tabstops_lite",["require","exports","module","ace/editor","ace/config"], function(require, exports, module) {
 "use strict";
 
 var ElasticTabstopsLite = function(editor) {
@@ -82,8 +52,6 @@ var ElasticTabstopsLite = function(editor) {
 
     this.$findCellWidthsForBlock = function(row) {
         var cellWidths = [], widths;
-
-        // starting row and backward
         var rowIter = row;
         while (rowIter >= 0) {
             widths = this.$cellWidthsForRow(rowIter);
@@ -94,8 +62,6 @@ var ElasticTabstopsLite = function(editor) {
             rowIter--;
         }
         var firstRow = rowIter + 1;
-
-        // forward (not including starting row)
         rowIter = row;
         var numRows = this.$editor.session.getLength();
 
@@ -114,7 +80,6 @@ var ElasticTabstopsLite = function(editor) {
 
     this.$cellWidthsForRow = function(row) {
         var selectionColumns = this.$selectionColumnsForRow(row);
-        // todo: support multicursor
 
         var tabs = [-1].concat(this.$tabsForRow(row));
         var widths = tabs.map(function(el) { return 0; } ).slice(1);
@@ -135,7 +100,6 @@ var ElasticTabstopsLite = function(editor) {
     this.$selectionColumnsForRow = function(row) {
         var selections = [], cursor = this.$editor.getCursorPosition();
         if (this.$editor.session.getSelection().isEmpty()) {
-            // todo: support multicursor
             if (row == cursor.row)
                 selections.push(cursor.column);
         }
@@ -153,8 +117,6 @@ var ElasticTabstopsLite = function(editor) {
                 console.error(column);
                 continue;
             }
-            // add an extra None to the end so that the end of the column automatically
-            // finishes a block
             column.push(NaN);
 
             for (var r = 0, s = column.length; r < s; r++) {
@@ -165,7 +127,6 @@ var ElasticTabstopsLite = function(editor) {
                     startingNewBlock = false;
                 }
                 if (isNaN(width)) {
-                    // block ended
                     blockEndRow = r;
 
                     for (var j = blockStartRow; j < blockEndRow; j++) {
@@ -216,8 +177,6 @@ var ElasticTabstopsLite = function(editor) {
             return;
 
         var bias = 0, location = -1;
-
-        // this always only contains two elements, so we're safe in the loop below
         var expandedSet = this.$izip(widths, rowTabs);
 
         for (var i = 0, l = expandedSet.length; i < l; i++) {
@@ -234,8 +193,6 @@ var ElasticTabstopsLite = function(editor) {
             var ispaces = partialLine.length - strippedPartialLine.length;
 
             if (difference > 0) {
-                // put the spaces after the tab and then delete the tab, so any insertion
-                // points behave as expected
                 this.$editor.session.getDocument().insertInLine({row: row, column: it + 1}, Array(difference + 1).join(" ") + "\t");
                 this.$editor.session.getDocument().removeInLine(row, it, it + 1);
 
@@ -248,8 +205,6 @@ var ElasticTabstopsLite = function(editor) {
             }
         }
     };
-
-    // the is a (naive) Python port--but works for these purposes
     this.$izip_longest = function(iterables) {
         if (!iterables[0])
             return [];
@@ -279,10 +234,7 @@ var ElasticTabstopsLite = function(editor) {
 
         return expandedSet;
     };
-
-    // an even more (naive) Python port
     this.$izip = function(widths, tabs) {
-        // grab the shorter size
         var size = widths.length >= tabs.length ? tabs.length : widths.length;
 
         var expandedSet = [];
@@ -316,4 +268,9 @@ require("../config").defineOptions(Editor.prototype, "editor", {
     }
 });
 
-});
+});
+;
+                (function() {
+                    window.require(["ace/ext/elastic_tabstops_lite"], function() {});
+                })();
+            

+ 417 - 93
services/web/public/js/ace/snippets.js → services/web/public/js/ace/ext-emmet.js

@@ -1,37 +1,10 @@
-/* ***** 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) {
+define("ace/snippets",["require","exports","module","ace/lib/oop","ace/lib/event_emitter","ace/lib/lang","ace/range","ace/anchor","ace/keyboard/hash_handler","ace/tokenizer","ace/lib/dom","ace/editor"], function(require, exports, module) {
 "use strict";
-var lang = require("./lib/lang")
-var Range = require("./range").Range
+var oop = require("./lib/oop");
+var EventEmitter = require("./lib/event_emitter").EventEmitter;
+var lang = require("./lib/lang");
+var Range = require("./range").Range;
+var Anchor = require("./anchor").Anchor;
 var HashHandler = require("./keyboard/hash_handler").HashHandler;
 var Tokenizer = require("./tokenizer").Tokenizer;
 var comparePoints = Range.comparePoints;
@@ -42,12 +15,14 @@ var SnippetManager = function() {
 };
 
 (function() {
+    oop.implement(this, EventEmitter);
+    
     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}]
+            return [{text: str}];
         }
         function escape(ch) {
             return "(?:[^\\\\" + ch + "]|\\\\.)";
@@ -125,7 +100,7 @@ var SnippetManager = function() {
         });
         SnippetManager.prototype.getTokenizer = function() {
             return SnippetManager.$tokenizer;
-        }
+        };
         return SnippetManager.$tokenizer;
     };
 
@@ -166,10 +141,9 @@ var SnippetManager = function() {
                 return s.getUseSoftTabs() ? "YES" : "NO";
             case "TAB_SIZE":
                 return s.getTabSize();
-            // defult but can't fill :(
             case "FILENAME":
             case "FILEPATH":
-                return "ace.ajax.org";
+                return "";
             case "FULLNAME":
                 return "Ace";
         }
@@ -180,8 +154,6 @@ var SnippetManager = function() {
             return this.variables[varName](editor, varName) || "";
         return this.$getDefaultValue(editor, varName) || "";
     };
-
-    // returns string formatted according to http://manual.macromates.com/en/regular_expressions#replacement_string_syntax_format_strings
     this.tmStrFormat = function(str, ch, editor) {
         var flag = ch.flag || "";
         var re = ch.guard;
@@ -262,15 +234,17 @@ var SnippetManager = function() {
         return result;
     };
 
-    this.insertSnippet = function(editor, snippetText) {
+    this.insertSnippetForSelection = 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 indentString = line.match(/^\s*/)[0];
+        
+        if (cursor.column < indentString.length)
+            indentString = indentString.slice(0, cursor.column);
 
         var tokens = this.tokenizeTmSnippet(snippetText);
         tokens = this.resolveVariables(tokens, editor);
-        // indent
         tokens = tokens.map(function(x) {
             if (x == "\n")
                 return x + indentString;
@@ -278,7 +252,6 @@ var SnippetManager = function() {
                 return x.replace(/\t/g, tabString);
             return x;
         });
-        // tabstop values
         var tabstops = [];
         tokens.forEach(function(p, i) {
             if (typeof p != "object")
@@ -305,12 +278,10 @@ var SnippetManager = function() {
                 ts.value = value.join("");
             }
         });
-
-        // expand tabstop values
         tabstops.forEach(function(ts) {ts.length = 0});
         var expanding = {};
         function copyValue(val) {
-            var copy = []
+            var copy = [];
             for (var i = 0; i < val.length; i++) {
                 var p = val[i];
                 if (typeof p == "object") {
@@ -329,8 +300,9 @@ var SnippetManager = function() {
                 continue;
             var id = p.tabstopId;
             var i1 = tokens.indexOf(p, i + 1);
-            if (expanding[id] == p) { 
-                expanding[id] = null;
+            if (expanding[id]) {
+                if (expanding[id] === p)
+                    expanding[id] = null;
                 continue;
             }
             
@@ -343,9 +315,7 @@ var SnippetManager = function() {
 
             if (ts.indexOf(p) === -1)
                 ts.push(p);
-        };
-        
-        // convert to plain text
+        }
         var row = 0, column = 0;
         var text = "";
         tokens.forEach(function(t) {
@@ -367,18 +337,30 @@ var SnippetManager = function() {
         var end = editor.session.replace(range, text);
 
         var tabstopManager = new TabstopManager(editor);
-        tabstopManager.addTabstops(tabstops, range.start, end);
-        tabstopManager.tabNext();
+        var selectionId = editor.inVirtualSelectionMode && editor.selection.index;
+        tabstopManager.addTabstops(tabstops, range.start, end, selectionId);
+    };
+    
+    this.insertSnippet = function(editor, snippetText) {
+        var self = this;
+        if (editor.inVirtualSelectionMode)
+            return self.insertSnippetForSelection(editor, snippetText);
+        
+        editor.forEachSelection(function() {
+            self.insertSnippetForSelection(editor, snippetText);
+        }, null, {keepOrder: true});
+        
+        if (editor.tabstopManager)
+            editor.tabstopManager.tabNext();
     };
 
     this.$getScope = function(editor) {
         var scope = editor.session.$mode.$id || "";
         scope = scope.split("/").pop();
         if (scope === "html" || scope === "php") {
-            // PHP is actually HTML
-            if (scope === "php") 
+            if (scope === "php" && !editor.session.$mode.inlinePhp) 
                 scope = "html";
-            var c = editor.getCursorPosition()
+            var c = editor.getCursorPosition();
             var state = editor.session.getState(c.row);
             if (typeof state === "object") {
                 state = state[0];
@@ -396,16 +378,36 @@ var SnippetManager = function() {
         return scope;
     };
 
-    this.expandWithTab = function(editor) {
+    this.getActiveScopes = function(editor) {
+        var scope = this.$getScope(editor);
+        var scopes = [scope];
+        var snippetMap = this.snippetMap;
+        if (snippetMap[scope] && snippetMap[scope].includeScopes) {
+            scopes.push.apply(scopes, snippetMap[scope].includeScopes);
+        }
+        scopes.push("_");
+        return scopes;
+    };
+
+    this.expandWithTab = function(editor, options) {
+        var self = this;
+        var result = editor.forEachSelection(function() {
+            return self.expandSnippetForSelection(editor, options);
+        }, null, {keepOrder: true});
+        if (result && editor.tabstopManager)
+            editor.tabstopManager.tabNext();
+        return result;
+    };
+    
+    this.expandSnippetForSelection = function(editor, options) {
         var cursor = editor.getCursorPosition();
         var line = editor.session.getLine(cursor.row);
         var before = line.substring(0, cursor.column);
         var after = line.substr(cursor.column);
 
-        var scope = this.$getScope(editor);
         var snippetMap = this.snippetMap;
         var snippet;
-        [scope, "_"].some(function(scope) {
+        this.getActiveScopes(editor).some(function(scope) {
             var snippets = snippetMap[scope];
             if (snippets)
                 snippet = this.findMatchingSnippet(snippets, before, after);
@@ -413,7 +415,8 @@ var SnippetManager = function() {
         }, this);
         if (!snippet)
             return false;
-
+        if (options && options.dryRun)
+            return true;
         editor.session.doc.removeInLine(cursor.row,
             cursor.column - snippet.replaceBefore.length,
             cursor.column + snippet.replaceAfter.length
@@ -421,7 +424,7 @@ var SnippetManager = function() {
 
         this.variables.M__ = snippet.matchBefore;
         this.variables.T__ = snippet.matchAfter;
-        this.insertSnippet(editor, snippet.content);
+        this.insertSnippetForSelection(editor, snippet.content);
 
         this.variables.M__ = this.variables.T__ = null;
         return true;
@@ -453,7 +456,7 @@ var SnippetManager = function() {
         var self = this;
         function wrapRegexp(src) {
             if (src && !/^\^?\(.*\)\$?$|^\\b$/.test(src))
-                src = "(?:" + src + ")"
+                src = "(?:" + src + ")";
 
             return src || "";
         }
@@ -475,7 +478,7 @@ var SnippetManager = function() {
         function addSnippet(s) {
             if (!s.scope)
                 s.scope = scope || "_";
-            scope = s.scope
+            scope = s.scope;
             if (!snippetMap[scope]) {
                 snippetMap[scope] = [];
                 snippetNameMap[scope] = {};
@@ -501,12 +504,14 @@ var SnippetManager = function() {
 
             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._signal("registerSnippets", {scope: scope});
     };
     this.unregister = function(snippets, scope) {
         var snippetMap = this.snippetMap;
@@ -535,7 +540,7 @@ var SnippetManager = function() {
         while (m = re.exec(str)) {
             if (m[1]) {
                 try {
-                    snippet = JSON.parse(m[1])
+                    snippet = JSON.parse(m[1]);
                     list.push(snippet);
                 } catch (e) {}
             } if (m[4]) {
@@ -562,10 +567,9 @@ var SnippetManager = function() {
         return list;
     };
     this.getSnippetByName = function(name, editor) {
-        var scope = editor && this.$getScope(editor);
         var snippetMap = this.snippetNameMap;
         var snippet;
-        [scope, "_"].some(function(scope) {
+        this.getActiveScopes(editor).some(function(scope) {
             var snippets = snippetMap[scope];
             if (snippets)
                 snippet = snippets[name];
@@ -589,9 +593,10 @@ var TabstopManager = function(editor) {
 };
 (function() {
     this.attach = function(editor) {
-        this.index = -1;
+        this.index = 0;
         this.ranges = [];
         this.tabstops = [];
+        this.$openTabstops = null;
         this.selectedTabstop = null;
 
         this.editor = editor;
@@ -631,7 +636,7 @@ var TabstopManager = function(editor) {
         }
         if (!this.$inChange && isRemove) {
             var ts = this.selectedTabstop;
-            var changedOutside = !ts.some(function(r) {
+            var changedOutside = ts && !ts.some(function(r) {
                 return comparePoints(r.start, start) <= 0 && comparePoints(r.end, end) >= 0;
             });
             if (changedOutside)
@@ -643,7 +648,7 @@ var TabstopManager = function(editor) {
             if (r.end.row < start.row)
                 continue;
 
-            if (comparePoints(start, r.start) < 0 && comparePoints(end, r.end) > 0) {
+            if (isRemove && comparePoints(start, r.start) < 0 && comparePoints(end, r.end) > 0) {
                 this.removeRange(r);
                 i--;
                 continue;
@@ -666,7 +671,7 @@ var TabstopManager = function(editor) {
     };
     this.updateLinkedFields = function() {
         var ts = this.selectedTabstop;
-        if (!ts.hasLinkedRanges)
+        if (!ts || !ts.hasLinkedRanges)
             return;
         this.$inChange = true;
         var session = this.editor.session;
@@ -675,7 +680,7 @@ var TabstopManager = function(editor) {
             var range = ts[i];
             if (!range.linked)
                 continue;
-            var fmt = exports.snippetManager.tmStrFormat(text, range.original)
+            var fmt = exports.snippetManager.tmStrFormat(text, range.original);
             session.replace(range, fmt);
         }
         this.$inChange = false;
@@ -686,7 +691,7 @@ var TabstopManager = function(editor) {
     };
     this.onChangeSelection = function() {
         if (!this.editor)
-            return
+            return;
         var lead = this.editor.selection.lead;
         var anchor = this.editor.selection.anchor;
         var isEmpty = this.editor.selection.isEmpty();
@@ -704,14 +709,17 @@ var TabstopManager = function(editor) {
         this.detach();
     };
     this.tabNext = function(dir) {
-        var max = this.tabstops.length - 1;
+        var max = this.tabstops.length;
         var index = this.index + (dir || 1);
-        index = Math.min(Math.max(index, 0), max);
-        this.selectTabstop(index);
+        index = Math.min(Math.max(index, 1), max);
         if (index == max)
+            index = 0;
+        this.selectTabstop(index);
+        if (index === 0)
             this.detach();
     };
     this.selectTabstop = function(index) {
+        this.$openTabstops = null;
         var ts = this.tabstops[this.index];
         if (ts)
             this.addTabstopMarkers(ts);
@@ -729,6 +737,8 @@ var TabstopManager = function(editor) {
                     continue;
                 sel.addRange(ts[i].clone(), true);
             }
+            if (sel.ranges[0])
+                sel.addRange(sel.ranges[0].clone());
         } else {
             this.editor.selection.setRange(ts.firstNonLinked);
         }
@@ -736,7 +746,8 @@ var TabstopManager = function(editor) {
         this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler);
     };
     this.addTabstops = function(tabstops, start, end) {
-        // add final tabstop if missing
+        if (!this.$openTabstops)
+            this.$openTabstops = [];
         if (!tabstops[0]) {
             var p = Range.fromPoints(end, end);
             moveRelative(p.start, start);
@@ -746,33 +757,43 @@ var TabstopManager = function(editor) {
         }
 
         var i = this.index;
-        var arg = [i, 0];
+        var arg = [i + 1, 0];
         var ranges = this.ranges;
-        var editor = this.editor;
-        tabstops.forEach(function(ts) {
+        tabstops.forEach(function(ts, index) {
+            var dest = this.$openTabstops[index] || ts;
+                
             for (var i = ts.length; i--;) {
                 var p = ts[i];
                 var range = Range.fromPoints(p.start, p.end || p.start);
                 movePoint(range.start, start);
                 movePoint(range.end, start);
                 range.original = p;
-                range.tabstop = ts;
+                range.tabstop = dest;
                 ranges.push(range);
-                ts[i] = range;
+                if (dest != ts)
+                    dest.unshift(range);
+                else
+                    dest[i] = range;
                 if (p.fmtString) {
                     range.linked = true;
-                    ts.hasLinkedRanges = true;
-                } else if (!ts.firstNonLinked)
-                    ts.firstNonLinked = range;
+                    dest.hasLinkedRanges = true;
+                } else if (!dest.firstNonLinked)
+                    dest.firstNonLinked = range;
             }
-            if (!ts.firstNonLinked)
-                ts.hasLinkedRanges = false;
-            arg.push(ts);
-            this.addTabstopMarkers(ts);
+            if (!dest.firstNonLinked)
+                dest.hasLinkedRanges = false;
+            if (dest === ts) {
+                arg.push(dest);
+                this.$openTabstops[index] = dest;
+            }
+            this.addTabstopMarkers(dest);
         }, this);
-        // tabstop 0 is the last one
-        arg.push(arg.splice(2, 1)[0]);
-        this.tabstops.splice.apply(this.tabstops, arg);
+        
+        if (arg.length > 2) {
+            if (this.tabstops.length)
+                arg.push(arg.splice(2, 1)[0]);
+            this.tabstops.splice.apply(this.tabstops, arg);
+        }
     };
 
     this.addTabstopMarkers = function(ts) {
@@ -795,11 +816,22 @@ var TabstopManager = function(editor) {
         i = this.ranges.indexOf(range);
         this.ranges.splice(i, 1);
         this.editor.session.removeMarker(range.markerId);
+        if (!range.tabstop.length) {
+            i = this.tabstops.indexOf(range.tabstop);
+            if (i != -1)
+                this.tabstops.splice(i, 1);
+            if (!this.tabstops.length)
+                this.detach();
+        }
     };
 
     this.keyboardHandler = new HashHandler();
     this.keyboardHandler.bindKeys({
         "Tab": function(ed) {
+            if (exports.snippetManager && exports.snippetManager.expandWithTab(ed)) {
+                return;
+            }
+
             ed.tabstopManager.tabNext(1);
         },
         "Shift-Tab": function(ed) {
@@ -809,13 +841,25 @@ var TabstopManager = function(editor) {
             ed.tabstopManager.detach();
         },
         "Return": function(ed) {
-            //ed.tabstopManager.tabNext(1);
             return false;
         }
     });
 }).call(TabstopManager.prototype);
 
 
+
+var changeTracker = {};
+changeTracker.onChange = Anchor.prototype.onChange;
+changeTracker.setPosition = function(row, column) {
+    this.pos.row = row;
+    this.pos.column = column;
+};
+changeTracker.update = function(pos, delta, $insertRight) {
+    this.$insertRight = $insertRight;
+    this.pos = pos; 
+    this.onChange(delta);
+};
+
 var movePoint = function(point, diff) {
     if (point.row == 0)
         point.column += diff.column;
@@ -841,4 +885,284 @@ require("./lib/dom").importCssString("\
 exports.snippetManager = new SnippetManager();
 
 
+var Editor = require("./editor").Editor;
+(function() {
+    this.insertSnippet = function(content, options) {
+        return exports.snippetManager.insertSnippet(this, content, options);
+    };
+    this.expandSnippet = function(options) {
+        return exports.snippetManager.expandWithTab(this, options);
+    };
+}).call(Editor.prototype);
+
+});
+
+define("ace/ext/emmet",["require","exports","module","ace/keyboard/hash_handler","ace/editor","ace/snippets","ace/range","resources","resources","range","tabStops","resources","utils","actions","ace/config"], function(require, exports, module) {
+"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);
+};
+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.selection.moveToPosition(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);
+        result = false
+    }
+    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;};
 });
+;
+                (function() {
+                    window.require(["ace/ext/emmet"], function() {});
+                })();
+            

+ 6 - 0
services/web/public/js/ace/ext-error_marker.js

@@ -0,0 +1,6 @@
+
+;
+                (function() {
+                    window.require(["ace/ext/error_marker"], function() {});
+                })();
+            

+ 180 - 0
services/web/public/js/ace/ext-keybinding_menu.js

@@ -0,0 +1,180 @@
+define("ace/ext/menu_tools/overlay_page",["require","exports","module","ace/lib/dom"], function(require, exports, module) {
+'use strict';
+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) {
+"use strict";
+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;
+};
+
+});
+
+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) {
+    "use strict";
+    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();
+            }
+        }]);
+    };
+
+});
+;
+                (function() {
+                    window.require(["ace/ext/keybinding_menu"], function() {});
+                })();
+            

+ 1822 - 0
services/web/public/js/ace/ext-language_tools.js

@@ -0,0 +1,1822 @@
+define("ace/snippets",["require","exports","module","ace/lib/oop","ace/lib/event_emitter","ace/lib/lang","ace/range","ace/anchor","ace/keyboard/hash_handler","ace/tokenizer","ace/lib/dom","ace/editor"], function(require, exports, module) {
+"use strict";
+var oop = require("./lib/oop");
+var EventEmitter = require("./lib/event_emitter").EventEmitter;
+var lang = require("./lib/lang");
+var Range = require("./range").Range;
+var Anchor = require("./anchor").Anchor;
+var HashHandler = require("./keyboard/hash_handler").HashHandler;
+var Tokenizer = require("./tokenizer").Tokenizer;
+var comparePoints = Range.comparePoints;
+
+var SnippetManager = function() {
+    this.snippetMap = {};
+    this.snippetNameMap = {};
+};
+
+(function() {
+    oop.implement(this, EventEmitter);
+    
+    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 "";
+            case "FULLNAME":
+                return "Ace";
+        }
+    };
+    this.variables = {};
+    this.getVariableValue = function(editor, varName) {
+        if (this.variables.hasOwnProperty(varName))
+            return this.variables[varName](editor, varName) || "";
+        return this.$getDefaultValue(editor, varName) || "";
+    };
+    this.tmStrFormat = function(str, ch, editor) {
+        var flag = ch.flag || "";
+        var re = ch.guard;
+        re = new RegExp(re, flag.replace(/[^gi]/, ""));
+        var fmtTokens = this.tokenizeTmSnippet(ch.fmt, "formatString");
+        var _self = this;
+        var formatted = str.replace(re, function() {
+            _self.variables.__ = arguments;
+            var fmtParts = _self.resolveVariables(fmtTokens, editor);
+            var gChangeCase = "E";
+            for (var i  = 0; i < fmtParts.length; i++) {
+                var ch = fmtParts[i];
+                if (typeof ch == "object") {
+                    fmtParts[i] = "";
+                    if (ch.changeCase && ch.local) {
+                        var next = fmtParts[i + 1];
+                        if (next && typeof next == "string") {
+                            if (ch.changeCase == "u")
+                                fmtParts[i] = next[0].toUpperCase();
+                            else
+                                fmtParts[i] = next[0].toLowerCase();
+                            fmtParts[i + 1] = next.substr(1);
+                        }
+                    } else if (ch.changeCase) {
+                        gChangeCase = ch.changeCase;
+                    }
+                } else if (gChangeCase == "U") {
+                    fmtParts[i] = ch.toUpperCase();
+                } else if (gChangeCase == "L") {
+                    fmtParts[i] = ch.toLowerCase();
+                }
+            }
+            return fmtParts.join("");
+        });
+        this.variables.__ = null;
+        return formatted;
+    };
+
+    this.resolveVariables = function(snippet, editor) {
+        var result = [];
+        for (var i = 0; i < snippet.length; i++) {
+            var ch = snippet[i];
+            if (typeof ch == "string") {
+                result.push(ch);
+            } else if (typeof ch != "object") {
+                continue;
+            } else if (ch.skip) {
+                gotoNext(ch);
+            } else if (ch.processed < i) {
+                continue;
+            } else if (ch.text) {
+                var value = this.getVariableValue(editor, ch.text);
+                if (value && ch.fmtString)
+                    value = this.tmStrFormat(value, ch);
+                ch.processed = i;
+                if (ch.expectIf == null) {
+                    if (value) {
+                        result.push(value);
+                        gotoNext(ch);
+                    }
+                } else {
+                    if (value) {
+                        ch.skip = ch.elseBranch;
+                    } else
+                        gotoNext(ch);
+                }
+            } else if (ch.tabstopId != null) {
+                result.push(ch);
+            } else if (ch.changeCase != null) {
+                result.push(ch);
+            }
+        }
+        function gotoNext(ch) {
+            var i1 = snippet.indexOf(ch, i + 1);
+            if (i1 != -1)
+                i = i1;
+        }
+        return result;
+    };
+
+    this.insertSnippetForSelection = function(editor, snippetText) {
+        var cursor = editor.getCursorPosition();
+        var line = editor.session.getLine(cursor.row);
+        var tabString = editor.session.getTabString();
+        var indentString = line.match(/^\s*/)[0];
+        
+        if (cursor.column < indentString.length)
+            indentString = indentString.slice(0, cursor.column);
+
+        var tokens = this.tokenizeTmSnippet(snippetText);
+        tokens = this.resolveVariables(tokens, editor);
+        tokens = tokens.map(function(x) {
+            if (x == "\n")
+                return x + indentString;
+            if (typeof x == "string")
+                return x.replace(/\t/g, tabString);
+            return x;
+        });
+        var tabstops = [];
+        tokens.forEach(function(p, i) {
+            if (typeof p != "object")
+                return;
+            var id = p.tabstopId;
+            var ts = tabstops[id];
+            if (!ts) {
+                ts = tabstops[id] = [];
+                ts.index = id;
+                ts.value = "";
+            }
+            if (ts.indexOf(p) !== -1)
+                return;
+            ts.push(p);
+            var i1 = tokens.indexOf(p, i + 1);
+            if (i1 === -1)
+                return;
+
+            var value = tokens.slice(i + 1, i1);
+            var isNested = value.some(function(t) {return typeof t === "object"});          
+            if (isNested && !ts.value) {
+                ts.value = value;
+            } else if (value.length && (!ts.value || typeof ts.value !== "string")) {
+                ts.value = value.join("");
+            }
+        });
+        tabstops.forEach(function(ts) {ts.length = 0});
+        var expanding = {};
+        function copyValue(val) {
+            var copy = [];
+            for (var i = 0; i < val.length; i++) {
+                var p = val[i];
+                if (typeof p == "object") {
+                    if (expanding[p.tabstopId])
+                        continue;
+                    var j = val.lastIndexOf(p, i - 1);
+                    p = copy[j] || {tabstopId: p.tabstopId};
+                }
+                copy[i] = p;
+            }
+            return copy;
+        }
+        for (var i = 0; i < tokens.length; i++) {
+            var p = tokens[i];
+            if (typeof p != "object")
+                continue;
+            var id = p.tabstopId;
+            var i1 = tokens.indexOf(p, i + 1);
+            if (expanding[id]) {
+                if (expanding[id] === p)
+                    expanding[id] = null;
+                continue;
+            }
+            
+            var ts = tabstops[id];
+            var arg = typeof ts.value == "string" ? [ts.value] : copyValue(ts.value);
+            arg.unshift(i + 1, Math.max(0, i1 - i));
+            arg.push(p);
+            expanding[id] = p;
+            tokens.splice.apply(tokens, arg);
+
+            if (ts.indexOf(p) === -1)
+                ts.push(p);
+        }
+        var row = 0, column = 0;
+        var text = "";
+        tokens.forEach(function(t) {
+            if (typeof t === "string") {
+                if (t[0] === "\n"){
+                    column = t.length - 1;
+                    row ++;
+                } else
+                    column += t.length;
+                text += t;
+            } else {
+                if (!t.start)
+                    t.start = {row: row, column: column};
+                else
+                    t.end = {row: row, column: column};
+            }
+        });
+        var range = editor.getSelectionRange();
+        var end = editor.session.replace(range, text);
+
+        var tabstopManager = new TabstopManager(editor);
+        var selectionId = editor.inVirtualSelectionMode && editor.selection.index;
+        tabstopManager.addTabstops(tabstops, range.start, end, selectionId);
+    };
+    
+    this.insertSnippet = function(editor, snippetText) {
+        var self = this;
+        if (editor.inVirtualSelectionMode)
+            return self.insertSnippetForSelection(editor, snippetText);
+        
+        editor.forEachSelection(function() {
+            self.insertSnippetForSelection(editor, snippetText);
+        }, null, {keepOrder: true});
+        
+        if (editor.tabstopManager)
+            editor.tabstopManager.tabNext();
+    };
+
+    this.$getScope = function(editor) {
+        var scope = editor.session.$mode.$id || "";
+        scope = scope.split("/").pop();
+        if (scope === "html" || scope === "php") {
+            if (scope === "php" && !editor.session.$mode.inlinePhp) 
+                scope = "html";
+            var c = editor.getCursorPosition();
+            var state = editor.session.getState(c.row);
+            if (typeof state === "object") {
+                state = state[0];
+            }
+            if (state.substring) {
+                if (state.substring(0, 3) == "js-")
+                    scope = "javascript";
+                else if (state.substring(0, 4) == "css-")
+                    scope = "css";
+                else if (state.substring(0, 4) == "php-")
+                    scope = "php";
+            }
+        }
+        
+        return scope;
+    };
+
+    this.getActiveScopes = function(editor) {
+        var scope = this.$getScope(editor);
+        var scopes = [scope];
+        var snippetMap = this.snippetMap;
+        if (snippetMap[scope] && snippetMap[scope].includeScopes) {
+            scopes.push.apply(scopes, snippetMap[scope].includeScopes);
+        }
+        scopes.push("_");
+        return scopes;
+    };
+
+    this.expandWithTab = function(editor, options) {
+        var self = this;
+        var result = editor.forEachSelection(function() {
+            return self.expandSnippetForSelection(editor, options);
+        }, null, {keepOrder: true});
+        if (result && editor.tabstopManager)
+            editor.tabstopManager.tabNext();
+        return result;
+    };
+    
+    this.expandSnippetForSelection = function(editor, options) {
+        var cursor = editor.getCursorPosition();
+        var line = editor.session.getLine(cursor.row);
+        var before = line.substring(0, cursor.column);
+        var after = line.substr(cursor.column);
+
+        var snippetMap = this.snippetMap;
+        var snippet;
+        this.getActiveScopes(editor).some(function(scope) {
+            var snippets = snippetMap[scope];
+            if (snippets)
+                snippet = this.findMatchingSnippet(snippets, before, after);
+            return !!snippet;
+        }, this);
+        if (!snippet)
+            return false;
+        if (options && options.dryRun)
+            return true;
+        editor.session.doc.removeInLine(cursor.row,
+            cursor.column - snippet.replaceBefore.length,
+            cursor.column + snippet.replaceAfter.length
+        );
+
+        this.variables.M__ = snippet.matchBefore;
+        this.variables.T__ = snippet.matchAfter;
+        this.insertSnippetForSelection(editor, snippet.content);
+
+        this.variables.M__ = this.variables.T__ = null;
+        return true;
+    };
+
+    this.findMatchingSnippet = function(snippetList, before, after) {
+        for (var i = snippetList.length; i--;) {
+            var s = snippetList[i];
+            if (s.startRe && !s.startRe.test(before))
+                continue;
+            if (s.endRe && !s.endRe.test(after))
+                continue;
+            if (!s.startRe && !s.endRe)
+                continue;
+
+            s.matchBefore = s.startRe ? s.startRe.exec(before) : [""];
+            s.matchAfter = s.endRe ? s.endRe.exec(after) : [""];
+            s.replaceBefore = s.triggerRe ? s.triggerRe.exec(before)[0] : "";
+            s.replaceAfter = s.endTriggerRe ? s.endTriggerRe.exec(after)[0] : "";
+            return s;
+        }
+    };
+
+    this.snippetMap = {};
+    this.snippetNameMap = {};
+    this.register = function(snippets, scope) {
+        var snippetMap = this.snippetMap;
+        var snippetNameMap = this.snippetNameMap;
+        var self = this;
+        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._signal("registerSnippets", {scope: scope});
+    };
+    this.unregister = function(snippets, scope) {
+        var snippetMap = this.snippetMap;
+        var snippetNameMap = this.snippetNameMap;
+
+        function removeSnippet(s) {
+            var nameMap = snippetNameMap[s.scope||scope];
+            if (nameMap && nameMap[s.name]) {
+                delete nameMap[s.name];
+                var map = snippetMap[s.scope||scope];
+                var i = map && map.indexOf(s);
+                if (i >= 0)
+                    map.splice(i, 1);
+            }
+        }
+        if (snippets.content)
+            removeSnippet(snippets);
+        else if (Array.isArray(snippets))
+            snippets.forEach(removeSnippet);
+    };
+    this.parseSnippetFile = function(str) {
+        str = str.replace(/\r/g, "");
+        var list = [], snippet = {};
+        var re = /^#.*|^({[\s\S]*})\s*$|^(\S+) (.*)$|^((?:\n*\t.*)+)/gm;
+        var m;
+        while (m = re.exec(str)) {
+            if (m[1]) {
+                try {
+                    snippet = JSON.parse(m[1]);
+                    list.push(snippet);
+                } catch (e) {}
+            } if (m[4]) {
+                snippet.content = m[4].replace(/^\t/gm, "");
+                list.push(snippet);
+                snippet = {};
+            } else {
+                var key = m[2], val = m[3];
+                if (key == "regex") {
+                    var guardRe = /\/((?:[^\/\\]|\\.)*)|$/g;
+                    snippet.guard = guardRe.exec(val)[1];
+                    snippet.trigger = guardRe.exec(val)[1];
+                    snippet.endTrigger = guardRe.exec(val)[1];
+                    snippet.endGuard = guardRe.exec(val)[1];
+                } else if (key == "snippet") {
+                    snippet.tabTrigger = val.match(/^\S*/)[0];
+                    if (!snippet.name)
+                        snippet.name = val;
+                } else {
+                    snippet[key] = val;
+                }
+            }
+        }
+        return list;
+    };
+    this.getSnippetByName = function(name, editor) {
+        var snippetMap = this.snippetNameMap;
+        var snippet;
+        this.getActiveScopes(editor).some(function(scope) {
+            var snippets = snippetMap[scope];
+            if (snippets)
+                snippet = snippets[name];
+            return !!snippet;
+        }, this);
+        return snippet;
+    };
+
+}).call(SnippetManager.prototype);
+
+
+var TabstopManager = function(editor) {
+    if (editor.tabstopManager)
+        return editor.tabstopManager;
+    editor.tabstopManager = this;
+    this.$onChange = this.onChange.bind(this);
+    this.$onChangeSelection = lang.delayedCall(this.onChangeSelection.bind(this)).schedule;
+    this.$onChangeSession = this.onChangeSession.bind(this);
+    this.$onAfterExec = this.onAfterExec.bind(this);
+    this.attach(editor);
+};
+(function() {
+    this.attach = function(editor) {
+        this.index = 0;
+        this.ranges = [];
+        this.tabstops = [];
+        this.$openTabstops = null;
+        this.selectedTabstop = null;
+
+        this.editor = editor;
+        this.editor.on("change", this.$onChange);
+        this.editor.on("changeSelection", this.$onChangeSelection);
+        this.editor.on("changeSession", this.$onChangeSession);
+        this.editor.commands.on("afterExec", this.$onAfterExec);
+        this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler);
+    };
+    this.detach = function() {
+        this.tabstops.forEach(this.removeTabstopMarkers, this);
+        this.ranges = null;
+        this.tabstops = null;
+        this.selectedTabstop = null;
+        this.editor.removeListener("change", this.$onChange);
+        this.editor.removeListener("changeSelection", this.$onChangeSelection);
+        this.editor.removeListener("changeSession", this.$onChangeSession);
+        this.editor.commands.removeListener("afterExec", this.$onAfterExec);
+        this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler);
+        this.editor.tabstopManager = null;
+        this.editor = null;
+    };
+
+    this.onChange = function(e) {
+        var changeRange = e.data.range;
+        var isRemove = e.data.action[0] == "r";
+        var start = changeRange.start;
+        var end = changeRange.end;
+        var startRow = start.row;
+        var endRow = end.row;
+        var lineDif = endRow - startRow;
+        var colDiff = end.column - start.column;
+
+        if (isRemove) {
+            lineDif = -lineDif;
+            colDiff = -colDiff;
+        }
+        if (!this.$inChange && isRemove) {
+            var ts = this.selectedTabstop;
+            var changedOutside = ts && !ts.some(function(r) {
+                return comparePoints(r.start, start) <= 0 && comparePoints(r.end, end) >= 0;
+            });
+            if (changedOutside)
+                return this.detach();
+        }
+        var ranges = this.ranges;
+        for (var i = 0; i < ranges.length; i++) {
+            var r = ranges[i];
+            if (r.end.row < start.row)
+                continue;
+
+            if (isRemove && comparePoints(start, r.start) < 0 && comparePoints(end, r.end) > 0) {
+                this.removeRange(r);
+                i--;
+                continue;
+            }
+
+            if (r.start.row == startRow && r.start.column > start.column)
+                r.start.column += colDiff;
+            if (r.end.row == startRow && r.end.column >= start.column)
+                r.end.column += colDiff;
+            if (r.start.row >= startRow)
+                r.start.row += lineDif;
+            if (r.end.row >= startRow)
+                r.end.row += lineDif;
+
+            if (comparePoints(r.start, r.end) > 0)
+                this.removeRange(r);
+        }
+        if (!ranges.length)
+            this.detach();
+    };
+    this.updateLinkedFields = function() {
+        var ts = this.selectedTabstop;
+        if (!ts || !ts.hasLinkedRanges)
+            return;
+        this.$inChange = true;
+        var session = this.editor.session;
+        var text = session.getTextRange(ts.firstNonLinked);
+        for (var i = ts.length; i--;) {
+            var range = ts[i];
+            if (!range.linked)
+                continue;
+            var fmt = exports.snippetManager.tmStrFormat(text, range.original);
+            session.replace(range, fmt);
+        }
+        this.$inChange = false;
+    };
+    this.onAfterExec = function(e) {
+        if (e.command && !e.command.readOnly)
+            this.updateLinkedFields();
+    };
+    this.onChangeSelection = function() {
+        if (!this.editor)
+            return;
+        var lead = this.editor.selection.lead;
+        var anchor = this.editor.selection.anchor;
+        var isEmpty = this.editor.selection.isEmpty();
+        for (var i = this.ranges.length; i--;) {
+            if (this.ranges[i].linked)
+                continue;
+            var containsLead = this.ranges[i].contains(lead.row, lead.column);
+            var containsAnchor = isEmpty || this.ranges[i].contains(anchor.row, anchor.column);
+            if (containsLead && containsAnchor)
+                return;
+        }
+        this.detach();
+    };
+    this.onChangeSession = function() {
+        this.detach();
+    };
+    this.tabNext = function(dir) {
+        var max = this.tabstops.length;
+        var index = this.index + (dir || 1);
+        index = Math.min(Math.max(index, 1), max);
+        if (index == max)
+            index = 0;
+        this.selectTabstop(index);
+        if (index === 0)
+            this.detach();
+    };
+    this.selectTabstop = function(index) {
+        this.$openTabstops = null;
+        var ts = this.tabstops[this.index];
+        if (ts)
+            this.addTabstopMarkers(ts);
+        this.index = index;
+        ts = this.tabstops[this.index];
+        if (!ts || !ts.length)
+            return;
+        
+        this.selectedTabstop = ts;
+        if (!this.editor.inVirtualSelectionMode) {        
+            var sel = this.editor.multiSelect;
+            sel.toSingleRange(ts.firstNonLinked.clone());
+            for (var i = ts.length; i--;) {
+                if (ts.hasLinkedRanges && ts[i].linked)
+                    continue;
+                sel.addRange(ts[i].clone(), true);
+            }
+            if (sel.ranges[0])
+                sel.addRange(sel.ranges[0].clone());
+        } else {
+            this.editor.selection.setRange(ts.firstNonLinked);
+        }
+        
+        this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler);
+    };
+    this.addTabstops = function(tabstops, start, end) {
+        if (!this.$openTabstops)
+            this.$openTabstops = [];
+        if (!tabstops[0]) {
+            var p = Range.fromPoints(end, end);
+            moveRelative(p.start, start);
+            moveRelative(p.end, start);
+            tabstops[0] = [p];
+            tabstops[0].index = 0;
+        }
+
+        var i = this.index;
+        var arg = [i + 1, 0];
+        var ranges = this.ranges;
+        tabstops.forEach(function(ts, index) {
+            var dest = this.$openTabstops[index] || ts;
+                
+            for (var i = ts.length; i--;) {
+                var p = ts[i];
+                var range = Range.fromPoints(p.start, p.end || p.start);
+                movePoint(range.start, start);
+                movePoint(range.end, start);
+                range.original = p;
+                range.tabstop = dest;
+                ranges.push(range);
+                if (dest != ts)
+                    dest.unshift(range);
+                else
+                    dest[i] = range;
+                if (p.fmtString) {
+                    range.linked = true;
+                    dest.hasLinkedRanges = true;
+                } else if (!dest.firstNonLinked)
+                    dest.firstNonLinked = range;
+            }
+            if (!dest.firstNonLinked)
+                dest.hasLinkedRanges = false;
+            if (dest === ts) {
+                arg.push(dest);
+                this.$openTabstops[index] = dest;
+            }
+            this.addTabstopMarkers(dest);
+        }, this);
+        
+        if (arg.length > 2) {
+            if (this.tabstops.length)
+                arg.push(arg.splice(2, 1)[0]);
+            this.tabstops.splice.apply(this.tabstops, arg);
+        }
+    };
+
+    this.addTabstopMarkers = function(ts) {
+        var session = this.editor.session;
+        ts.forEach(function(range) {
+            if  (!range.markerId)
+                range.markerId = session.addMarker(range, "ace_snippet-marker", "text");
+        });
+    };
+    this.removeTabstopMarkers = function(ts) {
+        var session = this.editor.session;
+        ts.forEach(function(range) {
+            session.removeMarker(range.markerId);
+            range.markerId = null;
+        });
+    };
+    this.removeRange = function(range) {
+        var i = range.tabstop.indexOf(range);
+        range.tabstop.splice(i, 1);
+        i = this.ranges.indexOf(range);
+        this.ranges.splice(i, 1);
+        this.editor.session.removeMarker(range.markerId);
+        if (!range.tabstop.length) {
+            i = this.tabstops.indexOf(range.tabstop);
+            if (i != -1)
+                this.tabstops.splice(i, 1);
+            if (!this.tabstops.length)
+                this.detach();
+        }
+    };
+
+    this.keyboardHandler = new HashHandler();
+    this.keyboardHandler.bindKeys({
+        "Tab": function(ed) {
+            if (exports.snippetManager && exports.snippetManager.expandWithTab(ed)) {
+                return;
+            }
+
+            ed.tabstopManager.tabNext(1);
+        },
+        "Shift-Tab": function(ed) {
+            ed.tabstopManager.tabNext(-1);
+        },
+        "Esc": function(ed) {
+            ed.tabstopManager.detach();
+        },
+        "Return": function(ed) {
+            return false;
+        }
+    });
+}).call(TabstopManager.prototype);
+
+
+
+var changeTracker = {};
+changeTracker.onChange = Anchor.prototype.onChange;
+changeTracker.setPosition = function(row, column) {
+    this.pos.row = row;
+    this.pos.column = column;
+};
+changeTracker.update = function(pos, delta, $insertRight) {
+    this.$insertRight = $insertRight;
+    this.pos = pos; 
+    this.onChange(delta);
+};
+
+var movePoint = function(point, diff) {
+    if (point.row == 0)
+        point.column += diff.column;
+    point.row += diff.row;
+};
+
+var moveRelative = function(point, start) {
+    if (point.row == start.row)
+        point.column -= start.column;
+    point.row -= start.row;
+};
+
+
+require("./lib/dom").importCssString("\
+.ace_snippet-marker {\
+    -moz-box-sizing: border-box;\
+    box-sizing: border-box;\
+    background: rgba(194, 193, 208, 0.09);\
+    border: 1px dotted rgba(211, 208, 235, 0.62);\
+    position: absolute;\
+}");
+
+exports.snippetManager = new SnippetManager();
+
+
+var Editor = require("./editor").Editor;
+(function() {
+    this.insertSnippet = function(content, options) {
+        return exports.snippetManager.insertSnippet(this, content, options);
+    };
+    this.expandSnippet = function(options) {
+        return exports.snippetManager.expandWithTab(this, options);
+    };
+}).call(Editor.prototype);
+
+});
+
+define("ace/autocomplete/popup",["require","exports","module","ace/edit_session","ace/virtual_renderer","ace/editor","ace/range","ace/lib/event","ace/lib/lang","ace/lib/dom"], function(require, exports, module) {
+"use strict";
+
+var EditSession = require("../edit_session").EditSession;
+var Renderer = require("../virtual_renderer").VirtualRenderer;
+var Editor = require("../editor").Editor;
+var Range = require("../range").Range;
+var event = require("../lib/event");
+var lang = require("../lib/lang");
+var dom = require("../lib/dom");
+
+var $singleLineEditor = function(el) {
+    var renderer = new Renderer(el);
+
+    renderer.$maxLines = 4;
+
+    var editor = new Editor(renderer);
+
+    editor.setHighlightActiveLine(false);
+    editor.setShowPrintMargin(false);
+    editor.renderer.setShowGutter(false);
+    editor.renderer.setHighlightGutterLine(false);
+
+    editor.$mouseHandler.$focusWaitTimout = 0;
+
+    return editor;
+};
+
+var AcePopup = function(parentNode) {
+    var el = dom.createElement("div");
+    var popup = new $singleLineEditor(el);
+
+    if (parentNode)
+        parentNode.appendChild(el);
+    el.style.display = "none";
+    popup.renderer.content.style.cursor = "default";
+    popup.renderer.setStyle("ace_autocomplete");
+
+    popup.setOption("displayIndentGuides", false);
+    popup.setOption("dragDelay", 150);
+
+    var noop = function(){};
+
+    popup.focus = noop;
+    popup.$isFocused = true;
+
+    popup.renderer.$cursorLayer.restartTimer = noop;
+    popup.renderer.$cursorLayer.element.style.opacity = 0;
+
+    popup.renderer.$maxLines = 8;
+    popup.renderer.$keepTextAreaAtCursor = false;
+
+    popup.setHighlightActiveLine(false);
+    popup.session.highlight("");
+    popup.session.$searchHighlight.clazz = "ace_highlight-marker";
+
+    popup.on("mousedown", function(e) {
+        var pos = e.getDocumentPosition();
+        popup.selection.moveToPosition(pos);
+        selectionMarker.start.row = selectionMarker.end.row = pos.row;
+        e.stop();
+    });
+
+    var lastMouseEvent;
+    var hoverMarker = new Range(-1,0,-1,Infinity);
+    var selectionMarker = new Range(-1,0,-1,Infinity);
+    selectionMarker.id = popup.session.addMarker(selectionMarker, "ace_active-line", "fullLine");
+    popup.setSelectOnHover = function(val) {
+        if (!val) {
+            hoverMarker.id = popup.session.addMarker(hoverMarker, "ace_line-hover", "fullLine");
+        } else if (hoverMarker.id) {
+            popup.session.removeMarker(hoverMarker.id);
+            hoverMarker.id = null;
+        }
+    }
+    popup.setSelectOnHover(false);
+    popup.on("mousemove", function(e) {
+        if (!lastMouseEvent) {
+            lastMouseEvent = e;
+            return;
+        }
+        if (lastMouseEvent.x == e.x && lastMouseEvent.y == e.y) {
+            return;
+        }
+        lastMouseEvent = e;
+        lastMouseEvent.scrollTop = popup.renderer.scrollTop;
+        var row = lastMouseEvent.getDocumentPosition().row;
+        if (hoverMarker.start.row != row) {
+            if (!hoverMarker.id)
+                popup.setRow(row);
+            setHoverMarker(row);
+        }
+    });
+    popup.renderer.on("beforeRender", function() {
+        if (lastMouseEvent && hoverMarker.start.row != -1) {
+            lastMouseEvent.$pos = null;
+            var row = lastMouseEvent.getDocumentPosition().row;
+            if (!hoverMarker.id)
+                popup.setRow(row);
+            setHoverMarker(row, true);
+        }
+    });
+    popup.renderer.on("afterRender", function() {
+        var row = popup.getRow();
+        var t = popup.renderer.$textLayer;
+        var selected = t.element.childNodes[row - t.config.firstRow];
+        if (selected == t.selectedNode)
+            return;
+        if (t.selectedNode)
+            dom.removeCssClass(t.selectedNode, "ace_selected");
+        t.selectedNode = selected;
+        if (selected)
+            dom.addCssClass(selected, "ace_selected");
+    });
+    var hideHoverMarker = function() { setHoverMarker(-1) };
+    var setHoverMarker = function(row, suppressRedraw) {
+        if (row !== hoverMarker.start.row) {
+            hoverMarker.start.row = hoverMarker.end.row = row;
+            if (!suppressRedraw)
+                popup.session._emit("changeBackMarker");
+            popup._emit("changeHoverMarker");
+        }
+    };
+    popup.getHoveredRow = function() {
+        return hoverMarker.start.row;
+    };
+
+    event.addListener(popup.container, "mouseout", hideHoverMarker);
+    popup.on("hide", hideHoverMarker);
+    popup.on("changeSelection", hideHoverMarker);
+
+    popup.session.doc.getLength = function() {
+        return popup.data.length;
+    };
+    popup.session.doc.getLine = function(i) {
+        var data = popup.data[i];
+        if (typeof data == "string")
+            return data;
+        return (data && data.value) || "";
+    };
+
+    var bgTokenizer = popup.session.bgTokenizer;
+    bgTokenizer.$tokenizeRow = function(i) {
+        var data = popup.data[i];
+        var tokens = [];
+        if (!data)
+            return tokens;
+        if (typeof data == "string")
+            data = {value: data};
+        if (!data.caption)
+            data.caption = data.value || data.name;
+
+        var last = -1;
+        var flag, c;
+        for (var i = 0; i < data.caption.length; i++) {
+            c = data.caption[i];
+            flag = data.matchMask & (1 << i) ? 1 : 0;
+            if (last !== flag) {
+                tokens.push({type: data.className || "" + ( flag ? "completion-highlight" : ""), value: c});
+                last = flag;
+            } else {
+                tokens[tokens.length - 1].value += c;
+            }
+        }
+
+        if (data.meta) {
+            var maxW = popup.renderer.$size.scrollerWidth / popup.renderer.layerConfig.characterWidth;
+            if (data.meta.length + data.caption.length < maxW - 2)
+                tokens.push({type: "rightAlignedText", value: data.meta});
+        }
+        return tokens;
+    };
+    bgTokenizer.$updateOnChange = noop;
+    bgTokenizer.start = noop;
+
+    popup.session.$computeWidth = function() {
+        return this.screenWidth = 0;
+    }
+    popup.isOpen = false;
+    popup.isTopdown = false;
+
+    popup.data = [];
+    popup.setData = function(list) {
+        popup.data = list || [];
+        popup.setValue(lang.stringRepeat("\n", list.length), -1);
+        popup.setRow(0);
+    };
+    popup.getData = function(row) {
+        return popup.data[row];
+    };
+
+    popup.getRow = function() {
+        return selectionMarker.start.row;
+    };
+    popup.setRow = function(line) {
+        line = Math.max(-1, Math.min(this.data.length, line));
+        if (selectionMarker.start.row != line) {
+            popup.selection.clearSelection();
+            selectionMarker.start.row = selectionMarker.end.row = line || 0;
+            popup.session._emit("changeBackMarker");
+            popup.moveCursorTo(line || 0, 0);
+            if (popup.isOpen)
+                popup._signal("select");
+        }
+    };
+
+    popup.on("changeSelection", function() {
+        if (popup.isOpen)
+            popup.setRow(popup.selection.lead.row);
+    });
+
+    popup.hide = function() {
+        this.container.style.display = "none";
+        this._signal("hide");
+        popup.isOpen = false;
+    };
+    popup.show = function(pos, lineHeight, topdownOnly) {
+        var el = this.container;
+        var screenHeight = window.innerHeight;
+        var screenWidth = window.innerWidth;
+        var renderer = this.renderer;
+        var maxH = renderer.$maxLines * lineHeight * 1.4;
+        var top = pos.top + this.$borderSize;
+        if (top + maxH > screenHeight - lineHeight && !topdownOnly) {
+            el.style.top = "";
+            el.style.bottom = screenHeight - top + "px";
+            popup.isTopdown = false;
+        } else {
+            top += lineHeight;
+            el.style.top = top + "px";
+            el.style.bottom = "";
+            popup.isTopdown = true;
+        }
+
+        el.style.display = "";
+        this.renderer.$textLayer.checkForSizeChanges();
+
+        var left = pos.left;
+        if (left + el.offsetWidth > screenWidth)
+            left = screenWidth - el.offsetWidth;
+
+        el.style.left = left + "px";
+
+        this._signal("show");
+        lastMouseEvent = null;
+        popup.isOpen = true;
+    };
+
+    popup.getTextLeftOffset = function() {
+        return this.$borderSize + this.renderer.$padding + this.$imageSize;
+    };
+
+    popup.$imageSize = 0;
+    popup.$borderSize = 1;
+
+    return popup;
+};
+
+dom.importCssString("\
+.ace_editor.ace_autocomplete .ace_marker-layer .ace_active-line {\
+    background-color: #CAD6FA;\
+    z-index: 1;\
+}\
+.ace_editor.ace_autocomplete .ace_line-hover {\
+    border: 1px solid #abbffe;\
+    margin-top: -1px;\
+    background: rgba(233,233,253,0.4);\
+}\
+.ace_editor.ace_autocomplete .ace_line-hover {\
+    position: absolute;\
+    z-index: 2;\
+}\
+.ace_editor.ace_autocomplete .ace_scroller {\
+   background: none;\
+   border: none;\
+   box-shadow: none;\
+}\
+.ace_rightAlignedText {\
+    color: gray;\
+    display: inline-block;\
+    position: absolute;\
+    right: 4px;\
+    text-align: right;\
+    z-index: -1;\
+}\
+.ace_editor.ace_autocomplete .ace_completion-highlight{\
+    color: #000;\
+    text-shadow: 0 0 0.01em;\
+}\
+.ace_editor.ace_autocomplete {\
+    width: 280px;\
+    z-index: 200000;\
+    background: #fbfbfb;\
+    color: #444;\
+    border: 1px lightgray solid;\
+    position: fixed;\
+    box-shadow: 2px 3px 5px rgba(0,0,0,.2);\
+    line-height: 1.4;\
+}");
+
+exports.AcePopup = AcePopup;
+
+});
+
+define("ace/autocomplete/util",["require","exports","module"], function(require, exports, module) {
+"use strict";
+
+exports.parForEach = function(array, fn, callback) {
+    var completed = 0;
+    var arLength = array.length;
+    if (arLength === 0)
+        callback();
+    for (var i = 0; i < arLength; i++) {
+        fn(array[i], function(result, err) {
+            completed++;
+            if (completed === arLength)
+                callback(result, err);
+        });
+    }
+};
+
+var ID_REGEX = /[\\a-zA-Z_0-9\$\-\u00A2-\uFFFF]/;
+
+exports.retrievePrecedingIdentifier = function(text, pos, regex) {
+    regex = regex || ID_REGEX;
+    var buf = [];
+    for (var i = pos-1; i >= 0; i--) {
+        if (regex.test(text[i]))
+            buf.push(text[i]);
+        else
+            break;
+    }
+    var frag = buf.reverse().join("");
+    console.log("NATIVE FRAGMENT", frag, buf, regex, text.slice(pos - 10, pos));
+    return frag;
+};
+
+exports.retrieveFollowingIdentifier = function(text, pos, regex) {
+    regex = regex || ID_REGEX;
+    var buf = [];
+    for (var i = pos; i < text.length; i++) {
+        if (regex.test(text[i]))
+            buf.push(text[i]);
+        else
+            break;
+    }
+    return buf;
+};
+
+});
+
+define("ace/autocomplete",["require","exports","module","ace/keyboard/hash_handler","ace/autocomplete/popup","ace/autocomplete/util","ace/lib/event","ace/lib/lang","ace/snippets"], function(require, exports, module) {
+"use strict";
+
+var HashHandler = require("./keyboard/hash_handler").HashHandler;
+var AcePopup = require("./autocomplete/popup").AcePopup;
+var util = require("./autocomplete/util");
+var event = require("./lib/event");
+var lang = require("./lib/lang");
+var snippetManager = require("./snippets").snippetManager;
+
+var Autocomplete = function() {
+    this.autoInsert = false;
+    this.autoSelect = true;
+    this.keyboardHandler = new HashHandler();
+    this.keyboardHandler.bindKeys(this.commands);
+
+    this.blurListener = this.blurListener.bind(this);
+    this.changeListener = this.changeListener.bind(this);
+    this.mousedownListener = this.mousedownListener.bind(this);
+    this.mousewheelListener = this.mousewheelListener.bind(this);
+
+    this.changeTimer = lang.delayedCall(function() {
+        this.updateCompletions(true);
+    }.bind(this));
+};
+
+(function() {
+    this.gatherCompletionsId = 0;
+
+    this.$init = function() {
+        this.popup = new AcePopup(document.body || document.documentElement);
+        this.popup.on("click", function(e) {
+            this.insertMatch();
+            e.stop();
+        }.bind(this));
+        this.popup.focus = this.editor.focus.bind(this.editor);
+    };
+
+    this.openPopup = function(editor, prefix, keepPopupPosition) {
+        if (!this.popup)
+            this.$init();
+
+        this.popup.setData(this.completions.filtered);
+
+        var renderer = editor.renderer;
+        this.popup.setRow(this.autoSelect ? 0 : -1);
+        if (!keepPopupPosition) {
+            this.popup.setTheme(editor.getTheme());
+            this.popup.setFontSize(editor.getFontSize());
+
+            var lineHeight = renderer.layerConfig.lineHeight;
+
+            var pos = renderer.$cursorLayer.getPixelPosition(this.base, true);
+            pos.left -= this.popup.getTextLeftOffset();
+
+            var rect = editor.container.getBoundingClientRect();
+            pos.top += rect.top - renderer.layerConfig.offset;
+            pos.left += rect.left - editor.renderer.scrollLeft;
+            pos.left += renderer.$gutterLayer.gutterWidth;
+
+            this.popup.show(pos, lineHeight);
+        }
+    };
+
+    this.detach = function() {
+        this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler);
+        this.editor.off("changeSelection", this.changeListener);
+        this.editor.off("blur", this.blurListener);
+        this.editor.off("mousedown", this.mousedownListener);
+        this.editor.off("mousewheel", this.mousewheelListener);
+        this.changeTimer.cancel();
+
+        if (this.popup && this.popup.isOpen) {
+            this.gatherCompletionsId += 1;
+            this.popup.hide();
+        }
+        
+        if (this.base)
+            this.base.detach();
+        this.activated = false;
+        this.completions = this.base = null;
+    };
+
+    this.changeListener = function(e) {
+        var cursor = this.editor.selection.lead;
+        if (cursor.row != this.base.row || cursor.column < this.base.column) {
+            this.detach();
+        }
+        if (this.activated)
+            this.changeTimer.schedule();
+        else
+            this.detach();
+    };
+
+    this.blurListener = function() {
+        var el = document.activeElement;
+        if (el != this.editor.textInput.getElement() && el.parentNode != this.popup.container)
+            this.detach();
+    };
+
+    this.mousedownListener = function(e) {
+        this.detach();
+    };
+
+    this.mousewheelListener = function(e) {
+        this.detach();
+    };
+
+    this.goTo = function(where) {
+        var row = this.popup.getRow();
+        var max = this.popup.session.getLength() - 1;
+
+        switch(where) {
+            case "up": row = row <= 0 ? max : row - 1; break;
+            case "down": row = row >= max ? -1 : row + 1; break;
+            case "start": row = 0; break;
+            case "end": row = max; break;
+        }
+
+        this.popup.setRow(row);
+    };
+
+    this.insertMatch = function(data) {
+        if (!data)
+            data = this.popup.getData(this.popup.getRow());
+        if (!data)
+            return false;
+
+        if (data.completer && data.completer.insertMatch) {
+            data.completer.insertMatch(this.editor);
+        } else {
+            if (this.completions.filterText) {
+                var ranges = this.editor.selection.getAllRanges();
+                for (var i = 0, range; range = ranges[i]; i++) {
+                    range.start.column -= this.completions.filterText.length;
+                    this.editor.session.remove(range);
+                }
+            }
+            if (data.snippet)
+                snippetManager.insertSnippet(this.editor, data.snippet);
+            else
+                this.editor.execCommand("insertstring", data.value || data);
+        }
+        this.detach();
+    };
+
+    this.commands = {
+        "Up": function(editor) { editor.completer.goTo("up"); },
+        "Down": function(editor) { editor.completer.goTo("down"); },
+        "Ctrl-Up|Ctrl-Home": function(editor) { editor.completer.goTo("start"); },
+        "Ctrl-Down|Ctrl-End": function(editor) { editor.completer.goTo("end"); },
+
+        "Esc": function(editor) { editor.completer.detach(); },
+        "Space": function(editor) { editor.completer.detach(); editor.insert(" ");},
+        "Return": function(editor) { return editor.completer.insertMatch(); },
+        "Shift-Return": function(editor) { editor.completer.insertMatch(true); },
+        "Tab": function(editor) {
+            var result = editor.completer.insertMatch();
+            if (!result && !editor.tabstopManager)
+                editor.completer.goTo("down");
+            else
+                return result;
+        },
+
+        "PageUp": function(editor) { editor.completer.popup.gotoPageUp(); },
+        "PageDown": function(editor) { editor.completer.popup.gotoPageDown(); }
+    };
+
+    this.gatherCompletions = function(editor, callback) {
+        console.log("gatherCompletions");
+        var session = editor.getSession();
+        var pos = editor.getCursorPosition();
+
+        var line = session.getLine(pos.row);
+        var prefix = util.retrievePrecedingIdentifier(line, pos.column);
+
+        this.base = session.doc.createAnchor(pos.row, pos.column - prefix.length);
+
+        var matches = [];
+        var total = editor.completers.length;
+        editor.completers.forEach(function(completer, i) {
+            completer.getCompletions(editor, session, pos, prefix, function(err, results) {
+                if (!err)
+                    matches = matches.concat(results);
+                var pos = editor.getCursorPosition();
+                var line = session.getLine(pos.row);
+                console.log("IN COMPLETER", results)
+                callback(null, {
+                    prefix: util.retrievePrecedingIdentifier(line, pos.column, results[0] && results[0].identifierRegex),
+                    matches: matches,
+                    finished: (--total === 0)
+                });
+            });
+        });
+        return true;
+    };
+
+    this.showPopup = function(editor) {
+        if (this.editor)
+            this.detach();
+
+        this.activated = true;
+
+        this.editor = editor;
+        if (editor.completer != this) {
+            if (editor.completer)
+                editor.completer.detach();
+            editor.completer = this;
+        }
+
+        editor.keyBinding.addKeyboardHandler(this.keyboardHandler);
+        editor.on("changeSelection", this.changeListener);
+        editor.on("blur", this.blurListener);
+        editor.on("mousedown", this.mousedownListener);
+        editor.on("mousewheel", this.mousewheelListener);
+
+        this.updateCompletions();
+    };
+
+    this.updateCompletions = function(keepPopupPosition) {
+        if (keepPopupPosition && this.base && this.completions) {
+            var pos = this.editor.getCursorPosition();
+            var prefix = this.editor.session.getTextRange({start: this.base, end: pos});
+            if (prefix == this.completions.filterText)
+                return;
+            this.completions.setFilter(prefix);
+            if (!this.completions.filtered.length)
+                return this.detach();
+            if (this.completions.filtered.length == 1
+            && this.completions.filtered[0].value == prefix
+            && !this.completions.filtered[0].snippet)
+                return this.detach();
+            this.openPopup(this.editor, prefix, keepPopupPosition);
+            return;
+        }
+        var _id = this.gatherCompletionsId;
+        this.gatherCompletions(this.editor, function(err, results) {
+            var detachIfFinished = function() {
+                if (!results.finished) return;
+                console.log("DETACHING");
+                return this.detach();
+            }.bind(this);
+
+            console.log("UPDATE COMPLETIONS CALLBACK", results)
+
+            var prefix = results.prefix;
+            var matches = results && results.matches;
+            
+            if (!matches || !matches.length)
+                return detachIfFinished();
+            if (prefix.indexOf(results.prefix) !== 0 || _id != this.gatherCompletionsId)
+                return;
+
+            this.completions = new FilteredList(matches);
+            this.completions.setFilter(prefix);
+            var filtered = this.completions.filtered;
+            if (!filtered.length)
+                return detachIfFinished();
+            if (filtered.length == 1 && filtered[0].value == prefix && !filtered[0].snippet)
+                return detachIfFinished();
+            if (this.autoInsert && filtered.length == 1)
+                return this.insertMatch(filtered[0]);
+
+            console.log("opening pop up", prefix, keepPopupPosition);
+            this.openPopup(this.editor, prefix, keepPopupPosition);
+        }.bind(this));
+    };
+
+    this.cancelContextMenu = function() {
+        this.editor.$mouseHandler.cancelContextMenu();
+    };
+
+}).call(Autocomplete.prototype);
+
+Autocomplete.startCommand = {
+    name: "startAutocomplete",
+    exec: function(editor) {
+        if (!editor.completer)
+            editor.completer = new Autocomplete();
+        editor.completer.autoInsert = false;
+        editor.completer.autoSelect = true;
+        editor.completer.showPopup(editor);
+        editor.completer.cancelContextMenu();
+    },
+    bindKey: "Ctrl-Space|Ctrl-Shift-Space|Alt-Space"
+};
+
+var FilteredList = function(array, filterText, mutateData) {
+    this.all = array;
+    this.filtered = array;
+    this.filterText = filterText || "";
+};
+(function(){
+    this.setFilter = function(str) {
+        if (str.length > this.filterText && str.lastIndexOf(this.filterText, 0) === 0)
+            var matches = this.filtered;
+        else
+            var matches = this.all;
+
+        this.filterText = str;
+        matches = this.filterCompletions(matches, this.filterText);
+        matches = matches.sort(function(a, b) {
+            return b.exactMatch - a.exactMatch || b.score - a.score;
+        });
+        var prev = null;
+        matches = matches.filter(function(item){
+            var caption = item.value || item.caption || item.snippet;
+            if (caption === prev) return false;
+            prev = caption;
+            return true;
+        });
+
+        this.filtered = matches;
+    };
+    this.filterCompletions = function(items, needle) {
+        var results = [];
+        var upper = needle.toUpperCase();
+        var lower = needle.toLowerCase();
+        loop: for (var i = 0, item; item = items[i]; i++) {
+            var caption = item.value || item.caption || item.snippet;
+            if (!caption) continue;
+            var lastIndex = -1;
+            var matchMask = 0;
+            var penalty = 0;
+            var index, distance;
+            for (var j = 0; j < needle.length; j++) {
+                var i1 = caption.indexOf(lower[j], lastIndex + 1);
+                var i2 = caption.indexOf(upper[j], lastIndex + 1);
+                index = (i1 >= 0) ? ((i2 < 0 || i1 < i2) ? i1 : i2) : i2;
+                if (index < 0)
+                    continue loop;
+                distance = index - lastIndex - 1;
+                if (distance > 0) {
+                    if (lastIndex === -1)
+                        penalty += 10;
+                    penalty += distance;
+                }
+                matchMask = matchMask | (1 << index);
+                lastIndex = index;
+            }
+            item.matchMask = matchMask;
+            item.exactMatch = penalty ? 0 : 1;
+            item.score = (item.score || 0) - penalty;
+            results.push(item);
+        }
+        return results;
+    };
+}).call(FilteredList.prototype);
+
+exports.Autocomplete = Autocomplete;
+exports.FilteredList = FilteredList;
+
+});
+
+define("ace/autocomplete/text_completer",["require","exports","module","ace/range"], function(require, exports, module) {
+    var Range = require("../range").Range;
+    
+    var splitRegex = /[^a-zA-Z_0-9\$\-\u00C0-\u1FFF\u2C00-\uD7FF\w]+/;
+
+    function getWordIndex(doc, pos) {
+        var textBefore = doc.getTextRange(Range.fromPoints({row: 0, column:0}, pos));
+        return textBefore.split(splitRegex).length - 1;
+    }
+    function wordDistance(doc, pos) {
+        var prefixPos = getWordIndex(doc, pos);
+        var words = doc.getValue().split(splitRegex);
+        var wordScores = Object.create(null);
+        
+        var currentWord = words[prefixPos];
+
+        words.forEach(function(word, idx) {
+            if (!word || word === currentWord) return;
+
+            var distance = Math.abs(prefixPos - idx);
+            var score = words.length - distance;
+            if (wordScores[word]) {
+                wordScores[word] = Math.max(score, wordScores[word]);
+            } else {
+                wordScores[word] = score;
+            }
+        });
+        return wordScores;
+    }
+
+    exports.getCompletions = function(editor, session, pos, prefix, callback) {
+        var wordScore = wordDistance(session, pos, prefix);
+        var wordList = Object.keys(wordScore);
+        callback(null, wordList.map(function(word) {
+            return {
+                caption: word,
+                value: word,
+                score: wordScore[word],
+                meta: "local"
+            };
+        }));
+    };
+});
+
+define("ace/ext/language_tools",["require","exports","module","ace/snippets","ace/autocomplete","ace/config","ace/autocomplete/util","ace/autocomplete/text_completer","ace/editor","ace/config"], function(require, exports, module) {
+"use strict";
+
+var snippetManager = require("../snippets").snippetManager;
+var Autocomplete = require("../autocomplete").Autocomplete;
+var config = require("../config");
+var util = require("../autocomplete/util");
+
+var textCompleter = require("../autocomplete/text_completer");
+var keyWordCompleter = {
+    getCompletions: function(editor, session, pos, prefix, callback) {
+        var state = editor.session.getState(pos.row);
+        var completions = session.$mode.getCompletions(state, session, pos, prefix);
+        callback(null, completions);
+    }
+};
+
+var snippetCompleter = {
+    getCompletions: function(editor, session, pos, prefix, callback) {
+        var snippetMap = snippetManager.snippetMap;
+        var completions = [];
+        snippetManager.getActiveScopes(editor).forEach(function(scope) {
+            var snippets = snippetMap[scope] || [];
+            for (var i = snippets.length; i--;) {
+                var s = snippets[i];
+                var caption = s.name || s.tabTrigger;
+                if (!caption)
+                    continue;
+                completions.push({
+                    caption: caption,
+                    snippet: s.content,
+                    meta: s.tabTrigger && !s.name ? s.tabTrigger + "\u21E5 " : "snippet"
+                });
+            }
+        }, this);
+        callback(null, completions);
+    }
+};
+
+var completers = [snippetCompleter, textCompleter, keyWordCompleter];
+exports.addCompleter = function(completer) {
+    completers.push(completer);
+};
+exports.textCompleter = textCompleter;
+exports.keyWordCompleter = keyWordCompleter;
+exports.snippetCompleter = snippetCompleter;
+
+var expandSnippet = {
+    name: "expandSnippet",
+    exec: function(editor) {
+        var success = snippetManager.expandWithTab(editor);
+        if (!success)
+            editor.execCommand("indent");
+    },
+    bindKey: "Tab"
+};
+
+var onChangeMode = function(e, editor) {
+    loadSnippetsForMode(editor.session.$mode);
+};
+
+var loadSnippetsForMode = function(mode) {
+    var id = mode.$id;
+    if (!snippetManager.files)
+        snippetManager.files = {};
+    loadSnippetFile(id);
+    if (mode.modes)
+        mode.modes.forEach(loadSnippetsForMode);
+};
+
+var loadSnippetFile = function(id) {
+    if (!id || snippetManager.files[id])
+        return;
+    var snippetFilePath = id.replace("mode", "snippets");
+    snippetManager.files[id] = {};
+    config.loadModule(snippetFilePath, function(m) {
+        if (m) {
+            snippetManager.files[id] = m;
+            if (!m.snippets && m.snippetText)
+                m.snippets = snippetManager.parseSnippetFile(m.snippetText);
+            snippetManager.register(m.snippets || [], m.scope);
+            if (m.includeScopes) {
+                snippetManager.snippetMap[m.scope].includeScopes = m.includeScopes;
+                m.includeScopes.forEach(function(x) {
+                    loadSnippetFile("ace/mode/" + x);
+                });
+            }
+        }
+    });
+};
+
+function getCompletionPrefix(editor) {
+    console.log("getCompletionPrefix");
+    var pos = editor.getCursorPosition();
+    var line = editor.session.getLine(pos.row);
+    var prefix = util.retrievePrecedingIdentifier(line, pos.column);
+    editor.completers.forEach(function(completer) {
+        if (completer.identifierRegexps) {
+            completer.identifierRegexps.forEach(function(identifierRegex) {
+                if (!prefix && identifierRegex)
+                    prefix = util.retrievePrecedingIdentifier(line, pos.column, identifierRegex);
+            });
+        }
+    });
+    return prefix;
+}
+
+var doLiveAutocomplete = function(e) {
+    var editor = e.editor;
+    var text = e.args || "";
+    var hasCompleter = editor.completer && editor.completer.activated;
+    if (e.command.name === "backspace") {
+        if (hasCompleter && !getCompletionPrefix(editor))
+            editor.completer.detach();
+    }
+    else if (e.command.name === "insertstring") {
+        var prefix = getCompletionPrefix(editor);
+        if (prefix && !hasCompleter) {
+            if (!editor.completer) {
+                editor.completer = new Autocomplete();
+            }
+            editor.completer.autoSelect = false;
+            editor.completer.autoInsert = false;
+            editor.completer.showPopup(editor);
+        }
+    }
+};
+
+var Editor = require("../editor").Editor;
+require("../config").defineOptions(Editor.prototype, "editor", {
+    enableBasicAutocompletion: {
+        set: function(val) {
+            if (val) {
+                if (!this.completers)
+                    this.completers = Array.isArray(val)? val: completers;
+                this.commands.addCommand(Autocomplete.startCommand);
+            } else {
+                this.commands.removeCommand(Autocomplete.startCommand);
+            }
+        },
+        value: false
+    },
+    enableLiveAutocompletion: {
+        set: function(val) {
+            if (val) {
+                if (!this.completers)
+                    this.completers = Array.isArray(val)? val: completers;
+                this.commands.on('afterExec', doLiveAutocomplete);
+            } else {
+                this.commands.removeListener('afterExec', doLiveAutocomplete);
+            }
+        },
+        value: false
+    },
+    enableSnippets: {
+        set: function(val) {
+            if (val) {
+                this.commands.addCommand(expandSnippet);
+                this.on("changeMode", onChangeMode);
+                onChangeMode(null, this);
+            } else {
+                this.commands.removeCommand(expandSnippet);
+                this.off("changeMode", onChangeMode);
+            }
+        },
+        value: false
+    }
+});
+});
+;
+                (function() {
+                    window.require(["ace/ext/language_tools"], function() {});
+                })();
+            

+ 53 - 0
services/web/public/js/ace/ext-linking.js

@@ -0,0 +1,53 @@
+define("ace/ext/linking",["require","exports","module","ace/editor","ace/config"], function(require, exports, module) {
+
+var Editor = require("ace/editor").Editor;
+
+require("../config").defineOptions(Editor.prototype, "editor", {
+    enableLinking: {
+        set: function(val) {
+            if (val) {
+                this.on("click", onClick);
+                this.on("mousemove", onMouseMove);
+            } else {
+                this.off("click", onClick);
+                this.off("mousemove", onMouseMove);
+            }
+        },
+        value: false
+    }
+})
+
+function onMouseMove(e) {
+    var editor = e.editor;
+    var ctrl = e.getAccelKey();
+
+    if (ctrl) {
+        var editor = e.editor;
+        var docPos = e.getDocumentPosition();
+        var session = editor.session;
+        var token = session.getTokenAt(docPos.row, docPos.column);
+
+        editor._emit("linkHover", {position: docPos, token: token});
+    }
+}
+
+function onClick(e) {
+    var ctrl = e.getAccelKey();
+    var button = e.getButton();
+
+    if (button == 0 && ctrl) {
+        var editor = e.editor;
+        var docPos = e.getDocumentPosition();
+        var session = editor.session;
+        var token = session.getTokenAt(docPos.row, docPos.column);
+
+        editor._emit("linkClick", {position: docPos, token: token});
+    }
+}
+
+});
+;
+                (function() {
+                    window.require(["ace/ext/linking"], function() {});
+                })();
+            

+ 14 - 11
services/web/public/js/ace/ext/modelist.js → services/web/public/js/ace/ext-modelist.js

@@ -1,13 +1,7 @@
-define(function(require, exports, module) {
+define("ace/ext/modelist",["require","exports","module"], 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();
@@ -39,8 +33,6 @@ var Mode = function(name, caption, extensions) {
 Mode.prototype.supportsFile = function(filename) {
     return filename.match(this.extRe);
 };
-
-// todo firstlinematch
 var supportedModes = {
     ABAP:        ["abap"],
     ActionScript:["as"],
@@ -52,7 +44,8 @@ var supportedModes = {
     BatchFile:   ["bat|cmd"],
     C9Search:    ["c9search_results"],
     C_Cpp:       ["cpp|c|cc|cxx|h|hh|hpp"],
-    Clojure:     ["clj"],
+    Cirru:       ["cirru|cr"],
+    Clojure:     ["clj|cljs"],
     Cobol:       ["CBL|COB"],
     coffee:      ["coffee|cf|cson|^Cakefile"],
     ColdFusion:  ["cfm"],
@@ -62,11 +55,14 @@ var supportedModes = {
     D:           ["d|di"],
     Dart:        ["dart"],
     Diff:        ["diff|patch"],
+    Dockerfile:  ["^Dockerfile"],
     Dot:         ["dot"],
     Erlang:      ["erl|hrl"],
     EJS:         ["ejs"],
     Forth:       ["frt|fs|ldr"],
     FTL:         ["ftl"],
+    Gherkin:     ["feature"],
+    Gitignore:   ["^.gitignore"],
     Glsl:        ["glsl|frag|vert"],
     golang:      ["go"],
     Groovy:      ["groovy"],
@@ -99,6 +95,7 @@ var supportedModes = {
     Makefile:    ["^Makefile|^GNUmakefile|^makefile|^OCamlMakefile|make"],
     MATLAB:      ["matlab"],
     Markdown:    ["md|markdown"],
+    MEL:         ["mel"],
     MySQL:       ["mysql"],
     MUSHCode:    ["mc|mush"],
     Nix:         ["nix"],
@@ -121,6 +118,7 @@ var supportedModes = {
     SASS:        ["sass"],
     SCAD:        ["scad"],
     Scala:       ["scala"],
+    Smarty:      ["smarty|tpl"],
     Scheme:      ["scm|rkt"],
     SCSS:        ["scss"],
     SH:          ["sh|bash|^.bashrc"],
@@ -138,6 +136,7 @@ var supportedModes = {
     Toml:        ["toml"],
     Twig:        ["twig"],
     Typescript:  ["ts|typescript|str"],
+    Vala:        ["vala"],
     VBScript:    ["vbs"],
     Velocity:    ["vm"],
     Verilog:     ["v|vh|sv|svh"],
@@ -172,4 +171,8 @@ module.exports = {
 };
 
 });
-
+;
+                (function() {
+                    window.require(["ace/ext/modelist"], function() {});
+                })();
+            

+ 478 - 0
services/web/public/js/ace/ext-old_ie.js

@@ -0,0 +1,478 @@
+define("ace/ext/searchbox",["require","exports","module","ace/lib/dom","ace/lib/lang","ace/lib/event","ace/keyboard/hash_handler","ace/lib/keys"], function(require, exports, module) {
+"use strict";
+
+var dom = require("../lib/dom");
+var lang = require("../lib/lang");
+var event = require("../lib/event");
+var searchboxCss = "\
+.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;\
+white-space: normal;\
+}\
+.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;\
+}";
+var HashHandler = require("../keyboard/hash_handler").HashHandler;
+var keyUtil = require("../lib/keys");
+
+dom.importCssString(searchboxCss, "ace_searchbox");
+
+var html = '<div class="ace_search right">\
+    <button type="button" action="hide" class="ace_searchbtn_close"></button>\
+    <div class="ace_search_form">\
+        <input class="ace_search_field" placeholder="Search for" spellcheck="false"></input>\
+        <button type="button" action="findNext" class="ace_searchbtn next"></button>\
+        <button type="button" action="findPrev" class="ace_searchbtn prev"></button>\
+    </div>\
+    <div class="ace_replace_form">\
+        <input class="ace_search_field" placeholder="Replace with" spellcheck="false"></input>\
+        <button type="button" action="replaceAndFindNext" class="ace_replacebtn">Replace</button>\
+        <button type="button" action="replaceAll" class="ace_replacebtn">All</button>\
+    </div>\
+    <div class="ace_search_options">\
+        <span action="toggleRegexpMode" class="ace_button" title="RegExp Search">.*</span>\
+        <span action="toggleCaseSensitive" class="ace_button" title="CaseSensitive Search">Aa</span>\
+        <span action="toggleWholeWords" class="ace_button" title="Whole Word Search">\\b</span>\
+    </div>\
+</div>'.replace(/>\s+/g, ">");
+
+var SearchBox = function(editor, range, showReplaceForm) {
+    var div = dom.createElement("div");
+    div.innerHTML = html;
+    this.element = div.firstChild;
+
+    this.$init();
+    this.setEditor(editor);
+};
+
+(function() {
+    this.setEditor = function(editor) {
+        editor.searchBox = this;
+        editor.container.appendChild(this.element);
+        this.editor = editor;
+    };
+
+    this.$initElements = function(sb) {
+        this.searchBox = sb.querySelector(".ace_search_form");
+        this.replaceBox = sb.querySelector(".ace_replace_form");
+        this.searchOptions = sb.querySelector(".ace_search_options");
+        this.regExpOption = sb.querySelector("[action=toggleRegexpMode]");
+        this.caseSensitiveOption = sb.querySelector("[action=toggleCaseSensitive]");
+        this.wholeWordOption = sb.querySelector("[action=toggleWholeWords]");
+        this.searchInput = this.searchBox.querySelector(".ace_search_field");
+        this.replaceInput = this.replaceBox.querySelector(".ace_search_field");
+    };
+    
+    this.$init = function() {
+        var sb = this.element;
+        
+        this.$initElements(sb);
+        
+        var _this = this;
+        event.addListener(sb, "mousedown", function(e) {
+            setTimeout(function(){
+                _this.activeInput.focus();
+            }, 0);
+            event.stopPropagation(e);
+        });
+        event.addListener(sb, "click", function(e) {
+            var t = e.target || e.srcElement;
+            var action = t.getAttribute("action");
+            if (action && _this[action])
+                _this[action]();
+            else if (_this.$searchBarKb.commands[action])
+                _this.$searchBarKb.commands[action].exec(_this);
+            event.stopPropagation(e);
+        });
+
+        event.addCommandKeyListener(sb, function(e, hashId, keyCode) {
+            var keyString = keyUtil.keyCodeToString(keyCode);
+            var command = _this.$searchBarKb.findKeyCommand(hashId, keyString);
+            if (command && command.exec) {
+                command.exec(_this);
+                event.stopEvent(e);
+            }
+        });
+
+        this.$onChange = lang.delayedCall(function() {
+            _this.find(false, false);
+        });
+
+        event.addListener(this.searchInput, "input", function() {
+            _this.$onChange.schedule(20);
+        });
+        event.addListener(this.searchInput, "focus", function() {
+            _this.activeInput = _this.searchInput;
+            _this.searchInput.value && _this.highlight();
+        });
+        event.addListener(this.replaceInput, "focus", function() {
+            _this.activeInput = _this.replaceInput;
+            _this.searchInput.value && _this.highlight();
+        });
+    };
+    this.$closeSearchBarKb = new HashHandler([{
+        bindKey: "Esc",
+        name: "closeSearchBar",
+        exec: function(editor) {
+            editor.searchBox.hide();
+        }
+    }]);
+    this.$searchBarKb = new HashHandler();
+    this.$searchBarKb.bindKeys({
+        "Ctrl-f|Command-f|Ctrl-H|Command-Option-F": function(sb) {
+            var isReplace = sb.isReplace = !sb.isReplace;
+            sb.replaceBox.style.display = isReplace ? "" : "none";
+            sb[isReplace ? "replaceInput" : "searchInput"].focus();
+        },
+        "Ctrl-G|Command-G": function(sb) {
+            sb.findNext();
+        },
+        "Ctrl-Shift-G|Command-Shift-G": function(sb) {
+            sb.findPrev();
+        },
+        "esc": function(sb) {
+            setTimeout(function() { sb.hide();});
+        },
+        "Return": function(sb) {
+            if (sb.activeInput == sb.replaceInput)
+                sb.replace();
+            sb.findNext();
+        },
+        "Shift-Return": function(sb) {
+            if (sb.activeInput == sb.replaceInput)
+                sb.replace();
+            sb.findPrev();
+        },
+        "Tab": function(sb) {
+            (sb.activeInput == sb.replaceInput ? sb.searchInput : sb.replaceInput).focus();
+        }
+    });
+
+    this.$searchBarKb.addCommands([{
+        name: "toggleRegexpMode",
+        bindKey: {win: "Alt-R|Alt-/", mac: "Ctrl-Alt-R|Ctrl-Alt-/"},
+        exec: function(sb) {
+            sb.regExpOption.checked = !sb.regExpOption.checked;
+            sb.$syncOptions();
+        }
+    }, {
+        name: "toggleCaseSensitive",
+        bindKey: {win: "Alt-C|Alt-I", mac: "Ctrl-Alt-R|Ctrl-Alt-I"},
+        exec: function(sb) {
+            sb.caseSensitiveOption.checked = !sb.caseSensitiveOption.checked;
+            sb.$syncOptions();
+        }
+    }, {
+        name: "toggleWholeWords",
+        bindKey: {win: "Alt-B|Alt-W", mac: "Ctrl-Alt-B|Ctrl-Alt-W"},
+        exec: function(sb) {
+            sb.wholeWordOption.checked = !sb.wholeWordOption.checked;
+            sb.$syncOptions();
+        }
+    }]);
+
+    this.$syncOptions = function() {
+        dom.setCssClass(this.regExpOption, "checked", this.regExpOption.checked);
+        dom.setCssClass(this.wholeWordOption, "checked", this.wholeWordOption.checked);
+        dom.setCssClass(this.caseSensitiveOption, "checked", this.caseSensitiveOption.checked);
+        this.find(false, false);
+    };
+
+    this.highlight = function(re) {
+        this.editor.session.highlight(re || this.editor.$search.$options.re);
+        this.editor.renderer.updateBackMarkers()
+    };
+    this.find = function(skipCurrent, backwards) {
+        var range = this.editor.find(this.searchInput.value, {
+            skipCurrent: skipCurrent,
+            backwards: backwards,
+            wrap: true,
+            regExp: this.regExpOption.checked,
+            caseSensitive: this.caseSensitiveOption.checked,
+            wholeWord: this.wholeWordOption.checked
+        });
+        var noMatch = !range && this.searchInput.value;
+        dom.setCssClass(this.searchBox, "ace_nomatch", noMatch);
+        this.editor._emit("findSearchBox", { match: !noMatch });
+        this.highlight();
+    };
+    this.findNext = function() {
+        this.find(true, false);
+    };
+    this.findPrev = function() {
+        this.find(true, true);
+    };
+    this.replace = function() {
+        if (!this.editor.getReadOnly())
+            this.editor.replace(this.replaceInput.value);
+    };    
+    this.replaceAndFindNext = function() {
+        if (!this.editor.getReadOnly()) {
+            this.editor.replace(this.replaceInput.value);
+            this.findNext()
+        }
+    };
+    this.replaceAll = function() {
+        if (!this.editor.getReadOnly())
+            this.editor.replaceAll(this.replaceInput.value);
+    };
+
+    this.hide = function() {
+        this.element.style.display = "none";
+        this.editor.keyBinding.removeKeyboardHandler(this.$closeSearchBarKb);
+        this.editor.focus();
+    };
+    this.show = function(value, isReplace) {
+        this.element.style.display = "";
+        this.replaceBox.style.display = isReplace ? "" : "none";
+
+        this.isReplace = isReplace;
+
+        if (value)
+            this.searchInput.value = value;
+        this.searchInput.focus();
+        this.searchInput.select();
+
+        this.editor.keyBinding.addKeyboardHandler(this.$closeSearchBarKb);
+    };
+
+}).call(SearchBox.prototype);
+
+exports.SearchBox = SearchBox;
+
+exports.Search = function(editor, isReplace) {
+    var sb = editor.searchBox || new SearchBox(editor);
+    sb.show(editor.session.getTextRange(), isReplace);
+};
+
+});
+
+define("ace/ext/old_ie",["require","exports","module","ace/lib/useragent","ace/tokenizer","ace/ext/searchbox","ace/mode/text"], 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\
+    }"
+);
+
+patch(
+    require("../mode/text").Mode.prototype, "getTokenizer",
+    /Tokenizer/,
+    "TokenizerModule.Tokenizer"
+);
+
+useragent.isOldIE = true;
+
+});
+;
+                (function() {
+                    window.require(["ace/ext/old_ie"], function() {});
+                })();
+            

+ 154 - 47
services/web/public/js/ace/ext/searchbox.js → services/web/public/js/ace/ext-searchbox.js

@@ -1,40 +1,157 @@
-/* ***** 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) {
+define("ace/ext/searchbox",["require","exports","module","ace/lib/dom","ace/lib/lang","ace/lib/event","ace/keyboard/hash_handler","ace/lib/keys"], function(require, exports, module) {
 "use strict";
 
 var dom = require("../lib/dom");
 var lang = require("../lib/lang");
 var event = require("../lib/event");
-var searchboxCss = require("../requirejs/text!./searchbox.css");
+var searchboxCss = "\
+.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;\
+white-space: normal;\
+}\
+.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;\
+}";
 var HashHandler = require("../keyboard/hash_handler").HashHandler;
 var keyUtil = require("../lib/keys");
 
@@ -133,8 +250,6 @@ var SearchBox = function(editor, range, showReplaceForm) {
             _this.searchInput.value && _this.highlight();
         });
     };
-
-    //keybinging outsite of the searchbox
     this.$closeSearchBarKb = new HashHandler([{
         bindKey: "Esc",
         name: "closeSearchBar",
@@ -142,8 +257,6 @@ var SearchBox = function(editor, range, showReplaceForm) {
             editor.searchBox.hide();
         }
     }]);
-
-    //keybinging outsite of the searchbox
     this.$searchBarKb = new HashHandler();
     this.$searchBarKb.bindKeys({
         "Ctrl-f|Command-f|Ctrl-H|Command-Option-F": function(sb) {
@@ -273,14 +386,8 @@ exports.Search = function(editor, isReplace) {
 };
 
 });
-
-
-/* ------------------------------------------------------------------------------------------
- * TODO
- * --------------------------------------------------------------------------------------- */
-/*
-- move search form to the left if it masks current word
-- includ all options that search has. ex: regex
-- searchbox.searchbox is not that pretty. we should have just searchbox
-- disable prev button if it makes sence
-*/
+;
+                (function() {
+                    window.require(["ace/ext/searchbox"], function() {});
+                })();
+            

+ 622 - 0
services/web/public/js/ace/ext-settings_menu.js

@@ -0,0 +1,622 @@
+define("ace/ext/menu_tools/element_generator",["require","exports","module"], function(require, exports, module) {
+'use strict';
+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;
+};
+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;
+};
+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;
+};
+module.exports.createLabel = function createLabel (text, labelFor) {
+    var el = document.createElement('label');
+    el.setAttribute('for', labelFor);
+    el.textContent = text;
+    return el;
+};
+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;
+};
+
+});
+
+define("ace/ext/modelist",["require","exports","module"], function(require, exports, module) {
+"use strict";
+
+var modes = [];
+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);
+};
+var supportedModes = {
+    ABAP:        ["abap"],
+    ActionScript:["as"],
+    ADA:         ["ada|adb"],
+    Apache_Conf: ["^htaccess|^htgroups|^htpasswd|^conf|htaccess|htgroups|htpasswd"],
+    AsciiDoc:    ["asciidoc"],
+    Assembly_x86:["asm"],
+    AutoHotKey:  ["ahk"],
+    BatchFile:   ["bat|cmd"],
+    C9Search:    ["c9search_results"],
+    C_Cpp:       ["cpp|c|cc|cxx|h|hh|hpp"],
+    Cirru:       ["cirru|cr"],
+    Clojure:     ["clj|cljs"],
+    Cobol:       ["CBL|COB"],
+    coffee:      ["coffee|cf|cson|^Cakefile"],
+    ColdFusion:  ["cfm"],
+    CSharp:      ["cs"],
+    CSS:         ["css"],
+    Curly:       ["curly"],
+    D:           ["d|di"],
+    Dart:        ["dart"],
+    Diff:        ["diff|patch"],
+    Dockerfile:  ["^Dockerfile"],
+    Dot:         ["dot"],
+    Erlang:      ["erl|hrl"],
+    EJS:         ["ejs"],
+    Forth:       ["frt|fs|ldr"],
+    FTL:         ["ftl"],
+    Gherkin:     ["feature"],
+    Gitignore:   ["^.gitignore"],
+    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"],
+    MEL:         ["mel"],
+    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"],
+    Smarty:      ["smarty|tpl"],
+    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"],
+    Vala:        ["vala"],
+    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).replace(/_/g, " ");
+    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
+};
+
+});
+
+define("ace/ext/themelist",["require","exports","module","ace/lib/fixoldbrowsers"], function(require, exports, module) {
+"use strict";
+require("ace/lib/fixoldbrowsers");
+
+var themeData = [
+    ["Chrome"         ],
+    ["Clouds"         ],
+    ["Crimson Editor" ],
+    ["Dawn"           ],
+    ["Dreamweaver"    ],
+    ["Eclipse"        ],
+    ["GitHub"         ],
+    ["Solarized Light"],
+    ["TextMate"       ],
+    ["Tomorrow"       ],
+    ["XCode"          ],
+    ["Kuroir"],
+    ["KatzenMilch"],
+    ["Ambiance"             ,"ambiance"                ,  "dark"],
+    ["Chaos"                ,"chaos"                   ,  "dark"],
+    ["Clouds Midnight"      ,"clouds_midnight"         ,  "dark"],
+    ["Cobalt"               ,"cobalt"                  ,  "dark"],
+    ["idle Fingers"         ,"idle_fingers"            ,  "dark"],
+    ["krTheme"              ,"kr_theme"                ,  "dark"],
+    ["Merbivore"            ,"merbivore"               ,  "dark"],
+    ["Merbivore Soft"       ,"merbivore_soft"          ,  "dark"],
+    ["Mono Industrial"      ,"mono_industrial"         ,  "dark"],
+    ["Monokai"              ,"monokai"                 ,  "dark"],
+    ["Pastel on dark"       ,"pastel_on_dark"          ,  "dark"],
+    ["Solarized Dark"       ,"solarized_dark"          ,  "dark"],
+    ["Terminal"             ,"terminal"                ,  "dark"],
+    ["Tomorrow Night"       ,"tomorrow_night"          ,  "dark"],
+    ["Tomorrow Night Blue"  ,"tomorrow_night_blue"     ,  "dark"],
+    ["Tomorrow Night Bright","tomorrow_night_bright"   ,  "dark"],
+    ["Tomorrow Night 80s"   ,"tomorrow_night_eighties" ,  "dark"],
+    ["Twilight"             ,"twilight"                ,  "dark"],
+    ["Vibrant Ink"          ,"vibrant_ink"             ,  "dark"]
+];
+
+
+exports.themesByName = {};
+exports.themes = themeData.map(function(data) {
+    var name = data[1] || data[0].replace(/ /g, "_").toLowerCase();
+    var theme = {
+        caption: data[0],
+        theme: "ace/theme/" + name,
+        isDark: data[2] == "dark",
+        name: name
+    };
+    exports.themesByName[name] = theme;
+    return theme;
+});
+
+});
+
+define("ace/ext/menu_tools/add_editor_menu_options",["require","exports","module","ace/ext/modelist","ace/ext/themelist"], function(require, exports, module) {
+'use strict';
+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"
+        }, {
+            textContent: "textarea",
+            value: "ace/keyboard/textarea"
+        }, {
+            textContent: "sublime",
+            value: "ace/keyboard/sublime"
+        }]
+    };
+
+    editor.menuOptions.setTheme = themelist.themes.map(function(theme) {
+        return {
+            textContent: theme.caption,
+            value: theme.theme
+        };
+    });
+
+    editor.menuOptions.setMode = modelist.modes.map(function(mode) {
+        return {
+            textContent: mode.name,
+            value: mode.mode
+        };
+    });
+};
+
+
+});
+
+define("ace/ext/menu_tools/get_set_functions",["require","exports","module"], function(require, exports, module) {
+'use strict';
+module.exports.getSetFunctions = function getSetFunctions (editor) {
+    var out = [];
+    var my = {
+        'editor' : editor,
+        'session' : editor.session,
+        'renderer' : editor.renderer
+    };
+    var opts = [];
+    var skip = [
+        'setOption',
+        'setUndoManager',
+        'setDocument',
+        'setValue',
+        'setBreakpoints',
+        'setScrollTop',
+        'setScrollLeft',
+        'setSelectionStyle',
+        'setWrapLimitRange'
+    ];
+    ['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) {
+                    opts.push(fn);
+                    out.push({
+                        'functionName' : fn,
+                        'parentObj' : esr,
+                        'parentName' : clss
+                    });
+                }
+            }
+        }
+    });
+    return out;
+};
+
+});
+
+define("ace/ext/menu_tools/generate_settings_menu",["require","exports","module","ace/ext/menu_tools/element_generator","ace/ext/menu_tools/add_editor_menu_options","ace/ext/menu_tools/get_set_functions"], 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;
+module.exports.generateSettingsMenu = function generateSettingsMenu (editor) {
+    var elements = [];
+    function cleanupElementsList() {
+        elements.sort(function(a, b) {
+            var x = a.getAttribute('contains');
+            var y = b.getAttribute('contains');
+            return x.localeCompare(y);
+        });
+    }
+    function wrapElements() {
+        var topmenu = document.createElement('div');
+        topmenu.setAttribute('id', 'ace_settingsmenu');
+        elements.forEach(function(element) {
+            topmenu.appendChild(element);
+        });
+        return topmenu;
+    }
+    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{
+                    obj[e.target.id](!!e.target.checked);
+                } catch (err) {
+                    throw new Error(err);
+                }
+            });
+        } else {
+            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;
+    }
+    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);
+    }
+    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) {
+            elements.push(makeDropdown(item, esr, clss, fn));
+        } else if(typeof esr[fn] === 'function') {
+            try {
+                val = esr[fn]();
+                if(typeof val === 'object') {
+                    val = val.$id;
+                }
+                elements.push(
+                    createNewEntry(esr, clss, item, val)
+                );
+            } catch (e) {
+            }
+        }
+    }
+    addEditorMenuOptions(editor);
+    getSetFunctions(editor).forEach(function(setObj) {
+        handleSet(setObj);
+    });
+    cleanupElementsList();
+    return wrapElements();
+};
+
+});
+
+define("ace/ext/menu_tools/overlay_page",["require","exports","module","ace/lib/dom"], function(require, exports, module) {
+'use strict';
+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/settings_menu",["require","exports","module","ace/ext/menu_tools/generate_settings_menu","ace/ext/menu_tools/overlay_page","ace/editor"], function(require, exports, module) {
+"use strict";
+var generateSettingsMenu = require('./menu_tools/generate_settings_menu').generateSettingsMenu;
+var overlayPage = require('./menu_tools/overlay_page').overlayPage;
+function showSettingsMenu(editor) {
+    var sm = document.getElementById('ace_settingsmenu');
+    if (!sm)    
+        overlayPage(editor, generateSettingsMenu(editor), '0', '0', '0');
+}
+module.exports.init = function(editor) {
+    var Editor = require("ace/editor").Editor;
+    Editor.prototype.showSettingsMenu = function() {
+        showSettingsMenu(this);
+    };
+};
+});
+;
+                (function() {
+                    window.require(["ace/ext/settings_menu"], function() {});
+                })();
+            

+ 6 - 3
services/web/public/js/ace/ext/spellcheck.js → services/web/public/js/ace/ext-spellcheck.js

@@ -1,4 +1,4 @@
-define(function(require, exports, module) {
+define("ace/ext/spellcheck",["require","exports","module","ace/lib/event","ace/editor","ace/config"], function(require, exports, module) {
 "use strict";
 var event = require("../lib/event");
 
@@ -49,7 +49,6 @@ exports.contextMenuHandler = function(e){
         return newVal;
     });
 };
-// todo support highlighting with typo.js
 var Editor = require("../editor").Editor;
 require("../config").defineOptions(Editor.prototype, "editor", {
     spellcheck: {
@@ -66,4 +65,8 @@ require("../config").defineOptions(Editor.prototype, "editor", {
 });
 
 });
-
+;
+                (function() {
+                    window.require(["ace/ext/spellcheck"], function() {});
+                })();
+            

+ 12 - 138
services/web/public/js/ace/split.js → services/web/public/js/ace/ext-split.js

@@ -1,34 +1,4 @@
-/* ***** 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) {
+define("ace/split",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/lib/event_emitter","ace/editor","ace/virtual_renderer","ace/edit_session"], function(require, exports, module) {
 "use strict";
 
 var oop = require("./lib/oop");
@@ -39,13 +9,6 @@ var Editor = require("./editor").Editor;
 var Renderer = require("./virtual_renderer").VirtualRenderer;
 var EditSession = require("./edit_session").EditSession;
 
-/** 
- * @class Split
- *
- *
- *
- **/
-
 
 var Split = function(container, theme, splits) {
     this.BELOW = 1;
@@ -115,97 +78,37 @@ var Split = function(container, theme, splits) {
         }
         this.resize();
     };
-
-    /**
-     * 
-     * Returns the number of splits.
-     * @returns {Number}
-     **/
     this.getSplits = function() {
         return this.$splits;
     };
-
-    /**
-     * @param {Number} idx The index of the editor you want
-     *
-     * Returns the editor identified by the index `idx`.
-     *
-     **/
     this.getEditor = function(idx) {
         return this.$editors[idx];
     };
-
-    /**
-     * 
-     * Returns the current editor.
-     * @returns {Editor}
-     **/
     this.getCurrentEditor = function() {
         return this.$cEditor;
     };
-
-    /** 
-     * Focuses the current editor.
-     * @related Editor.focus
-     **/
     this.focus = function() {
         this.$cEditor.focus();
     };
-
-    /** 
-     * Blurs the current editor.
-     * @related Editor.blur
-     **/
     this.blur = function() {
         this.$cEditor.blur();
     };
-
-    /** 
-     * 
-     * @param {String} theme The name of the theme to set
-     * 
-     * Sets a theme for each of the available editors.
-     * @related Editor.setTheme
-     **/
     this.setTheme = function(theme) {
         this.$editors.forEach(function(editor) {
             editor.setTheme(theme);
         });
     };
-
-    /** 
-     * 
-     * @param {String} keybinding 
-     * 
-     * Sets the keyboard handler for the editor.
-     * @related editor.setKeyboardHandler
-     **/
     this.setKeyboardHandler = function(keybinding) {
         this.$editors.forEach(function(editor) {
             editor.setKeyboardHandler(keybinding);
         });
     };
-
-    /** 
-     * 
-     * @param {Function} callback A callback function to execute
-     * @param {String} scope The default scope for the callback
-     * 
-     * Executes `callback` on all of the available editors. 
-     *
-     **/
     this.forEach = function(callback, scope) {
         this.$editors.forEach(callback, scope);
     };
 
 
     this.$fontSize = "";
-    /** 
-     * @param {Number} size The new font size
-     * 
-     * Sets the font size, in pixels, for all the available editors.
-     *
-     **/
     this.setFontSize = function(size) {
         this.$fontSize = size;
         this.forEach(function(editor) {
@@ -221,12 +124,7 @@ var Split = function(container, theme, splits) {
             var undoManagerProxy = new UndoManagerProxy(undoManager, s);
             s.setUndoManager(undoManagerProxy);
         }
-
-        // Overwrite the default $informUndoManager function such that new delas
-        // aren't added to the undo manager from the new and the old session.
         s.$informUndoManager = lang.delayedCall(function() { s.$deltas = []; });
-
-        // Copy over 'settings' from the session.
         s.setTabSize(session.getTabSize());
         s.setUseSoftTabs(session.getUseSoftTabs());
         s.setOverwrite(session.getOverwrite());
@@ -239,15 +137,6 @@ var Split = function(container, theme, splits) {
 
         return s;
     };
-
-   /** 
-     * 
-     * @param {EditSession} session The new edit session
-     * @param {Number} idx The editor's index you're interested in
-     * 
-     * Sets a new [[EditSession `EditSession`]] for the indicated editor.
-     * @related Editor.setSession
-     **/
     this.setSession = function(session, idx) {
         var editor;
         if (idx == null) {
@@ -255,12 +144,6 @@ var Split = function(container, theme, splits) {
         } else {
             editor = this.$editors[idx];
         }
-
-        // Check if the session is used already by any of the editors in the
-        // split. If it is, we have to clone the session as two editors using
-        // the same session can cause terrible side effects (e.g. UndoQueue goes
-        // wrong). This also gives the user of Split the possibility to treat
-        // each session on each split editor different.
         var isUsed = this.$editors.some(function(editor) {
            return editor.session === session;
         });
@@ -269,27 +152,11 @@ var Split = function(container, theme, splits) {
             session = this.$cloneSession(session);
         }
         editor.setSession(session);
-
-        // Return the session set on the editor. This might be a cloned one.
         return session;
     };
-
-   /** 
-     * 
-     * Returns the orientation.
-     * @returns {Number}
-     **/
     this.getOrientation = function() {
         return this.$orientation;
     };
-
-   /** 
-     * 
-     * Sets the orientation.
-     * @param {Number} orientation The new orientation value
-     *
-     *
-     **/
     this.setOrientation = function(orientation) {
         if (this.$orientation == orientation) {
             return;
@@ -297,10 +164,6 @@ var Split = function(container, theme, splits) {
         this.$orientation = orientation;
         this.resize();
     };
-
-   /**  
-     * Resizes the editor.
-     **/
     this.resize = function() {
         var width = this.$container.clientWidth;
         var height = this.$container.clientHeight;
@@ -371,3 +234,14 @@ function UndoManagerProxy(undoManager, session) {
 
 exports.Split = Split;
 });
+
+define("ace/ext/split",["require","exports","module","ace/split"], function(require, exports, module) {
+"use strict";
+module.exports = require("../split");
+
+});
+;
+                (function() {
+                    window.require(["ace/ext/split"], function() {});
+                })();
+            

+ 36 - 69
services/web/public/js/ace/ext/static_highlight.js → services/web/public/js/ace/ext-static_highlight.js

@@ -1,39 +1,36 @@
-/* ***** 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) {
+define("ace/ext/static_highlight",["require","exports","module","ace/edit_session","ace/layer/text","ace/config","ace/lib/dom"], function(require, exports, module) {
 "use strict";
 
 var EditSession = require("../edit_session").EditSession;
 var TextLayer = require("../layer/text").Text;
-var baseStyles = require("../requirejs/text!./static.css");
+var baseStyles = ".ace_static_highlight {\
+font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', 'Droid Sans Mono', monospace;\
+font-size: 12px;\
+}\
+.ace_static_highlight .ace_gutter {\
+width: 25px !important;\
+display: block;\
+float: left;\
+text-align: right;\
+padding: 0 3px 0 0;\
+margin-right: 3px;\
+position: static !important;\
+}\
+.ace_static_highlight .ace_line { clear: both; }\
+.ace_static_highlight .ace_gutter-cell {\
+-moz-user-select: -moz-none;\
+-khtml-user-select: none;\
+-webkit-user-select: none;\
+user-select: none;\
+}\
+.ace_static_highlight .ace_gutter-cell:before {\
+content: counter(ace_line, decimal);\
+counter-increment: ace_line;\
+}\
+.ace_static_highlight {\
+counter-reset: ace_line;\
+}\
+";
 var config = require("../config");
 var dom = require("../lib/dom");
 
@@ -79,32 +76,9 @@ var highlight = function(el, opts, callback) {
     });
 };
 
-/**
- * Transforms a given input code snippet into HTML using the given mode
- *
- * @param {string} input Code snippet
- * @param {string|mode} mode String specifying the mode to load such as
- *  `ace/mode/javascript` or, a mode loaded from `/ace/mode`
- *  (use 'ServerSideHiglighter.getMode').
- * @param {string|theme} theme String specifying the theme to load such as
- *  `ace/theme/twilight` or, a theme loaded from `/ace/theme`.
- * @param {number} lineStart A number indicating the first line number. Defaults
- *  to 1.
- * @param {boolean} disableGutter Specifies whether or not to disable the gutter.
- *  `true` disables the gutter, `false` enables the gutter. Defaults to `false`.
- * @param {function} callback When specifying the mode or theme as a string,
- *  this method has no return value and you must specify a callback function. The
- *  callback will receive the rendered object containing the properties `html`
- *  and `css`.
- * @returns {object} An object containing the properties `html` and `css`.
- */
-
 highlight.render = function(input, mode, theme, lineStart, disableGutter, callback) {
-    var waiting = 0;
+    var waiting = 1;
     var modeCache = EditSession.prototype.$modes;
-
-    // if either the theme or the mode were specified as objects
-    // then we need to lazily load them.
     if (typeof theme == "string") {
         waiting++;
         config.loadModule(['theme', theme], function(m) {
@@ -121,23 +95,13 @@ highlight.render = function(input, mode, theme, lineStart, disableGutter, callba
             --waiting || done();
         });
     }
-
-    // loads or passes the specified mode module then calls renderer
     function done() {
         var result = highlight.renderSync(input, mode, theme, lineStart, disableGutter);
         return callback ? callback(result) : result;
     }
-    return waiting || done();
+    return --waiting || done();
 };
 
-/* 
- * Transforms a given input code snippet into HTML using the given mode
- * @param {string} input Code snippet
- * @param {mode} mode Mode loaded from /ace/mode (use 'ServerSideHiglighter.getMode')
- * @param {string} r Code snippet
- * @returns {object} An object containing: html, css
- */
-
 highlight.renderSync = function(input, mode, theme, lineStart, disableGutter) {
     lineStart = parseInt(lineStart || 1, 10);
 
@@ -164,8 +128,6 @@ highlight.renderSync = function(input, mode, theme, lineStart, disableGutter) {
         textLayer.$renderLine(stringBuilder, ix, true, false);
         stringBuilder.push("\n</div>");
     }
-
-    // let's prepare the whole html
     var html = "<div class='" + theme.cssClass + "'>" +
         "<div class='ace_static_highlight' style='counter-reset:ace_line " + (lineStart - 1) + "'>" +
             stringBuilder.join("") +
@@ -184,3 +146,8 @@ highlight.renderSync = function(input, mode, theme, lineStart, disableGutter) {
 module.exports = highlight;
 module.exports.highlight =highlight;
 });
+;
+                (function() {
+                    window.require(["ace/ext/static_highlight"], function() {});
+                })();
+            

+ 7 - 3
services/web/public/js/ace/ext/statusbar.js → services/web/public/js/ace/ext-statusbar.js

@@ -1,6 +1,5 @@
-define(function(require, exports, module) {
+define("ace/ext/statusbar",["require","exports","module","ace/lib/dom","ace/lib/lang"], function(require, exports, module) {
 "use strict";
-/** simple statusbar **/
 var dom = require("ace/lib/dom");
 var lang = require("ace/lib/lang");
 
@@ -46,4 +45,9 @@ var StatusBar = function(editor, parentNode) {
 
 exports.StatusBar = StatusBar;
 
-});
+});
+;
+                (function() {
+                    window.require(["ace/ext/statusbar"], function() {});
+                })();
+            

+ 242 - 168
services/web/public/js/ace/ext/textarea.js → services/web/public/js/ace/ext-textarea.js

@@ -1,34 +1,195 @@
-/* ***** 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) {
+define("ace/theme/textmate",["require","exports","module","ace/lib/dom"], function(require, exports, module) {
+"use strict";
+
+exports.isDark = false;
+exports.cssClass = "ace-tm";
+exports.cssText = ".ace-tm .ace_gutter {\
+background: #f0f0f0;\
+color: #333;\
+}\
+.ace-tm .ace_print-margin {\
+width: 1px;\
+background: #e8e8e8;\
+}\
+.ace-tm .ace_fold {\
+background-color: #6B72E6;\
+}\
+.ace-tm {\
+background-color: #FFFFFF;\
+color: black;\
+}\
+.ace-tm .ace_cursor {\
+color: black;\
+}\
+.ace-tm .ace_invisible {\
+color: rgb(191, 191, 191);\
+}\
+.ace-tm .ace_storage,\
+.ace-tm .ace_keyword {\
+color: blue;\
+}\
+.ace-tm .ace_constant {\
+color: rgb(197, 6, 11);\
+}\
+.ace-tm .ace_constant.ace_buildin {\
+color: rgb(88, 72, 246);\
+}\
+.ace-tm .ace_constant.ace_language {\
+color: rgb(88, 92, 246);\
+}\
+.ace-tm .ace_constant.ace_library {\
+color: rgb(6, 150, 14);\
+}\
+.ace-tm .ace_invalid {\
+background-color: rgba(255, 0, 0, 0.1);\
+color: red;\
+}\
+.ace-tm .ace_support.ace_function {\
+color: rgb(60, 76, 114);\
+}\
+.ace-tm .ace_support.ace_constant {\
+color: rgb(6, 150, 14);\
+}\
+.ace-tm .ace_support.ace_type,\
+.ace-tm .ace_support.ace_class {\
+color: rgb(109, 121, 222);\
+}\
+.ace-tm .ace_keyword.ace_operator {\
+color: rgb(104, 118, 135);\
+}\
+.ace-tm .ace_string {\
+color: rgb(3, 106, 7);\
+}\
+.ace-tm .ace_comment {\
+color: rgb(76, 136, 107);\
+}\
+.ace-tm .ace_comment.ace_doc {\
+color: rgb(0, 102, 255);\
+}\
+.ace-tm .ace_comment.ace_doc.ace_tag {\
+color: rgb(128, 159, 191);\
+}\
+.ace-tm .ace_constant.ace_numeric {\
+color: rgb(0, 0, 205);\
+}\
+.ace-tm .ace_variable {\
+color: rgb(49, 132, 149);\
+}\
+.ace-tm .ace_xml-pe {\
+color: rgb(104, 104, 91);\
+}\
+.ace-tm .ace_entity.ace_name.ace_function {\
+color: #0000A2;\
+}\
+.ace-tm .ace_heading {\
+color: rgb(12, 7, 255);\
+}\
+.ace-tm .ace_list {\
+color:rgb(185, 6, 144);\
+}\
+.ace-tm .ace_meta.ace_tag {\
+color:rgb(0, 22, 142);\
+}\
+.ace-tm .ace_string.ace_regex {\
+color: rgb(255, 0, 0)\
+}\
+.ace-tm .ace_marker-layer .ace_selection {\
+background: rgb(181, 213, 255);\
+}\
+.ace-tm.ace_multiselect .ace_selection.ace_start {\
+box-shadow: 0 0 3px 0px white;\
+border-radius: 2px;\
+}\
+.ace-tm .ace_marker-layer .ace_step {\
+background: rgb(252, 255, 0);\
+}\
+.ace-tm .ace_marker-layer .ace_stack {\
+background: rgb(164, 229, 101);\
+}\
+.ace-tm .ace_marker-layer .ace_bracket {\
+margin: -1px 0 0 -1px;\
+border: 1px solid rgb(192, 192, 192);\
+}\
+.ace-tm .ace_marker-layer .ace_active-line {\
+background: rgba(0, 0, 0, 0.07);\
+}\
+.ace-tm .ace_gutter-active-line {\
+background-color : #dcdcdc;\
+}\
+.ace-tm .ace_marker-layer .ace_selected-word {\
+background: rgb(250, 250, 255);\
+border: 1px solid rgb(200, 200, 250);\
+}\
+.ace-tm .ace_indent-guide {\
+background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y;\
+}\
+";
+
+var dom = require("../lib/dom");
+dom.importCssString(exports.cssText, exports.cssClass);
+});
+
+define("ace/ace",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/dom","ace/lib/event","ace/editor","ace/edit_session","ace/undomanager","ace/virtual_renderer","ace/worker/worker_client","ace/keyboard/hash_handler","ace/placeholder","ace/multi_select","ace/mode/folding/fold_mode","ace/theme/textmate","ace/ext/error_marker","ace/config"], function(require, exports, module) {
+"use strict";
+
+require("./lib/fixoldbrowsers");
+
+var dom = require("./lib/dom");
+var event = require("./lib/event");
+
+var Editor = require("./editor").Editor;
+var EditSession = require("./edit_session").EditSession;
+var UndoManager = require("./undomanager").UndoManager;
+var Renderer = require("./virtual_renderer").VirtualRenderer;
+require("./worker/worker_client");
+require("./keyboard/hash_handler");
+require("./placeholder");
+require("./multi_select");
+require("./mode/folding/fold_mode");
+require("./theme/textmate");
+require("./ext/error_marker");
+
+exports.config = require("./config");
+exports.require = require;
+exports.edit = function(el) {
+    if (typeof(el) == "string") {
+        var _id = el;
+        el = document.getElementById(_id);
+        if (!el)
+            throw new Error("ace.edit can't find div #" + _id);
+    }
+
+    if (el.env && el.env.editor instanceof Editor)
+        return el.env.editor;
+
+    var doc = exports.createEditSession(dom.getInnerText(el));
+    el.innerHTML = '';
+
+    var editor = new Editor(new Renderer(el));
+    editor.setSession(doc);
+
+    var env = {
+        document: doc,
+        editor: editor,
+        onResize: editor.resize.bind(editor, null)
+    };
+    event.addListener(window, "resize", env.onResize);
+    editor.on("destroy", function() {
+        event.removeListener(window, "resize", env.onResize);
+    });
+    el.env = editor.env = env;
+    return editor;
+};
+exports.createEditSession = function(text, mode) {
+    var doc = new EditSession(text, mode);
+    doc.setUndoManager(new UndoManager());
+    return doc;
+}
+exports.EditSession = EditSession;
+exports.UndoManager = UndoManager;
+});
+
+define("ace/ext/textarea",["require","exports","module","ace/lib/event","ace/lib/useragent","ace/lib/net","ace/ace","ace/theme/textmate"], function(require, exports, module) {
 "use strict";
 
 var event = require("../lib/event");
@@ -39,16 +200,6 @@ var ace = require("../ace");
 require("../theme/textmate");
 
 module.exports = exports = ace;
-
-/*
- * Returns the CSS property of element.
- *   1) If the CSS property is on the style object of the element, use it, OR
- *   2) Compute the CSS property
- *
- * If the property can't get computed, is 'auto' or 'intrinsic', the former
- * calculated property is used (this can happen in cases where the textarea
- * is hidden and has no dimension styles).
- */
 var getCSSProperty = function(element, container, property) {
     var ret = element.style[property];
 
@@ -78,19 +229,7 @@ function setupContainer(element, getValue) {
     }
 
     var parentNode = element.parentNode;
-
-    // This will hold the editor.
     var container = document.createElement('div');
-
-    // To put Ace in the place of the textarea, we have to copy a few of the
-    // textarea's style attributes to the div container.
-    //
-    // The problem is that the properties have to get computed (they might be
-    // defined by a CSS file on the page - you can't access such rules that
-    // apply to an element via elm.style). Computed properties are converted to
-    // pixels although the dimension might be given as percentage. When the
-    // window resizes, the dimensions defined by percentages changes, so the
-    // properties have to get recomputed to get the new/true pixels.
     var resizeEvent = function() {
         var style = 'position:relative;';
         [
@@ -99,51 +238,20 @@ function setupContainer(element, getValue) {
             style += item + ':' +
                         getCSSProperty(element, container, item) + ';';
         });
-
-        // Calculating the width/height of the textarea is somewhat tricky. To
-        // do it right, you have to include the paddings to the sides as well
-        // (eg. width = width + padding-left, -right).  This works well, as
-        // long as the width of the element is not set or given in pixels. In
-        // this case and after the textarea is hidden, getCSSProperty(element,
-        // container, 'width') will still return pixel value. If the element
-        // has realtiv dimensions (e.g. width='95<percent>')
-        // getCSSProperty(...) will return pixel values only as long as the
-        // textarea is visible. After it is hidden getCSSProperty will return
-        // the relative dimensions as they are set on the element (in the case
-        // of width, 95<percent>).
-        // Making the sum of pixel vaules (e.g. padding) and realtive values
-        // (e.g. <percent>) is not possible. As such the padding styles are
-        // ignored.
-
-        // The complete width is the width of the textarea + the padding
-        // to the left and right.
         var width = getCSSProperty(element, container, 'width') || (element.clientWidth + "px");
         var height = getCSSProperty(element, container, 'height')  || (element.clientHeight + "px");
         style += 'height:' + height + ';width:' + width + ';';
-
-        // Set the display property to 'inline-block'.
         style += 'display:inline-block;';
         container.setAttribute('style', style);
     };
     event.addListener(window, 'resize', resizeEvent);
-
-    // Call the resizeEvent once, so that the size of the container is
-    // calculated.
     resizeEvent();
-
-    // Insert the div container after the element.
     parentNode.insertBefore(container, element.nextSibling);
-
-    // Override the forms onsubmit function. Set the innerHTML and value
-    // of the textarea before submitting.
     while (parentNode !== document) {
         if (parentNode.tagName.toUpperCase() === 'FORM') {
             var oldSumit = parentNode.onsubmit;
-            // Override the onsubmit function of the form.
             parentNode.onsubmit = function(evt) {
                 element.value = getValue();
-                // If there is a onsubmit function already, then call
-                // it with the current context and pass the event.
                 if (oldSumit) {
                     oldSumit.call(this, evt);
                 }
@@ -155,17 +263,13 @@ function setupContainer(element, getValue) {
     return container;
 }
 
-exports.transformTextarea = function(element, loader) {
+exports.transformTextarea = function(element, options) {
     var session;
     var container = setupContainer(element, function() {
         return session.getValue();
     });
-
-    // Hide the element.
     element.style.display = 'none';
     container.style.background = 'white';
-
-    //
     var editorDiv = document.createElement("div");
     applyStyles(editorDiv, {
         top: "0px",
@@ -215,23 +319,15 @@ exports.transformTextarea = function(element, loader) {
     applyStyles(settingDiv, settingDivStyles);
     container.appendChild(settingDiv);
 
-    // Power up ace on the textarea:
-    var options = {};
-
+    options = options || exports.defaultOptions;
     var editor = ace.edit(editorDiv);
     session = editor.getSession();
 
     session.setValue(element.value || element.innerHTML);
     editor.focus();
-
-    // Add the settingPanel opener to the editor's div.
     container.appendChild(settingOpener);
-
-    // Create the API.
-    setupApi(editor, editorDiv, settingDiv, ace, options, loader);
-
-    // Create the setting's panel.
-    setupSettingPanel(settingDiv, settingOpener, editor, options);
+    setupApi(editor, editorDiv, settingDiv, ace, options, load);
+    setupSettingPanel(settingDiv, settingOpener, editor);
 
     var state = "";
     event.addListener(settingOpener, "mousemove", function(e) {
@@ -296,37 +392,15 @@ function setupApi(editor, editorDiv, settingDiv, ace, options, loader) {
     };
 
     editor.$setOption = editor.setOption;
+    editor.$getOption = editor.getOption;
     editor.setOption = function(key, value) {
-        if (options[key] == value) return;
-
         switch (key) {
             case "mode":
-                if (value != "text") {
-                    // Load the required mode file. Files get loaded only once.
-                    loader("mode-" + value + ".js", "ace/mode/" + value, function() {
-                        var aceMode = require("../mode/" + value).Mode;
-                        session.setMode(new aceMode());
-                    });
-                } else {
-                    session.setMode(new (require("../mode/text").Mode));
-                }
+                editor.$setOption("mode", "ace/mode/" + value)
             break;
-
             case "theme":
-                if (value != "textmate") {
-                    // Load the required theme file. Files get loaded only once.
-                    loader("theme-" + value + ".js", "ace/theme/" + value, function() {
-                        editor.setTheme("ace/theme/" + value);
-                    });
-                } else {
-                    editor.setTheme("ace/theme/textmate");
-                }
+                editor.$setOption("theme", "ace/theme/" + value)
             break;
-
-            case "fontSize":
-                editorDiv.style.fontSize = value;
-            break;
-
             case "keybindings":
                 switch (value) {
                     case "vim":
@@ -341,58 +415,55 @@ function setupApi(editor, editorDiv, settingDiv, ace, options, loader) {
             break;
 
             case "softWrap":
-                switch (value) {
-                    case "off":
-                        session.setUseWrapMode(false);
-                        renderer.setPrintMarginColumn(80);
-                    break;
-                    case "40":
-                        session.setUseWrapMode(true);
-                        session.setWrapLimitRange(40, 40);
-                        renderer.setPrintMarginColumn(40);
-                    break;
-                    case "80":
-                        session.setUseWrapMode(true);
-                        session.setWrapLimitRange(80, 80);
-                        renderer.setPrintMarginColumn(80);
-                    break;
-                    case "free":
-                        session.setUseWrapMode(true);
-                        session.setWrapLimitRange(null, null);
-                        renderer.setPrintMarginColumn(80);
-                    break;
-                }
+            case "fontSize":
+                editor.$setOption(key, value);
             break;
             
             default:
                 editor.$setOption(key, toBool(value));
         }
-
-        options[key] = value;
     };
 
     editor.getOption = function(key) {
-        return options[key];
-    };
+        switch (key) {
+            case "mode":
+                return editor.$getOption("mode").substr("ace/mode/".length)
+            break;
 
-    editor.getOptions = function() {
-        return options;
-    };
+            case "theme":
+                return editor.$getOption("theme").substr("ace/theme/".length)
+            break;
 
-    editor.setOptions(exports.options);
+            case "keybindings":
+                var value = editor.getKeyboardHandler()
+                switch (value && value.$id) {
+                    case "ace/keyboard/vim":
+                        return "vim";
+                    case "ace/keyboard/emacs":
+                        return "emacs";
+                    default:
+                        return "ace";
+                }
+            break;
 
+            default:
+                return editor.$getOption(key);
+        }
+    };
+
+    editor.setOptions(options);
     return editor;
 }
 
-function setupSettingPanel(settingDiv, settingOpener, editor, options) {
+function setupSettingPanel(settingDiv, settingOpener, editor) {
     var BOOL = null;
 
     var desc = {
         mode:            "Mode:",
-        gutter:          "Display Gutter:",
+        wrap:            "Soft Wrap:",
         theme:           "Theme:",
         fontSize:        "Font Size:",
-        softWrap:        "Soft Wrap:",
+        showGutter:      "Display Gutter:",
         keybindings:     "Keyboard",
         showPrintMargin: "Show Print Margin:",
         useSoftTabs:     "Use Soft Tabs:",
@@ -445,7 +516,7 @@ function setupSettingPanel(settingDiv, settingOpener, editor, options) {
             twilight:         "Twilight",
             vibrant_ink:      "Vibrant Ink"
         },
-        gutter: BOOL,
+        showGutter: BOOL,
         fontSize: {
             "10px": "10px",
             "11px": "11px",
@@ -453,7 +524,7 @@ function setupSettingPanel(settingDiv, settingOpener, editor, options) {
             "14px": "14px",
             "16px": "16px"
         },
-        softWrap: {
+        wrap: {
             off:    "Off",
             40:     "40",
             80:     "80",
@@ -476,7 +547,7 @@ function setupSettingPanel(settingDiv, settingOpener, editor, options) {
         if (!obj) {
             builder.push(
                 "<input type='checkbox' title='", option, "' ",
-                    cValue == "true" ? "checked='true'" : "",
+                    cValue + "" == "true" ? "checked='true'" : "",
                "'></input>"
             );
             return;
@@ -496,10 +567,10 @@ function setupSettingPanel(settingDiv, settingOpener, editor, options) {
         builder.push("</select>");
     }
 
-    for (var option in options) {
+    for (var option in exports.defaultOptions) {
         table.push("<tr><td>", desc[option], "</td>");
         table.push("<td>");
-        renderOption(table, option, optionValues[option], options[option]);
+        renderOption(table, option, optionValues[option], editor.getOption(option));
         table.push("</td></tr>");
     }
     table.push("</table>");
@@ -530,14 +601,12 @@ function setupSettingPanel(settingDiv, settingOpener, editor, options) {
     settingDiv.appendChild(button);
     settingDiv.hideButton = button;
 }
-
-// Default startup options.
-exports.options = {
-    mode:               "text",
+exports.defaultOptions = {
+    mode:               "javascript",
     theme:              "textmate",
-    gutter:             "false",
+    wrap:               "off",
     fontSize:           "12px",
-    softWrap:           "off",
+    showGutter:         "false",
     keybindings:        "ace",
     showPrintMargin:    "false",
     useSoftTabs:        "true",
@@ -545,3 +614,8 @@ exports.options = {
 };
 
 });
+;
+                (function() {
+                    window.require(["ace/ext/textarea"], function() {});
+                })();
+            

+ 59 - 0
services/web/public/js/ace/ext-themelist.js

@@ -0,0 +1,59 @@
+define("ace/ext/themelist",["require","exports","module","ace/lib/fixoldbrowsers"], function(require, exports, module) {
+"use strict";
+require("ace/lib/fixoldbrowsers");
+
+var themeData = [
+    ["Chrome"         ],
+    ["Clouds"         ],
+    ["Crimson Editor" ],
+    ["Dawn"           ],
+    ["Dreamweaver"    ],
+    ["Eclipse"        ],
+    ["GitHub"         ],
+    ["Solarized Light"],
+    ["TextMate"       ],
+    ["Tomorrow"       ],
+    ["XCode"          ],
+    ["Kuroir"],
+    ["KatzenMilch"],
+    ["Ambiance"             ,"ambiance"                ,  "dark"],
+    ["Chaos"                ,"chaos"                   ,  "dark"],
+    ["Clouds Midnight"      ,"clouds_midnight"         ,  "dark"],
+    ["Cobalt"               ,"cobalt"                  ,  "dark"],
+    ["idle Fingers"         ,"idle_fingers"            ,  "dark"],
+    ["krTheme"              ,"kr_theme"                ,  "dark"],
+    ["Merbivore"            ,"merbivore"               ,  "dark"],
+    ["Merbivore Soft"       ,"merbivore_soft"          ,  "dark"],
+    ["Mono Industrial"      ,"mono_industrial"         ,  "dark"],
+    ["Monokai"              ,"monokai"                 ,  "dark"],
+    ["Pastel on dark"       ,"pastel_on_dark"          ,  "dark"],
+    ["Solarized Dark"       ,"solarized_dark"          ,  "dark"],
+    ["Terminal"             ,"terminal"                ,  "dark"],
+    ["Tomorrow Night"       ,"tomorrow_night"          ,  "dark"],
+    ["Tomorrow Night Blue"  ,"tomorrow_night_blue"     ,  "dark"],
+    ["Tomorrow Night Bright","tomorrow_night_bright"   ,  "dark"],
+    ["Tomorrow Night 80s"   ,"tomorrow_night_eighties" ,  "dark"],
+    ["Twilight"             ,"twilight"                ,  "dark"],
+    ["Vibrant Ink"          ,"vibrant_ink"             ,  "dark"]
+];
+
+
+exports.themesByName = {};
+exports.themes = themeData.map(function(data) {
+    var name = data[1] || data[0].replace(/ /g, "_").toLowerCase();
+    var theme = {
+        caption: data[0],
+        theme: "ace/theme/" + name,
+        isDark: data[2] == "dark",
+        name: name
+    };
+    exports.themesByName[name] = theme;
+    return theme;
+});
+
+});
+;
+                (function() {
+                    window.require(["ace/ext/themelist"], function() {});
+                })();
+            

+ 11 - 44
services/web/public/js/ace/ext/whitespace.js → services/web/public/js/ace/ext-whitespace.js

@@ -1,39 +1,7 @@
-/* ***** 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) {
+define("ace/ext/whitespace",["require","exports","module","ace/lib/lang"], function(require, exports, module) {
 "use strict";
 
 var lang = require("../lib/lang");
-
-// based on http://www.freehackers.org/Indent_Finder
 exports.$detectIndentation = function(lines, fallback) {
     var stats = [];
     var changes = [];
@@ -42,11 +10,9 @@ exports.$detectIndentation = function(lines, fallback) {
     var max = Math.min(lines.length, 1000);
     for (var i = 0; i < max; i++) {
         var line = lines[i];
-        // ignore empty and comment lines
         if (!/^\s*[^*+\-\s]/.test(line))
             continue;
 
-        var tabs = line.match(/^\t*/)[0].length;
         if (line[0] == "\t")
             tabIndents++;
 
@@ -59,12 +25,10 @@ exports.$detectIndentation = function(lines, fallback) {
             stats[spaces] = (stats[spaces] || 0) + 1;
         }
         prevSpaces = spaces;
-
-        // ignore lines ending with backslash
-        while (line[line.length - 1] == "\\")
+        while (i < max && line[line.length - 1] == "\\")
             line = lines[i++];
     }
-
+    
     function getScore(indent) {
         var score = 0;
         for (var i = indent; i < stats.length; i += indent)
@@ -79,13 +43,12 @@ exports.$detectIndentation = function(lines, fallback) {
     for (var i = 1; i < 12; i++) {
         if (i == 1) {
             spaceIndents = getScore(i);
-            var score = 1;
+            var score = stats.length && 1;
         } else
             var score = getScore(i) / spaceIndents;
 
-        if (changes[i]) {
+        if (changes[i])
             score += changes[i] / changesTotal;
-        }
 
         if (score > first.score)
             first = {score: score, length: i};
@@ -97,7 +60,7 @@ exports.$detectIndentation = function(lines, fallback) {
     if (tabIndents > spaceIndents + 1)
         return {ch: "\t", length: tabLength};
 
-    if (spaceIndents + 1 > tabIndents)
+    if (spaceIndents > tabIndents + 1)
         return {ch: " ", length: tabLength};
 };
 
@@ -187,7 +150,6 @@ exports.commands = [{
     name: "detectIndentation",
     exec: function(editor) {
         exports.detectIndentation(editor.session);
-        // todo show message?
     }
 }, {
     name: "trimTrailingSpace",
@@ -210,3 +172,8 @@ exports.commands = [{
 }];
 
 });
+;
+                (function() {
+                    window.require(["ace/ext/whitespace"], function() {});
+                })();
+            

+ 0 - 415
services/web/public/js/ace/ext/emmet.js

@@ -1,415 +0,0 @@
-/* ***** 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;};
-});
-

+ 0 - 86
services/web/public/js/ace/ext/keybinding_menu.js

@@ -1,86 +0,0 @@
-/* ***** 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();
-            }
-        }]);
-    };
-
-});

+ 0 - 129
services/web/public/js/ace/ext/language_tools.js

@@ -1,129 +0,0 @@
-/* ***** 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
-    }
-});
-
-});

+ 0 - 103
services/web/public/js/ace/ext/menu_tools/add_editor_menu_options.js

@@ -1,103 +0,0 @@
-/* ***** 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
-        };
-    });
-};
-
-
-});

+ 0 - 148
services/web/public/js/ace/ext/menu_tools/element_generator.js

@@ -1,148 +0,0 @@
-/* ***** 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;
-};
-
-});

+ 0 - 258
services/web/public/js/ace/ext/menu_tools/generate_settings_menu.js

@@ -1,258 +0,0 @@
-/* ***** 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();
-};
-
-});

+ 0 - 100
services/web/public/js/ace/ext/menu_tools/get_editor_keyboard_shortcuts.js

@@ -1,100 +0,0 @@
-/* ***** 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;
-};
-
-});

+ 0 - 141
services/web/public/js/ace/ext/menu_tools/get_set_functions.js

@@ -1,141 +0,0 @@
-/* ***** 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;
-};
-
-});

+ 0 - 116
services/web/public/js/ace/ext/menu_tools/overlay_page.js

@@ -1,116 +0,0 @@
-/* ***** 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();
-};
-
-});

+ 0 - 48
services/web/public/js/ace/ext/menu_tools/settings_menu.css

@@ -1,48 +0,0 @@
-#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;
-}

+ 0 - 108
services/web/public/js/ace/ext/old_ie.js

@@ -1,108 +0,0 @@
-/* ***** 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;
-
-});

+ 0 - 77
services/web/public/js/ace/ext/old_ie_test.js

@@ -1,77 +0,0 @@
-/* ***** 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()
-}

+ 0 - 158
services/web/public/js/ace/ext/searchbox.css

@@ -1,158 +0,0 @@
-
-
-/* ------------------------------------------------------------------------------------------
- * 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;
-    white-space: normal;
-}
-.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;
-}

+ 0 - 76
services/web/public/js/ace/ext/settings_menu.js

@@ -1,76 +0,0 @@
-/* ***** 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 Settings Menu
- * @fileOverview Show Settings Menu <br />
- * Displays an interactive settings menu mostly generated on the fly based on
- *  the current state of the editor.
- * @author <a href="mailto:matthewkastor@gmail.com">
- *  Matthew Christopher Kastor-Inare III </a><br />
- *  ☭ Hial Atropa!! ☭
- */
-
-define(function(require, exports, module) {
-"use strict";
-var generateSettingsMenu = require('./menu_tools/generate_settings_menu').generateSettingsMenu;
-var overlayPage = require('./menu_tools/overlay_page').overlayPage;
-/**
- * This displays the settings menu if it is not already being shown.
- * @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 showSettingsMenu(editor) {
-    // make sure the menu isn't open already.
-    var sm = document.getElementById('ace_settingsmenu');
-    if (!sm)    
-        overlayPage(editor, generateSettingsMenu(editor), '0', '0', '0');
-}
-
-/**
- * Initializes the settings menu extension. It adds the showSettingsMenu
- *  method to the given editor object and adds the showSettingsMenu command
- *  to the editor with appropriate keyboard shortcuts.
- * @param {ace.Editor} editor An instance of the Editor.
- */
-module.exports.init = function(editor) {
-    var Editor = require("ace/editor").Editor;
-    Editor.prototype.showSettingsMenu = function() {
-        showSettingsMenu(this);
-    };
-};
-});

+ 0 - 40
services/web/public/js/ace/ext/split.js

@@ -1,40 +0,0 @@
-/* ***** 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";
-
-/**
- * this is experimental, and subject to change, use at your own risk!
- */
-module.exports = require("../split");
-
-});
-

+ 0 - 32
services/web/public/js/ace/ext/static.css

@@ -1,32 +0,0 @@
-.ace_static_highlight {
-   font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', 'Droid Sans Mono', monospace;
-   font-size: 12px;
-}
-
-.ace_static_highlight .ace_gutter {
-    width: 25px !important;
-    display: block;
-    float: left;
-    text-align: right;
-    padding: 0 3px 0 0;
-    margin-right: 3px;
-    position: static !important;
-}
-
-.ace_static_highlight .ace_line { clear: both; }
-
-.ace_static_highlight .ace_gutter-cell {
-  -moz-user-select: -moz-none;
-  -khtml-user-select: none;
-  -webkit-user-select: none;
-  user-select: none;
-}
-
-
-.ace_static_highlight .ace_gutter-cell:before {
-    content: counter(ace_line, decimal);
-    counter-increment: ace_line;
-}
-.ace_static_highlight {
-    counter-reset: ace_line;
-}

+ 0 - 96
services/web/public/js/ace/ext/static_highlight_test.js

@@ -1,96 +0,0 @@
-if (typeof process !== "undefined") {
-    require("amd-loader");
-    require("../test/mockdom");
-}
-
-define(function(require, exports, module) {
-"use strict";
-
-var assert = require("assert");
-var highlighter = require("./static_highlight");
-var JavaScriptMode = require("../mode/javascript").Mode;
-var TextMode = require("../mode/text").Mode;
-
-// Execution ORDER: test.setUpSuite, setUp, testFn, tearDown, test.tearDownSuite
-module.exports = {
-    timeout: 10000,
-
-    "test simple snippet": function(next) {
-        var theme = require("../theme/tomorrow");
-        var snippet = [
-            "/** this is a function",
-            "*",
-            "*/",
-            "function hello (a, b, c) {",
-            "    console.log(a * b + c + 'sup$');",
-            "}"
-        ].join("\n");
-        var mode = new JavaScriptMode();
-
-        var result = highlighter.render(snippet, mode, theme);
-        assert.equal(result.html, "<div class='ace-tomorrow'><div class='ace_static_highlight' style='counter-reset:ace_line 0'>" 
-            + "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span><span class='ace_comment ace_doc'>/**\xa0this\xa0is\xa0a\xa0function</span>\n</div>"
-            + "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span><span class='ace_comment ace_doc'>*</span>\n</div>"
-            + "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span><span class='ace_comment ace_doc'>*/</span>\n</div>"
-            + "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span><span class='ace_storage ace_type'>function</span>\xa0<span class='ace_entity ace_name ace_function'>hello</span>\xa0<span class='ace_paren ace_lparen'>(</span><span class='ace_variable ace_parameter'>a</span><span class='ace_punctuation ace_operator'>,\xa0</span><span class='ace_variable ace_parameter'>b</span><span class='ace_punctuation ace_operator'>,\xa0</span><span class='ace_variable ace_parameter'>c</span><span class='ace_paren ace_rparen'>)</span>\xa0<span class='ace_paren ace_lparen'>{</span>\n</div>"
-            + "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span>\xa0\xa0\xa0\xa0<span class='ace_storage ace_type'>console</span><span class='ace_punctuation ace_operator'>.</span><span class='ace_support ace_function ace_firebug'>log</span><span class='ace_paren ace_lparen'>(</span><span class='ace_identifier'>a</span>\xa0<span class='ace_keyword ace_operator'>*</span>\xa0<span class='ace_identifier'>b</span>\xa0<span class='ace_keyword ace_operator'>+</span>\xa0<span class='ace_identifier'>c</span>\xa0<span class='ace_keyword ace_operator'>+</span>\xa0<span class='ace_string'>'sup$'</span><span class='ace_paren ace_rparen'>)</span><span class='ace_punctuation ace_operator'>;</span>\n</div>"
-            + "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span><span class='ace_paren ace_rparen'>}</span>\n</div>"
-            + "</div></div>");
-        assert.ok(!!result.css);
-        next();
-    },
-
-    "test css from theme is used": function(next) {
-        var theme = require("../theme/tomorrow");
-        var snippet = [
-            "/** this is a function",
-            "*",
-            "*/",
-            "function hello (a, b, c) {",
-            "    console.log(a * b + c + 'sup?');",
-            "}"
-        ].join("\n");
-        var mode = new JavaScriptMode();
-
-        var result = highlighter.render(snippet, mode, theme);
-
-        assert.ok(result.css.indexOf(theme.cssText) !== -1);
-
-        next();
-    },
-
-    "test theme classname should be in output html": function(next) {
-        var theme = require("../theme/tomorrow");
-        var snippet = [
-            "/** this is a function",
-            "*",
-            "*/",
-            "function hello (a, b, c) {",
-            "    console.log(a * b + c + 'sup?');",
-            "}"
-        ].join("\n");
-        var mode = new JavaScriptMode();
-
-        var result = highlighter.render(snippet, mode, theme);
-        assert.equal(!!result.html.match(/<div class='ace-tomorrow'>/), true);
-
-        next();
-    },
-    
-    "test js string replace specials": function(next) {
-        var theme = require("../theme/tomorrow");
-        var snippet = "$'$1$2$$$&";
-        var mode = new TextMode();
-
-        var result = highlighter.render(snippet, mode, theme);
-        assert.ok(result.html.indexOf(snippet) != -1);
-
-        next();
-    }
-};
-
-});
-
-if (typeof module !== "undefined" && module === require.main) {
-    require("asyncjs").test.testcase(module.exports).exec();
-}

+ 0 - 101
services/web/public/js/ace/ext/themelist.js

@@ -1,101 +0,0 @@
-/* ***** 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 */
-
-/**
- * Generates a list of themes available when ace was built.
- * @fileOverview Generates a list of themes available when ace was built.
- * @author <a href="mailto:matthewkastor@gmail.com">
- *  Matthew Christopher Kastor-Inare III </a><br />
- *  ☭ Hial Atropa!! ☭
- */
-
-define(function(require, exports, module) {
-"use strict";
-
-var themeData = [
-    ["Chrome"         ],
-    ["Clouds"         ],
-    ["Crimson Editor" ],
-    ["Dawn"           ],
-    ["Dreamweaver"    ],
-    ["Eclipse"        ],
-    ["GitHub"         ],
-    ["Solarized Light"],
-    ["TextMate"       ],
-    ["Tomorrow"       ],
-    ["XCode"          ],
-    ["Kuroir"],
-    ["KatzenMilch"],
-    ["Ambiance"             ,"ambiance"                ,  "dark"],
-    ["Chaos"                ,"chaos"                   ,  "dark"],
-    ["Clouds Midnight"      ,"clouds_midnight"         ,  "dark"],
-    ["Cobalt"               ,"cobalt"                  ,  "dark"],
-    ["idle Fingers"         ,"idle_fingers"            ,  "dark"],
-    ["krTheme"              ,"kr_theme"                ,  "dark"],
-    ["Merbivore"            ,"merbivore"               ,  "dark"],
-    ["Merbivore Soft"       ,"merbivore_soft"          ,  "dark"],
-    ["Mono Industrial"      ,"mono_industrial"         ,  "dark"],
-    ["Monokai"              ,"monokai"                 ,  "dark"],
-    ["Pastel on dark"       ,"pastel_on_dark"          ,  "dark"],
-    ["Solarized Dark"       ,"solarized_dark"          ,  "dark"],
-    ["Terminal"             ,"terminal"                ,  "dark"],
-    ["Tomorrow Night"       ,"tomorrow_night"          ,  "dark"],
-    ["Tomorrow Night Blue"  ,"tomorrow_night_blue"     ,  "dark"],
-    ["Tomorrow Night Bright","tomorrow_night_bright"   ,  "dark"],
-    ["Tomorrow Night 80s"   ,"tomorrow_night_eighties" ,  "dark"],
-    ["Twilight"             ,"twilight"                ,  "dark"],
-    ["Vibrant Ink"          ,"vibrant_ink"             ,  "dark"],
-]
-
-
-exports.themesByName = {};
-
-/**
- * An array containing information about available themes.
- */
-exports.themes = themeData.map(function(data) {
-    var name = data[1] || data[0].replace(/ /g, "_").toLowerCase();
-    var theme = {
-         caption: data[0],
-         theme: "ace/theme/" + name,
-         isDark: data[2] == "dark",
-         name: name
-    };
-    exports.themesByName[name] = theme;
-    return theme;
-});
-
-});
-

+ 0 - 259
services/web/public/js/ace/incremental_search.js

@@ -1,259 +0,0 @@
-/* ***** 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 oop = require("./lib/oop");
-var Range = require("./range").Range;
-var Search = require("./search").Search;
-var SearchHighlight = require("./search_highlight").SearchHighlight;
-var iSearchCommandModule = require("./commands/incremental_search_commands");
-var ISearchKbd = iSearchCommandModule.IncrementalSearchKeyboardHandler;
-
-/**
- * @class IncrementalSearch
- *
- * Implements immediate searching while the user is typing. When incremental
- * search is activated, keystrokes into the editor will be used for composing
- * a search term. Immediately after every keystroke the search is updated:
- * - so-far-matching characters are highlighted
- * - the cursor is moved to the next match
- *
- **/
-
-
-/**
- *
- *
- * Creates a new `IncrementalSearch` object.
- *
- * @constructor
- **/
-function IncrementalSearch() {
-    this.$options = {wrap: false, skipCurrent: false};
-    this.$keyboardHandler = new ISearchKbd(this);
-}
-
-oop.inherits(IncrementalSearch, Search);
-
-;(function() {
-
-    this.activate = function(ed, backwards) {
-        this.$editor = ed;
-        this.$startPos = this.$currentPos = ed.getCursorPosition();
-        this.$options.needle = '';
-        this.$options.backwards = backwards;
-        ed.keyBinding.addKeyboardHandler(this.$keyboardHandler);
-        this.$mousedownHandler = ed.addEventListener('mousedown', this.onMouseDown.bind(this));
-        this.selectionFix(ed);
-        this.statusMessage(true);
-    }
-
-    this.deactivate = function(reset) {
-        this.cancelSearch(reset);
-        this.$editor.keyBinding.removeKeyboardHandler(this.$keyboardHandler);
-        if (this.$mousedownHandler) {
-            this.$editor.removeEventListener('mousedown', this.$mousedownHandler);
-            delete this.$mousedownHandler;
-        }
-        this.message('');
-    }
-
-    this.selectionFix = function(editor) {
-        // Fix selection bug: When clicked inside the editor
-        // editor.selection.$isEmpty is false even if the mouse click did not
-        // open a selection. This is interpreted by the move commands to
-        // extend the selection. To only extend the selection when there is
-        // one, we clear it here
-        if (editor.selection.isEmpty() && !editor.session.$emacsMark) {
-            editor.clearSelection();
-        }
-    }
-
-    this.highlight = function(regexp) {
-        var sess = this.$editor.session,
-            hl = sess.$isearchHighlight = sess.$isearchHighlight || sess.addDynamicMarker(
-                new SearchHighlight(null, "ace_isearch-result", "text"));
-        hl.setRegexp(regexp);
-        sess._emit("changeBackMarker"); // force highlight layer redraw
-    }
-
-    this.cancelSearch = function(reset) {
-        var e = this.$editor;
-        this.$prevNeedle = this.$options.needle;
-        this.$options.needle = '';
-        if (reset) {
-            e.moveCursorToPosition(this.$startPos);
-            this.$currentPos = this.$startPos;
-        } else {
-            e.pushEmacsMark && e.pushEmacsMark(this.$startPos, false);
-        }
-        this.highlight(null);
-        return Range.fromPoints(this.$currentPos, this.$currentPos);
-    }
-
-    this.highlightAndFindWithNeedle = function(moveToNext, needleUpdateFunc) {
-        if (!this.$editor) return null;
-        var options = this.$options;
-
-        // get search term
-        if (needleUpdateFunc) {
-            options.needle = needleUpdateFunc.call(this, options.needle || '') || '';
-        }
-        if (options.needle.length === 0) {
-            this.statusMessage(true);
-            return this.cancelSearch(true);
-        };
-
-        // try to find the next occurence and enable  highlighting marker
-        options.start = this.$currentPos;
-        var session = this.$editor.session,
-            found = this.find(session);
-        if (found) {
-            if (options.backwards) found = Range.fromPoints(found.end, found.start);
-            this.$editor.moveCursorToPosition(found.end);
-            if (moveToNext) this.$currentPos = found.end;
-            // highlight after cursor move, so selection works properly
-            this.highlight(options.re)
-        }
-
-        this.statusMessage(found);
-
-        return found;
-    }
-
-    this.addChar = function(c) {
-        return this.highlightAndFindWithNeedle(false, function(needle) {
-            return needle + c;
-        });
-    }
-
-    this.removeChar = function(c) {
-        return this.highlightAndFindWithNeedle(false, function(needle) {
-            return needle.length > 0 ? needle.substring(0, needle.length-1) : needle;
-        });
-    }
-
-    this.next = function(options) {
-        // try to find the next occurence of whatever we have searched for
-        // earlier.
-        // options = {[backwards: BOOL], [useCurrentOrPrevSearch: BOOL]}
-        options = options || {};
-        this.$options.backwards = !!options.backwards;
-        this.$currentPos = this.$editor.getCursorPosition();
-        return this.highlightAndFindWithNeedle(true, function(needle) {
-            return options.useCurrentOrPrevSearch && needle.length === 0 ?
-                this.$prevNeedle || '' : needle;
-        });
-    }
-
-    this.onMouseDown = function(evt) {
-        // when mouse interaction happens then we quit incremental search
-        this.deactivate();
-        return true;
-    }
-
-    this.statusMessage = function(found) {
-        var options = this.$options, msg = '';
-        msg += options.backwards ? 'reverse-' : '';
-        msg += 'isearch: ' + options.needle;
-        msg += found ? '' : ' (not found)';
-        this.message(msg);
-    }
-
-    this.message = function(msg) {
-        if (this.$editor.showCommandLine) {
-            this.$editor.showCommandLine(msg);
-            this.$editor.focus();
-        } else {
-            console.log(msg);
-        }
-    }
-
-}).call(IncrementalSearch.prototype);
-
-
-exports.IncrementalSearch = IncrementalSearch;
-
-
-/**
- *
- * Config settings for enabling/disabling [[IncrementalSearch `IncrementalSearch`]].
- *
- **/
-
-var dom = require('./lib/dom');
-dom.importCssString && dom.importCssString("\
-.ace_marker-layer .ace_isearch-result {\
-  position: absolute;\
-  z-index: 6;\
-  -moz-box-sizing: border-box;\
-  -webkit-box-sizing: border-box;\
-  box-sizing: border-box;\
-}\
-div.ace_isearch-result {\
-  border-radius: 4px;\
-  background-color: rgba(255, 200, 0, 0.5);\
-  box-shadow: 0 0 4px rgb(255, 200, 0);\
-}\
-.ace_dark div.ace_isearch-result {\
-  background-color: rgb(100, 110, 160);\
-  box-shadow: 0 0 4px rgb(80, 90, 140);\
-}", "incremental-search-highlighting");
-
-// support for default keyboard handler
-var commands = require("./commands/command_manager");
-(function() {
-    this.setupIncrementalSearch = function(editor, val) {
-        if (this.usesIncrementalSearch == val) return;
-        this.usesIncrementalSearch = val;
-        var iSearchCommands = iSearchCommandModule.iSearchStartCommands;
-        var method = val ? 'addCommands' : 'removeCommands';
-        this[method](iSearchCommands);
-    };
-}).call(commands.CommandManager.prototype);
-
-// incremental search config option
-var Editor = require("./editor").Editor;
-require("./config").defineOptions(Editor.prototype, "editor", {
-    useIncrementalSearch: {
-        set: function(val) {
-            this.keyBinding.$handlers.forEach(function(handler) {
-                if (handler.setupIncrementalSearch) {
-                    handler.setupIncrementalSearch(this, val);
-                }
-            });
-            this._emit('incrementalSearchSettingChanged', {isEnabled: val});
-        }
-    }
-});
-
-});

+ 0 - 208
services/web/public/js/ace/incremental_search_test.js

@@ -1,208 +0,0 @@
-/* ***** 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 EditSession = require("./edit_session").EditSession;
-var Editor = require("./editor").Editor;
-var MockRenderer = require("./test/mockrenderer").MockRenderer;
-var Range = require("./range").Range;
-var assert = require("./test/assertions");
-var IncrementalSearch = require("./incremental_search").IncrementalSearch;
-
-var editor, iSearch;
-function testRanges(str, ranges) {
-    ranges = ranges || editor.selection.getAllRanges();
-    assert.equal(ranges + "", str + "");
-}
-
-// force "rerender"
-function callHighlighterUpdate() {
-    var session = editor.session,
-        ranges = [],
-        mockMarkerLayer = {
-            drawSingleLineMarker: function(_, markerRanges) {
-                ranges = ranges.concat(markerRanges);
-            }
-        }
-    session.$isearchHighlight.update([], mockMarkerLayer, session, {
-        firstRow: 0, lastRow: session.getRowLength()});
-    return ranges;
-}
-
-module.exports = {
-
-    name: "ACE incremental_search.js",
-
-    setUp: function() {
-        var session = new EditSession(["abc123", "xyz124"]);
-        editor = new Editor(new MockRenderer(), session);
-        iSearch = new IncrementalSearch();
-    },
-
-    "test: keyboard handler setup" : function() {
-        iSearch.activate(editor);
-        assert.equal(editor.getKeyboardHandler(), iSearch.$keyboardHandler);
-        iSearch.deactivate();
-        assert.notEqual(editor.getKeyboardHandler(), iSearch.$keyboardHandler);
-    },
-
-    "test: isearch highlight setup" : function() {
-        var sess = editor.session;
-        iSearch.activate(editor);
-        iSearch.highlight('foo');
-        var highl = sess.$isearchHighlight.id;
-        assert.ok(sess.$isearchHighlight, 'session has no isearch highlighter');
-        assert.equal(sess.getMarkers()[highl.id], highl.id, 'isearch highlight not in markers');
-        iSearch.deactivate();
-        iSearch.activate(editor);
-        iSearch.highlight('bar');
-        var highl2 = sess.$isearchHighlight.id;
-        assert.equal(highl2, highl, 'multiple isearch highlights');
-    },
-
-    "test: find simple text incrementally" : function() {
-        iSearch.activate(editor);
-        var range = iSearch.addChar('1'), // "1"
-            highlightRanges = callHighlighterUpdate(editor.session);
-        testRanges("Range: [0/3] -> [0/4]", [range], "range");
-        testRanges("Range: [0/3] -> [0/4],Range: [1/3] -> [1/4]", highlightRanges, "highlight");
-
-        range = iSearch.addChar('2'); // "12"
-        highlightRanges = callHighlighterUpdate(editor.session);
-        testRanges("Range: [0/3] -> [0/5]", [range], "range");
-        testRanges("Range: [0/3] -> [0/5],Range: [1/3] -> [1/5]", highlightRanges, "highlight");
-
-        range = iSearch.addChar('3'); // "123"
-        highlightRanges = callHighlighterUpdate(editor.session);
-        testRanges("Range: [0/3] -> [0/6]", [range], "range");
-        testRanges("Range: [0/3] -> [0/6]", highlightRanges, "highlight");
-
-        range = iSearch.removeChar(); // "12"
-        highlightRanges = callHighlighterUpdate(editor.session);
-        testRanges("Range: [0/3] -> [0/5]", [range], "range");
-        testRanges("Range: [0/3] -> [0/5],Range: [1/3] -> [1/5]", highlightRanges, "highlight");
-    },
-
-    "test: forward / backward" : function() {
-        iSearch.activate(editor);
-        iSearch.addChar('1'); iSearch.addChar('2');
-        var range = iSearch.next();
-        testRanges("Range: [1/3] -> [1/5]", [range], "range");
-
-        range = iSearch.next(); // nothing to find
-        testRanges("", [range], "range");
-
-        range = iSearch.next({backwards: true}); // backwards
-        testRanges("Range: [1/5] -> [1/3]", [range], "range");
-    },
-
-    "test: cancelSearch" : function() {
-        iSearch.activate(editor);
-        iSearch.addChar('1'); iSearch.addChar('2');
-        var range = iSearch.cancelSearch(true);
-        testRanges("Range: [0/0] -> [0/0]", [range], "range");
-
-        iSearch.addChar('1'); range = iSearch.addChar('2');
-        testRanges("Range: [0/3] -> [0/5]", [range], "range");
-    },
-
-    "test: failing search keeps pos" : function() {
-        iSearch.activate(editor);
-        iSearch.addChar('1'); iSearch.addChar('2');
-        var range = iSearch.addChar('x');
-        testRanges("", [range], "range");
-        assert.position(editor.getCursorPosition(), 0, 5);
-    },
-
-    "test: backwards search" : function() {
-        editor.moveCursorTo(1,0);
-        iSearch.activate(editor, true);
-        iSearch.addChar('1'); var range = iSearch.addChar('2');;
-        testRanges("Range: [0/5] -> [0/3]", [range], "range");
-        assert.position(editor.getCursorPosition(), 0, 3);
-    },
-
-    "test: forwards then backwards, same result, reoriented range" : function() {
-        iSearch.activate(editor);
-        iSearch.addChar('1'); var range = iSearch.addChar('2');;
-        testRanges("Range: [0/3] -> [0/5]", [range], "range");
-        assert.position(editor.getCursorPosition(), 0, 5);
-
-        range = iSearch.next({backwards: true});
-        testRanges("Range: [0/5] -> [0/3]", [range], "range");
-        assert.position(editor.getCursorPosition(), 0, 3);
-    },
-
-    "test: reuse prev search via option" : function() {
-        iSearch.activate(editor);
-        iSearch.addChar('1'); iSearch.addChar('2');;
-        assert.position(editor.getCursorPosition(), 0, 5);
-        iSearch.deactivate();
-
-        iSearch.activate(editor);
-        iSearch.next({backwards: false, useCurrentOrPrevSearch: true});
-        assert.position(editor.getCursorPosition(), 1, 5);
-    },
-
-    "test: don't extend selection range if selection is empty" : function() {
-        iSearch.activate(editor);
-        iSearch.addChar('1'); iSearch.addChar('2');;
-        testRanges("Range: [0/5] -> [0/5]", [editor.getSelectionRange()], "sel range");
-    },
-
-    "test: extend selection range if selection exists" : function() {
-        iSearch.activate(editor);
-        editor.selection.selectTo(0, 1);
-        iSearch.addChar('1'); iSearch.addChar('2');;
-        testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range");
-    },
-
-    "test: extend selection in emacs mark mode" : function() {
-        var emacs = require('./keyboard/emacs');
-        editor.keyBinding.addKeyboardHandler(emacs.handler);
-        emacs.handler.commands.setMark.exec(editor);
-        iSearch.activate(editor);
-        iSearch.addChar('1'); iSearch.addChar('2');;
-        testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range");
-    }
-
-};
-
-});
-
-if (typeof module !== "undefined" && module === require.main) {
-    require("asyncjs").test.testcase(module.exports).exec()
-}

+ 1070 - 0
services/web/public/js/ace/keybinding-emacs.js

@@ -0,0 +1,1070 @@
+define("ace/occur",["require","exports","module","ace/lib/oop","ace/range","ace/search","ace/edit_session","ace/search_highlight","ace/lib/dom"], function(require, exports, module) {
+"use strict";
+
+var oop = require("./lib/oop");
+var Range = require("./range").Range;
+var Search = require("./search").Search;
+var EditSession = require("./edit_session").EditSession;
+var SearchHighlight = require("./search_highlight").SearchHighlight;
+function Occur() {}
+
+oop.inherits(Occur, Search);
+
+(function() {
+    this.enter = function(editor, options) {
+        if (!options.needle) return false;
+        var pos = editor.getCursorPosition();
+        this.displayOccurContent(editor, options);
+        var translatedPos = this.originalToOccurPosition(editor.session, pos);
+        editor.moveCursorToPosition(translatedPos);
+        return true;
+    }
+    this.exit = function(editor, options) {
+        var pos = options.translatePosition && editor.getCursorPosition();
+        var translatedPos = pos && this.occurToOriginalPosition(editor.session, pos);
+        this.displayOriginalContent(editor);
+        if (translatedPos)
+            editor.moveCursorToPosition(translatedPos);
+        return true;
+    }
+
+    this.highlight = function(sess, regexp) {
+        var hl = sess.$occurHighlight = sess.$occurHighlight || sess.addDynamicMarker(
+                new SearchHighlight(null, "ace_occur-highlight", "text"));
+        hl.setRegexp(regexp);
+        sess._emit("changeBackMarker"); // force highlight layer redraw
+    }
+
+    this.displayOccurContent = function(editor, options) {
+        this.$originalSession = editor.session;
+        var found = this.matchingLines(editor.session, options);
+        var lines = found.map(function(foundLine) { return foundLine.content; });
+        var occurSession = new EditSession(lines.join('\n'));
+        occurSession.$occur = this;
+        occurSession.$occurMatchingLines = found;
+        editor.setSession(occurSession);
+        this.$useEmacsStyleLineStart = this.$originalSession.$useEmacsStyleLineStart;
+        occurSession.$useEmacsStyleLineStart = this.$useEmacsStyleLineStart;
+        this.highlight(occurSession, options.re);
+        occurSession._emit('changeBackMarker');
+    }
+
+    this.displayOriginalContent = function(editor) {
+        editor.setSession(this.$originalSession);
+        this.$originalSession.$useEmacsStyleLineStart = this.$useEmacsStyleLineStart;
+    }
+    this.originalToOccurPosition = function(session, pos) {
+        var lines = session.$occurMatchingLines;
+        var nullPos = {row: 0, column: 0};
+        if (!lines) return nullPos;
+        for (var i = 0; i < lines.length; i++) {
+            if (lines[i].row === pos.row)
+                return {row: i, column: pos.column};
+        }
+        return nullPos;
+    }
+    this.occurToOriginalPosition = function(session, pos) {
+        var lines = session.$occurMatchingLines;
+        if (!lines || !lines[pos.row])
+            return pos;
+        return {row: lines[pos.row].row, column: pos.column};
+    }
+
+    this.matchingLines = function(session, options) {
+        options = oop.mixin({}, options);
+        if (!session || !options.needle) return [];
+        var search = new Search();
+        search.set(options);
+        return search.findAll(session).reduce(function(lines, range) {
+            var row = range.start.row;
+            var last = lines[lines.length-1];
+            return last && last.row === row ?
+                lines :
+                lines.concat({row: row, content: session.getLine(row)});
+        }, []);
+    }
+
+}).call(Occur.prototype);
+
+var dom = require('./lib/dom');
+dom.importCssString(".ace_occur-highlight {\n\
+    border-radius: 4px;\n\
+    background-color: rgba(87, 255, 8, 0.25);\n\
+    position: absolute;\n\
+    z-index: 4;\n\
+    -moz-box-sizing: border-box;\n\
+    -webkit-box-sizing: border-box;\n\
+    box-sizing: border-box;\n\
+    box-shadow: 0 0 4px rgb(91, 255, 50);\n\
+}\n\
+.ace_dark .ace_occur-highlight {\n\
+    background-color: rgb(80, 140, 85);\n\
+    box-shadow: 0 0 4px rgb(60, 120, 70);\n\
+}\n", "incremental-occur-highlighting");
+
+exports.Occur = Occur;
+
+});
+
+define("ace/commands/occur_commands",["require","exports","module","ace/config","ace/occur","ace/keyboard/hash_handler","ace/lib/oop"], function(require, exports, module) {
+
+var config = require("../config"),
+    Occur = require("../occur").Occur;
+var occurStartCommand = {
+    name: "occur",
+    exec: function(editor, options) {
+        var alreadyInOccur = !!editor.session.$occur;
+        var occurSessionActive = new Occur().enter(editor, options);
+        if (occurSessionActive && !alreadyInOccur)
+            OccurKeyboardHandler.installIn(editor);
+    },
+    readOnly: true
+};
+
+var occurCommands = [{
+    name: "occurexit",
+    bindKey: 'esc|Ctrl-G',
+    exec: function(editor) {
+        var occur = editor.session.$occur;
+        if (!occur) return;
+        occur.exit(editor, {});
+        if (!editor.session.$occur) OccurKeyboardHandler.uninstallFrom(editor);
+    },
+    readOnly: true
+}, {
+    name: "occuraccept",
+    bindKey: 'enter',
+    exec: function(editor) {
+        var occur = editor.session.$occur;
+        if (!occur) return;
+        occur.exit(editor, {translatePosition: true});
+        if (!editor.session.$occur) OccurKeyboardHandler.uninstallFrom(editor);
+    },
+    readOnly: true
+}];
+
+var HashHandler = require("../keyboard/hash_handler").HashHandler;
+var oop = require("../lib/oop");
+
+
+function OccurKeyboardHandler() {}
+
+oop.inherits(OccurKeyboardHandler, HashHandler);
+
+;(function() {
+
+    this.isOccurHandler = true;
+
+    this.attach = function(editor) {
+        HashHandler.call(this, occurCommands, editor.commands.platform);
+        this.$editor = editor;
+    }
+
+    var handleKeyboard$super = this.handleKeyboard;
+    this.handleKeyboard = function(data, hashId, key, keyCode) {
+        var cmd = handleKeyboard$super.call(this, data, hashId, key, keyCode);
+        return (cmd && cmd.command) ? cmd : undefined;
+    }
+
+}).call(OccurKeyboardHandler.prototype);
+
+OccurKeyboardHandler.installIn = function(editor) {
+    var handler = new this();
+    editor.keyBinding.addKeyboardHandler(handler);
+    editor.commands.addCommands(occurCommands);
+}
+
+OccurKeyboardHandler.uninstallFrom = function(editor) {
+    editor.commands.removeCommands(occurCommands);
+    var handler = editor.getKeyboardHandler();
+    if (handler.isOccurHandler)
+        editor.keyBinding.removeKeyboardHandler(handler);
+}
+
+exports.occurStartCommand = occurStartCommand;
+
+});
+
+define("ace/commands/incremental_search_commands",["require","exports","module","ace/config","ace/lib/oop","ace/keyboard/hash_handler","ace/commands/occur_commands"], function(require, exports, module) {
+
+var config = require("../config");
+var oop = require("../lib/oop");
+var HashHandler = require("../keyboard/hash_handler").HashHandler;
+var occurStartCommand = require("./occur_commands").occurStartCommand;
+exports.iSearchStartCommands = [{
+    name: "iSearch",
+    bindKey: {win: "Ctrl-F", mac: "Command-F"},
+    exec: function(editor, options) {
+        config.loadModule(["core", "ace/incremental_search"], function(e) {
+            var iSearch = e.iSearch = e.iSearch || new e.IncrementalSearch();
+            iSearch.activate(editor, options.backwards);
+            if (options.jumpToFirstMatch) iSearch.next(options);
+        });
+    },
+    readOnly: true
+}, {
+    name: "iSearchBackwards",
+    exec: function(editor, jumpToNext) { editor.execCommand('iSearch', {backwards: true}); },
+    readOnly: true
+}, {
+    name: "iSearchAndGo",
+    bindKey: {win: "Ctrl-K", mac: "Command-G"},
+    exec: function(editor, jumpToNext) { editor.execCommand('iSearch', {jumpToFirstMatch: true, useCurrentOrPrevSearch: true}); },
+    readOnly: true
+}, {
+    name: "iSearchBackwardsAndGo",
+    bindKey: {win: "Ctrl-Shift-K", mac: "Command-Shift-G"},
+    exec: function(editor) { editor.execCommand('iSearch', {jumpToFirstMatch: true, backwards: true, useCurrentOrPrevSearch: true}); },
+    readOnly: true
+}];
+exports.iSearchCommands = [{
+    name: "restartSearch",
+    bindKey: {win: "Ctrl-F", mac: "Command-F"},
+    exec: function(iSearch) {
+        iSearch.cancelSearch(true);
+    },
+    readOnly: true,
+    isIncrementalSearchCommand: true
+}, {
+    name: "searchForward",
+    bindKey: {win: "Ctrl-S|Ctrl-K", mac: "Ctrl-S|Command-G"},
+    exec: function(iSearch, options) {
+        options.useCurrentOrPrevSearch = true;
+        iSearch.next(options);
+    },
+    readOnly: true,
+    isIncrementalSearchCommand: true
+}, {
+    name: "searchBackward",
+    bindKey: {win: "Ctrl-R|Ctrl-Shift-K", mac: "Ctrl-R|Command-Shift-G"},
+    exec: function(iSearch, options) {
+        options.useCurrentOrPrevSearch = true;
+        options.backwards = true;
+        iSearch.next(options);
+    },
+    readOnly: true,
+    isIncrementalSearchCommand: true
+}, {
+    name: "extendSearchTerm",
+    exec: function(iSearch, string) {
+        iSearch.addString(string);
+    },
+    readOnly: true,
+    isIncrementalSearchCommand: true
+}, {
+    name: "extendSearchTermSpace",
+    bindKey: "space",
+    exec: function(iSearch) { iSearch.addString(' '); },
+    readOnly: true,
+    isIncrementalSearchCommand: true
+}, {
+    name: "shrinkSearchTerm",
+    bindKey: "backspace",
+    exec: function(iSearch) {
+        iSearch.removeChar();
+    },
+    readOnly: true,
+    isIncrementalSearchCommand: true
+}, {
+    name: 'confirmSearch',
+    bindKey: 'return',
+    exec: function(iSearch) { iSearch.deactivate(); },
+    readOnly: true,
+    isIncrementalSearchCommand: true
+}, {
+    name: 'cancelSearch',
+    bindKey: 'esc|Ctrl-G',
+    exec: function(iSearch) { iSearch.deactivate(true); },
+    readOnly: true,
+    isIncrementalSearchCommand: true
+}, {
+    name: 'occurisearch',
+    bindKey: 'Ctrl-O',
+    exec: function(iSearch) {
+        var options = oop.mixin({}, iSearch.$options);
+        iSearch.deactivate();
+        occurStartCommand.exec(iSearch.$editor, options);
+    },
+    readOnly: true,
+    isIncrementalSearchCommand: true
+}, {
+    name: "yankNextWord",
+    bindKey: "Ctrl-w",
+    exec: function(iSearch) {
+        var ed = iSearch.$editor,
+            range = ed.selection.getRangeOfMovements(function(sel) { sel.moveCursorWordRight(); }),
+            string = ed.session.getTextRange(range);
+        iSearch.addString(string);
+    },
+    readOnly: true,
+    isIncrementalSearchCommand: true
+}, {
+    name: "yankNextChar",
+    bindKey: "Ctrl-Alt-y",
+    exec: function(iSearch) {
+        var ed = iSearch.$editor,
+            range = ed.selection.getRangeOfMovements(function(sel) { sel.moveCursorRight(); }),
+            string = ed.session.getTextRange(range);
+        iSearch.addString(string);
+    },
+    readOnly: true,
+    isIncrementalSearchCommand: true
+}, {
+    name: 'recenterTopBottom',
+    bindKey: 'Ctrl-l',
+    exec: function(iSearch) { iSearch.$editor.execCommand('recenterTopBottom'); },
+    readOnly: true,
+    isIncrementalSearchCommand: true
+}];
+
+function IncrementalSearchKeyboardHandler(iSearch) {
+    this.$iSearch = iSearch;
+}
+
+oop.inherits(IncrementalSearchKeyboardHandler, HashHandler);
+
+;(function() {
+
+    this.attach = function(editor) {
+        var iSearch = this.$iSearch;
+        HashHandler.call(this, exports.iSearchCommands, editor.commands.platform);
+        this.$commandExecHandler = editor.commands.addEventListener('exec', function(e) {
+            if (!e.command.isIncrementalSearchCommand) return undefined;
+            e.stopPropagation();
+            e.preventDefault();
+            return e.command.exec(iSearch, e.args || {});
+        });
+    }
+
+    this.detach = function(editor) {
+        if (!this.$commandExecHandler) return;
+        editor.commands.removeEventListener('exec', this.$commandExecHandler);
+        delete this.$commandExecHandler;
+    }
+
+    var handleKeyboard$super = this.handleKeyboard;
+    this.handleKeyboard = function(data, hashId, key, keyCode) {
+        if (((hashId === 1/*ctrl*/ || hashId === 8/*command*/) && key === 'v')
+         || (hashId === 1/*ctrl*/ && key === 'y')) return null;
+        var cmd = handleKeyboard$super.call(this, data, hashId, key, keyCode);
+        if (cmd.command) { return cmd; }
+        if (hashId == -1) {
+            var extendCmd = this.commands.extendSearchTerm;
+            if (extendCmd) { return {command: extendCmd, args: key}; }
+        }
+        return {command: "null", passEvent: hashId == 0 || hashId == 4};
+    }
+
+}).call(IncrementalSearchKeyboardHandler.prototype);
+
+
+exports.IncrementalSearchKeyboardHandler = IncrementalSearchKeyboardHandler;
+
+});
+
+define("ace/incremental_search",["require","exports","module","ace/lib/oop","ace/range","ace/search","ace/search_highlight","ace/commands/incremental_search_commands","ace/lib/dom","ace/commands/command_manager","ace/editor","ace/config"], function(require, exports, module) {
+"use strict";
+
+var oop = require("./lib/oop");
+var Range = require("./range").Range;
+var Search = require("./search").Search;
+var SearchHighlight = require("./search_highlight").SearchHighlight;
+var iSearchCommandModule = require("./commands/incremental_search_commands");
+var ISearchKbd = iSearchCommandModule.IncrementalSearchKeyboardHandler;
+function IncrementalSearch() {
+    this.$options = {wrap: false, skipCurrent: false};
+    this.$keyboardHandler = new ISearchKbd(this);
+}
+
+oop.inherits(IncrementalSearch, Search);
+
+;(function() {
+
+    this.activate = function(ed, backwards) {
+        this.$editor = ed;
+        this.$startPos = this.$currentPos = ed.getCursorPosition();
+        this.$options.needle = '';
+        this.$options.backwards = backwards;
+        ed.keyBinding.addKeyboardHandler(this.$keyboardHandler);
+        this.$originalEditorOnPaste = ed.onPaste; ed.onPaste = this.onPaste.bind(this);
+        this.$mousedownHandler = ed.addEventListener('mousedown', this.onMouseDown.bind(this));
+        this.selectionFix(ed);
+        this.statusMessage(true);
+    }
+
+    this.deactivate = function(reset) {
+        this.cancelSearch(reset);
+        var ed = this.$editor;
+        ed.keyBinding.removeKeyboardHandler(this.$keyboardHandler);
+        if (this.$mousedownHandler) {
+            ed.removeEventListener('mousedown', this.$mousedownHandler);
+            delete this.$mousedownHandler;
+        }
+        ed.onPaste = this.$originalEditorOnPaste;
+        this.message('');
+    }
+
+    this.selectionFix = function(editor) {
+        if (editor.selection.isEmpty() && !editor.session.$emacsMark) {
+            editor.clearSelection();
+        }
+    }
+
+    this.highlight = function(regexp) {
+        var sess = this.$editor.session,
+            hl = sess.$isearchHighlight = sess.$isearchHighlight || sess.addDynamicMarker(
+                new SearchHighlight(null, "ace_isearch-result", "text"));
+        hl.setRegexp(regexp);
+        sess._emit("changeBackMarker"); // force highlight layer redraw
+    }
+
+    this.cancelSearch = function(reset) {
+        var e = this.$editor;
+        this.$prevNeedle = this.$options.needle;
+        this.$options.needle = '';
+        if (reset) {
+            e.moveCursorToPosition(this.$startPos);
+            this.$currentPos = this.$startPos;
+        } else {
+            e.pushEmacsMark && e.pushEmacsMark(this.$startPos, false);
+        }
+        this.highlight(null);
+        return Range.fromPoints(this.$currentPos, this.$currentPos);
+    }
+
+    this.highlightAndFindWithNeedle = function(moveToNext, needleUpdateFunc) {
+        if (!this.$editor) return null;
+        var options = this.$options;
+        if (needleUpdateFunc) {
+            options.needle = needleUpdateFunc.call(this, options.needle || '') || '';
+        }
+        if (options.needle.length === 0) {
+            this.statusMessage(true);
+            return this.cancelSearch(true);
+        };
+        options.start = this.$currentPos;
+        var session = this.$editor.session,
+            found = this.find(session);
+        if (found) {
+            if (options.backwards) found = Range.fromPoints(found.end, found.start);
+            this.$editor.moveCursorToPosition(found.end);
+            if (moveToNext) this.$currentPos = found.end;
+            this.highlight(options.re)
+        }
+
+        this.statusMessage(found);
+
+        return found;
+    }
+
+    this.addString = function(s) {
+        return this.highlightAndFindWithNeedle(false, function(needle) {
+            return needle + s;
+        });
+    }
+
+    this.removeChar = function(c) {
+        return this.highlightAndFindWithNeedle(false, function(needle) {
+            return needle.length > 0 ? needle.substring(0, needle.length-1) : needle;
+        });
+    }
+
+    this.next = function(options) {
+        options = options || {};
+        this.$options.backwards = !!options.backwards;
+        this.$currentPos = this.$editor.getCursorPosition();
+        return this.highlightAndFindWithNeedle(true, function(needle) {
+            return options.useCurrentOrPrevSearch && needle.length === 0 ?
+                this.$prevNeedle || '' : needle;
+        });
+    }
+
+    this.onMouseDown = function(evt) {
+        this.deactivate();
+        return true;
+    }
+
+    this.onPaste = function(text) {
+        this.addString(text);
+    }
+
+    this.statusMessage = function(found) {
+        var options = this.$options, msg = '';
+        msg += options.backwards ? 'reverse-' : '';
+        msg += 'isearch: ' + options.needle;
+        msg += found ? '' : ' (not found)';
+        this.message(msg);
+    }
+
+    this.message = function(msg) {
+        if (this.$editor.showCommandLine) {
+            this.$editor.showCommandLine(msg);
+            this.$editor.focus();
+        } else {
+            console.log(msg);
+        }
+    }
+
+}).call(IncrementalSearch.prototype);
+
+
+exports.IncrementalSearch = IncrementalSearch;
+
+var dom = require('./lib/dom');
+dom.importCssString && dom.importCssString("\
+.ace_marker-layer .ace_isearch-result {\
+  position: absolute;\
+  z-index: 6;\
+  -moz-box-sizing: border-box;\
+  -webkit-box-sizing: border-box;\
+  box-sizing: border-box;\
+}\
+div.ace_isearch-result {\
+  border-radius: 4px;\
+  background-color: rgba(255, 200, 0, 0.5);\
+  box-shadow: 0 0 4px rgb(255, 200, 0);\
+}\
+.ace_dark div.ace_isearch-result {\
+  background-color: rgb(100, 110, 160);\
+  box-shadow: 0 0 4px rgb(80, 90, 140);\
+}", "incremental-search-highlighting");
+var commands = require("./commands/command_manager");
+(function() {
+    this.setupIncrementalSearch = function(editor, val) {
+        if (this.usesIncrementalSearch == val) return;
+        this.usesIncrementalSearch = val;
+        var iSearchCommands = iSearchCommandModule.iSearchStartCommands;
+        var method = val ? 'addCommands' : 'removeCommands';
+        this[method](iSearchCommands);
+    };
+}).call(commands.CommandManager.prototype);
+var Editor = require("./editor").Editor;
+require("./config").defineOptions(Editor.prototype, "editor", {
+    useIncrementalSearch: {
+        set: function(val) {
+            this.keyBinding.$handlers.forEach(function(handler) {
+                if (handler.setupIncrementalSearch) {
+                    handler.setupIncrementalSearch(this, val);
+                }
+            });
+            this._emit('incrementalSearchSettingChanged', {isEnabled: val});
+        }
+    }
+});
+
+});
+
+define("ace/keyboard/emacs",["require","exports","module","ace/lib/dom","ace/incremental_search","ace/commands/incremental_search_commands","ace/keyboard/hash_handler","ace/lib/keys"], function(require, exports, module) {
+"use strict";
+
+var dom = require("../lib/dom");
+require("../incremental_search");
+var iSearchCommandModule = require("../commands/incremental_search_commands");
+
+
+var screenToTextBlockCoordinates = function(x, y) {
+    var canvasPos = this.scroller.getBoundingClientRect();
+
+    var col = Math.floor(
+        (x + this.scrollLeft - canvasPos.left - this.$padding) / this.characterWidth
+    );
+    var row = Math.floor(
+        (y + this.scrollTop - canvasPos.top) / this.lineHeight
+    );
+
+    return this.session.screenToDocumentPosition(row, col);
+};
+
+var HashHandler = require("./hash_handler").HashHandler;
+exports.handler = new HashHandler();
+
+exports.handler.isEmacs = true;
+exports.handler.$id = "ace/keyboard/emacs";
+
+var initialized = false;
+var $formerLongWords;
+var $formerLineStart;
+
+exports.handler.attach = function(editor) {
+    if (!initialized) {
+        initialized = true;
+        dom.importCssString('\
+            .emacs-mode .ace_cursor{\
+                border: 2px rgba(50,250,50,0.8) solid!important;\
+                -moz-box-sizing: border-box!important;\
+                -webkit-box-sizing: border-box!important;\
+                box-sizing: border-box!important;\
+                background-color: rgba(0,250,0,0.9);\
+                opacity: 0.5;\
+            }\
+            .emacs-mode .ace_hidden-cursors .ace_cursor{\
+                opacity: 1;\
+                background-color: transparent;\
+            }\
+            .emacs-mode .ace_overwrite-cursors .ace_cursor {\
+                opacity: 1;\
+                background-color: transparent;\
+                border-width: 0 0 2px 2px !important;\
+            }\
+            .emacs-mode .ace_text-layer {\
+                z-index: 4\
+            }\
+            .emacs-mode .ace_cursor-layer {\
+                z-index: 2\
+            }', 'emacsMode'
+        );
+    }
+    $formerLongWords = editor.session.$selectLongWords;
+    editor.session.$selectLongWords = true;
+    $formerLineStart = editor.session.$useEmacsStyleLineStart;
+    editor.session.$useEmacsStyleLineStart = true;
+
+    editor.session.$emacsMark = null; // the active mark
+    editor.session.$emacsMarkRing = editor.session.$emacsMarkRing || [];
+
+    editor.emacsMark = function() {
+        return this.session.$emacsMark;
+    };
+
+    editor.setEmacsMark = function(p) {
+        this.session.$emacsMark = p;
+    };
+
+    editor.pushEmacsMark = function(p, activate) {
+        var prevMark = this.session.$emacsMark;
+        if (prevMark)
+            this.session.$emacsMarkRing.push(prevMark);
+        if (!p || activate) this.setEmacsMark(p);
+        else this.session.$emacsMarkRing.push(p);
+    };
+
+    editor.popEmacsMark = function() {
+        var mark = this.emacsMark();
+        if (mark) { this.setEmacsMark(null); return mark; }
+        return this.session.$emacsMarkRing.pop();
+    };
+
+    editor.getLastEmacsMark = function(p) {
+        return this.session.$emacsMark || this.session.$emacsMarkRing.slice(-1)[0];
+    };
+
+    editor.on("click", $resetMarkMode);
+    editor.on("changeSession", $kbSessionChange);
+    editor.renderer.screenToTextCoordinates = screenToTextBlockCoordinates;
+    editor.setStyle("emacs-mode");
+    editor.commands.addCommands(commands);
+    exports.handler.platform = editor.commands.platform;
+    editor.$emacsModeHandler = this;
+    editor.addEventListener('copy', this.onCopy);
+    editor.addEventListener('paste', this.onPaste);
+};
+
+exports.handler.detach = function(editor) {
+    delete editor.renderer.screenToTextCoordinates;
+    editor.session.$selectLongWords = $formerLongWords;
+    editor.session.$useEmacsStyleLineStart = $formerLineStart;
+    editor.removeEventListener("click", $resetMarkMode);
+    editor.removeEventListener("changeSession", $kbSessionChange);
+    editor.unsetStyle("emacs-mode");
+    editor.commands.removeCommands(commands);
+    editor.removeEventListener('copy', this.onCopy);
+    editor.removeEventListener('paste', this.onPaste);
+};
+
+var $kbSessionChange = function(e) {
+    if (e.oldSession) {
+        e.oldSession.$selectLongWords = $formerLongWords;
+        e.oldSession.$useEmacsStyleLineStart = $formerLineStart;
+    }
+
+    $formerLongWords = e.session.$selectLongWords;
+    e.session.$selectLongWords = true;
+    $formerLineStart = e.session.$useEmacsStyleLineStart;
+    e.session.$useEmacsStyleLineStart = true;
+
+    if (!e.session.hasOwnProperty('$emacsMark'))
+        e.session.$emacsMark = null;
+    if (!e.session.hasOwnProperty('$emacsMarkRing'))
+        e.session.$emacsMarkRing = [];
+};
+
+var $resetMarkMode = function(e) {
+    e.editor.session.$emacsMark = null;
+};
+
+var keys = require("../lib/keys").KEY_MODS;
+var eMods = {C: "ctrl", S: "shift", M: "alt", CMD: "command"};
+var combinations = ["C-S-M-CMD",
+                    "S-M-CMD", "C-M-CMD", "C-S-CMD", "C-S-M",
+                    "M-CMD", "S-CMD", "S-M", "C-CMD", "C-M", "C-S",
+                    "CMD", "M", "S", "C"];
+combinations.forEach(function(c) {
+    var hashId = 0;
+    c.split("-").forEach(function(c) {
+        hashId = hashId | keys[eMods[c]];
+    });
+    eMods[hashId] = c.toLowerCase() + "-";
+});
+
+exports.handler.onCopy = function(e, editor) {
+    if (editor.$handlesEmacsOnCopy) return;
+    editor.$handlesEmacsOnCopy = true;
+    exports.handler.commands.killRingSave.exec(editor);
+    delete editor.$handlesEmacsOnCopy;
+};
+
+exports.handler.onPaste = function(e, editor) {
+    editor.pushEmacsMark(editor.getCursorPosition());
+};
+
+exports.handler.bindKey = function(key, command) {
+    if (!key)
+        return;
+
+    var ckb = this.commandKeyBinding;
+    key.split("|").forEach(function(keyPart) {
+        keyPart = keyPart.toLowerCase();
+        ckb[keyPart] = command;
+        var keyParts = keyPart.split(" ").slice(0,-1);
+        keyParts.reduce(function(keyMapKeys, keyPart, i) {
+            var prefix = keyMapKeys[i-1] ? keyMapKeys[i-1] + ' ' : '';
+            return keyMapKeys.concat([prefix + keyPart]);
+        }, []).forEach(function(keyPart) {
+            if (!ckb[keyPart]) ckb[keyPart] = "null";
+        });
+    }, this);
+};
+
+exports.handler.handleKeyboard = function(data, hashId, key, keyCode) {
+    if (keyCode === -1) return undefined;
+
+    var editor = data.editor;
+    if (hashId == -1) {
+        editor.pushEmacsMark();
+        if (data.count) {
+            var str = new Array(data.count + 1).join(key);
+            data.count = null;
+            return {command: "insertstring", args: str};
+        }
+    }
+
+    if (key == "\x00") return undefined;
+
+    var modifier = eMods[hashId];
+    if (modifier == "c-" || data.universalArgument) {
+        var prevCount = String(data.count || 0);
+        var count = parseInt(key[key.length - 1]);
+        if (typeof count === 'number' && !isNaN(count)) {
+            data.count = parseInt(prevCount + count);
+            return {command: "null"};
+        } else if (data.universalArgument) {
+            data.count = 4;
+        }
+    }
+    data.universalArgument = false;
+    if (modifier) key = modifier + key;
+    if (data.keyChain) key = data.keyChain += " " + key;
+    var command = this.commandKeyBinding[key];
+    data.keyChain = command == "null" ? key : "";
+    if (!command) return undefined;
+    if (command === "null") return {command: "null"};
+
+    if (command === "universalArgument") {
+        data.universalArgument = true;
+        return {command: "null"};
+    }
+    var args;
+    if (typeof command !== "string") {
+        args = command.args;
+        if (command.command) command = command.command;
+        if (command === "goorselect") {
+            command = editor.emacsMark() ? args[1] : args[0];
+            args = null;
+        }
+    }
+
+    if (typeof command === "string") {
+        if (command === "insertstring" ||
+            command === "splitline" ||
+            command === "togglecomment") {
+            editor.pushEmacsMark();
+        }
+        command = this.commands[command] || editor.commands.commands[command];
+        if (!command) return undefined;
+    }
+
+    if (!command.readonly && !command.isYank)
+        data.lastCommand = null;
+
+    if (data.count) {
+        var count = data.count;
+        data.count = 0;
+        if (!command || !command.handlesCount) {
+            return {
+                args: args,
+                command: {
+                    exec: function(editor, args) {
+                        for (var i = 0; i < count; i++)
+                            command.exec(editor, args);
+                    }
+                }
+            };
+        } else {
+            if (!args) args = {};
+            if (typeof args === 'object') args.count = count;
+        }
+    }
+
+    return {command: command, args: args};
+};
+
+exports.emacsKeys = {
+    "Up|C-p"      : {command: "goorselect", args: ["golineup","selectup"]},
+    "Down|C-n"    : {command: "goorselect", args: ["golinedown","selectdown"]},
+    "Left|C-b"    : {command: "goorselect", args: ["gotoleft","selectleft"]},
+    "Right|C-f"   : {command: "goorselect", args: ["gotoright","selectright"]},
+    "C-Left|M-b"  : {command: "goorselect", args: ["gotowordleft","selectwordleft"]},
+    "C-Right|M-f" : {command: "goorselect", args: ["gotowordright","selectwordright"]},
+    "Home|C-a"    : {command: "goorselect", args: ["gotolinestart","selecttolinestart"]},
+    "End|C-e"     : {command: "goorselect", args: ["gotolineend","selecttolineend"]},
+    "C-Home|S-M-,": {command: "goorselect", args: ["gotostart","selecttostart"]},
+    "C-End|S-M-." : {command: "goorselect", args: ["gotoend","selecttoend"]},
+    "S-Up|S-C-p"      : "selectup",
+    "S-Down|S-C-n"    : "selectdown",
+    "S-Left|S-C-b"    : "selectleft",
+    "S-Right|S-C-f"   : "selectright",
+    "S-C-Left|S-M-b"  : "selectwordleft",
+    "S-C-Right|S-M-f" : "selectwordright",
+    "S-Home|S-C-a"    : "selecttolinestart",
+    "S-End|S-C-e"     : "selecttolineend",
+    "S-C-Home"        : "selecttostart",
+    "S-C-End"         : "selecttoend",
+
+    "C-l" : "recenterTopBottom",
+    "M-s" : "centerselection",
+    "M-g": "gotoline",
+    "C-x C-p": "selectall",
+    "C-Down": {command: "goorselect", args: ["gotopagedown","selectpagedown"]},
+    "C-Up": {command: "goorselect", args: ["gotopageup","selectpageup"]},
+    "PageDown|C-v": {command: "goorselect", args: ["gotopagedown","selectpagedown"]},
+    "PageUp|M-v": {command: "goorselect", args: ["gotopageup","selectpageup"]},
+    "S-C-Down": "selectpagedown",
+    "S-C-Up": "selectpageup",
+
+    "C-s": "iSearch",
+    "C-r": "iSearchBackwards",
+
+    "M-C-s": "findnext",
+    "M-C-r": "findprevious",
+    "S-M-5": "replace",
+    "Backspace": "backspace",
+    "Delete|C-d": "del",
+    "Return|C-m": {command: "insertstring", args: "\n"}, // "newline"
+    "C-o": "splitline",
+
+    "M-d|C-Delete": {command: "killWord", args: "right"},
+    "C-Backspace|M-Backspace|M-Delete": {command: "killWord", args: "left"},
+    "C-k": "killLine",
+
+    "C-y|S-Delete": "yank",
+    "M-y": "yankRotate",
+    "C-g": "keyboardQuit",
+
+    "C-w": "killRegion",
+    "M-w": "killRingSave",
+    "C-Space": "setMark",
+    "C-x C-x": "exchangePointAndMark",
+
+    "C-t": "transposeletters",
+    "M-u": "touppercase",    // Doesn't work
+    "M-l": "tolowercase",
+    "M-/": "autocomplete",   // Doesn't work
+    "C-u": "universalArgument",
+
+    "M-;": "togglecomment",
+
+    "C-/|C-x u|S-C--|C-z": "undo",
+    "S-C-/|S-C-x u|C--|S-C-z": "redo", //infinite undo?
+    "C-x r":  "selectRectangularRegion",
+    "M-x": {command: "focusCommandLine", args: "M-x "}
+};
+
+
+exports.handler.bindKeys(exports.emacsKeys);
+
+exports.handler.addCommands({
+    recenterTopBottom: function(editor) {
+        var renderer = editor.renderer;
+        var pos = renderer.$cursorLayer.getPixelPosition();
+        var h = renderer.$size.scrollerHeight - renderer.lineHeight;
+        var scrollTop = renderer.scrollTop;
+        if (Math.abs(pos.top - scrollTop) < 2) {
+            scrollTop = pos.top - h;
+        } else if (Math.abs(pos.top - scrollTop - h * 0.5) < 2) {
+            scrollTop = pos.top;
+        } else {
+            scrollTop = pos.top - h * 0.5;
+        }
+        editor.session.setScrollTop(scrollTop);
+    },
+    selectRectangularRegion:  function(editor) {
+        editor.multiSelect.toggleBlockSelection();
+    },
+    setMark:  {
+        exec: function(editor, args) {
+            if (args && args.count) {
+                var mark = editor.popEmacsMark();
+                mark && editor.selection.moveCursorToPosition(mark);
+                return;
+            }
+
+            var mark = editor.emacsMark(),
+                transientMarkModeActive = true;
+            if (transientMarkModeActive && (mark || !editor.selection.isEmpty())) {
+                editor.pushEmacsMark();
+                editor.clearSelection();
+                return;
+            }
+
+            if (mark) {
+                var cp = editor.getCursorPosition();
+                if (editor.selection.isEmpty() &&
+                    mark.row == cp.row && mark.column == cp.column) {
+                    editor.pushEmacsMark();
+                    return;
+                }
+            }
+            mark = editor.getCursorPosition();
+            editor.setEmacsMark(mark);
+            editor.selection.setSelectionAnchor(mark.row, mark.column);
+        },
+        readonly: true,
+        handlesCount: true,
+        multiSelectAction: "forEach"
+    },
+    exchangePointAndMark: {
+        exec: function(editor, args) {
+            var sel = editor.selection;
+            if (args.count) {
+                var pos = editor.getCursorPosition();
+                sel.clearSelection();
+                sel.moveCursorToPosition(editor.popEmacsMark());
+                editor.pushEmacsMark(pos);
+                return;
+            }
+            var lastMark = editor.getLastEmacsMark();
+            var range = sel.getRange();
+            if (range.isEmpty()) {
+                sel.selectToPosition(lastMark);
+                return;
+            }
+            sel.setSelectionRange(range, !sel.isBackwards());
+        },
+        readonly: true,
+        handlesCount: true,
+        multiSelectAction: "forEach"
+    },
+    killWord: {
+        exec: function(editor, dir) {
+            editor.clearSelection();
+            if (dir == "left")
+                editor.selection.selectWordLeft();
+            else
+                editor.selection.selectWordRight();
+
+            var range = editor.getSelectionRange();
+            var text = editor.session.getTextRange(range);
+            exports.killRing.add(text);
+
+            editor.session.remove(range);
+            editor.clearSelection();
+        },
+        multiSelectAction: "forEach"
+    },
+    killLine: function(editor) {
+        editor.pushEmacsMark(null);
+        var pos = editor.getCursorPosition();
+        if (pos.column === 0 &&
+            editor.session.doc.getLine(pos.row).length === 0) {
+            editor.selection.selectLine();
+        } else {
+            editor.clearSelection();
+            editor.selection.selectLineEnd();
+        }
+        var range = editor.getSelectionRange();
+        var text = editor.session.getTextRange(range);
+        exports.killRing.add(text);
+
+        editor.session.remove(range);
+        editor.clearSelection();
+    },
+    yank: function(editor) {
+        editor.onPaste(exports.killRing.get() || '');
+        editor.keyBinding.$data.lastCommand = "yank";
+    },
+    yankRotate: function(editor) {
+        if (editor.keyBinding.$data.lastCommand != "yank")
+            return;
+        editor.undo();
+        editor.onPaste(exports.killRing.rotate());
+        editor.keyBinding.$data.lastCommand = "yank";
+    },
+    killRegion: {
+        exec: function(editor) {
+            exports.killRing.add(editor.getCopyText());
+            editor.commands.byName.cut.exec(editor);
+        },
+        readonly: true,
+        multiSelectAction: "forEach"
+    },
+    killRingSave: {
+        exec: function(editor) {
+            exports.killRing.add(editor.getCopyText());
+            setTimeout(function() {
+                var sel = editor.selection,
+                    range = sel.getRange();
+                editor.pushEmacsMark(sel.isBackwards() ? range.end : range.start);
+                sel.clearSelection();
+            }, 0);
+        },
+        readonly: true
+    },
+    keyboardQuit: function(editor) {
+        editor.selection.clearSelection();
+        editor.setEmacsMark(null);
+    },
+    focusCommandLine: function(editor, arg) {
+        if (editor.showCommandLine)
+            editor.showCommandLine(arg);
+    }
+});
+
+exports.handler.addCommands(iSearchCommandModule.iSearchStartCommands);
+
+var commands = exports.handler.commands;
+commands.yank.isYank = true;
+commands.yankRotate.isYank = true;
+
+exports.killRing = {
+    $data: [],
+    add: function(str) {
+        str && this.$data.push(str);
+        if (this.$data.length > 30)
+            this.$data.shift();
+    },
+    get: function(n) {
+        n = n || 1;
+        return this.$data.slice(this.$data.length-n, this.$data.length).reverse().join('\n');
+    },
+    pop: function() {
+        if (this.$data.length > 1)
+            this.$data.pop();
+        return this.get();
+    },
+    rotate: function() {
+        this.$data.unshift(this.$data.pop());
+        return this.get();
+    }
+};
+
+});

+ 1758 - 0
services/web/public/js/ace/keybinding-vim.js

@@ -0,0 +1,1758 @@
+define("ace/keyboard/vim/registers",["require","exports","module"], function(require, exports, module) {
+
+"never use strict";
+
+module.exports = {
+    _default: {
+        text: "",
+        isLine: false
+    }
+};
+
+});
+
+define("ace/keyboard/vim/maps/util",["require","exports","module","ace/keyboard/vim/registers","ace/lib/dom"], function(require, exports, module) {
+var registers = require("../registers");
+
+var dom = require("../../../lib/dom");
+dom.importCssString('.insert-mode .ace_cursor{\
+    border-left: 2px solid #333333;\
+}\
+.ace_dark.insert-mode .ace_cursor{\
+    border-left: 2px solid #eeeeee;\
+}\
+.normal-mode .ace_cursor{\
+    border: 0!important;\
+    background-color: red;\
+    opacity: 0.5;\
+}', 'vimMode');
+
+module.exports = {
+    onVisualMode: false,
+    onVisualLineMode: false,
+    currentMode: 'normal',
+    noMode: function(editor) {
+        editor.unsetStyle('insert-mode');
+        editor.unsetStyle('normal-mode');
+        if (editor.commands.recording)
+            editor.commands.toggleRecording(editor);
+        editor.setOverwrite(false);
+    },
+    insertMode: function(editor) {
+        this.currentMode = 'insert';
+        editor.setStyle('insert-mode');
+        editor.unsetStyle('normal-mode');
+
+        editor.setOverwrite(false);
+        editor.keyBinding.$data.buffer = "";
+        editor.keyBinding.$data.vimState = "insertMode";
+        this.onVisualMode = false;
+        this.onVisualLineMode = false;
+        if(this.onInsertReplaySequence) {
+            editor.commands.macro = this.onInsertReplaySequence;
+            editor.commands.replay(editor);
+            this.onInsertReplaySequence = null;
+            this.normalMode(editor);
+        } else {
+            editor._emit("changeStatus");
+            if(!editor.commands.recording)
+                editor.commands.toggleRecording(editor);
+        }
+    },
+    normalMode: function(editor) {
+        this.currentMode = 'normal';
+
+        editor.unsetStyle('insert-mode');
+        editor.setStyle('normal-mode');
+        editor.clearSelection();
+
+        var pos;
+        if (!editor.getOverwrite()) {
+            pos = editor.getCursorPosition();
+            if (pos.column > 0)
+                editor.navigateLeft();
+        }
+
+        editor.setOverwrite(true);
+        editor.keyBinding.$data.buffer = "";
+        editor.keyBinding.$data.vimState = "start";
+        this.onVisualMode = false;
+        this.onVisualLineMode = false;
+        editor._emit("changeStatus");
+        if (editor.commands.recording) {
+            editor.commands.toggleRecording(editor);
+            return editor.commands.macro;
+        }
+        else {
+            return [];
+        }
+    },
+    visualMode: function(editor, lineMode) {
+        if (
+            (this.onVisualLineMode && lineMode)
+            || (this.onVisualMode && !lineMode)
+        ) {
+            this.normalMode(editor);
+            return;
+        }
+
+        editor.setStyle('insert-mode');
+        editor.unsetStyle('normal-mode');
+
+        editor._emit("changeStatus");
+        if (lineMode) {
+            this.onVisualLineMode = true;
+        } else {
+            this.onVisualMode = true;
+            this.onVisualLineMode = false;
+        }
+    },
+    getRightNthChar: function(editor, cursor, ch, n) {
+        var line = editor.getSession().getLine(cursor.row);
+        var matches = line.substr(cursor.column + 1).split(ch);
+
+        return n < matches.length ? matches.slice(0, n).join(ch).length : null;
+    },
+    getLeftNthChar: function(editor, cursor, ch, n) {
+        var line = editor.getSession().getLine(cursor.row);
+        var matches = line.substr(0, cursor.column).split(ch);
+
+        return n < matches.length ? matches.slice(-1 * n).join(ch).length : null;
+    },
+    toRealChar: function(ch) {
+        if (ch.length === 1)
+            return ch;
+
+        if (/^shift-./.test(ch))
+            return ch[ch.length - 1].toUpperCase();
+        else
+            return "";
+    },
+    copyLine: function(editor) {
+        var pos = editor.getCursorPosition();
+        editor.selection.moveTo(pos.row, pos.column);
+        editor.selection.selectLine();
+        registers._default.isLine = true;
+        registers._default.text = editor.getCopyText().replace(/\n$/, "");
+        editor.selection.moveTo(pos.row, pos.column);
+    }
+};
+});
+
+define("ace/keyboard/vim/maps/motions",["require","exports","module","ace/keyboard/vim/maps/util","ace/search","ace/range"], function(require, exports, module) {
+"use strict";
+
+var util = require("./util");
+
+var keepScrollPosition = function(editor, fn) {
+    var scrollTopRow = editor.renderer.getScrollTopRow();
+    var initialRow = editor.getCursorPosition().row;
+    var diff = initialRow - scrollTopRow;
+    fn && fn.call(editor);
+    editor.renderer.scrollToRow(editor.getCursorPosition().row - diff);
+};
+
+function Motion(m) {
+    if (typeof m == "function") {
+        var getPos = m;
+        m = this;
+    } else {
+        var getPos = m.getPos;
+    }
+    m.nav = function(editor, range, count, param) {
+        var a = getPos(editor, range, count, param, false);
+        if (!a)
+            return;
+        editor.selection.moveTo(a.row, a.column);
+    };
+    m.sel = function(editor, range, count, param) {
+        var a = getPos(editor, range, count, param, true);
+        if (!a)
+            return;
+        editor.selection.selectTo(a.row, a.column);
+    };
+    return m;
+}
+
+var nonWordRe = /[\s.\/\\()\"'-:,.;<>~!@#$%^&*|+=\[\]{}`~?]/;
+var wordSeparatorRe = /[.\/\\()\"'-:,.;<>~!@#$%^&*|+=\[\]{}`~?]/;
+var whiteRe = /\s/;
+var StringStream = function(editor, cursor) {
+    var sel = editor.selection;
+    this.range = sel.getRange();
+    cursor = cursor || sel.selectionLead;
+    this.row = cursor.row;
+    this.col = cursor.column;
+    var line = editor.session.getLine(this.row);
+    var maxRow = editor.session.getLength();
+    this.ch = line[this.col] || '\n';
+    this.skippedLines = 0;
+
+    this.next = function() {
+        this.ch = line[++this.col] || this.handleNewLine(1);
+        return this.ch;
+    };
+    this.prev = function() {
+        this.ch = line[--this.col] || this.handleNewLine(-1);
+        return this.ch;
+    };
+    this.peek = function(dir) {
+        var ch = line[this.col + dir];
+        if (ch)
+            return ch;
+        if (dir == -1)
+            return '\n';
+        if (this.col == line.length - 1)
+            return '\n';
+        return editor.session.getLine(this.row + 1)[0] || '\n';
+    };
+
+    this.handleNewLine = function(dir) {
+        if (dir == 1){
+            if (this.col == line.length)
+                return '\n';
+            if (this.row == maxRow - 1)
+                return '';
+            this.col = 0;
+            this.row ++;
+            line = editor.session.getLine(this.row);
+            this.skippedLines++;
+            return line[0] || '\n';
+        }
+        if (dir == -1) {
+            if (this.row === 0)
+                return '';
+            this.row --;
+            line = editor.session.getLine(this.row);
+            this.col = line.length;
+            this.skippedLines--;
+            return '\n';
+        }
+    };
+    this.debug = function() {
+        console.log(line.substring(0, this.col)+'|'+this.ch+'\''+this.col+'\''+line.substr(this.col+1));
+    };
+};
+
+var Search = require("../../../search").Search;
+var search = new Search();
+
+function find(editor, needle, dir) {
+    search.$options.needle = needle;
+    search.$options.backwards = dir == -1;
+    return search.find(editor.session);
+}
+
+var Range = require("../../../range").Range;
+
+var LAST_SEARCH_MOTION = {};
+
+module.exports = {
+    "w": new Motion(function(editor) {
+        var str = new StringStream(editor);
+
+        if (str.ch && wordSeparatorRe.test(str.ch)) {
+            while (str.ch && wordSeparatorRe.test(str.ch))
+                str.next();
+        } else {
+            while (str.ch && !nonWordRe.test(str.ch))
+                str.next();
+        }
+        while (str.ch && whiteRe.test(str.ch) && str.skippedLines < 2)
+            str.next();
+
+        str.skippedLines == 2 && str.prev();
+        return {column: str.col, row: str.row};
+    }),
+    "W": new Motion(function(editor) {
+        var str = new StringStream(editor);
+        while(str.ch && !(whiteRe.test(str.ch) && !whiteRe.test(str.peek(1))) && str.skippedLines < 2)
+            str.next();
+        if (str.skippedLines == 2)
+            str.prev();
+        else
+            str.next();
+
+        return {column: str.col, row: str.row};
+    }),
+    "b": new Motion(function(editor) {
+        var str = new StringStream(editor);
+
+        str.prev();
+        while (str.ch && whiteRe.test(str.ch) && str.skippedLines > -2)
+            str.prev();
+
+        if (str.ch && wordSeparatorRe.test(str.ch)) {
+            while (str.ch && wordSeparatorRe.test(str.ch))
+                str.prev();
+        } else {
+            while (str.ch && !nonWordRe.test(str.ch))
+                str.prev();
+        }
+        str.ch && str.next();
+        return {column: str.col, row: str.row};
+    }),
+    "B": new Motion(function(editor) {
+        var str = new StringStream(editor);
+        str.prev();
+        while(str.ch && !(!whiteRe.test(str.ch) && whiteRe.test(str.peek(-1))) && str.skippedLines > -2)
+            str.prev();
+
+        if (str.skippedLines == -2)
+            str.next();
+
+        return {column: str.col, row: str.row};
+    }),
+    "e": new Motion(function(editor) {
+        var str = new StringStream(editor);
+
+        str.next();
+        while (str.ch && whiteRe.test(str.ch))
+            str.next();
+
+        if (str.ch && wordSeparatorRe.test(str.ch)) {
+            while (str.ch && wordSeparatorRe.test(str.ch))
+                str.next();
+        } else {
+            while (str.ch && !nonWordRe.test(str.ch))
+                str.next();
+        }
+        str.ch && str.prev();
+        return {column: str.col, row: str.row};
+    }),
+    "E": new Motion(function(editor) {
+        var str = new StringStream(editor);
+        str.next();
+        while(str.ch && !(!whiteRe.test(str.ch) && whiteRe.test(str.peek(1))))
+            str.next();
+
+        return {column: str.col, row: str.row};
+    }),
+
+    "l": {
+        nav: function(editor) {
+            var pos = editor.getCursorPosition();
+            var col = pos.column;
+            var lineLen = editor.session.getLine(pos.row).length;
+            if (lineLen && col !== lineLen)
+                editor.navigateRight();
+        },
+        sel: function(editor) {
+            var pos = editor.getCursorPosition();
+            var col = pos.column;
+            var lineLen = editor.session.getLine(pos.row).length;
+            if (lineLen && col !== lineLen) //In selection mode you can select the newline
+                editor.selection.selectRight();
+        }
+    },
+    "h": {
+        nav: function(editor) {
+            var pos = editor.getCursorPosition();
+            if (pos.column > 0)
+                editor.navigateLeft();
+        },
+        sel: function(editor) {
+            var pos = editor.getCursorPosition();
+            if (pos.column > 0)
+                editor.selection.selectLeft();
+        }
+    },
+    "H": {
+        nav: function(editor) {
+            var row = editor.renderer.getScrollTopRow();
+            editor.moveCursorTo(row);
+        },
+        sel: function(editor) {
+            var row = editor.renderer.getScrollTopRow();
+            editor.selection.selectTo(row);
+        }
+    },
+    "M": {
+        nav: function(editor) {
+            var topRow = editor.renderer.getScrollTopRow();
+            var bottomRow = editor.renderer.getScrollBottomRow();
+            var row = topRow + ((bottomRow - topRow) / 2);
+            editor.moveCursorTo(row);
+        },
+        sel: function(editor) {
+            var topRow = editor.renderer.getScrollTopRow();
+            var bottomRow = editor.renderer.getScrollBottomRow();
+            var row = topRow + ((bottomRow - topRow) / 2);
+            editor.selection.selectTo(row);
+        }
+    },
+    "L": {
+        nav: function(editor) {
+            var row = editor.renderer.getScrollBottomRow();
+            editor.moveCursorTo(row);
+        },
+        sel: function(editor) {
+            var row = editor.renderer.getScrollBottomRow();
+            editor.selection.selectTo(row);
+        }
+    },
+    "k": {
+        nav: function(editor) {
+            editor.navigateUp();
+        },
+        sel: function(editor) {
+            editor.selection.selectUp();
+        }
+    },
+    "j": {
+        nav: function(editor) {
+            editor.navigateDown();
+        },
+        sel: function(editor) {
+            editor.selection.selectDown();
+        }
+    },
+
+    "i": {
+        param: true,
+        sel: function(editor, range, count, param) {
+            switch (param) {
+                case "w":
+                    editor.selection.selectWord();
+                    break;
+                case "W":
+                    editor.selection.selectAWord();
+                    break;
+                case "(":
+                case "{":
+                case "[":
+                    var cursor = editor.getCursorPosition();
+                    var end = editor.session.$findClosingBracket(param, cursor, /paren/);
+                    if (!end)
+                        return;
+                    var start = editor.session.$findOpeningBracket(editor.session.$brackets[param], cursor, /paren/);
+                    if (!start)
+                        return;
+                    start.column ++;
+                    editor.selection.setSelectionRange(Range.fromPoints(start, end));
+                    break;
+                case "'":
+                case '"':
+                case "/":
+                    var end = find(editor, param, 1);
+                    if (!end)
+                        return;
+                    var start = find(editor, param, -1);
+                    if (!start)
+                        return;
+                    editor.selection.setSelectionRange(Range.fromPoints(start.end, end.start));
+                    break;
+            }
+        }
+    },
+    "a": {
+        param: true,
+        sel: function(editor, range, count, param) {
+            switch (param) {
+                case "w":
+                    editor.selection.selectAWord();
+                    break;
+                case "W":
+                    editor.selection.selectAWord();
+                    break;
+                case ")":
+                case "}":
+                case "]":
+                    param = editor.session.$brackets[param];
+                case "(":
+                case "{":
+                case "[":
+                    var cursor = editor.getCursorPosition();
+                    var end = editor.session.$findClosingBracket(param, cursor, /paren/);
+                    if (!end)
+                        return;
+                    var start = editor.session.$findOpeningBracket(editor.session.$brackets[param], cursor, /paren/);
+                    if (!start)
+                        return;
+                    end.column ++;
+                    editor.selection.setSelectionRange(Range.fromPoints(start, end));
+                    break;
+                case "'":
+                case "\"":
+                case "/":
+                    var end = find(editor, param, 1);
+                    if (!end)
+                        return;
+                    var start = find(editor, param, -1);
+                    if (!start)
+                        return;
+                    end.column ++;
+                    editor.selection.setSelectionRange(Range.fromPoints(start.start, end.end));
+                    break;
+            }
+        }
+    },
+
+    "f": new Motion({
+        param: true,
+        handlesCount: true,
+        getPos: function(editor, range, count, param, isSel, isRepeat) {
+            if (param == "space") param = " ";
+            if (!isRepeat)
+                LAST_SEARCH_MOTION = {ch: "f", param: param};
+            var cursor = editor.getCursorPosition();
+            var column = util.getRightNthChar(editor, cursor, param, count || 1);
+
+            if (typeof column === "number") {
+                cursor.column += column + (isSel ? 2 : 1);
+                return cursor;
+            }
+        }
+    }),
+    "F": new Motion({
+        param: true,
+        handlesCount: true,
+        getPos: function(editor, range, count, param, isSel, isRepeat) {
+            if (param == "space") param = " ";
+            if (!isRepeat)
+                LAST_SEARCH_MOTION = {ch: "F", param: param};
+            var cursor = editor.getCursorPosition();
+            var column = util.getLeftNthChar(editor, cursor, param, count || 1);
+
+            if (typeof column === "number") {
+                cursor.column -= column + 1;
+                return cursor;
+            }
+        }
+    }),
+    "t": new Motion({
+        param: true,
+        handlesCount: true,
+        getPos: function(editor, range, count, param, isSel, isRepeat) {
+            if (param == "space") param = " ";
+            if (!isRepeat)
+                LAST_SEARCH_MOTION = {ch: "t", param: param};
+            var cursor = editor.getCursorPosition();
+            var column = util.getRightNthChar(editor, cursor, param, count || 1);
+
+            if (isRepeat && column == 0 && !(count > 1))
+                var column = util.getRightNthChar(editor, cursor, param, 2);
+                
+            if (typeof column === "number") {
+                cursor.column += column + (isSel ? 1 : 0);
+                return cursor;
+            }
+        }
+    }),
+    "T": new Motion({
+        param: true,
+        handlesCount: true,
+        getPos: function(editor, range, count, param, isSel, isRepeat) {
+            if (param == "space") param = " ";
+            if (!isRepeat)
+                LAST_SEARCH_MOTION = {ch: "T", param: param};
+            var cursor = editor.getCursorPosition();
+            var column = util.getLeftNthChar(editor, cursor, param, count || 1);
+
+            if (isRepeat && column == 0 && !(count > 1))
+                var column = util.getLeftNthChar(editor, cursor, param, 2);
+            
+            if (typeof column === "number") {
+                cursor.column -= column;
+                return cursor;
+            }
+        }
+    }),
+    ";": new Motion({
+        handlesCount: true,
+        getPos: function(editor, range, count, param, isSel) {
+            var ch = LAST_SEARCH_MOTION.ch;
+            if (!ch)
+                return;
+            return module.exports[ch].getPos(
+                editor, range, count, LAST_SEARCH_MOTION.param, isSel, true
+            );
+        }
+    }),
+    ",": new Motion({
+        handlesCount: true,
+        getPos: function(editor, range, count, param, isSel) {
+            var ch = LAST_SEARCH_MOTION.ch;
+            if (!ch)
+                return;
+            var up = ch.toUpperCase();
+            ch = ch === up ? ch.toLowerCase() : up;
+            
+            return module.exports[ch].getPos(
+                editor, range, count, LAST_SEARCH_MOTION.param, isSel, true
+            );
+        }
+    }),
+
+    "^": {
+        nav: function(editor) {
+            editor.navigateLineStart();
+        },
+        sel: function(editor) {
+            editor.selection.selectLineStart();
+        }
+    },
+    "$": {
+        handlesCount: true,
+        nav: function(editor, range, count, param) {
+            if (count > 1) {
+                editor.navigateDown(count-1);
+            }
+            editor.navigateLineEnd();
+        },
+        sel: function(editor, range, count, param) {
+            if (count > 1) {
+                editor.selection.moveCursorBy(count-1, 0);
+            }
+            editor.selection.selectLineEnd();
+        }
+    },
+    "0": new Motion(function(ed) {
+        return {row: ed.selection.lead.row, column: 0};
+    }),
+    "G": {
+        nav: function(editor, range, count, param) {
+            if (!count && count !== 0) { // Stupid JS
+                count = editor.session.getLength();
+            }
+            editor.gotoLine(count);
+        },
+        sel: function(editor, range, count, param) {
+            if (!count && count !== 0) { // Stupid JS
+                count = editor.session.getLength();
+            }
+            editor.selection.selectTo(count, 0);
+        }
+    },
+    "g": {
+        param: true,
+        nav: function(editor, range, count, param) {
+            switch(param) {
+                case "m":
+                    console.log("Middle line");
+                    break;
+                case "e":
+                    console.log("End of prev word");
+                    break;
+                case "g":
+                    editor.gotoLine(count || 0);
+                case "u":
+                    editor.gotoLine(count || 0);
+                case "U":
+                    editor.gotoLine(count || 0);
+            }
+        },
+        sel: function(editor, range, count, param) {
+            switch(param) {
+                case "m":
+                    console.log("Middle line");
+                    break;
+                case "e":
+                    console.log("End of prev word");
+                    break;
+                case "g":
+                    editor.selection.selectTo(count || 0, 0);
+            }
+        }
+    },
+    "o": {
+        nav: function(editor, range, count, param) {
+            count = count || 1;
+            var content = "";
+            while (0 < count--)
+                content += "\n";
+
+            if (content.length) {
+                editor.navigateLineEnd()
+                editor.insert(content);
+                util.insertMode(editor);
+            }
+        }
+    },
+    "O": {
+        nav: function(editor, range, count, param) {
+            var row = editor.getCursorPosition().row;
+            count = count || 1;
+            var content = "";
+            while (0 < count--)
+                content += "\n";
+
+            if (content.length) {
+                if(row > 0) {
+                    editor.navigateUp();
+                    editor.navigateLineEnd()
+                    editor.insert(content);
+                } else {
+                    editor.session.insert({row: 0, column: 0}, content);
+                    editor.navigateUp();
+                }
+                util.insertMode(editor);
+            }
+        }
+    },
+    "%": new Motion(function(editor){
+        var brRe = /[\[\]{}()]/g;
+        var cursor = editor.getCursorPosition();
+        var ch = editor.session.getLine(cursor.row)[cursor.column];
+        if (!brRe.test(ch)) {
+            var range = find(editor, brRe);
+            if (!range)
+                return;
+            cursor = range.start;
+        }
+        var match = editor.session.findMatchingBracket({
+            row: cursor.row,
+            column: cursor.column + 1
+        });
+
+        return match;
+    }),
+    "{": new Motion(function(ed) {
+        var session = ed.session;
+        var row = session.selection.lead.row;
+        while(row > 0 && !/\S/.test(session.getLine(row)))
+            row--;
+        while(/\S/.test(session.getLine(row)))
+            row--;
+        return {column: 0, row: row};
+    }),
+    "}": new Motion(function(ed) {
+        var session = ed.session;
+        var l = session.getLength();
+        var row = session.selection.lead.row;
+        while(row < l && !/\S/.test(session.getLine(row)))
+            row++;
+        while(/\S/.test(session.getLine(row)))
+            row++;
+        return {column: 0, row: row};
+    }),
+    "ctrl-d": {
+        nav: function(editor, range, count, param) {
+            editor.selection.clearSelection();
+            keepScrollPosition(editor, editor.gotoPageDown);
+        },
+        sel: function(editor, range, count, param) {
+            keepScrollPosition(editor, editor.selectPageDown);
+        }
+    },
+    "ctrl-u": {
+        nav: function(editor, range, count, param) {
+            editor.selection.clearSelection();
+            keepScrollPosition(editor, editor.gotoPageUp);
+        },
+        sel: function(editor, range, count, param) {
+            keepScrollPosition(editor, editor.selectPageUp);
+        }
+    },
+    "`": new Motion({
+        param: true,
+        handlesCount: true,
+        getPos: function(editor, range, count, param, isSel) {
+            var s = editor.session;
+            var marker = s.vimMarkers && s.vimMarkers[param];
+            if (marker) {
+                return marker.getPosition();
+            }
+        }
+    }),
+    "'": new Motion({
+        param: true,
+        handlesCount: true,
+        getPos: function(editor, range, count, param, isSel) {
+            var s = editor.session;
+            var marker = s.vimMarkers && s.vimMarkers[param];
+            if (marker) {
+                var pos = marker.getPosition();
+                var line = editor.session.getLine(pos.row);                
+                pos.column = line.search(/\S/);
+                if (pos.column == -1)
+                    pos.column = line.length;
+                return pos;
+            }
+        },
+        isLine: true
+    })
+};
+
+module.exports.backspace = module.exports.left = module.exports.h;
+module.exports.space = module.exports['return'] = module.exports.right = module.exports.l;
+module.exports.up = module.exports.k;
+module.exports.down = module.exports.j;
+module.exports.pagedown = module.exports["ctrl-d"];
+module.exports.pageup = module.exports["ctrl-u"];
+module.exports.home = module.exports["0"];
+module.exports.end = module.exports["$"];
+
+});
+
+define("ace/keyboard/vim/maps/operators",["require","exports","module","ace/keyboard/vim/maps/util","ace/keyboard/vim/registers","ace/range"], function(require, exports, module) {
+
+"use strict";
+
+var util = require("./util");
+var registers = require("../registers");
+var Range = require("../../../range").Range;
+
+module.exports = {
+    "d": {
+        selFn: function(editor, range, count, param) {
+            registers._default.text = editor.getCopyText();
+            registers._default.isLine = util.onVisualLineMode;
+            if(util.onVisualLineMode)
+                editor.removeLines();
+            else
+                editor.session.remove(range);
+            util.normalMode(editor);
+        },
+        fn: function(editor, range, count, param) {
+            count = count || 1;
+            switch (param) {
+                case "d":
+                    registers._default.text = "";
+                    registers._default.isLine = true;
+                    for (var i = 0; i < count; i++) {
+                        editor.selection.selectLine();
+                        registers._default.text += editor.getCopyText();
+                        var selRange = editor.getSelectionRange();
+                        if (!selRange.isMultiLine()) {
+                            var row = selRange.start.row - 1;
+                            var col = editor.session.getLine(row).length
+                            selRange.setStart(row, col);
+                            editor.session.remove(selRange);
+                            editor.selection.clearSelection();
+                            break;
+                        }
+                        editor.session.remove(selRange);
+                        editor.selection.clearSelection();
+                    }
+                    registers._default.text = registers._default.text.replace(/\n$/, "");
+                    break;
+                default:
+                    if (range) {
+                        editor.selection.setSelectionRange(range);
+                        registers._default.text = editor.getCopyText();
+                        registers._default.isLine = false;
+                        editor.session.remove(range);
+                        editor.selection.clearSelection();
+                    }
+            }
+        }
+    },
+    "c": {
+        selFn: function(editor, range, count, param) {
+            editor.session.remove(range);
+            util.insertMode(editor);
+        },
+        fn: function(editor, range, count, param) {
+            count = count || 1;
+            switch (param) {
+                case "c":
+                    editor.$blockScrolling++;
+                    editor.selection.$moveSelection(function() {
+                        editor.selection.moveCursorBy(count - 1, 0);
+                    });
+                    var rows = editor.$getSelectedRows();
+                    range = new Range(rows.first, 0, rows.last, Infinity);
+                    editor.session.remove(range);
+                    editor.$blockScrolling--;
+                    util.insertMode(editor);
+                    break;
+                default:
+                    if (range) {
+                        editor.session.remove(range);
+                        util.insertMode(editor);
+                    }
+            }
+        }
+    },
+    "y": {
+        selFn: function(editor, range, count, param) {
+            registers._default.text = editor.getCopyText();
+            registers._default.isLine = util.onVisualLineMode;
+            editor.selection.clearSelection();
+            util.normalMode(editor);
+        },
+        fn: function(editor, range, count, param) {
+            count = count || 1;
+            if (param && param.isLine) 
+                param = "y";
+            switch (param) {
+                case "y":
+                    var pos = editor.getCursorPosition();
+                    editor.selection.selectLine();
+                    for (var i = 0; i < count - 1; i++) {
+                        editor.selection.moveCursorDown();
+                    }
+                    registers._default.text = editor.getCopyText().replace(/\n$/, "");
+                    editor.selection.clearSelection();
+                    registers._default.isLine = true;
+                    editor.moveCursorToPosition(pos);
+                    break;
+                default:
+                    if (range) {
+                        var pos = editor.getCursorPosition();
+                        editor.selection.setSelectionRange(range);
+                        registers._default.text = editor.getCopyText();
+                        registers._default.isLine = false;
+                        editor.selection.clearSelection();
+                        editor.moveCursorTo(pos.row, pos.column);
+                    }
+            }
+        }
+    },
+    ">": {
+        selFn: function(editor, range, count, param) {
+            count = count || 1;
+            for (var i = 0; i < count; i++) {
+                editor.indent();
+            }
+            util.normalMode(editor);
+        },
+        fn: function(editor, range, count, param) {
+            count = parseInt(count || 1, 10);
+            switch (param) {
+                case ">":
+                    var pos = editor.getCursorPosition();
+                    editor.selection.selectLine();
+                    for (var i = 0; i < count - 1; i++) {
+                        editor.selection.moveCursorDown();
+                    }
+                    editor.indent();
+                    editor.selection.clearSelection();
+                    editor.moveCursorToPosition(pos);
+                    editor.navigateLineEnd();
+                    editor.navigateLineStart();
+                    break;
+            }
+        }
+    },
+    "<": {
+        selFn: function(editor, range, count, param) {
+            count = count || 1;
+            for (var i = 0; i < count; i++) {
+                editor.blockOutdent();
+            }
+            util.normalMode(editor);
+        },
+        fn: function(editor, range, count, param) {
+            count = count || 1;
+            switch (param) {
+                case "<":
+                    var pos = editor.getCursorPosition();
+                    editor.selection.selectLine();
+                    for (var i = 0; i < count - 1; i++) {
+                        editor.selection.moveCursorDown();
+                    }
+                    editor.blockOutdent();
+                    editor.selection.clearSelection();
+                    editor.moveCursorToPosition(pos);
+                    editor.navigateLineEnd();
+                    editor.navigateLineStart();
+                    break;
+            }
+        }
+    }
+};
+});
+
+"use strict"
+
+define("ace/keyboard/vim/maps/aliases",["require","exports","module"], function(require, exports, module) {
+module.exports = {
+    "x": {
+        operator: {
+            ch: "d",
+            count: 1
+        },
+        motion: {
+            ch: "l",
+            count: 1
+        }
+    },
+    "X": {
+        operator: {
+            ch: "d",
+            count: 1
+        },
+        motion: {
+            ch: "h",
+            count: 1
+        }
+    },
+    "D": {
+        operator: {
+            ch: "d",
+            count: 1
+        },
+        motion: {
+            ch: "$",
+            count: 1
+        }
+    },
+    "C": {
+        operator: {
+            ch: "c",
+            count: 1
+        },
+        motion: {
+            ch: "$",
+            count: 1
+        }
+    },
+    "s": {
+        operator: {
+            ch: "c",
+            count: 1
+        },
+        motion: {
+            ch: "l",
+            count: 1
+        }
+    },
+    "S": {
+        operator: {
+            ch: "c",
+            count: 1
+        },
+        param: "c"
+    }
+};
+});
+
+define("ace/keyboard/vim/commands",["require","exports","module","ace/lib/lang","ace/keyboard/vim/maps/util","ace/keyboard/vim/maps/motions","ace/keyboard/vim/maps/operators","ace/keyboard/vim/maps/aliases","ace/keyboard/vim/registers"], function(require, exports, module) {
+
+"never use strict";
+
+var lang = require("../../lib/lang");
+var util = require("./maps/util");
+var motions = require("./maps/motions");
+var operators = require("./maps/operators");
+var alias = require("./maps/aliases");
+var registers = require("./registers");
+
+var NUMBER = 1;
+var OPERATOR = 2;
+var MOTION = 3;
+var ACTION = 4;
+var HMARGIN = 8; // Minimum amount of line separation between margins;
+
+var repeat = function repeat(fn, count, args) {
+    while (0 < count--)
+        fn.apply(this, args);
+};
+
+var ensureScrollMargin = function(editor) {
+    var renderer = editor.renderer;
+    var pos = renderer.$cursorLayer.getPixelPosition();
+
+    var top = pos.top;
+
+    var margin = HMARGIN * renderer.layerConfig.lineHeight;
+    if (2 * margin > renderer.$size.scrollerHeight)
+        margin = renderer.$size.scrollerHeight / 2;
+
+    if (renderer.scrollTop > top - margin) {
+        renderer.session.setScrollTop(top - margin);
+    }
+
+    if (renderer.scrollTop + renderer.$size.scrollerHeight < top + margin + renderer.lineHeight) {
+        renderer.session.setScrollTop(top + margin + renderer.lineHeight - renderer.$size.scrollerHeight);
+    }
+};
+
+var actions = exports.actions = {
+    "z": {
+        param: true,
+        fn: function(editor, range, count, param) {
+            switch (param) {
+                case "z":
+                    editor.renderer.alignCursor(null, 0.5);
+                    break;
+                case "t":
+                    editor.renderer.alignCursor(null, 0);
+                    break;
+                case "b":
+                    editor.renderer.alignCursor(null, 1);
+                    break;
+                case "c":
+                    editor.session.onFoldWidgetClick(range.start.row, {domEvent:{target :{}}});
+                    break;
+                case "o":
+                    editor.session.onFoldWidgetClick(range.start.row, {domEvent:{target :{}}});
+                    break;
+                case "C":
+                    editor.session.foldAll();
+                    break;
+                case "O":
+                    editor.session.unfold();
+                    break;
+            }
+        }
+    },
+    "r": {
+        param: true,
+        fn: function(editor, range, count, param) {
+            if (param && param.length) {
+                if (param.length > 1)
+                    param = param == "return" ? "\n" : param == "tab" ? "\t" : param;
+                repeat(function() { editor.insert(param); }, count || 1);
+                editor.navigateLeft();
+            }
+        }
+    },
+    "R": {
+        fn: function(editor, range, count, param) {
+            util.insertMode(editor);
+            editor.setOverwrite(true);
+        }
+    },
+    "~": {
+        fn: function(editor, range, count) {
+            repeat(function() {
+                var range = editor.selection.getRange();
+                if (range.isEmpty())
+                    range.end.column++;
+                var text = editor.session.getTextRange(range);
+                var toggled = text.toUpperCase();
+                if (toggled != text)
+                    editor.session.replace(range, toggled);
+                else if (text.toLowerCase() != text)
+                    editor.session.replace(range, text.toLowerCase())
+                else
+                    editor.navigateRight();
+            }, count || 1);
+        }
+    },
+    "*": {
+        fn: function(editor, range, count, param) {
+            editor.selection.selectWord();
+            editor.findNext();
+            ensureScrollMargin(editor);
+            var r = editor.selection.getRange();
+            editor.selection.setSelectionRange(r, true);
+        }
+    },
+    "#": {
+        fn: function(editor, range, count, param) {
+            editor.selection.selectWord();
+            editor.findPrevious();
+            ensureScrollMargin(editor);
+            var r = editor.selection.getRange();
+            editor.selection.setSelectionRange(r, true);
+        }
+    },
+    "m": {
+        param: true,
+        fn: function(editor, range, count, param) {
+            var s =  editor.session;
+            var markers = s.vimMarkers || (s.vimMarkers = {});
+            var c = editor.getCursorPosition();
+            if (!markers[param]) {
+                markers[param] = editor.session.doc.createAnchor(c);
+            }
+            markers[param].setPosition(c.row, c.column, true);
+        }
+    },
+    "n": {
+        fn: function(editor, range, count, param) {
+            var options = editor.getLastSearchOptions();
+            options.backwards = false;
+            options.start = null;
+
+            editor.selection.moveCursorRight();
+            editor.selection.clearSelection();
+            editor.findNext(options);
+
+            ensureScrollMargin(editor);
+            var r = editor.selection.getRange();
+            r.end.row = r.start.row;
+            r.end.column = r.start.column;
+            editor.selection.setSelectionRange(r, true);
+        }
+    },
+    "N": {
+        fn: function(editor, range, count, param) {
+            var options = editor.getLastSearchOptions();
+            options.backwards = true;
+            options.start = null;
+
+            editor.findPrevious(options);
+            ensureScrollMargin(editor);
+            var r = editor.selection.getRange();
+            r.end.row = r.start.row;
+            r.end.column = r.start.column;
+            editor.selection.setSelectionRange(r, true);
+        }
+    },
+    "v": {
+        fn: function(editor, range, count, param) {
+            editor.selection.selectRight();
+            util.visualMode(editor, false);
+        },
+        acceptsMotion: true
+    },
+    "V": {
+        fn: function(editor, range, count, param) {
+            var row = editor.getCursorPosition().row;
+            editor.selection.moveTo(row, 0);
+            editor.selection.selectLineEnd();
+            editor.selection.visualLineStart = row;
+
+            util.visualMode(editor, true);
+        },
+        acceptsMotion: true
+    },
+    "Y": {
+        fn: function(editor, range, count, param) {
+            util.copyLine(editor);
+        }
+    },
+    "p": {
+        fn: function(editor, range, count, param) {
+            var defaultReg = registers._default;
+
+            editor.setOverwrite(false);
+            if (defaultReg.isLine) {
+                var pos = editor.getCursorPosition();
+                pos.column = editor.session.getLine(pos.row).length;
+                var text = lang.stringRepeat("\n" + defaultReg.text, count || 1);
+                editor.session.insert(pos, text);
+                editor.moveCursorTo(pos.row + 1, 0);
+            }
+            else {
+                editor.navigateRight();
+                editor.insert(lang.stringRepeat(defaultReg.text, count || 1));
+                editor.navigateLeft();
+            }
+            editor.setOverwrite(true);
+            editor.selection.clearSelection();
+        }
+    },
+    "P": {
+        fn: function(editor, range, count, param) {
+            var defaultReg = registers._default;
+            editor.setOverwrite(false);
+
+            if (defaultReg.isLine) {
+                var pos = editor.getCursorPosition();
+                pos.column = 0;
+                var text = lang.stringRepeat(defaultReg.text + "\n", count || 1);
+                editor.session.insert(pos, text);
+                editor.moveCursorToPosition(pos);
+            }
+            else {
+                editor.insert(lang.stringRepeat(defaultReg.text, count || 1));
+            }
+            editor.setOverwrite(true);
+            editor.selection.clearSelection();
+        }
+    },
+    "J": {
+        fn: function(editor, range, count, param) {
+            var session = editor.session;
+            range = editor.getSelectionRange();
+            var pos = {row: range.start.row, column: range.start.column};
+            count = count || range.end.row - range.start.row;
+            var maxRow = Math.min(pos.row + (count || 1), session.getLength() - 1);
+
+            range.start.column = session.getLine(pos.row).length;
+            range.end.column = session.getLine(maxRow).length;
+            range.end.row = maxRow;
+
+            var text = "";
+            for (var i = pos.row; i < maxRow; i++) {
+                var nextLine = session.getLine(i + 1);
+                text += " " + /^\s*(.*)$/.exec(nextLine)[1] || "";
+            }
+
+            session.replace(range, text);
+            editor.moveCursorTo(pos.row, pos.column);
+        }
+    },
+    "u": {
+        fn: function(editor, range, count, param) {
+            count = parseInt(count || 1, 10);
+            for (var i = 0; i < count; i++) {
+                editor.undo();
+            }
+            editor.selection.clearSelection();
+        }
+    },
+    "ctrl-r": {
+        fn: function(editor, range, count, param) {
+            count = parseInt(count || 1, 10);
+            for (var i = 0; i < count; i++) {
+                editor.redo();
+            }
+            editor.selection.clearSelection();
+        }
+    },
+    ":": {
+        fn: function(editor, range, count, param) {
+            var val = ":";
+            if (count > 1)
+                val = ".,.+" + count + val;
+            if (editor.showCommandLine)
+                editor.showCommandLine(val);
+        }
+    },
+    "/": {
+        fn: function(editor, range, count, param) {
+            if (editor.showCommandLine)
+                editor.showCommandLine("/");
+        }
+    },
+    "?": {
+        fn: function(editor, range, count, param) {
+            if (editor.showCommandLine)
+                editor.showCommandLine("?");
+        }
+    },
+    ".": {
+        fn: function(editor, range, count, param) {
+            util.onInsertReplaySequence = inputBuffer.lastInsertCommands;
+            var previous = inputBuffer.previous;
+            if (previous) // If there is a previous action
+                inputBuffer.exec(editor, previous.action, previous.param);
+        }
+    },
+    "ctrl-x": {
+        fn: function(editor, range, count, param) {
+            editor.modifyNumber(-(count || 1));
+        }
+    },
+    "ctrl-a": {
+        fn: function(editor, range, count, param) {
+            editor.modifyNumber(count || 1);
+        }
+    }
+};
+
+var inputBuffer = exports.inputBuffer = {
+    accepting: [NUMBER, OPERATOR, MOTION, ACTION],
+    currentCmd: null,
+    currentCount: "",
+    pendingCount: "",
+    status: "",
+    operator: null,
+    motion: null,
+
+    lastInsertCommands: [],
+
+    push: function(editor, ch, keyId) {
+        var status = this.status;
+        var isKeyHandled = true;
+        this.idle = false;
+        var wObj = this.waitingForParam;
+        if (/^numpad\d+$/i.test(ch))
+            ch = ch.substr(6);
+            
+        if (wObj) {
+            this.exec(editor, wObj, ch);
+        }
+        else if (!(ch === "0" && !this.currentCount.length) &&
+            (/^\d+$/.test(ch) && this.isAccepting(NUMBER))) {
+            this.currentCount += ch;
+            this.currentCmd = NUMBER;
+            this.accepting = [NUMBER, OPERATOR, MOTION, ACTION];
+        }
+        else if (!this.operator && this.isAccepting(OPERATOR) && operators[ch]) {
+            this.operator = {
+                ch: ch,
+                count: this.getCount()
+            };
+            this.currentCmd = OPERATOR;
+            this.accepting = [NUMBER, MOTION, ACTION];
+            this.exec(editor, { operator: this.operator });
+        }
+        else if (motions[ch] && this.isAccepting(MOTION)) {
+            this.currentCmd = MOTION;
+
+            var ctx = {
+                operator: this.operator,
+                motion: {
+                    ch: ch,
+                    count: this.getCount()
+                }
+            };
+
+            if (motions[ch].param)
+                this.waitForParam(ctx);
+            else
+                this.exec(editor, ctx);
+        }
+        else if (alias[ch] && this.isAccepting(MOTION)) {
+            alias[ch].operator.count = this.getCount();
+            this.exec(editor, alias[ch]);
+        }
+        else if (actions[ch] && this.isAccepting(ACTION)) {
+            var actionObj = {
+                action: {
+                    fn: actions[ch].fn,
+                    count: this.getCount()
+                }
+            };
+
+            if (actions[ch].param) {
+                this.waitForParam(actionObj);
+            }
+            else {
+                this.exec(editor, actionObj);
+            }
+
+            if (actions[ch].acceptsMotion)
+                this.idle = false;
+        }
+        else if (this.operator) {
+            this.operator.count = this.getCount();
+            this.exec(editor, { operator: this.operator }, ch);
+        }
+        else {
+            isKeyHandled = ch.length == 1;
+            this.reset();
+        }
+        
+        if (this.waitingForParam || this.motion || this.operator) {
+            this.status += ch;
+        } else if (this.currentCount) {
+            this.status = this.currentCount;
+        } else if (this.status) {
+            this.status = "";
+        }
+        if (this.status != status)
+            editor._emit("changeStatus");
+        return isKeyHandled;
+    },
+
+    waitForParam: function(cmd) {
+        this.waitingForParam = cmd;
+    },
+
+    getCount: function() {
+        var count = this.currentCount || this.pendingCount;
+        this.currentCount = "";
+        this.pendingCount = count;
+        return count && parseInt(count, 10);
+    },
+
+    exec: function(editor, action, param) {
+        var m = action.motion;
+        var o = action.operator;
+        var a = action.action;
+
+        if (!param)
+            param = action.param;
+
+        if (o) {
+            this.previous = {
+                action: action,
+                param: param
+            };
+        }
+
+        if (o && !editor.selection.isEmpty()) {
+            if (operators[o.ch].selFn) {
+                operators[o.ch].selFn(editor, editor.getSelectionRange(), o.count, param);
+                this.reset();
+            }
+            return;
+        }
+        else if (!m && !a && o && param) {
+            operators[o.ch].fn(editor, null, o.count, param);
+            this.reset();
+        }
+        else if (m) {
+            var run = function(fn) {
+                if (fn && typeof fn === "function") { // There should always be a motion
+                    if (m.count && !motionObj.handlesCount)
+                        repeat(fn, m.count, [editor, null, m.count, param]);
+                    else
+                        fn(editor, null, m.count, param);
+                }
+            };
+
+            var motionObj = motions[m.ch];
+            var selectable = motionObj.sel;
+
+            if (!o) {
+                if ((util.onVisualMode || util.onVisualLineMode) && selectable)
+                    run(motionObj.sel);
+                else
+                    run(motionObj.nav);
+            }
+            else if (selectable) {
+                repeat(function() {
+                    run(motionObj.sel);
+                    operators[o.ch].fn(editor, editor.getSelectionRange(), 
+                        o.count, motionObj.param ? motionObj : param);
+                }, o.count || 1);
+            }
+            this.reset();
+        }
+        else if (a) {
+            a.fn(editor, editor.getSelectionRange(), a.count, param);
+            this.reset();
+        }
+        handleCursorMove(editor);
+    },
+
+    isAccepting: function(type) {
+        return this.accepting.indexOf(type) !== -1;
+    },
+
+    reset: function() {
+        this.operator = null;
+        this.motion = null;
+        this.currentCount = "";
+        this.pendingCount = "";
+        this.status = "";
+        this.accepting = [NUMBER, OPERATOR, MOTION, ACTION];
+        this.idle = true;
+        this.waitingForParam = null;
+    }
+};
+
+function setPreviousCommand(fn) {
+    inputBuffer.previous = { action: { action: { fn: fn } } };
+}
+
+exports.coreCommands = {
+    start: {
+        exec: function start(editor) {
+            util.insertMode(editor);
+            setPreviousCommand(start);
+        }
+    },
+    startBeginning: {
+        exec: function startBeginning(editor) {
+            editor.navigateLineStart();
+            util.insertMode(editor);
+            setPreviousCommand(startBeginning);
+        }
+    },
+    stop: {
+        exec: function stop(editor) {
+            inputBuffer.reset();
+            util.onVisualMode = false;
+            util.onVisualLineMode = false;
+            inputBuffer.lastInsertCommands = util.normalMode(editor);
+        }
+    },
+    append: {
+        exec: function append(editor) {
+            var pos = editor.getCursorPosition();
+            var lineLen = editor.session.getLine(pos.row).length;
+            if (lineLen)
+                editor.navigateRight();
+            util.insertMode(editor);
+            setPreviousCommand(append);
+        }
+    },
+    appendEnd: {
+        exec: function appendEnd(editor) {
+            editor.navigateLineEnd();
+            util.insertMode(editor);
+            setPreviousCommand(appendEnd);
+        }
+    }
+};
+
+var handleCursorMove = exports.onCursorMove = function(editor, e) {
+    if (util.currentMode === 'insert' || handleCursorMove.running)
+        return;
+    else if(!editor.selection.isEmpty()) {
+        handleCursorMove.running = true;
+        if (util.onVisualLineMode) {
+            var originRow = editor.selection.visualLineStart;
+            var cursorRow = editor.getCursorPosition().row;
+            if(originRow <= cursorRow) {
+                var endLine = editor.session.getLine(cursorRow);
+                editor.selection.moveTo(originRow, 0);
+                editor.selection.selectTo(cursorRow, endLine.length);
+            } else {
+                var endLine = editor.session.getLine(originRow);
+                editor.selection.moveTo(originRow, endLine.length);
+                editor.selection.selectTo(cursorRow, 0);
+            }
+        }
+        handleCursorMove.running = false;
+        return;
+    }
+    else {
+        if (e && (util.onVisualLineMode || util.onVisualMode)) {
+            editor.selection.clearSelection();
+            util.normalMode(editor);
+        }
+
+        handleCursorMove.running = true;
+        var pos = editor.getCursorPosition();
+        var lineLen = editor.session.getLine(pos.row).length;
+
+        if (lineLen && pos.column === lineLen)
+            editor.navigateLeft();
+        handleCursorMove.running = false;
+    }
+};
+});
+
+define("ace/keyboard/vim",["require","exports","module","ace/keyboard/vim/commands","ace/keyboard/vim/maps/util","ace/lib/useragent"], function(require, exports, module) {
+"use strict";
+
+var cmds = require("./vim/commands");
+var coreCommands = cmds.coreCommands;
+var util = require("./vim/maps/util");
+var useragent = require("../lib/useragent");
+
+var startCommands = {
+    "i": {
+        command: coreCommands.start
+    },
+    "I": {
+        command: coreCommands.startBeginning
+    },
+    "a": {
+        command: coreCommands.append
+    },
+    "A": {
+        command: coreCommands.appendEnd
+    },
+    "ctrl-f": {
+        command: "gotopagedown"
+    },
+    "ctrl-b": {
+        command: "gotopageup"
+    }
+};
+
+exports.handler = {
+	$id: "ace/keyboard/vim",
+    handleMacRepeat: function(data, hashId, key) {
+        if (hashId == -1) {
+            data.inputChar = key;
+            data.lastEvent = "input";
+        } else if (data.inputChar && data.$lastHash == hashId && data.$lastKey == key) {
+            if (data.lastEvent == "input") {
+                data.lastEvent = "input1";
+            } else if (data.lastEvent == "input1") {
+                return true;
+            }
+        } else {
+            data.$lastHash = hashId;
+            data.$lastKey = key;
+            data.lastEvent = "keypress";
+        }
+    },
+    updateMacCompositionHandlers: function(editor, enable) {
+        var onCompositionUpdateOverride = function(text) {
+            if (util.currentMode !== "insert") {
+                var el = this.textInput.getElement();
+                el.blur();
+                el.focus();
+                el.value = text;
+            } else {
+                this.onCompositionUpdateOrig(text);
+            }
+        };
+        var onCompositionStartOverride = function(text) {
+            if (util.currentMode === "insert") {            
+                this.onCompositionStartOrig(text);
+            }
+        };
+        if (enable) {
+            if (!editor.onCompositionUpdateOrig) {
+                editor.onCompositionUpdateOrig = editor.onCompositionUpdate;
+                editor.onCompositionUpdate = onCompositionUpdateOverride;
+                editor.onCompositionStartOrig = editor.onCompositionStart;
+                editor.onCompositionStart = onCompositionStartOverride;
+            }
+        } else {
+            if (editor.onCompositionUpdateOrig) {
+                editor.onCompositionUpdate = editor.onCompositionUpdateOrig;
+                editor.onCompositionUpdateOrig = null;
+                editor.onCompositionStart = editor.onCompositionStartOrig;
+                editor.onCompositionStartOrig = null;
+            }
+        }
+    },
+
+    handleKeyboard: function(data, hashId, key, keyCode, e) {
+        if (hashId !== 0 && (!key || keyCode == -1))
+            return null;
+        
+        var editor = data.editor;
+        var vimState = data.vimState || "start";
+        
+        if (hashId == 1)
+            key = "ctrl-" + key;
+        if (key == "ctrl-c") {
+            if (!useragent.isMac && editor.getCopyText()) {
+                editor.once("copy", function() {
+                    if (vimState == "start")
+                        coreCommands.stop.exec(editor);
+                    else
+                        editor.selection.clearSelection();
+                });
+                return {command: "null", passEvent: true};
+            }
+            return {command: coreCommands.stop};
+        } else if ((key == "esc" && hashId === 0) || key == "ctrl-[") {
+            return {command: coreCommands.stop};
+        } else if (vimState == "start") {
+            if (useragent.isMac && this.handleMacRepeat(data, hashId, key)) {
+                hashId = -1;
+                key = data.inputChar;
+            }
+            
+            if (hashId == -1 || hashId == 1 || hashId === 0 && key.length > 1) {
+                if (cmds.inputBuffer.idle && startCommands[key])
+                    return startCommands[key];
+                var isHandled = cmds.inputBuffer.push(editor, key);
+                if (!isHandled && hashId !== -1)
+                    return;
+                return {command: "null", passEvent: !isHandled}; 
+            } else if (key == "esc" && hashId === 0) {
+                return {command: coreCommands.stop};
+            }
+            else if (hashId === 0 || hashId == 4) {
+                return {command: "null", passEvent: true};
+            } 
+        } else {
+            if (key == "ctrl-w") {
+                return {command: "removewordleft"};
+            }
+        }
+    },
+
+    attach: function(editor) {
+        editor.on("click", exports.onCursorMove);
+        if (util.currentMode !== "insert")
+            cmds.coreCommands.stop.exec(editor);
+        editor.$vimModeHandler = this;
+        
+        this.updateMacCompositionHandlers(editor, true);
+    },
+
+    detach: function(editor) {
+        editor.removeListener("click", exports.onCursorMove);
+        util.noMode(editor);
+        util.currentMode = "normal";
+        this.updateMacCompositionHandlers(editor, false);
+    },
+
+    actions: cmds.actions,
+    getStatusText: function() {
+        if (util.currentMode == "insert")
+            return "INSERT";
+        if (util.onVisualMode)
+            return (util.onVisualLineMode ? "VISUAL LINE " : "VISUAL ") + cmds.inputBuffer.status;
+        return cmds.inputBuffer.status;
+    }
+};
+
+
+exports.onCursorMove = function(e) {
+    cmds.onCursorMove(e.editor, e);
+    exports.onCursorMove.scheduled = false;
+};
+
+});

+ 0 - 599
services/web/public/js/ace/keyboard/emacs.js

@@ -1,599 +0,0 @@
-/* ***** 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 dom = require("../lib/dom");
-require("../incremental_search");
-var iSearchCommandModule = require("../commands/incremental_search_commands");
-
-
-var screenToTextBlockCoordinates = function(x, y) {
-    var canvasPos = this.scroller.getBoundingClientRect();
-
-    var col = Math.floor(
-        (x + this.scrollLeft - canvasPos.left - this.$padding) / this.characterWidth
-    );
-    var row = Math.floor(
-        (y + this.scrollTop - canvasPos.top) / this.lineHeight
-    );
-
-    return this.session.screenToDocumentPosition(row, col);
-};
-
-var HashHandler = require("./hash_handler").HashHandler;
-exports.handler = new HashHandler();
-
-exports.handler.isEmacs = true;
-exports.handler.$id = "ace/keyboard/emacs";
-
-var initialized = false;
-var $formerLongWords;
-var $formerLineStart;
-
-exports.handler.attach = function(editor) {
-    if (!initialized) {
-        initialized = true;
-        dom.importCssString('\
-            .emacs-mode .ace_cursor{\
-                border: 2px rgba(50,250,50,0.8) solid!important;\
-                -moz-box-sizing: border-box!important;\
-                -webkit-box-sizing: border-box!important;\
-                box-sizing: border-box!important;\
-                background-color: rgba(0,250,0,0.9);\
-                opacity: 0.5;\
-            }\
-            .emacs-mode .ace_hidden-cursors .ace_cursor{\
-                opacity: 1;\
-                background-color: transparent;\
-            }\
-            .emacs-mode .ace_overwrite-cursors .ace_cursor {\
-                opacity: 1;\
-                background-color: transparent;\
-                border-width: 0 0 2px 2px !important;\
-            }\
-            .emacs-mode .ace_text-layer {\
-                z-index: 4\
-            }\
-            .emacs-mode .ace_cursor-layer {\
-                z-index: 2\
-            }', 'emacsMode'
-        );
-    }
-    // in emacs, gotowordleft/right should not count a space as a word..
-    $formerLongWords = editor.session.$selectLongWords;
-    editor.session.$selectLongWords = true;
-    // CTRL-A should go to actual beginning of line
-    $formerLineStart = editor.session.$useEmacsStyleLineStart;
-    editor.session.$useEmacsStyleLineStart = true;
-
-    editor.session.$emacsMark = null; // the active mark
-    editor.session.$emacsMarkRing = editor.session.$emacsMarkRing || [];
-
-    editor.emacsMark = function() {
-        return this.session.$emacsMark;
-    }
-
-    editor.setEmacsMark = function(p) {
-        // to deactivate pass in a falsy value
-        this.session.$emacsMark = p;
-    }
-
-    editor.pushEmacsMark = function(p, activate) {
-        var prevMark = this.session.$emacsMark;
-        if (prevMark)
-            this.session.$emacsMarkRing.push(prevMark);
-        if (!p || activate) this.setEmacsMark(p)
-        else this.session.$emacsMarkRing.push(p);
-    }
-
-    editor.popEmacsMark = function() {
-        var mark = this.emacsMark();
-        if (mark) { this.setEmacsMark(null); return mark; }
-        return this.session.$emacsMarkRing.pop();
-    }
-
-    editor.getLastEmacsMark = function(p) {
-        return this.session.$emacsMark || this.session.$emacsMarkRing.slice(-1)[0];
-    }
-
-    editor.on("click", $resetMarkMode);
-    editor.on("changeSession", $kbSessionChange);
-    editor.renderer.screenToTextCoordinates = screenToTextBlockCoordinates;
-    editor.setStyle("emacs-mode");
-    editor.commands.addCommands(commands);
-    exports.handler.platform = editor.commands.platform;
-    editor.$emacsModeHandler = this;
-    editor.addEventListener('copy', this.onCopy);
-    editor.addEventListener('paste', this.onPaste);
-};
-
-exports.handler.detach = function(editor) {
-    delete editor.renderer.screenToTextCoordinates;
-    editor.session.$selectLongWords = $formerLongWords;
-    editor.session.$useEmacsStyleLineStart = $formerLineStart;
-    editor.removeEventListener("click", $resetMarkMode);
-    editor.removeEventListener("changeSession", $kbSessionChange);
-    editor.unsetStyle("emacs-mode");
-    editor.commands.removeCommands(commands);
-    editor.removeEventListener('copy', this.onCopy);
-    editor.removeEventListener('paste', this.onPaste);
-};
-
-var $kbSessionChange = function(e) {
-    if (e.oldSession) {
-        e.oldSession.$selectLongWords = $formerLongWords;
-        e.oldSession.$useEmacsStyleLineStart = $formerLineStart;
-    }
-
-    $formerLongWords = e.session.$selectLongWords;
-    e.session.$selectLongWords = true;
-    $formerLineStart = e.session.$useEmacsStyleLineStart;
-    e.session.$useEmacsStyleLineStart = true;
-
-    if (!e.session.hasOwnProperty('$emacsMark'))
-        e.session.$emacsMark = null;
-    if (!e.session.hasOwnProperty('$emacsMarkRing'))
-        e.session.$emacsMarkRing = [];
-}
-
-var $resetMarkMode = function(e) {
-    e.editor.session.$emacsMark = null;
-}
-
-var keys = require("../lib/keys").KEY_MODS,
-    eMods = {C: "ctrl", S: "shift", M: "alt", CMD: "command"},
-    combinations = ["C-S-M-CMD",
-                    "S-M-CMD", "C-M-CMD", "C-S-CMD", "C-S-M",
-                    "M-CMD", "S-CMD", "S-M", "C-CMD", "C-M", "C-S",
-                    "CMD", "M", "S", "C"];
-combinations.forEach(function(c) {
-    var hashId = 0;
-    c.split("-").forEach(function(c) {
-        hashId = hashId | keys[eMods[c]];
-    });
-    eMods[hashId] = c.toLowerCase() + "-";
-});
-
-exports.handler.onCopy = function(e, editor) {
-    if (editor.$handlesEmacsOnCopy) return;
-    editor.$handlesEmacsOnCopy = true;
-    exports.handler.commands.killRingSave.exec(editor);
-    delete editor.$handlesEmacsOnCopy;
-}
-
-exports.handler.onPaste = function(e, editor) {
-    editor.pushEmacsMark(editor.getCursorPosition());
-}
-
-exports.handler.bindKey = function(key, command) {
-    if (!key)
-        return;
-
-    var ckb = this.commandKeyBinding;
-    key.split("|").forEach(function(keyPart) {
-        keyPart = keyPart.toLowerCase();
-        ckb[keyPart] = command;
-        // register all partial key combos as null commands
-        // to be able to activate key combos with arbitrary length
-        // Example: if keyPart is "C-c C-l t" then "C-c C-l t" will
-        // get command assigned and "C-c" and "C-c C-l" will get
-        // a null command assigned in this.commandKeyBinding. For
-        // the lookup logic see handleKeyboard()
-        var keyParts = keyPart.split(" ").slice(0,-1);
-        keyParts.reduce(function(keyMapKeys, keyPart, i) {
-            var prefix = keyMapKeys[i-1] ? keyMapKeys[i-1] + ' ' : '';
-            return keyMapKeys.concat([prefix + keyPart]);
-        }, []).forEach(function(keyPart) {
-            if (!ckb[keyPart]) ckb[keyPart] = "null";
-        });
-    }, this);
-}
-
-exports.handler.handleKeyboard = function(data, hashId, key, keyCode) {
-    var editor = data.editor;
-    // insertstring data.count times
-    if (hashId == -1) {
-        editor.pushEmacsMark();
-        if (data.count) {
-            var str = Array(data.count + 1).join(key);
-            data.count = null;
-            return {command: "insertstring", args: str};
-        }
-    }
-
-    if (key == "\x00") return undefined;
-
-    var modifier = eMods[hashId];
-
-    // CTRL + number / universalArgument for setting data.count
-    if (modifier == "c-" || data.universalArgument) {
-        var prevCount = String(data.count || 0);
-        var count = parseInt(key[key.length - 1]);
-        if (typeof count === 'number' && !isNaN(count)) {
-            data.count = parseInt(prevCount + count);
-            return {command: "null"};
-        } else if (data.universalArgument) {
-            // if no number pressed use emacs defaults for universalArgument
-            // which is 4
-            data.count = 4;
-        }
-    }
-    data.universalArgument = false;
-
-    // this.commandKeyBinding maps key specs like "c-p" (for CTRL + P) to
-    // command objects, for lookup key needs to include the modifier
-    if (modifier) key = modifier + key;
-
-    // Key combos like CTRL+X H build up the data.keyChain
-    if (data.keyChain) key = data.keyChain += " " + key;
-
-    // Key combo prefixes get stored as "null" (String!) in this
-    // this.commandKeyBinding. When encountered no command is invoked but we
-    // buld up data.keyChain
-    var command = this.commandKeyBinding[key];
-    data.keyChain = command == "null" ? key : "";
-
-    // there really is no command
-    if (!command) return undefined;
-
-    // we pass b/c of key combo or universalArgument
-    if (command === "null") return {command: "null"};
-
-    if (command === "universalArgument") {
-        data.universalArgument = true;
-        return {command: "null"};
-    }
-
-    // lookup command
-    // TODO extract special handling of markmode
-    // TODO special case command.command is really unnecessary, remove
-    var args;
-    if (typeof command !== "string") {
-        args = command.args;
-        if (command.command) command = command.command;
-        if (command === "goorselect") {
-            command = editor.emacsMark() ? args[1] : args[0];
-            args = null;
-        }
-    }
-
-    if (typeof command === "string") {
-        if (command === "insertstring" ||
-            command === "splitline" ||
-            command === "togglecomment") {
-            editor.pushEmacsMark();
-        }
-        command = this.commands[command] || editor.commands.commands[command];
-        if (!command) return undefined;
-    }
-
-    if (!command.readonly && !command.isYank)
-        data.lastCommand = null;
-
-    if (data.count) {
-        var count = data.count;
-        data.count = 0;
-        if (!command || !command.handlesCount) {
-            return {
-                args: args,
-                command: {
-                    exec: function(editor, args) {
-                        for (var i = 0; i < count; i++)
-                            command.exec(editor, args);
-                    }
-                }
-            };
-        } else {
-            if (!args) args = {}
-            if (typeof args === 'object') args.count = count;
-        }
-    }
-
-    return {command: command, args: args};
-};
-
-exports.emacsKeys = {
-    // movement
-    "Up|C-p"      : {command: "goorselect", args: ["golineup","selectup"]},
-    "Down|C-n"    : {command: "goorselect", args: ["golinedown","selectdown"]},
-    "Left|C-b"    : {command: "goorselect", args: ["gotoleft","selectleft"]},
-    "Right|C-f"   : {command: "goorselect", args: ["gotoright","selectright"]},
-    "C-Left|M-b"  : {command: "goorselect", args: ["gotowordleft","selectwordleft"]},
-    "C-Right|M-f" : {command: "goorselect", args: ["gotowordright","selectwordright"]},
-    "Home|C-a"    : {command: "goorselect", args: ["gotolinestart","selecttolinestart"]},
-    "End|C-e"     : {command: "goorselect", args: ["gotolineend","selecttolineend"]},
-    "C-Home|S-M-,": {command: "goorselect", args: ["gotostart","selecttostart"]},
-    "C-End|S-M-." : {command: "goorselect", args: ["gotoend","selecttoend"]},
-
-    // selection
-    "S-Up|S-C-p"      : "selectup",
-    "S-Down|S-C-n"    : "selectdown",
-    "S-Left|S-C-b"    : "selectleft",
-    "S-Right|S-C-f"   : "selectright",
-    "S-C-Left|S-M-b"  : "selectwordleft",
-    "S-C-Right|S-M-f" : "selectwordright",
-    "S-Home|S-C-a"    : "selecttolinestart",
-    "S-End|S-C-e"     : "selecttolineend",
-    "S-C-Home"        : "selecttostart",
-    "S-C-End"         : "selecttoend",
-
-    "C-l" : "recenterTopBottom",
-    "M-s" : "centerselection",
-    "M-g": "gotoline",
-    "C-x C-p": "selectall",
-
-    // todo fix these
-    "C-Down": {command: "goorselect", args: ["gotopagedown","selectpagedown"]},
-    "C-Up": {command: "goorselect", args: ["gotopageup","selectpageup"]},
-    "PageDown|C-v": {command: "goorselect", args: ["gotopagedown","selectpagedown"]},
-    "PageUp|M-v": {command: "goorselect", args: ["gotopageup","selectpageup"]},
-    "S-C-Down": "selectpagedown",
-    "S-C-Up": "selectpageup",
-
-    "C-s": "iSearch",
-    "C-r": "iSearchBackwards",
-
-    "M-C-s": "findnext",
-    "M-C-r": "findprevious",
-    "S-M-5": "replace",
-
-    // basic editing
-    "Backspace": "backspace",
-    "Delete|C-d": "del",
-    "Return|C-m": {command: "insertstring", args: "\n"}, // "newline"
-    "C-o": "splitline",
-
-    "M-d|C-Delete": {command: "killWord", args: "right"},
-    "C-Backspace|M-Backspace|M-Delete": {command: "killWord", args: "left"},
-    "C-k": "killLine",
-
-    "C-y|S-Delete": "yank",
-    "M-y": "yankRotate",
-    "C-g": "keyboardQuit",
-
-    "C-w": "killRegion",
-    "M-w": "killRingSave",
-    "C-Space": "setMark",
-    "C-x C-x": "exchangePointAndMark",
-
-    "C-t": "transposeletters",
-    "M-u": "touppercase",    // Doesn't work
-    "M-l": "tolowercase",
-    "M-/": "autocomplete",   // Doesn't work
-    "C-u": "universalArgument",
-
-    "M-;": "togglecomment",
-
-    "C-/|C-x u|S-C--|C-z": "undo",
-    "S-C-/|S-C-x u|C--|S-C-z": "redo", //infinite undo?
-    // vertical editing
-    "C-x r":  "selectRectangularRegion",
-    "M-x": {command: "focusCommandLine", args: "M-x "}
-    // todo
-    // "C-x C-t" "M-t" "M-c" "F11" "C-M- "M-q"
-};
-
-
-exports.handler.bindKeys(exports.emacsKeys);
-
-exports.handler.addCommands({
-    recenterTopBottom: function(editor) {
-        var renderer = editor.renderer;
-        var pos = renderer.$cursorLayer.getPixelPosition();
-        var h = renderer.$size.scrollerHeight - renderer.lineHeight;
-        var scrollTop = renderer.scrollTop;
-        if (Math.abs(pos.top - scrollTop) < 2) {
-            scrollTop = pos.top - h;
-        } else if (Math.abs(pos.top - scrollTop - h * 0.5) < 2) {
-            scrollTop = pos.top;
-        } else {
-            scrollTop = pos.top - h * 0.5;
-        }
-        editor.session.setScrollTop(scrollTop);
-    },
-    selectRectangularRegion:  function(editor) {
-        editor.multiSelect.toggleBlockSelection();
-    },
-    setMark:  {
-        exec: function(editor, args) {
-            // Sets mark-mode and clears current selection.
-            // When mark is set, keyboard cursor movement commands become
-            // selection modification commands. That is,
-            // "goto" commands become "select" commands.
-            // Any insertion or mouse click resets mark-mode.
-            // setMark twice in a row at the same place resets markmode
-            if (args && args.count) {
-                var mark = editor.popEmacsMark();
-                mark && editor.selection.moveCursorToPosition(mark);
-                return;
-            }
-
-            var mark = editor.emacsMark(),
-                transientMarkModeActive = true;
-
-            // if transientMarkModeActive then mark behavior is a little
-            // different. Deactivate the mark when setMark is run with active
-            // mark
-            if (transientMarkModeActive && (mark || !editor.selection.isEmpty())) {
-                editor.pushEmacsMark();
-                editor.clearSelection();
-                return;
-            }
-
-            if (mark) {
-                var cp = editor.getCursorPosition();
-                if (editor.selection.isEmpty() &&
-                    mark.row == cp.row && mark.column == cp.column) {
-                    editor.pushEmacsMark();
-                    return;
-                }
-            }
-            // turn on mark mode
-            mark = editor.getCursorPosition();
-            editor.setEmacsMark(mark);
-            editor.selection.setSelectionAnchor(mark.row, mark.column);
-        },
-        readonly: true,
-        handlesCount: true,
-        multiSelectAction: "forEach"
-    },
-    exchangePointAndMark: {
-        exec: function(editor, args) {
-            var sel = editor.selection;
-            if (args.count) {
-                var pos = editor.getCursorPosition();
-                sel.clearSelection();
-                sel.moveCursorToPosition(editor.popEmacsMark());
-                editor.pushEmacsMark(pos);
-                return;
-            }
-            var lastMark = editor.getLastEmacsMark();
-            var range = sel.getRange();
-            if (range.isEmpty()) {
-                sel.selectToPosition(lastMark);
-                return;
-            }
-            sel.setSelectionRange(range, !sel.isBackwards());
-        },
-        readonly: true,
-        handlesCount: true,
-        multiSelectAction: "forEach"
-    },
-    killWord: {
-        exec: function(editor, dir) {
-            editor.clearSelection();
-            if (dir == "left")
-                editor.selection.selectWordLeft();
-            else
-                editor.selection.selectWordRight();
-
-            var range = editor.getSelectionRange();
-            var text = editor.session.getTextRange(range);
-            exports.killRing.add(text);
-
-            editor.session.remove(range);
-            editor.clearSelection();
-        },
-        multiSelectAction: "forEach"
-    },
-    killLine: function(editor) {
-        editor.pushEmacsMark(null);
-        var pos = editor.getCursorPosition();
-        if (pos.column == 0 &&
-            editor.session.doc.getLine(pos.row).length == 0) {
-            // If an already empty line is killed, remove
-            // the line entirely
-            editor.selection.selectLine();
-        } else {
-            // otherwise just remove from the current cursor position
-            // to the end (but don't delete the selection if it's before
-            // the cursor)
-            editor.clearSelection();
-            editor.selection.selectLineEnd();
-        }
-        var range = editor.getSelectionRange();
-        var text = editor.session.getTextRange(range);
-        exports.killRing.add(text);
-
-        editor.session.remove(range);
-        editor.clearSelection();
-    },
-    yank: function(editor) {
-        editor.onPaste(exports.killRing.get() || '');
-        editor.keyBinding.$data.lastCommand = "yank";
-    },
-    yankRotate: function(editor) {
-        if (editor.keyBinding.$data.lastCommand != "yank")
-            return;
-        editor.undo();
-        editor.onPaste(exports.killRing.rotate());
-        editor.keyBinding.$data.lastCommand = "yank";
-    },
-    killRegion: {
-        exec: function(editor) {
-            exports.killRing.add(editor.getCopyText());
-            editor.commands.byName.cut.exec(editor);
-        },
-        readonly: true,
-        multiSelectAction: "forEach"
-    },
-    killRingSave: {
-        exec: function(editor) {
-            exports.killRing.add(editor.getCopyText());
-            setTimeout(function() {
-                var sel = editor.selection,
-                    range = sel.getRange();
-                editor.pushEmacsMark(sel.isBackwards() ? range.end : range.start);
-                sel.clearSelection();
-            }, 0);
-        },
-        readonly: true
-    },
-    keyboardQuit: function(editor) {
-        editor.selection.clearSelection();
-        editor.setEmacsMark(null);
-    },
-    focusCommandLine: function(editor, arg) {
-        if (editor.showCommandLine)
-            editor.showCommandLine(arg);
-    }
-});
-
-exports.handler.addCommands(iSearchCommandModule.iSearchStartCommands);
-
-var commands = exports.handler.commands;
-commands.yank.isYank = true;
-commands.yankRotate.isYank = true;
-
-exports.killRing = {
-    $data: [],
-    add: function(str) {
-        str && this.$data.push(str);
-        if (this.$data.length > 30)
-            this.$data.shift();
-    },
-    get: function(n) {
-        n = n || 1;
-        return this.$data.slice(this.$data.length-n, this.$data.length).reverse().join('\n');
-    },
-    pop: function() {
-        if (this.$data.length > 1)
-            this.$data.pop();
-        return this.get();
-    },
-    rotate: function() {
-        this.$data.unshift(this.$data.pop());
-        return this.get();
-    }
-};
-
-});

+ 0 - 73
services/web/public/js/ace/keyboard/emacs_test.js

@@ -1,73 +0,0 @@
-/* ***** 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 EditSession = require("./../edit_session").EditSession,
-    Editor = require("./../editor").Editor,
-    MockRenderer = require("./../test/mockrenderer").MockRenderer,
-    emacs = require('./emacs'),
-    assert = require("./../test/assertions"),
-    editor;
-
-function initEditor(docString) {
-    var doc = new EditSession(docString.split("\n"));
-    editor = new Editor(new MockRenderer(), doc);
-    editor.setKeyboardHandler(emacs.handler);
-}
-
-module.exports = {
-
-    "test: detach removes emacs commands from command manager": function() {
-        initEditor('');
-        assert.ok(!!editor.commands.byName["keyboardQuit"], 'setup error: emacs commands not installed');
-        editor.keyBinding.removeKeyboardHandler(editor.getKeyboardHandler());
-        assert.ok(!editor.commands.byName["keyboardQuit"], 'emacs commands not removed');
-    },
-
-    "test: keyboardQuit clears selection": function() {
-        initEditor('foo');
-        editor.selectAll();
-        editor.execCommand('keyboardQuit');
-        assert.ok(editor.selection.isEmpty(), 'selection non-empty');
-    }
-
-};
-
-});
-
-if (typeof module !== "undefined" && module === require.main) {
-    require("asyncjs").test.testcase(module.exports).exec()
-}

+ 0 - 198
services/web/public/js/ace/keyboard/hash_handler.js

@@ -1,198 +0,0 @@
-/* ***** 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 keyUtil = require("../lib/keys");
-var useragent = require("../lib/useragent");
-
-function HashHandler(config, platform) {
-    this.platform = platform || (useragent.isMac ? "mac" : "win");
-    this.commands = {};
-    this.commandKeyBinding = {};
-    
-    // todo remove this after a while
-    if (this.__defineGetter__ && this.__defineSetter__ && typeof console != "undefined" && console.error) {
-        var warned = false;
-        var warn = function() {
-            if (!warned) {
-                warned = true;
-                console.error("commmandKeyBinding has too many m's. use commandKeyBinding");
-            }
-        };
-        this.__defineGetter__("commmandKeyBinding", function() {
-            warn();
-            return this.commandKeyBinding;
-        });
-        this.__defineSetter__("commmandKeyBinding", function(val) {
-            warn();
-            return this.commandKeyBinding = val;
-        });
-    } else {
-        this.commmandKeyBinding = this.commandKeyBinding;
-    }
-
-    this.addCommands(config);
-};
-
-(function() {
-
-    this.addCommand = function(command) {
-        if (this.commands[command.name])
-            this.removeCommand(command);
-
-        this.commands[command.name] = command;
-
-        if (command.bindKey)
-            this._buildKeyHash(command);
-    };
-
-    this.removeCommand = function(command) {
-        var name = (typeof command === 'string' ? command : command.name);
-        command = this.commands[name];
-        delete this.commands[name];
-
-        // exhaustive search is brute force but since removeCommand is
-        // not a performance critical operation this should be OK
-        var ckb = this.commandKeyBinding;
-        for (var hashId in ckb) {
-            for (var key in ckb[hashId]) {
-                if (ckb[hashId][key] == command)
-                    delete ckb[hashId][key];
-            }
-        }
-    };
-
-    this.bindKey = function(key, command) {
-        if(!key)
-            return;
-        if (typeof command == "function") {
-            this.addCommand({exec: command, bindKey: key, name: command.name || key});
-            return;
-        }
-
-        var ckb = this.commandKeyBinding;
-        key.split("|").forEach(function(keyPart) {
-            var binding = this.parseKeys(keyPart, command);
-            var hashId = binding.hashId;
-            (ckb[hashId] || (ckb[hashId] = {}))[binding.key] = command;
-        }, this);
-    };
-
-    this.addCommands = function(commands) {
-        commands && Object.keys(commands).forEach(function(name) {
-            var command = commands[name];
-            if (!command)
-                return;
-            
-            if (typeof command === "string")
-                return this.bindKey(command, name);
-
-            if (typeof command === "function")
-                command = { exec: command };
-
-            if (typeof command !== "object")
-                return;
-
-            if (!command.name)
-                command.name = name;
-
-            this.addCommand(command);
-        }, this);
-    };
-
-    this.removeCommands = function(commands) {
-        Object.keys(commands).forEach(function(name) {
-            this.removeCommand(commands[name]);
-        }, this);
-    };
-
-    this.bindKeys = function(keyList) {
-        Object.keys(keyList).forEach(function(key) {
-            this.bindKey(key, keyList[key]);
-        }, this);
-    };
-
-    this._buildKeyHash = function(command) {
-        var binding = command.bindKey;
-        if (!binding)
-            return;
-
-        var key = typeof binding == "string" ? binding: binding[this.platform];
-        this.bindKey(key, command);
-    };
-
-    // accepts keys in the form ctrl+Enter or ctrl-Enter
-    // keys without modifiers or shift only 
-    this.parseKeys = function(keys) {
-        // todo support keychains 
-        if (keys.indexOf(" ") != -1)
-            keys = keys.split(/\s+/).pop();
-
-        var parts = keys.toLowerCase().split(/[\-\+]([\-\+])?/).filter(function(x){return x});
-        var key = parts.pop();
-
-        var keyCode = keyUtil[key];
-        if (keyUtil.FUNCTION_KEYS[keyCode])
-            key = keyUtil.FUNCTION_KEYS[keyCode].toLowerCase();
-        else if (!parts.length)
-            return {key: key, hashId: -1};
-        else if (parts.length == 1 && parts[0] == "shift")
-            return {key: key.toUpperCase(), hashId: -1};
-
-        var hashId = 0;
-        for (var i = parts.length; i--;) {
-            var modifier = keyUtil.KEY_MODS[parts[i]];
-            if (modifier == null) {
-                if (typeof console != "undefined")
-                console.error("invalid modifier " + parts[i] + " in " + keys);
-                return false;
-            }
-            hashId |= modifier;
-        }
-        return {key: key, hashId: hashId};
-    };
-
-    this.findKeyCommand = function findKeyCommand(hashId, keyString) {
-        var ckbr = this.commandKeyBinding;
-        return ckbr[hashId] && ckbr[hashId][keyString];
-    };
-
-    this.handleKeyboard = function(data, hashId, keyString, keyCode) {
-        return {
-            command: this.findKeyCommand(hashId, keyString)
-        };
-    };
-
-}).call(HashHandler.prototype)
-
-exports.HashHandler = HashHandler;
-});

+ 0 - 136
services/web/public/js/ace/keyboard/keybinding.js

@@ -1,136 +0,0 @@
-/* ***** 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 keyUtil  = require("../lib/keys");
-var event = require("../lib/event");
-
-var KeyBinding = function(editor) {
-    this.$editor = editor;
-    this.$data = { };
-    this.$handlers = [];
-    this.setDefaultHandler(editor.commands);
-};
-
-(function() {
-    this.setDefaultHandler = function(kb) {
-        this.removeKeyboardHandler(this.$defaultHandler);
-        this.$defaultHandler = kb;
-        this.addKeyboardHandler(kb, 0);
-        this.$data = {editor: this.$editor};
-    };
-
-    this.setKeyboardHandler = function(kb) {
-        var h = this.$handlers;
-        if (h[h.length - 1] == kb)
-            return;
-
-        while (h[h.length - 1] && h[h.length - 1] != this.$defaultHandler)
-            this.removeKeyboardHandler(h[h.length - 1]);
-
-        this.addKeyboardHandler(kb, 1);
-    };
-
-    this.addKeyboardHandler = function(kb, pos) {
-        if (!kb)
-            return;
-        var i = this.$handlers.indexOf(kb);
-        if (i != -1)
-            this.$handlers.splice(i, 1);
-
-        if (pos == undefined)
-            this.$handlers.push(kb);
-        else
-            this.$handlers.splice(pos, 0, kb);
-
-        if (i == -1 && kb.attach)
-            kb.attach(this.$editor);
-    };
-
-    this.removeKeyboardHandler = function(kb) {
-        var i = this.$handlers.indexOf(kb);
-        if (i == -1)
-            return false;
-        this.$handlers.splice(i, 1);
-        kb.detach && kb.detach(this.$editor);
-        return true;
-    };
-
-    this.getKeyboardHandler = function() {
-        return this.$handlers[this.$handlers.length - 1];
-    };
-
-    this.$callKeyboardHandlers = function (hashId, keyString, keyCode, e) {
-        var toExecute;
-        var success = false;
-        var commands = this.$editor.commands;
-
-        for (var i = this.$handlers.length; i--;) {
-            toExecute = this.$handlers[i].handleKeyboard(
-                this.$data, hashId, keyString, keyCode, e
-            );
-            if (!toExecute || !toExecute.command)
-                continue;
-            
-            // allow keyboardHandler to consume keys
-            if (toExecute.command == "null") {
-                success = true;
-            } else {
-                success = commands.exec(toExecute.command, this.$editor, toExecute.args, e);                
-            }
-            // do not stop input events to not break repeating
-            if (success && e && hashId != -1 && 
-                toExecute.passEvent != true && toExecute.command.passEvent != true
-            ) {
-                event.stopEvent(e);
-            }
-            if (success)
-                break;
-        }
-        return success;
-    };
-
-    this.onCommandKey = function(e, hashId, keyCode) {
-        var keyString = keyUtil.keyCodeToString(keyCode);
-        this.$callKeyboardHandlers(hashId, keyString, keyCode, e);
-    };
-
-    this.onTextInput = function(text) {
-        var success = this.$callKeyboardHandlers(-1, text);
-        if (!success)
-            this.$editor.commands.exec("insertstring", this.$editor, text);
-    };
-
-}).call(KeyBinding.prototype);
-
-exports.KeyBinding = KeyBinding;
-});

+ 0 - 69
services/web/public/js/ace/keyboard/keybinding_test.js

@@ -1,69 +0,0 @@
-/* ***** 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 EditSession = require("./../edit_session").EditSession,
-    Editor = require("./../editor").Editor,
-    MockRenderer = require("./../test/mockrenderer").MockRenderer,
-    assert = require("./../test/assertions"),
-    HashHandler = require('./hash_handler').HashHandler,
-    keys = require('../lib/keys'),
-    editor;
-
-function initEditor(docString) {
-    var doc = new EditSession(docString.split("\n"));
-    editor = new Editor(new MockRenderer(), doc);
-}
-
-module.exports = {
-
-    "test: adding a new keyboard handler does not remove the default handler": function() {
-        initEditor('abc');
-        var handler = new HashHandler({'del': 'f1'});
-        editor.keyBinding.setKeyboardHandler(handler);
-        editor.onCommandKey({}, 0, keys['f1']);
-        assert.equal('bc', editor.getValue(), "binding of new handler");
-        editor.onCommandKey({}, 0, keys['delete']);
-        assert.equal('c', editor.getValue(), "bindings of the old handler should still work");
-    }
-
-};
-
-});
-
-if (typeof module !== "undefined" && module === require.main) {
-    require("asyncjs").test.testcase(module.exports).exec()
-}

+ 0 - 249
services/web/public/js/ace/keyboard/state_handler.js

@@ -1,249 +0,0 @@
-/* ***** 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";
-
-// If you're developing a new keymapping and want to get an idea what's going
-// on, then enable debugging.
-var DEBUG = false;
-
-function StateHandler(keymapping) {
-    this.keymapping = this.$buildKeymappingRegex(keymapping);
-}
-
-StateHandler.prototype = {
-    /*
-     * Build the RegExp from the keymapping as RegExp can't stored directly
-     * in the metadata JSON and as the RegExp used to match the keys/buffer
-     * need to be adapted.
-     */
-    $buildKeymappingRegex: function(keymapping) {
-        for (var state in keymapping) {
-            this.$buildBindingsRegex(keymapping[state]);
-        }
-        return keymapping;
-    },
-
-    $buildBindingsRegex: function(bindings) {
-        // Escape a given Regex string.
-        bindings.forEach(function(binding) {
-            if (binding.key) {
-                binding.key = new RegExp('^' + binding.key + '$');
-            } else if (Array.isArray(binding.regex)) {
-                if (!('key' in binding))
-                  binding.key = new RegExp('^' + binding.regex[1] + '$');
-                binding.regex = new RegExp(binding.regex.join('') + '$');
-            } else if (binding.regex) {
-                binding.regex = new RegExp(binding.regex + '$');
-            }
-        });
-    },
-
-    $composeBuffer: function(data, hashId, key, e) {
-        // Initialize the data object.
-        if (data.state == null || data.buffer == null) {
-            data.state = "start";
-            data.buffer = "";
-        }
-
-        var keyArray = [];
-        if (hashId & 1) keyArray.push("ctrl");
-        if (hashId & 8) keyArray.push("command");
-        if (hashId & 2) keyArray.push("option");
-        if (hashId & 4) keyArray.push("shift");
-        if (key)        keyArray.push(key);
-
-        var symbolicName = keyArray.join("-");
-        var bufferToUse = data.buffer + symbolicName;
-
-        // Don't add the symbolic name to the key buffer if the alt_ key is
-        // part of the symbolic name. If it starts with alt_, this means
-        // that the user hit an alt keycombo and there will be a single,
-        // new character detected after this event, which then will be
-        // added to the buffer (e.g. alt_j will result in ∆).
-        //
-        // We test for 2 and not for & 2 as we only want to exclude the case where
-        // the option key is pressed alone.
-        if (hashId != 2) {
-            data.buffer = bufferToUse;
-        }
-
-        var bufferObj = {
-            bufferToUse: bufferToUse,
-            symbolicName: symbolicName
-        };
-
-        if (e) {
-            bufferObj.keyIdentifier = e.keyIdentifier;
-        }
-
-        return bufferObj;
-    },
-
-    $find: function(data, buffer, symbolicName, hashId, key, keyIdentifier) {
-        // Holds the command to execute and the args if a command matched.
-        var result = {};
-
-        // Loop over all the bindings of the keymap until a match is found.
-        this.keymapping[data.state].some(function(binding) {
-            var match;
-
-            // Check if the key matches.
-            if (binding.key && !binding.key.test(symbolicName)) {
-                return false;
-            }
-
-            // Check if the regex matches.
-            if (binding.regex && !(match = binding.regex.exec(buffer))) {
-                return false;
-            }
-
-            // Check if the match function matches.
-            if (binding.match && !binding.match(buffer, hashId, key, symbolicName, keyIdentifier)) {
-                return false;
-            }
-
-            // Check for disallowed matches.
-            if (binding.disallowMatches) {
-                for (var i = 0; i < binding.disallowMatches.length; i++) {
-                    if (!!match[binding.disallowMatches[i]]) {
-                        return false;
-                    }
-                }
-            }
-
-            // If there is a command to execute, then figure out the
-            // command and the arguments.
-            if (binding.exec) {
-                result.command = binding.exec;
-
-                // Build the arguments.
-                if (binding.params) {
-                    var value;
-                    result.args = {};
-                    binding.params.forEach(function(param) {
-                        if (param.match != null && match != null) {
-                            value = match[param.match] || param.defaultValue;
-                        } else {
-                            value = param.defaultValue;
-                        }
-
-                        if (param.type === 'number') {
-                            value = parseInt(value);
-                        }
-
-                        result.args[param.name] = value;
-                    });
-                }
-                data.buffer = "";
-            }
-
-            // Handle the 'then' property.
-            if (binding.then) {
-                data.state = binding.then;
-                data.buffer = "";
-            }
-
-            // If no command is set, then execute the "null" fake command.
-            if (result.command == null) {
-                result.command = "null";
-            }
-
-            if (DEBUG) {
-                console.log("KeyboardStateMapper#find", binding);
-            }
-            return true;
-        });
-
-        if (result.command) {
-            return result;
-        } else {
-            data.buffer = "";
-            return false;
-        }
-    },
-
-    /*
-     * This function is called by keyBinding.
-     */
-    handleKeyboard: function(data, hashId, key, keyCode, e) {
-        if (hashId == -1)
-            hashId = 0
-        // If we pressed any command key but no other key, then ignore the input.
-        // Otherwise "shift-" is added to the buffer, and later on "shift-g"
-        // which results in "shift-shift-g" which doesn't make sense.
-        if (hashId != 0 && (key == "" || key == String.fromCharCode(0))) {
-            return null;
-        }
-
-        // Compute the current value of the keyboard input buffer.
-        var r = this.$composeBuffer(data, hashId, key, e);
-        var buffer = r.bufferToUse;
-        var symbolicName = r.symbolicName;
-        var keyId = r.keyIdentifier;
-
-        r = this.$find(data, buffer, symbolicName, hashId, key, keyId);
-        if (DEBUG) {
-            console.log("KeyboardStateMapper#match", buffer, symbolicName, r);
-        }
-
-        return r;
-    }
-}
-
-/*
- * This is a useful matching function and therefore is defined here so that
- * users of KeyboardStateMapper can use it.
- *
- * @return {Boolean} If no command key (Command|Option|Shift|Ctrl) is pressed, it
- *          returns true. If the only the Shift key is pressed + a character
- *          true is returned as well. Otherwise, false is returned.
- *          Summing up, the function returns true whenever the user typed
- *          a normal character on the keyboard and no shortcut.
- */
-exports.matchCharacterOnly = function(buffer, hashId, key, symbolicName) {
-    // If no command keys are pressed, then catch the input.
-    if (hashId == 0) {
-        return true;
-    }
-    // If only the shift key is pressed and a character key, then
-    // catch that input as well.
-    else if ((hashId == 4) && key.length == 1) {
-        return true;
-    }
-    // Otherwise, we let the input got through.
-    else {
-        return false;
-    }
-};
-
-exports.StateHandler = StateHandler;
-});

+ 0 - 505
services/web/public/js/ace/keyboard/textinput.js

@@ -1,505 +0,0 @@
-/* ***** 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 event = require("../lib/event");
-var useragent = require("../lib/useragent");
-var dom = require("../lib/dom");
-var lang = require("../lib/lang");
-var BROKEN_SETDATA = useragent.isChrome < 18;
-
-var TextInput = function(parentNode, host) {
-    var text = dom.createElement("textarea");
-    text.className = "ace_text-input";
-
-    if (useragent.isTouchPad)
-        text.setAttribute("x-palm-disable-auto-cap", true);
-
-    text.wrap = "off";
-    text.autocorrect = "off";
-    text.autocapitalize = "off";
-    text.spellcheck = false;
-
-    text.style.opacity = "0";
-    parentNode.insertBefore(text, parentNode.firstChild);
-
-    var PLACEHOLDER = "\x01\x01";
-
-    var cut = false;
-    var copied = false;
-    var pasted = false;
-    var inComposition = false;
-    var tempStyle = '';
-    var isSelectionEmpty = true;
-
-    // FOCUS
-    // ie9 throws error if document.activeElement is accessed too soon
-    try { var isFocused = document.activeElement === text; } catch(e) {}
-    
-    event.addListener(text, "blur", function() {
-        host.onBlur();
-        isFocused = false;
-    });
-    event.addListener(text, "focus", function() {
-        isFocused = true;
-        host.onFocus();
-        resetSelection();
-    });
-    this.focus = function() { text.focus(); };
-    this.blur = function() { text.blur(); };
-    this.isFocused = function() {
-        return isFocused;
-    };
-
-    // modifying selection of blured textarea can focus it (chrome mac/linux)
-    var syncSelection = lang.delayedCall(function() {
-        isFocused && resetSelection(isSelectionEmpty);
-    });
-    var syncValue = lang.delayedCall(function() {
-         if (!inComposition) {
-            text.value = PLACEHOLDER;
-            isFocused && resetSelection();
-         }
-    });
-
-    function resetSelection(isEmpty) {
-        if (inComposition)
-            return;
-        if (inputHandler) {
-            selectionStart = 0;
-            selectionEnd = isEmpty ? 0 : text.value.length - 1;
-        } else {
-            var selectionStart = isEmpty ? 2 : 1;
-            var selectionEnd = 2;
-        }
-        // on firefox this throws if textarea is hidden
-        try {
-            text.setSelectionRange(selectionStart, selectionEnd);
-        } catch(e){}
-    }
-
-    function resetValue() {
-        if (inComposition)
-            return;
-        text.value = PLACEHOLDER;
-        //http://code.google.com/p/chromium/issues/detail?id=76516
-        if (useragent.isWebKit)
-            syncValue.schedule();
-    }
-
-    useragent.isWebKit || host.addEventListener('changeSelection', function() {
-        if (host.selection.isEmpty() != isSelectionEmpty) {
-            isSelectionEmpty = !isSelectionEmpty;
-            syncSelection.schedule();
-        }
-    });
-
-    resetValue();
-    if (isFocused)
-        host.onFocus();
-
-
-    var isAllSelected = function(text) {
-        return text.selectionStart === 0 && text.selectionEnd === text.value.length;
-    };
-    // IE8 does not support setSelectionRange
-    if (!text.setSelectionRange && text.createTextRange) {
-        text.setSelectionRange = function(selectionStart, selectionEnd) {
-            var range = this.createTextRange();
-            range.collapse(true);
-            range.moveStart('character', selectionStart);
-            range.moveEnd('character', selectionEnd);
-            range.select();
-        };
-        isAllSelected = function(text) {
-            try {
-                var range = text.ownerDocument.selection.createRange();
-            }catch(e) {}
-            if (!range || range.parentElement() != text) return false;
-                return range.text == text.value;
-        }
-    }
-    if (useragent.isOldIE) {
-        var inPropertyChange = false;
-        var onPropertyChange = function(e){
-            if (inPropertyChange)
-                return;
-            var data = text.value;
-            if (inComposition || !data || data == PLACEHOLDER)
-                return;
-            // can happen either after delete or during insert operation
-            if (e && data == PLACEHOLDER[0])
-                return syncProperty.schedule();
-
-            sendText(data);
-            // ie8 calls propertychange handlers synchronously!
-            inPropertyChange = true;
-            resetValue();
-            inPropertyChange = false;
-        };
-        var syncProperty = lang.delayedCall(onPropertyChange);
-        event.addListener(text, "propertychange", onPropertyChange);
-
-        var keytable = { 13:1, 27:1 };
-        event.addListener(text, "keyup", function (e) {
-            if (inComposition && (!text.value || keytable[e.keyCode]))
-                setTimeout(onCompositionEnd, 0);
-            if ((text.value.charCodeAt(0)||0) < 129) {
-                return syncProperty.call();
-            }
-            inComposition ? onCompositionUpdate() : onCompositionStart();
-        });
-        // when user presses backspace after focusing the editor 
-        // propertychange isn't called for the next character
-        event.addListener(text, "keydown", function (e) {
-            syncProperty.schedule(50);
-        });
-    }
-
-    var onSelect = function(e) {
-        if (cut) {
-            cut = false;
-        } else if (copied) {
-            copied = false;
-        } else if (isAllSelected(text)) {
-            host.selectAll();
-            resetSelection();
-        } else if (inputHandler) {
-            resetSelection(host.selection.isEmpty());
-        }
-    };
-
-    var inputHandler = null;
-    this.setInputHandler = function(cb) {inputHandler = cb};
-    this.getInputHandler = function() {return inputHandler};
-    var afterContextMenu = false;
-    
-    var sendText = function(data) {
-        if (inputHandler) {
-            data = inputHandler(data);
-            inputHandler = null;
-        }
-        if (pasted) {
-            resetSelection();
-            if (data)
-                host.onPaste(data);
-            pasted = false;
-        } else if (data == PLACEHOLDER.charAt(0)) {
-            if (afterContextMenu)
-                host.execCommand("del", {source: "ace"});
-            else // some versions of android do not fire keydown when pressing backspace
-                host.execCommand("backspace", {source: "ace"});
-        } else {
-            if (data.substring(0, 2) == PLACEHOLDER)
-                data = data.substr(2);
-            else if (data.charAt(0) == PLACEHOLDER.charAt(0))
-                data = data.substr(1);
-            else if (data.charAt(data.length - 1) == PLACEHOLDER.charAt(0))
-                data = data.slice(0, -1);
-            // can happen if undo in textarea isn't stopped
-            if (data.charAt(data.length - 1) == PLACEHOLDER.charAt(0))
-                data = data.slice(0, -1);
-            
-            if (data)
-                host.onTextInput(data);
-        }
-        if (afterContextMenu)
-            afterContextMenu = false;
-    };
-    var onInput = function(e) {
-        // console.log("onInput", inComposition)
-        if (inComposition)
-            return;
-        var data = text.value;
-        sendText(data);
-        resetValue();
-    };
-
-    var onCut = function(e) {
-        var data = host.getCopyText();
-        if (!data) {
-            event.preventDefault(e);
-            return;
-        }
-
-        var clipboardData = e.clipboardData || window.clipboardData;
-
-        if (clipboardData && !BROKEN_SETDATA) {
-            // Safari 5 has clipboardData object, but does not handle setData()
-            var supported = clipboardData.setData("Text", data);
-            if (supported) {
-                host.onCut();
-                event.preventDefault(e);
-            }
-        }
-
-        if (!supported) {
-            cut = true;
-            text.value = data;
-            text.select();
-            setTimeout(function(){
-                cut = false;
-                resetValue();
-                resetSelection();
-                host.onCut();
-            });
-        }
-    };
-
-    var onCopy = function(e) {
-        var data = host.getCopyText();
-        if (!data) {
-            event.preventDefault(e);
-            return;
-        }
-
-        var clipboardData = e.clipboardData || window.clipboardData;
-        if (clipboardData && !BROKEN_SETDATA) {
-            // Safari 5 has clipboardData object, but does not handle setData()
-            var supported = clipboardData.setData("Text", data);
-            if (supported) {
-                host.onCopy();
-                event.preventDefault(e);
-            }
-        }
-        if (!supported) {
-            copied = true;
-            text.value = data;
-            text.select();
-            setTimeout(function(){
-                copied = false;
-                resetValue();
-                resetSelection();
-                host.onCopy();
-            });
-        }
-    };
-
-    var onPaste = function(e) {
-        var clipboardData = e.clipboardData || window.clipboardData;
-
-        if (clipboardData) {
-            var data = clipboardData.getData("Text");
-            if (data)
-                host.onPaste(data);
-            if (useragent.isIE)
-                setTimeout(resetSelection);
-            event.preventDefault(e);
-        }
-        else {
-            text.value = "";
-            pasted = true;
-        }
-    };
-
-    event.addCommandKeyListener(text, host.onCommandKey.bind(host));
-
-    event.addListener(text, "select", onSelect);
-
-    event.addListener(text, "input", onInput);
-
-    event.addListener(text, "cut", onCut);
-    event.addListener(text, "copy", onCopy);
-    event.addListener(text, "paste", onPaste);
-
-
-    // Opera has no clipboard events
-    if (!('oncut' in text) || !('oncopy' in text) || !('onpaste' in text)){
-        event.addListener(parentNode, "keydown", function(e) {
-            if ((useragent.isMac && !e.metaKey) || !e.ctrlKey)
-            return;
-
-            switch (e.keyCode) {
-                case 67:
-                    onCopy(e);
-                    break;
-                case 86:
-                    onPaste(e);
-                    break;
-                case 88:
-                    onCut(e);
-                    break;
-            }
-        });
-    }
-
-
-    // COMPOSITION
-    var onCompositionStart = function(e) {
-        if (inComposition) return;
-        // console.log("onCompositionStart", inComposition)
-        inComposition = {};
-        host.onCompositionStart();
-        setTimeout(onCompositionUpdate, 0);
-        host.on("mousedown", onCompositionEnd);
-        if (!host.selection.isEmpty()) {
-            host.insert("");
-            host.session.markUndoGroup();
-            host.selection.clearSelection();
-        }
-        host.session.markUndoGroup();
-    };
-
-    var onCompositionUpdate = function() {
-        // console.log("onCompositionUpdate", inComposition && JSON.stringify(text.value))
-        if (!inComposition) return;
-        var val = text.value.replace(/\x01/g, "");
-        if (inComposition.lastValue === val) return;
-        
-        host.onCompositionUpdate(val);
-        if (inComposition.lastValue)
-            host.undo();
-        inComposition.lastValue = val;
-        if (inComposition.lastValue) {
-            var r = host.selection.getRange();
-            host.insert(inComposition.lastValue);
-            host.session.markUndoGroup();
-            inComposition.range = host.selection.getRange();
-            host.selection.setRange(r);
-            host.selection.clearSelection();
-        }
-    };
-
-    var onCompositionEnd = function(e) {
-        // console.log("onCompositionEnd", inComposition &&inComposition.lastValue)
-        var c = inComposition;
-        inComposition = false;
-        var timer = setTimeout(function() {
-            timer = null;
-            var str = text.value.replace(/\x01/g, "");
-            // console.log(str, c.lastValue)
-            if (inComposition)
-                return
-            else if (str == c.lastValue)
-                resetValue();
-            else if (!c.lastValue && str) {
-                resetValue();
-                sendText(str);
-            }
-        });
-        inputHandler = function compositionInputHandler(str) {
-            // console.log("onCompositionEnd", str, c.lastValue)
-            if (timer)
-                clearTimeout(timer);
-            str = str.replace(/\x01/g, "");
-            if (str == c.lastValue)
-                return "";
-            if (c.lastValue && timer)
-                host.undo();
-            return str;
-        };
-        host.onCompositionEnd();
-        host.removeListener("mousedown", onCompositionEnd);
-        if (e.type == "compositionend" && c.range) {
-            host.selection.setRange(c.range);
-        }
-    };
-    
-    
-
-    var syncComposition = lang.delayedCall(onCompositionUpdate, 50);
-
-    event.addListener(text, "compositionstart", onCompositionStart);
-    if (useragent.isGecko) {
-        event.addListener(text, "text", function(){syncComposition.schedule()});
-    } else {
-        event.addListener(text, "keyup", function(){syncComposition.schedule()});
-        event.addListener(text, "keydown", function(){syncComposition.schedule()});
-    }
-    event.addListener(text, "compositionend", onCompositionEnd);
-
-    this.getElement = function() {
-        return text;
-    };
-
-    this.setReadOnly = function(readOnly) {
-       text.readOnly = readOnly;
-    };
-
-    this.onContextMenu = function(e) {
-        afterContextMenu = true;
-        if (!tempStyle)
-            tempStyle = text.style.cssText;
-
-        text.style.cssText = "z-index:100000;" + (useragent.isIE ? "opacity:0.1;" : "");
-
-        resetSelection(host.selection.isEmpty());
-        host._emit("nativecontextmenu", {target: host, domEvent: e});
-        var rect = host.container.getBoundingClientRect();
-        var style = dom.computedStyle(host.container);
-        var top = rect.top + (parseInt(style.borderTopWidth) || 0);
-        var left = rect.left + (parseInt(rect.borderLeftWidth) || 0);
-        var maxTop = rect.bottom - top - text.clientHeight;
-        var move = function(e) {
-            text.style.left = e.clientX - left - 2 + "px";
-            text.style.top = Math.min(e.clientY - top - 2, maxTop) + "px";
-        }; 
-        move(e);
-
-        if (e.type != "mousedown")
-            return;
-
-        if (host.renderer.$keepTextAreaAtCursor)
-            host.renderer.$keepTextAreaAtCursor = null;
-
-        // on windows context menu is opened after mouseup
-        if (useragent.isWin)
-            event.capture(host.container, move, onContextMenuClose);
-    };
-
-    this.onContextMenuClose = onContextMenuClose;
-    function onContextMenuClose() {
-        setTimeout(function () {
-            if (tempStyle) {
-                text.style.cssText = tempStyle;
-                tempStyle = '';
-            }
-            if (host.renderer.$keepTextAreaAtCursor == null) {
-                host.renderer.$keepTextAreaAtCursor = true;
-                host.renderer.$moveTextAreaToCursor();
-            }
-        }, 0);
-    }
-
-    // firefox fires contextmenu event after opening it
-    if (!useragent.isGecko || useragent.isMac) {
-        var onContextMenu = function(e) {
-            host.textInput.onContextMenu(e);
-            onContextMenuClose();
-        };
-        event.addListener(host.renderer.scroller, "contextmenu", onContextMenu);
-        event.addListener(text, "contextmenu", onContextMenu);
-    }
-};
-
-exports.TextInput = TextInput;
-});

+ 0 - 195
services/web/public/js/ace/keyboard/vim.js

@@ -1,195 +0,0 @@
-/* ***** 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 cmds = require("./vim/commands");
-var coreCommands = cmds.coreCommands;
-var util = require("./vim/maps/util");
-var useragent = require("../lib/useragent");
-
-var startCommands = {
-    "i": {
-        command: coreCommands.start
-    },
-    "I": {
-        command: coreCommands.startBeginning
-    },
-    "a": {
-        command: coreCommands.append
-    },
-    "A": {
-        command: coreCommands.appendEnd
-    },
-    "ctrl-f": {
-        command: "gotopagedown"
-    },
-    "ctrl-b": {
-        command: "gotopageup"
-    }
-};
-
-exports.handler = {
-	$id: "ace/keyboard/vim",
-    // workaround for j not repeating with `defaults write -g ApplePressAndHoldEnabled -bool true`
-    handleMacRepeat: function(data, hashId, key) {
-        if (hashId == -1) {
-            // record key
-            data.inputChar = key;
-            data.lastEvent = "input";
-        } else if (data.inputChar && data.$lastHash == hashId && data.$lastKey == key) {
-            // check for repeated keypress 
-            if (data.lastEvent == "input") {
-                data.lastEvent = "input1";
-            } else if (data.lastEvent == "input1") {
-                // simulate textinput
-                return true;
-            }
-        } else {
-            // reset
-            data.$lastHash = hashId;
-            data.$lastKey = key;
-            data.lastEvent = "keypress";
-        }
-    },
-    // on mac, with some keyboard layouts (e.g swedish) ^ starts composition, we don't need it in normal mode
-    updateMacCompositionHandlers: function(editor, enable) {
-        var onCompositionUpdateOverride = function(text) {
-            if (util.currentMode !== "insert") {
-                var el = this.textInput.getElement();
-                el.blur();
-                el.focus();
-                el.value = text;
-            } else {
-                this.onCompositionUpdateOrig(text);
-            }
-        };
-        var onCompositionStartOverride = function(text) {
-            if (util.currentMode === "insert") {            
-                this.onCompositionStartOrig(text);
-            }
-        }
-        if (enable) {
-            if (!editor.onCompositionUpdateOrig) {
-                editor.onCompositionUpdateOrig = editor.onCompositionUpdate;
-                editor.onCompositionUpdate = onCompositionUpdateOverride;
-                editor.onCompositionStartOrig = editor.onCompositionStart;
-                editor.onCompositionStart = onCompositionStartOverride;
-            }
-        } else {
-            if (editor.onCompositionUpdateOrig) {
-                editor.onCompositionUpdate = editor.onCompositionUpdateOrig;
-                editor.onCompositionUpdateOrig = null;
-                editor.onCompositionStart = editor.onCompositionStartOrig;
-                editor.onCompositionStartOrig = null;
-            }
-        }
-    },
-
-    handleKeyboard: function(data, hashId, key, keyCode, e) {
-        // ignore command keys (shift, ctrl etc.)
-        if (hashId != 0 && (key == "" || key == "\x00"))
-            return null;
-        
-        var editor = data.editor;
-        
-        if (hashId == 1)
-            key = "ctrl-" + key;
-        if (key == "ctrl-c") {
-            if (!useragent.isMac && editor.getCopyText()) {
-                editor.once("copy", function() {
-                    if (data.state == "start")
-                        coreCommands.stop.exec(editor);
-                    else
-                        editor.selection.clearSelection();
-                });
-                return {command: "null", passEvent: true};
-            }
-            return {command: coreCommands.stop};            
-        } else if ((key == "esc" && hashId == 0) || key == "ctrl-[") {
-            return {command: coreCommands.stop};
-        } else if (data.state == "start") {
-            if (useragent.isMac && this.handleMacRepeat(data, hashId, key)) {
-                hashId = -1;
-                key = data.inputChar;
-            }
-            
-            if (hashId == -1 || hashId == 1 || hashId == 0 && key.length > 1) {
-                if (cmds.inputBuffer.idle && startCommands[key])
-                    return startCommands[key];
-                cmds.inputBuffer.push(editor, key);
-                return {command: "null", passEvent: false}; 
-            } // if no modifier || shift: wait for input.
-            else if (key.length == 1 && (hashId == 0 || hashId == 4)) {
-                return {command: "null", passEvent: true};
-            } else if (key == "esc" && hashId == 0) {
-                return {command: coreCommands.stop};
-            }
-        } else {
-            if (key == "ctrl-w") {
-                return {command: "removewordleft"};
-            }
-        }
-    },
-
-    attach: function(editor) {
-        editor.on("click", exports.onCursorMove);
-        if (util.currentMode !== "insert")
-            cmds.coreCommands.stop.exec(editor);
-        editor.$vimModeHandler = this;
-        
-        this.updateMacCompositionHandlers(editor, true);
-    },
-
-    detach: function(editor) {
-        editor.removeListener("click", exports.onCursorMove);
-        util.noMode(editor);
-        util.currentMode = "normal";
-        this.updateMacCompositionHandlers(editor, false);
-    },
-
-    actions: cmds.actions,
-    getStatusText: function() {
-        if (util.currentMode == "insert")
-            return "INSERT";
-        if (util.onVisualMode)
-            return (util.onVisualLineMode ? "VISUAL LINE " : "VISUAL ") + cmds.inputBuffer.status;
-        return cmds.inputBuffer.status;
-    }
-};
-
-
-exports.onCursorMove = function(e) {
-    cmds.onCursorMove(e.editor, e);
-    exports.onCursorMove.scheduled = false;
-};
-
-});

+ 0 - 613
services/web/public/js/ace/keyboard/vim/commands.js

@@ -1,613 +0,0 @@
-/* ***** 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) {
-
-"never use strict";
-
-var lang = require("../../lib/lang");
-var util = require("./maps/util");
-var motions = require("./maps/motions");
-var operators = require("./maps/operators");
-var alias = require("./maps/aliases");
-var registers = require("./registers");
-
-var NUMBER = 1;
-var OPERATOR = 2;
-var MOTION = 3;
-var ACTION = 4;
-var HMARGIN = 8; // Minimum amount of line separation between margins;
-
-var repeat = function repeat(fn, count, args) {
-    while (0 < count--)
-        fn.apply(this, args);
-};
-
-var ensureScrollMargin = function(editor) {
-    var renderer = editor.renderer;
-    var pos = renderer.$cursorLayer.getPixelPosition();
-
-    var top = pos.top;
-
-    var margin = HMARGIN * renderer.layerConfig.lineHeight;
-    if (2 * margin > renderer.$size.scrollerHeight)
-        margin = renderer.$size.scrollerHeight / 2;
-
-    if (renderer.scrollTop > top - margin) {
-        renderer.session.setScrollTop(top - margin);
-    }
-
-    if (renderer.scrollTop + renderer.$size.scrollerHeight < top + margin + renderer.lineHeight) {
-        renderer.session.setScrollTop(top + margin + renderer.lineHeight - renderer.$size.scrollerHeight);
-    }
-};
-
-var actions = exports.actions = {
-    "z": {
-        param: true,
-        fn: function(editor, range, count, param) {
-            switch (param) {
-                case "z":
-                    editor.renderer.alignCursor(null, 0.5);
-                    break;
-                case "t":
-                    editor.renderer.alignCursor(null, 0);
-                    break;
-                case "b":
-                    editor.renderer.alignCursor(null, 1);
-                    break;
-                case "c":
-                    editor.session.onFoldWidgetClick(range.start.row, {domEvent:{target :{}}});
-                    break;
-                case "o":
-                    editor.session.onFoldWidgetClick(range.start.row, {domEvent:{target :{}}});
-                    break;
-                case "C":
-                    editor.session.foldAll();
-                    break;
-                case "O":
-                    editor.session.unfold();
-                    break;
-            }
-        }
-    },
-    "r": {
-        param: true,
-        fn: function(editor, range, count, param) {
-            if (param && param.length) {
-                if (param.length > 1)
-                    param = param == "return" ? "\n" : param == "tab" ? "\t" : param;
-                repeat(function() { editor.insert(param); }, count || 1);
-                editor.navigateLeft();
-            }
-        }
-    },
-    "R": {
-        fn: function(editor, range, count, param) {
-            util.insertMode(editor);
-            editor.setOverwrite(true);
-        }
-    },
-    "~": {
-        fn: function(editor, range, count) {
-            repeat(function() {
-                var range = editor.selection.getRange();
-                if (range.isEmpty())
-                    range.end.column++;
-                var text = editor.session.getTextRange(range);
-                var toggled = text.toUpperCase();
-                if (toggled == text)
-                    editor.navigateRight();
-                else
-                    editor.session.replace(range, toggled);
-            }, count || 1);
-        }
-    },
-    "*": {
-        fn: function(editor, range, count, param) {
-            editor.selection.selectWord();
-            editor.findNext();
-            ensureScrollMargin(editor);
-            var r = editor.selection.getRange();
-            editor.selection.setSelectionRange(r, true);
-        }
-    },
-    "#": {
-        fn: function(editor, range, count, param) {
-            editor.selection.selectWord();
-            editor.findPrevious();
-            ensureScrollMargin(editor);
-            var r = editor.selection.getRange();
-            editor.selection.setSelectionRange(r, true);
-        }
-    },
-    "m": {
-        param: true,
-        fn: function(editor, range, count, param) {
-            var s =  editor.session;
-            var markers = s.vimMarkers || (s.vimMarkers = {});
-            var c = editor.getCursorPosition();
-            if (!markers[param]) {
-                markers[param] = editor.session.doc.createAnchor(c);
-            }
-            markers[param].setPosition(c.row, c.column, true);
-        }
-    },
-    "n": {
-        fn: function(editor, range, count, param) {
-            var options = editor.getLastSearchOptions();
-            options.backwards = false;
-
-            editor.selection.moveCursorRight();
-            editor.selection.clearSelection();
-            editor.findNext(options);
-
-            ensureScrollMargin(editor);
-            var r = editor.selection.getRange();
-            r.end.row = r.start.row;
-            r.end.column = r.start.column;
-            editor.selection.setSelectionRange(r, true);
-        }
-    },
-    "N": {
-        fn: function(editor, range, count, param) {
-            var options = editor.getLastSearchOptions();
-            options.backwards = true;
-
-            editor.findPrevious(options);
-            ensureScrollMargin(editor);
-            var r = editor.selection.getRange();
-            r.end.row = r.start.row;
-            r.end.column = r.start.column;
-            editor.selection.setSelectionRange(r, true);
-        }
-    },
-    "v": {
-        fn: function(editor, range, count, param) {
-            editor.selection.selectRight();
-            util.visualMode(editor, false);
-        },
-        acceptsMotion: true
-    },
-    "V": {
-        fn: function(editor, range, count, param) {
-            //editor.selection.selectLine();
-            //editor.selection.selectLeft();
-            var row = editor.getCursorPosition().row;
-            editor.selection.clearSelection();
-            editor.selection.moveCursorTo(row, 0);
-            editor.selection.selectLineEnd();
-            editor.selection.visualLineStart = row;
-
-            util.visualMode(editor, true);
-        },
-        acceptsMotion: true
-    },
-    "Y": {
-        fn: function(editor, range, count, param) {
-            util.copyLine(editor);
-        }
-    },
-    "p": {
-        fn: function(editor, range, count, param) {
-            var defaultReg = registers._default;
-
-            editor.setOverwrite(false);
-            if (defaultReg.isLine) {
-                var pos = editor.getCursorPosition();
-                pos.column = editor.session.getLine(pos.row).length;
-                var text = lang.stringRepeat("\n" + defaultReg.text, count || 1);
-                editor.session.insert(pos, text);
-                editor.moveCursorTo(pos.row + 1, 0);
-            }
-            else {
-                editor.navigateRight();
-                editor.insert(lang.stringRepeat(defaultReg.text, count || 1));
-                editor.navigateLeft();
-            }
-            editor.setOverwrite(true);
-            editor.selection.clearSelection();
-        }
-    },
-    "P": {
-        fn: function(editor, range, count, param) {
-            var defaultReg = registers._default;
-            editor.setOverwrite(false);
-
-            if (defaultReg.isLine) {
-                var pos = editor.getCursorPosition();
-                pos.column = 0;
-                var text = lang.stringRepeat(defaultReg.text + "\n", count || 1);
-                editor.session.insert(pos, text);
-                editor.moveCursorToPosition(pos);
-            }
-            else {
-                editor.insert(lang.stringRepeat(defaultReg.text, count || 1));
-            }
-            editor.setOverwrite(true);
-            editor.selection.clearSelection();
-        }
-    },
-    "J": {
-        fn: function(editor, range, count, param) {
-            var session = editor.session;
-            range = editor.getSelectionRange();
-            var pos = {row: range.start.row, column: range.start.column};
-            count = count || range.end.row - range.start.row;
-            var maxRow = Math.min(pos.row + (count || 1), session.getLength() - 1);
-
-            range.start.column = session.getLine(pos.row).length;
-            range.end.column = session.getLine(maxRow).length;
-            range.end.row = maxRow;
-
-            var text = "";
-            for (var i = pos.row; i < maxRow; i++) {
-                var nextLine = session.getLine(i + 1);
-                text += " " + /^\s*(.*)$/.exec(nextLine)[1] || "";
-            }
-
-            session.replace(range, text);
-            editor.moveCursorTo(pos.row, pos.column);
-        }
-    },
-    "u": {
-        fn: function(editor, range, count, param) {
-            count = parseInt(count || 1, 10);
-            for (var i = 0; i < count; i++) {
-                editor.undo();
-            }
-            editor.selection.clearSelection();
-        }
-    },
-    "ctrl-r": {
-        fn: function(editor, range, count, param) {
-            count = parseInt(count || 1, 10);
-            for (var i = 0; i < count; i++) {
-                editor.redo();
-            }
-            editor.selection.clearSelection();
-        }
-    },
-    ":": {
-        fn: function(editor, range, count, param) {
-            var val = ":";
-            if (count > 1)
-                val = ".,.+" + count + val;
-            if (editor.showCommandLine)
-                editor.showCommandLine(val);
-        }
-    },
-    "/": {
-        fn: function(editor, range, count, param) {
-            if (editor.showCommandLine)
-                editor.showCommandLine("/");
-        }
-    },
-    "?": {
-        fn: function(editor, range, count, param) {
-            if (editor.showCommandLine)
-                editor.showCommandLine("?");
-        }
-    },
-    ".": {
-        fn: function(editor, range, count, param) {
-            util.onInsertReplaySequence = inputBuffer.lastInsertCommands;
-            var previous = inputBuffer.previous;
-            if (previous) // If there is a previous action
-                inputBuffer.exec(editor, previous.action, previous.param);
-        }
-    },
-    "ctrl-x": {
-        fn: function(editor, range, count, param) {
-            editor.modifyNumber(-(count || 1));
-        }
-    },
-    "ctrl-a": {
-        fn: function(editor, range, count, param) {
-            editor.modifyNumber(count || 1);
-        }
-    }
-};
-
-var inputBuffer = exports.inputBuffer = {
-    accepting: [NUMBER, OPERATOR, MOTION, ACTION],
-    currentCmd: null,
-    //currentMode: 0,
-    currentCount: "",
-    status: "",
-
-    // Types
-    operator: null,
-    motion: null,
-
-    lastInsertCommands: [],
-
-    push: function(editor, ch, keyId) {
-        var status = this.status;
-        var isKeyHandled = true;
-        this.idle = false;
-        var wObj = this.waitingForParam;
-        if (/^numpad\d+$/i.test(ch))
-            ch = ch.substr(6);
-            
-        if (wObj) {
-            this.exec(editor, wObj, ch);
-        }
-        // If input is a number (that doesn't start with 0)
-        else if (!(ch === "0" && !this.currentCount.length) &&
-            (/^\d+$/.test(ch) && this.isAccepting(NUMBER))) {
-            // Assuming that ch is always of type String, and not Number
-            this.currentCount += ch;
-            this.currentCmd = NUMBER;
-            this.accepting = [NUMBER, OPERATOR, MOTION, ACTION];
-        }
-        else if (!this.operator && this.isAccepting(OPERATOR) && operators[ch]) {
-            this.operator = {
-                ch: ch,
-                count: this.getCount()
-            };
-            this.currentCmd = OPERATOR;
-            this.accepting = [NUMBER, MOTION, ACTION];
-            this.exec(editor, { operator: this.operator });
-        }
-        else if (motions[ch] && this.isAccepting(MOTION)) {
-            this.currentCmd = MOTION;
-
-            var ctx = {
-                operator: this.operator,
-                motion: {
-                    ch: ch,
-                    count: this.getCount()
-                }
-            };
-
-            if (motions[ch].param)
-                this.waitForParam(ctx);
-            else
-                this.exec(editor, ctx);
-        }
-        else if (alias[ch] && this.isAccepting(MOTION)) {
-            alias[ch].operator.count = this.getCount();
-            this.exec(editor, alias[ch]);
-        }
-        else if (actions[ch] && this.isAccepting(ACTION)) {
-            var actionObj = {
-                action: {
-                    fn: actions[ch].fn,
-                    count: this.getCount()
-                }
-            };
-
-            if (actions[ch].param) {
-                this.waitForParam(actionObj);
-            }
-            else {
-                this.exec(editor, actionObj);
-            }
-
-            if (actions[ch].acceptsMotion)
-                this.idle = false;
-        }
-        else if (this.operator) {
-            this.operator.count = this.getCount();
-            this.exec(editor, { operator: this.operator }, ch);
-        }
-        else {
-            isKeyHandled = ch.length == 1;
-            this.reset();
-        }
-        
-        if (this.waitingForParam || this.motion || this.operator) {
-            this.status += ch;
-        } else if (this.currentCount) {
-            this.status = this.currentCount;
-        } else if (this.status) {
-            this.status = "";
-        }
-        if (this.status != status)
-            editor._emit("changeStatus");
-        return isKeyHandled;
-    },
-
-    waitForParam: function(cmd) {
-        this.waitingForParam = cmd;
-    },
-
-    getCount: function() {
-        var count = this.currentCount;
-        this.currentCount = "";
-        return count && parseInt(count, 10);
-    },
-
-    exec: function(editor, action, param) {
-        var m = action.motion;
-        var o = action.operator;
-        var a = action.action;
-
-        if (!param)
-            param = action.param;
-
-        if (o) {
-            this.previous = {
-                action: action,
-                param: param
-            };
-        }
-
-        if (o && !editor.selection.isEmpty()) {
-            if (operators[o.ch].selFn) {
-                operators[o.ch].selFn(editor, editor.getSelectionRange(), o.count, param);
-                this.reset();
-            }
-            return;
-        }
-
-        // There is an operator, but no motion or action. We try to pass the
-        // current ch to the operator to see if it responds to it (an example
-        // of this is the 'dd' operator).
-        else if (!m && !a && o && param) {
-            operators[o.ch].fn(editor, null, o.count, param);
-            this.reset();
-        }
-        else if (m) {
-            var run = function(fn) {
-                if (fn && typeof fn === "function") { // There should always be a motion
-                    if (m.count && !motionObj.handlesCount)
-                        repeat(fn, m.count, [editor, null, m.count, param]);
-                    else
-                        fn(editor, null, m.count, param);
-                }
-            };
-
-            var motionObj = motions[m.ch];
-            var selectable = motionObj.sel;
-
-            if (!o) {
-                if ((util.onVisualMode || util.onVisualLineMode) && selectable)
-                    run(motionObj.sel);
-                else
-                    run(motionObj.nav);
-            }
-            else if (selectable) {
-                repeat(function() {
-                    run(motionObj.sel);
-                    operators[o.ch].fn(editor, editor.getSelectionRange(), o.count, param);
-                }, o.count || 1);
-            }
-            this.reset();
-        }
-        else if (a) {
-            a.fn(editor, editor.getSelectionRange(), a.count, param);
-            this.reset();
-        }
-        handleCursorMove(editor);
-    },
-
-    isAccepting: function(type) {
-        return this.accepting.indexOf(type) !== -1;
-    },
-
-    reset: function() {
-        this.operator = null;
-        this.motion = null;
-        this.currentCount = "";
-        this.status = "";
-        this.accepting = [NUMBER, OPERATOR, MOTION, ACTION];
-        this.idle = true;
-        this.waitingForParam = null;
-    }
-};
-
-function setPreviousCommand(fn) {
-    inputBuffer.previous = { action: { action: { fn: fn } } };
-}
-
-exports.coreCommands = {
-    start: {
-        exec: function start(editor) {
-            util.insertMode(editor);
-            setPreviousCommand(start);
-        }
-    },
-    startBeginning: {
-        exec: function startBeginning(editor) {
-            editor.navigateLineStart();
-            util.insertMode(editor);
-            setPreviousCommand(startBeginning);
-        }
-    },
-    // Stop Insert mode as soon as possible. Works like typing <Esc> in
-    // insert mode.
-    stop: {
-        exec: function stop(editor) {
-            inputBuffer.reset();
-            util.onVisualMode = false;
-            util.onVisualLineMode = false;
-            inputBuffer.lastInsertCommands = util.normalMode(editor);
-        }
-    },
-    append: {
-        exec: function append(editor) {
-            var pos = editor.getCursorPosition();
-            var lineLen = editor.session.getLine(pos.row).length;
-            if (lineLen)
-                editor.navigateRight();
-            util.insertMode(editor);
-            setPreviousCommand(append);
-        }
-    },
-    appendEnd: {
-        exec: function appendEnd(editor) {
-            editor.navigateLineEnd();
-            util.insertMode(editor);
-            setPreviousCommand(appendEnd);
-        }
-    }
-};
-
-var handleCursorMove = exports.onCursorMove = function(editor, e) {
-    if (util.currentMode === 'insert' || handleCursorMove.running)
-        return;
-    else if(!editor.selection.isEmpty()) {
-        handleCursorMove.running = true;
-        if (util.onVisualLineMode) {
-            var originRow = editor.selection.visualLineStart;
-            var cursorRow = editor.getCursorPosition().row;
-            if(originRow <= cursorRow) {
-                var endLine = editor.session.getLine(cursorRow);
-                editor.selection.clearSelection();
-                editor.selection.moveCursorTo(originRow, 0);
-                editor.selection.selectTo(cursorRow, endLine.length);
-            } else {
-                var endLine = editor.session.getLine(originRow);
-                editor.selection.clearSelection();
-                editor.selection.moveCursorTo(originRow, endLine.length);
-                editor.selection.selectTo(cursorRow, 0);
-            }
-        }
-        handleCursorMove.running = false;
-        return;
-    }
-    else {
-        if (e && (util.onVisualLineMode || util.onVisualMode)) {
-            editor.selection.clearSelection();
-            util.normalMode(editor);
-        }
-
-        handleCursorMove.running = true;
-        var pos = editor.getCursorPosition();
-        var lineLen = editor.session.getLine(pos.row).length;
-
-        if (lineLen && pos.column === lineLen)
-            editor.navigateLeft();
-        handleCursorMove.running = false;
-    }
-};
-});

+ 0 - 94
services/web/public/js/ace/keyboard/vim/maps/aliases.js

@@ -1,94 +0,0 @@
-/* ***** 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 ***** */
- 
-"use strict"
-
-define(function(require, exports, module) {
-module.exports = {
-    "x": {
-        operator: {
-            ch: "d",
-            count: 1
-        },
-        motion: {
-            ch: "l",
-            count: 1
-        }
-    },
-    "X": {
-        operator: {
-            ch: "d",
-            count: 1
-        },
-        motion: {
-            ch: "h",
-            count: 1
-        }
-    },
-    "D": {
-        operator: {
-            ch: "d",
-            count: 1
-        },
-        motion: {
-            ch: "$",
-            count: 1
-        }
-    },
-    "C": {
-        operator: {
-            ch: "c",
-            count: 1
-        },
-        motion: {
-            ch: "$",
-            count: 1
-        }
-    },
-    "s": {
-        operator: {
-            ch: "c",
-            count: 1
-        },
-        motion: {
-            ch: "l",
-            count: 1
-        }
-    },
-    "S": {
-        operator: {
-            ch: "c",
-            count: 1
-        },
-        param: "c"
-    }
-};
-});
-

+ 0 - 664
services/web/public/js/ace/keyboard/vim/maps/motions.js

@@ -1,664 +0,0 @@
-/* ***** 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 util = require("./util");
-
-var keepScrollPosition = function(editor, fn) {
-    var scrollTopRow = editor.renderer.getScrollTopRow();
-    var initialRow = editor.getCursorPosition().row;
-    var diff = initialRow - scrollTopRow;
-    fn && fn.call(editor);
-    editor.renderer.scrollToRow(editor.getCursorPosition().row - diff);
-};
-
-function Motion(m) {
-    if (typeof m == "function") {
-        var getPos = m;
-        m = this;
-    } else {
-        var getPos = m.getPos;
-    }
-    m.nav = function(editor, range, count, param) {
-        var a = getPos(editor, range, count, param, false);
-        if (!a)
-            return;
-        editor.clearSelection();
-        editor.moveCursorTo(a.row, a.column);
-    };
-    m.sel = function(editor, range, count, param) {
-        var a = getPos(editor, range, count, param, true);
-        if (!a)
-            return;
-        editor.selection.selectTo(a.row, a.column);
-    };
-    return m;
-}
-
-var nonWordRe = /[\s.\/\\()\"'-:,.;<>~!@#$%^&*|+=\[\]{}`~?]/;
-var wordSeparatorRe = /[.\/\\()\"'-:,.;<>~!@#$%^&*|+=\[\]{}`~?]/;
-var whiteRe = /\s/;
-var StringStream = function(editor, cursor) {
-    var sel = editor.selection;
-    this.range = sel.getRange();
-    cursor = cursor || sel.selectionLead;
-    this.row = cursor.row;
-    this.col = cursor.column;
-    var line = editor.session.getLine(this.row);
-    var maxRow = editor.session.getLength();
-    this.ch = line[this.col] || '\n';
-    this.skippedLines = 0;
-
-    this.next = function() {
-        this.ch = line[++this.col] || this.handleNewLine(1);
-        //this.debug()
-        return this.ch;
-    };
-    this.prev = function() {
-        this.ch = line[--this.col] || this.handleNewLine(-1);
-        //this.debug()
-        return this.ch;
-    };
-    this.peek = function(dir) {
-        var ch = line[this.col + dir];
-        if (ch)
-            return ch;
-        if (dir == -1)
-            return '\n';
-        if (this.col == line.length - 1)
-            return '\n';
-        return editor.session.getLine(this.row + 1)[0] || '\n';
-    };
-
-    this.handleNewLine = function(dir) {
-        if (dir == 1){
-            if (this.col == line.length)
-                return '\n';
-            if (this.row == maxRow - 1)
-                return '';
-            this.col = 0;
-            this.row ++;
-            line = editor.session.getLine(this.row);
-            this.skippedLines++;
-            return line[0] || '\n';
-        }
-        if (dir == -1) {
-            if (this.row === 0)
-                return '';
-            this.row --;
-            line = editor.session.getLine(this.row);
-            this.col = line.length;
-            this.skippedLines--;
-            return '\n';
-        }
-    };
-    this.debug = function() {
-        console.log(line.substring(0, this.col)+'|'+this.ch+'\''+this.col+'\''+line.substr(this.col+1));
-    };
-};
-
-var Search = require("../../../search").Search;
-var search = new Search();
-
-function find(editor, needle, dir) {
-    search.$options.needle = needle;
-    search.$options.backwards = dir == -1;
-    return search.find(editor.session);
-}
-
-var Range = require("../../../range").Range;
-
-var LAST_SEARCH_MOTION = {};
-
-module.exports = {
-    "w": new Motion(function(editor) {
-        var str = new StringStream(editor);
-
-        if (str.ch && wordSeparatorRe.test(str.ch)) {
-            while (str.ch && wordSeparatorRe.test(str.ch))
-                str.next();
-        } else {
-            while (str.ch && !nonWordRe.test(str.ch))
-                str.next();
-        }
-        while (str.ch && whiteRe.test(str.ch) && str.skippedLines < 2)
-            str.next();
-
-        str.skippedLines == 2 && str.prev();
-        return {column: str.col, row: str.row};
-    }),
-    "W": new Motion(function(editor) {
-        var str = new StringStream(editor);
-        while(str.ch && !(whiteRe.test(str.ch) && !whiteRe.test(str.peek(1))) && str.skippedLines < 2)
-            str.next();
-        if (str.skippedLines == 2)
-            str.prev();
-        else
-            str.next();
-
-        return {column: str.col, row: str.row};
-    }),
-    "b": new Motion(function(editor) {
-        var str = new StringStream(editor);
-
-        str.prev();
-        while (str.ch && whiteRe.test(str.ch) && str.skippedLines > -2)
-            str.prev();
-
-        if (str.ch && wordSeparatorRe.test(str.ch)) {
-            while (str.ch && wordSeparatorRe.test(str.ch))
-                str.prev();
-        } else {
-            while (str.ch && !nonWordRe.test(str.ch))
-                str.prev();
-        }
-        str.ch && str.next();
-        return {column: str.col, row: str.row};
-    }),
-    "B": new Motion(function(editor) {
-        var str = new StringStream(editor);
-        str.prev();
-        while(str.ch && !(!whiteRe.test(str.ch) && whiteRe.test(str.peek(-1))) && str.skippedLines > -2)
-            str.prev();
-
-        if (str.skippedLines == -2)
-            str.next();
-
-        return {column: str.col, row: str.row};
-    }),
-    "e": new Motion(function(editor) {
-        var str = new StringStream(editor);
-
-        str.next();
-        while (str.ch && whiteRe.test(str.ch))
-            str.next();
-
-        if (str.ch && wordSeparatorRe.test(str.ch)) {
-            while (str.ch && wordSeparatorRe.test(str.ch))
-                str.next();
-        } else {
-            while (str.ch && !nonWordRe.test(str.ch))
-                str.next();
-        }
-        str.ch && str.prev();
-        return {column: str.col, row: str.row};
-    }),
-    "E": new Motion(function(editor) {
-        var str = new StringStream(editor);
-        str.next();
-        while(str.ch && !(!whiteRe.test(str.ch) && whiteRe.test(str.peek(1))))
-            str.next();
-
-        return {column: str.col, row: str.row};
-    }),
-
-    "l": {
-        nav: function(editor) {
-            var pos = editor.getCursorPosition();
-            var col = pos.column;
-            var lineLen = editor.session.getLine(pos.row).length;
-            if (lineLen && col !== lineLen)
-                editor.navigateRight();
-        },
-        sel: function(editor) {
-            var pos = editor.getCursorPosition();
-            var col = pos.column;
-            var lineLen = editor.session.getLine(pos.row).length;
-
-            // Solving the behavior at the end of the line due to the
-            // different 0 index-based colum positions in ACE.
-            if (lineLen && col !== lineLen) //In selection mode you can select the newline
-                editor.selection.selectRight();
-        }
-    },
-    "h": {
-        nav: function(editor) {
-            var pos = editor.getCursorPosition();
-            if (pos.column > 0)
-                editor.navigateLeft();
-        },
-        sel: function(editor) {
-            var pos = editor.getCursorPosition();
-            if (pos.column > 0)
-                editor.selection.selectLeft();
-        }
-    },
-    "H": {
-        nav: function(editor) {
-            var row = editor.renderer.getScrollTopRow();
-            editor.moveCursorTo(row);
-        },
-        sel: function(editor) {
-            var row = editor.renderer.getScrollTopRow();
-            editor.selection.selectTo(row);
-        }
-    },
-    "M": {
-        nav: function(editor) {
-            var topRow = editor.renderer.getScrollTopRow();
-            var bottomRow = editor.renderer.getScrollBottomRow();
-            var row = topRow + ((bottomRow - topRow) / 2);
-            editor.moveCursorTo(row);
-        },
-        sel: function(editor) {
-            var topRow = editor.renderer.getScrollTopRow();
-            var bottomRow = editor.renderer.getScrollBottomRow();
-            var row = topRow + ((bottomRow - topRow) / 2);
-            editor.selection.selectTo(row);
-        }
-    },
-    "L": {
-        nav: function(editor) {
-            var row = editor.renderer.getScrollBottomRow();
-            editor.moveCursorTo(row);
-        },
-        sel: function(editor) {
-            var row = editor.renderer.getScrollBottomRow();
-            editor.selection.selectTo(row);
-        }
-    },
-    "k": {
-        nav: function(editor) {
-            editor.navigateUp();
-        },
-        sel: function(editor) {
-            editor.selection.selectUp();
-        }
-    },
-    "j": {
-        nav: function(editor) {
-            editor.navigateDown();
-        },
-        sel: function(editor) {
-            editor.selection.selectDown();
-        }
-    },
-
-    "i": {
-        param: true,
-        sel: function(editor, range, count, param) {
-            switch (param) {
-                case "w":
-                    editor.selection.selectWord();
-                    break;
-                case "W":
-                    editor.selection.selectAWord();
-                    break;
-                case "(":
-                case "{":
-                case "[":
-                    var cursor = editor.getCursorPosition();
-                    var end = editor.session.$findClosingBracket(param, cursor, /paren/);
-                    if (!end)
-                        return;
-                    var start = editor.session.$findOpeningBracket(editor.session.$brackets[param], cursor, /paren/);
-                    if (!start)
-                        return;
-                    start.column ++;
-                    editor.selection.setSelectionRange(Range.fromPoints(start, end));
-                    break;
-                case "'":
-                case '"':
-                case "/":
-                    var end = find(editor, param, 1);
-                    if (!end)
-                        return;
-                    var start = find(editor, param, -1);
-                    if (!start)
-                        return;
-                    editor.selection.setSelectionRange(Range.fromPoints(start.end, end.start));
-                    break;
-            }
-        }
-    },
-    "a": {
-        param: true,
-        sel: function(editor, range, count, param) {
-            switch (param) {
-                case "w":
-                    editor.selection.selectAWord();
-                    break;
-                case "W":
-                    editor.selection.selectAWord();
-                    break;
-                case "(":
-                case "{":
-                case "[":
-                    var cursor = editor.getCursorPosition();
-                    var end = editor.session.$findClosingBracket(param, cursor, /paren/);
-                    if (!end)
-                        return;
-                    var start = editor.session.$findOpeningBracket(editor.session.$brackets[param], cursor, /paren/);
-                    if (!start)
-                        return;
-                    end.column ++;
-                    editor.selection.setSelectionRange(Range.fromPoints(start, end));
-                    break;
-                case "'":
-                case "\"":
-                case "/":
-                    var end = find(editor, param, 1);
-                    if (!end)
-                        return;
-                    var start = find(editor, param, -1);
-                    if (!start)
-                        return;
-                    end.column ++;
-                    editor.selection.setSelectionRange(Range.fromPoints(start.start, end.end));
-                    break;
-            }
-        }
-    },
-
-    "f": new Motion({
-        param: true,
-        handlesCount: true,
-        getPos: function(editor, range, count, param, isSel, isRepeat) {
-            if (!isRepeat)
-                LAST_SEARCH_MOTION = {ch: "f", param: param};
-            var cursor = editor.getCursorPosition();
-            var column = util.getRightNthChar(editor, cursor, param, count || 1);
-
-            if (typeof column === "number") {
-                cursor.column += column + (isSel ? 2 : 1);
-                return cursor;
-            }
-        }
-    }),
-    "F": new Motion({
-        param: true,
-        handlesCount: true,
-        getPos: function(editor, range, count, param, isSel, isRepeat) {
-            if (!isRepeat)
-                LAST_SEARCH_MOTION = {ch: "F", param: param};
-            var cursor = editor.getCursorPosition();
-            var column = util.getLeftNthChar(editor, cursor, param, count || 1);
-
-            if (typeof column === "number") {
-                cursor.column -= column + 1;
-                return cursor;
-            }
-        }
-    }),
-    "t": new Motion({
-        param: true,
-        handlesCount: true,
-        getPos: function(editor, range, count, param, isSel, isRepeat) {
-            if (!isRepeat)
-                LAST_SEARCH_MOTION = {ch: "t", param: param};
-            var cursor = editor.getCursorPosition();
-            var column = util.getRightNthChar(editor, cursor, param, count || 1);
-
-            if (isRepeat && column == 0 && !(count > 1))
-                var column = util.getRightNthChar(editor, cursor, param, 2);
-                
-            if (typeof column === "number") {
-                cursor.column += column + (isSel ? 1 : 0);
-                return cursor;
-            }
-        }
-    }),
-    "T": new Motion({
-        param: true,
-        handlesCount: true,
-        getPos: function(editor, range, count, param, isSel, isRepeat) {
-            if (!isRepeat)
-                LAST_SEARCH_MOTION = {ch: "T", param: param};
-            var cursor = editor.getCursorPosition();
-            var column = util.getLeftNthChar(editor, cursor, param, count || 1);
-
-            if (isRepeat && column == 0 && !(count > 1))
-                var column = util.getLeftNthChar(editor, cursor, param, 2);
-            
-            if (typeof column === "number") {
-                cursor.column -= column;
-                return cursor;
-            }
-        }
-    }),
-    ";": new Motion({
-        handlesCount: true,
-        getPos: function(editor, range, count, param, isSel) {
-            var ch = LAST_SEARCH_MOTION.ch;
-            if (!ch)
-                return;
-            return module.exports[ch].getPos(
-                editor, range, count, LAST_SEARCH_MOTION.param, isSel, true
-            );
-        }
-    }),
-    ",": new Motion({
-        handlesCount: true,
-        getPos: function(editor, range, count, param, isSel) {
-            var ch = LAST_SEARCH_MOTION.ch;
-            if (!ch)
-                return;
-            var up = ch.toUpperCase();
-            ch = ch === up ? ch.toLowerCase() : up;
-            
-            return module.exports[ch].getPos(
-                editor, range, count, LAST_SEARCH_MOTION.param, isSel, true
-            );
-        }
-    }),
-
-    "^": {
-        nav: function(editor) {
-            editor.navigateLineStart();
-        },
-        sel: function(editor) {
-            editor.selection.selectLineStart();
-        }
-    },
-    "$": {
-        nav: function(editor) {
-            editor.navigateLineEnd();
-        },
-        sel: function(editor) {
-            editor.selection.selectLineEnd();
-        }
-    },
-    "0": new Motion(function(ed) {
-        return {row: ed.selection.lead.row, column: 0};
-    }),
-    "G": {
-        nav: function(editor, range, count, param) {
-            if (!count && count !== 0) { // Stupid JS
-                count = editor.session.getLength();
-            }
-            editor.gotoLine(count);
-        },
-        sel: function(editor, range, count, param) {
-            if (!count && count !== 0) { // Stupid JS
-                count = editor.session.getLength();
-            }
-            editor.selection.selectTo(count, 0);
-        }
-    },
-    "g": {
-        param: true,
-        nav: function(editor, range, count, param) {
-            switch(param) {
-                case "m":
-                    console.log("Middle line");
-                    break;
-                case "e":
-                    console.log("End of prev word");
-                    break;
-                case "g":
-                    editor.gotoLine(count || 0);
-                case "u":
-                    editor.gotoLine(count || 0);
-                case "U":
-                    editor.gotoLine(count || 0);
-            }
-        },
-        sel: function(editor, range, count, param) {
-            switch(param) {
-                case "m":
-                    console.log("Middle line");
-                    break;
-                case "e":
-                    console.log("End of prev word");
-                    break;
-                case "g":
-                    editor.selection.selectTo(count || 0, 0);
-            }
-        }
-    },
-    "o": {
-        nav: function(editor, range, count, param) {
-            count = count || 1;
-            var content = "";
-            while (0 < count--)
-                content += "\n";
-
-            if (content.length) {
-                editor.navigateLineEnd()
-                editor.insert(content);
-                util.insertMode(editor);
-            }
-        }
-    },
-    "O": {
-        nav: function(editor, range, count, param) {
-            var row = editor.getCursorPosition().row;
-            count = count || 1;
-            var content = "";
-            while (0 < count--)
-                content += "\n";
-
-            if (content.length) {
-                if(row > 0) {
-                    editor.navigateUp();
-                    editor.navigateLineEnd()
-                    editor.insert(content);
-                } else {
-                    editor.session.insert({row: 0, column: 0}, content);
-                    editor.navigateUp();
-                }
-                util.insertMode(editor);
-            }
-        }
-    },
-    "%": new Motion(function(editor){
-        var brRe = /[\[\]{}()]/g;
-        var cursor = editor.getCursorPosition();
-        var ch = editor.session.getLine(cursor.row)[cursor.column];
-        if (!brRe.test(ch)) {
-            var range = find(editor, brRe);
-            if (!range)
-                return;
-            cursor = range.start;
-        }
-        var match = editor.session.findMatchingBracket({
-            row: cursor.row,
-            column: cursor.column + 1
-        });
-
-        return match;
-    }),
-    "{": new Motion(function(ed) {
-        var session = ed.session;
-        var row = session.selection.lead.row;
-        while(row > 0 && !/\S/.test(session.getLine(row)))
-            row--;
-        while(/\S/.test(session.getLine(row)))
-            row--;
-        return {column: 0, row: row};
-    }),
-    "}": new Motion(function(ed) {
-        var session = ed.session;
-        var l = session.getLength();
-        var row = session.selection.lead.row;
-        while(row < l && !/\S/.test(session.getLine(row)))
-            row++;
-        while(/\S/.test(session.getLine(row)))
-            row++;
-        return {column: 0, row: row};
-    }),
-    "ctrl-d": {
-        nav: function(editor, range, count, param) {
-            editor.selection.clearSelection();
-            keepScrollPosition(editor, editor.gotoPageDown);
-        },
-        sel: function(editor, range, count, param) {
-            keepScrollPosition(editor, editor.selectPageDown);
-        }
-    },
-    "ctrl-u": {
-        nav: function(editor, range, count, param) {
-            editor.selection.clearSelection();
-            keepScrollPosition(editor, editor.gotoPageUp);
-        },
-        sel: function(editor, range, count, param) {
-            keepScrollPosition(editor, editor.selectPageUp);
-        }
-    },
-    "`": new Motion({
-        param: true,
-        handlesCount: true,
-        getPos: function(editor, range, count, param, isSel) {
-            var s = editor.session;
-            var marker = s.vimMarkers && s.vimMarkers[param];
-            if (marker) {
-                return marker.getPosition();
-            }
-        }
-    }),
-    "'": new Motion({
-        param: true,
-        handlesCount: true,
-        getPos: function(editor, range, count, param, isSel) {
-            var s = editor.session;
-            var marker = s.vimMarkers && s.vimMarkers[param];
-            if (marker) {
-                var pos = marker.getPosition();
-                var line = editor.session.getLine(pos.row);                
-                pos.column = line.search(/\S/);
-                if (pos.column == -1)
-                    pos.column = line.length;
-                return pos;
-            }
-        }
-    })
-};
-
-module.exports.backspace = module.exports.left = module.exports.h;
-module.exports.space = module.exports['return'] = module.exports.right = module.exports.l;
-module.exports.up = module.exports.k;
-module.exports.down = module.exports.j;
-module.exports.pagedown = module.exports["ctrl-d"];
-module.exports.pageup = module.exports["ctrl-u"];
-
-});

+ 0 - 195
services/web/public/js/ace/keyboard/vim/maps/operators.js

@@ -1,195 +0,0 @@
-/* ***** 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 util = require("./util");
-var registers = require("../registers");
-
-module.exports = {
-    "d": {
-        selFn: function(editor, range, count, param) {
-            registers._default.text = editor.getCopyText();
-            registers._default.isLine = util.onVisualLineMode;
-            if(util.onVisualLineMode)
-                editor.removeLines();
-            else
-                editor.session.remove(range);
-            util.normalMode(editor);
-        },
-        fn: function(editor, range, count, param) {
-            count = count || 1;
-            switch (param) {
-                case "d":
-                    registers._default.text = "";
-                    registers._default.isLine = true;
-                    for (var i = 0; i < count; i++) {
-                        editor.selection.selectLine();
-                        registers._default.text += editor.getCopyText();
-                        var selRange = editor.getSelectionRange();
-                        // check if end of the document was reached
-                        if (!selRange.isMultiLine()) {
-                            var row = selRange.start.row - 1;
-                            var col = editor.session.getLine(row).length
-                            selRange.setStart(row, col);
-                            editor.session.remove(selRange);
-                            editor.selection.clearSelection();
-                            break;
-                        }
-                        editor.session.remove(selRange);
-                        editor.selection.clearSelection();
-                    }
-                    registers._default.text = registers._default.text.replace(/\n$/, "");
-                    break;
-                default:
-                    if (range) {
-                        editor.selection.setSelectionRange(range);
-                        registers._default.text = editor.getCopyText();
-                        registers._default.isLine = false;
-                        editor.session.remove(range);
-                        editor.selection.clearSelection();
-                    }
-            }
-        }
-    },
-    "c": {
-        selFn: function(editor, range, count, param) {
-            editor.session.remove(range);
-            util.insertMode(editor);
-        },
-        fn: function(editor, range, count, param) {
-            count = count || 1;
-            switch (param) {
-                case "c":
-                    for (var i = 0; i < count; i++) {
-                        editor.removeLines();
-                        util.insertMode(editor);
-                    }
-
-                    break;
-                default:
-                    if (range) {
-
-                        // range.end.column ++;
-                        editor.session.remove(range);
-                        util.insertMode(editor);
-                    }
-            }
-        }
-    },
-    "y": {
-        selFn: function(editor, range, count, param) {
-            registers._default.text = editor.getCopyText();
-            registers._default.isLine = util.onVisualLineMode;
-            editor.selection.clearSelection();
-            util.normalMode(editor);
-        },
-        fn: function(editor, range, count, param) {
-            count = count || 1;
-            switch (param) {
-                case "y":
-                    var pos = editor.getCursorPosition();
-                    editor.selection.selectLine();
-                    for (var i = 0; i < count - 1; i++) {
-                        editor.selection.moveCursorDown();
-                    }
-                    registers._default.text = editor.getCopyText().replace(/\n$/, "");
-                    editor.selection.clearSelection();
-                    registers._default.isLine = true;
-                    editor.moveCursorToPosition(pos);
-                    break;
-                default:
-                    if (range) {
-                        var pos = editor.getCursorPosition();
-                        editor.selection.setSelectionRange(range);
-                        registers._default.text = editor.getCopyText();
-                        registers._default.isLine = false;
-                        editor.selection.clearSelection();
-                        editor.moveCursorTo(pos.row, pos.column);
-                    }
-            }
-        }
-    },
-    ">": {
-        selFn: function(editor, range, count, param) {
-            count = count || 1;
-            for (var i = 0; i < count; i++) {
-                editor.indent();
-            }
-            util.normalMode(editor);
-        },
-        fn: function(editor, range, count, param) {
-            count = parseInt(count || 1, 10);
-            switch (param) {
-                case ">":
-                    var pos = editor.getCursorPosition();
-                    editor.selection.selectLine();
-                    for (var i = 0; i < count - 1; i++) {
-                        editor.selection.moveCursorDown();
-                    }
-                    editor.indent();
-                    editor.selection.clearSelection();
-                    editor.moveCursorToPosition(pos);
-                    editor.navigateLineEnd();
-                    editor.navigateLineStart();
-                    break;
-            }
-        }
-    },
-    "<": {
-        selFn: function(editor, range, count, param) {
-            count = count || 1;
-            for (var i = 0; i < count; i++) {
-                editor.blockOutdent();
-            }
-            util.normalMode(editor);
-        },
-        fn: function(editor, range, count, param) {
-            count = count || 1;
-            switch (param) {
-                case "<":
-                    var pos = editor.getCursorPosition();
-                    editor.selection.selectLine();
-                    for (var i = 0; i < count - 1; i++) {
-                        editor.selection.moveCursorDown();
-                    }
-                    editor.blockOutdent();
-                    editor.selection.clearSelection();
-                    editor.moveCursorToPosition(pos);
-                    editor.navigateLineEnd();
-                    editor.navigateLineStart();
-                    break;
-            }
-        }
-    }
-};
-});

+ 0 - 134
services/web/public/js/ace/keyboard/vim/maps/util.js

@@ -1,134 +0,0 @@
-define(function(require, exports, module) {
-var registers = require("../registers");
-
-var dom = require("../../../lib/dom");
-dom.importCssString('.insert-mode .ace_cursor{\
-    border-left: 2px solid #333333;\
-}\
-.ace_dark.insert-mode .ace_cursor{\
-    border-left: 2px solid #eeeeee;\
-}\
-.normal-mode .ace_cursor{\
-    border: 0!important;\
-    background-color: red;\
-    opacity: 0.5;\
-}', 'vimMode');
-
-module.exports = {
-    onVisualMode: false,
-    onVisualLineMode: false,
-    currentMode: 'normal',
-    noMode: function(editor) {
-        editor.unsetStyle('insert-mode');
-        editor.unsetStyle('normal-mode');
-        if (editor.commands.recording)
-            editor.commands.toggleRecording(editor);
-        editor.setOverwrite(false);
-    },
-    insertMode: function(editor) {
-        this.currentMode = 'insert';
-        // Switch editor to insert mode
-        editor.setStyle('insert-mode');
-        editor.unsetStyle('normal-mode');
-
-        editor.setOverwrite(false);
-        editor.keyBinding.$data.buffer = "";
-        editor.keyBinding.$data.state = "insertMode";
-        this.onVisualMode = false;
-        this.onVisualLineMode = false;
-        if(this.onInsertReplaySequence) {
-            // Ok, we're apparently replaying ("."), so let's do it
-            editor.commands.macro = this.onInsertReplaySequence;
-            editor.commands.replay(editor);
-            this.onInsertReplaySequence = null;
-            this.normalMode(editor);
-        } else {
-            editor._emit("changeStatus");
-            // Record any movements, insertions in insert mode
-            if(!editor.commands.recording)
-                editor.commands.toggleRecording(editor);
-        }
-    },
-    normalMode: function(editor) {
-        // Switch editor to normal mode
-        this.currentMode = 'normal';
-
-        editor.unsetStyle('insert-mode');
-        editor.setStyle('normal-mode');
-        editor.clearSelection();
-
-        var pos;
-        if (!editor.getOverwrite()) {
-            pos = editor.getCursorPosition();
-            if (pos.column > 0)
-                editor.navigateLeft();
-        }
-
-        editor.setOverwrite(true);
-        editor.keyBinding.$data.buffer = "";
-        editor.keyBinding.$data.state = "start";
-        this.onVisualMode = false;
-        this.onVisualLineMode = false;
-        editor._emit("changeStatus");
-        // Save recorded keystrokes
-        if (editor.commands.recording) {
-            editor.commands.toggleRecording(editor);
-            return editor.commands.macro;
-        }
-        else {
-            return [];
-        }
-    },
-    visualMode: function(editor, lineMode) {
-        if (
-            (this.onVisualLineMode && lineMode)
-            || (this.onVisualMode && !lineMode)
-        ) {
-            this.normalMode(editor);
-            return;
-        }
-
-        editor.setStyle('insert-mode');
-        editor.unsetStyle('normal-mode');
-
-        editor._emit("changeStatus");
-        if (lineMode) {
-            this.onVisualLineMode = true;
-        } else {
-            this.onVisualMode = true;
-            this.onVisualLineMode = false;
-        }
-    },
-    getRightNthChar: function(editor, cursor, ch, n) {
-        var line = editor.getSession().getLine(cursor.row);
-        var matches = line.substr(cursor.column + 1).split(ch);
-
-        return n < matches.length ? matches.slice(0, n).join(ch).length : null;
-    },
-    getLeftNthChar: function(editor, cursor, ch, n) {
-        var line = editor.getSession().getLine(cursor.row);
-        var matches = line.substr(0, cursor.column).split(ch);
-
-        return n < matches.length ? matches.slice(-1 * n).join(ch).length : null;
-    },
-    toRealChar: function(ch) {
-        if (ch.length === 1)
-            return ch;
-
-        if (/^shift-./.test(ch))
-            return ch[ch.length - 1].toUpperCase();
-        else
-            return "";
-    },
-    copyLine: function(editor) {
-        var pos = editor.getCursorPosition();
-        editor.selection.clearSelection();
-        editor.moveCursorTo(pos.row, pos.column);
-        editor.selection.selectLine();
-        registers._default.isLine = true;
-        registers._default.text = editor.getCopyText().replace(/\n$/, "");
-        editor.selection.clearSelection();
-        editor.moveCursorTo(pos.row, pos.column);
-    }
-};
-});

+ 0 - 42
services/web/public/js/ace/keyboard/vim/registers.js

@@ -1,42 +0,0 @@
-/* ***** 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) {
-
-"never use strict";
-
-module.exports = {
-    _default: {
-        text: "",
-        isLine: false
-    }
-};
-
-});

+ 0 - 217
services/web/public/js/ace/layer/cursor.js

@@ -1,217 +0,0 @@
-/* ***** 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 dom = require("../lib/dom");
-
-var Cursor = function(parentEl) {
-    this.element = dom.createElement("div");
-    this.element.className = "ace_layer ace_cursor-layer";
-    parentEl.appendChild(this.element);
-
-    this.isVisible = false;
-    this.isBlinking = true;
-    this.blinkInterval = 1000;
-    this.smoothBlinking = false;
-
-    this.cursors = [];
-    this.cursor = this.addCursor();
-    dom.addCssClass(this.element, "ace_hidden-cursors");
-};
-
-(function() {
-
-    this.$padding = 0;
-    this.setPadding = function(padding) {
-        this.$padding = padding;
-    };
-
-    this.setSession = function(session) {
-        this.session = session;
-    };
-
-    this.setBlinking = function(blinking) {
-        if (blinking != this.isBlinking){
-            this.isBlinking = blinking;
-            this.restartTimer();
-        }
-    };
-
-    this.setBlinkInterval = function(blinkInterval) {
-        if (blinkInterval != this.blinkInterval){
-            this.blinkInterval = blinkInterval;
-            this.restartTimer();
-        }
-    };
-
-    this.setSmoothBlinking = function(smoothBlinking) {
-        if (smoothBlinking != this.smoothBlinking) {
-            this.smoothBlinking = smoothBlinking;
-            if (smoothBlinking)
-                dom.addCssClass(this.element, "ace_smooth-blinking");
-            else
-                dom.removeCssClass(this.element, "ace_smooth-blinking");
-            this.restartTimer();
-        }
-    };
-
-    this.addCursor = function() {
-        var el = dom.createElement("div");
-        el.className = "ace_cursor";
-        this.element.appendChild(el);
-        this.cursors.push(el);
-        return el;
-    };
-
-    this.removeCursor = function() {
-        if (this.cursors.length > 1) {
-            var el = this.cursors.pop();
-            el.parentNode.removeChild(el);
-            return el;
-        }
-    };
-
-    this.hideCursor = function() {
-        this.isVisible = false;
-        dom.addCssClass(this.element, "ace_hidden-cursors");
-        this.restartTimer();
-    };
-
-    this.showCursor = function() {
-        this.isVisible = true;
-        dom.removeCssClass(this.element, "ace_hidden-cursors");
-        this.restartTimer();
-    };
-
-    this.restartTimer = function() {
-        clearInterval(this.intervalId);
-        clearTimeout(this.timeoutId);
-        if (this.smoothBlinking)
-            dom.removeCssClass(this.element, "ace_smooth-blinking");
-        for (var i = this.cursors.length; i--; )
-            this.cursors[i].style.opacity = "";
-
-        if (!this.isBlinking || !this.blinkInterval || !this.isVisible)
-            return;
-
-        if (this.smoothBlinking)
-            setTimeout(function(){
-                dom.addCssClass(this.element, "ace_smooth-blinking");
-            }.bind(this));
-
-        var blink = function(){
-            this.timeoutId = setTimeout(function() {
-                for (var i = this.cursors.length; i--; ) {
-                    this.cursors[i].style.opacity = 0;
-                }
-            }.bind(this), 0.6 * this.blinkInterval);
-        }.bind(this);
-
-        this.intervalId = setInterval(function() {
-            for (var i = this.cursors.length; i--; ) {
-                this.cursors[i].style.opacity = "";
-            }
-            blink();
-        }.bind(this), this.blinkInterval);
-
-        blink();
-    };
-
-    this.getPixelPosition = function(position, onScreen) {
-        if (!this.config || !this.session)
-            return {left : 0, top : 0};
-
-        if (!position)
-            position = this.session.selection.getCursor();
-        var pos = this.session.documentToScreenPosition(position);
-        var cursorLeft = this.$padding + pos.column * this.config.characterWidth;
-        var cursorTop = (pos.row - (onScreen ? this.config.firstRowScreen : 0)) *
-            this.config.lineHeight;
-
-        return {left : cursorLeft, top : cursorTop};
-    };
-
-    this.update = function(config) {
-        this.config = config;
-
-        var selections = this.session.$selectionMarkers;
-        var i = 0, cursorIndex = 0;
-
-        if (selections === undefined || selections.length === 0){
-            selections = [{cursor: null}];
-        }
-
-        for (var i = 0, n = selections.length; i < n; i++) {
-            var pixelPos = this.getPixelPosition(selections[i].cursor, true);
-            if ((pixelPos.top > config.height + config.offset ||
-                 pixelPos.top < -config.offset) && i > 1) {
-                continue;
-            }
-
-            var style = (this.cursors[cursorIndex++] || this.addCursor()).style;
-
-            style.left = pixelPos.left + "px";
-            style.top = pixelPos.top + "px";
-            style.width = config.characterWidth + "px";
-            style.height = config.lineHeight + "px";
-        }
-        while (this.cursors.length > cursorIndex)
-            this.removeCursor();
-
-        var overwrite = this.session.getOverwrite();
-        this.$setOverwrite(overwrite);
-
-        // cache for textarea and gutter highlight
-        this.$pixelPos = pixelPos;
-        this.restartTimer();
-    };
-
-    this.$setOverwrite = function(overwrite) {
-        if (overwrite != this.overwrite) {
-            this.overwrite = overwrite;
-            if (overwrite)
-                dom.addCssClass(this.element, "ace_overwrite-cursors");
-            else
-                dom.removeCssClass(this.element, "ace_overwrite-cursors");
-        }
-    };
-
-    this.destroy = function() {
-        clearInterval(this.intervalId);
-        clearTimeout(this.timeoutId);
-    };
-
-}).call(Cursor.prototype);
-
-exports.Cursor = Cursor;
-
-});

+ 0 - 272
services/web/public/js/ace/layer/gutter.js

@@ -1,272 +0,0 @@
-/* ***** 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 dom = require("../lib/dom");
-var oop = require("../lib/oop");
-var lang = require("../lib/lang");
-var EventEmitter = require("../lib/event_emitter").EventEmitter;
-
-var Gutter = function(parentEl) {
-    this.element = dom.createElement("div");
-    this.element.className = "ace_layer ace_gutter-layer";
-    parentEl.appendChild(this.element);
-    this.setShowFoldWidgets(this.$showFoldWidgets);
-    
-    this.gutterWidth = 0;
-
-    this.$annotations = [];
-    this.$updateAnnotations = this.$updateAnnotations.bind(this);
-
-    this.$cells = [];
-};
-
-(function() {
-
-    oop.implement(this, EventEmitter);
-
-    this.setSession = function(session) {
-        if (this.session)
-            this.session.removeEventListener("change", this.$updateAnnotations);
-        this.session = session;
-        session.on("change", this.$updateAnnotations);
-    };
-
-    this.addGutterDecoration = function(row, className){
-        if (window.console)
-            console.warn && console.warn("deprecated use session.addGutterDecoration");
-        this.session.addGutterDecoration(row, className);
-    };
-
-    this.removeGutterDecoration = function(row, className){
-        if (window.console)
-            console.warn && console.warn("deprecated use session.removeGutterDecoration");
-        this.session.removeGutterDecoration(row, className);
-    };
-
-    this.setAnnotations = function(annotations) {
-        // iterate over sparse array
-        this.$annotations = [];
-        for (var i = 0; i < annotations.length; i++) {
-            var annotation = annotations[i];
-            var row = annotation.row;
-            var rowInfo = this.$annotations[row];
-            if (!rowInfo)
-                rowInfo = this.$annotations[row] = {text: []};
-           
-            var annoText = annotation.text;
-            annoText = annoText ? lang.escapeHTML(annoText) : annotation.html || "";
-
-            if (rowInfo.text.indexOf(annoText) === -1)
-                rowInfo.text.push(annoText);
-
-            var type = annotation.type;
-            if (type == "error")
-                rowInfo.className = " ace_error";
-            else if (type == "warning" && rowInfo.className != " ace_error")
-                rowInfo.className = " ace_warning";
-            else if (type == "info" && (!rowInfo.className))
-                rowInfo.className = " ace_info";
-        }
-    };
-
-    this.$updateAnnotations = function (e) {
-        if (!this.$annotations.length)
-            return;
-        var delta = e.data;
-        var range = delta.range;
-        var firstRow = range.start.row;
-        var len = range.end.row - firstRow;
-        if (len === 0) {
-            // do nothing
-        } else if (delta.action == "removeText" || delta.action == "removeLines") {
-            this.$annotations.splice(firstRow, len + 1, null);
-        } else {
-            var args = new Array(len + 1);
-            args.unshift(firstRow, 1);
-            this.$annotations.splice.apply(this.$annotations, args);
-        }
-    };
-
-    this.update = function(config) {
-        var firstRow = config.firstRow;
-        var lastRow = config.lastRow;
-        var session = this.session;
-        var fold = session.getNextFoldLine(firstRow);
-        var foldStart = fold ? fold.start.row : Infinity;
-        var foldWidgets = this.$showFoldWidgets && session.foldWidgets;
-        var breakpoints = session.$breakpoints;
-        var decorations = session.$decorations;
-        var firstLineNumber = session.$firstLineNumber;
-        var lastLineNumber = 0;
-        
-        var gutterRenderer = session.gutterRenderer;
-
-        var cell = null;
-        var index = -1;
-        var row = firstRow;
-        while (true) {
-            if (row > foldStart) {
-                row = fold.end.row + 1;
-                fold = session.getNextFoldLine(row, fold);
-                foldStart = fold ? fold.start.row : Infinity;
-            }
-            if (row > lastRow) {
-                while (this.$cells.length > index + 1) {
-                    cell = this.$cells.pop();
-                    this.element.removeChild(cell.element);
-                }
-                break;
-            }
-
-            cell = this.$cells[++index];
-            if (!cell) {
-                cell = {element: null, textNode: null, foldWidget: null};
-                cell.element = dom.createElement("div");
-                cell.textNode = document.createTextNode('');
-                cell.element.appendChild(cell.textNode);
-                this.element.appendChild(cell.element);
-                this.$cells[index] = cell;
-            }
-
-            var className = "ace_gutter-cell ";
-            if (breakpoints[row])
-                className += breakpoints[row];
-            if (decorations[row])
-                className += decorations[row];
-            if (this.$annotations[row])
-                className += this.$annotations[row].className;
-            if (cell.element.className != className)
-                cell.element.className = className;
-
-            var height = session.getRowLength(row) * config.lineHeight + "px";
-            if (height != cell.element.style.height)
-                cell.element.style.height = height;
-
-            if (foldWidgets) {
-                var c = foldWidgets[row];
-                // check if cached value is invalidated and we need to recompute
-                if (c == null)
-                    c = foldWidgets[row] = session.getFoldWidget(row);
-            }
-
-            if (c) {
-                if (!cell.foldWidget) {
-                    cell.foldWidget = dom.createElement("span");
-                    cell.element.appendChild(cell.foldWidget);
-                }
-                var className = "ace_fold-widget ace_" + c;
-                if (c == "start" && row == foldStart && row < fold.end.row)
-                    className += " ace_closed";
-                else
-                    className += " ace_open";
-                if (cell.foldWidget.className != className)
-                    cell.foldWidget.className = className;
-
-                var height = config.lineHeight + "px";
-                if (cell.foldWidget.style.height != height)
-                    cell.foldWidget.style.height = height;
-            } else {
-                if (cell.foldWidget) {
-                    cell.element.removeChild(cell.foldWidget);
-                    cell.foldWidget = null;
-                }
-            }
-            
-            var text = lastLineNumber = gutterRenderer
-                ? gutterRenderer.getText(session, row)
-                : row + firstLineNumber;
-            if (text != cell.textNode.data)
-                cell.textNode.data = text;
-
-            row++;
-        }
-
-        this.element.style.height = config.minHeight + "px";
-
-        if (this.$fixedWidth || session.$useWrapMode)
-            lastLineNumber = session.getLength();
-
-        var gutterWidth = gutterRenderer 
-            ? gutterRenderer.getWidth(session, lastLineNumber, config)
-            : lastLineNumber.toString().length * config.characterWidth;
-        
-        var padding = this.$padding || this.$computePadding();
-        gutterWidth += padding.left + padding.right;
-        if (gutterWidth !== this.gutterWidth && !isNaN(gutterWidth)) {
-            this.gutterWidth = gutterWidth;
-            this.element.style.width = Math.ceil(this.gutterWidth) + "px";
-            this._emit("changeGutterWidth", gutterWidth);
-        }
-    };
-
-    this.$fixedWidth = false;
-    
-    this.$showFoldWidgets = true;
-    this.setShowFoldWidgets = function(show) {
-        if (show)
-            dom.addCssClass(this.element, "ace_folding-enabled");
-        else
-            dom.removeCssClass(this.element, "ace_folding-enabled");
-
-        this.$showFoldWidgets = show;
-        this.$padding = null;
-    };
-    
-    this.getShowFoldWidgets = function() {
-        return this.$showFoldWidgets;
-    };
-
-    this.$computePadding = function() {
-        if (!this.element.firstChild)
-            return {left: 0, right: 0};
-        var style = dom.computedStyle(this.element.firstChild);
-        this.$padding = {};
-        this.$padding.left = parseInt(style.paddingLeft) + 1 || 0;
-        this.$padding.right = parseInt(style.paddingRight) || 0;
-        return this.$padding;
-    };
-
-    this.getRegion = function(point) {
-        var padding = this.$padding || this.$computePadding();
-        var rect = this.element.getBoundingClientRect();
-        if (point.x < padding.left + rect.left)
-            return "markers";
-        if (this.$showFoldWidgets && point.x > rect.right - padding.right)
-            return "foldWidgets";
-    };
-
-}).call(Gutter.prototype);
-
-exports.Gutter = Gutter;
-
-});

+ 0 - 218
services/web/public/js/ace/layer/marker.js

@@ -1,218 +0,0 @@
-/* ***** 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 Range = require("../range").Range;
-var dom = require("../lib/dom");
-
-var Marker = function(parentEl) {
-    this.element = dom.createElement("div");
-    this.element.className = "ace_layer ace_marker-layer";
-    parentEl.appendChild(this.element);
-};
-
-(function() {
-
-    this.$padding = 0;
-
-    this.setPadding = function(padding) {
-        this.$padding = padding;
-    };
-    this.setSession = function(session) {
-        this.session = session;
-    };
-    
-    this.setMarkers = function(markers) {
-        this.markers = markers;
-    };
-
-    this.update = function(config) {
-        var config = config || this.config;
-        if (!config)
-            return;
-
-        this.config = config;
-
-
-        var html = [];
-        for (var key in this.markers) {
-            var marker = this.markers[key];
-
-            if (!marker.range) {
-                marker.update(html, this, this.session, config);
-                continue;
-            }
-
-            var range = marker.range.clipRows(config.firstRow, config.lastRow);
-            if (range.isEmpty()) continue;
-
-            range = range.toScreenRange(this.session);
-            if (marker.renderer) {
-                var top = this.$getTop(range.start.row, config);
-                var left = this.$padding + range.start.column * config.characterWidth;
-                marker.renderer(html, range, left, top, config);
-            } else if (marker.type == "fullLine") {
-                this.drawFullLineMarker(html, range, marker.clazz, config);
-            } else if (marker.type == "screenLine") {
-                this.drawScreenLineMarker(html, range, marker.clazz, config);
-            } else if (range.isMultiLine()) {
-                if (marker.type == "text")
-                    this.drawTextMarker(html, range, marker.clazz, config);
-                else
-                    this.drawMultiLineMarker(html, range, marker.clazz, config);
-            } else {
-                this.drawSingleLineMarker(html, range, marker.clazz + " ace_start", config);
-            }
-        }
-        this.element = dom.setInnerHtml(this.element, html.join(""));
-    };
-
-    this.$getTop = function(row, layerConfig) {
-        return (row - layerConfig.firstRowScreen) * layerConfig.lineHeight;
-    };
-
-    // Draws a marker, which spans a range of text on multiple lines 
-    this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig, extraStyle) {
-        // selection start
-        var row = range.start.row;
-
-        var lineRange = new Range(
-            row, range.start.column,
-            row, this.session.getScreenLastRowColumn(row)
-        );
-        this.drawSingleLineMarker(stringBuilder, lineRange, clazz + " ace_start", layerConfig, 1, extraStyle);
-
-        // selection end
-        row = range.end.row;
-        lineRange = new Range(row, 0, row, range.end.column);
-        this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 0, extraStyle);
-
-        for (row = range.start.row + 1; row < range.end.row; row++) {
-            lineRange.start.row = row;
-            lineRange.end.row = row;
-            lineRange.end.column = this.session.getScreenLastRowColumn(row);
-            this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 1, extraStyle);
-        }
-    };
-
-    // Draws a multi line marker, where lines span the full width
-    this.drawMultiLineMarker = function(stringBuilder, range, clazz, config, extraStyle) {
-        // from selection start to the end of the line
-        var padding = this.$padding;
-        var height = config.lineHeight;
-        var top = this.$getTop(range.start.row, config);
-        var left = padding + range.start.column * config.characterWidth;
-        extraStyle = extraStyle || "";
-
-        stringBuilder.push(
-            "<div class='", clazz, " ace_start' style='",
-            "height:", height, "px;",
-            "right:0;",
-            "top:", top, "px;",
-            "left:", left, "px;", extraStyle, "'></div>"
-        );
-
-        // from start of the last line to the selection end
-        top = this.$getTop(range.end.row, config);
-        var width = range.end.column * config.characterWidth;
-
-        stringBuilder.push(
-            "<div class='", clazz, "' style='",
-            "height:", height, "px;",
-            "width:", width, "px;",
-            "top:", top, "px;",
-            "left:", padding, "px;", extraStyle, "'></div>"
-        );
-
-        // all the complete lines
-        height = (range.end.row - range.start.row - 1) * config.lineHeight;
-        if (height < 0)
-            return;
-        top = this.$getTop(range.start.row + 1, config);
-
-        stringBuilder.push(
-            "<div class='", clazz, "' style='",
-            "height:", height, "px;",
-            "right:0;",
-            "top:", top, "px;",
-            "left:", padding, "px;", extraStyle, "'></div>"
-        );
-    };
-
-    // Draws a marker which covers part or whole width of a single screen line
-    this.drawSingleLineMarker = function(stringBuilder, range, clazz, config, extraLength, extraStyle) {
-        var height = config.lineHeight;
-        var width = (range.end.column + (extraLength || 0) - range.start.column) * config.characterWidth;
-
-        var top = this.$getTop(range.start.row, config);
-        var left = this.$padding + range.start.column * config.characterWidth;
-
-        stringBuilder.push(
-            "<div class='", clazz, "' style='",
-            "height:", height, "px;",
-            "width:", width, "px;",
-            "top:", top, "px;",
-            "left:", left, "px;", extraStyle || "", "'></div>"
-        );
-    };
-
-    this.drawFullLineMarker = function(stringBuilder, range, clazz, config, extraStyle) {
-        var top = this.$getTop(range.start.row, config);
-        var height = config.lineHeight;
-        if (range.start.row != range.end.row)
-            height += this.$getTop(range.end.row, config) - top;
-
-        stringBuilder.push(
-            "<div class='", clazz, "' style='",
-            "height:", height, "px;",
-            "top:", top, "px;",
-            "left:0;right:0;", extraStyle || "", "'></div>"
-        );
-    };
-    
-    this.drawScreenLineMarker = function(stringBuilder, range, clazz, config, extraStyle) {
-        var top = this.$getTop(range.start.row, config);
-        var height = config.lineHeight;
-
-        stringBuilder.push(
-            "<div class='", clazz, "' style='",
-            "height:", height, "px;",
-            "top:", top, "px;",
-            "left:0;right:0;", extraStyle || "", "'></div>"
-        );
-    };
-
-}).call(Marker.prototype);
-
-exports.Marker = Marker;
-
-});

+ 0 - 667
services/web/public/js/ace/layer/text.js

@@ -1,667 +0,0 @@
-/* ***** 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 oop = require("../lib/oop");
-var dom = require("../lib/dom");
-var lang = require("../lib/lang");
-var useragent = require("../lib/useragent");
-var EventEmitter = require("../lib/event_emitter").EventEmitter;
-
-var Text = function(parentEl) {
-    this.element = dom.createElement("div");
-    this.element.className = "ace_layer ace_text-layer";
-    parentEl.appendChild(this.element);
-
-    this.$characterSize = {width: 0, height: 0};
-    this.checkForSizeChanges();
-    this.$pollSizeChanges();
-};
-
-(function() {
-
-    oop.implement(this, EventEmitter);
-
-    this.EOF_CHAR = "\xB6"; //"&para;";
-    this.EOL_CHAR = "\xAC"; //"&not;";
-    this.TAB_CHAR = "\u2192"; //"&rarr;" "\u21E5";
-    this.SPACE_CHAR = "\xB7"; //"&middot;";
-    this.$padding = 0;
-
-    this.setPadding = function(padding) {
-        this.$padding = padding;
-        this.element.style.padding = "0 " + padding + "px";
-    };
-
-    this.getLineHeight = function() {
-        return this.$characterSize.height || 0;
-    };
-
-    this.getCharacterWidth = function() {
-        return this.$characterSize.width || 0;
-    };
-
-    this.checkForSizeChanges = function() {
-        var size = this.$measureSizes();
-        if (size && (this.$characterSize.width !== size.width || this.$characterSize.height !== size.height)) {
-            this.$measureNode.style.fontWeight = "bold";
-            var boldSize = this.$measureSizes();
-            this.$measureNode.style.fontWeight = "";
-            this.$characterSize = size;
-            this.allowBoldFonts = boldSize && boldSize.width === size.width && boldSize.height === size.height;
-            this._emit("changeCharacterSize", {data: size});
-        }
-    };
-
-    this.$pollSizeChanges = function() {
-        var self = this;
-        this.$pollSizeChangesTimer = setInterval(function() {
-            self.checkForSizeChanges();
-        }, 500);
-    };
-
-    this.$fontStyles = {
-        fontFamily : 1,
-        fontSize : 1,
-        fontWeight : 1,
-        fontStyle : 1,
-        lineHeight : 1
-    };
-
-    this.$measureSizes = useragent.isIE || useragent.isOldGecko ? function() {
-        var n = 1000;
-        if (!this.$measureNode) {
-            var measureNode = this.$measureNode = dom.createElement("div");
-            var style = measureNode.style;
-
-            style.width = style.height = "auto";
-            style.left = style.top = (-n * 40)  + "px";
-
-            style.visibility = "hidden";
-            style.position = "fixed";
-            style.overflow = "visible";
-            style.whiteSpace = "nowrap";
-
-            // in FF 3.6 monospace fonts can have a fixed sub pixel width.
-            // that's why we have to measure many characters
-            // Note: characterWidth can be a float!
-            measureNode.innerHTML = lang.stringRepeat("Xy", n);
-
-            if (this.element.ownerDocument.body) {
-                this.element.ownerDocument.body.appendChild(measureNode);
-            } else {
-                var container = this.element.parentNode;
-                while (!dom.hasCssClass(container, "ace_editor"))
-                    container = container.parentNode;
-                container.appendChild(measureNode);
-            }
-        }
-
-        // Size and width can be null if the editor is not visible or
-        // detached from the document
-        if (!this.element.offsetWidth)
-            return null;
-
-        var style = this.$measureNode.style;
-        var computedStyle = dom.computedStyle(this.element);
-        for (var prop in this.$fontStyles)
-            style[prop] = computedStyle[prop];
-
-        var size = {
-            height: this.$measureNode.offsetHeight,
-            width: this.$measureNode.offsetWidth / (n * 2)
-        };
-
-        // Size and width can be null if the editor is not visible or
-        // detached from the document
-        if (size.width == 0 || size.height == 0)
-            return null;
-
-        return size;
-    }
-    : function() {
-        if (!this.$measureNode) {
-            var measureNode = this.$measureNode = dom.createElement("div");
-            var style = measureNode.style;
-
-            style.width = style.height = "auto";
-            style.left = style.top = -100 + "px";
-
-            style.visibility = "hidden";
-            style.position = "fixed";
-            style.overflow = "visible";
-            style.whiteSpace = "nowrap";
-
-            // fixes fractional fixed-width fonts; see http://git.io/CavZNw
-            measureNode.innerHTML = lang.stringRepeat("X", 100);
-
-            var container = this.element.parentNode;
-            while (container && !dom.hasCssClass(container, "ace_editor"))
-                container = container.parentNode;
-
-            if (!container)
-                return this.$measureNode = null;
-
-            container.appendChild(measureNode);
-        }
-
-        var rect = this.$measureNode.getBoundingClientRect();
-
-        var size = {
-            height: rect.height,
-            width: rect.width / 100
-        };
-
-        // Size and width can be null if the editor is not visible or
-        // detached from the document
-        if (size.width == 0 || size.height == 0)
-            return null;
-
-        return size;
-    };
-
-    this.setSession = function(session) {
-        this.session = session;
-        this.$computeTabString();
-    };
-
-    this.showInvisibles = false;
-    this.setShowInvisibles = function(showInvisibles) {
-        if (this.showInvisibles == showInvisibles)
-            return false;
-
-        this.showInvisibles = showInvisibles;
-        this.$computeTabString();
-        return true;
-    };
-
-    this.displayIndentGuides = true;
-    this.setDisplayIndentGuides = function(display) {
-        if (this.displayIndentGuides == display)
-            return false;
-
-        this.displayIndentGuides = display;
-        this.$computeTabString();
-        return true;
-    };
-
-    this.$tabStrings = [];
-    this.onChangeTabSize =
-    this.$computeTabString = function() {
-        var tabSize = this.session.getTabSize();
-        this.tabSize = tabSize;
-        var tabStr = this.$tabStrings = [0];
-        for (var i = 1; i < tabSize + 1; i++) {
-            if (this.showInvisibles) {
-                tabStr.push("<span class='ace_invisible'>"
-                    + this.TAB_CHAR
-                    + lang.stringRepeat("\xa0", i - 1)
-                    + "</span>");
-            } else {
-                tabStr.push(lang.stringRepeat("\xa0", i));
-            }
-        }
-        if (this.displayIndentGuides) {
-            this.$indentGuideRe =  /\s\S| \t|\t |\s$/;
-            var className = "ace_indent-guide";
-            if (this.showInvisibles) {
-                className += " ace_invisible";
-                var spaceContent = lang.stringRepeat(this.SPACE_CHAR, this.tabSize);
-                var tabContent = this.TAB_CHAR + lang.stringRepeat("\xa0", this.tabSize - 1);
-            } else{
-                var spaceContent = lang.stringRepeat("\xa0", this.tabSize);
-                var tabContent = spaceContent;
-            }
-
-            this.$tabStrings[" "] = "<span class='" + className + "'>" + spaceContent + "</span>";
-            this.$tabStrings["\t"] = "<span class='" + className + "'>" + tabContent + "</span>";
-        }
-    };
-
-    this.updateLines = function(config, firstRow, lastRow) {
-        // Due to wrap line changes there can be new lines if e.g.
-        // the line to updated wrapped in the meantime.
-        if (this.config.lastRow != config.lastRow ||
-            this.config.firstRow != config.firstRow) {
-            this.scrollLines(config);
-        }
-        this.config = config;
-
-        var first = Math.max(firstRow, config.firstRow);
-        var last = Math.min(lastRow, config.lastRow);
-
-        var lineElements = this.element.childNodes;
-        var lineElementsIdx = 0;
-
-        for (var row = config.firstRow; row < first; row++) {
-            var foldLine = this.session.getFoldLine(row);
-            if (foldLine) {
-                if (foldLine.containsRow(first)) {
-                    first = foldLine.start.row;
-                    break;
-                } else {
-                    row = foldLine.end.row;
-                }
-            }
-            lineElementsIdx ++;
-        }
-
-        var row = first;
-        var foldLine = this.session.getNextFoldLine(row);
-        var foldStart = foldLine ? foldLine.start.row : Infinity;
-
-        while (true) {
-            if (row > foldStart) {
-                row = foldLine.end.row+1;
-                foldLine = this.session.getNextFoldLine(row, foldLine);
-                foldStart = foldLine ? foldLine.start.row :Infinity;
-            }
-            if (row > last)
-                break;
-
-            var lineElement = lineElements[lineElementsIdx++];
-            if (lineElement) {
-                var html = [];
-                this.$renderLine(
-                    html, row, !this.$useLineGroups(), row == foldStart ? foldLine : false
-                );
-                lineElement.style.height = config.lineHeight * this.session.getRowLength(row) + "px";
-                dom.setInnerHtml(lineElement, html.join(""));
-            }
-            row++;
-        }
-    };
-
-    this.scrollLines = function(config) {
-        var oldConfig = this.config;
-        this.config = config;
-
-        if (!oldConfig || oldConfig.lastRow < config.firstRow)
-            return this.update(config);
-
-        if (config.lastRow < oldConfig.firstRow)
-            return this.update(config);
-
-        var el = this.element;
-        if (oldConfig.firstRow < config.firstRow)
-            for (var row=this.session.getFoldedRowCount(oldConfig.firstRow, config.firstRow - 1); row>0; row--)
-                el.removeChild(el.firstChild);
-
-        if (oldConfig.lastRow > config.lastRow)
-            for (var row=this.session.getFoldedRowCount(config.lastRow + 1, oldConfig.lastRow); row>0; row--)
-                el.removeChild(el.lastChild);
-
-        if (config.firstRow < oldConfig.firstRow) {
-            var fragment = this.$renderLinesFragment(config, config.firstRow, oldConfig.firstRow - 1);
-            if (el.firstChild)
-                el.insertBefore(fragment, el.firstChild);
-            else
-                el.appendChild(fragment);
-        }
-
-        if (config.lastRow > oldConfig.lastRow) {
-            var fragment = this.$renderLinesFragment(config, oldConfig.lastRow + 1, config.lastRow);
-            el.appendChild(fragment);
-        }
-    };
-
-    this.$renderLinesFragment = function(config, firstRow, lastRow) {
-        var fragment = this.element.ownerDocument.createDocumentFragment();
-        var row = firstRow;
-        var foldLine = this.session.getNextFoldLine(row);
-        var foldStart = foldLine ? foldLine.start.row : Infinity;
-
-        while (true) {
-            if (row > foldStart) {
-                row = foldLine.end.row+1;
-                foldLine = this.session.getNextFoldLine(row, foldLine);
-                foldStart = foldLine ? foldLine.start.row : Infinity;
-            }
-            if (row > lastRow)
-                break;
-
-            var container = dom.createElement("div");
-
-            var html = [];
-            // Get the tokens per line as there might be some lines in between
-            // beeing folded.
-            this.$renderLine(html, row, false, row == foldStart ? foldLine : false);
-
-            // don't use setInnerHtml since we are working with an empty DIV
-            container.innerHTML = html.join("");
-            if (this.$useLineGroups()) {
-                container.className = 'ace_line_group';
-                fragment.appendChild(container);
-                container.style.height = config.lineHeight * this.session.getRowLength(row) + "px";
-
-            } else {
-                var lines = container.childNodes
-                while(lines.length)
-                    fragment.appendChild(lines[0]);
-            }
-
-            row++;
-        }
-        return fragment;
-    };
-
-    this.update = function(config) {
-        this.config = config;
-
-        var html = [];
-        var firstRow = config.firstRow, lastRow = config.lastRow;
-
-        var row = firstRow;
-        var foldLine = this.session.getNextFoldLine(row);
-        var foldStart = foldLine ? foldLine.start.row : Infinity;
-
-        while (true) {
-            if (row > foldStart) {
-                row = foldLine.end.row+1;
-                foldLine = this.session.getNextFoldLine(row, foldLine);
-                foldStart = foldLine ? foldLine.start.row :Infinity;
-            }
-            if (row > lastRow)
-                break;
-
-            if (this.$useLineGroups())
-                html.push("<div class='ace_line_group' style='height:", config.lineHeight*this.session.getRowLength(row), "px'>")
-
-            this.$renderLine(html, row, false, row == foldStart ? foldLine : false);
-
-            if (this.$useLineGroups())
-                html.push("</div>"); // end the line group
-
-            row++;
-        }
-        this.element = dom.setInnerHtml(this.element, html.join(""));
-    };
-
-    this.$textToken = {
-        "text": true,
-        "rparen": true,
-        "lparen": true
-    };
-
-    this.$renderToken = function(stringBuilder, screenColumn, token, value) {
-        var self = this;
-        var replaceReg = /\t|&|<|( +)|([\x00-\x1f\x80-\xa0\u1680\u180E\u2000-\u200f\u2028\u2029\u202F\u205F\u3000\uFEFF])|[\u1100-\u115F\u11A3-\u11A7\u11FA-\u11FF\u2329-\u232A\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3000-\u303E\u3041-\u3096\u3099-\u30FF\u3105-\u312D\u3131-\u318E\u3190-\u31BA\u31C0-\u31E3\u31F0-\u321E\u3220-\u3247\u3250-\u32FE\u3300-\u4DBF\u4E00-\uA48C\uA490-\uA4C6\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFF01-\uFF60\uFFE0-\uFFE6]/g;
-        var replaceFunc = function(c, a, b, tabIdx, idx4) {
-            if (a) {
-                return self.showInvisibles ?
-                    "<span class='ace_invisible'>" + lang.stringRepeat(self.SPACE_CHAR, c.length) + "</span>" :
-                    lang.stringRepeat("\xa0", c.length);
-            } else if (c == "&") {
-                return "&#38;";
-            } else if (c == "<") {
-                return "&#60;";
-            } else if (c == "\t") {
-                var tabSize = self.session.getScreenTabSize(screenColumn + tabIdx);
-                screenColumn += tabSize - 1;
-                return self.$tabStrings[tabSize];
-            } else if (c == "\u3000") {
-                // U+3000 is both invisible AND full-width, so must be handled uniquely
-                var classToUse = self.showInvisibles ? "ace_cjk ace_invisible" : "ace_cjk";
-                var space = self.showInvisibles ? self.SPACE_CHAR : "";
-                screenColumn += 1;
-                return "<span class='" + classToUse + "' style='width:" +
-                    (self.config.characterWidth * 2) +
-                    "px'>" + space + "</span>";
-            } else if (b) {
-                return "<span class='ace_invisible ace_invalid'>" + self.SPACE_CHAR + "</span>";
-            } else {
-                screenColumn += 1;
-                return "<span class='ace_cjk' style='width:" +
-                    (self.config.characterWidth * 2) +
-                    "px'>" + c + "</span>";
-            }
-        };
-
-        var output = value.replace(replaceReg, replaceFunc);
-
-        if (!this.$textToken[token.type]) {
-            var classes = "ace_" + token.type.replace(/\./g, " ace_");
-            var style = "";
-            if (token.type == "fold")
-                style = " style='width:" + (token.value.length * this.config.characterWidth) + "px;' ";
-            stringBuilder.push("<span class='", classes, "'", style, ">", output, "</span>");
-        }
-        else {
-            stringBuilder.push(output);
-        }
-        return screenColumn + value.length;
-    };
-
-    this.renderIndentGuide = function(stringBuilder, value, max) {
-        var cols = value.search(this.$indentGuideRe);
-        if (cols <= 0 || cols >= max)
-            return value;
-        if (value[0] == " ") {
-            cols -= cols % this.tabSize;
-            stringBuilder.push(lang.stringRepeat(this.$tabStrings[" "], cols/this.tabSize));
-            return value.substr(cols);
-        } else if (value[0] == "\t") {
-            stringBuilder.push(lang.stringRepeat(this.$tabStrings["\t"], cols));
-            return value.substr(cols);
-        }
-        return value;
-    };
-
-    this.$renderWrappedLine = function(stringBuilder, tokens, splits, onlyContents) {
-        var chars = 0;
-        var split = 0;
-        var splitChars = splits[0];
-        var screenColumn = 0;
-
-        for (var i = 0; i < tokens.length; i++) {
-            var token = tokens[i];
-            var value = token.value;
-            if (i == 0 && this.displayIndentGuides) {
-                chars = value.length;
-                value = this.renderIndentGuide(stringBuilder, value, splitChars);
-                if (!value)
-                    continue;
-                chars -= value.length;
-            }
-
-            if (chars + value.length < splitChars) {
-                screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value);
-                chars += value.length;
-            } else {
-                while (chars + value.length >= splitChars) {
-                    screenColumn = this.$renderToken(
-                        stringBuilder, screenColumn,
-                        token, value.substring(0, splitChars - chars)
-                    );
-                    value = value.substring(splitChars - chars);
-                    chars = splitChars;
-
-                    if (!onlyContents) {
-                        stringBuilder.push("</div>",
-                            "<div class='ace_line' style='height:",
-                            this.config.lineHeight, "px'>"
-                        );
-                    }
-
-                    split ++;
-                    screenColumn = 0;
-                    splitChars = splits[split] || Number.MAX_VALUE;
-                }
-                if (value.length != 0) {
-                    chars += value.length;
-                    screenColumn = this.$renderToken(
-                        stringBuilder, screenColumn, token, value
-                    );
-                }
-            }
-        }
-    };
-
-    this.$renderSimpleLine = function(stringBuilder, tokens) {
-        var screenColumn = 0;
-        var token = tokens[0];
-        var value = token.value;
-        if (this.displayIndentGuides)
-            value = this.renderIndentGuide(stringBuilder, value);
-        if (value)
-            screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value);
-        for (var i = 1; i < tokens.length; i++) {
-            token = tokens[i];
-            value = token.value;
-            screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value);
-        }
-    };
-
-    // row is either first row of foldline or not in fold
-    this.$renderLine = function(stringBuilder, row, onlyContents, foldLine) {
-        if (!foldLine && foldLine != false)
-            foldLine = this.session.getFoldLine(row);
-
-        if (foldLine)
-            var tokens = this.$getFoldLineTokens(row, foldLine);
-        else
-            var tokens = this.session.getTokens(row);
-
-
-        if (!onlyContents) {
-            stringBuilder.push(
-                "<div class='ace_line' style='height:", 
-                    this.config.lineHeight * (
-                        this.$useLineGroups() ? 1 :this.session.getRowLength(row)
-                    ), "px'>"
-            );
-        }
-
-        if (tokens.length) {
-            var splits = this.session.getRowSplitData(row);
-            if (splits && splits.length)
-                this.$renderWrappedLine(stringBuilder, tokens, splits, onlyContents);
-            else
-                this.$renderSimpleLine(stringBuilder, tokens);
-        }
-
-        if (this.showInvisibles) {
-            if (foldLine)
-                row = foldLine.end.row
-
-            stringBuilder.push(
-                "<span class='ace_invisible'>",
-                row == this.session.getLength() - 1 ? this.EOF_CHAR : this.EOL_CHAR,
-                "</span>"
-            );
-        }
-        if (!onlyContents)
-            stringBuilder.push("</div>");
-    };
-
-    this.$getFoldLineTokens = function(row, foldLine) {
-        var session = this.session;
-        var renderTokens = [];
-
-        function addTokens(tokens, from, to) {
-            var idx = 0, col = 0;
-            while ((col + tokens[idx].value.length) < from) {
-                col += tokens[idx].value.length;
-                idx++;
-
-                if (idx == tokens.length)
-                    return;
-            }
-            if (col != from) {
-                var value = tokens[idx].value.substring(from - col);
-                // Check if the token value is longer then the from...to spacing.
-                if (value.length > (to - from))
-                    value = value.substring(0, to - from);
-
-                renderTokens.push({
-                    type: tokens[idx].type,
-                    value: value
-                });
-
-                col = from + value.length;
-                idx += 1;
-            }
-
-            while (col < to && idx < tokens.length) {
-                var value = tokens[idx].value;
-                if (value.length + col > to) {
-                    renderTokens.push({
-                        type: tokens[idx].type,
-                        value: value.substring(0, to - col)
-                    });
-                } else
-                    renderTokens.push(tokens[idx]);
-                col += value.length;
-                idx += 1;
-            }
-        }
-
-        var tokens = session.getTokens(row);
-        foldLine.walk(function(placeholder, row, column, lastColumn, isNewRow) {
-            if (placeholder != null) {
-                renderTokens.push({
-                    type: "fold",
-                    value: placeholder
-                });
-            } else {
-                if (isNewRow)
-                    tokens = session.getTokens(row);
-
-                if (tokens.length)
-                    addTokens(tokens, lastColumn, column);
-            }
-        }, foldLine.end.row, this.session.getLine(foldLine.end.row).length);
-
-        return renderTokens;
-    };
-
-    this.$useLineGroups = function() {
-        // For the updateLines function to work correctly, it's important that the
-        // child nodes of this.element correspond on a 1-to-1 basis to rows in the
-        // document (as distinct from lines on the screen). For sessions that are
-        // wrapped, this means we need to add a layer to the node hierarchy (tagged
-        // with the class name ace_line_group).
-        return this.session.getUseWrapMode();
-    };
-
-    this.destroy = function() {
-        clearInterval(this.$pollSizeChangesTimer);
-        if (this.$measureNode)
-            this.$measureNode.parentNode.removeChild(this.$measureNode);
-        delete this.$measureNode;
-    };
-
-}).call(Text.prototype);
-
-exports.Text = Text;
-
-});

+ 0 - 126
services/web/public/js/ace/layer/text_test.js

@@ -1,126 +0,0 @@
-/* ***** 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");
-    require("../test/mockdom");
-}
-
-define(function(require, exports, module) {
-"use strict";
-
-var assert = require("../test/assertions");
-var EditSession = require("../edit_session").EditSession;
-var TextLayer = require("./text").Text;
-var JavaScriptMode = require("../mode/javascript").Mode;
-
-module.exports = {
-
-    setUp: function(next) {
-        this.session = new EditSession("");
-        this.session.setMode(new JavaScriptMode());
-        this.textLayer = new TextLayer(document.createElement("div"));
-        this.textLayer.setSession(this.session);
-        this.textLayer.config = {
-            characterWidth: 10,
-            lineHeight: 20
-        };
-        next()
-    },
-
-    "test: render line with hard tabs should render the same as lines with soft tabs" : function() {
-        this.session.setValue("a\ta\ta\t\na   a   a   \n");
-        this.textLayer.$computeTabString();
-        
-        // row with hard tabs
-        var stringBuilder = [];
-        this.textLayer.$renderLine(stringBuilder, 0);
-        
-        // row with soft tabs
-        var stringBuilder2 = [];
-        this.textLayer.$renderLine(stringBuilder2, 1);
-        assert.equal(stringBuilder.join(""), stringBuilder2.join(""));
-    },
-    
-    "test rendering width of ideographic space (U+3000)" : function() {
-        this.session.setValue("\u3000");
-        
-        var stringBuilder = [];
-        this.textLayer.$renderLine(stringBuilder, 0, true);
-        assert.equal(stringBuilder.join(""), "<span class='ace_cjk' style='width:20px'></span>");
-
-        this.textLayer.setShowInvisibles(true);
-        var stringBuilder = [];
-        this.textLayer.$renderLine(stringBuilder, 0, true);
-        assert.equal(
-            stringBuilder.join(""),
-            "<span class='ace_cjk ace_invisible' style='width:20px'>" + this.textLayer.SPACE_CHAR + "</span>"
-            + "<span class='ace_invisible'>\xB6</span>"
-        );
-    },
-    
-    "test rendering of indent guides" : function() {       
-        var textLayer = this.textLayer
-        var EOL = "<span class='ace_invisible'>" + textLayer.EOL_CHAR + "</span>";
-        var SPACE = function(i) {return Array(i+1).join("\xa0")}
-        var DOT = function(i) {return Array(i+1).join(textLayer.SPACE_CHAR)}
-        var TAB = function(i) {return textLayer.TAB_CHAR + SPACE(i-1)}
-        function testRender(results) {
-            for (var i = results.length; i--; ) {
-                var stringBuilder = [];
-                textLayer.$renderLine(stringBuilder, i, true);
-                assert.equal(stringBuilder.join(""), results[i]);
-            }
-        }
-        
-        this.session.setValue("      \n\t\tf\n   ");
-        testRender([
-            "<span class='ace_indent-guide'>" + SPACE(4) + "</span>" + SPACE(2),
-            "<span class='ace_indent-guide'>" + SPACE(4) + "</span>" + SPACE(4) + "<span class='ace_identifier'>f</span>",
-            SPACE(3)
-        ]);
-        this.textLayer.setShowInvisibles(true);
-        testRender([
-            "<span class='ace_indent-guide ace_invisible'>" + DOT(4) + "</span><span class='ace_invisible'>" + DOT(2) + "</span>" + EOL,
-            "<span class='ace_indent-guide ace_invisible'>" + TAB(4) + "</span><span class='ace_invisible'>" + TAB(4) + "</span><span class='ace_identifier'>f</span>" + EOL,
-        ]);
-        this.textLayer.setDisplayIndentGuides(false);
-        testRender([
-            "<span class='ace_invisible'>" + DOT(6) + "</span>" + EOL,
-            "<span class='ace_invisible'>" + TAB(4) + "</span><span class='ace_invisible'>" + TAB(4) + "</span><span class='ace_identifier'>f</span>" + EOL
-        ]);
-    }
-};
-
-});
-
-if (typeof module !== "undefined" && module === require.main) {
-    require("asyncjs").test.testcase(module.exports).exec()
-}

+ 0 - 283
services/web/public/js/ace/lib/dom.js

@@ -1,283 +0,0 @@
-/* ***** 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";
-
-if (typeof document == "undefined")
-    return;
-
-var XHTML_NS = "http://www.w3.org/1999/xhtml";
-
-exports.getDocumentHead = function(doc) {
-    if (!doc)
-        doc = document;
-    return doc.head || doc.getElementsByTagName("head")[0] || doc.documentElement;
-}
-
-exports.createElement = function(tag, ns) {
-    return document.createElementNS ?
-           document.createElementNS(ns || XHTML_NS, tag) :
-           document.createElement(tag);
-};
-
-exports.hasCssClass = function(el, name) {
-    var classes = el.className.split(/\s+/g);
-    return classes.indexOf(name) !== -1;
-};
-
-/*
-* Add a CSS class to the list of classes on the given node
-*/
-exports.addCssClass = function(el, name) {
-    if (!exports.hasCssClass(el, name)) {
-        el.className += " " + name;
-    }
-};
-
-/*
-* Remove a CSS class from the list of classes on the given node
-*/
-exports.removeCssClass = function(el, name) {
-    var classes = el.className.split(/\s+/g);
-    while (true) {
-        var index = classes.indexOf(name);
-        if (index == -1) {
-            break;
-        }
-        classes.splice(index, 1);
-    }
-    el.className = classes.join(" ");
-};
-
-exports.toggleCssClass = function(el, name) {
-    var classes = el.className.split(/\s+/g), add = true;
-    while (true) {
-        var index = classes.indexOf(name);
-        if (index == -1) {
-            break;
-        }
-        add = false;
-        classes.splice(index, 1);
-    }
-    if(add)
-        classes.push(name);
-
-    el.className = classes.join(" ");
-    return add;
-};
-
-/*
- * Add or remove a CSS class from the list of classes on the given node
- * depending on the value of <tt>include</tt>
- */
-exports.setCssClass = function(node, className, include) {
-    if (include) {
-        exports.addCssClass(node, className);
-    } else {
-        exports.removeCssClass(node, className);
-    }
-};
-
-exports.hasCssString = function(id, doc) {
-    var index = 0, sheets;
-    doc = doc || document;
-
-    if (doc.createStyleSheet && (sheets = doc.styleSheets)) {
-        while (index < sheets.length)
-            if (sheets[index++].owningElement.id === id) return true;
-    } else if ((sheets = doc.getElementsByTagName("style"))) {
-        while (index < sheets.length)
-            if (sheets[index++].id === id) return true;
-    }
-
-    return false;
-};
-
-exports.importCssString = function importCssString(cssText, id, doc) {
-    doc = doc || document;
-    // If style is already imported return immediately.
-    if (id && exports.hasCssString(id, doc))
-        return null;
-    
-    var style;
-    
-    if (doc.createStyleSheet) {
-        style = doc.createStyleSheet();
-        style.cssText = cssText;
-        if (id)
-            style.owningElement.id = id;
-    } else {
-        style = doc.createElementNS
-            ? doc.createElementNS(XHTML_NS, "style")
-            : doc.createElement("style");
-
-        style.appendChild(doc.createTextNode(cssText));
-        if (id)
-            style.id = id;
-
-        exports.getDocumentHead(doc).appendChild(style);
-    }
-};
-
-exports.importCssStylsheet = function(uri, doc) {
-    if (doc.createStyleSheet) {
-        doc.createStyleSheet(uri);
-    } else {
-        var link = exports.createElement('link');
-        link.rel = 'stylesheet';
-        link.href = uri;
-
-        exports.getDocumentHead(doc).appendChild(link);
-    }
-};
-
-exports.getInnerWidth = function(element) {
-    return (
-        parseInt(exports.computedStyle(element, "paddingLeft"), 10) +
-        parseInt(exports.computedStyle(element, "paddingRight"), 10) + 
-        element.clientWidth
-    );
-};
-
-exports.getInnerHeight = function(element) {
-    return (
-        parseInt(exports.computedStyle(element, "paddingTop"), 10) +
-        parseInt(exports.computedStyle(element, "paddingBottom"), 10) +
-        element.clientHeight
-    );
-};
-
-if (window.pageYOffset !== undefined) {
-    exports.getPageScrollTop = function() {
-        return window.pageYOffset;
-    };
-
-    exports.getPageScrollLeft = function() {
-        return window.pageXOffset;
-    };
-}
-else {
-    exports.getPageScrollTop = function() {
-        return document.body.scrollTop;
-    };
-
-    exports.getPageScrollLeft = function() {
-        return document.body.scrollLeft;
-    };
-}
-
-if (window.getComputedStyle)
-    exports.computedStyle = function(element, style) {
-        if (style)
-            return (window.getComputedStyle(element, "") || {})[style] || "";
-        return window.getComputedStyle(element, "") || {};
-    };
-else
-    exports.computedStyle = function(element, style) {
-        if (style)
-            return element.currentStyle[style];
-        return element.currentStyle;
-    };
-
-exports.scrollbarWidth = function(document) {
-    var inner = exports.createElement("ace_inner");
-    inner.style.width = "100%";
-    inner.style.minWidth = "0px";
-    inner.style.height = "200px";
-    inner.style.display = "block";
-
-    var outer = exports.createElement("ace_outer");
-    var style = outer.style;
-
-    style.position = "absolute";
-    style.left = "-10000px";
-    style.overflow = "hidden";
-    style.width = "200px";
-    style.minWidth = "0px";
-    style.height = "150px";
-    style.display = "block";
-
-    outer.appendChild(inner);
-
-    var body = document.documentElement;
-    body.appendChild(outer);
-
-    var noScrollbar = inner.offsetWidth;
-
-    style.overflow = "scroll";
-    var withScrollbar = inner.offsetWidth;
-
-    if (noScrollbar == withScrollbar) {
-        withScrollbar = outer.clientWidth;
-    }
-
-    body.removeChild(outer);
-
-    return noScrollbar-withScrollbar;
-};
-
-/*
- * Optimized set innerHTML. This is faster than plain innerHTML if the element
- * already contains a lot of child elements.
- *
- * See http://blog.stevenlevithan.com/archives/faster-than-innerhtml for details
- */
-exports.setInnerHtml = function(el, innerHtml) {
-    var element = el.cloneNode(false);//document.createElement("div");
-    element.innerHTML = innerHtml;
-    el.parentNode.replaceChild(element, el);
-    return element;
-};
-
-if ("textContent" in document.documentElement) {
-    exports.setInnerText = function(el, innerText) {
-        el.textContent = innerText;
-    };
-
-    exports.getInnerText = function(el) {
-        return el.textContent;
-    };
-}
-else {
-    exports.setInnerText = function(el, innerText) {
-        el.innerText = innerText;
-    };
-
-    exports.getInnerText = function(el) {
-        return el.innerText;
-    };
-}
-
-exports.getParentWindow = function(document) {
-    return document.defaultView || document.parentWindow;
-};
-
-});

Некоторые файлы не были показаны из-за большого количества измененных файлов