byline-1.1.2: src/Byline.hs
-- |
--
-- Copyright:
-- This file is part of the package addy. It is subject to the license
-- terms in the LICENSE file found in the top-level directory of this
-- distribution and at:
--
-- https://github.com/pjones/byline
--
-- No part of this package, including this file, may be copied,
-- modified, propagated, or distributed except according to the terms
-- contained in the LICENSE file.
--
-- License: BSD-2-Clause
module Byline
( -- * How to Use this Library
-- $use
-- * Byline Class and Transformer
MonadByline,
BylineT,
runBylineT,
-- * Basic User Interaction
say,
sayLn,
askLn,
askChar,
askPassword,
askUntil,
-- * Stylizing Modifiers
Stylized,
ToStylizedText (..),
text,
fg,
bg,
bold,
underline,
swapFgBg,
-- * Colors
Color,
black,
red,
green,
yellow,
blue,
magenta,
cyan,
white,
vivid,
dull,
rgb,
)
where
import Byline.Internal.Color
import Byline.Internal.Eval (BylineT, MonadByline (..), runBylineT)
import qualified Byline.Internal.Prim as Prim
import Byline.Internal.Stylized
-- | Output the given stylized text.
--
-- See also: 'sayLn'.
--
-- @since 1.0.0.0
say ::
(MonadByline m, ToStylizedText a) =>
-- | The stylized text to output.
a ->
m ()
say =
toStylizedText
>>> Prim.say
>>> liftByline
-- | Like 'say', but append a newline character.
--
-- @since 1.0.0.0
sayLn ::
(MonadByline m, ToStylizedText a) =>
-- | The stylized text to output. An appropirate line ending
-- character will be added to the end of this text.
a ->
m ()
sayLn =
toStylizedText
>>> Prim.sayLn
>>> liftByline
-- | Read a line of input after printing the given stylized text as a
-- prompt.
--
-- @since 1.0.0.0
askLn ::
(MonadByline m, ToStylizedText a) =>
-- | The prompt.
a ->
-- | The text to return if the user does not enter a response.
Maybe Text ->
-- | User input (or default answer).
m Text
askLn prompt def = liftByline (Prim.askLn (toStylizedText prompt) def)
-- | Read a single character of input.
--
-- @since 1.0.0.0
askChar ::
(MonadByline m, ToStylizedText a) =>
-- | The prompt to display.
a ->
m Char
askChar =
toStylizedText
>>> Prim.askChar
>>> liftByline
-- | Read a password without echoing it to the terminal. If a masking
-- character is given it will replace each typed character.
--
-- @since 1.0.0.0
askPassword ::
(MonadByline m, ToStylizedText a) =>
-- | The prompt to display.
a ->
-- | Optional masking character that will be printed each time the
-- user presses a key. When 'Nothing' is given the default behavior
-- will be used which is system dependent but usually results in no
-- characters being echoed to the terminal.
Maybe Char ->
m Text
askPassword prompt =
Prim.askPassword (toStylizedText prompt)
>>> liftByline
-- | Continue to prompt for a response until a confirmation function
-- returns a valid result.
--
-- @since 1.0.0.0
askUntil ::
(MonadByline m, ToStylizedText a, ToStylizedText e) =>
-- | The prompt to display.
a ->
-- | The default answer if the user presses enter without typing
-- anything.
Maybe Text ->
-- | A function to validate the user input. If the user input is
-- acceptable the function should return 'Right'. If the input is
-- invalid then it should return 'Left' with an error message to
-- display. The error message will be printed with 'sayLn'.
(Text -> m (Either e b)) ->
m b
askUntil prompt def confirm = go
where
go = do
answer <- askLn prompt def
confirm answer >>= \case
Left msg -> sayLn msg >> go
Right res -> pure res
-- $use
--
-- Byline provides a monad transformer that allows you to compose
-- interactive terminal actions. When producing output,
-- these actions accept stylized text that can include
-- foreground and background colors, underlined text, and
-- bold text.
--
-- Stylized text can be constructed with string literals
-- (using the @OverloadedStrings@ extension) or using the
-- 'text' function. Attributes such as color can be changed
-- using modifier functions and the 'Semigroup' @(<>)@ operator.
--
-- Actions that read user input can work with completion
-- functions which are activated when the user presses the
-- tab key. Most input actions also support default values
-- that will be returned when the user presses the enter key
-- without providing any input.
--
-- Example:
--
-- @
-- {-\# LANGUAGE OverloadedStrings \#-}
--
-- example :: MonadByline m => m Text
-- example = do
-- sayLn ("Hey, I like " <> ("Haskell" <> fg magenta) <> "!")
--
-- let question =
-- "What's "
-- <> ("your" <> bold)
-- <> " favorite "
-- <> ("language" <> fg green <> underline)
-- <> "? "
--
-- askLn question (Just "Haskell")
-- @
--
-- More complete examples can be found in the @examples@
-- directory of the distribution tarball or in the
-- repository.