Skip to content

Commit c291e16

Browse files
committed
refactor: split editable ranges and operation text separately
1 parent 8faaeb6 commit c291e16

1 file changed

Lines changed: 60 additions & 81 deletions

File tree

src/tools/utils/editorOperationUtils.ts

Lines changed: 60 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -21,83 +21,71 @@ function createNewOperation (
2121
)
2222
}
2323

24-
function getLockedRangeValueIndexesInText (
25-
editor: monaco.editor.ICodeEditor,
26-
range: monaco.Range,
27-
text: string
28-
): {
29-
startIndex: number | null
30-
endIndex: number | null
31-
} {
32-
const model = editor.getModel()
33-
if (model == null) {
34-
return { startIndex: null, endIndex: null }
24+
function createNewOperationsFromRanges (
25+
oldOperation: ValidAnnotatedEditOperation,
26+
editableRanges: monaco.Range[],
27+
splitText: (string | null)[]
28+
): ValidAnnotatedEditOperation[] {
29+
if (editableRanges.length <= 0) {
30+
return []
3531
}
3632

37-
const rangeValue = model.getValueInRange(range)
38-
const startIndex = text.indexOf(rangeValue)
39-
return {
40-
startIndex,
41-
endIndex: startIndex + rangeValue.length
33+
if (splitText.length === 1) {
34+
return [createNewOperation(oldOperation, oldOperation.range, splitText[0] ?? null, 0)]
4235
}
36+
37+
return splitText.map((text, index) => createNewOperation(oldOperation, editableRanges[index]!, text, index))
4338
}
4439

45-
function computeNewOperationsWithIntersectingLockedCode (
40+
function splitOperationText (
4641
editor: monaco.editor.ICodeEditor,
47-
operation: ValidAnnotatedEditOperation,
48-
uneditableRanges: monaco.Range[]
49-
): ValidAnnotatedEditOperation[] {
50-
const newOperations: ValidAnnotatedEditOperation[] = []
51-
const editableRanges: monaco.Range[] = minusRanges(operation.range, uneditableRanges)
52-
53-
// Index of the current uneditable range in the text
54-
let uneditableRangeIndex: number = 0
55-
// Index of the current editable range in the text
56-
let editableRangeIndex: number = 0
57-
// The operation text is null or an empty string when it's a delete
58-
let remainingText: string = operation.text ?? ''
42+
uneditableRanges: monaco.Range[],
43+
text: string | null
44+
): (string | null)[] {
45+
if (text == null || text === '') {
46+
return [text]
47+
}
5948

60-
do {
61-
const editableRange = editableRanges[editableRangeIndex]
62-
if (editableRange == null) {
63-
// There are no editable ranges left
64-
return newOperations
65-
}
49+
const model = editor.getModel()
50+
if (model == null) {
51+
return []
52+
}
6653

67-
const uneditableRange = uneditableRanges[uneditableRangeIndex]
68-
if (uneditableRange == null) {
69-
// There are no more locked ranges
70-
return [
71-
...newOperations,
72-
createNewOperation(operation, editableRange, remainingText, editableRangeIndex)
73-
]
54+
const splitText: string[] = []
55+
const uneditableRangesText = uneditableRanges.map(range => model.getValueInRange(range))
56+
let currentRange: number = 0
57+
let textToSplit: string | undefined = text
58+
while (textToSplit != null && textToSplit !== '' && currentRange < uneditableRangesText.length) {
59+
const rangeText = uneditableRangesText[currentRange]
60+
if (rangeText != null && rangeText !== '') {
61+
const result: string[] = textToSplit.split(rangeText)
62+
splitText.push(result[0]!)
63+
textToSplit = result[1]
7464
}
65+
currentRange++
66+
}
7567

76-
const { startIndex, endIndex } = getLockedRangeValueIndexesInText(editor, uneditableRange, remainingText)
77-
if (startIndex == null || endIndex == null) {
78-
return newOperations
79-
} else if (startIndex === -1) {
80-
// The uneditable text is not in the remaining operation text
81-
return [
82-
...newOperations,
83-
createNewOperation(operation, editableRange, remainingText, editableRangeIndex)
84-
]
85-
// remainingText = null
86-
} else if (startIndex === 0) {
87-
// The uneditable text is at the beginning of the remaining operation text
88-
uneditableRangeIndex++
89-
remainingText = remainingText.slice(endIndex)
90-
} else {
91-
// The uneditable text is in the middle or at the end of the remaining operation text
92-
newOperations.push(
93-
createNewOperation(operation, editableRange, remainingText.slice(0, startIndex), editableRangeIndex)
94-
)
95-
uneditableRangeIndex++
96-
editableRangeIndex++
97-
remainingText = remainingText.slice(endIndex)
98-
}
99-
} while (remainingText.length > 0)
68+
if (textToSplit != null && textToSplit !== '') {
69+
splitText.push(textToSplit)
70+
}
71+
return splitText
72+
}
10073

74+
function splitOperationsForLockedCode (
75+
editor: monaco.editor.ICodeEditor,
76+
operations: ValidAnnotatedEditOperation[],
77+
uneditableRanges: monaco.Range[]
78+
): ValidAnnotatedEditOperation[] {
79+
let newOperations: ValidAnnotatedEditOperation[] = []
80+
for (const operation of operations) {
81+
const operationEditableRanges: monaco.Range[] = minusRanges(operation.range, uneditableRanges)
82+
const operationUneditableRanges: monaco.Range[] = minusRanges(operation.range, operationEditableRanges)
83+
const splitText = splitOperationText(editor, operationUneditableRanges, operation.text)
84+
newOperations = [
85+
...newOperations,
86+
...createNewOperationsFromRanges(operation, operationEditableRanges, splitText)
87+
]
88+
}
10189
return newOperations
10290
}
10391

@@ -107,24 +95,15 @@ export function computeNewOperationsForLockedCode (
10795
editorOperations: ValidAnnotatedEditOperation[],
10896
withDecoration: boolean
10997
): ValidAnnotatedEditOperation[] {
98+
const model = editor.getModel()
99+
if (model == null) {
100+
return []
101+
}
102+
110103
const uneditableRanges = getLockedRanges(editor, decorationFilter, withDecoration)
111104
if (uneditableRanges.length <= 0) {
112105
return editorOperations
113106
}
114107

115-
const newOperations: ValidAnnotatedEditOperation[] = []
116-
for (const operation of editorOperations) {
117-
const operationRange = operation.range
118-
const uneditableRangesThatIntersects = uneditableRanges.filter(range => monaco.Range.areIntersecting(range, operationRange))
119-
120-
if (uneditableRangesThatIntersects.length <= 0) {
121-
// The operation range doesn't intersect with an uneditable range
122-
newOperations.push(operation)
123-
} else {
124-
// The operation range intersects with one or more uneditable range
125-
newOperations.push(...computeNewOperationsWithIntersectingLockedCode(editor, operation, uneditableRangesThatIntersects))
126-
}
127-
}
128-
129-
return newOperations
108+
return splitOperationsForLockedCode(editor, editorOperations, uneditableRanges)
130109
}

0 commit comments

Comments
 (0)