001: // Copyright (c) Corporation for National Research Initiatives
002: package org.python.util;
003:
004: import org.python.core.Py;
005: import org.python.core.PyBuiltinFunctionSet;
006: import org.python.core.PyException;
007: import org.python.core.PyObject;
008: import org.python.core.PySystemState;
009: import org.python.core.__builtin__;
010:
011: // Based on CPython-1.5.2's code module
012: public class InteractiveConsole extends InteractiveInterpreter {
013:
014: public static final String CONSOLE_FILENAME = "<console>";
015:
016: public String filename;
017:
018: public InteractiveConsole() {
019: this (null, CONSOLE_FILENAME);
020: }
021:
022: public InteractiveConsole(PyObject locals) {
023: this (locals, CONSOLE_FILENAME);
024: }
025:
026: public InteractiveConsole(PyObject locals, String filename) {
027: this (locals, filename, false);
028: }
029:
030: /**
031: * @param replaceRawInput -
032: * if true, we hook this Class's raw_input into the builtins
033: * table so that clients like cmd.Cmd use it.
034: */
035: public InteractiveConsole(PyObject locals, String filename,
036: boolean replaceRawInput) {
037: super (locals);
038: this .filename = filename;
039: if (replaceRawInput) {
040: PyObject newRawInput = new PyBuiltinFunctionSet(
041: "raw_input", 0, 0, 1) {
042:
043: public PyObject __call__() {
044: return __call__(Py.EmptyString);
045: }
046:
047: public PyObject __call__(PyObject prompt) {
048: return Py.newString(raw_input(prompt));
049: }
050: };
051: Py.getSystemState().builtins.__setitem__("raw_input",
052: newRawInput);
053: }
054: }
055:
056: /**
057: * Closely emulate the interactive Python console.
058: *
059: * The optional banner argument specifies the banner to print before the
060: * first interaction; by default it prints "Jython <version> on <platform>".
061: */
062: public void interact() {
063: interact(getDefaultBanner());
064: }
065:
066: public static String getDefaultBanner() {
067: return "Jython " + PySystemState.version + " on "
068: + PySystemState.platform;
069: }
070:
071: public void interact(String banner) {
072: if (banner != null) {
073: write(banner);
074: write("\n");
075: }
076: // Dummy exec in order to speed up response on first command
077: exec("2");
078: // System.err.println("interp2");
079: boolean more = false;
080: while (true) {
081: PyObject prompt = more ? systemState.ps2 : systemState.ps1;
082: String line;
083: try {
084: line = raw_input(prompt);
085: } catch (PyException exc) {
086: if (!Py.matchException(exc, Py.EOFError))
087: throw exc;
088: write("\n");
089: break;
090: }
091: more = push(line);
092: }
093: }
094:
095: /**
096: * Push a line to the interpreter.
097: *
098: * The line should not have a trailing newline; it may have internal
099: * newlines. The line is appended to a buffer and the interpreter's
100: * runsource() method is called with the concatenated contents of the buffer
101: * as source. If this indicates that the command was executed or invalid,
102: * the buffer is reset; otherwise, the command is incomplete, and the buffer
103: * is left as it was after the line was appended. The return value is 1 if
104: * more input is required, 0 if the line was dealt with in some way (this is
105: * the same as runsource()).
106: */
107: public boolean push(String line) {
108: if (buffer.length() > 0)
109: buffer.append("\n");
110: buffer.append(line);
111: boolean more = runsource(buffer.toString(), filename);
112: if (!more)
113: resetbuffer();
114: return more;
115: }
116:
117: /**
118: * Write a prompt and read a line.
119: *
120: * The returned line does not include the trailing newline. When the user
121: * enters the EOF key sequence, EOFError is raised.
122: *
123: * The base implementation uses the built-in function raw_input(); a
124: * subclass may replace this with a different implementation.
125: */
126: public String raw_input(PyObject prompt) {
127: return __builtin__.raw_input(prompt);
128: }
129: }
|