Logo Search packages:      
Sourcecode: eclipse-pydev version File versions  Download package

PySelection.java

/*
 * @author: ptoofani
 * @author Fabio Zadrozny
 * Created: June 2004
 * License: Common Public License v1.0
 */

package org.python.pydev.core.docutils;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.texteditor.ITextEditor;
import org.python.pydev.core.Tuple;
import org.python.pydev.core.log.Log;

/**
 * Redone the whole class, so that the interface is better defined and no
 * duplication of information is given.
 * 
 * Now, it is just used as 'shortcuts' to document and selection settings.
 * 
 * @author Fabio Zadrozny
 * @author Parhaum Toofanian
 */
00034 public class PySelection {
    
    private IDocument doc;
    private ITextSelection textSelection;


    /**
       * Alternate constructor for PySelection. Takes in a text editor from Eclipse.
       * 
       * @param textEditor The text editor operating in Eclipse
       */
00045     public PySelection(ITextEditor textEditor) {
        this(textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput()), 
                (ITextSelection) textEditor.getSelectionProvider().getSelection());
    }


    /**
     * @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
     */
00055     public PySelection(IDocument doc, ITextSelection selection) {
        this.doc = doc;
        this.textSelection = selection;
    }

    public PySelection(IDocument doc, int line, int col) {
      this(doc, line, col, 0);
    }
    
    public PySelection(IDocument doc, int line, int col, int len) {
      this.doc = doc;
      try {
                  IRegion offsetR = this.doc.getLineInformation(line);
                  this.textSelection = new TextSelection(doc, offsetR.getOffset() + col, 0);
            } catch (BadLocationException e) {
                  throw new RuntimeException(e);
            }
    }
    
    /**
     * @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)
     */
00078     public PySelection(IDocument doc, int offset) {
        this.doc = doc;
        this.textSelection = new TextSelection(doc, offset, 0);
    }

    /**
     * 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
     */
00088     public void setSelection(int absoluteStart, int absoluteEnd) {
        this.textSelection = new TextSelection(doc, absoluteStart, absoluteEnd-absoluteStart);
    }

    /**
     * Creates a selection for the document, so that no characters are selected and the offset is position 0
     * @param doc the document where we are doing the selection
     */
00096     public PySelection(IDocument doc) {
        this(doc, 0);
    }
    /**
     * In event of partial selection, used to select the full lines involved.
     */
00102     public void selectCompleteLine() {
        IRegion endLine = getEndLine();
        IRegion startLine = getStartLine();
        
        this.textSelection = new TextSelection(doc, startLine.getOffset(), endLine.getOffset() + endLine.getLength() - startLine.getOffset());
    }

    /**
     * @return the line where a global import would be able to happen.
     * 
     * The 'usual' structure that we take into consideration for a py file here is:
     * 
     * #coding ...
     * 
     * '''
     * multiline comment...
     * '''
     * 
     * imports #that's what we want to find out
     * 
     * code
     * 
     */
00125     public int getLineAvailableForImport() {
        StringBuffer multiLineBuf = new StringBuffer();
        int[] firstGlobalLiteral = getFirstGlobalLiteral(multiLineBuf, 0);

        if (multiLineBuf.length() > 0 && firstGlobalLiteral[0] >= 0 && firstGlobalLiteral[1] >= 0) {
            //ok, multiline found
            int startingMultilineComment = getLineOfOffset(firstGlobalLiteral[0]);
            
            if(startingMultilineComment < 4){
                
                //let's see if the multiline comment found is in the beggining of the document
                int lineOfOffset = getLineOfOffset(firstGlobalLiteral[1]);
                return lineOfOffset + 1;
            }else{

                return getFirstNonCommentLine();
            }
        } else {
            
            //ok, no multiline comment, let's get the first line that is not a comment
            return getFirstNonCommentLine();
        }
    }


    /**
     * @return the first line found that is not a comment.
     */
00153     private int getFirstNonCommentLine() {
        int lineToMoveImport = 0;
        int lines = getDoc().getNumberOfLines();
        for (int line = 0; line < lines; line++) {
            String str = getLine(line);
            if (! str.startsWith("#")) {
                lineToMoveImport = line;
                break;
            }
        }
        return lineToMoveImport;
    }
    
    
    /**
     * @param initialOffset this is the offset we should use to analyze it
     * @param buf (out) this is the comment itself
     * @return a tuple with the offset of the start and end of the first multiline comment found
     */
