use of com.intellij.psi.formatter.WhiteSpaceFormattingStrategy in project intellij-community by JetBrains.
the class AutoHardWrapHandler method wrapLineIfNecessary.
/**
* The user is allowed to configured IJ in a way that it automatically wraps line on right margin exceeding on typing
* (check {@link EditorSettings#isWrapWhenTypingReachesRightMargin(Project)}).
* <p/>
* This method encapsulates that functionality, i.e. it performs the following logical actions:
* <pre>
* <ol>
* <li>Check if IJ is configured to perform automatic line wrapping on typing. Return in case of the negative answer;</li>
* <li>Check if right margin is exceeded. Return in case of the negative answer;</li>
* <li>Perform line wrapping;</li>
* </ol>
</pre>
*
* @param editor active editor
* @param dataContext current data context
* @param modificationStampBeforeTyping document modification stamp before the current symbols typing
*/
public void wrapLineIfNecessary(@NotNull Editor editor, @NotNull DataContext dataContext, long modificationStampBeforeTyping) {
Project project = editor.getProject();
Document document = editor.getDocument();
AutoWrapChange change = myAutoWrapChanges.get(document);
if (change != null) {
change.charTyped(editor, modificationStampBeforeTyping);
}
// Return eagerly if we don't need to auto-wrap line, e.g. because of right margin exceeding.
if (/*editor.isOneLineMode()
|| */
project == null || !editor.getSettings().isWrapWhenTypingReachesRightMargin(project) || (TemplateManager.getInstance(project) != null && TemplateManager.getInstance(project).getActiveTemplate(editor) != null)) {
return;
}
CaretModel caretModel = editor.getCaretModel();
int caretOffset = caretModel.getOffset();
int line = document.getLineNumber(caretOffset);
int startOffset = document.getLineStartOffset(line);
int endOffset = document.getLineEndOffset(line);
final CharSequence endOfString = document.getCharsSequence().subSequence(caretOffset, endOffset);
final boolean endsWithSpaces = StringUtil.isEmptyOrSpaces(String.valueOf(endOfString));
// Check if right margin is exceeded.
int margin = editor.getSettings().getRightMargin(project);
if (margin <= 0) {
return;
}
VisualPosition visEndLinePosition = editor.offsetToVisualPosition(endOffset);
if (margin >= visEndLinePosition.column) {
if (change != null) {
change.modificationStamp = document.getModificationStamp();
}
return;
}
// We assume that right margin is exceeded if control flow reaches this place. Hence, we define wrap position and perform
// smart line break there.
LineWrapPositionStrategy strategy = LanguageLineWrapPositionStrategy.INSTANCE.forEditor(editor);
// We want to prevent such behavior, hence, we remove automatically generated wraps and wrap the line as a whole.
if (change == null) {
change = new AutoWrapChange();
myAutoWrapChanges.put(document, change);
} else {
final int start = change.change.getStart();
final int end = change.change.getEnd();
if (!change.isEmpty() && start < end) {
document.replaceString(start, end, change.change.getText());
}
change.reset();
}
change.update(editor);
// Is assumed to be max possible number of characters inserted on the visual line with caret.
int maxPreferredOffset = editor.logicalPositionToOffset(editor.visualToLogicalPosition(new VisualPosition(caretModel.getVisualPosition().line, margin - FormatConstants.RESERVED_LINE_WRAP_WIDTH_IN_COLUMNS)));
int wrapOffset = strategy.calculateWrapPosition(document, project, startOffset, endOffset, maxPreferredOffset, true, false);
if (wrapOffset < 0) {
return;
}
WhiteSpaceFormattingStrategy formattingStrategy = WhiteSpaceFormattingStrategyFactory.getStrategy(editor);
if (wrapOffset <= startOffset || wrapOffset > maxPreferredOffset || formattingStrategy.check(document.getCharsSequence(), startOffset, wrapOffset) >= wrapOffset) {
// on first non-white space symbol because wrapped part will have the same indent value).
return;
}
final int[] wrapIntroducedSymbolsNumber = new int[1];
final int[] caretOffsetDiff = new int[1];
final int baseCaretOffset = caretModel.getOffset();
DocumentListener listener = new DocumentListener() {
@Override
public void beforeDocumentChange(DocumentEvent event) {
if (event.getOffset() < baseCaretOffset + caretOffsetDiff[0]) {
caretOffsetDiff[0] += event.getNewLength() - event.getOldLength();
}
if (autoFormatted(event)) {
return;
}
wrapIntroducedSymbolsNumber[0] += event.getNewLength() - event.getOldLength();
}
private boolean autoFormatted(DocumentEvent event) {
return event.getNewLength() <= event.getOldLength() && endsWithSpaces;
}
@Override
public void documentChanged(DocumentEvent event) {
}
};
caretModel.moveToOffset(wrapOffset);
DataManager.getInstance().saveInDataContext(dataContext, AUTO_WRAP_LINE_IN_PROGRESS_KEY, true);
document.addDocumentListener(listener);
try {
EditorActionManager.getInstance().getActionHandler(IdeActions.ACTION_EDITOR_ENTER).execute(editor, dataContext);
} finally {
DataManager.getInstance().saveInDataContext(dataContext, AUTO_WRAP_LINE_IN_PROGRESS_KEY, null);
document.removeDocumentListener(listener);
}
change.modificationStamp = document.getModificationStamp();
change.change.setStart(wrapOffset);
change.change.setEnd(wrapOffset + wrapIntroducedSymbolsNumber[0]);
caretModel.moveToOffset(baseCaretOffset + caretOffsetDiff[0]);
}
use of com.intellij.psi.formatter.WhiteSpaceFormattingStrategy in project intellij-community by JetBrains.
the class AbstractXmlBlock method containsWhiteSpacesOnly.
public static boolean containsWhiteSpacesOnly(@NotNull ASTNode node) {
PsiElement psiElement = node.getPsi();
if (psiElement instanceof PsiWhiteSpace)
return true;
Language nodeLang = psiElement.getLanguage();
if (!nodeLang.isKindOf(XMLLanguage.INSTANCE) || isTextOnlyNode(node) || node.getElementType() == XmlElementType.XML_PROLOG) {
WhiteSpaceFormattingStrategy strategy = WhiteSpaceFormattingStrategyFactory.getStrategy(nodeLang);
int length = node.getTextLength();
return strategy.check(node.getChars(), 0, length) >= length;
}
return false;
}
Aggregations