1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
|
(** Simple, portable command-line interface library
This library provides a clean API for building CLI applications with subcommands,
automatic help generation, and good error messages. It requires no external
dependencies and works with OCaml 4.01+.
{2 Example Usage}
{[
open Cli
let build_cmd = command "build"
~doc:"Compile the project"
~args:[
flag "verbose" ~short:'v' ~doc:"Show detailed output";
option_int "jobs" ~short:'j' ~doc:"Number of parallel jobs";
]
~run:(fun ctx ->
let verbose = get_flag ctx "verbose" in
let jobs = get_int ctx "jobs" ~default:2 in
Printf.printf "Building with %d jobs (verbose=%b)\\n" jobs verbose
)
let cli = app "myapp"
~version:"1.0.0"
~doc:"My awesome application"
~commands:[build_cmd]
let () = run cli
]}
*)
(** {1 Core Types} *)
(** Execution context containing parsed arguments *)
type context
(** Command specification *)
type command
(** Application specification *)
type app
(** {1 Argument Specifications} *)
(** Flag argument (boolean, no value required) *)
val flag :
string ->
?short:char ->
?env:string ->
doc:string ->
command -> command
(** [flag name ~short ~env ~doc cmd] adds a boolean flag to command [cmd].
- [name]: Long name (e.g., "verbose" for --verbose)
- [short]: Optional short name (e.g., 'v' for -v)
- [env]: Optional environment variable name to read default from
- [doc]: Help documentation string *)
(** String option (requires a value) *)
val option_string :
string ->
?short:char ->
?env:string ->
?default:string ->
?placeholder:string ->
doc:string ->
command -> command
(** [option_string name ~short ~env ~default ~placeholder ~doc cmd] adds a string option.
- [placeholder]: Shown in help (e.g., "PATH" for --output PATH) *)
(** Integer option (requires an integer value) *)
val option_int :
string ->
?short:char ->
?env:string ->
?default:int ->
?placeholder:string ->
doc:string ->
command -> command
(** Boolean option (requires true/false/yes/no/1/0 value) *)
val option_bool :
string ->
?short:char ->
?env:string ->
?default:bool ->
?placeholder:string ->
doc:string ->
command -> command
(** [option_bool name ~short ~env ~default ~placeholder ~doc cmd] adds a boolean option.
- Accepts values: true/false, yes/no, 1/0, on/off (case insensitive)
- [placeholder]: Shown in help (default: "true|false") *)
(** String list option (can be specified multiple times) *)
val option_strings :
string ->
?short:char ->
?env:string ->
?placeholder:string ->
doc:string ->
command -> command
(** Values accumulate when flag is used multiple times *)
(** Positional arguments *)
val positional :
string ->
?placeholder:string ->
doc:string ->
command -> command
(** [positional name ~placeholder ~doc cmd] adds a required positional argument *)
val positionals :
string ->
?placeholder:string ->
doc:string ->
command -> command
(** [positionals name ~placeholder ~doc cmd] adds optional positional arguments (list) *)
(** {1 Command Construction} *)
val command :
string ->
doc:string ->
?description:string ->
?args:(command -> command) list ->
run:(context -> unit) ->
unit ->
command
(** [command name ~doc ~description ~args ~run] creates a command.
- [name]: Command name (e.g., "build")
- [doc]: Short one-line documentation
- [description]: Optional longer description shown in help
- [args]: List of argument specifications
- [run]: Function to execute with parsed context *)
val command_with_subcommands :
string ->
doc:string ->
?description:string ->
commands:command list ->
command
(** [command_with_subcommands name ~doc ~description ~commands] creates a command
that has its own subcommands (e.g., "git remote add") *)
(** {1 Application Construction} *)
val app :
string ->
version:string ->
doc:string ->
?description:string ->
?global_args:(command -> command) list ->
?on_global_args:(context -> unit) ->
commands:command list ->
unit ->
app
(** [app name ~version ~doc ~description ~global_args ~on_global_args ~commands] creates the application.
- [name]: Application name
- [version]: Version string
- [doc]: Short description
- [description]: Longer description
- [global_args]: Global flags/options available to all commands
- [on_global_args]: Optional callback invoked with parsed global args before command execution
- [commands]: List of commands *)
(** {1 Execution} *)
val run : ?argv:string array -> app -> unit
(** [run ~argv app] parses arguments and executes the appropriate command.
If [argv] is not provided, uses [Sys.argv].
Exits with code 0 on success, non-zero on error. *)
val run_result : ?argv:string array -> app -> (unit, string) Compat.result
(** [run_result ~argv app] same as [run] but returns a result instead of exiting.
Useful for testing. *)
(** {1 Context Accessors} *)
(** Get boolean flag value *)
val get_flag : context -> string -> bool
(** Get optional string value *)
val get_string_opt : context -> string -> string option
(** Get string value with default *)
val get_string : context -> string -> default:string -> string
(** Get optional integer value *)
val get_int_opt : context -> string -> int option
(** Get integer value with default *)
val get_int : context -> string -> default:int -> int
(** Get optional boolean value *)
val get_bool_opt : context -> string -> bool option
(** Get boolean value with default *)
val get_bool : context -> string -> default:bool -> bool
(** Get list of strings (from repeated options or positionals) *)
val get_strings : context -> string -> string list
(** Get positional arguments *)
val get_positionals : context -> string list
(** {1 Error Handling} *)
exception Parse_error of string
(** Raised when argument parsing fails *)
exception Validation_error of string
(** Raised when argument validation fails *)
(** {1 Error Handling Utilities} *)
val format_error : string -> string
(** [format_error msg] formats an error message with context and suggestions *)
val format_suggestion : string list -> string
(** [format_suggestion similar] formats a "Did you mean" suggestion *)
(** {1 Utilities} *)
val version_flag : command -> command
(** Adds standard --version flag *)
val help_flag : command -> command
(** Adds standard -h/--help flag *)
val verbose_flag : command -> command
(** Adds standard -v/--verbose flag *)
val quiet_flag : command -> command
(** Adds standard -q/--quiet flag *)
(** {1 Advanced Features} *)
val set_exit_code : int -> unit
(** Set the exit code (default: 0 for success, 1 for error) *)
val get_command_name : context -> string
(** Get the name of the currently executing command *)
val print_help : app -> command option -> unit
(** Print help text for the app or a specific command *)
val suggest_command : app -> string -> string list
(** [suggest_command app name] returns similar command names using fuzzy matching *)
(** {1 Shell Completion} *)
val generate_bash_completion : app -> string
(** [generate_bash_completion app] generates a bash completion script *)
val generate_zsh_completion : app -> string
(** [generate_zsh_completion app] generates a zsh completion script *)
val generate_fish_completion : app -> string
(** [generate_fish_completion app] generates a fish completion script *)
(** {1 Configuration File Support} *)
type config
(** Configuration loaded from config files *)
val load_config : ?paths:string list -> unit -> config
(** [load_config ~paths ()] loads configuration from files.
If [paths] is not provided, searches in default locations:
- ./.obuildrc (project-specific config)
- ~/.obuildrc (user config)
Project-specific config takes precedence over user config. *)
val config_get_string : config -> string -> string option
(** [config_get_string config key] retrieves a string value from config *)
val config_get_int : config -> string -> int option
(** [config_get_int config key] retrieves an integer value from config *)
val config_get_bool : config -> string -> bool option
(** [config_get_bool config key] retrieves a boolean value from config *)
val run_with_config : ?argv:string array -> ?config:config -> app -> unit
(** [run_with_config ~argv ~config app] runs the app with config file defaults.
Config values are applied as defaults before parsing command-line arguments.
Command-line arguments override config file values. *)
|