Web Inspector: highlight occurences of word in DefaultTextEditor
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 25 Jan 2013 16:22:00 +0000 (16:22 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 25 Jan 2013 16:22:00 +0000 (16:22 +0000)
https://bugs.webkit.org/show_bug.cgi?id=105523

Patch by Andrey Lushnikov <lushnikov@chromium.org> on 2013-01-25
Reviewed by Pavel Feldman.

Source/WebCore:

Highlight occurrences of selected word in DefaultTextEditor by the means of new highlight regex API.

Test: inspector/editor/text-editor-highlight-token.html

* inspector/front-end/DefaultTextEditor.js:
(WebInspector.TextEditorMainPanel):
(WebInspector.TextEditorMainPanel.prototype._handleSelectionChange):
(WebInspector.TextEditorMainPanel.TokenHighlighter): Added.
(WebInspector.TextEditorMainPanel.TokenHighlighter.prototype.handleSelectionChange):
(WebInspector.TextEditorMainPanel.TokenHighlighter.prototype._regexString):
(WebInspector.TextEditorMainPanel.TokenHighlighter.prototype._highlight):
(WebInspector.TextEditorMainPanel.TokenHighlighter.prototype._removeHighlight):
(WebInspector.TextEditorMainPanel.TokenHighlighter.prototype._isWord):
* inspector/front-end/textEditor.css:
(.text-editor-token-highlight):

LayoutTests:

Add new test to verify token highlightning functionality.

* inspector/editor/editor-test.js:
(initialize_EditorTests.InspectorTest.createTestEditor): Added optional TextEditorDelegate argument.
* inspector/editor/text-editor-highlight-token-expected.txt: Added.
* inspector/editor/text-editor-highlight-token.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@140828 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/inspector/editor/editor-test.js
LayoutTests/inspector/editor/text-editor-highlight-token-expected.txt [new file with mode: 0644]
LayoutTests/inspector/editor/text-editor-highlight-token.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/inspector/front-end/DefaultTextEditor.js
Source/WebCore/inspector/front-end/textEditor.css

index f11c1c84bc5699069ae5fa8c794f847e110c336a..4202bb6945f57a8935ae39cd2d3c04c10f0ff897 100644 (file)
@@ -1,3 +1,17 @@
+2013-01-25  Andrey Lushnikov  <lushnikov@chromium.org>
+
+        Web Inspector: highlight occurences of word in DefaultTextEditor
+        https://bugs.webkit.org/show_bug.cgi?id=105523
+
+        Reviewed by Pavel Feldman.
+
+        Add new test to verify token highlightning functionality.
+
+        * inspector/editor/editor-test.js:
+        (initialize_EditorTests.InspectorTest.createTestEditor): Added optional TextEditorDelegate argument.
+        * inspector/editor/text-editor-highlight-token-expected.txt: Added.
+        * inspector/editor/text-editor-highlight-token.html: Added.
+
 2013-01-25  Zan Dobersek  <zdobersek@igalia.com>
 
         Unreviewed GTK gardening.
index c71efb89773e84786e85e60c470d6bd90e34cee5..a499152d0fed6a829f22de7f84e5ef19be02bc29 100644 (file)
@@ -1,10 +1,10 @@
 function initialize_EditorTests()
 {
 
-InspectorTest.createTestEditor = function(clientHeight, chunkSize)
+InspectorTest.createTestEditor = function(clientHeight, chunkSize, textEditorDelegate)
 {
     WebInspector.debugDefaultTextEditor = true;
-    var textEditor = new WebInspector.DefaultTextEditor("", new WebInspector.TextEditorDelegate());
+    var textEditor = new WebInspector.DefaultTextEditor("", textEditorDelegate || new WebInspector.TextEditorDelegate());
     textEditor.overrideViewportForTest(0, clientHeight || 100, chunkSize || 10);
     textEditor.show(WebInspector.inspectorView.element);
     return textEditor;
diff --git a/LayoutTests/inspector/editor/text-editor-highlight-token-expected.txt b/LayoutTests/inspector/editor/text-editor-highlight-token-expected.txt
new file mode 100644 (file)
index 0000000..980b370
--- /dev/null
@@ -0,0 +1,37 @@
+This test checks text editor token highlight functionality.
+
+=========== TextEditor text ==========
+function findElement(collection, elem) {
+        for(var i = 0; i < collection.length; ++i)
+            if (collection[i] === elem)
+                return i;
+        return null;
+    }
+=========== Before selecting element ===========
+
+<div class="inner-container text-editor-editable" tabindex="0">
+<div class="webkit-line-content">function findElement(collection, elem) {</div>
+<div class="webkit-line-content">        for(var i = 0; i <span class="webkit-html-tag">&lt;</span> <span class="webkit-html-tag">collection.length;</span> <span class="webkit-html-attribute-name">++i)</span></div>
+<div class="webkit-line-content">            <span class="webkit-html-attribute-name">if</span> <span class="webkit-html-attribute-name">(collection</span>[<span class="webkit-html-attribute-name">i</span>] === <span class="webkit-html-attribute-value">elem)</span></div>
+<div class="webkit-line-content">                <span class="webkit-html-attribute-value">return</span> <span class="webkit-html-attribute-value">i;</span></div>
+<div class="webkit-line-content">        <span class="webkit-html-attribute-value">return</span> <span class="webkit-html-attribute-value">null;</span></div>
+<div class="webkit-line-content">    <span class="webkit-html-attribute-value">}</span></div></div>
+=========== After selecting 'collection' ===========
+
+<div class="inner-container text-editor-editable" tabindex="0">
+<div class="webkit-line-content">function findElement(collection, elem) {<span class="text-editor-token-highlight text-editor-overlay-highlight" style="left: 146px; width: 72px;"> </span></div>
+<div class="webkit-line-content">        for(var i = 0; i <span class="webkit-html-tag">&lt;</span> <span class="webkit-html-tag">collection.length;</span> <span class="webkit-html-attribute-name">++i)</span><span class="text-editor-token-highlight text-editor-overlay-highlight" style="left: 188px; width: 72px;"> </span></div>
+<div class="webkit-line-content">            <span class="webkit-html-attribute-name">if</span> <span class="webkit-html-attribute-name">(collection</span>[<span class="webkit-html-attribute-name">i</span>] === <span class="webkit-html-attribute-value">elem)</span><span class="text-editor-token-highlight text-editor-overlay-highlight" style="left: 111px; width: 72px;"> </span></div>
+<div class="webkit-line-content">                <span class="webkit-html-attribute-value">return</span> <span class="webkit-html-attribute-value">i;</span></div>
+<div class="webkit-line-content">        <span class="webkit-html-attribute-value">return</span> <span class="webkit-html-attribute-value">null;</span></div>
+<div class="webkit-line-content">    <span class="webkit-html-attribute-value">}</span></div></div>
+=========== After selecting 'elem' ===========
+
+<div class="inner-container text-editor-editable" tabindex="0">
+<div class="webkit-line-content">function findElement(collection, elem) {<span class="text-editor-token-highlight text-editor-overlay-highlight" style="left: 230px; width: 30px;"> </span></div>
+<div class="webkit-line-content">        for(var i = 0; i <span class="webkit-html-tag">&lt;</span> <span class="webkit-html-tag">collection.length;</span> <span class="webkit-html-attribute-name">++i)</span></div>
+<div class="webkit-line-content">            <span class="webkit-html-attribute-name">if</span> <span class="webkit-html-attribute-name">(collection</span>[<span class="webkit-html-attribute-name">i</span>] === <span class="webkit-html-attribute-value">elem)</span><span class="text-editor-token-highlight text-editor-overlay-highlight" style="left: 237px; width: 30px;"> </span></div>
+<div class="webkit-line-content">                <span class="webkit-html-attribute-value">return</span> <span class="webkit-html-attribute-value">i;</span></div>
+<div class="webkit-line-content">        <span class="webkit-html-attribute-value">return</span> <span class="webkit-html-attribute-value">null;</span></div>
+<div class="webkit-line-content">    <span class="webkit-html-attribute-value">}</span></div></div>
+
diff --git a/LayoutTests/inspector/editor/text-editor-highlight-token.html b/LayoutTests/inspector/editor/text-editor-highlight-token.html
new file mode 100644 (file)
index 0000000..d101b10
--- /dev/null
@@ -0,0 +1,64 @@
+<html>
+<head>
+<script src="../../http/tests/inspector/inspector-test.js"></script>
+<script src="editor-test.js"></script>
+<script>
+function test()
+{
+    function findElement(collection, elem) {
+        for(var i = 0; i < collection.length; ++i)
+            if (collection[i] === elem)
+                return i;
+        return null;
+    }
+
+    var steps = [step2, step1]; // reversed order
+    function selectionChangeListener()
+    {
+        if (steps.length)
+            steps.pop().call();
+    }
+
+    var textEditorDelegate = new WebInspector.TextEditorDelegate();
+    textEditorDelegate.selectionChanged = selectionChangeListener;
+
+    var textEditor = InspectorTest.createTestEditor(undefined, undefined, textEditorDelegate);
+    textEditor.setReadOnly(false);
+    textEditor.setText(findElement.toString());
+    textEditor.element.focus();
+
+    InspectorTest.addResult("=========== TextEditor text ==========");
+    InspectorTest.addResult(textEditor.text());
+
+    InspectorTest.addResult("=========== Before selecting element ===========");
+    InspectorTest.dumpEditorHTML(textEditor, true);
+
+    var range = new WebInspector.TextRange(0, 21, 0, 31);
+    textEditor.setSelection(range);
+
+    function step1()
+    {
+        InspectorTest.addResult("=========== After selecting '" + textEditor._textModel.copyRange(range) + "' ===========");
+        InspectorTest.dumpEditorHTML(textEditor, true);
+        range = new WebInspector.TextRange(0, 33, 0, 37);
+        textEditor.setSelection(range);
+    }
+
+    function step2()
+    {
+        InspectorTest.addResult("=========== After selecting '" + textEditor._textModel.copyRange(range) + "' ===========");
+        InspectorTest.dumpEditorHTML(textEditor, true);
+        InspectorTest.completeTest();
+    }
+
+}
+
+</script>
+</head>
+
+<body onload="runTest();">
+<p>
+This test checks text editor token highlight functionality.
+</p>
+</body>
+</html>
index 5e3f2e160285f3e6cbe8900e116989044c6f1860..6f34a3a39cc0c2fd8d71989ce3105daabde9538d 100644 (file)
@@ -1,3 +1,26 @@
+2013-01-25  Andrey Lushnikov  <lushnikov@chromium.org>
+
+        Web Inspector: highlight occurences of word in DefaultTextEditor
+        https://bugs.webkit.org/show_bug.cgi?id=105523
+
+        Reviewed by Pavel Feldman.
+
+        Highlight occurrences of selected word in DefaultTextEditor by the means of new highlight regex API.
+
+        Test: inspector/editor/text-editor-highlight-token.html
+
+        * inspector/front-end/DefaultTextEditor.js:
+        (WebInspector.TextEditorMainPanel):
+        (WebInspector.TextEditorMainPanel.prototype._handleSelectionChange):
+        (WebInspector.TextEditorMainPanel.TokenHighlighter): Added.
+        (WebInspector.TextEditorMainPanel.TokenHighlighter.prototype.handleSelectionChange):
+        (WebInspector.TextEditorMainPanel.TokenHighlighter.prototype._regexString):
+        (WebInspector.TextEditorMainPanel.TokenHighlighter.prototype._highlight):
+        (WebInspector.TextEditorMainPanel.TokenHighlighter.prototype._removeHighlight):
+        (WebInspector.TextEditorMainPanel.TokenHighlighter.prototype._isWord):
+        * inspector/front-end/textEditor.css:
+        (.text-editor-token-highlight):
+
 2013-01-25  Alexander Paschenko  <alexander.pashenko@lge.com>
 
         [TexMap] Flickering after transitions on Apple HTML5 demo
index b5386f66d358a768dbf771cdc2d9192708f7a0c2..f00d904d7f58e974f1a58a156e8a30e582798034 100644 (file)
@@ -1362,6 +1362,8 @@ WebInspector.TextEditorMainPanel = function(delegate, textModel, url, syncScroll
 
     this._highlightRegexs = {};
 
+    this._tokenHighlighter = new WebInspector.TextEditorMainPanel.TokenHighlighter(this, textModel);
+
     this._freeCachedElements();
     this.buildChunks();
 }
@@ -2622,6 +2624,8 @@ WebInspector.TextEditorMainPanel.prototype = {
         var textRange = this.selection();
         if (textRange)
             this._lastSelection = textRange;
+
+        this._tokenHighlighter.handleSelectionChange(textRange);
         this._delegate.selectionChanged(textRange);
     },
 
@@ -2944,4 +2948,92 @@ WebInspector.TextEditorMainChunk.prototype = {
     }
 }
 
+/**
+ * @constructor
+ * @param {WebInspector.TextEditorMainPanel} mainPanel
+ * @param {WebInspector.TextEditorModel} textModel
+ */
+WebInspector.TextEditorMainPanel.TokenHighlighter = function(mainPanel, textModel)
+{
+    this._mainPanel = mainPanel;
+    this._textModel = textModel;
+}
+
+WebInspector.TextEditorMainPanel.TokenHighlighter._NonWordCharRegex = /[^a-zA-Z0-9_]/;
+WebInspector.TextEditorMainPanel.TokenHighlighter._WordRegex = /^[a-zA-Z0-9_]+$/;
+
+WebInspector.TextEditorMainPanel.TokenHighlighter.prototype = {
+    /**
+     * @param {WebInspector.TextRange} range
+     */
+    handleSelectionChange: function(range)
+    {
+        if (!range) {
+            this._removeHighlight();
+            return;
+        }
+
+        if (range.startLine !== range.endLine) {
+            this._removeHighlight();
+            return;
+        }
+
+        range = range.normalize();
+        var selectedText = this._textModel.copyRange(range);
+        if (selectedText === this._selectedWord)
+            return;
+
+        if (selectedText === "") {
+            this._removeHighlight();
+            return;
+        }
+
+        if (this._isWord(range, selectedText))
+            this._highlight(selectedText);
+        else
+            this._removeHighlight();
+    },
+
+    /**
+     * @param {string} word
+     */
+    _regexString: function(word)
+    {
+        return "\\b" + word + "\\b";
+    },
+
+    /**
+     * @param {string} selectedWord
+     */
+    _highlight: function(selectedWord)
+    {
+        this._removeHighlight();
+        this._selectedWord = selectedWord;
+        this._mainPanel.highlightRegex(this._regexString(selectedWord), "text-editor-token-highlight")
+    },
+
+    _removeHighlight: function()
+    {
+        if (this._selectedWord) {
+            this._mainPanel.removeRegexHighlight(this._regexString(this._selectedWord));
+            delete this._selectedWord;
+        }
+    },
+
+    /**
+     * @param {WebInspector.TextRange} range
+     * @param {string} selectedText
+     * @return {boolean}
+     */
+    _isWord: function(range, selectedText)
+    {
+        const NonWordChar = WebInspector.TextEditorMainPanel.TokenHighlighter._NonWordCharRegex;
+        const WordRegex = WebInspector.TextEditorMainPanel.TokenHighlighter._WordRegex;
+        var line = this._textModel.line(range.startLine);
+        var leftBound = range.startColumn === 0 || NonWordChar.test(line.charAt(range.startColumn - 1));
+        var rightBound = range.endColumn === line.length - 1 || NonWordChar.test(line.charAt(range.endColumn));
+        return leftBound && rightBound && WordRegex.test(selectedText);
+    }
+}
+
 WebInspector.debugDefaultTextEditor = false;
index 694071bd11fecf67c26b1e9b5273d5c64867526b..c01780adeae008b61c1e579f813745163042ab0d 100644 (file)
     z-index: -1;
 }
 
+.text-editor-token-highlight {
+    -webkit-border-radius: 3px;
+    border: 1px solid gray;
+}
+
 .text-editor-contents .inner-container {
     position: absolute;
     top: 0;