{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE UndecidableInstances #-}
module IntervalAlgebra.IntervalDiagram
(
parseIntervalDiagram
, simpleIntervalDiagram
, standardExampleDiagram
, IntervalDiagramOptions(..)
, defaultIntervalDiagramOptions
, AxisPlacement(..)
, IntervalText
, IntervalDiagram
, IntervalTextLineParseError(..)
, AxisParseError(..)
, IntervalDiagramOptionsError(..)
, IntervalDiagramParseError(..)
, Prettyprinter.Pretty(..)
) where
import Data.Foldable (Foldable (toList))
import qualified Data.List.NonEmpty as NE hiding (toList)
import Data.Maybe (fromMaybe, isNothing)
import Data.Text (Text, pack)
import IntervalAlgebra.Core
import IntervalAlgebra.IntervalUtilities (rangeInterval)
import IntervalAlgebra.PairedInterval (PairedInterval, getPairData,
makePairedInterval)
import Prettyprinter
newtype IntervalText a = MkIntervalText (PairedInterval Char a) deriving (IntervalText a -> IntervalText a -> Bool
forall a. Eq a => IntervalText a -> IntervalText a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: IntervalText a -> IntervalText a -> Bool
$c/= :: forall a. Eq a => IntervalText a -> IntervalText a -> Bool
== :: IntervalText a -> IntervalText a -> Bool
$c== :: forall a. Eq a => IntervalText a -> IntervalText a -> Bool
Eq, Int -> IntervalText a -> ShowS
forall a. (Show a, Ord a) => Int -> IntervalText a -> ShowS
forall a. (Show a, Ord a) => [IntervalText a] -> ShowS
forall a. (Show a, Ord a) => IntervalText a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [IntervalText a] -> ShowS
$cshowList :: forall a. (Show a, Ord a) => [IntervalText a] -> ShowS
show :: IntervalText a -> String
$cshow :: forall a. (Show a, Ord a) => IntervalText a -> String
showsPrec :: Int -> IntervalText a -> ShowS
$cshowsPrec :: forall a. (Show a, Ord a) => Int -> IntervalText a -> ShowS
Show)
makeIntervalText :: Char -> Interval a -> IntervalText a
makeIntervalText :: forall a. Char -> Interval a -> IntervalText a
makeIntervalText Char
c = forall a. PairedInterval Char a -> IntervalText a
MkIntervalText forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall b a. b -> Interval a -> PairedInterval b a
makePairedInterval Char
c
instance Intervallic IntervalText where
getInterval :: forall a. IntervalText a -> Interval a
getInterval (MkIntervalText PairedInterval Char a
x) = forall (i :: * -> *) a. Intervallic i => i a -> Interval a
getInterval PairedInterval Char a
x
setInterval :: forall a b. IntervalText a -> Interval b -> IntervalText b
setInterval (MkIntervalText PairedInterval Char a
x) Interval b
i = forall a. PairedInterval Char a -> IntervalText a
MkIntervalText forall a b. (a -> b) -> a -> b
$ forall (i :: * -> *) a b. Intervallic i => i a -> Interval b -> i b
setInterval PairedInterval Char a
x Interval b
i
instance (Enum b, IntervalSizeable a b) => Pretty (IntervalText a) where
pretty :: forall ann. IntervalText a -> Doc ann
pretty (MkIntervalText PairedInterval Char a
x) = forall a ann. Pretty a => a -> Doc ann
pretty forall a b. (a -> b) -> a -> b
$ forall a. Int -> a -> [a]
replicate (forall a. Enum a => a -> Int
fromEnum (forall a b (i :: * -> *).
(IntervalSizeable a b, Intervallic i) =>
i a -> b
duration Interval a
i)) Char
c
where
c :: Char
c = forall b a. PairedInterval b a -> b
getPairData PairedInterval Char a
x
i :: Interval a
i = forall (i :: * -> *) a. Intervallic i => i a -> Interval a
getInterval PairedInterval Char a
x
data IntervalTextLine a = MkIntervalTextLine [IntervalText a] [Text]
deriving Int -> IntervalTextLine a -> ShowS
forall a. (Show a, Ord a) => Int -> IntervalTextLine a -> ShowS
forall a. (Show a, Ord a) => [IntervalTextLine a] -> ShowS
forall a. (Show a, Ord a) => IntervalTextLine a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [IntervalTextLine a] -> ShowS
$cshowList :: forall a. (Show a, Ord a) => [IntervalTextLine a] -> ShowS
show :: IntervalTextLine a -> String
$cshow :: forall a. (Show a, Ord a) => IntervalTextLine a -> String
showsPrec :: Int -> IntervalTextLine a -> ShowS
$cshowsPrec :: forall a. (Show a, Ord a) => Int -> IntervalTextLine a -> ShowS
Show
instance Pretty (IntervalTextLine Int) where
pretty :: forall ann. IntervalTextLine Int -> Doc ann
pretty (MkIntervalTextLine [IntervalText Int]
ivs [Text]
_) =
forall (t :: * -> *) ann.
Foldable t =>
(Doc ann -> Doc ann -> Doc ann) -> t (Doc ann) -> Doc ann
concatWith forall a. Semigroup a => a -> a -> a
(<>) (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\IntervalText Int
x -> forall ann. Int -> Doc ann -> Doc ann
indent (forall (i :: * -> *) a. Intervallic i => i a -> a
begin IntervalText Int
x) (forall a ann. Pretty a => a -> Doc ann
pretty IntervalText Int
x)) [IntervalText Int]
ivs)
instance Pretty (Either IntervalTextLineParseError (IntervalTextLine Int)) where
pretty :: forall ann.
Either IntervalTextLineParseError (IntervalTextLine Int) -> Doc ann
pretty (Left IntervalTextLineParseError
e) = forall a ann. Pretty a => a -> Doc ann
pretty forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> String
show IntervalTextLineParseError
e
pretty (Right IntervalTextLine Int
l) = forall a ann. Pretty a => a -> Doc ann
pretty IntervalTextLine Int
l
data IntervalTextLineParseError =
ConcurringIntervals
| UnsortedIntervals
| BeginsLessThanZero
deriving (IntervalTextLineParseError -> IntervalTextLineParseError -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: IntervalTextLineParseError -> IntervalTextLineParseError -> Bool
$c/= :: IntervalTextLineParseError -> IntervalTextLineParseError -> Bool
== :: IntervalTextLineParseError -> IntervalTextLineParseError -> Bool
$c== :: IntervalTextLineParseError -> IntervalTextLineParseError -> Bool
Eq, Int -> IntervalTextLineParseError -> ShowS
[IntervalTextLineParseError] -> ShowS
IntervalTextLineParseError -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [IntervalTextLineParseError] -> ShowS
$cshowList :: [IntervalTextLineParseError] -> ShowS
show :: IntervalTextLineParseError -> String
$cshow :: IntervalTextLineParseError -> String
showsPrec :: Int -> IntervalTextLineParseError -> ShowS
$cshowsPrec :: Int -> IntervalTextLineParseError -> ShowS
Show, Eq IntervalTextLineParseError
IntervalTextLineParseError -> IntervalTextLineParseError -> Bool
IntervalTextLineParseError
-> IntervalTextLineParseError -> Ordering
IntervalTextLineParseError
-> IntervalTextLineParseError -> IntervalTextLineParseError
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
min :: IntervalTextLineParseError
-> IntervalTextLineParseError -> IntervalTextLineParseError
$cmin :: IntervalTextLineParseError
-> IntervalTextLineParseError -> IntervalTextLineParseError
max :: IntervalTextLineParseError
-> IntervalTextLineParseError -> IntervalTextLineParseError
$cmax :: IntervalTextLineParseError
-> IntervalTextLineParseError -> IntervalTextLineParseError
>= :: IntervalTextLineParseError -> IntervalTextLineParseError -> Bool
$c>= :: IntervalTextLineParseError -> IntervalTextLineParseError -> Bool
> :: IntervalTextLineParseError -> IntervalTextLineParseError -> Bool
$c> :: IntervalTextLineParseError -> IntervalTextLineParseError -> Bool
<= :: IntervalTextLineParseError -> IntervalTextLineParseError -> Bool
$c<= :: IntervalTextLineParseError -> IntervalTextLineParseError -> Bool
< :: IntervalTextLineParseError -> IntervalTextLineParseError -> Bool
$c< :: IntervalTextLineParseError -> IntervalTextLineParseError -> Bool
compare :: IntervalTextLineParseError
-> IntervalTextLineParseError -> Ordering
$ccompare :: IntervalTextLineParseError
-> IntervalTextLineParseError -> Ordering
Ord)
parseIntervalTextLine
:: [Text]
-> [IntervalText Int]
-> Either IntervalTextLineParseError (IntervalTextLine Int)
parseIntervalTextLine :: [Text]
-> [IntervalText Int]
-> Either IntervalTextLineParseError (IntervalTextLine Int)
parseIntervalTextLine [Text]
labs [IntervalText Int]
l =
let vals :: Maybe (NonEmpty (IntervalText Int))
vals = forall a. [a] -> Maybe (NonEmpty a)
NE.nonEmpty [IntervalText Int]
l
in if
| forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry forall a (i0 :: * -> *) (i1 :: * -> *).
(Ord a, Intervallic i0, Intervallic i1) =>
ComparativePredicateOf2 (i0 a) (i1 a)
concur) (forall {a}. [a] -> [(a, a)]
pairs [IntervalText Int]
l) -> forall a b. a -> Either a b
Left IntervalTextLineParseError
ConcurringIntervals
| (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {b}. Ord b => [b] -> Bool
isSorted forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall (i :: * -> *) a. Intervallic i => i a -> Interval a
getInterval) [IntervalText Int]
l -> forall a b. a -> Either a b
Left IntervalTextLineParseError
UnsortedIntervals
| forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any ((forall a. Ord a => a -> a -> Bool
< Int
0) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (i :: * -> *) a. Intervallic i => i a -> a
begin) [IntervalText Int]
l -> forall a b. a -> Either a b
Left IntervalTextLineParseError
BeginsLessThanZero
| Bool
otherwise -> case Maybe (NonEmpty (IntervalText Int))
vals of
Maybe (NonEmpty (IntervalText Int))
Nothing -> forall a b. b -> Either a b
Right (forall a. [IntervalText a] -> [Text] -> IntervalTextLine a
MkIntervalTextLine [] [])
Just NonEmpty (IntervalText Int)
v ->
forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ forall a. [IntervalText a] -> [Text] -> IntervalTextLine a
MkIntervalTextLine (forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (NonEmpty (IntervalText Int) -> NonEmpty (IntervalText Int)
makeIntervalLine NonEmpty (IntervalText Int)
v)) [Text]
labs
where
makeIntervalLine
:: NE.NonEmpty (IntervalText Int) -> NE.NonEmpty (IntervalText Int)
makeIntervalLine :: NonEmpty (IntervalText Int) -> NonEmpty (IntervalText Int)
makeIntervalLine NonEmpty (IntervalText Int)
x =
forall a. NonEmpty a -> a
NE.head NonEmpty (IntervalText Int)
x forall a. a -> [a] -> NonEmpty a
NE.:| forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith forall a b (i1 :: * -> *) (i0 :: * -> *).
(IntervalSizeable a b, Intervallic i1, Intervallic i0) =>
i0 a -> i1 a -> i1 b
shiftFromEnd (forall (t :: * -> *) a. Foldable t => t a -> [a]
toList NonEmpty (IntervalText Int)
x) (forall a. NonEmpty a -> [a]
NE.tail NonEmpty (IntervalText Int)
x)
pairs :: [a] -> [(a, a)]
pairs = forall {a}. [a] -> [(a, a)]
go
where
go :: [a] -> [(a, a)]
go [] = []
go (a
x : [a]
xs) = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a
x, ) [a]
xs forall a. Semigroup a => a -> a -> a
<> [a] -> [(a, a)]
go [a]
xs
isSorted :: [b] -> Bool
isSorted [b]
xs = forall (t :: * -> *). Foldable t => t Bool -> Bool
and forall a b. (a -> b) -> a -> b
$ forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith forall a. Ord a => a -> a -> Bool
(<=) [b]
xs (forall a. [a] -> [a]
tail [b]
xs)
data AxisPlacement =
Top
| Bottom deriving (AxisPlacement -> AxisPlacement -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AxisPlacement -> AxisPlacement -> Bool
$c/= :: AxisPlacement -> AxisPlacement -> Bool
== :: AxisPlacement -> AxisPlacement -> Bool
$c== :: AxisPlacement -> AxisPlacement -> Bool
Eq, Int -> AxisPlacement -> ShowS
[AxisPlacement] -> ShowS
AxisPlacement -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AxisPlacement] -> ShowS
$cshowList :: [AxisPlacement] -> ShowS
show :: AxisPlacement -> String
$cshow :: AxisPlacement -> String
showsPrec :: Int -> AxisPlacement -> ShowS
$cshowsPrec :: Int -> AxisPlacement -> ShowS
Show)
newtype AxisLabels = MkAxisLabels (NE.NonEmpty (Int, Char))
deriving (AxisLabels -> AxisLabels -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AxisLabels -> AxisLabels -> Bool
$c/= :: AxisLabels -> AxisLabels -> Bool
== :: AxisLabels -> AxisLabels -> Bool
$c== :: AxisLabels -> AxisLabels -> Bool
Eq, Int -> AxisLabels -> ShowS
[AxisLabels] -> ShowS
AxisLabels -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AxisLabels] -> ShowS
$cshowList :: [AxisLabels] -> ShowS
show :: AxisLabels -> String
$cshow :: AxisLabels -> String
showsPrec :: Int -> AxisLabels -> ShowS
$cshowsPrec :: Int -> AxisLabels -> ShowS
Show)
data AxisConfig = MkAxisConfig
{ AxisConfig -> Maybe AxisPlacement
placement :: Maybe AxisPlacement
, AxisConfig -> Maybe AxisLabels
labels :: Maybe AxisLabels
}
deriving (AxisConfig -> AxisConfig -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AxisConfig -> AxisConfig -> Bool
$c/= :: AxisConfig -> AxisConfig -> Bool
== :: AxisConfig -> AxisConfig -> Bool
$c== :: AxisConfig -> AxisConfig -> Bool
Eq, Int -> AxisConfig -> ShowS
[AxisConfig] -> ShowS
AxisConfig -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AxisConfig] -> ShowS
$cshowList :: [AxisConfig] -> ShowS
show :: AxisConfig -> String
$cshow :: AxisConfig -> String
showsPrec :: Int -> AxisConfig -> ShowS
$cshowsPrec :: Int -> AxisConfig -> ShowS
Show)
intMapList :: NE.NonEmpty (Int, a) -> NE.NonEmpty (Int, a)
intMapList :: forall a. NonEmpty (Int, a) -> NonEmpty (Int, a)
intMapList = forall a. (a -> a -> Ordering) -> NonEmpty a -> NonEmpty a
NE.sortBy (\(Int
k, a
_) (Int
k', a
_) -> forall a. Ord a => a -> a -> Ordering
compare Int
k Int
k')
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> a -> Bool) -> NonEmpty a -> NonEmpty a
NE.nubBy (\(Int
k, a
_) (Int
k', a
_) -> Int
k forall a. Eq a => a -> a -> Bool
== Int
k')
prettyAxisLabels :: AxisPlacement -> AxisLabels -> [Doc ann]
prettyAxisLabels :: forall ann. AxisPlacement -> AxisLabels -> [Doc ann]
prettyAxisLabels AxisPlacement
pos (MkAxisLabels NonEmpty (Int, Char)
labs) = do
let labssorted :: NonEmpty (Int, Char)
labssorted = forall a. NonEmpty (Int, a) -> NonEmpty (Int, a)
intMapList NonEmpty (Int, Char)
labs
let ints :: NonEmpty Int
ints = forall a b. (a -> b) -> NonEmpty a -> NonEmpty b
NE.map forall a b. (a, b) -> a
fst NonEmpty (Int, Char)
labssorted
let marks :: String
marks = forall (t :: * -> *) a. Foldable t => t a -> [a]
toList forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> NonEmpty a -> NonEmpty b
NE.map forall a b. (a, b) -> b
snd NonEmpty (Int, Char)
labssorted
let labPos :: [Int]
labPos =
forall a. NonEmpty a -> a
NE.head NonEmpty Int
ints forall a. a -> [a] -> [a]
: forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\Int
x Int
y -> Int
y forall a. Num a => a -> a -> a
- Int
x forall a. Num a => a -> a -> a
- Int
1) (forall (t :: * -> *) a. Foldable t => t a -> [a]
toList NonEmpty Int
ints) (forall a. NonEmpty a -> [a]
NE.tail NonEmpty Int
ints)
let out :: [Doc ann]
out =
[ forall ann. [Doc ann] -> Doc ann
hcat forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\Int
i -> forall ann. Int -> Doc ann -> Doc ann
indent Int
i (forall a ann. Pretty a => a -> Doc ann
pretty Char
'|')) [Int]
labPos
, forall ann. [Doc ann] -> Doc ann
hcat forall a b. (a -> b) -> a -> b
$ forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith forall ann. Int -> Doc ann -> Doc ann
indent [Int]
labPos (forall a ann. Pretty a => a -> Doc ann
pretty forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String
marks)
]
case AxisPlacement
pos of
AxisPlacement
Top -> forall a. [a] -> [a]
reverse [Doc ann]
out
AxisPlacement
Bottom -> [Doc ann]
out
data Axis = MkAxis
{ Axis -> IntervalText Int
refInterval :: IntervalText Int
, Axis -> AxisConfig
config :: AxisConfig
}
deriving (Axis -> Axis -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Axis -> Axis -> Bool
$c/= :: Axis -> Axis -> Bool
== :: Axis -> Axis -> Bool
$c== :: Axis -> Axis -> Bool
Eq, Int -> Axis -> ShowS
[Axis] -> ShowS
Axis -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Axis] -> ShowS
$cshowList :: [Axis] -> ShowS
show :: Axis -> String
$cshow :: Axis -> String
showsPrec :: Int -> Axis -> ShowS
$cshowsPrec :: Int -> Axis -> ShowS
Show)
instance Pretty Axis where
pretty :: forall ann. Axis -> Doc ann
pretty (MkAxis IntervalText Int
ref (MkAxisConfig Maybe AxisPlacement
Nothing Maybe AxisLabels
_ )) = forall ann. Doc ann
emptyDoc
pretty (MkAxis IntervalText Int
ref (MkAxisConfig (Just AxisPlacement
_) Maybe AxisLabels
Nothing)) = forall a ann. Pretty a => a -> Doc ann
pretty IntervalText Int
ref
pretty (MkAxis IntervalText Int
ref (MkAxisConfig (Just AxisPlacement
Bottom) (Just AxisLabels
labels))) =
forall ann. [Doc ann] -> Doc ann
vcat forall a b. (a -> b) -> a -> b
$ forall a ann. Pretty a => a -> Doc ann
pretty IntervalText Int
ref forall a. a -> [a] -> [a]
: forall ann. AxisPlacement -> AxisLabels -> [Doc ann]
prettyAxisLabels AxisPlacement
Bottom AxisLabels
labels
pretty (MkAxis IntervalText Int
ref (MkAxisConfig (Just AxisPlacement
Top) (Just AxisLabels
labels))) =
forall ann. [Doc ann] -> Doc ann
vcat forall a b. (a -> b) -> a -> b
$ forall ann. AxisPlacement -> AxisLabels -> [Doc ann]
prettyAxisLabels AxisPlacement
Top AxisLabels
labels forall a. [a] -> [a] -> [a]
++ [forall a ann. Pretty a => a -> Doc ann
pretty IntervalText Int
ref]
instance Pretty ( Either AxisParseError Axis ) where
pretty :: forall ann. Either AxisParseError Axis -> Doc ann
pretty (Left AxisParseError
e) = forall a ann. Pretty a => a -> Doc ann
pretty forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> String
show AxisParseError
e
pretty (Right Axis
a) = forall a ann. Pretty a => a -> Doc ann
pretty Axis
a
data AxisParseError =
LabelsBeyondReference
| MultipleLabelAtSamePosition
deriving (AxisParseError -> AxisParseError -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AxisParseError -> AxisParseError -> Bool
$c/= :: AxisParseError -> AxisParseError -> Bool
== :: AxisParseError -> AxisParseError -> Bool
$c== :: AxisParseError -> AxisParseError -> Bool
Eq, Int -> AxisParseError -> ShowS
[AxisParseError] -> ShowS
AxisParseError -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AxisParseError] -> ShowS
$cshowList :: [AxisParseError] -> ShowS
show :: AxisParseError -> String
$cshow :: AxisParseError -> String
showsPrec :: Int -> AxisParseError -> ShowS
$cshowsPrec :: Int -> AxisParseError -> ShowS
Show)
parseAxis
:: [(Int, Char)]
-> Maybe AxisPlacement
-> IntervalText Int
-> Either AxisParseError Axis
parseAxis :: [(Int, Char)]
-> Maybe AxisPlacement
-> IntervalText Int
-> Either AxisParseError Axis
parseAxis [(Int, Char)]
_ Maybe AxisPlacement
Nothing IntervalText Int
i = forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ IntervalText Int -> AxisConfig -> Axis
MkAxis IntervalText Int
i (Maybe AxisPlacement -> Maybe AxisLabels -> AxisConfig
MkAxisConfig forall a. Maybe a
Nothing forall a. Maybe a
Nothing)
parseAxis [(Int, Char)]
l (Just AxisPlacement
p) IntervalText Int
i = do
let labels :: Maybe (NonEmpty (Int, Char))
labels = forall a. NonEmpty (Int, a) -> NonEmpty (Int, a)
intMapList forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. [a] -> Maybe (NonEmpty a)
NE.nonEmpty [(Int, Char)]
l
let labPos :: Maybe (NonEmpty Int)
labPos = forall a b. (a -> b) -> NonEmpty a -> NonEmpty b
NE.map forall a b. (a, b) -> a
fst forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe (NonEmpty (Int, Char))
labels
let inputLabelCount :: Int
inputLabelCount = forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Int, Char)]
l
if
|
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (\Int
x -> Int
x forall a. Ord a => a -> a -> Bool
< forall (i :: * -> *) a. Intervallic i => i a -> a
begin IntervalText Int
i Bool -> Bool -> Bool
|| Int
x forall a. Ord a => a -> a -> Bool
> forall (i :: * -> *) a. Intervallic i => i a -> a
end IntervalText Int
i) (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (a, b) -> a
fst [(Int, Char)]
l) -> forall a b. a -> Either a b
Left
AxisParseError
LabelsBeyondReference
|
Int
inputLabelCount forall a. Ord a => a -> a -> Bool
> Int
0 Bool -> Bool -> Bool
&& forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall (t :: * -> *) a. Foldable t => t a -> Int
length Maybe (NonEmpty (Int, Char))
labels forall a. Eq a => a -> a -> Bool
/= forall a. a -> Maybe a
Just Int
inputLabelCount -> forall a b. a -> Either a b
Left
AxisParseError
MultipleLabelAtSamePosition
|
Bool
otherwise -> forall a b. b -> Either a b
Right
forall a b. (a -> b) -> a -> b
$ IntervalText Int -> AxisConfig -> Axis
MkAxis IntervalText Int
i (Maybe AxisPlacement -> Maybe AxisLabels -> AxisConfig
MkAxisConfig (forall a. a -> Maybe a
Just AxisPlacement
p) (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap NonEmpty (Int, Char) -> AxisLabels
MkAxisLabels Maybe (NonEmpty (Int, Char))
labels))
data IntervalDiagramOptions = MkIntervalDiagramOptions
{
IntervalDiagramOptions -> LayoutOptions
layout :: LayoutOptions
, IntervalDiagramOptions -> Int
leftPadding :: Int
}
deriving (IntervalDiagramOptions -> IntervalDiagramOptions -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: IntervalDiagramOptions -> IntervalDiagramOptions -> Bool
$c/= :: IntervalDiagramOptions -> IntervalDiagramOptions -> Bool
== :: IntervalDiagramOptions -> IntervalDiagramOptions -> Bool
$c== :: IntervalDiagramOptions -> IntervalDiagramOptions -> Bool
Eq, Int -> IntervalDiagramOptions -> ShowS
[IntervalDiagramOptions] -> ShowS
IntervalDiagramOptions -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [IntervalDiagramOptions] -> ShowS
$cshowList :: [IntervalDiagramOptions] -> ShowS
show :: IntervalDiagramOptions -> String
$cshow :: IntervalDiagramOptions -> String
showsPrec :: Int -> IntervalDiagramOptions -> ShowS
$cshowsPrec :: Int -> IntervalDiagramOptions -> ShowS
Show)
data IntervalDiagramOptionsError =
UnboundedPageWidth
| LeftPaddingLessThan0
deriving (IntervalDiagramOptionsError -> IntervalDiagramOptionsError -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: IntervalDiagramOptionsError -> IntervalDiagramOptionsError -> Bool
$c/= :: IntervalDiagramOptionsError -> IntervalDiagramOptionsError -> Bool
== :: IntervalDiagramOptionsError -> IntervalDiagramOptionsError -> Bool
$c== :: IntervalDiagramOptionsError -> IntervalDiagramOptionsError -> Bool
Eq, Int -> IntervalDiagramOptionsError -> ShowS
[IntervalDiagramOptionsError] -> ShowS
IntervalDiagramOptionsError -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [IntervalDiagramOptionsError] -> ShowS
$cshowList :: [IntervalDiagramOptionsError] -> ShowS
show :: IntervalDiagramOptionsError -> String
$cshow :: IntervalDiagramOptionsError -> String
showsPrec :: Int -> IntervalDiagramOptionsError -> ShowS
$cshowsPrec :: Int -> IntervalDiagramOptionsError -> ShowS
Show)
parseDiagramOptions
:: IntervalDiagramOptions
-> Either IntervalDiagramOptionsError IntervalDiagramOptions
parseDiagramOptions :: IntervalDiagramOptions
-> Either IntervalDiagramOptionsError IntervalDiagramOptions
parseDiagramOptions IntervalDiagramOptions
opts = if
| IntervalDiagramOptions -> Int
leftPadding IntervalDiagramOptions
opts forall a. Ord a => a -> a -> Bool
< Int
0 -> forall a b. a -> Either a b
Left IntervalDiagramOptionsError
LeftPaddingLessThan0
| LayoutOptions -> PageWidth
layoutPageWidth (IntervalDiagramOptions -> LayoutOptions
layout IntervalDiagramOptions
opts) forall a. Eq a => a -> a -> Bool
== PageWidth
Unbounded -> forall a b. a -> Either a b
Left IntervalDiagramOptionsError
UnboundedPageWidth
| Bool
otherwise -> forall a b. b -> Either a b
Right IntervalDiagramOptions
opts
where isSorted :: [b] -> Bool
isSorted [b]
xs = forall (t :: * -> *). Foldable t => t Bool -> Bool
and forall a b. (a -> b) -> a -> b
$ forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith forall a. Ord a => a -> a -> Bool
(<=) [b]
xs (forall a. [a] -> [a]
tail [b]
xs)
defaultIntervalDiagramOptions :: IntervalDiagramOptions
defaultIntervalDiagramOptions :: IntervalDiagramOptions
defaultIntervalDiagramOptions = LayoutOptions -> Int -> IntervalDiagramOptions
MkIntervalDiagramOptions LayoutOptions
defaultLayoutOptions Int
0
data IntervalDiagram a = MkIntervalDiagram
{
forall a. IntervalDiagram a -> Interval a
reference :: Interval a
, forall a. IntervalDiagram a -> Axis
axis :: Axis
, forall a. IntervalDiagram a -> [IntervalTextLine Int]
intervalValues :: [IntervalTextLine Int]
, forall a. IntervalDiagram a -> IntervalDiagramOptions
options :: IntervalDiagramOptions
}
deriving Int -> IntervalDiagram a -> ShowS
forall a. (Show a, Ord a) => Int -> IntervalDiagram a -> ShowS
forall a. (Show a, Ord a) => [IntervalDiagram a] -> ShowS
forall a. (Show a, Ord a) => IntervalDiagram a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [IntervalDiagram a] -> ShowS
$cshowList :: forall a. (Show a, Ord a) => [IntervalDiagram a] -> ShowS
show :: IntervalDiagram a -> String
$cshow :: forall a. (Show a, Ord a) => IntervalDiagram a -> String
showsPrec :: Int -> IntervalDiagram a -> ShowS
$cshowsPrec :: forall a. (Show a, Ord a) => Int -> IntervalDiagram a -> ShowS
Show
data IntervalDiagramParseError =
IntervalsExtendBeyondAxis
| AxisWiderThanAvailable
| PaddingWithNoAxis
| OptionsError IntervalDiagramOptionsError
| AxisError AxisParseError
| IntervalLineError IntervalTextLineParseError
deriving (IntervalDiagramParseError -> IntervalDiagramParseError -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: IntervalDiagramParseError -> IntervalDiagramParseError -> Bool
$c/= :: IntervalDiagramParseError -> IntervalDiagramParseError -> Bool
== :: IntervalDiagramParseError -> IntervalDiagramParseError -> Bool
$c== :: IntervalDiagramParseError -> IntervalDiagramParseError -> Bool
Eq, Int -> IntervalDiagramParseError -> ShowS
[IntervalDiagramParseError] -> ShowS
IntervalDiagramParseError -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [IntervalDiagramParseError] -> ShowS
$cshowList :: [IntervalDiagramParseError] -> ShowS
show :: IntervalDiagramParseError -> String
$cshow :: IntervalDiagramParseError -> String
showsPrec :: Int -> IntervalDiagramParseError -> ShowS
$cshowsPrec :: Int -> IntervalDiagramParseError -> ShowS
Show)
instance (IntervalSizeable a b) => Pretty (IntervalDiagram a) where
pretty :: forall ann. IntervalDiagram a -> Doc ann
pretty (MkIntervalDiagram Interval a
_ Axis
axis [IntervalTextLine Int]
ivs IntervalDiagramOptions
opts) = do
let intervalLines :: [Doc ann]
intervalLines = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a ann. Pretty a => a -> Doc ann
pretty [IntervalTextLine Int]
ivs
let refDur :: Int
refDur = forall (i :: * -> *) a. Intervallic i => i a -> a
end (Axis -> IntervalText Int
refInterval Axis
axis)
let labelIndents :: [Int]
labelIndents = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b. IntervalSizeable a b => a -> a -> b
diff Int
refDur forall b c a. (b -> c) -> (a -> b) -> a -> c
. IntervalTextLine Int -> Int
intervalLineEnd) [IntervalTextLine Int]
ivs
let labelLines :: [Doc ann]
labelLines =
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\IntervalTextLine Int
i Int
l -> forall ann. Int -> Doc ann -> Doc ann
indent Int
l (forall ann. IntervalTextLine Int -> Doc ann
prettyLineLabel IntervalTextLine Int
i)) [IntervalTextLine Int]
ivs [Int]
labelIndents
let intervalDiagram :: Doc ann
intervalDiagram = forall ann. [Doc ann] -> Doc ann
vsep forall a b. (a -> b) -> a -> b
$ forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith forall a. Semigroup a => a -> a -> a
(<>) [Doc ann]
intervalLines [Doc ann]
labelLines
let mainDiagram :: Doc ann
mainDiagram = case (AxisConfig -> Maybe AxisPlacement
placement forall b c a. (b -> c) -> (a -> b) -> a -> c
. Axis -> AxisConfig
config) Axis
axis of
Maybe AxisPlacement
Nothing -> Doc ann
intervalDiagram
Just AxisPlacement
Top -> forall ann. [Doc ann] -> Doc ann
vcat [forall a ann. Pretty a => a -> Doc ann
pretty Axis
axis, Doc ann
intervalDiagram]
Just AxisPlacement
Bottom -> forall ann. [Doc ann] -> Doc ann
vcat [Doc ann
intervalDiagram, forall a ann. Pretty a => a -> Doc ann
pretty Axis
axis]
forall ann. Int -> Doc ann -> Doc ann
indent (IntervalDiagramOptions -> Int
leftPadding IntervalDiagramOptions
opts) Doc ann
mainDiagram
where
intervalLineEnd :: IntervalTextLine Int -> Int
intervalLineEnd :: IntervalTextLine Int -> Int
intervalLineEnd (MkIntervalTextLine [IntervalText Int]
x [Text]
_) = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall (i :: * -> *) a. Intervallic i => i a -> a
end [IntervalText Int]
x
prettyLineLabel :: IntervalTextLine Int -> Doc ann
prettyLineLabel :: forall ann. IntervalTextLine Int -> Doc ann
prettyLineLabel (MkIntervalTextLine [IntervalText Int]
_ [Text]
t) = if forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Text]
t
then forall ann. Doc ann
emptyDoc
else forall ann. Doc ann
space forall a. Semigroup a => a -> a -> a
<> forall a ann. Pretty a => a -> Doc ann
pretty (Text
"<-" :: Text) forall a. Semigroup a => a -> a -> a
<> forall ann. Doc ann
space forall a. Semigroup a => a -> a -> a
<> forall a ann. Pretty a => a -> Doc ann
pretty [Text]
t
instance (IntervalSizeable a b) =>
Pretty (Either IntervalDiagramParseError (IntervalDiagram a)) where
pretty :: forall ann.
Either IntervalDiagramParseError (IntervalDiagram a) -> Doc ann
pretty (Left IntervalDiagramParseError
e) = forall a ann. Pretty a => a -> Doc ann
pretty forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> String
show IntervalDiagramParseError
e
pretty (Right IntervalDiagram a
d) = forall a ann. Pretty a => a -> Doc ann
pretty IntervalDiagram a
d
parseIntervalDiagram
:: (Ord a, IntervalSizeable a b, Enum b)
=> IntervalDiagramOptions
-> [(Int, Char)]
-> Maybe AxisPlacement
-> IntervalText a
-> [([IntervalText a], [Text])]
-> Either IntervalDiagramParseError (IntervalDiagram a)
parseIntervalDiagram :: forall a b.
(Ord a, IntervalSizeable a b, Enum b) =>
IntervalDiagramOptions
-> [(Int, Char)]
-> Maybe AxisPlacement
-> IntervalText a
-> [([IntervalText a], [Text])]
-> Either IntervalDiagramParseError (IntervalDiagram a)
parseIntervalDiagram IntervalDiagramOptions
opts [(Int, Char)]
labels Maybe AxisPlacement
placement IntervalText a
ref [([IntervalText a], [Text])]
ivs =
case IntervalDiagramOptions
-> Either IntervalDiagramOptionsError IntervalDiagramOptions
parseDiagramOptions IntervalDiagramOptions
opts of
Left IntervalDiagramOptionsError
e -> forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ IntervalDiagramOptionsError -> IntervalDiagramParseError
OptionsError IntervalDiagramOptionsError
e
Right IntervalDiagramOptions
o -> if
|
PageWidth -> Bool
checkAvailableChar (LayoutOptions -> PageWidth
layoutPageWidth forall a b. (a -> b) -> a -> b
$ IntervalDiagramOptions -> LayoutOptions
layout IntervalDiagramOptions
o)
-> forall a b. a -> Either a b
Left IntervalDiagramParseError
AxisWiderThanAvailable
|
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (ComparativePredicateOf2 (IntervalText a) (IntervalText a)
extendsBeyond IntervalText a
ref) (forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap forall a b. (a, b) -> a
fst [([IntervalText a], [Text])]
ivs)
-> forall a b. a -> Either a b
Left IntervalDiagramParseError
IntervalsExtendBeyondAxis
|
IntervalDiagramOptions -> Int
leftPadding IntervalDiagramOptions
o forall a. Ord a => a -> a -> Bool
> Int
0 Bool -> Bool -> Bool
&& forall a. Maybe a -> Bool
isNothing Maybe AxisPlacement
placement
-> forall a b. a -> Either a b
Left IntervalDiagramParseError
PaddingWithNoAxis
| Bool
otherwise
-> let parsedReferencedIntervals :: Either IntervalTextLineParseError [IntervalTextLine Int]
parsedReferencedIntervals = forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse
(\([IntervalText a]
i, [Text]
t) -> [Text]
-> [IntervalText Int]
-> Either IntervalTextLineParseError (IntervalTextLine Int)
parseIntervalTextLine [Text]
t (forall {f :: * -> *} {a} {a} {i :: * -> *} {i0 :: * -> *}.
(Functor f, Enum a, IntervalSizeable a a, Intervallic i,
Intervallic i0) =>
i0 a -> f (i a) -> f (i Int)
rereferenceL IntervalText a
ref [IntervalText a]
i))
[([IntervalText a], [Text])]
ivs
in case Either IntervalTextLineParseError [IntervalTextLine Int]
parsedReferencedIntervals of
Left IntervalTextLineParseError
e -> forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ IntervalTextLineParseError -> IntervalDiagramParseError
IntervalLineError IntervalTextLineParseError
e
Right [IntervalTextLine Int]
vals ->
let parsedAxis :: Either AxisParseError Axis
parsedAxis =
[(Int, Char)]
-> Maybe AxisPlacement
-> IntervalText Int
-> Either AxisParseError Axis
parseAxis [(Int, Char)]
labels Maybe AxisPlacement
placement (forall {a} {a} {i :: * -> *} {i0 :: * -> *}.
(Enum a, IntervalSizeable a a, Intervallic i, Intervallic i0) =>
i0 a -> i a -> i Int
rereference IntervalText a
ref IntervalText a
ref)
in case Either AxisParseError Axis
parsedAxis of
Left AxisParseError
e -> forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ AxisParseError -> IntervalDiagramParseError
AxisError AxisParseError
e
Right Axis
axis ->
forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ forall a.
Interval a
-> Axis
-> [IntervalTextLine Int]
-> IntervalDiagramOptions
-> IntervalDiagram a
MkIntervalDiagram (forall (i :: * -> *) a. Intervallic i => i a -> Interval a
getInterval IntervalText a
ref) Axis
axis [IntervalTextLine Int]
vals IntervalDiagramOptions
o
where
extendsBeyond :: ComparativePredicateOf2 (IntervalText a) (IntervalText a)
extendsBeyond =
forall a (i0 :: * -> *) (i1 :: * -> *).
(Ord a, Intervallic i0, Intervallic i1) =>
ComparativePredicateOf2 (i0 a) (i1 a)
before forall (i0 :: * -> *) (i1 :: * -> *) a.
(Intervallic i0, Intervallic i1) =>
ComparativePredicateOf2 (i0 a) (i1 a)
-> ComparativePredicateOf2 (i0 a) (i1 a)
-> ComparativePredicateOf2 (i0 a) (i1 a)
<|> forall a (i0 :: * -> *) (i1 :: * -> *).
(Eq a, Intervallic i0, Intervallic i1) =>
ComparativePredicateOf2 (i0 a) (i1 a)
meets forall (i0 :: * -> *) (i1 :: * -> *) a.
(Intervallic i0, Intervallic i1) =>
ComparativePredicateOf2 (i0 a) (i1 a)
-> ComparativePredicateOf2 (i0 a) (i1 a)
-> ComparativePredicateOf2 (i0 a) (i1 a)
<|> forall a (i0 :: * -> *) (i1 :: * -> *).
(Ord a, Intervallic i0, Intervallic i1) =>
ComparativePredicateOf2 (i0 a) (i1 a)
overlaps forall (i0 :: * -> *) (i1 :: * -> *) a.
(Intervallic i0, Intervallic i1) =>
ComparativePredicateOf2 (i0 a) (i1 a)
-> ComparativePredicateOf2 (i0 a) (i1 a)
-> ComparativePredicateOf2 (i0 a) (i1 a)
<|> forall a (i0 :: * -> *) (i1 :: * -> *).
(Ord a, Intervallic i0, Intervallic i1) =>
ComparativePredicateOf2 (i0 a) (i1 a)
overlappedBy forall (i0 :: * -> *) (i1 :: * -> *) a.
(Intervallic i0, Intervallic i1) =>
ComparativePredicateOf2 (i0 a) (i1 a)
-> ComparativePredicateOf2 (i0 a) (i1 a)
-> ComparativePredicateOf2 (i0 a) (i1 a)
<|> forall a (i0 :: * -> *) (i1 :: * -> *).
(Eq a, Intervallic i0, Intervallic i1) =>
ComparativePredicateOf2 (i0 a) (i1 a)
metBy forall (i0 :: * -> *) (i1 :: * -> *) a.
(Intervallic i0, Intervallic i1) =>
ComparativePredicateOf2 (i0 a) (i1 a)
-> ComparativePredicateOf2 (i0 a) (i1 a)
-> ComparativePredicateOf2 (i0 a) (i1 a)
<|> forall a (i0 :: * -> *) (i1 :: * -> *).
(Ord a, Intervallic i0, Intervallic i1) =>
ComparativePredicateOf2 (i0 a) (i1 a)
after
checkAvailableChar :: PageWidth -> Bool
checkAvailableChar (AvailablePerLine Int
i Double
_) = forall a. Enum a => a -> Int
fromEnum (forall a b (i :: * -> *).
(IntervalSizeable a b, Intervallic i) =>
i a -> b
duration IntervalText a
ref) forall a. Ord a => a -> a -> Bool
> Int
i
checkAvailableChar PageWidth
Unbounded = Bool
True
rereference :: i0 a -> i a -> i Int
rereference i0 a
x = forall a (i :: * -> *). (Enum a, Intervallic i) => i a -> i Int
fromEnumInterval forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b (i1 :: * -> *) (i0 :: * -> *).
(IntervalSizeable a b, Intervallic i1, Intervallic i0) =>
i0 a -> i1 a -> i1 b
shiftFromBegin i0 a
x
rereferenceL :: i0 a -> f (i a) -> f (i Int)
rereferenceL i0 a
x = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall {a} {a} {i :: * -> *} {i0 :: * -> *}.
(Enum a, IntervalSizeable a a, Intervallic i, Intervallic i0) =>
i0 a -> i a -> i Int
rereference i0 a
x)
simpleIntervalDiagram
:: (Ord a, IntervalSizeable a b, Intervallic i, Enum b)
=> i a
-> [i a]
-> Either IntervalDiagramParseError (IntervalDiagram a)
simpleIntervalDiagram :: forall a b (i :: * -> *).
(Ord a, IntervalSizeable a b, Intervallic i, Enum b) =>
i a
-> [i a] -> Either IntervalDiagramParseError (IntervalDiagram a)
simpleIntervalDiagram i a
ref [i a]
ivs = forall a b.
(Ord a, IntervalSizeable a b, Enum b) =>
IntervalDiagramOptions
-> [(Int, Char)]
-> Maybe AxisPlacement
-> IntervalText a
-> [([IntervalText a], [Text])]
-> Either IntervalDiagramParseError (IntervalDiagram a)
parseIntervalDiagram
IntervalDiagramOptions
defaultIntervalDiagramOptions
[]
(forall a. a -> Maybe a
Just AxisPlacement
Bottom)
(forall a. Char -> Interval a -> IntervalText a
makeIntervalText Char
'=' (forall (i :: * -> *) a. Intervallic i => i a -> Interval a
getInterval i a
ref))
(forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\i a
x -> (forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall a. Char -> Interval a -> IntervalText a
makeIntervalText Char
'-' forall a b. (a -> b) -> a -> b
$ forall (i :: * -> *) a. Intervallic i => i a -> Interval a
getInterval i a
x, [])) [i a]
ivs)
standardExampleDiagram
:: (Num a, Ord a, Enum b, IntervalSizeable a b)
=> [(Interval a, String)]
-> [([Interval a], String)]
-> Either IntervalDiagramParseError (IntervalDiagram a)
standardExampleDiagram :: forall a b.
(Num a, Ord a, Enum b, IntervalSizeable a b) =>
[(Interval a, String)]
-> [([Interval a], String)]
-> Either IntervalDiagramParseError (IntervalDiagram a)
standardExampleDiagram [(Interval a, String)]
ivs [([Interval a], String)]
livs = Maybe (IntervalText a)
-> Either IntervalDiagramParseError (IntervalDiagram a)
op Maybe (IntervalText a)
ref
where
op :: Maybe (IntervalText a)
-> Either IntervalDiagramParseError (IntervalDiagram a)
op Maybe (IntervalText a)
Nothing = forall a b. a -> Either a b
Left IntervalDiagramParseError
IntervalsExtendBeyondAxis
op (Just IntervalText a
ref') = forall a b.
(Ord a, IntervalSizeable a b, Enum b) =>
IntervalDiagramOptions
-> [(Int, Char)]
-> Maybe AxisPlacement
-> IntervalText a
-> [([IntervalText a], [Text])]
-> Either IntervalDiagramParseError (IntervalDiagram a)
parseIntervalDiagram IntervalDiagramOptions
defaultIntervalDiagramOptions
[]
(forall a. a -> Maybe a
Just AxisPlacement
Bottom)
IntervalText a
ref'
[([IntervalText a], [Text])]
combIvs
range :: Maybe (Interval a)
range = forall a (t :: * -> *).
(Ord a, Foldable t) =>
t (Interval a) -> Maybe (Interval a)
rangeInterval forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst [(Interval a, String)]
ivs forall a. [a] -> [a] -> [a]
++ forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap forall a b. (a, b) -> a
fst [([Interval a], String)]
livs
anchoredRange :: Maybe (Interval a)
anchoredRange = case Maybe (Interval a)
range of
Maybe (Interval a)
Nothing -> forall a. Maybe a
Nothing
(Just Interval a
x) -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a b. IntervalSizeable a b => (a, a) -> Interval a
safeInterval (forall a. Ord a => a -> a -> a
min (forall (i :: * -> *) a. Intervallic i => i a -> a
begin Interval a
x) a
0, forall a. Ord a => a -> a -> a
max (forall (i :: * -> *) a. Intervallic i => i a -> a
end Interval a
x) a
0)
ref :: Maybe (IntervalText a)
ref = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a. Char -> Interval a -> IntervalText a
makeIntervalText Char
'=') Maybe (Interval a)
anchoredRange
f :: (a, b) -> ([a], b)
f (a
iv, b
s) = ([a
iv], b
s)
g :: ([Interval a], String) -> ([IntervalText a], [Text])
g ([Interval a]
ivs, String
s) = (forall a b. (a -> b) -> [a] -> [b]
map (forall a. Char -> Interval a -> IntervalText a
makeIntervalText Char
'-') [Interval a]
ivs, [String -> Text
pack String
s])
combIvs :: [([IntervalText a], [Text])]
combIvs = forall a b. (a -> b) -> [a] -> [b]
map (forall {a}. ([Interval a], String) -> ([IntervalText a], [Text])
g forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {a} {b}. (a, b) -> ([a], b)
f) [(Interval a, String)]
ivs forall a. [a] -> [a] -> [a]
++ forall a b. (a -> b) -> [a] -> [b]
map forall {a}. ([Interval a], String) -> ([IntervalText a], [Text])
g [([Interval a], String)]
livs