Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(31)

Side by Side Diff: Source/devtools/front_end/console/ConsoleView.js

Issue 632573002: Adding regex support to search bar in dev tools console (Closed) Base URL: https://chromium.googlesource.com/chromium/blink@master
Patch Set: Implement regex search similar to Sublime Text Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. 2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2009 Joseph Pecoraro 3 * Copyright (C) 2009 Joseph Pecoraro
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 8 *
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
(...skipping 21 matching lines...) Expand all
32 * @extends {WebInspector.VBox} 32 * @extends {WebInspector.VBox}
33 * @implements {WebInspector.Searchable} 33 * @implements {WebInspector.Searchable}
34 * @implements {WebInspector.TargetManager.Observer} 34 * @implements {WebInspector.TargetManager.Observer}
35 * @implements {WebInspector.ViewportControl.Provider} 35 * @implements {WebInspector.ViewportControl.Provider}
36 */ 36 */
37 WebInspector.ConsoleView = function() 37 WebInspector.ConsoleView = function()
38 { 38 {
39 WebInspector.VBox.call(this); 39 WebInspector.VBox.call(this);
40 this.registerRequiredCSS("filter.css"); 40 this.registerRequiredCSS("filter.css");
41 41
42 this._searchableView = new WebInspector.SearchableView(this); 42 this._searchableView = new WebInspector.SearchableView(this, true);
43 this._searchableView.setMinimalSearchQuerySize(0); 43 this._searchableView.setMinimalSearchQuerySize(0);
44 this._searchableView.show(this.element); 44 this._searchableView.show(this.element);
45 45
46 this._contentsElement = this._searchableView.element; 46 this._contentsElement = this._searchableView.element;
47 this._contentsElement.classList.add("console-view"); 47 this._contentsElement.classList.add("console-view");
48 this._visibleViewMessages = []; 48 this._visibleViewMessages = [];
49 this._urlToMessageCount = {}; 49 this._urlToMessageCount = {};
50 this._hiddenByFilterCount = 0; 50 this._hiddenByFilterCount = 0;
51 51
52 this._clearConsoleButton = new WebInspector.StatusBarButton(WebInspector.UIS tring("Clear console log."), "clear-status-bar-item"); 52 this._clearConsoleButton = new WebInspector.StatusBarButton(WebInspector.UIS tring("Clear console log."), "clear-status-bar-item");
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after
567 this._currentGroup = this._currentGroup.parentGroup(); 567 this._currentGroup = this._currentGroup.parentGroup();
568 return; 568 return;
569 } 569 }
570 if (!this._currentGroup.messagesHidden()) { 570 if (!this._currentGroup.messagesHidden()) {
571 var originatingMessage = viewMessage.consoleMessage().originatingMes sage(); 571 var originatingMessage = viewMessage.consoleMessage().originatingMes sage();
572 if (lastMessage && originatingMessage && lastMessage.consoleMessage( ) === originatingMessage) 572 if (lastMessage && originatingMessage && lastMessage.consoleMessage( ) === originatingMessage)
573 lastMessage.toMessageElement().classList.add("console-adjacent-u ser-command-result"); 573 lastMessage.toMessageElement().classList.add("console-adjacent-u ser-command-result");
574 574
575 this._visibleViewMessages.push(viewMessage); 575 this._visibleViewMessages.push(viewMessage);
576 576
577 if (this._searchRegex && viewMessage.matchesRegex(this._searchRegex) ) { 577 // TODO: Handle the regex search case
578 if (!this._searchableView.enableRegex && this._searchRegex &&
579 viewMessage.matchesRegex(this._searchRegex)) {
578 this._searchResults.push(viewMessage); 580 this._searchResults.push(viewMessage);
579 this._searchableView.updateSearchMatchesCount(this._searchResult s.length); 581 this._searchableView.updateSearchMatchesCount(this._searchResult s.length);
580 } 582 }
581 } 583 }
582 584
583 if (viewMessage.consoleMessage().isGroupStartMessage()) 585 if (viewMessage.consoleMessage().isGroupStartMessage())
584 this._currentGroup = new WebInspector.ConsoleGroup(this._currentGrou p, viewMessage); 586 this._currentGroup = new WebInspector.ConsoleGroup(this._currentGrou p, viewMessage);
585 }, 587 },
586 588
587 /** 589 /**
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after
911 */ 913 */
912 performSearch: function(query, shouldJump, jumpBackwards) 914 performSearch: function(query, shouldJump, jumpBackwards)
913 { 915 {
914 this.searchCanceled(); 916 this.searchCanceled();
915 this._searchableView.updateSearchMatchesCount(0); 917 this._searchableView.updateSearchMatchesCount(0);
916 this._searchRegex = createPlainTextSearchRegex(query, "gi"); 918 this._searchRegex = createPlainTextSearchRegex(query, "gi");
917 919
918 /** @type {!Array.<number>} */ 920 /** @type {!Array.<number>} */
919 this._searchResults = []; 921 this._searchResults = [];
920 for (var i = 0; i < this._visibleViewMessages.length; i++) { 922 for (var i = 0; i < this._visibleViewMessages.length; i++) {
921 if (this._visibleViewMessages[i].matchesRegex(this._searchRegex)) 923 if (this._visibleViewMessages[i].matchesRegex(this._searchRegex)) {
922 this._searchResults.push(i); 924 this._searchResults.push(i);
925 }
923 } 926 }
924 this._searchableView.updateSearchMatchesCount(this._searchResults.length ); 927 this._searchableView.updateSearchMatchesCount(this._searchResults.length );
925 this._currentSearchResultIndex = -1; 928 this._currentSearchResultIndex = -1;
926 if (shouldJump && this._searchResults.length) 929 if (shouldJump && this._searchResults.length) {
927 this._jumpToSearchResult(jumpBackwards ? -1 : 0); 930 this._jumpToSearchResult(jumpBackwards ? -1 : 0);
931 }
928 this._viewport.refresh(); 932 this._viewport.refresh();
929 }, 933 },
930 934
935 performRegexSearch: function(query, shouldJump, jumpBackwards)
936 {
937 this.searchCanceled();
938 this._searchableView.updateSearchMatchesCount(0);
939 try {
940 this._searchRegex = new RegExp(query, "gi");
941 } catch (e) {
942 return;
943 }
944
945 this._searchResults = [];
946 var messageRanges = [];
947 var allText = "";
948 var textOffset = 0;
949 for (var i = 0; i < this._visibleViewMessages.length; i++) {
950 var currentText = this._visibleViewMessages[i].getText() + "\n";
951 allText += currentText;
952 messageRanges.push({
953 start: textOffset,
954 end: textOffset + currentText.length - 1,
955 message: this._visibleViewMessages[i],
956 messageIndex: i,
957 });
958 textOffset += currentText.length;
959 }
960 var match = this._searchRegex.exec(allText);
961 this._regexMatchRanges = [];
962 while (match && match[0]) {
963 this._regexMatchRanges.push({
964 start: match.index,
965 end: match.index + match[0].length - 1,
966 messageIndexes: [],
967 messageRanges: [],
968 });
969 match = this._searchRegex.exec(allText);
970 }
971
972 this._searchableView.updateSearchMatchesCount(this._regexMatchRanges.len gth);
973 this._currentSearchResultIndex = -1;
974
975 console.log('Matching');
976 // Per match range, find corresponding messages and have them highlight the match
977 for (var i = 0; i < this._regexMatchRanges.length; ++i) {
978 var matchRange = this._regexMatchRanges[i];
979 var matchStart = matchRange.start;
980 var matchEnd = matchRange.end;
981 for (var j = 0; j < messageRanges.length; ++j) {
982 var messageRange = messageRanges[j];
983 var messageStart = messageRange.start;
984 var messageEnd = messageRange.end;
985 if ((messageStart <= matchStart && messageEnd >= matchStart) ||
986 (messageStart <= matchEnd && messageStart >= matchStart) ) {
987 console.log("Match " + i + " (" + matchStart + "," + matchEn d + ") matches message " +
988 j + " (" + messageStart + ", " + messageEnd + ")");
989 var startWithinMsg;
990 var endWithinMsg;
991 if (matchStart > messageStart) {
992 startWithinMsg = matchStart - messageStart;
993 } else {
994 startWithinMsg = 0;
995 }
996 if (matchEnd < messageEnd) {
997 endWithinMsg = matchEnd - messageStart;
998 } else {
999 // Subtract the logical \n character from the message en d position, since it's
1000 // not really part of the message
1001 endWithinMsg = messageEnd - 1;
1002 }
1003
1004 messageRange.message.highlightMatch(startWithinMsg, endWithi nMsg);
1005 this._searchResults.push(messageRange.messageIndex);
1006 matchRange.messageIndexes.push(messageRange.messageIndex);
1007 matchRange.messageRanges.push([startWithinMsg, endWithinMsg] );
1008 }
1009 }
1010 }
1011 // TODO:
1012 // 1. Jump to first matching message, and then to its matching element, which should be duly marked
1013
1014 if (shouldJump && this._searchResults.length) {
1015 this._jumpToSearchResult(jumpBackwards ? -1 : 0);
1016 }
1017 this._viewport.refresh();
1018 },
1019
931 jumpToNextSearchResult: function() 1020 jumpToNextSearchResult: function()
932 { 1021 {
933 if (!this._searchResults || !this._searchResults.length) 1022 if (!this._searchResults || !this._searchResults.length)
934 return; 1023 return;
935 this._jumpToSearchResult(this._currentSearchResultIndex + 1); 1024 this._jumpToSearchResult(this._currentSearchResultIndex + 1);
936 }, 1025 },
937 1026
938 jumpToPreviousSearchResult: function() 1027 jumpToPreviousSearchResult: function()
939 { 1028 {
940 if (!this._searchResults || !this._searchResults.length) 1029 if (!this._searchResults || !this._searchResults.length)
941 return; 1030 return;
942 this._jumpToSearchResult(this._currentSearchResultIndex - 1); 1031 this._jumpToSearchResult(this._currentSearchResultIndex - 1);
943 }, 1032 },
944 1033
945 _clearCurrentSearchResultHighlight: function() 1034 _clearCurrentSearchResultHighlight: function()
946 { 1035 {
947 if (!this._searchResults) 1036 if (!this._searchResults)
948 return; 1037 return;
949 1038 if (!this._searchableView.enableRegex) {
950 var highlightedViewMessage = this._visibleViewMessages[this._searchResul ts[this._currentSearchResultIndex]]; 1039 var highlightedViewMessage = this._visibleViewMessages[this._searchR esults[
951 if (highlightedViewMessage) 1040 this._currentSearchResultIndex]];
952 highlightedViewMessage.clearHighlight(); 1041 if (highlightedViewMessage)
953 this._currentSearchResultIndex = -1; 1042 highlightedViewMessage.clearHighlight();
1043 this._currentSearchResultIndex = -1;
1044 } else {
1045 for (var i = 0; i < this._searchResults.length; ++i) {
1046 this._visibleViewMessages[this._searchResults[i]].clearHighlight ();
1047 }
1048 }
954 }, 1049 },
955 1050
956 _jumpToSearchResult: function(index) 1051 _jumpToSearchResult: function(index)
957 { 1052 {
958 index = mod(index, this._searchResults.length); 1053 if (!this._searchableView.enableRegex) {
959 this._clearCurrentSearchResultHighlight(); 1054 index = mod(index, this._searchResults.length);
960 this._currentSearchResultIndex = index; 1055 this._clearCurrentSearchResultHighlight();
961 this._searchableView.updateCurrentMatchIndex(this._currentSearchResultIn dex); 1056 this._currentSearchResultIndex = index;
962 var currentViewMessageIndex = this._searchResults[index]; 1057 this._searchableView.updateCurrentMatchIndex(this._currentSearchResu ltIndex);
963 this._viewport.scrollItemIntoView(currentViewMessageIndex); 1058 var currentViewMessageIndex = this._searchResults[index];
964 this._visibleViewMessages[currentViewMessageIndex].highlightSearchResult s(this._searchRegex); 1059 this._viewport.scrollItemIntoView(currentViewMessageIndex);
1060 this._visibleViewMessages[currentViewMessageIndex].highlightSearchRe sults(this._searchRegex);
1061 } else {
1062 index = mod(index, this._regexMatchRanges.length);
1063 var matchRange;
1064 if (this._currentSearchResultIndex >= 0) {
1065 // Unmark current match range
1066 matchRange = this._regexMatchRanges[this._currentSearchResultInd ex];
1067 console.log("Unmarking current search result");
1068 for (var i = 0; i < matchRange.messageIndexes.length; ++i) {
1069 var currentMessageIndex = matchRange.messageIndexes[i];
1070 var message = this._visibleViewMessages[currentMessageIndex] ;
1071 var start = matchRange.messageRanges[i][0];
1072 var end = matchRange.messageRanges[i][1];
1073 message.highlightMatch(start, end);
1074 }
1075 }
1076 this._currentSearchResultIndex = index;
1077 this._searchableView.updateCurrentMatchIndex(this._currentSearchResu ltIndex);
1078 matchRange = this._regexMatchRanges[this._currentSearchResultIndex];
1079 console.log("Currently matched message indexes: " + matchRange.messa geIndexes);
1080 this._viewport.scrollItemIntoView(matchRange.messageIndexes[0]);
1081 for (var i = 0; i < matchRange.messageIndexes.length; ++i) {
1082 var currentMessageIndex = matchRange.messageIndexes[i];
1083 var message = this._visibleViewMessages[currentMessageIndex];
1084 var start = matchRange.messageRanges[i][0];
1085 var end = matchRange.messageRanges[i][1];
1086 console.log("Highlighting range " + start + "," + end + " in mes sage " +
1087 currentMessageIndex + " as part of the current match");
1088 message.highlightMatch(start, end, true);
1089 }
1090 }
965 }, 1091 },
966 1092
967 __proto__: WebInspector.VBox.prototype 1093 __proto__: WebInspector.VBox.prototype
968 } 1094 }
969 1095
970 /** 1096 /**
971 * @constructor 1097 * @constructor
972 * @extends {WebInspector.Object} 1098 * @extends {WebInspector.Object}
973 * @param {!WebInspector.ConsoleView} view 1099 * @param {!WebInspector.ConsoleView} view
974 */ 1100 */
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
1155 } 1281 }
1156 return this._element; 1282 return this._element;
1157 }, 1283 },
1158 1284
1159 _formatCommand: function() 1285 _formatCommand: function()
1160 { 1286 {
1161 this._formattedCommand = document.createElementWithClass("span", "consol e-message-text source-code"); 1287 this._formattedCommand = document.createElementWithClass("span", "consol e-message-text source-code");
1162 this._formattedCommand.textContent = this.text; 1288 this._formattedCommand.textContent = this.text;
1163 }, 1289 },
1164 1290
1291 /**
1292 * @return {!string}
1293 */
1294 getText: function()
1295 {
1296 return this.text;
1297 },
1298
1299 highlightMatch: function(start, end, isCurrent)
1300 {
1301 console.log("Highlighting from position " + start + " to " + end);
1302 WebInspector.highlightSearchResults(this._formattedCommand,
1303 [new WebInspector.SourceRange(start, end - start + 1)], undefined, i sCurrent);
1304 this._element.scrollIntoViewIfNeeded();
1305 },
1306
1165 __proto__: WebInspector.ConsoleViewMessage.prototype 1307 __proto__: WebInspector.ConsoleViewMessage.prototype
1166 } 1308 }
1167 1309
1168 /** 1310 /**
1169 * @constructor 1311 * @constructor
1170 * @extends {WebInspector.ConsoleViewMessage} 1312 * @extends {WebInspector.ConsoleViewMessage}
1171 * @param {!WebInspector.ConsoleMessage} message 1313 * @param {!WebInspector.ConsoleMessage} message
1172 * @param {!WebInspector.Linkifier} linkifier 1314 * @param {!WebInspector.Linkifier} linkifier
1173 * @param {number} nestingLevel 1315 * @param {number} nestingLevel
1174 */ 1316 */
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
1259 WebInspector.ConsoleView.ShowConsoleActionDelegate.prototype = { 1401 WebInspector.ConsoleView.ShowConsoleActionDelegate.prototype = {
1260 /** 1402 /**
1261 * @return {boolean} 1403 * @return {boolean}
1262 */ 1404 */
1263 handleAction: function() 1405 handleAction: function()
1264 { 1406 {
1265 WebInspector.console.show(); 1407 WebInspector.console.show();
1266 return true; 1408 return true;
1267 } 1409 }
1268 } 1410 }
OLDNEW
« no previous file with comments | « Source/devtools/front_end/components/SearchableView.js ('k') | Source/devtools/front_end/console/ConsoleViewMessage.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698