blob: c919eacc6a7f9c49a50be5cfa1edf1e56df3c8f7 [file] [log] [blame]
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.template.emmet.generators;
import com.intellij.codeInsight.template.CustomTemplateCallback;
import com.intellij.codeInsight.template.emmet.EmmetParser;
import com.intellij.codeInsight.template.emmet.XmlEmmetParser;
import com.intellij.codeInsight.template.emmet.ZenCodingTemplate;
import com.intellij.codeInsight.template.emmet.tokens.TemplateToken;
import com.intellij.codeInsight.template.emmet.tokens.ZenCodingToken;
import com.intellij.codeInsight.template.impl.TemplateImpl;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.options.UnnamedConfigurable;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* @author Eugene.Kudelevsky
*/
public abstract class ZenCodingGenerator {
private static final ExtensionPointName<ZenCodingGenerator> EP_NAME = new ExtensionPointName<ZenCodingGenerator>("com.intellij.xml.zenCodingGenerator");
public abstract TemplateImpl generateTemplate(@NotNull TemplateToken token, boolean hasChildren, @NotNull PsiElement context);
@Nullable
public TemplateImpl createTemplateByKey(@NotNull String key) {
return null;
}
public abstract boolean isMyContext(@NotNull PsiElement context, boolean wrapping);
@Nullable
public String getSuffix() {
return null;
}
public abstract boolean isAppliedByDefault(@NotNull PsiElement context);
public abstract boolean isEnabled();
public static List<ZenCodingGenerator> getInstances() {
List<ZenCodingGenerator> generators = new ArrayList<ZenCodingGenerator>();
Collections.addAll(generators, XmlZenCodingGeneratorImpl.INSTANCE);
Collections.addAll(generators, EP_NAME.getExtensions());
return generators;
}
@Nullable
public String computeTemplateKey(@NotNull CustomTemplateCallback callback) {
Editor editor = callback.getEditor();
int currentOffset = editor.getCaretModel().getOffset();
int startOffset = editor.getDocument().getLineStartOffset(editor.getCaretModel().getLogicalPosition().line);
String key = computeKey(editor.getDocument().getCharsSequence().subSequence(startOffset, currentOffset));
return !StringUtil.isEmpty(key) && ZenCodingTemplate.checkTemplateKey(key, callback, this) ? key : null;
}
@Nullable
protected String computeKey(@NotNull CharSequence text) {
int currentOffset = text.length();
int groupCount = 0;
int bracketCount = 0;
int textCount = 0;
while (currentOffset > 0) {
currentOffset--;
char c = text.charAt(currentOffset);
if (c == ']') {
bracketCount++;
}
else if (c == '[') {
if (bracketCount == 0) {
currentOffset++;
break;
}
bracketCount--;
}
else if (c == '}') {
textCount++;
}
else if (c == '{') {
if (textCount == 0) {
currentOffset++;
break;
}
textCount--;
}
else if (c == ')') {
groupCount++;
}
else if (c == '(') {
if (groupCount == 0) {
currentOffset++;
break;
}
groupCount--;
}
else {
if (bracketCount > 0 || textCount > 0) {
// respect all characters inside attribute sets or text nodes
continue;
}
if (!isAllowedChar(c)) {
currentOffset++;
break;
}
}
}
return groupCount == 0 && textCount == 0 && bracketCount == 0 && currentOffset >= 0 && currentOffset < text.length()
? text.subSequence(currentOffset, text.length()).toString().replaceFirst("^[*+>^]+", "")
: null;
}
private static boolean isAllowedChar(char c) {
return (Character.isDigit(c) || Character.isLetter(c) || StringUtil.containsChar("/>+^[](){}#.*:$-_!@|%", c));
}
@NotNull
public EmmetParser createParser(List<ZenCodingToken> tokens,
CustomTemplateCallback callback,
ZenCodingGenerator generator,
boolean surroundWithTemplate) {
return new XmlEmmetParser(tokens, callback, generator, surroundWithTemplate);
}
@Nullable
public UnnamedConfigurable createConfigurable() {
return null;
}
public boolean hasCompletionItem() {
return false;
}
}