-- |
-- Module: NetSpider.CLI.Snapshot
-- Description: CLI option parser for Query for snapshot graphs
-- Maintainer: Toshio Ito <toshio9.ito@toshiba.co.jp>
--
-- This module defines CLI option parser for 'Q.Query' for snapshot
-- graphs.
module NetSpider.CLI.Snapshot
  ( parserSnapshotQuery,
    makeSnapshotQuery,
    SnapshotConfig(..),
    CLISnapshotQuery
  ) where

import Control.Applicative ((<$>), (<*>), (<|>), many, optional, empty)
import Data.Int (Int64)
import NetSpider.Interval
  ( interval, parseTimeIntervalEnd, secSince, secUntil,
    IntervalEnd, Interval
  )
import qualified NetSpider.Query as Q
import NetSpider.Timestamp (Timestamp)
import qualified Options.Applicative as Opt
import qualified Options.Applicative.Types as OptT

-- | Configuration for option parser for Snapshot 'Q.Query'.
--
-- @since 0.2.0.0
data SnapshotConfig n =
  SnapshotConfig
  { SnapshotConfig n -> ReadM n
nodeIDReader :: Opt.ReadM n,
    -- ^ Parser that reads a CLI option to generate a node ID.
    SnapshotConfig n -> Bool
startsFromAsArguments :: Bool
    -- ^ If 'True', the 'Q.startsFrom' field is read from CLI
    -- arguments. If 'False', arguments are not parsed. In either
    -- case, \"-s\" option is always parsed to generate
    -- 'Q.startsFrom'.
  }

