--------------------------------------------------------------------
--
-- Module      :  Strings
-- Copyright   :
--
-- | a module with a class for strings, such that the normal functions are
--  all polymorphic for string and text (and total)
-- the string (i.e. [Char]) functions are the semantic definitions,
-- the other implementation are tested against these.
-- except intercalate, which returns Maybe
-- (the corresponding restrictions for the unlines and unwords functions are not enforced)
--
-- performance can be improved by using the "native" functions
-- could be expanded

-- class niceStrings can be replaced or integrated in the generic strings
-- it may be useful to have more than one show like operation
----------------------------------------------------------------------
{-# LANGUAGE FlexibleContexts      #-}
{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables   #-}
{-# LANGUAGE TypeFamilies          #-}
{-# LANGUAGE OverloadedStrings  #-}
{-# LANGUAGE UndecidableInstances  #-}
{-# LANGUAGE PackageImports  #-}

{-# OPTIONS_GHC -fno-warn-missing-methods #-}
{-# OPTIONS_GHC -w #-}

module Uniform.Strings.Utilities
    (module Uniform.Zero
    , module Uniform.ListForm
    , CharChains (..)
    , CharChains2 (..)
    , NiceStrings (..)
    , unlinesT, unwordsT
    , wordsT,  concatT, showT, readNoteT, readNoteTs
    , sortCaseInsensitive, cmpCaseInsensitive
    , maybe2string
    , showList'
    , putIOwords, debugPrint 
    , T.toTitle
    , toLowerStart, toUpperStart   
    , prop_filterChar
    , isSpace, isLower
    , PrettyStrings (..)
    -- to generalize
    , dropWhile, takeWhile, span, break
    , formatInt
    )
    where

import Uniform.Zero (Zeros(..))
import Uniform.ListForm ( ListForms(..) )


import           Data.Char                (isSpace, isLower, toLower, toUpper)
import           Text.Printf              (PrintfArg, PrintfType, printf)

import Data.List as L
    ( sortBy, intercalate, isInfixOf, isPrefixOf, nub, stripPrefix )
import           GHC.Exts                 (IsString (..))

import qualified Data.List.Split         as S (splitOn)
import Data.Maybe ( catMaybes )
-- import           Data.Monoid
import           Data.Text                (Text)
import qualified Data.Text                as T (head, cons, tail, append, singleton, unwords, words, unlines, lines, empty, toUpper, toLower, concat, isPrefixOf, isInfixOf, stripPrefix, stripSuffix, intercalate, splitOn, strip, dropEnd, reverse, length, filter, take, drop, replace, null, toTitle)
import qualified Data.List.Utils       as LU (replace)
import Safe ( readNote )
import Uniform.Strings.Conversion
    ( Text,
      BSUTF,
      LazyByteString,
      s2t,
      t2s,
      t2bu,
      bu2t,
      bu2s,
      t2b,
      s2bu,
      b2bl )
import qualified Data.ByteString.Lazy as Lazy (append, length, take, drop)
import          Text.Read (readMaybe)
import Text.Show.Pretty ( ppShow ) 
import "monads-tf" Control.Monad.State      (MonadIO, liftIO)
import Control.Monad (when)


readNoteTs :: (Show a, Read a) =>  [Text] -> Text -> a   -- TODO
-- ^ read a Text into a specific format
readNoteTs :: [Text] -> Text -> a
readNoteTs [Text]
msg Text
a = String -> String -> a
forall a. (Partial, Read a) => String -> String -> a
readNote  ([String] -> String
unlines ((Text -> String) -> [Text] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Text -> String
t2s [Text]
msg) String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Text -> String
forall a. Show a => a -> String
show Text
a) (String -> a) -> (Text -> String) -> Text -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
t2s (Text -> a) -> Text -> a
forall a b. (a -> b) -> a -> b
$ Text
a

readNoteT :: Read a =>  Text -> Text -> a   -- TODO
-- ^ read a Text into a specific format
readNoteT :: Text -> Text -> a
readNoteT Text
msg = String -> String -> a
forall a. (Partial, Read a) => String -> String -> a
readNote (Text -> String
t2s Text
msg) (String -> a) -> (Text -> String) -> Text -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
t2s

showList' :: Show a =>  [a] -> Text
-- ^ show a collection of lines
showList' :: [a] -> Text
showList' = [Text] -> Text
forall a. CharChains a => [a] -> a
unlines' ([Text] -> Text) -> ([a] -> [Text]) -> [a] -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Text) -> [a] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map a -> Text
forall a. Show a => a -> Text
showT

toLowerStart :: Text -> Text
-- ^ convert the first character to lowercase - for Properties in RDF
toLowerStart :: Text -> Text
toLowerStart Text
t = (Char -> Char
toLower (Char -> Char) -> (Text -> Char) -> Text -> Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Char
T.head (Text -> Char) -> Text -> Char
forall a b. (a -> b) -> a -> b
$ Text
t) Char -> Text -> Text
`T.cons` Text -> Text
T.tail Text
t

toUpperStart :: Text -> Text
-- ^ convert the first character to Uppercase - for  PosTags in Spanish
toUpperStart :: Text -> Text
toUpperStart Text
t = (Char -> Char
toUpper (Char -> Char) -> (Text -> Char) -> Text -> Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Char
T.head (Text -> Char) -> Text -> Char
forall a b. (a -> b) -> a -> b
$ Text
t) Char -> Text -> Text
`T.cons` Text -> Text
T.tail Text
t

dropLast :: Int -> [a] -> [a]
dropLast :: Int -> [a] -> [a]
dropLast Int
n = [a] -> [a]
forall a. [a] -> [a]
reverse ([a] -> [a]) -> ([a] -> [a]) -> [a] -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
drop Int
n ([a] -> [a]) -> ([a] -> [a]) -> [a] -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> [a]
forall a. [a] -> [a]
reverse

putIOwords :: MonadIO m =>  [Text] -> m ()
putIOwords :: [Text] -> m ()
putIOwords = IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> ([Text] -> IO ()) -> [Text] -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> IO ()
putStrLn (String -> IO ()) -> ([Text] -> String) -> [Text] -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
t2s (Text -> String) -> ([Text] -> Text) -> [Text] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Text] -> Text
forall a. CharChains a => [a] -> a
unwords'

debugPrint :: (MonadIO m) => Bool -> [Text] -> m ()
-- ^ print the texts when the bool is true (flag debug)
debugPrint :: Bool -> [Text] -> m ()
debugPrint Bool
flag [Text]
texts = Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
flag (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ [Text] -> m ()
forall (m :: * -> *). MonadIO m => [Text] -> m ()
putIOwords [Text]
texts 


--instance Zeros String where zero = (""::String)
instance Zeros Text where zero :: Text
zero = Text
"" :: Text

instance ListForms Text where
    type LF Text = Char
    appendTwo :: Text -> Text -> Text
appendTwo = Text -> Text -> Text
T.append
    mkOne :: LF Text -> Text
mkOne = Char -> Text
LF Text -> Text
T.singleton

instance ListForms String where
    type LF String = Char
    appendTwo :: String -> String -> String
appendTwo = String -> String -> String
forall a. [a] -> [a] -> [a]
(++)
    mkOne :: LF String -> String
mkOne = LF String -> String
forall a. Show a => a -> String
show

instance ListForms LazyByteString where
    type LF LazyByteString = Char
--    appendTwo = Lazy.append
    mkOne :: LF LazyByteString -> LazyByteString
mkOne = ByteString -> LazyByteString
b2bl (ByteString -> LazyByteString)
-> (Char -> ByteString) -> Char -> LazyByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
t2b (Text -> ByteString) -> (Char -> Text) -> Char -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Text
T.singleton

instance ListForms BSUTF where
    type LF BSUTF = Char
--    appendTwo a b =  t2bu . appendTwo  (bu2t a) $ bu2t b
    mkOne :: LF BSUTF -> BSUTF
mkOne =  Text -> BSUTF
t2bu (Text -> BSUTF) -> (Char -> Text) -> Char -> BSUTF
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Text
T.singleton

--instance Zeros BSUTF where   -- derived in Conversion
--    zero = t2bu ""

class (Zeros a, ListForms a, Eq a) => CharChains a where
--    {-# MINIMAL   #-}

    toString ::  a -> String
    toText :: Show a => a -> Text
    -- ^ conversion


    unwords' :: [a] -> a
    words' :: a -> [a]
    unlines' :: [a] -> a
    lines' :: a -> [a]
--    punwords :: [a] -> s
    toText = String -> Text
s2t (String -> Text) -> (a -> String) -> a -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> String
forall a. Show a => a -> String
show
    append', append   :: a -> a -> a  -- duplication?
    append = a -> a -> a
forall l. ListForms l => l -> l -> l
appendTwo
    append' = a -> a -> a
forall l. ListForms l => l -> l -> l
appendTwo

    null' :: a -> Bool
    null' = a -> Bool
forall z. (Zeros z, Eq z) => z -> Bool
isZero
    mknull :: a
    toLower' :: a -> a
    -- ^ convert the string to  lowercase, idempotent
    -- is not inverse of toUpper
    toUpper':: a -> a
    -- ^ is not idempotent and gives different results for string and text (sz and similar ligatures)

    isPrefixOf', isInfixOf', isPostfixOf' :: a -> a -> Bool
    isPostfixOf' a
a = a -> a -> Bool
forall a. CharChains a => a -> a -> Bool
isPrefixOf' (a -> a
forall a. CharChains a => a -> a
reverseString a
a) (a -> Bool) -> (a -> a) -> a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a
forall a. CharChains a => a -> a
reverseString
    stripPrefix' :: a -> a -> Maybe a
    -- ^ takes the prefix away, if present (and return rest). nothing if no prefix
    stripSuffix' :: a -> a -> Maybe a
    concat' :: [a] -> a
    trim' :: a -> a
    -- ^ removes all spaces front and back, idempotent
    reverseString, reverse' :: a -> a
    reverse' = a -> a
forall a. CharChains a => a -> a
reverseString
    removeLast :: a -> a
    -- ^ remove last char
    removeChar ::Char -> a -> a
    -- ^ remove a character from a string
    filterChar:: (Char -> Bool)  -> a -> a
    -- filter lets pass what is true
    lengthChar :: a -> Int
    nubChar :: a -> a
    drop' :: Int -> a -> a
    -- drop n char from input start
    take' :: Int -> a -> a
    -- ^ add a splitAt or dropN function
    intercalate' :: a -> [a] -> Maybe a
    -- ^ splitOn' and intercalate' are inverses (see Data.SplitList)
    -- returns Nothing if second  is empty and intercalate "x" "" gives Just ""
    -- return Nothing if first is empty or contained in second to achievee inverse with splitOn
    splitOn' :: a -> a -> Maybe [a]
    -- ^ splits the first by all occurences of the second 
    -- the second is removed from results
    -- returns Nothing if second is empty

    printf' :: (PrintfArg r) => String -> r -> a
    -- ^ formats a string accoding to a pattern - restricted to a single string (perhaps)
    -- requires type of argument fixed!

--    length' :: a -> Int
    replace' :: a -> a -> a -> a
    -- replace the first string with the second string in the third string
    readMaybe' :: Read b => a -> Maybe b
    -- read something... needs type hints

    prop_filterChar :: a -> Bool
    -- test with fixed set of chars to filter out

class CharChains2 x a where
    show' ::  x -> a
-- replaced with toString or toText

instance CharChains2 Int String where
    show' :: Int -> String
show' = Int -> String
forall a. Show a => a -> String
show
instance CharChains2 Bool String where
    show' :: Bool -> String
show' = Bool -> String
forall a. Show a => a -> String
show
instance CharChains2 () String where
    show' :: () -> String
show' = () -> String
forall a. Show a => a -> String
show
instance CharChains2 Int Text where
    show' :: Int -> Text
show' = String -> Text
s2t (String -> Text) -> (Int -> String) -> Int -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> String
forall a. Show a => a -> String
show
instance CharChains2 Bool Text where
    show' :: Bool -> Text
show' = String -> Text
s2t (String -> Text) -> (Bool -> String) -> Bool -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> String
forall a. Show a => a -> String
show
instance CharChains2 () Text where
    show' :: () -> Text
show' = String -> Text
s2t (String -> Text) -> (() -> String) -> () -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. () -> String
forall a. Show a => a -> String
show

instance CharChains2 Float String where
    show' :: Float -> String
show'  = Float -> String
forall a. Show a => a -> String
show
instance CharChains2 Float  Text where
    show' :: Float -> Text
show'  = String -> Text
s2t (String -> Text) -> (Float -> String) -> Float -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Float -> String
forall a. Show a => a -> String
show

instance CharChains2 Double String where
    show' :: Double -> String
show'  = Double -> String
forall a. Show a => a -> String
show
instance CharChains2 Double Text where
    show' :: Double -> Text
show'  = String -> Text
s2t (String -> Text) -> (Double -> String) -> Double -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> String
forall a. Show a => a -> String
show
instance CharChains2 Text Text where
    -- avoid the "" surrounding show text
    show' :: Text -> Text
show'  = Text -> Text
forall a. a -> a
id
instance CharChains2 String Text where
    show' :: String -> Text
show'  = String -> Text
s2t
instance CharChains2 Text String where
    -- avoid the "" surrounding show text
    show' :: Text -> String
show'  = Text -> String
t2s
instance CharChains2 String String where
    show' :: String -> String
show'  = String -> String
forall a. a -> a
id

instance (Show a, Show b) => CharChains2 (a,b) String where
    show' :: (a, b) -> String
show' (a
a,b
b) = (a, b) -> String
forall a. Show a => a -> String
show (a
a,b
b)
instance (Show a, Show b) => CharChains2 (a,b) Text where
    show' :: (a, b) -> Text
show' (a
a,b
b) = String -> Text
s2t (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ (a, b) -> String
forall a. Show a => a -> String
show (a
a,b
b)

instance (Show a) => CharChains2 [a] String where
    show' :: [a] -> String
show' [a]
s = [a] -> String
forall a. Show a => a -> String
show [a]
s
instance (Show a) => CharChains2 [a] Text where
    show' :: [a] -> Text
show' [a]
s = String -> Text
s2t (String -> Text) -> ([a] -> String) -> [a] -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> String
forall a. Show a => a -> String
show ([a] -> Text) -> [a] -> Text
forall a b. (a -> b) -> a -> b
$ [a]
s

instance CharChains String where
    toString :: String -> String
toString = String -> String
forall a. a -> a
id
    toText :: String -> Text
toText = String -> Text
s2t

    unwords' :: [String] -> String
unwords' = [String] -> String
unwords
    words' :: String -> [String]
words' = String -> [String]
words
    unlines' :: [String] -> String
unlines' = [String] -> String
unlines
    lines' :: String -> [String]
lines' = String -> [String]
lines
    null' :: String -> Bool
null' = String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null
    mknull :: String
mknull = String
""
    toUpper' :: String -> String
toUpper' = (Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toUpper
    toLower' :: String -> String
toLower' = (Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower
    concat' :: [String] -> String
concat' = [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
    isPrefixOf' :: String -> String -> Bool
isPrefixOf'  = String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isPrefixOf
    isInfixOf' :: String -> String -> Bool
isInfixOf' = String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isInfixOf
    stripPrefix' :: String -> String -> Maybe String
stripPrefix'  = String -> String -> Maybe String
forall a. Eq a => [a] -> [a] -> Maybe [a]
stripPrefix
    stripSuffix' :: String -> String -> Maybe String
stripSuffix' String
a  = (String -> String) -> Maybe String -> Maybe String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap String -> String
forall a. [a] -> [a]
reverse (Maybe String -> Maybe String)
-> (String -> Maybe String) -> String -> Maybe String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> Maybe String
forall a. Eq a => [a] -> [a] -> Maybe [a]
stripPrefix (String -> String
forall a. [a] -> [a]
reverse String
a) (String -> Maybe String)
-> (String -> String) -> String -> Maybe String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
forall a. [a] -> [a]
reverse

    intercalate' :: String -> [String] -> Maybe String
intercalate' String
s [String]
a
        | [String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
a = Maybe String
forall a. Maybe a
Nothing
        | String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
s = Maybe String
forall a. Maybe a
Nothing
        | String
s String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isInfixOf` [String] -> String
forall a. CharChains a => [a] -> a
concat' [String]
a = Maybe String
forall a. Maybe a
Nothing
        | Bool
otherwise = String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String) -> String -> Maybe String
forall a b. (a -> b) -> a -> b
$ String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
L.intercalate String
s [String]
a

    splitOn' :: String -> String -> Maybe [String]
splitOn' String
o String
s
        | String -> Bool
forall a. CharChains a => a -> Bool
null' String
o = [String] -> Maybe [String]
forall a. a -> Maybe a
Just []
        | String -> Bool
forall a. CharChains a => a -> Bool
null' String
s = [String] -> Maybe [String]
forall a. a -> Maybe a
Just [String
""]
        | Bool
otherwise = [String] -> Maybe [String]
forall a. a -> Maybe a
Just ([String] -> Maybe [String]) -> [String] -> Maybe [String]
forall a b. (a -> b) -> a -> b
$ String -> String -> [String]
forall a. Eq a => [a] -> [a] -> [[a]]
S.splitOn String
o String
s
    trim' :: String -> String
trim' = String -> String
f (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
f
        where f :: String -> String
f = String -> String
forall a. [a] -> [a]
reverse (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
dropWhile Char -> Bool
isSpace
    removeLast :: String -> String
removeLast String
a =  if String -> Bool
forall a. CharChains a => a -> Bool
null' String
a
        then String
forall a. CharChains a => a
mknull
        else String -> String
forall a. CharChains a => a -> a
reverseString (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
forall a. [a] -> [a]
tail (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
forall a. CharChains a => a -> a
reverseString (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String
a
    reverseString :: String -> String
reverseString = String -> String
forall a. [a] -> [a]
reverse
    printf' :: String -> r -> String
printf' = String -> r -> String
forall r. PrintfType r => String -> r
printf
    lengthChar :: String -> Int
lengthChar = String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length
    removeChar :: Char -> String -> String
removeChar Char
c = (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
filter (Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/=)
    filterChar :: (Char -> Bool) -> String -> String
filterChar = (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
filter

    nubChar :: String -> String
nubChar = String -> String
forall a. Eq a => [a] -> [a]
nub
    take' :: Int -> String -> String
take'  = Int -> String -> String
forall a. Int -> [a] -> [a]
take
    drop' :: Int -> String -> String
drop' = Int -> String -> String
forall a. Int -> [a] -> [a]
drop
    replace' :: String -> String -> String -> String
replace' = String -> String -> String -> String
forall a. Eq a => [a] -> [a] -> [a] -> [a]
LU.replace
    readMaybe' :: String -> Maybe b
readMaybe' = String -> Maybe b
forall b. Read b => String -> Maybe b
readMaybe

instance CharChains Text where
    toString :: Text -> String
toString = Text -> String
t2s
    toText :: Text -> Text
toText = Text -> Text
forall a. a -> a
id

    unwords' :: [Text] -> Text
unwords' = [Text] -> Text
T.unwords
    words' :: Text -> [Text]
words' =  Text -> [Text]
T.words
    lines' :: Text -> [Text]
lines' = Text -> [Text]
T.lines
    unlines' :: [Text] -> Text
unlines' = [Text] -> Text
T.unlines
    mknull :: Text
mknull = Text
T.empty
    toUpper' :: Text -> Text
toUpper' = Text -> Text
T.toUpper
    toLower' :: Text -> Text
toLower' = Text -> Text
T.toLower
    concat' :: [Text] -> Text
concat' = [Text] -> Text
T.concat
    isPrefixOf' :: Text -> Text -> Bool
isPrefixOf' = Text -> Text -> Bool
T.isPrefixOf
    isInfixOf' :: Text -> Text -> Bool
isInfixOf' = Text -> Text -> Bool
T.isInfixOf
    stripPrefix' :: Text -> Text -> Maybe Text
stripPrefix' = Text -> Text -> Maybe Text
T.stripPrefix
    stripSuffix' :: Text -> Text -> Maybe Text
stripSuffix' = Text -> Text -> Maybe Text
T.stripSuffix

    intercalate' :: Text -> [Text] -> Maybe Text
intercalate' Text
s [Text]
a
      | [Text] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Text]
a = Maybe Text
forall a. Maybe a
Nothing :: Maybe Text
      | Text -> Bool
forall a. CharChains a => a -> Bool
null' Text
s = Maybe Text
forall a. Maybe a
Nothing
      | Text
s Text -> Text -> Bool
forall a. CharChains a => a -> a -> Bool
`isInfixOf'` [Text] -> Text
forall a. CharChains a => [a] -> a
concat' [Text]
a = Maybe Text
forall a. Maybe a
Nothing
      | Bool
otherwise = Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text -> [Text] -> Text
T.intercalate Text
s [Text]
a

    splitOn' :: Text -> Text -> Maybe [Text]
splitOn' Text
o Text
s
      | Text -> Bool
forall a. CharChains a => a -> Bool
null' Text
o = [Text] -> Maybe [Text]
forall a. a -> Maybe a
Just []
      | Text -> Bool
forall a. CharChains a => a -> Bool
null' Text
s = [Text] -> Maybe [Text]
forall a. a -> Maybe a
Just [Text
""]
      | Bool
otherwise = [Text] -> Maybe [Text]
forall a. a -> Maybe a
Just ([Text] -> Maybe [Text]) -> [Text] -> Maybe [Text]
forall a b. (a -> b) -> a -> b
$ Text -> Text -> [Text]
T.splitOn Text
o Text
s

    trim' :: Text -> Text
trim' = Text -> Text
T.strip 
    removeLast :: Text -> Text
removeLast Text
a = Int -> Text -> Text
T.dropEnd Int
1 Text
a

    reverseString :: Text -> Text
reverseString = Text -> Text
T.reverse  

    printf' :: String -> r -> Text
printf' String
p   = String -> Text
s2t (String -> Text) -> (r -> String) -> r -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> r -> String
forall r. PrintfType r => String -> r
printf String
p
    lengthChar :: Text -> Int
lengthChar = Text -> Int
T.length
    removeChar :: Char -> Text -> Text
removeChar Char
c = (Char -> Bool) -> Text -> Text
T.filter (Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/=)
    filterChar :: (Char -> Bool) -> Text -> Text
filterChar = (Char -> Bool) -> Text -> Text
T.filter
    nubChar :: Text -> Text
nubChar = String -> Text
s2t (String -> Text) -> (Text -> String) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
forall a. Eq a => [a] -> [a]
nub (String -> String) -> (Text -> String) -> Text -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Text -> String
t2s
    take' :: Int -> Text -> Text
take' = Int -> Text -> Text
T.take
    drop' :: Int -> Text -> Text
drop' = Int -> Text -> Text
T.drop

    prop_filterChar :: Text -> Bool
prop_filterChar Text
a = Text -> String
t2s Text
af String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== ((Char -> Bool) -> String -> String
forall a. CharChains a => (Char -> Bool) -> a -> a
filterChar Char -> Bool
cond (String -> String) -> (Text -> String) -> Text -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
t2s (Text -> String) -> Text -> String
forall a b. (a -> b) -> a -> b
$ Text
a)
      where
          cond :: Char -> Bool
cond Char
x = Char
x Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [Char
'a', Char
'\r', Char
'1']
          af :: Text
af = (Char -> Bool) -> Text -> Text
forall a. CharChains a => (Char -> Bool) -> a -> a
filterChar Char -> Bool
cond Text
a :: Text
    replace' :: Text -> Text -> Text -> Text
replace' = Text -> Text -> Text -> Text
T.replace
    readMaybe' :: Text -> Maybe b
readMaybe' = String -> Maybe b
forall a b. (CharChains a, Read b) => a -> Maybe b
readMaybe' (String -> Maybe b) -> (Text -> String) -> Text -> Maybe b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
t2s

instance CharChains LazyByteString where
    append' :: LazyByteString -> LazyByteString -> LazyByteString
append' = LazyByteString -> LazyByteString -> LazyByteString
Lazy.append
    lengthChar :: LazyByteString -> Int
lengthChar LazyByteString
a = Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int64 -> Int)
-> (LazyByteString -> Int64) -> LazyByteString -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LazyByteString -> Int64
Lazy.length (LazyByteString -> Int) -> LazyByteString -> Int
forall a b. (a -> b) -> a -> b
$ LazyByteString
a  
        --  gives not exact value??
    take' :: Int -> LazyByteString -> LazyByteString
take' = Int64 -> LazyByteString -> LazyByteString
Lazy.take (Int64 -> LazyByteString -> LazyByteString)
-> (Int -> Int64) -> Int -> LazyByteString -> LazyByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral 
    drop' :: Int -> LazyByteString -> LazyByteString
drop' = Int64 -> LazyByteString -> LazyByteString
Lazy.drop (Int64 -> LazyByteString -> LazyByteString)
-> (Int -> Int64) -> Int -> LazyByteString -> LazyByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral  

unwordsT :: [Text] -> Text
unwordsT :: [Text] -> Text
unwordsT = [Text] -> Text
T.unwords  
-- ^ to fix types for overloaded strings

wordsT :: Text -> [Text]
wordsT :: Text -> [Text]
wordsT = Text -> [Text]
forall a. CharChains a => a -> [a]
words'

concatT ::  [Text] -> Text
concatT :: [Text] -> Text
concatT = [Text] -> Text
forall a. CharChains a => [a] -> a
concat'

showT :: a -> Text
showT a
t = String -> Text
s2t String
c
    where c :: String
c = a -> String
forall a. Show a => a -> String
show a
t :: String

instance CharChains BSUTF  where
-- works on utf8 encoded bytestring, convert with b2bu and bu2b

    toString :: BSUTF -> String
toString = BSUTF -> String
bu2s
    toText :: BSUTF -> Text
toText = BSUTF -> Text
bu2t

    unwords' :: [BSUTF] -> BSUTF
unwords' = Text -> BSUTF
t2bu (Text -> BSUTF) -> ([BSUTF] -> Text) -> [BSUTF] -> BSUTF
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Text] -> Text
forall a. CharChains a => [a] -> a
unwords' ([Text] -> Text) -> ([BSUTF] -> [Text]) -> [BSUTF] -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (BSUTF -> Text) -> [BSUTF] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map BSUTF -> Text
bu2t
    words' :: BSUTF -> [BSUTF]
words' =  (Text -> BSUTF) -> [Text] -> [BSUTF]
forall a b. (a -> b) -> [a] -> [b]
map Text -> BSUTF
t2bu ([Text] -> [BSUTF]) -> (BSUTF -> [Text]) -> BSUTF -> [BSUTF]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  Text -> [Text]
forall a. CharChains a => a -> [a]
words' (Text -> [Text]) -> (BSUTF -> Text) -> BSUTF -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BSUTF -> Text
bu2t
    lines' :: BSUTF -> [BSUTF]
lines' = (Text -> BSUTF) -> [Text] -> [BSUTF]
forall a b. (a -> b) -> [a] -> [b]
map Text -> BSUTF
t2bu ([Text] -> [BSUTF]) -> (BSUTF -> [Text]) -> BSUTF -> [BSUTF]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Text]
forall a. CharChains a => a -> [a]
lines' (Text -> [Text]) -> (BSUTF -> Text) -> BSUTF -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BSUTF -> Text
bu2t
    unlines' :: [BSUTF] -> BSUTF
unlines' =  Text -> BSUTF
t2bu (Text -> BSUTF) -> ([BSUTF] -> Text) -> [BSUTF] -> BSUTF
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Text] -> Text
forall a. CharChains a => [a] -> a
unlines' ([Text] -> Text) -> ([BSUTF] -> [Text]) -> [BSUTF] -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (BSUTF -> Text) -> [BSUTF] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map BSUTF -> Text
bu2t

--    append' a b = t2bu . append' (bu2t a) $ bu2t b
    null' :: BSUTF -> Bool
null' = Text -> Bool
T.null (Text -> Bool) -> (BSUTF -> Text) -> BSUTF -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BSUTF -> Text
bu2t
    toUpper' :: BSUTF -> BSUTF
toUpper' = Text -> BSUTF
t2bu (Text -> BSUTF) -> (BSUTF -> Text) -> BSUTF -> BSUTF
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
forall a. CharChains a => a -> a
toUpper' (Text -> Text) -> (BSUTF -> Text) -> BSUTF -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BSUTF -> Text
bu2t
    toLower' :: BSUTF -> BSUTF
toLower' = Text -> BSUTF
t2bu (Text -> BSUTF) -> (BSUTF -> Text) -> BSUTF -> BSUTF
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
forall a. CharChains a => a -> a
toLower' (Text -> Text) -> (BSUTF -> Text) -> BSUTF -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BSUTF -> Text
bu2t
    concat' :: [BSUTF] -> BSUTF
concat' = Text -> BSUTF
t2bu (Text -> BSUTF) -> ([BSUTF] -> Text) -> [BSUTF] -> BSUTF
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Text] -> Text
forall a. CharChains a => [a] -> a
concat' ([Text] -> Text) -> ([BSUTF] -> [Text]) -> [BSUTF] -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (BSUTF -> Text) -> [BSUTF] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map BSUTF -> Text
bu2t
    isPrefixOf' :: BSUTF -> BSUTF -> Bool
isPrefixOf' BSUTF
t BSUTF
s  = Text -> Text -> Bool
forall a. CharChains a => a -> a -> Bool
isPrefixOf' (BSUTF -> Text
bu2t BSUTF
s) (BSUTF -> Text
bu2t BSUTF
t)
    isInfixOf' :: BSUTF -> BSUTF -> Bool
isInfixOf' BSUTF
t BSUTF
s  = Text -> Text -> Bool
forall a. CharChains a => a -> a -> Bool
isInfixOf' (BSUTF -> Text
bu2t BSUTF
s) (BSUTF -> Text
bu2t BSUTF
t)
    stripPrefix' :: BSUTF -> BSUTF -> Maybe BSUTF
stripPrefix' BSUTF
p BSUTF
s = Text -> BSUTF
t2bu (Text -> BSUTF) -> Maybe Text -> Maybe BSUTF
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Text -> Maybe Text
forall a. CharChains a => a -> a -> Maybe a
stripPrefix' (BSUTF -> Text
bu2t BSUTF
p)  (BSUTF -> Text
bu2t BSUTF
s)
    intercalate' :: BSUTF -> [BSUTF] -> Maybe BSUTF
