module Data.Vector.Split.Internal 
  ( split
  , Splitter
  , splitOn
  , splitOneOf
  , splitWhen
  , endBy
  , oneOf
  , endByOneOf
  , wordsBy
  , linesBy
  , onSublist
  , whenElt
  , dropDelims
  , keepDelimsL
  , keepDelimsR
  , condense
  , dropInitBlank
  , dropInnerBlanks
  , dropFinalBlank
  , dropBlanks
  , startsWith
  , startsWithOneOf
  , endsWith
  , endsWithOneOf
  ) where


import           Data.Vector.Generic (Vector)
import qualified Data.Vector.Generic as V

import qualified Data.Vector as BV

-- | A delimiter is a list of predicates on elements, matched by some
--   contiguous subsequence of a list.
newtype Delimiter a = Delimiter (BV.Vector (a -> Bool))

-- | Try to match a delimiter at the start of a list, either failing
--   or decomposing the list into the portion which matched the delimiter
--   and the remainder.
matchDelim :: Vector v a => Delimiter a -> v a -> Maybe (v a, v a)
matchDelim :: forall (v :: * -> *) a.
Vector v a =>
Delimiter a -> v a -> Maybe (v a, v a)
matchDelim (Delimiter Vector (a -> Bool)
ds) v a
xs = if Bool
match Bool -> Bool -> Bool
&& Bool
lengthOk then forall a. a -> Maybe a
Just (forall (v :: * -> *) a. Vector v a => Int -> v a -> (v a, v a)
V.splitAt (forall (v :: * -> *) a. Vector v a => v a -> Int
V.length Vector (a -> Bool)
ds) v a
xs) else forall a. Maybe a
Nothing
    where match :: Bool
match = forall (v :: * -> *). Vector v Bool => v Bool -> Bool
V.and forall a b. (a -> b) -> a -> b
$ forall (v :: * -> *) a b c.
(Vector v a, Vector v b, Vector v c) =>
(a -> b -> c) -> v a -> v b -> v c
V.zipWith forall a b. (a -> b) -> a -> b
($) Vector (a -> Bool)
ds (forall (v :: * -> *) a (w :: * -> *).
(Vector v a, Vector w a) =>
v a -> w a
V.convert v a
xs)
          lengthOk :: Bool
lengthOk = forall (v :: * -> *) a. Vector v a => v a -> Int
V.length Vector (a -> Bool)
ds forall a. Ord a => a -> a -> Bool
<= forall (v :: * -> *) a. Vector v a => v a -> Int
V.length v a
xs




data Chunk v a = Delim (v a) | Text (v a)
    deriving (Int -> Chunk v a -> ShowS
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall (v :: * -> *) a. Show (v a) => Int -> Chunk v a -> ShowS
forall (v :: * -> *) a. Show (v a) => [Chunk v a] -> ShowS
forall (v :: * -> *) a. Show (v a) => Chunk v a -> String
showList :: [Chunk v a] -> ShowS
$cshowList :: forall (v :: * -> *) a. Show (v a) => [Chunk v a] -> ShowS
show :: Chunk v a -> String
$cshow :: forall (v :: * -> *) a. Show (v a) => Chunk v a -> String
showsPrec :: Int -> Chunk v a -> ShowS
$cshowsPrec :: forall (v :: * -> *) a. Show (v a) => Int -> Chunk v a -> ShowS
Show, Chunk v a -> Chunk v a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall (v :: * -> *) a. Eq (v a) => Chunk v a -> Chunk v a -> Bool
/= :: Chunk v a -> Chunk v a -> Bool
$c/= :: forall (v :: * -> *) a. Eq (v a) => Chunk v a -> Chunk v a -> Bool
== :: Chunk v a -> Chunk v a -> Bool
$c== :: forall (v :: * -> *) a. Eq (v a) => Chunk v a -> Chunk v a -> Bool
Eq)


type SplitList v a = [Chunk v a]

type Splitter v a = v a -> SplitList v a




toSplitList :: Vector v a => Delimiter a -> v a -> SplitList v a
toSplitList :: forall (v :: * -> *) a.
Vector v a =>
Delimiter a -> v a -> SplitList v a
toSplitList Delimiter a
d v a
v = Int -> [Chunk v a]
go Int
0
    where go :: Int -> [Chunk v a]
