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/Setup.lhs b/Setup.lhs
deleted file mode 100644
--- a/Setup.lhs
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/bin/env runhaskell
-> import Distribution.Simple
-> main = defaultMain
diff --git a/doc/ch4/FormattedText.tex b/doc/ch4/FormattedText.tex
--- a/doc/ch4/FormattedText.tex
+++ b/doc/ch4/FormattedText.tex
@@ -66,53 +66,35 @@
 constructor function, \fw{text\-Widget}:
 
 \begin{haskellcode}
- t <- textWidget wrap "foobar"
+ t <- textWidget someFormatter "foobar"
 \end{haskellcode}
 
 In addition, the formatter for a text widget can be set at any time
 with \fw{setTextFormatter}:
 
 \begin{haskellcode}
- setTextFormatter t wrap
+ setTextFormatter t someFormatter
 \end{haskellcode}
 
 When a text widget's contents are updated, the text is automatically
 broken up into tokens (see Section \ref{sec:updatingText}).  It is
 these tokens on which formatters operate.
 
-The \fw{Text} module provides two formatters: \fw{wrap} and
-\fw{highlight}.  \fw{wrap} wraps the text to fit into the
-\fw{DisplayRegion} available at rendering time, so this will end up
-doing the right thing depending on the parent widget of the
-\fw{FormattedText} widget.  \fw{highlight} accepts a regular
-expression\footnote{Any instance of \fw{RegexLike} is acceptable.} to
-match text for highlighting.  To construct a highlighting formatter,
-we must provide the regular expression used to match strings as well
-as the attribute that should be applied to the matches:\footnote{Since
-  formatters operate on individual tokens, the \fw{highlight}
-  formatter applies its regular expression to each token individually,
-  so it will only ever match sequences of characters in each token
-  rather than matching more than one token.  You can certainly write
-  your own formatter that considers more than one token at a time,
-  though.}
-
-Here is an example using \fw{highlight} with the \fw{Regex} type from
-the \fw{regex-pcre} package:
+The \fw{Text} module provides an example formatter called \fw{wrap}.
+\fw{wrap} wraps the text to fit into the \fw{DisplayRegion} available
+at rendering time, so this will end up doing the right thing depending
+on the parent widget of the \fw{FormattedText} widget.  Here is an
+example using \fw{wrap}:
 
 \begin{haskellcode}
- let doHighlight sz t = do
-   Right r <- compile compUngreedy execBlank "<.*>"
-   highlight r (fgColor bright_green) sz t
- t <- textWidget doHighlight "foo <bar> baz"
+ t <- textWidget wrap "(some long text message)"
 \end{haskellcode}
 
-Formatters can be composed with the \fw{\&.\&} operator.  This
-operator constructs a new formatter which will apply the operand
-formatters in the specified order.  We can use this operator to
-compose the built-in formatters on a single \fw{FormattedText} widget:
+Formatters form a \fw{Monoid}, and we can use this functionality to
+compose formatters:
 
 \begin{haskellcode}
- t <- textWidget (doHighlight &.& wrap) "Foo <bar> baz"
+ t <- textWidget (someFormatter `mappend` wrap) "Foo bar baz"
 \end{haskellcode}
 
 For detailed information on the token types on which the formatters
diff --git a/doc/macros.tex b/doc/macros.tex
--- a/doc/macros.tex
+++ b/doc/macros.tex
@@ -1,6 +1,6 @@
 % Custom macros.
 
