-- | This Module exports the main datatype of this library: Task.
-- It is provided with FromJSON and ToJSON instances.
--
module Taskwarrior.Task
  ( Task(..)
  , Tag
  , makeTask
  -- | == Adherence to specification
  -- This library uses the [taskwarrior specification for the JSON serialisation format](https://taskwarrior.org/docs/design/task.html).
  -- But it deviates in a small number of ways to be more pragmatic.
  --
  -- * 'Task' has the fields 'id' and 'urgency' although they are technically UDAs.
  -- * There are two invalid states which are not prevented via the Haskell type system by the chosen modeling:
  --
  --   1. A 'Task' with a 'Just' value for 'recurringChild' should not have the 'Status' 'Taskwarrior.Status.Recurring'.
  --   2. The 'due' field needs to be a 'Just' value on a 'Task' with 'Status' 'Taskwarrior.Status.Recurring'.
  )
where

import           Prelude                 hiding ( id )

import qualified Data.Text                     as Text
import           Data.Text                      ( Text )
import           Data.Time                      ( UTCTime )
import qualified Data.UUID                     as UUID
import           Data.UUID                      ( UUID )
import qualified Data.Aeson                    as Aeson
import qualified Data.Aeson.Types              as Aeson.Types
import           Data.Aeson                     ( withObject
                                                , withText
                                                , FromJSON
                                                , ToJSON
                                                , parseJSON
                                                , (.:)
                                                , (.=)
                                                , (.:?)
                                                , Value
                                                )
import qualified Data.Semigroup                as Semigroup
import           Data.Maybe                     ( fromMaybe )
import qualified Data.Maybe                    as Maybe
import           Control.Monad                  ( join )
import qualified Data.Foldable                 as Foldable
import           Taskwarrior.Status             ( Status )
import qualified Taskwarrior.Status            as Status
import           Taskwarrior.RecurringChild     ( RecurringChild )
import qualified Taskwarrior.RecurringChild    as RecurringChild
import           Taskwarrior.Priority           ( Priority )
import qualified Taskwarrior.Priority          as Priority
import           Taskwarrior.UDA                ( UDA )
import           Taskwarrior.Annotation         ( Annotation )
import qualified Taskwarrior.Time              as Time
import qualified Data.HashMap.Strict           as HashMap
import           Data.Set                       ( Set )
import qualified Data.Set                      as Set
import           Foreign.Marshal.Utils          ( fromBool )

-- | A 'Task' represents a task from taskwarrior.
-- The specification demands, that the existence of some fields is dependent on the status of the task.
-- Those fields are therefore bundled in 'Status' as a sum-type.
--
-- All fields in an imported task which are not part of the specification will be put in the 'UDA' (user defined attributes) 'Data.HashMap.Strict.HashMap'.
--
-- Since the json can have multiple semantically equivalent representations of a task first serializing and then deserializing is not identity.
-- But deserializing and then serializing should be. (Thus making serializing and deserializing idempotent.)
data Task = Task {
        Task -> Status
status         :: Status,
        Task -> Maybe RecurringChild
recurringChild :: Maybe RecurringChild,
        Task -> UUID
uuid           :: UUID,
        Task -> Maybe Integer
id             :: Maybe Integer,
        Task -> UTCTime
entry          :: UTCTime,
        Task -> Text
description    :: Text,
        Task -> Maybe UTCTime
start          :: Maybe UTCTime,
        Task -> Maybe UTCTime
modified       :: Maybe UTCTime,
        Task -> Maybe UTCTime
due            :: Maybe UTCTime,
        Task -> Maybe UTCTime
until          :: Maybe UTCTime,
        Task -> Set Annotation
annotations    :: Set Annotation,
        Task -> Maybe UTCTime
scheduled      :: Maybe UTCTime,
        Task -> Maybe Text
project        :: Maybe Text,
        Task -> Maybe Priority
priority       :: Maybe Priority,
        Task -> Set UUID
depends        :: Set UUID,
        Task -> Set Text
tags           :: Set Tag,
        Task -> Double
urgency        :: Double,
        Task -> UDA
uda            :: UDA
} deriving (Task -> Task -> Bool
(Task -> Task -> Bool) -> (Task -> Task -> Bool) -> Eq Task
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Task -> Task -> Bool
$c/= :: Task -> Task -> Bool
== :: Task -> Task -> Bool
$c== :: Task -> Task -> Bool
Eq, Int -> Task -> ShowS
[Task] -> ShowS
Task -> String
(Int -> Task -> ShowS)
-> (Task -> String) -> ([Task] -> ShowS) -> Show Task
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Task] -> ShowS
$cshowList :: [Task] -> ShowS
show :: Task -> String
$cshow :: Task -> String
showsPrec :: Int -> Task -> ShowS
$cshowsPrec :: Int -> Task -> ShowS
Show, ReadPrec [Task]
ReadPrec Task
Int -> ReadS Task
ReadS [Task]
(Int -> ReadS Task)
-> ReadS [Task] -> ReadPrec Task -> ReadPrec [Task] -> Read Task
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Task]
$creadListPrec :: ReadPrec [Task]
readPrec :: ReadPrec Task
$creadPrec :: ReadPrec Task
readList :: ReadS [Task]
$creadList :: ReadS [Task]
readsPrec :: Int -> ReadS Task
$creadsPrec :: Int -> ReadS Task
Read)

