ligo/tools/lsp/squirrel/src/Pretty.hs

105 lines
2.2 KiB
Haskell
Raw Normal View History

2020-05-08 01:18:26 +04:00
{-
2020-06-04 13:48:04 +04:00
Pretty printer, a small extension of GHC `pretty` package.
2020-05-08 01:18:26 +04:00
-}
module Pretty
2020-06-04 13:48:04 +04:00
( -- * Output `Text`
ppToText
-- * `Show` instance generator
2020-06-01 22:02:16 +04:00
, PP(..)
2020-06-04 13:48:04 +04:00
-- * Interfaces
2020-06-01 22:02:16 +04:00
, Pretty(..)
, Pretty1(..)
2020-06-04 13:48:04 +04:00
-- * Helpers
2020-06-01 22:02:16 +04:00
, tuple
, list
, indent
, above
, train
, block
, sepByDot
, mb
, sparseBlock
2020-06-04 13:48:04 +04:00
-- * Full might of pretty printing
, module Text.PrettyPrint
)
where
2020-05-08 22:07:53 +04:00
import qualified Data.Text as Text
2020-06-01 18:17:33 +04:00
import Data.Text (Text, pack)
import Text.PrettyPrint hiding ((<>))
2020-06-01 22:02:16 +04:00
-- | Pretty-print to `Text`. Through `String`. Yep.
2020-06-01 18:17:33 +04:00
ppToText :: Pretty a => a -> Text
ppToText = pack . show . pp
2020-05-08 01:18:26 +04:00
-- | With this, one can `data X = ...; derive Show via PP X`
newtype PP a = PP { unPP :: a }
instance Pretty a => Show (PP a) where
show = show . pp . unPP
2020-05-08 01:18:26 +04:00
-- | Pretty-printable types.
class Pretty p where
pp :: p -> Doc
2020-06-01 22:02:16 +04:00
-- | Pretty-printable `Functors`.
2020-06-01 18:17:33 +04:00
class Pretty1 p where
pp1 :: p Doc -> Doc
instance Pretty () where
pp _ = "-"
2020-06-01 18:17:33 +04:00
instance (Pretty1 p, Functor p, Pretty a) => Pretty (p a) where
pp = pp1 . fmap pp
2020-05-08 01:18:26 +04:00
-- | Common instance.
instance Pretty Text where
2020-05-08 22:07:53 +04:00
pp = text . Text.unpack
2020-06-01 18:17:33 +04:00
-- | Common instance.
instance Pretty Doc where
pp = id
2020-06-01 22:02:16 +04:00
-- | Decorate list of stuff as a tuple.
2020-05-08 22:07:53 +04:00
tuple :: Pretty p => [p] -> Doc
tuple = parens . train ","
2020-06-01 22:02:16 +04:00
-- | Decorate list of stuff as a list.
2020-05-08 22:07:53 +04:00
list :: Pretty p => [p] -> Doc
list = brackets . train ";"
infixr 2 `indent`
2020-06-01 22:02:16 +04:00
-- | First argument is a header to an indented second one.
indent :: Doc -> Doc -> Doc
2020-05-08 22:07:53 +04:00
indent a b = hang a 2 b
infixr 1 `above`
2020-06-01 22:02:16 +04:00
-- | Horisontal composition.
above :: Doc -> Doc -> Doc
2020-05-08 22:07:53 +04:00
above a b = hang a 0 b
2020-06-01 22:02:16 +04:00
-- | Pretty print as a sequence with given separator.
train :: Pretty p => Doc -> [p] -> Doc
2020-06-04 17:16:04 +04:00
train sep' = fsep . punctuate sep' . map pp
2020-05-08 22:07:53 +04:00
2020-06-01 22:02:16 +04:00
-- | Pretty print as a vertical block.
2020-05-08 22:07:53 +04:00
block :: Pretty p => [p] -> Doc
block = vcat . map pp
2020-06-01 22:02:16 +04:00
-- | For pretty-printing qualified names.
2020-05-08 22:07:53 +04:00
sepByDot :: Pretty p => [p] -> Doc
sepByDot = cat . map (("." <>) . pp)
2020-06-01 22:02:16 +04:00
-- | For pretty-printing `Maybe`s.
2020-05-08 22:07:53 +04:00
mb :: Pretty a => (Doc -> Doc) -> Maybe a -> Doc
mb f = maybe empty (f . pp)
2020-06-01 22:02:16 +04:00
-- | Pretty print as a vertical with elements separated by newline.
2020-05-08 22:07:53 +04:00
sparseBlock :: Pretty a => [a] -> Doc
sparseBlock = vcat . punctuate "\n" . map (($$ empty) . pp)