Installation
As usual, e.g.
] add YAArguParser
Specification
We approximate the Microsoft command-line syntax. Optional arguments are surrounded by square brackets, values are surrounded by angle brackets (chevrons), and mutually exclusive items are separated by a vertical bar.
Usage
Apart from these usage examples (you find the complete sources in the./examples
folder), we suggest you also check the the testsuite ./test/runtests.jl
.
Example 1 - common usage
We first create an ArgumentParser
object, then add and parse our command-line arguments. We will automagically generate a usage
string from our key-value store of command-line arguments here, but is also possible to write your own help message instead.
using YAArguParser: ArgumentParser, add_argument!, add_example!, help, parse_args!, args_pairs, generate_usage!
function main()
ap = ArgumentParser(description="YAArguParser example.", add_help=true)
add_argument!(ap, "-h", "--help", type=Bool, default=false, description="Help switch.")
add_argument!(ap, "-i", "--input", type=String, default="filename.txt", description="Input file.")
add_argument!(ap, "-n", "--number", type=Int, default=0, description="Integer number.")
add_argument!(ap, "-v", "--verbose", type=Bool, default=false, description="Verbose mode switch.")
add_example!(ap, "julia $(ap.filename) --input dir/file.txt --number 10 --verbose")
add_example!(ap, "julia $(ap.filename) --help")
parse_args!(ap)
# get all arguments as NamedTuple
args = NamedTuple(args_pairs(ap))
# print the usage/help message in magenta if asked for help
args.help && help(ap, color="magenta")
# display the arguments
println(args)
# DO SOMETHING ELSE
return 0
end
main()
That is about as simple as it gets and closely follows Python's argparse
.
Example 2 - customized help
Now let's define a customized help message:
using YAArguParser
const usage = raw"""
Usage: main.jl --input <PATH> [--verbose] [--problem] [--help]
A Julia script with command-line arguments.
Options:
-i, --input <PATH> Path to the input file.
-v, --verbose Enable verbose message output.
-p, --problem Print the problem statement.
-h, --help Print this help message.
Examples:
$ julia main.jl --input dir/file.txt --verbose
$ julia main.jl --help
"""
function main()
ap = ArgumentParser(description="YAArguParser example.", add_help=true, color="cyan")
add_argument!(ap, "-h", "--help", type=Bool, default=false, description="Help switch.")
add_argument!(ap, "-i", "--input", type=String, default="filename.txt", description="Input file.")
add_argument!(ap, "-n", "--number", type=Int, default=0, description="Integer number.")
add_argument!(ap, "-v", "--verbose", type=Bool, default=false, description="Verbose mode switch.")
add_example!(ap, "julia $(ap.filename) --input dir/file.txt --number 10 --verbose")
add_example!(ap, "julia $(ap.filename) --help")
# add usage/help text from above
ap.usage = usage
parse_args!(ap)
# print the usage/help message in color defined in ap
help(ap)
# DO SOMETHING ELSE
return 0
end
main()
Example 3 - validating arguments
For Validator details, read Docstrings sections for RealValidator
, StrValidator
and validate
.
using YAArguParser
using YAArguParser: shell_split
function main()
ap = ArgumentParser(;
description="Command line options parser",
add_help=true,
color = "cyan",
)
add_argument!(ap, "-p", "--plotformat";
type=String,
default="PNG",
description="Accepted file format: PNG (default), PDF, SVG or NONE",
validator=StrValidator(; upper_case=true, patterns=["PNG", "SVG", "PDF", "NONE"]),
)
add_argument!(ap, "-n", "--number";
type=Int,
# an argument with a default value is optional, without - required
# default=nothing,
description="an integer value ranging from 0 to 42",
validator=RealValidator{Int}(; incl_ivls=[(0, 42)]),
)
add_example!(ap, "$(ap.filename) -n 1 --plotformat NONE")
add_example!(ap, "$(ap.filename) -n 1")
add_example!(ap, "$(ap.filename) --help")
# simulate supplied args
str = "-p SVG -n 33 --help"
args = shell_split(str)
parse_args!(ap; cli_args=args)
# get all arguments as NamedTuple
args = NamedTuple(args_pairs(ap))
# print the usage/help message in color defined during initialization, if asked for help
args.help && help(ap)
# display the arguments
println(args)
# DO SOMETHING with args
return ap
end
main()
Example 4 - custom parser, initparser
This example shows how to create a customized parser. Here, we create LegacyArgumentParser
type which is equivalent to ArgumentParser
of SimpleArgParse
. You see that by making our type a subtype of AbstractArgumentParser
we achieve a flattened access to the struct
properties. This is used by initparser
function, which simplifies initilalization of nested structs.
using YAArguParser
using YAArguParser: AbstractArgumentParser
@kwdef mutable struct LegacyArgumentParser <: AbstractArgumentParser
ap::ArgumentParser = ArgumentParser()
authors::Vector{String} = String[]
documentation::String = ""
repository::String = ""
license::String = ""
end
lp = initparser(LegacyArgumentParser; license="MIT", authors=["Eben60"], description="Example how to extend an argument parser")
@assert lp.ap.description == lp.description
Example 5 - positional arguments, custom validator, initparser
using Dates
using YAArguParser
using YAArguParser: AbstractValidator, warn_and_return
import YAArguParser: validate
@kwdef struct FullAgeValidator <: AbstractValidator
legal_age::Int = 18
end
function validate(v::Union{AbstractString, Date}, vl::FullAgeValidator)
birthdate = today()
try
birthdate = Date(v)
catch
return warn_and_return(v)
end
d = day(birthdate)
m = month(birthdate)
fullageyear = year(birthdate) + vl.legal_age
Date(fullageyear, m, d) > today() && return warn_and_return(v)
return (; ok=true, v=birthdate)
end
function askandget(pp; color=pp.color)
colorprint(pp.introduction, color)
colorprint(pp.prompt, color, false; bold=true)
answer = readline()
cli_args = Base.shell_split(answer)
parse_args!(pp; cli_args)
r = NamedTuple(args_pairs(pp))
if r.help
help(pp)
exit()
end
r.abort && exit()
return r
end
function main()
color = "cyan"
prompt = "legal age check> "
ask_full_age = let
pp = initparser(InteractiveArgumentParser;
description="Asking if one is of full age",
add_help=true,
color = color,
introduction="Are you of full legal age? Please type y[es] or n[o] and press <ENTER>",
throw_on_exception = true,
prompt=prompt,
)
add_argument!(pp, "-y", "--yes_no";
type=String,
positional=true,
description="Asking about legal age",
validator=StrValidator(; upper_case=true, starts_with=true, patterns=["yes", "no"]),
)
add_argument!(pp, "-a", "--abort",
type=Bool,
default=false,
description="Abort?",
)
add_example!(pp, "$(pp.prompt) y")
add_example!(pp, "$(pp.prompt) --abort")
add_example!(pp, "$(pp.prompt) --help")
pp
end
check_full_age = let
pp = initparser(InteractiveArgumentParser;
description="Checking if one is of full age",
add_help=true,
color=color,
throw_on_exception = true,
introduction="Please enter your birth date in the yyyy-mm-dd format",
prompt=prompt,
)
add_argument!(pp, "-d", "--birthdate";
type=Date,
positional=true,
description="Asking about legal age",
validator=FullAgeValidator(),
)
add_argument!(pp, "-a", "--abort",
type=Bool,
default=false,
description="Abort?",
)
add_example!(pp, "$(pp.prompt) 2000-02-29")
add_example!(pp, "$(pp.prompt) --abort")
add_example!(pp, "$(pp.prompt) --help")
pp
end
(; yes_no ) = askandget(ask_full_age)
yes = (yes_no == "YES")
yes || return false
(; birthdate) = askandget(check_full_age )
println("You appear to be of full age.")
return true
end
main()