{-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE OverloadedStrings #-} {-| Module : Headroom.Data.TextExtra Description : Additional utilities for text manipulation Copyright : (c) 2019-2020 Vaclav Svejcar License : BSD-3-Clause Maintainer : vaclav.svejcar@gmail.com Stability : experimental Portability : POSIX Module containing bunch of useful functions for working with text. -} module Headroom.Data.TextExtra ( read -- * Working with text lines , mapLines , fromLines , toLines ) where import RIO import qualified RIO.Text as T -- | Maps given function over individual lines of the given text. -- -- >>> mapLines ("T: " <>) "foo zz\nbar" -- "T: foo zz\nT: bar" mapLines :: (Text -> Text) -- ^ function to map over individual lines -> Text -- ^ input text -> Text -- ^ result text mapLines fn = fromLines . go . toLines where go [] = [] go (x : xs) = fn x : go xs -- | Same as 'readMaybe', but takes 'Text' as input instead of 'String'. -- -- >>> read "123" :: Maybe Int -- Just 123 read :: Read a => Text -- ^ input text to parse -> Maybe a -- ^ parsed value read = readMaybe . T.unpack -- | Similar to 'T.unlines', but does not automatically adds @\n@ at the end -- of the text. Advantage is that when used together with 'toLines', it doesn't -- ocassionaly change the newlines ad the end of input text: -- -- >>> fromLines . toLines $ "foo\nbar" -- "foo\nbar" -- -- >>> fromLines . toLines $ "foo\nbar\n" -- "foo\nbar\n" -- -- Other examples: -- -- >>> fromLines [] -- "" -- -- >>> fromLines ["foo"] -- "foo" -- -- >>> fromLines ["first", "second"] -- "first\nsecond" -- -- >>> fromLines ["first", "second", ""] -- "first\nsecond\n" fromLines :: [Text] -- ^ lines to join -> Text -- ^ text joined from individual lines fromLines = T.intercalate "\n" -- | Similar to 'T.lines', but does not drop trailing newlines from output. -- Advantage is that when used together with 'fromLines', it doesn't ocassionaly -- change the newlines ad the end of input text: -- -- >>> fromLines . toLines $ "foo\nbar" -- "foo\nbar" -- -- >>> fromLines . toLines $ "foo\nbar\n" -- "foo\nbar\n" -- -- Other examples: -- -- >>> toLines "" -- [] -- -- >>> toLines "first\nsecond" -- ["first","second"] -- -- >>> toLines "first\nsecond\n" -- ["first","second",""] toLines :: Text -- ^ text to break into lines -> [Text] -- ^ lines of input text toLines input | T.null input = [] | otherwise = T.split (== '\n') input