From 1d5ed92d34e34c8392a5f229e9c0f5081738f813 Mon Sep 17 00:00:00 2001 From: Kai Saba Date: Fri, 13 Dec 2024 09:48:43 +0100 Subject: [PATCH 1/4] fix: format Windows and old Mac line breaks to enable copy-paste --- .../editorOperationUtils/lockedCode.test.ts | 47 +++++++++++++++++++ src/tools/utils/editorOperationUtils.ts | 3 +- src/tools/utils/stringUtils.ts | 3 ++ 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 src/tools/utils/stringUtils.ts diff --git a/src/tests/editorOperationUtils/lockedCode.test.ts b/src/tests/editorOperationUtils/lockedCode.test.ts index 0dc187e..646778d 100644 --- a/src/tests/editorOperationUtils/lockedCode.test.ts +++ b/src/tests/editorOperationUtils/lockedCode.test.ts @@ -1,3 +1,4 @@ +/* eslint-disable quotes */ import { describe, expect, test, beforeEach, afterEach, jest } from '@jest/globals' import * as monaco from 'monaco-editor' import { DisposableStore } from 'vscode/monaco' @@ -356,4 +357,50 @@ function findLargest(numbers: number[]): number { text: '' }) }) + + test('Handle all systems line break character', () => { + const model = createDefaultTestModel() + disposableStore.add(model) + const editor = monaco.editor.create(document.createElement('div'), { + model + }) + disposableStore.add(editor) + disposableStore.add(lockCodeRanges(editor, { + getLockedRanges () { + return createDefaultTestLockedCodeRanges(model) + } + })) + + const operationRange = createTestRange(model, 12, 22) + const operation = createTestOperation(operationRange, + "/* Ignore and do not change the code below */\n" + + "// toto\r\n" + + "/* Ignore and do not change the code above */\n" + + "\n" + + "// new comment\r\n" + + "// on two lines\r" + + "\n" + + "/* Ignore and do not change the code below */\r\n" + + "// toto\r" + + "/* Ignore and do not change the code above */\n" + + "\n" + + "// other comment\n" + ) + + const onDidChangeContent = jest.fn() + disposableStore.add(model.onDidChangeContent(onDidChangeContent)) + + editor.executeEdits(null, [operation]) + + expect(onDidChangeContent).toHaveBeenCalledTimes(1) + expect(onDidChangeContent.mock.calls[0]![0]).toMatchObject({ + changes: [{ + range: { startLineNumber: 21, startColumn: 1, endLineNumber: 22, endColumn: 24 }, + text: '\n// other comment\n' + }, { + range: { startLineNumber: 15, startColumn: 1, endLineNumber: 17, endColumn: 1 }, + text: '\n// new comment\n// on two lines' + }] + }) + }) }) diff --git a/src/tools/utils/editorOperationUtils.ts b/src/tools/utils/editorOperationUtils.ts index a3e4a6d..4c4db1a 100644 --- a/src/tools/utils/editorOperationUtils.ts +++ b/src/tools/utils/editorOperationUtils.ts @@ -1,6 +1,7 @@ import * as monaco from 'monaco-editor' import { ValidAnnotatedEditOperation } from 'vscode/vscode/vs/editor/common/model' import { excludeRanges } from './rangeUtils' +import { normalizeStringLineBreaks } from './stringUtils' export class LockedCodeError extends Error {} @@ -50,7 +51,7 @@ function tryIgnoreLockedCodeTextForOperation ( const splitText: string[] = [] const uneditableRangesText = uneditableRangesInOperationRange.map(range => model.getValueInRange(range)) let currentRange: number = 0 - let remainingText: string = operationText + let remainingText: string = normalizeStringLineBreaks(operationText) while (remainingText.length > 0 && currentRange < uneditableRangesText.length) { const rangeText = uneditableRangesText[currentRange] if (rangeText != null && rangeText !== '') { diff --git a/src/tools/utils/stringUtils.ts b/src/tools/utils/stringUtils.ts new file mode 100644 index 0000000..7091cb0 --- /dev/null +++ b/src/tools/utils/stringUtils.ts @@ -0,0 +1,3 @@ +export function normalizeStringLineBreaks (str: string, lineBreakCharacter: string = '\n'): string { + return str.replaceAll(/\r?\n|\r/g, lineBreakCharacter) +} From 1d3e741ad4737773148d124352e3df0e1a7e4104 Mon Sep 17 00:00:00 2001 From: Kai Saba Date: Fri, 13 Dec 2024 10:51:59 +0100 Subject: [PATCH 2/4] fix: don't change selection for locked code if only moving cursor --- src/tools.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools.ts b/src/tools.ts index 9684c8a..17219a5 100644 --- a/src/tools.ts +++ b/src/tools.ts @@ -177,7 +177,7 @@ export function lockCodeRanges ( // Handle selection of the last line of an editable range disposableStore.add( editor.onDidChangeCursorSelection((e) => { - if (canEditRange(e.selection)) { + if (canEditRange(e.selection) || e.selection.isEmpty()) { return } const model = editor.getModel() From 8a292348b4861e96756165260ed6c9129688dddd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= Date: Fri, 13 Dec 2024 12:01:14 +0100 Subject: [PATCH 3/4] fix: do not disable rule --- .../editorOperationUtils/lockedCode.test.ts | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/tests/editorOperationUtils/lockedCode.test.ts b/src/tests/editorOperationUtils/lockedCode.test.ts index 646778d..0c07e01 100644 --- a/src/tests/editorOperationUtils/lockedCode.test.ts +++ b/src/tests/editorOperationUtils/lockedCode.test.ts @@ -1,4 +1,3 @@ -/* eslint-disable quotes */ import { describe, expect, test, beforeEach, afterEach, jest } from '@jest/globals' import * as monaco from 'monaco-editor' import { DisposableStore } from 'vscode/monaco' @@ -373,18 +372,18 @@ function findLargest(numbers: number[]): number { const operationRange = createTestRange(model, 12, 22) const operation = createTestOperation(operationRange, - "/* Ignore and do not change the code below */\n" + - "// toto\r\n" + - "/* Ignore and do not change the code above */\n" + - "\n" + - "// new comment\r\n" + - "// on two lines\r" + - "\n" + - "/* Ignore and do not change the code below */\r\n" + - "// toto\r" + - "/* Ignore and do not change the code above */\n" + - "\n" + - "// other comment\n" + '/* Ignore and do not change the code below */\n' + + '// toto\r\n' + + '/* Ignore and do not change the code above */\n' + + '\n' + + '// new comment\r\n' + + '// on two lines\r' + + '\n' + + '/* Ignore and do not change the code below */\r\n' + + '// toto\r' + + '/* Ignore and do not change the code above */\n' + + '\n' + + '// other comment\n' ) const onDidChangeContent = jest.fn() From 5da9691577061e54ad328e6be855192ec989a469 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= Date: Fri, 13 Dec 2024 12:01:24 +0100 Subject: [PATCH 4/4] fix: use model EOL --- src/tools/utils/editorOperationUtils.ts | 2 +- src/tools/utils/stringUtils.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tools/utils/editorOperationUtils.ts b/src/tools/utils/editorOperationUtils.ts index 4c4db1a..08f71c9 100644 --- a/src/tools/utils/editorOperationUtils.ts +++ b/src/tools/utils/editorOperationUtils.ts @@ -51,7 +51,7 @@ function tryIgnoreLockedCodeTextForOperation ( const splitText: string[] = [] const uneditableRangesText = uneditableRangesInOperationRange.map(range => model.getValueInRange(range)) let currentRange: number = 0 - let remainingText: string = normalizeStringLineBreaks(operationText) + let remainingText: string = normalizeStringLineBreaks(operationText, model.getEOL()) while (remainingText.length > 0 && currentRange < uneditableRangesText.length) { const rangeText = uneditableRangesText[currentRange] if (rangeText != null && rangeText !== '') { diff --git a/src/tools/utils/stringUtils.ts b/src/tools/utils/stringUtils.ts index 7091cb0..ef235c2 100644 --- a/src/tools/utils/stringUtils.ts +++ b/src/tools/utils/stringUtils.ts @@ -1,3 +1,3 @@ -export function normalizeStringLineBreaks (str: string, lineBreakCharacter: string = '\n'): string { - return str.replaceAll(/\r?\n|\r/g, lineBreakCharacter) +export function normalizeStringLineBreaks (str: string, lineBreakCharacter: string): string { + return str.replace(/\r\n|\r|\n/g, lineBreakCharacter) }