-- | A Tag can be basically any string. But beware: Special symbols work but might clash with @task@ cli syntax. As an example you can use a space in a @'Tag'@. But then you cannot use @task +my tag@ on the command line.
type Tag = Text


reservedKeys :: [Text]
reservedKeys :: [Text]
reservedKeys =
  [ Text
"status"
  , Text
"uuid"
  , Text
"id"
  , Text
"description"
  , Text
"entry"
  , Text
"modified"
  , Text
"due"
  , Text
"until"
  , Text
"scheduled"
  , Text
"annotations"
  , Text
"start"
  , Text
"project"
  , Text
"priority"
  , Text
"depends"
  , Text
"tags"
  , Text
"wait"
  , Text
"end"
  , Text
"mask"
  , Text
"imask"
  , Text
"parent"
  , Text
"recur"
  , Text
"urgency"
  ]

instance FromJSON Task where
  parseJSON :: Value -> Parser Task
parseJSON = String -> (UDA -> Parser Task) -> Value -> Parser Task
forall a. String -> (UDA -> Parser a) -> Value -> Parser a
withObject String
"Task" ((UDA -> Parser Task) -> Value -> Parser Task)
-> (UDA -> Parser Task) -> Value -> Parser Task
forall a b. (a -> b) -> a -> b
$ \UDA
object -> do
    let parseTimeFromFieldMay :: Text -> Parser (Maybe UTCTime)
parseTimeFromFieldMay = (Value -> Parser UTCTime) -> UDA -> Text -> Parser (Maybe UTCTime)
forall a. (Value -> Parser a) -> UDA -> Text -> Parser (Maybe a)
parseFromFieldWithMay Value -> Parser UTCTime
Time.parse UDA
object
        uda :: UDA
uda = (Text -> Value -> Bool) -> UDA -> UDA
forall k v. (k -> v -> Bool) -> HashMap k v -> HashMap k v
HashMap.filterWithKey (\Text
k Value
_ -> Text
k Text -> [Text] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [Text]
reservedKeys) UDA
object
    Status
status         <- UDA -> Parser Status
Status.parseFromObject UDA
object
    Maybe RecurringChild
recurringChild <- UDA -> Parser (Maybe RecurringChild)
RecurringChild.parseFromObjectMay UDA
object
    UUID
uuid           <- UDA
object UDA -> Text -> Parser UUID
forall a. FromJSON a => UDA -> Text -> Parser a
.: Text
"uuid"
    Maybe Integer
idRaw          <- UDA
object UDA -> Text -> Parser (Maybe Integer)
forall a. FromJSON a => UDA -> Text -> Parser (Maybe a)
.:? Text
"id"
    let id :: Maybe Integer
id = if Maybe Integer
idRaw Maybe Integer -> Maybe Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer -> Maybe Integer
forall a. a -> Maybe a
Just Integer
0 then Maybe Integer
forall a. Maybe a
Nothing else Maybe Integer
idRaw
    UTCTime
