15
15
*/
16
16
package org .fusesource .jansi ;
17
17
18
- import org .fusesource .jansi .internal .Kernel32 ;
19
-
20
18
import static org .fusesource .jansi .internal .CLibrary .STDERR_FILENO ;
21
19
import static org .fusesource .jansi .internal .CLibrary .STDOUT_FILENO ;
22
20
import static org .fusesource .jansi .internal .CLibrary .isatty ;
25
23
import java .io .IOException ;
26
24
import java .io .OutputStream ;
27
25
import java .io .PrintStream ;
28
- import java .io .UnsupportedEncodingException ;
29
- import java .nio .charset .Charset ;
30
26
import java .util .Locale ;
31
27
32
28
/**
33
29
* Provides consistent access to an ANSI aware console PrintStream.
34
30
*
35
31
* @author <a href="http://hiramchirino.com">Hiram Chirino</a>
36
32
* @since 1.0
33
+ * @see #wrapPrintStream(PrintStream, int)
37
34
*/
38
35
public class AnsiConsole {
39
36
@@ -58,31 +55,18 @@ public class AnsiConsole {
58
55
static final JansiOutputType JANSI_STDOUT_TYPE ;
59
56
static final JansiOutputType JANSI_STDERR_TYPE ;
60
57
static {
61
- String charset = Charset .defaultCharset ().name ();
62
- if (IS_WINDOWS && !IS_CYGWIN && !IS_MINGW ) {
63
- int codepage = Kernel32 .GetConsoleOutputCP ();
64
- //http://docs.oracle.com/javase/6/docs/technotes/guides/intl/encoding.doc.html
65
- if (Charset .isSupported ("ms" + codepage )) {
66
- charset = "ms" + codepage ;
67
- } else if (Charset .isSupported ("cp" + codepage )) {
68
- charset = "cp" + codepage ;
69
- }
70
- }
71
- try {
72
- out = new PrintStream (wrapOutputStream (system_out ), false , charset );
73
- JANSI_STDOUT_TYPE = jansiOutputType ;
74
- err = new PrintStream (wrapErrorOutputStream (system_err ), false , charset );
75
- JANSI_STDERR_TYPE = jansiOutputType ;
76
- } catch (UnsupportedEncodingException e ) {
77
- throw new RuntimeException (e );
78
- }
58
+ out = wrapSystemOut (system_out );
59
+ JANSI_STDOUT_TYPE = jansiOutputType ;
60
+ err = wrapSystemErr (system_err );
61
+ JANSI_STDERR_TYPE = jansiOutputType ;
79
62
}
80
63
81
64
private static int installed ;
82
65
83
66
private AnsiConsole () {
84
67
}
85
68
69
+ @ Deprecated
86
70
public static OutputStream wrapOutputStream (final OutputStream stream ) {
87
71
try {
88
72
return wrapOutputStream (stream , STDOUT_FILENO );
@@ -91,6 +75,15 @@ public static OutputStream wrapOutputStream(final OutputStream stream) {
91
75
}
92
76
}
93
77
78
+ public static PrintStream wrapSystemOut (final PrintStream ps ) {
79
+ try {
80
+ return wrapPrintStream (ps , STDOUT_FILENO );
81
+ } catch (Throwable ignore ) {
82
+ return wrapPrintStream (ps , 1 );
83
+ }
84
+ }
85
+
86
+ @ Deprecated
94
87
public static OutputStream wrapErrorOutputStream (final OutputStream stream ) {
95
88
try {
96
89
return wrapOutputStream (stream , STDERR_FILENO );
@@ -99,6 +92,15 @@ public static OutputStream wrapErrorOutputStream(final OutputStream stream) {
99
92
}
100
93
}
101
94
95
+ public static PrintStream wrapSystemErr (final PrintStream ps ) {
96
+ try {
97
+ return wrapPrintStream (ps , STDERR_FILENO );
98
+ } catch (Throwable ignore ) {
99
+ return wrapPrintStream (ps , 2 );
100
+ }
101
+ }
102
+
103
+ @ Deprecated
102
104
public static OutputStream wrapOutputStream (final OutputStream stream , int fileno ) {
103
105
104
106
// If the jansi.passthrough property is set, then don't interpret
@@ -161,13 +163,91 @@ public void close() throws IOException {
161
163
};
162
164
}
163
165
166
+ /**
167
+ * Wrap PrintStream applying rules in following order:<ul>
168
+ * <li>if <code>jansi.passthrough</code> is <code>true</code>, don't wrap but just passthrough (console is
169
+ * expected to natively support ANSI escape codes),</li>
170
+ * <li>if <code>jansi.strip</code> is <code>true</code>, just strip ANSI escape codes inconditionally,</li>
171
+ * <li>if OS is Windows and terminal is not Cygwin or Mingw, wrap as WindowsAnsiPrintStream to process ANSI escape codes,</li>
172
+ * <li>if file descriptor is a terminal (see <code>isatty(int)</code>) or <code>jansi.force</code> is <code>true</code>,
173
+ * just passthrough,</li>
174
+ * <li>else strip ANSI escape codes (not a terminal).</li>
175
+ * </ul>
176
+ *
177
+ * @param ps original PrintStream to wrap
178
+ * @param fileno file descriptor
179
+ * @return wrapped PrintStream depending on OS and system properties
180
+ */
181
+ public static PrintStream wrapPrintStream (final PrintStream ps , int fileno ) {
182
+
183
+ // If the jansi.passthrough property is set, then don't interpret
184
+ // any of the ansi sequences.
185
+ if (Boolean .getBoolean ("jansi.passthrough" )) {
186
+ jansiOutputType = JansiOutputType .PASSTHROUGH ;
187
+ return ps ;
188
+ }
189
+
190
+ // If the jansi.strip property is set, then we just strip the
191
+ // the ansi escapes.
192
+ if (Boolean .getBoolean ("jansi.strip" )) {
193
+ jansiOutputType = JansiOutputType .STRIP_ANSI ;
194
+ return new AnsiPrintStream (ps );
195
+ }
196
+
197
+ if (IS_WINDOWS && !IS_CYGWIN && !IS_MINGW ) {
198
+
199
+ // On windows we know the console does not interpret ANSI codes..
200
+ try {
201
+ jansiOutputType = JansiOutputType .WINDOWS ;
202
+ return new WindowsAnsiPrintStream (ps );
203
+ } catch (Throwable ignore ) {
204
+ // this happens when JNA is not in the path.. or
205
+ // this happens when the stdout is being redirected to a file.
206
+ }
207
+
208
+ // Use the AnsiPrintStream to strip out the ANSI escape sequences.
209
+ jansiOutputType = JansiOutputType .STRIP_ANSI ;
210
+ return new AnsiPrintStream (ps );
211
+ }
212
+
213
+ // We must be on some Unix variant, including Cygwin or MSYS(2) on Windows...
214
+ try {
215
+ // If the jansi.force property is set, then we force to output
216
+ // the ansi escapes for piping it into ansi color aware commands (e.g. less -r)
217
+ boolean forceColored = Boolean .getBoolean ("jansi.force" );
218
+ // If we can detect that stdout is not a tty.. then setup
219
+ // to strip the ANSI sequences..
220
+ if (!forceColored && isatty (fileno ) == 0 ) {
221
+ jansiOutputType = JansiOutputType .STRIP_ANSI ;
222
+ return new AnsiPrintStream (ps );
223
+ }
224
+ } catch (Throwable ignore ) {
225
+ // These errors happen if the JNI lib is not available for your platform.
226
+ // But since we are on ANSI friendly platform, assume the user is on the console.
227
+ }
228
+
229
+ // By default we assume your Unix tty can handle ANSI codes.
230
+ // Just wrap it up so that when we get closed, we reset the
231
+ // attributes.
232
+ jansiOutputType = JansiOutputType .RESET_ANSI_AT_CLOSE ;
233
+ return new FilterPrintStream (ps ) {
234
+ @ Override
235
+ public void close () {
236
+ ps .print (AnsiPrintStream .RESET_CODE );
237
+ ps .flush ();
238
+ super .close ();
239
+ }
240
+ };
241
+ }
242
+
164
243
/**
165
244
* If the standard out natively supports ANSI escape codes, then this just
166
245
* returns System.out, otherwise it will provide an ANSI aware PrintStream
167
246
* which strips out the ANSI escape sequences or which implement the escape
168
247
* sequences.
169
248
*
170
249
* @return a PrintStream which is ANSI aware.
250
+ * @see #wrapPrintStream(PrintStream, int)
171
251
*/
172
252
public static PrintStream out () {
173
253
return out ;
@@ -180,6 +260,7 @@ public static PrintStream out() {
180
260
* sequences.
181
261
*
182
262
* @return a PrintStream which is ANSI aware.
263
+ * @see #wrapPrintStream(PrintStream, int)
183
264
*/
184
265
public static PrintStream err () {
185
266
return err ;
0 commit comments