Skip to content

Commit dcb3a0c

Browse files
committed
Fix issue #17: 0 columns does weird wrapping
1 parent 679b0b9 commit dcb3a0c

File tree

3 files changed

+55
-13
lines changed

3 files changed

+55
-13
lines changed

src/main/kotlin/com/xenomachina/argparser/DefaultHelpFormatter.kt

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,19 @@ class DefaultHelpFormatter(
7070
columns: Int,
7171
values: List<HelpFormatter.Value>
7272
): String {
73+
val effectiveColumns = when {
74+
columns < 0 -> throw IllegalArgumentException("columns must be non-negative")
75+
columns == 0 -> Int.MAX_VALUE
76+
else -> columns
77+
}
7378
val sb = StringBuilder()
74-
appendUsage(sb, columns, progName, values)
79+
appendUsage(sb, effectiveColumns, progName, values)
7580
sb.append("\n")
7681

7782
if (!prologue.isNullOrEmpty()) {
7883
sb.append("\n")
7984
// we just checked that prologue is non-null
80-
sb.append(prologue!!.wrapText(columns))
85+
sb.append(prologue!!.wrapText(effectiveColumns))
8186
sb.append("\n")
8287
}
8388

@@ -92,19 +97,23 @@ class DefaultHelpFormatter(
9297
else -> optional
9398
}.add(value)
9499
}
95-
// Make left column as narrow as possible without wrapping any of the individual usages, though no wider than
96-
// half the screen.
97-
val usageColumns = (2 * indentWidth - 1 + (
98-
values.map { usageText(it).split(" ").map { it.length }.max() ?: 0 }.max() ?: 0)
99-
).coerceAtMost(columns / 2)
100-
appendSection(sb, usageColumns, columns, "required", required)
101-
appendSection(sb, usageColumns, columns, "optional", optional)
102-
appendSection(sb, usageColumns, columns, "positional", positional)
100+
val usageColumns = 2 * indentWidth - 1 + if (columns == 0) {
101+
values.map { usageText(it).length }.max() ?: 0
102+
} else {
103+
// Make left column as narrow as possible without wrapping any of the individual usages, though no wider than
104+
// half the screen.
105+
values.map { usageText(it).split(" ").map { it.length }.max() ?: 0 }.max() ?: 0
106+
.coerceAtMost(effectiveColumns / 2)
107+
}
108+
109+
appendSection(sb, usageColumns, effectiveColumns, "required", required)
110+
appendSection(sb, usageColumns, effectiveColumns, "optional", optional)
111+
appendSection(sb, usageColumns, effectiveColumns, "positional", positional)
103112

104113
if (!epilogue?.trim().isNullOrEmpty()) {
105114
sb.append("\n")
106115
// we just checked that epilogue is non-null
107-
sb.append(epilogue!!.trim().wrapText(columns))
116+
sb.append(epilogue!!.trim().wrapText(effectiveColumns))
108117
sb.append("\n")
109118
}
110119

src/main/kotlin/com/xenomachina/argparser/HelpFormatter.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ interface HelpFormatter {
2727
*
2828
* @param progName name of the program as it should appear in usage information, or null if
2929
* program name is unknown.
30-
* @param columns width of display help should be formatted for, measured in character cells.
30+
* @param columns width of display help should be formatted for, measured in character cells, or 0 for infinite
31+
* width.
3132
* @param values [Value] objects describing the arguments types available.
3233
*/
3334
fun format(progName: String?, columns: Int, values: List<Value>): String

src/test/kotlin/com/xenomachina/argparser/ArgParserTest.kt

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1047,6 +1047,38 @@ consectetur adipiscing elit. Donec vel tortor nunc. Sed eu
10471047
massa sed turpis auctor faucibus. Donec vel pellentesque
10481048
tortor. Ut ultrices tempus lectus fermentum vestibulum.
10491049
Phasellus.
1050+
""".trimStart()
1051+
1052+
// Regression test for issue #17
1053+
val help_wide = StringWriter().apply { printUserMessage(this, "program_name", 0) }.toString()
1054+
help_wide shouldBe """
1055+
usage: program_name [-h] [-n] [-I INCLUDE]... -o OUTPUT [-v]... SOURCE... DEST
1056+
1057+
1058+
This is the prologue. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam malesuada maximus eros. Fusce luctus risus eget quam consectetur, eu auctor est ullamcorper. Maecenas eget suscipit dui, sed sodales erat. Phasellus.
1059+
1060+
1061+
required arguments:
1062+
-o OUTPUT, --output OUTPUT directory in which all output should be generated
1063+
1064+
1065+
optional arguments:
1066+
-h, --help show this help message and exit
1067+
1068+
-n, --dry-run don't do anything
1069+
1070+
-I INCLUDE, --include INCLUDE search in this directory for header files
1071+
1072+
-v, --verbose increase verbosity
1073+
1074+
1075+
positional arguments:
1076+
SOURCE source file
1077+
1078+
DEST destination file
1079+
1080+
1081+
This is the epilogue. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vel tortor nunc. Sed eu massa sed turpis auctor faucibus. Donec vel pellentesque tortor. Ut ultrices tempus lectus fermentum vestibulum. Phasellus.
10501082
""".trimStart()
10511083
}
10521084
})
@@ -1435,4 +1467,4 @@ optional arguments:
14351467
14361468
--baz QUUX test help message""".trim()
14371469
}
1438-
})
1470+
})

0 commit comments

Comments
 (0)