/*=============================================================================#
# Copyright (c) 2005-2016 Stephan Wahlbrink (WalWare.de) and others.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
#
# Contributors:
# Stephan Wahlbrink - initial API and implementation
#=============================================================================*/
package de.walware.ecommons.ltk.ui.templates;
import java.util.List;
import java.util.regex.Matcher;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.jface.text.templates.DocumentTemplateContext;
import org.eclipse.jface.text.templates.Template;
import org.eclipse.jface.text.templates.TemplateBuffer;
import org.eclipse.jface.text.templates.TemplateContextType;
import org.eclipse.jface.text.templates.TemplateException;
import org.eclipse.jface.text.templates.TemplateTranslator;
import org.eclipse.jface.text.templates.TemplateVariable;
import org.eclipse.text.edits.InsertEdit;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.TextEdit;
import de.walware.ecommons.text.TextUtil;
import de.walware.ecommons.ltk.core.model.ISourceUnit;
import de.walware.ecommons.ltk.ui.sourceediting.ISourceEditor;
public class SourceEditorTemplateContext extends DocumentTemplateContext implements IWorkbenchTemplateContext {
private final ISourceEditor fEditor;
public SourceEditorTemplateContext(final TemplateContextType type, final IDocument document, final int offset, final int length,
final ISourceEditor editor) {
super(type, document, offset, length);
fEditor = editor;
}
@Override
public ISourceEditor getEditor() {
return fEditor;
}
@Override
public ISourceUnit getSourceUnit() {
return fEditor.getSourceUnit();
}
@Override
public String evaluateInfo(final Template template) throws BadLocationException, TemplateException {
final TemplateBuffer buffer = super.evaluate(template);
if (buffer != null) {
return buffer.getString();
}
return null;
}
@Override
public TemplateBuffer evaluate(final Template template) throws BadLocationException, TemplateException {
if (!canEvaluate(template)) {
return null;
}
final String ln = TextUtilities.getDefaultLineDelimiter(getDocument());
final TemplateTranslator translator = new TemplateTranslator();
String pattern = template.getPattern();
// correct line delimiter
final Matcher matcher = TextUtil.LINE_DELIMITER_PATTERN.matcher(pattern);
if (matcher.find()) {
pattern = matcher.replaceAll(ln);
}
// default, see super
final TemplateBuffer buffer = translator.translate(pattern);
getContextType().resolve(buffer, this);
indent(buffer);
final String selection = getVariable("selection"); //$NON-NLS-1$
if (selection != null && TextUtilities.indexOf(getDocument().getLegalLineDelimiters(), selection, 0)[0] != -1) {
buffer.setContent(buffer.getString()+ln, buffer.getVariables());
}
return buffer;
}
private void indent(final TemplateBuffer buffer) throws BadLocationException {
final TemplateVariable[] variables = buffer.getVariables();
final List<TextEdit> positions = TemplatesUtil.variablesToPositions(variables);
final IDocument baseDoc = getDocument();
final IDocument templateDoc = new Document(buffer.getString());
final MultiTextEdit root = new MultiTextEdit(0, templateDoc.getLength());
root.addChildren(positions.toArray(new TextEdit[positions.size()]));
String indentation = getVariable("indentation"); //$NON-NLS-1$
// first line
int offset = templateDoc.getLineOffset(0);
if (indentation != null) {
final TextEdit edit = new InsertEdit(offset, indentation);
root.addChild(edit);
root.apply(templateDoc, TextEdit.UPDATE_REGIONS);
root.removeChild(edit);
}
else {
indentation = TemplatesUtil.searchIndentation(baseDoc, getStart());
}
// following lines
for (int line = 1; line < templateDoc.getNumberOfLines(); line++) {
final IRegion region = templateDoc.getLineInformation(line);
offset = region.getOffset();
final TextEdit edit = new InsertEdit(offset, indentation);
root.addChild(edit);
root.apply(templateDoc, TextEdit.UPDATE_REGIONS);
root.removeChild(edit);
}
TemplatesUtil.positionsToVariables(positions, variables);
buffer.setContent(templateDoc.get(), variables);
}
}