/** Constructor to be used only in tests! */ public RefactoringInfo( IDocument document, ITextSelection selection, IGrammarVersionProvider versionProvider) { this.sourceFile = null; this.nature = null; this.versionProvider = versionProvider; this.doc = document; this.indentPrefs = PydevPlugin.getDefault() == null ? new TestIndentPrefs(document.get().indexOf('\t') < 0, 4) : DefaultIndentPrefs.get(); initInfo(selection); }
/** * Recalculates indent prefixes based upon preferences * * <p>we hold onto the same array SourceViewer has, and write directly into it. This is because * there is no way to tell SourceViewer that indent prefixes have changed. And we need this * functionality when user resets the tabs vs. spaces preference */ public void resetIndentPrefixes() { IPreferenceStore prefs = PydevPlugin.getDefault().getPreferenceStore(); int tabWidth = DefaultIndentPrefs.getStaticTabWidth(); FastStringBuffer spaces = new FastStringBuffer(8); for (int i = 0; i < tabWidth; i++) { spaces.append(" "); } boolean spacesFirst = prefs.getBoolean(PydevEditorPrefs.SUBSTITUTE_TABS) && !(getPyAutoIndentStrategy()).getIndentPrefs().getForceTabs(); if (spacesFirst) { indentPrefixes[0] = spaces.toString(); indentPrefixes[1] = "\t"; } else { indentPrefixes[0] = "\t"; indentPrefixes[1] = spaces.toString(); } }
/** * TabWidth is defined inside pydev preferences. * * <p>Python uses its own tab width, since I think that its standard is 8 */ public int getTabWidth(ISourceViewer sourceViewer) { return DefaultIndentPrefs.getStaticTabWidth(); }
/** * Performs the action with a given PySelection * * @param ps Given PySelection * @return boolean The success or failure of the action */ public int perform(PySelection ps) { // What we'll be replacing the selected text with FastStringBuffer strbuf = new FastStringBuffer(); try { // discover 1st line that starts the block comment int i; int startLineIndex = getStartIndex(ps); int endLineIndex = getEndIndex(ps); if (startLineIndex == -1 || endLineIndex == -1) { if (startLineIndex == -1 && endLineIndex == -1) { return -1; } else if (startLineIndex == -1) { startLineIndex = endLineIndex; } else { endLineIndex = startLineIndex; } } // For each line, uncomment it for (i = startLineIndex; i <= endLineIndex; i++) { boolean addDelim = true; String spacesBefore = ""; String line = ps.getLine(i); int lineLen = line.length(); for (int j = 0; j < lineLen; j++) { char c = line.charAt(j); if (c == '#') { // ok, it starts with # (so, remove the whitespaces before it) if (j > 0) { spacesBefore = line.substring(0, j); } line = line.substring(j); break; } else { if (!Character.isWhitespace(c)) { break; } } } if (line.startsWith("#")) { line = line.substring(1); } // get the chars used in block-comments AbstractBlockCommentAction[] acts = new AbstractBlockCommentAction[] { new PyAddSingleBlockComment(), new PyAddBlockComment() }; HashSet<Character> chars = new HashSet<Character>(); for (int j = 0; j < acts.length; j++) { AbstractBlockCommentAction action = acts[j]; chars.add(action.getColsAndChar().o2); } if (line.length() > 0) { boolean removedChar = false; char lastChar = '\0'; for (int j = 0; j < line.length(); j++) { lastChar = line.charAt(j); if (!chars.contains(lastChar)) { break; } else { removedChar = true; line = line.substring(1); j--; } } if (line.length() == 0 && removedChar) { addDelim = false; } if (removedChar && lastChar == ' ') { line = line.substring(1); } } if (addDelim) { strbuf.append(spacesBefore); strbuf.append(line); String lineDelimiter = ps.getDoc().getLineDelimiter(i); if (lineDelimiter != null) { strbuf.append(lineDelimiter); } } } // Ok, at this point things should be correct, but make sure than on uncomment, // the code goes to a proper indent position (remove spaces we may have added when creating a // block). String string = strbuf.toString(); List<String> lines = StringUtils.splitInLines(string); Tuple<Integer, String> posAndLine = new Tuple<Integer, String>(-1, ""); for (String line : lines) { int firstCharPosition = PySelection.getFirstCharPosition(line); if (firstCharPosition < posAndLine.o1 || posAndLine.o1 < 0) { posAndLine.o1 = firstCharPosition; posAndLine.o2 = line; } } if (posAndLine.o1 > 0) { final String sub = posAndLine.o2.substring(0, posAndLine.o1); if (sub.endsWith( " ")) { // If it ends with a tab, we won't change anything (only spaces are removed -- // which we may have introduced) boolean allEqual = true; for (String line : lines) { if (!line.startsWith(sub)) { allEqual = false; break; } } if (allEqual) { if (sub.startsWith("\t")) { // Tabs based indent: remove any ending spaces (and at this point we know a string // ends with a space) int j; for (j = sub.length() - 1; j >= 0; j--) { char c = sub.charAt(j); if (c != ' ') { j++; break; } } String newSub = sub.substring(0, j); strbuf.clear(); for (String line : lines) { strbuf.append(newSub); strbuf.append(line.substring(sub.length())); } } else { IIndentPrefs indentPrefs; if (targetEditor instanceof PyEdit) { PyEdit pyEdit = (PyEdit) targetEditor; indentPrefs = pyEdit.getIndentPrefs(); } else { indentPrefs = DefaultIndentPrefs.get(); } String indentationString = indentPrefs.getIndentationString(); int subLen = sub.length(); int indentLen = indentationString.length(); int mod = subLen % indentLen; if (mod != 0) { String substring = sub.substring(subLen - mod, subLen); boolean onlyWhitespaces = true; for (int k = 0; k < substring.length(); k++) { if (substring.charAt(k) != ' ') { onlyWhitespaces = false; break; } } if (onlyWhitespaces) { String newSub = sub.substring(0, subLen - mod); strbuf.clear(); for (String line : lines) { strbuf.append(newSub); strbuf.append(line.substring(sub.length())); } } } } } } } // Replace the text with the modified information int startLineOffset = ps.getLineOffset(startLineIndex); int endLineOffset = ps.getEndLineOffset(endLineIndex); String endLineDelimiter = ps.getDoc().getLineDelimiter(endLineIndex); if (endLineDelimiter != null) { endLineOffset += endLineDelimiter.length(); } String str = strbuf.toString(); ps.getDoc().replace(startLineOffset, endLineOffset - startLineOffset, str); return startLineOffset + str.length(); } catch (Exception e) { beep(e); } // In event of problems, return false return -1; }