diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2010 sreservoir.
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of sreservoir nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/Text/Regex/Less.hs b/Text/Regex/Less.hs
new file mode 100644
--- /dev/null
+++ b/Text/Regex/Less.hs
@@ -0,0 +1,70 @@
+{- copyright (c) sreservoir.
+   license bsd three-clause. -}
+
+module Text.Regex.Less ((=~),truth,yank,base,subst,backref,unjust) where
+
+import qualified Data.ByteString.Char8 as B
+import qualified Text.Regex.PCRE.Light as R
+import Data.List
+import Text.Regex.Less.Quackers
+
+type Result = (String,Maybe [String])
+
+-- standard usage:
+  --  "" =~ ""
+  --  "" =~ "" << RECOpts
+  --  "" =~ "" << REEOpts
+  --  "" =~ "" << RECOpts << REEOpts
+-- value suitable for use below.
+infixl 6 =~
+(=~) :: QLR a => String -> a -> Result
+a =~ b =
+  case R.match (compile b) (B.pack a) (runopts b) of
+    Just c -> (a,Just (map B.unpack c))
+    Nothing -> (a,Nothing)
+
+-- success/failure of a regex.
+truth :: Result -> Bool
+truth (_,a) =
+  case a of
+    Just _ -> True
+    Nothing -> False
+
+-- yanks out the matches.
+yank :: Result -> [String]
+yank (_,a) = unjust a
+
+-- returns the original string.
+base :: Result -> String
+base (a,_) = a
+
+-- substitutes the matched part.
+-- does backrefs with derefs.
+subst :: Result -> String -> String
+subst a b = subst' (base a) b (yank a)
+  where subst' [] _ _ = []
+        subst' _ _ [] = []
+        subst' ca@(c:cs) d es@(e:_)
+          | e `isPrefixOf` ca = derefs es d ++ unjust (stripPrefix e ca)
+          | otherwise = c : subst' cs d es
+
+-- dereferences backrefs with ^ .
+derefs :: [String] -> String -> String
+derefs a ('^':'^':bs) = '^' : derefs a bs
+derefs a ('^':bs) =
+  case reads bs of
+    [(c,d)] -> a !! c ++ derefs a d
+    _       -> error "there's nothing here."
+derefs a (b:bs) = b : derefs a bs
+derefs _ [] = []
+
+-- takes the backrefs of a match.
+  -- backref 0 is the whole match.
+backref :: Result -> Int -> String
+backref a b = yank a !! b
+
+-- takes a Maybe(Just)'s value.
+-- fails with [] on Nothing.
+unjust :: Maybe a -> a
+unjust (Just a) = a
+unjust Nothing  = error "not unjustifiable."
diff --git a/Text/Regex/Less/Quackers.hs b/Text/Regex/Less/Quackers.hs
new file mode 100644
--- /dev/null
+++ b/Text/Regex/Less/Quackers.hs
@@ -0,0 +1,62 @@
+{- copyright (c) sreservoir.
+   license bsd three-clause. -}
+
+{-# LANGUAGE FlexibleInstances,TypeSynonymInstances #-}
+
+module Text.Regex.Less.Quackers (QLR(..)) where
+
+import qualified Text.Regex.PCRE.Light as R
+import qualified Data.ByteString.Char8 as B
+import Text.Regex.Less.REOpts
+
+-- the QLR (QuacksLikeRegex) class:
+  -- compile
+  -- runopts
+-- instances of QLR:
+  -- String
+  -- (String,[RECtOpts])
+  -- (String,[RERtOpts])
+  -- (String,([RECtOpts],[RERtOpts]))
+  -- (String,([RERtOpts],[RECtOpts]))
+  -- ((String,[RECtOpts]),[RERtOpts])
+  -- ((String,[RERtOpts]),[RECtOpts])
+
+-- QuacksLikeRegex: can =~ .
+class QLR a where
+  compile :: a -> R.Regex
+  runopts :: a -> [R.PCREExecOption]
+
+-- standard string.
+instance QLR String where
+  compile a = R.compile (B.pack a) []
+  runopts _ = []
+
+-- re << compile
+instance QLR (String,[RECtOpt]) where
+  compile (a,b) = R.compile (B.pack a) (reCtOpts b)
+  runopts (_,_) = []
+
+-- re << runtime
+instance QLR (String,[RERtOpt]) where
+  compile (a,_) = R.compile (B.pack a) []
+  runopts (_,b) = reRtOpts b
+
+-- re << compile << runtime
+instance QLR (String,([RECtOpt],[RERtOpt])) where
+  compile (a,(b,_)) = R.compile (B.pack a) (reCtOpts b)
+  runopts (_,(_,c)) = reRtOpts c
+
+-- re << runtime << compile
+instance QLR (String,([RERtOpt],[RECtOpt])) where
+  compile (a,(_,b)) = R.compile (B.pack a) (reCtOpts b)
+  runopts (_,(c,_)) = reRtOpts c
+
+-- (re << compile) << runtime
+instance QLR ((String,[RECtOpt]),[RERtOpt]) where
+  compile ((a,b),_) = R.compile (B.pack a) (reCtOpts b)
+  runopts ((_,_),c) = reRtOpts c
+
+-- (re << runtime) << compile
+instance QLR ((String,[RERtOpt]),[RECtOpt]) where
+  compile ((a,_),b) = R.compile (B.pack a) (reCtOpts b)
+  runopts ((_,c),_) = reRtOpts c
diff --git a/Text/Regex/Less/RECtOpts.hs b/Text/Regex/Less/RECtOpts.hs
new file mode 100644
--- /dev/null
+++ b/Text/Regex/Less/RECtOpts.hs
@@ -0,0 +1,42 @@
+{- copyright (c) sreservoir.
+   license bsd three-clause. -}
+
+module Text.Regex.Less.RECtOpts (reCtOpts,RECtOpt(..)) where
+
+import qualified Text.Regex.PCRE.Light as R
+
+-- compile options.
+data RECtOpt = CtAnchored | CtAutoCallout | CtCaseless | CtDollarEndOnly
+            | CtDotAll | CtDupNames | CtExtended | CtFirstLine | CtMultiLine
+            | CtNoAutoCapture | CtReverseGreedy | CtUtf8 | CtNoUtf8Check
+            | CtNlAnyCrLf | CtNlAnyUnicode | CtNlCr | CtNlLf | CtNlCrLf
+            | CtRAnyCrLf | CtRAnyUnicode | CtExtra
+  deriving (Eq,Show)
+
+-- translates lists of compile option constructors.
+reCtOpts :: [RECtOpt] -> [R.PCREOption]
+reCtOpts = map reCtOpt1
+
+-- translates a compile option constructor.
+reCtOpt1 :: RECtOpt -> R.PCREOption
+reCtOpt1 CtAnchored = R.anchored
+reCtOpt1 CtAutoCallout = R.auto_callout
+reCtOpt1 CtCaseless = R.caseless
+reCtOpt1 CtDollarEndOnly = R.dollar_endonly
+reCtOpt1 CtDotAll = R.dotall
+reCtOpt1 CtDupNames = R.dupnames
+reCtOpt1 CtExtended = R.extended
+reCtOpt1 CtFirstLine = R.firstline
+reCtOpt1 CtMultiLine = R.multiline
+reCtOpt1 CtNoAutoCapture = R.no_auto_capture
+reCtOpt1 CtReverseGreedy = R.ungreedy
+reCtOpt1 CtUtf8 = R.utf8
+reCtOpt1 CtNoUtf8Check = R.no_utf8_check
+reCtOpt1 CtNlCr = R.newline_cr
+reCtOpt1 CtNlLf = R.newline_lf
+reCtOpt1 CtNlCrLf = R.newline_crlf
+--reCtOpt1 CtNAnyCrLf    = R.newline_anycrlf
+--reCtOpt1 CtNAnyUnicode = R.newline_any
+--reCtOpt1 CtNAnyCrLf    = R.bsr_anycrlf
+--reCtOpt1 CtNAnyUnicode = R.bsr_unicode
+reCtOpt1 _                = undefined
diff --git a/Text/Regex/Less/REOpts.hs b/Text/Regex/Less/REOpts.hs
new file mode 100644
--- /dev/null
+++ b/Text/Regex/Less/REOpts.hs
@@ -0,0 +1,9 @@
+{- copyright (c) sreservoir.
+   licensed under mit (x11). -}
+
+module Text.Regex.Less.REOpts
+  ( module Text.Regex.Less.RECtOpts,
+    module Text.Regex.Less.RERtOpts) where
+
+import Text.Regex.Less.RECtOpts
+import Text.Regex.Less.RERtOpts
diff --git a/Text/Regex/Less/RERtOpts.hs b/Text/Regex/Less/RERtOpts.hs
new file mode 100644
--- /dev/null
+++ b/Text/Regex/Less/RERtOpts.hs
@@ -0,0 +1,31 @@
+{- copyright (c) sreservoir.
+   license bsd three-clause. -}
+
+module Text.Regex.Less.RERtOpts (reRtOpts,RERtOpt(..)) where
+
+import qualified Text.Regex.PCRE.Light as R
+
+-- runtime options.
+data RERtOpt = RtAnchored | RtNlAny | RtNlAnyCrLf | RtNlCr | RtNlLf
+            | RtNlCrLf | RtNotBol | RtNotRtOl | RtNotEmpty | RtNoUtf8Check
+            | RtPartial
+  deriving (Eq,Show)
+
+-- translates lists of runtime option constructors.
+reRtOpts :: [RERtOpt] -> [R.PCREExecOption]
+reRtOpts = map reRtOpt1
+
+-- translates a runtime option constructor.
+reRtOpt1 :: RERtOpt -> R.PCREExecOption
+reRtOpt1 RtAnchored = R.exec_anchored
+reRtOpt1 RtNlCr = R.exec_newline_cr
+reRtOpt1 RtNlLf = R.exec_newline_lf
+reRtOpt1 RtNlCrLf = R.exec_newline_crlf
+reRtOpt1 RtNotBol = R.exec_notbol
+reRtOpt1 RtNotRtOl = R.exec_noteol
+reRtOpt1 RtNotEmpty = R.exec_notempty
+reRtOpt1 RtNoUtf8Check = R.exec_no_utf8_check
+reRtOpt1 RtPartial = R.exec_partial ;
+--reRtOpt1 RtNlAny = R.exec_newline_any
+--reRtOpt1 RtNlAnyCrLf = R.exec_newline_anycrlf
+reRtOpt1 _                = undefined
diff --git a/pcre-less.cabal b/pcre-less.cabal
new file mode 100644
--- /dev/null
+++ b/pcre-less.cabal
@@ -0,0 +1,27 @@
+name:                pcre-less
+version:             0.0.0
+synopsis:            Nicer interface to pcre-light.
+description:
+  You'll have to read the comments until I get around to writing docs.
+homepage:            ~
+license:             BSD3
+-- The file containing the license text.
+license-file:        LICENSE
+author:              sreservoir
+maintainer:          sreservoir@gmail.com
+category:            Text
+build-type:          Simple
+cabal-version:       >= 1.2
+
+library
+  exposed-modules:
+    Text.Regex.Less
+    Text.Regex.Less.REOpts
+  other-modules:
+    Text.Regex.Less.RECtOpts
+    Text.Regex.Less.RERtOpts
+    Text.Regex.Less.Quackers
+  build-depends: base >= 4 && < 5,pcre-light >= 0.4,bytestring >= 0.9
+  extensions: FlexibleInstances,TypeSynonymInstances
+  ghc-options: -O2
+  ghc-prof-options: -auto-all
