This commit is contained in:
atagen 2026-03-23 15:06:49 +11:00
parent 76656231be
commit adea668355
6 changed files with 76 additions and 27 deletions

View file

@ -455,6 +455,41 @@ let extract_entries lines =
else (name, best)
) ("none", []) candidates |> snd
(* --- NAME section description extraction --- *)
let extract_name_description contents =
let lines = String.split_on_char '\n' contents in
let classified = List.map classify_line lines in
let rec find = function
| [] -> None
| Macro ("SH", args) :: rest
when String.uppercase_ascii (String.trim args) = "NAME" ->
collect rest []
| _ :: rest -> find rest
and collect lines acc =
match lines with
| Macro ("SH", _) :: _ | [] -> finish acc
| Text s :: rest -> collect rest (s :: acc)
| Macro (("B" | "BI" | "BR" | "I" | "IR"), args) :: rest ->
let s = strip_inline_macro_args args |> strip_groff_escapes |> String.trim in
collect rest (if String.length s > 0 then s :: acc else acc)
| Macro ("Nm", args) :: rest ->
let s = strip_groff_escapes args |> String.trim in
collect rest (if String.length s > 0 then s :: acc else acc)
| Macro ("Nd", args) :: rest ->
let s = strip_groff_escapes args |> String.trim in
collect rest (if String.length s > 0 then ("\\- " ^ s) :: acc else acc)
| _ :: rest -> collect rest acc
and finish acc =
let full = String.concat " " (List.rev acc) |> String.trim in
(* NAME lines look like: "git-add \- Add file contents to the index" *)
let sep = Str.regexp {| *\\- *\| +- +|} in
match Str.bounded_split sep full 2 with
| [_; desc] -> Some (String.trim desc)
| _ -> None
in
find classified
(* --- SYNOPSIS command name extraction --- *)
let extract_synopsis_command_lines lines =
@ -661,7 +696,7 @@ let parse_mdoc_lines lines =
) ([], [])
|> snd |> List.rev
in
{ entries = List.rev entries; subcommands = []; positionals }
{ entries = List.rev entries; subcommands = []; positionals; description = "" }
(* --- Top-level API --- *)
@ -672,12 +707,15 @@ let parse_manpage_lines lines =
let options_section = extract_options_section lines in
let entries = extract_entries options_section in
let positionals = extract_synopsis_positionals_lines lines in
{ entries; subcommands = []; positionals }
{ entries; subcommands = []; positionals; description = "" }
end
let parse_manpage_string contents =
let lines = String.split_on_char '\n' contents in
parse_manpage_lines lines
let result = parse_manpage_lines lines in
let description = match extract_name_description contents with
| Some d -> d | None -> "" in
{ result with description }
let read_manpage_file path =
if Filename.check_suffix path ".gz" then begin