intercalate' BSUTF
x [BSUTF]
a  =  (Text -> BSUTF) -> Maybe Text -> Maybe BSUTF
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Text -> BSUTF
t2bu  (Text -> [Text] -> Maybe Text
forall a. CharChains a => a -> [a] -> Maybe a
intercalate' (BSUTF -> Text
bu2t BSUTF
x) ((BSUTF -> Text) -> [BSUTF] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map BSUTF -> Text
bu2t [BSUTF]
a))
    splitOn' :: BSUTF -> BSUTF -> Maybe [BSUTF]
splitOn' BSUTF
o BSUTF
s = (Text -> BSUTF) -> [Text] -> [BSUTF]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Text -> BSUTF
t2bu ([Text] -> [BSUTF]) -> Maybe [Text] -> Maybe [BSUTF]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Text -> Maybe [Text]
forall a. CharChains a => a -> a -> Maybe [a]
splitOn' (BSUTF -> Text
bu2t BSUTF
o) (BSUTF -> Text
bu2t BSUTF
s)
    trim' :: BSUTF -> BSUTF
trim' = String -> BSUTF
s2bu (String -> BSUTF) -> (BSUTF -> String) -> BSUTF -> BSUTF
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
forall a. CharChains a => a -> a
trim' (String -> String) -> (BSUTF -> String) -> BSUTF -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BSUTF -> String
bu2s

