diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2013, Chris Done
+
+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 Chris Done 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/formatting.cabal b/formatting.cabal
new file mode 100644
--- /dev/null
+++ b/formatting.cabal
@@ -0,0 +1,22 @@
+name:                formatting
+version:             3.0.0
+synopsis:            Combinator-based type-safe formatting (like printf() or FORMAT)
+description:         Combinator-based type-safe formatting (like printf() or FORMAT), modelled from the HoleyMonoids package.
+license:             BSD3
+license-file:        LICENSE
+author:              Chris Done, Shachaf Ben-Kiki, Martijn van Steenbergen
+maintainer:          chrisdone@gmail.com
+copyright:           2013 Chris Done, Shachaf Ben-Kiki, Martijn van Steenbergen
+category:            Text
+build-type:          Simple
+cabal-version:       >=1.8
+
+library
+  exposed-modules:   Formatting,
+                     Formatting.Holey,
+                     Formatting.Formatters,
+                     Formatting.ShortFormatters
+  build-depends:     base >= 4 && < 5,
+                     text-format,
+                     text
+  hs-source-dirs:    src
diff --git a/src/Formatting.hs b/src/Formatting.hs
new file mode 100644
--- /dev/null
+++ b/src/Formatting.hs
@@ -0,0 +1,50 @@
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# OPTIONS -Wall #-}
+
+-- |
+-- Module      : Text.Format
+-- Copyright   : (c) 2013 Chris Done, 2013 Shachaf Ben-Kiki
+-- License     : BSD3
+-- Maintainer  : chrisdone@gmail.com
+-- Stability   : experimental
+-- Portability : GHC
+--
+-- Combinator-based type-safe formatting (like printf() or FORMAT) for Text.
+--
+-- Example:
+--
+-- >>> format ("Person's name is " %text% ", age is " %hex) "Dave" 54
+
+module Formatting
+  (
+  -- * Top-level functions
+  format,
+  fprint,
+  hprint,
+  -- * Formatting library
+  module Formatting.Holey,
+  module Formatting.Formatters
+ ) where
+
+import           Formatting.Holey
+import           Formatting.Formatters
+
+import           Data.Text.Lazy (Text)
+import           Data.Text.Lazy.Builder (Builder)
+import qualified Data.Text.Lazy.Builder as T
+import qualified Data.Text.Lazy.IO      as T
+import           System.IO
+
+-- | Run the formatter and return a "Text" value.
+format :: Holey Builder Text a -> a
+format m = runHM m T.toLazyText
+
+-- | Run the formatter and print out the text to stdout.
+fprint :: Holey Builder (IO ()) a -> a
+fprint m = runHM m (T.putStr . T.toLazyText)
+
+-- | Run the formatter and put the output onto the given "Handle".
+hprint :: Handle -> Holey Builder (IO ()) a -> a
+hprint h m = runHM m (T.hPutStr h . T.toLazyText)
diff --git a/src/Formatting/Formatters.hs b/src/Formatting/Formatters.hs
new file mode 100644
--- /dev/null
+++ b/src/Formatting/Formatters.hs
@@ -0,0 +1,86 @@
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# OPTIONS -Wall #-}
+
+-- |
+-- Module      : Formatting.Formatters
+-- Copyright   : (c) 2013 Chris Done, 2013 Shachaf Ben-Kiki
+-- License     : BSD3
+-- Maintainer  : chrisdone@gmail.com
+-- Stability   : experimental
+-- Portability : GHC
+--
+-- Formatting functions.
+
+module Formatting.Formatters
+  (
+  -- * Formatters
+  text,
+  hex,
+  stext,
+  string,
+  expt,
+  fixed,
+  prec,
+  shortest,
+  left,
+  right
+  ) where
+
+import           Formatting.Holey
+
+import qualified Data.Text as S
+import qualified Data.Text as T
+import           Data.Text.Buildable    (Buildable)
+import qualified Data.Text.Format       as T
+import           Data.Text.Lazy (Text)
+import qualified Data.Text.Lazy.Builder as T
+
+-- | Output a lazy text.
+text :: Format Text
+text = later T.fromLazyText
+
+-- | Render an integer using hexadecimal notation. (No leading 0x is
+-- added.)
+hex :: Format Integer
+hex = later T.hex
+
+-- | Output a strict text.
+stext :: Format S.Text
+stext = later T.fromText
+
+-- | Output a string.
+string :: Format String
+string = later (T.fromText . T.pack)
+
+-- | Render a floating point number using scientific/engineering
+-- notation (e.g. 2.3e123), with the given number of decimal places.
+expt :: Real a => Int -> Format a
+expt i = later (T.expt i)
+
+-- | Render a floating point number using normal notation, with the
+-- given number of decimal places.
+fixed :: Real a => Int -> Format a
+fixed i = later (T.fixed i)
+
+-- | Render a floating point number, with the given number of digits
+-- of precision. Uses decimal notation for values between 0.1 and
+-- 9,999,999, and scientific notation otherwise.
+prec :: Real a => Int -> Format a
+prec i = later (T.prec i)
+
+-- | Render a floating point number using the smallest number of
+-- digits that correctly represent it.
+shortest :: Real a => Format a
+shortest = later T.shortest
+
+-- | Pad the left hand side of a string until it reaches k characters
+-- wide, if necessary filling with character c.
+left :: Buildable a => Int -> Char -> Format a
+left i c = later (T.left i c)
+
+-- | Pad the right hand side of a string until it reaches k characters
+-- wide, if necessary filling with character c.
+right :: Buildable a => Int -> Char -> Format a
+right i c = later (T.right i c)
diff --git a/src/Formatting/Holey.hs b/src/Formatting/Holey.hs
new file mode 100644
--- /dev/null
+++ b/src/Formatting/Holey.hs
@@ -0,0 +1,69 @@
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# OPTIONS -Wall #-}
+
+-- |
+-- Module      : Formatting.Holey
+-- Copyright   : (c) 2013 Chris Done, 2013 Shachaf Ben-Kiki
+-- License     : BSD3
+-- Maintainer  : chrisdone@gmail.com
+-- Stability   : experimental
+-- Portability : GHC
+--
+-- Copy of the holey monoids library but with constructor exported.
+
+module Formatting.Holey
+  (
+  -- * Formatting library
+  Format,
+  Holey (..),
+  (%),
+  now,
+  bind,
+  later,
+  hmap
+  ) where
+
+import Data.Monoid
+import Data.String
+import Data.Text.Lazy.Builder (Builder)
+
+-- | A formatter.
+type Format a = forall r. Holey Builder r (a -> r)
+
+-- | The type of a monoid with holes. The underlying monoid is
+-- represented by type parameter @m@. The @r@ is the result type and
+-- stays polymorphic until the very last moment when 'run' is
+-- called. The last argument @a@ is always a function with zero or
+-- more arguments, finally resulting in @r@. Ordering the arguments in
+-- this order allows holey monoids to be composed using `.`, stacking
+-- the expected arguments. Note that the `Monoid` constraint is only
+-- used in the identity 'Holey' and in composing two 'Holey's.
+newtype Holey m r a = Holey { runHM :: (m -> r) -> a }
+
+-- | Very useful instance for writing format string.
+instance (IsString m, a ~ r) => IsString (Holey m r a) where
+  fromString = now . fromString
+
+-- | Composition operator. The same as category composition.
+(%) :: Monoid n => Holey n b c -> Holey n b1 b -> Holey n b1 c
+f % g = f `bind` \a -> g `bind` \b -> now (a `mappend` b)
+
+-- | Insert a constant monoidal value.
+now :: m -> Holey m r r
+now a = Holey ($ a)
+
+-- | Monadic indexed bind for holey monoids.
+bind :: Holey m b c -> (m -> Holey n a b) -> Holey n a c
+m `bind` f = Holey $ \k -> runHM m (\a -> runHM (f a) k)
+
+-- | Insert a monoidal value that is not specified until the
+-- computation is 'run'. The argument that is expected later is
+-- converted to the monoid type using the given conversion function.
+later :: (a -> m) -> Holey m r (a -> r)
+later f = Holey (. f)
+
+-- | Convert between underlying 'Monoid' types.
+hmap :: (m -> n) -> Holey m r a -> Holey n r a
+hmap g m = Holey (\k -> runHM m (k . g))
diff --git a/src/Formatting/ShortFormatters.hs b/src/Formatting/ShortFormatters.hs
new file mode 100644
--- /dev/null
+++ b/src/Formatting/ShortFormatters.hs
@@ -0,0 +1,73 @@
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# OPTIONS -Wall #-}
+
+-- |
+-- Module      : Formatting.ShortFormatters
+-- Copyright   : (c) 2013 Chris Done, 2013 Shachaf Ben-Kiki
+-- License     : BSD3
+-- Maintainer  : chrisdone@gmail.com
+-- Stability   : experimental
+-- Portability : GHC
+--
+-- Single letters for short formatting.
+
+module Formatting.ShortFormatters where
+
+import           Formatting.Holey
+
+import qualified Data.Text as S
+import qualified Data.Text as T
+import           Data.Text.Buildable    (Buildable)
+import qualified Data.Text.Format       as T
+import           Data.Text.Lazy (Text)
+import qualified Data.Text.Lazy.Builder as T
+
+-- | Output a lazy text.
+t :: Format Text
+t = later T.fromLazyText
+
+-- | Render an integer using hexadecimal notation. (No leading 0x is
+-- added.)
+x :: Format Integer
+x = later T.hex
+
+-- | Output a strict text.
+st :: Format S.Text
+st = later T.fromText
+
+-- | Output a string.
+s :: Format String
+s = later (T.fromText . T.pack)
+
+-- | Render a floating point number using scientific/engineering
+-- notation (e.g. 2.3e123), with the given number of decimal places.
+ef :: Real a => Int -> Format a
+ef i = later (T.expt i)
+
+-- | Render a floating point number using normal notation, with the
+-- given number of decimal places.
+f :: Real a => Int -> Format a
+f i = later (T.fixed i)
+
+-- | Render a floating point number, with the given number of digits
+-- of precision. Uses decimal notation for values between 0.1 and
+-- 9,999,999, and scientific notation otherwise.
+pf :: Real a => Int -> Format a
+pf i = later (T.prec i)
+
+-- | Render a floating point number using the smallest number of
+-- digits that correctly represent it.
+sf :: Real a => Format a
+sf = later T.shortest
+
+-- | Pad the left hand side of a string until it reaches k characters
+-- wide, if necessary filling with character c.
+l :: Buildable a => Int -> Char -> Format a
+l i c = later (T.left i c)
+
+-- | Pad the right hand side of a string until it reaches k characters
+-- wide, if necessary filling with character c.
+r :: Buildable a => Int -> Char -> Format a
+r i c = later (T.right i c)
