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.OptionCollection;
34 import org.apache.rat.VersionInfo;
35 import org.apache.rat.commandline.Arg;
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 AbstractHelp() {
61 helpFormatter = new RatHelpFormatter();
62 versionInfo = new VersionInfo();
63 }
64
65
66 public static final Function<Option, String> DEPRECATED_MSG = o -> {
67 StringBuilder sb = new StringBuilder("[").append(o.getDeprecated().toString()).append("]");
68 if (o.getDescription() != null) {
69 sb.append(" ").append(o.getDescription());
70 }
71 return sb.toString();
72 };
73
74
75
76
77
78
79 public static String createPadding(final int len) {
80 char[] padding = new char[len];
81 Arrays.fill(padding, ' ');
82 return new String(padding);
83 }
84
85
86
87
88
89
90 public static String header(final String txt) {
91 return String.format("%n====== %s ======%n", WordUtils.capitalizeFully(txt));
92 }
93
94
95
96
97 public class RatHelpFormatter extends HelpFormatter {
98
99
100
101
102 RatHelpFormatter() {
103 super();
104 this.optionComparator = OptionCollection.OPTION_COMPARATOR;
105 this.setWidth(HELP_WIDTH);
106 }
107
108
109
110
111
112
113
114
115
116 public void printHelp(final PrintWriter writer, final String cmdLineSyntax, final String header, final Options options, final String footer) {
117 if (StringUtils.isEmpty(cmdLineSyntax)) {
118 throw new IllegalArgumentException("cmdLineSyntax not provided");
119 }
120
121 helpFormatter.printUsage(writer, HELP_WIDTH, cmdLineSyntax);
122
123 if (header != null && !header.isEmpty()) {
124 helpFormatter.printWrapped(writer, HELP_WIDTH, header);
125 }
126 printOptions(writer, HELP_WIDTH, options, helpFormatter.getLeftPadding(), helpFormatter.getDescPadding());
127 if (footer != null && !footer.isEmpty()) {
128 helpFormatter.printWrapped(writer, helpFormatter.getWidth(), footer);
129 }
130 }
131
132 @Override
133 protected StringBuffer renderOptions(final StringBuffer sb, final int width, final Options options, final int leftPad, final int descPad) {
134 final String lpad = createPadding(leftPad);
135 final String dpad = createPadding(descPad);
136
137
138
139
140 int max = 0;
141 final List<StringBuffer> prefixList = new ArrayList<>();
142 final List<Option> optList = new ArrayList<>(options.getOptions());
143 optList.sort(helpFormatter.getOptionComparator());
144
145 for (final Option option : optList) {
146 final StringBuffer optBuf = new StringBuffer();
147 if (option.getOpt() == null) {
148 optBuf.append(lpad).append(" ").append(getLongOptPrefix()).append(option.getLongOpt());
149 } else {
150 optBuf.append(lpad).append(getOptPrefix()).append(option.getOpt());
151 if (option.hasLongOpt()) {
152 optBuf.append(',').append(getLongOptPrefix()).append(option.getLongOpt());
153 }
154 }
155 if (option.hasArg()) {
156 final String argName = option.getArgName();
157 if (argName != null && argName.isEmpty()) {
158
159 optBuf.append(' ');
160 } else {
161 optBuf.append(option.hasLongOpt() ? helpFormatter.getLongOptSeparator() : " ");
162 optBuf.append("<").append(argName != null ? option.getArgName() : getArgName()).append(">");
163 }
164 }
165 prefixList.add(optBuf);
166 max = Math.max(optBuf.length(), max);
167 }
168 int x = 0;
169 for (final Iterator<Option> it = optList.iterator(); it.hasNext();) {
170 final Option option = it.next();
171 final StringBuilder optBuf = new StringBuilder(prefixList.get(x++).toString());
172 if (optBuf.length() < max) {
173 optBuf.append(createPadding(max - optBuf.length()));
174 }
175 optBuf.append(dpad);
176 final int nextLineTabStop = max + descPad;
177
178 if (option.isDeprecated()) {
179 optBuf.append(DEPRECATED_MSG.apply(option).trim());
180 } else if (option.getDescription() != null) {
181 optBuf.append(option.getDescription());
182 }
183
184 if (option.hasArgs()) {
185 optBuf.append(END_OF_OPTION_MSG);
186 }
187
188 Arg arg = Arg.findArg(option);
189 String defaultValue = arg == null ? null : arg.defaultValue();
190 if (defaultValue != null) {
191 optBuf.append(format(" (Default value = %s)", defaultValue));
192 }
193 renderWrappedText(sb, width, nextLineTabStop, optBuf.toString());
194 if (it.hasNext()) {
195 sb.append(getNewLine());
196 }
197 }
198 return sb;
199 }
200 }
201 }