!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
module cubetools_primitive_opt
  use cubetools_parameters
  use cubesyntax_messaging
  use cubetools_primitive_arg
  use cubetools_terminal_tool
  use cubetools_list
  !
  public :: primitive_opt_t,opti_k,narg_k,strg_quest
  public :: cubetools_primitive_opt_ptr
  !
  private
  !
  integer(kind=code_k), parameter :: help_src_unkn=0  ! Unknown
  integer(kind=code_k), parameter :: help_src_none=1  ! No help => look at abstract
  integer(kind=code_k), parameter :: help_src_strg=2  ! From string
  integer(kind=code_k), parameter :: help_src_file=3  ! From file
  !
  integer(kind=4), parameter :: opti_k = 4
  integer(kind=4), parameter :: opti_l = 16
  integer(kind=4), parameter :: abst_l = 80
  integer(kind=4), parameter :: synt_l = 60
  !
  character(len=*), parameter :: strg_quest = '?' ! Short help
  !
  type, extends(tools_object_t) :: primitive_opt_t
     integer(kind=opti_k)          :: inum     = code_abs  ! Option number in command
     character(len=opti_l)         :: name     = strg_unk
     character(len=synt_l)         :: syntax   = strg_emp
     character(len=abst_l)         :: abstract = strg_emp  ! One-line abstract help
     integer(kind=code_k)          :: help_src = help_src_unkn
     character(len=:), allocatable :: help_strg            ! Long/multiline help OR
     character(len=file_l)         :: help_file            ! File name for help
     integer(kind=narg_k)          :: nargmin  = code_abs
     integer(kind=narg_k)          :: nargmax  = code_abs
     type(tools_list_t)            :: arg                  ! List of arguments to the option
     procedure(opt_check_interface),          pointer :: check => null()
     procedure(opt_build_syntax_interface),   pointer :: build_syntax => null()
     procedure(opt_print_abstract_interface), pointer :: print_abstract => null()
   contains
     ! Parsing
     procedure :: getnarg      => cubetools_option_getnarg
     procedure :: present      => cubetools_option_present
     procedure, private :: traphelp  => cubetools_option_traphelp
     procedure, private :: getarg_i4 => cubetools_option_getarg_i4
     procedure, private :: getarg_i8 => cubetools_option_getarg_i8
     procedure, private :: getarg_r4 => cubetools_option_getarg_r4
     procedure, private :: getarg_r8 => cubetools_option_getarg_r8
     procedure, private :: getarg_st => cubetools_option_getarg_st
     generic   :: getarg       => getarg_i4, getarg_i8, getarg_r4, getarg_r8, getarg_st
     !
     ! General
     procedure :: init  => cubetools_option_init
     procedure :: final => cubetools_option_final
     procedure :: free  => cubetools_option_free
     !
     ! Registering
     procedure :: put          => cubetools_option_put
     !
     ! Listing and Help
     procedure :: list           => cubetools_option_list
     procedure :: help           => cubetools_option_help
     procedure :: summary        => cubetools_option_summary
     procedure :: show_syntax    => cubetools_option_show_syntax
     procedure :: help_iterate   => cubetools_option_help_iterate
     procedure, private :: print_syntax    => cubetools_option_print_syntax
     procedure, private :: print_help_strg => cubetools_option_print_help_strg
     procedure, private :: print_help_file => cubetools_option_print_help_file
  end type primitive_opt_t
  !
  abstract interface
    subroutine opt_check_interface(opt,command,line,error)
      import primitive_opt_t
      class(primitive_opt_t), intent(in)    :: opt
      character(len=*),       intent(in)    :: command
      character(len=*),       intent(in)    :: line
      logical,                intent(inout) :: error
    end subroutine opt_check_interface
    subroutine opt_build_syntax_interface(opt,syntax,error)
      import primitive_opt_t
      class(primitive_opt_t), intent(in)    :: opt
      character(len=*),       intent(out)   :: syntax
      logical,                intent(inout) :: error
    end subroutine opt_build_syntax_interface
    subroutine opt_print_abstract_interface(opt,error)
      import primitive_opt_t
      class(primitive_opt_t), intent(in)    :: opt
      logical,                intent(inout) :: error
    end subroutine opt_print_abstract_interface
  end interface
  !
