{-# LANGUAGE FlexibleInstances #-}
module Options.Applicative.Help.Chunk
( Chunk(..)
, chunked
, listToChunk
, (<<+>>)
, (<</>>)
, vcatChunks
, vsepChunks
, isEmpty
, stringChunk
, paragraph
, extractChunk
, tabulate
, chunkFlatAlt
, chunkIsEffectivelyEmpty
) where
import Control.Applicative
import Control.Monad
import Data.List.NonEmpty (NonEmpty(..))
import Data.Maybe
import Data.Semigroup
import Prelude
import Options.Applicative.Help.Ann
import Options.Applicative.Help.Pretty
newtype Chunk a = Chunk
{ Chunk a -> Maybe a
unChunk :: Maybe a }
deriving (Chunk a -> Chunk a -> Bool
(Chunk a -> Chunk a -> Bool)
-> (Chunk a -> Chunk a -> Bool) -> Eq (Chunk a)
forall a. Eq a => Chunk a -> Chunk a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Chunk a -> Chunk a -> Bool
$c/= :: forall a. Eq a => Chunk a -> Chunk a -> Bool
== :: Chunk a -> Chunk a -> Bool
$c== :: forall a. Eq a => Chunk a -> Chunk a -> Bool
Eq, Int -> Chunk a -> ShowS
[Chunk a] -> ShowS
Chunk a -> String
(Int -> Chunk a -> ShowS)
-> (Chunk a -> String) -> ([Chunk a] -> ShowS) -> Show (Chunk a)
forall a. Show a => Int -> Chunk a -> ShowS
forall a. Show a => [Chunk a] -> ShowS
forall a. Show a => Chunk a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Chunk a] -> ShowS
$cshowList :: forall a. Show a => [Chunk a] -> ShowS
show :: Chunk a -> String
$cshow :: forall a. Show a => Chunk a -> String
showsPrec :: Int -> Chunk a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Chunk a -> ShowS
Show)
instance CanAnnotate (Chunk Doc) where
annTrace :: Int -> String -> Chunk Doc -> Chunk Doc
annTrace Int
n = (Doc -> Doc) -> Chunk Doc -> Chunk Doc
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Doc -> Doc) -> Chunk Doc -> Chunk Doc)
-> (String -> Doc -> Doc) -> String -> Chunk Doc -> Chunk Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> String -> Doc -> Doc
forall a. CanAnnotate a => Int -> String -> a -> a
annTrace Int
n
instance Functor Chunk where
fmap :: (a -> b) -> Chunk a -> Chunk b
fmap a -> b
f = Maybe b -> Chunk b
forall a. Maybe a -> Chunk a
Chunk (Maybe b -> Chunk b) -> (Chunk a -> Maybe b) -> Chunk a -> Chunk b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f (Maybe a -> Maybe b) -> (Chunk a -> Maybe a) -> Chunk a -> Maybe b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Chunk a -> Maybe a
forall a. Chunk a -> Maybe a
unChunk
instance Applicative Chunk where
pure :: a -> Chunk a
pure = Maybe a -> Chunk a
forall a. Maybe a -> Chunk a
Chunk (Maybe a -> Chunk a) -> (a -> Maybe a) -> a -> Chunk a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
Chunk Maybe (a -> b)
f <*> :: Chunk (a -> b) -> Chunk a -> Chunk b
<*> Chunk Maybe a
x = Maybe b -> Chunk b
forall a. Maybe a -> Chunk a
Chunk (Maybe (a -> b)
f Maybe (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Maybe a
x)
instance Alternative Chunk where
empty :: Chunk a
empty = Maybe a -> Chunk a
forall a. Maybe a -> Chunk a
Chunk Maybe a
forall (f :: * -> *) a. Alternative f => f a
Control.Applicative.empty
Chunk a
a <|> :: Chunk a -> Chunk a -> Chunk a
<|> Chunk a
b = Maybe a -> Chunk a
forall a. Maybe a -> Chunk a
Chunk (Maybe a -> Chunk a) -> Maybe a -> Chunk a
forall a b. (a -> b) -> a -> b
$ Chunk a -> Maybe a
forall a. Chunk a -> Maybe a
unChunk Chunk a
a Maybe a -> Maybe a -> Maybe a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Chunk a -> Maybe a
forall a. Chunk a -> Maybe a
unChunk Chunk a
b
instance Monad Chunk where
return :: a -> Chunk a
return = a -> Chunk a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
Chunk a
m >>= :: Chunk a -> (a -> Chunk b) -> Chunk b
>>= a -> Chunk b
f = Maybe b -> Chunk b
forall a. Maybe a -> Chunk a
Chunk (Maybe b -> Chunk b) -> Maybe b -> Chunk b
forall a b. (a -> b) -> a -> b
$ Chunk a -> Maybe a
forall a. Chunk a -> Maybe a
unChunk Chunk a
m Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Chunk b -> Maybe b
forall a. Chunk a -> Maybe a
unChunk (Chunk b -> Maybe b) -> (a -> Chunk b) -> a -> Maybe b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Chunk b
f
instance Semigroup a => Semigroup (Chunk a) where
<> :: Chunk a -> Chunk a -> Chunk a
(<>) = (a -> a -> a) -> Chunk a -> Chunk a -> Chunk a
forall a. (a -> a -> a) -> Chunk a -> Chunk a -> Chunk a
chunked a -> a -> a
forall a. Semigroup a => a -> a -> a
(<>)
instance Semigroup a => Monoid (Chunk a) where
mempty :: Chunk a
mempty = Maybe a -> Chunk a
forall a. Maybe a -> Chunk a
Chunk Maybe a
forall a. Maybe a
Nothing
mappend :: Chunk a -> Chunk a -> Chunk a
mappend = Chunk a -> Chunk a -> Chunk a
forall a. Semigroup a => a -> a -> a
(<>)
instance MonadPlus Chunk where
mzero :: Chunk a
mzero = Maybe a -> Chunk a
forall a. Maybe a -> Chunk a
Chunk Maybe a
forall (m :: * -> *) a. MonadPlus m => m a
mzero
mplus :: Chunk a -> Chunk a -> Chunk a
mplus Chunk a
m1 Chunk a
m2 = Maybe a -> Chunk a
forall a. Maybe a -> Chunk a
Chunk (Maybe a -> Chunk a) -> Maybe a -> Chunk a
forall a b. (a -> b) -> a -> b
$ Maybe a -> Maybe a -> Maybe a
forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
mplus (Chunk a -> Maybe a
forall a. Chunk a -> Maybe a
unChunk Chunk a
m1) (Chunk a -> Maybe a
forall a. Chunk a -> Maybe a
unChunk Chunk a
m2)
chunked :: (a -> a -> a)
-> Chunk a -> Chunk a -> Chunk a
chunked :: (a -> a -> a) -> Chunk a -> Chunk a -> Chunk a
chunked a -> a -> a
_ (Chunk Maybe a
Nothing) Chunk a
y = Chunk a
y
chunked a -> a -> a
_ Chunk a
x (Chunk Maybe a
Nothing) = Chunk a
x
chunked a -> a -> a
f (Chunk (Just a
x)) (Chunk (Just a
y)) = Maybe a -> Chunk a
forall a. Maybe a -> Chunk a
Chunk (a -> Maybe a
forall a. a -> Maybe a
Just (a -> a -> a
f a
x a
y))
listToChunk :: Semigroup a => [a] -> Chunk a
listToChunk :: [a] -> Chunk a
listToChunk [] = Chunk a
forall a. Monoid a => a
mempty
listToChunk (a
x:[a]
xs) = a -> Chunk a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (NonEmpty a -> a
forall a. Semigroup a => NonEmpty a -> a
sconcat (a
x a -> [a] -> NonEmpty a
forall a. a -> [a] -> NonEmpty a
:| [a]
xs))
extractChunk :: Monoid a => Chunk a -> a
= a -> Maybe a -> a
forall a. a -> Maybe a -> a
fromMaybe a
forall a. Monoid a => a
mempty (Maybe a -> a) -> (Chunk a -> Maybe a) -> Chunk a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Chunk a -> Maybe a
forall a. Chunk a -> Maybe a
unChunk
(<<+>>) :: Chunk Doc -> Chunk Doc -> Chunk Doc
<<+>> :: Chunk Doc -> Chunk Doc -> Chunk Doc
(<<+>>) = (Chunk Doc -> Chunk Doc)
-> (Chunk Doc -> Chunk Doc) -> Chunk Doc -> Chunk Doc
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Int -> String -> Chunk Doc -> Chunk Doc
forall a. CanAnnotate a => Int -> String -> a -> a
annTrace Int
1 String
"(<<+>>)") ((Chunk Doc -> Chunk Doc) -> Chunk Doc -> Chunk Doc)
-> (Chunk Doc -> Chunk Doc -> Chunk Doc)
-> Chunk Doc
-> Chunk Doc
-> Chunk Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Doc -> Doc -> Doc) -> Chunk Doc -> Chunk Doc -> Chunk Doc
forall a. (a -> a -> a) -> Chunk a -> Chunk a -> Chunk a
chunked Doc -> Doc -> Doc
forall ann. Doc ann -> Doc ann -> Doc ann
(<+>)
(<</>>) :: Chunk Doc -> Chunk Doc -> Chunk Doc
<</>> :: Chunk Doc -> Chunk Doc -> Chunk Doc
(<</>>) = (Chunk Doc -> Chunk Doc)
-> (Chunk Doc -> Chunk Doc) -> Chunk Doc -> Chunk Doc
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Int -> String -> Chunk Doc -> Chunk Doc
forall a. CanAnnotate a => Int -> String -> a -> a
annTrace Int
1 String
"(<</>>)") ((Chunk Doc -> Chunk Doc) -> Chunk Doc -> Chunk Doc)
-> (Chunk Doc -> Chunk Doc -> Chunk Doc)
-> Chunk Doc
-> Chunk Doc
-> Chunk Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Doc -> Doc -> Doc) -> Chunk Doc -> Chunk Doc -> Chunk Doc
forall a. (a -> a -> a) -> Chunk a -> Chunk a -> Chunk a
chunked Doc -> Doc -> Doc
(</>)
vcatChunks :: [Chunk Doc] -> Chunk Doc
vcatChunks :: [Chunk Doc] -> Chunk Doc
vcatChunks = (Doc -> Doc) -> Chunk Doc -> Chunk Doc
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Int -> String -> Doc -> Doc
forall a. CanAnnotate a => Int -> String -> a -> a
annTrace Int
1 String
"vcatChunks") (Chunk Doc -> Chunk Doc)
-> ([Chunk Doc] -> Chunk Doc) -> [Chunk Doc] -> Chunk Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Chunk Doc -> Chunk Doc -> Chunk Doc)
-> Chunk Doc -> [Chunk Doc] -> Chunk Doc
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr ((Doc -> Doc -> Doc) -> Chunk Doc -> Chunk Doc -> Chunk Doc
forall a. (a -> a -> a) -> Chunk a -> Chunk a -> Chunk a
chunked Doc -> Doc -> Doc
(.$.)) Chunk Doc
forall a. Monoid a => a
mempty
vsepChunks :: [Chunk Doc] -> Chunk Doc
vsepChunks :: [Chunk Doc] -> Chunk Doc
vsepChunks = Int -> String -> Chunk Doc -> Chunk Doc
forall a. CanAnnotate a => Int -> String -> a -> a
annTrace Int
1 String
"vsepChunks" (Chunk Doc -> Chunk Doc)
-> ([Chunk Doc] -> Chunk Doc) -> [Chunk Doc] -> Chunk Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Chunk Doc -> Chunk Doc -> Chunk Doc)
-> Chunk Doc -> [Chunk Doc] -> Chunk Doc
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr ((Doc -> Doc -> Doc) -> Chunk Doc -> Chunk Doc -> Chunk Doc
forall a. (a -> a -> a) -> Chunk a -> Chunk a -> Chunk a
chunked (\Doc
x Doc
y -> Doc
x Doc -> Doc -> Doc
.$. Doc
forall a. Monoid a => a
mempty Doc -> Doc -> Doc
.$. Doc
y)) Chunk Doc
forall a. Monoid a => a
mempty
isEmpty :: Chunk a -> Bool
isEmpty :: Chunk a -> Bool
isEmpty = Maybe a -> Bool
forall a. Maybe a -> Bool
isNothing (Maybe a -> Bool) -> (Chunk a -> Maybe a) -> Chunk a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Chunk a -> Maybe a
forall a. Chunk a -> Maybe a
unChunk
stringChunk :: String -> Chunk Doc
stringChunk :: String -> Chunk Doc
stringChunk String
"" = Int -> String -> Chunk Doc -> Chunk Doc
forall a. CanAnnotate a => Int -> String -> a -> a
annTrace Int
0 String
"stringChunk" Chunk Doc
forall a. Monoid a => a
mempty
stringChunk String
s = Int -> String -> Chunk Doc -> Chunk Doc
forall a. CanAnnotate a => Int -> String -> a -> a
annTrace Int
0 String
"stringChunk" (Chunk Doc -> Chunk Doc) -> Chunk Doc -> Chunk Doc
forall a b. (a -> b) -> a -> b
$ Doc -> Chunk Doc
forall (f :: * -> *) a. Applicative f => a -> f a
pure (String -> Doc
string String
s)
paragraph :: String -> Chunk Doc
paragraph :: String -> Chunk Doc
paragraph = Int -> String -> Chunk Doc -> Chunk Doc
forall a. CanAnnotate a => Int -> String -> a -> a
annTrace Int
0 String
"paragraph"
(Chunk Doc -> Chunk Doc)
-> (String -> Chunk Doc) -> String -> Chunk Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> Chunk Doc -> Chunk Doc)
-> Chunk Doc -> [String] -> Chunk Doc
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr ((Doc -> Doc -> Doc) -> Chunk Doc -> Chunk Doc -> Chunk Doc
forall a. (a -> a -> a) -> Chunk a -> Chunk a -> Chunk a
chunked Doc -> Doc -> Doc
(</>) (Chunk Doc -> Chunk Doc -> Chunk Doc)
-> (String -> Chunk Doc) -> String -> Chunk Doc -> Chunk Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Chunk Doc
stringChunk) Chunk Doc
forall a. Monoid a => a
mempty
([String] -> Chunk Doc)
-> (String -> [String]) -> String -> Chunk Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
words
tabulate :: Int -> [(Doc, Doc)] -> Chunk Doc
tabulate :: Int -> [(Doc, Doc)] -> Chunk Doc
tabulate Int
_ [] = Int -> String -> Chunk Doc -> Chunk Doc
forall a. CanAnnotate a => Int -> String -> a -> a
annTrace Int
1 String
"tabulate" Chunk Doc
forall a. Monoid a => a
mempty
tabulate Int
size [(Doc, Doc)]
table = Int -> String -> Chunk Doc -> Chunk Doc
forall a. CanAnnotate a => Int -> String -> a -> a
annTrace Int
1 String
"tabulate" (Chunk Doc -> Chunk Doc) -> (Doc -> Chunk Doc) -> Doc -> Chunk Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Doc -> Chunk Doc
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Doc -> Chunk Doc) -> Doc -> Chunk Doc
forall a b. (a -> b) -> a -> b
$ [Doc] -> Doc
forall ann. [Doc ann] -> Doc ann
vcat
[ Int -> Doc -> Doc
indent Int
2 (Int -> Doc -> Doc
forall ann. Int -> Doc ann -> Doc ann
fillBreak Int
size Doc
key Doc -> Doc -> Doc
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc
value)
| (Doc
key, Doc
value) <- [(Doc, Doc)]
table ]
chunkFlatAlt :: Chunk Doc -> Chunk Doc -> Chunk Doc
chunkFlatAlt :: Chunk Doc -> Chunk Doc -> Chunk Doc
chunkFlatAlt Chunk Doc
x Chunk Doc
y = if Doc -> Bool
isEffectivelyEmpty Doc
doc then Chunk Doc
forall a. Monoid a => a
mempty else Doc -> Chunk Doc
forall (f :: * -> *) a. Applicative f => a -> f a
pure Doc
doc
where
doc :: Doc
doc = Doc -> Doc -> Doc
forall ann. Doc ann -> Doc ann -> Doc ann
flatAlt (Chunk Doc -> Doc
forall a. Monoid a => Chunk a -> a
extractChunk Chunk Doc
x) (Chunk Doc -> Doc
forall a. Monoid a => Chunk a -> a
extractChunk Chunk Doc
y)
chunkIsEffectivelyEmpty :: Chunk Doc -> Bool
chunkIsEffectivelyEmpty :: Chunk Doc -> Bool
chunkIsEffectivelyEmpty = Bool -> (Doc -> Bool) -> Maybe Doc -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
True Doc -> Bool
isEffectivelyEmpty (Maybe Doc -> Bool)
-> (Chunk Doc -> Maybe Doc) -> Chunk Doc -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Chunk Doc -> Maybe Doc
forall a. Chunk a -> Maybe a
unChunk