mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
logic for indenting after pasting does not based on copying now
PY-6884, PY-6965, PY-6966, PY-6907
This commit is contained in:
+1
-1
@@ -96,7 +96,7 @@ public abstract class CopyPasteReferenceProcessor<TRef extends PsiElement> imple
|
||||
public void processTransferableData(final Project project,
|
||||
final Editor editor,
|
||||
final RangeMarker bounds,
|
||||
int caretColumn,
|
||||
int caretOffset,
|
||||
Ref<Boolean> indented, final ReferenceTransferableData value) {
|
||||
if (DumbService.getInstance(project).isDumb()) {
|
||||
return;
|
||||
|
||||
+1
-1
@@ -83,7 +83,7 @@ public class CopyPasteFoldingProcessor implements CopyPastePostProcessor<Folding
|
||||
public void processTransferableData(final Project project,
|
||||
final Editor editor,
|
||||
final RangeMarker bounds,
|
||||
int caretColumn,
|
||||
int caretOffset,
|
||||
Ref<Boolean> indented,
|
||||
final FoldingTransferableData value) {
|
||||
final CodeFoldingManagerImpl foldingManager = (CodeFoldingManagerImpl)CodeFoldingManager.getInstance(project);
|
||||
|
||||
+45
-63
@@ -1,27 +1,26 @@
|
||||
package com.intellij.codeInsight.editorActions;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightSettings;
|
||||
import com.intellij.codeStyle.CodeStyleFacade;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.editor.actions.EditorActionUtil;
|
||||
import com.intellij.openapi.editor.impl.DocumentImpl;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.CharFilter;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.text.CharArrayUtil;
|
||||
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
import java.awt.datatransfer.Transferable;
|
||||
import java.awt.datatransfer.UnsupportedFlavorException;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
@@ -35,26 +34,7 @@ public class CopyPasteIndentProcessor implements CopyPastePostProcessor<IndentTr
|
||||
if (!acceptFileType(file.getFileType())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (startOffsets.length != 1) {
|
||||
return null;
|
||||
}
|
||||
Document document = editor.getDocument();
|
||||
int selStartLine = document.getLineNumber(startOffsets[0]);
|
||||
// check that selection starts at or before the first non-whitespace character on a line
|
||||
for (int offset = startOffsets[0] - 1; offset >= document.getLineStartOffset(selStartLine); offset--) {
|
||||
if (!Character.isWhitespace(document.getCharsSequence().charAt(offset))) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
int tabSize = CodeStyleFacade.getInstance(file.getProject()).getTabSize(file.getFileType());
|
||||
int start = document.getLineStartOffset(selStartLine);
|
||||
int end = document.getLineEndOffset(selStartLine);
|
||||
int minIndent = getIndent(document.getCharsSequence(), start, end, tabSize);
|
||||
|
||||
int firstNonSpaceChar = CharArrayUtil.shiftForward(document.getCharsSequence(), startOffsets[0], " \t");
|
||||
int firstLineLeadingSpaces = (firstNonSpaceChar <= document.getLineEndOffset(selStartLine)) ? firstNonSpaceChar - startOffsets[0] : 0;
|
||||
return new IndentTransferableData(minIndent, 0, firstLineLeadingSpaces);
|
||||
return new IndentTransferableData(editor.getCaretModel().getOffset());
|
||||
}
|
||||
|
||||
private static boolean acceptFileType(FileType fileType) {
|
||||
@@ -66,24 +46,6 @@ public class CopyPasteIndentProcessor implements CopyPastePostProcessor<IndentTr
|
||||
return false;
|
||||
}
|
||||
|
||||
private static int getIndent(CharSequence chars, int start, int end, int tabSize) {
|
||||
int result = 0;
|
||||
boolean nonEmpty = false;
|
||||
for(int i=start; i<end; i++) {
|
||||
if (chars.charAt(i) == ' ') {
|
||||
result++;
|
||||
}
|
||||
else if (chars.charAt(i) == '\t') {
|
||||
result = ((result / tabSize) + 1) * tabSize;
|
||||
}
|
||||
else {
|
||||
nonEmpty = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return nonEmpty ? result : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IndentTransferableData extractTransferableData(Transferable content) {
|
||||
IndentTransferableData indentData = null;
|
||||
@@ -109,12 +71,14 @@ public class CopyPasteIndentProcessor implements CopyPastePostProcessor<IndentTr
|
||||
public void processTransferableData(final Project project,
|
||||
final Editor editor,
|
||||
final RangeMarker bounds,
|
||||
final int caretColumn,
|
||||
final int caretOffset,
|
||||
final Ref<Boolean> indented,
|
||||
final IndentTransferableData value) {
|
||||
if (!CodeInsightSettings.getInstance().INDENT_TO_CARET_ON_PASTE) {
|
||||
return;
|
||||
}
|
||||
if (value.getOffset() == editor.getCaretModel().getOffset()) return;
|
||||
|
||||
final Document document = editor.getDocument();
|
||||
final PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document);
|
||||
if (psiFile == null || !acceptFileType(psiFile.getFileType())) {
|
||||
@@ -129,33 +93,45 @@ public class CopyPasteIndentProcessor implements CopyPastePostProcessor<IndentTr
|
||||
int startLine = document.getLineNumber(bounds.getStartOffset());
|
||||
int endLine = document.getLineNumber(bounds.getEndOffset());
|
||||
|
||||
//calculate from indent
|
||||
int fromIndent = StringUtil.findFirst(pastedText, CharFilter.NOT_WHITESPACE_FILTER);
|
||||
if (fromIndent < 0) fromIndent = 0;
|
||||
|
||||
//calculate to indent
|
||||
String initialText = document.getText(TextRange.create(0, bounds.getStartOffset())) +
|
||||
document.getText(TextRange.create(bounds.getEndOffset(), document.getTextLength()));
|
||||
final DocumentImpl initialDocument = new DocumentImpl(initialText);
|
||||
final int lineNumber = initialDocument.getLineNumber(caretOffset);
|
||||
final int offset = getLineStartSafeOffset(initialDocument, lineNumber);
|
||||
final int caretColumn = caretOffset - offset;
|
||||
|
||||
String toString = initialDocument.getText(TextRange.create(offset, initialDocument.getLineEndOffset(lineNumber)));
|
||||
int toIndent = StringUtil.findFirst(toString, new CharFilter() {
|
||||
@Override
|
||||
public boolean accept(char ch) {
|
||||
return ch != ' ';
|
||||
}
|
||||
});
|
||||
if (toIndent < 0 || toString.startsWith("\n")) {
|
||||
if (StringUtil.isEmptyOrSpaces(toString) && toString.length() > 0) {
|
||||
toIndent = toString.length();
|
||||
}
|
||||
else {
|
||||
toIndent = caretColumn;
|
||||
}
|
||||
}
|
||||
|
||||
// actual difference in indentation level
|
||||
int indent = toIndent - fromIndent;
|
||||
|
||||
// don't indent single-line text
|
||||
if (!StringUtil.startsWithWhitespace(pastedText) && !StringUtil.endsWithLineBreak(pastedText) &&
|
||||
!(StringUtil.splitByLines(pastedText).length > 1))
|
||||
return;
|
||||
|
||||
int startLineStart = document.getLineStartOffset(startLine);
|
||||
// don't indent first line if there's any text before it
|
||||
final String textBeforeFirstLine = document.getText(new TextRange(startLineStart, bounds.getStartOffset()));
|
||||
if (pastedText.endsWith("\n")) endLine -= 1;
|
||||
|
||||
final int caretOffset = editor.getCaretModel().getOffset();
|
||||
int realCaretColumn = caretOffset - document.getLineStartOffset(document.getLineNumber(caretOffset));
|
||||
|
||||
//insert on top level, doesn't need indent
|
||||
if (realCaretColumn == 0 && !pastedText.startsWith(" "))
|
||||
return;
|
||||
|
||||
if (textBeforeFirstLine.trim().length() == 0) {
|
||||
EditorActionUtil.indentLine(project, editor, startLine, -value.getFirstLineLeadingSpaces());
|
||||
}
|
||||
|
||||
|
||||
final List<String> strings = StringUtil.split(pastedText, "\n");
|
||||
if (realCaretColumn >= value.getIndent() && !strings.isEmpty() &&
|
||||
StringUtil.isEmptyOrSpaces(strings.get(strings.size()-1))) endLine -=1;
|
||||
|
||||
for (int i = startLine+1; i <= endLine; i++) {
|
||||
int indent = realCaretColumn - value.getIndent();
|
||||
for (int i = startLine; i <= endLine; i++) {
|
||||
EditorActionUtil.indentLine(project, editor, i, indent);
|
||||
}
|
||||
indented.set(Boolean.TRUE);
|
||||
@@ -163,4 +139,10 @@ public class CopyPasteIndentProcessor implements CopyPastePostProcessor<IndentTr
|
||||
});
|
||||
//System.out.println("--- after indent ---\n" + document.getText());
|
||||
}
|
||||
|
||||
public static int getLineStartSafeOffset(final Document document, int line) {
|
||||
if (line == document.getLineCount()) return document.getTextLength();
|
||||
return document.getLineStartOffset(line);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ public interface CopyPastePostProcessor<T extends TextBlockTransferableData> {
|
||||
void processTransferableData(final Project project,
|
||||
final Editor editor,
|
||||
final RangeMarker bounds,
|
||||
int caretColumn,
|
||||
int caretOffset,
|
||||
Ref<Boolean> indented,
|
||||
final T value);
|
||||
}
|
||||
|
||||
+6
-17
@@ -11,26 +11,15 @@ import java.io.Serializable;
|
||||
public class IndentTransferableData implements TextBlockTransferableData, Serializable {
|
||||
private static @NonNls DataFlavor ourFlavor;
|
||||
|
||||
private final int myIndent;
|
||||
private final int myMaxIndent;
|
||||
private final int myFirstLineLeadingSpaces;
|
||||
private final int myOffset;
|
||||
|
||||
public IndentTransferableData(int indent, int maxIndent, int firstLineLeadingSpaces) {
|
||||
myIndent = indent;
|
||||
myMaxIndent = maxIndent;
|
||||
myFirstLineLeadingSpaces = firstLineLeadingSpaces;
|
||||
public IndentTransferableData(int offset) {
|
||||
myOffset = offset;
|
||||
}
|
||||
|
||||
public int getIndent() {
|
||||
return myIndent;
|
||||
}
|
||||
|
||||
public int getMaxIndent() {
|
||||
return myMaxIndent;
|
||||
}
|
||||
|
||||
public int getFirstLineLeadingSpaces() {
|
||||
return myFirstLineLeadingSpaces;
|
||||
public int getOffset() {
|
||||
return myOffset;
|
||||
}
|
||||
|
||||
public DataFlavor getFlavor() {
|
||||
@@ -66,6 +55,6 @@ public class IndentTransferableData implements TextBlockTransferableData, Serial
|
||||
}
|
||||
|
||||
protected IndentTransferableData clone() {
|
||||
return new IndentTransferableData(myIndent, myMaxIndent, myFirstLineLeadingSpaces);
|
||||
return new IndentTransferableData(myOffset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@ public class PasteHandler extends EditorActionHandler implements EditorTextInser
|
||||
final Ref<Boolean> indented = new Ref<Boolean>(Boolean.FALSE);
|
||||
for(Map.Entry<CopyPastePostProcessor, TextBlockTransferableData> e: extraData.entrySet()) {
|
||||
//noinspection unchecked
|
||||
e.getKey().processTransferableData(project, editor, bounds, col, indented, e.getValue());
|
||||
e.getKey().processTransferableData(project, editor, bounds, offset, indented, e.getValue());
|
||||
}
|
||||
|
||||
boolean pastedTextContainsWhiteSpacesOnly =
|
||||
|
||||
Reference in New Issue
Block a user