boolean (char typed, @NotNull Editor editor, @NotNull PsiFile file, @NotNull SelectionModel selectionModel, char selectedChar) { int selectionStart = selectionModel.getSelectionStart(); PsiElement leaf = file.findElementAt(selectionStart); PsiElement element = leaf; while (element != null) { TextRange textRange = element.getTextRange(); if (textRange != null && textRange.getLength() >= 2 && (selectionStart == textRange.getStartOffset() || textRange.getEndOffset() == selectionStart + 1)) { int matchingCharOffset = selectionStart == textRange.getStartOffset() ? textRange.getEndOffset() - 1 : textRange.getStartOffset(); Document document = editor.getDocument(); CharSequence charsSequence = document.getCharsSequence(); if (matchingCharOffset < charsSequence.length()) { char matchingChar = charsSequence.charAt(matchingCharOffset); boolean otherQuoteMatchesSelected = matchingChar == selectedChar; if (otherQuoteMatchesSelected) { boolean handleEscaping = element == leaf; // can't handle interpolation TextRange innerRange = TextRange.create(textRange.getStartOffset() + 1, textRange.getEndOffset() - 1); String body = document.getText(innerRange); List<Pair<Integer, Boolean>> quotesInside = containsCharInside(body, selectedChar, typed); if (handleEscaping || quotesInside.isEmpty()) { replaceChar(document, textRange.getStartOffset(), typed); replaceChar(document, textRange.getEndOffset() - 1, typed); int offsetDelta = 0; if (handleEscaping && !quotesInside.isEmpty()) { StringBuilder newBody = new StringBuilder(body); for (Pair<Integer, Boolean> pair : quotesInside) { int offsetInBody = pair.first; char quote = body.charAt(offsetInBody); if (quote == typed && !pair.second) { newBody.insert(offsetInBody + offsetDelta, '\\'); offsetDelta++; } else if (quote == selectedChar && pair.second) { newBody.deleteCharAt(offsetInBody + offsetDelta - 1); offsetDelta--; } } document.replaceString(innerRange.getStartOffset(), innerRange.getEndOffset(), newBody); } editor.getCaretModel().moveToOffset(selectionModel.getSelectionEnd()); selectionModel.removeSelection(); return true; } } } } if (element instanceof PsiFile) break; element = element.getParent(); } return false; }