Added sed and selfless

This commit is contained in:
Gabriel Gonzalez 2015-01-18 08:45:58 -08:00
parent 4cef7d59d5
commit 09f95103c5
2 changed files with 33 additions and 9 deletions

View file

@ -75,6 +75,7 @@ module Turtle.Pattern (
-- * Combinators
, star
, plus
, selfless
, choice
, count
, between
@ -435,6 +436,20 @@ signed p = do
star :: Pattern Char -> Pattern Text
star p = fmap Text.pack (many p)
{-| Patterns that match multiple times are greedy by default, meaning that they
try to match as many times as possible. The `selfless` combinator makes a
pattern match as few times as possible
>>> match (selfless (star anyChar) *> char '1') "123"
"1"
>>> match (selfless (star anyChar)) "123"
["","1","12","123"]
>>> match (selfless (star anyChar <* eof)) "123"
["123"]
-}
selfless :: Pattern a -> Pattern a
selfless p = Pattern (StateT (\s -> reverse (runStateT (runPattern p) s)))
{-| Parse 1 or more occurrences of the given character
>>> match (some anyChar) "123"

View file

@ -5,11 +5,12 @@ import Control.Applicative (Alternative(..))
import Control.Monad (guard)
import Control.Monad.IO.Class (liftIO)
import Data.Text (Text)
import qualified Data.Text as Text
import qualified Data.Text.IO as Text
import qualified System.IO as IO
import Prelude hiding (FilePath)
import Turtle.Pattern (Pattern, anyChar, match, star)
import Turtle.Pattern (Pattern, anyChar, match, selfless, plus, star)
import Turtle.Resource
import Turtle.Shell
@ -22,21 +23,29 @@ select (a:as) = return a <|> select as
cat :: [Shell a] -> Shell a
cat = foldr (<|>) empty
-- | Keep all lines that match the given `Pattern`
-- | Keep all lines that match the given `Pattern` anywhere within the line
grep :: Pattern a -> Shell Text -> Shell Text
grep p shell = do
grep pattern shell = do
txt <- shell
let p' = do
let pattern' = do
_ <- star anyChar
p
guard (not (null (match p' txt)))
pattern
guard (not (null (match pattern' txt)))
return txt
-- | Replace all occurrences of a `Pattern` with its `Text` result
sed :: Pattern Text -> Shell Text -> Shell Text
sed pattern shell = do
let pattern' = fmap Text.concat (many (pattern <|> selfless (plus anyChar)))
txt <- shell
txt':_ <- return (match pattern' txt)
return txt'
-- | Parse a structured value from each line of `Text`
form :: Pattern a -> Shell Text -> Shell a
form p s = do
txt <- s
a:_ <- return (match p txt)
form pattern shell = do
txt <- shell
a:_ <- return (match pattern txt)
return a
-- | Read lines of `Text` from a `Handle`