fix recursive readings for subcommands that return identical help

This commit is contained in:
atagen 2026-03-29 13:41:47 +11:00
parent ba9dda073d
commit 845ff03632
2 changed files with 103 additions and 5 deletions

View file

@ -675,9 +675,18 @@ let help_resolve_par ?(timeout=200) ?(mandirs=[]) cmd rest name =
| Error _ -> None
| Ok r when r.entries = [] && r.subcommands = [] && r.positionals = [] -> None
| Ok r ->
let at_limit = depth >= 5 in
let subs = if at_limit then [] else r.subcommands in
Some (r, subs, []))
let self_listed = match cmd_args with
| [] -> false
| _ ->
let leaf = List.nth cmd_args (List.length cmd_args - 1) in
List.exists (fun (sc : subcommand) -> sc.name = leaf) r.subcommands in
if self_listed then
Some ({ entries = []; subcommands = []; positionals = [];
description = "" }, [], [])
else
let at_limit = depth >= 5 in
let subs = if at_limit then [] else r.subcommands in
Some (r, subs, []))
else
match parse_help text with
| Error _ -> None
@ -688,7 +697,13 @@ let help_resolve_par ?(timeout=200) ?(mandirs=[]) cmd rest name =
| _ ->
let leaf = List.nth cmd_args (List.length cmd_args - 1) in
List.exists (fun (sc : subcommand) -> sc.name = leaf) r.subcommands in
if self_listed then None
if self_listed then
(* the subcommand's --help returned the parent's help text
* (it lists itself as a subcommand). cache a leaf stub so the
* completer knows this is a leaf node, not a parent with
* further subcommands. *)
Some ({ entries = []; subcommands = []; positionals = [];
description = "" }, [], [])
else
let at_limit = depth >= 5 in
let subs = if at_limit then [] else r.subcommands in
@ -871,7 +886,22 @@ let cmd_index bindirs mandirs ignorelist help_only dir =
done_cmds := SSet.add sub_cmd !done_cmds;
incr result_count
end
) subs
) subs;
(* for COMMANDS section subcommands (e.g. systemctl start/stop),
* write leaf stubs so the completer treats them as leaf nodes
* rather than falling back to the parent's flags/subcommands.
* only when there are no clap-style sub-sections (subs = []),
* meaning the subcommands came from the COMMANDS section.
* deliberately not added to done_cmds if a per-subcommand
* manpage exists (e.g. docker-start.1), it will overwrite the stub. *)
if subs = [] then
List.iter (fun (sc : subcommand) ->
let sub_cmd = cmd ^ " " ^ sc.name in
if not (SSet.mem sub_cmd !done_cmds) then
write_result ~dir ~source:"manpage" sub_cmd
{ entries = []; subcommands = []; positionals = [];
description = sc.desc }
) result.subcommands
) files
end
) command_sections