/** * 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.actions; import java.util.List; import org.eclipse.jface.action.IAction; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.python.pydev.core.IIndentPrefs; import org.python.pydev.core.docutils.PySelection; import org.python.pydev.core.docutils.StringUtils; import org.python.pydev.editor.PyEdit; /** * This action was created so that we can make the shift left even if there are less characters in the line than * the expected indent (the default shift left won't do the dedent in that case). */ public class PyShiftLeft extends PyAction { /** * Grabs the selection information and performs the action. * * Note that setting the rewrite session and undo/redo must be done from the caller. */ public void run(IAction action) { try { if (!canModifyEditor()) { return; } PyEdit pyEdit = (PyEdit) getTextEditor(); IIndentPrefs indentPrefs = pyEdit.getIndentPrefs(); PySelection ps = new PySelection(pyEdit); perform(ps, indentPrefs); } catch (Exception e) { beep(e); } } /** * Performs the action with a given PySelection * * @param ps Given PySelection * @param indentPrefs * @return the new selection * @throws BadLocationException */ public void perform(PySelection ps, IIndentPrefs indentPrefs) throws BadLocationException { int endLineIndex = ps.getEndLineIndex(); int startLineIndex = ps.getStartLineIndex(); // If they selected a partial line, count it as a full one ps.selectCompleteLine(); String selectedText = ps.getSelectedText(); List<String> ret = StringUtils.splitInLines(selectedText); int tabWidth = indentPrefs.getTabWidth(); int tabWidthToUse = tabWidth; //Calculate the tab width we should use for (String line : ret) { String lineIndent = PySelection.getIndentationFromLine(line); if (lineIndent.length() > 0) { if (lineIndent.startsWith("\t")) { //Tab will be treated by removing the whole tab, so, just go on } else { //String with spaces... let's see if we have less spaces than we have the tab width int spaces = 0; for (int i = 0; i < lineIndent.length(); i++) { char c = lineIndent.charAt(i); if (c == ' ') { spaces += 1; } else { break; //ok, found all spaces available } } if (spaces > 0) { tabWidthToUse = Math.min(spaces, tabWidthToUse); } } } } String defaultIndentStr = StringUtils.createSpaceString(tabWidthToUse); //Note that we remove the contents line by line just erasing the needed chars //(if we did a full replacement in the end, the cursor wouldn't end in the correct position //and trying to set the cursor later also changed the editor scroll position). IDocument doc = ps.getDoc(); for (int i = startLineIndex; i <= endLineIndex; i++) { String line = ps.getLine(i); if (line.startsWith("\t")) { doc.replace(ps.getLineOffset(i), 1, ""); } else if (line.startsWith(defaultIndentStr)) { doc.replace(ps.getLineOffset(i), defaultIndentStr.length(), ""); } } } }