Skip to content

Instantly share code, notes, and snippets.

@jdabtieu
Last active March 28, 2022 03:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jdabtieu/9c46b1ca23630e657a6262d854476320 to your computer and use it in GitHub Desktop.
Save jdabtieu/9c46b1ca23630e657a6262d854476320 to your computer and use it in GitHub Desktop.
Enables colors in the Windows terminal for Java console programs. Read the comment before blindly copy pasting!
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.net.URLClassLoader;
public class Main {
static void enableColor() {
// https://stackoverflow.com/questions/52767585/how-can-you-use-vt100-escape-codes-in-java-on-windows
try {
// Load classes
URLClassLoader loader = new URLClassLoader(new URL[] {
new URL("https://repo1.maven.org/maven2/net/java/dev/jna/jna/5.11.0/jna-5.11.0.jar"),
new URL("https://repo1.maven.org/maven2/net/java/dev/jna/jna-platform/5.11.0/jna-platform-5.11.0.jar")});
Class<?> Function = loader.loadClass("com.sun.jna.Function");
Class<?> WinDef = loader.loadClass("com.sun.jna.platform.win32.WinDef");
Class<?> WinNT = loader.loadClass("com.sun.jna.platform.win32.WinNT");
Class<?> HANDLE = null;
Class<?> DWORD = null;
Class<?> BOOL = null;
Class<?> DWORDByReference = null;
for (Class<?> c : WinDef.getClasses()) {
if (c.getSimpleName().equals("BOOL")) BOOL = c;
else if (c.getSimpleName().equals("DWORD")) DWORD = c;
else if (c.getSimpleName().equals("DWORDByReference")) DWORDByReference = c;
}
for (Class<?> c : WinNT.getClasses()) {
if (c.getSimpleName().equals("HANDLE")) HANDLE = c;
}
Object GetStdHandleFunc = Function.getDeclaredMethod("getFunction", String.class, String.class).invoke(null, "kernel32", "GetStdHandle");
Object STD_OUTPUT_HANDLE = DWORD.getConstructor(long.class).newInstance(-11);
Object hOut = Function.getMethod("invoke", Class.class, Object[].class).invoke(GetStdHandleFunc, HANDLE, new Object[] {STD_OUTPUT_HANDLE});
Object p_dwMode = DWORDByReference.getConstructor(DWORD).newInstance(DWORD.getConstructor(long.class).newInstance(0));
Object GetConsoleModeFunc = Function.getDeclaredMethod("getFunction", String.class, String.class).invoke(null, "kernel32", "GetConsoleMode");
Function.getMethod("invoke", Class.class, Object[].class).invoke(GetConsoleModeFunc, BOOL, new Object[] {hOut, p_dwMode});
int ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4;
Object dwMode = DWORDByReference.getMethod("getValue").invoke(p_dwMode);
DWORD.getMethod("setValue", long.class).invoke(dwMode, (int) DWORD.getMethod("intValue").invoke(dwMode) | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
Object SetConsoleModeFunc = Function.getDeclaredMethod("getFunction", String.class, String.class).invoke(null, "kernel32", "SetConsoleMode");
Function.getMethod("invoke", Class.class, Object[].class).invoke(SetConsoleModeFunc, BOOL, new Object[] {hOut, dwMode});
loader.close();
} catch (IOException | ClassNotFoundException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException | InstantiationException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
enableColor();
final String ANSI_RED = "\u001B[31m";
System.out.println("Demo: " + ANSI_RED + "red");
}
}
@jdabtieu
Copy link
Author

This is a reflection implementation of https://stackoverflow.com/questions/52767585/how-can-you-use-vt100-escape-codes-in-java-on-windows. This enables a Java console program to use ANSI colors on the Windows command line, without setting VirtualTerminalLevel.

IMPORTANT: If it is possible to include additional JARs on the classpath, it is highly recommended to use the original StackOverflow code. Not only will it be faster, it also does not require internet access (to download the JARs), and has much cleaner code. However, for projects (assignments) where you are only allowed to submit one file, this can do the job.

@jdabtieu
Copy link
Author

To use: simply add the call to enableColor() anywhere before the first print statement with color. Typically, right at the start of main will work.

Demo (with color enabled):
image

Demo (without enabling color):
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment