org.python.util.ConsoleOutputStream Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jython-slim Show documentation
Show all versions of jython-slim Show documentation
Jython is an implementation of the high-level, dynamic, object-oriented
language Python written in 100% Pure Java, and seamlessly integrated with
the Java platform. It thus allows you to run Python on any Java platform.
// Copyright (c) 2013 Jython Developers
package org.python.util;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
/**
* This class may be used to wrap and replace System.out
so that the console handling
* library (JLine or Java Readline) can treat an incomplete line (one without a newline) as a prompt
* string, and so know the true position of the cursor. It achieves this by keeping a copy of bytes
* that pass through from from upstream to the true System.out
, until either a newline
* arrives, or a defined capacity (typically the console width) is reached. If client code requests
* the partial line as a prompt, that action also empties the buffer. In that case, the client
* (which is the console object) is responsible for making the prompt emerge on the real console.
*/
public class ConsoleOutputStream extends FilterOutputStream {
/** The storage buffer for accumulating the partial line */
protected ByteBuffer buf;
/**
* Create a wrapper on an OutputStream
that holds a copy of the last incomplete
* line written to it (as bytes), in case it is needed as a console prompt.
*
* @param out the stream wrapped (normally System.out
)
* @param promptCapacity maximum number of bytes to buffer
*/
public ConsoleOutputStream(OutputStream out, int promptCapacity) {
super(out);
buf = ByteBuffer.allocate(Math.max(4, promptCapacity));
}
/**
* This write method steals a copy of each byte in a buffer while passing it on to the wrapped
* stream. The buffer is reset by each newline, when it overflows, or by the client when it is
* taken as a console prompt in {@link #getPrompt(Charset)}.
*/
@Override
public void write(int b) throws IOException {
buf.put((byte)b);
out.write(b);
if (b == '\n' || buf.remaining() == 0) {
// Empty the prompt buffer
buf.position(0);
}
}
@Override
public void flush() throws IOException {
// Flush passed on to wrapped System.out
out.flush();
}
@Override
public void close() throws IOException {
super.close(); // ... with a flush
out.close();
}
/**
* Return the stored bytes encoded as characters. Whatever is in the buffer at the point this
* method is called will be returned, decoded as a CharSequence (from which a String can easily
* be got) and the buffer left empty. The expectation is that the characters will be issued by
* the caller as a prompt.
*
* @param encoding with which to decode the bytes
* @return the decoded prompt
*/
protected CharSequence getPrompt(Charset encoding) {
buf.flip();
CharSequence prompt = encoding.decode(buf);
buf.compact();
return prompt;
}
}