mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-15 02:59:33 +07:00
fixed PY-9337 Copy paste doesn't always preserve the relative indentation of what is pasted.
check if we need to add leading spaces to pasted text
This commit is contained in:
@@ -10,6 +10,7 @@ import com.intellij.openapi.util.text.StringUtil;
|
|||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import com.intellij.psi.PsiFile;
|
import com.intellij.psi.PsiFile;
|
||||||
import com.intellij.psi.PsiWhiteSpace;
|
import com.intellij.psi.PsiWhiteSpace;
|
||||||
|
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||||
import com.intellij.psi.tree.IElementType;
|
import com.intellij.psi.tree.IElementType;
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
@@ -44,13 +45,15 @@ public class PythonCopyPasteProcessor implements CopyPastePreProcessor {
|
|||||||
if (!CodeInsightSettings.getInstance().INDENT_TO_CARET_ON_PASTE) {
|
if (!CodeInsightSettings.getInstance().INDENT_TO_CARET_ON_PASTE) {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
final boolean useTabs =
|
final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(project);
|
||||||
CodeStyleSettingsManager.getSettings(project).useTabCharacter(PythonFileType.INSTANCE);
|
final boolean useTabs = codeStyleSettings.useTabCharacter(PythonFileType.INSTANCE);
|
||||||
|
final int indentSize = codeStyleSettings.getIndentSize(PythonFileType.INSTANCE);
|
||||||
CharFilter NOT_INDENT_FILTER = new CharFilter() {
|
CharFilter NOT_INDENT_FILTER = new CharFilter() {
|
||||||
public boolean accept(char ch) {
|
public boolean accept(char ch) {
|
||||||
return useTabs? ch != '\t' : ch != ' ';
|
return useTabs? ch != '\t' : ch != ' ';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
final String indentChar = useTabs ? "\t" : " ";
|
||||||
|
|
||||||
final CaretModel caretModel = editor.getCaretModel();
|
final CaretModel caretModel = editor.getCaretModel();
|
||||||
final SelectionModel selectionModel = editor.getSelectionModel();
|
final SelectionModel selectionModel = editor.getSelectionModel();
|
||||||
@@ -60,6 +63,7 @@ public class PythonCopyPasteProcessor implements CopyPastePreProcessor {
|
|||||||
final int lineNumber = document.getLineNumber(caretOffset);
|
final int lineNumber = document.getLineNumber(caretOffset);
|
||||||
final int lineStartOffset = getLineStartSafeOffset(document, lineNumber);
|
final int lineStartOffset = getLineStartSafeOffset(document, lineNumber);
|
||||||
|
|
||||||
|
text = addLeadingSpaces(text, NOT_INDENT_FILTER, indentSize, indentChar);
|
||||||
final String indentText = getIndentText(file, document, caretOffset, lineNumber);
|
final String indentText = getIndentText(file, document, caretOffset, lineNumber);
|
||||||
|
|
||||||
int toRemove = calculateIndentToRemove(text, NOT_INDENT_FILTER);
|
int toRemove = calculateIndentToRemove(text, NOT_INDENT_FILTER);
|
||||||
@@ -72,7 +76,7 @@ public class PythonCopyPasteProcessor implements CopyPastePreProcessor {
|
|||||||
String newText = "";
|
String newText = "";
|
||||||
if (StringUtil.isEmptyOrSpaces(indentText)) {
|
if (StringUtil.isEmptyOrSpaces(indentText)) {
|
||||||
for (String s : strings) {
|
for (String s : strings) {
|
||||||
newText += indentText + StringUtil.trimStart(s, StringUtil.repeat(useTabs? "\t" : " ", toRemove));
|
newText += indentText + StringUtil.trimStart(s, StringUtil.repeat(indentChar, toRemove));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -85,6 +89,19 @@ public class PythonCopyPasteProcessor implements CopyPastePreProcessor {
|
|||||||
return newText;
|
return newText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String addLeadingSpaces(String text, final CharFilter filter, int indentSize, String indentChar) {
|
||||||
|
final List<String> strings = StringUtil.split(text, "\n", false);
|
||||||
|
if (strings.size() > 1) {
|
||||||
|
int firstLineIndent = StringUtil.findFirst(strings.get(0), filter);
|
||||||
|
int secondLineIndent = StringUtil.findFirst(strings.get(1), filter);
|
||||||
|
final int diff = secondLineIndent - firstLineIndent;
|
||||||
|
if (diff > indentSize) {
|
||||||
|
text = StringUtil.repeat(indentChar, diff - indentSize) + text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
private static String getIndentText(@NotNull final PsiFile file,
|
private static String getIndentText(@NotNull final PsiFile file,
|
||||||
@NotNull final Document document,
|
@NotNull final Document document,
|
||||||
int caretOffset,
|
int caretOffset,
|
||||||
@@ -143,13 +160,9 @@ public class PythonCopyPasteProcessor implements CopyPastePreProcessor {
|
|||||||
|
|
||||||
private static boolean inStatementList(@NotNull final PsiFile file, int caretOffset) {
|
private static boolean inStatementList(@NotNull final PsiFile file, int caretOffset) {
|
||||||
final PsiElement element = file.findElementAt(caretOffset);
|
final PsiElement element = file.findElementAt(caretOffset);
|
||||||
final PsiElement element1 = file.findElementAt(caretOffset);
|
|
||||||
return PsiTreeUtil.getParentOfType(element, PyStatementList.class) != null ||
|
return PsiTreeUtil.getParentOfType(element, PyStatementList.class) != null ||
|
||||||
PsiTreeUtil.getParentOfType(element1, PyStatementList.class) != null ||
|
|
||||||
PsiTreeUtil.getParentOfType(element, PyFunction.class) != null ||
|
PsiTreeUtil.getParentOfType(element, PyFunction.class) != null ||
|
||||||
PsiTreeUtil.getParentOfType(element1, PyFunction.class) != null ||
|
PsiTreeUtil.getParentOfType(element, PyClass.class) != null;
|
||||||
PsiTreeUtil.getParentOfType(element, PyClass.class) != null ||
|
|
||||||
PsiTreeUtil.getParentOfType(element1, PyClass.class) != null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean addLinebreak(@NotNull String text, @NotNull String toString, boolean useTabs) {
|
private static boolean addLinebreak(@NotNull String text, @NotNull String toString, boolean useTabs) {
|
||||||
|
|||||||
15
python/testData/copyPaste/InnerToOuterFunction.after.py
Normal file
15
python/testData/copyPaste/InnerToOuterFunction.after.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# original function # this is line 1 of the code.
|
||||||
|
def foo():
|
||||||
|
print 'f00'
|
||||||
|
def bar(num):
|
||||||
|
for _ in range(num):
|
||||||
|
print 'bar'
|
||||||
|
bar(7)
|
||||||
|
|
||||||
|
|
||||||
|
def bar(num):
|
||||||
|
for _ in range(num):
|
||||||
|
print 'bar'
|
||||||
|
|
||||||
|
|
||||||
|
bar(7)
|
||||||
9
python/testData/copyPaste/InnerToOuterFunction.dst.py
Normal file
9
python/testData/copyPaste/InnerToOuterFunction.dst.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# original function # this is line 1 of the code.
|
||||||
|
def foo():
|
||||||
|
print 'f00'
|
||||||
|
def bar(num):
|
||||||
|
for _ in range(num):
|
||||||
|
print 'bar'
|
||||||
|
bar(7)
|
||||||
|
|
||||||
|
<caret>
|
||||||
10
python/testData/copyPaste/InnerToOuterFunction.src.py
Normal file
10
python/testData/copyPaste/InnerToOuterFunction.src.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# original function # this is line 1 of the code.
|
||||||
|
def foo():
|
||||||
|
print 'f00'
|
||||||
|
<selection>def bar(num):
|
||||||
|
for _ in range(num):
|
||||||
|
print 'bar'
|
||||||
|
bar(7)</selection><caret>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -297,6 +297,10 @@ public class PyCopyPasteTest extends PyTestCase {
|
|||||||
doTest();
|
doTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testInnerToOuterFunction() {
|
||||||
|
doTest();
|
||||||
|
}
|
||||||
|
|
||||||
private void doTestTabs() {
|
private void doTestTabs() {
|
||||||
final CommonCodeStyleSettings.IndentOptions indentOptions =
|
final CommonCodeStyleSettings.IndentOptions indentOptions =
|
||||||
CodeStyleSettingsManager.getSettings(myFixture.getProject()).getIndentOptions(PythonFileType.INSTANCE);
|
CodeStyleSettingsManager.getSettings(myFixture.getProject()).getIndentOptions(PythonFileType.INSTANCE);
|
||||||
|
|||||||
Reference in New Issue
Block a user