NAMELIST input has some underutilized uses. Unlike similar file formats it is built into the standard, allows multiple sets in a single file which it searches sequentially for by name, and ignores lines in the file not in a NAMELIST group format. One perhaps unexpected use is to let you simulate exposing variables in the program for the user to change interactively.
Taking advantage of NAMELIST reads not requiring all values to be specified, it takes very little code to make an interactive prompt for values of the form
NAME=VALUE(S)
For example, the following relatively short program shows placing a number of variables into a NAMELIST and then letting you interactively change them with a session looking something like:
args>>show
args>>f='courier' t='new title'
args>>view=1,2,3
args>>a=456.789
args>>! run with new values
args>> .
args>>h=t
args>>! run again
args>> .
args>>stop
program namelist_prompter
implicit none
! create a NAMELIST group with lots of options
! this is just a sample
real :: a=0.0
real :: view(3)=[0.0,0.0,0.0]
character(len=80) :: t='title'
character(len=80) :: f='roman'
logical :: h=.false.
namelist /args/ a,view,t,h,f
character(len=:),allocatable :: status
character(len=256) :: answer
integer :: lun
integer :: ios
do
call readargs(status) ! interactively change NAMELIST group
if(status.eq.'stop')exit
call dosomething() ! use the NAMELIST values
enddo
contains
subroutine readargs(status)
character(len=:),intent(out),allocatable :: status
character(len=256) :: line
status=''
write(*,'(a)')'args>> "." to run, "stop" to end, "show" to show &
& keywords,"read","write","sh"'
do
write(*,'(a)',advance='no')'args>>'
read(*,'(a)')line
if(line(1:1).eq.'!')cycle
select case(line)
case('.')
exit
case('show')
write(*,*)'SO FAR'
write(*,args)
case('stop')
status='stop'
exit
case('sh')
call execute_command_line('bash')
case('read')
write(*,'(a)',advance='no')'filename:'
read(*,'(a)',iostat=ios)answer
if(ios.ne.0)exit
open(file=answer,iostat=ios,newunit=lun)
if(ios.ne.0)exit
read(lun,args,iostat=ios)
close(unit=lun,iostat=ios)
case('write')
write(*,'(a)',advance='no')'filename:'
read(*,'(a)',iostat=ios)answer
if(ios.ne.0)exit
open(file=answer,iostat=ios,newunit=lun)
if(ios.ne.0)exit
write(lun,args,iostat=ios)
close(unit=lun,iostat=ios)
case default
UPDATE: block
character(len=:),allocatable :: intmp
character(len=256) :: message
integer :: ios
intmp='&ARGS '//trim(line)//'/'
read(intmp,nml=args,iostat=ios,iomsg=message)
if(ios.ne.0)then
write(*,*)'ERROR:',trim(message)
endif
endblock UPDATE
end select
enddo
end subroutine readargs
subroutine dosomething()
! placeholder
write(*,*)'USE ALL THOSE VALUES'
end subroutine dosomething
end program namelist_prompter