go Int
i | Int
i forall a. Ord a => a -> a -> Bool
< forall (v :: * -> *) a. Vector v a => v a -> Int
V.length v a
v = case forall (v :: * -> *) a.
Vector v a =>
Delimiter a -> v a -> Maybe (v a, v a)
matchDelim Delimiter a
d (forall (v :: * -> *) a. Vector v a => Int -> v a -> v a
V.drop Int
i v a
v) of
                                      Just (v a
l,v a
r) -> forall (v :: * -> *) a. v a -> Chunk v a
Text (forall (v :: * -> *) a. Vector v a => Int -> v a -> v a
V.take Int
i v a
v) forall a. a -> [a] -> [a]
: forall (v :: * -> *) a. v a -> Chunk v a
Delim v a
l forall a. a -> [a] -> [a]
: forall (v :: * -> *) a.
Vector v a =>
Delimiter a -> v a -> SplitList v a
toSplitList Delimiter a
d v a
r
                                      Maybe (v a, v a)
Nothing    -> Int -> [Chunk v a]
go (Int
iforall a. Num a => a -> a -> a
+Int
1)
               | Bool
otherwise      = [forall (v :: * -> *) a. v a -> Chunk v a
Text v a
v]


split :: Vector v a => Splitter v a -> v a -> [v a]
split :: forall (v :: * -> *) a. Vector v a => Splitter v a -> v a -> [v a]
split Splitter v a
s v a
v = forall a b. (a -> b) -> [a] -> [b]
map forall {v :: * -> *} {a}. Chunk v a -> v a
go forall a b. (a -> b) -> a -> b
$ Splitter v a
s v a
v
    where go :: Chunk v a -> v a
go (Text v a
t)  = v a
t
          go (Delim v a
d) = v a
d


-- Convenience functions

-- | Split on the given sublist. Equivalent to split . dropDelims . onSublist. For example:
--
-- >>> splitOn (BV.fromList "..") (BV.fromList "a..b...c....d..")
-- ["a","b",".c","","d",""]
-- 
-- In some parsing combinator frameworks this is also known as sepBy.
--
-- Note that this is the right inverse of the intercalate function from Data.List, that is,
--
-- >> \xs -> (intercalate xs . splitOn xs) === id
--
-- splitOn x . intercalate x is the identity on certain lists, but it is
-- tricky to state the precise conditions under which this holds. (For
-- example, it is not enough to say that x does not occur in any elements
-- of the input list. Working out why is left as an exercise for the
-- reader.)
splitOn :: (Vector v a, Eq a) => v a -> v a -> [v a]
splitOn :: forall (v :: * -> *) a. (Vector v a, Eq a) => v a -> v a -> [v a]
splitOn v a
xs = forall (v :: * -> *) a. Vector v a => Splitter v a -> v a -> [v a]
split (forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
dropDelims forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (v :: * -> *) a. (Vector v a, Eq a) => v a -> Splitter v a
onSublist v a
xs)

-- | Split on any of the given elements. Equivalent to split . dropDelims . oneOf. For example:
--
-- >>> splitOneOf (BV.fromList ";.,") (BV.fromList "foo,bar;baz.glurk")
-- ["foo","bar","baz","glurk"]
splitOneOf :: (Vector v a, Eq a) => v a -> v a -> [v a]
splitOneOf :: forall (v :: * -> *) a. (Vector v a, Eq a) => v a -> v a -> [v a]
splitOneOf v a
xs = forall (v :: * -> *) a. Vector v a => Splitter v a -> v a -> [v a]
split (forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
dropDelims forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (v :: * -> *) a. (Vector v a, Eq a) => v a -> Splitter v a
oneOf v a
xs)

-- | Split on elements satisfying the given predicate. Equivalent to split . dropDelims . whenElt. For example:
--
-- >>> splitWhen (<0) (BV.fromList [1,3,-4,5,7,-9,0,2])
-- [[1,3],[5,7],[0,2]]
splitWhen :: (Vector v a) => (a -> Bool) -> v a -> [v a]
splitWhen :: forall (v :: * -> *) a. Vector v a => (a -> Bool) -> v a -> [v a]
splitWhen a -> Bool
p = forall (v :: * -> *) a. Vector v a => Splitter v a -> v a -> [v a]
split (forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
dropDelims forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (v :: * -> *) a. Vector v a => (a -> Bool) -> Splitter v a
whenElt a -> Bool
p)

