Parcourir la source

Add ability to parse id sequences to subcommands

 + Types and helper function placed in id_sequences since it's closely
 related to this module, whereas command_def deals with interface
 definition more specifically.
 + The helper function may be generalised to other types than int if
 necessary, though ids are integers and those do not require anything
 else.
 + Indentation and subcommands documentation need to be improved
 + A shorthand for helper function will be applied.
Leo il y a 8 ans
Parent
commit
da65332d47
4 fichiers modifiés avec 48 ajouts et 20 suppressions
  1. 2 0
      CHANGELOG.md
  2. 23 20
      src/command_def.ml
  3. 21 0
      src/id_parsing.ml
  4. 2 0
      src/id_parsing.mli

+ 2 - 0
CHANGELOG.md

@@ -39,6 +39,8 @@ This version introduce major changes in the tmp and rc file.
  + Improve **edit subcommand** (explain how to use to add commands, improve
    messages, offer to reedit when nothing was done).
  + Improve **delete subcommand**, asking for confirmation before deleting.
+ + Allow *most subcommand* (in fact every subcommand for which it makes sense) to
+   parse lists of entries ids like **1,4-8,10**
 
 #### Minor
 

+ 23 - 20
src/command_def.ml

@@ -45,6 +45,9 @@ type return_arg = {
   rc : Settings_t.rc_file Lazy.t;
 }
 
+(* Shorthand *)
+let id_seq = Id_parsing.id_sequence;;
+
 (* A set of default arguments, usable with most of the commands *)
 let shared_params =
   let open Param in
@@ -133,7 +136,7 @@ let reset =
       empty
       +> shared_params
       +> anon ("target_number" %: int)
-      +> anon (maybe ("command_number" %: int))
+      +> anon (maybe ("command_number" %: id_seq))
     )
     (fun { rc } num cmd () ->
        (* Call the right function, according to optionnal argument.
@@ -144,8 +147,9 @@ let reset =
         * num: number to reset *)
        let rc = Lazy.force rc in
        match ( num, cmd ) with
-       | ( num, Some cmd ) -> Tmp_file.reset_cmd ~rc num cmd
-       | ( num, None ) -> Tmp_file.reset2num ~rc num
+       | ( num, None ) | ( num, Some [] ) -> Tmp_file.reset2num ~rc num
+       | ( num, Some cmd_list ) ->
+           List.iter ~f:(fun cmd -> Tmp_file.reset_cmd ~rc num cmd) cmd_list
     )
 ;;
 let reset_all =
@@ -201,11 +205,11 @@ let add =
     Spec.(
       empty
       +> shared_params
-      +> anon (maybe ("number" %: int))
+      +> anon (maybe ("number" %: id_seq))
     )
-    (fun { rc } num_cmd () ->
+    (fun { rc } cmd_seq () ->
        let rc = Lazy.force rc in
-       Add_command.run ~rc num_cmd
+       Id_parsing.helper ~f:(fun num_cmd -> Add_command.run ~rc num_cmd) cmd_seq
     )
 ;;
 
@@ -217,12 +221,13 @@ let delete =
     Spec.(
       empty
       +> shared_params
-      +> anon (maybe ("command_number" %: int))
+      +> anon (maybe ("command_number" %: id_seq))
     )
-    (fun { rc } num_cmd () ->
+    (fun { rc } cmd_seq () ->
        let rc = Lazy.force rc in
-       (*Tmp_file.reset ~rc reset_cmd 0)*)
-       Remove_command.run ~rc num_cmd)
+       Id_parsing.helper
+         ~f:(fun num_cmd ->
+           Remove_command.run ~rc num_cmd) cmd_seq)
 ;;
 
 (* To display current state *)
@@ -248,15 +253,16 @@ let edit =
     Spec.(
       empty
       +> shared_params
-      +> anon (maybe ("command_number" %: int))
+      +> anon (maybe ("command_number" %: id_seq))
     )
-    (fun { rc } n () ->
+    (fun { rc } cmd_seq () ->
        let rc = Lazy.force rc in
+       Id_parsing.helper cmd_seq ~f:(fun n ->
        let position =
          Option.value n
            ~default:(List.length (rc.Settings_t.progs) - 1)
        in
-       Edit_command.run ~rc position)
+       Edit_command.run ~rc position))
 ;;
 
 (* To display informations about the licence *)
@@ -283,15 +289,12 @@ let default =
     Spec.(
       empty
       +> shared_params
-      +> anon (maybe (sequence ("command_number" %: int)))
+      +> anon (maybe ("command_number" %: id_seq))
     )
-    (fun { rc } n_list () ->
+    (fun { rc } cmd_seq () ->
        let rc = Lazy.force rc in
-       (* XXX Manually dealing with the None case to make sure we are running
-        * next command if nothing is given *)
-       match n_list with None -> Default.run ~rc None
-       | Some n_list ->
-           List.iter n_list ~f:(fun n -> Default.run ~rc (Some n)))
+       Id_parsing.helper cmd_seq ~f:(fun n -> Default.run ~rc n)
+    )
 
 let run ~version ~build_info () =
   (* Store begin time *)

+ 21 - 0
src/id_parsing.ml

@@ -99,3 +99,24 @@ let list_from_human human =
     Unique a -> a | _ -> assert false)
   |> Tools.spy1_list ~f:Int.to_string
 ;;
+
+(* Type for command line parsing, an "id sequence" is something like 1,3-6,10 *)
+let id_sequence =
+  Command.Spec.Arg_type.create list_from_human
+;;
+
+(* With id sequences, we get None or Some [] from command line instructions and
+ * we get Some list in other cases. With this function, we iterate (over a list
+ * of ids) call of function having the following behavior:
+   * - Default value when nothing is given (None)
+   * - Execute things one by one *)
+let helper ~f = function
+  | None | Some [] ->
+      Messages.debug "Nothing given, default behavior";
+      (f None)
+  | Some li ->
+      Messages.debug "Working with the following arguments:";
+      Tools.spy1_list ~f:Int.to_string li |> ignore;
+      List.iter ~f:(fun element -> f (Some element)) li
+;;
+

+ 2 - 0
src/id_parsing.mli

@@ -37,3 +37,5 @@
 open Core.Std;;
 
 val list_from_human : string -> int list
+val id_sequence : int list Command.Spec.Arg_type.t
+val helper : f:(int option -> unit) -> int list option -> unit