1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.rat.help;
20
21 import java.io.PrintWriter;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.function.Function;
27
28 import org.apache.commons.cli.HelpFormatter;
29 import org.apache.commons.cli.Option;
30 import org.apache.commons.cli.Options;
31 import org.apache.commons.lang3.StringUtils;
32 import org.apache.commons.text.WordUtils;
33 import org.apache.rat.CLIOptionCollection;
34 import org.apache.rat.OptionCollection;
35 import org.apache.rat.VersionInfo;
36
37 import static java.lang.String.format;
38
39
40
41
42 public abstract class AbstractHelp {
43
44 private static final String END_OF_OPTION_MSG = " Multiple values may be specified. " +
45 "Note that '--' or a following option is required when using this parameter.";
46
47
48 public static final int HELP_WIDTH = 120;
49
50 public static final int HELP_PADDING = 4;
51
52
53 protected final RatHelpFormatter helpFormatter;
54
55 protected final VersionInfo versionInfo;
56
57
58
59
60 protected final CLIOptionCollection cliOptionCollection = new CLIOptionCollection();
61
62
63
64
65 protected AbstractHelp() {
66 helpFormatter = new RatHelpFormatter();
67 versionInfo = new VersionInfo();
68 }
69
70
71 public static final Function<Option, String> DEPRECATED_MSG = o -> {
72 StringBuilder sb = new StringBuilder("[").append(o.getDeprecated().toString()).append("]");
73 if (o.getDescription() != null) {
74 sb.append(" ").append(o.getDescription());
75 }
76 return sb.toString();
77 };
78
79
80
81
82
83
84 public static String createPadding(final int len) {
85 char[] padding = new char[len];
86 Arrays.fill(padding, ' ');
87 return new String(padding);
88 }
89
90
91
92
93
94
95 public static String header(final String txt) {
96 return String.format("%n====== %s ======%n", WordUtils.capitalizeFully(txt));
97 }
98
99
100
101
102 public class RatHelpFormatter extends HelpFormatter {
103
104
105
106
107 RatHelpFormatter() {
108 super();
109 this.optionComparator = OptionCollection.OPTION_COMPARATOR;
110 this.setWidth(HELP_WIDTH);
111 }
112
113
114
115
116
117
118
119
120
121 public void printHelp(final PrintWriter writer, final String cmdLineSyntax, final String header, final Options options, final String footer) {
122 if (StringUtils.isEmpty(cmdLineSyntax)) {
123 throw new IllegalArgumentException("cmdLineSyntax not provided");
124 }
125
126 helpFormatter.printUsage(writer, HELP_WIDTH, cmdLineSyntax);
127
128 if (header != null && !header.isEmpty()) {
129 helpFormatter.printWrapped(writer, HELP_WIDTH, header);
130 }
131 printOptions(writer, HELP_WIDTH, options, helpFormatter.getLeftPadding(), helpFormatter.getDescPadding());
132 if (footer != null && !footer.isEmpty()) {
133 helpFormatter.printWrapped(writer, helpFormatter.getWidth(), footer);
134 }
135 }
136
137 @Override
138 protected StringBuffer renderOptions(final StringBuffer sb, final int width, final Options options, final int leftPad, final int descPad) {
139 final String lpad = createPadding(leftPad);
140 final String dpad = createPadding(descPad);
141
142
143
144
145 int max = 0;
146 final List<StringBuffer> prefixList = new ArrayList<>();
147 final List<Option> optList = new ArrayList<>(options.getOptions());
148 optList.sort(helpFormatter.getOptionComparator());
149
150 for (final Option option : optList) {
151 final StringBuffer optBuf = new StringBuffer();
152 if (option.getOpt() == null) {
153 optBuf.append(lpad).append(" ").append(getLongOptPrefix()).append(option.getLongOpt());
154 } else {
155 optBuf.append(lpad).append(getOptPrefix()).append(option.getOpt());
156 if (option.hasLongOpt()) {
157 optBuf.append(',').append(getLongOptPrefix()).append(option.getLongOpt());
158 }
159 }
160 if (option.hasArg()) {
161 final String argName = option.getArgName();
162 if (argName != null && argName.isEmpty()) {
163
164 optBuf.append(' ');
165 } else {
166 optBuf.append(option.hasLongOpt() ? helpFormatter.getLongOptSeparator() : " ");
167 optBuf.append("<").append(argName != null ? option.getArgName() : getArgName()).append(">");
168 }
169 }
170 prefixList.add(optBuf);
171 max = Math.max(optBuf.length(), max);
172 }
173 int x = 0;
174 for (final Iterator<Option> it = optList.iterator(); it.hasNext();) {
175 final Option option = it.next();
176 final StringBuilder optBuf = new StringBuilder(prefixList.get(x++).toString());
177 if (optBuf.length() < max) {
178 optBuf.append(createPadding(max - optBuf.length()));
179 }
180 optBuf.append(dpad);
181 final int nextLineTabStop = max + descPad;
182
183 if (option.isDeprecated()) {
184 optBuf.append(DEPRECATED_MSG.apply(option).trim());
185 } else if (option.getDescription() != null) {
186 optBuf.append(option.getDescription());
187 }
188
189 if (option.hasArgs()) {
190 optBuf.append(END_OF_OPTION_MSG);
191 }
192
193 String defaultValue = cliOptionCollection.defaultValue(option);
194 if (defaultValue != null) {
195 optBuf.append(format(" (Default value = %s)", defaultValue));
196 }
197 renderWrappedText(sb, width, nextLineTabStop, optBuf.toString());
198 if (it.hasNext()) {
199 sb.append(getNewLine());
200 }
201 }
202 return sb;
203 }
204 }
205 }