entry       <- UDA
object UDA -> Text -> Parser Value
forall a. FromJSON a => UDA -> Text -> Parser a
.: Text
"entry" Parser Value -> (Value -> Parser UTCTime) -> Parser UTCTime
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Value -> Parser UTCTime
Time.parse
    Text
description <- UDA
object UDA -> Text -> Parser Text
forall a. FromJSON a => UDA -> Text -> Parser a
.: Text
"description"
    Maybe UTCTime
start       <- Text -> Parser (Maybe UTCTime)
parseTimeFromFieldMay Text
"start"
    Maybe UTCTime
modified    <- Text -> Parser (Maybe UTCTime)
parseTimeFromFieldMay Text
"modified"
    Maybe UTCTime
due         <- Text -> Parser (Maybe UTCTime)
parseTimeFromFieldMay Text
"due"
    Maybe UTCTime
until_      <- Text -> Parser (Maybe UTCTime)
parseTimeFromFieldMay Text
"until"
    Maybe UTCTime
scheduled   <- Text -> Parser (Maybe UTCTime)
parseTimeFromFieldMay Text
"scheduled"
    Set Annotation
annotations <- Maybe (Set Annotation) -> Set Annotation
forall (t :: * -> *) m. (Foldable t, Monoid m) => t m -> m
Foldable.fold (Maybe (Set Annotation) -> Set Annotation)
-> Parser (Maybe (Set Annotation)) -> Parser (Set Annotation)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> UDA
object UDA -> Text -> Parser (Maybe (Set Annotation))
forall a. FromJSON a => UDA -> Text -> Parser (Maybe a)
.:? Text
"annotations"
    Maybe Text
project     <- UDA
object UDA -> Text -> Parser (Maybe Text)
forall a. FromJSON a => UDA -> Text -> Parser (Maybe a)
.:? Text
"project"
    Maybe Priority
priority    <- Maybe (Maybe Priority) -> Maybe Priority
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join
      (Maybe (Maybe Priority) -> Maybe Priority)
-> Parser (Maybe (Maybe Priority)) -> Parser (Maybe Priority)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Value -> Parser (Maybe Priority))
-> UDA -> Text -> Parser (Maybe (Maybe Priority))
forall a. (Value -> Parser a) -> UDA -> Text -> Parser (Maybe a)
parseFromFieldWithMay Value -> Parser (Maybe Priority)
Priority.parseMay UDA
object Text
"priority"
    Set UUID
depends <- Parser (Set UUID)
-> (Value -> Parser (Set UUID)) -> Maybe Value -> Parser (Set UUID)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Set UUID -> Parser (Set UUID)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Set UUID
forall a. Monoid a => a
mempty)
                     Value -> Parser (Set UUID)
parseUuidList
                     (Text -> UDA -> Maybe Value
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HashMap.lookup Text
"depends" UDA
object)
    Set Text
tags    <- Maybe (Set Text) -> Set Text
forall (t :: * -> *) m. (Foldable t, Monoid m) => t m -> m
Foldable.fold (Maybe (Set Text) -> Set Text)
-> Parser (Maybe (Set Text)) -> Parser (Set Text)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> UDA
object UDA -> Text -> Parser (Maybe (Set Text))
forall a. FromJSON a => UDA -> Text -> Parser (Maybe a)
.:? Text
"tags"
    Double
urgency <- Double -> Maybe Double -> Double
forall a. a -> Maybe a -> a
fromMaybe Double
0 (Maybe Double -> Double) -> Parser (Maybe Double) -> Parser Double
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> UDA
object UDA -> Text -> Parser (Maybe Double)
forall a. FromJSON a => UDA -> Text -> Parser (Maybe a)
.:? Text
"urgency"
    Task -> Parser Task
forall (f :: * -> *) a. Applicative f => a -> f a
pure Task :: Status
-> Maybe RecurringChild
-> UUID
-> Maybe Integer
-> UTCTime
-> Text
-> Maybe UTCTime
-> Maybe UTCTime
-> Maybe UTCTime
-> Maybe UTCTime
-> Set Annotation
-> Maybe UTCTime
-> Maybe Text
-> Maybe Priority
-> Set UUID
-> Set Text
-> Double
-> UDA
-> Task
Task { until :: Maybe UTCTime
until = Maybe UTCTime
until_, Double
Maybe Integer
Maybe Text
Maybe UTCTime
Maybe Priority
Maybe RecurringChild
Text
UTCTime
UDA
Set Text
Set UUID
Set Annotation
UUID
Status
urgency :: Double
tags :: Set Text
depends :: Set UUID
priority :: Maybe Priority
project :: Maybe Text
annotations :: Set Annotation
scheduled :: Maybe UTCTime
due :: Maybe UTCTime
modified :: Maybe UTCTime
start :: Maybe UTCTime
description :: Text
entry :: UTCTime
id :: Maybe Integer
uuid :: UUID
recurringChild :: Maybe RecurringChild
status :: Status
uda :: UDA
uda :: UDA
urgency :: Double
tags :: Set Text
depends :: Set UUID
priority :: Maybe Priority
project :: Maybe Text
scheduled :: Maybe UTCTime
annotations :: Set Annotation
due :: Maybe UTCTime
modified :: Maybe UTCTime
start :: Maybe UTCTime
description :: Text
entry :: UTCTime
id :: Maybe Integer
uuid :: UUID
recurringChild :: Maybe RecurringChild
status :: Status
.. }

parseFromFieldWithMay
  :: (Value -> Aeson.Types.Parser a)
  -> Aeson.Object
  -> Text
  -> Aeson.Types.Parser (Maybe a)
parseFromFieldWithMay :: (Value -> Parser a) -> UDA -> Text -> Parser (Maybe a)
parseFromFieldWithMay Value -> Parser a
parser UDA
object Text
name =
  (Value -> Parser a) -> Maybe Value -> Parser (Maybe a)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse Value -> Parser a
parser (Text -> UDA -> Maybe Value
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HashMap.lookup Text
name UDA
object)

parseUuidList :: Aeson.Value -> Aeson.Types.Parser (Set UUID)
parseUuidList :: Value -> Parser (Set UUID)
parseUuidList =
  String -> (Text -> Parser (Set UUID)) -> Value -> Parser (Set UUID)
forall a. String -> (Text -> Parser a) -> Value -> Parser a
withText String
"Text"
    ((Text -> Parser (Set UUID)) -> Value -> Parser (Set UUID))
-> (Text -> Parser (Set UUID)) -> Value -> Parser (Set UUID)
forall a b. (a -> b) -> a -> b
$ ([UUID] -> Set UUID) -> Parser [UUID] -> Parser (Set UUID)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [UUID] -> Set UUID
forall a. Ord a => [a] -> Set a
Set.fromList
    (Parser [UUID] -> Parser (Set UUID))
-> (Text -> Parser [UUID]) -> Text -> Parser (Set UUID)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Parser UUID) -> [Text] -> Parser [UUID]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (Value -> Parser UUID
forall a. FromJSON a => Value -> Parser a
parseJSON (Value -> Parser UUID) -> (Text -> Value) -> Text -> Parser UUID
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Value
Aeson.String)
    ([Text] -> Parser [UUID])
-> (Text -> [Text]) -> Text -> Parser [UUID]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text -> [Text]
Text.splitOn Text
","

instance ToJSON Task where
  toJSON :: Task -> Value
toJSON Task { until :: Task -> Maybe UTCTime
until = Maybe UTCTime
until_, Double
Maybe Integer
Maybe Text
Maybe UTCTime
Maybe Priority
Maybe RecurringChild
Text
UTCTime
UDA
Set Text
Set UUID
Set Annotation
UUID
Status
uda :: UDA
urgency :: Double
tags :: Set Text
depends :: Set UUID
priority :: Maybe Priority
project :: Maybe Text
scheduled :: Maybe UTCTime
annotations :: Set Annotation
due :: Maybe UTCTime
modified :: Maybe UTCTime
start :: Maybe UTCTime
description :: Text
entry :: UTCTime
id :: Maybe Integer
uuid :: UUID
recurringChild :: Maybe RecurringChild
status :: Status
uda :: Task -> UDA
urgency :: Task -> Double
tags :: Task -> Set Text
depends :: Task -> Set UUID
priority :: Task -> Maybe Priority
project :: Task -> Maybe Text
scheduled :: Task -> Maybe UTCTime
annotations :: Task -> Set Annotation
due :: Task -> Maybe UTCTime
modified :: Task -> Maybe UTCTime
start :: Task -> Maybe UTCTime
description :: Task -> Text
entry :: Task -> UTCTime
id :: Task -> Maybe Integer
uuid :: Task -> UUID
recurringChild :: Task -> Maybe RecurringChild
status :: Task -> Status
..} =
    [Pair] -> Value
