markup header point = do
    markedPoints <- mapM (transMapList (listOfPoint point)) ["CR", "MA", "SL", "SQ", "TR"]
    marks        <- foldM addMarks Map.empty . zip [Circle ..] $ markedPoints
    labels       <- transMapList (listOf (compose point (simple header))) "LB"
    arrows       <- consumePointPairs "AR"
    lines        <- consumePointPairs "LN"
    dim          <- transMapMulti ( listOfPoint point) "DD"
    visible      <- transMapMulti (elistOfPoint point) "VW"
    numbering    <- transMap number "PM"
    figure       <- transMap (figurePTranslator header) "FG"

    tell . map DuplicateLabelOmitted $ labels \\ nubBy (on (==) fst) labels
    tell [UnknownNumberingIgnored n | Just n <- [numbering], n < 0 || n > 2]
    -- TODO: some kind of warning when omitting arrows and lines

    return Markup {
        T.marks     = marks,
        T.labels    = Map.fromList labels,
        T.arrows    = prune arrows,
        T.lines     = prune . map canonicalize $ lines,
        T.dim       = fmap Set.fromList dim,
        T.visible   = fmap Set.fromList visible,
        T.numbering = numbering >>= flip lookup (zip [0..] [Unnumbered ..]),
        T.figure    = figure
    }
    where
    consumePointPairs = transMapList (listOf (join compose point))
    prune = Set.fromList . filter (uncurry (/=))
    canonicalize (x, y) = (min x y, max x y)
markup header point = do
    markedPoints <- mapM (transMapList (listOfPoint point)) ["CR", "MA", "SL", "SQ", "TR"]
    marks        <- foldM addMarks Map.empty . zip [Circle ..] $ markedPoints
    labels       <- transMapList (listOf (compose point (simple header))) "LB"
    arrows       <- consumePointPairs "AR"
    lines        <- consumePointPairs "LN"
    dim          <- transMapMulti ( listOfPoint point) "DD"
    visible      <- transMapMulti (elistOfPoint point) "VW"
    numbering    <- transMap number "PM"
    figure       <- transMap (figurePTranslator header) "FG"

    tell . map DuplicateLabelOmitted $ labels \\ nubBy (on (==) fst) labels
    tell [UnknownNumberingIgnored n | Just n <- [numbering], n < 0 || n > 2]
    -- TODO: some kind of warning when omitting arrows and lines

    return Markup {
        T.marks     = marks,
        T.labels    = Map.fromList labels,
        T.arrows    = prune arrows,
        T.lines     = prune . map canonicalize $ lines,
        T.dim       = fmap Set.fromList dim,
        T.visible   = fmap Set.fromList visible,
        T.numbering = numbering >>= flip lookup (zip [0..] [Unnumbered ..]),
        T.figure    = figure
    }
    where
    consumePointPairs = transMapList (listOf (join compose point))
    prune = Set.fromList . filter (uncurry (/=))
    canonicalize (x, y) = (min x y, max x y)
markup header point = do
    markedPoints <- mapM (transMapList (listOfPoint point)) ["CR", "MA", "SL", "SQ", "TR"]
    marks        <- foldM addMarks Map.empty . zip [Circle ..] $ markedPoints
    labels       <- transMapList (listOf (compose point (simple header))) "LB"
    arrows       <- consumePointPairs "AR"
    lines        <- consumePointPairs "LN"
    dim          <- transMapMulti ( listOfPoint point) "DD"
    visible      <- transMapMulti (elistOfPoint point) "VW"
    numbering    <- transMap number "PM"
    figure       <- transMap (figurePTranslator header) "FG"

    tell . map DuplicateLabelOmitted $ labels \\ nubBy (on (==) fst) labels
    tell [UnknownNumberingIgnored n | Just n <- [numbering], n < 0 || n > 2]
    -- TODO: some kind of warning when omitting arrows and lines

    return Markup {
        T.marks     = marks,
        T.labels    = Map.fromList labels,
        T.arrows    = prune arrows,
        T.lines     = prune . map canonicalize $ lines,
        T.dim       = fmap Set.fromList dim,
        T.visible   = fmap Set.fromList visible,
        T.numbering = numbering >>= flip lookup (zip [0..] [Unnumbered ..]),
        T.figure    = figure
    }
    where
    consumePointPairs = transMapList (listOf (join compose point))
    prune = Set.fromList . filter (uncurry (/=))
    canonicalize (x, y) = (min x y, max x y)