Skip to content

Commit 56d6be5

Browse files
committed
Change the ansi support detection to return true for Windows 10+
1 parent bd663c1 commit 56d6be5

File tree

2 files changed

+69
-3
lines changed

2 files changed

+69
-3
lines changed

core/spring-boot/src/main/java/org/springframework/boot/ansi/AnsiOutput.java

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
*
3232
* @author Phillip Webb
3333
* @author Yong-Hyun Kim
34+
* @author Philemon Hilscher
3435
* @since 1.0.0
3536
*/
3637
public abstract class AnsiOutput {
@@ -43,8 +44,6 @@ public abstract class AnsiOutput {
4344

4445
private static @Nullable Boolean ansiCapable;
4546

46-
private static final String OPERATING_SYSTEM_NAME = System.getProperty("os.name").toLowerCase(Locale.ENGLISH);
47-
4847
private static final String ENCODE_START = "\033[";
4948

5049
private static final String ENCODE_END = "m";
@@ -171,13 +170,35 @@ private static boolean detectIfAnsiCapable() {
171170
}
172171
}
173172
}
174-
return !(OPERATING_SYSTEM_NAME.contains("win"));
173+
if (isWindows(System.getProperty("os.name"))) {
174+
return isWindowsAnsiCapable(System.getProperty("os.version"));
175+
}
176+
return true;
175177
}
176178
catch (Throwable ex) {
177179
return false;
178180
}
179181
}
180182

183+
static boolean isWindows(String osName) {
184+
return osName.toLowerCase(Locale.ENGLISH).contains("win");
185+
}
186+
187+
static boolean isWindowsAnsiCapable(String osVersion) {
188+
String[] parts = osVersion.split("\\.");
189+
if (parts.length >= 2) {
190+
try {
191+
int major = Integer.parseInt(parts[0]);
192+
int minor = Integer.parseInt(parts[1]);
193+
// ANSI support on Windows 10 = 10.0, Build 10586+
194+
return (major > 10) || (major == 10 && minor >= 0);
195+
} catch (NumberFormatException ex) {
196+
return false;
197+
}
198+
}
199+
return false;
200+
}
201+
181202
/**
182203
* Possible values to pass to {@link AnsiOutput#setEnabled}. Determines when to output
183204
* ANSI escape sequences for coloring application output.

core/spring-boot/src/test/java/org/springframework/boot/ansi/AnsiOutputTests.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,25 @@
1616

1717
package org.springframework.boot.ansi;
1818

19+
import java.util.stream.Stream;
20+
1921
import org.junit.jupiter.api.AfterAll;
2022
import org.junit.jupiter.api.BeforeAll;
2123
import org.junit.jupiter.api.Test;
24+
import org.junit.jupiter.params.ParameterizedTest;
25+
import org.junit.jupiter.params.provider.Arguments;
26+
import org.junit.jupiter.params.provider.MethodSource;
2227

2328
import org.springframework.boot.ansi.AnsiOutput.Enabled;
2429

2530
import static org.assertj.core.api.Assertions.assertThat;
31+
import static org.junit.jupiter.api.Assertions.assertEquals;
2632

2733
/**
2834
* Tests for {@link AnsiOutput}.
2935
*
3036
* @author Phillip Webb
37+
* @author Philemon Hilscher
3138
*/
3239
class AnsiOutputTests {
3340

@@ -48,4 +55,42 @@ void encoding() {
4855
assertThat(encoded).isEqualTo("ABDEF");
4956
}
5057

58+
private static Stream<Arguments> provideOsNames() {
59+
return Stream.of(
60+
Arguments.of("", false),
61+
Arguments.of("Windows 7", true),
62+
Arguments.of("Windows 8", true),
63+
Arguments.of("Windows 8.1", true),
64+
Arguments.of("Windows 10", true),
65+
Arguments.of("Windows 11", true),
66+
Arguments.of("Linux", false),
67+
Arguments.of("Mac OS X", false),
68+
Arguments.of("Mac OS", false)
69+
);
70+
}
71+
72+
@ParameterizedTest
73+
@MethodSource("provideOsNames")
74+
void testDetectIfIsWindows(String osName, boolean expected) {
75+
boolean actual = AnsiOutput.isWindows(osName);
76+
assertEquals(expected, actual);
77+
}
78+
79+
private static Stream<Arguments> provideOsVersionNumbers() {
80+
return Stream.of(
81+
Arguments.of("", false),
82+
Arguments.of("6.1", false), // Windows 7 / Server 2008 R2
83+
Arguments.of("6.2", false), // Windows 8 / Server 2012
84+
Arguments.of("6.3", false), // Windows 8.1 / Server 2012 R2
85+
Arguments.of("10.0", true) // Windows 10 / 11 / Server 2016+
86+
);
87+
}
88+
89+
@ParameterizedTest
90+
@MethodSource("provideOsVersionNumbers")
91+
void testDetectIfIsWindowsAnsiCapable(String osVersion, boolean expected) {
92+
boolean actual = AnsiOutput.isWindowsAnsiCapable(osVersion);
93+
assertEquals(expected, actual);
94+
}
95+
5196
}

0 commit comments

Comments
 (0)