void (final @NotNull Project project, final @NotNull Editor editor, final @NotNull RangeMarker bounds, final int caretOffset, final @NotNull Ref<? super Boolean> indented, final @NotNull List<? extends IndentTransferableData> values) { if (!CodeInsightSettings.getInstance().INDENT_TO_CARET_ON_PASTE) { return; } assert values.size() == 1; if (values.get(0).getOffset() == caretOffset) return; final Document document = editor.getDocument(); final PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document); if (psiFile == null || !acceptFileType(psiFile.getFileType())) { return; } //System.out.println("--- before indent ---\n" + document.getText()); ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { final boolean useTabs = CodeStyle.getSettings(psiFile).useTabCharacter(psiFile.getFileType()); CharFilter NOT_INDENT_FILTER = ch -> useTabs ? ch != '\t' : ch != ' '; String pastedText = document.getText(bounds.getTextRange()); int startLine = document.getLineNumber(bounds.getStartOffset()); int endLine = document.getLineNumber(bounds.getEndOffset()); //calculate from indent int fromIndent = StringUtil.findFirst(pastedText, NOT_INDENT_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())); int toIndent = 0; if (initialText.length() > 0) { final DocumentImpl initialDocument = new DocumentImpl(initialText); int lineNumber = initialDocument.getTextLength() > caretOffset? initialDocument.getLineNumber(caretOffset) : initialDocument.getLineCount() - 1; final int offset = getLineStartSafeOffset(initialDocument, lineNumber); if (bounds.getStartOffset() == offset) { String toString = initialDocument.getText(TextRange.create(offset, initialDocument.getLineEndOffset(lineNumber))); toIndent = StringUtil.findFirst(toString, NOT_INDENT_FILTER); if (toIndent < 0 && StringUtil.isEmptyOrSpaces(toString)) { toIndent = toString.length(); } else if ((toIndent < 0 || toString.startsWith("\n")) && initialText.length() >= caretOffset) { toIndent = caretOffset - offset; } } else if (isNotApplicable(initialDocument, offset)) return; else { // selection startLine += 1; toIndent = Math.abs(bounds.getStartOffset() - offset); } } // actual difference in indentation level int indent = toIndent - fromIndent; if (useTabs) // indent is counted in tab units indent *= CodeStyle.getSettings(psiFile).getTabSize(psiFile.getFileType()); // don't indent single-line text if (!StringUtil.startsWithWhitespace(pastedText) && !StringUtil.endsWithLineBreak(pastedText) && !(StringUtil.splitByLines(pastedText).length > 1)) return; if (pastedText.endsWith("\n")) endLine -= 1; for (int i = startLine; i <= endLine; i++) { EditorActionUtil.indentLine(project, editor, i, indent); } indented.set(Boolean.TRUE); } private boolean isNotApplicable(DocumentImpl initialDocument, int offset) { return caretOffset < initialDocument.getTextLength() && !StringUtil .isEmptyOrSpaces(initialDocument.getText(TextRange.create(offset, caretOffset))); } }); //System.out.println("--- after indent ---\n" + document.getText()); }