formatInt :: Int -> Int -> Text
formatInt :: Int -> Int -> Text
formatInt Int
n  = String -> Text
s2t (String -> Text) -> (Int -> String) -> Int -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. case Int
n of
        Int
6 -> String -> Int -> String
forall r. PrintfType r => String -> r
printf  [Char
'%', Char
'0', Char
'6', Char
'd']
        Int
5 ->  String -> Int -> String
forall r. PrintfType r => String -> r
printf  [Char
'%', Char
'0', Char
'5', Char
'd']
        Int
3 -> String -> Int -> String
forall r. PrintfType r => String -> r
printf  [Char
'%', Char
'0', Char
'3', Char
'd']
        Int
2 ->  String -> Int -> String
forall r. PrintfType r => String -> r
printf  [Char
'%', Char
'0', Char
'2', Char
'd']
        Int
a -> String -> Int -> String
forall a. Partial => String -> a
error (String
"formatInt not expected int" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show Int
a)

unlinesT :: [Text] -> Text
unlinesT :: [Text] -> Text
unlinesT = [Text] -> Text
forall a. CharChains a => [a] -> a
unlines'

sortCaseInsensitive :: (Ord a, CharChains a) => [a] -> [a]
sortCaseInsensitive :: [a] -> [a]
sortCaseInsensitive = (a -> a -> Ordering) -> [a] -> [a]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy a -> a -> Ordering
forall a. (Ord a, CharChains a) => a -> a -> Ordering
cmpCaseInsensitive

