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.Closeable;
021import java.io.File;
022import java.io.FileInputStream;
023import java.io.IOException;
024import java.io.InputStream;
025import java.io.InputStreamReader;
026import java.io.PrintStream;
027import java.io.Reader;
028import java.util.Properties;
029
030import org.fusesource.hawtjni.runtime.Library;
031import org.fusesource.jansi.internal.CLibrary;
032import static org.fusesource.jansi.internal.CLibrary.isatty;
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            + " (Jansi native " + getPomPropertiesVersion("org.fusesource.jansi/jansi-native")
055            + ", HawtJNI runtime " + getPomPropertiesVersion("org.fusesource.hawtjni/hawtjni-runtime") + ")");
056
057        System.out.println();
058
059        // info on native library
060        System.out.println("library.jansi.path= " + System.getProperty("library.jansi.path", ""));
061        System.out.println("library.jansi.version= " + System.getProperty("library.jansi.version", ""));
062        Library lib = new Library("jansi", CLibrary.class);
063        lib.load();
064        System.out.println("Jansi native library loaded from " + lib.getNativeLibraryPath());
065        if (lib.getNativeLibrarySourceUrl() != null) {
066            System.out.println("   which was auto-extracted from " + lib.getNativeLibrarySourceUrl());
067        }
068
069        System.out.println();
070
071        System.out.println("os.name= " + System.getProperty("os.name") + ", "
072                        + "os.version= " + System.getProperty("os.version") + ", "
073                        + "os.arch= " + System.getProperty("os.arch"));
074        System.out.println("file.encoding= " + System.getProperty("file.encoding"));
075        System.out.println("java.version= " + System.getProperty("java.version") + ", "
076                        + "java.vendor= " + System.getProperty("java.vendor") + ","
077                        + " java.home= " + System.getProperty("java.home"));
078
079        System.out.println();
080
081        System.out.println("jansi.passthrough= " + Boolean.getBoolean("jansi.passthrough"));
082        System.out.println("jansi.strip= " + Boolean.getBoolean("jansi.strip"));
083        System.out.println("jansi.force= " + Boolean.getBoolean("jansi.force"));
084        System.out.println(Ansi.DISABLE + "= " + Boolean.getBoolean(Ansi.DISABLE));
085
086        System.out.println();
087
088        System.out.println("IS_WINDOWS: " + AnsiConsole.IS_WINDOWS);
089        if (AnsiConsole.IS_WINDOWS) {
090            System.out.println("IS_CYGWIN: " + AnsiConsole.IS_CYGWIN);
091            System.out.println("IS_MINGW_XTERM: " + AnsiConsole.IS_MINGW_XTERM);
092        }
093
094        System.out.println();
095
096        diagnoseTty(false); // System.out
097        diagnoseTty(true);  // System.err
098
099        AnsiConsole.systemInstall();
100
101        System.out.println();
102
103        System.out.println("Resulting Jansi modes for stout/stderr streams:");
104        System.out.println("  - System.out: " + AnsiConsole.JANSI_STDOUT_TYPE);
105        System.out.println("  - System.err: " + AnsiConsole.JANSI_STDERR_TYPE);
106        System.out.println("modes description:");
107        int n = 1;
108        for(AnsiConsole.JansiOutputType type: AnsiConsole.JansiOutputType.values()) {
109            System.out.println(n++ + ". " + type + ": " + type.getDescription());
110        }
111
112        try {
113            System.out.println();
114
115            testAnsi(false);
116            testAnsi(true);
117
118            if (args.length == 0) {
119                printJansiLogoDemo();
120                return;
121            }
122
123            System.out.println();
124
125            if (args.length == 1) {
126                File f = new File(args[0]);
127                if (f.exists())
128                {
129                    // write file content
130                    System.out.println(ansi().bold().a("\"" + args[0] + "\" content:").reset());
131                    writeFileContent(f);
132                    return;
133                }
134            }
135
136            // write args without Jansi then with Jansi AnsiConsole
137            System.out.println(ansi().bold().a("original args:").reset());
138            int i = 1;
139            for (String arg: args) {
140                AnsiConsole.system_out.print(i++ + ": ");
141                AnsiConsole.system_out.println(arg);
142            }
143
144            System.out.println(ansi().bold().a("Jansi filtered args:").reset());
145            i = 1;
146            for (String arg: args) {
147                System.out.print(i++ + ": ");
148                System.out.println(arg);
149            }
150        } finally {
151            AnsiConsole.systemUninstall();
152        }
153    }
154
155    private static String getJansiVersion() {
156        Package p = AnsiMain.class.getPackage();
157        return ( p == null ) ? null : p.getImplementationVersion();
158    }
159
160    private static void diagnoseTty(boolean stderr) {
161        int fd = stderr ? CLibrary.STDERR_FILENO : CLibrary.STDOUT_FILENO;
162        int isatty = isatty(fd);
163
164        System.out.println("isatty(STD" + (stderr ? "ERR" : "OUT") + "_FILENO): " + isatty + ", System."
165            + (stderr ? "err" : "out") + " " + ((isatty == 0) ? "is *NOT*" : "is") + " a terminal");
166    }
167
168    private static void testAnsi(boolean stderr) {
169        @SuppressWarnings( "resource" )
170        PrintStream s = stderr ? System.err : System.out;
171        s.print("test on System." + (stderr ? "err" : "out") + ":");
172        for(Ansi.Color c: Ansi.Color.values()) {
173            s.print(" " + ansi().fg(c) + c + ansi().reset());
174        }
175        s.println();
176        s.print("            bright:");
177        for(Ansi.Color c: Ansi.Color.values()) {
178            s.print(" " + ansi().fgBright(c) + c + ansi().reset());
179        }
180        s.println();
181        s.print("              bold:");
182        for(Ansi.Color c: Ansi.Color.values()) {
183            s.print(" " + ansi().bold().fg(c) + c + ansi().reset());
184        }
185        s.println();
186    }
187
188    private static String getPomPropertiesVersion(String path) throws IOException {
189        InputStream in = AnsiMain.class.getResourceAsStream("/META-INF/maven/" + path + "/pom.properties");
190        if (in == null) {
191            return null;
192        }
193        try {
194            Properties p = new Properties();
195            p.load(in);
196            return p.getProperty("version");
197        } finally {
198            closeQuietly(in);
199        }
200    }
201
202    private static void printJansiLogoDemo() throws IOException {
203        Reader in = new InputStreamReader(AnsiMain.class.getResourceAsStream("jansi.txt"), "UTF-8");
204        try {
205            char[] buf = new char[1024];
206            int l = 0;
207            while ((l = in.read(buf)) >= 0) {
208                for(int i = 0; i < l; i++) {
209                    System.out.print(buf[i]);
210                }
211            }
212        } finally {
213            closeQuietly(in);
214        }
215    }
216
217    private static void writeFileContent(File f) throws IOException {
218        InputStream in = new FileInputStream(f);
219        try {
220            byte[] buf = new byte[1024];
221            int l = 0;
222            while ((l = in.read(buf)) >= 0) {
223                System.out.write(buf, 0, l);
224            }
225        } finally {
226            closeQuietly(in);
227        }
228    }
229
230    private static void closeQuietly(Closeable c) {
231        try {
232            c.close();
233        } catch (IOException ioe) {
234            ioe.printStackTrace(System.err);
235        }
236    }
237}