-- | Split into chunks terminated by the given subsequence. Equivalent to split . dropFinalBlank . dropDelims . onSublist. For example:
--
-- >>> endBy (BV.fromList ";") (BV.fromList "foo;bar;baz;")
-- ["foo","bar","baz"]
--
-- Note also that the lines function from Data.List is equivalent to endBy "\n".
endBy :: (Vector v a, Eq a) => v a -> v a -> [v a]
endBy :: forall (v :: * -> *) a. (Vector v a, Eq a) => v a -> v a -> [v a]
endBy v a
xs = forall (v :: * -> *) a. Vector v a => Splitter v a -> v a -> [v a]
split (forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
dropFinalBlank forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
dropDelims forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (v :: * -> *) a. (Vector v a, Eq a) => v a -> Splitter v a
onSublist v a
xs)
-- Basic Strategies

-- | A splitting strategy that splits on any one of the given elements. For example:
-- >>> split (oneOf (BV.fromList "xyz")) (BV.fromList "aazbxyzcxd")
-- ["aa","z","b","x","","y","","z","c","x","d"]
oneOf :: (Vector v a, Eq a) => v a -> Splitter v a
oneOf :: forall (v :: * -> *) a. (Vector v a, Eq a) => v a -> Splitter v a
oneOf v a
xs = forall (v :: * -> *) a.
Vector v a =>
Delimiter a -> v a -> SplitList v a
toSplitList Delimiter a
delim
    where delim :: Delimiter a
delim = forall a. Vector (a -> Bool) -> Delimiter a
Delimiter (forall a. a -> Vector a
BV.singleton (forall (v :: * -> *) a. (Vector v a, Eq a) => a -> v a -> Bool
`V.elem` v a
xs))


-- | Split into chunks terminated by one of the given elements. Equivalent to split . dropFinalBlank . dropDelims . oneOf. For example:
--
-- >>> endByOneOf (BV.fromList ";,") (BV.fromList "foo;bar,baz;") 
-- ["foo","bar","baz"]
endByOneOf :: (Vector v a, Eq a) => v a -> v a -> [v a]
endByOneOf :: forall (v :: * -> *) a. (Vector v a, Eq a) => v a -> v a -> [v a]
endByOneOf v a
xs = forall (v :: * -> *) a. Vector v a => Splitter v a -> v a -> [v a]
split (forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
dropFinalBlank forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
dropDelims forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (v :: * -> *) a. (Vector v a, Eq a) => v a -> Splitter v a
oneOf v a
xs)


-- | Split into "words", with word boundaries indicated by the given predicate. Satisfies words === wordsBy isSpace; equivalent to split . dropBlanks . dropDelims . whenElt. For example:
--
-- >>> wordsBy (=='x') (BV.fromList "dogxxxcatxbirdxx") 
-- ["dog","cat","bird"]
wordsBy :: Vector v a => (a -> Bool) -> v a -> [v a]
wordsBy :: forall (v :: * -> *) a. Vector v a => (a -> Bool) -> v a -> [v a]
wordsBy a -> Bool
p = forall (v :: * -> *) a. Vector v a => Splitter v a -> v a -> [v a]
split (forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
dropBlanks forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
dropDelims forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (v :: * -> *) a. Vector v a => (a -> Bool) -> Splitter v a
whenElt a -> Bool
p)


-- | Split into "lines", with line boundaries indicated by the given predicate. Satisfies lines === linesBy (=='\n'); equivalent to split . dropFinalBlank . dropDelims . whenElt. For example:
--
-- >>> linesBy (=='x') (BV.fromList "dogxxxcatxbirdxx")
-- ["dog","","","cat","bird",""]
linesBy :: Vector v a => (a -> Bool) -> v a -> [v a]
linesBy :: forall (v :: * -> *) a. Vector v a => (a -> Bool) -> v a -> [v a]
linesBy a -> Bool
p = forall (v :: * -> *) a. Vector v a => Splitter v a -> v a -> [v a]
split (forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
dropFinalBlank forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
dropDelims forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (v :: * -> *) a. Vector v a => (a -> Bool) -> Splitter v a
whenElt a -> Bool
p)


-- | A splitting strategy that splits on the given list, when it is
-- encountered as an exact subsequence. For example:
--
-- >>> split (onSublist (BV.fromList "xyz")) (BV.fromList "aazbxyzcxd")
-- ["aazb","xyz","cxd"]
--
-- Note that splitting on the empty list is not allowed in `vector-split`.
-- This is a major difference between `split` and `vector-split`. In any
-- case nobody should use `vector-split` to do this anyway.
onSublist :: (Vector v a, Eq a) => v a -> Splitter v a
onSublist :: forall (v :: * -> *) a. (Vector v a, Eq a) => v a -> Splitter v a
onSublist v a
xs = forall (v :: * -> *) a.
Vector v a =>
Delimiter a -> v a -> SplitList v a
toSplitList Delimiter a
delim
    where delim :: Delimiter a