cmpCaseInsensitive :: (Ord a, CharChains a) => a -> a -> Ordering
cmpCaseInsensitive :: a -> a -> Ordering
cmpCaseInsensitive a
s1 a
s2 =  a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare  (  a -> a
forall a. CharChains a => a -> a
toLower' a
s1) (  a -> a
forall a. CharChains a => a -> a
toLower' a
s2)

maybe2string :: (IsString s) =>  Maybe s -> s
maybe2string :: Maybe s -> s
maybe2string Maybe s
Nothing  = s
""  -- TODO
maybe2string (Just s
s) = s
s

string2maybe :: (Eq a, IsString a) => a -> Maybe a
string2maybe :: a -> Maybe a
string2maybe a
x = if a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
"" then Maybe a
forall a. Maybe a
Nothing else a -> Maybe a
forall a. a -> Maybe a
Just a
x

class   NiceStrings a where
    shownice, showNice :: a -> Text
    showNice = a -> Text
forall a. NiceStrings a => a -> Text
shownice
    shownice = a -> Text
forall a. NiceStrings a => a -> Text
showNice 
    showlong :: a -> Text
    showlong = a -> Text
forall a. NiceStrings a => a -> Text
shownice  -- a default
class Show a => PrettyStrings a where 
    showPretty :: a -> Text
