packages feed

lipstick-0.1.0.0: src/Lipstick/Mod.hs

-- | Modifiers, in the style of optparse-applicative's builder.
--
-- A @'Mod' f@ is a change to a thing @f@ (a 'Lipstick.Style.Style', a
-- 'Lipstick.Table.Table', a 'Lipstick.Place.Place', …). Modifiers form a
-- monoid in which the later setting wins, so styles are built and extended
-- with '<>':
--
-- > card :: Mod Style
-- > card = bold <> fg "#FAFAFA" <> bg "#7D56F4" <> padding 1 2
-- >
-- > warning :: Mod Style
-- > warning = card <> bg "#F25D94"
--
-- As in optparse-applicative's @Mod@, a change to the properties every
-- thing has is kept apart from a change to the thing's own fields:
--
-- * the properties every thing has are text attributes and the
--   'maxWidth' / 'maxHeight' crop. Text attributes, such as 'fg' or
--   'bold', can be set on any thing, and the crop on any thing but
--   'Lipstick.Block.Inline' text ('HasCrop'). Each thing's text attributes
--   are the base for what it draws (for a style, only its content: see
--   'Lipstick.Style.Style'), overridden by anything more specific inside
--   it (a cell style, an item style, the attributes of a placed block).
--
-- * modifiers of fields that several things have go through the classes
--   'HasBox', 'HasBorder', 'HasSize', 'HasAlign' and 'HasWrap'; the rest,
--   such as 'Lipstick.Table.cellStyle', belong to one thing.
--
-- == Examples
--
-- The examples print with 'Lipstick.Terminal.putBlock'; the output is
-- shown without colours and other attributes.
--
-- Text attributes work on any thing:
--
-- >>> let base = bold <> fg red
-- >>> putBlock (render (base <> border normalBorder) "a style")
-- ┌───────┐
-- │a style│
-- └───────┘
-- >>> putBlock (table base ["a table"] [["cell"]])
-- ╭───────╮
-- │a table│
-- ├───────┤
-- │cell   │
-- ╰───────╯
-- >>> putBlock (list base ["a list"])
-- • a list
--
-- Padding and margins are given as vertical then horizontal amounts, or
-- per side:
--
-- >>> putBlock (render (border normalBorder <> padding 0 3) "wide")
-- ┌──────────┐
-- │   wide   │
-- └──────────┘
-- >>> putBlock (render (border normalBorder <> paddingLeft 4) "indented")
-- ┌────────────┐
-- │    indented│
-- └────────────┘
--
-- Borders, and which of their sides are drawn:
--
-- >>> putBlock (render (border roundedBorder <> borderBottom False) "open below")
-- ╭──────────╮
-- │open below│
--
-- 'width' is the width with padding and border. The thing shrinks when
-- there is less room:
--
-- >>> let note = render (width 24 <> border normalBorder) "Wraps to its width"
-- >>> putBlock note
-- ┌──────────────────────┐
-- │Wraps to its width    │
-- └──────────────────────┘
-- >>> putBlock (fromGrid (layout (Just 14) note))
-- ┌────────────┐
-- │Wraps to its│
-- │width       │
-- └────────────┘
--
-- 'maxWidth' and 'maxHeight' crop the result:
--
-- >>> putBlock (render (border normalBorder <> maxWidth 6) "cropped")
-- ┌─────
-- │cropp
-- └─────
--
-- Alignment of content in a box that is larger than it:
--
-- >>> putBlock (render (width 12 <> height 5 <> border normalBorder <> align right <> valign bottom) "corner")
-- ┌──────────┐
-- │          │
-- │          │
-- │    corner│
-- └──────────┘
--
-- An @unset@ modifier undoes a setting made earlier:
--
-- >>> let boxed = border normalBorder <> padding 0 1
-- >>> putBlock (render (boxed <> unsetBorder) "no border")
--  no border
module Lipstick.Mod
  ( Mod
  , HasBox
  , HasBorder
  , HasSize
  , HasAlign
  , HasWrap
  , HasCrop
  , Sides (..)

    -- * Text attributes
  , bold
  , faint
  , italic
  , blink
  , reverseVideo
  , strikethrough
  , Flag (..)
  , flag
  , unsetFlag
  , underline
  , Underline (..)
  , underlineStyle
  , underlineColor
  , fg
  , bg
  , unsetFg
  , unsetBg
  , unsetUnderline
  , unsetUnderlineColor
  , link
  , unsetLink

    -- * Padding and margins
  , padding
  , paddingAll
  , paddingTop
  , paddingRight
  , paddingBottom
  , paddingLeft
  , margin
  , marginAll
  , marginTop
  , marginRight
  , marginBottom
  , marginLeft
  , marginBg
  , paddingChar
  , marginChar
  , unsetPadding
  , unsetMargins
  , unsetMarginBg

    -- * Borders
  , border
  , borderFg
  , borderBg
  , borderFgBlend
  , borderFgBlendOffset
  , borderTopFg
  , borderRightFg
  , borderBottomFg
  , borderLeftFg
  , borderTopBg
  , borderRightBg
  , borderBottomBg
  , borderLeftBg
  , unsetBorder
  , borderTop
  , borderRight
  , borderBottom
  , borderLeft

    -- * Size
  , width
  , height
  , maxWidth
  , maxHeight
  , grow
  , fillWidth
  , stretchHeight
  , unsetWidth
  , unsetHeight
  , unsetMaxWidth
  , unsetMaxHeight

    -- * Alignment
  , align
  , valign
  , unsetAlign
  , Position
  , position
  , left
  , center
  , right
  , top
  , bottom

    -- * Wrapping
  , noWrap
  , unsetNoWrap
  ) where

import Lipstick.Internal.Mod
import Lipstick.Internal.Types (Flag (..), Position, Underline (..), bottom, center, left, position, right, top)

-- $setup
-- >>> import Lipstick