00172     public int[] getFirstGlobalLiteral(StringBuffer buf, int initialOffset){
        try {
            IDocument d = getDoc();
            String strDoc = d.get(initialOffset, d.getLength() - initialOffset);
            
            if(initialOffset > strDoc.length()-1){
                return new int[]{-1, -1};
            }
            
            char current = strDoc.charAt(initialOffset);
            
            //for checking if it is global, it must be in the beggining of a line (must be right after a \r or \n).
            
            while (current != '\'' && current != '"' && initialOffset < strDoc.length()-1) {
                  
                  //if it is inside a parenthesis, we will not take it into consideration.
                if(current == '('){
                    initialOffset = ParsingUtils.eatPar(strDoc, initialOffset, buf);
                }
                
                
                initialOffset += 1;
                if(initialOffset < strDoc.length()-1){
                    current = strDoc.charAt(initialOffset);
                }
            }

            //either, we are at the end of the document or we found a literal
            if(initialOffset < strDoc.length()-1){

                  if(initialOffset == 0){ //first char of the document... this is ok
                      int i = ParsingUtils.eatLiterals(strDoc, buf, initialOffset);
                      return new int[]{initialOffset, i};
                  }
                  
                  char lastChar = strDoc.charAt(initialOffset-1);
                  //it is only global if after \r or \n
                  if(lastChar == '\r' || lastChar == '\n'){
                      int i = ParsingUtils.eatLiterals(strDoc, buf, initialOffset);
                      return new int[]{initialOffset, i};
                  }
                  
                //ok, still not found, let's keep going
                  return getFirstGlobalLiteral(buf, initialOffset+1);
            }else{
                  return new int[]{-1, -1};
                  
            }
        } catch (BadLocationException e) {
            throw new RuntimeException(e);
        }
    }

    protected static void beep(Exception e) {
        Log.log(e);
        PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell().getDisplay().beep();
    }

    public static String getLineWithoutComments(String l) {
        int i;
        if((i = l.indexOf('#') ) != -1){
            l = l.substring(0, i);
        }
        return l;
        
    }
    public String getLineWithoutComments() {
        return getLineWithoutComments(getLine());
    }
    
    /**
     * Gets current line from document.
     * 
     * @return String line in String form
     */
00247     public String getLine() {
        return getLine(getDoc(), getCursorLine());
    }
    

    /**
     * Gets line from document.
     * 
     * @param i Line number
     * @return String line in String form
     */
00258     public String getLine(int i) {
        return getLine(getDoc(), i);
    }
    
    /**
     * Gets line from document.
     * 
     * @param i Line number
     * @return String line in String form
     */
00268     public static String getLine(IDocument doc, int i) {
        try {
            return doc.get(doc.getLineInformation(i).getOffset(), doc.getLineInformation(i).getLength());
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * @param offset the offset we want to get the line
     * @return the line of the passed offset
     */
00280     public int getLineOfOffset(int offset) {
        try {
            return getDoc().getLineOfOffset(offset);
        } catch (BadLocationException e) {
            return 0;
        }
    }
    /**
     * Gets cursor offset within a line.
     * 
     * @return int Offset to put cursor at
     */
00292     public int getLineOffset() {
        try {
            return getDoc().getLineInformation(getCursorLine()).getOffset();
        } catch (Exception e) {
            return 0;
        }
    }

    /**
     * Deletes a line from the document
     * @param i
     */
00304     public void deleteLine(int i) {
        deleteLine(getDoc(), i);
    }

    /**
     * Removes comments at the end of the document
     * @param doc this is the document from where the comments must be removed
     * @return a StringBuffer with the comments that have been removed
     */
00313     public static StringBuffer removeEndingComments(IDocument doc){
        StringBuffer comments = new StringBuffer();
        int lines = doc.getNumberOfLines();
        String delimiter = PySelection.getDelimiter(doc);
        for (int i = lines-1; i >= 0; i--) {
            String line = PySelection.getLine(doc, i);
            String trimmed = line.trim();
            if(trimmed.length() > 0 && trimmed.charAt(0) != '#'){
                return comments;
            }
            comments.insert(0,line);
            comments.insert(0,delimiter);
            try {
                if(line.length() > 0){
                    PySelection.deleteLine(doc, i);
                }
            } catch (Exception e) {
                //ignore
            }
        }
        return comments;
    }
    
    /**
     * Deletes a line from the document
     * @param i
     */
00340     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) {
            e.printStackTrace();
        } 
    }
    
    /**
     * Deletes the current selected text
     * 
     * @throws BadLocationException
     */
