-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Two-dimensional box pretty printing, with colors -- -- Please see README.md @package rainbox @version 0.24.2.0 -- | Contains the innards of Rainbox. You shouldn't need anything -- in here. Some functions here are partial or have undefined results if -- their inputs don't respect particular invariants. module Rainbox.Core -- | Alignment. Used in conjunction with Horizontal and -- Vertical, this determines how a payload aligns with the axis of -- a Box. data Alignment a Center :: Alignment a NonCenter :: a -> Alignment a -- | Determines how a payload aligns with a horizontal axis. data Horizontal Top :: Horizontal Bottom :: Horizontal -- | Determines how a payload aligns with a vertical axis. data Vertical Port :: Vertical Starboard :: Vertical -- | Place this payload so that it is centered on the vertical axis or -- horizontal axis. center :: Alignment a -- | Center horizontally; like center, but monomorphic. centerH :: Alignment Horizontal -- | Center vertically; like center, but monomorphic. centerV :: Alignment Vertical -- | Place this payload's left edge on the vertical axis. left :: Alignment Vertical -- | Place this payload's right edge on the vertical axis. right :: Alignment Vertical -- | Place this payload's top edge on the horizontal axis. top :: Alignment Horizontal -- | Place this payload's bottom edge on the horizontal axis. bottom :: Alignment Horizontal -- | A count of rows. newtype Height Height :: Int -> Height -- | A count of columns. newtype Width Width :: Int -> Width class HasHeight a height :: HasHeight a => a -> Int class HasWidth a width :: HasWidth a => a -> Int -- | A Core is either a single Chunk or, if the box is blank, -- is merely a height and a width. newtype Core Core :: Either Chunk (Height, Width) -> Core -- | An intermediate type used in rendering; it consists either of text -- Chunk or of a number of spaces coupled with a background color. newtype Rod Rod :: Either (Int, Radiant) Chunk -> Rod -- | A list of screen rows; each screen row is a Seq of Rod. -- -- A RodRows with width but no height does nothing if rendered -- alone, but it can affect the width of other RodRows if combined -- with them. data RodRows -- | Each outer Seq represents a single screen row. Each Seq -- has a height of 1. -- -- The outer Seq must have a length of at least 1, even if the -- inner Seq is empty. If the outer Seq has a length of -- zero, undefined behavior occurs. For a RodRows with no height -- and no width, use RodRowsNoHeight. RodRowsWithHeight :: Seq (Seq Rod) -> RodRows -- | A RodRows that has no height. If the Int is less than 1, -- the RodRows has no width and no height. Otherwise, the -- RodRows has no height but has the given width. RodRowsNoHeight :: Int -> RodRows -- | Convert a Core to a Seq of Rod for rendering. rodRowsFromCore :: Radiant -> Core -> RodRows -- | Converts a RodRows to a nested Seq of Chunk in -- preparation for rendering. Newlines are added to the end of each line. chunksFromRodRows :: RodRows -> Seq (Seq Chunk) -- | A Payload holds a RodRows, which determines the number -- and content of the screen rows. The Payload also has an -- Alignment, which specifies how the payload aligns with the -- axis. Whether the Alignment is Horizontal or -- Vertical determines the orientation of the Payload. The -- Payload also contains a background color, which is type -- Radiant. The background color extends continuously from the -- Payload in both directions that are perpendicular to the axis. data Payload a Payload :: Alignment a -> Radiant -> Either RodRows Core -> Payload a -- | Adds padding to the top and bottom of each Payload. A Payload with a -- Core is converted to a RodRows and has padding added; a Payload with a -- RodRows has necessary padding added to the top and bottom. The number -- of elements in the resulting Seq is the same as the number of elements -- in the input Seq; no merging is performed. addVerticalPadding :: Box Horizontal -> Seq RodRows -- | Merges multiple horizontal RodRows into a single RodRows. All RodRows -- must already have been the same height; if they are not the same -- height, undefined behavior occurs. horizontalMerge :: Seq RodRows -> RodRows -- | Split a number into two parts, so that the sum of the two parts is -- equal to the original number. split :: Int -> (Int, Int) -- | Adds padding to the left and right of each Payload. A Payload with a -- Core is converted to a RodRows and has padding added; a Payload with a -- RodRows has necessary padding added to the left and right. The number -- of elements in the resulting Seq is the same as the number of elements -- in the input Seq; no merging is performed. addHorizontalPadding :: Box Vertical -> Seq RodRows -- | Merge multiple vertical RodRows into a single RodRows. Each RodRows -- should already be the same width. verticalMerge :: Seq RodRows -> RodRows -- | A Box is the central building block. It consists of zero or -- more payloads; each payload has the same orientation, which is either -- Horizontal or Vertical. This orientation also determines -- the orientation of the entire Box. -- -- A Box is a Monoid so you can combine them using the -- usual monoid functions. For a Box Vertical, the leftmost -- values added with mappend are at the top of the Box; for -- a Box Horizontal, the leftmost values added with -- mappend are on the left side of the Box. newtype Box a Box :: Seq (Payload a) -> Box a -- | This typeclass is responsible for transforming a Box into -- Rainbow Chunk so they can be printed to your screen. This -- requires adding appropriate whitespace with the right colors, as well -- as adding newlines in the right places. class Orientation a rodRows :: Orientation a => Box a -> RodRows -- | Builds a one-dimensional box of the given size; its single dimension -- is parallel to the axis. When added to a box, it will insert blank -- space of the given length. For a Box Horizontal, this -- produces a horizontal line; for a Box Vertical, a -- vertical line. spacer :: Orientation a => Radiant -> Int -> Box a -- | Builds a one-dimensional box of the given size; its single dimension -- is perpendicular to the axis. This can be used to make a Box -- Vertical wider or a Box Horizontal taller. spreader :: Orientation a => Alignment a -> Int -> Box a -- | Things that are oriented around a vertical axis. class LeftRight a -- | Length to the left of the vertical axis. port :: LeftRight a => a -> Int -- | Length to the right of the vertical axis. starboard :: LeftRight a => a -> Int -- | Things that are oriented around a horizontal axis. class UpDown a -- | Number of lines above the horizontal axis. above :: UpDown a => a -> Int -- | Number of lines below the horizontal axis. below :: UpDown a => a -> Int -- | Construct a box from a single Chunk. fromChunk :: Alignment a -> Radiant -> Chunk -> Box a -- | Construct a blank box. Useful for adding in background spacers. For -- functions that build one-dimensional boxes, see spacer and -- spreader. blank :: Alignment a -> Radiant -> Height -> Width -> Box a -- | Wrap a Box in another Box. Useful for changing a -- Horizontal Box to a Vertical one, or simply for -- putting a Box inside another one to control size and background -- color. wrap :: Orientation a => Alignment b -> Radiant -> Box a -> Box b -- | Convert a box to a Seq of Chunk in preparation for -- rendering. Use toList to convert the Seq of Chunk -- to a list so that you can print it using the functions in -- Rainbow. render :: Orientation a => Box a -> Seq Chunk -- | Renders a Box to the given Handle. This uses -- hPutChunks so consult that function for more details on how -- this works; generally it is going to use the maximum number of colors -- possible for your terminal. hPutBox :: Orientation a => Handle -> Box a -> IO () -- | Uses hPutBox to render the given Box to standard output. putBox :: Orientation a => Box a -> IO () -- | A single cell in a spreadsheet-like grid. data Cell Cell :: Seq (Seq Chunk) -> Alignment Horizontal -> Alignment Vertical -> Radiant -> Cell -- | The cell can have multiple rows of text; there is one Seq for -- each row of text. [_rows] :: Cell -> Seq (Seq Chunk) -- | How this Cell should align compared to other Cell in its -- row. [_horizontal] :: Cell -> Alignment Horizontal -- | How this Cell should align compared to other Cell in its -- column. [_vertical] :: Cell -> Alignment Vertical -- | Background color for this cell. The background in the individual -- Chunk in the cellRows are not affected by -- cellBackground; instead, cellBackground determines -- the color of necessary padding that will be added so that the cells -- make a uniform table. [_background] :: Cell -> Radiant rows :: Lens' Cell (Seq (Seq Chunk)) horizontal :: Lens' Cell (Alignment Horizontal) vertical :: Lens' Cell (Alignment Vertical) background :: Lens' Cell Radiant -- | Creates a blank Cell with the given background color and width; -- useful for adding separators between columns. separator :: Radiant -> Int -> Cell -- | Create a table where each inner Seq is a row of cells, from -- left to right. If necessary, blank cells are added to the end of a row -- to ensure that each row has the same number of cells as the longest -- row. tableByRows :: Seq (Seq Cell) -> Box Vertical rowToBoxV :: Box Horizontal -> Box Vertical cellToBoxV :: Cell -> (Box Vertical, Alignment Horizontal, Radiant) toBoxH :: (Box Vertical, Alignment Horizontal, Radiant) -> Box Horizontal addWidthMap :: Seq (Seq (Box Vertical, b, c)) -> (Map Int (Int, Int), Seq (Seq (Box Vertical, b, c))) padBoxV :: Map Int (Int, Int) -> Seq (Seq (Box Vertical, a, b)) -> Seq (Seq (Box Vertical, a, b)) widestCellMap :: Seq (Seq (Box Vertical)) -> Map Int (Int, Int) -- | Create a table where each inner Seq is a column of cells, from -- top to bottom. If necessary, blank cells are added to the end of a -- column to ensure that each column has the same number of cells as the -- longest column. tableByColumns :: Seq (Seq Cell) -> Box Horizontal rowToBoxH :: Box Vertical -> Box Horizontal cellToBoxH :: Cell -> (Box Horizontal, Alignment Vertical, Radiant) addHeightMap :: Seq (Seq (Box Horizontal, b, c)) -> (Map Int (Int, Int), Seq (Seq (Box Horizontal, b, c))) tallestCellMap :: Seq (Seq (Box Horizontal)) -> Map Int (Int, Int) padBoxH :: Map Int (Int, Int) -> Seq (Seq (Box Horizontal, a, b)) -> Seq (Seq (Box Horizontal, a, b)) toBoxV :: (Box Horizontal, Alignment Vertical, Radiant) -> Box Vertical -- | Ensures that each inner Seq is the same length by adding the -- given empty element where needed. equalize :: a -> Seq (Seq a) -> Seq (Seq a) mconcatSeq :: Monoid a => Seq a -> a instance GHC.Show.Show Rainbox.Core.Cell instance GHC.Classes.Ord Rainbox.Core.Cell instance GHC.Classes.Eq Rainbox.Core.Cell instance GHC.Show.Show a => GHC.Show.Show (Rainbox.Core.Box a) instance GHC.Classes.Ord a => GHC.Classes.Ord (Rainbox.Core.Box a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Rainbox.Core.Box a) instance GHC.Show.Show a => GHC.Show.Show (Rainbox.Core.Payload a) instance GHC.Classes.Ord a => GHC.Classes.Ord (Rainbox.Core.Payload a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Rainbox.Core.Payload a) instance GHC.Show.Show Rainbox.Core.RodRows instance GHC.Classes.Ord Rainbox.Core.RodRows instance GHC.Classes.Eq Rainbox.Core.RodRows instance GHC.Show.Show Rainbox.Core.Rod instance GHC.Classes.Ord Rainbox.Core.Rod instance GHC.Classes.Eq Rainbox.Core.Rod instance GHC.Show.Show Rainbox.Core.Core instance GHC.Classes.Ord Rainbox.Core.Core instance GHC.Classes.Eq Rainbox.Core.Core instance GHC.Show.Show Rainbox.Core.Width instance GHC.Classes.Ord Rainbox.Core.Width instance GHC.Classes.Eq Rainbox.Core.Width instance GHC.Show.Show Rainbox.Core.Height instance GHC.Classes.Ord Rainbox.Core.Height instance GHC.Classes.Eq Rainbox.Core.Height instance GHC.Show.Show Rainbox.Core.Vertical instance GHC.Classes.Ord Rainbox.Core.Vertical instance GHC.Classes.Eq Rainbox.Core.Vertical instance GHC.Show.Show Rainbox.Core.Horizontal instance GHC.Classes.Ord Rainbox.Core.Horizontal instance GHC.Classes.Eq Rainbox.Core.Horizontal instance Data.Traversable.Traversable Rainbox.Core.Alignment instance Data.Foldable.Foldable Rainbox.Core.Alignment instance GHC.Base.Functor Rainbox.Core.Alignment instance GHC.Show.Show a => GHC.Show.Show (Rainbox.Core.Alignment a) instance GHC.Classes.Ord a => GHC.Classes.Ord (Rainbox.Core.Alignment a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Rainbox.Core.Alignment a) instance GHC.Base.Semigroup Rainbox.Core.Cell instance GHC.Base.Monoid Rainbox.Core.Cell instance Rainbox.Core.UpDown (Rainbox.Core.Payload Rainbox.Core.Horizontal) instance Rainbox.Core.UpDown (Rainbox.Core.Box Rainbox.Core.Horizontal) instance Rainbox.Core.HasHeight (Rainbox.Core.Box Rainbox.Core.Horizontal) instance Rainbox.Core.LeftRight (Rainbox.Core.Payload Rainbox.Core.Vertical) instance Rainbox.Core.LeftRight (Rainbox.Core.Box Rainbox.Core.Vertical) instance Rainbox.Core.HasWidth (Rainbox.Core.Box Rainbox.Core.Vertical) instance Rainbox.Core.Orientation Rainbox.Core.Vertical instance Rainbox.Core.Orientation Rainbox.Core.Horizontal instance GHC.Base.Semigroup (Rainbox.Core.Box a) instance GHC.Base.Monoid (Rainbox.Core.Box a) instance Rainbox.Core.HasHeight (Rainbox.Core.Box Rainbox.Core.Vertical) instance Rainbox.Core.HasWidth (Rainbox.Core.Box Rainbox.Core.Horizontal) instance Rainbox.Core.HasWidth (Rainbox.Core.Payload a) instance Rainbox.Core.HasHeight (Rainbox.Core.Payload a) instance Rainbox.Core.HasHeight Rainbox.Core.RodRows instance Rainbox.Core.HasWidth Rainbox.Core.RodRows instance Rainbox.Core.HasWidth Rainbox.Core.Rod instance Rainbox.Core.HasWidth Rainbox.Core.Core instance Rainbox.Core.HasHeight Rainbox.Core.Core instance Rainbox.Core.HasWidth Rainbox.Core.Width instance Rainbox.Core.HasWidth Rainbow.Types.Chunk instance (Rainbox.Core.HasWidth a, Rainbox.Core.HasWidth b) => Rainbox.Core.HasWidth (Data.Either.Either a b) instance Rainbox.Core.HasHeight Rainbox.Core.Height instance Rainbox.Core.HasHeight Rainbow.Types.Chunk instance (Rainbox.Core.HasHeight a, Rainbox.Core.HasHeight b) => Rainbox.Core.HasHeight (Data.Either.Either a b) instance GHC.Base.Semigroup (Rainbox.Core.Alignment a) instance GHC.Base.Monoid (Rainbox.Core.Alignment a) -- | Typically to use Rainbox you will want these imports: -- --
--   import qualified Data.Sequence as Seq
--   import Rainbow
--   import Rainbox
--   
--   -- and, for GHC before 7.10:
--   import Data.Monoid
--   
-- -- Rainbox does not re-export anything from Data.Sequence or -- Rainbow because I don't know if you want all those things -- dumped into the same namespace. -- -- Rainbox.Tutorial wil get you started. Rainbox.Core -- contains the implementation details, which you should not need to pay -- attention to (if you do need to use Rainbox.Core for ordinary -- usage of the library, that's a bug; please report it.) module Rainbox -- | Alignment. Used in conjunction with Horizontal and -- Vertical, this determines how a payload aligns with the axis of -- a Box. data Alignment a -- | Determines how a payload aligns with a horizontal axis. data Horizontal -- | Determines how a payload aligns with a vertical axis. data Vertical -- | Place this payload so that it is centered on the vertical axis or -- horizontal axis. center :: Alignment a -- | Place this payload's left edge on the vertical axis. left :: Alignment Vertical -- | Place this payload's right edge on the vertical axis. right :: Alignment Vertical -- | Place this payload's top edge on the horizontal axis. top :: Alignment Horizontal -- | Place this payload's bottom edge on the horizontal axis. bottom :: Alignment Horizontal -- | Center horizontally; like center, but monomorphic. centerH :: Alignment Horizontal -- | Center vertically; like center, but monomorphic. centerV :: Alignment Vertical -- | A Box is the central building block. It consists of zero or -- more payloads; each payload has the same orientation, which is either -- Horizontal or Vertical. This orientation also determines -- the orientation of the entire Box. -- -- A Box is a Monoid so you can combine them using the -- usual monoid functions. For a Box Vertical, the leftmost -- values added with mappend are at the top of the Box; for -- a Box Horizontal, the leftmost values added with -- mappend are on the left side of the Box. data Box a -- | This typeclass is responsible for transforming a Box into -- Rainbow Chunk so they can be printed to your screen. This -- requires adding appropriate whitespace with the right colors, as well -- as adding newlines in the right places. class Orientation a -- | Builds a one-dimensional box of the given size; its single dimension -- is parallel to the axis. When added to a box, it will insert blank -- space of the given length. For a Box Horizontal, this -- produces a horizontal line; for a Box Vertical, a -- vertical line. spacer :: Orientation a => Radiant -> Int -> Box a -- | Builds a one-dimensional box of the given size; its single dimension -- is perpendicular to the axis. This can be used to make a Box -- Vertical wider or a Box Horizontal taller. spreader :: Orientation a => Alignment a -> Int -> Box a -- | Construct a box from a single Chunk. fromChunk :: Alignment a -> Radiant -> Chunk -> Box a -- | Construct a blank box. Useful for adding in background spacers. For -- functions that build one-dimensional boxes, see spacer and -- spreader. blank :: Alignment a -> Radiant -> Height -> Width -> Box a -- | Wrap a Box in another Box. Useful for changing a -- Horizontal Box to a Vertical one, or simply for -- putting a Box inside another one to control size and background -- color. wrap :: Orientation a => Alignment b -> Radiant -> Box a -> Box b -- | Convert a box to a Seq of Chunk in preparation for -- rendering. Use toList to convert the Seq of Chunk -- to a list so that you can print it using the functions in -- Rainbow. render :: Orientation a => Box a -> Seq Chunk -- | Uses hPutBox to render the given Box to standard output. putBox :: Orientation a => Box a -> IO () -- | Renders a Box to the given Handle. This uses -- hPutChunks so consult that function for more details on how -- this works; generally it is going to use the maximum number of colors -- possible for your terminal. hPutBox :: Orientation a => Handle -> Box a -> IO () -- | A single cell in a spreadsheet-like grid. data Cell Cell :: Seq (Seq Chunk) -> Alignment Horizontal -> Alignment Vertical -> Radiant -> Cell -- | The cell can have multiple rows of text; there is one Seq for -- each row of text. [_rows] :: Cell -> Seq (Seq Chunk) -- | How this Cell should align compared to other Cell in its -- row. [_horizontal] :: Cell -> Alignment Horizontal -- | How this Cell should align compared to other Cell in its -- column. [_vertical] :: Cell -> Alignment Vertical -- | Background color for this cell. The background in the individual -- Chunk in the cellRows are not affected by -- cellBackground; instead, cellBackground determines -- the color of necessary padding that will be added so that the cells -- make a uniform table. [_background] :: Cell -> Radiant -- | Creates a blank Cell with the given background color and width; -- useful for adding separators between columns. separator :: Radiant -> Int -> Cell rows :: Lens' Cell (Seq (Seq Chunk)) horizontal :: Lens' Cell (Alignment Horizontal) vertical :: Lens' Cell (Alignment Vertical) background :: Lens' Cell Radiant -- | Create a table where each inner Seq is a row of cells, from -- left to right. If necessary, blank cells are added to the end of a row -- to ensure that each row has the same number of cells as the longest -- row. tableByRows :: Seq (Seq Cell) -> Box Vertical -- | Create a table where each inner Seq is a column of cells, from -- top to bottom. If necessary, blank cells are added to the end of a -- column to ensure that each column has the same number of cells as the -- longest column. tableByColumns :: Seq (Seq Cell) -> Box Horizontal -- | The Rainbox tutorial -- -- Rainbox helps you create arrangements of (possibly) colorful text -- boxes. This module contains a tutorial. Typically the Rainbox -- module contains all you need. There is also a Rainbox.Core -- module which contains all the innards of Rainbox, but ordinarily you -- won't need it. -- -- The basic building block of Rainbox is known as a core. A -- core is either a single Chunk or a blank box of arbitrary -- size. A core made of a single Chunk should not contain any -- newlines. Leave newline handling up to Rainbox. However, Rainbox will -- not check to ensure that your Chunk does not contain any -- newline characters. If it does contain newlines, your boxes will not -- look right. Also, Rainbox needs to know how wide your Chunk -- are, in columns. To measure width, Rainbox simply counts the number of -- characters in the Chunk. Therefore, if you need accented -- characters, be sure to use a single character, not composed -- characters. That is, to get รก, use U+00E1, not U+00B4 and U+0061. -- -- Many things in Rainbox have height and width. Both the height and -- width of an object can be zero, but never less than zero. A -- core made from a Chunk always has a height of 1, and -- its width is equal to the number of characters in the Texts -- that make up the Chunk. A core made from a blank box -- has the height and width that you give it, though neither its height -- nor its width is ever smaller than zero. -- -- The next biggest building block after the core is -- payload. There are two different types of payloads: vertical -- payloads and horizontal ones. A vertical payload aligns itself next to -- other vertical payloads on a vertical axis, creating a chain of -- payloads. The vertical payload also has an alignment. The alignment -- determines whether the payload lines up along the axis on its left -- side, right side, or in the center of the payload. -- -- The vertical payload also has a background color, which has type -- Radiant. Think of the background color as extending -- infinitely from both the left and right side of the vertical payload. -- When the vertical payload is combined with other vertical payloads -- into a Box Vertical, this background color is used -- as necessary so that the Box Vertical forms a -- rectangle. -- -- The horizontal payload is similar to the vertical payload, but the -- axis is horizontal rather than vertical. The alignment determines -- whether the payload aligns the axis along the top, center, or bottom -- of the payload. A horizontal payload also contains a background color; -- it extends infinitely from both the top and bottom of the horizontal -- payload. -- -- Finally, the biggest building block of Rainbox is the box. There are -- two types of boxes: a Box Horizontal, which holds -- zero or more horizontal payloads, and a Box -- Vertical, which holds zero or more vertical payloads. Each -- kind of box is a Monoid, so you can combine it using the usual -- monoid functions. So, to give a visual, a Box -- Vertical with five payloads might look like this: -- --
--   -- function: box1
--   
--              V Vertical axis
--   
--              +----+
--              | v1 |
--              |    |
--              +----+--------+
--              |     v2      |
--              |             |
--     +--------+-------------+
--     |        |
--     |  v3    |
--     |        |
--     |        |
--     +--------+----------+
--              |    v4    |
--         +----+----+-----+
--         | v5      |
--         |         |
--         +---------+
--   
-- -- Each payload is marked in the middle with v1, v2, -- etc. Note how each payload has a different size. v1 and -- v2, and v4 have a left alignment, as their -- left edge is lined up with the vertical axis. v3 has a -- right alignment. v5 has a center alignment. -- Think of each payload has having a background color extending -- infinitely off of its left and right sides. These five payloads put -- together make a Box Vertical. Since Box -- Vertical is a monoid, you can combine various Box -- Vertical. Indeed, the pictured Box Vertical -- can be built only by combining smaller Box Vertical, -- as when you create payloads they are always given to you as a single -- payload wrapped in a Box Vertical. -- -- Now, you want to render your Box Vertical. You use -- the render function, which makes a sequence of Rainbow -- Chunk. This turns your Box Vertical into a -- nice rectangle for on-screen rendering: -- --
--   -- function: renderBox1
--   
--     +--------+----+--------+
--     |        | v1 |        |
--     |        |    |        |
--     +--------+----+--------+
--     |        |     v2      |
--     |        |             |
--     +--------+-------------+
--     |        |             |
--     |  v3    |             |
--     |        |             |
--     |        |             |
--     +--------+----------+--+
--     |        |    v4    |  |
--     +---+----+----+-----+--+
--     |   | v5      |        |
--     |   |         |        |
--     +---+---------+--------+
--   
-- -- The spaces to the left and right of each payload are filled in with -- the appropriate background color, which is the background color of the -- adjoining payload. -- -- What if you want to place the Box Vertical alongside -- another box? If you want to put it next to another Box -- Vertical, just use mappend or <>. But -- what if you want to put it next to a Box Horizontal? -- Let's suppose you have a Box Horizontal that looks -- like this: -- --
--   -- function: box2
--   
--                           +----+
--                           | h1 |
--                           |    |
--   Horizontal Axis >       +----+----------+
--                                |          |
--                                |   h2     |
--                                |          |
--                                +----------+
--   
-- -- The h1 payload has alignment bottom, because its -- bottom edge is lined up along the horizontal axis. The h2 -- payload has alignment top. You want to connect this -- Box Horizontal with the Box -- Vertical made above. You can't connect them directly because -- they are different types. You can, however, take a complete -- Box and wrap it inside another Box. This allows you -- to wrap a Box Vertical inside of a Box -- Horizontal, and vice versa, or even wrap a Box -- Horizontal inside of another Box -- Horizontal. You do this with the wrap function, -- which is applied to the alignment for the new box, its background -- color, and the box you want to wrap. ao, let's say you take the -- Box Vertical created above and wrap it inside a -- Box Horizontal with top alignment and a -- background color, and then you combine it with the Box -- Horizontal created above. The result: -- --
--   -- function: box3
--   
--                            +----+
--                            | h1 |
--                            |    |
--     +--------+----+--------+----+----------+
--     |        | v1 |        |    |          |
--     |        |    |        |    |    h2    |
--     +--------+----+--------+    |          |
--     |        |     v2      |    +----------+
--     |        |             |
--     +--------+-------------+
--     |        |             |
--     |  v3    |             |
--     |        |             |
--     |        |             |
--     +--------+----------+--+
--     |        |    v4    |  |
--     +---+----+----+-----+--+
--     |   | v5      |        |
--     |   |         |        |
--     +---+---------+--------+
--   
-- -- The old Box Vertical, which is now wrapped in a -- Box Horizontal, now has a background color which -- extends infinitely from the top and bottom of the box. It is now just -- a payload inside of the Box Horizontal. The other -- two payloads in the Box Horizontal, h1 and -- h2, also have background colors extending from their tops and -- bottoms. -- -- So, when you render this Box Horizontal with -- render, you get this: -- --
--   -- function: renderBox3
--   
--     +----------------------+----+----------+
--     |                      | h1 |          |
--     |                      |    |          |
--     +--------+----+--------+----+----------+
--     |        | v1 |        |    |          |
--     |        |    |        |    |    h2    |
--     +--------+----+--------+    |          |
--     |        |     v2      |    +----------+
--     |        |             |    |          |
--     +--------+-------------+    |          |
--     |        |             |    |          |
--     |  v3    |             |    |          |
--     |        |             |    |          |
--     |        |             |    |          |
--     +--------+----------+--+    |          |
--     |        |    v4    |  |    |          |
--     +---+----+----+-----+--+    |          |
--     |   | v5      |        |    |          |
--     |   |         |        |    |          |
--     +---+---------+--------+----+----------+
--   
-- -- The area above the old Box Vertical has the -- background color that we used in the application of convert. -- The area below the h1 payload has its background color, and -- the area above and below the h2 payload has its background -- color. -- -- What if you just want to create an empty space? You can create entire -- blank boxes with blank, but often it is enough to use -- spacer, which gives you a one-dimensional Box -- Horizontal or Box Vertical. If you are -- creating a Box Horizontal, spacer gives you -- a box with width, but no height; for a Box Vertical, -- you get a box with height, but no width. So, to return to the example -- Box Horizontal, let's say you want to add a blank -- space a few columns wide on the right side. You mappend a -- Box Horizontal created with spacer to get -- this: -- --
--   -- function: box4
--   
--                           +----+
--                           | h1 |
--                           |    |
--   Horizontal Axis >       +----+----------+--+
--                                |          |
--                                |   h2     |
--                                |          |
--                                +----------+
--   
-- -- On the right side you now have a payload with width, but no height. -- But it does have a background color. So when you render the -- box, you get this: -- --
--   -- function: renderBox4
--   
--                           +----+----------+--+
--                           | h1 |          |  |
--                           |    |          |  |
--                           +----+----------+  |
--                           |    |          |  |
--                           |    |   h2     |  |
--                           |    |          |  |
--                           +----+----------+--+
--   
-- -- You can also use spreader to make a Box -- Horizontal taller or a Box Vertical wider. -- spreader creates a one-dimensional Box that is -- perpendicular to the axis. Pay attention to the alignment of the -- spreader as this will determine how your box expands. Let's -- say I want to take the Box that contains the h1 and -- h2 payloads as created above, but I also want to make sure -- the box is at least 12 rows tall. To do this, mappend a -- spreader that is 12 rows tall. The result upon -- rendering is: -- --
--                           
--   -- functions: box5 renderBox5
--   
--                           +----+----------+--+
--                           |    |          |  |
--                           +----+          |  |
--                           | h1 |          |  |
--                           |    |          |  |
--                           +----+----------+  |
--                           |    |          |  |
--                           |    |   h2     |  |
--                           |    |          |  |
--                           |    +----------+  |
--                           |    |          |  |
--                           +----+----------+--+
--   
-- -- Those are the basics of the Rainbox model, which should be enough to -- get you started. Also helpful are the tableByRows and -- tableByColumns functions, which will help you build a simple -- grid that resembles a spreadsheet; see its documentation for hints to -- get started with that. You will also find an example using the -- tableByRows, as well as code to produce all of the examples -- shown above, in the source code below. -- --

