{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DeriveFoldable #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-} -- | Rainbow handles colors and special effects for text. The basic -- building block of Rainbow is the 'Chunk'. The 'Chunk' contains -- both text and formatting information such as colors, bold, -- underlining, etc. 'Chunk' is an instance of -- 'Data.String.IsString' so you can create a 'Chunk' using the -- @OverloadedStrings@ extension. Such a chunk has the given text -- and has no formatting. -- -- When printed, each 'Chunk' starts off with a clean slate, so if -- you want special formatting such as any color, bold, etc, then you -- must specify it for every 'Chunk'. The appearance of one -- 'Chunk' does not affect the appearance of the next 'Chunk'. -- This makes it easy to reason about how a particular 'Chunk' will -- look. -- -- Rainbow supports only 256-color terminals or printing with no colors at all. -- -- Here are some basic examples: -- -- @ -- ghci> import Rainbow -- ghci> import Data.Function ((&)) -- ghci> :set -XOverloadedStrings -- ghci> 'putChunkLn' $ \"Some blue text\" '&' 'fore' 'blue' -- ghci> 'putChunkLn' $ \"Blue on red background\" -- '&' 'fore' 'blue' '&' 'back' 'red' -- ghci> 'putChunkLn' $ \"Blue on red, foreground bold\" -- '&' 'fore' 'blue' '&' 'back' 'red' '&' 'bold' -- @ -- -- Each 'Chunk' affects the formatting only of that 'Chunk'. So -- to print things in different colors, make more than one 'Chunk': -- -- @ -- ghci> 'putChunksLn' -- [ \"Roses\" '&' 'fore' 'red' -- , \"Violets\" '&' 'fore' 'blue' ] -- @ -- -- If there are conflicting formatting instructions, the one that is applied -- last is the one that will \"win\": -- -- @ -- ghci> 'putChunkLn' $ -- \"This text will be blue\" '&' 'fore' 'red' '&' 'fore' 'blue' -- @ -- -- Most of the above examples use 'putChunkLn', but that function -- may be inefficient if you are printing many 'Chunk's. For -- greater efficiency use functions that handle a list of 'Chunk', such as -- 'putChunksLn' and 'putChunks'. module Rainbow ( -- * Chunk Chunk , chunk , content -- * Formatting -- | These combinators affect the way a 'Chunk' is displayed. , bold , faint , italic , underline , blink , inverse , invisible , strikeout -- * Colors , fore , back , black , red , green , yellow , blue , magenta , cyan , white , bright , grey , color256 -- * Converting multiple 'Chunk' to 'Data.ByteString.ByteString' -- | To print a 'Chunk', you need to convert it to some -- 'Data.ByteString.ByteString's. First you will convert it to a -- 'Data.ByteString.Builder.Builder' and then you can convert that to a -- 'Data.ByteString.ByteString' or send it directly to the terminal. , toBuilderColors0 , toBuilderColors256 , builderFromEnvironment , builderFromHandle , chunksToBuilder -- * Writing multiple 'Chunk' to a handle or to standard output , putChunks , hPutChunks , putChunksLn , hPutChunksLn -- * Quick and dirty functions for IO -- | For efficiency reasons you probably don't want to use these -- when printing large numbers of 'Chunk', but they are handy for -- throwaway uses like experimenting in GHCi. , putChunk , putChunkLn -- * Notes on terminals -- $termNotes ) where import Rainbow.Internal {- $termNotes Earlier versions of Rainbow used the Haskell terminfo library for dealing with the terminal. Terminfo is available at Terminfo, in turn, uses the UNIX terminfo library. The biggest advantage of using Terminfo is that it is compatible with a huge variety of terminals. Many of these terminals are hardware models that are gathering dust in an IBM warehouse somewhere, but even modern software terminals might have quirks. Terminfo covers all those. The disadvantage is that using Terminfo requires you to perform IO whenever you need to format output for the terminal. Your only choice when using Terminfo is to send output directly to the terminal, or to a handle. This goes against typical Haskell practice, where we try to write pure code whenever possible. Perhaps surprisingly, there are times where you may want to format output, but not immediately send it to the terminal. Maybe you want to send it to a file instead, or maybe you want to use a Haskell library like Pipes and stream it somewhere. Terminfo is a binding to a Unix library that is not designed for this sort of thing. The closest you could get using Terminfo would be to make a Handle that is backed by a in-memory buffer. There is a package for that sort of thing: but it seems like a nasty workaround. Or you can hijack stdout and send that somewhere--again, nasty workaround. So I decided to stop using Terminfo. That means Rainbow no longer supports a menagerie of bizarre terminals. It instead just uses the standard ISO 6429 / ECMA 48 terminal codes. These are the same codes that are used by xterm, the OS X Terminal, the Linux console, or any other reasonably modern software terminal. Realistically they are the only terminals Rainbow would be used for. The 256 color capability is not in ISO 6429, but it is widely supported. Probably the most common so-called terminals in use today that do NOT support the ISO 6429 codes are those that are not really terminals. For instance, you might use an Emacs shell buffer. For those situations just use 'toByteStringsColors0'. I also decided to standardize on UTF-8 for the 'Data.Text.Text' output. These days that seems reasonable. Apparently it's difficult to get ISO 6429 support on Microsoft Windows. Oh well. -}