=head1 NAME

appspec-bash - Command line framework generator for bash

=head1 ABSTRACT

Generate commandline parser, completion and man pages

=head1 DESCRIPTION

This script can generate a commandline parser for bash from a specification
file written in YAML.

Writing a parser for commandline arguments isn't rocket science, but it's
something you don't want to do manually for all of your scripts, especially
in bash. Some tools exist, but they often don't support subcommands or
validating of option values.

C<appspec>/C<appspec-bash> can generate pretty much everything for you:

=over

=item Commandline parser for subcommands, options and parameters

=item Usage output

=item Shell completion files

=item man pages

=back

=head2 EXAMPLES

Here is an example of a very simple script.

The following files are needed:

  share/mytool.yaml
  bin/mytool
  lib/mytool
  lib/appspec                       # generated
  share/completion/zsh/_mytool      # generated
  share/completion/bash/mytool.bash # generated
  pod/mytool.pod                    # generated
  lib/help                          # generated

The spec:

  # share/mytool.yaml
  ---
  name: mytool           # commandname
  appspec: { version: 0.001 }
  plugins: [-Meta]       # not supported in bash
  title: My cool tool    # Will be shown in help
  class: MyTool          # "Class name" (means function prefix here)

  subcommands:
    command1:
      op: command1       # The function name (MyTool.command1)
      summary: cmd one   # Will be shown in help and completion
      options:
      - foo|f=s --Foo    # --foo or -f; '=s' means string
      - bar|b   --Bar    # --bar or -b; a flag

Your script C<mytool> would look like this:

  # bin/mytool
  #!/bin/bash
  DIR="$( dirname $BASH_SOURCE )"
  source "$DIR/../lib/appspec"
  source "$DIR/../lib/mytool"
  APPSPEC.run $@

The actual app:

  # lib/mytool
  #!/bin/bash
  MyTool.command1() {
      echo "=== OPTION foo: $OPT_FOO"
      echo "=== OPTION bar: $OPT_BAR"
  }

=head3 Generating the parser

Then generate the parser like this:

  $ appspec-bash generate parser share/mytool.yaml lib/appspec


C<APPSPEC.run> will parse the arguments and then call the function
C<MyTool.command1>. In this function you can use the options via
C<$OPT_FOO> and C<$OPT_BAR>.

  $ ./bin/mytool command1 --foo x --bar
  # or
  $ mytool command1 -f x -b
  === OPTION foo: x
  === OPTION bar: true

=head3 Generate completion

    $ appspec completion share/mytool.yaml --zsh >share/completion/zsh/_mytool
    $ appspec completion share/mytool.yaml --bash >share/completion/bash/mytool.bash

=head3 Generate pod

    $ appspec pod share/mytool.yaml > pod/mytool.pod
    $ perldoc pod/mytool.pod

=head3 Generate help

    $ appspec-bash generate help share/mydemo.yaml lib/help

=head2 Generate a new app skeleton

  appspec-bash new --class MyTool --name mytool

This will create your app C<mytool> in the directory C<MyTool> and output
some usage information like this:

  To generate the parser and help, do:

    % cd MyTool
    % appspec-bash generate parser share/mytool.yaml lib/appspec
    % appspec-bash generate help share/mytool.yaml lib/help

  Try it out:

    % bin/mytool cmd1 -ab --opt-x x -yfoo --opt-y bar
    % bin/mytool cmd2 -vvv
    % bin/mytool cmd2 -vvv foo

=head2 OPTION AND PARAMETER PARSING

appspec-bash supports various types of options.

=head3 Flags

    # YAML
    options:
    - verbose|v -- Verbose output

    % mytool --verbose
    % mytool -v

You can also stack several flags:

    % mytool -abc

=head3 Options with values

    # YAML
    options:
    - color|c=s --Specify color

    % mytool --color red
    % mytool -c red
    % mytool -cred
    # Not yet supported
    # mytool --color=red

You can stack flags together with options. If you have the flags C<-a> and
C<-b> and the option C<-c>, then you can use this syntax:

    % mytool -abc23

=head3 Incremental flags

    # YAML
    options:
    - verbose|v+ --Verbose output (incremental)

    % mytool -vvv                # like: declare -i OPT_VERBOSE=3
    % mytool --verbose --verbose # like: declare -i OPT_VERBOSE=2

=head3 Options with multiple values

    # YAML
    options:
    - server|s=s@  --List of servers

    % mytool --server foo --server bar
    % mytool -s foo -s bar

=head3 Parameters

    # YAML
    parameters:
    - name: server
      required: true
      summary: Server name

=head3 Option types

By default, an option is a flag. To accept a value, add a C<=>. Then it will
be a string by default:

    - foo=
    # or
    - foo=s

You can also create integer options:

    - max=i --Specify maximum value

Then you can treat it as an integer and use C<OPT_MAX+=1> for example.

There are also the types C<file>, C<dir>, C<filename> and C<dirname>.
Currently they are only relevant for completion.

    # YAML
    - input= +file      --Input filename
    - source-dir= +dir  --Source directory
    - output= +filename --Output file
    - out-dir= +dirname --Output directory

In the future, C<file> and C<dir> will check for an existing file or
directory. And C<filename> and C<dirname> can be used if the file
or directory doesn't exist yet, but the tab completion will still offer
file or directory names.

See the C<mydemo> app in the example directory for examples of options and
parameters.


=head2 GLOBAL OPTIONS

    --help -h    Show command help (flag)


=head2 SUBCOMMANDS

=head3  generate

    appspec-bash  generate <subcommands>

Generate parser, help


=head3 generate help

    appspec-bash generate help <spec> <output>

Generate help functions

Parameters:

    spec    *  YAML Specification file   
    output  *  Output file, e.g. lib/help

=head3 generate parser

    appspec-bash generate parser <spec> <output>

Generate main commandline parser script

Parameters:

    spec    *  YAML Specification file      
    output  *  Output file, e.g. lib/appspec

=head3  new

    appspec-bash  new [options] [<path>]

Generate new app

This command creates a skeleton for a new app.
It will create a directory for your app and write a skeleton
spec file.

Example:

  appspec-bash new --name mytool --class MyTool MyTool


Options:

    --name -n       *  The (file) name of the app                                    
    --class -c      *  The main "class" (function prefix) for your app implementation
    --overwrite -o     Overwrite existing dist directory (flag)                      

Parameters:

    path    Path to the distribution directory (default is the classname in current directory)

=head3  help

    appspec-bash  help <subcommands> [options]

Show command help

Options:

    --all     (flag)


=head3  _meta

    appspec-bash  _meta <subcommands>

Information and utilities for this app


=head3 _meta completion

    appspec-bash _meta completion <subcommands>

Shell completion functions


=head3 _meta completion generate

    appspec-bash _meta completion generate [options]

Generate self completion

Options:

    --name    name of the program (optional, override name in spec)
    --zsh     for zsh (flag)                                       
    --bash    for bash (flag)                                      


=head3 _meta pod

    appspec-bash _meta pod <subcommands>

Pod documentation


=head3 _meta pod generate

    appspec-bash _meta pod generate

Generate self pod