Appearance
Subcommands
FLAP builds git-style interfaces, where a program dispatches on a named command: fake_git commit -m "fix", fake_git tag -a v1. In FLAP's own terms a command is a group of command line arguments.
Concepts
- The top level (the unnamed group) holds the arguments given before any command name.
- Each command is a named group with its own arguments, its own help and its own builtins (
--help, ...). - The arguments after a command name belong to that command, up to the next command name.
- Commands are not nested: a command has no subcommands of its own. A command line can call several commands, one after the other (
fake_git init commit -m first), each at most once;set_mutually_exclusive_groupsforbids a pair.
f90
call cli%init(progname = 'fake_git', &
version = 'v2.1.5', &
authors = 'Stefano Zaghi', &
license = 'MIT', &
description = 'A toy git-like program demonstrating FLAP', &
examples = ['fake_git --help ', &
'fake_git init ', &
'fake_git commit -m "fix bug #1"', &
'fake_git tag -a "v2.1.5" '])
! a top-level option
call cli%add(switch='--authors', switch_ab='-a', help='Print the authors', required=.false., act='store_true', &
def='.false.', error=error)
! the commands
call cli%add_group(group='init', description='Initialise versioning')
call cli%add_group(group='commit', description='Commit changes to the current branch')
call cli%add_group(group='tag', description='Tag the current commit')
! the options of the commands
call cli%add(group='commit', switch='--message', switch_ab='-m', help='Commit message', required=.false., act='store', &
def='', error=error)
call cli%add(group='tag', switch='--annotate', switch_ab='-a', help='Tag annotation', required=.false., act='store', &
def='', error=error)$ fake_git --help
usage: fake_git [--authors] [--help] [--markdown] [--version] {init,commit,tag} ...
A toy git-like program demonstrating FLAP
Optional switches:
--authors, -a
default value .false.
Print the authors
--help, -h
Print this help message
--markdown, -md
Save this help message in a Markdown file
--version, -v
Print version
Commands:
init
Initialise versioning
commit
Commit changes to the current branch
tag
Tag the current commit
For more detailed commands help try:
fake_git init -h,--help
fake_git commit -h,--help
fake_git tag -h,--help
Examples:
fake_git --help
fake_git init
fake_git commit -m "fix bug #1"
fake_git tag -a "v2.1.5"Each command has its own help:
$ fake_git commit --help
usage: fake_git commit [--message value] [--help] [--markdown] [--version]
Commit changes to the current branch
Optional switches:
--message value, -m value
Commit message
--help, -h
Print this help message
--markdown, -md
Save this help message in a Markdown file
--version, -v
Print versionAdding a command — cli%add_group
fortran
call cli%add_group(group, description, help, exclude, examples, no_args_is_help, deprecated, aliases, error)| Argument | Type | Purpose |
|---|---|---|
group | character(*) | The command name |
description | character(*), optional | Shown in the top-level help and in the help of the command |
help | character(*), optional | Text before the usage line of the command (default 'usage: ') |
examples | character(*), dimension(:), optional | Examples shown in the help of the command |
exclude | character(*), optional | A command that cannot be called together with this one (as set_mutually_exclusive_groups) |
no_args_is_help | logical, optional | prog <command> alone prints the help of the command (STATUS_NO_ARGS) |
deprecated | character(*), optional | The command is deprecated: calling it prints a warning (see Advanced) |
aliases | character(*), optional | Other names of the command, comma separated (see Aliases) |
error | integer, optional | Error code (0 = success) |
The arguments of a command are added with group=; add creates the command if it does not exist yet.
Which command was called — cli%run_command
cli%run_command('commit') is .true. when the command (or one of its aliases) is on the command line:
f90
call cli%parse(error=error)
if (error /= 0) stop 1, quiet=.true.
call cli%get(switch='-a', val=authors, error=error)
if (authors) print '(A)', 'Authors: '//cli%authors
if (cli%run_command('init')) print '(A)', 'Initialising versioning'
if (cli%run_command('commit')) then
call cli%get(group='commit', switch='-m', val=message, error=error)
print '(A)', 'Committing with message: "'//trim(message)//'"'
endif
if (cli%run_command('tag')) then
call cli%get(group='tag', switch='-a', val=annotation, error=error)
print '(A)', 'Tagging with annotation: "'//trim(annotation)//'"'
endif$ fake_git commit -m "fix bug"
Committing with message: "fix bug"$ fake_git init commit -m first
Initialising versioning
Committing with message: "first"Values that look like command names
A value is never mistaken for a command: in fake_git commit -m tag the message is tag and the tag command is not called, because -m takes exactly one value. This holds for every option with a fixed number of values (one value, or nargs='N'). A list with a variable number of values (nargs='+' or nargs='*') ends at the first command name: in prog --files a b init, the list is a b and init is called.
$ fake_git commit -m tag
Committing with message: "tag"A command passed twice (directly, or through an alias) is ERROR_COMMAND_REPEATED (1013), reported before --help:
$ fake_git commit -m x commit
fake_git: error: the command "commit" is passed more than once!
Try 'fake_git --help' for help.
[exit status 1]An unknown command gets the closest names as suggestions:
$ fake_git comit
fake_git: error: argument "comit" is unknown! Did you mean "commit"?
Try 'fake_git --help' for help.
[exit status 1]Aliases
aliases gives a command other names: invoking an alias is invoking the command.
f90
call cli%add_group(group='compile', aliases='co, c', description='Compile the sources')
call cli%add_group(group='link', description='Link the objects')Every query accepts an alias too: run_command('co') is run_command('compile'), get(group='co', ...) reads the compile options, and mutually exclusive commands can be declared through an alias. The help lists compile, co, c under Commands:, and the completion scripts offer the aliases. With init(case_insensitive=.true.) aliases match in any case, as command names do.
An alias equal to a command name or to another alias, repeated, blank, or equal to its own command, and a command name equal to an existing alias, are ERROR_GROUP_ALIAS (1008): printed, returned by error=, and kept on the command, so that parse fails too.
Reusable option sets — cli%copy_options
fortran
call cli%copy_options(to_group, from_group, switches, pref, error)Options defined once (at the top level by default, or in from_group) are copied into a command:
f90
! defined once at the top level, then copied into the commands
call cli%add(switch='--jobs', switch_ab='-j', help='Parallel jobs', required=.false., act='store', def='1')
call cli%add(switch='--verbose', help='Verbose', required=.false., act='store_true', def='.false.')
call cli%copy_options(to_group='compile') ! --jobs and --verbose
call cli%copy_options(to_group='link', switches='--verbose') ! --verbose only$ aliases co -j 4 link --verbose
compile, jobs = 4
link, verbose = T$ aliases compile --help
usage: aliases compile [--jobs value] [--verbose] [--help] [--markdown] [--version]
Compile the sources
Optional switches:
--jobs value, -j value
default value 1
Parallel jobs
--verbose
default value .false.
Verbose
--help, -h
Print this help message
--markdown, -md
Save this help message in a Markdown file
--version, -v
Print version- The definitions are copied by value, at the call: help, action, default,
nargs, choices, envvar, hidden, negation, range, map, path checks, deprecation, ... Later changes to the source do not propagate. - Each copy has its own value:
compile -j 4sets the--jobsofcompileonly. - Only named options are copied; the builtins never (each command has its own). Naming a positional in
switchesisERROR_COPY_POSITIONAL(1009), an unknown nameERROR_MISSING_CLA(nothing is copied then), an unknown groupERROR_MISSING_GROUP; a switch the target already defines is the group consistency error (100). - An explicit
envvaris copied verbatim (every copy reads the same variable); a name generated byinit(auto_envvar_prefix=)is generated again for the target (APP_COMPILE_JOBS). - A pairwise
exclude=keeps working when both options are copied; with only one, the link is inert. Mutually exclusive sets (set_mutually_exclusive_switches) belong to a group and are not copied.
Mutually exclusive commands — cli%set_mutually_exclusive_groups
fortran
call cli%set_mutually_exclusive_groups(group1='commit', group2='init')Both commands must be defined before the call. Calling both is ERROR_GROUP_M_EXCLUDE (101), reported by parse.