parse Subroutine

private subroutine parse(self, pref, args, error)

Parse Command Line Interfaces by means of a previously initialized CLAs groups list.

Note

The leading and trailing white spaces are removed from CLA values.

Note

If the args argument is passed the command line arguments are taken from it and not from the actual program CLI invocations.

Type Bound

command_line_interface

Arguments

Type IntentOptional Attributes Name
class(command_line_interface), intent(inout) :: self

CLI data.

character(len=*), intent(in), optional :: pref

Prefixing string.

character(len=*), intent(in), optional :: args

String containing command line arguments.

integer(kind=I4P), intent(out), optional :: error

Error trapping flag.


Calls

proc~~parse~2~~CallsGraph proc~parse~2 flap_command_line_interface_t::command_line_interface%parse none~get_args flap_command_line_interface_t::command_line_interface%get_args proc~parse~2->none~get_args proc~add~2 flap_command_line_interface_t::command_line_interface%add proc~parse~2->proc~add~2 proc~check_m_exclusive~2 flap_command_line_interface_t::command_line_interface%check_m_exclusive proc~parse~2->proc~check_m_exclusive~2 proc~check~3 flap_command_line_interface_t::command_line_interface%check proc~parse~2->proc~check~3 proc~is_defined~2 flap_command_line_interface_t::command_line_interface%is_defined proc~parse~2->proc~is_defined~2 proc~is_required_passed flap_command_line_arguments_group_t::command_line_arguments_group%is_required_passed proc~parse~2->proc~is_required_passed proc~parse flap_command_line_arguments_group_t::command_line_arguments_group%parse proc~parse~2->proc~parse proc~print_version flap_object_t::object%print_version proc~parse~2->proc~print_version proc~sanitize_defaults flap_command_line_arguments_group_t::command_line_arguments_group%sanitize_defaults proc~parse~2->proc~sanitize_defaults proc~save_usage_to_markdown flap_command_line_interface_t::command_line_interface%save_usage_to_markdown proc~parse~2->proc~save_usage_to_markdown proc~usage~3 flap_command_line_interface_t::command_line_interface%usage proc~parse~2->proc~usage~3 proc~get_args_from_invocation flap_command_line_interface_t::command_line_interface%get_args_from_invocation none~get_args->proc~get_args_from_invocation proc~get_args_from_string flap_command_line_interface_t::command_line_interface%get_args_from_string none~get_args->proc~get_args_from_string proc~add flap_command_line_arguments_group_t::command_line_arguments_group%add proc~add~2->proc~add proc~add_group flap_command_line_interface_t::command_line_interface%add_group proc~add~2->proc~add_group proc~assign_object flap_object_t::object%assign_object proc~add~2->proc~assign_object proc~check~2 flap_command_line_argument_t::command_line_argument%check proc~add~2->proc~check~2 proc~is_defined_group flap_command_line_interface_t::command_line_interface%is_defined_group proc~add~2->proc~is_defined_group proc~upper_case flap_utils_m::upper_case proc~add~2->proc~upper_case proc~check_m_exclusive~2->proc~is_defined_group proc~raise_error_m_exclude flap_command_line_arguments_group_t::command_line_arguments_group%raise_error_m_exclude proc~check_m_exclusive~2->proc~raise_error_m_exclude proc~check flap_command_line_arguments_group_t::command_line_arguments_group%check proc~check~3->proc~check proc~check~3->proc~is_defined_group proc~is_defined flap_command_line_arguments_group_t::command_line_arguments_group%is_defined proc~is_defined~2->proc~is_defined proc~is_defined~2->proc~is_defined_group proc~is_required_passed~2 flap_command_line_argument_t::command_line_argument%is_required_passed proc~is_required_passed->proc~is_required_passed~2 proc~usage flap_command_line_arguments_group_t::command_line_arguments_group%usage proc~is_required_passed->proc~usage proc~parse->proc~sanitize_defaults cton cton proc~parse->cton proc~parse->proc~add proc~parse->proc~assign_object proc~check_m_exclusive flap_command_line_arguments_group_t::command_line_arguments_group%check_m_exclusive proc~parse->proc~check_m_exclusive proc~parse->proc~is_defined proc~raise_error_duplicated_clas flap_command_line_argument_t::command_line_argument%raise_error_duplicated_clas proc~parse->proc~raise_error_duplicated_clas proc~raise_error_nargs_insufficient flap_command_line_argument_t::command_line_argument%raise_error_nargs_insufficient proc~parse->proc~raise_error_nargs_insufficient proc~raise_error_switch_unknown flap_command_line_argument_t::command_line_argument%raise_error_switch_unknown proc~parse->proc~raise_error_switch_unknown proc~raise_error_value_missing flap_command_line_argument_t::command_line_argument%raise_error_value_missing proc~parse->proc~raise_error_value_missing proc~sanitize_defaults~2 flap_command_line_argument_t::command_line_argument%sanitize_defaults proc~sanitize_defaults->proc~sanitize_defaults~2 proc~save_usage_to_markdown->proc~usage~3 proc~signature~3 flap_command_line_interface_t::command_line_interface%signature proc~save_usage_to_markdown->proc~signature~3 strz strz proc~save_usage_to_markdown->strz proc~usage~3->proc~signature~3 proc~usage~3->proc~usage proc~add->proc~check proc~add_group->proc~assign_object proc~add_group->proc~is_defined_group proc~set_examples flap_object_t::object%set_examples proc~add_group->proc~set_examples proc~check->proc~is_defined proc~errored flap_command_line_arguments_group_t::command_line_arguments_group%errored proc~check->proc~errored proc~is_passed flap_command_line_arguments_group_t::command_line_arguments_group%is_passed proc~check_m_exclusive->proc~is_passed proc~raise_error_m_exclude~2 flap_command_line_argument_t::command_line_argument%raise_error_m_exclude proc~check_m_exclusive->proc~raise_error_m_exclude~2 proc~check_action_consistency flap_command_line_argument_t::command_line_argument%check_action_consistency proc~check~2->proc~check_action_consistency proc~check_envvar_consistency flap_command_line_argument_t::command_line_argument%check_envvar_consistency proc~check~2->proc~check_envvar_consistency proc~check_m_exclude_consistency flap_command_line_argument_t::command_line_argument%check_m_exclude_consistency proc~check~2->proc~check_m_exclude_consistency proc~check_named_consistency flap_command_line_argument_t::command_line_argument%check_named_consistency proc~check~2->proc~check_named_consistency proc~check_optional_consistency flap_command_line_argument_t::command_line_argument%check_optional_consistency proc~check~2->proc~check_optional_consistency proc~check_positional_consistency flap_command_line_argument_t::command_line_argument%check_positional_consistency proc~check~2->proc~check_positional_consistency proc~get_clasg_indexes flap_command_line_interface_t::command_line_interface%get_clasg_indexes proc~get_args_from_invocation->proc~get_clasg_indexes proc~get_args_from_string->proc~get_clasg_indexes proc~tokenize flap_utils_m::tokenize proc~get_args_from_string->proc~tokenize proc~errored~2 flap_command_line_argument_t::command_line_argument%errored proc~is_required_passed~2->proc~errored~2 proc~raise_error_duplicated_clas->proc~errored~2 proc~raise_error_m_exclude->proc~errored proc~raise_error_nargs_insufficient->proc~errored~2 proc~raise_error_switch_unknown->proc~errored~2 proc~raise_error_value_missing->proc~errored~2 proc~replace_all flap_utils_m::replace_all proc~sanitize_defaults~2->proc~replace_all proc~unique flap_utils_m::unique proc~sanitize_defaults~2->proc~unique proc~wstrip flap_utils_m::wstrip proc~sanitize_defaults~2->proc~wstrip proc~signature flap_command_line_arguments_group_t::command_line_arguments_group%signature proc~signature~3->proc~signature proc~usage->proc~signature proc~usage~2 flap_command_line_argument_t::command_line_argument%usage proc~usage->proc~usage~2 proc~check_action_consistency->proc~errored~2 proc~check_envvar_consistency->proc~errored~2 proc~check_m_exclude_consistency->proc~errored~2 proc~check_named_consistency->proc~errored~2 proc~check_optional_consistency->proc~errored~2 proc~check_positional_consistency->proc~errored~2 interface~colorize face::colorize proc~errored->interface~colorize proc~print_error_message flap_object_t::object%print_error_message proc~errored->proc~print_error_message str str proc~errored->str proc~errored~2->interface~colorize proc~errored~2->proc~print_error_message proc~errored~2->str proc~get_clasg_indexes->proc~is_defined_group proc~raise_error_m_exclude~2->proc~errored~2 proc~replace_all->proc~wstrip proc~replace flap_utils_m::replace proc~replace_all->proc~replace proc~signature~2 flap_command_line_argument_t::command_line_argument%signature proc~signature->proc~signature~2 proc~usage~2->cton proc~usage~2->proc~replace_all proc~usage~2->interface~colorize proc~usage~2->str proc~colorize_default face::colorize_default interface~colorize->proc~colorize_default proc~signature~2->cton proc~signature~2->str proc~has_choices flap_command_line_argument_t::command_line_argument%has_choices proc~signature~2->proc~has_choices proc~color_index face::color_index proc~colorize_default->proc~color_index proc~style_index face::style_index proc~colorize_default->proc~style_index proc~upper face::upper proc~colorize_default->proc~upper

