diff --git a/infer/src/base/CommandDoc.ml b/infer/src/base/CommandDoc.ml index cff7ab7da..288f2a3ac 100644 --- a/infer/src/base/CommandDoc.ml +++ b/infer/src/base/CommandDoc.ml @@ -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 = exe_name_of_command cmd 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 let environment = Option.value environment_opt ~default:[`I (Printf.sprintf "$(b,%s), $(b,%s), $(b,%s)" @@ -94,8 +94,9 @@ let clang = ~synopsis:"$(b,InferClang) $(i,[clang options])" ~description:[`P "This is used internally by other infer commands. You shouldn't need to call \ this directly."] - ~options:[`P "Accepts the same command line options as $(b,clang)(1) (but still reads infer \ - options from the environment)."] + ~options:(`Replace + [`P "Accepts the same command line options as $(b,clang)(1) (but still reads infer \ + options from the environment)."]) ~see_also:CLOpt.[Capture] let compile = @@ -148,24 +149,26 @@ 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 \ manual. See their respective manuals for more information about each."; ] - ~options:[ - `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,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 \ - option may affect and thus be list in the manual of several commands."; - `P (Printf.sprintf - "Options are read from the $(b,%s) file, then from the $(b,%s) environment variable, \ - then from the command line. Options in $(b,%s) take precedence over options in \ - $(b,%s), and options passed on the command line take precedence over options in \ - $(b,%s). See the $(i,%s) and $(i,%s) sections of this manual for more information." - inferconfig_file CLOpt.args_env_var - CLOpt.args_env_var - inferconfig_file - CLOpt.args_env_var Cmdliner.Manpage.s_environment Cmdliner.Manpage.s_files - ); - ] + ~options:(`Prepend [ + `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,infer-run)(1). Otherwise, $(b,infer) behaves as $(b,infer-analyze)(1)."; + `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."; + `P (Printf.sprintf + "Options are read from the $(b,%s) file, then from the $(b,%s) environment variable, \ + then from the command line. Options in $(b,%s) take precedence over options in \ + $(b,%s), and options passed on the command line take precedence over options in \ + $(b,%s). See the $(i,%s) and $(i,%s) sections of this manual for more information." + inferconfig_file CLOpt.args_env_var + CLOpt.args_env_var + inferconfig_file + 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:[ `P (Printf.sprintf "Extra arguments may be passed to all infer commands using the $(b,%s) \ diff --git a/infer/src/base/CommandLineOption.ml b/infer/src/base/CommandLineOption.ml index a8ccf0495..c1b45df97 100644 --- a/infer/src/base/CommandLineOption.ml +++ b/infer/src/base/CommandLineOption.ml @@ -82,9 +82,12 @@ let all_commands = [ type command_doc = { title : Cmdliner.Manpage.title; - manual_pre_options : Cmdliner.Manpage.block list; - manual_options : Cmdliner.Manpage.block list option; - manual_post_options : Cmdliner.Manpage.block list; + manual_before_options : Cmdliner.Manpage.block list; + manual_options : [ + | `Prepend of Cmdliner.Manpage.block list + | `Replace of Cmdliner.Manpage.block list + ]; + manual_after_options : Cmdliner.Manpage.block list; } type desc = { @@ -158,6 +161,7 @@ module SectionMap = Caml.Map.Make (struct let help_sections_desc_lists = List.map all_commands ~f:(fun command -> (command, ref SectionMap.empty)) +let visible_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 @@ -173,7 +177,9 @@ let add parse_mode sections desc = sections := SectionMap.add section (desc::prev_contents) !sections in List.iter sections ~f:add_to_section; 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 = @@ -516,7 +522,7 @@ let mk_command_doc ~title ~section ~version ~date ~short_description ~synopsis ~ let add_if section blocks = match blocks with | None -> `Blocks [] | Some bs -> `Blocks (`S section :: bs) in - let manual_pre_options = [ + let manual_before_options = [ `S Cmdliner.Manpage.s_name; (* the format of the following line is mandated by man(7) *) `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; `Blocks description; ] 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_environment environment; add_if Cmdliner.Manpage.s_files files; @@ -537,7 +544,7 @@ let mk_command_doc ~title ~section ~version ~date ~short_description ~synopsis ~ ] in let command_doc = { 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 command_doc @@ -845,13 +852,10 @@ let show_manual ?internal_section format default_doc command_opt = doc_first_line) :: List.concat_map (List.concat_map ~f:(wrap_line indent_string width) doc_other_lines) ~f:(fun s -> [`Noblank; `Pre s]) in - let option_blocks = match command_doc.manual_options, command_opt with - | None, None -> - failwithf "Cannot create %s section" Cmdliner.Manpage.s_options - | Some blocks, _ -> + let option_blocks = match command_doc.manual_options with + | `Replace blocks -> `S Cmdliner.Manpage.s_options :: blocks - | None, Some command -> - let sections = List.Assoc.find_exn help_sections_desc_lists command in + | `Prepend blocks -> let hidden = match internal_section with | 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) | None -> [] in - SectionMap.fold (fun section descs result -> - `S section :: - List.concat_map ~f:block_of_desc (normalize_desc_list descs) @ result) - !sections hidden in - let blocks = [`Blocks command_doc.manual_pre_options; `Blocks option_blocks; - `Blocks command_doc.manual_post_options] 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 -> + `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) + !sections hidden + | None -> + `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); () diff --git a/infer/src/base/CommandLineOption.mli b/infer/src/base/CommandLineOption.mli index 6f782a447..d252471eb 100644 --- a/infer/src/base/CommandLineOption.mli +++ b/infer/src/base/CommandLineOption.mli @@ -167,15 +167,16 @@ type command_doc - [version] is the version string of the command - [date] is the date of the last modification of the manual - [short_description] is a one-line description of the command - - [options] if specified, will populate the OPTIONS section; otherwise, the options are taken - from the command's + - [options] can be either [`Replace blocks], which populates the OPTIONS section with [blocks], + 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]. Some are mandatory and some are not. *) val mk_command_doc : title:string -> section:int -> version:string -> date:string -> short_description:string -> synopsis: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 -> ?environment:Cmdliner.Manpage.block list -> ?files:Cmdliner.Manpage.block list -> diff --git a/infer/src/base/Config.ml b/infer/src/base/Config.ml index 447db1cd1..904c0ba4d 100644 --- a/infer/src/base/Config.ml +++ b/infer/src/base/Config.ml @@ -480,8 +480,7 @@ and ( ~suffix:"blacklist-path-regex" ~deprecated_suffix:["blacklist"] ~help:"blacklist the analysis of files whose relative path matches the specified OCaml-style \ - regex\n\ - (to whitelist: $(b,---whitelist-path-regex))" + regex (to whitelist: $(b,---whitelist-path-regex))" ~meta:"path regex", mk_filtering_options ~suffix:"whitelist-path-regex"