diff --git a/python/helpers/pydev/pydev_console_utils.py b/python/helpers/pydev/pydev_console_utils.py
index bc6708727c26..ef8f68670239 100644
--- a/python/helpers/pydev/pydev_console_utils.py
+++ b/python/helpers/pydev/pydev_console_utils.py
@@ -132,6 +132,11 @@ class StdIn(BaseStdIn):
return '\n'
+class ExecCode:
+ def __init__(self, code, is_single_line=True):
+ self.code = code
+ self.is_single_line = is_single_line
+
#=======================================================================================================================
# BaseInterpreterInterface
#=======================================================================================================================
@@ -142,20 +147,14 @@ class BaseInterpreterInterface:
self.exec_queue = _queue.Queue(0)
self.buffer = []
- def needMore(self, buffer, line):
- if not buffer:
- buffer = []
- buffer.append(line)
- source = "\n".join(buffer)
+ def needMoreForCode(self, source):
if hasattr(self.interpreter, 'is_complete'):
return not self.interpreter.is_complete(source)
-
try:
- code = self.interpreter.compile(source, "", "single")
+ code = self.interpreter.compile(source, "", "exec")
except (OverflowError, SyntaxError, ValueError):
# Case 1
return False
-
if code is None:
# Case 2
return True
@@ -163,8 +162,16 @@ class BaseInterpreterInterface:
# Case 3
return False
+ def needMore(self, buffer, line):
+ if not buffer:
+ buffer = []
+ buffer.append(line)
+ source = "\n".join(buffer)
+
+ return self.needMoreForCode(source)
- def addExec(self, line):
+
+ def addExec(self, command):
original_in = sys.stdin
try:
help = None
@@ -203,7 +210,7 @@ class BaseInterpreterInterface:
try:
self.startExec()
- more = self.doAddExec(line)
+ more = self.doAddExec(command)
self.finishExec()
finally:
if help is not None:
@@ -229,7 +236,7 @@ class BaseInterpreterInterface:
return more, need_input
- def doAddExec(self, line):
+ def doAddExec(self, command):
'''
Subclasses should override.
@@ -309,14 +316,22 @@ class BaseInterpreterInterface:
def execLine(self, line):
try:
- #buffer = self.interpreter.buffer[:]
- self.exec_queue.put(line)
+ self.exec_queue.put(ExecCode(line, True))
return self.needMore(self.buffer, line)
except:
traceback.print_exc()
return False
+ def execMultipleLines(self, lines):
+ try:
+ self.exec_queue.put(ExecCode(lines, False))
+ return self.needMoreForCode(lines)
+ except:
+ traceback.print_exc()
+ return False
+
+
def interrupt(self):
try:
if self.interruptable:
diff --git a/python/helpers/pydev/pydev_ipython_console.py b/python/helpers/pydev/pydev_ipython_console.py
index d3d4ae8492a3..d38127165bea 100644
--- a/python/helpers/pydev/pydev_ipython_console.py
+++ b/python/helpers/pydev/pydev_ipython_console.py
@@ -39,14 +39,14 @@ class InterpreterInterface(BaseInterpreterInterface):
def get_greeting_msg(self):
return self.interpreter.get_greeting_msg()
- def doAddExec(self, line):
+ def doAddExec(self, command):
self.notify_about_magic()
- if (line.rstrip().endswith('??')):
+ if (command.rstrip().endswith('??')):
print('IPython-->')
try:
- res = bool(self.interpreter.addExec(line))
+ res = bool(self.interpreter.addExec(command))
finally:
- if (line.rstrip().endswith('??')):
+ if (command.rstrip().endswith('??')):
print('<--IPython')
return res
diff --git a/python/helpers/pydev/pydevconsole.py b/python/helpers/pydev/pydevconsole.py
index 026fb7f9880c..a5f66a80d3e4 100644
--- a/python/helpers/pydev/pydevconsole.py
+++ b/python/helpers/pydev/pydevconsole.py
@@ -10,7 +10,6 @@ import os
import sys
from pydevd_constants import USE_LIB_COPY
-from pydevd_utils import *
if USE_LIB_COPY:
import _pydev_threading as threading
@@ -72,56 +71,25 @@ try:
except ImportError:
import _pydev_xmlrpclib as xmlrpclib
-try:
- class ExecState:
- FIRST_CALL = True
- PYDEV_CONSOLE_RUN_IN_UI = False #Defines if we should run commands in the UI thread.
- from org.python.pydev.core.uiutils import RunInUiThread #@UnresolvedImport
- from java.lang import Runnable #@UnresolvedImport
+class Command:
+ def __init__(self, interpreter, command):
+ """
+ :type command: object
+ :type interpreter: InteractiveConsole
+ """
+ self.interpreter = interpreter
+ self.command = command
+ self.more = None
- class Command(Runnable):
- def __init__(self, interpreter, line):
- self.interpreter = interpreter
- self.line = line
-
- def run(self):
- if ExecState.FIRST_CALL:
- ExecState.FIRST_CALL = False
- sys.stdout.write('\nYou are now in a console within Eclipse.\nUse it with care as it can halt the VM.\n')
- sys.stdout.write(
- 'Typing a line with "PYDEV_CONSOLE_TOGGLE_RUN_IN_UI"\nwill start executing all the commands in the UI thread.\n\n')
-
- if self.line == 'PYDEV_CONSOLE_TOGGLE_RUN_IN_UI':
- ExecState.PYDEV_CONSOLE_RUN_IN_UI = not ExecState.PYDEV_CONSOLE_RUN_IN_UI
- if ExecState.PYDEV_CONSOLE_RUN_IN_UI:
- sys.stdout.write(
- 'Running commands in UI mode. WARNING: using sys.stdin (i.e.: calling raw_input()) WILL HALT ECLIPSE.\n')
- else:
- sys.stdout.write('No longer running commands in UI mode.\n')
- self.more = False
- else:
- self.more = self.interpreter.push(self.line)
-
-
- def Sync(runnable):
- if ExecState.PYDEV_CONSOLE_RUN_IN_UI:
- return RunInUiThread.sync(runnable)
+ def run(self):
+ if self.command.is_single_line:
+ self.more = self.interpreter.push(self.command.code)
else:
- return runnable.run()
+ self.more = self.interpreter.runsource(self.command.code, '', 'exec')
-except:
- #If things are not there, define a way in which there's no 'real' sync, only the default execution.
- class Command:
- def __init__(self, interpreter, line):
- self.interpreter = interpreter
- self.line = line
-
- def run(self):
- self.more = self.interpreter.push(self.line)
-
- def Sync(runnable):
- runnable.run()
+def Sync(runnable):
+ runnable.run()
try:
try:
@@ -152,8 +120,8 @@ class InterpreterInterface(BaseInterpreterInterface):
self._input_error_printed = False
- def doAddExec(self, line):
- command = Command(self.interpreter, line)
+ def doAddExec(self, command):
+ command = Command(self.interpreter, command)
Sync(command)
return command.more
@@ -185,11 +153,11 @@ def process_exec_queue(interpreter):
while 1:
try:
try:
- line = interpreter.exec_queue.get(block=True, timeout=0.05)
+ command = interpreter.exec_queue.get(block=True, timeout=0.05)
except _queue.Empty:
continue
- if not interpreter.addExec(line): #TODO: think about locks here
+ if not interpreter.addExec(command): #TODO: think about locks here
interpreter.buffer = []
except KeyboardInterrupt:
interpreter.buffer = []
@@ -274,6 +242,7 @@ def start_server(host, port, interpreter):
raise
server.register_function(interpreter.execLine)
+ server.register_function(interpreter.execMultipleLines)
server.register_function(interpreter.getCompletions)
server.register_function(interpreter.getFrame)
server.register_function(interpreter.getVariable)
diff --git a/python/pydevSrc/com/jetbrains/python/console/pydev/ConsoleCommunication.java b/python/pydevSrc/com/jetbrains/python/console/pydev/ConsoleCommunication.java
index a114c2c07f57..51604d73ee5c 100644
--- a/python/pydevSrc/com/jetbrains/python/console/pydev/ConsoleCommunication.java
+++ b/python/pydevSrc/com/jetbrains/python/console/pydev/ConsoleCommunication.java
@@ -18,7 +18,7 @@ public interface ConsoleCommunication {
boolean isExecuting();
- void execInterpreter(String s, Function callback);
+ void execInterpreter(ConsoleCodeFragment code, Function callback);
void interrupt();
@@ -27,4 +27,21 @@ public interface ConsoleCommunication {
void notifyCommandExecuted();
void notifyInputRequested();
+ class ConsoleCodeFragment {
+ private final String myText;
+ private final boolean myIsSingleLine;
+
+ public ConsoleCodeFragment(String text, boolean isSingleLine) {
+ myText = text;
+ myIsSingleLine = isSingleLine;
+ }
+
+ public String getText() {
+ return myText;
+ }
+
+ public boolean isSingleLine() {
+ return myIsSingleLine;
+ }
+ }
}
diff --git a/python/pydevSrc/com/jetbrains/python/console/pydev/IScriptConsoleCommunication.java b/python/pydevSrc/com/jetbrains/python/console/pydev/IScriptConsoleCommunication.java
deleted file mode 100644
index 3c998c8e1e32..000000000000
--- a/python/pydevSrc/com/jetbrains/python/console/pydev/IScriptConsoleCommunication.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*******************************************************************************
- * 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 com.jetbrains.python.console.pydev;
-
-import com.intellij.util.Function;
-
-/**
- * Interface for the console communication.
- *
- * This interface is meant to be the way to communicate with the shell.
- */
-public interface IScriptConsoleCommunication {
-
- /**
- * Executes a given command in the interpreter (push a line)
- *
- * @param command the command to be executed
- * @return the response from the interpreter (contains the stdout, stderr, etc).
- * @throws Exception
- */
- void execInterpreter(String command, Function onResponseReceived);
-
- /**
- * Creates the completions to be applied in the interpreter.
- *
- * @param text the text with what should be completed (e.g.: xxx.bar.foo)
- * @param offset the offset where the completion was requested in the console document
- * @return a list of proposals that can be applied for the given text.
- * @throws Exception
- */
- //public ICompletionProposal[] getCompletions(String text, int offset) throws Exception;
-
- /**
- * Gets the description to be shown on hover to the user
- *
- * @param text the text representing the completion to be applied
- * @return the description to be shown to the user
- * @throws Exception
- */
- String getDescription(String text) throws Exception;
-
- /**
- * Stops the communication with the server. Should ask the server to terminate at this point.
- * @throws Exception
- */
- void close();
-}
\ No newline at end of file
diff --git a/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java b/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java
index b0ef1d378699..387226f7ae14 100644
--- a/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java
+++ b/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java
@@ -53,10 +53,11 @@ import java.util.Vector;
*
* @author Fabio
*/
-public class PydevConsoleCommunication extends AbstractConsoleCommunication implements IScriptConsoleCommunication, XmlRpcHandler,
+public class PydevConsoleCommunication extends AbstractConsoleCommunication implements XmlRpcHandler,
PyFrameAccessor {
private static final String EXEC_LINE = "execLine";
+ private static final String EXEC_MULTILINE = "execMultipleLines";
private static final String GET_COMPLETIONS = "getCompletions";
private static final String GET_DESCRIPTION = "getDescription";
private static final String GET_FRAME = "getFrame";
@@ -64,6 +65,7 @@ public class PydevConsoleCommunication extends AbstractConsoleCommunication impl
private static final String CHANGE_VARIABLE = "changeVariable";
private static final String HANDSHAKE = "handshake";
private static final String CLOSE = "close";
+
/**
* XML-RPC client for sending messages to the server.
*/
@@ -261,12 +263,13 @@ public class PydevConsoleCommunication extends AbstractConsoleCommunication impl
/**
* Executes the needed command
*
+ * @param command
* @return a Pair with (null, more) or (error, false)
* @throws XmlRpcException
*/
- protected Pair exec(final String command) throws XmlRpcException {
+ protected Pair exec(final ConsoleCodeFragment command) throws XmlRpcException {
setExecuting(true);
- Object execute = myClient.execute(EXEC_LINE, new Object[]{command});
+ Object execute = myClient.execute(command.isSingleLine() ? EXEC_LINE : EXEC_MULTILINE, new Object[]{command.getText()});
Object object;
if (execute instanceof Vector) {
@@ -314,10 +317,10 @@ public class PydevConsoleCommunication extends AbstractConsoleCommunication impl
*
* @param command the command to be executed in the client
*/
- public void execInterpreter(final String command, final Function onResponseReceived) {
+ public void execInterpreter(final ConsoleCodeFragment command, final Function onResponseReceived) {
nextResponse = null;
if (waitingForInput) {
- inputReceived = command;
+ inputReceived = command.getText();
waitingForInput = false;
//the thread that we started in the last exec is still alive if we were waiting for an input.
}
diff --git a/python/src/com/jetbrains/python/console/PydevConsoleExecuteActionHandler.java b/python/src/com/jetbrains/python/console/PydevConsoleExecuteActionHandler.java
index 7721db25b4b6..4698cc8baec6 100644
--- a/python/src/com/jetbrains/python/console/PydevConsoleExecuteActionHandler.java
+++ b/python/src/com/jetbrains/python/console/PydevConsoleExecuteActionHandler.java
@@ -40,8 +40,6 @@ import com.jetbrains.python.console.pydev.InterpreterResponse;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.Scanner;
-
/**
* @author traff
*/
@@ -76,10 +74,11 @@ public class PydevConsoleExecuteActionHandler extends ConsoleExecuteActionHandle
processOneLine(text);
}
else {
- Scanner s = new Scanner(text);
- while (s.hasNextLine()) {
- String line = s.nextLine();
- processOneLine(line);
+ if (StringUtil.countNewLines(text.trim()) > 0) {
+ executeMultiLine(text);
+ }
+ else {
+ processOneLine(text);
}
}
if (execAnyway && myCurrentIndentSize > 0 && indentBefore == 0) { //if code was indented and we need to exec anyway
@@ -87,6 +86,19 @@ public class PydevConsoleExecuteActionHandler extends ConsoleExecuteActionHandle
}
}
+ private void executeMultiLine(@NotNull String text) {
+ if (myInputBuffer == null) {
+ myInputBuffer = new StringBuilder();
+ }
+
+ myInputBuffer.append(text);
+
+ final LanguageConsoleImpl console = myConsoleView.getConsole();
+ final Editor currentEditor = console.getConsoleEditor();
+
+ sendLineToConsole(new ConsoleCommunication.ConsoleCodeFragment(myInputBuffer.toString(), false), null, console, currentEditor);
+ }
+
private void processOneLine(String line) {
int indentSize = IndentHelperImpl.getIndent(getProject(), PythonFileType.INSTANCE, line, false);
line = StringUtil.trimTrailing(line);
@@ -174,16 +186,22 @@ public class PydevConsoleExecuteActionHandler extends ConsoleExecuteActionHandle
}
+ sendLineToConsole(new ConsoleCommunication.ConsoleCodeFragment(myInputBuffer.toString(), true), line, console, currentEditor);
+ }
+
+ private void sendLineToConsole(@NotNull final ConsoleCommunication.ConsoleCodeFragment code,
+ @Nullable final String line,
+ @NotNull final LanguageConsoleImpl console,
+ @NotNull final Editor currentEditor) {
if (myConsoleCommunication != null) {
final boolean waitedForInputBefore = myConsoleCommunication.isWaitingForInput();
- final String command = myInputBuffer.toString();
if (myConsoleCommunication.isWaitingForInput()) {
myInputBuffer.setLength(0);
}
else {
executingPrompt(console);
}
- myConsoleCommunication.execInterpreter(command, new Function() {
+ myConsoleCommunication.execInterpreter(code, new Function() {
public Object fun(final InterpreterResponse interpreterResponse) {
// clear
myInputBuffer = null;
@@ -192,7 +210,8 @@ public class PydevConsoleExecuteActionHandler extends ConsoleExecuteActionHandle
more(console, currentEditor);
if (myCurrentIndentSize == 0) {
// compute current indentation
- setCurrentIndentSize(IndentHelperImpl.getIndent(getProject(), PythonFileType.INSTANCE, line, false) + getPythonIndent());
+ setCurrentIndentSize(
+ (line != null ? IndentHelperImpl.getIndent(getProject(), PythonFileType.INSTANCE, line, false) : 0) + getPythonIndent());
// In this case we can insert indent automatically
indentEditor(currentEditor, myCurrentIndentSize);
}
diff --git a/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java b/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java
index 8f55aed81db1..d24a2a8a8320 100644
--- a/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java
+++ b/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java
@@ -63,8 +63,8 @@ public class PythonDebugConsoleCommunication extends AbstractConsoleCommunicatio
return false;
}
- protected void exec(final String command, final ProcessDebugger.DebugCallback> callback) {
- myDebugProcess.consoleExec(command, new ProcessDebugger.DebugCallback() {
+ protected void exec(final ConsoleCodeFragment command, final ProcessDebugger.DebugCallback> callback) {
+ myDebugProcess.consoleExec(command.getText(), new ProcessDebugger.DebugCallback() {
@Override
public void ok(String value) {
callback.ok(parseExecResponseString(value));
@@ -77,9 +77,9 @@ public class PythonDebugConsoleCommunication extends AbstractConsoleCommunicatio
});
}
- public void execInterpreter(String s, final Function callback) {
- myExpression.append(s);
- exec(myExpression.toString(), new ProcessDebugger.DebugCallback>() {
+ public void execInterpreter(ConsoleCodeFragment code, final Function callback) {
+ myExpression.append(code.getText());
+ exec(new ConsoleCodeFragment(myExpression.toString(), false), new ProcessDebugger.DebugCallback>() {
@Override
public void ok(Pair executed) {
boolean more = executed.second;