-- | Settings for Snapshot 'Q.Query' parsed from the command-line
-- options. You can make 'Q.Query' by 'makeSnapshotQuery' function.
--
-- @since 0.2.0.0
data CLISnapshotQuery n =
  CLISnapshotQuery
  { CLISnapshotQuery n -> [n]
startsFrom :: [n],
    CLISnapshotQuery n -> Maybe Int64
timeDurationSec :: Maybe Int64,
    CLISnapshotQuery n -> Maybe (IntervalEnd Timestamp)
timeFrom :: Maybe (IntervalEnd Timestamp),
    CLISnapshotQuery n -> Maybe (IntervalEnd Timestamp)
timeTo :: Maybe (IntervalEnd Timestamp)
  }
  deriving (Int -> CLISnapshotQuery n -> ShowS
[CLISnapshotQuery n] -> ShowS
CLISnapshotQuery n -> String
(Int -> CLISnapshotQuery n -> ShowS)
-> (CLISnapshotQuery n -> String)
-> ([CLISnapshotQuery n] -> ShowS)
-> Show (CLISnapshotQuery n)
forall n. Show n => Int -> CLISnapshotQuery n -> ShowS
forall n. Show n => [CLISnapshotQuery n] -> ShowS
forall n. Show n => CLISnapshotQuery n -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CLISnapshotQuery n] -> ShowS
$cshowList :: forall n. Show n => [CLISnapshotQuery n] -> ShowS
show :: CLISnapshotQuery n -> String
$cshow :: forall n. Show n => CLISnapshotQuery n -> String
showsPrec :: Int -> CLISnapshotQuery n -> ShowS
$cshowsPrec :: forall n. Show n => Int -> CLISnapshotQuery n -> ShowS
Show,CLISnapshotQuery n -> CLISnapshotQuery n -> Bool
(CLISnapshotQuery n -> CLISnapshotQuery n -> Bool)
-> (CLISnapshotQuery n -> CLISnapshotQuery n -> Bool)
-> Eq (CLISnapshotQuery n)
forall n. Eq n => CLISnapshotQuery n -> CLISnapshotQuery n -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CLISnapshotQuery n -> CLISnapshotQuery n -> Bool
$c/= :: forall n. Eq n => CLISnapshotQuery n -> CLISnapshotQuery n -> Bool
== :: CLISnapshotQuery n -> CLISnapshotQuery n -> Bool
$c== :: forall n. Eq n => CLISnapshotQuery n -> CLISnapshotQuery n -> Bool
Eq,Eq (CLISnapshotQuery n)
Eq (CLISnapshotQuery n)
-> (CLISnapshotQuery n -> CLISnapshotQuery n -> Ordering)
-> (CLISnapshotQuery n -> CLISnapshotQuery n -> Bool)
-> (CLISnapshotQuery n -> CLISnapshotQuery n -> Bool)
-> (CLISnapshotQuery n -> CLISnapshotQuery n -> Bool)
-> (CLISnapshotQuery n -> CLISnapshotQuery n -> Bool)
-> (CLISnapshotQuery n -> CLISnapshotQuery n -> CLISnapshotQuery n)
-> (CLISnapshotQuery n -> CLISnapshotQuery n -> CLISnapshotQuery n)
-> Ord (CLISnapshotQuery n)
CLISnapshotQuery n -> CLISnapshotQuery n -> Bool
CLISnapshotQuery n -> CLISnapshotQuery n -> Ordering
CLISnapshotQuery n -> CLISnapshotQuery n -> CLISnapshotQuery n
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall n. Ord n => Eq (CLISnapshotQuery n)
forall n. Ord n => CLISnapshotQuery n -> CLISnapshotQuery n -> Bool
forall n.
Ord n =>
CLISnapshotQuery n -> CLISnapshotQuery n -> Ordering
forall n.
Ord n =>
CLISnapshotQuery n -> CLISnapshotQuery n -> CLISnapshotQuery n
min :: CLISnapshotQuery n -> CLISnapshotQuery n -> CLISnapshotQuery n
$cmin :: forall n.
Ord n =>
CLISnapshotQuery n -> CLISnapshotQuery n -> CLISnapshotQuery n
max :: CLISnapshotQuery n -> CLISnapshotQuery n -> CLISnapshotQuery n
$cmax :: forall n.
Ord n =>
CLISnapshotQuery n -> CLISnapshotQuery n -> CLISnapshotQuery n
>= :: CLISnapshotQuery n -> CLISnapshotQuery n -> Bool
$c>= :: forall n. Ord n => CLISnapshotQuery n -> CLISnapshotQuery n -> Bool
> :: CLISnapshotQuery n -> CLISnapshotQuery n -> Bool
$c> :: forall n. Ord n => CLISnapshotQuery n -> CLISnapshotQuery n -> Bool
<= :: CLISnapshotQuery n -> CLISnapshotQuery n -> Bool
$c<= :: forall n. Ord n => CLISnapshotQuery n -> CLISnapshotQuery n -> Bool
< :: CLISnapshotQuery n -> CLISnapshotQuery n -> Bool
$c< :: forall n. Ord n => CLISnapshotQuery n -> CLISnapshotQuery n -> Bool
compare :: CLISnapshotQuery n -> CLISnapshotQuery n -> Ordering
$ccompare :: forall n.
Ord n =>
CLISnapshotQuery n -> CLISnapshotQuery n -> Ordering
$cp1Ord :: forall n. Ord n => Eq (CLISnapshotQuery n)
Ord)

-- | Make a 'Q.Query' by applying 'CLISnapshotQuery' to the base
-- query. The 'CLISnapshotQuery' overwrites 'Q.startsFrom' and
-- 'Q.timeInterval' fields.
--
-- It can fail to convert 'CLISnapshotQuery' to 'Q.Query' fields. In
-- that case, the result is 'Left' with a human-readable error
-- message.
--
-- @since 0.2.0.0
makeSnapshotQuery :: Q.Query n na fla sla -- ^ base query
                  -> CLISnapshotQuery n
                  -> Either String (Q.Query n na fla sla)
                  -- ^ Left: human-readable error message. Right: updated query
makeSnapshotQuery :: Query n na fla sla
-> CLISnapshotQuery n -> Either String (Query n na fla sla)
makeSnapshotQuery Query n na fla sla
q CLISnapshotQuery n
cliq = do
  Interval Timestamp
ivl <- CLISnapshotQuery n -> Either String (Interval Timestamp)
forall n. CLISnapshotQuery n -> Either String (Interval Timestamp)
makeTimeInterval CLISnapshotQuery n
cliq
  Query n na fla sla -> Either String (Query n na fla sla)
forall (m :: * -> *) a. Monad m => a -> m a
return (Query n na fla sla -> Either String (Query n na fla sla))
-> Query n na fla sla -> Either String (Query n na fla sla)
forall a b. (a -> b) -> a -> b
$ Query n na fla sla
q { startsFrom :: [n]
Q.startsFrom = CLISnapshotQuery n -> [n]
forall n. CLISnapshotQuery n -> [n]
startsFrom CLISnapshotQuery n
cliq,
               timeInterval :: Interval Timestamp
Q.timeInterval = Interval Timestamp
ivl
             }

makeTimeInterval :: CLISnapshotQuery n -> Either String (Interval Timestamp)
makeTimeInterval :: CLISnapshotQuery n -> Either String (Interval Timestamp)
makeTimeInterval CLISnapshotQuery n
c =
  case (CLISnapshotQuery n -> Maybe (IntervalEnd Timestamp)
forall n. CLISnapshotQuery n -> Maybe (IntervalEnd Timestamp)
timeFrom CLISnapshotQuery n
c, CLISnapshotQuery n -> Maybe (IntervalEnd Timestamp)
forall n. CLISnapshotQuery n -> Maybe (IntervalEnd Timestamp)
timeTo CLISnapshotQuery n
c, CLISnapshotQuery n -> Maybe Int64
forall n. CLISnapshotQuery n -> Maybe Int64
timeDurationSec CLISnapshotQuery n
c) of
    (Maybe (IntervalEnd Timestamp)
ms, Maybe (IntervalEnd Timestamp)
me, Maybe Int64
Nothing) -> Interval Timestamp -> Either String (Interval Timestamp)
forall a b. b -> Either a b
Right (Interval Timestamp -> Either String (Interval Timestamp))
-> Interval Timestamp -> Either String (Interval Timestamp)
forall a b. (a -> b) -> a -> b
$ IntervalEnd Timestamp
-> IntervalEnd Timestamp -> Interval Timestamp
forall r. Ord r => IntervalEnd r -> IntervalEnd r -> Interval r
interval IntervalEnd Timestamp
s IntervalEnd Timestamp
e
      where
        s :: IntervalEnd Timestamp
s = IntervalEnd Timestamp
-> (IntervalEnd Timestamp -> IntervalEnd Timestamp)
-> Maybe (IntervalEnd Timestamp)
-> IntervalEnd Timestamp
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Extended Timestamp
forall r. Extended r
Q.NegInf, Bool
False) IntervalEnd Timestamp -> IntervalEnd Timestamp
forall a. a -> a
id Maybe (IntervalEnd Timestamp)
ms
        e :: IntervalEnd Timestamp
e = IntervalEnd Timestamp
-> (IntervalEnd Timestamp -> IntervalEnd Timestamp)
-> Maybe (IntervalEnd Timestamp)
-> IntervalEnd Timestamp
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Extended Timestamp
forall r. Extended r
Q.PosInf, Bool
False) IntervalEnd Timestamp -> IntervalEnd Timestamp
forall a. a -> a
id Maybe (IntervalEnd Timestamp)
me
    (Just IntervalEnd Timestamp
s, Maybe (IntervalEnd Timestamp)
Nothing, Just Int64
d) -> Interval Timestamp -> Either String (Interval Timestamp)
forall a b. b -> Either a b
Right (Interval Timestamp -> Either String (Interval Timestamp))
-> Interval Timestamp -> Either String (Interval Timestamp)
forall a b. (a -> b) -> a -> b
$ Int64 -> IntervalEnd Timestamp -> Interval Timestamp
secSince Int64
d IntervalEnd Timestamp
s
    (Maybe (IntervalEnd Timestamp)
Nothing, Just IntervalEnd Timestamp
e, Just Int64
d) -> Interval Timestamp -> Either String (Interval Timestamp)
forall a b. b -> Either a b
Right (Interval Timestamp -> Either String (Interval Timestamp))
-> Interval Timestamp -> Either String (Interval Timestamp)
forall a b. (a -> b) -> a -> b
$ Int64 -> IntervalEnd Timestamp -> Interval Timestamp
secUntil Int64
d IntervalEnd Timestamp
e
    (Just IntervalEnd Timestamp
_, Just IntervalEnd Timestamp
_, Just Int64
_) -> String -> Either String (Interval Timestamp)
forall a b. a -> Either a b
Left (String
"Specifying all --time-to, --time-from and --duration is not allowed.")
    (Maybe (IntervalEnd Timestamp)
Nothing, Maybe (IntervalEnd Timestamp)
Nothing, Just Int64
_) -> String -> Either String (Interval Timestamp)
forall a b. a -> Either a b
Left (String
"Specifying --duration only is not allowed. Specify --time-to or --time-from, too.")

-- | CLI option parser for Snapshot 'Q.Query'. Use 'makeSnapshotQuery'
-- to convert 'CLISnapshotQuery' to 'Q.Query'.
--
-- @since 0.2.0.0
parserSnapshotQuery :: SnapshotConfig n
                    -> Opt.Parser (CLISnapshotQuery n)
parserSnapshotQuery :: SnapshotConfig n -> Parser (CLISnapshotQuery n)
parserSnapshotQuery SnapshotConfig n
conf =
  [n]
-> Maybe Int64
-> Maybe (IntervalEnd Timestamp)
-> Maybe (IntervalEnd Timestamp)
-> CLISnapshotQuery n
forall n.
[n]
-> Maybe Int64
-> Maybe (IntervalEnd Timestamp)
-> Maybe (IntervalEnd Timestamp)
-> CLISnapshotQuery n
CLISnapshotQuery ([n]
 -> Maybe Int64
 -> Maybe (IntervalEnd Timestamp)
 -> Maybe (IntervalEnd Timestamp)
 -> CLISnapshotQuery n)
-> Parser [n]
-> Parser
     (Maybe Int64
      -> Maybe (IntervalEnd Timestamp)
      -> Maybe (IntervalEnd Timestamp)
      -> CLISnapshotQuery n)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser [n]
pStartsFromTotal Parser
  (Maybe Int64
   -> Maybe (IntervalEnd Timestamp)
   -> Maybe (IntervalEnd Timestamp)
   -> CLISnapshotQuery n)
-> Parser (Maybe Int64)
-> Parser
     (Maybe (IntervalEnd Timestamp)
      -> Maybe (IntervalEnd Timestamp) -> CLISnapshotQuery n)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser (Maybe Int64)
pDuration Parser
  (Maybe (IntervalEnd Timestamp)
   -> Maybe (IntervalEnd Timestamp) -> CLISnapshotQuery n)
-> Parser (Maybe (IntervalEnd Timestamp))
-> Parser (Maybe (IntervalEnd Timestamp) -> CLISnapshotQuery n)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser (Maybe (IntervalEnd Timestamp))
pTimeLower Parser (Maybe (IntervalEnd Timestamp) -> CLISnapshotQuery n)
-> Parser (Maybe (IntervalEnd Timestamp))
-> Parser (CLISnapshotQuery n)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser (Maybe (IntervalEnd Timestamp))
pTimeUpper
  where
    pStartsFromTotal :: Parser [n]
pStartsFromTotal = [n] -> [n] -> [n]
forall a. [a] -> [a] -> [a]
(++) ([n] -> [n] -> [n]) -> Parser [n] -> Parser ([n] -> [n])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser [n]
pStartsFrom Parser ([n] -> [n]) -> Parser [n] -> Parser [n]
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser [n]
pStartsFromArgs
    rNodeID :: ReadM n
rNodeID = SnapshotConfig n -> ReadM n
forall n. SnapshotConfig n -> ReadM n
nodeIDReader SnapshotConfig n
conf
    nodeID_metavar :: String
nodeID_metavar = String
"NODE-ID"
    pStartsFrom :: Parser [n]
pStartsFrom = Parser n -> Parser [n]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many (Parser n -> Parser [n]) -> Parser n -> Parser [n]
forall a b. (a -> b) -> a -> b
$ ReadM n -> Mod OptionFields n -> Parser n
forall a. ReadM a -> Mod OptionFields a -> Parser a
Opt.option ReadM n
rNodeID (Mod OptionFields n -> Parser n) -> Mod OptionFields n -> Parser n
forall a b. (a -> b) -> a -> b
$ [Mod OptionFields n] -> Mod OptionFields n
forall a. Monoid a => [a] -> a
mconcat
                  [ Char -> Mod OptionFields n
forall (f :: * -> *) a. HasName f => Char -> Mod f a
Opt.short Char
's',
                    String -> Mod OptionFields n
forall (f :: * -> *) a. HasName f => String -> Mod f a
Opt.long String
"starts-from",
                    String -> Mod OptionFields n
forall (f :: * -> *) a. String -> Mod f a
Opt.help String
"ID of a node from which the Spider starts traversing the history graph. You can specify this option multiple times.",
                    String -> Mod OptionFields n
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
Opt.metavar String
nodeID_metavar
                  ]
    pStartsFromArgs :: Parser [n]
pStartsFromArgs = if Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ SnapshotConfig n -> Bool
forall n. SnapshotConfig n -> Bool
startsFromAsArguments SnapshotConfig n
conf
                      then [n] -> Parser [n]
forall (f :: * -> *) a. Applicative f => a -> f a
pure []
                      else Parser n -> Parser [n]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many (Parser n -> Parser [n]) -> Parser n -> Parser [n]
forall a b. (a -> b) -> a -> b
$ ReadM n -> Mod ArgumentFields n -> Parser n
forall a. ReadM a -> Mod ArgumentFields a -> Parser a
Opt.argument ReadM n
rNodeID (Mod ArgumentFields n -> Parser n)
-> Mod ArgumentFields n -> Parser n
forall a b. (a -> b) -> a -> b
$ [Mod ArgumentFields n] -> Mod ArgumentFields n
forall a. Monoid a => [a] -> a
mconcat
                           [ String -> Mod ArgumentFields n
forall (f :: * -> *) a. String -> Mod f a
Opt.help (String -> Mod ArgumentFields n) -> String -> Mod ArgumentFields n
forall a b. (a -> b) -> a -> b
$ String
"Same as -s option.",
                             String -> Mod ArgumentFields n
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
Opt.metavar (String -> Mod ArgumentFields n) -> String -> Mod ArgumentFields n
forall a b. (a -> b) -> a -> b
$ String
nodeID_metavar
                           ]
    pTimeLower :: Parser (Maybe (IntervalEnd Timestamp))
pTimeLower =
      Parser (IntervalEnd Timestamp)
-> Parser (Maybe (IntervalEnd Timestamp))
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Parser (IntervalEnd Timestamp)
 -> Parser (Maybe (IntervalEnd Timestamp)))
-> Parser (IntervalEnd Timestamp)
-> Parser (Maybe (IntervalEnd Timestamp))
forall a b. (a -> b) -> a -> b
$ ReadM (IntervalEnd Timestamp)
-> Mod OptionFields (IntervalEnd Timestamp)
-> Parser (IntervalEnd Timestamp)
forall a. ReadM a -> Mod OptionFields a -> Parser a
Opt.option ((String -> Either String (IntervalEnd Timestamp))
-> ReadM (IntervalEnd Timestamp)
forall a. (String -> Either String a) -> ReadM a
Opt.eitherReader String -> Either String (IntervalEnd Timestamp)
parseTimeIntervalEnd) (Mod OptionFields (IntervalEnd Timestamp)
 -> Parser (IntervalEnd Timestamp))
-> Mod OptionFields (IntervalEnd Timestamp)
-> Parser (IntervalEnd Timestamp)
forall a b. (a -> b) -> a -> b
$ [Mod OptionFields (IntervalEnd Timestamp)]
-> Mod OptionFields (IntervalEnd Timestamp)
forall a. Monoid a => [a] -> a
mconcat
      ( [ Char -> Mod OptionFields (IntervalEnd Timestamp)
forall (f :: * -> *) a. HasName f => Char -> Mod f a
Opt.short Char
'f',
          String -> Mod OptionFields (IntervalEnd Timestamp)
forall (f :: * -> *) a. HasName f => String -> Mod f a
Opt.long String
"time-from",
          String -> Mod OptionFields (IntervalEnd Timestamp)
forall (f :: * -> *) a. String -> Mod f a
Opt.help ( String
"Lower bound of query timestamp. "
                     String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"Local findings with timestamp newer than this value are used to create the snapshot graph. "
                     String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"ISO 8601 format is used for timestamps (e.g. `2019-03-22T10:20:12+09:00`). "
                     String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"The timezone is optional. "
                     String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"By default, the lower bound is inclusive. "
                     String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"Add prefix 'x' to make it exclusive (e.g. `x2019-03-22T10:20:12+09:00`). "
                     String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"Prefix of 'i' explicitly mark the lower bound is inclusive. "
                     String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"Special value `x-inf` indicates there is no lower bound. "
                     String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"Default: x-inf"
                   ),
          String -> Mod OptionFields (IntervalEnd Timestamp)
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
Opt.metavar String
"TIMESTAMP"
        ]
      )
    pTimeUpper :: Parser (Maybe (IntervalEnd Timestamp))
pTimeUpper =
      Parser (IntervalEnd Timestamp)
-> Parser (Maybe (IntervalEnd Timestamp))
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Parser (IntervalEnd Timestamp)
 -> Parser (Maybe (IntervalEnd Timestamp)))
-> Parser (IntervalEnd Timestamp)
-> Parser (Maybe (IntervalEnd Timestamp))
forall a b. (a -> b) -> a -> b
$ ReadM (IntervalEnd Timestamp)
-> Mod OptionFields (IntervalEnd Timestamp)
-> Parser (IntervalEnd Timestamp)
forall a. ReadM a -> Mod OptionFields a -> Parser a
Opt.option ((String -> Either String (IntervalEnd Timestamp))
-> ReadM (IntervalEnd Timestamp)
forall a. (String -> Either String a) -> ReadM a
Opt.eitherReader String -> Either String (IntervalEnd Timestamp)
parseTimeIntervalEnd) (Mod OptionFields (IntervalEnd Timestamp)
 -> Parser (IntervalEnd Timestamp))
-> Mod OptionFields (IntervalEnd Timestamp)
-> Parser (IntervalEnd Timestamp)
forall a b. (a -> b) -> a -> b
$ [Mod OptionFields (IntervalEnd Timestamp)]
-> Mod OptionFields (IntervalEnd Timestamp)
forall a. Monoid a => [a] -> a
mconcat
      ( [ Char -> Mod OptionFields (IntervalEnd Timestamp)
forall (f :: * -> *) a. HasName f => Char -> Mod f a
Opt.short Char
't',
          String -> Mod OptionFields (IntervalEnd Timestamp)
forall (f :: * -> *) a. HasName f => String -> Mod f a
Opt.long String
"time-to",
          String -> Mod OptionFields (IntervalEnd Timestamp)
forall (f :: * -> *) a. String -> Mod f a
Opt.help ( String
"Upper bound of query timestamp. "
                     String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"Local findings with timestamp older than this value are used to create the snapshot graph. "
                     String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"See --time-from for format of timestamps. "
                     String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"Special value `x+inf` indicates there is no upper bound. "
                     String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"Default: x+inf"
                   ),
          String -> Mod OptionFields (IntervalEnd Timestamp)
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
Opt.metavar String
"TIMESTAMP"
        ]
      )
    pDuration :: Parser (Maybe Int64)
pDuration = Parser Int64 -> Parser (Maybe Int64)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Parser Int64 -> Parser (Maybe Int64))
-> Parser Int64 -> Parser (Maybe Int64)
forall a b. (a -> b) -> a -> b
$ ReadM Int64 -> Mod OptionFields Int64 -> Parser Int64
forall a. ReadM a -> Mod OptionFields a -> Parser a
Opt.option ReadM Int64
forall a. Read a => ReadM a
Opt.auto (Mod OptionFields Int64 -> Parser Int64)
-> Mod OptionFields Int64 -> Parser Int64
forall a b. (a -> b) -> a -> b
$ [Mod OptionFields Int64] -> Mod OptionFields Int64
forall a. Monoid a => [a] -> a
mconcat
                [ Char -> Mod OptionFields Int64
forall (f :: * -> *) a. HasName f => Char -> Mod f a
Opt.short Char
'd',
                  String -> Mod OptionFields Int64
forall (f :: * -> *) a. HasName f => String -> Mod f a
Opt.long String
"duration",
                  String -> Mod OptionFields Int64
forall (f :: * -> *) a. String -> Mod f a
Opt.help ( String
"Duration of the query time interval in seconds. "
                             String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" Use with either --time-to or --time-from option."
                           ),
                  String -> Mod OptionFields Int64
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
Opt.metavar String
"SECONDS"
                ]