Skip to content

Commit 18dc116

Browse files
authored
Fix #40; Help output regression tests (#121)
1 parent 1f89123 commit 18dc116

12 files changed

+224
-35
lines changed

confutils.nim

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -174,12 +174,14 @@ func isCliSwitch(opt: OptInfo): bool =
174174
opt.kind == CliSwitch or
175175
(opt.kind == Discriminator and opt.isCommand == false)
176176

177+
func isOpt(opt: OptInfo): bool =
178+
opt.isCliSwitch and not opt.isHidden
179+
177180
func hasOpts(cmd: CmdInfo): bool =
178181
for opt in cmd.opts:
179-
if opt.isCliSwitch and not opt.isHidden:
182+
if opt.isOpt:
180183
return true
181-
182-
return false
184+
false
183185

184186
func hasArgs(cmd: CmdInfo): bool =
185187
for opt in cmd.opts:
@@ -213,27 +215,43 @@ iterator subCmds(cmd: CmdInfo): CmdInfo =
213215
template isSubCommand(cmd: CmdInfo): bool =
214216
cmd.name.len > 0
215217

216-
func maxNameLen(cmd: CmdInfo): int =
218+
func maxNameLen(cmd: CmdInfo, commands = false): int =
217219
result = 0
218220
for opt in cmd.opts:
219-
if opt.kind == Arg or opt.kind == Discriminator and opt.isCommand:
220-
continue
221-
result = max(result, opt.name.len)
222-
if opt.kind == Discriminator:
221+
if opt.isOpt or opt.kind == Arg:
222+
result = max(result, opt.name.len)
223+
if opt.kind == Discriminator:
224+
for subCmd in opt.subCmds:
225+
result = max(result, maxNameLen(subCmd, commands))
226+
elif commands and opt.kind == Discriminator and opt.isCommand:
223227
for subCmd in opt.subCmds:
224-
result = max(result, subCmd.maxNameLen)
228+
result = max(result, maxNameLen(subCmd, commands))
229+
230+
func maxNameLen(cmds: openArray[CmdInfo]): int =
231+
result = 0
232+
for i, cmd in cmds:
233+
result = max(result, maxNameLen(cmd, commands = i == cmds.high))
225234

226-
func hasAbbrs(cmd: CmdInfo): bool =
235+
func hasAbbrs(cmd: CmdInfo, commands = false): bool =
227236
for opt in cmd.opts:
228-
if opt.kind == Arg or opt.kind == Discriminator and opt.isCommand:
229-
continue
230-
if opt.abbr.len > 0:
231-
return true
232-
if opt.kind == Discriminator:
237+
if opt.isOpt:
238+
if opt.abbr.len > 0:
239+
return true
240+
if opt.kind == Discriminator:
241+
for subCmd in opt.subCmds:
242+
if hasAbbrs(subCmd, commands):
243+
return true
244+
elif commands and opt.kind == Discriminator and opt.isCommand:
233245
for subCmd in opt.subCmds:
234-
if hasAbbrs(subCmd):
246+
if hasAbbrs(subCmd, commands):
235247
return true
236248

249+
func hasAbbrs(cmds: openArray[CmdInfo]): bool =
250+
for i, cmd in cmds:
251+
if hasAbbrs(cmd, commands = i == cmds.high):
252+
return true
253+
false
254+
237255
func humaneName(opt: OptInfo): string =
238256
if opt.name.len > 0: opt.name
239257
else: opt.abbr
@@ -274,7 +292,6 @@ proc describeInvocation(help: var string,
274292
cmd: CmdInfo, cmdInvocation: string,
275293
appInfo: HelpAppInfo) =
276294
helpOutput styleBright, "\p", fgCommand, cmdInvocation
277-
var longestArg = 0
278295