contains
  !
  !---Parsing-utilities--------------------------------------------------
  !
  function cubetools_option_getnarg(opt)
    use gkernel_interfaces
    !-------------------------------------------------------------------
    ! Returns number of arguments given to option
    !-------------------------------------------------------------------
    integer(kind=narg_k) :: cubetools_option_getnarg
    class(primitive_opt_t), intent(in) :: opt
    !
    cubetools_option_getnarg = sic_narg(opt%inum)
  end function cubetools_option_getnarg
  !
  subroutine cubetools_option_present(opt,line,present,error)
    use gkernel_interfaces
    !-------------------------------------------------------------------
    ! Returns if option is present.
    ! If the option has a question mark (?) argument, show the either
    ! the option or the argument help.
    !-------------------------------------------------------------------
    class(primitive_opt_t), intent(in)    :: opt
    character(len=*),       intent(in)    :: line
    logical,                intent(out)   :: present
    logical,                intent(inout) :: error
    !
    integer(kind=4) :: nc,narg
    character(len=1) :: arg1
    character(len=argu_l) :: arg
    character(len=*), parameter :: rname='OPTION>PRESENT'
    !
    call cubesyntax_message(syntaxseve%trace,rname,'Welcome')
    !
    present = sic_present(opt%inum,icomm)
    if (.not.present)  return
    !
    ! Trap ? on last argument
    narg = opt%getnarg()
    if (narg.le.0)  return  ! No argument present
    !
    if (sic_len(opt%inum,narg).ne.1)  return  ! Argument can not be ?
    !
    call sic_ch(line,opt%inum,narg,arg1,nc,mandatory,error)
    if (error) return
    if (arg1.ne.strg_quest)  return  ! Not a question mark
    !
    if (narg.eq.1) then
      ! Question mark follows the option: show help summary
      call opt%summary(error)
      if (error) return
    else
      ! Question mark follows an argument: show its full summary
      call sic_ke(line,opt%inum,narg-1,arg,nc,mandatory,error)
      if (error) return
      call cubetools_option_help_onearg(opt,arg(1:nc),error)
      if (error) return
    endif
    !
    ! Raise error to ensure the whole calling cascade is exited.
    error = .true.
    return
  end subroutine cubetools_option_present
  !
  subroutine cubetools_option_traphelp(opt,line,iarg,argum,nc,error)
    use gkernel_interfaces
    !----------------------------------------------------------------------
    ! Get the iarg-th argument (as a string) of the option from the command
    ! line. If the argument is a question mark (?), show the option help.
    !----------------------------------------------------------------------
    class(primitive_opt_t), intent(in)    :: opt
    character(len=*),       intent(in)    :: line
    integer(kind=argu_k),   intent(in)    :: iarg
    character(len=*),       intent(out)   :: argum
    integer(kind=4),        intent(out)   :: nc
    logical,                intent(inout) :: error
    !
    logical :: obligatory
    type(primitive_arg_t), pointer :: parg
    character(len=*), parameter :: rname='GET>ARG>TRAP>HELP'
    !
    call cubesyntax_message(syntaxseve%trace,rname,'Welcome')
    !
    parg => cubetools_primitive_arg_ptr(opt%arg%list(iarg)%p,error)
    obligatory = parg%mandatory.eq.code_arg_mandatory.or.parg%mandatory.eq.code_arg_optional
    call sic_ch(line,opt%inum,iarg,argum,nc,obligatory,error)
    if (error) return
    if (argum.eq.strg_quest) then
       call opt%summary(error)
       if (error) return
       error = .true.
       return
    endif
  end subroutine cubetools_option_traphelp
  !
  subroutine cubetools_option_getarg_i4(opt,line,iarg,value,error)
    use gkernel_interfaces
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(primitive_opt_t), intent(in)    :: opt
    character(len=*),       intent(in)    :: line
    integer(kind=argu_k),   intent(in)    :: iarg
    integer(kind=4),        intent(inout) :: value
    logical,                intent(inout) :: error
    !
    character(len=base_l) :: argum
    integer(kind=4) :: nc
    character(len=*), parameter :: rname='GET>ARG>I4'
    !
    call cubesyntax_message(syntaxseve%trace,rname,'Welcome')
    !
    call opt%traphelp(line,iarg,argum,nc,error)
    if (error) return
    call sic_math_inte(argum,nc,value,error)
    if (error) then
       error = .false.
       call opt%show_syntax(error)
       error = .true.
       return
    endif
  end subroutine cubetools_option_getarg_i4
  !
  subroutine cubetools_option_getarg_i8(opt,line,iarg,value,error)
    use gkernel_interfaces
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(primitive_opt_t), intent(in)    :: opt
    character(len=*),       intent(in)    :: line
    integer(kind=argu_k),   intent(in)    :: iarg
    integer(kind=8),        intent(inout) :: value
    logical,                intent(inout) :: error
    !
    character(len=base_l) :: argum
    integer(kind=4) :: nc
    character(len=*), parameter :: rname='GET>ARG>I8'
    !
    call cubesyntax_message(syntaxseve%trace,rname,'Welcome')
    !
    call opt%traphelp(line,iarg,argum,nc,error)
    if (error) return
    call sic_math_long(argum,nc,value,error)
    if (error) then
       error = .false.
       call opt%show_syntax(error)
       error = .true.
       return
    endif
  end subroutine cubetools_option_getarg_i8
  !
  subroutine cubetools_option_getarg_r4(opt,line,iarg,value,error)
    use gkernel_interfaces
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(primitive_opt_t), intent(in)    :: opt
    character(len=*),       intent(in)    :: line
    integer(kind=argu_k),   intent(in)    :: iarg
    real(kind=4),           intent(inout) :: value
    logical,                intent(inout) :: error
    !
    character(len=base_l) :: argum
    integer(kind=4) :: nc
    character(len=*), parameter :: rname='GET>ARG>I8'
    !
    call cubesyntax_message(syntaxseve%trace,rname,'Welcome')
    !
    call opt%traphelp(line,iarg,argum,nc,error)
    if (error) return
    call sic_math_real(argum,nc,value,error)
    if (error) then
       error = .false.
       call opt%show_syntax(error)
       error = .true.
       return
    endif
  end subroutine cubetools_option_getarg_r4
  !
  subroutine cubetools_option_getarg_r8(opt,line,iarg,value,error)
    use gkernel_interfaces
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(primitive_opt_t), intent(in)    :: opt
    character(len=*),       intent(in)    :: line
    integer(kind=argu_k),   intent(in)    :: iarg
    real(kind=8),           intent(inout) :: value
    logical,                intent(inout) :: error
    !
    character(len=base_l) :: argum
    integer(kind=4) :: nc
    character(len=*), parameter :: rname='GET>ARG>I8'
    !
    call cubesyntax_message(syntaxseve%trace,rname,'Welcome')
    !
    call opt%traphelp(line,iarg,argum,nc,error)
    if (error) return
    call sic_math_dble(argum,nc,value,error)
    if (error) then
       error = .false.
       call opt%show_syntax(error)
       error = .true.
       return
    endif
  end subroutine cubetools_option_getarg_r8
  !
  subroutine cubetools_option_getarg_st(opt,line,iarg,value,error)
    use gkernel_interfaces
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(primitive_opt_t), intent(in)    :: opt
    character(len=*),       intent(in)    :: line
    integer(kind=argu_k),   intent(in)    :: iarg
    character(len=*),       intent(inout) :: value
    logical,                intent(inout) :: error
    !
    integer(kind=4) :: nc
    character(len=*), parameter :: rname='GET>ARG>ST'
    !
    call cubesyntax_message(syntaxseve%trace,rname,'Welcome')
    !
    call opt%traphelp(line,iarg,value,nc,error)
    if (error) return
  end subroutine cubetools_option_getarg_st
  !
  !---General-routines-----------------------------------------------------
  !
  subroutine cubetools_option_init(opt,error)
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(primitive_opt_t), intent(out)   :: opt
    logical,                intent(inout) :: error
    !
    character(len=*), parameter :: rname='OPTION>INIT'
    !
    call cubesyntax_message(syntaxseve%trace,rname,'Welcome')
  end subroutine cubetools_option_init
  !
  subroutine cubetools_option_final(opt,error)
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(primitive_opt_t), intent(out)   :: opt
    logical,                intent(inout) :: error
    !
    character(len=*), parameter :: rname='OPTION>FINAL'
    !
    call cubesyntax_message(syntaxseve%trace,rname,'Welcome')
    !
    call cubetools_option_free(opt,error)
    if (error) return
  end subroutine cubetools_option_final
  !
  function cubetools_primitive_opt_ptr(tot,error)
    !-------------------------------------------------------------------
    ! Check if the input class is of type(primitive_opt_t), and return
    ! a pointer to it if relevant.
    !-------------------------------------------------------------------
    class(primitive_opt_t), pointer :: cubetools_primitive_opt_ptr  ! Function value on return
    class(tools_object_t), pointer       :: tot
    logical,               intent(inout) :: error
    !
    character(len=*), parameter :: rname='PRIMITIVE>OPT>PTR'
    !
    select type(tot)
    class is (primitive_opt_t)
      cubetools_primitive_opt_ptr => tot
    class default
      cubetools_primitive_opt_ptr => null()
      call cubesyntax_message(seve%e,rname,  &
        'Internal error: object is not a primitive_opt_t type')
      error = .true.
      return
    end select
  end function cubetools_primitive_opt_ptr
  !
  subroutine cubetools_option_free(opt,error)
    !----------------------------------------------------------------------
    ! Free the contents of an 'primitive_opt_t'
    !----------------------------------------------------------------------
    class(primitive_opt_t), intent(inout) :: opt
    logical,                intent(inout) :: error
    !
    character(len=*), parameter :: rname='OPTION>FREE'
    !
    call cubesyntax_message(syntaxseve%trace,rname,'Welcome')
    !
    call opt%arg%free(error)
    if (error) return
  end subroutine cubetools_option_free
  !
  !---Registering----------------------------------------------------------
  !
  subroutine cubetools_option_put(opt,inum,name,syntax,abstract,help,error)
    use gkernel_interfaces
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(primitive_opt_t), intent(inout) :: opt
    integer(kind=opti_k),   intent(in)    :: inum
    character(len=*),       intent(in)    :: name
    character(len=*),       intent(in)    :: syntax
    character(len=*),       intent(in)    :: abstract
    character(len=*),       intent(in)    :: help
    logical,                intent(inout) :: error
    !
    character(len=file_l) :: filename
    character(len=*), parameter :: rname='OPTION>PUT'
    !
    call cubesyntax_message(syntaxseve%trace,rname,'Welcome')
    !
    call cubetools_option_final(opt,error)
    if (error) return
    call cubetools_option_init(opt,error)
    if (error) return
    !
    opt%inum     = inum
    opt%name     = name
    opt%syntax   = syntax
    opt%abstract = abstract
    if (help.eq.strg_id) then
      opt%help_src = help_src_none
    else
      call sic_parse_file(help,'','',filename)
      if (gag_inquire(filename,len_trim(filename)).eq.0) then
         opt%help_src = help_src_file
         opt%help_file = filename
      else
         opt%help_src = help_src_strg
         opt%help_strg = help
      endif
    endif
    opt%nargmin  = 0
    opt%nargmax  = 0
  end subroutine cubetools_option_put
  !
  !---Listing-and-Help---------------------------------------------------
  !
  subroutine cubetools_option_print_syntax(opt,error)
    use cubetools_format
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(primitive_opt_t), intent(in)    :: opt
    logical,                intent(inout) :: error
    !
    integer(kind=4) :: width,nmess,noptsyntax
    character(len=mess_l) :: mess,key
    character(len=synt_l) :: optsyntax
    character(len=*), parameter :: rname='OPTION>PRINT>SYNTAX'
    !
    call cubesyntax_message(syntaxseve%trace,rname,'Welcome')
    !
    mess = ''
    nmess = 0
    width = terminal%width()
    key = 'Syntax'
    call opt%build_syntax(optsyntax,error)
    if (error)  return
    noptsyntax = len_trim(optsyntax)
    width = width+bold_l
    mess = '  '//cubetools_format_stdkey_stdval(key,optsyntax,width)
    call cubesyntax_message(syntaxseve%help,rname,mess)
  end subroutine cubetools_option_print_syntax
  !
  subroutine cubetools_option_list(opt,error)
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(primitive_opt_t), intent(in)    :: opt
    logical,                intent(inout) :: error
    !
    character(len=mess_l) :: mess
    integer(kind=narg_k) :: iarg
    class(primitive_arg_t), pointer :: arg
    character(len=*), parameter :: rname='OPTION>LIST'
    !
    call cubesyntax_message(syntaxseve%trace,rname,'Welcome')
    !
    if (opt%arg%n.le.0) return
    !
    call cubesyntax_message(syntaxseve%help,rname,terminal%dash_strg())
    write(mess,'(a)') '  Arguments'
    call cubesyntax_message(syntaxseve%help,rname,mess)
    do iarg=1,opt%arg%n
       arg => cubetools_primitive_arg_ptr(opt%arg%list(iarg)%p,error)
       if (error) return
       call arg%print_abstract(iarg,error)
       if (error) return
    enddo !iarg
  end subroutine cubetools_option_list
  !
  subroutine cubetools_option_help(opt,error)
    !-------------------------------------------------------------------
    ! Print option help
    !-------------------------------------------------------------------
    class(primitive_opt_t), intent(in)    :: opt
    logical,                intent(inout) :: error
    !
    character(len=*), parameter :: rname='OPTION>HELP'
    !
    call cubesyntax_message(syntaxseve%trace,rname,'Welcome')
    !
    select case (opt%help_src)
    case (help_src_none)
      ! Only abstract is available
      return
    case (help_src_strg)
      call opt%print_help_strg(error)
      if (error) return
    case (help_src_file)
      call opt%print_help_file(error)
      if (error) return
    case default
      call cubesyntax_message(seve%e,rname,'Unexpected help source')
      error = .true.
      return
    end select
    !
  end subroutine cubetools_option_help
  !
  subroutine cubetools_option_print_help_strg(opt,error)
    !-------------------------------------------------------------------
    ! Print option help from opt%help_strg
    !-------------------------------------------------------------------
    class(primitive_opt_t), intent(in)    :: opt
    logical,                intent(inout) :: error
    !
    character(len=*), parameter :: rname='OPTION>PRINT>HELP>STRG'
    !
    call cubesyntax_message(syntaxseve%trace,rname,'Welcome')
    !
    call cubesyntax_message(syntaxseve%help,rname,blankstr)
    call terminal%print_strg(opt%help_strg,error)
    if (error) return
  end subroutine cubetools_option_print_help_strg
  !
  subroutine cubetools_option_print_help_file(opt,error)
    use gkernel_interfaces
    !-------------------------------------------------------------------
    ! Print option help from file opt%help_file
    !-------------------------------------------------------------------
    class(primitive_opt_t), intent(in)    :: opt
    logical,                intent(inout) :: error
    !
    character(len=*), parameter :: rname='OPTION>PRINT>HELP>FILE'
    character(len=256) :: line
    integer(kind=4) :: ier,ilun
    !
    call cubesyntax_message(syntaxseve%trace,rname,'Welcome')
    !
    call cubesyntax_message(syntaxseve%help,rname,blankstr)
    !
    ier = sic_getlun(ilun)
    if (ier.ne.1) then
      call cubesyntax_message(seve%e,rname,'No logical unit left')
      error = .true.
      return
    endif
    ier = sic_open(ilun,opt%help_file,'OLD',.true.)
    if (ier.ne.0) then
      call cubesyntax_message(seve%e,rname,'Cannot open '//opt%help_file)
      call putios('E-OPTION>HELP>FILE,  ',ier)
      error = .true.
      return
    endif
    do while (.true.)
      read(ilun,'(A)',end=40,err=50) line
      if (line.eq.'ENDOFHELP')  goto 40
      call cubesyntax_message(syntaxseve%help,rname,line)
    enddo
    !
    ! Error
50  call cubesyntax_message(seve%e,rname,'Error reading '//opt%help_file)
    error = .true.
    !
    ! Error and success
40  ier = sic_close(ilun)
    call sic_frelun(ilun)
  end subroutine cubetools_option_print_help_file
  !
  subroutine cubetools_option_summary(opt,error)
    !-------------------------------------------------------------------
    ! Short option summary
    !-------------------------------------------------------------------
    class(primitive_opt_t), intent(in)    :: opt
    logical,                intent(inout) :: error
    !
    character(len=*), parameter :: rname='OPTION>SUMMARY'
    !
    call cubesyntax_message(syntaxseve%trace,rname,'Welcome')
    !
    call opt%print_syntax(error)
    if (error) return
    call cubesyntax_message(syntaxseve%help,rname,terminal%dash_strg())
    call opt%print_abstract(error)
    if (error) return
    call opt%help(error)
    if (error) return
    call opt%list(error)
    if (error) return
    call cubesyntax_message(syntaxseve%help,rname,blankstr)
  end subroutine cubetools_option_summary
  !
  subroutine cubetools_option_show_syntax(opt,error)
    !-------------------------------------------------------------------
    ! Short option syntax reminder
    !-------------------------------------------------------------------
    class(primitive_opt_t), intent(in)    :: opt
    logical,                intent(inout) :: error
    !
    character(len=*), parameter :: rname='OPTION>SHOW>SYNTAX'
    !
    call cubesyntax_message(syntaxseve%trace,rname,'Welcome')
    !
    call opt%print_syntax(error)
    call opt%list(error)
    call cubesyntax_message(syntaxseve%help,rname,'')
  end subroutine cubetools_option_show_syntax
  !
  subroutine cubetools_option_help_onearg(opt,arg,error)
    use cubetools_disambiguate
    !-------------------------------------------------------------------
    ! Disambiguate and show the help for one argument of the option
    ! (among all the other arguments). Might show the option help as
    ! fallback.
    !-------------------------------------------------------------------
    class(primitive_opt_t), intent(in)    :: opt
    character(len=*),       intent(in)    :: arg
    logical,                intent(inout) :: error
    !
    integer(kind=4) :: iarg,ikey
    character(len=argu_l) :: solved
    class(primitive_arg_t), pointer :: parg
    character(len=argu_l), allocatable :: arglist(:)
    character(len=*), parameter :: rname='OPTION>PRESENT'
    !
    call cubesyntax_message(syntaxseve%trace,rname,'Welcome')
    !
    ! Build the list of argument names
    allocate(arglist(opt%arg%n))
    do iarg=1,opt%arg%n
      parg => cubetools_primitive_arg_ptr(opt%arg%list(iarg)%p,error)
      if (error) return
      arglist(iarg) = parg%name
    enddo
    !
    ! Identify and show help
    call cubetools_disambiguate_flexible(arg,arglist,ikey,solved,error)
    if (error) return
    if (ikey.eq.code_unresolved) then
      ! Not a known argument
      call cubesyntax_message(seve%w,rname,  &
        'Unrecognized argument '//arg//'. Possible arguments are:')
      call opt%list(error)
      if (error) return
    else
      ! Show argument help summary
      parg => cubetools_primitive_arg_ptr(opt%arg%list(ikey)%p,error)
      call parg%summary(error)
      if (error) return
    endif
  end subroutine cubetools_option_help_onearg
  !
  subroutine cubetools_option_help_iterate(opt,langname,commname,error)
    !-------------------------------------------------------------------
    !
    !-------------------------------------------------------------------
    class(primitive_opt_t), intent(in)    :: opt
    character(len=*),       intent(in)    :: langname
    character(len=*),       intent(in)    :: commname
    logical,                intent(inout) :: error
    !
    character(len=*), parameter :: rname='OPTION>HELP>ITERATE'
    !
    call cubesyntax_message(syntaxseve%help,rname,'\subsubsection{'//trim(commname)//' /'//trim(opt%name)//'}')
    call cubesyntax_message(syntaxseve%help,rname,'\label{sec:'//trim(langname)//':'//trim(commname)//&
         ':'//trim(opt%name)//':help}')
    call cubesyntax_message(syntaxseve%help,rname,'\index{'//trim(langname)//' '//trim(commname)//&
         ' /'//trim(opt%name)//' option}')
    !
    call cubesyntax_message(syntaxseve%help,rname,'\begin{PlusVerbatim}')
    call opt%summary(error)
    if (error) return
    call cubesyntax_message(syntaxseve%help,rname,'\end{PlusVerbatim}')
  end subroutine cubetools_option_help_iterate
  !
end module cubetools_primitive_opt
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