delim = forall a. Vector (a -> Bool) -> Delimiter a
Delimiter (forall (v :: * -> *) a b.
(Vector v a, Vector v b) =>
(a -> b) -> v a -> v b
V.map forall a. Eq a => a -> a -> Bool
(==) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (v :: * -> *) a (w :: * -> *).
(Vector v a, Vector w a) =>
v a -> w a
V.convert forall a b. (a -> b) -> a -> b
$ v a
xs)

-- | A splitting strategy that splits on any elements that satisfy the given predicate. For example:
--
-- >>> split (whenElt (<0)) (BV.fromList [2,4,-3,6,-9,1])
-- [[2,4],[-3],[6],[-9],[1]]
whenElt :: (Vector v a) => (a -> Bool) -> Splitter v a
whenElt :: forall (v :: * -> *) a. Vector v a => (a -> Bool) -> Splitter v a
whenElt a -> Bool
p = forall (v :: * -> *) a.
Vector v a =>
Delimiter a -> v a -> SplitList v a
toSplitList Delimiter a
delim
    where delim :: Delimiter a
delim = forall a. Vector (a -> Bool) -> Delimiter a
Delimiter (forall (v :: * -> *) a. Vector v a => a -> v a
V.singleton a -> Bool
p)


-- Strategy Transformers

-- | Drop delimiters from the output (the default is to keep them). For example,
--
-- >>> split (oneOf (BV.fromList ":")) (BV.fromList "a:b:c")
-- ["a",":","b",":","c"]
-- >>> split (dropDelims . oneOf (BV.fromList ":")) (BV.fromList "a:b:c")
-- ["a","b","c"]
dropDelims :: Vector v a => SplitList v a -> SplitList v a
dropDelims :: forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
dropDelims = forall a. (a -> Bool) -> [a] -> [a]
filter forall {v :: * -> *} {a}. Chunk v a -> Bool
go 
    where go :: Chunk v a -> Bool
go (Delim v a
_) = Bool
False
          go (Text v a
_ ) = Bool
True

-- | Keep delimiters in the output by prepending them to adjacent chunks. For example:
--
-- >>> split (keepDelimsL . oneOf (BV.fromList "xyz")) (BV.fromList "aazbxyzcxd")
-- ["aa","zb","x","y","zc","xd"]
keepDelimsL :: Vector v a => SplitList v a -> SplitList v a
keepDelimsL :: forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
keepDelimsL (Delim v a
d : Text v a
t : [Chunk v a]
rst) = forall (v :: * -> *) a. v a -> Chunk v a
Text (v a
d forall (v :: * -> *) a. Vector v a => v a -> v a -> v a
V.++ v a
t) forall a. a -> [a] -> [a]
: forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
keepDelimsL [Chunk v a]
rst
keepDelimsL (Chunk v a
rs : [Chunk v a]
rst)               = Chunk v a
rs forall a. a -> [a] -> [a]
: forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
keepDelimsL [Chunk v a]
rst
keepDelimsL []                       = []

-- | Keep delimiters in the output by appending them to adjacent chunks. For example:
--
-- >>> split (keepDelimsR . oneOf (BV.fromList "xyz")) (BV.fromList "aazbxyzcxd")
-- ["aaz","bx","y","z","cx","d"]
keepDelimsR :: Vector v a => SplitList v a -> SplitList v a
keepDelimsR :: forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
keepDelimsR (Text v a
t : Delim v a
d : [Chunk v a]
rst) = forall (v :: * -> *) a. v a -> Chunk v a
Text (v a
t forall (v :: * -> *) a. Vector v a => v a -> v a -> v a
V.++ v a
d) forall a. a -> [a] -> [a]
: forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
keepDelimsR [Chunk v a]
rst
keepDelimsR (Chunk v a
rs : [Chunk v a]
rst)               = Chunk v a
rs forall a. a -> [a] -> [a]
: forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
keepDelimsR [Chunk v a]
rst
keepDelimsR []                       = []

-- FIXME really not sure about the delim : text : delim case ... 
-- this was inserted to be compatible with the split package

