Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid printing extra new lines at the end of usage and refactor blank lines #592

Merged
merged 5 commits into from
Dec 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions src/main/java/com/beust/jcommander/DefaultUsageFormatter.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public DefaultUsageFormatter(JCommander commander) {
public final void usage(String commandName) {
StringBuilder sb = new StringBuilder();
usage(commandName, sb);
commander.getConsole().println(sb.toString());
commander.getConsole().print(sb.toString());
}

/**
Expand All @@ -67,7 +67,7 @@ public final void usage(String commandName, StringBuilder out, String indent) {

if (description != null) {
out.append(indent).append(description);
out.append("\n");
out.append('\n');
}
jc.getUsageFormatter().usage(out, indent);
}
Expand Down Expand Up @@ -154,7 +154,7 @@ public void appendMainLine(StringBuilder out, boolean hasOptions, boolean hasCom
mainLine.append(" ").append(commander.getMainParameter().getDescription().getDescription());
}
wrapDescription(out, indentCount, mainLine.toString());
out.append("\n");
out.append('\n');
}

/**
Expand All @@ -169,6 +169,7 @@ public void appendMainLine(StringBuilder out, boolean hasOptions, boolean hasCom
public void appendAllParametersDetails(StringBuilder out, int indentCount, String indent,
List<ParameterDescription> sortedParameters) {
if (sortedParameters.size() > 0) {
out.append('\n');
out.append(indent).append(" Options:\n");
}

Expand All @@ -182,7 +183,7 @@ public void appendAllParametersDetails(StringBuilder out, int indentCount, Strin
.append(" ")
.append(parameter.required() ? "* " : " ")
.append(pd.getNames())
.append("\n");
.append('\n');

if (hasDescription) {
wrapDescription(out, indentCount, s(indentCount) + description);
Expand Down Expand Up @@ -241,7 +242,7 @@ public void appendAllParametersDetails(StringBuilder out, int indentCount, Strin
out.append(possibleValues);
}
}
out.append("\n");
out.append('\n');
}
}

Expand Down Expand Up @@ -269,27 +270,33 @@ public void appendCommands(StringBuilder out, int indentCount, int descriptionIn
if (hasOnlyHiddenCommands)
return;

out.append('\n');
out.append(indent + " Commands:\n");

var firstCommand = true;
// The magic value 3 is the number of spaces between the name of the option and its description
for (Map.Entry<JCommander.ProgramName, JCommander> commands : commander.getRawCommands().entrySet()) {
Object arg = commands.getValue().getObjects().get(0);
Parameters p = arg.getClass().getAnnotation(Parameters.class);

if (p == null || !p.hidden()) {
if (!firstCommand) {
out.append('\n');
} else {
firstCommand = false;
}
JCommander.ProgramName progName = commands.getKey();
String dispName = progName.getDisplayName();
String commandDescription = Optional.ofNullable(getCommandDescription(progName.getName()))
.map(desc -> s(6) + desc)
.orElse("");
String description = indent + s(4) + dispName + commandDescription;
wrapDescription(out, indentCount + descriptionIndent, description);
out.append("\n");
out.append('\n');

// Options for this command
JCommander jc = commander.findCommandByAlias(progName.getName());
jc.getUsageFormatter().usage(out, indent + s(6));
out.append("\n");
}
}
}
Expand Down Expand Up @@ -362,7 +369,7 @@ public void wrapDescription(StringBuilder out, int indent, int currentLineIndent
current++;
}
} else {
out.append("\n").append(s(indent)).append(word).append(" ");
out.append('\n').append(s(indent)).append(word).append(" ");
current = indent + word.length() + 1;
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/com/beust/jcommander/JCommander.java
Original file line number Diff line number Diff line change
Expand Up @@ -1096,7 +1096,7 @@ public void setProgramName(String name, String... aliases) {
public void usage() {
StringBuilder sb = new StringBuilder();
usageFormatter.usage(sb);
getConsole().println(sb.toString());
getConsole().print(sb.toString());
}

/**
Expand All @@ -1105,7 +1105,7 @@ public void usage() {
public void usage(String commandName) {
StringBuilder sb = new StringBuilder();
usageFormatter.usage(commandName, sb);
getConsole().println(sb.toString());
getConsole().print(sb.toString());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public void appendAllParametersDetails(StringBuilder out, int indentCount, Strin
// The magic value 3 is the number of spaces between the name of the option and its description
// in DefaultUsageFormatter#appendCommands(..)
wrapDescription(out, indentCount + prefixIndent - 3, initialLinePrefixLength, description);
out.append("\n");
out.append('\n');
}
}
}
67 changes: 63 additions & 4 deletions src/test/java/com/beust/jcommander/DefaultUsageFormatterTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
import org.testng.Assert;
import org.testng.annotations.Test;

import java.util.*;
import java.util.ResourceBundle;
import java.util.*;

@Test
public class DefaultUsageFormatterTest {
Expand All @@ -28,6 +28,56 @@ private enum TestEnum1 {
private enum TestEnum2 {
}

@Test
public void testUsage() {
class MainParameters {
@Parameter(names = {"-a", "--a", "--a-parameter"}, description = "a parameter")
public int a;
}
@Parameters(commandNames = "one", commandDescription = "one command")
class OneCommand {
@Parameter(names = {"-b", "--b", "--b-parameter"}, description = "b parameter")
public int b;
}
@Parameters(commandNames = "two", commandDescription = "two command")
class TwoCommand {
@Parameter(names = {"-c", "--c", "--c-parameter"}, description = "c parameter")
public int c;
}
JCommander jc = JCommander.newBuilder()
.addObject(new MainParameters())
.addCommand(new OneCommand())
.addCommand(new TwoCommand())
.build();
StringBuilder output = new StringBuilder();
jc.setConsole(new StringBuilderConsole(output));
jc.usage();
String expected = "Usage: <main class> [options] [command] [command options]\n"
+ "\n"
+ " Options:\n"
+ " -a, --a, --a-parameter\n"
+ " a parameter\n"
+ " Default: 0\n"
+ "\n"
+ " Commands:\n"
+ " one one command\n"
+ " Usage: one [options]\n"
+ "\n"
+ " Options:\n"
+ " -b, --b, --b-parameter\n"
+ " b parameter\n"
+ " Default: 0\n"
+ "\n"
+ " two two command\n"
+ " Usage: two [options]\n"
+ "\n"
+ " Options:\n"
+ " -c, --c, --c-parameter\n"
+ " c parameter\n"
+ " Default: 0\n";
Assert.assertEquals(output.toString(), expected);
}

@Test
public void testOutputFormat() {
class ArgsTemplate {
Expand Down Expand Up @@ -64,6 +114,7 @@ class ArgsTemplate {

// verify
String expected = "Usage: <main class> [options]\n"
+ "\n"
+ " Options:\n"
+ " --a, -a\n"
+ " Default: 0\n"
Expand Down Expand Up @@ -313,7 +364,7 @@ class ArgCommandB {

StringBuilder sb = new StringBuilder();
c.getUsageFormatter().usage(sb);
Assert.assertTrue(sb.toString().contains("[command options]\n Commands:"));
Assert.assertTrue(sb.toString().contains("[command options]\n\n Commands:"));
}

@Test
Expand Down Expand Up @@ -341,7 +392,15 @@ class ArgCommandB {

StringBuilder sb = new StringBuilder();
c.getUsageFormatter().usage(sb);
Assert.assertTrue(sb.toString().contains("command a parameters\n\n b"));
String expected = "Usage: <main class> [command] [command options]\n"
+ "\n"
+ " Commands:\n"
+ " a command a\n"
+ " Usage: a command a parameters\n"
+ "\n"
+ " b command b\n"
+ " Usage: b command b parameters\n";
Assert.assertEquals(sb.toString(), expected);
}

@Test
Expand Down Expand Up @@ -373,7 +432,7 @@ class ArgCommandB {

StringBuilder sb = new StringBuilder();
c.getUsageFormatter().usage(sb);
Assert.assertTrue(sb.toString().contains("command a parameters\n Commands:"));
Assert.assertTrue(sb.toString().contains("command a parameters\n\n Commands:"));
Assert.assertTrue(sb.toString().contains("command b\n Usage:"));
}

Expand Down
29 changes: 29 additions & 0 deletions src/test/java/com/beust/jcommander/StringBuilderConsole.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.beust.jcommander;

import com.beust.jcommander.internal.Console;

public class StringBuilderConsole implements Console {

public final StringBuilder output;

public StringBuilderConsole(StringBuilder output) {
this.output = output;
}

@Override
public void print(String msg) {
output.append(msg);
}

@Override
public void println(String msg) {
print(msg);
output.append('\n');
}

@Override
public char[] readPassword(boolean echoInput) {
throw new UnsupportedOperationException();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ class ArgCommandB {

StringBuilder sb = new StringBuilder();
jc.getUsageFormatter().usage(sb);
Assert.assertTrue(sb.toString().contains("[command options]\n Commands:"));
Assert.assertTrue(sb.toString().contains("[command options]\n\n Commands:"));
}

@Test
Expand Down Expand Up @@ -331,7 +331,15 @@ class ArgCommandB {

StringBuilder sb = new StringBuilder();
jc.getUsageFormatter().usage(sb);
Assert.assertTrue(sb.toString().contains("command a parameters\n\n b"));
String expected = "Usage: <main class> [command] [command options]\n"
+ "\n"
+ " Commands:\n"
+ " a command a\n"
+ " Usage: a command a parameters\n"
+ "\n"
+ " b command b\n"
+ " Usage: b command b parameters\n";
Assert.assertEquals(sb.toString(), expected);
}

@Test
Expand Down Expand Up @@ -364,7 +372,7 @@ class ArgCommandB {

StringBuilder sb = new StringBuilder();
jc.getUsageFormatter().usage(sb);
Assert.assertTrue(sb.toString().contains("command a parameters\n Commands:"));
Assert.assertTrue(sb.toString().contains("command a parameters\n\n Commands:"));
Assert.assertTrue(sb.toString().contains("command b\n Usage:"));
}

Expand Down