instance  {-# OVERLAPPABLE #-} Show a => PrettyStrings a where
    showPretty :: a -> Text
showPretty = String -> Text
s2t (String -> Text) -> (a -> String) -> a -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> String
forall a. Show a => a -> String
ppShow

instance NiceStrings Text where
    shownice :: Text -> Text
shownice = Text -> Text
forall a. a -> a
id
    showlong :: Text -> Text
showlong = Text -> Text
forall a. a -> a
id

instance NiceStrings Int where
    shownice :: Int -> Text
shownice = Int -> Text
forall x a. CharChains2 x a => x -> a
show'
    showlong :: Int -> Text
showlong = Int -> Text
forall x a. CharChains2 x a => x -> a
show'
instance NiceStrings Double where
    shownice :: Double -> Text
shownice = Double -> Text
forall x a. CharChains2 x a => x -> a
show'
    showlong :: Double -> Text
showlong = Double -> Text
forall x a. CharChains2 x a => x -> a
show'

instance (NiceStrings a, NiceStrings b) => NiceStrings (a,b) where
    shownice :: (a, b) -> Text
shownice (a
a,b
b) = [Text] -> Text
forall a. CharChains a => [a] -> a
unwords' [a -> Text
forall a. NiceStrings a => a -> Text
shownice a
a, b -> Text
forall a. NiceStrings a => a -> Text
shownice b
b]
    showlong :: (a, b) -> Text