Why the use of Seq everywhere, rather than lists?

-- -- Rainbox uses Seq from Data.Sequence because lists can be -- infinite. Practically every function in Rainbox will not accept -- infinite inputs, because Rainbox needs to know exactly how long and -- wide various payloads and boxes are in order to line them up -- correctly. Use of the Seq most accurately reflects the fact -- that Rainbox does not work on infinite inputs. module Rainbox.Tutorial -- | Create a Box for the given text. The default foreground and -- background colors of the terminal are used for the Text; the -- given background is used as the background color for any added -- padding. textBox :: Radiant -> Text -> Box a -- | Centers the given Box within a larger Box that has -- the given height and width and background color. The larger -- Box has the given Alignment. within :: Orientation a => Alignment a -> Int -> Int -> Radiant -> Box a -> Box a -- | Puts the given text in the center of a box. The resulting box is -- center aligned. textWithin :: Orientation a => Alignment a -> Int -> Int -> Radiant -> Radiant -> Text -> Box a box1 :: Box Vertical renderBox1 :: IO () box2 :: Box Horizontal renderBox2 :: IO () box3 :: Box Horizontal renderBox3 :: IO () box4 :: Box Horizontal renderBox4 :: IO () box5 :: Box Horizontal renderBox5 :: IO () data Line Red :: Line Blue :: Line Orange :: Line Green :: Line Yellow :: Line Silver :: Line data Station Station :: Text -> [Line] -> [Text] -> Bool -> Station [name] :: Station -> Text [metroLines] :: Station -> [Line] [address] :: Station -> [Text] [underground] :: Station -> Bool nameCell :: Radiant -> Text -> Cell linesCell :: Radiant -> [Line] -> Cell lineRow :: Radiant -> Line -> Seq Chunk addressCell :: Radiant -> [Text] -> Cell undergroundCell :: Radiant -> Bool -> Cell stations :: [Station] coloredBack :: Radiant -- | Converts a Station to a list of Cell. stationRow :: Radiant -> Station -> [Cell] allStationRows :: [[Cell]] verticalStationTable :: Box Vertical renderVerticalStationTable :: IO () stationColumn :: Station -> [Cell] allStationColumns :: [[Cell]] horizontalStationTable :: Box Horizontal renderHorizontalStationTable :: IO () instance GHC.Enum.Enum Rainbox.Tutorial.Line instance GHC.Show.Show Rainbox.Tutorial.Line instance GHC.Classes.Ord Rainbox.Tutorial.Line instance GHC.Classes.Eq Rainbox.Tutorial.Line