fix partial, systemctl manpage
This commit is contained in:
parent
71de2e7b4b
commit
76eb2c2aef
4 changed files with 176 additions and 12 deletions
|
|
@ -129,12 +129,14 @@ let param_parser =
|
|||
space_upper_param; space_type_param ]
|
||||
>>| fun a -> Some a)
|
||||
|
||||
(* Switch parser: -a, --all | --all / -a | -a | --all *)
|
||||
(* Switch parser: -a, --all | -a --all | --all / -a | -a | --all *)
|
||||
let switch_parser =
|
||||
choice
|
||||
[
|
||||
(short_switch >>= fun s ->
|
||||
comma *> long_switch >>| fun l -> Both (s, l));
|
||||
(short_switch >>= fun s ->
|
||||
char ' ' *> long_switch >>| fun l -> Both (s, l));
|
||||
(long_switch >>= fun l ->
|
||||
inline_ws *> char '/' *> inline_ws *>
|
||||
short_switch >>| fun s -> Both (s, l));
|
||||
|
|
@ -222,16 +224,61 @@ let entry =
|
|||
|
||||
(* --- Subcommand parsing --- *)
|
||||
|
||||
(* A subcommand line: " name description" *)
|
||||
(* A subcommand line: " name description"
|
||||
Also handles argument placeholders: " name UNIT... description" *)
|
||||
let is_subcommand_char = function
|
||||
| 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '-' | '_' -> true
|
||||
| _ -> false
|
||||
|
||||
(* Skip argument placeholders like UNIT..., [PATTERN...|PID...], <file>
|
||||
that appear between the subcommand name and the description.
|
||||
Only consumes single-space gaps — the two-space gap before the
|
||||
description is left for the main parser. *)
|
||||
let skip_arg_placeholders =
|
||||
fix (fun self ->
|
||||
(* Peek ahead: single space followed by arg-like token *)
|
||||
available >>= fun avail ->
|
||||
if avail < 2 then return ()
|
||||
else
|
||||
peek_string (min avail 2) >>= fun s2 ->
|
||||
if String.length s2 >= 2 && s2.[0] = ' ' && s2.[1] <> ' ' then
|
||||
(* Single space — could be an arg placeholder *)
|
||||
let next = s2.[1] in
|
||||
if next = '[' || next = '<'
|
||||
|| (next >= 'A' && next <= 'Z') then
|
||||
(* Peek the full token to check if it's ALL_CAPS/brackets *)
|
||||
peek_string (min avail 80) >>= fun preview ->
|
||||
(* Extract the token after the single space *)
|
||||
let tok_start = 1 in
|
||||
let tok_end = ref tok_start in
|
||||
while !tok_end < String.length preview
|
||||
&& preview.[!tok_end] <> ' '
|
||||
&& preview.[!tok_end] <> '\n'
|
||||
&& preview.[!tok_end] <> '\r' do
|
||||
incr tok_end
|
||||
done;
|
||||
let tok = String.sub preview tok_start (!tok_end - tok_start) in
|
||||
(* Accept as placeholder if it starts with [ or < or is ALL_CAPS
|
||||
(possibly with dots, pipes, dashes) *)
|
||||
let is_placeholder =
|
||||
tok.[0] = '[' || tok.[0] = '<'
|
||||
|| String.for_all (fun c ->
|
||||
(c >= 'A' && c <= 'Z') || c = '_' || c = '-'
|
||||
|| c = '.' || c = '|' || c = ',' || (c >= '0' && c <= '9')
|
||||
) tok
|
||||
in
|
||||
if is_placeholder then
|
||||
advance (1 + String.length tok) *> self
|
||||
else return ()
|
||||
else return ()
|
||||
else return ())
|
||||
|
||||
let subcommand_entry =
|
||||
inline_ws *>
|
||||
take_while1 is_subcommand_char >>= fun name ->
|
||||
if String.length name < 2 then fail "subcommand name too short"
|
||||
else
|
||||
skip_arg_placeholders *>
|
||||
char ' ' *> char ' ' *> inline_ws *>
|
||||
rest_of_line <* eol >>| fun desc ->
|
||||
{ name = String.lowercase_ascii name;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue