2019-10-20 02:01:59 +03:00
|
|
|
{-# LANGUAGE DeriveDataTypeable #-}
|
|
|
|
|
2014-03-26 04:10:30 +04:00
|
|
|
{-|
|
|
|
|
|
|
|
|
hledger's cmdargs modes parse command-line arguments to an
|
|
|
|
intermediate format, RawOpts (an association list), rather than a
|
|
|
|
fixed ADT like CliOpts. This allows the modes and flags to be reused
|
|
|
|
more easily by hledger commands/scripts in this and other packages.
|
|
|
|
|
|
|
|
-}
|
|
|
|
|
|
|
|
module Hledger.Data.RawOptions (
|
|
|
|
RawOpts,
|
|
|
|
setopt,
|
|
|
|
setboolopt,
|
|
|
|
inRawOpts,
|
|
|
|
boolopt,
|
2019-10-20 02:01:59 +03:00
|
|
|
choiceopt,
|
|
|
|
collectopts,
|
2014-03-26 04:10:30 +04:00
|
|
|
stringopt,
|
|
|
|
maybestringopt,
|
|
|
|
listofstringopt,
|
|
|
|
intopt,
|
2018-09-07 20:12:13 +03:00
|
|
|
maybeintopt,
|
|
|
|
maybecharopt
|
2014-03-26 04:10:30 +04:00
|
|
|
)
|
|
|
|
where
|
|
|
|
|
|
|
|
import Data.Maybe
|
2019-10-20 02:01:59 +03:00
|
|
|
import Data.Data
|
|
|
|
import Data.Default
|
2014-03-26 04:10:30 +04:00
|
|
|
import Safe
|
|
|
|
|
|
|
|
import Hledger.Utils
|
|
|
|
|
|
|
|
|
|
|
|
-- | The result of running cmdargs: an association list of option names to string values.
|
2019-10-20 02:01:59 +03:00
|
|
|
newtype RawOpts = RawOpts { unRawOpts :: [(String,String)] }
|
|
|
|
deriving (Show, Data, Typeable)
|
|
|
|
|
|
|
|
instance Default RawOpts where def = RawOpts []
|
|
|
|
|
|
|
|
overRawOpts f = RawOpts . f . unRawOpts
|
2014-03-26 04:10:30 +04:00
|
|
|
|
|
|
|
setopt :: String -> String -> RawOpts -> RawOpts
|
2019-10-20 02:01:59 +03:00
|
|
|
setopt name val = overRawOpts (++ [(name, val)])
|
2014-03-26 04:10:30 +04:00
|
|
|
|
|
|
|
setboolopt :: String -> RawOpts -> RawOpts
|
2019-10-20 02:01:59 +03:00
|
|
|
setboolopt name = overRawOpts (++ [(name,"")])
|
2014-03-26 04:10:30 +04:00
|
|
|
|
|
|
|
-- | Is the named option present ?
|
|
|
|
inRawOpts :: String -> RawOpts -> Bool
|
2019-10-20 02:01:59 +03:00
|
|
|
inRawOpts name = isJust . lookup name . unRawOpts
|
2014-03-26 04:10:30 +04:00
|
|
|
|
|
|
|
boolopt :: String -> RawOpts -> Bool
|
|
|
|
boolopt = inRawOpts
|
|
|
|
|
2019-11-24 00:03:26 +03:00
|
|
|
-- | From a list of RawOpts, get the last one (ie the right-most on the command line)
|
|
|
|
-- for which the given predicate returns a Just value.
|
|
|
|
-- Useful for exclusive choice flags like --daily|--weekly|--quarterly...
|
2019-10-20 02:01:59 +03:00
|
|
|
--
|
|
|
|
-- >>> choiceopt Just (RawOpts [("a",""), ("b",""), ("c","")])
|
|
|
|
-- Just "c"
|
|
|
|
-- >>> choiceopt (const Nothing) (RawOpts [("a","")])
|
|
|
|
-- Nothing
|
2019-11-19 22:43:19 +03:00
|
|
|
-- >>> choiceopt readMay (RawOpts [("LT",""),("EQ",""),("Neither","")]) :: Maybe Ordering
|
|
|
|
-- Just EQ
|
|
|
|
choiceopt :: (String -> Maybe a) -- ^ "parser" that returns 'Just' value for valid choice
|
|
|
|
-> RawOpts -- ^ actual options where to look for flag
|
|
|
|
-> Maybe a -- ^ exclusive choice among those returned as 'Just' from "parser"
|
2019-10-20 02:01:59 +03:00
|
|
|
choiceopt f = lastMay . collectopts (f . fst)
|
|
|
|
|
|
|
|
-- | Collects processed and filtered list of options preserving their order
|
|
|
|
--
|
|
|
|
-- >>> collectopts (const Nothing) (RawOpts [("x","")])
|
|
|
|
-- []
|
|
|
|
-- >>> collectopts Just (RawOpts [("a",""),("b","")])
|
|
|
|
-- [("a",""),("b","")]
|
|
|
|
collectopts :: ((String, String) -> Maybe a) -> RawOpts -> [a]
|
|
|
|
collectopts f = mapMaybe f . unRawOpts
|
|
|
|
|
2014-03-26 04:10:30 +04:00
|
|
|
maybestringopt :: String -> RawOpts -> Maybe String
|
2019-10-20 02:01:59 +03:00
|
|
|
maybestringopt name = lookup name . reverse . unRawOpts
|
2014-03-26 04:10:30 +04:00
|
|
|
|
|
|
|
stringopt :: String -> RawOpts -> String
|
|
|
|
stringopt name = fromMaybe "" . maybestringopt name
|
|
|
|
|
2018-09-07 20:12:13 +03:00
|
|
|
maybecharopt :: String -> RawOpts -> Maybe Char
|
2019-10-20 02:01:59 +03:00
|
|
|
maybecharopt name (RawOpts rawopts) = lookup name rawopts >>= headMay
|
2018-09-07 20:12:13 +03:00
|
|
|
|
2014-03-26 04:10:30 +04:00
|
|
|
listofstringopt :: String -> RawOpts -> [String]
|
2019-10-20 02:01:59 +03:00
|
|
|
listofstringopt name (RawOpts rawopts) = [v | (k,v) <- rawopts, k==name]
|
2014-03-26 04:10:30 +04:00
|
|
|
|
|
|
|
maybeintopt :: String -> RawOpts -> Maybe Int
|
|
|
|
maybeintopt name rawopts =
|
|
|
|
let ms = maybestringopt name rawopts in
|
|
|
|
case ms of Nothing -> Nothing
|
2017-03-29 18:00:30 +03:00
|
|
|
Just s -> Just $ readDef (usageError $ "could not parse "++name++" number: "++s) s
|
2014-03-26 04:10:30 +04:00
|
|
|
|
|
|
|
intopt :: String -> RawOpts -> Int
|
|
|
|
intopt name = fromMaybe 0 . maybeintopt name
|
|
|
|
|