Aeson.object
      ([Pair] -> Value) -> [Pair] -> Value
forall a b. (a -> b) -> a -> b
$  Status -> [Pair]
Status.toPairs Status
status
      [Pair] -> [Pair] -> [Pair]
forall a. Semigroup a => a -> a -> a
<> [ Text
"uuid" Text -> UUID -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= UUID
uuid
         , Text
"entry" Text -> Value -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= UTCTime -> Value
Time.toValue UTCTime
entry
         , Text
"description" Text -> Text -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
description
         ]
      [Pair] -> [Pair] -> [Pair]
forall a. Semigroup a => a -> a -> a
<> [ Text
"urgency" Text -> Double -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
urgency | Double
urgency Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
/= Double
0 ]
      [Pair] -> [Pair] -> [Pair]
forall a. Semigroup a => a -> a -> a
<> [Pair]
-> (RecurringChild -> [Pair]) -> Maybe RecurringChild -> [Pair]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] RecurringChild -> [Pair]
RecurringChild.toPairs Maybe RecurringChild
recurringChild
      [Pair] -> [Pair] -> [Pair]
forall a. Semigroup a => a -> a -> a
<> Set Annotation -> (Set Annotation -> Pair) -> [Pair]
forall b a. Ord b => Set b -> (Set b -> a) -> [a]
ifNotNullSet Set Annotation
annotations (Text
"annotations" Text -> Set Annotation -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.=)
      [Pair] -> [Pair] -> [Pair]
forall a. Semigroup a => a -> a -> a
<> ((Text, Maybe UTCTime) -> Maybe Pair)
-> [(Text, Maybe UTCTime)] -> [Pair]
forall a b. (a -> Maybe b) -> [a] -> [b]
Maybe.mapMaybe
           (\(Text
name, Maybe UTCTime
value) -> (Text
name Text -> Value -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.=) (Value -> Pair) -> (UTCTime -> Value) -> UTCTime -> Pair
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UTCTime -> Value
Time.toValue (UTCTime -> Pair) -> Maybe UTCTime -> Maybe Pair
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe UTCTime
value)
           [ (Text
"start"    , Maybe UTCTime
start)
           , (Text
"modified" , Maybe UTCTime
modified)
           , (Text
"due"      , Maybe UTCTime
due)
           , (Text
"scheduled", Maybe UTCTime
scheduled)
           , (Text
"until"    , Maybe UTCTime
until_)
           ]
      [Pair] -> [Pair] -> [Pair]
forall a. Semigroup a => a -> a -> a
<> [Maybe Pair] -> [Pair]
forall a. [Maybe a] -> [a]
Maybe.catMaybes
           [ (Text
"id" Text -> Integer -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.=) (Integer -> Pair) -> Maybe Integer -> Maybe Pair
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Integer
id
           , (Text
"project" Text -> Text -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.=) (Text -> Pair) -> Maybe Text -> Maybe Pair
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Text
project
           , (Text
"priority" Text -> Priority -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.=) (Priority -> Pair) -> Maybe Priority -> Maybe Pair
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Priority
priority
           ]
      [Pair] -> [Pair] -> [Pair]
forall a. Semigroup a => a -> a -> a
<> Set UUID -> (Set UUID -> Pair) -> [Pair]
forall b a. Ord b => Set b -> (Set b -> a) -> [a]
ifNotNullSet
           Set UUID
depends
           ( (Text
"depends" Text -> Text -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.=)
           (Text -> Pair) -> (Set UUID -> Text) -> Set UUID -> Pair
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Text] -> Text
Text.intercalate Text
","
           ([Text] -> Text) -> (Set UUID -> [Text]) -> Set UUID -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UUID -> Text) -> [UUID] -> [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap UUID -> Text
UUID.toText
           ([UUID] -> [Text]) -> (Set UUID -> [UUID]) -> Set UUID -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Set UUID -> [UUID]
forall a. Set a -> [a]
Set.toList
           )
      [Pair] -> [Pair] -> [Pair]
