{-# LANGUAGE OverloadedStrings #-}
{-|
Module      : Foreign.Lua.Module.Text
Copyright   : © 2017–2019 Albert Krewinkel
License     : MIT
Maintainer  : Albert Krewinkel <tarleb+hslua@zeitkraut.de>
Stability   : alpha
Portability : ForeignFunctionInterface

Provide a lua module containing a selection of useful Text functions.
-}
module Foreign.Lua.Module.Text
  ( pushModule
  , pushModuleText
  , preloadTextModule
  )where

import Control.Applicative ((<$>))
import Data.ByteString (ByteString)
import Data.Text (Text)
import Data.Maybe (fromMaybe)
import Foreign.Lua (NumResults, Lua, Peekable, Pushable, ToHaskellFunction)
import qualified Foreign.Lua as Lua
import qualified Data.Text as T

-- | Pushes the @text@ module to the Lua stack.
pushModule :: Lua NumResults
pushModule :: Lua NumResults
pushModule = do
  Lua ()
Lua.newtable
  String -> (Text -> Lua Text) -> Lua ()
forall a. ToHaskellFunction a => String -> a -> Lua ()
Lua.addfunction "lower" (Text -> Lua Text
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> Lua Text) -> (Text -> Text) -> Text -> Lua Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
T.toLower :: Text -> Lua Text)
  String -> (Text -> Lua Text) -> Lua ()
forall a. ToHaskellFunction a => String -> a -> Lua ()
Lua.addfunction "upper" (Text -> Lua Text
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> Lua Text) -> (Text -> Text) -> Text -> Lua Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
T.toUpper :: Text -> Lua Text)
  String -> (Text -> Lua Text) -> Lua ()
forall a. ToHaskellFunction a => String -> a -> Lua ()
Lua.addfunction "reverse" (Text -> Lua Text
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> Lua Text) -> (Text -> Text) -> Text -> Lua Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
T.reverse :: Text -> Lua Text)
  String -> (Text -> Lua Integer) -> Lua ()
forall a. ToHaskellFunction a => String -> a -> Lua ()
Lua.addfunction "len" (Integer -> Lua Integer
forall (m :: * -> *) a. Monad m => a -> m a
return (Integer -> Lua Integer)
-> (Text -> Integer) -> Text -> Lua Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Integer) -> (Text -> Int) -> Text -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Int
T.length :: Text -> Lua Lua.Integer)
  String
-> (Text -> Integer -> Optional Integer -> Lua Text) -> Lua ()
forall a. ToHaskellFunction a => String -> a -> Lua ()
Lua.addfunction "sub" Text -> Integer -> Optional Integer -> Lua Text
sub
  NumResults -> Lua NumResults
forall (m :: * -> *) a. Monad m => a -> m a
return 1

-- | Legacy alias for '@pushModule@'.
pushModuleText :: Lua NumResults
pushModuleText :: Lua NumResults
pushModuleText = Lua NumResults
pushModule

-- | Add the text module under the given name to the table of preloaded
-- packages.
preloadTextModule :: String -> Lua ()
preloadTextModule :: String -> Lua ()
preloadTextModule = (String -> Lua NumResults -> Lua ())
-> Lua NumResults -> String -> Lua ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip String -> Lua NumResults -> Lua ()
Lua.preloadhs Lua NumResults
pushModule

-- | Returns a substring, using Lua's string indexing rules.
sub :: Text -> Lua.Integer -> Lua.Optional Lua.Integer -> Lua Text
sub :: Text -> Integer -> Optional Integer -> Lua Text
sub s :: Text
s i :: Integer
i j :: Optional Integer
j =
  let i' :: Int
i' = Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
i
      j' :: Int
j' = Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer -> Int)
-> (Maybe Integer -> Integer) -> Maybe Integer -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Maybe Integer -> Integer
forall a. a -> Maybe a -> a
fromMaybe (-1) (Maybe Integer -> Int) -> Maybe Integer -> Int
forall a b. (a -> b) -> a -> b
$ Optional Integer -> Maybe Integer
forall a. Optional a -> Maybe a
Lua.fromOptional Optional Integer
j
      fromStart :: Int
fromStart = if Int
i' Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= 0 then  Int
i' Int -> Int -> Int
forall a. Num a => a -> a -> a
- 1 else Text -> Int
T.length Text
s Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
i'
      fromEnd :: Int
fromEnd   = if Int
j' Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<  0 then -Int
j' Int -> Int -> Int
forall a. Num a => a -> a -> a
- 1 else Text -> Int
T.length Text
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
j'
  in Text -> Lua Text
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> Lua Text) -> (Text -> Text) -> Text -> Lua Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Text -> Text
T.dropEnd Int
fromEnd (Text -> Text) -> (Text -> Text) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Text -> Text
T.drop Int
fromStart (Text -> Lua Text) -> Text -> Lua Text
forall a b. (a -> b) -> a -> b
$ Text
s