Skip to content

Commit 79c7f0a

Browse files
committed
promptForExclusions allows range selection
1 parent 30e9a32 commit 79c7f0a

File tree

2 files changed

+58
-19
lines changed

2 files changed

+58
-19
lines changed

src/main/java/cf/maybelambda/fedora/ConsoleIOHelper.java

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ public class ConsoleIOHelper {
1414
static final String GREEN = "\u001B[32m";
1515
static final String RED = "\u001B[31m";
1616
static final String BLUE = "\u001B[34m";
17+
private static final String EXCLUDE_PROMPT = "Type in the number and/or range of numbers of packages to exclude "
18+
+ "(comma-separated, i.e. 2,3,5..9)\nor press Enter to keep all: ";
1719

1820
static boolean confirm(Scanner scanner, String prompt) {
1921
System.out.print(prompt + " [y/N]: ");
@@ -25,32 +27,42 @@ static List<String> promptForExclusions(List<String> packages, Scanner scanner)
2527
for (int i = 0; i < packages.size(); i++) {
2628
System.out.printf("%2d. %s\n", i + 1, packages.get(i));
2729
}
28-
System.out.print("Enter the numbers of any packages to exclude (comma-separated), or press Enter to keep all: ");
30+
System.out.print(EXCLUDE_PROMPT);
2931

3032
String excludeInput = scanner.nextLine().trim();
31-
String validInputRE = "^$|^\\d+$|^(\\d+,)+\\d$";
33+
String validInputRE = "^$|^(\\d+|\\d+\\.\\.\\d+)(,(\\d+|\\d+\\.\\.\\d+))*$";
3234
if (!excludeInput.matches(validInputRE)) {
3335
throw new RuntimeException("Invalid selection");
3436
}
3537

3638
Set<Integer> excludeIndexes = new HashSet<>();
37-
if (!excludeInput.isEmpty()) {
38-
for (String part : excludeInput.split(",")) {
39-
try {
40-
int idx = Integer.parseInt(part.trim());
41-
if (idx >= 1 && idx <= packages.size()) {
42-
excludeIndexes.add(idx - 1);
39+
for (String part : excludeInput.split(",")) {
40+
if (excludeInput.isEmpty()) {
41+
break;
42+
}
43+
if (part.contains("..")) {
44+
String[] limits = part.split("\\.\\.");
45+
int s = Integer.parseInt(limits[0]);
46+
int e = Integer.parseInt(limits[1]);
47+
if (s >= 1 && e <= packages.size()) {
48+
for (int i = s; i <= e; i++) {
49+
excludeIndexes.add(i - 1);
4350
}
44-
} catch (NumberFormatException ignored) {}
51+
}
52+
} else {
53+
int idx = Integer.parseInt(part.trim());
54+
if (idx >= 1 && idx <= packages.size()) {
55+
excludeIndexes.add(idx - 1);
56+
}
4557
}
4658
}
59+
4760
List<String> filtered = new ArrayList<>();
4861
for (int i = 0; i < packages.size(); i++) {
4962
if (!excludeIndexes.contains(i)) {
5063
filtered.add(packages.get(i));
5164
}
5265
}
53-
5466
return filtered;
5567
}
5668

src/test/java/cf/maybelambda/fedora/ConsoleIOHelperTests.java

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -74,32 +74,59 @@ void promptForExclusionsKeepsAllWhenInputIsEmpty() {
7474
@Test
7575
void promptForExclusionsRemovesSome() {
7676
List<String> pkgs = List.of("nano", "vim", "htop", "curl");
77-
Scanner scanner = new Scanner(new ByteArrayInputStream("2,4\n".getBytes(StandardCharsets.UTF_8)));
77+
Scanner scanner = mock(Scanner.class);
78+
when(scanner.nextLine()).thenReturn("2,4\n");
7879

7980
List<String> result = promptForExclusions(pkgs, scanner);
8081

8182
assertEquals(List.of("nano", "htop"), result);
83+
84+
when(scanner.nextLine()).thenReturn("4\n");
85+
result = promptForExclusions(pkgs, scanner);
86+
assertEquals(List.of("nano", "vim", "htop"), result);
87+
88+
when(scanner.nextLine()).thenReturn("1,3..4\n");
89+
result = promptForExclusions(pkgs, scanner);
90+
assertEquals(List.of("vim"), result);
91+
92+
when(scanner.nextLine()).thenReturn("1..3\n");
93+
result = promptForExclusions(pkgs, scanner);
94+
assertEquals(List.of("curl"), result);
95+
96+
when(scanner.nextLine()).thenReturn("3..4,2\n");
97+
result = promptForExclusions(pkgs, scanner);
98+
assertEquals(List.of("nano"), result);
8299
}
83100

84101
@Test
85102
void promptForExclusionsHandlesInvalidIndexes() {
86103
List<String> pkgs = List.of("pkg1", "pkg2", "pkg3");
87-
Scanner scanner = new Scanner(new ByteArrayInputStream("0,5,2\n".getBytes(StandardCharsets.UTF_8)));
104+
Scanner scanner = mock(Scanner.class);
105+
when(scanner.nextLine()).thenReturn("0,5,2\n");
88106

89107
List<String> result = promptForExclusions(pkgs, scanner);
90108

91109
assertEquals(List.of("pkg1", "pkg3"), result);
110+
111+
when(scanner.nextLine()).thenReturn("0..1\n");
112+
result = promptForExclusions(pkgs, scanner);
113+
assertEquals(pkgs, result);
114+
115+
when(scanner.nextLine()).thenReturn("1..99\n");
116+
result = promptForExclusions(pkgs, scanner);
117+
assertEquals(pkgs, result);
92118
}
93119

94120
@ParameterizedTest
95121
@ValueSource(strings = {
96-
"1,,3", // multiple consecutive commas
97-
"1,3,", // trailing comma
98-
",1,3", // leading comma
99-
"1a,2", // invalid characters mixed with valid numbers
100-
"1,abc,2", // non-numeric characters
101-
"qwerty", // completely non-numeric input
102-
"!@#, $%^, &*()" // special characters
122+
"1,,3", // multiple consecutive commas
123+
"1,3,", // trailing comma
124+
",1,3", // leading comma
125+
"1a,2", "3, 5", // invalid characters mixed with valid numbers
126+
"1,abc,2", // non-numeric characters
127+
"qwerty", // completely non-numeric input
128+
"!@#, $%^, &*()", // special characters
129+
"1.54", "1...54", "6.-.12" // malformed range
103130
})
104131
void promptForExclusionsThrowsRuntimeExceptionWhenInvalidInputRead(String input) {
105132
List<String> pkgs = List.of("pkg");

0 commit comments

Comments
 (0)