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();
}