Skip to content
This repository was archived by the owner on Jun 3, 2025. It is now read-only.

Commit 638e504

Browse files
authored
Merge pull request #285 from tmc-cli/set-props-jclc
command for setting/unsetting/viewing properties
2 parents 899227b + 67a1bee commit 638e504

18 files changed

+302
-45
lines changed

src/main/java/fi/helsinki/cs/tmc/cli/Application.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -261,12 +261,11 @@ public void setWorkdir(WorkDir workDir) {
261261

262262
public HashMap<String, String> getProperties() {
263263
// Loads properties from the global configuration file in .config/tmc-cli/
264-
return (HashMap<String, String>) this.properties.clone();
264+
return this.properties;
265265
}
266266

267-
public Boolean setProperties(HashMap<String, String> properties) {
267+
public Boolean saveProperties() {
268268
// Saves properties to the global configuration file in .config/tmc-cli/
269-
this.properties = properties;
270269
return SettingsIo.saveProperties(properties);
271270
}
272271

@@ -305,6 +304,6 @@ private void versionCheck() {
305304

306305
long timestamp = now.getTime();
307306
properties.put(previousUpdateDateKey, Long.toString(timestamp));
308-
setProperties(properties);
307+
saveProperties();
309308
}
310309
}

src/main/java/fi/helsinki/cs/tmc/cli/command/DownloadExercisesCommand.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import fi.helsinki.cs.tmc.cli.command.core.AbstractCommand;
55
import fi.helsinki.cs.tmc.cli.command.core.Command;
66
import fi.helsinki.cs.tmc.cli.io.Io;
7+
import fi.helsinki.cs.tmc.cli.io.TmcCliProgressObserver;
78
import fi.helsinki.cs.tmc.cli.tmcstuff.CourseInfo;
89
import fi.helsinki.cs.tmc.cli.tmcstuff.CourseInfoIo;
910
import fi.helsinki.cs.tmc.cli.tmcstuff.TmcUtil;
@@ -51,9 +52,8 @@ public void run(CommandLine args, Io io) {
5152
io.println("Course doesn't exist.");
5253
return;
5354
}
54-
55-
List<Exercise> exercises = TmcUtil.downloadAllExercises(core, course);
56-
io.println("");
55+
TmcCliProgressObserver progobs = new TmcCliProgressObserver(io);
56+
List<Exercise> exercises = TmcUtil.downloadAllExercises(core, course, progobs);
5757
io.println(exercises.toString());
5858

5959
Path configFile = app.getWorkDir().getWorkingDirectory()

src/main/java/fi/helsinki/cs/tmc/cli/command/LoginCommand.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public void run(CommandLine args, Io io) {
4242

4343
Settings settings = new Settings(serverAddress, username, password);
4444
if (loginPossible(settings) && saveLoginSettings(settings)) {
45-
io.println("Login succesful.");
45+
io.println("Login successful.");
4646
}
4747
}
4848

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package fi.helsinki.cs.tmc.cli.command;
2+
3+
import fi.helsinki.cs.tmc.cli.command.core.AbstractCommand;
4+
import fi.helsinki.cs.tmc.cli.command.core.Command;
5+
import fi.helsinki.cs.tmc.cli.io.Io;
6+
7+
import org.apache.commons.cli.CommandLine;
8+
import org.apache.commons.cli.Options;
9+
import org.slf4j.Logger;
10+
import org.slf4j.LoggerFactory;
11+
12+
import java.util.HashMap;
13+
import java.util.Iterator;
14+
import java.util.List;
15+
16+
@Command(name = "prop", desc = "Set/unset TMC-CLI properties")
17+
public class PropertiesCommand extends AbstractCommand {
18+
19+
private static final Logger logger
20+
= LoggerFactory.getLogger(PropertiesCommand.class);
21+
private Io io;
22+
23+
@Override
24+
public void getOptions(Options options) {
25+
options.addOption("u", "unset", false, "Unset given property keys");
26+
}
27+
28+
@Override
29+
public void run(CommandLine args, Io io) {
30+
this.io = io;
31+
Boolean unset = args.hasOption("u");
32+
List<String> arguments = args.getArgList();
33+
HashMap<String, String> props = getApp().getProperties();
34+
if (arguments.isEmpty()) {
35+
printAllProps(props);
36+
return;
37+
}
38+
39+
if (arguments.size() % 2 == 1 && !unset) {
40+
io.println("Invalid argument count. Usage: tmc prop KEY VALUE ...");
41+
return;
42+
}
43+
44+
if (unset) {
45+
if (arguments.size() > 1) {
46+
io.print("Unsetting property keys:");
47+
for (String arg : arguments) {
48+
io.print(" " + arg);
49+
}
50+
io.println("");
51+
if (!io.readConfirmation("Are you sure?", true)) {
52+
return;
53+
}
54+
}
55+
for (String key : arguments) {
56+
io.println("Unset key " + key + ", was " + props.remove(key));
57+
}
58+
getApp().saveProperties();
59+
return;
60+
} else {
61+
if (arguments.size() > 2) {
62+
io.print("Setting property keys:");
63+
for (int i = 0; i < arguments.size(); i = i + 2) {
64+
io.print(" " + arguments.get(i) + "=>" + arguments.get(i + 1));
65+
}
66+
io.println("");
67+
if (!io.readConfirmation("Are you sure?", true)) {
68+
return;
69+
}
70+
}
71+
for (int i = 0; i < arguments.size(); i = i + 2) {
72+
String last = props.put(arguments.get(i), arguments.get(i + 1));
73+
io.println("Set " + arguments.get(i) + "=>" + arguments.get(i + 1)
74+
+ ", was " + last);
75+
}
76+
getApp().saveProperties();
77+
return;
78+
}
79+
}
80+
81+
private void printAllProps(HashMap<String, String> props) {
82+
int longest = longestKey(props);
83+
io.println("TMC-CLI properties:");
84+
StringBuilder sb = new StringBuilder();
85+
sb.append("<KEY> ");
86+
for (int i = 7; i < longest + 1; i++) {
87+
sb.append(" ");
88+
}
89+
sb.append("<VALUE>");
90+
io.println(sb.toString());
91+
92+
for (String key : props.keySet()) {
93+
sb = new StringBuilder();
94+
sb.append(key + ":");
95+
for (int i = key.length() + 1; i < Math.max(longest + 1, 7); i++) {
96+
sb.append(" ");
97+
}
98+
sb.append(props.get(key));
99+
io.println(sb.toString());
100+
}
101+
}
102+
103+
private int longestKey(HashMap<String, String> props) {
104+
int longest = 0;
105+
Iterator iterator = props.keySet().iterator();
106+
while (iterator.hasNext()) {
107+
String key = (String) iterator.next();
108+
longest = Math.max(longest, key.length());
109+
}
110+
return longest;
111+
}
112+
}

src/main/java/fi/helsinki/cs/tmc/cli/command/RunTestsCommand.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public class RunTestsCommand extends AbstractCommand {
3131
private static final Logger logger
3232
= LoggerFactory.getLogger(RunTestsCommand.class);
3333

34-
private Io io;
34+
// private Io io;
3535
private boolean showPassed;
3636
private boolean showDetails;
3737

@@ -43,7 +43,7 @@ public void getOptions(Options options) {
4343

4444
@Override
4545
public void run(CommandLine args, Io io) {
46-
this.io = io;
46+
// this.io = io;
4747

4848
List<String> exercisesFromArgs = parseArgs(args);
4949
if (exercisesFromArgs == null) {
@@ -89,13 +89,17 @@ public void run(CommandLine args, Io io) {
8989
//name = name.replace("-", File.separator);
9090
Exercise exercise = new Exercise(name, courseName);
9191

92-
runResult = core.runTests(ProgressObserver.NULL_OBSERVER, exercise).call();
92+
TmcCliProgressObserver progobs = new TmcCliProgressObserver(io);
93+
runResult = core.runTests(progobs, exercise).call();
94+
progobs.end(0);
95+
9396
resultPrinter.printRunResult(runResult, isOnlyExercise);
9497
total += runResult.testResults.size();
9598
passed += ResultPrinter.passedTests(runResult.testResults);
9699
}
97100
if (total > 0 && !isOnlyExercise) {
98101
// Print a progress bar showing how the ratio of passed exercises
102+
// But only if more than one exercise was tested
99103
io.println("");
100104
io.println("Total tests passed: " + passed + "/" + total);
101105
io.println(TmcCliProgressObserver.getPassedTestsBar(passed, total));

src/main/java/fi/helsinki/cs/tmc/cli/command/TestCommand.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package fi.helsinki.cs.tmc.cli.command;
22

3-
import fi.helsinki.cs.tmc.cli.Application;
43
import fi.helsinki.cs.tmc.cli.command.core.AbstractCommand;
54
import fi.helsinki.cs.tmc.cli.command.core.Command;
65
import fi.helsinki.cs.tmc.cli.io.Color;
@@ -43,7 +42,7 @@ public void run(CommandLine args, Io io) {
4342
HashMap<String, String> props = getApp().getProperties();
4443
io.println(props.toString());
4544
props.put(args.getOptionValue("p"), "stupid");
46-
getApp().setProperties(props);
45+
getApp().saveProperties();
4746
} else {
4847
io.println("Let's run easter egg.");
4948
}

src/main/java/fi/helsinki/cs/tmc/cli/command/UpdateCommand.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import fi.helsinki.cs.tmc.cli.command.core.AbstractCommand;
44
import fi.helsinki.cs.tmc.cli.command.core.Command;
55
import fi.helsinki.cs.tmc.cli.io.Io;
6+
import fi.helsinki.cs.tmc.cli.io.TmcCliProgressObserver;
67
import fi.helsinki.cs.tmc.cli.tmcstuff.CourseInfo;
78
import fi.helsinki.cs.tmc.cli.tmcstuff.CourseInfoIo;
89
import fi.helsinki.cs.tmc.cli.tmcstuff.ExerciseUpdater;
@@ -64,7 +65,8 @@ public void updateExercises(TmcCore core, CourseInfo info, Path configFile) {
6465
printExercises(exerciseUpdater.getUpdatedExercises(), "Modified exercises:");
6566
io.println("");
6667

67-
List<Exercise> downloaded = exerciseUpdater.downloadUpdates();
68+
List<Exercise> downloaded = exerciseUpdater.downloadUpdates(
69+
new TmcCliProgressObserver(io));
6870
if (downloaded.isEmpty()) {
6971
io.println("Failed to download exercises");
7072
return;

src/main/java/fi/helsinki/cs/tmc/cli/io/Io.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ public void println(String str) {
1818

1919
public abstract String readLine(String prompt);
2020

21+
public abstract Boolean readConfirmation(String prompt, Boolean defaultToYes);
22+
2123
public abstract String readPassword(String prompt);
2224

2325
@Override

src/main/java/fi/helsinki/cs/tmc/cli/io/TerminalIo.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,30 @@ public String readLine(String prompt) {
2525
}
2626
}
2727

28+
@Override
29+
public Boolean readConfirmation(String prompt, Boolean defaultToYes) {
30+
String yesNo;
31+
String input;
32+
if (defaultToYes) {
33+
yesNo = " [Y/n] ";
34+
} else {
35+
yesNo = " [y/N] ";
36+
}
37+
System.out.print(prompt + yesNo);
38+
try {
39+
input = new Scanner(System.in).nextLine().toLowerCase();
40+
} catch (Exception e) {
41+
logger.warn("Line could not be read.", e);
42+
return null;
43+
}
44+
if (input.equals("y")) {
45+
return true;
46+
} else if (input.equals("n")) {
47+
return false;
48+
}
49+
return defaultToYes;
50+
}
51+
2852
@Override
2953
public String readPassword(String prompt) {
3054
if (System.console() != null) {

src/main/java/fi/helsinki/cs/tmc/cli/io/TmcCliProgressObserver.java

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@
66
* Created by jclakkis on 27.5.2016.
77
*/
88
public class TmcCliProgressObserver extends ProgressObserver {
9-
protected static final char PIPCHAR = '#';
10-
protected static final char EMPTYCHAR = ' ';
9+
protected static final char PIPCHAR = '';
10+
protected static final char EMPTYCHAR = '';
1111
protected static final char BARLEFT = '[';
1212
protected static final char BARRIGHT = ']';
1313

1414
protected Io io;
1515
private int pips;
1616
protected int maxline;
17-
private Color.AnsiColor color;
17+
private Color.AnsiColor color1;
18+
private Color.AnsiColor color2;
1819
protected String lastMessage;
1920
protected Boolean hasProgressBar;
2021

@@ -23,15 +24,16 @@ public TmcCliProgressObserver() {
2324
}
2425

2526
public TmcCliProgressObserver(Io io) {
26-
this(io, Color.AnsiColor.ANSI_CYAN);
27+
this(io, Color.AnsiColor.ANSI_CYAN, Color.AnsiColor.ANSI_CYAN);
2728
}
2829

29-
public TmcCliProgressObserver(Io io, Color.AnsiColor color) {
30+
public TmcCliProgressObserver(Io io, Color.AnsiColor color1, Color.AnsiColor color2) {
3031
this.hasProgressBar = false;
3132
this.io = io;
3233
this.maxline = getMaxline();
3334
this.pips = this.maxline - 6;
34-
this.color = color;
35+
this.color1 = color1;
36+
this.color2 = color2;
3537
}
3638

3739
// Clearly this is not the best place for this function
@@ -64,7 +66,7 @@ public void progress(long id, Double progress, String message) {
6466
lastMessage = message;
6567
io.println("");
6668
}
67-
this.io.print("\r" + this.progressBar(progress, this.maxline, this.color));
69+
this.io.print("\r" + this.progressBar(progress, this.maxline, this.color1, this.color2));
6870
}
6971

7072
protected void printMessage(String message) {
@@ -81,8 +83,11 @@ public void start(long id) {
8183
public void end(long id) {
8284
// Most likely not going to be used
8385
if (this.hasProgressBar) {
84-
this.io.println("\r" + this.percentage(1.0)
85-
+ this.progressBar(1.0, this.pips, this.color));
86+
this.io.print("\r");
87+
flush(this.maxline);
88+
this.io.print("\r");
89+
// this.io.println("\r" + this.percentage(1.0)
90+
// + this.progressBar(1.0, this.pips, this.color1, this.color2));
8691
} else {
8792
this.io.println("");
8893
}
@@ -108,10 +113,17 @@ protected void flush(int length) {
108113
io.print(sb);
109114
}
110115

111-
public static String progressBar(double progress, int length, Color.AnsiColor color) {
116+
public static String progressBar(double progress, int length,
117+
Color.AnsiColor color) {
112118
return progressBar(progress, length, color, color, BARLEFT, BARRIGHT, PIPCHAR, EMPTYCHAR);
113119
}
114120

121+
public static String progressBar(double progress, int length,
122+
Color.AnsiColor color1, Color.AnsiColor color2) {
123+
return progressBar(progress, length, color1, color2,
124+
BARLEFT, BARRIGHT, PIPCHAR, EMPTYCHAR);
125+
}
126+
115127
public static String progressBar(
116128
double progress,
117129
int length,
@@ -156,7 +168,7 @@ public static String getPassedTestsBar(int passed, int total) {
156168
TmcCliProgressObserver.getMaxline(),
157169
Color.AnsiColor.ANSI_GREEN,
158170
Color.AnsiColor.ANSI_RED,
159-
'[', ']', '#', '-'
171+
'[', ']', '', ''
160172
);
161173
}
162174
}

0 commit comments

Comments
 (0)