Search in sources :

Example 1 with CharFilter

use of com.intellij.openapi.util.text.CharFilter in project intellij-community by JetBrains.

the class CopyPasteIndentProcessor method processTransferableData.

@Override
public void processTransferableData(final Project project, final Editor editor, final RangeMarker bounds, final int caretOffset, final Ref<Boolean> indented, final List<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 = CodeStyleSettingsManager.getSettings(project).useTabCharacter(psiFile.getFileType());
            CharFilter NOT_INDENT_FILTER = new CharFilter() {

                @Override
                public boolean accept(char ch) {
                    return useTabs ? ch != '\t' : ch != ' ';
                }
            };
            String pastedText = document.getText(TextRange.create(bounds));
            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 (// indent is counted in tab units
            useTabs)
                indent *= CodeStyleSettingsManager.getSettings(project).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());
}
Also used : CharFilter(com.intellij.openapi.util.text.CharFilter) PsiFile(com.intellij.psi.PsiFile) Document(com.intellij.openapi.editor.Document) DocumentImpl(com.intellij.openapi.editor.impl.DocumentImpl)

Aggregations

Document (com.intellij.openapi.editor.Document)1 DocumentImpl (com.intellij.openapi.editor.impl.DocumentImpl)1 CharFilter (com.intellij.openapi.util.text.CharFilter)1 PsiFile (com.intellij.psi.PsiFile)1