Command line parsing, the concept of publishing goals.
[goaljobs.git] / goaljobs.ml
index 282c29e..c68bc31 100644 (file)
@@ -128,6 +128,11 @@ let memory_set = Hashtbl.replace memory
 let memory_get k = try Some (Hashtbl.find memory k) with Not_found -> None
 let memory_delete = Hashtbl.remove memory
 
+let published_goals = ref []
+let publish name fn = published_goals := (name, fn) :: !published_goals
+let get_goal name =
+  try Some (List.assoc name !published_goals) with Not_found -> None
+
 let goal_file_exists filename =
   if not (file_exists filename) then (
     let msg = sprintf "file '%s' required but not found" filename in
@@ -154,3 +159,64 @@ let goal_memory_exists k =
     let msg = sprintf "memory_exists: key '%s' required but does not exist" k in
     goal_failed msg
   )
+
+(* Run the program. *)
+let init () =
+  let prog = Sys.executable_name in
+  let prog = Filename.basename prog in
+
+  let args = ref [] in
+
+  let display_version () =
+    printf "%s %s\n" Config.package_name Config.package_version;
+    exit 0
+  in
+
+  let list_goals () =
+    let names = !published_goals in
+    let names = List.map fst names in
+    let names = List.sort compare names in
+    List.iter print_endline names
+  in
+
+  let argspec = Arg.align [
+    "--goals", Arg.Unit list_goals, " List all goals";
+    "-l", Arg.Unit list_goals, " List all goals";
+    "-V", Arg.Unit display_version, " Display version number and exit";
+    "--version", Arg.Unit display_version, " Display version number and exit";
+  ] in
+  let anon_fun str = args := str :: !args in
+  let usage_msg = sprintf "\
+%s: a script generated by goaljobs
+
+List all goals:                %s -l
+Run a single goal like this:   %s <name-of-goal> [<goal-args ...>]
+
+For more information see the goaljobs(1) man page.
+
+Options:
+" prog prog prog in
+
+  Arg.parse argspec anon_fun usage_msg;
+
+  let args = List.rev !args in
+
+  (* Was a goal named on the command line? *)
+  match args with
+  | name :: args ->
+    (match get_goal name with
+    | Some fn -> fn args
+    | None ->
+      eprintf "error: no goal called '%s' was found.\n" name;
+      eprintf "Use %s -l to list all published goals in this script.\n" name;
+      exit 1
+    )
+  | [] ->
+    (* Does a published 'all' goal exist? *)
+    match get_goal "all" with
+    | Some fn -> fn []
+    | None ->
+      (* No published 'all' goal.  This is only a warning, because
+       * other top-level code may exist in the script.
+       *)
+      eprintf "warning: no 'all' goal found.\n"