| /*=============================================================================# |
| # Copyright (c) 2005, 2021 Stephan Wahlbrink and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.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.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 org.eclipse.statet.jcommons.lang.NonNullByDefault; |
| import org.eclipse.statet.jcommons.lang.Nullable; |
| import org.eclipse.statet.jcommons.text.core.TextRegion; |
| |
| import org.eclipse.statet.ecommons.text.TextUtil; |
| |
| import org.eclipse.statet.ltk.model.core.element.SourceUnit; |
| import org.eclipse.statet.ltk.ui.sourceediting.SourceEditor; |
| |
| |
| @NonNullByDefault |
| public class SourceEditorTemplateContext extends DocumentTemplateContext implements IWorkbenchTemplateContext { |
| |
| |
| public static final int FORMAT= 1 << 4; |
| public static final int FORMAT_START= 1 << 5; |
| |
| |
| protected static final String SELECTION_VAR_NAME= "selection"; //$NON-NLS-1$ |
| protected static final String INDENTATION_VAR_NAME= "indentation"; //$NON-NLS-1$ |
| |
| |
| private final SourceEditor editor; |
| |
| private final int flags; |
| |
| |
| public SourceEditorTemplateContext(final TemplateContextType type, final IDocument document, |
| final TextRegion region, |
| final SourceEditor editor, final int flags) { |
| super(type, document, region.getStartOffset(), region.getLength()); |
| this.editor= editor; |
| this.flags= flags; |
| } |
| |
| |
| @Override |
| public SourceEditor getEditor() { |
| return this.editor; |
| } |
| |
| @Override |
| public @Nullable SourceUnit getSourceUnit() { |
| return this.editor.getSourceUnit(); |
| } |
| |
| public int getFlags() { |
| return this.flags; |
| } |
| |
| |
| @Override |
| public @Nullable String evaluateInfo(final Template template) throws BadLocationException, TemplateException { |
| final TemplateBuffer buffer= super.evaluate(template); |
| if (buffer != null) { |
| return buffer.getString(); |
| } |
| return null; |
| } |
| |
| @Override |
| public @Nullable 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); |
| |
| format(buffer); |
| final String selection= getVariable(SELECTION_VAR_NAME); |
| if (selection != null && TextUtilities.indexOf(getDocument().getLegalLineDelimiters(), selection, 0)[0] != -1) { |
| buffer.setContent(buffer.getString() + ln, buffer.getVariables()); |
| } |
| |
| return buffer; |
| } |
| |
| private void format(final TemplateBuffer buffer) throws BadLocationException { |
| final TemplateVariable[] variables= buffer.getVariables(); |
| final List<TextEdit> positions= TemplateUtils.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()])); |
| |
| format(root, templateDoc, variables, baseDoc); |
| |
| root.apply(templateDoc, TextEdit.UPDATE_REGIONS); |
| |
| TemplateUtils.positionsToVariables(positions, variables); |
| buffer.setContent(templateDoc.get(), variables); |
| } |
| |
| protected void format(final MultiTextEdit root, final IDocument templateDoc, |
| final TemplateVariable[] variables, final IDocument baseDoc) |
| throws BadLocationException { |
| indent(root, templateDoc, variables, baseDoc); |
| |
| if ((getFlags() & FORMAT_START) != 0 && getVariable(INDENTATION_VAR_NAME) == null |
| && getStart() > 0 && !Character.isWhitespace(baseDoc.getChar(getStart() - 1)) |
| && templateDoc.getLength() > 0 && !Character.isWhitespace(templateDoc.getChar(0)) ) { |
| root.addChild(new InsertEdit(0, " ")); //$NON-NLS-1$ |
| } |
| } |
| |
| protected void indent(final MultiTextEdit root, final IDocument templateDoc, |
| final TemplateVariable[] variables, final IDocument baseDoc) |
| throws BadLocationException { |
| String indentation= getVariable(INDENTATION_VAR_NAME); |
| // first line |
| { int line= 0; |
| int offset= templateDoc.getLineOffset(line); |
| if (indentation != null) { |
| final TextEdit edit= new InsertEdit(offset, indentation); |
| root.addChild(edit); |
| } |
| else { |
| indentation= TemplateUtils.searchIndentation(baseDoc, getStart()); |
| } |
| // following lines |
| while (++line < templateDoc.getNumberOfLines()) { |
| offset= templateDoc.getLineOffset(line); |
| |
| final TextEdit edit= new InsertEdit(offset, indentation); |
| root.addChild(edit); |
| } |
| } |
| } |
| |
| } |