/** * Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Eclipse Public License (EPL). * Please see the license.txt included with this distribution for details. * Any modifications to this file must keep this entire header intact. */ package org.python.pydev.editor.codecompletion.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.core.IIndentPrefs; import org.python.pydev.core.docutils.PySelection; import org.python.pydev.core.docutils.StringUtils; import org.python.pydev.core.log.Log; import com.aptana.shared_core.string.FastStringBuffer; public class DocumentTemplateContextWithIndent extends DocumentTemplateContext { private final String indentTo; private IIndentPrefs indentPrefs; /** * Note that it's in the default context because it should be used on subclasses. */ /* default */DocumentTemplateContextWithIndent(TemplateContextType type, IDocument document, int offset, int length, String indentTo, IIndentPrefs indentPrefs) { super(type, document, offset, length); this.indentTo = indentTo; this.indentPrefs = indentPrefs; } @Override public TemplateBuffer evaluate(Template template) throws BadLocationException, TemplateException { if (!canEvaluate(template)) { return null; } String spacesIndentString = StringUtils.createSpaceString(indentPrefs.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 (indentPrefs.getUseSpaces(true)) { 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 != null ? indentTo : ""; String endLineDelim = PySelection.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()); } }