Skip to content

Commit 93f784b

Browse files
fix: incorrect multiline autoindent (#1002)
Fixes #1000 Open to suggestions. I feel like there is no very good way of do this. This is the best I could come up with. If we want to preserve the relative indent, then we would just need to handle the midline paste case. Let me know what you think Thanks!
1 parent 25c9a99 commit 93f784b

2 files changed

Lines changed: 39 additions & 8 deletions

File tree

org.eclipse.tm4e.languageconfiguration.tests/src/main/java/org/eclipse/tm4e/languageconfiguration/tests/TestIndentationRules.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,18 @@ public void testIndentAdjustmentOnPaste() throws Exception {
5858
text.insert("function bar() {\n}");
5959
assertThat(text.getText()).isEqualTo("public class Foo {\n\tfunction bar() {\n\t}\n}");
6060

61+
// insert a code snippet with unindented first line and expect the snippet to be correctly indented
62+
text.setText("public class Foo {\n\n}");
63+
text.setSelection(19);
64+
text.insert("function bar() {\n\t\t\n\t}");
65+
assertThat(text.getText()).isEqualTo("public class Foo {\n\tfunction bar() {\n\t\t\n\t}\n}");
66+
67+
// insert an else code snippet with unindented first line after the if code snippet and expect the snippet to be correctly indented
68+
text.setText("public class Foo {\n\tfunction foo() {\n\t\tif (cond) {\n\t\t} \n\t}\n}");
69+
text.setSelection(55);
70+
text.insert("else {\n\t\t}");
71+
assertThat(text.getText()).isEqualTo("public class Foo {\n\tfunction foo() {\n\t\tif (cond) {\n\t\t} else {\n\t\t}\n\t}\n}");
72+
6173
// insert single line text and ensure the text is only indented in blank lines
6274
text.setText("public class Foo {\n\n}");
6375
text.setSelection(19);

org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/LanguageConfigurationAutoEditStrategy.java

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -163,17 +163,36 @@ && isFollowedBy(doc, command.offset, charPair.close))) {
163163

164164
final var newIndent = registry.getGoodIndentForLine(doc, lineIndex, contentType, IIndentConverter.of(cursorCfg));
165165
if (newIndent != null) {
166+
final var normalizedIndent = cursorCfg.normalizeIndentation(newIndent);
166167
final var lineStartOffset = doc.getLineOffset(lineIndex);
167-
168-
// check if the content was pasted into a line while the cursor was not at the beginning of the line
169-
// but inside or at the end of an existing line indentation
170168
final var offsetInLine = command.offset - lineStartOffset;
171-
if (offsetInLine > 0 && doc.get(lineStartOffset, offsetInLine).isBlank()) {
172-
command.offset = lineStartOffset;
173-
command.length += offsetInLine;
169+
final int firstNewline = command.text.indexOf('\n');
170+
171+
if (firstNewline >= 0) {
172+
final var firstLine = command.text.substring(0, firstNewline + 1);
173+
// Re-indent lines after the first line
174+
final var reindentedRest = TextUtils.replaceIndent(
175+
command.text.substring(firstNewline + 1), cursorCfg.indentSize, normalizedIndent, false);
176+
177+
if (offsetInLine > 0 && !doc.get(lineStartOffset, offsetInLine).isBlank()) {
178+
// Content was pasted midline after non-whitespace
179+
// First pasted line continues existing content, don't replace indentation
180+
command.text = firstLine + reindentedRest;
181+
} else {
182+
// Content was pasted at the start of the line, or preceded only by whitespace
183+
// Replace any existing leading whitespace with the correct indent
184+
if (offsetInLine > 0) {
185+
command.offset = lineStartOffset;
186+
command.length += offsetInLine;
187+
}
188+
command.text = normalizedIndent + firstLine.replaceFirst("^[ \\t]+", "") + reindentedRest;
189+
}
190+
} else {
191+
// Single-line paste: straightforward indent replacement
192+
command.text = TextUtils
193+
.replaceIndent(command.text, cursorCfg.indentSize, normalizedIndent, false)
194+
.toString();
174195
}
175-
command.text = TextUtils.replaceIndent(command.text, cursorCfg.indentSize,
176-
cursorCfg.normalizeIndentation(newIndent), false).toString();
177196
command.shiftsCaret = true;
178197
}
179198
}

0 commit comments

Comments
 (0)