/****************************************************************************** * Copyright (C) 2007-2013 Fabio Zadrozny * * 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: * Fabio Zadrozny <fabiofz@gmail.com> - initial API and implementation ******************************************************************************/ package org.python.pydev.shared_ui.templates; import java.util.List; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; 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.python.pydev.shared_core.log.Log; import org.python.pydev.shared_core.string.FastStringBuffer; import org.python.pydev.shared_core.string.StringUtils; import org.python.pydev.shared_core.string.TextSelectionUtils; public abstract class AbstractDocumentTemplateContextWithIndent extends DocumentTemplateContext { public final String indentTo; public AbstractDocumentTemplateContextWithIndent(TemplateContextType type, IDocument document, int offset, int length, String indentTo) { super(type, document, offset, length); this.indentTo = indentTo != null ? indentTo : ""; } protected abstract int getTabWidth(); protected abstract boolean getUseSpaces(); @Override public TemplateBuffer evaluate(Template template) throws BadLocationException, TemplateException { if (!canEvaluate(template)) { return null; } String spacesIndentString = StringUtils.createSpaceString(getTabWidth()); //indent to needed level and //replace any \t for the indentation string String pattern = template.getPattern(); List<String> splitted = StringUtils.splitInLines(pattern); boolean changed = false; if (getUseSpaces()) { if (pattern.indexOf("\t") != -1) { template = createNewTemplate(template, StringUtils.replaceAll(pattern, "\t", spacesIndentString)); changed = true; } } else { if (pattern.indexOf(spacesIndentString) != -1) { FastStringBuffer newPattern = new FastStringBuffer(); FastStringBuffer newTabsIndent = new FastStringBuffer(); for (int i = 0; i < splitted.size(); i++) { String string = splitted.get(i); int spacesFound = 0; while (string.length() > 0 && string.charAt(0) == ' ') { string = string.substring(1); spacesFound += 1; } int tabsToAdd = 0; if (spacesFound > 0) { tabsToAdd = spacesFound / spacesIndentString.length(); if (spacesFound % spacesIndentString.length() != 0) { tabsToAdd += 1; } newTabsIndent.clear(); for (int j = 0; j < tabsToAdd; j++) { newTabsIndent.append("\t"); } newPattern.append(newTabsIndent); } newPattern.append(string); } template = createNewTemplate(template, newPattern.toString()); changed = true; } } //recreate it (if needed). if (changed) { pattern = template.getPattern(); splitted = StringUtils.splitInLines(pattern); } String indentToStr = indentTo; String endLineDelim = TextSelectionUtils.getDelimiter(this.getDocument()); int size = splitted.size(); if (size > 0) { FastStringBuffer buffer = new FastStringBuffer("", (pattern.length() + (size * 2)) + ((size + 1) * indentToStr.length())); for (int i = 0; i < size; i++) { //we don't want to get the first line if (i != 0) { //the 1st line is not indented (that's where the user requested the completion -- others should be indented to it) buffer.append(indentToStr); } String str = splitted.get(i); //we have to make the new line delimiter correct: //https://sourceforge.net/tracker/index.php?func=detail&aid=2019419&group_id=85796&atid=577329 boolean hasNewLine = false; if (str.endsWith("\r") || str.endsWith("\n")) { hasNewLine = true; if (str.endsWith("\r\n")) { str = str.substring(0, str.length() - 2); } else { str = str.substring(0, str.length() - 1); } } buffer.append(str); if (hasNewLine) { buffer.append(endLineDelim); } } //just to change the pattern... template = createNewTemplate(template, buffer.toString()); } try { TemplateTranslator translator = new TemplateTranslator(); TemplateBuffer templateBuffer = translator.translate(template); getContextType().resolve(templateBuffer, this); return templateBuffer; } catch (Exception e) { Log.log(e); throw new RuntimeException(e); } } private Template createNewTemplate(Template template, String newString) { return new Template(template.getName(), template.getDescription(), template.getContextTypeId(), newString, template.isAutoInsertable()); } }