forall a. Semigroup a => a -> a -> a
<> Set Text -> (Set Text -> Pair) -> [Pair]
forall b a. Ord b => Set b -> (Set b -> a) -> [a]
ifNotNullSet Set Text
tags (Text
"tags" Text -> Set Text -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.=)
      [Pair] -> [Pair] -> [Pair]
forall a. Semigroup a => a -> a -> a
<> UDA -> [Pair]
forall k v. HashMap k v -> [(k, v)]
HashMap.toList UDA
uda

ifNotNullSet :: (Ord b) => Set b -> (Set b -> a) -> [a]
ifNotNullSet :: Set b -> (Set b -> a) -> [a]
ifNotNullSet Set b
set Set b -> a
f =
  (Integer -> [a] -> [a]
forall b a. (Integral b, Monoid a) => b -> a -> a
Semigroup.stimesMonoid (Integer -> [a] -> [a])
-> (Set b -> Integer) -> Set b -> [a] -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool -> Integer
forall a. Num a => Bool -> a
fromBool :: Bool -> Integer) (Bool -> Integer) -> (Set b -> Bool) -> Set b -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Bool
not (Bool -> Bool) -> (Set b -> Bool) -> Set b -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Set b -> Bool
forall a. Set a -> Bool
Set.null (Set b -> [a] -> [a]) -> Set b -> [a] -> [a]
forall a b. (a -> b) -> a -> b
$ Set b
set
    )
    [Set b -> a
f Set b
set]

-- | Makes a Task with the given mandatory fields uuid, entry time and description. See createTask for a non-pure version which needs less parameters.
makeTask :: UUID -> UTCTime -> Text -> Task
makeTask :: UUID -> UTCTime -> Text -> Task
makeTask UUID
uuid UTCTime
entry Text
description = Task :: Status
-> Maybe RecurringChild
-> UUID
-> Maybe Integer
-> UTCTime
-> Text
-> Maybe UTCTime
-> Maybe UTCTime
-> Maybe UTCTime
-> Maybe UTCTime
-> Set Annotation
-> Maybe UTCTime
-> Maybe Text
-> Maybe Priority
-> Set UUID
-> Set Text
-> Double
-> UDA
-> Task
Task { UUID
uuid :: UUID
uuid :: UUID
uuid
                                       , Text
description :: Text
description :: Text
description
                                       , UTCTime
entry :: UTCTime
entry :: UTCTime
entry
                                       , id :: Maybe Integer
id             = Maybe Integer
forall a. Maybe a
Nothing
                                       , modified :: Maybe UTCTime
modified       = UTCTime -> Maybe UTCTime
forall a. a -> Maybe a
Just UTCTime
entry
                                       , status :: Status
status         = Status
Status.Pending
                                       , recurringChild :: Maybe RecurringChild
recurringChild = Maybe RecurringChild
forall a. Maybe a
Nothing
                                       , due :: Maybe UTCTime
due            = Maybe UTCTime
forall a. Maybe a
Nothing
                                       , priority :: Maybe Priority
priority       = Maybe Priority
forall a. Maybe a
Nothing
                                       , project :: Maybe Text
project        = Maybe Text
forall a. Maybe a
Nothing
                                       , start :: Maybe UTCTime
start          = Maybe UTCTime
forall a. Maybe a
Nothing
                                       , scheduled :: Maybe UTCTime
scheduled      = Maybe UTCTime
forall a. Maybe a
Nothing
                                       , until :: Maybe UTCTime
until          = Maybe UTCTime
forall a. Maybe a
Nothing
                                       , annotations :: Set Annotation
annotations    = Set Annotation
forall a. Monoid a => a
mempty
                                       , depends :: Set UUID
depends        = Set UUID
forall a. Monoid a => a
mempty
                                       , tags :: Set Text
tags           = Set Text
forall a. Monoid a => a
mempty
                                       , urgency :: Double
urgency        = Double
0
                                       , uda :: UDA
uda            = UDA
forall k v. HashMap k v
HashMap.empty
                                       }