diff --git a/python/src/com/jetbrains/python/editor/PythonCopyPasteProcessor.java b/python/src/com/jetbrains/python/editor/PythonCopyPasteProcessor.java index 62b8eadb8e40..49826cb049cd 100644 --- a/python/src/com/jetbrains/python/editor/PythonCopyPasteProcessor.java +++ b/python/src/com/jetbrains/python/editor/PythonCopyPasteProcessor.java @@ -2,18 +2,17 @@ package com.jetbrains.python.editor; import com.intellij.codeInsight.CodeInsightSettings; import com.intellij.codeInsight.editorActions.CopyPastePreProcessor; -import com.intellij.openapi.editor.CaretModel; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.RawText; +import com.intellij.openapi.editor.*; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.CharFilter; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiWhiteSpace; +import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtilCore; +import com.jetbrains.python.PythonFileType; import com.jetbrains.python.psi.PyFile; import com.jetbrains.python.psi.PyStringLiteralExpression; @@ -52,7 +51,18 @@ public class PythonCopyPasteProcessor implements CopyPastePreProcessor { if (StringUtil.countChars(text, '\n') > 0 || StringUtil.startsWithWhitespace(text)) { //2, 3, 4 case from doc final PsiElement element = PsiUtilCore.getElementAtOffset(file, caretOffset - 1); if (PsiTreeUtil.getParentOfType(element, PyStringLiteralExpression.class) != null) return text; - caretModel.moveToOffset(lineStartOffset); + + final SelectionModel selectionModel = editor.getSelectionModel(); + if (selectionModel.getSelectionStart() != selectionModel.getSelectionEnd()) { + final int line = document.getLineNumber(selectionModel.getSelectionStart()); + final int lineOffset = getLineStartSafeOffset(document, line); + final PsiElement ws = file.findElementAt(lineOffset); + int offset = ws instanceof PsiWhiteSpace? ws.getTextRange().getEndOffset() : lineOffset; + caretModel.moveToOffset(offset); + selectionModel.setSelection(offset, selectionModel.getSelectionEnd()); + } + else + caretModel.moveToOffset(lineStartOffset); String spaceString; int indent = 0; @@ -69,12 +79,17 @@ public class PythonCopyPasteProcessor implements CopyPastePreProcessor { if (indent < 0) indent = StringUtil.isEmptyOrSpaces(spaceString) ? spaceString.length() : 0; - final String trimmed = StringUtil.trimLeading(strings.get(0)); //decrease indent if needed - if (trimmed.startsWith("def ") || trimmed.startsWith("if ") || trimmed.startsWith("try:") || - trimmed.startsWith("class ") || trimmed.startsWith("for ") || trimmed.startsWith("elif ") || - trimmed.startsWith("else:") || trimmed.startsWith("except") || trimmed.startsWith("while ")) { - indent = StringUtil.findFirst(spaceString, CharFilter.NOT_WHITESPACE_FILTER) / 2; - if (indent < 0) indent = 0; + if (indent == CodeStyleSettingsManager.getSettings(project).getIndentSize(PythonFileType.INSTANCE)) { + indent = 0; + } + else { + final String trimmed = StringUtil.trimLeading(strings.get(0)); //decrease indent if needed + if (trimmed.startsWith("def ") || trimmed.startsWith("if ") || trimmed.startsWith("try:") || + trimmed.startsWith("class ") || trimmed.startsWith("for ") || trimmed.startsWith("elif ") || + trimmed.startsWith("else:") || trimmed.startsWith("except") || trimmed.startsWith("while ")) { + indent = StringUtil.findFirst(spaceString, CharFilter.NOT_WHITESPACE_FILTER) / 2; + if (indent < 0) indent = 0; + } } } } diff --git a/python/testData/copyPaste/Selection1.after.py b/python/testData/copyPaste/Selection1.after.py new file mode 100644 index 000000000000..3db8d323445a --- /dev/null +++ b/python/testData/copyPaste/Selection1.after.py @@ -0,0 +1,9 @@ + +if True: + a = 1 + b = 2 + +def f(): + if True: + a = 1 + b = 2 \ No newline at end of file diff --git a/python/testData/copyPaste/Selection1.dst.py b/python/testData/copyPaste/Selection1.dst.py new file mode 100644 index 000000000000..4b58920ffbcb --- /dev/null +++ b/python/testData/copyPaste/Selection1.dst.py @@ -0,0 +1,7 @@ + +if True: + a = 1 + b = 2 + +def f(): + c = 3 \ No newline at end of file diff --git a/python/testData/copyPaste/Selection1.src.py b/python/testData/copyPaste/Selection1.src.py new file mode 100644 index 000000000000..f9659c9f6340 --- /dev/null +++ b/python/testData/copyPaste/Selection1.src.py @@ -0,0 +1,7 @@ + +if True: + a = 1 + b = 2 + +def f(): + c = 3 \ No newline at end of file diff --git a/python/testData/copyPaste/Selection2.after.py b/python/testData/copyPaste/Selection2.after.py new file mode 100644 index 000000000000..3db8d323445a --- /dev/null +++ b/python/testData/copyPaste/Selection2.after.py @@ -0,0 +1,9 @@ + +if True: + a = 1 + b = 2 + +def f(): + if True: + a = 1 + b = 2 \ No newline at end of file diff --git a/python/testData/copyPaste/Selection2.dst.py b/python/testData/copyPaste/Selection2.dst.py new file mode 100644 index 000000000000..b35eab3629eb --- /dev/null +++ b/python/testData/copyPaste/Selection2.dst.py @@ -0,0 +1,7 @@ + +if True: + a = 1 + b = 2 + +def f(): + c = 3 \ No newline at end of file diff --git a/python/testData/copyPaste/Selection2.src.py b/python/testData/copyPaste/Selection2.src.py new file mode 100644 index 000000000000..f9659c9f6340 --- /dev/null +++ b/python/testData/copyPaste/Selection2.src.py @@ -0,0 +1,7 @@ + +if True: + a = 1 + b = 2 + +def f(): + c = 3 \ No newline at end of file diff --git a/python/testData/copyPaste/Selection3.after.py b/python/testData/copyPaste/Selection3.after.py new file mode 100644 index 000000000000..224eea87ee5f --- /dev/null +++ b/python/testData/copyPaste/Selection3.after.py @@ -0,0 +1,8 @@ +if True: + a = 1 + b = 2 + +def f(): + if True: + a = 1 + b = 2 diff --git a/python/testData/copyPaste/Selection3.dst.py b/python/testData/copyPaste/Selection3.dst.py new file mode 100644 index 000000000000..0c35503621d5 --- /dev/null +++ b/python/testData/copyPaste/Selection3.dst.py @@ -0,0 +1,7 @@ +if True: + a = 1 + b = 2 + +def f(): + c = 3 + \ No newline at end of file diff --git a/python/testData/copyPaste/Selection3.src.py b/python/testData/copyPaste/Selection3.src.py new file mode 100644 index 000000000000..f9659c9f6340 --- /dev/null +++ b/python/testData/copyPaste/Selection3.src.py @@ -0,0 +1,7 @@ + +if True: + a = 1 + b = 2 + +def f(): + c = 3 \ No newline at end of file diff --git a/python/testData/copyPaste/SelectionReverse1.after.py b/python/testData/copyPaste/SelectionReverse1.after.py new file mode 100644 index 000000000000..e5f402ade765 --- /dev/null +++ b/python/testData/copyPaste/SelectionReverse1.after.py @@ -0,0 +1,10 @@ + +if True: + a = 1 + b = 2 + +def f(): + if True: + a = 1 + b = 2 + diff --git a/python/testData/copyPaste/SelectionReverse1.dst.py b/python/testData/copyPaste/SelectionReverse1.dst.py new file mode 100644 index 000000000000..cd914e1332c1 --- /dev/null +++ b/python/testData/copyPaste/SelectionReverse1.dst.py @@ -0,0 +1,7 @@ + +if True: + a = 1 + b = 2 + +def f(): + c = 3 diff --git a/python/testData/copyPaste/SelectionReverse1.src.py b/python/testData/copyPaste/SelectionReverse1.src.py new file mode 100644 index 000000000000..f9659c9f6340 --- /dev/null +++ b/python/testData/copyPaste/SelectionReverse1.src.py @@ -0,0 +1,7 @@ + +if True: + a = 1 + b = 2 + +def f(): + c = 3 \ No newline at end of file diff --git a/python/testData/copyPaste/SelectionReverse2.after.py b/python/testData/copyPaste/SelectionReverse2.after.py new file mode 100644 index 000000000000..7c5d73080073 --- /dev/null +++ b/python/testData/copyPaste/SelectionReverse2.after.py @@ -0,0 +1,9 @@ + +if True: + a = 1 + b = 2 + +def f(): + if True: + a = 1 + b = 2 diff --git a/python/testData/copyPaste/SelectionReverse2.dst.py b/python/testData/copyPaste/SelectionReverse2.dst.py new file mode 100644 index 000000000000..290cc92f6940 --- /dev/null +++ b/python/testData/copyPaste/SelectionReverse2.dst.py @@ -0,0 +1,7 @@ + +if True: + a = 1 + b = 2 + +def f(): + c = 3 \ No newline at end of file diff --git a/python/testData/copyPaste/SelectionReverse2.src.py b/python/testData/copyPaste/SelectionReverse2.src.py new file mode 100644 index 000000000000..f9659c9f6340 --- /dev/null +++ b/python/testData/copyPaste/SelectionReverse2.src.py @@ -0,0 +1,7 @@ + +if True: + a = 1 + b = 2 + +def f(): + c = 3 \ No newline at end of file diff --git a/python/testData/copyPaste/SelectionReverse3.after.py b/python/testData/copyPaste/SelectionReverse3.after.py new file mode 100644 index 000000000000..7c5d73080073 --- /dev/null +++ b/python/testData/copyPaste/SelectionReverse3.after.py @@ -0,0 +1,9 @@ + +if True: + a = 1 + b = 2 + +def f(): + if True: + a = 1 + b = 2 diff --git a/python/testData/copyPaste/SelectionReverse3.dst.py b/python/testData/copyPaste/SelectionReverse3.dst.py new file mode 100644 index 000000000000..2a5eda88518b --- /dev/null +++ b/python/testData/copyPaste/SelectionReverse3.dst.py @@ -0,0 +1,8 @@ + +if True: + a = 1 + b = 2 + +def f(): + c = 3 + \ No newline at end of file diff --git a/python/testData/copyPaste/SelectionReverse3.src.py b/python/testData/copyPaste/SelectionReverse3.src.py new file mode 100644 index 000000000000..f9659c9f6340 --- /dev/null +++ b/python/testData/copyPaste/SelectionReverse3.src.py @@ -0,0 +1,7 @@ + +if True: + a = 1 + b = 2 + +def f(): + c = 3 \ No newline at end of file diff --git a/python/testData/copyPaste/multiLine/IndentInnerFunction1.after.py b/python/testData/copyPaste/multiLine/IndentInnerFunction1.after.py index 49521da959a8..291a28f46f39 100644 --- a/python/testData/copyPaste/multiLine/IndentInnerFunction1.after.py +++ b/python/testData/copyPaste/multiLine/IndentInnerFunction1.after.py @@ -1,7 +1,6 @@ def foo(self): x = 1 y = 2 - def foo(self): x = 1 y = 2 diff --git a/python/testData/copyPaste/multiLine/IndentInnerFunction2.after.py b/python/testData/copyPaste/multiLine/IndentInnerFunction2.after.py index 933900cac4f5..b3d0376b4ecd 100644 --- a/python/testData/copyPaste/multiLine/IndentInnerFunction2.after.py +++ b/python/testData/copyPaste/multiLine/IndentInnerFunction2.after.py @@ -1,9 +1,8 @@ def foo(self): x = 1 y = 2 - - def foo(self): - x = 1 - y = 2 + def foo(self): + x = 1 + y = 2 z = 3 \ No newline at end of file diff --git a/python/testData/copyPaste/multiLine/IndentTopLevel.after.py b/python/testData/copyPaste/multiLine/IndentTopLevel.after.py index 675d73067acc..ad8dfc390761 100644 --- a/python/testData/copyPaste/multiLine/IndentTopLevel.after.py +++ b/python/testData/copyPaste/multiLine/IndentTopLevel.after.py @@ -1,8 +1,6 @@ def f(): a = 1 b = 2 - - def f(): a = 1 b = 2 diff --git a/python/testSrc/com/jetbrains/python/PyCopyPasteTest.java b/python/testSrc/com/jetbrains/python/PyCopyPasteTest.java index 77fcbd378d0d..a0f89efd79a3 100644 --- a/python/testSrc/com/jetbrains/python/PyCopyPasteTest.java +++ b/python/testSrc/com/jetbrains/python/PyCopyPasteTest.java @@ -47,6 +47,30 @@ public class PyCopyPasteTest extends PyTestCase { doTest(); } + public void testSelection1() { //PY-6994 + doTest(); + } + + public void testSelection2() { //PY-6994 + doTest(); + } + + public void testSelection3() { //PY-6994 + doTest(); + } + + public void testSelectionReverse1() { //PY-6994 + doTest(); + } + + public void testSelectionReverse2() { //PY-6994 + doTest(); + } + + public void testSelectionReverse3() { //PY-6994 + doTest(); + } + public void testIndent11() { doTestSingleLine(); }