prettyprinter-ansi-terminal (empty) → 0.1
raw patch · 7 files changed
+373/−0 lines, 7 filesdep +ansi-terminaldep +basedep +doctestsetup-changed
Dependencies added: ansi-terminal, base, doctest, prettyprinter, text
Files
- LICENSE.md +23/−0
- README.md +9/−0
- Setup.lhs +3/−0
- misc/version-compatibility-macros.h +19/−0
- prettyprinter-ansi-terminal.cabal +54/−0
- src/Data/Text/Prettyprint/Doc/Render/Terminal.hs +259/−0
- test/Doctest/Main.hs +6/−0
+ LICENSE.md view
@@ -0,0 +1,23 @@+Copyright 2008, Daan Leijen and Max Bolingbroke, 2016 David Luposchainsky. All+rights reserved.++Redistribution and use in source and binary forms, with or without modification,+are permitted provided that the following conditions are met:++ - Redistributions of source code must retain the above copyright notice, this+ list of conditions and the following disclaimer.++ - Redistributions in binary form must reproduce the above copyright notice,+ this list of conditions and the following disclaimer in the documentation+ and/or other materials provided with the distribution.++This software is provided by the copyright holders "as is" and any express or+implied warranties, including, but not limited to, the implied warranties of+merchantability and fitness for a particular purpose are disclaimed. In no event+shall the copyright holders be liable for any direct, indirect, incidental,+special, exemplary, or consequential damages (including, but not limited to,+procurement of substitute goods or services; loss of use, data, or profits; or+business interruption) however caused and on any theory of liability, whether in+contract, strict liability, or tort (including negligence or otherwise) arising+in any way out of the use of this software, even if advised of the possibility+of such damage.
+ README.md view
@@ -0,0 +1,9 @@+ANSI terminal prettyprinter renderer+====================================++This package defines a renderer for documents generated by the `wl-pprint`+package, suitable for displaying them on ANSI-compatible terminals, including+colors, boldening, underlining and italication.++For more information about the prettyprinter in general, refer to the main+`wl-pprint` package documentation.
+ Setup.lhs view
@@ -0,0 +1,3 @@+#!/usr/bin/env runhaskell+> import Distribution.Simple+> main = defaultMain
+ misc/version-compatibility-macros.h view
@@ -0,0 +1,19 @@+#ifndef VERSION_COMPATIBILITY_MACROS+#define VERSION_COMPATIBILITY_MACROS++#ifndef MIN_VERSION_base+#error "MIN_VERSION_base macro not defined!"+#endif++-- These macros allow writing CPP compatibility hacks in a way that makes their+-- purpose much clearer than just demanding a specific version of a library.++#define APPLICATIVE_MONAD MIN_VERSION_base(4,8,0)+#define FOLDABLE_TRAVERSABLE_IN_PRELUDE MIN_VERSION_base(4,8,0)+#define MONOID_IN_PRELUDE MIN_VERSION_base(4,8,0)+#define NATURAL_IN_BASE MIN_VERSION_base(4,8,0)+#define SEMIGROUP_IN_BASE MIN_VERSION_base(4,8,0)++#define MONAD_FAIL MIN_VERSION_base(4,9,0)++#endif
+ prettyprinter-ansi-terminal.cabal view
@@ -0,0 +1,54 @@+name: prettyprinter-ansi-terminal+version: 0.1+cabal-version: >= 1.10+category: User Interfaces, Text+synopsis: ANSI terminal backend for the modern, extensible and well-documented prettyprinter.+description: See README.md+license: BSD2+license-file: LICENSE.md+extra-source-files: README.md+ , misc/version-compatibility-macros.h+author: David Luposchainsky+maintainer: David Luposchainsky <dluposchainsky at google>+bug-reports: http://github.com/quchen/prettyprinter/issues+homepage: http://github.com/quchen/prettyprinter+build-type: Simple+tested-with: GHC==7.8.4, GHC==7.10.2, GHC==7.10.3, GHC==8.0.1, GHC==8.0.2++source-repository head+ type: git+ location: git://github.com/quchen/prettyprinter.git++library+ exposed-modules: Data.Text.Prettyprint.Doc.Render.Terminal+ ghc-options: -Wall+ hs-source-dirs: src+ include-dirs: misc+ default-language: Haskell2010+ other-extensions:+ CPP+ , LambdaCase+ , OverloadedStrings+++ build-depends:+ base < 127+ , ansi-terminal >= 0.4.0 && < 0.7+ , text+ , prettyprinter >= 0 && < 0.2++ if impl(ghc >= 8.0)+ ghc-options: -Wcompat++test-suite doctest+ type: exitcode-stdio-1.0+ hs-source-dirs: test/Doctest+ main-is: Main.hs+ build-depends:+ base < 127+ , doctest >= 0.9+ ghc-options: -Wall -threaded -rtsopts -with-rtsopts=-N+ default-language: Haskell2010+ if impl (ghc < 7.10)+ buildable: False+ -- Doctest cannot search folders in old versions it seems :-(
+ src/Data/Text/Prettyprint/Doc/Render/Terminal.hs view
@@ -0,0 +1,259 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}++#include "version-compatibility-macros.h"++-- | Render 'SimpleDoc' in a terminal.+module Data.Text.Prettyprint.Doc.Render.Terminal (+ -- * Styling+ AnsiTerminal, Color(..),++ -- ** Font color+ color, colorDull,+ --+ -- ** Background color+ bgColor, bgColorDull,++ -- ** Font style+ bold, italics, underline,++ -- * Conversion to ANSI-infused 'Text'+ renderLazy, renderStrict,++ -- * Render directly to 'stdout'+ renderIO,++ -- ** Convenience functions+ putDoc, hPutDoc,+) where++++import Control.Monad+import Data.Functor+import Data.Maybe+import Data.Text (Text)+import qualified Data.Text as T+import qualified Data.Text.Lazy as TL+import qualified Data.Text.Lazy.Builder as TLB+import qualified Data.Text.Lazy.IO as TL+import qualified System.Console.ANSI as ANSI+import System.IO (Handle, stdout)++import Data.Text.Prettyprint.Doc+import Data.Text.Prettyprint.Doc.Render.Util.Panic+import Data.Text.Prettyprint.Doc.Render.Util.StackMachine++#if !(APPLICATIVE_MONAD)+import Control.Applicative+#endif++++-- $setup+--+-- (Definitions for the doctests)+--+-- >>> :set -XOverloadedStrings+-- >>> import qualified Data.Text.Lazy.IO as TL+-- >>> import qualified Data.Text.Lazy as TL+-- >>> import Data.Text.Prettyprint.Doc.Render.Terminal++++-- | A general ANSI style. Use e.g. 'color' or 'bold' to apply a style to a+-- 'Doc'ument.+data AnsiTerminal =+ Italicized+ | Bold+ | Underlined+ | Color Layer Intensity Color+ deriving (Eq, Ord, Show)++-- | 8 different colors, so that all can be displayed in an ANSI terminal.+data Color = Black | Red | Green | Yellow | Blue | Magenta | Cyan | White+ deriving (Eq, Ord, Show)++-- | Dull or vivid coloring, as supported by ANSI terminals.+data Intensity = Vivid | Dull+ deriving (Eq, Ord, Show)++-- | Foreground (text) or background (paper) color+data Layer = Foreground | Background+ deriving (Eq, Ord, Show)++-- | Style the foreground with a vivid color.+color :: Color -> Doc AnsiTerminal -> Doc AnsiTerminal+color c = annotate (Color Foreground Vivid c)++-- | Style the background with a vivid color.+bgColor :: Color -> Doc AnsiTerminal -> Doc AnsiTerminal+bgColor c = annotate (Color Background Vivid c)++-- | Style the foreground with a dull color.+colorDull :: Color -> Doc AnsiTerminal -> Doc AnsiTerminal+colorDull c = annotate (Color Foreground Dull c)++-- | Style the background with a dull color.+bgColorDull :: Color -> Doc AnsiTerminal -> Doc AnsiTerminal+bgColorDull c = annotate (Color Background Dull c)++-- | Render the enclosed document in __bold__.+bold :: Doc AnsiTerminal -> Doc AnsiTerminal+bold = annotate Bold++-- | Render the enclosed document in /italics/.+italics :: Doc AnsiTerminal -> Doc AnsiTerminal+italics = annotate Italicized++-- | Render the enclosed document underlined.+underline :: Doc AnsiTerminal -> Doc AnsiTerminal+underline = annotate Underlined+++-- | @('renderLazy' doc)@ takes the output @doc@ from a rendering function+-- and transforms it to lazy text, including ANSI styling directives for things+-- like colorization.+--+-- ANSI color information will be discarded by this function unless you are+-- running on a Unix-like operating system. This is due to a technical+-- limitation in Windows ANSI support.+--+-- With a bit of trickery to make the ANSI codes printable, here is an example+-- that would render colored in an ANSI terminal:+--+-- >>> let render = TL.putStrLn . TL.replace "\ESC" "\\e" . renderLazy . layoutPretty defaultLayoutOptions+-- >>> let doc = color Red ("red" <+> align (vsep [color Blue ("blue" <+> bold "bold" <+> "blue"), "red"]))+-- >>> render (unAnnotate doc)+-- red blue bold blue+-- red+-- >>> render doc+-- \e[0;91mred \e[0;94mblue \e[0;94;1mbold\e[0;94m blue\e[0;91m+-- red\e[0m+--+-- Run the above via @echo -e '...'@ in your terminal to see the coloring.+renderLazy :: SimpleDoc AnsiTerminal -> TL.Text+renderLazy doc+ = let (resultBuilder, remainingStyles) = execStackMachine [emptyStyle] (build doc)+ in case remainingStyles of+ [] -> error ("There is no empty style left at the end of rendering" +++ " (but there should be). Please report this as a bug.")+ [_] -> TLB.toLazyText resultBuilder+ xs -> error ("There are " <> show (length xs) <> " styles left at the" +++ "end of rendering (there should be only 1). Please report" +++ " this as a bug.")++build :: SimpleDoc AnsiTerminal -> StackMachine TLB.Builder CombinedStyle ()+build = \case+ SFail -> panicUncaughtFail+ SEmpty -> pure ()+ SChar c x -> do+ writeOutput (TLB.singleton c)+ build x+ SText _l t x -> do+ writeOutput (TLB.fromText t)+ build x+ SLine i x -> do+ writeOutput (TLB.singleton '\n')+ writeOutput (TLB.fromText (T.replicate i " "))+ build x+ SAnnPush s x -> do+ currentStyle <- unsafePeekStyle+ let newStyle = currentStyle `addStyle` s+ writeOutput (styleToBuilder newStyle)+ pushStyle newStyle+ build x+ SAnnPop x -> do+ _currentStyle <- unsafePopStyle+ newStyle <- unsafePeekStyle+ writeOutput (styleToBuilder newStyle)+ build x++styleToBuilder :: CombinedStyle -> TLB.Builder+styleToBuilder = TLB.fromString . ANSI.setSGRCode . stylesToSgrs++data CombinedStyle = CombinedStyle+ (Maybe (Intensity, Color)) -- Foreground+ (Maybe (Intensity, Color)) -- Background+ Bool -- Bold+ Bool -- Italics+ Bool -- Underlining++addStyle :: CombinedStyle -> AnsiTerminal -> CombinedStyle+addStyle (CombinedStyle m'fg m'bg b i u) = \case+ Italicized -> CombinedStyle m'fg m'bg b True u+ Bold -> CombinedStyle m'fg m'bg True i u+ Underlined -> CombinedStyle m'fg m'bg b i True+ Color Foreground dv col -> CombinedStyle (Just (dv, col)) m'bg b i u+ Color Background dv col -> CombinedStyle m'fg (Just (dv, col)) b i u++emptyStyle :: CombinedStyle+emptyStyle = CombinedStyle Nothing Nothing False False False++stylesToSgrs :: CombinedStyle -> [ANSI.SGR]+stylesToSgrs (CombinedStyle m'fg m'bg b i u) = catMaybes+ [ Just ANSI.Reset+ , fmap (\(intensity, c) -> ANSI.SetColor ANSI.Foreground (convertIntensity intensity) (convertColor c)) m'fg+ , fmap (\(intensity, c) -> ANSI.SetColor ANSI.Background (convertIntensity intensity) (convertColor c)) m'bg+ , guard b $> ANSI.SetConsoleIntensity ANSI.BoldIntensity+ , guard i $> ANSI.SetItalicized True+ , guard u $> ANSI.SetUnderlining ANSI.SingleUnderline+ ]+ where+ convertIntensity :: Intensity -> ANSI.ColorIntensity+ convertIntensity = \case+ Vivid -> ANSI.Vivid+ Dull -> ANSI.Dull++ convertColor :: Color -> ANSI.Color+ convertColor = \case+ Black -> ANSI.Black+ Red -> ANSI.Red+ Green -> ANSI.Green+ Yellow -> ANSI.Yellow+ Blue -> ANSI.Blue+ Magenta -> ANSI.Magenta+ Cyan -> ANSI.Cyan+ White -> ANSI.White++++-- | @('renderStrict' sdoc)@ takes the output @sdoc@ from a rendering and+-- transforms it to strict text.+renderStrict :: SimpleDoc AnsiTerminal -> Text+renderStrict = TL.toStrict . renderLazy++++-- | @('renderIO' h sdoc)@ writes @sdoc@ to the file @h@.+--+-- >>> renderIO System.IO.stdout (layoutPretty defaultLayoutOptions "hello\nworld")+-- hello+-- world+renderIO :: Handle -> SimpleDoc AnsiTerminal -> IO ()+renderIO h sdoc = TL.hPutStrLn h (renderLazy sdoc)++-- | @('putDoc' doc)@ prettyprints document @doc@ to standard output, with a page+-- width of 80 characters and a ribbon width of 32 characters.+--+-- >>> putDoc ("hello" <+> "world")+-- hello world+--+-- @+-- 'putDoc' = 'hPutDoc' 'stdout'+-- @+putDoc :: Doc AnsiTerminal -> IO ()+putDoc = hPutDoc stdout++-- | Like 'putDoc', but instead of using 'stdout', print to a user-provided+-- handle, e.g. a file or a socket. Uses a line length of 80, and a ribbon width+-- of 32 characters.+--+-- > main = withFile "someFile.txt" (\h -> hPutDoc h (vcat ["vertical", "text"]))+--+-- @+-- 'hPutDoc' h doc = 'renderIO' h ('layoutPretty' 'defaultLayoutOptions' doc)+-- @+hPutDoc :: Handle -> Doc AnsiTerminal -> IO ()+hPutDoc h doc = renderIO h (layoutPretty defaultLayoutOptions doc)
+ test/Doctest/Main.hs view
@@ -0,0 +1,6 @@+module Main (main) where++import Test.DocTest++main :: IO ()+main = doctest [ "src" , "-Imisc"]