001/*
002 * Copyright (C) 2009-2017 the original author(s).
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.fusesource.jansi;
017
018import static org.fusesource.jansi.Ansi.ansi;
019
020import java.io.BufferedReader;
021import java.io.Closeable;
022import java.io.File;
023import java.io.FileInputStream;
024import java.io.IOException;
025import java.io.InputStream;
026import java.io.InputStreamReader;
027import java.io.PrintStream;
028import java.util.Properties;
029
030import org.fusesource.jansi.Ansi.Attribute;
031import org.fusesource.jansi.internal.CLibrary;
032import org.fusesource.jansi.internal.JansiLoader;
033
034/**
035 * Main class for the library, providing executable jar to diagnose Jansi setup.
036 * <p>If no system property is set and output is sent to a terminal (no redirect to a file):
037 * <ul>
038 * <li>any terminal on any Unix should get <code>RESET_ANSI_AT_CLOSE</code> mode,</li>
039 * <li>on Windows, Git-bash or Cygwin terminals should get <code>RESET_ANSI_AT_CLOSE</code> mode also, since they
040 * support natively ANSI escape sequences like any Unix terminal,</li>
041 * <li>on Windows, cmd.exe, PowerShell or Git-cmd terminals should get <code>WINDOWS</code> mode.</li>
042 * </ul>
043 * If stdout is redirected to a file (<code>&gt; out.txt</code>), System.out should switch to <code>STRIP_ANSI</code>.
044 * Same for stderr redirection (<code>2&gt; err.txt</code>) which should affect System.err mode.
045 * <p>The results will vary if you play with <code>jansi.passthrough</code>, <code>jansi.strip</code> or
046 * <code>jansi.force</code> system property, or if you redirect output to a file.
047 * <p>If you have a specific situation that is not covered, please report precise conditions to reproduce
048 * the issue and ideas on how to detect precisely the affected situation.
049 * @see AnsiConsole
050 */
051public class AnsiMain {
052    public static void main(String... args) throws IOException {
053        System.out.println("Jansi " + getJansiVersion());
054
055        System.out.println();
056
057        // info on native library
058        System.out.println("library.jansi.path= " + System.getProperty("library.jansi.path", ""));
059        System.out.println("library.jansi.version= " + System.getProperty("library.jansi.version", ""));
060        boolean loaded = JansiLoader.initialize();
061        if (loaded) {
062            System.out.println("Jansi native library loaded from " + JansiLoader.getNativeLibraryPath());
063            if (JansiLoader.getNativeLibrarySourceUrl() != null) {
064                System.out.println("   which was auto-extracted from " + JansiLoader.getNativeLibrarySourceUrl());
065            }
066        } else {
067            String prev = System.getProperty(AnsiConsole.JANSI_GRACEFUL);
068            try {
069                System.setProperty(AnsiConsole.JANSI_GRACEFUL, "false");
070                JansiLoader.initialize();
071            } catch (Throwable e) {
072                e.printStackTrace(System.out);
073            } finally {
074                if (prev != null) {
075                    System.setProperty(AnsiConsole.JANSI_GRACEFUL, prev);
076                } else {
077                    System.clearProperty(AnsiConsole.JANSI_GRACEFUL);
078                }
079            }
080        }
081
082        System.out.println();
083
084        System.out.println("os.name= " + System.getProperty("os.name") + ", "
085                        + "os.version= " + System.getProperty("os.version") + ", "
086                        + "os.arch= " + System.getProperty("os.arch"));
087        System.out.println("file.encoding= " + System.getProperty("file.encoding"));
088        System.out.println("java.version= " + System.getProperty("java.version") + ", "
089                        + "java.vendor= " + System.getProperty("java.vendor") + ","
090                        + " java.home= " + System.getProperty("java.home"));
091
092        System.out.println();
093
094        System.out.println(AnsiConsole.JANSI_GRACEFUL + "= " + System.getProperty(AnsiConsole.JANSI_GRACEFUL, ""));
095        System.out.println(AnsiConsole.JANSI_MODE + "= " + System.getProperty(AnsiConsole.JANSI_MODE, ""));
096        System.out.println(AnsiConsole.JANSI_OUT_MODE + "= " + System.getProperty(AnsiConsole.JANSI_OUT_MODE, ""));
097        System.out.println(AnsiConsole.JANSI_ERR_MODE + "= " + System.getProperty(AnsiConsole.JANSI_ERR_MODE, ""));
098        System.out.println(AnsiConsole.JANSI_COLORS + "= " + System.getProperty(AnsiConsole.JANSI_COLORS, ""));
099        System.out.println(AnsiConsole.JANSI_OUT_COLORS + "= " + System.getProperty(AnsiConsole.JANSI_OUT_COLORS, ""));
100        System.out.println(AnsiConsole.JANSI_ERR_COLORS + "= " + System.getProperty(AnsiConsole.JANSI_ERR_COLORS, ""));
101        System.out.println(AnsiConsole.JANSI_PASSTHROUGH + "= " + AnsiConsole.getBoolean(AnsiConsole.JANSI_PASSTHROUGH));
102        System.out.println(AnsiConsole.JANSI_STRIP + "= " + AnsiConsole.getBoolean(AnsiConsole.JANSI_STRIP));
103        System.out.println(AnsiConsole.JANSI_FORCE + "= " + AnsiConsole.getBoolean(AnsiConsole.JANSI_FORCE));
104        System.out.println(AnsiConsole.JANSI_NORESET + "= " + AnsiConsole.getBoolean(AnsiConsole.JANSI_NORESET));
105        System.out.println(Ansi.DISABLE + "= " + AnsiConsole.getBoolean(Ansi.DISABLE));
106
107        System.out.println();
108
109        System.out.println("IS_WINDOWS: " + AnsiConsole.IS_WINDOWS);
110        if (AnsiConsole.IS_WINDOWS) {
111            System.out.println("IS_CONEMU: " + AnsiConsole.IS_CONEMU);
112            System.out.println("IS_CYGWIN: " + AnsiConsole.IS_CYGWIN);
113            System.out.println("IS_MSYSTEM: " + AnsiConsole.IS_MSYSTEM);
114        }
115
116        System.out.println();
117
118        diagnoseTty(false); // System.out
119        diagnoseTty(true);  // System.err
120
121        AnsiConsole.systemInstall();
122
123        System.out.println();
124
125        System.out.println("Resulting Jansi modes for stout/stderr streams:");
126        System.out.println("  - System.out: " + AnsiConsole.out().toString());
127        System.out.println("  - System.err: " + AnsiConsole.err().toString());
128        System.out.println("Processor types description:");
129        for (AnsiType type : AnsiType.values()) {
130            System.out.println("  - " + type + ": " + type.getDescription());
131        }
132        System.out.println("Colors support description:");
133        for (AnsiColors colors : AnsiColors.values()) {
134            System.out.println("  - " + colors + ": " + colors.getDescription());
135        }
136        System.out.println("Modes description:");
137        for (AnsiMode mode : AnsiMode.values()) {
138            System.out.println("  - " + mode + ": " + mode.getDescription());
139        }
140
141        try {
142            System.out.println();
143
144            testAnsi(false);
145            testAnsi(true);
146
147            if (args.length == 0) {
148                printJansiLogoDemo();
149                return;
150            }
151
152            System.out.println();
153
154            if (args.length == 1) {
155                File f = new File(args[0]);
156                if (f.exists())
157                {
158                    // write file content
159                    System.out.println(ansi().bold().a("\"" + args[0] + "\" content:").reset());
160                    writeFileContent(f);
161                    return;
162                }
163            }
164
165            // write args without Jansi then with Jansi AnsiConsole
166            System.out.println(ansi().bold().a("original args:").reset());
167            int i = 1;
168            for (String arg: args) {
169                AnsiConsole.system_out.print(i++ + ": ");
170                AnsiConsole.system_out.println(arg);
171            }
172
173            System.out.println(ansi().bold().a("Jansi filtered args:").reset());
174            i = 1;
175            for (String arg: args) {
176                System.out.print(i++ + ": ");
177                System.out.println(arg);
178            }
179        } finally {
180            AnsiConsole.systemUninstall();
181        }
182    }
183
184    private static String getJansiVersion() {
185        Package p = AnsiMain.class.getPackage();
186        return ( p == null ) ? null : p.getImplementationVersion();
187    }
188
189    private static void diagnoseTty(boolean stderr) {
190        int fd = stderr ? CLibrary.STDERR_FILENO : CLibrary.STDOUT_FILENO;
191        int isatty = CLibrary.LOADED ? CLibrary.isatty(fd) : 0;
192
193        System.out.println("isatty(STD" + (stderr ? "ERR" : "OUT") + "_FILENO): " + isatty + ", System."
194            + (stderr ? "err" : "out") + " " + ((isatty == 0) ? "is *NOT*" : "is") + " a terminal");
195    }
196
197    private static void testAnsi(boolean stderr) {
198        @SuppressWarnings( "resource" )
199        PrintStream s = stderr ? System.err : System.out;
200        s.print("test on System." + (stderr ? "err" : "out") + ":");
201        for(Ansi.Color c: Ansi.Color.values()) {
202            s.print(" " + ansi().fg(c) + c + ansi().reset());
203        }
204        s.println();
205        s.print("            bright:");
206        for(Ansi.Color c: Ansi.Color.values()) {
207            s.print(" " + ansi().fgBright(c) + c + ansi().reset());
208        }
209        s.println();
210        s.print("              bold:");
211        for(Ansi.Color c: Ansi.Color.values()) {
212            s.print(" " + ansi().bold().fg(c) + c + ansi().reset());
213        }
214        s.println();
215        s.print("             faint:");
216        for(Ansi.Color c: Ansi.Color.values()) {
217            s.print(" " + ansi().a(Attribute.INTENSITY_FAINT).fg(c) + c + ansi().reset());
218        }
219        s.println();
220        s.print("        bold+faint:");
221        for(Ansi.Color c: Ansi.Color.values()) {
222            s.print(" " + ansi().bold().a(Attribute.INTENSITY_FAINT).fg(c) + c + ansi().reset());
223        }
224        s.println();
225        Ansi ansi = ansi();
226        ansi.a("        256 colors: ");
227        for (int i = 0; i < 6*6*6; i++) {
228            if (i > 0 && i % 36 == 0) {
229                ansi.reset();
230                ansi.newline();
231                ansi.a("                    ");
232            } else if (i > 0 && i % 6 == 0) {
233                ansi.reset();
234                ansi.a("  ");
235            }
236            int a0 = i % 6;
237            int a1 = (i  / 6) % 6;
238            int a2 = i / 36;
239            ansi.bg(16 + a0 + a2 * 6 + a1 * 36).a(' ');
240        }
241        ansi.reset();
242        s.println(ansi);
243        ansi = ansi();
244        ansi.a("         truecolor: ");
245        for (int i = 0; i < 256; i++) {
246            if (i > 0 && i % 48 == 0) {
247                ansi.reset();
248                ansi.newline();
249                ansi.a("                    ");
250            }
251            int r = 255 - i;
252            int g = i * 2 > 255 ? 255 - 2 * i : 2 * i;
253            int b = i;
254            ansi.bgRgb(r, g, b).fgRgb(255 - r, 255 - g, 255 - b).a(i % 2 == 0 ? '/' : '\\');
255        }
256        ansi.reset();
257        s.println(ansi);
258    }
259
260    private static String getPomPropertiesVersion(String path) throws IOException {
261        InputStream in = AnsiMain.class.getResourceAsStream("/META-INF/maven/" + path + "/pom.properties");
262        if (in == null) {
263            return null;
264        }
265        try {
266            Properties p = new Properties();
267            p.load(in);
268            return p.getProperty("version");
269        } finally {
270            closeQuietly(in);
271        }
272    }
273
274    private static void printJansiLogoDemo() throws IOException {
275        BufferedReader in = new BufferedReader(new InputStreamReader(AnsiMain.class.getResourceAsStream("jansi.txt"), "UTF-8"));
276        try {
277            String l;
278            while ((l = in.readLine()) != null) {
279                System.out.println(l);
280            }
281        } finally {
282            closeQuietly(in);
283        }
284    }
285
286    private static void writeFileContent(File f) throws IOException {
287        InputStream in = new FileInputStream(f);
288        try {
289            byte[] buf = new byte[1024];
290            int l = 0;
291            while ((l = in.read(buf)) >= 0) {
292                System.out.write(buf, 0, l);
293            }
294        } finally {
295            closeQuietly(in);
296        }
297    }
298
299    private static void closeQuietly(Closeable c) {
300        try {
301            c.close();
302        } catch (IOException ioe) {
303            ioe.printStackTrace(System.err);
304        }
305    }
306}