javaswingansi-colors

ANSI colors in Java Swing text fields


Is there any simple way to parse Ansi colors in log files, and use it in text fields in Swing (JTextArea, JTextPAne,...)?


Solution

  • Not tried it, but there's some code here (which needs some formatting to look nice) which claims to be an ANSI colored JTextPane subclass...


    For posterity, here is the class run through NetBeans to format the code

    import javax.swing.*;
    import javax.swing.text.*;
    import java.awt.Color;
    
    public class ColorPane extends JTextPane {
      static final Color D_Black   = Color.getHSBColor( 0.000f, 0.000f, 0.000f );
      static final Color D_Red     = Color.getHSBColor( 0.000f, 1.000f, 0.502f );
      static final Color D_Blue    = Color.getHSBColor( 0.667f, 1.000f, 0.502f );
      static final Color D_Magenta = Color.getHSBColor( 0.833f, 1.000f, 0.502f );
      static final Color D_Green   = Color.getHSBColor( 0.333f, 1.000f, 0.502f );
      static final Color D_Yellow  = Color.getHSBColor( 0.167f, 1.000f, 0.502f );
      static final Color D_Cyan    = Color.getHSBColor( 0.500f, 1.000f, 0.502f );
      static final Color D_White   = Color.getHSBColor( 0.000f, 0.000f, 0.753f );
      static final Color B_Black   = Color.getHSBColor( 0.000f, 0.000f, 0.502f );
      static final Color B_Red     = Color.getHSBColor( 0.000f, 1.000f, 1.000f );
      static final Color B_Blue    = Color.getHSBColor( 0.667f, 1.000f, 1.000f );
      static final Color B_Magenta = Color.getHSBColor( 0.833f, 1.000f, 1.000f );
      static final Color B_Green   = Color.getHSBColor( 0.333f, 1.000f, 1.000f );
      static final Color B_Yellow  = Color.getHSBColor( 0.167f, 1.000f, 1.000f );
      static final Color B_Cyan    = Color.getHSBColor( 0.500f, 1.000f, 1.000f );
      static final Color B_White   = Color.getHSBColor( 0.000f, 0.000f, 1.000f );
      static final Color cReset    = Color.getHSBColor( 0.000f, 0.000f, 1.000f );
      static Color colorCurrent    = cReset;
      String remaining = "";
    
      public void append(Color c, String s) {
        StyleContext sc = StyleContext.getDefaultStyleContext();
        AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, c);
        int len = getDocument().getLength(); // same value as getText().length();
        setCaretPosition(len);  // place caret at the end (with no selection)
        setCharacterAttributes(aset, false);
        replaceSelection(s); // there is no selection, so inserts at caret
      }
    
      public void appendANSI(String s) { // convert ANSI color codes first
        int aPos = 0;   // current char position in addString
        int aIndex = 0; // index of next Escape sequence
        int mIndex = 0; // index of "m" terminating Escape sequence
        String tmpString = "";
        boolean stillSearching = true; // true until no more Escape sequences
        String addString = remaining + s;
        remaining = "";
    
        if (addString.length() > 0) {
          aIndex = addString.indexOf("\u001B"); // find first escape
          if (aIndex == -1) { // no escape/color change in this string, so just send it with current color
            append(colorCurrent,addString);
            return;
          }
    // otherwise There is an escape character in the string, so we must process it
    
          if (aIndex > 0) { // Escape is not first char, so send text up to first escape
            tmpString = addString.substring(0,aIndex);
            append(colorCurrent, tmpString);
            aPos = aIndex;
          }
    // aPos is now at the beginning of the first escape sequence
    
          stillSearching = true;
          while (stillSearching) {
            mIndex = addString.indexOf("m",aPos); // find the end of the escape sequence
            if (mIndex < 0) { // the buffer ends halfway through the ansi string!
              remaining = addString.substring(aPos,addString.length());
              stillSearching = false;
              continue;
            }
            else {
              tmpString = addString.substring(aPos,mIndex+1);
              colorCurrent = getANSIColor(tmpString);
            }
            aPos = mIndex + 1;
    // now we have the color, send text that is in that color (up to next escape)
    
            aIndex = addString.indexOf("\u001B", aPos);
    
            if (aIndex == -1) { // if that was the last sequence of the input, send remaining text
              tmpString = addString.substring(aPos,addString.length());
              append(colorCurrent, tmpString);
              stillSearching = false;
              continue; // jump out of loop early, as the whole string has been sent now
            }
    
            // there is another escape sequence, so send part of the string and prepare for the next
            tmpString = addString.substring(aPos,aIndex);
            aPos = aIndex;
            append(colorCurrent, tmpString);
    
          } // while there's text in the input buffer
        }
      }
    
      public Color getANSIColor(String ANSIColor) {
        if (ANSIColor.equals("\u001B[30m"))        { return D_Black; }
        else if (ANSIColor.equals("\u001B[31m"))   { return D_Red; }
        else if (ANSIColor.equals("\u001B[32m"))   { return D_Green; }
        else if (ANSIColor.equals("\u001B[33m"))   { return D_Yellow; }
        else if (ANSIColor.equals("\u001B[34m"))   { return D_Blue; }
        else if (ANSIColor.equals("\u001B[35m"))   { return D_Magenta; }
        else if (ANSIColor.equals("\u001B[36m"))   { return D_Cyan; }
        else if (ANSIColor.equals("\u001B[37m"))   { return D_White; }
        else if (ANSIColor.equals("\u001B[0;30m")) { return D_Black; }
        else if (ANSIColor.equals("\u001B[0;31m")) { return D_Red; }
        else if (ANSIColor.equals("\u001B[0;32m")) { return D_Green; }
        else if (ANSIColor.equals("\u001B[0;33m")) { return D_Yellow; }
        else if (ANSIColor.equals("\u001B[0;34m")) { return D_Blue; }
        else if (ANSIColor.equals("\u001B[0;35m")) { return D_Magenta; }
        else if (ANSIColor.equals("\u001B[0;36m")) { return D_Cyan; }
        else if (ANSIColor.equals("\u001B[0;37m")) { return D_White; }
        else if (ANSIColor.equals("\u001B[1;30m")) { return B_Black; }
        else if (ANSIColor.equals("\u001B[1;31m")) { return B_Red; }
        else if (ANSIColor.equals("\u001B[1;32m")) { return B_Green; }
        else if (ANSIColor.equals("\u001B[1;33m")) { return B_Yellow; }
        else if (ANSIColor.equals("\u001B[1;34m")) { return B_Blue; }
        else if (ANSIColor.equals("\u001B[1;35m")) { return B_Magenta; }
        else if (ANSIColor.equals("\u001B[1;36m")) { return B_Cyan; }
        else if (ANSIColor.equals("\u001B[1;37m")) { return B_White; }
        else if (ANSIColor.equals("\u001B[0m"))    { return cReset; }
        else { return B_White; }
      }
    }