4

I am currently working on a project that requires parsing command line arguments. So far I have been following this tutorial, which has been incredibly helpful, but I can't figure out how to return a variable (--author=example) in the arguments. I also can't figure out why parse [] = getContents causes an error (I had to uncomment it).

Here is my code:

module Main where

import qualified System.Environment as SE
import qualified System.Exit as E
import qualified Lib as Lib

main = do
  args <- SE.getArgs
  rem <- parse args
  Lib.someFunc
  putStrLn rem
  putStrLn "Hello"

tac  = unlines . reverse . lines

parse ["--help"]    = usage   >> exit
parse ["--version"] = version >> exit
parse ["--author=xyz"] = return "xyz"
-- parse ["--author=?"] = ?
{-
this is the code I am trying to figure out... how do I get parse the passed in variable name?
-}

-- parse []            = getContents
{-
the above line generates this error when I run 'main' in GHCi:

  *Main> <stdin>: hIsEOF: illegal operation (handle is semi-closed)
  Process intero exited abnormally with code 1

-}
parse fs            = concat `fmap` mapM readFile fs

usage   = putStrLn "Usage: gc2"
version = putStrLn "gc2 -- git-cal in Haskell2010 - 0.1"
exit    = E.exitWith E.ExitSuccess
die     = E.exitWith (E.ExitFailure 1)
6
  • 2
    getContents fetches ALL the input, and requires that you don't read anything from input after that. Are you satisfying that contract? Check Lib.someFunc, for instance. Commented Dec 6, 2017 at 21:37
  • Thank you, that makes sense (and it seems the error was because I was using System.Process in Lib.someFunc). Commented Dec 6, 2017 at 21:40
  • 1
    There are argument parsing libraries out there. Is there a reason not to use one of them? Commented Dec 6, 2017 at 21:51
  • @ThomasM.DuBuisson: I am ignorant of those. Would you mind pointing me towards them? Commented Dec 6, 2017 at 21:56
  • 2
    optparse-applicative is the powerful preferred parser by many developers. However, for simple jobs I like the aptly named simple-get-opt. Commented Dec 6, 2017 at 21:59

1 Answer 1

9

To follow up on @ThomasM.DuBuisson comment optparse-applicative is a great package for cli and arguments parsing. There is also another package optparse-simple that is built on top of the previous one and has a few helpers that simplify things a bit.

Just so you can get started with optparse-applicative here is an implementation of your example:

data Options = Options
  { author :: String
  }

main :: IO ()
main = do
  let ver = "gc2 -- git-cal in Haskell2010 - 0.1"
  args <-
    execParser $
    info
      (Options <$>
       strOption (long "author" <>
                  short 'a' <>
                  help "Name of the author.") <*
       infoOption ver (long "version" <>
                       short 'v' <>
                       help "Display version and exit.") <*
       abortOption ShowHelpText (long "help" <>
                                 short 'h' <>
                                 help "Display this message."))
      (progDesc "Very powerful tool." <> fullDesc)
  putStrLn $ author args

And usage example from GHCi:

λ> :main
Missing: (-a|--author ARG)

Usage: <interactive> (-a|--author ARG) [-v|--version] [-h|--help]
  Very powerful tool.
*** Exception: ExitFailure 1
λ> :main --version
gc2 -- git-cal in Haskell2010 - 0.1
*** Exception: ExitSuccess
λ> :main --help
Usage: <interactive> (-a|--author ARG) [-v|--version] [-h|--help]
  Very powerful tool.

Available options:
  -a,--author ARG          Name of the author.
  -v,--version             Display version and exit.
  -h,--help                Display this message.
*** Exception: ExitSuccess
λ> :main --author Me
Me
Sign up to request clarification or add additional context in comments.

2 Comments

What's the ShowHelpText?
@przemo_li It is a type constructor that will fail parsing the cli arguments and terminate the program while showing the help test, i.e. options, descriptions and such. stackage.org/haddock/lts-12.5/optparse-applicative-0.14.2.0/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.