| 4 |
4 |
| 5 import java.util.List; |
5 import java.util.List; |
| 6 |
6 |
| 7 import static de.unixwork.uwproj.Util.shId; |
7 import static de.unixwork.uwproj.Util.shId; |
| 8 |
8 |
| 9 public final class Feature { |
9 public final class Feature extends AbstractOption { |
| 10 private final String name; |
10 private final String name; |
| 11 private final String arg; |
|
| 12 private final boolean auto; |
11 private final boolean auto; |
| 13 private final TargetData targetData; |
12 private final TargetData targetData; |
| 14 private final TargetData disabled = new TargetData(); |
13 private final TargetData disabled = new TargetData(); |
| 15 private String desc = ""; |
|
| 16 |
14 |
| 17 public Feature(Element e) { |
15 public Feature(Element e) { |
| |
16 super(Util.getAttrOrDefault(e, "arg", e.getAttribute("name"))); |
| 18 name = e.getAttribute("name"); |
17 name = e.getAttribute("name"); |
| 19 arg = Util.getAttrOrDefault(e, "arg", name); |
|
| 20 auto = Boolean.parseBoolean(e.getAttribute("default")); |
18 auto = Boolean.parseBoolean(e.getAttribute("default")); |
| 21 targetData = new TargetData(e); |
19 targetData = new TargetData(e); |
| 22 |
20 |
| 23 Util.getChildElements(e).forEach(elm -> { |
21 Util.getChildElements(e).forEach(elm -> { |
| 24 switch (elm.getNodeName()) { |
22 switch (elm.getNodeName()) { |
| 66 |
64 |
| 67 public boolean isAuto() { |
65 public boolean isAuto() { |
| 68 return auto; |
66 return auto; |
| 69 } |
67 } |
| 70 |
68 |
| 71 /** |
69 @Override |
| 72 * Generates help text for the feature option. |
70 public String getHelpTextArg() { |
| 73 * <p> |
71 return (auto ? "--disable-" : "--enable-")+arg; |
| 74 * If {@link #isAuto()} returns true, the option name will be --disable-${@link #getArg()}, otherwise |
|
| 75 * it will be --enable-${@link #getArg()}, preceded by two spaces, respectively. |
|
| 76 * <p> |
|
| 77 * If no description is available via {@link #getDesc()}, only the option name is generated. Otherwise, |
|
| 78 * description is added according to the following rules: |
|
| 79 * <p> |
|
| 80 * When the option name does not consume more than 25 characters, the description starts in the same line. |
|
| 81 * Otherwise, a line break is added, first. The description will be placed in a block starting from column |
|
| 82 * 27 to 80 and automatically break when necessary. The description must not contain a single word |
|
| 83 * that is longer than 54 characters, or it will break the layout. |
|
| 84 * |
|
| 85 * @return a help text for terminal output |
|
| 86 */ |
|
| 87 public String getHelpText() { |
|
| 88 final var builder = new StringBuilder(); |
|
| 89 |
|
| 90 // Compute option name |
|
| 91 final var opt = (auto ? " --disable-" : " --enable-")+arg; |
|
| 92 |
|
| 93 // Add option name |
|
| 94 builder.append(opt); |
|
| 95 |
|
| 96 // Stop, if there is no description |
|
| 97 if (desc.isBlank()) return builder.toString(); |
|
| 98 |
|
| 99 // Prepare the description by replacing some unwanted spaces |
|
| 100 final var hdesc = desc.trim() |
|
| 101 .replaceAll("\\r", "") |
|
| 102 .replaceAll("\\t", " "); |
|
| 103 |
|
| 104 // Declare our frame where the description shall be placed |
|
| 105 final int startx = 26; |
|
| 106 final int endx = 80; |
|
| 107 |
|
| 108 // Move to startx (break, if we already past that) |
|
| 109 if (opt.length() >= startx) { |
|
| 110 builder.append("\n"); |
|
| 111 builder.append(" ".repeat(startx)); |
|
| 112 } else { |
|
| 113 builder.append(" ".repeat(startx-opt.length())); |
|
| 114 } |
|
| 115 |
|
| 116 // Append the description keeping the layout intact |
|
| 117 int x = startx; |
|
| 118 for (int i = 0 ; i < hdesc.length() ;) { |
|
| 119 // get the next word and see where we would end |
|
| 120 int s = hdesc.indexOf(' ', i); |
|
| 121 if (s < 0) s = hdesc.length(); |
|
| 122 int n = hdesc.indexOf('\n', i); |
|
| 123 if (n < 0) n = hdesc.length(); |
|
| 124 s = Math.min(s, n); |
|
| 125 int l = s-i; |
|
| 126 if (x + l > endx) { |
|
| 127 // does not fit, break into next line |
|
| 128 builder.append('\n'); |
|
| 129 builder.append(" ".repeat(startx)); |
|
| 130 x = startx; |
|
| 131 } |
|
| 132 // append the word |
|
| 133 builder.append(hdesc, i, s); |
|
| 134 x += l; |
|
| 135 i += l; |
|
| 136 // append the next spaces |
|
| 137 while (i < hdesc.length()) { |
|
| 138 int c = hdesc.charAt(i); |
|
| 139 if (c == ' ') { |
|
| 140 // as long as we don't need to break, add the spaces |
|
| 141 i++; |
|
| 142 x++; |
|
| 143 if (x < endx) builder.append(' '); |
|
| 144 } else if (c == '\n') { |
|
| 145 // if user wants us to break, comply |
|
| 146 i++; |
|
| 147 // if we have still space, just move to the end of the line |
|
| 148 if (x < endx) { |
|
| 149 x = endx; |
|
| 150 } else { |
|
| 151 // otherwise, we need to add an extra blank line |
|
| 152 builder.append('\n'); |
|
| 153 } |
|
| 154 } else { |
|
| 155 // we have found the next word, so continue with the outer loop |
|
| 156 break; |
|
| 157 } |
|
| 158 } |
|
| 159 // break to new line, when spaces moved us outside the frame |
|
| 160 if (x > endx) { |
|
| 161 builder.append('\n'); |
|
| 162 builder.append(" ".repeat(startx)); |
|
| 163 x = startx; |
|
| 164 } |
|
| 165 } |
|
| 166 |
|
| 167 return builder.toString(); |
|
| 168 } |
72 } |
| 169 } |
73 } |