module Text.Trifecta.Parser
( P
, line
, slice
, sliced
, careted
, spanned
, fixit
) where
import Control.Applicative
import Control.Monad.Trans.Class
import Data.Semigroup
import Data.Interned
import Data.Foldable (toList)
import Data.FingerTree as FingerTree
import Data.ByteString as Strict
import Data.ByteString.Lazy as Lazy
import Text.Trifecta.Hunk
import Text.Trifecta.Bytes
import Text.Trifecta.Rope as Rope
import Text.Trifecta.Delta
import Text.Trifecta.Strand
import Text.Trifecta.Caret
import Text.Trifecta.Span
import Text.Trifecta.Fixit
import Text.Trifecta.It
import Text.Parsec.Prim hiding ((<|>))
type P u = ParsecT Delta u It
line :: Delta -> P u Strict.ByteString
line d = lift $ Strict.concat
. Lazy.toChunks
. Lazy.takeWhile (/= 10)
. snd <$> peekIt (rewind d)
slice :: Delta -> Delta -> P u Strict.ByteString
slice !i !j = lift (Cont loop)
where
bi = bytes i
bj = bytes j
loop t eof
| bj <= bytes t || eof = Done t eof $ go $ strands t
| otherwise = Cont $ \t' eof' -> loop (t <> t') eof'
go !t
| required <= Strict.length first = Strict.take required first
| otherwise = Strict.concat
$ Lazy.toChunks
$ Lazy.take (fromIntegral required)
$ Lazy.fromChunks
$ first : Prelude.foldr iter [] (toList r')
where
iter (HunkStrand h) b = unintern h : b
iter (PathStrand _) b = b
(l,r) = FingerTree.split (\m -> bytes m > bi) t
HunkStrand (Hunk _ _ a) :< r' = FingerTree.viewl r
first = Strict.drop (bi bytes l) a
required = bj bi
sliced :: P u a -> P u Strict.ByteString
sliced pa = do
mark <- getInput
_ <- pa
release <- getInput
slice mark release
spanned :: P u a -> P u (Spanned a)
spanned p = do
m <- getInput
l <- line m
a <- p
r <- getInput
return $ a :~ Span m r l
careted :: P u a -> P u (Careted a)
careted p = do
m <- getInput
l <- line m
a <- p
return $ a :^ Caret m l
fixit :: P u Strict.ByteString -> P u Fixit
fixit p = (\(rep :~ s) -> Fixit s rep) <$> spanned p