Called by

proc~~parse~2~~CalledByGraph proc~parse~2 flap_command_line_interface_t::command_line_interface%parse proc~fake_call flap_test_group::fake_call proc~fake_call->proc~parse~2 none~get~2 flap_command_line_interface_t::command_line_interface%get proc~fake_call->none~get~2 proc~get_cla_list_varying_char~2 flap_command_line_interface_t::command_line_interface%get_cla_list_varying_char proc~get_cla_list_varying_char~2->proc~parse~2 proc~get_cla_list_varying_i1p~2 flap_command_line_interface_t::command_line_interface%get_cla_list_varying_I1P proc~get_cla_list_varying_i1p~2->proc~parse~2 proc~get_cla_list_varying_i2p~2 flap_command_line_interface_t::command_line_interface%get_cla_list_varying_I2P proc~get_cla_list_varying_i2p~2->proc~parse~2 proc~get_cla_list_varying_i4p~2 flap_command_line_interface_t::command_line_interface%get_cla_list_varying_I4P proc~get_cla_list_varying_i4p~2->proc~parse~2 proc~get_cla_list_varying_i8p~2 flap_command_line_interface_t::command_line_interface%get_cla_list_varying_I8P proc~get_cla_list_varying_i8p~2->proc~parse~2 proc~get_cla_list_varying_logical~2 flap_command_line_interface_t::command_line_interface%get_cla_list_varying_logical proc~get_cla_list_varying_logical~2->proc~parse~2 proc~get_cla_list_varying_r16p~2 flap_command_line_interface_t::command_line_interface%get_cla_list_varying_R16P proc~get_cla_list_varying_r16p~2->proc~parse~2 proc~get_cla_list_varying_r4p~2 flap_command_line_interface_t::command_line_interface%get_cla_list_varying_R4P proc~get_cla_list_varying_r4p~2->proc~parse~2 proc~get_cla_list_varying_r8p~2 flap_command_line_interface_t::command_line_interface%get_cla_list_varying_R8P proc~get_cla_list_varying_r8p~2->proc~parse~2 proc~get_cla_list~2 flap_command_line_interface_t::command_line_interface%get_cla_list proc~get_cla_list~2->proc~parse~2 proc~get_cla~2 flap_command_line_interface_t::command_line_interface%get_cla proc~get_cla~2->proc~parse~2 program~flap_save_bash_completion flap_save_bash_completion program~flap_save_bash_completion->proc~parse~2 program~flap_test_basic flap_test_basic program~flap_test_basic->proc~parse~2 none~get_varying~2 flap_command_line_interface_t::command_line_interface%get_varying program~flap_test_basic->none~get_varying~2 program~flap_test_basic->none~get~2 program~flap_test_choices_logical flap_test_choices_logical program~flap_test_choices_logical->proc~parse~2 program~flap_test_choices_logical->none~get~2 program~flap_test_nested flap_test_nested program~flap_test_nested->proc~parse~2 program~flap_test_nested->none~get~2 program~flap_test_string flap_test_string program~flap_test_string->proc~parse~2 program~flap_test_string->none~get~2 none~get_varying~2->proc~get_cla_list_varying_char~2 none~get_varying~2->proc~get_cla_list_varying_i1p~2 none~get_varying~2->proc~get_cla_list_varying_i2p~2 none~get_varying~2->proc~get_cla_list_varying_i4p~2 none~get_varying~2->proc~get_cla_list_varying_i8p~2 none~get_varying~2->proc~get_cla_list_varying_logical~2 none~get_varying~2->proc~get_cla_list_varying_r4p~2 none~get_varying~2->proc~get_cla_list_varying_r8p~2 none~get~2->proc~get_cla_list~2 none~get~2->proc~get_cla~2 program~flap_test_group flap_test_group program~flap_test_group->proc~fake_call program~flap_save_man_page flap_save_man_page program~flap_save_man_page->none~get~2 program~flap_save_usage_to_markdown flap_save_usage_to_markdown program~flap_save_usage_to_markdown->none~get~2 program~flap_test_action_store flap_test_action_store program~flap_test_action_store->none~get_varying~2 program~flap_test_action_store->none~get~2 program~flap_test_ansi_color_style flap_test_ansi_color_style program~flap_test_ansi_color_style->none~get~2 program~flap_test_duplicated_clas flap_test_duplicated_clas program~flap_test_duplicated_clas->none~get~2 program~flap_test_group_examples flap_test_group_examples program~flap_test_group_examples->none~get~2 program~flap_test_hidden flap_test_hidden program~flap_test_hidden->none~get~2 program~flap_test_ignore_unknown_clas flap_test_ignore_unknown_clas program~flap_test_ignore_unknown_clas->none~get~2 program~flap_test_minimal flap_test_minimal program~flap_test_minimal->none~get~2 program~flap_test_nargs_insufficient flap_test_nargs_insufficient program~flap_test_nargs_insufficient->none~get~2 program~flap_test_nargs_insufficient~2 flap_test_nargs_insufficient program~flap_test_nargs_insufficient~2->none~get~2

