Last active
March 28, 2022 03:33
-
-
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!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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):
Demo (without enabling color):