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

📄 pylinkedmodecompletionproposal.java

📁 Python Development Environment (Python IDE plugin for Eclipse). Features editor, code completion, re
💻 JAVA
字号:
/*
 * Created on Jul 1, 2006
 * @author Fabio
 */
package org.python.pydev.editor.codecompletion;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.ICompletionProposalExtension;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.link.LinkedModeModel;
import org.eclipse.jface.text.link.LinkedModeUI;
import org.eclipse.jface.text.link.LinkedPositionGroup;
import org.eclipse.jface.text.link.ProposalPosition;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.ui.texteditor.link.EditorLinkedModeUI;
import org.python.pydev.core.uiutils.RunInUiThread;
import org.python.pydev.plugin.PydevPlugin;

public class PyLinkedModeCompletionProposal extends PyCompletionProposalExtension2 implements ICompletionProposalExtension{
    

    private int firstParameterLen = 0;
    
    /**
     * The number of positions that we should add to the original position.
     * 
     * Used so that when we enter '.', we add an additional position (because '.' will be added when applying the completion) 
     * or so that we can go back one position when the toggle mode (ctrl) is on and a completion with parameters is applied (and they
     * are removed)
     */
    private int nPositionsAdded = 0;
    
    public PyLinkedModeCompletionProposal(String replacementString, int replacementOffset, int replacementLength, int cursorPosition, Image image, String displayString, IContextInformation contextInformation, String additionalProposalInfo, int priority, int onApplyAction, String args) {
        super(replacementString, replacementOffset, replacementLength, cursorPosition, image, displayString, contextInformation, additionalProposalInfo, priority, onApplyAction, args);
    }
    
    /*
     * @see ICompletionProposal#getSelection(IDocument)
     */
    public Point getSelection(IDocument document) {
        if(onApplyAction == ON_APPLY_JUST_SHOW_CTX_INFO){
            return null;
        }
        if(onApplyAction == ON_APPLY_SHOW_CTX_INFO_AND_ADD_PARAMETETRS ){
            if(fArgs.length() > 0){
                return new Point(fReplacementOffset + fCursorPosition-1, firstParameterLen); //the difference is the firstParameterLen here (instead of 0)
            }
            return null;
        }
        if(onApplyAction == ON_APPLY_DEFAULT ){
            return new Point(fReplacementOffset + fCursorPosition + nPositionsAdded, firstParameterLen); //the difference is the firstParameterLen here (instead of 0)
        }
        throw new RuntimeException("Unexpected apply mode:"+onApplyAction);
    }


