[manual] list all supported options in `infer --help` and `infer --help-full`

Summary: It's useful to have all the options in a single man page for discoverability.

Reviewed By: mbouaziz

Differential Revision: D5028007

fbshipit-source-id: 37f8d2e
master
Jules Villard 8 years ago committed by Facebook Github Bot
parent d508b0880d
commit 6c3845257f

@ -38,7 +38,7 @@ let mk_command_doc ~see_also:see_also_commands ?and_also ?environment:environmen
let exe_names = List.map see_also_commands ~f:(fun cmd -> let exe_names = List.map see_also_commands ~f:(fun cmd ->
let exe = exe_name_of_command cmd in let exe = exe_name_of_command cmd in
Printf.sprintf "$(b,%s)(%d)" (Cmdliner.Manpage.escape exe) section) in Printf.sprintf "$(b,%s)(%d)" (Cmdliner.Manpage.escape exe) section) in
let suffix = match and_also with None -> "" | Some msg -> " " ^ msg in let suffix = Option.value ~default:"" and_also in
[`P (String.concat ~sep:", " exe_names ^ suffix)] in [`P (String.concat ~sep:", " exe_names ^ suffix)] in
let environment = Option.value environment_opt let environment = Option.value environment_opt
~default:[`I (Printf.sprintf "$(b,%s), $(b,%s), $(b,%s)" ~default:[`I (Printf.sprintf "$(b,%s), $(b,%s), $(b,%s)"
@ -94,8 +94,9 @@ let clang =
~synopsis:"$(b,InferClang) $(i,[clang options])" ~synopsis:"$(b,InferClang) $(i,[clang options])"
~description:[`P "This is used internally by other infer commands. You shouldn't need to call \ ~description:[`P "This is used internally by other infer commands. You shouldn't need to call \
this directly."] this directly."]
~options:[`P "Accepts the same command line options as $(b,clang)(1) (but still reads infer \ ~options:(`Replace
options from the environment)."] [`P "Accepts the same command line options as $(b,clang)(1) (but still reads infer \
options from the environment)."])
~see_also:CLOpt.[Capture] ~see_also:CLOpt.[Capture]
let compile = let compile =
@ -148,11 +149,10 @@ let infer = mk_command_doc ~title:"Infer Static Analyzer"
`P "Infer consists of a collection of tools referenced in the $(i,SEE ALSO) section of this \ `P "Infer consists of a collection of tools referenced in the $(i,SEE ALSO) section of this \
manual. See their respective manuals for more information about each."; manual. See their respective manuals for more information about each.";
] ]
~options:[ ~options:(`Prepend [
`P "If a compilation command is specified via the $(b,--) option or one of the \ `P "If a compilation command is specified via the $(b,--) option or one of the \
$(b,--clang-compilation-database[-escaped]) options, $(b,infer) behaves as \ $(b,--clang-compilation-database[-escaped]) options, $(b,infer) behaves as \
$(b,infer-run)(1). Otherwise, $(b,infer) behaves as $(b,infer-analyze)(1)."; $(b,infer-run)(1). Otherwise, $(b,infer) behaves as $(b,infer-analyze)(1).";
`P "See the manuals of individual infer commands for details about their supported options.";
`P "Every infer command accepts the arguments from all the other infer commands. The same \ `P "Every infer command accepts the arguments from all the other infer commands. The same \
option may affect and thus be list in the manual of several commands."; option may affect and thus be list in the manual of several commands.";
`P (Printf.sprintf `P (Printf.sprintf
@ -165,7 +165,10 @@ let infer = mk_command_doc ~title:"Infer Static Analyzer"
inferconfig_file inferconfig_file
CLOpt.args_env_var Cmdliner.Manpage.s_environment Cmdliner.Manpage.s_files CLOpt.args_env_var Cmdliner.Manpage.s_environment Cmdliner.Manpage.s_files
); );
] `P "See the manuals of individual infer commands for details about their supported \
options. The following is a list of all the supported options (see also \
$(b,--help-full) for options reserved for internal use).";
])
~environment:[ ~environment:[
`P (Printf.sprintf `P (Printf.sprintf
"Extra arguments may be passed to all infer commands using the $(b,%s) \ "Extra arguments may be passed to all infer commands using the $(b,%s) \

@ -82,9 +82,12 @@ let all_commands = [
type command_doc = { type command_doc = {
title : Cmdliner.Manpage.title; title : Cmdliner.Manpage.title;
manual_pre_options : Cmdliner.Manpage.block list; manual_before_options : Cmdliner.Manpage.block list;
manual_options : Cmdliner.Manpage.block list option; manual_options : [
manual_post_options : Cmdliner.Manpage.block list; | `Prepend of Cmdliner.Manpage.block list
| `Replace of Cmdliner.Manpage.block list
];
manual_after_options : Cmdliner.Manpage.block list;
} }
type desc = { type desc = {
@ -158,6 +161,7 @@ module SectionMap = Caml.Map.Make (struct
let help_sections_desc_lists = let help_sections_desc_lists =
List.map all_commands ~f:(fun command -> (command, ref SectionMap.empty)) List.map all_commands ~f:(fun command -> (command, ref SectionMap.empty))
let visible_descs_list = ref []
let hidden_descs_list = ref [] let hidden_descs_list = ref []
(** add [desc] to the one relevant parse_tag_desc_lists for the purposes of parsing, and, in the (** add [desc] to the one relevant parse_tag_desc_lists for the purposes of parsing, and, in the
@ -173,7 +177,9 @@ let add parse_mode sections desc =
sections := SectionMap.add section (desc::prev_contents) !sections in sections := SectionMap.add section (desc::prev_contents) !sections in
List.iter sections ~f:add_to_section; List.iter sections ~f:add_to_section;
if List.is_empty sections then if List.is_empty sections then
hidden_descs_list := desc :: !hidden_descs_list; hidden_descs_list := desc :: !hidden_descs_list
else
visible_descs_list := desc :: !visible_descs_list;
() ()
let deprecate_desc parse_mode ~long ~short ~deprecated desc = let deprecate_desc parse_mode ~long ~short ~deprecated desc =
@ -516,7 +522,7 @@ let mk_command_doc ~title ~section ~version ~date ~short_description ~synopsis ~
let add_if section blocks = match blocks with let add_if section blocks = match blocks with
| None -> `Blocks [] | None -> `Blocks []
| Some bs -> `Blocks (`S section :: bs) in | Some bs -> `Blocks (`S section :: bs) in
let manual_pre_options = [ let manual_before_options = [
`S Cmdliner.Manpage.s_name; `S Cmdliner.Manpage.s_name;
(* the format of the following line is mandated by man(7) *) (* the format of the following line is mandated by man(7) *)
`Pre (Printf.sprintf "%s - %s" command_str short_description); `Pre (Printf.sprintf "%s - %s" command_str short_description);
@ -525,7 +531,8 @@ let mk_command_doc ~title ~section ~version ~date ~short_description ~synopsis ~
`S Cmdliner.Manpage.s_description; `S Cmdliner.Manpage.s_description;
`Blocks description; `Blocks description;
] in ] in
let manual_post_options = [ let manual_options = Option.value ~default:(`Prepend []) options in
let manual_after_options = [
add_if Cmdliner.Manpage.s_exit_status exit_status; add_if Cmdliner.Manpage.s_exit_status exit_status;
add_if Cmdliner.Manpage.s_environment environment; add_if Cmdliner.Manpage.s_environment environment;
add_if Cmdliner.Manpage.s_files files; add_if Cmdliner.Manpage.s_files files;
@ -537,7 +544,7 @@ let mk_command_doc ~title ~section ~version ~date ~short_description ~synopsis ~
] in ] in
let command_doc = { let command_doc = {
title = command_str, section, date, version, title; title = command_str, section, date, version, title;
manual_pre_options; manual_options = options; manual_post_options; manual_before_options; manual_options; manual_after_options;
} in } in
command_doc command_doc
@ -845,13 +852,10 @@ let show_manual ?internal_section format default_doc command_opt =
doc_first_line) doc_first_line)
:: List.concat_map (List.concat_map ~f:(wrap_line indent_string width) doc_other_lines) :: List.concat_map (List.concat_map ~f:(wrap_line indent_string width) doc_other_lines)
~f:(fun s -> [`Noblank; `Pre s]) in ~f:(fun s -> [`Noblank; `Pre s]) in
let option_blocks = match command_doc.manual_options, command_opt with let option_blocks = match command_doc.manual_options with
| None, None -> | `Replace blocks ->
failwithf "Cannot create %s section" Cmdliner.Manpage.s_options
| Some blocks, _ ->
`S Cmdliner.Manpage.s_options :: blocks `S Cmdliner.Manpage.s_options :: blocks
| None, Some command -> | `Prepend blocks ->
let sections = List.Assoc.find_exn help_sections_desc_lists command in
let hidden = let hidden =
match internal_section with match internal_section with
| Some section -> | Some section ->
@ -859,11 +863,19 @@ let show_manual ?internal_section format default_doc command_opt =
:: List.concat_map ~f:block_of_desc (normalize_desc_list !hidden_descs_list) :: List.concat_map ~f:block_of_desc (normalize_desc_list !hidden_descs_list)
| None -> | None ->
[] in [] in
match command_opt with
| Some command ->
let sections = List.Assoc.find_exn help_sections_desc_lists command in
SectionMap.fold (fun section descs result -> SectionMap.fold (fun section descs result ->
`S section :: `S section ::
(if String.equal section Cmdliner.Manpage.s_options then blocks else []) @
List.concat_map ~f:block_of_desc (normalize_desc_list descs) @ result) List.concat_map ~f:block_of_desc (normalize_desc_list descs) @ result)
!sections hidden in !sections hidden
let blocks = [`Blocks command_doc.manual_pre_options; `Blocks option_blocks; | None ->
`Blocks command_doc.manual_post_options] in `S Cmdliner.Manpage.s_options :: blocks @
List.concat_map ~f:block_of_desc (normalize_desc_list !visible_descs_list) @
hidden in
let blocks = [`Blocks command_doc.manual_before_options; `Blocks option_blocks;
`Blocks command_doc.manual_after_options] in
Cmdliner.Manpage.print format Format.std_formatter (command_doc.title, blocks); Cmdliner.Manpage.print format Format.std_formatter (command_doc.title, blocks);
() ()

@ -167,15 +167,16 @@ type command_doc
- [version] is the version string of the command - [version] is the version string of the command
- [date] is the date of the last modification of the manual - [date] is the date of the last modification of the manual
- [short_description] is a one-line description of the command - [short_description] is a one-line description of the command
- [options] if specified, will populate the OPTIONS section; otherwise, the options are taken - [options] can be either [`Replace blocks], which populates the OPTIONS section with [blocks],
from the command's or [`Prepend blocks], in which case the options from the command are used, prepended by
[blocks]. If unspecified it defaults to [`Prepend []].
- All the other [section_name] options correspond to the contents of the section [section_name]. - All the other [section_name] options correspond to the contents of the section [section_name].
Some are mandatory and some are not. Some are mandatory and some are not.
*) *)
val mk_command_doc : title:string -> section:int -> version:string -> date:string -> val mk_command_doc : title:string -> section:int -> version:string -> date:string ->
short_description:string -> synopsis:Cmdliner.Manpage.block list -> short_description:string -> synopsis:Cmdliner.Manpage.block list ->
description:Cmdliner.Manpage.block list -> description:Cmdliner.Manpage.block list ->
?options:Cmdliner.Manpage.block list -> ?options:[`Prepend of Cmdliner.Manpage.block list | `Replace of Cmdliner.Manpage.block list] ->
?exit_status:Cmdliner.Manpage.block list -> ?exit_status:Cmdliner.Manpage.block list ->
?environment:Cmdliner.Manpage.block list -> ?environment:Cmdliner.Manpage.block list ->
?files:Cmdliner.Manpage.block list -> ?files:Cmdliner.Manpage.block list ->

@ -480,8 +480,7 @@ and (
~suffix:"blacklist-path-regex" ~suffix:"blacklist-path-regex"
~deprecated_suffix:["blacklist"] ~deprecated_suffix:["blacklist"]
~help:"blacklist the analysis of files whose relative path matches the specified OCaml-style \ ~help:"blacklist the analysis of files whose relative path matches the specified OCaml-style \
regex\n\ regex (to whitelist: $(b,--<analyzer>-whitelist-path-regex))"
(to whitelist: $(b,--<analyzer>-whitelist-path-regex))"
~meta:"path regex", ~meta:"path regex",
mk_filtering_options mk_filtering_options
~suffix:"whitelist-path-regex" ~suffix:"whitelist-path-regex"

Loading…
Cancel
Save