module Nix.Expr.Strings where
import Nix.Utils
import Relude.Unsafe as Unsafe
import Data.List ( dropWhileEnd
, minimum
, lookup
)
import qualified Data.Text as T
import Nix.Expr
mergePlain :: [Antiquoted Text r] -> [Antiquoted Text r]
mergePlain :: [Antiquoted Text r] -> [Antiquoted Text r]
mergePlain [] = [Antiquoted Text r]
forall a. Monoid a => a
mempty
mergePlain (Plain Text
a : Antiquoted Text r
EscapedNewline : Plain Text
b : [Antiquoted Text r]
xs) =
[Antiquoted Text r] -> [Antiquoted Text r]
forall r. [Antiquoted Text r] -> [Antiquoted Text r]
mergePlain (Text -> Antiquoted Text r
forall v r. v -> Antiquoted v r
Plain (Text
a Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\n" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
b) Antiquoted Text r -> [Antiquoted Text r] -> [Antiquoted Text r]
forall a. a -> [a] -> [a]
: [Antiquoted Text r]
xs)
mergePlain (Plain Text
a : Plain Text
b : [Antiquoted Text r]
xs) = [Antiquoted Text r] -> [Antiquoted Text r]
forall r. [Antiquoted Text r] -> [Antiquoted Text r]
mergePlain (Text -> Antiquoted Text r
forall v r. v -> Antiquoted v r
Plain (Text
a Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
b) Antiquoted Text r -> [Antiquoted Text r] -> [Antiquoted Text r]
forall a. a -> [a] -> [a]
: [Antiquoted Text r]
xs)
mergePlain (Antiquoted Text r
x : [Antiquoted Text r]
xs) = Antiquoted Text r
x Antiquoted Text r -> [Antiquoted Text r] -> [Antiquoted Text r]
forall a. a -> [a] -> [a]
: [Antiquoted Text r] -> [Antiquoted Text r]
forall r. [Antiquoted Text r] -> [Antiquoted Text r]
mergePlain [Antiquoted Text r]
xs
removePlainEmpty :: [Antiquoted Text r] -> [Antiquoted Text r]
removePlainEmpty :: [Antiquoted Text r] -> [Antiquoted Text r]
removePlainEmpty = (Antiquoted Text r -> Bool)
-> [Antiquoted Text r] -> [Antiquoted Text r]
forall a. (a -> Bool) -> [a] -> [a]
filter Antiquoted Text r -> Bool
forall a r. (Eq a, Monoid a) => Antiquoted a r -> Bool
f where
f :: Antiquoted a r -> Bool
f (Plain a
x) = a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
forall a. Monoid a => a
mempty
f Antiquoted a r
_ = Bool
True
runAntiquoted :: v -> (v -> a) -> (r -> a) -> Antiquoted v r -> a
runAntiquoted :: v -> (v -> a) -> (r -> a) -> Antiquoted v r -> a
runAntiquoted v
_ v -> a
f r -> a
_ (Plain v
v) = v -> a
f v
v
runAntiquoted v
nl v -> a
f r -> a
_ Antiquoted v r
EscapedNewline = v -> a
f v
nl
runAntiquoted v
_ v -> a
_ r -> a
k (Antiquoted r
r) = r -> a
k r
r
splitLines :: [Antiquoted Text r] -> [[Antiquoted Text r]]
splitLines :: [Antiquoted Text r] -> [[Antiquoted Text r]]
splitLines = ([[Antiquoted Text r]]
-> [Antiquoted Text r] -> [[Antiquoted Text r]])
-> ([[Antiquoted Text r]], [Antiquoted Text r])
-> [[Antiquoted Text r]]
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry (([Antiquoted Text r]
-> [[Antiquoted Text r]] -> [[Antiquoted Text r]])
-> [[Antiquoted Text r]]
-> [Antiquoted Text r]
-> [[Antiquoted Text r]]
forall a b c. (a -> b -> c) -> b -> a -> c
flip (:)) (([[Antiquoted Text r]], [Antiquoted Text r])
-> [[Antiquoted Text r]])
-> ([Antiquoted Text r]
-> ([[Antiquoted Text r]], [Antiquoted Text r]))
-> [Antiquoted Text r]
-> [[Antiquoted Text r]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Antiquoted Text r] -> ([[Antiquoted Text r]], [Antiquoted Text r])
forall r.
[Antiquoted Text r] -> ([[Antiquoted Text r]], [Antiquoted Text r])
go where
go :: [Antiquoted Text r] -> ([[Antiquoted Text r]], [Antiquoted Text r])
go (Plain Text
t : [Antiquoted Text r]
xs) = (Text -> Antiquoted Text r
forall v r. v -> Antiquoted v r
Plain Text
l Antiquoted Text r -> [Antiquoted Text r] -> [Antiquoted Text r]
forall a. a -> [a] -> [a]
:) ([Antiquoted Text r] -> [Antiquoted Text r])
-> ([[Antiquoted Text r]], [Antiquoted Text r])
-> ([[Antiquoted Text r]], [Antiquoted Text r])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Text
-> ([[Antiquoted Text r]], [Antiquoted Text r])
-> ([[Antiquoted Text r]], [Antiquoted Text r]))
-> ([[Antiquoted Text r]], [Antiquoted Text r])
-> [Text]
-> ([[Antiquoted Text r]], [Antiquoted Text r])
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Text
-> ([[Antiquoted Text r]], [Antiquoted Text r])
-> ([[Antiquoted Text r]], [Antiquoted Text r])
forall b v r.
Monoid b =>
v
-> ([[Antiquoted v r]], [Antiquoted v r])
-> ([[Antiquoted v r]], b)
f ([Antiquoted Text r] -> ([[Antiquoted Text r]], [Antiquoted Text r])
go [Antiquoted Text r]
xs) [Text]
ls where
(Text
l : [Text]
ls) = (Char -> Bool) -> Text -> [Text]
T.split (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'\n') Text
t
f :: v
-> ([[Antiquoted v r]], [Antiquoted v r])
-> ([[Antiquoted v r]], b)
f v
prefix ([[Antiquoted v r]]
finished, [Antiquoted v r]
current) = ((v -> Antiquoted v r
forall v r. v -> Antiquoted v r
Plain v
prefix Antiquoted v r -> [Antiquoted v r] -> [Antiquoted v r]
forall a. a -> [a] -> [a]
: [Antiquoted v r]
current) [Antiquoted v r] -> [[Antiquoted v r]] -> [[Antiquoted v r]]
forall a. a -> [a] -> [a]
: [[Antiquoted v r]]
finished, b
forall a. Monoid a => a
mempty)
go (Antiquoted r
a : [Antiquoted Text r]
xs) = (r -> Antiquoted Text r
forall v r. r -> Antiquoted v r
Antiquoted r
a Antiquoted Text r -> [Antiquoted Text r] -> [Antiquoted Text r]
forall a. a -> [a] -> [a]
:) ([Antiquoted Text r] -> [Antiquoted Text r])
-> ([[Antiquoted Text r]], [Antiquoted Text r])
-> ([[Antiquoted Text r]], [Antiquoted Text r])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Antiquoted Text r] -> ([[Antiquoted Text r]], [Antiquoted Text r])
go [Antiquoted Text r]
xs
go (Antiquoted Text r
EscapedNewline : [Antiquoted Text r]
xs) = (Antiquoted Text r
forall v r. Antiquoted v r
EscapedNewline Antiquoted Text r -> [Antiquoted Text r] -> [Antiquoted Text r]
forall a. a -> [a] -> [a]
:) ([Antiquoted Text r] -> [Antiquoted Text r])
-> ([[Antiquoted Text r]], [Antiquoted Text r])
-> ([[Antiquoted Text r]], [Antiquoted Text r])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Antiquoted Text r] -> ([[Antiquoted Text r]], [Antiquoted Text r])
go [Antiquoted Text r]
xs
go [] = ([[Antiquoted Text r]]
forall a. Monoid a => a
mempty, [Antiquoted Text r]
forall a. Monoid a => a
mempty)
unsplitLines :: [[Antiquoted Text r]] -> [Antiquoted Text r]
unsplitLines :: [[Antiquoted Text r]] -> [Antiquoted Text r]
unsplitLines = [Antiquoted Text r] -> [[Antiquoted Text r]] -> [Antiquoted Text r]
forall a. [a] -> [[a]] -> [a]
intercalate [Text -> Antiquoted Text r
forall v r. v -> Antiquoted v r
Plain Text
"\n"]
stripIndent :: [Antiquoted Text r] -> NString r
stripIndent :: [Antiquoted Text r] -> NString r
stripIndent [] = Int -> [Antiquoted Text r] -> NString r
forall r. Int -> [Antiquoted Text r] -> NString r
Indented Int
0 [Antiquoted Text r]
forall a. Monoid a => a
mempty
stripIndent [Antiquoted Text r]
xs =
Int -> [Antiquoted Text r] -> NString r
forall r. Int -> [Antiquoted Text r] -> NString r
Indented
Int
minIndent
([Antiquoted Text r] -> [Antiquoted Text r]
forall r. [Antiquoted Text r] -> [Antiquoted Text r]
removePlainEmpty ([Antiquoted Text r] -> [Antiquoted Text r])
-> [Antiquoted Text r] -> [Antiquoted Text r]
forall a b. (a -> b) -> a -> b
$
[Antiquoted Text r] -> [Antiquoted Text r]
forall r. [Antiquoted Text r] -> [Antiquoted Text r]
mergePlain ([Antiquoted Text r] -> [Antiquoted Text r])
-> [Antiquoted Text r] -> [Antiquoted Text r]
forall a b. (a -> b) -> a -> b
$
((Maybe (Antiquoted Text r), Antiquoted Text r) -> Antiquoted Text r
forall a b. (a, b) -> b
snd ((Maybe (Antiquoted Text r), Antiquoted Text r)
-> Antiquoted Text r)
-> [(Maybe (Antiquoted Text r), Antiquoted Text r)]
-> [Antiquoted Text r]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>) ([(Maybe (Antiquoted Text r), Antiquoted Text r)]
-> [Antiquoted Text r])
-> [(Maybe (Antiquoted Text r), Antiquoted Text r)]
-> [Antiquoted Text r]
forall a b. (a -> b) -> a -> b
$
((Maybe (Antiquoted Text r), Antiquoted Text r) -> Bool)
-> [(Maybe (Antiquoted Text r), Antiquoted Text r)]
-> [(Maybe (Antiquoted Text r), Antiquoted Text r)]
forall a. (a -> Bool) -> [a] -> [a]
dropWhileEnd
(Maybe (Antiquoted Text r), Antiquoted Text r) -> Bool
forall r r. (Maybe (Antiquoted Text r), Antiquoted Text r) -> Bool
cleanup
([(Maybe (Antiquoted Text r), Antiquoted Text r)]
-> [(Maybe (Antiquoted Text r), Antiquoted Text r)])
-> [(Maybe (Antiquoted Text r), Antiquoted Text r)]
-> [(Maybe (Antiquoted Text r), Antiquoted Text r)]
forall a b. (a -> b) -> a -> b
$ [Antiquoted Text r]
-> [(Maybe (Antiquoted Text r), Antiquoted Text r)]
forall b. [b] -> [(Maybe b, b)]
pairWithLast ([Antiquoted Text r]
-> [(Maybe (Antiquoted Text r), Antiquoted Text r)])
-> [Antiquoted Text r]
-> [(Maybe (Antiquoted Text r), Antiquoted Text r)]
forall a b. (a -> b) -> a -> b
$ [[Antiquoted Text r]] -> [Antiquoted Text r]
forall r. [[Antiquoted Text r]] -> [Antiquoted Text r]
unsplitLines [[Antiquoted Text r]]
ls'
)
where
pairWithLast :: [b] -> [(Maybe b, b)]
pairWithLast [b]
ys =
[Maybe b] -> [b] -> [(Maybe b, b)]
forall a b. [a] -> [b] -> [(a, b)]
zip
(Maybe b -> ([b] -> Maybe b) -> [b] -> Maybe b
forall (t :: * -> *) b a. Foldable t => b -> (t a -> b) -> t a -> b
list
Maybe b
forall a. Maybe a
Nothing
(b -> Maybe b
forall (f :: * -> *) a. Applicative f => a -> f a
pure (b -> Maybe b) -> ([b] -> b) -> [b] -> Maybe b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [b] -> b
forall a. [a] -> a
Unsafe.last)
([b] -> Maybe b) -> [[b]] -> [Maybe b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [b] -> [[b]]
forall a. [a] -> [[a]]
inits [b]
ys
)
[b]
ys
ls :: [[Antiquoted Text r]]
ls = [[Antiquoted Text r]] -> [[Antiquoted Text r]]
forall r. [[Antiquoted Text r]] -> [[Antiquoted Text r]]
stripEmptyOpening ([[Antiquoted Text r]] -> [[Antiquoted Text r]])
-> [[Antiquoted Text r]] -> [[Antiquoted Text r]]
forall a b. (a -> b) -> a -> b
$ [Antiquoted Text r] -> [[Antiquoted Text r]]
forall r. [Antiquoted Text r] -> [[Antiquoted Text r]]
splitLines [Antiquoted Text r]
xs
ls' :: [[Antiquoted Text r]]
ls' = Int -> [Antiquoted Text r] -> [Antiquoted Text r]
forall r. Int -> [Antiquoted Text r] -> [Antiquoted Text r]
dropSpaces Int
minIndent ([Antiquoted Text r] -> [Antiquoted Text r])
-> [[Antiquoted Text r]] -> [[Antiquoted Text r]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [[Antiquoted Text r]]
ls
minIndent :: Int
minIndent =
Int
-> ([[Antiquoted Text r]] -> Int) -> [[Antiquoted Text r]] -> Int
forall (t :: * -> *) b a. Foldable t => b -> (t a -> b) -> t a -> b
list
Int
0
([Int] -> Int
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum ([Int] -> Int)
-> ([[Antiquoted Text r]] -> [Int]) -> [[Antiquoted Text r]] -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Antiquoted Text r] -> Int
forall r. [Antiquoted Text r] -> Int
countSpaces ([Antiquoted Text r] -> Int)
-> ([Antiquoted Text r] -> [Antiquoted Text r])
-> [Antiquoted Text r]
-> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Antiquoted Text r] -> [Antiquoted Text r]
forall r. [Antiquoted Text r] -> [Antiquoted Text r]
mergePlain ([Antiquoted Text r] -> Int) -> [[Antiquoted Text r]] -> [Int]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>))
([[Antiquoted Text r]] -> [[Antiquoted Text r]]
forall r. [[Antiquoted Text r]] -> [[Antiquoted Text r]]
stripEmptyLines [[Antiquoted Text r]]
ls)
stripEmptyLines :: [[Antiquoted Text r]] -> [[Antiquoted Text r]]
stripEmptyLines = ([Antiquoted Text r] -> Bool)
-> [[Antiquoted Text r]] -> [[Antiquoted Text r]]
forall a. (a -> Bool) -> [a] -> [a]
filter (([Antiquoted Text r] -> Bool)
-> [[Antiquoted Text r]] -> [[Antiquoted Text r]])
-> ([Antiquoted Text r] -> Bool)
-> [[Antiquoted Text r]]
-> [[Antiquoted Text r]]
forall a b. (a -> b) -> a -> b
$ \case
[Plain Text
t] -> Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Text -> Bool
T.null (Text -> Bool) -> Text -> Bool
forall a b. (a -> b) -> a -> b
$ Text -> Text
T.strip Text
t
[Antiquoted Text r]
_ -> Bool
True
stripEmptyOpening :: [[Antiquoted Text r]] -> [[Antiquoted Text r]]
stripEmptyOpening ([Plain Text
t] : [[Antiquoted Text r]]
ts) | Text -> Bool
T.null (Text -> Text
T.strip Text
t) = [[Antiquoted Text r]]
ts
stripEmptyOpening [[Antiquoted Text r]]
ts = [[Antiquoted Text r]]
ts
countSpaces :: [Antiquoted Text r] -> Int
countSpaces (Antiquoted r
_ : [Antiquoted Text r]
_) = Int
0
countSpaces (Antiquoted Text r
EscapedNewline : [Antiquoted Text r]
_) = Int
0
countSpaces (Plain Text
t : [Antiquoted Text r]
_) = Text -> Int
T.length (Text -> Int) -> (Text -> Text) -> Text -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> Text -> Text
T.takeWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
' ') (Text -> Int) -> Text -> Int
forall a b. (a -> b) -> a -> b
$ Text
t
countSpaces [] = Int
0
dropSpaces :: Int -> [Antiquoted Text r] -> [Antiquoted Text r]
dropSpaces Int
0 [Antiquoted Text r]
x = [Antiquoted Text r]
x
dropSpaces Int
n (Plain Text
t : [Antiquoted Text r]
cs) = Text -> Antiquoted Text r
forall v r. v -> Antiquoted v r
Plain (Int -> Text -> Text
T.drop Int
n Text
t) Antiquoted Text r -> [Antiquoted Text r] -> [Antiquoted Text r]
forall a. a -> [a] -> [a]
: [Antiquoted Text r]
cs
dropSpaces Int
_ [Antiquoted Text r]
_ = String -> [Antiquoted Text r]
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"stripIndent: impossible"
cleanup :: (Maybe (Antiquoted Text r), Antiquoted Text r) -> Bool
cleanup (Maybe (Antiquoted Text r)
Nothing, Plain Text
y) = (Char -> Bool) -> Text -> Bool
T.all (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
' ') Text
y
cleanup (Just (Plain Text
x), Plain Text
y) | Text
"\n" Text -> Text -> Bool
`T.isSuffixOf` Text
x = (Char -> Bool) -> Text -> Bool
T.all (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
' ') Text
y
cleanup (Maybe (Antiquoted Text r), Antiquoted Text r)
_ = Bool
False
escapeCodes :: [(Char, Char)]
escapeCodes :: [(Char, Char)]
escapeCodes =
[(Char
'\n', Char
'n'), (Char
'\r', Char
'r'), (Char
'\t', Char
't'), (Char
'\\', Char
'\\'), (Char
'$', Char
'$'), (Char
'"', Char
'"')]
fromEscapeCode :: Char -> Maybe Char
fromEscapeCode :: Char -> Maybe Char
fromEscapeCode = (Char -> [(Char, Char)] -> Maybe Char
forall a b. Eq a => a -> [(a, b)] -> Maybe b
`lookup` ((Char, Char) -> (Char, Char)) -> [(Char, Char)] -> [(Char, Char)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Char, Char) -> (Char, Char)
forall a b. (a, b) -> (b, a)
swap [(Char, Char)]
escapeCodes)
toEscapeCode :: Char -> Maybe Char
toEscapeCode :: Char -> Maybe Char
toEscapeCode = (Char -> [(Char, Char)] -> Maybe Char
forall a b. Eq a => a -> [(a, b)] -> Maybe b
`lookup` [(Char, Char)]
escapeCodes)