blob: a82ab071846b37743a779534be967bf52e36f68c [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;
import com.intellij.codeInsight.template.CustomTemplateCallback;
import com.intellij.codeInsight.template.Template;
import com.intellij.codeInsight.template.TemplateEditingListener;
import com.intellij.codeInsight.template.emmet.filters.ZenCodingFilter;
import com.intellij.codeInsight.template.emmet.generators.XmlZenCodingGenerator;
import com.intellij.codeInsight.template.emmet.generators.ZenCodingGenerator;
import com.intellij.codeInsight.template.impl.TemplateImpl;
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.event.CaretAdapter;
import com.intellij.openapi.editor.event.CaretEvent;
import com.intellij.openapi.editor.event.DocumentAdapter;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileFactory;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.xml.XmlFile;
import com.intellij.util.Producer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.Map;
public class EmmetPreviewUtil {
private EmmetPreviewUtil() {
}
@Nullable
public static String calculateTemplateText(@NotNull Editor editor, @NotNull PsiFile file, boolean expandPrimitiveAbbreviations) {
if (file instanceof XmlFile) {
final Ref<TemplateImpl> generatedTemplate = new Ref<TemplateImpl>();
PsiDocumentManager.getInstance(file.getProject()).commitDocument(editor.getDocument());
CustomTemplateCallback callback = createCallback(editor, file, generatedTemplate);
PsiElement context = callback.getContext();
ZenCodingGenerator generator = ZenCodingTemplate.findApplicableDefaultGenerator(context, false);
if (generator != null && generator instanceof XmlZenCodingGenerator) {
final String templatePrefix = new ZenCodingTemplate().computeTemplateKeyWithoutContextChecking(callback);
if (templatePrefix != null) {
try {
ZenCodingTemplate.expand(templatePrefix, callback, generator, Collections.<ZenCodingFilter>emptyList(),
expandPrimitiveAbbreviations, 0);
TemplateImpl template = generatedTemplate.get();
String templateText = template != null ? template.getTemplateText() : null;
if (!StringUtil.isEmpty(templateText)) {
return template.isToReformat() ? reformatTemplateText(file, templateText) : templateText;
}
}
catch (EmmetException e) {
return e.getMessage();
}
}
}
}
return null;
}
public static void addEmmetPreviewListeners(@NotNull final Editor editor,
@NotNull final PsiFile file,
final boolean expandPrimitiveAbbreviations) {
editor.getDocument().addDocumentListener(new DocumentAdapter() {
@Override
public void documentChanged(@NotNull DocumentEvent e) {
EmmetPreviewHint existingHint = EmmetPreviewHint.getExistingHint(editor);
if (existingHint != null) {
existingHint.updateText(new TemplateTextProducer(editor, file, expandPrimitiveAbbreviations));
}
else {
e.getDocument().removeDocumentListener(this);
}
}
});
editor.getCaretModel().addCaretListener(new CaretAdapter() {
@Override
public void caretPositionChanged(@NotNull CaretEvent e) {
EmmetPreviewHint existingHint = EmmetPreviewHint.getExistingHint(e.getEditor());
if (existingHint != null) {
existingHint.updateText(new TemplateTextProducer(editor, file, expandPrimitiveAbbreviations));
}
else {
e.getEditor().getCaretModel().removeCaretListener(this);
}
}
});
}
private static String reformatTemplateText(@NotNull final PsiFile file, @NotNull String templateText) {
final PsiFile copy = PsiFileFactory.getInstance(file.getProject()).createFileFromText(file.getName(), file.getFileType(), templateText);
VirtualFile vFile = copy.getVirtualFile();
if (vFile != null) {
vFile.putUserData(UndoConstants.DONT_RECORD_UNDO, Boolean.TRUE);
}
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
@Override
public void run() {
CodeStyleManager.getInstance(file.getProject()).reformat(copy);
}
});
}
});
return copy.getText();
}
@NotNull
private static CustomTemplateCallback createCallback(@NotNull Editor editor,
@NotNull PsiFile file,
@NotNull final Ref<TemplateImpl> generatedTemplate) {
return new CustomTemplateCallback(editor, file) {
@Override
public void startTemplate(@NotNull Template template, Map<String, String> predefinedValues, TemplateEditingListener listener) {
if (template instanceof TemplateImpl && !((TemplateImpl)template).isDeactivated()) {
generatedTemplate.set((TemplateImpl)template);
}
}
@Override
public void deleteTemplateKey(@NotNull String key) {
}
};
}
private static class TemplateTextProducer implements Producer<String> {
@NotNull private final Editor myEditor;
@NotNull private final PsiFile myFile;
private final boolean myExpandPrimitiveAbbreviations;
public TemplateTextProducer(@NotNull Editor editor, @NotNull PsiFile file, boolean expandPrimitiveAbbreviations) {
myEditor = editor;
myFile = file;
myExpandPrimitiveAbbreviations = expandPrimitiveAbbreviations;
}
@Nullable
@Override
public String produce() {
return calculateTemplateText(myEditor, myFile, myExpandPrimitiveAbbreviations);
}
}
}