Global CLI flag in OCaml Core.Command

151 Views Asked by At

I am currently creating a CLI application in OCaml and using Core.Command, the CLI parser included in core (v0.10), to parse the command line.

I want to have a global flag that can be used for any subcommand (like the --paginate or --git-dir flags in git for example).

For instance, I want a -debug flag so that the two following commands are valid

my-cli -debug hello world
my-cli -debug goodbye world

However, I could not find a way to do this with the Core.Command API.

Here is a simplified version what I currently have.

open Core

let initialize_logger debug =
  Logs.set_reporter (Logs_fmt.reporter ());
  let log_level = if debug then Logs.Debug else Logs.Info in
  Logs.set_level (Some log_level)

let some_func_with_logging () =
  Logs.debug (fun m -> m "the flag debug was passed!")

let hello name =
  some_func_with_logging ();
  Printf.printf "Hello %s!\n" name

let goodbye name =
  some_func_with_logging ();
  Printf.printf "Goodbye %s!\n" name

let hello_command = 
  let open Command.Let_syntax in
  Command.basic
    ~summary:"says hello"
    [%map_open
      let name = anon ("name" %: string)
      and debug = flag "debug" no_arg ~doc:"debug" in
      fun () ->
        initialize_logger debug;
        hello name
    ]

let goodbye_command =
  let open Command.Let_syntax in
  Command.basic
    ~summary:"says goodbye"
    [%map_open
      let name = anon ("name" %: string)
      and debug = flag "debug" no_arg ~doc:"debug" in
      fun () ->
        initialize_logger debug;
        goodbye name
    ]

let main_command =
  Command.group ~summary:"a cool CLI tool"
    [ ("hello", hello_command);
      ("goodbye", goodbye_command);
    ]

let () = Command.run main_command

There are two main issues here:

  1. the debug flag as well as the call to initialize_logger is duplicated in every subcommand
  2. the debug flag needs to be passed after the subcommand when invoking the command: my-cli hello world -debug instead of my-cli -debug hello world

Is there a clean way to handle this with Core.Command API?

0

There are 0 best solutions below