function getSearchMatches(contents, queryExpr) {
    if (!contents) {
        return;
    }
    // Quick exit if not found or if we hit the limit
    if (foundMaximum || contents.search(queryExpr) === -1) {
        return [];
    }

    var match, lineNum, line, ch, totalMatchLength, matchedLines, numMatchedLines, lastLineLength, endCh,
        padding, leftPadding, rightPadding, highlightOffset, highlightEndCh,
        lines   = contents.split("\n"),
        matches = [];

    while ((match = queryExpr.exec(contents)) !== null) {
        lineNum          = offsetToLineNum(lines, match.index);
        line             = lines[lineNum];
        ch               = match.index - contents.lastIndexOf("\n", match.index) - 1;  // 0-based index
        matchedLines     = match[0].split("\n");
        numMatchedLines  = matchedLines.length;
        totalMatchLength = match[0].length;
        lastLineLength   = matchedLines[matchedLines.length - 1].length;
        endCh            = (numMatchedLines === 1 ? ch + totalMatchLength : lastLineLength);
        highlightEndCh   = (numMatchedLines === 1 ? endCh : line.length);
        highlightOffset  = 0;

        if (highlightEndCh <= MAX_DISPLAY_LENGTH) {
            // Don't store more than 200 chars per line
            line = line.substr(0, Math.min(MAX_DISPLAY_LENGTH, line.length));
        } else if (totalMatchLength > MAX_DISPLAY_LENGTH) {
            // impossible to display the whole match
            line = line.substr(ch, ch + MAX_DISPLAY_LENGTH);
            highlightOffset = ch;
        } else {
            // Try to have both beginning and end of match displayed
            padding = MAX_DISPLAY_LENGTH - totalMatchLength;
            rightPadding = Math.floor(Math.min(padding / 2, line.length - highlightEndCh));
            leftPadding = Math.ceil(padding - rightPadding);
            highlightOffset = ch - leftPadding;
            line = line.substring(highlightOffset, highlightEndCh + rightPadding);
        }

        matches.push({
            start:       {line: lineNum, ch: ch},
            end:         {line: lineNum + numMatchedLines - 1, ch: endCh},

            highlightOffset: highlightOffset,

            // Note that the following offsets from the beginning of the file are *not* updated if the search
            // results change. These are currently only used for multi-file replacement, and we always
            // abort the replace (by shutting the results panel) if we detect any result changes, so we don't
            // need to keep them up to date. Eventually, we should either get rid of the need for these (by
            // doing everything in terms of line/ch offsets, though that will require re-splitting files when
            // doing a replace) or properly update them.
            startOffset: match.index,
            endOffset:   match.index + totalMatchLength,

            line:        line,
            result:      match,
            isChecked:   true
        });

        // We have the max hits in just this 1 file. Stop searching this file.
        // This fixed issue #1829 where code hangs on too many hits.
        // Adds one over MAX_RESULTS_IN_A_FILE in order to know if the search has exceeded
        // or is equal to MAX_RESULTS_IN_A_FILE. Additional result removed in SearchModel
        if (matches.length > MAX_RESULTS_IN_A_FILE) {
            queryExpr.lastIndex = 0;
            break;
        }

        // Pathological regexps like /^/ return 0-length matches. Ensure we make progress anyway
        if (totalMatchLength === 0) {
            queryExpr.lastIndex++;
        }
    }

    return matches;
}
function getSearchMatches(contents, queryExpr) {
    if (!contents) {
        return;
    }
    // Quick exit if not found or if we hit the limit
    if (foundMaximum || contents.search(queryExpr) === -1) {
        return [];
    }

    var match, lineNum, line, ch, totalMatchLength, matchedLines, numMatchedLines, lastLineLength, endCh,
        padding, leftPadding, rightPadding, highlightOffset, highlightEndCh,
        lines   = contents.split("\n"),
        matches = [];

    while ((match = queryExpr.exec(contents)) !== null) {
        lineNum          = offsetToLineNum(lines, match.index);
        line             = lines[lineNum];
        ch               = match.index - contents.lastIndexOf("\n", match.index) - 1;  // 0-based index
        matchedLines     = match[0].split("\n");
        numMatchedLines  = matchedLines.length;
        totalMatchLength = match[0].length;
        lastLineLength   = matchedLines[matchedLines.length - 1].length;
        endCh            = (numMatchedLines === 1 ? ch + totalMatchLength : lastLineLength);
        highlightEndCh   = (numMatchedLines === 1 ? endCh : line.length);
        highlightOffset  = 0;

        if (highlightEndCh <= MAX_DISPLAY_LENGTH) {
            // Don't store more than 200 chars per line
            line = line.substr(0, Math.min(MAX_DISPLAY_LENGTH, line.length));
        } else if (totalMatchLength > MAX_DISPLAY_LENGTH) {
            // impossible to display the whole match
            line = line.substr(ch, ch + MAX_DISPLAY_LENGTH);
            highlightOffset = ch;
        } else {
            // Try to have both beginning and end of match displayed
            padding = MAX_DISPLAY_LENGTH - totalMatchLength;
            rightPadding = Math.floor(Math.min(padding / 2, line.length - highlightEndCh));
            leftPadding = Math.ceil(padding - rightPadding);
            highlightOffset = ch - leftPadding;
            line = line.substring(highlightOffset, highlightEndCh + rightPadding);
        }

        matches.push({
            start:       {line: lineNum, ch: ch},
            end:         {line: lineNum + numMatchedLines - 1, ch: endCh},

            highlightOffset: highlightOffset,

            // Note that the following offsets from the beginning of the file are *not* updated if the search
            // results change. These are currently only used for multi-file replacement, and we always
            // abort the replace (by shutting the results panel) if we detect any result changes, so we don't
            // need to keep them up to date. Eventually, we should either get rid of the need for these (by
            // doing everything in terms of line/ch offsets, though that will require re-splitting files when
            // doing a replace) or properly update them.
            startOffset: match.index,
            endOffset:   match.index + totalMatchLength,

            line:        line,
            result:      match,
            isChecked:   true
        });

        // We have the max hits in just this 1 file. Stop searching this file.
        // This fixed issue #1829 where code hangs on too many hits.
        // Adds one over MAX_RESULTS_IN_A_FILE in order to know if the search has exceeded
        // or is equal to MAX_RESULTS_IN_A_FILE. Additional result removed in SearchModel
        if (matches.length > MAX_RESULTS_IN_A_FILE) {
            queryExpr.lastIndex = 0;
            break;
        }

        // Pathological regexps like /^/ return 0-length matches. Ensure we make progress anyway
        if (totalMatchLength === 0) {
            queryExpr.lastIndex++;
        }
    }

    return matches;
}
function getSearchMatches ( contents , queryExpr ) { if ( ! contents ) { return ; } // Quick exit if not found or if we hit the limit if ( foundMaximum || contents . search ( queryExpr ) === - 1 ) { return [ ] ; } var match , lineNum , line , ch , totalMatchLength , matchedLines , numMatchedLines , lastLineLength , endCh , padding , leftPadding , rightPadding , highlightOffset , highlightEndCh , lines = contents . split ( "\n" ) , matches = [ ] ; while ( ( match = queryExpr . exec ( contents ) ) !== null ) { lineNum = offsetToLineNum ( lines , match . index ) ; line = lines [ lineNum ] ; ch = match . index - contents . lastIndexOf ( "\n" , match . index ) - 1 ; // 0-based index matchedLines = match [ 0 ] . split ( "\n" ) ; numMatchedLines = matchedLines . length ; totalMatchLength = match [ 0 ] . length ; lastLineLength = matchedLines [ matchedLines . length - 1 ] . length ; endCh = ( numMatchedLines === 1 ? ch + totalMatchLength : lastLineLength ) ; highlightEndCh = ( numMatchedLines === 1 ? endCh : line . length ) ; highlightOffset = 0 ; if ( highlightEndCh <= MAX_DISPLAY_LENGTH ) { // Don't store more than 200 chars per line line = line . substr ( 0 , Math . min ( MAX_DISPLAY_LENGTH , line . length ) ) ; } else if ( totalMatchLength > MAX_DISPLAY_LENGTH ) { // impossible to display the whole match line = line . substr ( ch , ch + MAX_DISPLAY_LENGTH ) ; highlightOffset = ch ; } else { // Try to have both beginning and end of match displayed padding = MAX_DISPLAY_LENGTH - totalMatchLength ; rightPadding = Math . floor ( Math . min ( padding / 2 , line . length - highlightEndCh ) ) ; leftPadding = Math . ceil ( padding - rightPadding ) ; highlightOffset = ch - leftPadding ; line = line . substring ( highlightOffset , highlightEndCh + rightPadding ) ; } matches . push ( { start : { line : lineNum , ch : ch } , end : { line : lineNum + numMatchedLines - 1 , ch : endCh } , highlightOffset : highlightOffset , // Note that the following offsets from the beginning of the file are *not* updated if the search // results change. These are currently only used for multi-file replacement, and we always // abort the replace (by shutting the results panel) if we detect any result changes, so we don't // need to keep them up to date. Eventually, we should either get rid of the need for these (by // doing everything in terms of line/ch offsets, though that will require re-splitting files when // doing a replace) or properly update them. startOffset : match . index , endOffset : match . index + totalMatchLength , line : line , result : match , isChecked : true } ) ; // We have the max hits in just this 1 file. Stop searching this file. // This fixed issue #1829 where code hangs on too many hits. // Adds one over MAX_RESULTS_IN_A_FILE in order to know if the search has exceeded // or is equal to MAX_RESULTS_IN_A_FILE. Additional result removed in SearchModel if ( matches . length > MAX_RESULTS_IN_A_FILE ) { queryExpr . lastIndex = 0 ; break ; } // Pathological regexps like /^/ return 0-length matches. Ensure we make progress anyway if ( totalMatchLength === 0 ) { queryExpr . lastIndex ++ ; } } return matches ; }
Searches through the contents and returns an array of matches
@param {string} contents
@param {RegExp} queryExpr
@return {!Array.<{start: {line:number,ch:number}, end: {line:number,ch:number}, line: string}>}
Searches through the contents and returns an array of matches
Search matches in the contents of a phrase