-\newcommand{\vtyuiversion}{1.3.1}
+\newcommand{\vtyuiversion}{1.4}
 
 \newcommand{\fw}[1]{\texttt{#1}}
 \newcommand{\vtyui}{\fw{vty-ui}}
diff --git a/src/ComplexDemo.hs b/src/ComplexDemo.hs
--- a/src/ComplexDemo.hs
+++ b/src/ComplexDemo.hs
@@ -7,8 +7,6 @@
 import Control.Concurrent
 import Data.Time.Clock
 import Data.Time.Format
-import Text.Regex.PCRE
-import Text.Regex.PCRE.String
 import Graphics.Vty hiding (pad)
 import Graphics.Vty.Widgets.All
 
@@ -19,12 +17,6 @@
 headerAttr = fgColor bright_green
 msgAttr = fgColor blue
 
--- Formatter to apply a color to "<...>"
-color :: Formatter
-color sz t = do
-  Right r <- compile compUngreedy execBlank "<.*>"
-  highlight r (fgColor bright_green) sz t
-
 -- Multi-state checkbox value type
 data FrostingType = Chocolate
                   | Vanilla
@@ -46,7 +38,7 @@
            withNormalAttribute (bgColor blue) >>=
            withBorderAttribute (fgColor green)
 
-  tw <- (textWidget (wrap &.& color) msg) >>= withNormalAttribute msgAttr
+  tw <- (textWidget wrap msg) >>= withNormalAttribute msgAttr
   mainBox <- vBox table tw >>= withBoxSpacing 1
 
   r1 <- newCheckbox "Cake"
diff --git a/src/Graphics/Vty/Widgets/Table.hs b/src/Graphics/Vty/Widgets/Table.hs
--- a/src/Graphics/Vty/Widgets/Table.hs
+++ b/src/Graphics/Vty/Widgets/Table.hs
@@ -9,9 +9,9 @@
     , ColumnSize(..)
     , BorderStyle(..)
     , BorderFlag(..)
-    , RowLike
+    , RowLike(..)
     , TableError(..)
-    , ColumnSpec
+    , ColumnSpec(..)
     , Alignment(..)
     , Alignable(..)
     , (.|.)
@@ -27,6 +27,7 @@
     )
 where
 
+import Data.Monoid
 import Data.Typeable
 import Data.Word
 import Data.List
@@ -160,6 +161,10 @@
     where
       (TableRow cs) = mkRow a
       (TableRow ds) = mkRow b
+
+instance Monoid TableRow where
+    mempty = TableRow []
+    (TableRow as) `mappend` (TableRow bs) = TableRow $ as ++ bs
 
 infixl 2 .|.
 
diff --git a/src/Graphics/Vty/Widgets/Text.hs b/src/Graphics/Vty/Widgets/Text.hs
--- a/src/Graphics/Vty/Widgets/Text.hs
+++ b/src/Graphics/Vty/Widgets/Text.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, FlexibleContexts #-}
+{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
 -- |This module provides functionality for rendering 'String's as
 -- 'Widget's, including functionality to make structural and/or visual
 -- changes at rendering time.  To get started, turn your ordinary
@@ -16,20 +16,19 @@
     , setTextFormatter
     , setTextAppearFocused
     -- *Formatting
-    , Formatter
+    , Formatter(Formatter)
+    , applyFormatter
     , getTextFormatter
-    , (&.&)
-    , highlight
     , nullFormatter
     , wrap
     )
 where
 
+import Data.Monoid
 import Data.Word
 import Graphics.Vty
 import Graphics.Vty.Widgets.Core
 import Text.Trans.Tokenize
-import Text.Regex.Base
 import Graphics.Vty.Widgets.Util
 
 -- |A formatter makes changes to text at rendering time.  Some
@@ -37,15 +36,19 @@
 -- area, which is not known until render time (e.g., text wrapping).
 -- Thus, a formatter takes a 'DisplayRegion' which indicates the size
 -- of screen area available for formatting.
-type Formatter = DisplayRegion -> TextStream Attr -> IO (TextStream Attr)
+newtype Formatter = Formatter (DisplayRegion -> TextStream Attr -> IO (TextStream Attr))
 
--- |Formatter composition: @a &.& b@ applies @a@ followed by @b@.
-(&.&) :: Formatter -> Formatter -> Formatter
-f1 &.& f2 = \sz t -> f1 sz t >>= f2 sz
+instance Monoid Formatter where
+    mempty = nullFormatter
+    mappend (Formatter f1) (Formatter f2) =
+        Formatter (\sz t -> f1 sz t >>= f2 sz)
 
+applyFormatter :: Formatter -> DisplayRegion -> TextStream Attr -> IO (TextStream Attr)
+applyFormatter (Formatter f) sz t = f sz t
+
 -- |The null formatter which has no effect on text streams.
 nullFormatter :: Formatter
-nullFormatter = \_ t -> return t
+nullFormatter = Formatter (\_ t -> return t)
 
 -- |The type of formatted text widget state.  Stores the text itself
 -- and the formatter used to apply attributes to the text.
@@ -81,33 +84,10 @@
 -- to use other structure-sensitive formatters, run this formatter
 -- last.
 wrap :: Formatter
-wrap sz ts = do
-  let width = fromEnum $ region_width sz
-  return $ wrapStream width ts
-
--- |A highlight formatter takes a regular expression used to scan the
--- text and an attribute to assign to matches.  The regular expression
--- is only applied to individual string tokens (individual words,
--- whitespace strings, etc.); it is NOT applied to whole lines,
--- paragraphs, or text spanning multiple lines.  If you have need of
--- that kind of functionality, apply your own attributes with your own
--- regular expression prior to calling 'setTextWithAttrs'.
-highlight :: (RegexLike r String) => r -> Attr -> Formatter
-highlight regex attr =
-    \_ (TS ts) -> return $ TS $ map highlightToken ts
-        where
-          highlightToken :: TextStreamEntity Attr -> TextStreamEntity Attr
-          highlightToken NL = NL
-          highlightToken (T t) =
-              if tokenAttr t /= def_attr
-              then T t
-              else T (highlightToken' t)
-
-          highlightToken' :: Token Attr -> Token Attr
-          highlightToken' t =
-              if null $ matchAll regex $ tokenStr t
-              then t
-              else t { tokenAttr = attr }
+wrap =
+    Formatter $ \sz ts -> do
+      let width = fromEnum $ region_width sz
+      return $ wrapStream width ts
 
 -- |Construct a text widget formatted with the specified formatters
 -- and initial content.  The formatters will be applied in the order
@@ -172,7 +152,7 @@
            -> DisplayRegion
            -> RenderContext
            -> IO Image
-renderText t foc format sz ctx = do
+renderText t foc (Formatter format) sz ctx = do
   TS newText <- format sz t
 
   -- Truncate the tokens at the specified column and split them up
diff --git a/vty-ui.cabal b/vty-ui.cabal
--- a/vty-ui.cabal
+++ b/vty-ui.cabal
@@ -1,15 +1,22 @@
 Name:                vty-ui
-Version:             1.3.1
-Synopsis:            An interactive terminal user interface library
-                     for Vty
-Description:         An extensible library of user interface widgets
-                     for composing and laying out Vty user interfaces.
-                     This library provides a collection of widgets for
-                     building and composing interactive interactive,
-                     event-driven terminal interfaces.  This library
-                     is intended to make non-trivial user interfaces
-                     easy to express and modify without having to
-                     worry about terminal size.
+Version:             1.4
+Synopsis:
+  An interactive terminal user interface library for Vty
+
+Description:
+  An extensible library of user interface widgets for composing and
+  laying out Vty user interfaces.  This library provides a collection
+  of widgets for building and composing interactive interactive,
+  event-driven terminal interfaces.  This library is intended to make
+  non-trivial user interfaces easy to express and modify without
+  having to worry about terminal size.
+  .
+  Be sure to check out the user manual for the version you're using
+  at: <http://codevine.org/vty-ui/>
+  .
+  Build with the 'demos' flag to get a set of demonstration programs
+  to see some of the things the library can do!
+
 Category:            User Interfaces
 Author:              Jonathan Daugherty <jtd@galois.com>
 Maintainer:          Jonathan Daugherty <jtd@galois.com>
@@ -81,7 +88,6 @@
     base >= 4 && < 5,
     vty >= 4.6 && < 4.8,
     containers >= 0.2 && < 0.5,
-    regex-pcre >= 0.94 && < 0.95,
     regex-base >= 0.93 && < 0.94,
     directory >= 1.0 && < 1.2,
     filepath >= 1.1 && < 1.3,
@@ -165,7 +171,6 @@
     bytestring >= 0.9 && < 1.0,
     time >= 1.1 && < 1.3,
     old-locale >= 1.0 && < 1.1,
-    regex-pcre >= 0.94 && < 0.95,
     vty >= 4.6 && < 4.8
   if !flag(demos)
     Buildable: False
