[Pydev-cvs] org.python.pydev.debug/src_console/org/python/pydev/debug/newconsole PydevConsoleInter
Brought to you by:
fabioz
From: Fabio Z. <fa...@us...> - 2008-03-18 02:55:00
|
Update of /cvsroot/pydev/org.python.pydev.debug/src_console/org/python/pydev/debug/newconsole In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8187/src_console/org/python/pydev/debug/newconsole Added Files: PydevConsoleInterpreter.java PydevConsole.java PydevConsoleCommunication.java PydevConsoleCompletionProcessor.java PydevConsoleConstants.java PydevConsoleTextHover.java package.html PydevConsoleFactory.java PydevConsolePreferencesInitializer.java Log Message: Initial commit of console. Based on dltk implementation (but with extensive changes to work in pydev). --- NEW FILE: PydevConsoleConstants.java --- package org.python.pydev.debug.newconsole; /** * Constants for the console */ public final class PydevConsoleConstants { public static final String PREF_NEW_PROMPT = "pydevconsole.new_invitation"; public static final String PREF_CONTINUE_PROMPT = "pydevconsole.continue_invitation"; public static final String DEFAULT_NEW_PROMPT = ">>> "; public static final String DEFAULT_CONTINUE_PROMPT = "... "; } --- NEW FILE: PydevConsoleFactory.java --- package org.python.pydev.debug.newconsole; import java.io.IOException; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.model.IProcess; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.console.IConsoleFactory; import org.python.pydev.core.IInterpreterManager; import org.python.pydev.debug.newconsole.env.IProcessFactory; import org.python.pydev.debug.newconsole.env.UserCanceledException; import org.python.pydev.dltk.console.ScriptConsolePrompt; import org.python.pydev.dltk.console.ui.ScriptConsoleManager; import org.python.pydev.editor.PyEdit; import org.python.pydev.plugin.PydevPlugin; import org.python.pydev.plugin.SocketUtil; /** * Could ask to configure the interpreter in the preferences * * PreferencesUtil.createPreferenceDialogOn(null, preferencePageId, null, null) * * This is the class responsible for creating the console (and setting up the communication * between the console server and the client). * * @author Fabio */ public class PydevConsoleFactory implements IConsoleFactory { /** * @return the prompt to be used in the console. */ protected ScriptConsolePrompt createConsolePrompt() { IPreferenceStore store = PydevPlugin.getDefault().getPreferenceStore(); String newPrompt = store.getString(PydevConsoleConstants.PREF_NEW_PROMPT); String continuePrompt = store.getString(PydevConsoleConstants.PREF_CONTINUE_PROMPT); if (newPrompt == null || newPrompt.length() == 0) { newPrompt = PydevConsoleConstants.DEFAULT_NEW_PROMPT; } if (continuePrompt == null || continuePrompt.length() == 0) { continuePrompt = PydevConsoleConstants.DEFAULT_CONTINUE_PROMPT; } return new ScriptConsolePrompt(newPrompt, continuePrompt); } /** * @see IConsoleFactory#openConsole() */ public void openConsole() { ScriptConsoleManager manager = ScriptConsoleManager.getInstance(); try { PydevConsoleInterpreter interpreter = createDefaultPydevInterpreter(); PydevConsole console = new PydevConsole(interpreter); console.setPrompt(createConsolePrompt()); manager.add(console, true); } catch (Exception e) { PydevPlugin.log(e); } } /** * @return A PydevConsoleInterpreter with its communication configured. * * @throws CoreException * @throws IOException * @throws UserCanceledException */ public static PydevConsoleInterpreter createDefaultPydevInterpreter() throws CoreException, IOException, UserCanceledException { IWorkbenchWindow workbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); IWorkbenchPage activePage = workbenchWindow.getActivePage(); IEditorPart activeEditor = activePage.getActiveEditor(); if (activeEditor instanceof PyEdit) { PyEdit edit = (PyEdit) activeEditor; IProject project = edit.getProject(); IInterpreterManager manager = edit.getPythonNature().getRelatedInterpreterManager(); int port = SocketUtil.findUnusedLocalPort(); final ILaunch launch = new IProcessFactory().createILaunch(project, PydevPlugin.getScriptWithinPySrc("pydevconsole.py"), manager, ""+port); // import sys; sys.ps1=''; sys.ps2='' // import sys;print >> sys.stderr, ' '.join([sys.executable, sys.platform, sys.version]) // print >> sys.stderr, 'PYTHONPATH:' // for p in sys.path: // print >> sys.stderr, p // // print >> sys.stderr, 'Ok, all set up... Enjoy' PydevConsoleInterpreter interpreter = new PydevConsoleInterpreter(); interpreter.setConsoleCommunication(new PydevConsoleCommunication(port)); if (launch != null) { interpreter.addCloseOperation(new Runnable() { public void run() { IProcess[] processes = launch.getProcesses(); if (processes != null) { for (int i = 0; i < processes.length; i++) { try { processes[i].terminate(); } catch (DebugException e) { PydevPlugin.log(e); } } } } }); } return interpreter; } else { PydevPlugin.log("Active editor must be an instance of a Pydev Editor for creating a console!"); return null; } } } --- NEW FILE: PydevConsolePreferencesInitializer.java --- package org.python.pydev.debug.newconsole; import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer; import org.eclipse.core.runtime.preferences.DefaultScope; import org.osgi.service.prefs.Preferences; /** * Initializes the preferences for the console. */ public class PydevConsolePreferencesInitializer extends AbstractPreferenceInitializer { @Override public void initializeDefaultPreferences() { Preferences node = new DefaultScope().getNode("org.python.pydev.debug"); //text node.put(PydevConsoleConstants.PREF_CONTINUE_PROMPT, PydevConsoleConstants.DEFAULT_CONTINUE_PROMPT); node.put(PydevConsoleConstants.PREF_NEW_PROMPT, PydevConsoleConstants.DEFAULT_NEW_PROMPT); } } --- NEW FILE: PydevConsoleCommunication.java --- package org.python.pydev.debug.newconsole; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.apache.xmlrpc.client.XmlRpcClient; import org.apache.xmlrpc.client.XmlRpcClientConfigImpl; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.python.pydev.core.ICompletionState; import org.python.pydev.core.IToken; import org.python.pydev.dltk.console.IScriptConsoleCommunication; import org.python.pydev.dltk.console.InterpreterResponse; import org.python.pydev.editor.codecompletion.AbstractPyCodeCompletion; import org.python.pydev.editor.codecompletion.IPyCodeCompletion; import org.python.pydev.editor.codecompletion.IPyCompletionProposal; import org.python.pydev.editor.codecompletion.PyCodeCompletionImages; import org.python.pydev.editor.codecompletion.PyCompletionProposal; /** * Communication with Xml-rpc with the client. * * @author Fabio */ public class PydevConsoleCommunication implements IScriptConsoleCommunication{ private XmlRpcClient client; public PydevConsoleCommunication(int port) throws MalformedURLException { XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl(); config.setServerURL(new URL("http://127.0.0.1:"+port)); XmlRpcClient client = new XmlRpcClient(); client.setConfig(config); this.client = client; } public void close() throws IOException { System.out.println("Finishing communication."); } public InterpreterResponse execInterpreter(String command) throws Exception { Object[] execute = (Object[]) this.client.execute("addExec", new Object[]{command}); boolean more = extractBool(execute[2]); boolean needInput = extractBool(execute[3]); return new InterpreterResponse((String)execute[0], (String)execute[1], more, needInput); } private boolean extractBool(Object execute) { if(execute instanceof Boolean){ return (Boolean)execute; } return Boolean.parseBoolean(execute.toString()); } @SuppressWarnings("unchecked") public ICompletionProposal[] getCompletions(String text, int offset) throws Exception { Object fromServer = client.execute("getCompletions", new Object[]{text}); List<ICompletionProposal> ret = new ArrayList<ICompletionProposal>(); int length = text.lastIndexOf('.'); if(length == -1){ length = text.length(); }else{ length = text.length()-length-1; } if(fromServer instanceof Object[]){ Object[] comps = (Object[]) fromServer; for(Object o:comps){ if(o instanceof Object[]){ //name, doc, args, type Object[] comp = (Object[]) o; String name = (String) comp[0]; String docStr = (String) comp[1]; int type = extractType(comp[3]); String args = AbstractPyCodeCompletion.getArgs((String) comp[2], type, ICompletionState.LOOKING_FOR_INSTANCED_VARIABLE) ; name += args; int priority = IPyCompletionProposal.PRIORITY_DEFAULT; if(type == IToken.TYPE_PARAM){ priority = IPyCompletionProposal.PRIORITY_LOCALS; } ret.add(new PyCompletionProposal(name.substring(length), offset, 0, 0, PyCodeCompletionImages.getImageForType(type), name, null, docStr, priority)); } } } ICompletionProposal[] proposals = ret.toArray(new ICompletionProposal[ret.size()]); Arrays.sort(proposals, IPyCodeCompletion.PROPOSAL_COMPARATOR); return proposals; } private int extractType(Object type) { if(type instanceof Integer){ return (Integer)type; } return Integer.parseInt(type.toString()); } public String getDescription(String text) throws Exception { return "Need description: text"; } } --- NEW FILE: PydevConsole.java --- package org.python.pydev.debug.newconsole; import org.python.pydev.dltk.console.ui.ScriptConsole; public class PydevConsole extends ScriptConsole { public static final String CONSOLE_TYPE = "org.python.pydev.debug.newconsole.PydevConsole"; public static final String CONSOLE_NAME = "Pydev Console"; public static int nextId = -1; private static String getNextId() { nextId += 1; return String.valueOf(nextId); } public PydevConsole(PydevConsoleInterpreter interpreter) { super(CONSOLE_NAME + " [" + getNextId() + "]", CONSOLE_TYPE); setInterpreter(interpreter); setTextHover(new PydevConsoleTextHover(interpreter)); setContentAssistProcessor(new PydevConsoleCompletionProcessor(interpreter)); } } --- NEW FILE: PydevConsoleCompletionProcessor.java --- package org.python.pydev.debug.newconsole; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.TextPresentation; 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.IContextInformationPresenter; import org.eclipse.jface.text.contentassist.IContextInformationValidator; import org.python.pydev.dltk.console.IScriptConsoleShell; import org.python.pydev.dltk.console.ui.IScriptConsoleViewer; import org.python.pydev.plugin.PydevPlugin; public class PydevConsoleCompletionProcessor implements IContentAssistProcessor { protected static class Validator implements IContextInformationValidator, IContextInformationPresenter { protected int installOffset; public boolean isContextInformationValid(int offset) { return Math.abs(installOffset - offset) < 5; } public void install(IContextInformation info, ITextViewer viewer, int offset) { installOffset = offset; } public boolean updatePresentation(int documentPosition, TextPresentation presentation) { return false; } } private IContextInformationValidator validator; private IScriptConsoleShell interpreterShell; private String errorMessage = null; public PydevConsoleCompletionProcessor(IScriptConsoleShell interpreterShell) { this.interpreterShell = interpreterShell; } public char[] getContextInformationAutoActivationCharacters() { return null; } public char[] getCompletionProposalAutoActivationCharacters() { return new char[] { '.' }; } public ICompletionProposal[] computeCompletionProposals(ITextViewer v, int offset) { IScriptConsoleViewer viewer = (IScriptConsoleViewer) v; try { String commandLine = viewer.getCommandLine(); int cursorPosition = offset - viewer.getCommandLineOffset(); return interpreterShell.getCompletions(commandLine, cursorPosition, offset); } catch (Exception e) { this.errorMessage = e.getMessage(); PydevPlugin.log(e); } return new ICompletionProposal[] {}; } public IContextInformation[] computeContextInformation(ITextViewer v, int offset) { // IScriptConsoleViewer viewer = (IScriptConsoleViewer) v; return null; } public IContextInformationValidator getContextInformationValidator() { if (validator == null) { validator = new Validator(); } return validator; } public String getErrorMessage() { String msg = errorMessage; errorMessage = null; return msg; } } --- NEW FILE: package.html --- The difference from the 'new' interactive console to the old is that this console will have a much better handling on how things work. The old version was basically a wrapper around python.exe. The only thing that was worth on it was that it did send code from the editor to the shell. This console should also contain: code-completion, description of things on hover. For that, it'll create a process executing a script that'll be able to provide those things from a xml communication. --- NEW FILE: PydevConsoleTextHover.java --- /******************************************************************************* * Copyright (c) 2005, 2007 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * *******************************************************************************/ package org.python.pydev.debug.newconsole; import org.eclipse.jface.text.IRegion; import org.python.pydev.dltk.console.IScriptConsoleShell; import org.python.pydev.dltk.console.ui.IScriptConsoleViewer; import org.python.pydev.dltk.console.ui.ScriptConsoleTextHover; import org.python.pydev.plugin.PydevPlugin; public class PydevConsoleTextHover extends ScriptConsoleTextHover { private IScriptConsoleShell interpreterShell; public PydevConsoleTextHover(IScriptConsoleShell interpreterShell) { this.interpreterShell = interpreterShell; } protected String getHoverInfoImpl(IScriptConsoleViewer viewer, IRegion hoverRegion) { try { int cursorPosition = hoverRegion.getOffset() - viewer.getCommandLineOffset(); String commandLine = viewer.getCommandLine(); return interpreterShell.getDescription(commandLine, cursorPosition); } catch (Exception e) { PydevPlugin.log(e); return null; } } } --- NEW FILE: PydevConsoleInterpreter.java --- package org.python.pydev.debug.newconsole; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.python.pydev.core.docutils.PySelection; import org.python.pydev.core.docutils.PySelection.ActivationTokenAndQual; import org.python.pydev.dltk.console.IScriptConsoleCommunication; import org.python.pydev.dltk.console.IScriptConsoleInterpreter; import org.python.pydev.dltk.console.InterpreterResponse; /** * Default implementation for the console interpreter. * * Will ask things to the IScriptConsoleCommunication */ public class PydevConsoleInterpreter implements IScriptConsoleInterpreter { private IScriptConsoleCommunication consoleCommunication; private List<Runnable> closeRunnables = new ArrayList<Runnable>(); /* * (non-Javadoc) * @see org.python.pydev.dltk.console.IScriptConsoleInterpreter#exec(java.lang.String) */ public InterpreterResponse exec(String command) throws Exception { return consoleCommunication.execInterpreter(command); } /* * (non-Javadoc) * @see org.python.pydev.dltk.console.IScriptConsoleShell#getCompletions(java.lang.String, int, int) */ public ICompletionProposal[] getCompletions(String commandLine, int position, int offset) throws Exception { String text = commandLine.substring(0, position); ActivationTokenAndQual tokenAndQual = PySelection.getActivationTokenAndQual(new Document(text), text.length(), true, false); String actTok = tokenAndQual.activationToken; if(tokenAndQual.qualifier != null && tokenAndQual.qualifier.length() > 0){ if(actTok.length() > 0 && actTok.charAt(actTok.length()-1) != '.'){ actTok += '.'; } actTok += tokenAndQual.qualifier; } return consoleCommunication.getCompletions(actTok, offset); } /* * (non-Javadoc) * @see org.python.pydev.dltk.console.IScriptConsoleShell#getDescription(java.lang.String, int) */ public String getDescription(String commandLine, int position) throws Exception { return consoleCommunication.getDescription(commandLine); } /* * (non-Javadoc) * @see org.python.pydev.dltk.console.IScriptConsoleShell#close() */ public void close() throws IOException { if (consoleCommunication != null) { consoleCommunication.close(); consoleCommunication = null; } // run all close runnables. for (Runnable r:this.closeRunnables) { r.run(); } //we can close just once! this.closeRunnables = null; } /* * (non-Javadoc) * @see org.python.pydev.dltk.console.IConsoleRequest#setConsoleCommunication(org.python.pydev.dltk.console.IScriptConsoleCommunication) */ public void setConsoleCommunication(IScriptConsoleCommunication protocol) { this.consoleCommunication = protocol; } public void addCloseOperation(Runnable runnable) { this.closeRunnables.add(runnable); } } |