-
Notifications
You must be signed in to change notification settings - Fork 226
Expand file tree
/
Copy pathConsoleOutputStream.java
More file actions
79 lines (70 loc) · 2.92 KB
/
ConsoleOutputStream.java
File metadata and controls
79 lines (70 loc) · 2.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
// 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 <code>System.out</code> 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 <code>System.out</code>, 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 <code>OutputStream</code> 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 <code>System.out</code>)
* @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;
}
}