From 7084534dc0652dd1bb78eec38907c0cef814397f Mon Sep 17 00:00:00 2001 From: Oondanomala <87101222+Oondanomala@users.noreply.github.com> Date: Fri, 6 Feb 2026 03:22:20 +0100 Subject: [PATCH 1/4] Support jline.jansi alongside fusesource.jansi --- src/main/java/picocli/CommandLine.java | 33 ++++++++++++++++++-------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/main/java/picocli/CommandLine.java b/src/main/java/picocli/CommandLine.java index 7857e4ed6..bf79a0135 100644 --- a/src/main/java/picocli/CommandLine.java +++ b/src/main/java/picocli/CommandLine.java @@ -17954,29 +17954,42 @@ static boolean isJansiConsoleInstalled() { if (jansiInstalled == null) { jansiInstalled = calcIsJansiConsoleInstalled(); } return jansiInstalled; } - /** Returns {@code false} if system property {@code org.fusesource.jansi.Ansi.disable} is set to {@code "true"} - * (case-insensitive); otherwise, returns {@code false} if the Jansi library is in the classpath but has been disabled - * (either via system property {@code org.fusesource.jansi.Ansi.disable} or via a Jansi API call); + /** Returns {@code false} if either system properties {@code org.fusesource.jansi.Ansi.disable} + * or {@code org.jline.jansi.Ansi.disable} are set to {@code "true"} (case-insensitive); + * otherwise, returns {@code false} if the Jansi library is in the classpath but has been disabled + * (either via the aforementioned system properties or via a Jansi API call); * otherwise, returns {@code true} if the Jansi library is in the classpath and has been installed. */ static boolean calcIsJansiConsoleInstalled() { try { // first check if JANSI was explicitly disabled _without loading any JANSI classes_: // see https://github.com/remkop/picocli/issues/1106 - if (Boolean.getBoolean("org.fusesource.jansi.Ansi.disable")) { + if (Boolean.getBoolean("org.jline.jansi.Ansi.disable") || + Boolean.getBoolean("org.fusesource.jansi.Ansi.disable")) { return false; } - // the Ansi class internally also checks system property "org.fusesource.jansi.Ansi.disable" + // the Ansi class internally also checks system property "org.jline.jansi.Ansi.disable" // but may also have been set with Ansi.setEnabled or a custom detector - Class ansi = Class.forName("org.fusesource.jansi.Ansi"); + Class ansi; + try { + // Try to support both the original jansi library and the newer jline jansi + ansi = Class.forName("org.fusesource.jansi.Ansi"); + } catch (ClassNotFoundException e) { + ansi = Class.forName("org.jline.jansi.Ansi"); + } Boolean enabled = (Boolean) ansi.getDeclaredMethod("isEnabled").invoke(null); if (!enabled) { return false; } - // loading this class will load the native library org.fusesource.jansi.internal.CLibrary - Class ansiConsole = Class.forName("org.fusesource.jansi.AnsiConsole"); - Field out = ansiConsole.getField("out"); - return out.get(null) == System.out; + // loading this class will load the native library org.jline.jansi.internal.CLibrary + Class ansiConsole; + try { + ansiConsole = Class.forName("org.fusesource.jansi.AnsiConsole"); + } catch (ClassNotFoundException e) { + ansiConsole = Class.forName("org.jline.jansi.AnsiConsole"); + } + Object out = ansiConsole.getDeclaredMethod("out").invoke(null); + return out == System.out; } catch (Exception reflectionFailed) { return false; } From a9d3c2192f4081b09aca10a75dc1c7abf10a0470 Mon Sep 17 00:00:00 2001 From: Oondanomala <87101222+Oondanomala@users.noreply.github.com> Date: Fri, 6 Feb 2026 19:45:27 +0100 Subject: [PATCH 2/4] Replace out() method call with isInstalled() as out() also initializes things This was added in Jansi 2.1.0, which is hopefully old enough (6 years ago). --- src/main/java/picocli/CommandLine.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/picocli/CommandLine.java b/src/main/java/picocli/CommandLine.java index bf79a0135..7ddebd066 100644 --- a/src/main/java/picocli/CommandLine.java +++ b/src/main/java/picocli/CommandLine.java @@ -17988,8 +17988,7 @@ static boolean calcIsJansiConsoleInstalled() { } catch (ClassNotFoundException e) { ansiConsole = Class.forName("org.jline.jansi.AnsiConsole"); } - Object out = ansiConsole.getDeclaredMethod("out").invoke(null); - return out == System.out; + return (Boolean) ansiConsole.getDeclaredMethod("isInstalled").invoke(null); } catch (Exception reflectionFailed) { return false; } From f7b2dc08b60ecb42723b8ccbf56d42ff872eb1e6 Mon Sep 17 00:00:00 2001 From: Oondanomala <87101222+Oondanomala@users.noreply.github.com> Date: Tue, 24 Feb 2026 23:31:23 +0100 Subject: [PATCH 3/4] Keep support for old Jansi Turns out the tests depend on Jansi 1.15 to keep Java 5 support, so this is in fact wanted --- src/main/java/picocli/CommandLine.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/picocli/CommandLine.java b/src/main/java/picocli/CommandLine.java index 7ddebd066..94bd48b99 100644 --- a/src/main/java/picocli/CommandLine.java +++ b/src/main/java/picocli/CommandLine.java @@ -17988,7 +17988,13 @@ static boolean calcIsJansiConsoleInstalled() { } catch (ClassNotFoundException e) { ansiConsole = Class.forName("org.jline.jansi.AnsiConsole"); } - return (Boolean) ansiConsole.getDeclaredMethod("isInstalled").invoke(null); + try { + return (Boolean) ansiConsole.getDeclaredMethod("isInstalled").invoke(null); + } catch (ReflectiveOperationException e) { + // isInstalled was "only" added in 2.1.0, try to support older jansi + Field out = ansiConsole.getField("out"); + return out.get(null) == System.out; + } } catch (Exception reflectionFailed) { return false; } From 10850ebf5ea4d514bba3ff5212c1647c38e99691 Mon Sep 17 00:00:00 2001 From: Oondanomala <87101222+Oondanomala@users.noreply.github.com> Date: Wed, 25 Feb 2026 00:32:39 +0100 Subject: [PATCH 4/4] No ReflectiveOperationException in Java 5-6 Great --- src/main/java/picocli/CommandLine.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/picocli/CommandLine.java b/src/main/java/picocli/CommandLine.java index 94bd48b99..adb789224 100644 --- a/src/main/java/picocli/CommandLine.java +++ b/src/main/java/picocli/CommandLine.java @@ -17990,7 +17990,7 @@ static boolean calcIsJansiConsoleInstalled() { } try { return (Boolean) ansiConsole.getDeclaredMethod("isInstalled").invoke(null); - } catch (ReflectiveOperationException e) { + } catch (Exception e) { // isInstalled was "only" added in 2.1.0, try to support older jansi Field out = ansiConsole.getField("out"); return out.get(null) == System.out;