Source Code

  subroutine parse(self, pref, args, error)
  !< Parse Command Line Interfaces by means of a previously initialized CLAs groups list.
  !<
  !< @note The leading and trailing white spaces are removed from CLA values.
  !<
  !< @note If the *args* argument is passed the command line arguments are taken from it and not from the actual program CLI
  !< invocations.
  class(command_line_interface), intent(inout) :: self    !< CLI data.
  character(*), optional,        intent(in)    :: pref    !< Prefixing string.
  character(*), optional,        intent(in)    :: args    !< String containing command line arguments.
  integer(I4P), optional,        intent(out)   :: error   !< Error trapping flag.
  integer(I4P)                                 :: g       !< Counter for CLAs group.
  integer(I4P), allocatable                    :: ai(:,:) !< Counter for CLAs grouped.

  if (present(error)) error = 0
  if (self%is_parsed_) return

  ! add help, markdown and version switches if not done by user
  if (.not.self%disable_hv) then
    do g=0,size(self%clasg,dim=1)-1
      if (.not.(self%is_defined(group=self%clasg(g)%group, switch='--help').and.&
                self%is_defined(group=self%clasg(g)%group, switch='-h'))) &
        call self%add(pref        = pref,                      &
                      group_index = g,                         &
                      switch      = '--help',                  &
                      switch_ab   = '-h',                      &
                      help        = 'Print this help message', &
                      required    = .false.,                   &
                      def         = '',                        &
                      act         = 'print_help')
      if (.not.(self%is_defined(group=self%clasg(g)%group, switch='--markdown').and.&
                self%is_defined(group=self%clasg(g)%group, switch='-md'))) &
        call self%add(pref        = pref,                      &
                      group_index = g,                         &
                      switch      = '--markdown',              &
                      switch_ab   = '-md',                     &
                      help        = 'Save this help message in a Markdown file', &
                      required    = .false.,                   &
                      def         = '',                        &
                      act         = 'print_markdown')
      if (.not.(self%is_defined(group=self%clasg(g)%group, switch='--version').and. &
                self%is_defined(group=self%clasg(g)%group, switch='-v'))) &
        call self%add(pref        = pref,            &
                      group_index = g,               &
                      switch      = '--version',     &
                      switch_ab   = '-v',            &
                      help        = 'Print version', &
                      required    = .false.,         &
                      def         = '',              &
                      act         = 'print_version')
    enddo
  endif

  ! add hidden CLA '--' for getting the rid of eventual trailing CLAs garbage
  do g=0,size(self%clasg,dim=1)-1
    if (.not.self%is_defined(group=self%clasg(g)%group, switch='--')) &
      call self%add(pref        = pref,    &
                    group_index = g,       &
                    switch      = '--',    &
                    required    = .false., &
                    hidden      = .true.,  &
                    nargs       = '*',     &
                    def         = '',      &
                    act         = 'store')
  enddo

  ! parse passed CLAs grouping in indexes
  if (present(args)) then
    call self%get_args(args=args, ai=ai)
  else
    call self%get_args(ai=ai)
  endif

  ! check CLI consistency
  call self%check(pref=pref)
  if (self%error>0) then
    if (((self%error==ERROR_UNKNOWN).and.(.not.self%ignore_unknown_clas)).or.(self%error/=ERROR_UNKNOWN)) then
       if (present(error)) error = self%error
       return
    else
       self%error_unknown_clas = ERROR_UNKNOWN_CLAS_IGNORED
    endif
  endif

  ! parse CLI
  do g=0,size(ai,dim=1)-1
    if (ai(g,1)>0) then
      call self%clasg(g)%parse(args=self%args(ai(g,1):ai(g,2)), ignore_unknown_clas=self%ignore_unknown_clas, &
                               pref=pref, error_unknown_clas=self%error_unknown_clas)
    else
      call self%clasg(g)%sanitize_defaults
    endif
    self%error = self%clasg(g)%error
    if (self%error < 0) exit
    if (self%error > 0) then
       if (((self%error==ERROR_UNKNOWN).and.(.not.self%ignore_unknown_clas)).or.(self%error/=ERROR_UNKNOWN)) then
          if (present(error)) error = self%error
          exit
       else
          self%error_unknown_clas = ERROR_UNKNOWN_CLAS_IGNORED
       endif
    endif
  enddo
  if (self%error>0) then
    if (((self%error==ERROR_UNKNOWN).and.(.not.self%ignore_unknown_clas)).or.(self%error/=ERROR_UNKNOWN)) then
       if (present(error)) error = self%error
       return
    else
       self%error_unknown_clas = ERROR_UNKNOWN_CLAS_IGNORED
    endif
  endif

  ! trap the special cases of version/help printing
  if (self%error == STATUS_PRINT_V) then
    call self%print_version(pref=pref)
    stop
  elseif (self%error == STATUS_PRINT_H) then
    do g=0,size(ai,dim=1)-1
      if(self%clasg(g)%error == STATUS_PRINT_H) then
        write(self%usage_lun,'(A)') self%usage(pref=pref, g=g)
        stop
      endif
    enddo
  elseif (self%error == STATUS_PRINT_M) then
    call self%save_usage_to_markdown(trim(self%progname)//'.md')
    stop
  endif

  ! check if all required CLAs have been passed
  do g=0, size(ai,dim=1)-1
    call self%clasg(g)%is_required_passed(pref=pref)
    self%error = self%clasg(g)%error
    if (self%error>0) then
       if (((self%error==ERROR_UNKNOWN).and.(.not.self%ignore_unknown_clas)).or.(self%error/=ERROR_UNKNOWN)) then
          if (present(error)) error = self%error
          exit
       else
          self%error_unknown_clas = ERROR_UNKNOWN_CLAS_IGNORED
       endif
    endif
  enddo
  if (self%error>0) then
    if (((self%error==ERROR_UNKNOWN).and.(.not.self%ignore_unknown_clas)).or.(self%error/=ERROR_UNKNOWN)) then
       if (present(error)) error = self%error
       return
    else
       self%error_unknown_clas = ERROR_UNKNOWN_CLAS_IGNORED
    endif
  endif

  ! check mutually exclusive interaction
  call self%check_m_exclusive(pref=pref)

  self%is_parsed_ = .true.

  ! check if the only error found is for unknown passed CLAs and if it is ignored by the user
  if (self%error==ERROR_UNKNOWN.and.self%error_unknown_clas==ERROR_UNKNOWN_CLAS_IGNORED) self%error = ERROR_UNKNOWN_CLAS_IGNORED

  if (present(error)) error = self%error
  endsubroutine parse