使OCaml Arg.parse函数接受以。开头的匿名参数

时间:2015-04-30 11:47:57

标签: parsing ocaml

我正在尝试使用Arg.parse OCaml函数来读取命令行选项和参数,包括未指定以-开头的参数。根据手册:

  

要让用户能够指定以 - 开头的匿名参数,请在("-", String anon_fun, doc)中包含例如speclist

所以我希望这个例子有效:

let other_option x = Format.printf "Other option: %s@." x
let other_argument x = Format.printf "Other argument: %s@." x
let arg_speclist =[
 ("-a", Arg.Unit (fun () -> Format.printf "Known option: -a@."), "option a");
 ("-", Arg.String other_option, "any option")
]
let () = Arg.parse arg_speclist other_argument "Usage:"

使用指定的-a选项和其他参数,它正在运行:

$ ocaml test.ml arg1 -a arg2
Other argument: arg1
Known option: -a
Other argument: arg2

但尝试使用以-开头的内容时不是这样:

$ ocaml test.ml -x
test.ml: unknown option '-x'.
Usage:
  -a option a
  - any option
  -help  Display this list of options
  --help  Display this list of options

我希望调用other_option函数。 我做错了什么?

1 个答案:

答案 0 :(得分:4)

使用("-", String anon_fun, doc)并不允许您按照自己的想法行事,它允许您以这种方式输入选项:

ocaml test.ml - -x

基本上,它使"-"成为"逃避"将下一个传递给anon_fun的选项。

您想要的确切行为无法通过Arg轻松完成(这绝不是一个详尽的复杂参数解析器AFAIK)。

作为一种可能的解决方法,您可以先手动浏览argv(不要忘记阅读0)并动态地向您的规范列表中添加选项:

let speclist = [ ("-option", Arg.String print_endline, "handled option") ]
let speclist =
 let r = ref speclist in
 for i = 1 to pred (Array.length Sys.argv) do
  let s = Sys.argv.(i) in
  if s.[0] = '-' && not List.exists (fun (s',_,_) -> s = s') !r
  then r := (s, Arg.Unit (fun () -> anon_fun s), "any_option") :: !r
 done;
 !r

另一种选择是从Arg获取代码并根据您的模型进行修改,或使用其他更强大的工具。也许Cmdliner是您正在寻找的东西(我从未使用过它,所以我不知道它是否有效)。