-- | Condense multiple consecutive delimiters into one. For example:
--
-- >>> split (condense . oneOf (BV.fromList "xyz")) (BV.fromList "aazbxyzcxd")
-- ["aa","z","b","xyz","c","x","d"]
-- >>> split (dropDelims . oneOf (BV.fromList "xyz")) (BV.fromList "aazbxyzcxd")
-- ["aa","b","","","c","d"]
-- >>> split (condense . dropDelims . oneOf (BV.fromList "xyz")) (BV.fromList "aazbxyzcxd")
-- ["aa","b","c","d"]
--
-- FIXME this function is not fully compatible with the Data.List.Split version.
condense :: Vector v a => SplitList v a -> SplitList v a
condense :: forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
condense (Delim v a
a : Delim v a
b : [Chunk v a]
rst) = forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
condense (forall (v :: * -> *) a. v a -> Chunk v a
Delim (v a
a forall (v :: * -> *) a. Vector v a => v a -> v a -> v a
V.++ v a
b) forall a. a -> [a] -> [a]
: [Chunk v a]
rst)
condense (Delim v a
a : Text v a
t : Delim v a
b : [Chunk v a]
rst) | forall (v :: * -> *) a. Vector v a => v a -> Bool
V.null v a
t = forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
condense (forall (v :: * -> *) a. v a -> Chunk v a
Delim (v a
a forall (v :: * -> *) a. Vector v a => v a -> v a -> v a
V.++ v a
b) forall a. a -> [a] -> [a]
: [Chunk v a]
rst)
condense (Chunk v a
t : [Chunk v a]
rst) = Chunk v a
t forall a. a -> [a] -> [a]
: forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
condense [Chunk v a]
rst
condense []                        = []

-- | Don't generate a blank chunk if there is a delimiter at the beginning. For example:
--
-- >>> split (oneOf (BV.fromList ":")) (BV.fromList ":a:b")
-- ["",":","a",":","b"]
-- >>> split (dropInitBlank . oneOf (BV.fromList ":")) (BV.fromList ":a:b")
-- [":","a",":","b"]
dropInitBlank :: Vector v a => SplitList v a -> SplitList v a
dropInitBlank :: forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
dropInitBlank (Text v a
t : [Chunk v a]
rst) | forall (v :: * -> *) a. Vector v a => v a -> Bool
V.null v a
t = [Chunk v a]
rst
dropInitBlank [Chunk v a]
rst                       = [Chunk v a]
rst

-- | Don't generate a blank chunk if there is a delimiter at the end. For example:
--
-- split (oneOf (BV.fromList ":")) (BV.fromList "a:b:")
-- ["a",":","b",":",""]
-- split (dropFinalBlank . oneOf (BV.fromList ":")) (BV.fromList "a:b:")
-- ["a",":","b",":"]
dropFinalBlank :: Vector v a => SplitList v a -> SplitList v a
dropFinalBlank :: forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
dropFinalBlank [Text v a
t]         | forall (v :: * -> *) a. Vector v a => v a -> Bool
V.null v a
t = []
dropFinalBlank (Chunk v a
rs : [Chunk v a]
rst)       = Chunk v a
rs forall a. a -> [a] -> [a]
: forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
dropFinalBlank [Chunk v a]
rst
dropFinalBlank []               = []

-- | Don't generate blank chunks between consecutive delimiters. For example:
--
-- >>> split (oneOf (BV.fromList ":")) (BV.fromList "::b:::a")
-- ["",":","",":","b",":","",":","",":","a"]
-- >>> split (dropInnerBlanks . oneOf (BV.fromList ":")) (BV.fromList "::b:::a")
-- ["",":",":","b",":",":",":","a"]
dropInnerBlanks :: Vector v a => SplitList v a -> SplitList v a
dropInnerBlanks :: forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
dropInnerBlanks (Text v a
a : [Chunk v a]
rst) = forall (v :: * -> *) a. v a -> Chunk v a
Text v a
a forall a. a -> [a] -> [a]
: forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
dropInnerBlanksGo [Chunk v a]
rst
dropInnerBlanks [Chunk v a]
rst            = forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
dropInnerBlanksGo [Chunk v a]
rst

dropInnerBlanksGo :: Vector v a => [Chunk v a] -> [Chunk v a]
dropInnerBlanksGo :: forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
dropInnerBlanksGo [Text v a
a]                  = [forall (v :: * -> *) a. v a -> Chunk v a
Text v a
a]
dropInnerBlanksGo (Text v a
a : [Chunk v a]
rst) | forall (v :: * -> *) a. Vector v a => v a -> Bool
V.null v a
a = forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
dropInnerBlanksGo [Chunk v a]
rst
dropInnerBlanksGo (Chunk v a
chunk  : [Chunk v a]
rst)            = Chunk v a
chunk forall a. a -> [a] -> [a]
: forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
dropInnerBlanksGo [Chunk v a]
rst
dropInnerBlanksGo []                        = []


