Paweł Wieczorek avatar Paweł Wieczorek committed cac44dd Draft

Exception handling, usage as string, not io operation

Comments (0)

Files changed (6)

 open CommandTree.Type
 open CommandTree.Executor
-open CommandTree.GetOpt
 
 
 module AboutCommand = struct
 
 ;;
 
-execute_command_tree_v menu Sys.argv
+try
+    execute_command_tree_v menu Sys.argv
+with 
+    | Invalid_usage (lazyUsage, NoCommand) ->
+        print_endline (Lazy.force lazyUsage);
+        -1
+
+    | Invalid_usage (lazyUsage, UnknownCommand command_name) ->
+        Printf.printf "error: unknown command %s\n" command_name;
+        print_endline (Lazy.force lazyUsage);
+        -1
+
+    | Invalid_usage (lazyUsage, GetOptError message) ->
+        Printf.printf "error: %s\n" message;
+        print_endline (Lazy.force lazyUsage);
+        -1

src/CommandTree.mlpack

+Type
 GetOpt
-Type
 Executor
 
 open Type
 
-exception Unknown_command of string
-
 type tree
     = XLeaf of (module Command)
     | XNode of string * (string, tree) Hashtbl.t 
 
+type error
+    = GetOptError of string
+    | UnknownCommand of string
+    | NoCommand
+
+exception Invalid_usage of (string Lazy.t * error)
+
 (*********************************************************************************************************************
  * Hash table fillers
  ********************************************************************************************************************)
     hash_table
 
 (*********************************************************************************************************************
- * Printers
+ * showers
  ********************************************************************************************************************)
 
-let print_path = function
+let show_path = function
     | [] ->
         ""
 
         in
     let cmp (name1, _) (name2, _) = compare name1 name2 in
     let entries = List.sort cmp (Hashtbl.fold prepare_hashtbl_entry hash_table []) in
-    let print_entry (name, title) = Printf.sprintf " %-15s %s" name title in
-    String.concat "\n" (List.map print_entry entries)
+    let show_entry (name, title) = Printf.sprintf " %-15s %s" name title in
+    String.concat "\n" (List.map show_entry entries)
 
 let usage_of_node path hash_table = String.concat "\n"
-    [ "usage: " ^ print_path path
+    [ "usage: " ^ show_path path
     ; ""
     ; "List of available commands:"
     ; list_of_available_commands hash_table
 let usage_of_leaf path command_module = 
     let module Command  = (val command_module : Command) in
     String.concat "\n"
-    [ "usage: " ^ print_path path
+    [ "usage: " ^ show_path path
     ; ""
     ; Command.description
     ; ""
     ; GetOpt.usage_message Command.options
     ]
 
-let print_usage_of_node path hash_table =
-    print_endline (usage_of_node path hash_table)
+(*********************************************************************************************************************
+ * Exceptions
+ ********************************************************************************************************************)
 
-let print_usage_of_leaf path command_module =
-    print_endline (usage_of_leaf path command_module)
+let invalid_usage str error =
+    raise (Invalid_usage (str, error))
+
+let invalid_usage_of_node path hash_table error =
+    invalid_usage (lazy (usage_of_node path hash_table)) error
+
+let invalid_usage_of_leaf path command_module error =
+    invalid_usage (lazy (usage_of_leaf path command_module)) error
 
 (*********************************************************************************************************************
- * Entries
+ * Executor
  ********************************************************************************************************************)
 
 let execute_command path command_module passed_arguments =
     try
         let (flags, arguments) = GetOpt.getopt Command.options passed_arguments in
         Command.action flags arguments
-    with Invalid_usage str ->
-        print_usage_of_leaf path command_module;
-        -1
+    with GetOpt.Invalid_option str ->
+        invalid_usage_of_leaf path command_module (GetOptError str)
 
 let rec execute path hash_table = function
     | [] ->
-        print_usage_of_node path hash_table;
-        0
+        invalid_usage_of_node path hash_table (NoCommand)
 
     | command_name :: passed_arguments ->
         try
 
         with 
             | Not_found ->
-                print_usage_of_node path hash_table;
-                -1
+                invalid_usage_of_node path hash_table (UnknownCommand command_name)
                 
 
 (*********************************************************************************************************************
         execute [executable_name] hash_table passed_arguments
 
     | [] ->
-        print_usage_of_node [] hash_table;
-        0
+        invalid_usage_of_node [] hash_table (NoCommand)
 
 let execute_command_tree_v commands passed_arguments_v =
     let passed_arguments = Array.to_list passed_arguments_v in
  * Copyrights(C) 2012,2013 by Pawel Wieczorek <wieczyk at gmail>
  *)
 
+type error
+    = GetOptError of string
+    | UnknownCommand of string
+    | NoCommand
 
-exception Unknown_command of string
+exception Invalid_usage of (string Lazy.t * error)
 
 val execute_command_tree_v : Type.command_tree list -> string array -> int
 
 
 open Type
 
+exception Invalid_option of string
+
 (*********************************************************************************************************************
  * Helpers
  ********************************************************************************************************************)
  * Helpers
  ********************************************************************************************************************)
 
+let invalid_option str =
+    Invalid_option str
+
 let rec compute_flags mappings result = function
     | "--"::xs ->
         (List.rev result, xs)
     | x::xs when is_looking_like_option x ->
         begin match check_argument_in_mappings mappings x with
             | None ->
-                raise (Invalid_usage ("unknown option: " ^ x))
+                raise (Invalid_option ("unknown option: " ^ x))
 
             | Some (WithoutArgument (flag, _, _, _)) ->
                 compute_flags mappings (flag::result) xs
         compute_flags mappings (flag_func x :: result) xs
 
     | _ ->
-        raise (Invalid_usage ("argument required for: " ^ passed_argument))
+        raise (Invalid_option ("argument required for: " ^ passed_argument))
 
 
 (*********************************************************************************************************************
  * Types
  ********************************************************************************************************************)
 
-exception Invalid_usage of string
-
 type 'flag option_specification
     = WithArgument of (string -> 'flag) * string * char option * string option * string
     | WithoutArgument of 'flag * char option * string option * string
 
 end
 
-
-
 type command_tree
     = Leaf of (module Command)
     | Node of string * string * command_tree list
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.