Make the OCaml Arg.parse function take anonymous arguments starting with

I am trying to use Arg.parse

OCaml function to read command line options and arguments, including unspecified arguments starting with -

. According to the manual:

To enable the user to specify anonymous arguments that start with a -, include, for example, ("-", String anon_fun, doc)

in speclist

.

So I expect this example to work:

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:"

      

With the specified parameter -a

and other arguments, it works:

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

      

But that's not when trying to use something starting with -

:

$ 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

I would expect the function to be called other_option

. What am I doing wrong?

+3


source to share


1 answer


Usage ("-", String anon_fun, doc)

doesn't let you do what you think it does, it lets you enter parameters like this:

ocaml test.ml - -x

      

Basically, it does an "-"

"escaping" option, which will pass the next one to anon_fun.

The exact behavior you want cannot be easily accomplished with Arg

(which has never been considered an exhaustive argument parser AFAIK).



As a possible workaround, you can manually view your argv by hand (remember not to read 0

) and dynamically add the parameters to your list:

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

      

Another option is to get the code from Arg

and modify it to fit your model, or use another more powerful tool. Perhaps Cmdliner

- this is what you are looking for (I have never used it, so I don't know if it does the trick).

+4


source







All Articles