From 3a16b519110d861eb811adf86b037d2f3d3cbad0 Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Fri, 18 Jun 2010 20:40:02 +0400 Subject: [PATCH] added django template quote handler (PY-1088) --- python/src/META-INF/python-plugin-common.xml | 2 + .../python/editor/BaseQuoteHandler.java | 69 +++++++++++++++++++ .../python/editor/PythonQuoteHandler.java | 65 ++--------------- 3 files changed, 75 insertions(+), 61 deletions(-) create mode 100644 python/src/com/jetbrains/python/editor/BaseQuoteHandler.java diff --git a/python/src/META-INF/python-plugin-common.xml b/python/src/META-INF/python-plugin-common.xml index 89a695f570c4..64adafd7c20d 100644 --- a/python/src/META-INF/python-plugin-common.xml +++ b/python/src/META-INF/python-plugin-common.xml @@ -232,6 +232,8 @@ + + diff --git a/python/src/com/jetbrains/python/editor/BaseQuoteHandler.java b/python/src/com/jetbrains/python/editor/BaseQuoteHandler.java new file mode 100644 index 000000000000..de28ca9c3673 --- /dev/null +++ b/python/src/com/jetbrains/python/editor/BaseQuoteHandler.java @@ -0,0 +1,69 @@ +package com.jetbrains.python.editor; + +import com.intellij.codeInsight.editorActions.SimpleTokenSetQuoteHandler; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.highlighter.HighlighterIterator; +import com.intellij.psi.tree.TokenSet; +import com.jetbrains.python.PyTokenTypes; + +import java.util.Arrays; + +/** + * @author yole + */ +public class BaseQuoteHandler extends SimpleTokenSetQuoteHandler { + + private final char[] ourAutoClosingChars; // we add auto-close quotes before these + + public BaseQuoteHandler(TokenSet tokenSet, char[] autoClosingChars) { + super(tokenSet); + ourAutoClosingChars = autoClosingChars; + Arrays.sort(ourAutoClosingChars); + } + + @Override + public boolean isOpeningQuote(HighlighterIterator iterator, int offset) { + // don't assume an opening quote unless we're in an explicitly "blank" context + CharSequence text = iterator.getDocument().getCharsSequence(); + if (offset+1 >= text.length() || Arrays.binarySearch(ourAutoClosingChars, text.charAt(offset+1)) >= 0) { + char the_quote = text.charAt(offset); + // if we're next to two same quotes, don't auto-close, the user may want a triple quote + if ( + offset >= 2 && + text.charAt(offset-1) == the_quote && + text.charAt(offset-2) == the_quote && + (offset < 3 || text.charAt(offset-3) != the_quote) + ) return false; + // handle string literal context + if (super.isOpeningQuote(iterator, offset)) { + return true; + } + if (myLiteralTokenSet.contains(iterator.getTokenType())) { + int start = iterator.getStart(); + if (offset - start <= 2) { + if (getLiteralStartOffset(text, start) == offset) return true; + } + } + } + return false; + } + + private static int getLiteralStartOffset(CharSequence text, int start) { + char c = Character.toUpperCase(text.charAt(start)); + if (c == 'U' || c == 'B') { + start++; + c = Character.toUpperCase(text.charAt(start)); + } + if (c == 'R') { + start++; + } + return start; + } + + @Override + protected boolean isNonClosedLiteral(HighlighterIterator iterator, CharSequence chars) { + if (getLiteralStartOffset(chars, iterator.getStart()) >= iterator.getEnd() - 1) return true; + if (chars.charAt(iterator.getEnd() - 1) != '\"' && chars.charAt(iterator.getEnd() - 1) != '\'') return true; + return false; + } +} diff --git a/python/src/com/jetbrains/python/editor/PythonQuoteHandler.java b/python/src/com/jetbrains/python/editor/PythonQuoteHandler.java index de52b1b2837c..3ad479a24ae6 100644 --- a/python/src/com/jetbrains/python/editor/PythonQuoteHandler.java +++ b/python/src/com/jetbrains/python/editor/PythonQuoteHandler.java @@ -1,70 +1,13 @@ package com.jetbrains.python.editor; -import com.intellij.codeInsight.editorActions.SimpleTokenSetQuoteHandler; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.highlighter.HighlighterIterator; +import com.intellij.psi.tree.TokenSet; import com.jetbrains.python.PyTokenTypes; -import java.util.Arrays; - /** - * @author yole + * @author traff */ -public class PythonQuoteHandler extends SimpleTokenSetQuoteHandler { - - private static final char[] ourAutoClosingChars; // we add auto-close quotes before these - static { - ourAutoClosingChars = new char[]{'}', ']', ')', ',', ':', ';', ' ', '\t', '\n'}; - Arrays.sort(ourAutoClosingChars); - } - +public class PythonQuoteHandler extends BaseQuoteHandler { public PythonQuoteHandler() { - super(PyTokenTypes.STRING_LITERAL); - } - - @Override - public boolean isOpeningQuote(HighlighterIterator iterator, int offset) { - // don't assume an opening quote unless we're in an explicitly "blank" context - CharSequence text = iterator.getDocument().getCharsSequence(); - if (offset+1 >= text.length() || Arrays.binarySearch(ourAutoClosingChars, text.charAt(offset+1)) >= 0) { - char the_quote = text.charAt(offset); - // if we're next to two same quotes, don't auto-close, the user may want a triple quote - if ( - offset >= 2 && - text.charAt(offset-1) == the_quote && - text.charAt(offset-2) == the_quote && - (offset < 3 || text.charAt(offset-3) != the_quote) - ) return false; - // handle string literal context - if (super.isOpeningQuote(iterator, offset)) { - return true; - } - if (myLiteralTokenSet.contains(iterator.getTokenType())) { - int start = iterator.getStart(); - if (offset - start <= 2) { - if (getLiteralStartOffset(text, start) == offset) return true; - } - } - } - return false; - } - - private static int getLiteralStartOffset(CharSequence text, int start) { - char c = Character.toUpperCase(text.charAt(start)); - if (c == 'U' || c == 'B') { - start++; - c = Character.toUpperCase(text.charAt(start)); - } - if (c == 'R') { - start++; - } - return start; - } - - @Override - protected boolean isNonClosedLiteral(HighlighterIterator iterator, CharSequence chars) { - if (getLiteralStartOffset(chars, iterator.getStart()) >= iterator.getEnd() - 1) return true; - if (chars.charAt(iterator.getEnd() - 1) != '\"' && chars.charAt(iterator.getEnd() - 1) != '\'') return true; - return false; + super(TokenSet.create(PyTokenTypes.STRING_LITERAL), new char[]{'}', ']', ')', ',', ':', ';', ' ', '\t', '\n'}); } }