⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pyselection.java

📁 Python Development Environment (Python IDE plugin for Eclipse). Features editor, code completion, re
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
/*
 * @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 java.util.regex.Pattern;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentPartitioner;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.texteditor.ITextEditor;
import org.python.pydev.core.IPythonPartitions;
import org.python.pydev.core.Tuple;
import org.python.pydev.core.Tuple3;
import org.python.pydev.core.ICodeCompletionASTManager.ImportInfo;
import org.python.pydev.core.log.Log;
import org.python.pydev.core.uiutils.RunInUiThread;

/**
 * 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
 */
public class PySelection {
    
    private IDocument doc;
    private ITextSelection textSelection;
	public static final String[] DEDENT_TOKENS = new String[]{
	    "return",
	    "break",
	    "continue",
	    "pass",
	    "raise",
	    "yield"
	};

	public static final String[] CLASS_AND_FUNC_TOKENS = new String[]{
	    "def"     ,
	    "class"   ,
    };
    
	public static final String[] INDENT_TOKENS = new String[]{
		"if"      , 
		"for"     , 
		"except"  , 
		"def"     ,
		"class"   ,
		"else"    ,
		"elif"    ,
		"while"   ,
		"try"     ,
		"with"     ,
		"finally" 
	};
	

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

    /**
     * This is a 'factory' method so that we can create a PySelection from a non-ui thread (it syncs the execution
     * if needed).
     * 
     * @param textEditor the text editor that will be used to create the selection
     * @return the pyselection created
     */
    public static PySelection createFromNonUiThread(final ITextEditor textEditor) {
    	final Tuple<PySelection, Object> t = new Tuple<PySelection, Object>(null, null);
        Runnable r = new Runnable(){
            public void run() {
                try {
					t.o1 = new PySelection(textEditor);
				} catch (NullPointerException e) {
					// this can happen if the selection was still not set up
				}
            }
        };
        RunInUiThread.sync(r);
        return t.o1;
    }

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

    /**
     * Creates a selection from a document
     * @param doc the document to be used
     * @param line the line (starts at 0)
     * @param col the col (starts at 0)
     */
    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;
		this.textSelection = new TextSelection(doc, getAbsoluteCursorOffset(line, col), len);
    }
    
    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);
        }
    }
    
    public int getAbsoluteCursorOffset(int line, int col) {
        return getAbsoluteCursorOffset(doc, line, col);
    }

    
    /**
     * @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 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
     */
    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
     */
    public PySelection(IDocument doc) {
        this(doc, 0);
    }
    /**
     * In event of partial selection, used to select the full lines involved. 
     */
    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
     * 
     */
    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 beginning of the document
                int lineOfOffset = getLineOfOffset(firstGlobalLiteral[1]);
                return getFirstNonCommentLineOrAfterCurrentImports(lineOfOffset + 1);
            }else{

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


    private int getFirstNonCommentLineOrAfterCurrentImports() {
        return getFirstNonCommentLineOrAfterCurrentImports(0);
    }
    
    /**
     * @return the first line found that is not a comment.
     */
    private int getFirstNonCommentLineOrAfterCurrentImports(int startingAtLine) {
        int firstNonCommentLine = -1;
        int afterFirstImports = -1;
        
        IDocument document = getDoc();
        int lines = document.getNumberOfLines();
        for (int line = startingAtLine; line < lines; line++) {
            String str = getLine(line);
            if (str.startsWith("#")) {
                continue;
            }else{
                int i;
                if((i = str.indexOf('#')) != -1){
                    str = str.substring(0, i);
                }
                
                if(firstNonCommentLine == -1){
                    firstNonCommentLine = line;
                }
                ImportInfo importInfo = ImportsSelection.getImportsTipperStr(str, false);
                if(importInfo != null && importInfo.importsTipperStr != null && importInfo.importsTipperStr.trim().length() > 0){
                    if((i = str.indexOf('(')) != -1){
                        StringBuffer buf = new StringBuffer();
                        //start of a multiline import
                        int lineOffset = -1;
                        try {
							lineOffset = document.getLineOffset(line);
						} catch (BadLocationException e1) {
							throw new RuntimeException(e1);
						}
                        int j = ParsingUtils.eatPar(document, lineOffset+i, buf);
                        try {
                            line = document.getLineOfOffset(j);
                        } catch (BadLocationException e) {
                            Log.log(e);
                        }
                    }else if(str.endsWith("\\")){
                        while(str.endsWith("\\") && line < lines){
                            line++;
                            str = getLine(line);
                        }
                    }
                    afterFirstImports = line+1;
                }else if(str.trim().length() > 0){
                    //found some non-empty, non-import, non-comment line (break it here)
                    break;
                }
            }
        }
        return afterFirstImports > firstNonCommentLine?afterFirstImports:firstNonCommentLine;
    }
    
    
    /**
     * @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
     */
    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 getLineWithoutCommentsOrLiterals(String l) {
        StringBuffer buf = new StringBuffer(l);
        ParsingUtils.removeCommentsWhitespacesAndLiterals(buf, false);
        return buf.toString();
        
    }
    public String getLineWithoutCommentsOrLiterals() {
        return getLineWithoutCommentsOrLiterals(getLine());
    }

	public static String getLineWithoutLiterals(String line) {
		StringBuffer buf = new StringBuffer(line);
		ParsingUtils.removeLiterals(buf);
		return buf.toString();
	}
    
    /**
     * @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 {
            return doc.get(doc.getLineInformation(i).getOffset(), doc.getLineInformation(i).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) {
            return 0;
        }
    }
    
    /**

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -