diff --git a/Text/Chatty/Extended/Printer.hs b/Text/Chatty/Extended/Printer.hs
--- a/Text/Chatty/Extended/Printer.hs
+++ b/Text/Chatty/Extended/Printer.hs
@@ -56,6 +56,7 @@
 takeBrace n ('}':ss) = '}' : takeBrace (n-1) ss
 takeBrace n ('{':ss) = '{' : takeBrace (n+1) ss
 takeBrace n (s:ss) = s : takeBrace n ss
+takeBrace n [] = ""
 
 splitBrace ss = let nm = takeBrace 0 ss in (nm, drop (length nm + 1) ss)
 
diff --git a/Text/Chatty/Interactor.hs b/Text/Chatty/Interactor.hs
--- a/Text/Chatty/Interactor.hs
+++ b/Text/Chatty/Interactor.hs
@@ -26,6 +26,7 @@
 
 import Text.Chatty.Printer
 import Text.Chatty.Scanner
+import Text.Chatty.Scanner.Buffered
 import Text.Chatty.Finalizer
 import Text.Chatty.Expansion
 import Text.Chatty.Expansion.Vars
@@ -38,23 +39,25 @@
 import System.Chatty.Spawn
 import System.Chatty.Spawn.Overlay
 import Control.Monad
+import Control.Monad.State
 import Control.Monad.Trans.Class
 import Control.Monad.Identity
 import System.IO
 
-mkInteractor ''RecorderT mkScanner mkFinalizer mkExpander mkExpanderEnv mkHistoryEnv mkSpawn mkRandom mkClock
-mkInteractor ''DeafT mkScanner mkFinalizer mkExpander mkExpanderEnv mkHistoryEnv mkSpawn mkRandom mkClock
-mkInteractor ''OutRedirT mkScanner mkFinalizer mkExpander mkExpanderEnv mkHistoryEnv mkSpawn mkRandom mkClock
-mkInteractor ''HandleCloserT mkScanner mkPrinter mkExpander mkExpanderEnv mkHistoryEnv mkSpawn mkRandom mkClock mkDefCP
-mkInteractor ''ExpanderT mkScanner mkPrinter mkFinalizer mkSpawn mkRandom mkClock mkHistoryEnv mkDefCP
+mkInteractor ''RecorderT mkScanner mkBufferedScanner mkFinalizer mkExpander mkExpanderEnv mkHistoryEnv mkSpawn mkRandom mkClock
+mkInteractor ''DeafT mkScanner mkBufferedScanner mkFinalizer mkExpander mkExpanderEnv mkHistoryEnv mkSpawn mkRandom mkClock
+mkInteractor ''OutRedirT mkScanner mkBufferedScanner mkFinalizer mkExpander mkExpanderEnv mkHistoryEnv mkSpawn mkRandom mkClock
+mkInteractor ''HandleCloserT mkScanner mkBufferedScanner mkPrinter mkExpander mkExpanderEnv mkHistoryEnv mkSpawn mkRandom mkClock mkDefCP
+mkInteractor ''ExpanderT mkScanner mkBufferedScanner mkPrinter mkFinalizer mkSpawn mkRandom mkClock mkHistoryEnv mkDefCP
 mkInteractor ''HereStringT mkPrinter mkExtendedPrinter mkExpander mkExpanderEnv mkHistoryEnv mkSpawn mkRandom mkClock mkDefCP
 mkInteractor ''QuietT mkPrinter mkExtendedPrinter mkExpander mkExpanderEnv mkHistoryEnv mkSpawn mkRandom mkClock mkDefCP
 mkInteractor ''InRedirT mkPrinter mkExtendedPrinter mkExpander mkExpanderEnv mkHistoryEnv mkSpawn mkRandom mkClock mkDefCP
-mkInteractor ''SpawnOverlayT mkPrinter mkExtendedPrinter mkScanner mkExpander mkExpanderEnv mkHistoryEnv mkFinalizer mkRandom mkClock mkDefCP
-mkInteractor ''HtmlPrinterT mkScanner mkExpanderEnv mkHistoryEnv mkFinalizer mkSpawn mkRandom mkClock mkDefCP
-mkInteractor ''AnsiPrinterT mkScanner mkExpanderEnv mkHistoryEnv mkFinalizer mkSpawn mkRandom mkClock mkDefCP
-mkInteractor ''NullExpanderT mkScanner mkPrinter mkExtendedPrinter mkFinalizer mkSpawn mkRandom mkClock mkDefCP
-mkInteractor ''HistoryT  mkScanner mkPrinter mkExtendedPrinter mkFinalizer mkSpawn mkRandom mkClock mkExpanderEnv mkDefCP
+mkInteractor ''SpawnOverlayT mkPrinter mkExtendedPrinter mkScanner mkBufferedScanner mkExpander mkExpanderEnv mkHistoryEnv mkFinalizer mkRandom mkClock mkDefCP
+mkInteractor ''HtmlPrinterT mkScanner mkBufferedScanner mkExpanderEnv mkHistoryEnv mkFinalizer mkSpawn mkRandom mkClock mkDefCP
+mkInteractor ''AnsiPrinterT mkScanner mkBufferedScanner mkExpanderEnv mkHistoryEnv mkFinalizer mkSpawn mkRandom mkClock mkDefCP
+mkInteractor ''NullExpanderT mkScanner mkBufferedScanner mkPrinter mkExtendedPrinter mkFinalizer mkSpawn mkRandom mkClock mkDefCP
+mkInteractor ''HistoryT  mkScanner mkBufferedScanner mkPrinter mkExtendedPrinter mkFinalizer mkSpawn mkRandom mkClock mkExpanderEnv mkDefCP
+mkInteractor ''ScannerBufferT mkPrinter mkExtendedPrinter mkExpander mkExpanderEnv mkHistoryEnv mkFinalizer mkRandom mkClock mkDefCP mkSpawn
 mkInteractor ''IntArchiverT mkArchiver
 mkInteractor ''BoolArchiverT mkArchiver
 mkInteractor ''HandleArchiverT mkArchiver
diff --git a/Text/Chatty/Interactor/Templates.hs b/Text/Chatty/Interactor/Templates.hs
--- a/Text/Chatty/Interactor/Templates.hs
+++ b/Text/Chatty/Interactor/Templates.hs
@@ -22,9 +22,10 @@
 -}
 
 -- | Declares serveral templates for comfortable instance derivation
-module Text.Chatty.Interactor.Templates (mkScanner, mkPrinter, mkFinalizer, mkExpander,mkExpanderEnv,mkHistoryEnv,mkInteractor,mkSpawn,mkRandom,mkClock,mkChatty,mkChannelPrinter,mkDefCP,mkArchiver,mkExtendedPrinter) where
+module Text.Chatty.Interactor.Templates (mkScanner, mkPrinter, mkFinalizer, mkExpander,mkExpanderEnv,mkHistoryEnv,mkInteractor,mkSpawn,mkRandom,mkClock,mkChatty,mkChannelPrinter,mkDefCP,mkArchiver,mkExtendedPrinter,mkBufferedScanner) where
 
 import Text.Chatty.Scanner
+import Text.Chatty.Scanner.Buffered
 import Text.Chatty.Printer
 import Text.Chatty.Finalizer
 import Text.Chatty.Expansion
@@ -53,6 +54,15 @@
   |]
   where sx = strToType s
 
+-- | Automatically derives a BufferedScanner instance for you.
+mkBufferedScanner :: Name -> Q [Dec]
+mkBufferedScanner s = [d|
+    instance BufferedScanner m => BufferedScanner ($sx m) where
+      mpeek1 = lift mpeek1
+      mprepend = lift . mprepend
+  |]
+  where sx = strToType s
+
 -- | Automatically derives a MonadPrinter instance for you.
 mkPrinter :: Name -> Q [Dec]
 mkPrinter s = [d|
@@ -176,6 +186,7 @@
   mkPrinter mkScanner mkFinalizer mkExpander
   mkSpawn mkRandom mkClock mkExpanderEnv
   mkHistoryEnv mkDefCP mkExtendedPrinter
+  mkBufferedScanner
 --  mkDefBC
 
 -- | Automatically derives all chatty typeclasses that are sensible for an ArchiverT.
diff --git a/Text/Chatty/Parser/Nondeterministic.hs b/Text/Chatty/Parser/Nondeterministic.hs
new file mode 100644
--- /dev/null
+++ b/Text/Chatty/Parser/Nondeterministic.hs
@@ -0,0 +1,81 @@
+{-
+  This module is part of Chatty.
+  Copyleft (c) 2014 Marvin Cohrs
+
+  All wrongs reversed. Sharing is an act of love, not crime.
+  Please share Antisplice with everyone you like.
+
+  Chatty is free software: you can redistribute it and/or modify
+  it under the terms of the GNU Affero General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  Chatty is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  GNU Affero General Public License for more details.
+
+  You should have received a copy of the GNU Affero General Public License
+  along with Chatty. If not, see <http://www.gnu.org/licenses/>.
+-}
+
+module Text.Chatty.Parser.Nondeterministic where
+
+import Control.Monad
+import Data.List
+import qualified Data.Foldable as F
+import Text.Chatty.Parser
+import Text.Chatty.Scanner
+
+data ForkerT m a = Result (m a) (Char -> ForkerT m a) | Failed
+
+instance (MonadPlus m,F.Foldable m) => Monad (ForkerT m) where
+  return a = Result (return a) $ const Failed
+  (Result as f) >>= m = Result (results >>= rResult) (\k -> F.foldl (???) (f k >>= m) (liftM (flip rFunction k) results))
+    where isResult (Result _ _) = True
+          isResult _ = False
+          rResult (Result x _) = x
+          rFunction (Result _ f) = f
+          results = mfilter isResult $ liftM m as
+  Failed >>= m = Failed
+  fail _ = Failed
+
+instance (MonadPlus m,F.Foldable m) => MonadParser (ForkerT m) where
+  pabort = Failed
+  Failed ?? b = b
+  a ?? Failed = a
+  (Result as f) ?? (Result bs g) = Result (msum $ liftM return $ nub $ F.foldr (:) [] $ mplus as bs) $ \k -> f k ?? g k
+  Failed ??? b = b
+  a ??? Failed = a
+  (Result as f) ??? (Result bs g) = Result (mplus as bs) $ \k -> f k ??? g k
+  ptry Failed = Failed
+  ptry (Result as f) = Result (msum $ liftM return [msum $ liftM return $ F.foldr (:) [] as]) $ \k -> ptry $ f k
+
+instance (MonadPlus m,F.Foldable m) => MonadScanner (ForkerT m) where
+  mscan1 = Result mzero return
+  mscanL = do
+    c <- mscan1
+    cs <- mscanL
+    return (c:cs)
+  mscannable = return True
+  mready = return False
+
+feedForkerT1 :: (MonadPlus m,F.Foldable m) => Char -> ForkerT m a -> ForkerT m a
+feedForkerT1 _ Failed = Failed
+feedForkerT1 c (Result _ f) = f c
+
+feedForkerT :: (MonadPlus m,F.Foldable m) => String -> ForkerT m a -> ForkerT m a
+feedForkerT [] = id
+feedForkerT (c:cs) = feedForkerT cs . feedForkerT1 c
+
+embedForkerT :: (MonadPlus n,F.Foldable n,MonadScanner m) => ForkerT n a -> m (n a)
+embedForkerT f = do
+  b <- mscannable
+  if not b then
+      case f of
+        Failed -> return mzero
+        Result xs _ -> return xs
+    else do
+      k <- mscan1
+      embedForkerT $ feedForkerT1 k f
+        
diff --git a/Text/Chatty/Scanner/Buffered.hs b/Text/Chatty/Scanner/Buffered.hs
new file mode 100644
--- /dev/null
+++ b/Text/Chatty/Scanner/Buffered.hs
@@ -0,0 +1,69 @@
+{-# LANGUAGE FlexibleInstances #-}
+
+{-
+  This module is part of Chatty.
+  Copyleft (c) 2014 Marvin Cohrs
+
+  All wrongs reversed. Sharing is an act of love, not crime.
+  Please share Antisplice with everyone you like.
+
+  Chatty is free software: you can redistribute it and/or modify
+  it under the terms of the GNU Affero General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  Chatty is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  GNU Affero General Public License for more details.
+
+  You should have received a copy of the GNU Affero General Public License
+  along with Chatty. If not, see <http://www.gnu.org/licenses/>.
+-}
+
+module Text.Chatty.Scanner.Buffered where
+
+import Control.Monad
+import Control.Monad.IO.Class
+import Control.Monad.State
+import Control.Monad.Trans.Class
+import Text.Chatty.Scanner
+
+class MonadScanner m => BufferedScanner m where
+  mpeek1 :: m Char
+  mprepend :: String -> m ()
+
+instance Monad m => BufferedScanner (StateT String m) where
+  mpeek1 = gets head
+  mprepend s = modify (s++)
+  
+instance Monad m => BufferedScanner (HereStringT m) where
+  mpeek1 = HereString $ \ss -> return (head ss, ss)
+  mprepend s = HereString $ \ss -> return ((), s++ss)
+
+newtype ScannerBufferT m a = ScannerBuffer { runScannerBufferT :: String -> m (a,String) }
+
+instance Monad m => Monad (ScannerBufferT m) where
+  return a = ScannerBuffer $ \s -> return (a,s)
+  (ScannerBuffer c) >>= f = ScannerBuffer $ \s -> do (a,s') <- c s; runScannerBufferT (f a) s'
+
+instance MonadTrans ScannerBufferT where
+  lift m = ScannerBuffer $ \s -> do a <- m; return (a,s)
+
+instance Monad m => Functor (ScannerBufferT m) where
+  fmap = liftM
+
+instance MonadScanner m => MonadScanner (ScannerBufferT m) where
+  mscan1 = ScannerBuffer $ \ss -> (if null ss then do s <- mscan1; return (s,[]) else return (head ss,tail ss))
+  mscanL = ScannerBuffer $ \ss -> do l <- mscanL; return (ss++l, [])
+  mscannable = ScannerBuffer $ \ss -> (if null ss then do b <- mscannable; return (b,[]) else return (True,ss))
+  mscanh = return Nothing
+  mready = ScannerBuffer $ \ss -> (if null ss then do b <- mready; return (b,[]) else return (True,ss))
+
+instance MonadIO m => MonadIO (ScannerBufferT m) where
+  liftIO = lift . liftIO
+
+instance MonadScanner m => BufferedScanner (ScannerBufferT m) where
+  mpeek1 = ScannerBuffer $ \ss -> (if null ss then do s <- mscan1; return (s,[s]) else return (head ss,ss))
+  mprepend s = ScannerBuffer $ \ss -> return ((),s++ss)
+
diff --git a/Text/Chatty/Typograph.hs b/Text/Chatty/Typograph.hs
new file mode 100644
--- /dev/null
+++ b/Text/Chatty/Typograph.hs
@@ -0,0 +1,60 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-
+  This module is part of Chatty.
+  Copyleft (c) 2014 Marvin Cohrs
+
+  All wrongs reversed. Sharing is an act of love, not crime.
+  Please share Antisplice with everyone you like.
+
+  Chatty is free software: you can redistribute it and/or modify
+  it under the terms of the GNU Affero General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  Chatty is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  GNU Affero General Public License for more details.
+
+  You should have received a copy of the GNU Affero General Public License
+  along with Chatty. If not, see <http://www.gnu.org/licenses/>.
+-}
+
+module Text.Chatty.Typograph where
+
+import Control.Monad
+import Control.Monad.Trans.Class
+import Data.Char
+import Text.Chatty.Interactor
+import Text.Chatty.Printer
+import Text.Chatty.Scanner
+import Text.Chatty.Scanner.Buffered
+
+simpleTypesetter :: (Functor m,MonadScanner m,MonadPrinter m) => Int -> m ()
+simpleTypesetter width = void $ runScannerBufferT (typeset width) ""
+  where scanw = mscannable >>= \b -> if not b then return [] else do
+          k <- mpeek1
+          if isSpace k then return [] else do
+            mscan1
+            ks <- scanw
+            return (k:ks)
+        skipw :: BufferedScanner m => m Int
+        skipw = mscannable >>= \b -> if not b then return 0 else do
+          k <- mpeek1
+          if not (isSpace k) then return 0 else do
+            mscan1
+            w <- skipw
+            return (w + if k == '\n' then 1 else 0)
+        tsetw i w
+          | length w < i = mprint (w ++ " ") >> typeset (i - 1 - length w)
+          | length w == i = mprintLn w >> typeset width
+          | length w > width && i == width = mprintLn (take i w) >> tsetw width (drop i w)
+          | otherwise = mprintLn "" >> tsetw width w
+        typeset i = mscannable >>= \b -> when b $ do
+          ls <- skipw
+          if ls > 0
+            then forM_ [1..ls] (const $ mprintLn "") >> typeset width
+            else do
+              w <- scanw
+              tsetw i w
diff --git a/chatty.cabal b/chatty.cabal
--- a/chatty.cabal
+++ b/chatty.cabal
@@ -10,7 +10,7 @@
 -- PVP summary:      +-+------- breaking API changes
 --                   | | +----- non-breaking API additions
 --                   | | | +--- code changes with no API change
-version:             0.5.4.2
+version:             0.5.5.0
 
 -- A short (one-line) description of the package.
 synopsis:            Some monad transformers and typeclasses to simplify I/O on a transformer stack.
@@ -48,7 +48,7 @@
 
 library
   -- Modules exported by the library.
-  exposed-modules:     Text.Chatty.Expansion, System.Chatty.Commands, System.Chatty.Spawn, Text.Chatty.Printer, Text.Chatty.Finalizer, Text.Chatty.Templates, Text.Chatty.Scanner, Text.Chatty.Interactor, System.Chatty.Spawn.Overlay, System.Chatty.Spawn.Builtins, Text.Chatty.Interactor.Templates, System.Chatty.Misc, Text.Chatty.Extended.Printer, Text.Chatty.Extended.HTML, Text.Chatty.Extended.ANSI, Text.Chatty.Expansion.Vars, Text.Chatty.Expansion.History, Text.Chatty.Channel.Printer, Text.Chatty.Channel.Broadcast
+  exposed-modules:     Text.Chatty.Expansion, System.Chatty.Commands, System.Chatty.Spawn, Text.Chatty.Printer, Text.Chatty.Finalizer, Text.Chatty.Templates, Text.Chatty.Scanner, Text.Chatty.Interactor, System.Chatty.Spawn.Overlay, System.Chatty.Spawn.Builtins, Text.Chatty.Interactor.Templates, System.Chatty.Misc, Text.Chatty.Extended.Printer, Text.Chatty.Extended.HTML, Text.Chatty.Extended.ANSI, Text.Chatty.Expansion.Vars, Text.Chatty.Expansion.History, Text.Chatty.Channel.Printer, Text.Chatty.Channel.Broadcast, Text.Chatty.Scanner.Buffered, Text.Chatty.Typograph, Text.Chatty.Parser.Nondeterministic
   
   -- Modules included in this library but not exported.
   -- other-modules:       
