Skip to content
/ M_CLI Public template

Unix-like command line parsing -- prototype style converts command line to a NAMELIST group

License

Notifications You must be signed in to change notification settings

urbanjost/M_CLI

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

87 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

M_CLI.f90 and associated files

parse

Name

M_CLI - parse Unix-like command line arguments from Fortran

Description

M_CLI(3f) is a Fortran module that will crack the command line when given a NAMELIST and a prototype string that looks very much like an invocation of the program. Using the NAMELIST group has the benefit that there is no requirement to convert the strings to their required types or to duplicate the type declarations.

Download

    git clone https://github.com/urbanjost/M_CLI.git
    cd M_CLI/src
    # change Makefile if not using one of the listed compilers
  
    # for gfortran
    make clean
    make F90=gfortran gfortran
  
    # for ifort
    make clean
    make F90=ifort ifort

    # for nvfortran
    make clean
    make F90=nvfortran nvfortran

This will compile the M_CLI module and build all the example programs.

Supports FPM fpm

(registered at the fpm(1) registry )

Alternatively, download the github repository and build it with fpm ( as described at Fortran Package Manager )

     git clone https://github.com/urbanjost/M_CLI.git
     cd M_CLI
     fpm test

or just list it as a dependency in your fpm.toml project file.

        [dependencies]
        M_CLI        = { git = "https://github.com/urbanjost/M_CLI.git" }

Functional Specification

This is how the interface works --

  • Basically you define a NAMELIST group called ARGS that has the names of all your command line arguments.
  • Next, pass in a string that looks like the command you would use to execute the program with all values specified.
  • you read the output as the NAMELIST group ARGS with a fixed block of code (that could be in an INCLUDE file)
  • Now call a routine to handle errors and help-related text

Now all the values in the NAMELIST should be updated using values from the command line and ready to use.

Documentation docs

There are several styles possible for defining the NAMELIST group as well as options on whether to do the parsing in the main program or in a contained procedure. These demo programs provide templates for the most common usage:

  • demo1 full usage
  • demo2 shows putting everything including help and version information into a contained procedure.
  • demo3 example of basic use
  • demo4 using COMPLEX values!
  • demo5 demo2 with added example code for interactively editing the NAMELIST group
  • demo6 a more complex example showing how to create a command with subcommands
  • demo7 problems with CHARACTER arrays and quotes

man-pages

  • M_CLI -- An overview of the M_CLI module

  • commandline -- parses the command line options

  • check_commandline -- convenience routine for checking status of READ of NAMELIST group

  • print_dictionary -- print the dictionary of command line keywords and values (typically not directly by a user, as automatically called when --usage option is supplied).

  • specified -- detect if a keyword was specified on the command line

  • BOOK_M_CLI -- All man-pages consolidated using JavaScript

doxygen

Example Program

This short program defines a command that can be called like

   ./show -x 10 -y -20 --point 10,20,30 --title 'plot of stuff' *.in
   ./show -x 10 -y -20 --point 10,20,30 --title 'plot of stuff' *.in
   ./show -z 300
   ./show *.in
   ./show --usage
   ./show --help
   ./show --version
   program show
   use M_CLI, only : commandline, check_commandline, files=>unnamed
   implicit none
   integer :: i
   
   !! DEFINE NAMELIST
   real               :: x, y, z             ; namelist /args/ x,y,z
   real               :: point(3)            ; namelist /args/ point
   character(len=80)  :: title               ; namelist /args/ title
   logical            :: l                   ; namelist /args/ l
   
   !! DEFINE COMMAND
   character(len=*),parameter :: cmd= &
      '-x 1 -y 2.0 -z 3.5e0 --point -1,-2,-3 --title "my title" -l F '
   
   !! THIS BLOCK DOES THE COMMAND LINE PARSING AND SHOULD NOT HAVE TO CHANGE
      COMMANDLIN : block
         character(len=255)           :: message
         character(len=:),allocatable :: readme
         integer                      :: ios
         readme=commandline(cmd)
         read(readme,nml=args,iostat=ios,iomsg=message) !! UPDATE NAMELIST VARIABLES
         call check_commandline(ios,message)     !! HANDLE ERRORS FROM NAMELIST READ AND --usage
      endblock COMMANDLIN
   
   !! USE THE VALUES IN YOUR PROGRAM.
      write(*,nml=args)
   
   !! OPTIONAL UNNAMED VALUES FROM COMMAND LINE
      if(size(files).gt.0)then
         write(*,'(a)')'files:'
         write(*,'(i6.6,3a)')(i,'[',files(i),']',i=1,size(files))
      endif
   
   end program show

Feedback

Please provide feedback on the wiki or in the issues section or star the repository if you use the module (or let me know why not and let others know what you did use!).


Other things to do with NAMELIST

click on the link for some unusual things to do with NAMELIST, Capture and Replay unit testing, exposing variables for interactive editing ...