00367     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);
    }
    
    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 (!contents.endsWith(endLineDelim)){
                contents += endLineDelim;
            }
            
            if(offset >= 0){
                doc.replace(offset, 0, contents);
            }
        } catch (BadLocationException e) {
            e.printStackTrace();
        } 
    }

    /**
     * @param ps
     * @return the line where the cursor is (from the beggining of the line to the cursor position).
     * @throws BadLocationException
     */
00406     public String getLineContentsFromCursor() throws BadLocationException {
        int lineOfOffset = getDoc().getLineOfOffset(getAbsoluteCursorOffset());
        IRegion lineInformation = getDoc().getLineInformation(lineOfOffset);
        
        
        String lineToCursor = getDoc().get(getAbsoluteCursorOffset(),   lineInformation.getOffset() + lineInformation.getLength() - getAbsoluteCursorOffset());
        return lineToCursor;
    }

    /**
     * @param ps
     * @return the line where the cursor is (from the beggining of the line to the cursor position).
     * @throws BadLocationException
     */
00420     public String getLineContentsToCursor() throws BadLocationException {
        int lineOfOffset = getDoc().getLineOfOffset(getAbsoluteCursorOffset());
        IRegion lineInformation = getDoc().getLineInformation(lineOfOffset);
        String lineToCursor = getDoc().get(lineInformation.getOffset(), getAbsoluteCursorOffset() - lineInformation.getOffset());
        return lineToCursor;
    }

    /**
     * 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.
     */
00433     public void selectAll(boolean forceNewSelection) {
        if (!forceNewSelection){
            if(getSelLength() > 0)
                return;
        }
        
        textSelection = new TextSelection(doc, 0, doc.getLength());
    }

    /**
     * @return Returns the startLineIndex.
     */
00445     public int getStartLineIndex() {
        return this.getTextSelection().getStartLine();
    }


    /**
     * @return Returns the endLineIndex.
     */
00453     public int getEndLineIndex() {
        return this.getTextSelection().getEndLine();
    }

    /**
     * @return Returns the doc.
     */
00460     public IDocument getDoc() {
        return doc;
    }


    /**
     * @return Returns the selLength.
     */
00468     public int getSelLength() {
        return this.getTextSelection().getLength();
    }


    /**
     * @return Returns the selection.
     */
00476     public String getCursorLineContents() {
        try {
            int start = getStartLine().getOffset();
            int end = getEndLine().getOffset() + getEndLine().getLength();
            return this.doc.get(start, end-start);
        } catch (BadLocationException e) {
            Log.log(e);
        }
        return "";
    }

    public static String getDelimiter(IDocument doc){
        return getDelimiter(doc, 0);
    }
    
    /**
     * This method returns the delimiter for the document
     * @param doc
     * @param startLineIndex
     * @return  delimiter for the document (\n|\r\|r\n)
     * @throws BadLocationException
     */
00498     public static String getDelimiter(IDocument doc, int line){
        String endLineDelim;
        try {
            if (doc.getNumberOfLines() > 1){
                endLineDelim = doc.getLineDelimiter(line);
                if (endLineDelim == null) {
                    endLineDelim = doc.getLegalLineDelimiters()[0];
                }
                return endLineDelim;
            }
        } catch (BadLocationException e) {
            Log.log(e);
        }
        return System.getProperty("line.separator"); 
        
    }

    /**
     * @return Returns the endLineDelim.
     */
00518     public String getEndLineDelim() {
        return getDelimiter(getDoc());
    }

    /**
     * @return Returns the startLine.
     */
00525     public IRegion getStartLine() {
        try {
            return getDoc().getLineInformation(getStartLineIndex());
        } catch (BadLocationException e) {
            Log.log(e);
        }
        return null;
    }

    /**
     * @return Returns the endLine.
     */
00537     public IRegion getEndLine() {
        try {
            return getDoc().getLineInformation(getEndLineIndex());
        } catch (BadLocationException e) {
            Log.log(e);
        }
        return null;
    }

    /**
     * @return Returns the cursorLine.
     */
