Skip to content

Commit

Permalink
search: fix freezing ui on long lines
Browse files Browse the repository at this point in the history
  • Loading branch information
connor4312 committed Nov 10, 2020
1 parent e300dfc commit df7fdd6
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 22 deletions.
5 changes: 1 addition & 4 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,7 @@
"port": 5876,
"outFiles": [
"${workspaceFolder}/out/**/*.js"
],
"presentation": {
"hidden": true,
}
]
},
{
"type": "node",
Expand Down
50 changes: 32 additions & 18 deletions src/vs/workbench/services/search/common/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ export const VIEW_ID = 'workbench.view.search';

export const SEARCH_EXCLUDE_CONFIG = 'search.exclude';

const SEARCH_SINGLE_RANGE_DIVIDER = '...';

export const ISearchService = createDecorator<ISearchService>('searchService');

/**
Expand Down Expand Up @@ -260,24 +262,31 @@ export class TextSearchMatch implements ITextSearchMatch {
// Trim preview if this is one match and a single-line match with a preview requested.
// Otherwise send the full text, like for replace or for showing multiple previews.
// TODO this is fishy.
if (previewOptions && previewOptions.matchLines === 1 && (!Array.isArray(range) || range.length === 1) && isSingleLineRange(range)) {
const oneRange = Array.isArray(range) ? range[0] : range;

const ranges = Array.isArray(range) ? range : [range];
if (previewOptions && previewOptions.matchLines === 1 && isSingleLineRangeList(ranges)) {
// 1 line preview requested
text = getNLines(text, previewOptions.matchLines);
const leadingChars = Math.floor(previewOptions.charsPerLine / 5);
const previewStart = Math.max(oneRange.startColumn - leadingChars, 0);
const previewText = text.substring(previewStart, previewOptions.charsPerLine + previewStart);

const endColInPreview = (oneRange.endLineNumber - oneRange.startLineNumber + 1) <= previewOptions.matchLines ?
Math.min(previewText.length, oneRange.endColumn - previewStart) : // if number of match lines will not be trimmed by previewOptions
previewText.length; // if number of lines is trimmed
let result = '';
let shift = 0;
let lastEnd = 0;
const leadingChars = Math.floor(previewOptions.charsPerLine / 5);
const matches: ISearchRange[] = [];
for (const range of ranges) {
const previewStart = Math.max(range.startColumn - leadingChars, 0);
const previewEnd = range.startColumn + previewOptions.charsPerLine;
if (previewStart > lastEnd + leadingChars) {
result += SEARCH_SINGLE_RANGE_DIVIDER + text.slice(previewStart, previewEnd);
shift += previewStart - (lastEnd + SEARCH_SINGLE_RANGE_DIVIDER.length);
} else {
result += text.slice(lastEnd, previewEnd);
}

matches.push(new OneLineRange(0, range.startColumn - shift, range.endColumn - shift));
lastEnd = previewEnd;
}

const oneLineRange = new OneLineRange(0, oneRange.startColumn - previewStart, endColInPreview);
this.preview = {
text: previewText,
matches: Array.isArray(range) ? [oneLineRange] : oneLineRange
};
this.preview = { text: result, matches: matches.length === 1 ? matches[0] : matches };
} else {
const firstMatchLine = Array.isArray(range) ? range[0].startLineNumber : range.startLineNumber;

Expand All @@ -289,10 +298,15 @@ export class TextSearchMatch implements ITextSearchMatch {
}
}

function isSingleLineRange(range: ISearchRange | ISearchRange[]): boolean {
return Array.isArray(range) ?
range[0].startLineNumber === range[0].endLineNumber :
range.startLineNumber === range.endLineNumber;
function isSingleLineRangeList(ranges: ISearchRange[]): boolean {
const line = ranges[0].startLineNumber;
for (const r of ranges) {
if (r.startLineNumber !== line || r.endLineNumber !== line) {
return false;
}
}

return true;
}

export class SearchRange implements ISearchRange {
Expand Down
14 changes: 14 additions & 0 deletions src/vs/workbench/services/search/test/common/search.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,20 @@ suite('TextSearchResult', () => {
assert.equal((<SearchRange>result.preview.matches).endColumn, 3);
});

test('compacts multiple ranges on long lines', () => {
const previewOptions: ITextSearchPreviewOptions = {
matchLines: 1,
charsPerLine: 10
};

const range1 = new SearchRange(5, 4, 5, 7);
const range2 = new SearchRange(5, 53, 5, 56);
const range3 = new SearchRange(5, 61, 5, 64);
const result = new TextSearchMatch('foo bar 1234567890123456789012345678901234567890 foo bar baz bar', [range1, range2, range3], previewOptions);
assert.deepEqual(result.preview.matches, [new SearchRange(0, 4, 0, 7), new SearchRange(0, 19, 0, 22), new SearchRange(0, 27, 0, 30)]);
assert.equal(result.preview.text, 'foo bar 123456...o bar baz bar');
});

// test('all lines of multiline match', () => {
// const previewOptions: ITextSearchPreviewOptions = {
// matchLines: 5,
Expand Down

0 comments on commit df7fdd6

Please sign in to comment.