use of org.python.pydev.shared_interactive_console.console.InterpreterResponse in project Pydev by fabioz.
the class ScriptConsoleDocumentListener method execCommand.
/**
* Here is where we run things not using the UI thread. It's a recursive function. In summary, it'll
* run each line in the commands received in a new thread, and as each finishes, it calls itself again
* for the next command. The last command will reconnect to the document.
*
* Exceptions had to be locally handled, because they're not well tolerated under this scenario
* (if on of the callbacks fail, the others won't be executed and we'd get into a situation
* where the shell becomes unusable).
*/
private void execCommand(final boolean addedNewLine, final String delim, final String[] finalIndentString, final String cmd, final List<String> commands, final int currentCommand, final String text, final char addedParen, final int start, final char addedCloseParen, final int newDeltaCaretPosition) {
applyStyleToUserAddedText(cmd, doc.getLength());
// the cmd could be something as '\n'
appendText(cmd);
// and the command line the actual contents to be executed at this time
final String commandLine = getCommandLine();
if (handler.isOnStateWhereCommandHandlingShouldStop(commandLine)) {
return;
}
history.update(commandLine);
// handle the command line:
// When the user presses a return and goes to a new line, the contents of the current line are sent to
// the interpreter (and its results properly handled).
appendText(getDelimeter());
final boolean finalAddedNewLine = addedNewLine;
final String finalDelim = delim;
final ICallback<Object, InterpreterResponse> onResponseReceived = new ICallback<Object, InterpreterResponse>() {
@Override
public Object call(final InterpreterResponse arg) {
// When we receive the response, we must handle it in the UI thread.
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
processResult(arg);
if (finalAddedNewLine) {
List<String> historyList = history.getAsList();
IDocument historyDoc = new Document(StringUtils.join("\n", historyList.subList(historyFullLine, historyList.size())) + "\n");
int currHistoryLen = historyDoc.getLength();
if (currHistoryLen > 0) {
DocCmd docCmd = new DocCmd(currHistoryLen - 1, 0, finalDelim);
strategy.customizeNewLine(historyDoc, docCmd);
// remove any new line added!
finalIndentString[0] = docCmd.text.replaceAll("\\r\\n|\\n|\\r", "");
if (currHistoryLen != historyDoc.getLength()) {
Log.log("Error: the document passed to the customizeNewLine should not be changed!");
}
}
}
} catch (Throwable e) {
// Yeap, it can never fail!
Log.log(e);
}
if (currentCommand + 1 < commands.size()) {
execCommand(finalAddedNewLine, finalDelim, finalIndentString, commands.get(currentCommand + 1), commands, currentCommand + 1, text, addedParen, start, addedCloseParen, newDeltaCaretPosition);
} else {
// last one
try {
onAfterAllLinesHandled(text, addedParen, start, readOnlyColumnsInCurrentBeforePrompt, addedCloseParen, finalIndentString[0], newDeltaCaretPosition);
} finally {
// We must disconnect
// reconnect with the document
stopDisconnected();
}
}
}
};
RunInUiThread.async(runnable);
return null;
}
};
handler.beforeHandleCommand(commandLine, onResponseReceived);
// Handle the command in a thread that doesn't block the U/I.
Job j = new Job("PyDev Console Hander") {
@Override
protected IStatus run(IProgressMonitor monitor) {
promptReady = false;
handler.handleCommand(commandLine, onResponseReceived);
return Status.OK_STATUS;
}
};
j.setSystem(true);
j.schedule();
}
use of org.python.pydev.shared_interactive_console.console.InterpreterResponse in project Pydev by fabioz.
the class PydevConsoleCommunication method interrupt.
/**
* Instructs the client to raise KeyboardInterrupt and return to a clean command prompt. This can be
* called to terminate:
* - infinite or excessively long processing loops (CPU bound)
* - I/O wait (e.g. urlopen, time.sleep)
* - asking for input from the console i.e. input(); this is a special case of the above because PyDev
* is involved
* - command prompt continuation processing, so that the user doesn't have to work out the exact
* sequence of close brackets required to get the prompt back
* This requires the cooperation of the client (the call to interrupt must be processed by the XMLRPC
* server) but in most cases is better than just terminating the process.
*/
@Override
public void interrupt() {
Job job = new Job("Interrupt console process") {
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
lastResponse = null;
setNextResponse(new InterpreterResponse(false, false));
moreBuffer.clear();
PydevConsoleCommunication.this.client.execute("interrupt", new Object[0]);
if (PydevConsoleCommunication.this.waitingForInput) {
PydevConsoleCommunication.this.inputReceived = "";
PydevConsoleCommunication.this.waitingForInput = false;
}
} catch (Exception e) {
Log.log(IStatus.ERROR, "Problem interrupting python process", e);
}
return Status.OK_STATUS;
}
};
job.schedule();
}
use of org.python.pydev.shared_interactive_console.console.InterpreterResponse in project Pydev by fabioz.
the class PydevConsoleCommunication method execInterpreter.
/**
* Executes a given line in the interpreter.
*
* @param command the command to be executed in the client
*/
@Override
public void execInterpreter(String command, final ICallback<Object, InterpreterResponse> onResponseReceived) {
setNextResponse(null);
if (waitingForInput) {
inputReceived = command;
waitingForInput = false;
// the thread that we started in the last exec is still alive if we were waiting for an input.
} else {
if (lastResponse != null && lastResponse.need_input == false && lastResponse.more) {
if (command.trim().length() > 0 && Character.isWhitespace(command.charAt(0))) {
moreBuffer.add(command);
// Pass same response back again (we still need more input to try to do some evaluation).
onResponseReceived.call(lastResponse);
return;
}
}
final String executeCommand;
if (moreBuffer.size() > 0) {
executeCommand = StringUtils.join("\n", moreBuffer) + "\n" + command;
moreBuffer.clear();
} else {
executeCommand = command;
}
// create a thread that'll keep locked until an answer is received from the server.
Job job = new Job("PyDev Console Communication") {
/**
* Executes the needed command
*
* @return a tuple with (null, more) or (error, false)
*
* @throws XmlRpcException
*/
private boolean exec() throws XmlRpcException {
if (client == null) {
return false;
}
Object ret = client.execute(executeCommand.contains("\n") ? "execMultipleLines" : "execLine", new Object[] { executeCommand });
if (!(ret instanceof Boolean)) {
if (ret instanceof Object[]) {
Object[] objects = (Object[]) ret;
ret = StringUtils.join(" ", objects);
} else {
ret = "" + ret;
}
if (onContentsReceived != null) {
onContentsReceived.call(new Tuple<String, String>("", ret.toString()));
}
return false;
}
boolean more = (Boolean) ret;
return more;
}
@Override
protected IStatus run(IProgressMonitor monitor) {
final boolean needInput = false;
try {
if (!firstCommWorked) {
throw new Exception("hello must be called successfully before execInterpreter can be used.");
}
finishedExecution.unset();
boolean more = exec();
if (!more) {
finishedExecution.waitForSet();
}
setNextResponse(new InterpreterResponse(more, needInput));
} catch (Exception e) {
Log.log(e);
setNextResponse(new InterpreterResponse(false, needInput));
}
return Status.OK_STATUS;
}
};
job.schedule();
}
// busy loop until we have a response
InterpreterResponse waitForSet = nextResponse.waitForSet();
lastResponse = waitForSet;
onResponseReceived.call(waitForSet);
}
use of org.python.pydev.shared_interactive_console.console.InterpreterResponse in project Pydev by fabioz.
the class PydevConsoleCommunication method requestInput.
private Object requestInput() {
waitingForInput = true;
inputReceived = null;
boolean needInput = true;
// let the busy loop from execInterpreter free and enter a busy loop
// in this function until execInterpreter gives us an input
setNextResponse(new InterpreterResponse(false, needInput));
// busy loop until we have an input
while (inputReceived == null) {
synchronized (lock) {
try {
lock.wait(10);
} catch (InterruptedException e) {
Log.log(e);
}
}
}
return inputReceived;
}
use of org.python.pydev.shared_interactive_console.console.InterpreterResponse in project Pydev by fabioz.
the class ScriptConsoleDocumentListenerTest method setUp.
@Override
protected void setUp() throws Exception {
super.setUp();
this.doc = new Document();
final List<String> commandsHandled = new ArrayList<String>();
ScriptConsolePrompt prompt = new ScriptConsolePrompt(">>> ", "... ");
listener = new ScriptConsoleDocumentListener(new IScriptConsoleViewer2ForDocumentListener() {
@Override
public IDocument getDocument() {
return doc;
}
@Override
public IConsoleStyleProvider getStyleProvider() {
return null;
}
@Override
public void revealEndOfDocument() {
// do nothing
}
@Override
public void setCaretOffset(int length, boolean async) {
// do nothing
}
@Override
public int getCommandLineOffset() {
return 0;
}
@Override
public int getConsoleWidthInCharacters() {
return 0;
}
@Override
public int getCaretOffset() {
return 0;
}
@Override
public IScriptConsoleSession getConsoleSession() {
return null;
}
}, new ICommandHandler() {
@Override
public void beforeHandleCommand(String userInput, ICallback<Object, InterpreterResponse> onResponseReceived) {
commandsHandled.add(userInput);
}
@Override
public void handleCommand(String userInput, ICallback<Object, InterpreterResponse> onResponseReceived) {
boolean more = false;
if (userInput.endsWith(":") || userInput.endsWith("\\")) {
more = true;
}
onResponseReceived.call(new InterpreterResponse(more, false));
}
@Override
public ICompletionProposalHandle[] getTabCompletions(String commandLine, int cursorPosition) {
return null;
}
@Override
public void setOnContentsReceivedCallback(ICallback<Object, Tuple<String, String>> onContentsReceived) {
}
@Override
public boolean isOnStateWhereCommandHandlingShouldStop(String commandLine) {
return false;
}
}, prompt, new ScriptConsoleHistory(), new ArrayList<IConsoleLineTracker>(), "", new PyAutoIndentStrategy(new IAdaptable() {
@Override
public <T> T getAdapter(Class<T> adapter) {
return null;
}
}));
PyAutoIndentStrategy strategy = (PyAutoIndentStrategy) listener.getIndentStrategy();
strategy.setIndentPrefs(new TestIndentPrefs(true, 4));
listener.setDocument(doc);
}
Aggregations