Say someone is developing a package, and wants to include some command line interface. What are current best practices / ways to do this? My motivation here is twofold - I am actively working on such a project, and also would like to contribute to Modern Julia Workflows (cf. this issue).
Ideally, this guidance would be
- Currently supported - that is something can can be used with currently released julia features (eg not relying on juliac / Pkg support)
- Generic - that is not reliant on specific frameworks (eg Comonicon.jl) or argument parsing libraries (eg ArgParse.jl, Docopt.jl)
- Have a clear upgrade path for when juliac / App support does arrive.
Some things to consider:
- Code organization - CLI as a module included within package? Separate package?
bin/
directory inside package? - Installation - How to make cli calls available to users / accessible via PATH, etc?
- Precompilation / sysimages - how to reduce the latency for users?
- Upgrade paths - assuming a user already has an installation, how to replace it / make sure the latest version is installed?
As a provocation to get things going, lets say we want to add a CLI for Example.jl. One way to do this (this is how I’m doing it in my current project) - we can create Example.jl/bin/src/ExampleCLI.jl
that contains
module ExampleCLI
export main
using Example
function (@main)(ARGS)
if first(ARGS) == "hello"
println(hello(last(ARGS)))
elseif first(ARGS) == "domath"
num = parse(Int, last(ARGS))
println(domath(num))
else
throw(ArgumentError("Command $(first(ARGS)) not supported"))
end
return 0
end
end
Then create bin/Project.toml
with:
name = "ExampleCLI"
uuid = "9a0c4f26-9756-4254-a226-e60a319fd9cd"
[deps]
Example = "7876af07-990d-54b4-ab0e-23690620f79a"
[compat]
Example = "0.5.5"
And run
❯ julia --project=bin -e 'using Pkg; Pkg.instantiate()'
❯ julia --project=bin -e 'using ExampleCLI' domath 32
37
❯ julia --project=bin -e 'using ExampleCLI' hello world
Hello, world
So then, how would we precompile this or make a system image for it? How would we ask users to install it? How would we want to actually run it? Would you organize this differently?
Some related topics:
- How to PackageCompile ArgParse - #6 by mattother
- Tooling for Julia command-line scripts
- Organizing a project with a CLI - #2 by Tero_Frondelius
- Creating a CLI app in Julia
- Command line interface for the Julia language - a CLI tool (with a GUI future)
- https://discourse.julialang.org/t/comonicon-jl-fast-simple-and-light-weight-cli-generator/4374