/**
* 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.
*/
/*
* Created on May 5, 2005
*
* @author Fabio Zadrozny
*/
package org.python.pydev.editor.autoedit;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DocumentCommand;
import org.eclipse.jface.text.IDocument;
import org.python.pydev.core.IIndentPrefs;
import org.python.pydev.core.docutils.StringUtils;
import com.aptana.shared_core.string.FastStringBuffer;
/**
* @author Fabio Zadrozny
*/
public abstract class AbstractIndentPrefs implements IIndentPrefs {
private boolean forceTabs = false;
public boolean getForceTabs() {
return forceTabs;
}
public void setForceTabs(boolean forceTabs) {
this.forceTabs = forceTabs;
}
/**
* Naive implementation. Always redoes the indentation string based in the
* spaces and tabs settings.
*
* @see org.python.pydev.core.IIndentPrefs#getIndentationString()
*/
public String getIndentationString() {
if (getUseSpaces(true))
return StringUtils.createSpaceString(getTabWidth());
else
return "\t";
}
/**
* Converts spaces to tabs or vice-versa depending on the user preferences
*/
public void convertToStd(IDocument document, DocumentCommand command) {
try {
if (getUseSpaces(true)) {
command.text = convertTabsToSpaces(document, command.text, command.offset, getIndentationString());
}
else {
command.text = convertSpacesToTabs(document, command.text, command.offset, getIndentationString());
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//------------------------------------------------------------- UTILS
/**
* Replaces tabs if needed by indent string or just a space depending of the
* tab location
*
*/
private String convertTabsToSpaces(IDocument document, String text, int offset, String indentString)
throws BadLocationException {
// only interesting if it contains a tab (also if it is a tab only)
if (text.indexOf("\t") != -1) {
// get some text infos
if (text.equals("\t")) {
//only a single tab?
deleteWhitespaceAfter(document, offset);
text = indentString;
} else {
// contains a char (pasted text)
char[] chars = text.toCharArray();
FastStringBuffer newText = new FastStringBuffer();
for (int count = 0; count < chars.length; count++) {
if (chars[count] == '\t') {
newText.append(indentString);
} else { // if it is not a tab add the char
newText.append((char) chars[count]);
}
}
text = newText.toString();
}
}
return text;
}
/**
* Converts spaces to strings. Useful when pasting
*/
private String convertSpacesToTabs(IDocument document, String text, int offset, String indentString)
throws BadLocationException {
String spaceStr = StringUtils.createSpaceString(getTabWidth());
while (text.startsWith(spaceStr)) {
text = text.replaceAll(spaceStr, "\t");
}
return text;
}
/**
* When hitting TAB, delete the whitespace after the cursor in the line
*/
private void deleteWhitespaceAfter(IDocument document, int offset) throws BadLocationException {
if (offset < document.getLength() && !endsWithNewline(document, document.get(offset, 1))) {
int lineLength = document.getLineInformationOfOffset(offset).getLength();
int lineStart = document.getLineInformationOfOffset(offset).getOffset();
String textAfter = document.get(offset, (lineStart + lineLength) - offset);
if (textAfter.length() > 0 && isWhitespace(textAfter)) {
document.replace(offset, textAfter.length(), "");
}
}
}
/**
* Checks if the string is solely composed of spaces
*
* @param s the string analyzed
* @return true if it's only composed of spaces and false otherwise.
*/
private boolean isWhitespace(String s) {
int len = s.length();
//it's done backwards because the chance of finding a non-whitespace char is higher at the end of the string
//than at the beggining
for (int i = len - 1; i > -1; i--) {
if (!Character.isWhitespace(s.charAt(i))) {
return false;
}
}
return true;
}
/**
* True if text ends with a newline delimiter
*/
public static boolean endsWithNewline(IDocument document, String text) {
String[] newlines = document.getLegalLineDelimiters();
boolean ends = false;
for (int i = 0; i < newlines.length; i++) {
String delimiter = newlines[i];
if (text.indexOf(delimiter) != -1)
ends = true;
}
return ends;
}
}