001package Torello.Java; 002 003import java.util.Vector; 004import java.util.HashMap; 005import java.io.File; 006 007/** 008 * A UNIX Terminal Color-Codes implementation for printing colored text to terminal. 009 * 010 * <BR /><BR /><EMBED CLASS='external-html' DATA-FILE-ID=UNIX_COLORS> 011 */ 012@Torello.JavaDoc.StaticFunctional 013public class C 014{ 015 private C() { } 016 017 /** 018 * If Java is not running on a UNIX machine, the terminal output that contains "color" will not function. 019 * If it does not, then the Shell color commands will default to empty, zero-length strings. 020 * 021 * <BR /><BR /><B CLASS=JDDescLabel>WINDOWS SUPPORT:</B> 022 * 023 * <BR />Since Windows Release 1909, which was the 2019 Version of Windows 10, MS-DOS Command 024 * Prompt Windows will also support ANSI Color-Code Escape Sequences; 025 */ 026 public static final boolean colorANSI; 027 028 static 029 { 030 String osName = System.getProperty("os.name"); 031 String osArch = System.getProperty("os.arch"); 032 String osVers = System.getProperty("os.version"); 033 boolean windows = StrCmpr.containsIgnoreCase(osName, "win"); 034 boolean unix = StrCmpr.containsOR_CI(osName, "nix", "nux", "aix"); 035 float version = -1; 036 037 if (windows) 038 039 try 040 { version = Float.parseFloat(osVers); } 041 042 catch (Exception e) { } 043 044 /* 045 // Finding out where this class works is more difficult than you realize 046 System.out.println( 047 "os.name: " + osName + '\n' + 048 "os.arch: " + osArch + '\n' + 049 "os.version: " + osVers + '\n' + 050 "version: " + version 051 ); 052 Q.BP(); 053 */ 054 055 if (windows) colorANSI = (version >= 10); 056 else if (unix) colorANSI = true; 057 058 else if (StrCmpr.containsIgnoreCase(osName, "max")) colorANSI = false; 059 else if (StrCmpr.containsIgnoreCase(osName, "sunos")) colorANSI = false; 060 else colorANSI = true; 061 } 062 063 064 public static final String RESET = colorANSI ? "\u001B[0m" : ""; 065 066 public static final String BLACK = colorANSI ? "\u001B[30m" : ""; 067 public static final String RED = colorANSI ? "\u001B[31m" : ""; 068 public static final String GREEN = colorANSI ? "\u001B[32m" : ""; 069 public static final String YELLOW = colorANSI ? "\u001B[33m" : ""; 070 public static final String BLUE = colorANSI ? "\u001B[34m" : ""; 071 public static final String PURPLE = colorANSI ? "\u001B[35m" : ""; 072 public static final String CYAN = colorANSI ? "\u001B[36m" : ""; 073 public static final String WHITE = colorANSI ? "\u001B[37m" : ""; 074 075 public static final String BLACK_BKGND = colorANSI ? "\u001B[40m" : ""; 076 public static final String RED_BKGND = colorANSI ? "\u001B[41m" : ""; 077 public static final String GREEN_BKGND = colorANSI ? "\u001B[42m" : ""; 078 public static final String YELLOW_BKGND = colorANSI ? "\u001B[43m" : ""; 079 public static final String BLUE_BKGND = colorANSI ? "\u001B[44m" : ""; 080 public static final String PURPLE_BKGND = colorANSI ? "\u001B[45m" : ""; 081 public static final String CYAN_BKGND = colorANSI ? "\u001B[46m" : ""; 082 public static final String WHITE_BKGND = colorANSI ? "\u001B[47m" : ""; 083 084 public static final String BBLACK = colorANSI ? "\u001B[90m" : ""; 085 public static final String BRED = colorANSI ? "\u001B[91m" : ""; 086 public static final String BGREEN = colorANSI ? "\u001B[92m" : ""; 087 public static final String BYELLOW = colorANSI ? "\u001B[93m" : ""; 088 public static final String BBLUE = colorANSI ? "\u001B[94m" : ""; 089 public static final String BPURPLE = colorANSI ? "\u001B[95m" : ""; 090 public static final String BCYAN = colorANSI ? "\u001B[96m" : ""; 091 public static final String BWHITE = colorANSI ? "\u001B[97m" : ""; 092 093 public static final String BBLACK_BKGND = colorANSI ? "\u001B[100m" : ""; 094 public static final String BRED_BKGND = colorANSI ? "\u001B[101m" : ""; 095 public static final String BGREEN_BKGND = colorANSI ? "\u001B[102m" : ""; 096 public static final String BYELLOW_BKGND = colorANSI ? "\u001B[103m" : ""; 097 public static final String BBLUE_BKGND = colorANSI ? "\u001B[104m" : ""; 098 public static final String BPURPLE_BKGND = colorANSI ? "\u001B[105m" : ""; 099 public static final String BCYAN_BKGND = colorANSI ? "\u001B[106m" : ""; 100 public static final String BWHITE_BKGND = colorANSI ? "\u001B[107m" : ""; 101 102 private static final String CSS_DEFINITIONS_FILE = 103 "data-files" + File.separator + "C-CSS.sdat"; 104 105 private static final String HTML_SPANS_FILE = 106 "data-files" + File.separator + "C-SPANS.sarrdat"; 107 108 @SuppressWarnings("rawtypes") 109 private static final Vector v = LFEC.readObjectFromFile_JAR 110 (Torello.Java.C.class, HTML_SPANS_FILE, true, Vector.class); 111 112 113 // This list has: 114 // "</SPAN>" (Maps to: C.RESET) 115 // "<SPAN CLASS=SC1>" through SC8 (Maps to: C.BLACK ... C.WHITE) 116 // "<SPAN CLASS=SB1>" through SB8 (Maps to: C.BLACK_BKGND ... C.WHITE_BKGND) 117 // "<SPAN CLASS=BC1>" through BC8 (Maps to: C.BBLACK ... C.BWHITE) 118 // "<SPAN CLASS=BB1>" through BB8 (Maps to: C.BBLACK_BKGND ... C.BWHITE_BKGND) 119 120 @SuppressWarnings("unchecked") 121 private static final String[] htmlSpansCSSClasses = (String[]) v.elementAt(0); 122 123 // This list is identical to the one above, but uses **INLINE** STYLE ATTRIBUTES: 124 // C.RESET ==> "</SPAN>" 125 // C.BLACK ==> "<SPAN style='color: black;'>" 126 // C.BLACK_BKGND ==> "<SPAN style='background: black;'>" 127 // C.BBLACK ==> "<SPAN style='color: black; font-weight: bold;'>" 128 // C.BBLACK_BKGN ==> "<SPAN style='background: brightblack;'>" 129 130 @SuppressWarnings("unchecked") 131 private static final String[] htmlSpansStyleAttributes = (String[]) v.elementAt(1); 132 133 // Efficiently (using HashMap) converts a "Char Code String" to an array position 134 // The "Char Code String" may be any one of the 33 String defined in this class. 135 // The array position is an index into the PREVIOUS TWO ARRAYS. 136 137 @SuppressWarnings("unchecked") 138 private static final HashMap<String, Integer> charCodesMap = 139 (HashMap<String, Integer>) v.elementAt(2); 140 141 // less efficient version, 'StrRepace' requires this... Note - these Strings are all 142 // extremely short. There isn't a way to improve StrReplace in this regard - it *MUST* 143 // check for *ALL* of the codes... 144 145 private static final String[] charCodesArr = (String[]) v.elementAt(3); 146 147 148 /** 149 * This will convert a UNIX 'Character Code' into an HTML Tag if it is necessary to convert 150 * UNIX colored-text into HTML. 151 * 152 * <BR /><BR /><B CLASS=JDDescLabel>CSS-Definitions:</B> 153 * 154 * <BR />This method returns an HTML {@code SPAN}-Tag that contains an inline 155 * {@code CSS-CLASS}. It is (hopefully) obvious that the definitiions for any / all 156 * {@code CSS-CLASSES} that are used will need to be provided on the page. 157 * 158 * <BR /><BR />The method {@link #getCSSDefinitions()} will return the complete definition 159 * page for all {@code CSS CLASSES} that are employed by this method. 160 * 161 * <BR /><BR />You may also view the contents of the CSS Definitions Below: 162 * 163 * <BR /><BR /><B><A HREF="hilite-files/C.css.html">Shell.C CSS Definitions</A></B> 164 * 165 * @param charCode Any one of the 33 codes defined in this class. 166 * 167 * @return An HTML {@code <SPAN CLASS=...>} element that may be used as a substitute for 168 * one of the codes defined in this class. 169 * 170 * @throws IllegalArgumentException If the {@code String} that is passed to parameter 171 * {@code 'charCode'} is not one of the defined codes in this class. 172 * 173 * @see #getCSSDefinitions() 174 */ 175 public static String span(String charCode) 176 { 177 Integer arrPos = charCodesMap.get(charCode); 178 179 if (arrPos == null) throw new IllegalArgumentException( 180 "The value passed to parameter 'charCode' is not one of the defined codes in " + 181 "this class." 182 ); 183 184 return htmlSpansCSSClasses[arrPos]; 185 } 186 187 /** 188 * This will convert a UNIX 'Character Code' into an HTML Tag if it is necessary to convert 189 * UNIX colored-text into HTML. 190 * 191 * <BR /><BR /><B CLASS=JDDescLabel>CSS Inline-Style:</B> 192 * 193 * <BR />This method returns an HTML {@code SPAN}-Tag that contains an <B>inline 194 * {@code STYLE}-Attribute</B>. Remember, if you are converting large Text-{@code String's} 195 * into HTML using inlne {@code STYLE}-Attributes, your output could potentially grow very 196 * large, and rather quickly. 197 * 198 * <BR /><BR />Using {@code CSS-CLASSES} provided by method {@link #span(java.lang.String)} 199 * <I>will make your generated HTML <B>somewhat</B> more efficient</I>. If you do, you must 200 * remember to import the CSS Definitions for these classes somewhere in your HTML-File. 201 * 202 * @param charCode Any one of the 33 codes defined in this class. 203 * 204 * @return An HTML {@code <SPAN STYLE=...>} element that may be used as a substitute for 205 * one of the color-codes defined in this class. 206 * 207 * @throws IllegalArgumentException If the {@code String} that is passed to parameter 208 * {@code 'charCode'} is not one of the defined codes in this class. 209 */ 210 public static String spanInlineStyle(String charCode) 211 { 212 Integer arrPos = charCodesMap.get(charCode); 213 214 if (arrPos == null) throw new IllegalArgumentException( 215 "The value passed to parameter 'charCode' is not one of the defined codes in " + 216 "this class." 217 ); 218 219 return htmlSpansStyleAttributes[arrPos]; 220 } 221 222 /** 223 * Convenience Method. 224 * <BR />Invokes: {@link #toHTML(String, boolean, boolean, boolean)} 225 */ 226 public static String toHTML(String text) { return toHTML(text, false, true, false); } 227 228 // Used in method below 229 private static final String[] MATCH_STRS_1 = { "<", ">", "\n\r", "\r\n", "\n", "\r" }; 230 private static final String[] MATCH_STRS_2 = { "<", ">" }; 231 private static final String[] MATCH_STRS_3 = { "\n\r", "\r\n", "\n", "\r" }; 232 233 private static final String REPLACER(int i, String s) 234 { 235 switch (s) 236 { 237 case "<" : return "<"; 238 case ">" : return ">"; 239 case "\n" : 240 case "\r" : 241 case "\n\r" : 242 case "\r\n" : return "<BR />\n"; 243 default: throw new UnreachableError(); 244 } 245 } 246 247 /** 248 * Converts the instances of these escape-sequences that are found inside of Java 249 * {@code String's} that were generated using these ANSI UNIX color escape sequences, and 250 * produces a valid HTML {@code String} that contains HTML 251 * {@code <SPAN STYLE="color-information">} replacements! 252 * 253 * <BR /><BR /><B CLASS=JDDescLabel>New-Line Characters:</B> 254 * 255 * <BR />Any new-line Character-Sequences such as {@code '\n'} or {@code '\r\n'} will be 256 * replaced with HTML {@code <BR />} elements. 257 * 258 * @param text This should be any string, usually one that is saved from a 259 * {@code 'StorageWriter'}, although any text that includes these UNIX Color Escape Codes 260 * is fine. 261 * 262 * @param preFormat When this parameter receives {@code FALSE}, everywhere in the input 263 * text-{@code String} that a {@code CRLF} (new-line) occurs, that newline will be replaced 264 * by an HTML {@code <BR />} element, in addition to the original newline. 265 * 266 * <BR /><BR />This parameter is referring to the CSS {@code 'white-space: pre'} setting, 267 * which can be used. Althought, sometimes going with the plain-old-vanilla {@code <BR />} 268 * tag can also be advisable. 269 * 270 * @param escapeHTMLElements Whenever HTML is sent to the input-parameter 'text' - if the 271 * intention is to render the HTML using the browser, this parameter should be 272 * {@code FALSE}. If it is intended to allow the UI to "show the HTML" like it were 273 * text-to-be-viewed, then each and every greater-than-symbol {@code '>'} and also every 274 * less-than-symbol {@code '<'} will be escaped. This is done to prevent the browser from 275 * trying to parse the text as HTML. 276 * 277 * @param useCSSClasses When this parameter receives {@code TRUE}, all returned 278 * {@code <SPAN STYLE=...>} elements shall be converted to using a simplified 279 * {@code CSS Class Name}. The {@code CLASS} definitions for the returned {@code String} 280 * can be retrieved by simply calling the method: {@link #getCSSDefinitions()}. 281 * 282 * <BR /><BR /><B><SPAN STYLE="color: red;">IMPORTANT:</SPAN></B> If this parameter does 283 * receive a {@code TRUE} value, it is imperitive to include the {@code CSS STYLE} 284 * definitions that are returned by the above mentioned method, or else the colors shall 285 * not be visible. 286 * 287 * <BR /><BR />You may view the contents of the CSS Definitions Below: 288 * 289 * <BR /><BR /><B><A HREF="hilite-files/C.css.html">Shell.C CSS Definitions</A></B> 290 * 291 * @return Every UNIX-ANSI color escape-sequence that is found/identified in this text will 292 * be replaced with an HTML 293 * {@code <SPAN STYLE="color: a-color; background: a-background-color">} element. 294 */ 295 public static String toHTML 296 (String text, boolean preFormat, boolean escapeHTMLElements, boolean useCSSClasses) 297 { 298 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 299 // Old Way, much less efficient 300 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 301 302 // If the input text, itself, has HTML elements, then those have to be "escaped" to 303 // properly render. If the intention was to have them rendered has HTML Elements 304 // (not text), then this boolean should be false. 305 306 // if (escapeHTMLElements) text = text.replace("<", "<").replace(">", ">"); 307 308 // With "Pre-Formatted Text" - there is no need to add "<BR />" where line-breaks 309 // occur CRLF will automatically be inserted courtesy of the browser 310 311 // if (! preFormat) text = text.replaceAll("\n|\r\n|\r", "<BR />\n"); 312 313 314 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 315 // Quite a bit faster 316 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 317 318 String[] matchStrs = null; 319 320 // Replaces both '<', '>' **AND** '\n', '\r', '\n\r', '\r\n' (all at once) 321 if (escapeHTMLElements && (! preFormat)) matchStrs = MATCH_STRS_1; 322 323 // Replaces ONLY '<' and '>' 324 else if (escapeHTMLElements && preFormat) matchStrs = MATCH_STRS_2; 325 326 // Replaces ONLY '\n', '\r', '\n\r', '\r\n' 327 else if ((! escapeHTMLElements) && (! preFormat)) matchStrs = MATCH_STRS_3; 328 329 // NOW RUN IT... 330 if (matchStrs != null) text = StrReplace.r(text, matchStrs, C::REPLACER); 331 332 return StrReplace.r( 333 text, charCodesArr, 334 useCSSClasses ? htmlSpansCSSClasses : htmlSpansStyleAttributes 335 ); 336 } 337 338 /** 339 * If the {@code 'useCSSDefinitions'} option is selected with the 340 * {@link #toHTML(String, boolean, boolean, boolean)} method, then the {@code String} 341 * returned from this method shall provide the {@code CSS Style} definitions needed to use 342 * the colors provided by {@code toHTML(...)} 343 * 344 * @return This shall visit the internal data-files for this JAR distribution, and return a 345 * list of {@code CSS Style} definitions that will colorize the HTML produced by an 346 * invocation of {@code toHTML()}. 347 * 348 * <BR /><BR />You may view the contents of the CSS Definitions Below: 349 * 350 * <BR /><BR /><B><A HREF="hilite-files/C.css.html">Shell.C CSS Definitions</A></B> 351 */ 352 public static String getCSSDefinitions() 353 { 354 /* 355 return LFEC.readObjectFromFile_JAR 356 (Torello.Data.DataFileLoader.class, CSS_DEFINITIONS_FILE, true, String.class); 357 */ 358 359 return LFEC.readObjectFromFile_JAR 360 (Torello.Java.C.class, CSS_DEFINITIONS_FILE, true, String.class); 361 } 362 363 /** 364 * Convenience Method. 365 * <BR />Creates an {@code '.html'}-file from the output produced by 366 * {@link #toHTML(String, boolean, boolean, boolean)} 367 * <BR />Invokes: {@link #getCSSDefinitions()} 368 * <BR />And Invokes: {@link #toHTML(String, boolean, boolean, boolean)} 369 * <BR />Passes: {@code TRUE} to parameter {@code 'useCSSClasses'} 370 */ 371 public static String toHTML 372 (String text, boolean preFormat, boolean escapeHTMLElements, String titleStr) 373 { 374 return 375 "<HTML>\n" + 376 "<HEAD>\n" + 377 "<TITLE>" + titleStr + "</TITLE>\n" + 378 "<STYLE TYPE='text/css'>\n" + '\n' + 379 380 // This method simply copies the CSS-Definitions File out of the Java-HTML JAR, and 381 // into a String that is returned to the user. Make sure to wrap that String 382 // inside of a <STYLE>...</STYLE> HTML-Tag. Also - set the background color 383 384 getCSSDefinitions() + 385 386 "BODY { background: black; color: white; }\n" + 387 "</STYLE>\n" + 388 "</HEAD>\n" + 389 "<BODY>\n" + 390 (preFormat ? "<PRE>\n" : "") + 391 392 // NOTE: This just calls the other variant of 'toHTML' - but ensures that 'true' is 393 // passed to the 'useCSSClasses' parameter. 394 395 toHTML(text, preFormat, escapeHTMLElements, true) + 396 397 (preFormat ? "</PRE>\n" : "") + 398 "</BODY>\n" + 399 "</HTML>"; 400 } 401}