0

I want to colorize a formatted output. But the format of the colorized text is ignored:

String leftAlignFormat = "| %-15s | %-15s |";
System.out.format(leftAlignFormat, "\033[38;5;16;48;5;40mHello\033[0m", "World");
| Hello | World           |

The word Hello is correctly colored, but why is the word Hello not correctly formatted?

Joe
  • 287
  • 3
  • 13
  • 1
    Does this answer your question? [How to print color in console using System.out.println?](https://stackoverflow.com/questions/5762491/how-to-print-color-in-console-using-system-out-println) – Shivam Puri Oct 28 '20 at 07:25
  • Thanks for your answer. No, the post only explains how to print colored text. – Joe Oct 28 '20 at 07:33
  • 2
    To confirm: you are asking how to make `.format(...)` not count ANSI color escape codes when padding to some desired width (in this case, 15 characters wide)? – Dilum Ranatunga Oct 28 '20 at 07:46
  • 1
    @DilumRanatunga: Yes, exactly. I have precized my question. – Joe Oct 28 '20 at 07:54

3 Answers3

2

Java's APIs don't natively understand ANSI color escape codes, so the format(...) API is counting those as characters in the string.

But when those characters written to an ANSI terminal, the escape codes do not move the cursor, so the formatting appears incorrect.

Depending on the complexity of the usecase, you will need to build your own wrapper APIs (if there are strings with several colors), or you can work around it by knowing exactly how many extra characters you add to generate a color, and increase your padding width accordingly. For simplicity, I would recommend always prepending the color code sequence and appending the reset, so the "extra" padding is a fixed amount.

Also keep in mind that ANSI escape codes are not portable, so you may need to support a no color code & template path, depending on your target execution environment(s)

Dilum Ranatunga
  • 13,254
  • 3
  • 41
  • 52
  • Thank you. Your explanation solved my problem. For my special use case I have now implemented a dynamic alignment regarding to the escape codes. – Joe Oct 29 '20 at 07:32
1

This is because formatting is based on String length. Following code will explain what happens:

        String hello = "\033[38;5;16;48;5;40mHello\033[0m";
        System.out.println(hello);
        System.out.println(hello.length());

        String leftAlignFormat = "| %-27s | %-20s |";
        System.out.format(leftAlignFormat, hello,  "World");
        System.out.println("");
        leftAlignFormat = "| %-28s | %-20s |";
        System.out.format(leftAlignFormat, hello,  "World");

String length will output 27. So a setting of 28 will start padding the String. It might be looking awkward, but formatting is String based - not meant to be an ANSI formatting tool.

supernova
  • 1,762
  • 1
  • 14
  • 31
0

The color format "\033[0m" is used to reset the colors.

In your format you have used it just at the end of the first string; hence rest of the text is reset to default colors.

System.out.format(leftAlignFormat, "\033[38;5;16;48;5;40mHello\033[0m", "World");

Based on this format, the work Hello must be highlighted with green, but not the rest.

enter image description here

This is how I see it in my IDE.

lkamal
  • 3,788
  • 1
  • 20
  • 34
  • The colouring works as I expected. But my question is why the formatting of the colorized text is ignored. – Joe Oct 28 '20 at 07:49
  • I have added a screenshot on how I see it in the IDE, so you are referring why the space used is similar to the other word (World)? – lkamal Oct 28 '20 at 07:57
  • I think you have got the answer from @Dilum Ranatunga – lkamal Oct 28 '20 at 08:03