Last active
April 6, 2022 18:19
-
-
Save jtpaasch/fdc9283a04baed6d00788484d1ca37d2 to your computer and use it in GitHub Desktop.
A simple example of using Cmdliner to create a command line tool
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(executable | |
(name main) | |
(libraries findlib.dynload bap)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(lang dune 3.0) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(** A simple example of using [Cmdliner]. | |
The basic idea is that you have a function you want to run (in the code | |
below, that function is [App.run]). That function might require arguments | |
(in the code below, [App.run] takes an optional string (a username). | |
With [Cmdliner], you declare the arguments you want to collect from the | |
command line, then you declare a "runner" (which the [Cmdliner] | |
documentation calls a "term"). Basically, a "runner" runs your function | |
(i.e., [App.run]) with the arguments it collects from the command line. | |
For more, see the documentation: | |
https://erratique.ch/software/cmdliner/doc/ | |
*) | |
module App = struct | |
(* A simple app. This just prints an optional username given to it. *) | |
let run (username : string option) : unit = | |
Printf.printf "username: %s\n%!" | |
(match username with | |
| Some s -> s | |
| None -> "none given") | |
end | |
module Cli = struct | |
open Cmdliner | |
(* The following declares some info for the tool's help and manpage. *) | |
let version = "00" | |
let name = "tool" | |
let doc = "A simple command line tool" | |
let man = [ | |
`S Manpage.s_description; | |
`P "This is the bit where we give a general description | |
of what this command line tool does."; | |
`P "We can put in multiple paragraphs of text here | |
but I'm actually not going to do that."; | |
`S Manpage.s_examples; | |
`P "I could give some examples here:"; | |
`Pre "let foo = bar + 2"; | |
] | |
let info = Cmd.info name ~doc ~man ~version | |
(* This declares a [-u foo] or [--username foo] command line argument. *) | |
let username = | |
let info = Arg.info ["u"; "username"] | |
~docv:"USERNAME" | |
~doc:"A username" | |
in | |
let parser = Arg.some Arg.string in | |
let default = None in | |
Arg.value (Arg.opt parser default info) | |
(* This creates a "runner," i.e., it parses the command line args and then | |
it feeds the parsed values as arguments into a specified function. | |
Here, we want to execute [App.run], but give it the value from the | |
the parsed [username] argument given on the command line. To declare | |
that, we define a [Term], where [const App.run] is the function we | |
want to execute, and then [$ username] says that the next argument | |
given to [App.run] should be the one we got from [username]. *) | |
let runner = Term.(const App.run $ username) | |
(* This declares the command. *) | |
let cmd = Cmd.v info runner | |
end | |
let () = exit (Cmdliner.Cmd.eval Cli.cmd) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
TOOL := main.exe | |
##################################################### | |
# DEFAULT | |
##################################################### | |
.DEFAULT_GOAL := all | |
all: clean run | |
##################################################### | |
# THE TOOL | |
##################################################### | |
.PHONY: clean | |
clean: | |
dune clean | |
build: | |
dune build ./$(TOOL) | |
run: build | |
dune exec ./$(TOOL) -- -u dudleydoolittle |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
To run this, put the above files in a directory, then run
make
.