From af3f68abf0beb6ab0a589229705c451a98582bea Mon Sep 17 00:00:00 2001 From: Alexander Zolotov Date: Fri, 15 Feb 2013 17:13:33 +0400 Subject: [PATCH] Emmet support - css abbreviations with values specifying - supplying css values with units - add important modifier - explicit vendor prefixing --- .../template/emmet/EmmetParser.java | 2 +- .../template/emmet/ZenCodingTemplate.java | 93 ++----------------- .../template/emmet/nodes/GenerationNode.java | 9 +- .../template/emmet/nodes/LoremNode.java | 4 +- .../template/emmet/nodes/TextNode.java | 6 +- .../template/emmet/tokens/TemplateToken.java | 84 ++++++++++++++++- 6 files changed, 97 insertions(+), 101 deletions(-) diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/EmmetParser.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/EmmetParser.java index 0a60d6d2db40..3c89772773fb 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/EmmetParser.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/EmmetParser.java @@ -219,7 +219,7 @@ public abstract class EmmetParser { if (template == null) { return false; } - return ZenCodingTemplate.doSetTemplate(token, template, myCallback); + return token.setTemplate(template, myCallback); } @Nullable diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/ZenCodingTemplate.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/ZenCodingTemplate.java index f98078dd4f88..6f4e29d58187 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/ZenCodingTemplate.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/ZenCodingTemplate.java @@ -30,30 +30,21 @@ import com.intellij.codeInsight.template.impl.TemplateImpl; import com.intellij.codeInsight.template.impl.TemplateState; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; -import com.intellij.openapi.command.undo.UndoConstants; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorModificationUtil; import com.intellij.openapi.editor.ScrollType; -import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.ui.InputValidatorEx; import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.*; -import com.intellij.psi.xml.XmlAttribute; -import com.intellij.psi.xml.XmlDocument; -import com.intellij.psi.xml.XmlFile; -import com.intellij.psi.xml.XmlTag; -import com.intellij.util.ArrayUtil; -import com.intellij.util.LocalTimeCounter; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; import com.intellij.xml.XmlBundle; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collections; -import java.util.Iterator; import java.util.List; @@ -62,32 +53,6 @@ import java.util.List; */ public class ZenCodingTemplate implements CustomLiveTemplate { public static final char MARKER = '\0'; - public static final String ATTRS = "ATTRS"; - - private static void addMissingAttributes(XmlTag tag, List> value) { - List> attr2value = new ArrayList>(value); - for (Iterator> iterator = attr2value.iterator(); iterator.hasNext(); ) { - Pair pair = iterator.next(); - if (tag.getAttribute(pair.first) != null) { - iterator.remove(); - } - } - addAttributesBefore(tag, attr2value); - } - - private static void addAttributesBefore(XmlTag tag, List> attr2value) { - XmlAttribute firstAttribute = ArrayUtil.getFirstElement(tag.getAttributes()); - XmlElementFactory factory = XmlElementFactory.getInstance(tag.getProject()); - for (Pair pair : attr2value) { - XmlAttribute xmlAttribute = factory.createXmlAttribute(pair.first, ""); - if (firstAttribute != null) { - tag.addBefore(xmlAttribute, firstAttribute); - } - else { - tag.add(xmlAttribute); - } - } - } @Nullable public static ZenCodingGenerator findApplicableDefaultGenerator(@NotNull PsiElement context, boolean wrapping) { @@ -99,19 +64,10 @@ public class ZenCodingTemplate implements CustomLiveTemplate { return null; } - @NotNull - private static XmlFile parseXmlFileInTemplate(String templateString, CustomTemplateCallback callback, boolean createPhysicalFile) { - XmlFile xmlFile = (XmlFile)PsiFileFactory.getInstance(callback.getProject()) - .createFileFromText("dummy.xml", StdFileTypes.XML, templateString, LocalTimeCounter.currentTime(), createPhysicalFile); - VirtualFile vFile = xmlFile.getVirtualFile(); - if (vFile != null) { - vFile.putUserData(UndoConstants.DONT_RECORD_UNDO, Boolean.TRUE); - } - return xmlFile; - } - @Nullable - private static ZenCodingNode parse(@NotNull String text, @NotNull CustomTemplateCallback callback, @NotNull ZenCodingGenerator generator) { + private static ZenCodingNode parse(@NotNull String text, + @NotNull CustomTemplateCallback callback, + @NotNull ZenCodingGenerator generator) { List tokens = new EmmetLexer().lex(text); if (tokens == null) { return null; @@ -246,7 +202,7 @@ public class ZenCodingTemplate implements CustomLiveTemplate { } } for (ZenCodingFilter filter : filters) { - if(filter instanceof SingleLineEmmetFilter) { + if (filter instanceof SingleLineEmmetFilter) { builder.setIsToReformat(false); break; } @@ -333,8 +289,8 @@ public class ZenCodingTemplate implements CustomLiveTemplate { } public static void doWrap(final String selection, - final String abbreviation, - final CustomTemplateCallback callback) { + final String abbreviation, + final CustomTemplateCallback callback) { final ZenCodingGenerator defaultGenerator = findApplicableDefaultGenerator(callback.getContext(), true); assert defaultGenerator != null; ApplicationManager.getApplication().runWriteAction(new Runnable() { @@ -367,16 +323,6 @@ public class ZenCodingTemplate implements CustomLiveTemplate { return (char)WebEditorOptions.getInstance().getZenCodingExpandShortcut(); } - protected static boolean containsAttrsVar(TemplateImpl template) { - for (int i = 0; i < template.getVariableCount(); i++) { - String varName = template.getVariableNameAt(i); - if (ATTRS.equals(varName)) { - return true; - } - } - return false; - } - public String computeTemplateKey(@NotNull CustomTemplateCallback callback) { ZenCodingGenerator generator = findApplicableDefaultGenerator(callback.getContext(), false); if (generator == null) return null; @@ -386,25 +332,4 @@ public class ZenCodingTemplate implements CustomLiveTemplate { public boolean supportsWrapping() { return true; } - - public static boolean doSetTemplate(final TemplateToken token, TemplateImpl template, CustomTemplateCallback callback) { - token.setTemplate(template); - final XmlFile xmlFile = parseXmlFileInTemplate(template.getString(), callback, true); - token.setFile(xmlFile); - XmlDocument document = xmlFile.getDocument(); - final XmlTag tag = document != null ? document.getRootTag() : null; - if (token.getAttribute2Value().size() > 0 && tag == null) { - return false; - } - if (tag != null) { - if (!containsAttrsVar(template) && token.getAttribute2Value().size() > 0) { - ApplicationManager.getApplication().runWriteAction(new Runnable() { - public void run() { - addMissingAttributes(tag, token.getAttribute2Value()); - } - }); - } - } - return true; - } } diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/nodes/GenerationNode.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/nodes/GenerationNode.java index 771f1a825525..031ed23394ae 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/nodes/GenerationNode.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/nodes/GenerationNode.java @@ -18,7 +18,6 @@ package com.intellij.codeInsight.template.emmet.nodes; import com.google.common.base.Strings; import com.intellij.codeInsight.template.CustomTemplateCallback; import com.intellij.codeInsight.template.LiveTemplateBuilder; -import com.intellij.codeInsight.template.emmet.ZenCodingTemplate; import com.intellij.codeInsight.template.emmet.ZenCodingUtil; import com.intellij.codeInsight.template.emmet.filters.SingleLineEmmetFilter; import com.intellij.codeInsight.template.emmet.filters.ZenCodingFilter; @@ -213,9 +212,6 @@ public class GenerationNode extends UserDataHolderBase { end = e; } } - /*if (end != -1) { - builder.insertVariableSegment(end, TemplateImpl.END); - }*/ if(singleLineFilterEnabled) { builder.setIsToReformat(false); } @@ -305,8 +301,7 @@ public class GenerationNode extends UserDataHolderBase { if (flag) { builder.append(">'); - final XmlTag tag1 = XmlElementFactory.getInstance(tag.getProject()).createTagFromText(builder.toString(), XMLLanguage.INSTANCE); - return tag1; + return XmlElementFactory.getInstance(tag.getProject()).createTagFromText(builder.toString(), XMLLanguage.INSTANCE); } return tag; } @@ -372,7 +367,7 @@ public class GenerationNode extends UserDataHolderBase { Map predefinedValues = null; if (attributes != null) { predefinedValues = new HashMap(); - predefinedValues.put(ZenCodingTemplate.ATTRS, attributes); + predefinedValues.put(TemplateToken.ATTRS, attributes); } return predefinedValues; } diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/nodes/LoremNode.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/nodes/LoremNode.java index c116390d361c..43ae8aac7479 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/nodes/LoremNode.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/nodes/LoremNode.java @@ -16,7 +16,6 @@ package com.intellij.codeInsight.template.emmet.nodes; import com.intellij.codeInsight.template.CustomTemplateCallback; -import com.intellij.codeInsight.template.emmet.ZenCodingTemplate; import com.intellij.codeInsight.template.emmet.generators.LoremGenerator; import com.intellij.codeInsight.template.emmet.tokens.TemplateToken; import com.intellij.codeInsight.template.impl.TemplateImpl; @@ -48,8 +47,7 @@ public class LoremNode extends ZenCodingNode { final TemplateToken templateToken = new TemplateToken("", Collections.>emptyList()); final TemplateImpl template = new TemplateImpl("", myLoremGenerator.generate(myWordsCount, numberInIteration <= 0), ""); - ZenCodingTemplate.doSetTemplate(templateToken, template, callback); - + templateToken.setTemplate(template, callback); final GenerationNode node = new GenerationNode(templateToken, numberInIteration, totalIterations, surroundedText, insertSurroundedTextAtTheEnd, parent); return Collections.singletonList(node); diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/nodes/TextNode.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/nodes/TextNode.java index f715aecebf59..e47de7a937cc 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/nodes/TextNode.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/nodes/TextNode.java @@ -1,12 +1,10 @@ package com.intellij.codeInsight.template.emmet.nodes; import com.intellij.codeInsight.template.CustomTemplateCallback; -import com.intellij.codeInsight.template.emmet.ZenCodingTemplate; import com.intellij.codeInsight.template.emmet.ZenCodingUtil; import com.intellij.codeInsight.template.emmet.tokens.TemplateToken; import com.intellij.codeInsight.template.emmet.tokens.TextToken; import com.intellij.codeInsight.template.impl.TemplateImpl; -import com.intellij.openapi.util.Pair; import org.jetbrains.annotations.NotNull; import java.util.Collections; @@ -33,12 +31,12 @@ public class TextNode extends ZenCodingNode { int totalIterations, String surroundedText, CustomTemplateCallback callback, boolean insertSurroundedTextAtTheEnd, GenerationNode parent) { - final TemplateToken templateToken = new TemplateToken("", Collections.>emptyList()); + final TemplateToken templateToken = new TemplateToken(""); final boolean containsSurroundedTextMarker = ZenCodingUtil.containsSurroundedTextMarker(myText); final String text = ZenCodingUtil.replaceMarkers(myText.replace("${nl}", "\n"), numberInIteration, totalIterations, surroundedText); final TemplateImpl template = new TemplateImpl("", text, ""); - ZenCodingTemplate.doSetTemplate(templateToken, template, callback); + templateToken.setTemplate(template, callback); final GenerationNode node = new GenerationNode(templateToken, numberInIteration, totalIterations, containsSurroundedTextMarker ? null : surroundedText, diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/tokens/TemplateToken.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/tokens/TemplateToken.java index dac15a95fd1d..25a4c5b1f054 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/tokens/TemplateToken.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/tokens/TemplateToken.java @@ -15,18 +15,33 @@ */ package com.intellij.codeInsight.template.emmet.tokens; +import com.intellij.codeInsight.template.CustomTemplateCallback; import com.intellij.codeInsight.template.impl.TemplateImpl; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.undo.UndoConstants; +import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiFileFactory; +import com.intellij.psi.XmlElementFactory; +import com.intellij.psi.xml.XmlAttribute; +import com.intellij.psi.xml.XmlDocument; import com.intellij.psi.xml.XmlFile; +import com.intellij.psi.xml.XmlTag; +import com.intellij.util.ArrayUtil; +import com.intellij.util.LocalTimeCounter; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; /** * @author Eugene.Kudelevsky */ public class TemplateToken extends ZenCodingToken { + public static final String ATTRS = "ATTRS"; public final static TemplateToken EMPTY_TEMPLATE_TOKEN = new TemplateToken("", new ArrayList>()); private final String myKey; @@ -55,12 +70,77 @@ public class TemplateToken extends ZenCodingToken { myFile = file; } - public String getKey() { + public String getKey() { return myKey; } - public void setTemplate(TemplateImpl template) { + public boolean setTemplate(TemplateImpl template, CustomTemplateCallback callback) { myTemplate = template; + final XmlFile xmlFile = parseXmlFileInTemplate(template.getString(), callback, true); + setFile(xmlFile); + XmlDocument document = xmlFile.getDocument(); + final XmlTag tag = document != null ? document.getRootTag() : null; + if (getAttribute2Value().size() > 0 && tag == null) { + return false; + } + if (tag != null) { + if (!containsAttrsVar(template) && getAttribute2Value().size() > 0) { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + addMissingAttributes(tag, getAttribute2Value()); + } + }); + } + } + return true; + } + + + private static boolean containsAttrsVar(TemplateImpl template) { + for (int i = 0; i < template.getVariableCount(); i++) { + String varName = template.getVariableNameAt(i); + if (ATTRS.equals(varName)) { + return true; + } + } + return false; + } + + @NotNull + private static XmlFile parseXmlFileInTemplate(String templateString, CustomTemplateCallback callback, boolean createPhysicalFile) { + XmlFile xmlFile = (XmlFile)PsiFileFactory.getInstance(callback.getProject()) + .createFileFromText("dummy.xml", StdFileTypes.XML, templateString, LocalTimeCounter.currentTime(), createPhysicalFile); + VirtualFile vFile = xmlFile.getVirtualFile(); + if (vFile != null) { + vFile.putUserData(UndoConstants.DONT_RECORD_UNDO, Boolean.TRUE); + } + return xmlFile; + } + + + private static void addMissingAttributes(XmlTag tag, List> value) { + List> attr2value = new ArrayList>(value); + for (Iterator> iterator = attr2value.iterator(); iterator.hasNext(); ) { + Pair pair = iterator.next(); + if (tag.getAttribute(pair.first) != null) { + iterator.remove(); + } + } + addAttributesBefore(tag, attr2value); + } + + private static void addAttributesBefore(XmlTag tag, List> attr2value) { + XmlAttribute firstAttribute = ArrayUtil.getFirstElement(tag.getAttributes()); + XmlElementFactory factory = XmlElementFactory.getInstance(tag.getProject()); + for (Pair pair : attr2value) { + XmlAttribute xmlAttribute = factory.createXmlAttribute(pair.first, ""); + if (firstAttribute != null) { + tag.addBefore(xmlAttribute, firstAttribute); + } + else { + tag.add(xmlAttribute); + } + } } @Nullable