{-# LANGUAGE OverloadedStrings
, FlexibleInstances
, StandaloneDeriving #-}
module System.Posix.ARX.Sh ( Val(), val, Var(), var,
setEU, Render(..), Raw(..) ) where
import Control.Monad
import Data.ByteString (ByteString)
import qualified Data.ByteString.Char8 as Bytes
import Data.Monoid
import qualified Blaze.ByteString.Builder as Blaze
import qualified Text.ShellEscape as Esc
setEU :: Blaze.Builder
setEU :: Builder
setEU = Builder
"set -e -u\n"
newtype Val = Val ByteString
deriving instance Eq Val
deriving instance Ord Val
deriving instance Show Val
instance Render Val where
render :: Val -> Builder
render (Val ByteString
bytes) = (ByteString -> Builder
Blaze.fromByteString (ByteString -> Builder)
-> (ByteString -> ByteString) -> ByteString -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sh -> ByteString
forall t. Escape t => t -> ByteString
Esc.bytes (Sh -> ByteString)
-> (ByteString -> Sh) -> ByteString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Sh
Esc.sh) ByteString
bytes
instance Raw Val where
raw :: Val -> ByteString
raw (Val ByteString
bytes) = ByteString
bytes
val :: ByteString -> Maybe Val
val :: ByteString -> Maybe Val
val ByteString
bytes = Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard ((Char -> Bool) -> ByteString -> Bool
Bytes.all (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'\0') ByteString
bytes) Maybe () -> Maybe Val -> Maybe Val
forall a b. Maybe a -> Maybe b -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Val -> Maybe Val
forall a. a -> Maybe a
Just (ByteString -> Val
Val ByteString
bytes)
newtype Var = Var ByteString
deriving instance Eq Var
deriving instance Ord Var
deriving instance Show Var
instance Render Var where
render :: Var -> Builder
render (Var ByteString
bytes) = ByteString -> Builder
Blaze.fromByteString ByteString
bytes
instance Raw Var where
raw :: Var -> ByteString
raw (Var ByteString
bytes) = ByteString
bytes
var :: ByteString -> Maybe Var
var :: ByteString -> Maybe Var
var ByteString
"" = Maybe Var
forall a. Maybe a
Nothing
var ByteString
bytes = Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Char -> Bool
leading Char
h Bool -> Bool -> Bool
&& (Char -> Bool) -> ByteString -> Bool
Bytes.all Char -> Bool
body ByteString
t) Maybe () -> Maybe Var -> Maybe Var
forall a b. Maybe a -> Maybe b -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Var -> Maybe Var
forall a. a -> Maybe a
Just (ByteString -> Var
Var ByteString
bytes)
where
(Char
h, ByteString
t) = (ByteString -> Char
Bytes.head ByteString
bytes, HasCallStack => ByteString -> ByteString
ByteString -> ByteString
Bytes.tail ByteString
bytes)
body :: Char -> Bool
body Char
c = Char -> Bool
leading Char
c Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'0' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'9')
leading :: Char -> Bool
leading Char
c = (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'A' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'Z') Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'a' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'z') Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'_'
instance Render [(Var, Val)] where
render :: [(Var, Val)] -> Builder
render [ ] = Builder
forall a. Monoid a => a
mempty
render ((Var
k,Val
v):[(Var, Val)]
t) = Builder
exportStatement Builder -> Builder -> Builder
forall a. Monoid a => a -> a -> a
`mappend` [(Var, Val)] -> Builder
forall t. Render t => t -> Builder
render [(Var, Val)]
t
where
exportStatement :: Builder
exportStatement = [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat [Builder
"export ", Var -> Builder
forall t. Render t => t -> Builder
render Var
k, Builder
"=", Val -> Builder
forall t. Render t => t -> Builder
render Val
v, Builder
"\n"]
instance Render [Val] where
render :: [Val] -> Builder
render = [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat ([Builder] -> Builder) -> ([Val] -> [Builder]) -> [Val] -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Val -> Builder) -> [Val] -> [Builder]
forall a b. (a -> b) -> [a] -> [b]
map (Builder -> Builder -> Builder
forall a. Monoid a => a -> a -> a
mappend Builder
" " (Builder -> Builder) -> (Val -> Builder) -> Val -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Val -> Builder
forall t. Render t => t -> Builder
render)
class Render t where
render :: t -> Blaze.Builder
class Raw t where
raw :: t -> ByteString