showlong (a
a,b
b) = [Text] -> Text
forall a. CharChains a => [a] -> a
unwords' [a -> Text
forall a. NiceStrings a => a -> Text
showlong a
a, b -> Text
forall a. NiceStrings a => a -> Text
showlong b
b]
instance (NiceStrings a) => NiceStrings [a] where
    shownice :: [a] -> Text
shownice [a]
as = [Text] -> Text
forall a. CharChains a => [a] -> a
concat' ([Text] -> Text)
-> ([Maybe Text] -> [Text]) -> [Maybe Text] -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Maybe Text] -> [Text]
forall a. [Maybe a] -> [a]
catMaybes ([Maybe Text] -> Text) -> [Maybe Text] -> Text
forall a b. (a -> b) -> a -> b
$ [Text -> [Text] -> Maybe Text
forall a. CharChains a => a -> [a] -> Maybe a
intercalate' Text
"," ([Text] -> Maybe Text) -> ([a] -> [Text]) -> [a] -> Maybe Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  (a -> Text) -> [a] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map a -> Text
forall a. NiceStrings a => a -> Text
shownice ([a] -> Maybe Text) -> [a] -> Maybe Text
forall a b. (a -> b) -> a -> b
$ [a]
as, Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"\n"]
    shownice [a]
as = [Text] -> Text
forall a. CharChains a => [a] -> a
concat' ([Text] -> Text)
-> ([Maybe Text] -> [Text]) -> [Maybe Text] -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Maybe Text] -> [Text]
forall a. [Maybe a] -> [a]
catMaybes ([Maybe Text] -> Text) -> [Maybe Text] -> Text
forall a b. (a -> b) -> a -> b
$ [Text -> [Text] -> Maybe Text
forall a. CharChains a => a -> [a] -> Maybe a
intercalate' Text
"," ([Text] -> Maybe Text) -> ([a] -> [Text]) -> [a] -> Maybe Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  (a -> Text) -> [a] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map a -> Text
forall a. NiceStrings a => a -> Text
showlong ([a] -> Maybe Text) -> [a] -> Maybe Text
forall a b. (a -> b) -> a -> b
$ [a]
as, Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"\n"]

instance (NiceStrings a) => NiceStrings (Maybe a) where
    shownice :: Maybe a -> Text
shownice (Just a
a)  = a -> Text
forall a. NiceStrings a => a -> Text
shownice a
a
    shownice Maybe a
Nothing = Text
"Nothing"