<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[185935] trunk/Source/WebInspectorUI</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/185935">185935</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2015-06-24 16:54:12 -0700 (Wed, 24 Jun 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Web Inspector: Pressing tab in the styles sidebar shouldn't insert a tab character
https://bugs.webkit.org/show_bug.cgi?id=146189

Patch by Devin Rousso &lt;drousso@apple.com&gt; on 2015-06-24
Reviewed by Timothy Hatcher.

* UserInterface/Controllers/CodeMirrorCompletionController.js: Added variable to control whether semicolons are added to the end of autocompleted css values.
(WebInspector.CodeMirrorCompletionController):
(WebInspector.CodeMirrorCompletionController.prototype.set noEndingSemicolon):
(WebInspector.CodeMirrorCompletionController.prototype._generateCSSCompletions):
* UserInterface/Views/CSSStyleDeclarationSection.js:
(WebInspector.CSSStyleDeclarationSection):
(WebInspector.CSSStyleDeclarationSection.prototype.cssStyleDeclarationTextEditorSwitchRule):
(WebInspector.CSSStyleDeclarationSection.prototype.focusRuleSelector):
(WebInspector.CSSStyleDeclarationSection.prototype.selectLastProperty):
(WebInspector.CSSStyleDeclarationSection.prototype.get selectorLocked):
(WebInspector.CSSStyleDeclarationSection.prototype.get locked):
(WebInspector.CSSStyleDeclarationSection.prototype._handleKeyDown):
* UserInterface/Views/CSSStyleDeclarationTextEditor.js:
(WebInspector.CSSStyleDeclarationTextEditor): Added functions for &quot;Tab&quot;, &quot;Shift-Tab&quot;, and &quot;Shift-Enter&quot; keypresses to improve usability.
(WebInspector.CSSStyleDeclarationTextEditor.prototype.selectFirstProperty): Highlights the first property.
(WebInspector.CSSStyleDeclarationTextEditor.prototype.selectLastProperty): Highlights the last property.
(WebInspector.CSSStyleDeclarationTextEditor.prototype._insertNewlineAfterCurrentLine): Inserts a newline after the currently selected line.
(WebInspector.CSSStyleDeclarationTextEditor.prototype._handleShiftTabKey.switchRule):
(WebInspector.CSSStyleDeclarationTextEditor.prototype._handleShiftTabKey): Pressing shift-tab will move the cursor to the previous non-word character that is immediately after a word character.
(WebInspector.CSSStyleDeclarationTextEditor.prototype._handleTabKey.switchRule):
(WebInspector.CSSStyleDeclarationTextEditor.prototype._handleTabKey.highlightNextNameOrValue):
(WebInspector.CSSStyleDeclarationTextEditor.prototype._handleTabKey): Pressing tab will move the cursor to each space character until the end of the line is reached, at
which point the cursor will move to the beginning of the next line.  Once the cursor is at the last line, pressing tab again will insert a newline.
* UserInterface/Views/RulesStyleDetailsPanel.js:
(WebInspector.RulesStyleDetailsPanel.prototype.cssStyleDeclarationSectionEditorNextRule): Switches the focused rule to the next section.
(WebInspector.RulesStyleDetailsPanel.prototype.cssStyleDeclarationSectionEditorPrevRule): Switches the focused rule to the previous section.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceControllersCodeMirrorCompletionControllerjs">trunk/Source/WebInspectorUI/UserInterface/Controllers/CodeMirrorCompletionController.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsCSSStyleDeclarationSectionjs">trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDeclarationSection.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsCSSStyleDeclarationTextEditorjs">trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDeclarationTextEditor.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsRulesStyleDetailsPaneljs">trunk/Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (185934 => 185935)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog        2015-06-24 23:48:11 UTC (rev 185934)
+++ trunk/Source/WebInspectorUI/ChangeLog        2015-06-24 23:54:12 UTC (rev 185935)
</span><span class="lines">@@ -1,3 +1,37 @@
</span><ins>+2015-06-24  Devin Rousso  &lt;drousso@apple.com&gt;
+
+        Web Inspector: Pressing tab in the styles sidebar shouldn't insert a tab character
+        https://bugs.webkit.org/show_bug.cgi?id=146189
+
+        Reviewed by Timothy Hatcher.
+
+        * UserInterface/Controllers/CodeMirrorCompletionController.js: Added variable to control whether semicolons are added to the end of autocompleted css values.
+        (WebInspector.CodeMirrorCompletionController):
+        (WebInspector.CodeMirrorCompletionController.prototype.set noEndingSemicolon):
+        (WebInspector.CodeMirrorCompletionController.prototype._generateCSSCompletions):
+        * UserInterface/Views/CSSStyleDeclarationSection.js:
+        (WebInspector.CSSStyleDeclarationSection):
+        (WebInspector.CSSStyleDeclarationSection.prototype.cssStyleDeclarationTextEditorSwitchRule):
+        (WebInspector.CSSStyleDeclarationSection.prototype.focusRuleSelector):
+        (WebInspector.CSSStyleDeclarationSection.prototype.selectLastProperty):
+        (WebInspector.CSSStyleDeclarationSection.prototype.get selectorLocked):
+        (WebInspector.CSSStyleDeclarationSection.prototype.get locked):
+        (WebInspector.CSSStyleDeclarationSection.prototype._handleKeyDown):
+        * UserInterface/Views/CSSStyleDeclarationTextEditor.js:
+        (WebInspector.CSSStyleDeclarationTextEditor): Added functions for &quot;Tab&quot;, &quot;Shift-Tab&quot;, and &quot;Shift-Enter&quot; keypresses to improve usability.
+        (WebInspector.CSSStyleDeclarationTextEditor.prototype.selectFirstProperty): Highlights the first property.
+        (WebInspector.CSSStyleDeclarationTextEditor.prototype.selectLastProperty): Highlights the last property.
+        (WebInspector.CSSStyleDeclarationTextEditor.prototype._insertNewlineAfterCurrentLine): Inserts a newline after the currently selected line.
+        (WebInspector.CSSStyleDeclarationTextEditor.prototype._handleShiftTabKey.switchRule):
+        (WebInspector.CSSStyleDeclarationTextEditor.prototype._handleShiftTabKey): Pressing shift-tab will move the cursor to the previous non-word character that is immediately after a word character.
+        (WebInspector.CSSStyleDeclarationTextEditor.prototype._handleTabKey.switchRule):
+        (WebInspector.CSSStyleDeclarationTextEditor.prototype._handleTabKey.highlightNextNameOrValue):
+        (WebInspector.CSSStyleDeclarationTextEditor.prototype._handleTabKey): Pressing tab will move the cursor to each space character until the end of the line is reached, at
+        which point the cursor will move to the beginning of the next line.  Once the cursor is at the last line, pressing tab again will insert a newline.
+        * UserInterface/Views/RulesStyleDetailsPanel.js:
+        (WebInspector.RulesStyleDetailsPanel.prototype.cssStyleDeclarationSectionEditorNextRule): Switches the focused rule to the next section.
+        (WebInspector.RulesStyleDetailsPanel.prototype.cssStyleDeclarationSectionEditorPrevRule): Switches the focused rule to the previous section.
+
</ins><span class="cx"> 2015-06-24  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: console.group looks poor in console
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceControllersCodeMirrorCompletionControllerjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/CodeMirrorCompletionController.js (185934 => 185935)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Controllers/CodeMirrorCompletionController.js        2015-06-24 23:48:11 UTC (rev 185934)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/CodeMirrorCompletionController.js        2015-06-24 23:54:12 UTC (rev 185935)
</span><span class="lines">@@ -39,6 +39,7 @@
</span><span class="cx">         this._endOffset = NaN;
</span><span class="cx">         this._lineNumber = NaN;
</span><span class="cx">         this._prefix = &quot;&quot;;
</span><ins>+        this._noEndingSemicolon = false;
</ins><span class="cx">         this._completions = [];
</span><span class="cx">         this._extendedCompletionProviders = {};
</span><span class="cx"> 
</span><span class="lines">@@ -185,6 +186,11 @@
</span><span class="cx">         this._commitCompletionHint();
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    set noEndingSemicolon(noEndingSemicolon)
+    {
+        this._noEndingSemicolon = noEndingSemicolon;
+    }
+
</ins><span class="cx">     // Private
</span><span class="cx"> 
</span><span class="cx">     get _currentReplacementText()
</span><span class="lines">@@ -524,7 +530,7 @@
</span><span class="cx"> 
</span><span class="cx">             // If there is a suffix and it isn't a semicolon, then we should use a space since
</span><span class="cx">             // the user is editing in the middle.
</span><del>-            this._implicitSuffix = suffix &amp;&amp; suffix !== &quot;;&quot; ? &quot; &quot; : &quot;;&quot;;
</del><ins>+            this._implicitSuffix = suffix &amp;&amp; suffix !== &quot;;&quot; ? &quot; &quot; : (this._noEndingSemicolon ? &quot;&quot; : &quot;;&quot;);
</ins><span class="cx"> 
</span><span class="cx">             // Don't use an implicit suffix if it would be the same as the existing suffix.
</span><span class="cx">             if (this._implicitSuffix === suffix)
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsCSSStyleDeclarationSectionjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDeclarationSection.js (185934 => 185935)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDeclarationSection.js        2015-06-24 23:48:11 UTC (rev 185934)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDeclarationSection.js        2015-06-24 23:54:12 UTC (rev 185935)
</span><span class="lines">@@ -50,6 +50,7 @@
</span><span class="cx">     this._selectorElement.setAttribute(&quot;spellcheck&quot;, &quot;false&quot;);
</span><span class="cx">     this._selectorElement.addEventListener(&quot;mouseover&quot;, this._highlightNodesWithSelector.bind(this));
</span><span class="cx">     this._selectorElement.addEventListener(&quot;mouseout&quot;, this._hideHighlightOnNodesWithSelector.bind(this));
</span><ins>+    this._selectorElement.addEventListener(&quot;keydown&quot;, this._handleKeyDown.bind(this));
</ins><span class="cx">     this._headerElement.appendChild(this._selectorElement);
</span><span class="cx"> 
</span><span class="cx">     this._originElement = document.createElement(&quot;span&quot;);
</span><span class="lines">@@ -333,6 +334,54 @@
</span><span class="cx">             this._delegate.cssStyleDeclarationSectionEditorFocused(this);
</span><span class="cx">     },
</span><span class="cx"> 
</span><ins>+    cssStyleDeclarationTextEditorSwitchRule: function(reverse)
+    {
+        if (!this._delegate)
+            return;
+
+        if (reverse &amp;&amp; typeof this._delegate.cssStyleDeclarationSectionEditorPreviousRule === &quot;function&quot;)
+            this._delegate.cssStyleDeclarationSectionEditorPreviousRule(this);
+        else if (!reverse &amp;&amp; typeof this._delegate.cssStyleDeclarationSectionEditorNextRule === &quot;function&quot;)
+            this._delegate.cssStyleDeclarationSectionEditorNextRule(this);
+    },
+
+    focusRuleSelector: function(reverse)
+    {
+        if (this.selectorLocked) {
+            this.focus();
+            return;
+        }
+
+        if (this.locked) {
+            this.cssStyleDeclarationTextEditorSwitchRule(reverse);
+            return;
+        }
+
+        var selection = window.getSelection();
+        selection.removeAllRanges();
+
+        this._element.scrollIntoViewIfNeeded();
+
+        var range = document.createRange();
+        range.selectNodeContents(this._selectorElement);
+        selection.addRange(range);
+    },
+
+    selectLastProperty: function()
+    {
+        this._propertiesTextEditor.selectLastProperty();
+    },
+
+    get selectorLocked()
+    {
+        return !this.locked &amp;&amp; !this._style.ownerRule;
+    },
+
+    get locked()
+    {
+        return !this._style.editable;
+    },
+
</ins><span class="cx">     // Private
</span><span class="cx"> 
</span><span class="cx">     _handleContextMenuEvent: function(event)
</span><span class="lines">@@ -418,6 +467,25 @@
</span><span class="cx">         DOMAgent.hideHighlight();
</span><span class="cx">     },
</span><span class="cx"> 
</span><ins>+    _handleKeyDown: function(event)
+    {
+        if (event.keyCode !== 9)
+            return;
+
+        if (event.shiftKey &amp;&amp; this._delegate &amp;&amp; typeof this._delegate.cssStyleDeclarationSectionEditorPreviousRule === &quot;function&quot;) {
+            event.preventDefault();
+            this._delegate.cssStyleDeclarationSectionEditorPreviousRule(this, true);
+            return;
+        }
+
+        if (!event.metaKey) {
+            event.preventDefault();
+            this.focus();
+            this._propertiesTextEditor.selectFirstProperty();
+            return;
+        }
+    },
+
</ins><span class="cx">     _commitSelector: function(mutations)
</span><span class="cx">     {
</span><span class="cx">         console.assert(this._style.ownerRule);
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsCSSStyleDeclarationTextEditorjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDeclarationTextEditor.js (185934 => 185935)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDeclarationTextEditor.js        2015-06-24 23:48:11 UTC (rev 185934)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDeclarationTextEditor.js        2015-06-24 23:54:12 UTC (rev 185935)
</span><span class="lines">@@ -57,9 +57,17 @@
</span><span class="cx">             autoCloseBrackets: true
</span><span class="cx">         });
</span><span class="cx"> 
</span><ins>+        this._codeMirror.addKeyMap({
+            &quot;Shift-Enter&quot;: this._insertNewlineAfterCurrentLine.bind(this),
+            &quot;Shift-Tab&quot;: this._handleShiftTabKey.bind(this),
+            &quot;Tab&quot;: this._handleTabKey.bind(this)
+        });
+
</ins><span class="cx">         this._completionController = new WebInspector.CodeMirrorCompletionController(this._codeMirror, this);
</span><span class="cx">         this._tokenTrackingController = new WebInspector.CodeMirrorTokenTrackingController(this._codeMirror, this);
</span><span class="cx"> 
</span><ins>+        this._completionController.noEndingSemicolon = true;
+
</ins><span class="cx">         this._jumpToSymbolTrackingModeEnabled = false;
</span><span class="cx">         this._tokenTrackingController.classNameForHighlightedRange = WebInspector.CodeMirrorTokenTrackingController.JumpToSymbolHighlightStyleClassName;
</span><span class="cx">         this._tokenTrackingController.mouseOverDelayDuration = 0;
</span><span class="lines">@@ -335,6 +343,28 @@
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    selectFirstProperty()
+    {
+        var line = this._codeMirror.getLine(0);
+        var trimmedLine = line.trimRight();
+
+        if (!line || !trimmedLine.trimLeft().length)
+            this.clearSelection();
+
+        var index = line.indexOf(&quot;:&quot;);
+        this._codeMirror.setSelection({line: 0, ch: 0}, {line: 0, ch: index &lt; 0 ? trimmedLine.length : index});
+    }
+
+    selectLastProperty()
+    {
+        var line = this._codeMirror.lineCount() - 1;
+        var lineText = this._codeMirror.getLine(line);
+        var trimmedLine = lineText.trimRight();
+
+        var colon = /(?::\s*)/.exec(lineText);
+        this._codeMirror.setSelection({line, ch: colon ? colon.index + colon[0].length : 0}, {line, ch: trimmedLine.length - trimmedLine.endsWith(&quot;;&quot;)});
+    }
+
</ins><span class="cx">     // Protected
</span><span class="cx"> 
</span><span class="cx">     didDismissPopover(popover)
</span><span class="lines">@@ -359,6 +389,146 @@
</span><span class="cx"> 
</span><span class="cx">     // Private
</span><span class="cx"> 
</span><ins>+    _insertNewlineAfterCurrentLine(codeMirror)
+    {
+        var cursor = codeMirror.getCursor();
+        var line = codeMirror.getLine(cursor.line);
+        var trimmedLine = line.trimRight();
+
+        cursor.ch = trimmedLine.length;
+
+        if (cursor.ch) {
+            codeMirror.replaceRange(trimmedLine.endsWith(&quot;;&quot;) ? &quot;\n&quot; : &quot;;\n&quot;, cursor);
+            return;
+        }
+
+        return CodeMirror.Pass;
+    }
+
+    _handleShiftTabKey(codeMirror)
+    {
+        function switchRule()
+        {
+            if (this._delegate &amp;&amp; typeof this._delegate.cssStyleDeclarationTextEditorSwitchRule === &quot;function&quot;) {
+                this._delegate.cssStyleDeclarationTextEditorSwitchRule(true);
+                return;
+            }
+
+            return CodeMirror.Pass;
+        }
+
+        var cursor = codeMirror.getCursor();
+        var line = codeMirror.getLine(cursor.line);
+        var previousLine = codeMirror.getLine(cursor.line - 1);
+        var trimmedPreviousLine = previousLine ? previousLine.trimRight() : &quot;&quot;;
+
+        if (!line &amp;&amp; !previousLine &amp;&amp; !cursor.line)
+            return switchRule.call(this);
+
+        if (cursor.ch === line.indexOf(&quot;:&quot;) || line.indexOf(&quot;:&quot;) &lt; 0) {
+            if (previousLine) {
+                var colon = /(?::\s*)/.exec(previousLine);
+                codeMirror.setSelection({line: cursor.line - 1, ch: colon ? colon.index + colon[0].length : 0}, {line: cursor.line - 1, ch: trimmedPreviousLine.length - trimmedPreviousLine.endsWith(&quot;;&quot;)});
+                return;
+            }
+
+            if (cursor.line) {
+                codeMirror.setCursor(cursor.line - 1, 0);
+                return;
+            }
+
+            return switchRule.call(this);
+        }
+
+        var match = line.match(/(?:[^:;\s]\s*)+/g);
+        var lastMatch = line.indexOf(match.lastValue) + match.lastValue.length;
+        var prevHead = cursor.ch &gt; lastMatch ? line.indexOf(match.lastValue) : line.indexOf(match[0]);
+        var prevAnchor = cursor.ch &gt; lastMatch ? lastMatch : line.indexOf(match[0]) + match[0].length;
+
+        codeMirror.setSelection({line: cursor.line, ch: prevHead}, {line: cursor.line, ch: prevAnchor});
+    }
+
+    _handleTabKey(codeMirror)
+    {
+        function switchRule() {
+            if (this._delegate &amp;&amp; typeof this._delegate.cssStyleDeclarationTextEditorSwitchRule === &quot;function&quot;) {
+                this._delegate.cssStyleDeclarationTextEditorSwitchRule();
+                return;
+            }
+
+            return CodeMirror.Pass;
+        }
+
+        function highlightNextNameOrValue(text)
+        {
+            var match = text.match(/(?:[^:;\s]\s*)+/g);
+            var firstMatch = text.indexOf(match[0]) + match[0].length;
+            var nextHead = cursor.ch &lt; firstMatch ? text.indexOf(match[0]) : text.indexOf(match[1]);
+            var nextAnchor = cursor.ch &lt; firstMatch ? firstMatch : text.indexOf(match[1]) + match[1].length;
+
+            codeMirror.setSelection({line: cursor.line, ch: nextHead}, {line: cursor.line, ch: nextAnchor});
+        }
+
+        var cursor = codeMirror.getCursor();
+        var line = codeMirror.getLine(cursor.line);
+        var trimmedLine = line.trimRight();
+        var lastLine = cursor.line === codeMirror.lineCount() - 1;
+        var nextLine = codeMirror.getLine(cursor.line + 1);
+        var trimmedNextLine = nextLine ? nextLine.trimRight() : &quot;&quot;;
+
+        if (!trimmedLine.trimLeft().length) {
+            if (lastLine)
+                return switchRule.call(this);
+
+            if (!trimmedNextLine.trimLeft().length) {
+                codeMirror.setCursor(cursor.line + 1, 0);
+                return;
+            }
+
+            ++cursor.line;
+            highlightNextNameOrValue(nextLine);
+            return;
+        }
+
+        if (trimmedLine.endsWith(&quot;:&quot;)) {
+            codeMirror.setCursor(cursor.line, line.length);
+            this._completionController._completeAtCurrentPosition(true);
+            return;
+        }
+
+        var hasEndingSemicolon = trimmedLine.endsWith(&quot;;&quot;);
+
+        if (cursor.ch &gt;= line.trimRight().length - hasEndingSemicolon) {
+            if (!line.includes(&quot;:&quot;)) {
+                codeMirror.setCursor(cursor.line, line.length);
+                codeMirror.replaceRange(&quot;: &quot;, cursor);
+                return;
+            }
+
+            var replacement = &quot;&quot;;
+
+            if (!hasEndingSemicolon)
+                replacement += &quot;;&quot;;
+
+            if (lastLine)
+                replacement += &quot;\n&quot;;
+
+            if (replacement.length)
+                codeMirror.replaceRange(replacement, {line: cursor.line, ch: trimmedLine.length});
+
+            if (!nextLine) {
+                codeMirror.setCursor(cursor.line + 1, 0);
+                return;
+            }
+
+            var colon = nextLine.indexOf(&quot;:&quot;);
+            codeMirror.setSelection({line: cursor.line + 1, ch: 0}, {line: cursor.line + 1, ch: colon &lt; 0 ? trimmedNextLine.length : colon});
+            return;
+        }
+
+        highlightNextNameOrValue(line);
+    }
+
</ins><span class="cx">     _clearRemoveEditingLineClassesTimeout()
</span><span class="cx">     {
</span><span class="cx">         if (!this._removeEditingLineClassesTimeout)
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsRulesStyleDetailsPaneljs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.js (185934 => 185935)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.js        2015-06-24 23:48:11 UTC (rev 185934)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.js        2015-06-24 23:54:12 UTC (rev 185935)
</span><span class="lines">@@ -302,6 +302,35 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    cssStyleDeclarationSectionEditorNextRule(currentSection)
+    {
+        currentSection.clearSelection();
+
+        var index = this._sections.indexOf(currentSection);
+        this._sections[index &lt; this._sections.length - 1 ? index + 1 : 0].focusRuleSelector();
+    }
+
+    cssStyleDeclarationSectionEditorPreviousRule(currentSection, selectLastProperty) {
+        currentSection.clearSelection();
+
+        if (selectLastProperty || currentSection.selectorLocked) {
+            var index = this._sections.indexOf(currentSection);
+            index = index &gt; 0 ? index - 1 : this._sections.length - 1;
+
+            var section = this._sections[index];
+            while (section.locked) {
+                index = index &gt; 0 ? index - 1 : this._sections.length - 1;
+                section = this._sections[index];
+            }
+
+            section.focus();
+            section.selectLastProperty();
+            return;
+        }
+
+        currentSection.focusRuleSelector(true);
+    }
+
</ins><span class="cx">     filterDidChange(filterBar)
</span><span class="cx">     {
</span><span class="cx">         for (var labels of this._ruleMediaAndInherticanceList) {
</span></span></pre>
</div>
</div>

</body>
</html>