    public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) {
        boolean eat = (stateMask & SWT.MOD1) != 0;
        IDocument doc = viewer.getDocument();
        
        if(onApplyAction == ON_APPLY_JUST_SHOW_CTX_INFO){
            return;
        }
        if(onApplyAction == ON_APPLY_SHOW_CTX_INFO_AND_ADD_PARAMETETRS){
            try {
                String args;
                if(fArgs.length() > 0){
                    args = fArgs.substring(1, fArgs.length()-1); //remove the parentesis
                }else{
                    args = "";
                }
                super.apply(doc);
                int iPar = -1;
                int exitPos = offset + args.length()+1;
                goToLinkedModeFromArgs(viewer, offset, doc, exitPos, iPar, args);

            }catch(BadLocationException e){
                PydevPlugin.log(e);
            }
            return;
        }
        
        
        if(onApplyAction == ON_APPLY_DEFAULT){
            try {
                int dif = offset - fReplacementOffset;
                String strToAdd = fReplacementString.substring(dif);
                boolean doReturn = applyOnDoc(offset, eat, doc, dif, trigger);
                
                if(doReturn){
                    return;
                }
                
                //ok, now, on to the linking part
                int iPar = strToAdd.indexOf('(');
                if(iPar != -1 && strToAdd.charAt(strToAdd.length()-1) == ')'){
                    String newStr = strToAdd.substring(iPar+1, strToAdd.length()-1);
                    goToLinkedModeFromArgs(viewer, offset, doc, offset + strToAdd.length()+nPositionsAdded, iPar, newStr);
                }
            } catch (BadLocationException e) {
                PydevPlugin.log(e);
            }
            return;
        }
        
        throw new RuntimeException("Unexpected apply mode:"+onApplyAction);

    }

    /**
     * Applies the changes in the document (useful for testing)
     * 
     * @param offset the offset where the change should be applied
     * @param eat whether we should 'eat' the selection (on toggle)
     * @param doc the document where the changes should be applied 
     * @param dif the difference between the offset and and the replacement offset  
     * 
     * @return whether we should return (and not keep on with the linking mode)
     * @throws BadLocationException
     */
    public boolean applyOnDoc(int offset, boolean eat, IDocument doc, int dif, char trigger) throws BadLocationException {
        boolean doReturn = false;
        
        String rep = fReplacementString;
        int iPar = rep.indexOf('(');
        
        if(eat){
            
            //behavior change: when we have a parenthesis and we're in toggle (eat) mode, let's not add the 
            //parenthesis anymore.
            if(/*fLastIsPar &&*/ iPar != -1){
                rep = rep.substring(0, iPar);
                doc.replace(offset-dif, dif+this.fLen, rep);
                //if the last was a parenthesis, there's nothing to link, so, let's return
                if(!fLastIsPar){
                    nPositionsAdded = -1;
                }
                doReturn = true;
            }else{
                doc.replace(offset-dif, dif+this.fLen, rep);
            }
        }else{
            if(trigger == '.'){
                if(iPar != -1){
                    //if we had a completion with parameters, we should just remove everything that would appear after
                    //the parenthesis -- and we don't need to raise nTriggerCharsAdded because the cursor position would
                    //already be after the '(. -- which in this case we'll substitute for a '.'
                    rep = rep.substring(0, iPar);
                }else{
                    nPositionsAdded = 1;
                }
                rep = rep+trigger;
                
                //linking should not happen when applying '.'
                doReturn = true;
            }
            doc.replace(offset-dif, dif, rep);
        }
        return doReturn;
    }

    private void goToLinkedModeFromArgs(ITextViewer viewer, int offset, IDocument doc, int exitPos, int iPar, String newStr) throws BadLocationException {
        List<Integer> offsetsAndLens = new ArrayList<Integer>();
        
        StringBuffer buffer = new StringBuffer();
        for (int i = 0; i < newStr.length(); i++) {
            char c = newStr.charAt(i);
            
            if(Character.isJavaIdentifierPart(c)){
                if(buffer.length() == 0){
                    offsetsAndLens.add(i);
                    buffer.append(c);
                }else{
                    buffer.append(c);
                }
            }else{
                if(buffer.length() > 0){
                    offsetsAndLens.add(buffer.length());
                    buffer = new StringBuffer();
                }
            }
        }
        if(buffer.length() > 0){
            offsetsAndLens.add(buffer.length());
        }
        buffer = null;
        
        goToLinkedMode(viewer, offset, doc, exitPos, iPar, offsetsAndLens);
    }

    private void goToLinkedMode(ITextViewer viewer, int offset, IDocument doc, int exitPos, int iPar, List<Integer> offsetsAndLens) throws BadLocationException {
        if(offsetsAndLens.size() > 0){
            LinkedModeModel model= new LinkedModeModel();
            
            for (int i = 0; i < offsetsAndLens.size(); i++) {
                Integer offs = offsetsAndLens.get(i);
                i++;
                Integer len = offsetsAndLens.get(i);
                if(i == 1){
                    firstParameterLen = len;
                }
                int location = offset+iPar+offs+1;
                LinkedPositionGroup group= new LinkedPositionGroup();
                ProposalPosition proposalPosition = new ProposalPosition(doc, location, len, 0 , new ICompletionProposal[0]);
                group.addPosition(proposalPosition);
                model.addGroup(group);
            }
            
            model.forceInstall();
            
            final LinkedModeUI ui= new EditorLinkedModeUI(model, viewer);
            ui.setDoContextInfo(true); //set it to request the ctx info from the completion processor
            ui.setExitPosition(viewer, exitPos, 0, Integer.MAX_VALUE);
            Runnable r = new Runnable(){
                public void run() {
                    ui.enter();
                }
            };
            RunInUiThread.async(r);

        }
    }
    
    
    
    //ICompletionProposalExtension

    protected final static char[] VAR_TRIGGER= new char[] { '.' };
    
    /**
     * We want to apply it on \n or on '.'
     * 
     * When . is entered, the user will finish (and apply) the current completion
     * and request a new one with '.'
     */
    public char[] getTriggerCharacters(){
        if(onApplyAction == ON_APPLY_DEFAULT){
            return VAR_TRIGGER;
        }
        return null;
    }
    
    public void apply(IDocument document, char trigger, int offset) {
        throw new RuntimeException("Not implemented");
    }

    public int getContextInformationPosition() {
        return this.fCursorPosition;
    }

    public boolean isValidFor(IDocument document, int offset) {
        return validate(document, offset, null);
    }
    
    

}

⌨️ 快捷键说明

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