#!/bin/bash

# Generated by perl modules
# App::Spec v0.013
# App::Spec::Bash v0.000
# mydemo - Demo

set -e

declare OP=
declare -a ERRORS=()
declare -a COMMANDS=()
declare stdout_terminal=false stderr_terminal=false
declare END_OF_OPTIONS=false
declare APPSPEC_COLOR_BOLD='\x1b[1m'
declare APPSPEC_COLOR_RED='\x1b[31m'
declare APPSPEC_COLOR_ERROR="$GIT_HUB_COLOR_RED$GIT_HUB_COLOR_BOLD"
declare APPSPEC_COLOR_GREEN='\x1b[32m'
declare APPSPEC_COLOR_CYAN='\x1b[36m'
declare APPSPEC_COLOR_MAGENTA='\x1b[35m'
declare APPSPEC_COLOR_YELLOW='\x1b[33m'
declare APPSPEC_COLOR_DARKGRAY='\x1b[90m'
declare APPSPEC_NO_COLOR='\x1b[0m'



DEBUG=false
[[ -n "$APPSPEC_BASH_DEBUG" ]] && DEBUG=true

APPSPEC.run() {
  APPSPEC.init-terminal
  APPSPEC.parse "$@"
}

APPSPEC.run-op() {
  if (( ${#ERRORS[*]} > 0 )); then
    APPSPEC.show_help
    for i in "${ERRORS[@]}"; do
      APPSPEC.error "$i"
    done
    exit 1
  else
    debug "OP: $OP"
  fi
  if [[ ${#argv[@]} -gt 0 ]]; then
    debug "leftover args in ARGV: (${argv[*]})"
    ARGV=("${argv[@]}")
  fi
  debug "Running MyDemo.$OP"
  if [[ -n "$OP" ]]; then
    MyDemo.$OP
  else
    echo "No operation found"
  fi
}

APPSPEC.parse() {
  local argv=("$@")
  debug "ARGV: ${argv[*]}"
      declare OPT_VERSION=false
      declare OPT_HELP=false

  if [[ ${#argv[@]} -eq 0 ]]; then
      APPSPEC.add-error "Missing subcommand"
      APPSPEC.run-op
      return
  fi
  while [[ ${#argv[@]} -gt 0 ]]; do
    debug "processing ${argv[0]}..."
    case "${argv[0]}" in
    --version)
        debug "LONG OPTION version"
        OPT_VERSION=true
        shift_arg

    ;;
    --help)
        debug "LONG OPTION help"
        OPT_HELP=true
        shift_arg

    ;;
    --) shift_arg; END_OF_OPTIONS=true; break
    ;;
    --*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break
    ;;

    -*)
      local i arg=${argv[0]/-/}
      for (( i=0; i < "${#arg}"; i++ )); do
        local char="${arg:$i:1}"
        value="${arg:$i+1}"
        if (( $i+1 == ${#arg} )); then
          shift_arg
          value="${argv[0]}"
        fi
        debug "processing short $char. arg=$arg value=$value"
        case "$char" in
        V)
          debug "SHORT OPTION version"
          OPT_VERSION=true

        ;;
        h)
          debug "SHORT OPTION help"
          OPT_HELP=true

        ;;
        *)
          APPSPEC.add-error "Unknown option '-$char'"
          shift_arg
          break
        ;;
        esac
      done

    ;;

    # SUBCOMMANDS
    help)
      COMMANDS+=("help")
      declare OPT_ALL=false

      shift_arg
      APPSPEC.parse-help

      if [[ -z "$OP" ]]; then
        OP=cmd_help
        APPSPEC.run-op
      fi

      return
    ;;
    nested1)
      COMMANDS+=("nested1")

      shift_arg
      APPSPEC.parse-nested1

      if [[ -z "$OP" ]]; then
        OP=nested1
        APPSPEC.run-op
      fi

      return
    ;;
    service)
      COMMANDS+=("service")

      shift_arg
      APPSPEC.parse-service

      if [[ -z "$OP" ]]; then
        APPSPEC.add-error "Missing subcommand"
        APPSPEC.run-op
      fi

      return
    ;;
    test1)
      COMMANDS+=("test1")
      declare OPT_FLAG_A=false
      declare OPT_FLAG_B=false
      declare -i OPT_FLAG_C=0
      declare OPT_TEST_D=
      declare OPT_TEST_E=
      declare -a OPT_TEST_F=()
      declare OPT_TEST_G=

      shift_arg
      APPSPEC.parse-test1

      if [[ -z "$OP" ]]; then
        OP=test1
        APPSPEC.run-op
      fi

      return
    ;;
    *)
      APPSPEC.add-error "Unknown subcommand '${argv[0]}'"
      shift_arg
      APPSPEC.run-op
      return
    ;;


    esac
  done

  debug "ARGV: ${argv[*]}"
}

APPSPEC.parse-help-nested1-nested2() {
  debug "APPSPEC.parse-help-nested1-nested2()"

  while [[ ${#argv[@]} -gt 0 ]]; do
    if APPSPEC.parse-options-help-nested1-nested2; then
        break
    fi

    case "${argv[0]}" in
    # SUBCOMMANDS
    *) break
    ;;

    esac
  done

}

APPSPEC.parse-options-help-nested1-nested2() {
  debug "APPSPEC.parse-options-help-nested1-nested2()"
  $END_OF_OPTIONS && return 1
  while [[ ${#argv[@]} -gt 0 ]]; do
    case "${argv[0]}" in
    --) shift_arg; END_OF_OPTIONS=true; break
    ;;
    --*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break
    ;;

    -*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break

    ;;

    *) return 1
    ;;
    esac
  done
  return 0
}

APPSPEC.parse-help-nested1() {
  debug "APPSPEC.parse-help-nested1()"

  while [[ ${#argv[@]} -gt 0 ]]; do
    if APPSPEC.parse-options-help-nested1; then
        break
    fi

    case "${argv[0]}" in
    # SUBCOMMANDS
    nested2)
      COMMANDS+=("nested2")

      shift_arg
      APPSPEC.parse-help-nested1-nested2


      return
    ;;
    *)
      APPSPEC.add-error "Unknown subcommand '${argv[0]}'"
      shift_arg
      APPSPEC.run-op
      return
    ;;


    esac
  done

}

APPSPEC.parse-options-help-nested1() {
  debug "APPSPEC.parse-options-help-nested1()"
  $END_OF_OPTIONS && return 1
  while [[ ${#argv[@]} -gt 0 ]]; do
    case "${argv[0]}" in
    --) shift_arg; END_OF_OPTIONS=true; break
    ;;
    --*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break
    ;;

    -*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break

    ;;

    *) return 1
    ;;
    esac
  done
  return 0
}

APPSPEC.parse-help-service-list() {
  debug "APPSPEC.parse-help-service-list()"

  while [[ ${#argv[@]} -gt 0 ]]; do
    if APPSPEC.parse-options-help-service-list; then
        break
    fi

    case "${argv[0]}" in
    # SUBCOMMANDS
    *) break
    ;;

    esac
  done

}

APPSPEC.parse-options-help-service-list() {
  debug "APPSPEC.parse-options-help-service-list()"
  $END_OF_OPTIONS && return 1
  while [[ ${#argv[@]} -gt 0 ]]; do
    case "${argv[0]}" in
    --) shift_arg; END_OF_OPTIONS=true; break
    ;;
    --*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break
    ;;

    -*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break

    ;;

    *) return 1
    ;;
    esac
  done
  return 0
}

APPSPEC.parse-help-service-start() {
  debug "APPSPEC.parse-help-service-start()"

  while [[ ${#argv[@]} -gt 0 ]]; do
    if APPSPEC.parse-options-help-service-start; then
        break
    fi

    case "${argv[0]}" in
    # SUBCOMMANDS
    *) break
    ;;

    esac
  done

}

APPSPEC.parse-options-help-service-start() {
  debug "APPSPEC.parse-options-help-service-start()"
  $END_OF_OPTIONS && return 1
  while [[ ${#argv[@]} -gt 0 ]]; do
    case "${argv[0]}" in
    --) shift_arg; END_OF_OPTIONS=true; break
    ;;
    --*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break
    ;;

    -*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break

    ;;

    *) return 1
    ;;
    esac
  done
  return 0
}

APPSPEC.parse-help-service-status() {
  debug "APPSPEC.parse-help-service-status()"

  while [[ ${#argv[@]} -gt 0 ]]; do
    if APPSPEC.parse-options-help-service-status; then
        break
    fi

    case "${argv[0]}" in
    # SUBCOMMANDS
    *) break
    ;;

    esac
  done

}

APPSPEC.parse-options-help-service-status() {
  debug "APPSPEC.parse-options-help-service-status()"
  $END_OF_OPTIONS && return 1
  while [[ ${#argv[@]} -gt 0 ]]; do
    case "${argv[0]}" in
    --) shift_arg; END_OF_OPTIONS=true; break
    ;;
    --*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break
    ;;

    -*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break

    ;;

    *) return 1
    ;;
    esac
  done
  return 0
}

APPSPEC.parse-help-service-stop() {
  debug "APPSPEC.parse-help-service-stop()"

  while [[ ${#argv[@]} -gt 0 ]]; do
    if APPSPEC.parse-options-help-service-stop; then
        break
    fi

    case "${argv[0]}" in
    # SUBCOMMANDS
    *) break
    ;;

    esac
  done

}

APPSPEC.parse-options-help-service-stop() {
  debug "APPSPEC.parse-options-help-service-stop()"
  $END_OF_OPTIONS && return 1
  while [[ ${#argv[@]} -gt 0 ]]; do
    case "${argv[0]}" in
    --) shift_arg; END_OF_OPTIONS=true; break
    ;;
    --*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break
    ;;

    -*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break

    ;;

    *) return 1
    ;;
    esac
  done
  return 0
}

APPSPEC.parse-help-service() {
  debug "APPSPEC.parse-help-service()"

  while [[ ${#argv[@]} -gt 0 ]]; do
    if APPSPEC.parse-options-help-service; then
        break
    fi

    case "${argv[0]}" in
    # SUBCOMMANDS
    list)
      COMMANDS+=("list")

      shift_arg
      APPSPEC.parse-help-service-list


      return
    ;;
    start)
      COMMANDS+=("start")

      shift_arg
      APPSPEC.parse-help-service-start


      return
    ;;
    status)
      COMMANDS+=("status")

      shift_arg
      APPSPEC.parse-help-service-status


      return
    ;;
    stop)
      COMMANDS+=("stop")

      shift_arg
      APPSPEC.parse-help-service-stop


      return
    ;;
    *)
      APPSPEC.add-error "Unknown subcommand '${argv[0]}'"
      shift_arg
      APPSPEC.run-op
      return
    ;;


    esac
  done

}

APPSPEC.parse-options-help-service() {
  debug "APPSPEC.parse-options-help-service()"
  $END_OF_OPTIONS && return 1
  while [[ ${#argv[@]} -gt 0 ]]; do
    case "${argv[0]}" in
    --) shift_arg; END_OF_OPTIONS=true; break
    ;;
    --*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break
    ;;

    -*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break

    ;;

    *) return 1
    ;;
    esac
  done
  return 0
}

APPSPEC.parse-help-test1() {
  debug "APPSPEC.parse-help-test1()"

  while [[ ${#argv[@]} -gt 0 ]]; do
    if APPSPEC.parse-options-help-test1; then
        break
    fi

    case "${argv[0]}" in
    # SUBCOMMANDS
    *) break
    ;;

    esac
  done

}

APPSPEC.parse-options-help-test1() {
  debug "APPSPEC.parse-options-help-test1()"
  $END_OF_OPTIONS && return 1
  while [[ ${#argv[@]} -gt 0 ]]; do
    case "${argv[0]}" in
    --) shift_arg; END_OF_OPTIONS=true; break
    ;;
    --*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break
    ;;

    -*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break

    ;;

    *) return 1
    ;;
    esac
  done
  return 0
}

APPSPEC.parse-help() {
  debug "APPSPEC.parse-help()"

  while [[ ${#argv[@]} -gt 0 ]]; do
    if APPSPEC.parse-options-help; then
        break
    fi

    case "${argv[0]}" in
    # SUBCOMMANDS
    nested1)
      COMMANDS+=("nested1")

      shift_arg
      APPSPEC.parse-help-nested1


      return
    ;;
    service)
      COMMANDS+=("service")

      shift_arg
      APPSPEC.parse-help-service


      return
    ;;
    test1)
      COMMANDS+=("test1")

      shift_arg
      APPSPEC.parse-help-test1


      return
    ;;
    *)
      APPSPEC.add-error "Unknown subcommand '${argv[0]}'"
      shift_arg
      APPSPEC.run-op
      return
    ;;


    esac
  done

}

APPSPEC.parse-options-help() {
  debug "APPSPEC.parse-options-help()"
  $END_OF_OPTIONS && return 1
  while [[ ${#argv[@]} -gt 0 ]]; do
    case "${argv[0]}" in
    --all)
        debug "LONG OPTION all"
        OPT_ALL=true
        shift_arg

    ;;
    --) shift_arg; END_OF_OPTIONS=true; break
    ;;
    --*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break
    ;;

    -*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break

    ;;

    *) return 1
    ;;
    esac
  done
  return 0
}

APPSPEC.parse-nested1-nested2() {
  debug "APPSPEC.parse-nested1-nested2()"

  while [[ ${#argv[@]} -gt 0 ]]; do
    if APPSPEC.parse-options-nested1-nested2; then
        break
    fi

    case "${argv[0]}" in
    # SUBCOMMANDS
    *) break
    ;;

    esac
  done

}

APPSPEC.parse-options-nested1-nested2() {
  debug "APPSPEC.parse-options-nested1-nested2()"
  $END_OF_OPTIONS && return 1
  while [[ ${#argv[@]} -gt 0 ]]; do
    case "${argv[0]}" in
    --) shift_arg; END_OF_OPTIONS=true; break
    ;;
    --*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break
    ;;

    -*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break

    ;;

    *) return 1
    ;;
    esac
  done
  return 0
}

APPSPEC.parse-nested1() {
  debug "APPSPEC.parse-nested1()"

  while [[ ${#argv[@]} -gt 0 ]]; do
    if APPSPEC.parse-options-nested1; then
        break
    fi

    case "${argv[0]}" in
    # SUBCOMMANDS
    nested2)
      COMMANDS+=("nested2")

      shift_arg
      APPSPEC.parse-nested1-nested2

      if [[ -z "$OP" ]]; then
        OP=nested2
        APPSPEC.run-op
      fi

      return
    ;;
    *)
      APPSPEC.add-error "Unknown subcommand '${argv[0]}'"
      shift_arg
      APPSPEC.run-op
      return
    ;;


    esac
  done

}

APPSPEC.parse-options-nested1() {
  debug "APPSPEC.parse-options-nested1()"
  $END_OF_OPTIONS && return 1
  while [[ ${#argv[@]} -gt 0 ]]; do
    case "${argv[0]}" in
    --) shift_arg; END_OF_OPTIONS=true; break
    ;;
    --*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break
    ;;

    -*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break

    ;;

    *) return 1
    ;;
    esac
  done
  return 0
}

APPSPEC.parse-service-list() {
  debug "APPSPEC.parse-service-list()"

  while [[ ${#argv[@]} -gt 0 ]]; do
    if APPSPEC.parse-options-service-list; then
        break
    fi

    case "${argv[0]}" in
    # SUBCOMMANDS
    *) break
    ;;

    esac
  done

}

APPSPEC.parse-options-service-list() {
  debug "APPSPEC.parse-options-service-list()"
  $END_OF_OPTIONS && return 1
  while [[ ${#argv[@]} -gt 0 ]]; do
    case "${argv[0]}" in
    --) shift_arg; END_OF_OPTIONS=true; break
    ;;
    --*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break
    ;;

    -*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break

    ;;

    *) return 1
    ;;
    esac
  done
  return 0
}

APPSPEC.params-service-start() {
  debug "APPSPEC.params-service-start()"
  while [[ ${#argv[@]} -gt 0 ]]; do
    if APPSPEC.parse-options-service-start; then
        break
    fi
    PARAM_SERVICE="${argv[0]}"
    shift_arg
    break
  done
  if APPSPEC.parse-options-service-start; then
    true
  fi
  if [[ -z "$PARAM_SERVICE" ]]; then
    APPSPEC.add-error "Missing required parameter 'service'"
  fi

}

APPSPEC.parse-service-start() {
  debug "APPSPEC.parse-service-start()"

  while [[ ${#argv[@]} -gt 0 ]]; do
    if APPSPEC.parse-options-service-start; then
        break
    fi

    case "${argv[0]}" in
    # SUBCOMMANDS
    *) break
    ;;

    esac
  done

}

APPSPEC.parse-options-service-start() {
  debug "APPSPEC.parse-options-service-start()"
  $END_OF_OPTIONS && return 1
  while [[ ${#argv[@]} -gt 0 ]]; do
    case "${argv[0]}" in
    --restart)
        debug "LONG OPTION restart"
        OPT_RESTART=true
        shift_arg

    ;;
    --) shift_arg; END_OF_OPTIONS=true; break
    ;;
    --*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break
    ;;

    -*)
      local i arg=${argv[0]/-/}
      for (( i=0; i < "${#arg}"; i++ )); do
        local char="${arg:$i:1}"
        value="${arg:$i+1}"
        if (( $i+1 == ${#arg} )); then
          shift_arg
          value="${argv[0]}"
        fi
        debug "processing short $char. arg=$arg value=$value"
        case "$char" in
        r)
          debug "SHORT OPTION restart"
          OPT_RESTART=true

        ;;
        *)
          APPSPEC.add-error "Unknown option '-$char'"
          shift_arg
          break
        ;;
        esac
      done

    ;;

    *) return 1
    ;;
    esac
  done
  return 0
}

APPSPEC.params-service-status() {
  debug "APPSPEC.params-service-status()"
  while [[ ${#argv[@]} -gt 0 ]]; do
    if APPSPEC.parse-options-service-status; then
        break
    fi
    PARAM_SERVICE="${argv[0]}"
    shift_arg
    break
  done
  if APPSPEC.parse-options-service-status; then
    true
  fi
  if [[ -z "$PARAM_SERVICE" ]]; then
    APPSPEC.add-error "Missing required parameter 'service'"
  fi

}

APPSPEC.parse-service-status() {
  debug "APPSPEC.parse-service-status()"

  while [[ ${#argv[@]} -gt 0 ]]; do
    if APPSPEC.parse-options-service-status; then
        break
    fi

    case "${argv[0]}" in
    # SUBCOMMANDS
    *) break
    ;;

    esac
  done

}

APPSPEC.parse-options-service-status() {
  debug "APPSPEC.parse-options-service-status()"
  $END_OF_OPTIONS && return 1
  while [[ ${#argv[@]} -gt 0 ]]; do
    case "${argv[0]}" in
    --) shift_arg; END_OF_OPTIONS=true; break
    ;;
    --*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break
    ;;

    -*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break

    ;;

    *) return 1
    ;;
    esac
  done
  return 0
}

APPSPEC.params-service-stop() {
  debug "APPSPEC.params-service-stop()"
  while [[ ${#argv[@]} -gt 0 ]]; do
    if APPSPEC.parse-options-service-stop; then
        break
    fi
    PARAM_SERVICE="${argv[0]}"
    shift_arg
    break
  done
  if APPSPEC.parse-options-service-stop; then
    true
  fi
  if [[ -z "$PARAM_SERVICE" ]]; then
    APPSPEC.add-error "Missing required parameter 'service'"
  fi

}

APPSPEC.parse-service-stop() {
  debug "APPSPEC.parse-service-stop()"

  while [[ ${#argv[@]} -gt 0 ]]; do
    if APPSPEC.parse-options-service-stop; then
        break
    fi

    case "${argv[0]}" in
    # SUBCOMMANDS
    *) break
    ;;

    esac
  done

}

APPSPEC.parse-options-service-stop() {
  debug "APPSPEC.parse-options-service-stop()"
  $END_OF_OPTIONS && return 1
  while [[ ${#argv[@]} -gt 0 ]]; do
    case "${argv[0]}" in
    --) shift_arg; END_OF_OPTIONS=true; break
    ;;
    --*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break
    ;;

    -*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break

    ;;

    *) return 1
    ;;
    esac
  done
  return 0
}

APPSPEC.parse-service() {
  debug "APPSPEC.parse-service()"

  while [[ ${#argv[@]} -gt 0 ]]; do
    if APPSPEC.parse-options-service; then
        break
    fi

    case "${argv[0]}" in
    # SUBCOMMANDS
    list)
      COMMANDS+=("list")

      shift_arg
      APPSPEC.parse-service-list

      if [[ -z "$OP" ]]; then
        OP=list
        APPSPEC.run-op
      fi

      return
    ;;
    start)
      COMMANDS+=("start")
      declare OPT_RESTART=false
      declare PARAM_SERVICE # REQUIRED

      shift_arg
      APPSPEC.parse-service-start
      APPSPEC.params-service-start
      if [[ -z "$OP" ]]; then
        OP=start
        APPSPEC.run-op
      fi

      return
    ;;
    status)
      COMMANDS+=("status")
      declare PARAM_SERVICE # REQUIRED

      shift_arg
      APPSPEC.parse-service-status
      APPSPEC.params-service-status
      if [[ -z "$OP" ]]; then
        OP=status
        APPSPEC.run-op
      fi

      return
    ;;
    stop)
      COMMANDS+=("stop")
      declare PARAM_SERVICE # REQUIRED

      shift_arg
      APPSPEC.parse-service-stop
      APPSPEC.params-service-stop
      if [[ -z "$OP" ]]; then
        OP=stop
        APPSPEC.run-op
      fi

      return
    ;;
    *)
      APPSPEC.add-error "Unknown subcommand '${argv[0]}'"
      shift_arg
      APPSPEC.run-op
      return
    ;;


    esac
  done

}

APPSPEC.parse-options-service() {
  debug "APPSPEC.parse-options-service()"
  $END_OF_OPTIONS && return 1
  while [[ ${#argv[@]} -gt 0 ]]; do
    case "${argv[0]}" in
    --) shift_arg; END_OF_OPTIONS=true; break
    ;;
    --*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break
    ;;

    -*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break

    ;;

    *) return 1
    ;;
    esac
  done
  return 0
}

APPSPEC.parse-test1() {
  debug "APPSPEC.parse-test1()"

  while [[ ${#argv[@]} -gt 0 ]]; do
    if APPSPEC.parse-options-test1; then
        break
    fi

    case "${argv[0]}" in
    # SUBCOMMANDS
    *) break
    ;;

    esac
  done

}

APPSPEC.parse-options-test1() {
  debug "APPSPEC.parse-options-test1()"
  $END_OF_OPTIONS && return 1
  while [[ ${#argv[@]} -gt 0 ]]; do
    case "${argv[0]}" in
    --flag-a)
        debug "LONG OPTION flag-a"
        OPT_FLAG_A=true
        shift_arg

    ;;
    --flag-b)
        debug "LONG OPTION flag-b"
        OPT_FLAG_B=true
        shift_arg

    ;;
    --flag-c)
        debug "LONG OPTION flag-c"
        OPT_FLAG_C+=1
        shift_arg

    ;;
    --test-d)
        debug "LONG OPTION test-d"
        shift_arg
        OPT_TEST_D="${argv[0]}"
        shift_arg

    ;;
    --test-e)
        debug "LONG OPTION test-e"
        shift_arg
        OPT_TEST_E="${argv[0]}"
        shift_arg

    ;;
    --test-f)
        debug "LONG OPTION test-f"
        shift_arg
        OPT_TEST_F+=("${argv[0]}")
        shift_arg

    ;;
    --test-g)
        debug "LONG OPTION test-g"
        shift_arg
        OPT_TEST_G="${argv[0]}"
        shift_arg

    ;;
    --) shift_arg; END_OF_OPTIONS=true; break
    ;;
    --*)
        APPSPEC.add-error "Unknown option '${argv[0]}'"
        shift_arg
        break
    ;;

    -*)
      local i arg=${argv[0]/-/}
      for (( i=0; i < "${#arg}"; i++ )); do
        local char="${arg:$i:1}"
        value="${arg:$i+1}"
        if (( $i+1 == ${#arg} )); then
          shift_arg
          value="${argv[0]}"
        fi
        debug "processing short $char. arg=$arg value=$value"
        case "$char" in
        a)
          debug "SHORT OPTION flag-a"
          OPT_FLAG_A=true

        ;;
        b)
          debug "SHORT OPTION flag-b"
          OPT_FLAG_B=true

        ;;
        c)
          debug "SHORT OPTION flag-c"
          OPT_FLAG_C+=1

        ;;
        d)
          debug "SHORT OPTION test-d"
          OPT_TEST_D="$value"
          shift_arg
          break

        ;;
        e)
          debug "SHORT OPTION test-e"
          OPT_TEST_E="$value"
          shift_arg
          break

        ;;
        f)
          debug "SHORT OPTION test-f"
          OPT_TEST_F+=("$value")
          shift_arg
          break

        ;;
        g)
          debug "SHORT OPTION test-g"
          OPT_TEST_G="$value"
          shift_arg
          break

        ;;
        *)
          APPSPEC.add-error "Unknown option '-$char'"
          shift_arg
          break
        ;;
        esac
      done

    ;;

    *) return 1
    ;;
    esac
  done
  return 0
}




APPSPEC.colored() {
    local fh="$1"
    local message="$2"
    if [[ "$fh" == "stdout" ]] && ! $stdout_terminal; then
        echo "$message"
        return
    fi
    if [[ "$fh" == stderr ]] && ! $stderr_terminal; then
        echo "$message"
        return
    fi
    shift
    shift
    local colornames=($@)
    local varname value colored=

    for i in "${colornames[@]}"; do
        varname="APPSPEC_COLOR_$i"
        value="${!varname}"
        colored+="$value"
    done

    colored+="$message"
    colored+="$APPSPEC_NO_COLOR"
    echo "$colored"

}

APPSPEC.colorize() {
    local fh="$1"
    local message="$2"
    shift
    shift
    [[ "$fh" == stdout ]] && echo -e "$(APPSPEC.colored "$fh" "$message" $@)"
    [[ "$fh" == stderr ]] && echo -e "$(APPSPEC.colored "$fh" "$message" $@)" >&2
}

APPSPEC.say() {
    local message="$1"
    shift
    if [[ $# -gt 0 ]]; then
        echo -e "$(APPSPEC.colored stdout "$message" $@)"
    else
        echo "$message"
    fi
}

APPSPEC.error() {
    local message="$1"
    echo -e "$(APPSPEC.colored stderr "$message" BOLD RED)" >&2
}

APPSPEC.add-error() {
    debug "$1"
    ERRORS+=("$1")
}

APPSPEC.init-terminal() {
  if [[ -t 1 ]]; then
    stdout_terminal=true
  fi
  if [[ -t 2 ]]; then
    stderr_terminal=true
  fi
}


APPSPEC.cmd_help() {
  debug "======== APPSPEC.cmd_help"
  COMMANDS=("${COMMANDS[@]:1}")
  APPSPEC.show_help
}

APPSPEC.show_help() {
  source "$APPSPECDIR/lib/help"
  debug "======== APPSPEC.show_help"
  if [[ -n "$COMMANDS" ]]; then
    local func="${COMMANDS[*]}"
    func="${func/ /-}"
    debug "func $func"
    APPSPEC.help-$func
  else
    APPSPEC.help-ROOT
  fi
}

shift_arg() {
    argv=("${argv[@]:1}")
}

debug() {
  $DEBUG && APPSPEC.colorize stderr "$@" DARKGRAY || true
}