/** * Copyright (c) 2005-2013 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.shared_core.string; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Set; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.DocumentRewriteSession; import org.eclipse.jface.text.DocumentRewriteSessionType; import org.eclipse.jface.text.FindReplaceDocumentAdapter; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IDocumentExtension4; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.text.Region; import org.eclipse.jface.text.TextSelection; import org.eclipse.jface.text.TextUtilities; import org.python.pydev.shared_core.log.Log; import org.python.pydev.shared_core.structure.Tuple; public class TextSelectionUtils { protected IDocument doc; protected ITextSelection textSelection; /** * @param document the document we are using to make the selection * @param selection that's the actual selection. It might have an offset and a number of selected chars */ public TextSelectionUtils(IDocument doc, ITextSelection selection) { this.doc = doc; this.textSelection = selection; } /** * @param document the document we are using to make the selection * @param offset the offset where the selection will happen (0 characters will be selected) */ public TextSelectionUtils(IDocument doc, int offset) { this(doc, new TextSelection(doc, offset, 0)); } /** * @return the offset of the line where the cursor is */ public final int getLineOffset() { return getLineOffset(getCursorLine()); } /** * @return the offset of the specified line */ public final int getLineOffset(int line) { try { return getDoc().getLineInformation(line).getOffset(); } catch (Exception e) { return 0; } } /** * @return Returns the doc. */ public final IDocument getDoc() { return doc; } /** * @return Returns the cursorLine. */ public final int getCursorLine() { return this.getTextSelection().getEndLine(); } /** * @return Returns the textSelection. */ public final ITextSelection getTextSelection() { return textSelection; } /** * @return Returns the absoluteCursorOffset. */ public final int getAbsoluteCursorOffset() { return this.getTextSelection().getOffset(); } /** * @param src * @return */ public static int getFirstCharPosition(String src) { int i = 0; boolean breaked = false; int len = src.length(); while (i < len) { if (!Character.isWhitespace(src.charAt(i))) { i++; breaked = true; break; } i++; } if (!breaked) { i++; } return (i - 1); } /** * @return the offset mapping to the end of the line passed as parameter. * @throws BadLocationException */ public final int getEndLineOffset(int line) throws BadLocationException { IRegion lineInformation = doc.getLineInformation(line); return lineInformation.getOffset() + lineInformation.getLength(); } /** * @return the offset mapping to the end of the current 'end' line. */ public final int getEndLineOffset() { IRegion endLine = getEndLine(); return endLine.getOffset() + endLine.getLength(); } /** * @return Returns the endLine. */ public final IRegion getEndLine() { try { int endLineIndex = getEndLineIndex(); if (endLineIndex == -1) { return null; } return getDoc().getLineInformation(endLineIndex); } catch (BadLocationException e) { Log.log(e); } return null; } /** * @return Returns the endLineIndex. */ public final int getEndLineIndex() { return this.getTextSelection().getEndLine(); } /** * @return Returns the startLine. */ public IRegion getStartLine() { try { return getDoc().getLineInformation(getStartLineIndex()); } catch (BadLocationException e) { //Log.log(e); } return null; } /** * @return Returns the startLineIndex. */ public int getStartLineIndex() { return this.getTextSelection().getStartLine(); } /** * In event of partial selection, used to select the full lines involved. */ public void selectCompleteLine() { if (doc.getNumberOfLines() == 1) { this.textSelection = new TextSelection(doc, 0, doc.getLength()); return; } IRegion endLine = getEndLine(); IRegion startLine = getStartLine(); this.textSelection = new TextSelection(doc, startLine.getOffset(), endLine.getOffset() + endLine.getLength() - startLine.getOffset()); } /** * @return the Selected text */ public String getSelectedText() { ITextSelection txtSel = getTextSelection(); int start = txtSel.getOffset(); int len = txtSel.getLength(); try { return this.doc.get(start, len); } catch (BadLocationException e) { throw new RuntimeException(e); } } /** * Readjust the selection so that the whole document is selected. * * @param onlyIfNothingSelected: If false, check if we already have a selection. If we * have a selection, it is not changed, however, if it is true, it always selects everything. */ public void selectAll(boolean forceNewSelection) { if (!forceNewSelection) { if (getSelLength() > 0) { return; } } textSelection = new TextSelection(doc, 0, doc.getLength()); } /** * @return Returns the selLength. */ public int getSelLength() { return this.getTextSelection().getLength(); } /** * @return Returns the selection. */ public String getCursorLineContents() { try { IRegion startLine = getStartLine(); if (startLine == null) { return ""; } int start = startLine.getOffset(); IRegion endLine = getEndLine(); if (endLine == null) { return ""; } int end = endLine.getOffset() + endLine.getLength(); return this.doc.get(start, end - start); } catch (BadLocationException e) { Log.log(e); } return ""; } /** * @return the delimiter that should be used for the passed document */ public static String getDelimiter(IDocument doc) { return TextUtilities.getDefaultLineDelimiter(doc); } /** * @return Returns the endLineDelim. */ public String getEndLineDelim() { return getDelimiter(getDoc()); } /** * @return * @throws BadLocationException */ public char getCharAfterCurrentOffset() throws BadLocationException { return getDoc().getChar(getAbsoluteCursorOffset() + 1); } /** * @return * @throws BadLocationException */ public char getCharAtCurrentOffset() throws BadLocationException { return getDoc().getChar(getAbsoluteCursorOffset()); } /** * @return * @throws BadLocationException */ public char getCharBeforeCurrentOffset() throws BadLocationException { return getDoc().getChar(getAbsoluteCursorOffset() - 1); } public static int getAbsoluteCursorOffset(IDocument doc, int line, int col) { try { IRegion offsetR = doc.getLineInformation(line); return offsetR.getOffset() + col; } catch (Exception e) { throw new RuntimeException(e); } } /** * @param line 0-based * @param col 0-based * @return the absolute cursor offset in the contained document */ public int getAbsoluteCursorOffset(int line, int col) { return getAbsoluteCursorOffset(doc, line, col); } /** * Changes the selection * @param absoluteStart this is the offset of the start of the selection * @param absoluteEnd this is the offset of the end of the selection */ public void setSelection(int absoluteStart, int absoluteEnd) { this.textSelection = new TextSelection(doc, absoluteStart, absoluteEnd - absoluteStart); } /** * @return the current column that is selected from the cursor. */ public int getCursorColumn() { try { int absoluteOffset = getAbsoluteCursorOffset(); IRegion region = doc.getLineInformationOfOffset(absoluteOffset); return absoluteOffset - region.getOffset(); } catch (BadLocationException e) { throw new RuntimeException(e); } } /** * Gets current line from document. * * @return String line in String form */ public String getLine() { return getLine(getDoc(), getCursorLine()); } /** * Gets line from document. * * @param i Line number * @return String line in String form */ public String getLine(int i) { return getLine(getDoc(), i); } /** * Gets line from document. * * @param i Line number * @return String line in String form */ public static String getLine(IDocument doc, int i) { try { IRegion lineInformation = doc.getLineInformation(i); return doc.get(lineInformation.getOffset(), lineInformation.getLength()); } catch (Exception e) { return ""; } } public int getLineOfOffset() { return getLineOfOffset(this.getAbsoluteCursorOffset()); } public int getLineOfOffset(int offset) { return getLineOfOffset(getDoc(), offset); } /** * @param offset the offset we want to get the line * @return the line of the passed offset */ public static int getLineOfOffset(IDocument doc, int offset) { try { return doc.getLineOfOffset(offset); } catch (BadLocationException e) { if (offset > doc.getLength() - 1) { int numberOfLines = doc.getNumberOfLines(); if (numberOfLines == 0) { return 0; } return numberOfLines - 1; } return 0; } } /** * Deletes a line from the document * @param i */ public void deleteLine(int i) { deleteLine(getDoc(), i); } /** * Deletes a line from the document * @param i */ public static void deleteLine(IDocument doc, int i) { try { IRegion lineInformation = doc.getLineInformation(i); int offset = lineInformation.getOffset(); int length = -1; if (doc.getNumberOfLines() > i) { int nextLineOffset = doc.getLineInformation(i + 1).getOffset(); length = nextLineOffset - offset; } else { length = lineInformation.getLength(); } if (length > -1) { doc.replace(offset, length, ""); } } catch (BadLocationException e) { Log.log(e); } } public void deleteSpacesAfter(int offset) { try { final int len = countSpacesAfter(offset); if (len > 0) { doc.replace(offset, len, ""); } } catch (Exception e) { //ignore } } public int countSpacesAfter(int offset) throws BadLocationException { if (offset >= doc.getLength()) { return 0; } int initial = offset; String next = doc.get(offset, 1); //don't delete 'all' that is considered whitespace (as \n and \r) try { while (next.charAt(0) == ' ' || next.charAt(0) == '\t') { offset++; next = doc.get(offset, 1); } } catch (Exception e) { // ignore } return offset - initial; } /** * Deletes the current selected text * * @throws BadLocationException */ public void deleteSelection() throws BadLocationException { int offset = textSelection.getOffset(); doc.replace(offset, textSelection.getLength(), ""); } public void addLine(String contents, int afterLine) { addLine(getDoc(), getEndLineDelim(), contents, afterLine); } /** * Adds a line to the document. * * @param doc the document * @param endLineDelim the delimiter that should be used * @param contents what should be added (the end line delimiter may be added before or after those contents * (depending on what are the current contents of the document). * @param afterLine the contents should be added after the line specified here. */ public static void addLine(IDocument doc, String endLineDelim, String contents, int afterLine) { try { int offset = -1; if (doc.getNumberOfLines() > afterLine) { offset = doc.getLineInformation(afterLine + 1).getOffset(); } else { offset = doc.getLineInformation(afterLine).getOffset(); } if (doc.getNumberOfLines() - 1 == afterLine) { contents = endLineDelim + contents; } if (!contents.endsWith(endLineDelim)) { contents += endLineDelim; } if (offset >= 0) { doc.replace(offset, 0, contents); } } catch (BadLocationException e) { Log.log(e); } } public String getLineContentsFromCursor() throws BadLocationException { return getLineContentsFromCursor(getAbsoluteCursorOffset()); } /** * @return the line where the cursor is (from the cursor position to the end of the line). * @throws BadLocationException */ public String getLineContentsFromCursor(int offset) throws BadLocationException { int lineOfOffset = doc.getLineOfOffset(offset); IRegion lineInformation = doc.getLineInformation(lineOfOffset); String lineToCursor = doc.get(offset, lineInformation.getOffset() + lineInformation.getLength() - offset); return lineToCursor; } /** * @param ps * @return the line where the cursor is (from the beginning of the line to the cursor position). * @throws BadLocationException */ public String getLineContentsToCursor() throws BadLocationException { int offset = getAbsoluteCursorOffset(); return getLineContentsToCursor(offset); } public String getLineContentsToCursor(int offset) throws BadLocationException { return getLineContentsToCursor(doc, offset); } public static String getLineContentsToCursor(IDocument doc, int offset) throws BadLocationException { int lineOfOffset = doc.getLineOfOffset(offset); IRegion lineInformation = doc.getLineInformation(lineOfOffset); String lineToCursor = doc.get(lineInformation.getOffset(), offset - lineInformation.getOffset()); return lineToCursor; } /** * Helpful for having a '|' where the cursor == | and pressing a backspace and deleting both chars. */ public Tuple<String, String> getBeforeAndAfterMatchingChars(char c) { final int initial = getAbsoluteCursorOffset(); int curr = initial - 1; IDocument doc = getDoc(); FastStringBuffer buf = new FastStringBuffer(10); int length = doc.getLength(); while (curr >= 0 && curr < length) { char gotten; try { gotten = doc.getChar(curr); } catch (BadLocationException e) { break; } if (gotten == c) { buf.append(c); } else { break; } curr--; } String before = buf.toString(); buf.clear(); curr = initial; while (curr >= 0 && curr < length) { char gotten; try { gotten = doc.getChar(curr); } catch (BadLocationException e) { break; } if (gotten == c) { buf.append(c); } else { break; } curr++; } String after = buf.toString(); return new Tuple<String, String>(before, after); } /** * @return the offset mapping to the start of the current line. */ public int getStartLineOffset() { IRegion startLine = getStartLine(); return startLine.getOffset(); } /** * @return the complete dotted string given the current selection and the strings after * * e.g.: if we have a text of * 'value = aa.bb.cc()' and 'aa' is selected, this method would return the whole dotted string ('aa.bb.cc') * @throws BadLocationException */ public String getFullRepAfterSelection() throws BadLocationException { int absoluteCursorOffset = getAbsoluteCursorOffset(); int length = doc.getLength(); int end = absoluteCursorOffset; char ch = doc.getChar(end); while (Character.isLetterOrDigit(ch) || ch == '.') { end++; //check if we can still get some char if (length - 1 < end) { break; } ch = doc.getChar(end); } return doc.get(absoluteCursorOffset, end - absoluteCursorOffset); } /** * This function gets the activation token from the document given the current cursor position. * * @param document this is the document we want info on * @param offset this is the cursor position * @param getFullQualifier if true we get the full qualifier (even if it passes the current cursor location) * @return a tuple with the activation token and the cursor offset (may change if we need to get the full qualifier, * otherwise, it is the same offset passed as a parameter). */ public static Tuple<String, Integer> extractActivationToken(IDocument document, int offset, boolean getFullQualifier) { try { if (getFullQualifier) { //if we have to get the full qualifier, we'll have to walk the offset (cursor) forward while (offset < document.getLength()) { char ch = document.getChar(offset); if (Character.isJavaIdentifierPart(ch)) { offset++; } else { break; } } } int i = offset; if (i > document.getLength()) { return new Tuple<String, Integer>("", document.getLength()); //$NON-NLS-1$ } while (i > 0) { char ch = document.getChar(i - 1); if (!Character.isJavaIdentifierPart(ch)) { break; } i--; } return new Tuple<String, Integer>(document.get(i, offset - i), offset); } catch (BadLocationException e) { return new Tuple<String, Integer>("", offset); //$NON-NLS-1$ } } /** * @param c * @param string */ public static boolean containsOnly(char c, String string) { for (int i = 0; i < string.length(); i++) { if (string.charAt(i) != c) { return false; } } return true; } /** * @param string the string we care about * @return true if the string passed is only composed of whitespaces (or characters that * are regarded as whitespaces by Character.isWhitespace) */ public static boolean containsOnlyWhitespaces(String string) { for (int i = 0; i < string.length(); i++) { if (Character.isWhitespace(string.charAt(i)) == false) { return false; } } return true; } /** * @param selection the text from where we want to get the indentation * @return a string representing the whitespaces and tabs befor the first char in the passed line. */ public static String getIndentationFromLine(String selection) { int firstCharPosition = getFirstCharPosition(selection); return selection.substring(0, firstCharPosition); } public String getIndentationFromLine() { return getIndentationFromLine(getCursorLineContents()); } /** * @param doc * @param region * @return * @throws BadLocationException */ public static int getFirstCharRelativePosition(IDocument doc, IRegion region) throws BadLocationException { int offset = region.getOffset(); String src = doc.get(offset, region.getLength()); return getFirstCharPosition(src); } /** * @param doc * @param cursorOffset * @return * @throws BadLocationException */ public static int getFirstCharRelativeLinePosition(IDocument doc, int line) throws BadLocationException { IRegion region; region = doc.getLineInformation(line); return getFirstCharRelativePosition(doc, region); } /** * @param doc * @param cursorOffset * @return * @throws BadLocationException */ public static int getFirstCharRelativePosition(IDocument doc, int cursorOffset) throws BadLocationException { IRegion region; region = doc.getLineInformationOfOffset(cursorOffset); return getFirstCharRelativePosition(doc, region); } /** * Returns the position of the first non whitespace char in the current line. * @param doc * @param cursorOffset * @return position of the first character of the line (returned as an absolute * offset) * @throws BadLocationException */ public static int getFirstCharPosition(IDocument doc, int cursorOffset) throws BadLocationException { IRegion region; region = doc.getLineInformationOfOffset(cursorOffset); int offset = region.getOffset(); return offset + getFirstCharRelativePosition(doc, cursorOffset); } public int getFirstCharPositionInCurrentCursorOffset() throws BadLocationException { return getFirstCharPosition(getDoc(), getAbsoluteCursorOffset()); } /** * @param offset * @return */ public boolean intersects(int offset, int len) { int currOffset = this.textSelection.getOffset(); int currLen = this.textSelection.getLength(); ///The end is after the end of the current sel if (offset >= currOffset + currLen) { return false; } if (offset + len <= currOffset) { return false; } return true; } /** * @return the current token and its initial offset for this token * @throws BadLocationException */ public Tuple<String, Integer> getCurrToken() throws BadLocationException { Tuple<String, Integer> tup = extractActivationToken(doc, getAbsoluteCursorOffset(), false); String prefix = tup.o1; // ok, now, get the rest of the token, as we already have its prefix int start = tup.o2 - prefix.length(); int end = start; while (doc.getLength() - 1 >= end) { char ch = doc.getChar(end); if (Character.isJavaIdentifierPart(ch)) { end++; } else { break; } } String post = doc.get(tup.o2, end - tup.o2); return new Tuple<String, Integer>(prefix + post, start); } /** * @return the current token and its initial offset for this token * @param the chars to be considered separators (note that whitespace chars are always considered separators * and don't need to be in this set). * @throws BadLocationException */ public Tuple<String, Integer> getCurrToken(Set<Character> separatorChars) throws BadLocationException { int offset = getAbsoluteCursorOffset(); int i = offset; if (i > doc.getLength()) { return new Tuple<String, Integer>("", doc.getLength()); //$NON-NLS-1$ } while (i > 0) { char ch = doc.getChar(i - 1); if (separatorChars.contains(ch) || Character.isWhitespace(ch)) { break; } i--; } Tuple<String, Integer> tup = new Tuple<String, Integer>(doc.get(i, offset - i), offset); String prefix = tup.o1; // ok, now, get the rest of the token, as we already have its prefix int start = tup.o2 - prefix.length(); int end = start; while (doc.getLength() - 1 >= end) { char ch = doc.getChar(end); if (separatorChars.contains(ch) || Character.isWhitespace(ch)) { break; } end++; } String post = doc.get(tup.o2, end - tup.o2); return new Tuple<String, Integer>(prefix + post, start); } /** * This function replaces all the contents in the current line before the cursor for the contents passed * as parameter */ public void replaceLineContentsToSelection(String newContents) throws BadLocationException { int lineOfOffset = getDoc().getLineOfOffset(getAbsoluteCursorOffset()); IRegion lineInformation = getDoc().getLineInformation(lineOfOffset); getDoc().replace(lineInformation.getOffset(), getAbsoluteCursorOffset() - lineInformation.getOffset(), newContents); } /** * @param theDoc * @param documentOffset * @return * @throws BadLocationException */ public static int eatFuncCall(IDocument theDoc, int documentOffset) throws BadLocationException { String c = theDoc.get(documentOffset, 1); if (c.equals(")") == false) { throw new AssertionError("Expecting ) to eat callable. Received: " + c); } while (documentOffset > 0 && theDoc.get(documentOffset, 1).equals("(") == false) { documentOffset -= 1; } return documentOffset; } /** * Checks if the activationToken ends with some char from cs. */ public static boolean endsWithSomeChar(char cs[], String activationToken) { for (int i = 0; i < cs.length; i++) { if (activationToken.endsWith(cs[i] + "")) { return true; } } return false; } public static List<Integer> getLineStartOffsets(String replacementString) { ArrayList<Integer> ret = new ArrayList<Integer>(); ret.add(0);//there is always a starting one at 0 //we may have line breaks with \r\n, or only \n or \r for (int i = 0; i < replacementString.length(); i++) { char c = replacementString.charAt(i); if (c == '\r') { i++; int foundAt = i; if (i < replacementString.length()) { c = replacementString.charAt(i); if (c == '\n') { // i++; foundAt = i + 1; } } ret.add(foundAt); } else if (c == '\n') { ret.add(i + 1); } } return ret; } public static List<Integer> getLineBreakOffsets(String replacementString) { ArrayList<Integer> ret = new ArrayList<Integer>(); int lineBreaks = 0; int ignoreNextNAt = -1; //we may have line breaks with \r\n, or only \n or \r for (int i = 0; i < replacementString.length(); i++) { char c = replacementString.charAt(i); if (c == '\r') { lineBreaks++; ret.add(i); ignoreNextNAt = i + 1; } else if (c == '\n') { if (ignoreNextNAt != i) { ret.add(i); lineBreaks++; } } } return ret; } /** * @return if the offset is inside the region */ public static boolean isInside(int offset, IRegion region) { if (offset >= region.getOffset() && offset <= (region.getOffset() + region.getLength())) { return true; } return false; } /** * @return if the col is inside the initial col/len */ public static boolean isInside(int col, int initialCol, int len) { if (col >= initialCol && col <= (initialCol + len)) { return true; } return false; } /** * @return if the region passed is composed of a single line */ public static boolean endsInSameLine(IDocument document, IRegion region) { try { int startLine = document.getLineOfOffset(region.getOffset()); int end = region.getOffset() + region.getLength(); int endLine = document.getLineOfOffset(end); return startLine == endLine; } catch (BadLocationException e) { return false; } } /** * @param offset the offset we want info on * @return a tuple with the line, col of the passed offset in the document */ public Tuple<Integer, Integer> getLineAndCol(int offset) { try { IRegion region = doc.getLineInformationOfOffset(offset); int line = doc.getLineOfOffset(offset); int col = offset - region.getOffset(); return new Tuple<Integer, Integer>(line, col); } catch (BadLocationException e) { throw new RuntimeException(e); } } /** * @return the contents from the document starting at the cursor line until a colon is reached. */ public String getToColon() { FastStringBuffer buffer = new FastStringBuffer(); int docLen = doc.getLength(); for (int i = getLineOffset(); i < docLen; i++) { try { char c = doc.getChar(i); buffer.append(c); if (c == ':') { return buffer.toString(); } } catch (BadLocationException e) { throw new RuntimeException(e); } } return ""; //unable to find a colon } public IRegion getRegion() { return new Region(this.textSelection.getOffset(), this.textSelection.getLength()); } public int getEndOfDocummentOffset() { int length = this.doc.getLength(); return length; } public List<IRegion> searchOccurrences(String searchFor) { ArrayList<IRegion> lst = new ArrayList<IRegion>(); FindReplaceDocumentAdapter adapter = new FindReplaceDocumentAdapter(this.doc); boolean regExSearch = false; boolean wholeWord = true; boolean caseSensitive = true; boolean forwardSearch = true; int startOffset = 0; try { while (true) { IRegion found = adapter.find(startOffset, searchFor, forwardSearch, caseSensitive, wholeWord, regExSearch); if (found == null) { break; } lst.add(found); startOffset = found.getOffset() + found.getLength(); } } catch (BadLocationException e) { Log.log(e); } return lst; } /** * 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; } /** * @param docContents should be == doc.get() (just optimizing if the user already did that before). */ public static void setOnlyDifferentCode(IDocument doc, String docContents, String newContents) { String contents = docContents; if (contents == null) { contents = doc.get(); } int minorLen; int contentsLen = contents.length(); if (contentsLen > newContents.length()) { minorLen = newContents.length(); } else { minorLen = contentsLen; } int applyFrom = 0; for (; applyFrom < minorLen; applyFrom++) { if (contents.charAt(applyFrom) == newContents.charAt(applyFrom)) { continue; } else { //different break; } } if (applyFrom >= contentsLen) { //Document is the same. return; } try { doc.replace(applyFrom, contentsLen - applyFrom, newContents.substring(applyFrom)); } catch (BadLocationException e) { Log.log(e); } } public Tuple<String, Integer> getCurrDottedStatement(ICharacterPairMatcher2 pairMatcher) throws BadLocationException { int absoluteCursorOffset = getAbsoluteCursorOffset(); int start = absoluteCursorOffset; for (int i = absoluteCursorOffset - 1; i >= 0; i--) { char c = doc.getChar(i); if (!Character.isJavaIdentifierPart(c) && c != '.') { //We're at the start now, so, let's go onwards now... if (StringUtils.isClosingPeer(c)) { int j = pairMatcher.searchForOpeningPeer(i, StringUtils.getPeer(c), c, doc); if (j < 0) { break; } i = j; } else { break; } } start = i; } int len = doc.getLength(); int end = absoluteCursorOffset; for (int i = absoluteCursorOffset; i < len; i++) { char c = doc.getChar(i); if (!Character.isJavaIdentifierPart(c) && c != '.') { if (StringUtils.isOpeningPeer(c)) { int j = pairMatcher.searchForClosingPeer(i, c, StringUtils.getPeer(c), doc); if (j < 0) { break; } i = j; } else { break; } } end = i + 1; } if (start != end) { return new Tuple<String, Integer>(doc.get(start, end - start), start); } return new Tuple<String, Integer>("", absoluteCursorOffset); } /** * Stop a rewrite session */ public static void endWrite(IDocument doc, DocumentRewriteSession session) { if (doc instanceof IDocumentExtension4 && session != null) { IDocumentExtension4 d = (IDocumentExtension4) doc; d.stopRewriteSession(session); } } /** * Starts a rewrite session (keep things in a single undo/redo) */ public static DocumentRewriteSession startWrite(IDocument doc) { if (doc instanceof IDocumentExtension4) { IDocumentExtension4 d = (IDocumentExtension4) doc; return d.startRewriteSession(DocumentRewriteSessionType.UNRESTRICTED); } return null; } /** * Performs a simple sort without taking into account the actual contents of the selection (aside from lines * ending with '\' which are considered as a single line). * * @param doc the document to be sorted * @param startLine the first line where the sort should happen * @param endLine the last line where the sort should happen */ public void performSimpleSort(IDocument doc, int startLine, int endLine) { String endLineDelim = this.getEndLineDelim(); try { ArrayList<String> list = new ArrayList<String>(); StringBuffer lastLine = null; for (int i = startLine; i <= endLine; i++) { String line = getLine(doc, i); if (lastLine != null) { int len = lastLine.length(); if (len > 0 && lastLine.charAt(len - 1) == '\\') { lastLine.append(endLineDelim); lastLine.append(line); } else { list.add(lastLine.toString()); lastLine = new StringBuffer(line); } } else { lastLine = new StringBuffer(line); } } if (lastLine != null) { list.add(lastLine.toString()); } Collections.sort(list); StringBuffer all = new StringBuffer(); for (Iterator<String> iter = list.iterator(); iter.hasNext();) { String element = iter.next(); all.append(element); if (iter.hasNext()) { all.append(endLineDelim); } } int length = doc.getLineInformation(endLine).getLength(); int endOffset = doc.getLineInformation(endLine).getOffset() + length; int startOffset = doc.getLineInformation(startLine).getOffset(); doc.replace(startOffset, endOffset - startOffset, all.toString()); } catch (BadLocationException e) { Log.log(e); } } public String getContentsFromLineRange(int startLine, int endLine) { try { IRegion startRegion = doc.getLineInformation(startLine); IRegion endRegion = doc.getLineInformation(endLine); String contents = doc.get(startRegion.getOffset(), endRegion.getOffset() + endRegion.getLength() - startRegion.getOffset()); return contents; } catch (BadLocationException e) { return ""; } } }