279296
if cmd.opts.len > 0:
280297
if cmd.hasOpts: helpOutput " [OPTIONS]..."
@@ -284,7 +301,6 @@ proc describeInvocation(help: var string,
284301

285302
for arg in cmd.args:
286303
helpOutput " <", arg.name, ">"
287-
longestArg = max(longestArg, arg.name.len)
288304

289305
helpOutput "\p"
290306

@@ -299,9 +315,9 @@ proc describeInvocation(help: var string,
299315
helpOutput "\p"
300316
argsSectionStarted = true
301317

302-
let cliArg = " <" & arg.humaneName & ">"
303-
helpOutput fgArg, styleBright, cliArg
304-
helpOutput padding(cliArg, 6 + appInfo.namesWidth)
318+
let cliArg = "<" & arg.name & ">"
319+
helpOutput fgArg, styleBright, " ", cliArg
320+
helpOutput padding(cliArg, appInfo.namesWidth)
305321
help.writeDesc appInfo, arg.desc, arg.defaultInHelpText
306322
help.writeLongDesc appInfo, arg.longDesc
307323
helpOutput "\p"
@@ -413,8 +429,8 @@ proc showHelp(help: var string,
413429

414430
let cmd = activeCmds[^1]
415431

416-
appInfo.maxNameLen = cmd.maxNameLen
417-
appInfo.hasAbbrs = cmd.hasAbbrs
432+
appInfo.maxNameLen = activeCmds.maxNameLen
433+
appInfo.hasAbbrs = activeCmds.hasAbbrs
418434
let termWidth =
419435
try:
420436
terminalWidth()

tests/help/snapshots/test_argument.txt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,25 @@ Available sub-commands:
66

77
test_argument argAfterOpt [OPTIONS]... <arg-after-opt-arg1>
88

9-
<arg-after-opt-arg1> arg1 desc.
9+
<arg-after-opt-arg1> arg1 desc.
1010

1111
The following options are available:
1212

13-
--arg-after-opt-opt1 opt1 desc [=opt1 default].
13+
--arg-after-opt-opt1 opt1 desc [=opt1 default].
1414

1515
test_argument argBeforeOpt [OPTIONS]... <arg-before-opt-arg2>
1616

17-
<arg-before-opt-arg2> arg2 desc.
17+
<arg-before-opt-arg2> arg2 desc.
1818

1919
The following options are available:
2020

21-
--arg-before-opt-opt2 opt2 desc [=opt2 default].
21+
--arg-before-opt-opt2 opt2 desc [=opt2 default].
2222

2323
test_argument argAroundOpt [OPTIONS]... <arg-around-opt-arg4> <arg-around-opt-arg5>
2424

25-
<arg-around-opt-arg4> arg4 desc.
26-
<arg-around-opt-arg5> arg5 desc.
25+
<arg-around-opt-arg4> arg4 desc.
26+
<arg-around-opt-arg5> arg5 desc.
2727

2828
The following options are available:
2929

30-
--arg-around-opt-opt3 opt3 desc [=opt3 default].
30+
--arg-around-opt-opt3 opt3 desc [=opt3 default].
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Usage:
2+
3+
test_default_value_desc [OPTIONS]...
4+
5+
The following options are available:
6+
7+
--opt1 tcp port [=9000].
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
Usage:
2+
3+
test_longdesc [OPTIONS]... command
4+
5+
The following options are available:
6+
7+
-o, --opt1 opt1 regular description [=opt1 default].
8+
opt1 longdesc line one.
9+
longdesc line two.
10+
longdesc line three.
11+
12+
Available sub-commands:
13+
14+
test_longdesc lvl1Cmd1 [OPTIONS]...
15+
16+
The following options are available:
17+
18+
--opt2 opt2 regular description [=opt2 default].
19+
opt2 longdesc line one.
20+
longdesc line two.
21+
longdesc line three.
22+
--opt3 opt3 desc [=opt3 default].
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
Usage:
2+
3+
test_longdesc lvl1Cmd1 [OPTIONS]...
4+
5+
The following options are available:
6+
7+
-o, --opt1 opt1 regular description [=opt1 default].
8+
opt1 longdesc line one.
9+
longdesc line two.
10+
longdesc line three.
11+
--opt2 opt2 regular description [=opt2 default].
12+
opt2 longdesc line one.
13+
longdesc line two.
14+
longdesc line three.
15+
--opt3 opt3 desc [=opt3 default].

tests/help/snapshots/test_nested_cmd.txt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,27 @@ test_nested_cmd [OPTIONS]... command
44

55
The following options are available:
66

7-
--top-arg1 topArg1 desc [=topArg1 default].
8-
--lvl1-no-command-arg1 lvl1NoCommandArg1 desc [=lvl1NoCommandArg1 default].
7+
--top-arg1 topArg1 desc [=topArg1 default].
8+
--lvl1-no-command-arg1 lvl1NoCommandArg1 desc [=lvl1NoCommandArg1 default].
99

1010
Available sub-commands:
1111

1212
test_nested_cmd lvl1Cmd1 [OPTIONS]... command
1313

1414
The following options are available:
1515

16-
--lvl1-cmd1-arg1 lvl1Cmd1Arg1 desc [=lvl1Cmd1Arg1 default].
16+
--lvl1-cmd1-arg1 lvl1Cmd1Arg1 desc [=lvl1Cmd1Arg1 default].
1717

1818
Available sub-commands:
1919

2020
test_nested_cmd lvl1Cmd1 lvl2Cmd1 [OPTIONS]...
2121

2222
The following options are available:
2323

24-
--lvl2-cmd1-arg1 lvl2Cmd1Arg1 desc [=lvl2Cmd1Arg1 default].
24+
--lvl2-cmd1-arg1 lvl2Cmd1Arg1 desc [=lvl2Cmd1Arg1 default].
2525

2626
test_nested_cmd lvl1Cmd1 lvl2Cmd2 [OPTIONS]...
2727

2828
The following options are available:
2929

30-
--lvl2-cmd2-arg1 lvl2Cmd2Arg1 desc [=lvl2Cmd2Arg1 default].
30+
--lvl2-cmd2-arg1 lvl2Cmd2Arg1 desc [=lvl2Cmd2Arg1 default].
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
Usage:
2+
3+
test_separator [OPTIONS]...
4+
5+
The following options are available:
6+
7+
Network Options:
8+
--opt1 opt1 desc [=opt1 default].
9+
--opt2 opt2 desc [=opt2 default].
10+
11+
----------------
12+
--opt3 opt3 desc [=opt3 default].
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# confutils
2+
# Copyright (c) 2018-2025 Status Research & Development GmbH
3+
# Licensed under either of
4+
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
5+
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
6+
# at your option.
7+
# This file may not be copied, modified, or distributed except according to
8+
# those terms.
9+
10+
import ../../confutils
11+
12+
const defaultEth2TcpPort = 9000
13+
14+
type
15+
TestConf = object
16+
opt1 {.
17+
defaultValue: defaultEth2TcpPort
18+
defaultValueDesc: $defaultEth2TcpPort
19+
desc: "tcp port"
20+
name: "opt1" }: int
21+
22+
let c = TestConf.load(termWidth = int.high)

tests/help/test_longdesc.nim

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# confutils
2+
# Copyright (c) 2018-2025 Status Research & Development GmbH
3+
# Licensed under either of
4+
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
5+
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
6+
# at your option.
7+
# This file may not be copied, modified, or distributed except according to
8+
# those terms.
9+
10+
import ../../confutils
11+
12+
type
13+
Lvl1Cmd = enum
14+
lvl1Cmd1
15+
16+
TestConf = object
17+
opt1 {.
18+
desc: "opt1 regular description"
19+
longDesc:
20+
"opt1 longdesc line one\n" &
21+
"longdesc line two\n" &
22+
"longdesc line three"
23+
defaultValue: "opt1 default"
24+
name: "opt1"
25+
abbr: "o" }: string
26+
27+
case cmd {.command.}: Lvl1Cmd
28+
of Lvl1Cmd.lvl1Cmd1:
29+
opt2 {.
30+
desc: "opt2 regular description"
31+
longDesc:
32+
"opt2 longdesc line one\n" &
33+
"longdesc line two\n" &
34+
"longdesc line three"
35+
defaultValue: "opt2 default"
36+
name: "opt2" }: string
37+
opt3 {.
38+
defaultValue: "opt3 default"
39+
desc: "opt3 desc"
40+
name: "opt3" }: string
41+
42+
let c = TestConf.load(termWidth = int.high)

tests/help/test_nested_cmd.nim

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
# confutils
2+
# Copyright (c) 2018-2025 Status Research & Development GmbH
3+
# Licensed under either of
4+
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
5+
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
6+
# at your option.
7+
# This file may not be copied, modified, or distributed except according to
8+
# those terms.
9+
110
import ../../confutils
211

312
type

0 commit comments

Comments
 (0)