15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2012 Google Inc. All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions are
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * met:
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions of source code must retain the above copyright
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions in binary form must reproduce the above
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * in the documentation and/or other materials provided with the
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distribution.
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Neither the name of Google Inc. nor the names of its
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * contributors may be used to endorse or promote products derived from
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this software without specific prior written permission.
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)importScript("cm/codemirror.js");
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)importScript("cm/css.js");
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)importScript("cm/javascript.js");
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)importScript("cm/xml.js");
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)importScript("cm/htmlmixed.js");
36591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
37926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)importScript("cm/matchbrackets.js");
38926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)importScript("cm/closebrackets.js");
3953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)importScript("cm/markselection.js");
405267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)importScript("cm/comment.js");
415267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)importScript("cm/overlay.js");
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
43591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochimportScript("cm/htmlembedded.js");
44591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochimportScript("cm/clike.js");
45591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochimportScript("cm/coffeescript.js");
46591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochimportScript("cm/php.js");
47591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochimportScript("cm/python.js");
48591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochimportScript("cm/shell.js");
49591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @extends {WebInspector.View}
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @implements {WebInspector.TextEditor}
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {?string} url
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {WebInspector.TextEditorDelegate} delegate
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WebInspector.CodeMirrorTextEditor = function(url, delegate)
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    WebInspector.View.call(this);
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._delegate = delegate;
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._url = url;
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
63926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.registerRequiredCSS("cm/codemirror.css");
64926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.registerRequiredCSS("cm/cmdevtools.css");
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._codeMirror = window.CodeMirror(this.element, {
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        lineNumbers: true,
6853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        gutters: ["CodeMirror-linenumbers"],
69926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        matchBrackets: true,
7053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        smartIndent: false,
7153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        styleSelectedText: true,
7253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        electricChars: false,
73e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        autoCloseBrackets: { explode: false }
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    });
755267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    this._codeMirror._codeMirrorTextEditor = this;
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
77591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    CodeMirror.keyMap["devtools-common"] = {
78591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Left": "goCharLeft",
79591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Right": "goCharRight",
80591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Up": "goLineUp",
81591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Down": "goLineDown",
82591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "End": "goLineEnd",
83591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Home": "goLineStartSmart",
84591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "PageUp": "goPageUp",
85591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "PageDown": "goPageDown",
86591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Delete": "delCharAfter",
87591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Backspace": "delCharBefore",
88591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Tab": "defaultTab",
89591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Shift-Tab": "indentLess",
90591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Enter": "smartNewlineAndIndent",
91591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Ctrl-Space": "autocomplete"
92591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    };
93591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
94591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    CodeMirror.keyMap["devtools-pc"] = {
95591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Ctrl-A": "selectAll",
967757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        "Ctrl-Z": "undoAndReveal",
977757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        "Shift-Ctrl-Z": "redoAndReveal",
98591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Ctrl-Y": "redo",
99591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Ctrl-Home": "goDocStart",
100591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Ctrl-Up": "goDocStart",
101591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Ctrl-End": "goDocEnd",
102591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Ctrl-Down": "goDocEnd",
103591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Ctrl-Left": "goGroupLeft",
104591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Ctrl-Right": "goGroupRight",
105591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Alt-Left": "goLineStart",
106591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Alt-Right": "goLineEnd",
107591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Ctrl-Backspace": "delGroupBefore",
108591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Ctrl-Delete": "delGroupAfter",
109591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Ctrl-/": "toggleComment",
110591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        fallthrough: "devtools-common"
111591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    };
112591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
113591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    CodeMirror.keyMap["devtools-mac"] = {
114591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Cmd-A" : "selectAll",
1157757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        "Cmd-Z" : "undoAndReveal",
1167757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        "Shift-Cmd-Z": "redoAndReveal",
117591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Cmd-Up": "goDocStart",
118591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Cmd-Down": "goDocEnd",
119591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Alt-Left": "goGroupLeft",
120591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Alt-Right": "goGroupRight",
121e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        "Cmd-Left": "goLineStartSmart",
122591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Cmd-Right": "goLineEnd",
123591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Alt-Backspace": "delGroupBefore",
124591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Alt-Delete": "delGroupAfter",
125591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        "Cmd-/": "toggleComment",
126591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        fallthrough: "devtools-common"
127591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    };
128591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
129591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    WebInspector.settings.textEditorIndent.addChangeListener(this._updateEditorIndentation, this);
130591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    this._updateEditorIndentation();
131591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    WebInspector.settings.showWhitespacesInEditor.addChangeListener(this._updateCodeMirrorMode, this);
132591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
133591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    this._codeMirror.setOption("keyMap", WebInspector.isMac() ? "devtools-mac" : "devtools-pc");
1345267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    this._codeMirror.setOption("flattenSpans", false);
135591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    this._codeMirror.setOption("maxHighlightLength", 1000);
136591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    this._codeMirror.setOption("mode", null);
137926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
13883750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch    this._shouldClearHistory = true;
13983750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch    this._lineSeparator = "\n";
14083750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch
141926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._tokenHighlighter = new WebInspector.CodeMirrorTextEditor.TokenHighlighter(this._codeMirror);
142926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._blockIndentController = new WebInspector.CodeMirrorTextEditor.BlockIndentController(this._codeMirror);
143926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._fixWordMovement = new WebInspector.CodeMirrorTextEditor.FixWordMovement(this._codeMirror);
144e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    this._autocompleteController = new WebInspector.CodeMirrorTextEditor.AutocompleteController(this, this._codeMirror);
145926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._codeMirror.on("change", this._change.bind(this));
14793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    this._codeMirror.on("beforeChange", this._beforeChange.bind(this));
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._codeMirror.on("gutterClick", this._gutterClick.bind(this));
149926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._codeMirror.on("cursorActivity", this._cursorActivity.bind(this));
150926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._codeMirror.on("scroll", this._scroll.bind(this));
151591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    this._codeMirror.on("focus", this._focus.bind(this));
152e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    this._codeMirror.on("blur", this._blur.bind(this));
153926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.addEventListener("contextmenu", this._contextMenu.bind(this));
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1557757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    this.element.addStyleClass("fill");
156f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    this.element.style.overflow = "hidden";
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.element.firstChild.addStyleClass("source-code");
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.element.firstChild.addStyleClass("fill");
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._elementToWidget = new Map();
160926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._nestedUpdatesCounter = 0;
161926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
162926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.addEventListener("focus", this._handleElementFocus.bind(this), false);
163e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    this.element.addEventListener("keydown", this._handleKeyDown.bind(this), true);
164926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.tabIndex = 0;
165591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
166591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    this._overrideModeWithPrefixedTokens("css-base", "css-");
167591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    this._overrideModeWithPrefixedTokens("javascript", "js-");
168591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    this._overrideModeWithPrefixedTokens("xml", "xml-");
169591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
17053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    this._setupSelectionColor();
1715267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    this._setupWhitespaceHighlight();
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1745267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)WebInspector.CodeMirrorTextEditor.autocompleteCommand = function(codeMirror)
1755267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
176e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    codeMirror._codeMirrorTextEditor._autocompleteController.autocomplete();
1775267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
1785267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)CodeMirror.commands.autocomplete = WebInspector.CodeMirrorTextEditor.autocompleteCommand;
1795267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
180591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochCodeMirror.commands.smartNewlineAndIndent = function(codeMirror)
181591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
182591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    codeMirror.operation(innerSmartNewlineAndIndent.bind(this, codeMirror));
183591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
184591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    function countIndent(line)
185591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    {
186591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        for(var i = 0; i < line.length; ++i) {
187591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            if (!WebInspector.TextUtils.isSpaceChar(line[i]))
188591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                return i;
189591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        }
190591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        return line.length;
191591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    }
192591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
193591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    function innerSmartNewlineAndIndent(codeMirror)
194591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    {
195e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var cur = codeMirror.getCursor("start");
196591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        var line = codeMirror.getLine(cur.line);
197591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        var indent = cur.line > 0 ? countIndent(line) : 0;
198591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (cur.ch <= indent) {
199591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            codeMirror.replaceSelection("\n" + line.substring(0, cur.ch), "end", "+input");
200591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            codeMirror.setSelection(new CodeMirror.Pos(cur.line + 1, cur.ch));
201591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        } else
202591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            codeMirror.execCommand("newlineAndIndent");
203591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    }
204591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
205591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
2067757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen MurdochCodeMirror.commands.undoAndReveal = function(codemirror)
2077757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch{
2087757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    var scrollInfo = codemirror.getScrollInfo();
2097757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    codemirror.execCommand("undo");
2107757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    var cursor = codemirror.getCursor("start");
2117757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    codemirror._codeMirrorTextEditor._innerRevealLine(cursor.line, scrollInfo);
2127757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch}
2137757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
2147757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen MurdochCodeMirror.commands.redoAndReveal = function(codemirror)
2157757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch{
2167757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    var scrollInfo = codemirror.getScrollInfo();
2177757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    codemirror.execCommand("redo");
2187757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    var cursor = codemirror.getCursor("start");
2197757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    codemirror._codeMirrorTextEditor._innerRevealLine(cursor.line, scrollInfo);
2207757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch}
2217757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
222591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochWebInspector.CodeMirrorTextEditor.LongLineModeLineLengthThreshold = 2000;
2235267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)WebInspector.CodeMirrorTextEditor.MaximumNumberOfWhitespacesPerSingleSpan = 16;
2245267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WebInspector.CodeMirrorTextEditor.prototype = {
226f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    wasShown: function()
227f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    {
228f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        this._codeMirror.refresh();
229f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    },
230f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)
231e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    _guessIndentationLevel: function()
232e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    {
233e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var tabRegex = /^\t+/;
234e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var tabLines = 0;
235e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var indents = {};
236e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        function processLine(lineHandle)
237e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        {
238e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            var text = lineHandle.text;
239e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            if (text.length === 0 || !WebInspector.TextUtils.isSpaceChar(text[0]))
240e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch                return;
241e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            if (tabRegex.test(text)) {
242e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch                ++tabLines;
243e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch                return;
244e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            }
245e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            var i = 0;
246e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            while (i < text.length && WebInspector.TextUtils.isSpaceChar(text[i]))
247e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch                ++i;
248e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            if (i % 2 !== 0)
249e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch                return;
250e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            indents[i] = 1 + (indents[i] || 0);
251e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        }
252e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        this._codeMirror.eachLine(processLine);
253e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
254e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var onePercentFilterThreshold = this.linesCount / 100;
255e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (tabLines && tabLines > onePercentFilterThreshold)
256e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            return "\t";
257e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var minimumIndent = Infinity;
258e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        for (var i in indents) {
259f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            if (indents[i] < onePercentFilterThreshold)
260e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch                continue;
261e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            var indent = parseInt(i, 10);
262e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            if (minimumIndent > indent)
263e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch                minimumIndent = indent;
264e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        }
265e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (minimumIndent === Infinity)
266e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            return WebInspector.TextUtils.Indent.FourSpaces;
267e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        return new Array(minimumIndent + 1).join(" ");
268e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    },
269e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
270591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    _updateEditorIndentation: function()
271591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    {
272591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        var extraKeys = {};
273591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        var indent = WebInspector.settings.textEditorIndent.get();
27483750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch        if (WebInspector.settings.textEditorAutoDetectIndent.get())
275e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            indent = this._guessIndentationLevel();
276591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (indent === WebInspector.TextUtils.Indent.TabCharacter) {
277591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            this._codeMirror.setOption("indentWithTabs", true);
278591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            this._codeMirror.setOption("indentUnit", 4);
279591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        } else {
280591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            this._codeMirror.setOption("indentWithTabs", false);
281591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            this._codeMirror.setOption("indentUnit", indent.length);
282591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            extraKeys.Tab = function(codeMirror)
283591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            {
284591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                if (codeMirror.somethingSelected())
285591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                    return CodeMirror.Pass;
286591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                var pos = codeMirror.getCursor("head");
287591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                codeMirror.replaceRange(indent.substring(pos.ch % indent.length), codeMirror.getCursor());
288591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            }
289591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        }
290591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        this._codeMirror.setOption("extraKeys", extraKeys);
291e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        this._indentationLevel = indent;
292e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    },
293e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
294e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    /**
295e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch     * @return {string}
296e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch     */
297e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    indent: function()
298e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    {
299e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        return this._indentationLevel;
300591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    },
301591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
302591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    /**
303591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     * @param {!RegExp} regex
304591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     * @param {WebInspector.TextRange} range
305591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     */
306591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    highlightSearchResults: function(regex, range)
307591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    {
308591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        function innerHighlightRegex()
309591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        {
310591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            if (range) {
311591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                this.revealLine(range.startLine);
312591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                this.setSelection(WebInspector.TextRange.createFromLocation(range.startLine, range.startColumn));
313591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            } else {
314591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                // Collapse selection to end on search start so that we jump to next occurence on the first enter press.
315591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                this.setSelection(this.selection().collapseToEnd());
316591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            }
317591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            this._tokenHighlighter.highlightSearchResults(regex, range);
318591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        }
319591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
320591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        this._codeMirror.operation(innerHighlightRegex.bind(this));
321591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    },
322591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
323591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    cancelSearchResultsHighlight: function()
324591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    {
325591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        this._codeMirror.operation(this._tokenHighlighter.highlightSelectedTokens.bind(this._tokenHighlighter));
326591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    },
327926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
32853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    undo: function()
32953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    {
33053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        this._codeMirror.undo();
33153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    },
33253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
33353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    redo: function()
33453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    {
33553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        this._codeMirror.redo();
33653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    },
33753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
33853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    _setupSelectionColor: function()
33953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    {
34053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        if (WebInspector.CodeMirrorTextEditor._selectionStyleInjected)
34153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            return;
34253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        WebInspector.CodeMirrorTextEditor._selectionStyleInjected = true;
34353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        var backgroundColor = WebInspector.getSelectionBackgroundColor();
34453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        var backgroundColorRule = backgroundColor ? ".CodeMirror .CodeMirror-selected { background-color: " + backgroundColor + ";}" : "";
34553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        var foregroundColor = WebInspector.getSelectionForegroundColor();
3465267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        var foregroundColorRule = foregroundColor ? ".CodeMirror .CodeMirror-selectedtext:not(.CodeMirror-persist-highlight) { color: " + foregroundColor + "!important;}" : "";
34753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        if (!foregroundColorRule && !backgroundColorRule)
34853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            return;
34953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
35053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        var style = document.createElement("style");
35153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        style.textContent = backgroundColorRule + foregroundColorRule;
35253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        document.head.appendChild(style);
35353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    },
35453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
3555267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    _setupWhitespaceHighlight: function()
3565267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    {
357521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        if (WebInspector.CodeMirrorTextEditor._whitespaceStyleInjected || !WebInspector.settings.showWhitespacesInEditor.get())
3585267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            return;
3595267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        WebInspector.CodeMirrorTextEditor._whitespaceStyleInjected = true;
3605267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        const classBase = ".cm-whitespace-";
3615267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        const spaceChar = "·";
3625267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        var spaceChars = "";
3635267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        var rules = "";
3645267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        for(var i = 1; i <= WebInspector.CodeMirrorTextEditor.MaximumNumberOfWhitespacesPerSingleSpan; ++i) {
3655267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            spaceChars += spaceChar;
3665267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            var rule = classBase + i + "::before { content: '" + spaceChars + "';}\n";
3675267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            rules += rule;
3685267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        }
369521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        rules += ".cm-tab:before { display: block !important; }\n";
3705267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        var style = document.createElement("style");
3715267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        style.textContent = rules;
3725267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        document.head.appendChild(style);
3735267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    },
3745267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
37593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    _handleKeyDown: function(e)
37693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    {
377e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (this._autocompleteController.keyDown(e))
37893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            e.consume(true);
37993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    },
38093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
3817757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    _shouldProcessWordForAutocompletion: function(word)
3827757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    {
3837757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        return word.length && (word[0] < '0' || word[0] > '9');
3847757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    },
3857757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
38693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    /**
38793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)     * @param {string} text
38893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)     */
38993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    _addTextToCompletionDictionary: function(text)
39093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    {
39193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        var words = WebInspector.TextUtils.textToWords(text);
39293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        for(var i = 0; i < words.length; ++i) {
3937757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            if (this._shouldProcessWordForAutocompletion(words[i]))
3947757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch                this._dictionary.addWord(words[i]);
39593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        }
39693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    },
39793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
39893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    /**
39993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)     * @param {string} text
40093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)     */
40193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    _removeTextFromCompletionDictionary: function(text)
40293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    {
40393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        var words = WebInspector.TextUtils.textToWords(text);
40493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        for(var i = 0; i < words.length; ++i) {
4057757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            if (this._shouldProcessWordForAutocompletion(words[i]))
4067757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch                this._dictionary.removeWord(words[i]);
40793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        }
40893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    },
40993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
41093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    /**
41193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)     * @param {WebInspector.CompletionDictionary} dictionary
41293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)     */
41393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    setCompletionDictionary: function(dictionary)
41493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    {
41593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        this._dictionary = dictionary;
41693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        this._addTextToCompletionDictionary(this.text());
41793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    },
41893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
41953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    /**
42053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)     * @param {number} lineNumber
42153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)     * @param {number} column
42253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)     * @return {?{x: number, y: number, height: number}}
42353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)     */
42453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    cursorPositionToCoordinates: function(lineNumber, column)
42553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    {
426e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (lineNumber >= this._codeMirror.lineCount() || lineNumber < 0 || column < 0 || column > this._codeMirror.getLine(lineNumber).length)
42753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            return null;
42853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
42953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        var metrics = this._codeMirror.cursorCoords(new CodeMirror.Pos(lineNumber, column));
43053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
43153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return {
43253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            x: metrics.left,
43353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            y: metrics.top,
43453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            height: metrics.bottom - metrics.top
43553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        };
43653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    },
43753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
43853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    /**
43953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)     * @param {number} x
44053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)     * @param {number} y
44153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)     * @return {?WebInspector.TextRange}
44253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)     */
44353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    coordinatesToCursorPosition: function(x, y)
44453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    {
44553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        var element = document.elementFromPoint(x, y);
44653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        if (!element || !element.isSelfOrDescendant(this._codeMirror.getWrapperElement()))
44753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            return null;
44853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        var gutterBox = this._codeMirror.getGutterElement().boxInWindow();
44953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        if (x >= gutterBox.x && x <= gutterBox.x + gutterBox.width &&
45053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            y >= gutterBox.y && y <= gutterBox.y + gutterBox.height)
45153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            return null;
45253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        var coords = this._codeMirror.coordsChar({left: x, top: y});
45353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return this._toRange(coords, coords);
45453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    },
45553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
45653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    _convertTokenType: function(tokenType)
45753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    {
458591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (tokenType.startsWith("js-variable") || tokenType.startsWith("js-property") || tokenType === "js-def")
45953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            return "javascript-ident";
460591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (tokenType === "js-string-2")
46153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            return "javascript-regexp";
462591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (tokenType === "js-number" || tokenType === "js-comment" || tokenType === "js-string" || tokenType === "js-keyword")
463591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            return "javascript-" + tokenType.substring("js-".length);
46453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return null;
46553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    },
46653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
46753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    /**
46853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)     * @param {number} lineNumber
46953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)     * @param {number} column
47053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)     * @return {?{startColumn: number, endColumn: number, type: string}}
47153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)     */
47253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    tokenAtTextPosition: function(lineNumber, column)
47353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    {
47453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        if (lineNumber < 0 || lineNumber >= this._codeMirror.lineCount())
47553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            return null;
476e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var token = this._codeMirror.getTokenAt(new CodeMirror.Pos(lineNumber, (column || 0) + 1));
47753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        if (!token || !token.type)
47853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            return null;
47953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        var convertedType = this._convertTokenType(token.type);
48053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        if (!convertedType)
48153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            return null;
48253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return {
48353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            startColumn: token.start,
48453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            endColumn: token.end - 1,
48553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            type: convertedType
48653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        };
48753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    },
48853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
489926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
490926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {WebInspector.TextRange} textRange
491926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {string}
492926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
493926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    copyRange: function(textRange)
494926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
495926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var pos = this._toPos(textRange);
496926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return this._codeMirror.getRange(pos.start, pos.end);
497926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
498926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
50053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)     * @return {boolean}
50153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)     */
50253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    isClean: function()
50353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    {
50453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return this._codeMirror.isClean();
50553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    },
50653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
50753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    markClean: function()
50853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    {
50953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        this._codeMirror.markClean();
51053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    },
51153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
5125267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    _hasLongLines: function()
5135267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    {
5145267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        function lineIterator(lineHandle)
5155267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        {
516591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            if (lineHandle.text.length > WebInspector.CodeMirrorTextEditor.LongLineModeLineLengthThreshold)
5175267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)                hasLongLines = true;
518591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            return hasLongLines;
5195267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        }
5205267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        var hasLongLines = false;
5215267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        this._codeMirror.eachLine(lineIterator);
5225267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return hasLongLines;
5235267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    },
5245267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
525591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    /**
526591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     * @param {string} mimeType
527591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     * @return {string}
528591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     */
5295267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    _whitespaceOverlayMode: function(mimeType)
5305267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    {
531591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        var modeName = CodeMirror.mimeModes[mimeType] + "+whitespaces";
5325267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        if (CodeMirror.modes[modeName])
5335267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            return modeName;
5345267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
5355267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        function modeConstructor(config, parserConfig)
5365267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        {
5375267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            function nextToken(stream)
5385267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            {
5395267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)                if (stream.peek() === " ") {
5405267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)                    var spaces = 0;
5415267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)                    while (spaces < WebInspector.CodeMirrorTextEditor.MaximumNumberOfWhitespacesPerSingleSpan && stream.peek() === " ") {
5425267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)                        ++spaces;
5435267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)                        stream.next();
5445267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)                    }
5455267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)                    return "whitespace whitespace-" + spaces;
5465267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)                }
5475267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)                while (!stream.eol() && stream.peek() !== " ")
5485267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)                    stream.next();
5495267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)                return null;
5505267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            }
5515267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            var whitespaceMode = {
5525267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)                token: nextToken
5535267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            };
5545267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            return CodeMirror.overlayMode(CodeMirror.getMode(config, mimeType), whitespaceMode, false);
5555267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        }
5565267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        CodeMirror.defineMode(modeName, modeConstructor);
5575267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return modeName;
5585267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    },
5595267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
56053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    /**
561591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     * @param {string} modeName
562591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     * @param {string} tokenPrefix
5635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
564591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    _overrideModeWithPrefixedTokens: function(modeName, tokenPrefix)
5655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
566591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        var oldModeName = modeName + "-old";
567591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (CodeMirror.modes[oldModeName])
5685267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            return;
569591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
570591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        CodeMirror.defineMode(oldModeName, CodeMirror.modes[modeName]);
571591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        CodeMirror.defineMode(modeName, modeConstructor);
572591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
573591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        function modeConstructor(config, parserConfig)
574591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        {
575591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            var innerConfig = {};
576591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            for (var i in parserConfig)
577591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                innerConfig[i] = parserConfig[i];
578591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            innerConfig.name = oldModeName;
579591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            var codeMirrorMode = CodeMirror.getMode(config, innerConfig);
580591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            codeMirrorMode.name = modeName;
581591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            codeMirrorMode.token = tokenOverride.bind(this, codeMirrorMode.token);
582591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            return codeMirrorMode;
5835267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        }
584591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
585591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        function tokenOverride(superToken, stream, state)
586591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        {
587591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            var token = superToken(stream, state);
588591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            return token ? tokenPrefix + token : token;
5895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
5905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
5915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
592591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    _enableLongLinesMode: function()
593591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    {
594591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        this._codeMirror.setOption("styleSelectedText", false);
595591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        this._longLinesMode = true;
596591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    },
597591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
598591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    _disableLongLinesMode: function()
599591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    {
600591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        this._codeMirror.setOption("styleSelectedText", true);
601591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        this._longLinesMode = false;
602591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    },
603591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
604591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    _updateCodeMirrorMode: function()
605591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    {
606591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        var showWhitespaces = WebInspector.settings.showWhitespacesInEditor.get();
607591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        this._codeMirror.setOption("mode", showWhitespaces ? this._whitespaceOverlayMode(this._mimeType) : this._mimeType);
608591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    },
609591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
610591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    /**
611591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     * @param {string} mimeType
612591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     */
613591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    setMimeType: function(mimeType)
614591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    {
615591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        this._mimeType = mimeType;
616591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (this._hasLongLines())
617591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            this._enableLongLinesMode();
618591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        else
619591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            this._disableLongLinesMode();
620591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        this._updateCodeMirrorMode();
621591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    },
622591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
6235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
6245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {boolean} readOnly
6255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
6265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setReadOnly: function(readOnly)
6275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
628e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        this.element.enableStyleClass("CodeMirror-readonly", readOnly)
629e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        this._codeMirror.setOption("readOnly", readOnly);
6305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
6315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
6335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @return {boolean}
6345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
6355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    readOnly: function()
6365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
6375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return !!this._codeMirror.getOption("readOnly");
6385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
6395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
641926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {Object} highlightDescriptor
642926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
643926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    removeHighlight: function(highlightDescriptor)
644926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
645926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        highlightDescriptor.clear();
646926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
647926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
648926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
649926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {WebInspector.TextRange} range
650926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {string} cssClass
651926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {Object}
652926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
653926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    highlightRange: function(range, cssClass)
654926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
6555267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        cssClass = "CodeMirror-persist-highlight " + cssClass;
656926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var pos = this._toPos(range);
65753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        ++pos.end.ch;
65853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return this._codeMirror.markText(pos.start, pos.end, {
65953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            className: cssClass,
66053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            startStyle: cssClass + "-start",
66153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            endStyle: cssClass + "-end"
66253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        });
663926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
664926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
665926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
66653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)     * @param {string} regex
66753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)     * @param {string} cssClass
66853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)     * @return {Object}
66953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)     */
67053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    highlightRegex: function(regex, cssClass) { },
67153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
67253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    /**
6735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @return {Element}
6745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
6755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    defaultFocusedElement: function()
6765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
677926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return this.element;
6785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
6795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    focus: function()
6815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
6825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._codeMirror.focus();
6835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
6845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
685926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    _handleElementFocus: function()
686926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
687926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._codeMirror.focus();
688926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
6895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
690926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    beginUpdates: function()
691926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
692926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        ++this._nestedUpdatesCounter;
693926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
694926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
695926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    endUpdates: function()
696926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
69753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        if (!--this._nestedUpdatesCounter)
698926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            this._codeMirror.refresh();
699926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
7005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
7025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {number} lineNumber
7035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
7045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    revealLine: function(lineNumber)
7055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
7067757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        this._innerRevealLine(lineNumber, this._codeMirror.getScrollInfo());
7077757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    },
7087757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
7097757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    /**
7107757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch     * @param {number} lineNumber
7117757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch     * @param {{left: number, top: number, width: number, height: number, clientWidth: number, clientHeight: number}} scrollInfo
7127757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch     */
7137757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    _innerRevealLine: function(lineNumber, scrollInfo)
7147757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    {
7155267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        var topLine = this._codeMirror.lineAtHeight(scrollInfo.top, "local");
7165267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        var bottomLine = this._codeMirror.lineAtHeight(scrollInfo.top + scrollInfo.clientHeight, "local");
7177757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        var linesPerScreen = bottomLine - topLine + 1;
7187757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        if (lineNumber < topLine) {
719fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch            var topLineToReveal = Math.max(lineNumber - (linesPerScreen / 2) + 1, 0) | 0;
7207757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            this._codeMirror.scrollIntoView(new CodeMirror.Pos(topLineToReveal, 0));
7217757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        } else if (lineNumber > bottomLine) {
722fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch            var bottomLineToReveal = Math.min(lineNumber + (linesPerScreen / 2) - 1, this.linesCount - 1) | 0;
7237757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            this._codeMirror.scrollIntoView(new CodeMirror.Pos(bottomLineToReveal, 0));
724926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
7255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
7265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _gutterClick: function(instance, lineNumber, gutter, event)
7285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
7295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.dispatchEventToListeners(WebInspector.TextEditor.Events.GutterClick, { lineNumber: lineNumber, event: event });
7305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
7315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
732926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    _contextMenu: function(event)
733926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
734926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var contextMenu = new WebInspector.ContextMenu(event);
735926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var target = event.target.enclosingNodeOrSelfWithClass("CodeMirror-gutter-elt");
736926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (target)
737926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            this._delegate.populateLineGutterContextMenu(contextMenu, parseInt(target.textContent, 10) - 1);
738926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        else
73953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            this._delegate.populateTextAreaContextMenu(contextMenu, 0);
740926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        contextMenu.show();
741926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
742926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
7435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
7445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {number} lineNumber
7455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {boolean} disabled
7465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {boolean} conditional
7475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
7485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    addBreakpoint: function(lineNumber, disabled, conditional)
7495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
75023e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch        if (lineNumber < 0 || lineNumber >= this._codeMirror.lineCount())
75123e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch            return;
75253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        var className = "cm-breakpoint" + (conditional ? " cm-breakpoint-conditional" : "") + (disabled ? " cm-breakpoint-disabled" : "");
75353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        this._codeMirror.addLineClass(lineNumber, "wrap", className);
7545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
7555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
7575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {number} lineNumber
7585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
7595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    removeBreakpoint: function(lineNumber)
7605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
76123e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch        if (lineNumber < 0 || lineNumber >= this._codeMirror.lineCount())
76223e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch            return;
76353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        var wrapClasses = this._codeMirror.getLineHandle(lineNumber).wrapClass;
76453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        if (!wrapClasses)
76553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            return;
76653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        var classes = wrapClasses.split(" ");
76753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        for(var i = 0; i < classes.length; ++i) {
76853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            if (classes[i].startsWith("cm-breakpoint"))
76953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)                this._codeMirror.removeLineClass(lineNumber, "wrap", classes[i]);
77053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        }
7715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
7725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
7745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {number} lineNumber
7755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
7765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setExecutionLine: function(lineNumber)
7775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
7785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._executionLine = this._codeMirror.getLineHandle(lineNumber);
77953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        this._codeMirror.addLineClass(this._executionLine, "wrap", "cm-execution-line");
7805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
7815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    clearExecutionLine: function()
7835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
7845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (this._executionLine)
78553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            this._codeMirror.removeLineClass(this._executionLine, "wrap", "cm-execution-line");
7865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        delete this._executionLine;
7875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
7885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
7905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {number} lineNumber
7915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {Element} element
7925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
7935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    addDecoration: function(lineNumber, element)
7945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
7955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var widget = this._codeMirror.addLineWidget(lineNumber, element);
7965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._elementToWidget.put(element, widget);
7975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
7985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
8005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {number} lineNumber
8015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {Element} element
8025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
8035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    removeDecoration: function(lineNumber, element)
8045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
8055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var widget = this._elementToWidget.remove(element);
8065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (widget)
8075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            this._codeMirror.removeLineWidget(widget);
8085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
8095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
8115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {number} lineNumber
81293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)     * @param {number=} columnNumber
8135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
81493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    highlightPosition: function(lineNumber, columnNumber)
8155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
81693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        if (lineNumber < 0)
81793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            return;
818521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        lineNumber = Math.min(lineNumber, this._codeMirror.lineCount() - 1);
81993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        if (typeof columnNumber !== "number" || columnNumber < 0 || columnNumber > this._codeMirror.getLine(lineNumber).length)
82093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            columnNumber = 0;
82193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
82293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        this.clearPositionHighlight();
8235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._highlightedLine = this._codeMirror.getLineHandle(lineNumber);
8245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!this._highlightedLine)
8255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          return;
826926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.revealLine(lineNumber);
8275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._codeMirror.addLineClass(this._highlightedLine, null, "cm-highlight");
82893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        this._clearHighlightTimeout = setTimeout(this.clearPositionHighlight.bind(this), 2000);
82993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        if (!this.readOnly())
83093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            this._codeMirror.setSelection(new CodeMirror.Pos(lineNumber, columnNumber));
8315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
8325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
83393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    clearPositionHighlight: function()
8345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
8355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (this._clearHighlightTimeout)
8365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            clearTimeout(this._clearHighlightTimeout);
8375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        delete this._clearHighlightTimeout;
8385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         if (this._highlightedLine)
8405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            this._codeMirror.removeLineClass(this._highlightedLine, null, "cm-highlight");
8415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        delete this._highlightedLine;
8425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
8435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
8455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @return {Array.<Element>}
8465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
8475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    elementsToRestoreScrollPositionsFor: function()
8485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
8495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return [];
8505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
8515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
8535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {WebInspector.TextEditor} textEditor
8545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
8555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    inheritScrollPositions: function(textEditor)
8565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
8575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
8585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8590474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch    _updatePaddingBottom: function(width, height)
8600474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch    {
8610474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch        var scrollInfo = this._codeMirror.getScrollInfo();
8620474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch        var newPaddingBottom;
8630474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch        var linesElement = this.element.firstChild.querySelector(".CodeMirror-lines");
8640474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch        var lineCount = this._codeMirror.lineCount();
8650474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch        if (lineCount <= 1)
8660474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch            newPaddingBottom = 0;
8670474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch        else
8680474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch            newPaddingBottom = Math.max(scrollInfo.clientHeight - this._codeMirror.getLineHandle(this._codeMirror.lastLine()).height, 0);
8690474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch        newPaddingBottom += "px";
8700474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch        linesElement.style.paddingBottom = newPaddingBottom;
8710474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch        this._codeMirror.setSize(width, height);
8720474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch    },
8730474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch
8740474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch    _resizeEditor: function()
8755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
8760474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch        var scrollInfo = this._codeMirror.getScrollInfo();
877f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        var width = this.element.parentElement.offsetWidth;
878f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        var height = this.element.parentElement.offsetHeight;
879f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        this._codeMirror.setSize(width, height);
8800474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch        this._updatePaddingBottom(width, height);
8810474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch        this._codeMirror.scrollTo(scrollInfo.left, scrollInfo.top);
8820474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch    },
8830474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch
8840474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch    onResize: function()
8850474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch    {
8860474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch        if (WebInspector.experimentsSettings.scrollBeyondEndOfFile.isEnabled())
8870474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch            this._resizeEditor();
8880474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch        else {
8890474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch            var width = this.element.parentElement.offsetWidth;
8900474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch            var height = this.element.parentElement.offsetHeight;
8910474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch            this._codeMirror.setSize(width, height);
8920474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch        }
8935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
8945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
8965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {WebInspector.TextRange} range
8975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {string} text
8985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @return {WebInspector.TextRange}
8995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
9005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    editRange: function(range, text)
9015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
9025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var pos = this._toPos(range);
9035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._codeMirror.replaceRange(text, pos.start, pos.end);
9045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var newRange = this._toRange(pos.start, this._codeMirror.posFromIndex(this._codeMirror.indexFromPos(pos.start) + text.length));
9055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._delegate.onTextChanged(range, newRange);
90683750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch        if (WebInspector.settings.textEditorAutoDetectIndent.get())
907e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            this._updateEditorIndentation();
9085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newRange;
9095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
9105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
91193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    /**
91293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)     * @param {number} lineNumber
91393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)     * @param {number} column
91493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)     * @param {boolean=} prefixOnly
91593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)     * @return {?WebInspector.TextRange}
91693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)     */
91793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    _wordRangeForCursorPosition: function(lineNumber, column, prefixOnly)
91893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    {
91993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        var line = this.line(lineNumber);
920e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (column === 0 || !WebInspector.TextUtils.isWordChar(line.charAt(column - 1)))
92193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            return null;
92293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        var wordStart = column - 1;
92393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        while(wordStart > 0 && WebInspector.TextUtils.isWordChar(line.charAt(wordStart - 1)))
92493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            --wordStart;
92593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        if (prefixOnly)
92693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            return new WebInspector.TextRange(lineNumber, wordStart, lineNumber, column);
92793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        var wordEnd = column;
92893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        while(wordEnd < line.length && WebInspector.TextUtils.isWordChar(line.charAt(wordEnd)))
92993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            ++wordEnd;
93093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        return new WebInspector.TextRange(lineNumber, wordStart, lineNumber, wordEnd);
93193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    },
93293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
93393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    _beforeChange: function(codeMirror, changeObject)
93493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    {
93593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        if (!this._dictionary)
93693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            return;
93793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        this._updatedLines = this._updatedLines || {};
93893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        for(var i = changeObject.from.line; i <= changeObject.to.line; ++i)
93993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            this._updatedLines[i] = this.line(i);
94093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    },
94193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
942e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    /**
943e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch     * @param {CodeMirror} codeMirror
944e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch     * @param {{origin: string, text: Array.<string>, removed: Array.<string>}} changeObject
945e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch     */
94693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    _change: function(codeMirror, changeObject)
9475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
9480474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch        if (WebInspector.experimentsSettings.scrollBeyondEndOfFile.isEnabled()) {
9490474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch            var hasOneLine = this._codeMirror.lineCount() === 1;
9500474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch            if (hasOneLine !== this._hasOneLine)
9510474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch                this._resizeEditor();
9520474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch            this._hasOneLine = hasOneLine;
9530474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch        }
9545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var widgets = this._elementToWidget.values();
9555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var i = 0; i < widgets.length; ++i)
9565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            this._codeMirror.removeLineWidget(widgets[i]);
9575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._elementToWidget.clear();
9585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
95993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        if (this._updatedLines) {
96093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            for(var lineNumber in this._updatedLines)
96193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)                this._removeTextFromCompletionDictionary(this._updatedLines[lineNumber]);
96293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            delete this._updatedLines;
96393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        }
96493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
96593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        var linesToUpdate = {};
966e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var singleCharInput = false;
96793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        do {
96893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            var oldRange = this._toRange(changeObject.from, changeObject.to);
96993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            var newRange = oldRange.clone();
97093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            var linesAdded = changeObject.text.length;
971e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            singleCharInput = (changeObject.origin === "+input" && changeObject.text.length === 1 && changeObject.text[0].length === 1) ||
972e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch                (changeObject.origin === "+delete" && changeObject.removed.length === 1 && changeObject.removed[0].length === 1);
97393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            if (linesAdded === 0) {
97493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)                newRange.endLine = newRange.startLine;
97593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)                newRange.endColumn = newRange.startColumn;
97693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            } else if (linesAdded === 1) {
97793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)                newRange.endLine = newRange.startLine;
97893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)                newRange.endColumn = newRange.startColumn + changeObject.text[0].length;
97993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            } else {
98093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)                newRange.endLine = newRange.startLine + linesAdded - 1;
98193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)                newRange.endColumn = changeObject.text[linesAdded - 1].length;
98293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            }
98393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
98493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            if (!this._muteTextChangedEvent)
98593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)                this._delegate.onTextChanged(oldRange, newRange);
98693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
98793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            for(var i = newRange.startLine; i <= newRange.endLine; ++i) {
98893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)                linesToUpdate[i] = true;
98993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            }
99093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            if (this._dictionary) {
99193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)                for(var i = newRange.startLine; i <= newRange.endLine; ++i)
99293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)                    linesToUpdate[i] = this.line(i);
99393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            }
99493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        } while (changeObject = changeObject.next);
99593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        if (this._dictionary) {
99693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            for(var lineNumber in linesToUpdate)
99793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)                this._addTextToCompletionDictionary(linesToUpdate[lineNumber]);
99893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        }
999e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (singleCharInput)
1000e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            this._autocompleteController.autocomplete();
10015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
10025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1003926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    _cursorActivity: function()
1004926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
1005926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var start = this._codeMirror.getCursor("anchor");
1006926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var end = this._codeMirror.getCursor("head");
1007926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._delegate.selectionChanged(this._toRange(start, end));
1008591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (!this._tokenHighlighter.highlightedRegex())
1009591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            this._codeMirror.operation(this._tokenHighlighter.highlightSelectedTokens.bind(this._tokenHighlighter));
1010926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
1011926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1012926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    _scroll: function()
1013926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
10145267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        if (this._scrollTimer)
10155267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            clearTimeout(this._scrollTimer);
10165267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        var topmostLineNumber = this._codeMirror.lineAtHeight(this._codeMirror.getScrollInfo().top, "local");
10175267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        this._scrollTimer = setTimeout(this._delegate.scrollChanged.bind(this._delegate, topmostLineNumber), 100);
1018926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
1019926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1020591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    _focus: function()
1021591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    {
1022591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        this._delegate.editorFocused();
1023591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    },
1024591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
1025e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    _blur: function()
1026e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    {
1027e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        this._autocompleteController.finishAutocomplete();
1028e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    },
1029e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
10305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
10315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {number} lineNumber
10325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
10335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    scrollToLine: function(lineNumber)
10345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1035591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        var pos = new CodeMirror.Pos(lineNumber, 0);
1036591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        var coords = this._codeMirror.charCoords(pos, "local");
1037591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        this._codeMirror.scrollTo(0, coords.top);
10385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
10395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
1041e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch     * @return {number}
1042e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch     */
1043e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    firstVisibleLine: function()
1044e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    {
1045e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        return this._codeMirror.lineAtHeight(this._codeMirror.getScrollInfo().top, "local");
1046e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    },
1047e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
1048e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    /**
1049fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch     * @return {number}
1050fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch     */
1051fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch    lastVisibleLine: function()
1052fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch    {
1053fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch        var scrollInfo = this._codeMirror.getScrollInfo();
1054fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch        return this._codeMirror.lineAtHeight(scrollInfo.top + scrollInfo.clientHeight, "local");
1055fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch    },
1056fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
1057fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch    /**
10585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @return {WebInspector.TextRange}
10595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
106053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    selection: function()
10615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1062e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var start = this._codeMirror.getCursor("anchor");
1063e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var end = this._codeMirror.getCursor("head");
10645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._toRange(start, end);
10665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
10675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
10695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @return {WebInspector.TextRange?}
10705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
10715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    lastSelection: function()
10725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
10735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._lastSelection;
10745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
10755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
10775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {WebInspector.TextRange} textRange
10785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
10795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setSelection: function(textRange)
10805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1081591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        this._lastSelection = textRange;
1082591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        var pos = this._toPos(textRange);
1083591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        this._codeMirror.setSelection(pos.start, pos.end);
10845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
10855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
10875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {string} text
10885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
108983750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch    _detectLineSeparator: function(text)
109083750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch    {
109183750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch        this._lineSeparator = text.indexOf("\r\n") >= 0 ? "\r\n" : "\n";
109283750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch    },
109383750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch
109483750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch    /**
109583750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch     * @param {string} text
109683750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch     */
10975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setText: function(text)
10985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
109953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        this._muteTextChangedEvent = true;
11005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._codeMirror.setValue(text);
1101e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        this._updateEditorIndentation();
110283750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch        if (this._shouldClearHistory) {
110383750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch            this._codeMirror.clearHistory();
110483750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch            this._shouldClearHistory = false;
110583750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch        }
110683750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch        this._detectLineSeparator(text);
110753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        delete this._muteTextChangedEvent;
11085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
11095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
11115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @return {string}
11125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
11135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    text: function()
11145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
111583750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch        return this._codeMirror.getValue().replace(/\n/g, this._lineSeparator);
11165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
11175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
11195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @return {WebInspector.TextRange}
11205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
11215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    range: function()
11225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
11235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var lineCount = this.linesCount;
11245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var lastLine = this._codeMirror.getLine(lineCount - 1);
112553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return this._toRange(new CodeMirror.Pos(0, 0), new CodeMirror.Pos(lineCount - 1, lastLine.length));
11265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
11275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
11295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {number} lineNumber
11305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @return {string}
11315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
11325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    line: function(lineNumber)
11335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
11345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._codeMirror.getLine(lineNumber);
11355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
11365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
11385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @return {number}
11395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
11405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    get linesCount()
11415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
11425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._codeMirror.lineCount();
11435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
11445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
11465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {number} line
11475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {string} name
11485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {Object?} value
11495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
11505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setAttribute: function(line, name, value)
11515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
115223e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch        if (line < 0 || line >= this._codeMirror.lineCount())
115323e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch            return;
11545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var handle = this._codeMirror.getLineHandle(line);
11555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (handle.attributes === undefined) handle.attributes = {};
11565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        handle.attributes[name] = value;
11575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
11585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
11605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {number} line
11615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {string} name
116223e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch     * @return {?Object} value
11635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
11645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    getAttribute: function(line, name)
11655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
116623e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch        if (line < 0 || line >= this._codeMirror.lineCount())
116723e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch            return null;
11685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var handle = this._codeMirror.getLineHandle(line);
11695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return handle.attributes && handle.attributes[name] !== undefined ? handle.attributes[name] : null;
11705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
11715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
11735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {number} line
11745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {string} name
11755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
11765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    removeAttribute: function(line, name)
11775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
117823e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch        if (line < 0 || line >= this._codeMirror.lineCount())
117923e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch            return;
11805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var handle = this._codeMirror.getLineHandle(line);
11815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (handle && handle.attributes)
11825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            delete handle.attributes[name];
11835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
11845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
118553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    /**
118653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)     * @param {WebInspector.TextRange} range
118753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)     * @return {{start: CodeMirror.Pos, end: CodeMirror.Pos}}
118853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)     */
11895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _toPos: function(range)
11905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
11915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return {
119253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            start: new CodeMirror.Pos(range.startLine, range.startColumn),
119353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            end: new CodeMirror.Pos(range.endLine, range.endColumn)
11945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
11955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
11965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _toRange: function(start, end)
11985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
11995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return new WebInspector.TextRange(start.line, start.ch, end.line, end.ch);
12005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
12015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    __proto__: WebInspector.View.prototype
12035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1204926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
120553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)/**
120653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * @constructor
120753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * @param {CodeMirror} codeMirror
120853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) */
1209926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)WebInspector.CodeMirrorTextEditor.TokenHighlighter = function(codeMirror)
1210926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
1211926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._codeMirror = codeMirror;
1212926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
1213926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1214926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)WebInspector.CodeMirrorTextEditor.TokenHighlighter.prototype = {
1215591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    /**
1216591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     * @param {RegExp} regex
1217591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     * @param {WebInspector.TextRange} range
1218591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     */
1219591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    highlightSearchResults: function(regex, range)
1220591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    {
1221591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        var oldRegex = this._highlightRegex;
1222591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        this._highlightRegex = regex;
1223591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        this._highlightRange = range;
1224591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (this._searchResultMarker) {
1225591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            this._searchResultMarker.clear();
1226591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            delete this._searchResultMarker;
1227591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        }
1228591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (this._highlightDescriptor && this._highlightDescriptor.selectionStart)
1229591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            this._codeMirror.removeLineClass(this._highlightDescriptor.selectionStart.line, "wrap", "cm-line-with-selection");
1230591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        var selectionStart = this._highlightRange ? new CodeMirror.Pos(this._highlightRange.startLine, this._highlightRange.startColumn) : null;
1231591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (selectionStart)
1232591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            this._codeMirror.addLineClass(selectionStart.line, "wrap", "cm-line-with-selection");
1233591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (this._highlightRegex === oldRegex) {
1234591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            // Do not re-add overlay mode if regex did not change for better performance.
12350474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch            if (this._highlightDescriptor)
12360474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch                this._highlightDescriptor.selectionStart = selectionStart;
1237591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        } else {
1238591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            this._removeHighlight();
1239591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            this._setHighlighter(this._searchHighlighter.bind(this, this._highlightRegex, this._highlightRange), selectionStart);
1240591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        }
1241591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (selectionStart) {
1242591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            var pos = WebInspector.CodeMirrorTextEditor.prototype._toPos(this._highlightRange);
1243591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            this._searchResultMarker = this._codeMirror.markText(pos.start, pos.end, {className: "cm-column-with-selection"});
1244591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        }
1245591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    },
1246591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
1247591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    highlightedRegex: function()
1248926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
1249591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        return this._highlightRegex;
1250591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    },
1251591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
1252591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    highlightSelectedTokens: function()
1253591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    {
1254591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        delete this._highlightRegex;
1255591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        delete this._highlightRange;
1256591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
1257591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (this._highlightDescriptor && this._highlightDescriptor.selectionStart)
1258591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            this._codeMirror.removeLineClass(this._highlightDescriptor.selectionStart.line, "wrap", "cm-line-with-selection");
1259591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        this._removeHighlight();
1260926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var selectionStart = this._codeMirror.getCursor("start");
1261926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var selectionEnd = this._codeMirror.getCursor("end");
1262926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (selectionStart.line !== selectionEnd.line)
1263926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return;
1264926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (selectionStart.ch === selectionEnd.ch)
1265926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return;
1266926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1267926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var selectedText = this._codeMirror.getSelection();
1268591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (this._isWord(selectedText, selectionStart.line, selectionStart.ch, selectionEnd.ch)) {
1269591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            if (selectionStart)
1270591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                this._codeMirror.addLineClass(selectionStart.line, "wrap", "cm-line-with-selection")
1271591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            this._setHighlighter(this._tokenHighlighter.bind(this, selectedText, selectionStart), selectionStart);
1272591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        }
1273926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
1274926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1275591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    /**
1276591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     * @param {string} selectedText
1277591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     * @param {number} lineNumber
1278591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     * @param {number} startColumn
1279591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     * @param {number} endColumn
1280591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     */
1281926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    _isWord: function(selectedText, lineNumber, startColumn, endColumn)
1282926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
1283926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var line = this._codeMirror.getLine(lineNumber);
1284926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var leftBound = startColumn === 0 || !WebInspector.TextUtils.isWordChar(line.charAt(startColumn - 1));
1285926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var rightBound = endColumn === line.length || !WebInspector.TextUtils.isWordChar(line.charAt(endColumn));
1286926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return leftBound && rightBound && WebInspector.TextUtils.isWord(selectedText);
1287926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
1288926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1289926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    _removeHighlight: function()
1290926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
1291926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (this._highlightDescriptor) {
1292926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            this._codeMirror.removeOverlay(this._highlightDescriptor.overlay);
1293926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            delete this._highlightDescriptor;
1294926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
1295926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
1296926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1297591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    /**
1298591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     * @param {RegExp} regex
1299591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     * @param {WebInspector.TextRange} range
1300591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     * @param {CodeMirror.StringStream} stream
1301591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     */
1302591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    _searchHighlighter: function(regex, range, stream)
1303926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
1304591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (stream.column() === 0)
1305591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            delete this._searchMatchLength;
1306591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (this._searchMatchLength) {
1307591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            if (this._searchMatchLength > 1) {
1308591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                for (var i = 0; i < this._searchMatchLength - 2; ++i)
1309591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                    stream.next();
1310591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                this._searchMatchLength = 1;
1311591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                return "search-highlight";
1312591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            } else {
1313591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                stream.next();
1314591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                delete this._searchMatchLength;
1315591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                return "search-highlight search-highlight-end";
1316591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            }
1317926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
1318591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        var match = stream.match(regex, false);
1319591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (match) {
1320591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            stream.next();
1321591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            var matchLength = match[0].length;
1322591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            if (matchLength === 1)
1323591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                return "search-highlight search-highlight-full";
1324591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            this._searchMatchLength = matchLength;
1325591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            return "search-highlight search-highlight-start";
1326591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        }
1327591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
1328591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        while (!stream.match(regex, false) && stream.next()) {};
1329591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    },
1330591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
1331591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    /**
1332591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     * @param {string} token
1333591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     * @param {CodeMirror.Pos} selectionStart
1334591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     * @param {CodeMirror.StringStream} stream
1335591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     */
1336591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    _tokenHighlighter: function(token, selectionStart, stream)
1337591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    {
1338591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        var tokenFirstChar = token.charAt(0);
1339591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (stream.match(token) && (stream.eol() || !WebInspector.TextUtils.isWordChar(stream.peek())))
1340591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            return stream.column() === selectionStart.ch ? "token-highlight column-with-selection" : "token-highlight";
1341591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
1342591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        var eatenChar;
1343591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        do {
1344591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            eatenChar = stream.next();
1345591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        } while (eatenChar && (WebInspector.TextUtils.isWordChar(eatenChar) || stream.peek() !== tokenFirstChar));
1346591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    },
1347926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1348591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    /**
1349591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     * @param {function(CodeMirror.StringStream)} highlighter
1350591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     */
1351591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    _setHighlighter: function(highlighter, selectionStart)
1352591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    {
1353926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var overlayMode = {
1354591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            token: highlighter
1355926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        };
1356926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._codeMirror.addOverlay(overlayMode);
1357926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._highlightDescriptor = {
1358926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            overlay: overlayMode,
1359926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            selectionStart: selectionStart
1360926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        };
1361926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
1362926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
1363926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
136453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)/**
136553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * @constructor
136653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * @param {CodeMirror} codeMirror
136753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) */
1368926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)WebInspector.CodeMirrorTextEditor.BlockIndentController = function(codeMirror)
1369926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
1370926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    codeMirror.addKeyMap(this);
1371926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
1372926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1373926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)WebInspector.CodeMirrorTextEditor.BlockIndentController.prototype = {
1374926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    name: "blockIndentKeymap",
1375926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1376926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Enter: function(codeMirror)
1377926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
1378926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (codeMirror.somethingSelected())
1379926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return CodeMirror.Pass;
1380926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var cursor = codeMirror.getCursor();
1381591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (cursor.ch === 0)
1382591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            return CodeMirror.Pass;
1383926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var line = codeMirror.getLine(cursor.line);
1384926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (line.substr(cursor.ch - 1, 2) === "{}") {
1385926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            codeMirror.execCommand("newlineAndIndent");
1386926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            codeMirror.setCursor(cursor);
1387926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            codeMirror.execCommand("newlineAndIndent");
138853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            codeMirror.execCommand("indentMore");
1389591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        } else if (line.substr(cursor.ch - 1, 1) === "{") {
139053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            codeMirror.execCommand("newlineAndIndent");
139153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            codeMirror.execCommand("indentMore");
1392926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        } else
1393926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return CodeMirror.Pass;
139453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    },
139553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
139653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    "'}'": function(codeMirror)
139753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    {
139853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        var cursor = codeMirror.getCursor();
139953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        var line = codeMirror.getLine(cursor.line);
140053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        for(var i = 0 ; i < line.length; ++i)
140153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            if (!WebInspector.TextUtils.isSpaceChar(line.charAt(i)))
140253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)                return CodeMirror.Pass;
140353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
140453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        codeMirror.replaceRange("}", cursor);
140553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        var matchingBracket = codeMirror.findMatchingBracket();
1406591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (!matchingBracket || !matchingBracket.match)
140753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            return;
140853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
140953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        line = codeMirror.getLine(matchingBracket.to.line);
141053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        var desiredIndentation = 0;
141153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        while (desiredIndentation < line.length && WebInspector.TextUtils.isSpaceChar(line.charAt(desiredIndentation)))
141253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            ++desiredIndentation;
141353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
141453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        codeMirror.replaceRange(line.substr(0, desiredIndentation) + "}", new CodeMirror.Pos(cursor.line, 0), new CodeMirror.Pos(cursor.line, cursor.ch + 1));
1415926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
1416926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
1417926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
141853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)/**
141953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * @constructor
142053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * @param {CodeMirror} codeMirror
142153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) */
1422926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)WebInspector.CodeMirrorTextEditor.FixWordMovement = function(codeMirror)
1423926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
1424926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    function moveLeft(shift, codeMirror)
1425926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
1426926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var cursor = codeMirror.getCursor("head");
1427926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (cursor.ch !== 0 || cursor.line === 0)
1428926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return CodeMirror.Pass;
1429926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        codeMirror.setExtending(shift);
1430926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        codeMirror.execCommand("goLineUp");
1431926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        codeMirror.execCommand("goLineEnd")
1432926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        codeMirror.setExtending(false);
1433926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
1434926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    function moveRight(shift, codeMirror)
1435926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
1436926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var cursor = codeMirror.getCursor("head");
1437926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var line = codeMirror.getLine(cursor.line);
1438926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (cursor.ch !== line.length || cursor.line + 1 === codeMirror.lineCount())
1439926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return CodeMirror.Pass;
1440926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        codeMirror.setExtending(shift);
1441926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        codeMirror.execCommand("goLineDown");
1442926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        codeMirror.execCommand("goLineStart");
1443926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        codeMirror.setExtending(false);
1444926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
1445e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    function delWordBack(codeMirror)
1446e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    {
1447e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (codeMirror.somethingSelected())
1448e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            return CodeMirror.Pass;
1449e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var cursor = codeMirror.getCursor("head");
1450e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (cursor.ch === 0)
1451e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            codeMirror.execCommand("delCharBefore");
1452e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        else
1453e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            return CodeMirror.Pass;
1454e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    }
1455926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1456926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var modifierKey = WebInspector.isMac() ? "Alt" : "Ctrl";
1457926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var leftKey = modifierKey + "-Left";
1458926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var rightKey = modifierKey + "-Right";
1459926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var keyMap = {};
1460926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    keyMap[leftKey] = moveLeft.bind(this, false);
1461926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    keyMap[rightKey] = moveRight.bind(this, false);
1462926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    keyMap["Shift-" + leftKey] = moveLeft.bind(this, true);
1463926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    keyMap["Shift-" + rightKey] = moveRight.bind(this, true);
1464e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    keyMap[modifierKey + "-Backspace"] = delWordBack.bind(this);
1465926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    codeMirror.addKeyMap(keyMap);
1466926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
1467e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
1468e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch/**
1469e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch * @constructor
1470e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch * @implements {WebInspector.SuggestBoxDelegate}
1471e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch * @param {WebInspector.CodeMirrorTextEditor} textEditor
1472e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch * @param {CodeMirror} codeMirror
1473e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch */
1474e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben MurdochWebInspector.CodeMirrorTextEditor.AutocompleteController = function(textEditor, codeMirror)
1475e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch{
1476e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    this._textEditor = textEditor;
1477e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    this._codeMirror = codeMirror;
1478e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    this._codeMirror.on("scroll", this._onScroll.bind(this));
1479e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    this._codeMirror.on("cursorActivity", this._onCursorActivity.bind(this));
1480e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch}
1481e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
1482e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben MurdochWebInspector.CodeMirrorTextEditor.AutocompleteController.prototype = {
1483e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    autocomplete: function()
1484e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    {
1485e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var dictionary = this._textEditor._dictionary;
1486e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (!dictionary || this._codeMirror.somethingSelected()) {
1487e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            this.finishAutocomplete();
1488e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            return;
1489e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        }
1490e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
1491e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var cursor = this._codeMirror.getCursor();
1492e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var substituteRange = this._textEditor._wordRangeForCursorPosition(cursor.line, cursor.ch, false);
1493e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (!substituteRange || substituteRange.startColumn === cursor.ch) {
1494e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            this.finishAutocomplete();
1495e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            return;
1496e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        }
1497e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var prefixRange = substituteRange.clone();
1498e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        prefixRange.endColumn = cursor.ch;
1499e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
1500e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var substituteWord = this._textEditor.copyRange(substituteRange);
1501e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var hasPrefixInDictionary = dictionary.hasWord(substituteWord);
1502e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (hasPrefixInDictionary)
1503e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            dictionary.removeWord(substituteWord);
1504e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var wordsWithPrefix = dictionary.wordsWithPrefix(this._textEditor.copyRange(prefixRange));
1505e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (hasPrefixInDictionary)
1506e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            dictionary.addWord(substituteWord);
1507e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
1508e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        function sortSuggestions(a, b)
1509e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        {
15101fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch            return dictionary.wordCount(b) - dictionary.wordCount(a) || a.length - b.length;
1511e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        }
1512e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
1513e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        wordsWithPrefix.sort(sortSuggestions);
1514e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
1515e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (!this._suggestBox) {
1516e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            this._suggestBox = new WebInspector.SuggestBox(this, this._textEditor.element, "generic-suggest", 6);
1517e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            this._anchorBox = this._anchorBoxForPosition(cursor.line, cursor.ch);
1518e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        }
1519e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        this._suggestBox.updateSuggestions(this._anchorBox, wordsWithPrefix, 0, true, this._textEditor.copyRange(prefixRange));
1520e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        this._prefixRange = prefixRange;
1521e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (!this._suggestBox.visible())
1522e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            this.finishAutocomplete();
1523e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    },
1524e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
1525e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    finishAutocomplete: function()
1526e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    {
1527e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (!this._suggestBox)
1528e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            return;
1529e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        this._suggestBox.hide();
1530e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        this._suggestBox = null;
1531e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        this._prefixRange = null;
1532e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        this._anchorBox = null;
1533e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    },
1534e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
1535e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    /**
1536e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch     * @param {Event} e
1537e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch     */
1538e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    keyDown: function(e)
1539e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    {
1540e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (!this._suggestBox)
1541e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            return false;
1542e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (e.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code) {
1543e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            this.finishAutocomplete();
1544e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            return true;
1545e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        }
15467757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        if (e.keyCode === WebInspector.KeyboardShortcut.Keys.Tab.code) {
15477757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            this._suggestBox.acceptSuggestion();
15487757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            this.finishAutocomplete();
15497757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            return true;
15507757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        }
1551e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        return this._suggestBox.keyPressed(e);
1552e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    },
1553e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
1554e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    /**
1555e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch     * @param {string} suggestion
1556e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch     * @param {boolean=} isIntermediateSuggestion
1557e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch     */
1558e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    applySuggestion: function(suggestion, isIntermediateSuggestion)
1559e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    {
1560e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        this._currentSuggestion = suggestion;
1561e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    },
1562e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
1563e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    acceptSuggestion: function()
1564e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    {
1565e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (this._prefixRange.endColumn - this._prefixRange.startColumn !== this._currentSuggestion.length) {
1566e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            var pos = this._textEditor._toPos(this._prefixRange);
1567e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            this._codeMirror.replaceRange(this._currentSuggestion, pos.start, pos.end, "+autocomplete");
1568e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        }
1569e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    },
1570e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
1571e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    _onScroll: function()
1572e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    {
1573e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (!this._suggestBox)
1574e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            return;
1575e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var cursor = this._codeMirror.getCursor();
1576e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var scrollInfo = this._codeMirror.getScrollInfo();
1577e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var topmostLineNumber = this._codeMirror.lineAtHeight(scrollInfo.top, "local");
1578e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var bottomLine = this._codeMirror.lineAtHeight(scrollInfo.top + scrollInfo.clientHeight, "local");
1579e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (cursor.line < topmostLineNumber || cursor.line > bottomLine)
1580e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            this.finishAutocomplete();
1581e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        else {
1582e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            this._anchorBox = this._anchorBoxForPosition(cursor.line, cursor.ch);
1583e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            this._suggestBox.setPosition(this._anchorBox);
1584e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        }
1585e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    },
1586e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
1587e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    _onCursorActivity: function()
1588e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    {
1589e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (!this._suggestBox)
1590e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            return;
1591e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var cursor = this._codeMirror.getCursor();
1592e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (cursor.line !== this._prefixRange.startLine || cursor.ch > this._prefixRange.endColumn || cursor.ch < this._prefixRange.startColumn)
1593e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            this.finishAutocomplete();
1594e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    },
1595e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
1596e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    /**
1597e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch     * @param {number} line
1598e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch     * @param {number} column
1599e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch     * @return {AnchorBox}
1600e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch     */
1601e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    _anchorBoxForPosition: function(line, column)
1602e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    {
1603e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var metrics = this._textEditor.cursorPositionToCoordinates(line, column);
1604e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        return metrics ? new AnchorBox(metrics.x, metrics.y, 0, metrics.height) : null;
1605e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    },
1606e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch}
1607