K.S.
K.S.

Reputation: 3199

Using ocaml Args in program

I'm trying to create an ocaml program where a user enters input similar to command line arguments, such as......

./program
$ -s foo -i 84
$ -s bar -i 22

...basically a simple menu program.

I was hoping to be able to use ocaml Args to do this (especially with the 'usage', etc built in), but I realize this is just for the command line. Is there a way to re-purpose this library to work for in-program user input, or is it better to hack something together from the Stream/Parser library or a different solution entirely?

Upvotes: 3

Views: 2486

Answers (2)

K.S.
K.S.

Reputation: 3199

Thanks to Jeffrey for the correct API call... Initially, I couldn't figure out how to use that call more than once (as in the values would get set to the first set you give ONLY), and the trick is you must use the optional argument ?current:(Some (ref 0)) to use the call more than once.

Here is my code if it helps anyone else (note I am NOT checking errors, etc):

(* default values *)
let somestr = ref ""
let someint = ref 0
let usage = "usage: set [-s string] [-d int]"

(* from http://rosettacode.org/wiki/Command-line_arguments#OCaml *)
let speclist = [
    ("-s", Arg.String (fun s -> somestr := s), ": follows -s sets some string");
    ("-d", Arg.Int    (fun d -> someint := d), ": some int parameter");
  ]

let parseinput userinp =
  (* Read the arguments *)
  Printf.printf "String:%s\n" (Array.get userinp 2);
  Arg.parse_argv ?current:(Some (ref 0)) userinp
    speclist
    (fun x -> raise (Arg.Bad ("Bad argument : " ^ x)))
    usage;
  Printf.printf "Set stuff to:   %d '%s'\n%!"  !someint !somestr 

let  parseit line =
  Printf.printf "processing %s%!\n" line;
  (* TODO rewrite without Str*)
  let listl = (Str.split (Str.regexp " ") line) in
  parseinput (Array.of_list listl)

let _ =
try
  while true do
    let line = input_line stdin in
    parseit line
  done;
  None
with
  End_of_file -> None

Compile:

ocamlc str.cma -o args args.ml

Commands to give it:

set -d 8332 -s lalalla
set -d 11111 -s fffffff

Upvotes: 3

Jeffrey Scofield
Jeffrey Scofield

Reputation: 66823

(Note that the module name is Arg, not Args.)

The function Arg.parse_argv seems to do exactly what you want if you're willing to write code to break the line into words.

(Note that in a Unix-like system it's the shell, not the Arg module, that breaks lines into words. So to use Arg this way you have to do what the shell would do.)

Upvotes: 5

Related Questions