ggetopt
A module for the
V programming language
Version 0.6
Features:
- V-like getopt() shim
- V-like getopt_long() shim
- Auto
--helpoutput generation
Installation
$ v install edam.ggetopt
Usage
The API has been kept in the spirit of GNU getopt library.
Short Options (very basic)
At its most basic, you can use
getopt()
import edam.ggetopt
struct Options {
mut:
verbose bool
name string = 'user'
}
fn main() {
mut opts := &Options{}
ggetopt.getopt_cli('vu:?', fn [mut opts] (arg string, val ?string) ! {
match arg {
'v' { opts.verbose = true }
'u' { opts.name = val or { '' } }
'?' { println('Usage: myprog [-v] [-u NAME] [-?]') exit(0) }
else {}
}
})!
if opts.verbose {
println('debug: printing name')
}
println('Hi ${opts.name}!')
}
Notes
-
getopt(args []string, options string, process_fn ProcessFn) ![]stringprocessed short opts and returns any unused arguments -
getopt_cli()just calls getopt(), passing in os.argsas the first argument.
Long Options (typical usage)
Defining long options is done in an array, just like
getopt_long()
The array of options (
OptDef
-
opt(long_name string, short_opt ?rune) OptDefis an option factory function -
(OptDef) arg(arg_name string, required bool) OptDefcan be used to extend an option, giving it an argument -
opt_help() OptDefis a factory function returning a standard --helpoption
import edam.ggetopt
const options = [
ggetopt.opt('user', `u`).arg('NAME', true),
ggetopt.opt('insult', `i`).arg('ADJECTIVE', false),
ggetopt.opt('verbose', none),
ggetopt.opt_help(),
]
@[heap]
struct Options {
mut:
name string = 'user'
insult ?string
verbose bool
}
fn (mut o Options) process_arg(arg string, val ?string) ! {
match arg {
'u', 'user' {
o.name = val or { '' }
}
'i', 'insult' {
o.insult = val or { 'stinky' }
}
'verbose' {
o.verbose = true
}
'help' {
ggetopt.print_help(options)
exit(0)
}
else {}
}
}
fn main() {
mut opts := Options{}
rest := ggetopt.getopt_long_cli(options, opts.process_arg) or {
ggetopt.die_hint(err)
}
if rest.len > 0 {
ggetopt.die_hint('extra arguments on command line')
}
if opts.verbose {
println('debug: printing message')
}
greet := if insult := opts.insult { 'Hi ${insult}' } else { 'Hello' }
println('${greet} ${opts.name}!')
}
Notes
-
print_help(options []OptDef, conf PrintConfig)can be used to automatically generate help for an array of OptDefs. PrintConfigcan be omitted. -
die[T](msg ...T)can be used to terminate with error (exit code 1) and print a message to stderr prefixed with the binary name, e.g.: myprog: some message. -
die_hint[T](msg ...T), as shown above, is the same as die()but also includes a message hinting the user to "Try myprog --helpfor more information."
OptDefs and Automatic Help (getting fancy!)
The array of
OptDef
print_help()
More of those array-building helpers:
-
(OptDef) help(text string) OptDefcan be used to extend an option and supplement it with help text -
text(lines ...string) OptDefis a factory function for a line of help text (i.e., not an option) -
opt_version() OptDefis a factory function returning a standard --versionoption
E.g.,
const options = [
ggetopt.text('Usage: ${ggetopt.prog()} [OPTION]... [MESSAGE]...')
ggetopt.text()
ggetopt.text('Options:')
ggetopt.opt('user', `u`).arg('NAME', true)
.help("provide the user's NAME")
ggetopt.opt('insult', `i`).arg('ADJECTIVE', false)
.help('insult the user (default: stinky)')
ggetopt.opt('verbose', none)
.help('show debug information')
ggetopt.opt_help()
]
If
options
--help
Usage: myprog [OPTION]... [MESSAGE]...
Options:
-u, --user=NAME provide the user's NAME
-i, --insult[=ADJECTIVE] insult the user (default: stinky)
--verbose show debug information
--help display this help and exit
Notes
-
print_version(version string, description []string, conf PrintConfig)also exists to complement print_help()and generates output for --version. PrintConfigcan be omitted. -
prog() string, as shown above, can be used to get the name of the binary (which it gets from os.args[0]).
Error handling
By default, GNU getopt writes errors to stderr. This is disabled by default in
the V wrapper, since errors are returned, and the recommendation is that you
display them yourself and exit with
die_hint()
If you want to turn on the default behaviour of the C getopt library back on, so that errors are automatically emitted to stderr, please note the following:
-
When turned on, some emitted errors have to be generated by the V wrapper where there is no equivalent in underlying C library, so this is still not "pure GNU getopt" behaviour.
-
In some cases, minimal difference exist between the errors returned and the ones emitted, so that all the errors are more consistent.
Notes
-
report_errors(enable bool)can use used to turn on/off automatic error emitting.
Development
Testing the module
$ v test .
Debugging
To dump GNU getopt library state, after each call to
getopt_long()
trace_ggetopt
$ v -d trace_ggetopt ...
Changes
0.1 - Initial version
0.2 - Renamed opt() fns; tests; help-gen improvements (wrapping, config)
0.3 - Added print_version(); fixed tests
0.4 - Added die(), prog(); fixed text(''); gen_wraped_lines() handles newlines; errors from process_fn() are eprintln()ed when reporting_errors(true)
0.5 - fix warnings; fix for lines starting with spaces
0.6 - fix returned non-option args; added die_hint(); rename trace_ggetopt; report_errors off by default; text(...string)
Licence
Copyright (C) 2023-2024 Tim Marston [email protected]