headroom-0.1.0.0: src/Headroom/Text.hs
{-|
Module : MODULE_NAME
Description : Extras for text manipulation
Copyright : (c) 2019-2020 Vaclav Svejcar
License : BSD-3
Maintainer : vaclav.svejcar@gmail.com
Stability : experimental
Portability : POSIX
Adds some extra functionality to the "Data.Text" module.
-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
module Headroom.Text
( detectNewLine
, showNewLine
, lines'
, unlines'
)
where
import Headroom.Types ( NewLine(..) )
import RIO
import RIO.Text ( isInfixOf )
import qualified RIO.Text as T
import qualified RIO.Text.Partial as TP
-- | Detects which newline character is used in given text (if any).
--
-- >>> detectNewLine "foo\nbar"
-- Just LF
detectNewLine :: Text -- ^ input text
-> Maybe NewLine -- ^ detected newline character
detectNewLine text | showNewLine CRLF `isInfixOf` text = Just CRLF
| showNewLine CR `isInfixOf` text = Just CR
| showNewLine LF `isInfixOf` text = Just LF
| otherwise = Nothing
-- | Renders appropriate newline character (e.g. @\n@) for given 'NewLine'
-- representation.
--
-- >>> showNewLine LF
-- "\n"
showNewLine :: NewLine -- ^ newline character to render
-> Text -- ^ rendered character
showNewLine = \case
CR -> "\r"
CRLF -> "\r\n"
LF -> "\n"
-- | Split text into lines, return lines and detected newline separator.
--
-- >>> lines' "foo\nbar"
-- (LF,["foo","bar"])
lines' :: Text -- ^ text to split
-> (NewLine, [Text]) -- ^ detected newline separator and split lines
lines' text = (newLine, chunks)
where
newLine = fromMaybe LF (detectNewLine text)
chunks = TP.splitOn (showNewLine newLine) text
-- | Join individual text lines into single text, using given newline separator.
--
-- >>> unlines' LF ["foo", "bar"]
-- "foo\nbar"
unlines' :: NewLine -> [Text] -> Text
unlines' newLine = T.intercalate $ showNewLine newLine