-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Execute arbitrary actions for each item from RSS/Atom feeds -- -- Cf README file @package imm @version 2.1.2.0 module Imm.Pretty -- | Newtype wrapper to prettyprint a key uniquely identifying an object newtype PrettyKey a PrettyKey :: a -> PrettyKey a -- | Newtype wrapper to prettyprint a user-friendly name referring to an -- object newtype PrettyName a PrettyName :: a -> PrettyName a -- | Newtype wrapper to prettyprint a short description of an object newtype PrettyShort a PrettyShort :: a -> PrettyShort a bold :: Doc AnsiStyle -> Doc AnsiStyle cyan :: Doc AnsiStyle -> Doc AnsiStyle green :: Doc AnsiStyle -> Doc AnsiStyle magenta :: Doc AnsiStyle -> Doc AnsiStyle red :: Doc AnsiStyle -> Doc AnsiStyle yellow :: Doc AnsiStyle -> Doc AnsiStyle -- | Infix operator for line (<++>) :: Doc a -> Doc a -> Doc a prettyKey :: Pretty (PrettyKey a) => a -> Doc b prettyName :: Pretty (PrettyName a) => a -> Doc b prettyShort :: Pretty (PrettyShort a) => a -> Doc b prettyTree :: Pretty a => Tree a -> Doc b prettyTime :: UTCTime -> Doc a prettyPerson :: AtomPerson -> Doc a prettyLink :: AtomLink -> Doc a prettyURI :: URIRef a -> Doc b prettyAtomText :: AtomText -> Doc a prettyElement :: Element -> Doc a prettyNode :: Node -> Doc a prettyContent :: Content -> Doc a prettyEntry :: AtomEntry -> Doc a prettyItem :: RssItem e -> Doc a prettyGuid :: RssGuid -> Doc a prettyAtomContent :: AtomContent -> Doc a -- | The abstract data type Doc ann represents pretty -- documents that have been annotated with data of type ann. -- -- More specifically, a value of type Doc represents a -- non-empty set of possible layouts of a document. The layout functions -- select one of these possibilities, taking into account things like the -- width of the output document. -- -- The annotation is an arbitrary piece of data associated with (part of) -- a document. Annotations may be used by the rendering backends in order -- to display output differently, such as -- --
-- >>> putStrLn (show (vsep ["hello", "world"])) -- hello -- world --data () => Doc ann -- | Options to influence the layout algorithms. newtype () => LayoutOptions LayoutOptions :: PageWidth -> LayoutOptions [layoutPageWidth] :: LayoutOptions -> PageWidth -- | Maximum number of characters that fit in one line. The layout -- algorithms will try not to exceed the set limit by inserting line -- breaks when applicable (e.g. via softline'). data () => PageWidth -- | Layouters should not exceed the specified space per line. -- --
-- >>> pretty 1 <+> pretty "hello" <+> pretty 1.234 -- 1 hello 1.234 --pretty :: Pretty a => a -> Doc ann -- | prettyList is only used to define the instance -- Pretty a => Pretty [a]. In normal circumstances -- only the pretty function is used. -- --
-- >>> prettyList [1, 23, 456] -- [1, 23, 456] --prettyList :: Pretty a => [a] -> Doc ann -- | Render the annotated document in a certain style. Styles not set in -- the annotation will use the style of the surrounding document, or the -- terminal’s default if none has been set yet. -- --
-- style = color Green <> bold -- styledDoc = annotate style "hello world" --data () => AnsiStyle -- | An associative operation. -- --
-- >>> [1,2,3] <> [4,5,6] -- [1,2,3,4,5,6] --(<>) :: Semigroup a => a -> a -> a infixr 6 <> -- |
-- >>> comma -- , --comma :: Doc ann -- |
-- >>> colon -- : --colon :: Doc ann -- |
-- >>> "a" <> space <> "b" -- a b ---- -- This is mostly used via <+>, -- --
-- >>> "a" <+> "b" -- a b --space :: Doc ann -- | (group x) tries laying out x into a single -- line by removing the contained line breaks; if this does not fit the -- page, or when a hardline within x prevents it from -- being flattened, x is laid out without any changes. -- -- The group function is key to layouts that adapt to available -- space nicely. -- -- See vcat, line, or flatAlt for examples that are -- related, or make good use of it. group :: Doc ann -> Doc ann -- | (fill i x) lays out the document x. It then -- appends spaces until the width is equal to i. If the -- width of x is already larger, nothing is appended. -- -- This function is quite useful in practice to output a list of -- bindings: -- --
-- >>> let types = [("empty","Doc"), ("nest","Int -> Doc -> Doc"), ("fillSep","[Doc] -> Doc")]
--
-- >>> let ptype (name, tp) = fill 5 (pretty name) <+> "::" <+> pretty tp
--
-- >>> "let" <+> align (vcat (map ptype types))
-- let empty :: Doc
-- nest :: Int -> Doc -> Doc
-- fillSep :: [Doc] -> Doc
--
fill :: Int -> Doc ann -> Doc ann
-- | -- >>> parens "·" -- (·) --parens :: Doc ann -> Doc ann -- | (x <+> y) concatenates document x and -- y with a space in between. -- --
-- >>> "hello" <+> "world" -- hello world ---- --
-- x <+> y = x <> space <> y --(<+>) :: Doc ann -> Doc ann -> Doc ann infixr 6 <+> -- | (align x) lays out the document x with the -- nesting level set to the current column. It is used for example to -- implement hang. -- -- As an example, we will put a document right above another one, -- regardless of the current nesting level. Without alignment, the -- second line is put simply below everything we've had so far: -- --
-- >>> "lorem" <+> vsep ["ipsum", "dolor"] -- lorem ipsum -- dolor ---- -- If we add an align to the mix, the vsep's -- contents all start in the same column: -- --
-- >>> "lorem" <+> align (vsep ["ipsum", "dolor"]) -- lorem ipsum -- dolor --align :: Doc ann -> Doc ann -- |
-- >>> pipe -- | --pipe :: Doc ann -- | (fuse depth doc) combines text nodes so they can be -- rendered more efficiently. A fused document is always laid out -- identical to its unfused version. -- -- When laying a Document out to a SimpleDocStream, every -- component of the input is translated directly to the simpler output -- format. This sometimes yields undesirable chunking when many pieces -- have been concatenated together. -- -- For example -- --
-- >>> "a" <> "b" <> pretty 'c' <> "d" -- abcd ---- -- results in a chain of four entries in a SimpleDocStream, -- although this is fully equivalent to the tightly packed -- --
-- >>> "abcd" :: Doc ann -- abcd ---- -- which is only a single SimpleDocStream entry, and can be -- processed faster. -- -- It is therefore a good idea to run fuse on concatenations of -- lots of small strings that are used many times: -- --
-- >>> let oftenUsed = fuse Shallow ("a" <> "b" <> pretty 'c' <> "d")
--
-- >>> hsep (replicate 5 oftenUsed)
-- abcd abcd abcd abcd abcd
--
fuse :: FusionDepth -> Doc ann -> Doc ann
-- | The line document advances to the next line and
-- indents to the current nesting level.
--
-- -- >>> let doc = "lorem ipsum" <> line <> "dolor sit amet" -- -- >>> doc -- lorem ipsum -- dolor sit amet ---- -- line behaves like space if the line -- break is undone by group: -- --
-- >>> group doc -- lorem ipsum dolor sit amet --line :: Doc ann -- | Add an annotation to a Doc. This annotation can then -- be used by the renderer to e.g. add color to certain parts of the -- output. For a full tutorial example on how to use it, see the -- Prettyprinter.Render.Tutorials.StackMachineTutorial or -- Prettyprinter.Render.Tutorials.TreeRenderingTutorial modules. -- -- This function is only relevant for custom formats with their own -- annotations, and not relevant for basic prettyprinting. The predefined -- renderers, e.g. Prettyprinter.Render.Text, should be enough for -- the most common needs. annotate :: ann -> Doc ann -> Doc ann -- | (enclose l r x) encloses document x between -- documents l and r using <>. -- --
-- >>> enclose "A" "Z" "·" -- A·Z ---- --
-- enclose l r x = l <> x <> r --enclose :: Doc ann -> Doc ann -> Doc ann -> Doc ann -- |
-- >>> angles "·" -- <·> --angles :: Doc ann -> Doc ann -- |
-- >>> braces "·"
-- {·}
--
braces :: Doc ann -> Doc ann
-- | -- >>> dot -- . --dot :: Doc ann -- |
-- >>> equals -- = --equals :: Doc ann -- |
-- >>> langle -- < --langle :: Doc ann -- |
-- >>> lbrace
-- {
--
lbrace :: Doc ann
-- | -- >>> lbracket -- [ --lbracket :: Doc ann -- |
-- >>> lparen -- ( --lparen :: Doc ann -- |
-- >>> rangle -- > --rangle :: Doc ann -- |
-- >>> rbrace -- } --rbrace :: Doc ann -- |
-- >>> rbracket -- ] --rbracket :: Doc ann -- |
-- >>> rparen -- ) --rparen :: Doc ann -- | Layout a document depending on which column it starts at. align -- is implemented in terms of column. -- --
-- >>> column (\l -> "Columns are" <+> pretty l <> "-based.") -- Columns are 0-based. ---- --
-- >>> let doc = "prefix" <+> column (\l -> "| <- column" <+> pretty l) -- -- >>> vsep [indent n doc | n <- [0,4,8]] -- prefix | <- column 7 -- prefix | <- column 11 -- prefix | <- column 15 --column :: (Int -> Doc ann) -> Doc ann -- | Convenience function to convert a Showable value to a -- Doc. If the String does not contain newlines, consider -- using the more performant unsafeViaShow. viaShow :: Show a => a -> Doc ann -- | Convenience function to convert a Showable value /that must not -- contain newlines/ to a Doc. If there may be newlines, use -- viaShow instead. unsafeViaShow :: Show a => a -> Doc ann -- | The empty document behaves like (pretty ""), so it has -- a height of 1. This may lead to surprising behaviour if we expect it -- to bear no weight inside e.g. vcat, where we get an empty line -- of output from it (parens for visibility only): -- --
-- >>> vsep ["hello", parens emptyDoc, "world"] -- hello -- () -- world ---- -- Together with <>, emptyDoc forms the Monoid -- Doc. emptyDoc :: Doc ann -- | (nest i x) lays out the document x with the -- current nesting level (indentation of the following lines) increased -- by i. Negative values are allowed, and decrease the nesting -- level accordingly. -- --
-- >>> vsep [nest 4 (vsep ["lorem", "ipsum", "dolor"]), "sit", "amet"] -- lorem -- ipsum -- dolor -- sit -- amet ---- -- See also -- --
-- >>> let doc = "lorem ipsum" <> line' <> "dolor sit amet" -- -- >>> doc -- lorem ipsum -- dolor sit amet -- -- >>> group doc -- lorem ipsumdolor sit amet --line' :: Doc ann -- | softline behaves like space if the -- resulting output fits the page, otherwise like line. -- -- Here, we have enough space to put everything in one line: -- --
-- >>> let doc = "lorem ipsum" <> softline <> "dolor sit amet" -- -- >>> putDocW 80 doc -- lorem ipsum dolor sit amet ---- -- If we narrow the page to width 10, the layouter produces a line break: -- --
-- >>> putDocW 10 doc -- lorem ipsum -- dolor sit amet ---- --
-- softline = group line --softline :: Doc ann -- | softline' is like softline, but -- behaves like mempty if the resulting output does not -- fit on the page (instead of space). In other words, -- line is to line' how -- softline is to softline'. -- -- With enough space, we get direct concatenation: -- --
-- >>> let doc = "ThisWord" <> softline' <> "IsWayTooLong" -- -- >>> putDocW 80 doc -- ThisWordIsWayTooLong ---- -- If we narrow the page to width 10, the layouter produces a line break: -- --
-- >>> putDocW 10 doc -- ThisWord -- IsWayTooLong ---- --
-- softline' = group line' --softline' :: Doc ann -- | A hardline is always laid out as a line break, -- even when grouped or when there is plenty of space. Note that -- it might still be simply discarded if it is part of a flatAlt -- inside a group. -- --
-- >>> let doc = "lorem ipsum" <> hardline <> "dolor sit amet" -- -- >>> putDocW 1000 doc -- lorem ipsum -- dolor sit amet ---- --
-- >>> group doc -- lorem ipsum -- dolor sit amet --hardline :: Doc ann -- | By default, (flatAlt x y) renders as x. -- However when grouped, y will be preferred, with -- x as the fallback for the case when y doesn't fit. -- --
-- >>> let doc = flatAlt "a" "b" -- -- >>> putDoc doc -- a -- -- >>> putDoc (group doc) -- b -- -- >>> putDocW 0 (group doc) -- a ---- -- flatAlt is particularly useful for defining conditional -- separators such as -- --
-- softline = group (flatAlt hardline " ") ---- --
-- >>> let hello = "Hello" <> softline <> "world!" -- -- >>> putDocW 12 hello -- Hello world! -- -- >>> putDocW 11 hello -- Hello -- world! ---- --
-- >>> let open = flatAlt "" "{ "
--
-- >>> let close = flatAlt "" " }"
--
-- >>> let separator = flatAlt "" "; "
--
-- >>> let prettyDo xs = group ("do" <+> align (encloseSep open close separator xs))
--
-- >>> let statements = ["name:_ <- getArgs", "let greet = \"Hello, \" <> name", "putStrLn greet"]
--
--
-- This is put into a single line with {;} style if it fits:
--
--
-- >>> putDocW 80 (prettyDo statements)
-- do { name:_ <- getArgs; let greet = "Hello, " <> name; putStrLn greet }
--
--
-- When there is not enough space the statements are broken up into lines
-- nicely:
--
-- -- >>> putDocW 10 (prettyDo statements) -- do name:_ <- getArgs -- let greet = "Hello, " <> name -- putStrLn greet ---- --
-- >>> let ugly = group (flatAlt "even wider" "too wide") -- -- >>> putDocW 7 ugly -- even wider ---- -- Also note that group will flatten y: -- --
-- >>> putDoc (group (flatAlt "x" ("y" <> line <> "y")))
-- y y
--
--
-- This also means that an "unflattenable" y which contains a
-- hard linebreak will never be rendered:
--
--
-- >>> putDoc (group (flatAlt "x" ("y" <> hardline <> "y")))
-- x
--
flatAlt :: Doc ann -> Doc ann -> Doc ann
-- | (hang i x) lays out the document x with a
-- nesting level set to the current column plus i.
-- Negative values are allowed, and decrease the nesting level
-- accordingly.
--
--
-- >>> let doc = reflow "Indenting these words with hang"
--
-- >>> putDocW 24 ("prefix" <+> hang 4 doc)
-- prefix Indenting these
-- words with
-- hang
--
--
-- This differs from nest, which is based on the current
-- nesting level plus i. When you're not sure, try the more
-- efficient nest first. In our example, this would yield
--
--
-- >>> let doc = reflow "Indenting these words with nest"
--
-- >>> putDocW 24 ("prefix" <+> nest 4 doc)
-- prefix Indenting these
-- words with nest
--
--
-- -- hang i doc = align (nest i doc) --hang :: Int -> Doc ann -> Doc ann -- | (indent i x) indents document x by i -- columns, starting from the current cursor position. -- --
-- >>> let doc = reflow "The indent function indents these words!"
--
-- >>> putDocW 24 ("prefix" <> indent 4 doc)
-- prefix The indent
-- function
-- indents these
-- words!
--
--
--
-- indent i d = hang i ({i spaces} <> d)
--
indent :: Int -> Doc ann -> Doc ann
-- | (encloseSep l r sep xs) concatenates the documents
-- xs separated by sep, and encloses the resulting
-- document by l and r.
--
-- The documents are laid out horizontally if that fits the page:
--
-- -- >>> let doc = "list" <+> align (encloseSep lbracket rbracket comma (map pretty [1,20,300,4000])) -- -- >>> putDocW 80 doc -- list [1,20,300,4000] ---- -- If there is not enough space, then the input is split into lines -- entry-wise therwise they are laid out vertically, with separators put -- in the front: -- --
-- >>> putDocW 10 doc -- list [1 -- ,20 -- ,300 -- ,4000] ---- -- Note that doc contains an explicit call to align so -- that the list items are aligned vertically. -- -- For putting separators at the end of entries instead, have a look at -- punctuate. encloseSep :: Doc ann -> Doc ann -> Doc ann -> [Doc ann] -> Doc ann -- | Haskell-inspired variant of encloseSep with parentheses and -- comma as separator. -- --
-- >>> let doc = tupled (map pretty [1,20,300,4000]) ---- --
-- >>> putDocW 80 doc -- (1, 20, 300, 4000) ---- --
-- >>> putDocW 10 doc -- ( 1 -- , 20 -- , 300 -- , 4000 ) --tupled :: [Doc ann] -> Doc ann -- | Concatenate all documents element-wise with a binary function. -- --
-- concatWith _ [] = mempty -- concatWith (**) [x,y,z] = x ** y ** z ---- -- Multiple convenience definitions based on concatWith are -- already predefined, for example: -- --
-- hsep = concatWith (<+>) -- fillSep = concatWith (\x y -> x <> softline <> y) ---- -- This is also useful to define customized joiners: -- --
-- >>> concatWith (surround dot) ["Prettyprinter", "Render", "Text"] -- Prettyprinter.Render.Text --concatWith :: Foldable t => (Doc ann -> Doc ann -> Doc ann) -> t (Doc ann) -> Doc ann -- | (hsep xs) concatenates all documents xs -- horizontally with <+>, i.e. it puts a space -- between all entries. -- --
-- >>> let docs = Util.words "lorem ipsum dolor sit amet" ---- --
-- >>> hsep docs -- lorem ipsum dolor sit amet ---- -- hsep does not introduce line breaks on its own, even -- when the page is too narrow: -- --
-- >>> putDocW 5 (hsep docs) -- lorem ipsum dolor sit amet ---- -- For automatic line breaks, consider using fillSep instead. hsep :: [Doc ann] -> Doc ann -- | (vsep xs) concatenates all documents xs above -- each other. If a group undoes the line breaks inserted by -- vsep, the documents are separated with a space -- instead. -- -- Using vsep alone yields -- --
-- >>> "prefix" <+> vsep ["text", "to", "lay", "out"] -- prefix text -- to -- lay -- out ---- -- grouping a vsep separates the documents with a -- space if it fits the page (and does nothing otherwise). See -- the sep convenience function for this use case. -- -- The align function can be used to align the documents under -- their first element: -- --
-- >>> "prefix" <+> align (vsep ["text", "to", "lay", "out"]) -- prefix text -- to -- lay -- out ---- -- Since grouping a vsep is rather common, sep is a -- built-in for doing that. vsep :: [Doc ann] -> Doc ann -- | (fillSep xs) concatenates the documents xs -- horizontally with <+> as long as it fits the -- page, then inserts a line and continues doing that for -- all documents in xs. (line means that if -- grouped, the documents are separated with a space -- instead of newlines. Use fillCat if you do not want a -- space.) -- -- Let's print some words to fill the line: -- --
-- >>> let docs = take 20 (cycle ["lorem", "ipsum", "dolor", "sit", "amet"])
--
-- >>> putDocW 80 ("Docs:" <+> fillSep docs)
-- Docs: lorem ipsum dolor sit amet lorem ipsum dolor sit amet lorem ipsum dolor
-- sit amet lorem ipsum dolor sit amet
--
--
-- The same document, printed at a width of only 40, yields
--
--
-- >>> putDocW 40 ("Docs:" <+> fillSep docs)
-- Docs: lorem ipsum dolor sit amet lorem
-- ipsum dolor sit amet lorem ipsum dolor
-- sit amet lorem ipsum dolor sit amet
--
fillSep :: [Doc ann] -> Doc ann
-- | (sep xs) tries laying out the documents xs
-- separated with spaces, and if this does not fit the page,
-- separates them with newlines. This is what differentiates it from
-- vsep, which always lays out its contents beneath each other.
--
-- -- >>> let doc = "prefix" <+> sep ["text", "to", "lay", "out"] -- -- >>> putDocW 80 doc -- prefix text to lay out ---- -- With a narrower layout, the entries are separated by newlines: -- --
-- >>> putDocW 20 doc -- prefix text -- to -- lay -- out ---- --
-- sep = group . vsep --sep :: [Doc ann] -> Doc ann -- | (hcat xs) concatenates all documents xs -- horizontally with <> (i.e. without any spacing). -- -- It is provided only for consistency, since it is identical to -- mconcat. -- --
-- >>> let docs = Util.words "lorem ipsum dolor" -- -- >>> hcat docs -- loremipsumdolor --hcat :: [Doc ann] -> Doc ann -- | (vcat xs) vertically concatenates the documents -- xs. If it is grouped, the line breaks are removed. -- -- In other words vcat is like vsep, with -- newlines removed instead of replaced by spaces. -- --
-- >>> let docs = Util.words "lorem ipsum dolor" -- -- >>> vcat docs -- lorem -- ipsum -- dolor -- -- >>> group (vcat docs) -- loremipsumdolor ---- -- Since grouping a vcat is rather common, cat is a -- built-in shortcut for it. vcat :: [Doc ann] -> Doc ann -- | (fillCat xs) concatenates documents xs -- horizontally with <> as long as it fits the -- page, then inserts a line' and continues doing that -- for all documents in xs. This is similar to how an ordinary -- word processor lays out the text if you just keep typing after you hit -- the maximum line length. -- -- (line' means that if grouped, the documents are -- separated with nothing instead of newlines. See fillSep if you -- want a space instead.) -- -- Observe the difference between fillSep and fillCat. -- fillSep concatenates the entries spaced when -- grouped: -- --
-- >>> let docs = take 20 (cycle (["lorem", "ipsum", "dolor", "sit", "amet"]))
--
-- >>> putDocW 40 ("Grouped:" <+> group (fillSep docs))
-- Grouped: lorem ipsum dolor sit amet
-- lorem ipsum dolor sit amet lorem ipsum
-- dolor sit amet lorem ipsum dolor sit
-- amet
--
--
-- On the other hand, fillCat concatenates the entries directly
-- when grouped:
--
--
-- >>> putDocW 40 ("Grouped:" <+> group (fillCat docs))
-- Grouped: loremipsumdolorsitametlorem
-- ipsumdolorsitametloremipsumdolorsitamet
-- loremipsumdolorsitamet
--
fillCat :: [Doc ann] -> Doc ann
-- | (cat xs) tries laying out the documents xs
-- separated with nothing, and if this does not fit the page, separates
-- them with newlines. This is what differentiates it from vcat,
-- which always lays out its contents beneath each other.
--
--
-- >>> let docs = Util.words "lorem ipsum dolor"
--
-- >>> putDocW 80 ("Docs:" <+> cat docs)
-- Docs: loremipsumdolor
--
--
-- When there is enough space, the documents are put above one another:
--
--
-- >>> putDocW 10 ("Docs:" <+> cat docs)
-- Docs: lorem
-- ipsum
-- dolor
--
--
-- -- cat = group . vcat --cat :: [Doc ann] -> Doc ann -- | (punctuate p xs) appends p to all but the -- last document in xs. -- --
-- >>> let docs = punctuate comma (Util.words "lorem ipsum dolor sit amet") -- -- >>> putDocW 80 (hsep docs) -- lorem, ipsum, dolor, sit, amet ---- -- The separators are put at the end of the entries, which we can see if -- we position the result vertically: -- --
-- >>> putDocW 20 (vsep docs) -- lorem, -- ipsum, -- dolor, -- sit, -- amet ---- -- If you want put the commas in front of their elements instead of at -- the end, you should use tupled or, in general, -- encloseSep. punctuate :: Doc ann -> [Doc ann] -> [Doc ann] -- | Layout a document depending on the current nesting level. -- align is implemented in terms of nesting. -- --
-- >>> let doc = "prefix" <+> nesting (\l -> brackets ("Nested:" <+> pretty l))
--
-- >>> vsep [indent n doc | n <- [0,4,8]]
-- prefix [Nested: 0]
-- prefix [Nested: 4]
-- prefix [Nested: 8]
--
nesting :: (Int -> Doc ann) -> Doc ann
-- | Layout a document depending on the page width, if one has been
-- specified.
--
-- -- >>> let prettyPageWidth (AvailablePerLine l r) = "Width:" <+> pretty l <> ", ribbon fraction:" <+> pretty r -- -- >>> let doc = "prefix" <+> pageWidth (brackets . prettyPageWidth) -- -- >>> putDocW 32 (vsep [indent n doc | n <- [0,4,8]]) -- prefix [Width: 32, ribbon fraction: 1.0] -- prefix [Width: 32, ribbon fraction: 1.0] -- prefix [Width: 32, ribbon fraction: 1.0] --pageWidth :: (PageWidth -> Doc ann) -> Doc ann -- | (fillBreak i x) first lays out the document -- x. It then appends spaces until the width is equal -- to i. If the width of x is already larger than -- i, the nesting level is increased by i and a -- line is appended. When we redefine ptype in the -- example given in fill to use fillBreak, we get -- a useful variation of the output: -- --
-- >>> let types = [("empty","Doc"), ("nest","Int -> Doc -> Doc"), ("fillSep","[Doc] -> Doc")]
--
-- >>> let ptype (name, tp) = fillBreak 5 (pretty name) <+> "::" <+> pretty tp
--
-- >>> "let" <+> align (vcat (map ptype types))
-- let empty :: Doc
-- nest :: Int -> Doc -> Doc
-- fillSep
-- :: [Doc] -> Doc
--
fillBreak :: Int -> Doc ann -> Doc ann
-- | (plural n one many) is one if n is
-- 1, and many otherwise. A typical use case is adding
-- a plural "s".
--
-- -- >>> let things = [True] -- -- >>> let amount = length things -- -- >>> pretty things <+> "has" <+> pretty amount <+> plural "entry" "entries" amount -- [True] has 1 entry --plural :: (Num amount, Eq amount) => doc -> doc -> amount -> doc -- | (surround x l r) surrounds document x with -- l and r. -- --
-- >>> surround "·" "A" "Z" -- A·Z ---- -- This is merely an argument reordering of enclose, but -- allows for definitions like -- --
-- >>> concatWith (surround dot) ["Prettyprinter", "Render", "Text"] -- Prettyprinter.Render.Text --surround :: Doc ann -> Doc ann -> Doc ann -> Doc ann -- | Remove all annotations. -- -- Although unAnnotate is idempotent with respect to rendering, -- --
-- unAnnotate . unAnnotate = unAnnotate ---- -- it should not be used without caution, for each invocation traverses -- the entire contained document. If possible, it is preferrable to -- unannotate after producing the layout by using unAnnotateS. unAnnotate :: Doc ann -> Doc xxx -- | Change the annotation of a Document. -- -- Useful in particular to embed documents with one form of annotation in -- a more generally annotated document. -- -- Since this traverses the entire Doc tree, including -- parts that are not rendered due to other layouts fitting better, it is -- preferrable to reannotate after producing the layout by using -- reAnnotateS. -- -- Since reAnnotate has the right type and satisfies -- 'reAnnotate id = id', it is used to define the -- Functor instance of Doc. reAnnotate :: (ann -> ann') -> Doc ann -> Doc ann' -- | Change the annotations of a Document. Individual annotations -- can be removed, changed, or replaced by multiple ones. -- -- This is a general function that combines unAnnotate and -- reAnnotate, and it is useful for mapping semantic annotations -- (such as »this is a keyword«) to display annotations (such as »this is -- red and underlined«), because some backends may not care about certain -- annotations, while others may. -- -- Annotations earlier in the new list will be applied earlier, i.e. -- returning [Bold, Green] will result in a bold document that -- contains green text, and not vice-versa. -- -- Since this traverses the entire Doc tree, including -- parts that are not rendered due to other layouts fitting better, it is -- preferrable to reannotate after producing the layout by using -- alterAnnotationsS. alterAnnotations :: (ann -> [ann']) -> Doc ann -> Doc ann' -- | Remove all annotations. unAnnotate for SimpleDocStream. unAnnotateS :: SimpleDocStream ann -> SimpleDocStream xxx -- | Change the annotation of a document. reAnnotate for -- SimpleDocStream. reAnnotateS :: (ann -> ann') -> SimpleDocStream ann -> SimpleDocStream ann' -- | Change the annotation of a document to a different annotation, or none -- at all. alterAnnotations for SimpleDocStream. -- -- Note that the Doc version is more flexible, since it allows -- changing a single annotation to multiple ones. (SimpleDocTree -- restores this flexibility again.) alterAnnotationsS :: (ann -> Maybe ann') -> SimpleDocStream ann -> SimpleDocStream ann' -- | Remove all trailing space characters. -- -- This has some performance impact, because it does an entire additional -- pass over the SimpleDocStream. -- -- No trimming will be done inside annotations, which are considered to -- contain no (trimmable) whitespace, since the annotation might actually -- be about the whitespace, for example a renderer that colors the -- background of trailing whitespace, as e.g. git diff can be -- configured to do. -- -- Historical note: Since v1.7.0, layoutPretty and -- layoutSmart avoid producing the trailing whitespace that was -- the original motivation for creating removeTrailingWhitespace. -- See https://github.com/quchen/prettyprinter/pull/139 for some -- background info. removeTrailingWhitespace :: SimpleDocStream ann -> SimpleDocStream ann -- | The default layout options, suitable when you just want some output, -- and don’t particularly care about the details. Used by the Show -- instance, for example. -- --
-- >>> defaultLayoutOptions
-- LayoutOptions {layoutPageWidth = AvailablePerLine 80 1.0}
--
defaultLayoutOptions :: LayoutOptions
-- | This is the default layout algorithm, and it is used by show,
-- putDoc and hPutDoc.
--
-- layoutPretty commits to rendering something in a
-- certain way if the next element fits the layout constraints; in other
-- words, it has one SimpleDocStream element lookahead when
-- rendering. Consider using the smarter, but a bit less performant,
-- layoutSmart algorithm if the results seem to run off
-- to the right before having lots of line breaks.
layoutPretty :: LayoutOptions -> Doc ann -> SimpleDocStream ann
-- | A layout algorithm with more lookahead than layoutPretty, that
-- introduces line breaks earlier if the content does not (or will not,
-- rather) fit into one line.
--
-- Consider the following python-ish document,
--
--
-- >>> let fun x = hang 2 ("fun(" <> softline' <> x) <> ")"
--
-- >>> let doc = (fun . fun . fun . fun . fun) (align (list ["abcdef", "ghijklm"]))
--
--
-- which we’ll be rendering using the following pipeline (where the
-- layout algorithm has been left open):
--
-- -- >>> import Data.Text.IO as T -- -- >>> import Prettyprinter.Render.Text -- -- >>> let hr = pipe <> pretty (replicate (26-2) '-') <> pipe -- -- >>> let go layouter x = (T.putStrLn . renderStrict . layouter (LayoutOptions (AvailablePerLine 26 1))) (vsep [hr, x, hr]) ---- -- If we render this using layoutPretty with a page width of 26 -- characters per line, all the fun calls fit into the first -- line so they will be put there: -- --
-- >>> go layoutPretty doc -- |------------------------| -- fun(fun(fun(fun(fun( -- [ abcdef -- , ghijklm ]))))) -- |------------------------| ---- -- Note that this exceeds the desired 26 character page width. The same -- document, rendered with layoutSmart, fits the layout -- contstraints: -- --
-- >>> go layoutSmart doc -- |------------------------| -- fun( -- fun( -- fun( -- fun( -- fun( -- [ abcdef -- , ghijklm ]))))) -- |------------------------| ---- -- The key difference between layoutPretty and layoutSmart -- is that the latter will check the potential document until it -- encounters a line with the same indentation or less than the start of -- the document. Any line encountered earlier is assumed to belong to the -- same syntactic structure. layoutPretty checks only the first -- line. -- -- Consider for example the question of whether the As fit into -- the document below: -- --
-- 1 A -- 2 A -- 3 A -- 4 B -- 5 B ---- -- layoutPretty will check only line 1, ignoring whether e.g. line -- 2 might already be too wide. By contrast, layoutSmart stops -- only once it reaches line 4, where the B has the same -- indentation as the first A. layoutSmart :: LayoutOptions -> Doc ann -> SimpleDocStream ann -- | (layoutCompact x) lays out the document x without -- adding any indentation and without preserving annotations. Since no -- 'pretty' printing is involved, this layouter is very fast. The -- resulting output contains fewer characters than a prettyprinted -- version and can be used for output that is read by other programs. -- --
-- >>> let doc = hang 4 (vsep ["lorem", "ipsum", hang 4 (vsep ["dolor", "sit"])]) -- -- >>> doc -- lorem -- ipsum -- dolor -- sit ---- --
-- >>> let putDocCompact = renderIO System.IO.stdout . layoutCompact -- -- >>> putDocCompact doc -- lorem -- ipsum -- dolor -- sit --layoutCompact :: Doc ann1 -> SimpleDocStream ann2 -- |
-- >>> squotes "·" -- '·' --squotes :: Doc ann -> Doc ann -- |
-- >>> dquotes "·" -- "·" --dquotes :: Doc ann -> Doc ann -- |
-- >>> brackets "·" -- [·] --brackets :: Doc ann -> Doc ann -- |
-- >>> squote -- ' --squote :: Doc ann -- |
-- >>> dquote -- " --dquote :: Doc ann -- |
-- >>> semi -- ; --semi :: Doc ann -- |
-- >>> slash -- / --slash :: Doc ann -- |
-- >>> backslash -- \ --backslash :: Doc ann -- | Logger module abstracts over logging data. -- -- This module follows the Handle pattern. -- --
-- import qualified Imm.Logger as Logger (Handle) -- import Imm.Logger hiding (Handle) --module Imm.Logger data Handle m Handle :: (LogLevel -> Doc AnsiStyle -> m ()) -> m LogLevel -> (LogLevel -> m ()) -> Handle m [log] :: Handle m -> LogLevel -> Doc AnsiStyle -> m () [getLogLevel] :: Handle m -> m LogLevel [setLogLevel] :: Handle m -> LogLevel -> m () data LogLevel Debug :: LogLevel Info :: LogLevel Warning :: LogLevel Error :: LogLevel instance GHC.Show.Show Imm.Logger.LogLevel instance GHC.Read.Read Imm.Logger.LogLevel instance GHC.Classes.Ord Imm.Logger.LogLevel instance GHC.Classes.Eq Imm.Logger.LogLevel instance Prettyprinter.Internal.Pretty Imm.Logger.LogLevel -- | HTTP module abstracts over HTTP requests to the external world. -- -- This module follows the Handle pattern. -- --
-- import qualified Imm.HTTP as HTTP --module Imm.HTTP -- | Handle to perform GET HTTP requests. newtype Handle m Handle :: (forall a. URI -> (Response (Producer ByteString m ()) -> m a) -> m a) -> Handle m [_withGet] :: Handle m -> forall a. URI -> (Response (Producer ByteString m ()) -> m a) -> m a -- | Simple wrapper around _withGet that also logs the requested -- URI. withGet :: Monad m => Handle m -> Handle m -> URI -> (Response (Producer ByteString m ()) -> m a) -> m a module URI.ByteString.Extended data AnyURI AnyURI :: URIRef a -> AnyURI sameURIType :: URIRef a1 -> URIRef a2 -> Maybe (URIRef a1 :~: URIRef a2) withAnyURI :: (forall a. URIRef a -> b) -> AnyURI -> b toAbsoluteURI :: Scheme -> AnyURI -> URI instance GHC.Show.Show URI.ByteString.Extended.AnyURI instance GHC.Classes.Eq URI.ByteString.Extended.AnyURI instance GHC.Classes.Ord URI.ByteString.Extended.AnyURI instance Prettyprinter.Internal.Pretty URI.ByteString.Extended.AnyURI instance Data.Aeson.Types.ToJSON.ToJSON URI.ByteString.Extended.AnyURI instance Data.Aeson.Types.FromJSON.FromJSON URI.ByteString.Extended.AnyURI -- | Simplified model for RFC 8288 links. -- -- Cf https://tools.ietf.org/html/rfc8288 . . module Imm.Link data Link Link :: Maybe Relation -> Text -> Maybe MediaType -> AnyURI -> Link [_linkRelation] :: Link -> Maybe Relation [_linkTitle] :: Link -> Text [_linkType] :: Link -> Maybe MediaType [_linkURI] :: Link -> AnyURI -- | Cf -- https://www.iana.org/assignments/link-relations/link-relations.xhtml -- . data Relation Alternate :: Relation Edit :: Relation Next :: Relation NoFollow :: Relation Replies :: Relation Self :: Relation OtherRelation :: Text -> Relation parseRelation :: Text -> Maybe Relation -- | https://tools.ietf.org/html/rfc6838 -- https://en.wikipedia.org/wiki/Media_type data MediaType MediaType :: Text -> Text -> Text -> [Text] -> MediaType [_mediaType] :: MediaType -> Text [_mediaSubtype] :: MediaType -> Text [_mediaSuffix] :: MediaType -> Text [_mediaParameters] :: MediaType -> [Text] parseMediaType :: Stream s Identity Char => s -> Maybe MediaType pattern MediaTypeRSS :: [Text] -> MediaType pattern MediaTypeAtom :: [Text] -> MediaType pattern MediaTypeApplicationXML :: Text -> [Text] -> MediaType pattern MediaTypeTextXML :: Text -> [Text] -> MediaType pattern MediaTypeHTML :: Text -> [Text] -> MediaType instance GHC.Show.Show Imm.Link.Relation instance GHC.Read.Read Imm.Link.Relation instance GHC.Classes.Ord Imm.Link.Relation instance GHC.Generics.Generic Imm.Link.Relation instance GHC.Classes.Eq Imm.Link.Relation instance GHC.Show.Show Imm.Link.MediaType instance GHC.Read.Read Imm.Link.MediaType instance GHC.Classes.Ord Imm.Link.MediaType instance GHC.Generics.Generic Imm.Link.MediaType instance GHC.Classes.Eq Imm.Link.MediaType instance GHC.Show.Show Imm.Link.Link instance GHC.Classes.Ord Imm.Link.Link instance GHC.Generics.Generic Imm.Link.Link instance GHC.Classes.Eq Imm.Link.Link instance Data.Aeson.Types.ToJSON.ToJSON Imm.Link.Link instance Data.Aeson.Types.FromJSON.FromJSON Imm.Link.Link instance Data.Aeson.Types.ToJSON.ToJSON Imm.Link.MediaType instance Data.Aeson.Types.FromJSON.FromJSON Imm.Link.MediaType instance Data.Aeson.Types.ToJSON.ToJSON Imm.Link.Relation instance Data.Aeson.Types.FromJSON.FromJSON Imm.Link.Relation -- | Feed data structures. module Imm.Feed -- | Feed location identifies a feed. It is either: - the feed URI - a -- webpage URI that refers to the feed through an alternate link, in -- which case an optional feed title can be provided to disambiguate -- multiple such links data FeedLocation FeedLocation :: URI -> Text -> FeedLocation -- | Database identifier for a feed type UID = Int -- | A query describes a set of feeds through some criteria. data FeedQuery QueryByUID :: UID -> FeedQuery QueryAll :: FeedQuery newtype FeedDefinition FeedDefinition :: Text -> FeedDefinition [_feedTitle] :: FeedDefinition -> Text data FeedItem FeedItem :: Maybe UTCTime -> Text -> Text -> [Link] -> Text -> [Author] -> FeedItem [_itemDate] :: FeedItem -> Maybe UTCTime [_itemTitle] :: FeedItem -> Text [_itemContent] :: FeedItem -> Text [_itemLinks] :: FeedItem -> [Link] [_itemIdentifier] :: FeedItem -> Text [_itemAuthors] :: FeedItem -> [Author] data Author Author :: Text -> Text -> Maybe AnyURI -> Author [_authorName] :: Author -> Text [_authorEmail] :: Author -> Text [_authorURI] :: Author -> Maybe AnyURI parseFeed :: MonadCatch m => Text -> m (FeedDefinition, [FeedItem]) -- | Conduit version of parseFeed feedC :: MonadCatch m => ConduitT Event o m (Maybe (FeedDefinition, [FeedItem])) parseFeedItem :: MonadCatch m => Text -> m FeedItem getMainLink :: FeedItem -> Maybe Link areSameItem :: FeedItem -> FeedItem -> Bool instance GHC.Show.Show Imm.Feed.FeedLocation instance GHC.Classes.Ord Imm.Feed.FeedLocation instance GHC.Generics.Generic Imm.Feed.FeedLocation instance GHC.Classes.Eq Imm.Feed.FeedLocation instance GHC.Show.Show Imm.Feed.FeedQuery instance GHC.Read.Read Imm.Feed.FeedQuery instance GHC.Classes.Ord Imm.Feed.FeedQuery instance GHC.Classes.Eq Imm.Feed.FeedQuery instance GHC.Show.Show Imm.Feed.FeedDefinition instance GHC.Read.Read Imm.Feed.FeedDefinition instance GHC.Classes.Ord Imm.Feed.FeedDefinition instance GHC.Generics.Generic Imm.Feed.FeedDefinition instance GHC.Classes.Eq Imm.Feed.FeedDefinition instance GHC.Show.Show Imm.Feed.Author instance GHC.Classes.Ord Imm.Feed.Author instance GHC.Generics.Generic Imm.Feed.Author instance GHC.Classes.Eq Imm.Feed.Author instance GHC.Show.Show Imm.Feed.FeedItem instance GHC.Classes.Ord Imm.Feed.FeedItem instance GHC.Generics.Generic Imm.Feed.FeedItem instance GHC.Classes.Eq Imm.Feed.FeedItem instance Data.Aeson.Types.ToJSON.ToJSON Imm.Feed.FeedItem instance Data.Aeson.Types.FromJSON.FromJSON Imm.Feed.FeedItem instance Prettyprinter.Internal.Pretty (Imm.Pretty.PrettyName Imm.Feed.FeedItem) instance Prettyprinter.Internal.Pretty Imm.Feed.FeedItem instance Data.Aeson.Types.ToJSON.ToJSON Imm.Feed.Author instance Data.Aeson.Types.FromJSON.FromJSON Imm.Feed.Author instance Prettyprinter.Internal.Pretty Imm.Feed.Author instance Data.Aeson.Types.ToJSON.ToJSON Imm.Feed.FeedDefinition instance Data.Aeson.Types.FromJSON.FromJSON Imm.Feed.FeedDefinition instance Prettyprinter.Internal.Pretty Imm.Feed.FeedDefinition instance Prettyprinter.Internal.Pretty (Imm.Pretty.PrettyName Imm.Feed.FeedDefinition) instance Prettyprinter.Internal.Pretty Imm.Feed.FeedQuery instance Prettyprinter.Internal.Pretty Imm.Feed.FeedLocation instance Data.Aeson.Types.ToJSON.ToJSON Imm.Feed.FeedLocation instance Data.Aeson.Types.FromJSON.FromJSON Imm.Feed.FeedLocation -- | XML module abstracts over the parsing of RSS/Atom feeds. -- -- This module follows the Handle pattern. -- --
-- import qualified Imm.XML as XML --module Imm.XML newtype Handle m Handle :: (URI -> LByteString -> m (FeedDefinition, [FeedItem])) -> Handle m [parseXml] :: Handle m -> URI -> LByteString -> m (FeedDefinition, [FeedItem]) module Imm.Callback -- | External program run for each feed element. -- -- Data is passed to that program through standard input -- (stdin). data Callback Callback :: FilePath -> [Text] -> Callback [_executable] :: Callback -> FilePath [_arguments] :: Callback -> [Text] -- | Data structure passed to the external program, through JSON format. -- -- The data schema is described in file schema/imm.json, -- provided with this library. data CallbackMessage CallbackMessage :: FeedLocation -> FeedDefinition -> FeedItem -> CallbackMessage [_callbackFeedLocation] :: CallbackMessage -> FeedLocation [_callbackFeedDefinition] :: CallbackMessage -> FeedDefinition [_callbackFeedItem] :: CallbackMessage -> FeedItem runCallback :: MonadIO m => Handle m -> Callback -> CallbackMessage -> m (Either (Callback, Int, LByteString, LByteString) (Callback, LByteString, LByteString)) instance GHC.Show.Show Imm.Callback.Callback instance GHC.Read.Read Imm.Callback.Callback instance GHC.Classes.Ord Imm.Callback.Callback instance GHC.Generics.Generic Imm.Callback.Callback instance GHC.Classes.Eq Imm.Callback.Callback instance GHC.Show.Show Imm.Callback.CallbackMessage instance GHC.Classes.Ord Imm.Callback.CallbackMessage instance GHC.Generics.Generic Imm.Callback.CallbackMessage instance GHC.Classes.Eq Imm.Callback.CallbackMessage instance Data.Aeson.Types.ToJSON.ToJSON Imm.Callback.CallbackMessage instance Data.Aeson.Types.FromJSON.FromJSON Imm.Callback.CallbackMessage instance Prettyprinter.Internal.Pretty (Imm.Pretty.PrettyShort Imm.Callback.CallbackMessage) instance Dhall.Marshal.Decode.FromDhall Imm.Callback.Callback instance Prettyprinter.Internal.Pretty Imm.Callback.Callback -- | Meta-module that reexports many Imm sub-modules. module Imm -- | External program run for each feed element. -- -- Data is passed to that program through standard input -- (stdin). data Callback Callback :: FilePath -> [Text] -> Callback [_executable] :: Callback -> FilePath [_arguments] :: Callback -> [Text] -- | Define a HTTP proxy, consisting of a hostname and port number. data () => Proxy Proxy :: ByteString -> Int -> Proxy -- | The host name of the HTTP proxy in URI format. IPv6 addresses in -- square brackets. [proxyHost] :: Proxy -> ByteString -- | The port number of the HTTP proxy. [proxyPort] :: Proxy -> Int -- | An exception which may be generated by this library data () => HttpException -- | Most exceptions are specific to a Request. Inspect the -- HttpExceptionContent value for details on what occurred. HttpExceptionRequest :: Request -> HttpExceptionContent -> HttpException -- | A URL (first field) is invalid for a given reason (second argument). InvalidUrlException :: String -> String -> HttpException -- | Keeps track of open connections for keep-alive. -- -- If possible, you should share a single Manager between multiple -- threads and requests. -- -- Since 0.1.0 data () => Manager -- | Status of streaming a request body from a file. -- -- Since 0.4.9 data () => StreamFileStatus StreamFileStatus :: Int64 -> Int64 -> Int -> StreamFileStatus [fileSize] :: StreamFileStatus -> Int64 [readSoFar] :: StreamFileStatus -> Int64 [thisChunkSize] :: StreamFileStatus -> Int class () => HasHttpManager a getHttpManager :: HasHttpManager a => a -> Manager -- | How the HTTP proxy server settings should be discovered. -- -- Since 0.4.7 data () => ProxyOverride -- | Settings for a Manager. Please use the -- defaultManagerSettings function and then modify individual -- settings. For more information, see -- http://www.yesodweb.com/book/settings-types. -- -- Since 0.1.0 data () => ManagerSettings -- | A simple representation of the HTTP response. -- -- Since 0.1.0 data () => Response body -- | How to deal with timing out on retrieval of response headers. data () => ResponseTimeout -- | All information on how to connect to a host and what should be sent in -- the HTTP request. -- -- If you simply wish to download from a URL, see parseRequest. -- -- The constructor for this data type is not exposed. Instead, you should -- use either the defaultRequest value, or parseRequest -- to construct from a URL, and then use the records below to make -- modifications. This approach allows http-client to add configuration -- options without breaking backwards compatibility. -- -- For example, to construct a POST request, you could do something like: -- --
-- initReq <- parseRequest "http://www.example.com/path"
-- let req = initReq
-- { method = "POST"
-- }
--
--
-- For more information, please see
-- http://www.yesodweb.com/book/settings-types.
--
-- Since 0.1.0
data () => Request
-- | A function which will provide a Popper to a NeedsPopper.
-- This seemingly convoluted structure allows for creation of request
-- bodies which allocate scarce resources in an exception safe manner.
--
-- Since 0.1.0
type GivesPopper a = NeedsPopper a -> IO a
-- | A function which must be provided with a Popper.
--
-- Since 0.1.0
type NeedsPopper a = Popper -> IO a
-- | A function which generates successive chunks of a request body,
-- provider a single empty bytestring when no more data is available.
--
-- Since 0.1.0
type Popper = IO ByteString
-- | When using one of the RequestBodyStream /
-- RequestBodyStreamChunked constructors, you must ensure that the
-- GivesPopper can be called multiple times. Usually this is not a
-- problem.
--
-- The RequestBodyStreamChunked will send a chunked request body.
-- Note that not all servers support this. Only use
-- RequestBodyStreamChunked if you know the server you're sending
-- to supports chunked request bodies.
--
-- Since 0.1.0
data () => RequestBody
RequestBodyLBS :: ByteString -> RequestBody
RequestBodyBS :: ByteString -> RequestBody
RequestBodyBuilder :: Int64 -> Builder -> RequestBody
RequestBodyStream :: Int64 -> GivesPopper () -> RequestBody
RequestBodyStreamChunked :: GivesPopper () -> RequestBody
-- | Allows creation of a RequestBody inside the IO
-- monad, which is useful for making easier APIs (like
-- setRequestBodyFile).
RequestBodyIO :: IO RequestBody -> RequestBody
data () => CookieJar
data () => Cookie
Cookie :: ByteString -> ByteString -> UTCTime -> ByteString -> ByteString -> UTCTime -> UTCTime -> Bool -> Bool -> Bool -> Bool -> Cookie
[cookie_name] :: Cookie -> ByteString
[cookie_value] :: Cookie -> ByteString
[cookie_expiry_time] :: Cookie -> UTCTime
[cookie_domain] :: Cookie -> ByteString
[cookie_path] :: Cookie -> ByteString
[cookie_creation_time] :: Cookie -> UTCTime
[cookie_last_access_time] :: Cookie -> UTCTime
[cookie_persistent] :: Cookie -> Bool
[cookie_host_only] :: Cookie -> Bool
[cookie_secure_only] :: Cookie -> Bool
[cookie_http_only] :: Cookie -> Bool
data () => HttpExceptionContent
-- | Generated by the parseUrlThrow function when the server
-- returns a non-2XX response status code.
--
-- May include the beginning of the response body.
StatusCodeException :: Response () -> ByteString -> HttpExceptionContent
-- | The server responded with too many redirects for a request.
--
-- Contains the list of encountered responses containing redirects in
-- reverse chronological order; including last redirect, which triggered
-- the exception and was not followed.
TooManyRedirects :: [Response ByteString] -> HttpExceptionContent
-- | Either too many headers, or too many total bytes in a single header,
-- were returned by the server, and the memory exhaustion protection in
-- this library has kicked in.
OverlongHeaders :: HttpExceptionContent
-- | The server took too long to return a response. This can be altered via
-- responseTimeout or managerResponseTimeout.
ResponseTimeout :: HttpExceptionContent
-- | Attempting to connect to the server timed out.
ConnectionTimeout :: HttpExceptionContent
-- | An exception occurred when trying to connect to the server.
ConnectionFailure :: SomeException -> HttpExceptionContent
-- | The status line returned by the server could not be parsed.
InvalidStatusLine :: ByteString -> HttpExceptionContent
-- | The given response header line could not be parsed
InvalidHeader :: ByteString -> HttpExceptionContent
-- | The given request header is not compliant (e.g. has newlines)
InvalidRequestHeader :: ByteString -> HttpExceptionContent
-- | An exception was raised by an underlying library when performing the
-- request. Most often, this is caused by a failing socket action or a
-- TLS exception.
InternalException :: SomeException -> HttpExceptionContent
-- | A non-200 status code was returned when trying to connect to the proxy
-- server on the given host and port.
ProxyConnectException :: ByteString -> Int -> Status -> HttpExceptionContent
-- | No response data was received from the server at all. This exception
-- may deserve special handling within the library, since it may indicate
-- that a pipelining has been used, and a connection thought to be open
-- was in fact closed.
NoResponseDataReceived :: HttpExceptionContent
-- | Exception thrown when using a Manager which does not have
-- support for secure connections. Typically, you will want to use
-- tlsManagerSettings from http-client-tls to overcome
-- this.
TlsNotSupported :: HttpExceptionContent
-- | The request body provided did not match the expected size.
--
-- Provides the expected and actual size.
WrongRequestBodyStreamSize :: Word64 -> Word64 -> HttpExceptionContent
-- | The returned response body is too short. Provides the expected size
-- and actual size.
ResponseBodyTooShort :: Word64 -> Word64 -> HttpExceptionContent
-- | A chunked response body had invalid headers.
InvalidChunkHeaders :: HttpExceptionContent
-- | An incomplete set of response headers were returned.
IncompleteHeaders :: HttpExceptionContent
-- | The host we tried to connect to is invalid (e.g., an empty string).
InvalidDestinationHost :: ByteString -> HttpExceptionContent
-- | An exception was thrown when inflating a response body.
HttpZlibException :: ZlibException -> HttpExceptionContent
-- | Values in the proxy environment variable were invalid. Provides the
-- environment variable name and its value.
InvalidProxyEnvironmentVariable :: Text -> Text -> HttpExceptionContent
-- | Attempted to use a Connection which was already closed
ConnectionClosed :: HttpExceptionContent
-- | Proxy settings are not valid (Windows specific currently) @since 0.5.7
InvalidProxySettings :: Text -> HttpExceptionContent
-- | An IO action that represents an incoming response body coming
-- from the server. Data provided by this action has already been
-- gunzipped and de-chunked, and respects any content-length headers
-- present.
--
-- The action gets a single chunk of data from the response body, or an
-- empty bytestring if no more data is available.
--
-- Since 0.4.0
type BodyReader = IO ByteString
-- | A datatype holding information on redirected requests and the final
-- response.
--
-- Since 0.4.1
data () => HistoriedResponse body
-- | Data structure passed to the external program, through JSON format.
--
-- The data schema is described in file schema/imm.json,
-- provided with this library.
data CallbackMessage
CallbackMessage :: FeedLocation -> FeedDefinition -> FeedItem -> CallbackMessage
[_callbackFeedLocation] :: CallbackMessage -> FeedLocation
[_callbackFeedDefinition] :: CallbackMessage -> FeedDefinition
[_callbackFeedItem] :: CallbackMessage -> FeedItem
-- | Feed location identifies a feed. It is either: - the feed URI - a
-- webpage URI that refers to the feed through an alternate link, in
-- which case an optional feed title can be provided to disambiguate
-- multiple such links
data FeedLocation
FeedLocation :: URI -> Text -> FeedLocation
-- | Database identifier for a feed
type UID = Int
-- | A query describes a set of feeds through some criteria.
data FeedQuery
QueryByUID :: UID -> FeedQuery
QueryAll :: FeedQuery
newtype FeedDefinition
FeedDefinition :: Text -> FeedDefinition
[_feedTitle] :: FeedDefinition -> Text
data FeedItem
FeedItem :: Maybe UTCTime -> Text -> Text -> [Link] -> Text -> [Author] -> FeedItem
[_itemDate] :: FeedItem -> Maybe UTCTime
[_itemTitle] :: FeedItem -> Text
[_itemContent] :: FeedItem -> Text
[_itemLinks] :: FeedItem -> [Link]
[_itemIdentifier] :: FeedItem -> Text
[_itemAuthors] :: FeedItem -> [Author]
data Author
Author :: Text -> Text -> Maybe AnyURI -> Author
[_authorName] :: Author -> Text
[_authorEmail] :: Author -> Text
[_authorURI] :: Author -> Maybe AnyURI
data LogLevel
Debug :: LogLevel
Info :: LogLevel
Warning :: LogLevel
Error :: LogLevel
log :: Handle m -> LogLevel -> Doc AnsiStyle -> m ()
getLogLevel :: Handle m -> m LogLevel
setLogLevel :: Handle m -> LogLevel -> m ()
-- | Create a Manager. The Manager will be shut down
-- automatically via garbage collection.
--
-- Creating a new Manager is a relatively expensive operation, you
-- are advised to share a single Manager between requests instead.
--
-- The first argument to this function is often
-- defaultManagerSettings, though add-on libraries may provide a
-- recommended replacement.
--
-- Since 0.1.0
newManager :: ManagerSettings -> IO Manager
-- | Instead of (==).
--
-- Since there was some confusion in the history of this library about
-- how the Eq instance should work, it was removed for clarity,
-- and replaced by equal and equiv. equal
-- gives you equality of all fields of the Cookie record.
equalCookie :: Cookie -> Cookie -> Bool
-- | Equality of name, domain, path only. This corresponds to step 11 of
-- the algorithm described in Section 5.3 "Storage Model". See also:
-- equal.
equivCookie :: Cookie -> Cookie -> Bool
-- | Instead of instance Ord Cookie. See equalCookie,
-- equivCookie.
compareCookies :: Cookie -> Cookie -> Ordering
-- | See equalCookie.
equalCookieJar :: CookieJar -> CookieJar -> Bool
-- | See equalCookieJar, equalCookie.
equivCookieJar :: CookieJar -> CookieJar -> Bool
-- | Create a new Connection from a read, write, and close function.
makeConnection :: IO ByteString -> (ByteString -> IO ()) -> IO () -> IO Connection
-- | Create a new Connection from a Socket.
socketConnection :: Socket -> Int -> IO Connection
-- | strippedHostName takes a URI host name, as extracted by
-- regName, and strips square brackets around IPv6 addresses.
--
-- The result is suitable for passing to services such as name resolution
-- (getAddr).
--
-- @since
strippedHostName :: String -> String
-- | Get a single chunk of data from the response body, or an empty
-- bytestring if no more data is available.
--
-- Note that in order to consume the entire request body, you will need
-- to repeatedly call this function until you receive an empty
-- ByteString as a result.
--
-- Since 0.1.0
brRead :: BodyReader -> IO ByteString
-- | Continuously call brRead, building up a lazy ByteString until a
-- chunk is constructed that is at least as many bytes as requested.
--
-- Since 0.4.20
brReadSome :: BodyReader -> Int -> IO ByteString
-- | Strictly consume all remaining chunks of data from the stream.
--
-- Since 0.1.0
brConsume :: BodyReader -> IO [ByteString]
-- | Deprecated synonym for parseUrlThrow. You probably want
-- parseRequest or parseRequest_ instead.
parseUrl :: MonadThrow m => String -> m Request
-- | Same as parseRequest, except will throw an HttpException
-- in the event of a non-2XX response. This uses
-- throwErrorStatusCodes to implement checkResponse.
parseUrlThrow :: MonadThrow m => String -> m Request
-- | Throws a StatusCodeException wrapped in
-- HttpExceptionRequest, if the response's status code indicates
-- an error (if it isn't 2xx). This can be used to implement
-- checkResponse.
throwErrorStatusCodes :: MonadIO m => Request -> Response BodyReader -> m ()
-- | Convert a URL into a Request.
--
-- This function defaults some of the values in Request, such as
-- setting method to GET and requestHeaders
-- to [].
--
-- Since this function uses MonadThrow, the return monad can be
-- anything that is an instance of MonadThrow, such as IO
-- or Maybe.
--
-- You can place the request method at the beginning of the URL separated
-- by a space, e.g.:
--
-- -- parseRequest "POST http://httpbin.org/post" ---- -- Note that the request method must be provided as all capital letters. -- -- A Request created by this function won't cause exceptions on -- non-2XX response status codes. -- -- To create a request which throws on non-2XX status codes, see -- parseUrlThrow parseRequest :: MonadThrow m => String -> m Request -- | Same as parseRequest, but parse errors cause an impure -- exception. Mostly useful for static strings which are known to be -- correctly formatted. parseRequest_ :: String -> Request -- | Convert a URI into a Request. -- -- This can fail if the given URI is not absolute, or if the -- URI scheme is not "http" or "https". In these -- cases the function will throw an error via MonadThrow. -- -- This function defaults some of the values in Request, such as -- setting method to GET and requestHeaders -- to []. -- -- A Request created by this function won't cause exceptions on -- non-2XX response status codes. requestFromURI :: MonadThrow m => URI -> m Request -- | Same as requestFromURI, but if the conversion would fail, -- throws an impure exception. requestFromURI_ :: URI -> Request -- | Extract a URI from the request. -- -- Since 0.1.0 getUri :: Request -> URI -- | A default request value, a GET request of localhost/:80, with an empty -- request body. -- -- Note that the default checkResponse does nothing. defaultRequest :: Request -- | Add a Basic Auth header (with the specified user name and password) to -- the given Request. Ignore error handling: -- --
-- applyBasicAuth "user" "pass" $ parseRequest_ url ---- -- NOTE: The function applyDigestAuth is provided by the -- http-client-tls package instead of this package due to extra -- dependencies. Please use that package if you need to use digest -- authentication. -- -- Since 0.1.0 applyBasicAuth :: ByteString -> ByteString -> Request -> Request -- | Add a Bearer Auth header to the given Request applyBearerAuth :: ByteString -> Request -> Request -- | Add a Proxy-Authorization header (with the specified username and -- password) to the given Request. Ignore error handling: -- --
-- applyBasicProxyAuth "user" "pass" <$> parseRequest "http://example.org" ---- -- Since 0.3.4 applyBasicProxyAuth :: ByteString -> ByteString -> Request -> Request -- | Add url-encoded parameters to the Request. -- -- This sets a new requestBody, adds a content-type request header -- and changes the method to POST. -- -- Since 0.1.0 urlEncodedBody :: [(ByteString, ByteString)] -> Request -> Request -- | Modify the request so that non-2XX status codes do not generate a -- runtime StatusCodeException. setRequestIgnoreStatus :: Request -> Request -- | Modify the request so that non-2XX status codes generate a runtime -- StatusCodeException, by using throwErrorStatusCodes setRequestCheckStatus :: Request -> Request -- | Set the query string to the given key/value pairs. -- -- Since 0.3.6 setQueryString :: [(ByteString, Maybe ByteString)] -> Request -> Request -- | Set the query string to the given key/value pairs. setQueryStringPartialEscape :: [(ByteString, [EscapeItem])] -> Request -> Request -- | Send a file as the request body. -- -- It is expected that the file size does not change between calling -- streamFile and making any requests using this request body. -- -- Since 0.4.9 streamFile :: FilePath -> IO RequestBody -- | Send a file as the request body, while observing streaming progress -- via a PopObserver. Observations are made between reading and -- sending a chunk. -- -- It is expected that the file size does not change between calling -- observedStreamFile and making any requests using this request -- body. -- -- Since 0.4.9 observedStreamFile :: (StreamFileStatus -> IO ()) -> FilePath -> IO RequestBody -- | Retrieve the orignal Request from a Response -- -- Note that the requestBody is not available and always set to -- empty. getOriginalRequest :: Response a -> Request -- | A value for the managerRawConnection setting, but also allows -- you to modify the underlying Socket to set additional -- settings. For a motivating use case, see: -- https://github.com/snoyberg/http-client/issues/71. -- -- Since 0.3.8 rawConnectionModifySocket :: (Socket -> IO ()) -> IO (Maybe HostAddress -> String -> Int -> IO Connection) -- | Same as rawConnectionModifySocket, but also takes in a chunk -- size. rawConnectionModifySocketSize :: (Socket -> IO ()) -> IO (Int -> Maybe HostAddress -> String -> Int -> IO Connection) -- | Default value for ManagerSettings. -- -- Note that this value does not have support for SSL/TLS. If you -- need to make any https connections, please use the http-client-tls -- package, which provides a tlsManagerSettings value. -- -- Since 0.1.0 defaultManagerSettings :: ManagerSettings -- | Close all connections in a Manager. -- -- Note that this doesn't affect currently in-flight connections, meaning -- you can safely use it without hurting any queries you may have -- concurrently running. -- -- Since 0.1.0 closeManager :: Manager -> IO () -- | Create, use and close a Manager. -- -- Since 0.2.1 withManager :: ManagerSettings -> (Manager -> IO a) -> IO a -- | Get the proxy settings from the Request itself. -- -- Since 0.4.7 proxyFromRequest :: ProxyOverride -- | Never connect using a proxy, regardless of the proxy value in the -- Request. -- -- Since 0.4.7 noProxy :: ProxyOverride -- | Use the given proxy settings, regardless of the proxy value in the -- Request. -- -- Since 0.4.7 useProxy :: Proxy -> ProxyOverride -- | Send secure requests to the proxy in plain text rather than using -- CONNECT, regardless of the value in the Request. useProxySecureWithoutConnect :: Proxy -> ProxyOverride -- | Get the proxy settings from the default environment variable -- (http_proxy for insecure, https_proxy for secure). -- If no variable is set, then fall back to the given value. -- Nothing is equivalent to noProxy, Just is -- equivalent to useProxy. -- -- Since 0.4.7 proxyEnvironment :: Maybe Proxy -> ProxyOverride -- | Same as proxyEnvironment, but instead of default environment -- variable names, allows you to set your own name. -- -- Since 0.4.7 proxyEnvironmentNamed :: Text -> Maybe Proxy -> ProxyOverride -- | The default proxy settings for a manager. In particular: if the -- http_proxy (or https_proxy) environment variable is -- set, use it. Otherwise, use the values in the Request. -- -- Since 0.4.7 defaultProxy :: ProxyOverride isIpAddress :: ByteString -> Bool -- | This corresponds to the subcomponent algorithm entitled "Domain -- Matching" detailed in section 5.1.3 domainMatches :: ByteString -> ByteString -> Bool -- | This corresponds to the subcomponent algorithm entitled "Paths" -- detailed in section 5.1.4 defaultPath :: Request -> ByteString -- | This corresponds to the subcomponent algorithm entitled "Path-Match" -- detailed in section 5.1.4 pathMatches :: ByteString -> ByteString -> Bool createCookieJar :: [Cookie] -> CookieJar destroyCookieJar :: CookieJar -> [Cookie] removeExistingCookieFromCookieJar :: Cookie -> CookieJar -> (Maybe Cookie, CookieJar) -- | Algorithm described in "Secure Contexts", Section 3.1, "Is origin -- potentially trustworthy?" -- -- Note per RFC6265 section 5.4 user agent is free to define the meaning -- of "secure" protocol. -- -- See: -- https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy isPotentiallyTrustworthyOrigin :: Bool -> ByteString -> Bool -- | This corresponds to the eviction algorithm described in Section 5.3 -- "Storage Model" evictExpiredCookies :: CookieJar -> UTCTime -> CookieJar -- | This applies the computeCookieString to a given Request insertCookiesIntoRequest :: Request -> CookieJar -> UTCTime -> (Request, CookieJar) -- | This corresponds to the algorithm described in Section 5.4 "The Cookie -- Header" computeCookieString :: Request -> CookieJar -> UTCTime -> Bool -> (ByteString, CookieJar) -- | This applies receiveSetCookie to a given Response updateCookieJar :: Response a -> Request -> UTCTime -> CookieJar -> (CookieJar, Response a) -- | This corresponds to the algorithm described in Section 5.3 "Storage -- Model" This function consists of calling generateCookie -- followed by insertCheckedCookie. Use this function if you plan -- to do both in a row. generateCookie and -- insertCheckedCookie are only provided for more fine-grained -- control. receiveSetCookie :: SetCookie -> Request -> UTCTime -> Bool -> CookieJar -> CookieJar -- | Insert a cookie created by generateCookie into the cookie jar (or not -- if it shouldn't be allowed in) insertCheckedCookie :: Cookie -> CookieJar -> Bool -> CookieJar -- | Turn a SetCookie into a Cookie, if it is valid generateCookie :: SetCookie -> Request -> UTCTime -> Bool -> Maybe Cookie -- | Perform a Request using a connection acquired from the given -- Manager, and then provide the Response to the given -- function. This function is fully exception safe, guaranteeing that the -- response will be closed when the inner function exits. It is defined -- as: -- --
-- withResponse req man f = bracket (responseOpen req man) responseClose f ---- -- It is recommended that you use this function in place of explicit -- calls to responseOpen and responseClose. -- -- You will need to use functions such as brRead to consume the -- response body. -- -- Since 0.1.0 withResponse :: Request -> Manager -> (Response BodyReader -> IO a) -> IO a -- | A convenience wrapper around withResponse which reads in the -- entire response body and immediately closes the connection. Note that -- this function performs fully strict I/O, and only uses a lazy -- ByteString in its response for memory efficiency. If you are -- anticipating a large response body, you are encouraged to use -- withResponse and brRead instead. -- -- Since 0.1.0 httpLbs :: Request -> Manager -> IO (Response ByteString) -- | A convenient wrapper around withResponse which ignores the -- response body. This is useful, for example, when performing a HEAD -- request. -- -- Since 0.3.2 httpNoBody :: Request -> Manager -> IO (Response ()) -- | The most low-level function for initiating an HTTP request. -- -- The first argument to this function gives a full specification on the -- request: the host to connect to, whether to use SSL, headers, etc. -- Please see Request for full details. The second argument -- specifies which Manager should be used. -- -- This function then returns a Response with a BodyReader. -- The Response contains the status code and headers that were -- sent back to us, and the BodyReader contains the body of the -- request. Note that this BodyReader allows you to have fully -- interleaved IO actions during your HTTP download, making it possible -- to download very large responses in constant memory. -- -- An important note: the response body returned by this function -- represents a live HTTP connection. As such, if you do not use the -- response body, an open socket will be retained indefinitely. You must -- be certain to call responseClose on this response to free up -- resources. -- -- This function automatically performs any necessary redirects, as -- specified by the redirectCount setting. -- -- When implementing a (reverse) proxy using this function or relating -- functions, it's wise to remove Transfer-Encoding:, Content-Length:, -- Content-Encoding: and Accept-Encoding: from request and response -- headers to be relayed. -- -- Since 0.1.0 responseOpen :: Request -> Manager -> IO (Response BodyReader) -- | Close any open resources associated with the given Response. -- In general, this will either close an active Connection or -- return it to the Manager to be reused. -- -- Since 0.1.0 responseClose :: Response a -> IO () -- | Perform an action using a Connection acquired from the given -- Manager. -- -- You should use this only when you have to read and write interactively -- through the connection (e.g. connection by the WebSocket protocol). withConnection :: Request -> Manager -> (Connection -> IO a) -> IO a -- | A variant of responseOpen which keeps a history of all -- redirects performed in the interim, together with the first 1024 bytes -- of their response bodies. -- -- Since 0.4.1 responseOpenHistory :: Request -> Manager -> IO (HistoriedResponse BodyReader) -- | A variant of withResponse which keeps a history of all -- redirects performed in the interim, together with the first 1024 bytes -- of their response bodies. -- -- Since 0.4.1 withResponseHistory :: Request -> Manager -> (HistoriedResponse BodyReader -> IO a) -> IO a -- | Set the proxy override value, only for HTTP (insecure) connections. -- -- Since 0.4.7 managerSetInsecureProxy :: ProxyOverride -> ManagerSettings -> ManagerSettings -- | Set the proxy override value, only for HTTPS (secure) connections. -- -- Since 0.4.7 managerSetSecureProxy :: ProxyOverride -> ManagerSettings -> ManagerSettings -- | Set the proxy override value, for both HTTP (insecure) and HTTPS -- (insecure) connections. -- -- Since 0.4.7 managerSetProxy :: ProxyOverride -> ManagerSettings -> ManagerSettings managerSetMaxHeaderLength :: Int -> ManagerSettings -> ManagerSettings -- | Specify maximum time in microseconds the retrieval of response headers -- is allowed to take responseTimeoutMicro :: Int -> ResponseTimeout -- | Do not have a response timeout responseTimeoutNone :: ResponseTimeout -- | Use the default response timeout -- -- When used on a Request, means: use the manager's timeout value -- -- When used on a ManagerSettings, means: default to 30 seconds responseTimeoutDefault :: ResponseTimeout parseFeed :: MonadCatch m => Text -> m (FeedDefinition, [FeedItem]) runCallback :: MonadIO m => Handle m -> Callback -> CallbackMessage -> m (Either (Callback, Int, LByteString, LByteString) (Callback, LByteString, LByteString)) -- | Conduit version of parseFeed feedC :: MonadCatch m => ConduitT Event o m (Maybe (FeedDefinition, [FeedItem])) parseFeedItem :: MonadCatch m => Text -> m FeedItem getMainLink :: FeedItem -> Maybe Link areSameItem :: FeedItem -> FeedItem -> Bool _withGet :: Handle m -> forall a. URI -> (Response (Producer ByteString m ()) -> m a) -> m a -- | Simple wrapper around _withGet that also logs the requested -- URI. withGet :: Monad m => Handle m -> Handle m -> URI -> (Response (Producer ByteString m ()) -> m a) -> m a parseXml :: Handle m -> URI -> LByteString -> m (FeedDefinition, [FeedItem])