00549     public int getCursorLine() {
        return this.getTextSelection().getEndLine();
    }

    /**
     * @return Returns the absoluteCursorOffset.
     */
00556     public int getAbsoluteCursorOffset() {
        return this.getTextSelection().getOffset();
    }

    /**
     * @return Returns the textSelection.
     */
00563     public ITextSelection getTextSelection() {
        return textSelection;
    }


    /**
     * @return the Selected text
     */
00571     public String getSelectedText() {
        int start = getTextSelection().getOffset();
        int len = getTextSelection().getLength();
        try {
            return this.doc.get(start, len);
        } catch (BadLocationException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * @return
     * @throws BadLocationException
     */
00586     public char getCharAfterCurrentOffset() throws BadLocationException {
        return getDoc().getChar(getAbsoluteCursorOffset()+1);
    }
    
    /**
     * @return
     * @throws BadLocationException
     */
00594     public char getCharAtCurrentOffset() throws BadLocationException {
        return getDoc().getChar(getAbsoluteCursorOffset());
    }

    
    /**
     * @return the offset mapping to the end of the line passed as parameter.
     * @throws BadLocationException 
     */
00603     public 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 line.
     */
00611     public int getEndLineOffset() {
        IRegion endLine = getEndLine();
        return endLine.getOffset() + endLine.getLength();
    }

    /**
     * @return the offset mapping to the start of the current line.
     */
00619     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 
     */
00632     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 tokens inside the parenthesis that start at the current selection line
         * 
         * @param addSelf: this defines whether tokens named self should be added if it is found.
         * 
         * @return a Tuple so that the first param is the list and the second the offset of the end of the parentesis it may return null if no starting parentesis was found at the current line
         */
00656     public Tuple<List<String>, Integer> getInsideParentesisToks(boolean addSelf) {
        List<String> l = new ArrayList<String>();

        String line = getLine();
        int openParIndex = line.indexOf('(');
        if (openParIndex == -1) { // we are in a line that does not have a parentesis
            return null;
        }
        int lineOffset = getStartLineOffset();
        StringBuffer buf = new StringBuffer();
        String docContents = doc.get();
        int i = lineOffset + openParIndex;
        int j = ParsingUtils.eatPar(docContents, i, buf);
        String insideParentesisTok = docContents.substring(i + 1, j);

        StringTokenizer tokenizer = new StringTokenizer(insideParentesisTok, ",");
        while (tokenizer.hasMoreTokens()) {
            String tok = tokenizer.nextToken();
            String trimmed = tok.split("=")[0].trim();
            trimmed = trimmed.replaceAll("\\(", "");
            trimmed = trimmed.replaceAll("\\)", "");
            if (!addSelf && trimmed.equals("self")) {
                // don't add self...
            } else {
                l.add(trimmed);
            }
        }
        return new Tuple<List<String>, Integer>(l, j);
    }


    /**
     * This function replaces all the contents in the current line before the cursor for the contents passed
     * as parameter 
     */
00691     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);

    }


    /**
     * This function goes backward in the document searching for an 'if' and returns the line that has it.
     * 
     * May return null if it was not found.
     */
00704     public String getPreviousLineThatAcceptsElse() {
        DocIterator iterator = new DocIterator(this.getCursorLine(), false);
        while(iterator.hasNext()){
            String line = (String) iterator.next();
            String trimmed = line.trim();
            if(trimmed.startsWith("if ") || trimmed.startsWith("if(") || trimmed.startsWith("for ")  || trimmed.startsWith("for(") 
                    || trimmed.startsWith("except")|| trimmed.startsWith("except(") ){
                return line;
            }
        }
        return null;
    }

    class DocIterator implements Iterator{
        private int startingLine;
        private boolean forward;

        public DocIterator(int startingLine, boolean forward){
            this.startingLine = startingLine;
            this.forward = forward;
        }

        public boolean hasNext() {
            if(forward){
                throw new RuntimeException("Forward iterator not implemented.");
            }else{
                return startingLine >= 0;
            }
        }

        public Object next() {
            String line = getLine(startingLine);
            if(forward){
                throw new RuntimeException("Forward iterator not implemented.");
            }else{
                startingLine--;
            }
            return line;
        }

        public void remove() {
            throw new RuntimeException("Remove not implemented.");
        }
    }


  
  
}

Generated by  Doxygen 1.6.0   Back to index