Skip to content

Commit 4d9cbf3

Browse files
committed
wip
1 parent b8b0b55 commit 4d9cbf3

2 files changed

Lines changed: 90 additions & 70 deletions

File tree

src/vs/editor/common/viewModel/characterHardWrappingLineMapper.ts

Lines changed: 83 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -111,31 +111,40 @@ function createLineMapping(classifier: WrappingCharacterClassifier, previousBrea
111111
const prevBreakingOffsetsVisibleColumn = previousBreakingData.breakingOffsetsVisibleColumn;
112112

113113
let breakingColumn = firstLineBreakingColumn;
114+
let lastBreakingOffsetVisibleColumn = 0;
114115
const prevLen = prevBreakingOffsets.length;
115116
let prevIndex = 0;
116-
while (prevIndex < prevLen) {
117117

118-
// Allow for prevIndex to be -1 (for the case where we hit a tab when walking backwards from the first break)
119-
let breakOffset = prevIndex < 0 ? 0 : prevBreakingOffsets[prevIndex];
120-
let breakOffsetVisibleColumn = prevIndex < 0 ? 0 : prevBreakingOffsetsVisibleColumn[prevIndex];
121-
122-
if (breakOffsetVisibleColumn === breakingColumn) {
123-
// perfect fit, nothing to do
124-
breakingOffsets[breakingOffsetsCount] = breakOffset;
125-
breakingOffsetsVisibleColumn[breakingOffsetsCount] = breakOffsetVisibleColumn;
126-
breakingOffsetsCount++;
127-
breakingColumn = breakOffsetVisibleColumn + wrappedLineBreakingColumn;
118+
if (prevIndex >= 0) {
119+
let currentDiff = Math.abs(prevBreakingOffsetsVisibleColumn[prevIndex] - breakingColumn);
120+
while (prevIndex + 1 < prevLen) {
121+
const potentialDiff = Math.abs(prevBreakingOffsetsVisibleColumn[prevIndex + 1] - breakingColumn);
122+
if (potentialDiff >= currentDiff) {
123+
break;
124+
}
125+
currentDiff = potentialDiff;
128126
prevIndex++;
129-
} else if (breakOffsetVisibleColumn < breakingColumn) {
130-
// try to add more characters
131-
const initialBreakOffset = breakOffset;
132-
let visibleColumn = breakOffsetVisibleColumn;
133-
breakOffset = 0;
127+
}
128+
}
129+
130+
while (prevIndex < prevLen) {
131+
// Allow for prevIndex to be -1 (for the case where we hit a tab when walking backwards from the first break)
132+
const prevBreakOffset = prevIndex < 0 ? 0 : prevBreakingOffsets[prevIndex];
133+
const prevBreakoffsetVisibleColumn = prevIndex < 0 ? 0 : prevBreakingOffsetsVisibleColumn[prevIndex];;
134134

135-
let prevCharCode = lineText.charCodeAt(initialBreakOffset - 1);
135+
let breakOffset = 0;
136+
let breakOffsetVisibleColumn = 0;
137+
138+
let forcedBreakOffset = 0;
139+
let forcedBreakOffsetVisibleColumn = 0;
140+
141+
// initially, we search as much as possible to the right (if it fits)
142+
if (prevBreakoffsetVisibleColumn <= breakingColumn) {
143+
let visibleColumn = prevBreakoffsetVisibleColumn;
144+
let prevCharCode = lineText.charCodeAt(prevBreakOffset - 1);
136145
let prevCharCodeClass = classifier.get(prevCharCode);
137-
let mustBreak = false;
138-
for (let i = initialBreakOffset; i < len; i++) {
146+
let entireLineFits = true;
147+
for (let i = prevBreakOffset; i < len; i++) {
139148
const charCode = lineText.charCodeAt(i);
140149
const charCodeClass = classifier.get(charCode);
141150

@@ -145,6 +154,7 @@ function createLineMapping(classifier: WrappingCharacterClassifier, previousBrea
145154
prevCharCode = charCode;
146155
prevCharCodeClass = charCodeClass;
147156
continue;
157+
148158
}
149159

150160
if (canBreak(prevCharCodeClass, charCodeClass)) {
@@ -157,48 +167,40 @@ function createLineMapping(classifier: WrappingCharacterClassifier, previousBrea
157167

158168
if (visibleColumn > breakingColumn) {
159169
// We need to break at least before character at `i`:
170+
forcedBreakOffset = i;
171+
forcedBreakOffsetVisibleColumn = visibleColumn - charWidth;
160172

161-
if (breakOffset === 0 || visibleColumn - breakOffsetVisibleColumn > wrappedLineBreakingColumn) {
162-
// Cannot break at `breakOffset`, must break at `i`
163-
breakOffset = i;
164-
breakOffsetVisibleColumn = visibleColumn - charWidth;
173+
if (visibleColumn - breakOffsetVisibleColumn > wrappedLineBreakingColumn) {
174+
// Cannot break at `breakOffset` => reset it if it was set
175+
breakOffset = 0;
165176
}
166177

167-
mustBreak = true;
178+
entireLineFits = false;
168179
break;
169180
}
170181

171182
prevCharCode = charCode;
172183
prevCharCodeClass = charCodeClass;
173184
}
174185

175-
if (!mustBreak) {
186+
if (entireLineFits) {
176187
// there is no more need to break => stop the outer loop!
177188
// Add last segment
178189
breakingOffsets[breakingOffsetsCount] = prevBreakingOffsets[prevBreakingOffsets.length - 1];
179190
breakingOffsetsVisibleColumn[breakingOffsetsCount] = prevBreakingOffsetsVisibleColumn[prevBreakingOffsets.length - 1];
180191
break;
181192
}
193+
}
182194

183-
breakingOffsets[breakingOffsetsCount] = breakOffset;
184-
breakingOffsetsVisibleColumn[breakingOffsetsCount] = breakOffsetVisibleColumn;
185-
breakingOffsetsCount++;
186-
breakingColumn = breakOffsetVisibleColumn + wrappedLineBreakingColumn;
187-
prevIndex++;
188-
} else if (breakOffsetVisibleColumn > breakingColumn) {
189-
const initialBreakOffset = breakOffset;
190-
let visibleColumn = breakOffsetVisibleColumn;
191-
breakOffset = 0;
192-
193-
let charCode = lineText.charCodeAt(initialBreakOffset);
195+
if (breakOffset === 0) {
196+
// must search left
197+
let visibleColumn = prevBreakoffsetVisibleColumn;
198+
let charCode = lineText.charCodeAt(prevBreakOffset);
194199
let charCodeClass = classifier.get(charCode);
195-
let hitTab = false;
196-
197-
let firstValidBreakOffset = 0;
198-
let firstValidBreakOffsetVisibleColumn = 0;
199-
for (let i = initialBreakOffset - 1; i >= 0; i--) {
200-
let prevCharCode = lineText.charCodeAt(i);
201-
let prevCharCodeClass = classifier.get(prevCharCode);
200+
let hitATabCharacter = false;
201+
for (let i = prevBreakOffset - 1; i >= 0; i--) {
202+
const prevCharCode = lineText.charCodeAt(i);
203+
const prevCharCodeClass = classifier.get(prevCharCode);
202204

203205
if (strings.isHighSurrogate(prevCharCode)) {
204206
// A surrogate pair must always be considered as a single unit, so it is never to be broken
@@ -210,16 +212,16 @@ function createLineMapping(classifier: WrappingCharacterClassifier, previousBrea
210212

211213
if (prevCharCode === CharCode.Tab) {
212214
// cannot determine the width of a tab when going backwards, so we must go forwards
213-
hitTab = true;
215+
hitATabCharacter = true;
214216
break;
215217
}
216218

217219
const charWidth = (strings.isFullWidthCharacter(prevCharCode) ? columnsForFullWidthChar : 1);
218220

219221
if (visibleColumn <= breakingColumn) {
220-
if (firstValidBreakOffset === 0) {
221-
firstValidBreakOffset = i + 1;
222-
firstValidBreakOffsetVisibleColumn = visibleColumn;
222+
if (forcedBreakOffset === 0) {
223+
forcedBreakOffset = i + 1;
224+
forcedBreakOffsetVisibleColumn = visibleColumn;
223225
}
224226

225227
if (visibleColumn <= breakingColumn - wrappedLineBreakingColumn) {
@@ -239,36 +241,37 @@ function createLineMapping(classifier: WrappingCharacterClassifier, previousBrea
239241
charCodeClass = prevCharCodeClass;
240242
}
241243

242-
if (hitTab) {
243-
// cannot determine the width of a tab when going backwards, so we must go forwards
244+
if (hitATabCharacter) {
245+
// cannot determine the width of a tab when going backwards, so we must go forwards from the previous break
244246
prevIndex--;
245247
continue;
246248
}
249+
}
247250

248-
if (breakOffset === 0) {
249-
// Could not find a good breaking point
250-
breakOffset = firstValidBreakOffset;
251-
breakOffsetVisibleColumn = firstValidBreakOffsetVisibleColumn;
252-
}
251+
if (breakOffset === 0) {
252+
// Could not find a good breaking point
253+
breakOffset = forcedBreakOffset;
254+
breakOffsetVisibleColumn = forcedBreakOffsetVisibleColumn;
255+
}
256+
257+
breakingOffsets[breakingOffsetsCount] = breakOffset;
258+
breakingOffsetsVisibleColumn[breakingOffsetsCount] = breakOffsetVisibleColumn;
259+
breakingOffsetsCount++;
260+
breakingColumn = breakOffsetVisibleColumn + wrappedLineBreakingColumn;
253261

254-
breakingOffsets[breakingOffsetsCount] = breakOffset;
255-
breakingOffsetsVisibleColumn[breakingOffsetsCount] = breakOffsetVisibleColumn;
256-
breakingOffsetsCount++;
257-
breakingColumn = breakOffsetVisibleColumn + wrappedLineBreakingColumn;
262+
while (prevIndex < 0 || (prevIndex < prevLen && prevBreakingOffsetsVisibleColumn[prevIndex] < breakOffsetVisibleColumn)) {
263+
prevIndex++;
258264
}
259265

260-
if (prevIndex < 0) {
261-
prevIndex = 0;
262-
} else {
263-
let currentDiff = Math.abs(prevBreakingOffsetsVisibleColumn[prevIndex] - breakingColumn);
264-
while (prevIndex + 1 < prevLen) {
265-
const potentialDiff = Math.abs(prevBreakingOffsetsVisibleColumn[prevIndex + 1] - breakingColumn);
266-
if (potentialDiff >= currentDiff) {
267-
break;
268-
}
269-
currentDiff = potentialDiff;
270-
prevIndex++;
266+
let currentDiff = Math.abs(prevBreakingOffsetsVisibleColumn[prevIndex] - breakingColumn);
267+
// let lastBreakingColumn
268+
while (prevIndex + 1 < prevLen) {
269+
const potentialDiff = Math.abs(prevBreakingOffsetsVisibleColumn[prevIndex + 1] - breakingColumn);
270+
if (potentialDiff >= currentDiff) {
271+
break;
271272
}
273+
currentDiff = potentialDiff;
274+
prevIndex++;
272275
}
273276
}
274277

@@ -284,11 +287,19 @@ function createLineMapping(classifier: WrappingCharacterClassifier, previousBrea
284287
} catch (err) {
285288
console.log(`BREAKING!!`);
286289
console.log(err);
290+
console.log(`previous breaks: ${JSON.stringify(prevBreakingOffsets)}, breakingOffsetsVisibleColumn: ${JSON.stringify(prevBreakingOffsetsVisibleColumn)}`);
291+
console.log(`expected breakOffsets: ${JSON.stringify(expected?.breakOffsets)}, breakingOffsetsVisibleColumn: ${JSON.stringify(expected?.breakingOffsetsVisibleColumn)}`);
292+
console.log(`actual breakOffsets: ${JSON.stringify(actual?.breakOffsets)}, breakingOffsetsVisibleColumn: ${JSON.stringify(actual?.breakingOffsetsVisibleColumn)}`);
293+
294+
console.log(`actual str: ${toAnnotatedText(lineText, actual)}`);
295+
296+
287297
console.log(`
288298
assertIncrementalLineMapping(
289299
factory, ${str(lineText)}, 4,
290300
${previousBreakingData.breakingColumn}, ${str(toAnnotatedText(lineText, previousBreakingData))},
291-
${expected!.breakingColumn}, ${str(toAnnotatedText(lineText, expected))}
301+
${expected!.breakingColumn}, ${str(toAnnotatedText(lineText, expected))},
302+
WrappingIndent.${hardWrappingIndent === WrappingIndent.None ? 'None' : hardWrappingIndent === WrappingIndent.Same ? 'Same' : hardWrappingIndent === WrappingIndent.Indent ? 'Indent' : 'DeepIndent'}
292303
);
293304
`);
294305
function str(strr: string) {
@@ -381,6 +392,8 @@ function createLineMapping(classifier: WrappingCharacterClassifier, previousBrea
381392
return new LineBreakingData(firstLineBreakingColumn, breakingOffsets, breakingOffsetsVisibleColumn, wrappedTextIndentLength);
382393
}
383394

395+
function
396+
384397
// class BreakSearchResult {
385398

386399
// public static INSTANCE = new BreakSearchResult();

src/vs/editor/test/common/viewModel/characterHardWrappingLineMapper.test.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,13 @@ suite('Editor ViewModel - CharacterHardWrappingLineMapper', () => {
147147
57, 'An his legere persecuti, oblique delicata efficiantur ex |vix, vel at graecis officiis maluisset. Et per impedit |voluptua, usu discere maiorum at. Ut assum ornatus |temporibus vis, an sea melius pericula. Ea dicunt |oblique phaedrum nam, eu duo movet nobis. His melius |facilis eu, vim malorum temporibus ne. Nec no sale |regione, meliore civibus placerat id eam. Mea alii |fabulas definitionem te, agam volutpat ad vis, et per |bonorum nonumes repudiandae.',
148148
58, 'An his legere persecuti, oblique delicata efficiantur ex |vix, vel at graecis officiis maluisset. Et per impedit |voluptua, usu discere maiorum at. Ut assum ornatus |temporibus vis, an sea melius pericula. Ea dicunt oblique |phaedrum nam, eu duo movet nobis. His melius facilis eu, |vim malorum temporibus ne. Nec no sale regione, meliore |civibus placerat id eam. Mea alii fabulas definitionem te,| agam volutpat ad vis, et per bonorum nonumes repudiandae.'
149149
);
150+
151+
assertIncrementalLineMapping(
152+
factory, '\t\t"owner": "vscode",', 4,
153+
14, '\t\t"owner|": |"vscod|e",',
154+
16, '\t\t"owner":| |"vscode"|,',
155+
WrappingIndent.Same
156+
);
150157
});
151158

152159

0 commit comments

Comments
 (0)