-- Derived combinators

-- | Drop all blank chunks from the output, and condense consecutive
-- delimiters into one. 
-- Equivalent to dropInitBlank . dropFinalBlank . condense. For example:
--
-- >>> split (oneOf (BV.fromList ":")) (BV.fromList "::b:::a")
-- ["",":","",":","b",":","",":","",":","a"]
-- >>> split (dropBlanks . oneOf (BV.fromList ":")) (BV.fromList "::b:::a")
-- ["::","b",":::","a"]
dropBlanks :: Vector v a => SplitList v a -> SplitList v a
dropBlanks :: forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
dropBlanks = forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
condense forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Bool) -> [a] -> [a]
filter forall {v :: * -> *} {a}. Vector v a => Chunk v a -> Bool
go
    where go :: Chunk v a -> Bool
go (Text v a
t) | forall (v :: * -> *) a. Vector v a => v a -> Bool
V.null v a
t = Bool
False
          go Chunk v a
_                   = Bool
True

-- | Make a strategy that splits a list into chunks that all start with the
-- given subsequence (except possibly the first). Equivalent to
-- dropInitBlank . keepDelimsL . onSublist. For example:
--
-- >>> split (startsWith (BV.fromList "app")) (BV.fromList "applyapplicativeapplaudapproachapple")
-- ["apply","applicative","applaud","approach","apple"]
startsWith :: (Vector v a, Eq a) => v a -> Splitter v a
startsWith :: forall (v :: * -> *) a. (Vector v a, Eq a) => v a -> Splitter v a
startsWith v a
xs = forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
dropInitBlank forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
keepDelimsL forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (v :: * -> *) a. (Vector v a, Eq a) => v a -> Splitter v a
onSublist v a
xs

-- | Make a strategy that splits a list into chunks that all start with one
-- of the given elements (except possibly the first). Equivalent to
-- dropInitBlank . keepDelimsL . oneOf. For example:
--
-- >>> split (startsWithOneOf (BV.fromList ['A'..'Z'])) (BV.fromList "ACamelCaseIdentifier")
-- ["A","Camel","Case","Identifier"]
startsWithOneOf :: (Vector v a, Eq a) => v a -> Splitter v a
startsWithOneOf :: forall (v :: * -> *) a. (Vector v a, Eq a) => v a -> Splitter v a
startsWithOneOf v a
xs = forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
dropInitBlank forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
keepDelimsL forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (v :: * -> *) a. (Vector v a, Eq a) => v a -> Splitter v a
oneOf v a
xs

-- | Make a strategy that splits a list into chunks that all end with the
-- given subsequence, except possibly the last. Equivalent to
-- dropFinalBlank . keepDelimsR . onSublist. For example:
--
-- >>> split (endsWith (BV.fromList "ly")) (BV.fromList "happilyslowlygnarlylily")
-- ["happily","slowly","gnarly","lily"]
endsWith :: (Vector v a, Eq a) => v a -> Splitter v a
endsWith :: forall (v :: * -> *) a. (Vector v a, Eq a) => v a -> Splitter v a
endsWith v a
xs = forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
dropFinalBlank forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
keepDelimsR forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (v :: * -> *) a. (Vector v a, Eq a) => v a -> Splitter v a
onSublist v a
xs



-- Note: this function is not consistent with the Data.List.Split version

-- | Make a strategy that splits a list into chunks that all end with one of
-- the given elements, except possibly the last. Equivalent to
-- dropFinalBlank . keepDelimsR . oneOf. For example:
--
-- >>> split (condense . endsWithOneOf (BV.fromList ".,?! ")) (BV.fromList "Hi, there!  How are you?")
-- ["Hi, ","there!  ","How ","are ","you?"]
endsWithOneOf :: (Vector v a, Eq a) => v a -> Splitter v a
endsWithOneOf :: forall (v :: * -> *) a. (Vector v a, Eq a) => v a -> Splitter v a
endsWithOneOf v a
xs = forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
dropFinalBlank forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (v :: * -> *) a.
Vector v a =>
SplitList v a -> SplitList v a
keepDelimsR forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (v :: * -> *) a. (Vector v a, Eq a) => v a -> Splitter v a
oneOf v a
xs