[Pydev-cvs] org.python.pydev/src/org/python/pydev/editor/codecompletion PyTemplateCompletion.java,NO
Brought to you by:
fabioz
Update of /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/codecompletion In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21162/src/org/python/pydev/editor/codecompletion Added Files: PyTemplateCompletion.java PythonCompletionProcessor.java PyCodeCompletion.java CompletionCache.java Log Message: Refactored code completion. --- NEW FILE: PyTemplateCompletion.java --- /* * Created on Aug 11, 2004 * * @author Fabio Zadrozny */ package org.python.pydev.editor.codecompletion; import java.util.List; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.eclipse.jface.text.templates.Template; import org.eclipse.jface.text.templates.TemplateCompletionProcessor; import org.eclipse.jface.text.templates.TemplateContextType; import org.eclipse.swt.graphics.Image; import org.python.pydev.editor.templates.PyContextType; import org.python.pydev.plugin.PydevPlugin; /** * @author Fabio Zadrozny */ public class PyTemplateCompletion extends TemplateCompletionProcessor{ /* * (non-Javadoc) * * @see org.eclipse.jface.text.templates.TemplateCompletionProcessor#getTemplates(java.lang.String) */ protected Template[] getTemplates(String contextTypeId) { return PydevPlugin.getDefault().getTemplateStore().getTemplates(); } /* * (non-Javadoc) * * @see org.eclipse.jface.text.templates.TemplateCompletionProcessor#getContextType(org.eclipse.jface.text.ITextViewer, * org.eclipse.jface.text.IRegion) */ protected TemplateContextType getContextType(ITextViewer viewer, IRegion region) { return PydevPlugin.getDefault().getContextTypeRegistry() .getContextType(PyContextType.PY_CONTEXT_TYPE); } /* * (non-Javadoc) * * @see org.eclipse.jface.text.templates.TemplateCompletionProcessor#getImage(org.eclipse.jface.text.templates.Template) */ protected Image getImage(Template template) { // TODO Auto-generated method stub return null; } /** * @param viewer * @param documentOffset * @param propList * */ protected void addTemplateProposals(ITextViewer viewer, int documentOffset, List propList) { String str = extractPrefix(viewer, documentOffset); ICompletionProposal[] templateProposals = computeCompletionProposals(viewer, documentOffset); for (int j = 0; j < templateProposals.length; j++) { if ( templateProposals[j].getDisplayString().startsWith(str)){ propList.add(templateProposals[j]); } } } public String extractPrefix(ITextViewer viewer, int offset) { String str =""; int i = offset - 1; if (i == -1){ return ""; } char c; try { c = viewer.getDocument().getChar(i); while (c != ' ' && c != '\n' && c != '\r') { str = c + str; i--; if(i < 0){ break; }else{ c = viewer.getDocument().getChar(i); } } } catch (BadLocationException e) { e.printStackTrace(); } return str; } } --- NEW FILE: PyCodeCompletion.java --- /* * Created on Aug 11, 2004 * * @author Fabio Zadrozny */ package org.python.pydev.editor.codecompletion; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.util.ArrayList; import java.util.List; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.osgi.framework.Bundle; import org.python.pydev.plugin.PydevPlugin; /** * @author Dmoore * @author Fabio Zadrozny */ public class PyCodeCompletion { /* * (non-Javadoc) * * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeCompletionProposals(org.eclipse.jface.text.ITextViewer, * int) */ int docBoundary = -1; // the document prior to the activation token /** * @param theDoc: the whole document as a string. * @param documentOffset: the cursor position */ String partialDocument(String theDoc, int documentOffset) { if (this.docBoundary < 0) { calcDocBoundary(theDoc, documentOffset); } if(this.docBoundary != -1){ String before = theDoc.substring(0, this.docBoundary); return before; } return ""; } /** * Returns a list with the tokens to use for autocompletion. * * @param theCode * @param theActivationToken * @return */ public List autoComplete(java.lang.String theCode, java.lang.String theActivationToken) { List theList = new ArrayList(); String s = new String(); File tmp = null; try { // get the inspect.py file from the package: s = getAutoCompleteScript(); } catch (CoreException e) { e.printStackTrace(); } try { //We actually write a file with all of our code to a temporary location, //so that we can get its code completion from the typper.py script. // //TODO: there must be a faster strategy... // tmp = bufferContent(theCode); if (tmp == null) { System.out .println("DBG:bufferContent() null. No tip for you!!"); return theList; } String ss = new String("python " + s + " " + tmp.getAbsolutePath()); Process p = Runtime.getRuntime().exec(ss); BufferedReader in = new BufferedReader(new InputStreamReader(p .getInputStream())); String str; while ((str = in.readLine()) != null) { if (!str.startsWith("tip: ")){ continue; } str = str.substring(5); theList.add(str); } in.close(); InputStream eInput = p.getErrorStream(); BufferedReader eIn = new BufferedReader(new InputStreamReader( eInput)); while ((str = eIn.readLine()) != null) { //System.out.println("error output: " + str); } p.waitFor(); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } return theList; } /** * We actually write a file with all of our code to a temporary location, * so that we can get its code completion from the typper.py script. * * @param theCode code to be written to file. */ private File bufferContent(java.lang.String theCode) { // try { // Create temp file. File temp = File.createTempFile("PyDev", ".tmp"); // Delete temp file when program exits. temp.deleteOnExit(); // Write to temp file BufferedWriter out = new BufferedWriter(new FileWriter(temp)); out.write(theCode); out.close(); return temp; } catch (IOException e) { return null; } } /** * * @return the script to get the variables. * * @throws CoreException */ public static String getAutoCompleteScript() throws CoreException { String targetExec = "tipper.py"; IPath relative = new Path("PySrc").addTrailingSeparator().append( targetExec); Bundle bundle = PydevPlugin.getDefault().getBundle(); URL bundleURL = Platform.find(bundle, relative); URL fileURL; try { fileURL = Platform.asLocalURL(bundleURL); String filePath = new File(fileURL.getPath()).getAbsolutePath(); return filePath; } catch (IOException e) { throw new CoreException(PydevPlugin.makeStatus(IStatus.ERROR, "Can't find python debug script", null)); } } /** * The docBoundary should get until the last line before the one * we are editing. * * @param qualifier * @param documentOffset * @param proposals */ public void calcDocBoundary(String theDoc, int documentOffset) { this.docBoundary = theDoc.substring(0, documentOffset) .lastIndexOf('\n'); } /** * Returns the activation token. * * @param theDoc * @param documentOffset * @return */ public String getActivationToken(String theDoc, int documentOffset) { if (this.docBoundary < 0) { calcDocBoundary(theDoc, documentOffset); } return theDoc.substring(this.docBoundary + 1, documentOffset); } } --- NEW FILE: PythonCompletionProcessor.java --- /* * Created on Mar 29, 2004 * */ package org.python.pydev.editor.codecompletion; import java.util.ArrayList; import java.util.Iterator; import java.util.List; 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.IContentAssistProcessor; import org.eclipse.jface.text.contentassist.IContextInformation; import org.eclipse.jface.text.contentassist.IContextInformationValidator; import org.eclipse.swt.graphics.Point; /** * @author Dmoore * @author Fabio Zadrozny * * This class is responsible for code completion / template completion. */ public class PythonCompletionProcessor implements IContentAssistProcessor { private PyTemplateCompletion templatesCompletion = new PyTemplateCompletion(); private PyCodeCompletion codeCompletion = new PyCodeCompletion(); private CompletionCache completionCache = new CompletionCache(); public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int documentOffset) { List propList = new ArrayList(); IDocument doc = viewer.getDocument(); Point selectedRange = viewer.getSelectedRange(); // there may not be a selected range java.lang.String theDoc = doc.get(); codeCompletion.calcDocBoundary(theDoc, documentOffset); String activationToken = codeCompletion .getActivationToken(theDoc, documentOffset); java.lang.String qualifier = ""; while(activationToken.endsWith(".") == false && activationToken.length() > 0){ qualifier = activationToken.charAt(activationToken.length()-1) + qualifier; activationToken = activationToken.substring(0, activationToken.length()-1); } theDoc = codeCompletion.partialDocument(theDoc, documentOffset); int qlen = qualifier.length(); theDoc += "\n" + activationToken; List allProposals = this.completionCache.getAllProposals(theDoc, activationToken, documentOffset, qlen, codeCompletion); //templates proposals are added here. this.templatesCompletion.addTemplateProposals(viewer, documentOffset, propList); for (Iterator iter = allProposals.iterator(); iter.hasNext();) { ICompletionProposal proposal = (ICompletionProposal) iter.next(); if(proposal.getDisplayString().startsWith(qualifier)){ propList.add(proposal); } } ICompletionProposal[] proposals = new ICompletionProposal[propList .size()]; // and fill with list elements propList.toArray(proposals); // Return the proposals return proposals; } /* * (non-Javadoc) * * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeContextInformation(org.eclipse.jface.text.ITextViewer, * int) */ public IContextInformation[] computeContextInformation(ITextViewer viewer, int documentOffset) { // TODO Auto-generated method stub return null; } /* * (non-Javadoc) * * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getCompletionProposalAutoActivationCharacters() */ public char[] getCompletionProposalAutoActivationCharacters() { return new char[] { '.'/*, '(', '['*/ }; } /* * (non-Javadoc) * * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationAutoActivationCharacters() */ public char[] getContextInformationAutoActivationCharacters() { // is this _really_ what we want to use?? return new char[] { '.' }; } /* * (non-Javadoc) * * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getErrorMessage() */ public java.lang.String getErrorMessage() { // TODO Auto-generated method stub return null; } /* * (non-Javadoc) * * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationValidator() */ public IContextInformationValidator getContextInformationValidator() { // TODO Auto-generated method stub return null; } } --- NEW FILE: CompletionCache.java --- /* * Created on Aug 11, 2004 * * @author Fabio Zadrozny */ package org.python.pydev.editor.codecompletion; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.jface.text.contentassist.CompletionProposal; /** * @author Fabio Zadrozny */ public class CompletionCache { private Map cache = new HashMap(); private List cacheEntries = new ArrayList(); public List getAllProposals(String theDoc, String activationToken, int documentOffset, int qlen, PyCodeCompletion codeCompletion) { List allProposals = null; if (cache.containsKey(theDoc)) { //if it is in the cache, we can just get the proposals, //the only thing here, is that we have to change its size depending //on the new qlen. allProposals = new ArrayList(); List proposals = (List) cache.get(theDoc); for (Iterator iter = proposals.iterator(); iter.hasNext();) { CompletionProposal prop = (CompletionProposal) iter.next(); String displayString = prop.getDisplayString(); allProposals.add(new CompletionProposal(displayString, documentOffset - qlen, qlen, displayString.length())); } } else { List theList = codeCompletion.autoComplete(theDoc, activationToken); allProposals = new ArrayList(); for (Iterator iter = theList.iterator(); iter.hasNext();) { String element = (String) iter.next(); CompletionProposal proposal = new CompletionProposal(element, documentOffset - qlen, qlen, element.length()); allProposals.add(proposal); } cacheEntries.add(theDoc); cache.put(theDoc, allProposals); //we don't want this the get huge... if (cacheEntries.size() > 20) { Object entry = cacheEntries.remove(0); cache.remove(entry); } } return allProposals; } } |