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

Commit eaf3eef

Browse files
author
Aleksi Salmela
committed
Print proper usage messages for commands.
1 parent c235ac4 commit eaf3eef

11 files changed

Lines changed: 154 additions & 18 deletions

File tree

src/main/java/fi/helsinki/cs/tmc/cli/backend/TmcUtil.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,6 @@ public static URI sendPaste(CliContext ctx, Exercise exercise, String message) {
172172
} catch (Exception e) {
173173
TmcUtil.handleTmcExceptions(ctx, e);
174174
logger.error("Failed to send paste", e);
175-
ctx.getIo().println(e.toString());
176175
return null;
177176
}
178177
}
@@ -238,6 +237,7 @@ protected static void handleTmcExceptions(CliContext ctx, Exception exception) {
238237
return;
239238
}
240239
logger.error("Command failed in tmc-core", exception);
240+
//TODO we seem to write twice error message; here and in the commands.
241241
io.errorln("Command failed in tmc-core, check tmc-cli.log file for more info");
242242
}
243243

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ public class DownloadExercisesCommand extends AbstractCommand {
2727
private CliContext ctx;
2828
private boolean showAll;
2929

30+
@Override
31+
public String[] getUsages() {
32+
return new String[] {"[-a] COURSE"};
33+
}
34+
3035
@Override
3136
public void getOptions(Options options) {
3237
options.addOption("a", "all", false,
@@ -44,7 +49,7 @@ public void run(CliContext context, CommandLine args) {
4449
String[] stringArgs = args.getArgs();
4550
if (stringArgs.length == 0 || stringArgs.length > 1) {
4651
io.errorln("You must give a course name as an argument.");
47-
io.errorln("Usage: tmc download COURSE");
52+
printUsage(ctx);
4853
return;
4954
}
5055

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ public class InfoCommand extends AbstractCommand {
3131
private boolean fetchFromInternet;
3232
private boolean showAll;
3333

34+
@Override
35+
public String[] getUsages() {
36+
return new String[] {"[-a] [-i] COURSE-OR-EXERSICE"};
37+
}
38+
3439
@Override
3540
public void getOptions(Options options) {
3641
options.addOption("a", "all", false, "Show all information for a specific course");
@@ -55,6 +60,7 @@ public void run(CliContext context, CommandLine args) {
5560
if (fetchFromInternet) {
5661
if (useWorkingDirectory) {
5762
io.errorln("You must give a course as an argument.");
63+
printUsage(ctx);
5864
return;
5965
}
6066
String courseName = stringArgs[0];
@@ -83,6 +89,7 @@ private void printLocalInfo(String[] stringArgs) {
8389
io.errorln("You have to be in a course directory"
8490
+ " or use the -i option with the course name "
8591
+ "to get the information from the server.");
92+
printUsage(ctx);
8693
return;
8794
}
8895

@@ -97,6 +104,7 @@ private void printLocalInfo(String[] stringArgs) {
97104
} else {
98105
if (stringArgs.length != 1) {
99106
io.errorln("You can only give one path for this command.");
107+
printUsage(ctx);
100108
return;
101109
}
102110
String path = stringArgs[0];
@@ -120,6 +128,7 @@ private void printInfoFromParameters(String pathName) {
120128
io.errorln("Not a course directory. ");
121129
io.errorln("Use the -i option to get course from "
122130
+ "server.");
131+
printUsage(ctx);
123132
}
124133
}
125134

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ public class ListExercisesCommand extends AbstractCommand {
2626
private CliContext ctx;
2727
private Io io;
2828

29+
@Override
30+
public String[] getUsages() {
31+
return new String[] {"[-n] [-i] COURSE"};
32+
}
33+
2934
@Override
3035
public void getOptions(Options options) {
3136
options.addOption("n", "no-pager", false, "Don't use a pager to list the exercises");
@@ -141,6 +146,7 @@ private String getExercisesAsString(String courseName, List<Exercise> exercises)
141146
return sb.toString();
142147
}
143148

149+
//TODO duplicate code existed in info command!!!!!!!
144150
private String getDeadline(Exercise exercise) {
145151
String deadline = exercise.getDeadline();
146152
if (deadline == null) {

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ public class LoginCommand extends AbstractCommand {
2323
private String username;
2424
private String password;
2525

26+
@Override
27+
public String[] getUsages() {
28+
return new String[] {"[-u=USERNAME] [-p=PASSWORD] [-s=SERVER_ADDRESS]"};
29+
}
30+
2631
@Override
2732
public void getOptions(Options options) {
2833
options.addOption("u", "user", true, "TMC username");
@@ -35,6 +40,12 @@ public void run(CliContext context, CommandLine args) {
3540
this.ctx = context;
3641
this.io = ctx.getIo();
3742

43+
if(args.getArgs().length > 0) {
44+
io.errorln("Login doesn't take any arguments.");
45+
printUsage(context);
46+
return;
47+
}
48+
3849
if (!ctx.loadBackendWithoutLogin()) {
3950
return;
4051
}

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import fi.helsinki.cs.tmc.cli.core.AbstractCommand;
55
import fi.helsinki.cs.tmc.cli.core.CliContext;
66
import fi.helsinki.cs.tmc.cli.core.Command;
7+
import fi.helsinki.cs.tmc.cli.io.Io;
78

89
import org.apache.commons.cli.CommandLine;
910
import org.apache.commons.cli.Options;
@@ -17,7 +18,14 @@ public void getOptions(Options options) {
1718

1819
@Override
1920
public void run(CliContext context, CommandLine args) {
21+
Io io = context.getIo();
22+
if(args.getArgs().length > 0) {
23+
io.errorln("Logout doesn't take any arguments.");
24+
printUsage(context);
25+
return;
26+
}
27+
2028
SettingsIo.delete();
21-
context.getIo().println("Logged out.");
29+
io.println("Logged out.");
2230
}
2331
}

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

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public void run(CliContext context, CommandLine args) {
6464
return;
6565
}
6666

67-
String message;
67+
String message = "";
6868
if (!args.hasOption("n")) {
6969
if (args.hasOption("m")) {
7070
message = args.getOptionValue("m");
@@ -77,11 +77,7 @@ public void run(CliContext context, CommandLine args) {
7777
+ "# Lines beginning with # are comments and will be ignored.",
7878
"tmc-paste-message",
7979
true);
80-
} else {
81-
message = "";
8280
}
83-
} else {
84-
message = "";
8581
}
8682

8783
String exerciseName = exercisenames.get(0);

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ public class PropertiesCommand extends AbstractCommand {
2121
= LoggerFactory.getLogger(PropertiesCommand.class);
2222
private Io io;
2323

24+
@Override
25+
public String[] getUsages() {
26+
return new String[] {"KEY VALUE ..."};
27+
}
28+
2429
@Override
2530
public void getOptions(Options options) {
2631
options.addOption("u", "unset", false, "Unset given property keys");
@@ -40,7 +45,8 @@ public void run(CliContext context, CommandLine args) {
4045
}
4146

4247
if (arguments.length % 2 == 1 && !unset) {
43-
io.errorln("Invalid argument count. Usage: tmc prop KEY VALUE ...");
48+
io.errorln("Invalid argument count.");
49+
printUsage(ctx);
4450
return;
4551
}
4652

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public void run(CliContext context, CommandLine args) {
3737

3838
if (stringArgs.length > 0) {
3939
io.errorln("Use in the course directory");
40+
printUsage(ctx);
4041
return;
4142
}
4243

src/main/java/fi/helsinki/cs/tmc/cli/core/AbstractCommand.java

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
import org.slf4j.LoggerFactory;
1313

1414
public abstract class AbstractCommand {
15+
1516
private static final Logger logger = LoggerFactory.getLogger(AbstractCommand.class);
17+
private Command command;
1618

1719
/**
1820
* Override this method if you want longer description for the command than
@@ -24,6 +26,17 @@ public String getDescription() {
2426
return null;
2527
}
2628

29+
/**
30+
* Override this method if you want to give usage description.
31+
* Dont't add the 'tmc-cli COMMAND' prefix, because it is added
32+
* automatically to every line.
33+
*
34+
* @return Description text
35+
*/
36+
public String[] getUsages() {
37+
return null;
38+
}
39+
2740
public abstract void getOptions(Options options);
2841

2942
private Options getOptions() {
@@ -69,18 +82,59 @@ public CommandLine parseArgs(CliContext context, String[] stringArgs) {
6982
}
7083

7184
if (args.hasOption("h")) {
85+
printHelp(context);
86+
return null;
87+
}
88+
return args;
89+
}
90+
91+
protected void printUsage(CliContext context) {
92+
Io io = context.getIo();
93+
io.println(getUsageString());
94+
}
95+
96+
private Command getCommand() {
97+
if(this.command == null) {
7298
Class<Command> klass;
7399
klass = CommandFactory.castToCommandClass(this.getClass());
74-
Command command = CommandFactory.getCommand(klass);
100+
this.command = CommandFactory.getCommand(klass);
101+
}
102+
return this.command;
103+
}
104+
105+
private void printHelp(CliContext context) {
106+
Io io = context.getIo();
107+
Options options = getOptions();
75108

76-
String usage = "tmc " + command.name();
77-
String desc = getDescription();
78-
if (desc == null) {
79-
desc = command.desc();
109+
String usage = getUsageString();
110+
String desc = getDescription();
111+
if (desc == null) {
112+
desc = getCommand().desc();
113+
}
114+
HelpGenerator.run(io, usage, desc, options);
115+
}
116+
117+
/**
118+
* TODO print the "Usage:" and "Or:" prefixes to every line.
119+
* @return The printable usage string.
120+
*/
121+
private String getUsageString() {
122+
String prefix = "tmc " + getCommand().name() + " ";
123+
String[] usages = getUsages();
124+
if(usages == null) {
125+
return prefix;
126+
}
127+
128+
StringBuilder builder = new StringBuilder();
129+
boolean first = true;
130+
for(String line : usages) {
131+
if(!first) {
132+
builder.append("\n");
80133
}
81-
HelpGenerator.run(io, usage, desc, options);
82-
return null;
134+
builder.append(prefix);
135+
builder.append(line);
136+
first = false;
83137
}
84-
return args;
138+
return builder.toString();
85139
}
86-
}
140+
}

0 commit comments

Comments
 (0)