diff --git a/cmdtheline.cabal b/cmdtheline.cabal
--- a/cmdtheline.cabal
+++ b/cmdtheline.cabal
@@ -1,5 +1,5 @@
 Name: cmdtheline
-Version: 0.2.2
+Version: 0.2.3
 Synopsis: Declarative command-line option parsing and documentation library.
 Description:
   CmdTheLine aims to remove tedium from the definition of command-line
@@ -97,3 +97,10 @@
   ghc-options:   -Wall -Werror -fno-warn-name-shadowing -rtsopts
   hs-source-dirs: src, test
   main-is:        Main.hs
+  other-modules:  Arith,
+                  Cipher,
+                  CP,
+                  Fail,
+                  FizzBuzz,
+                  Grep,
+                  Hello
diff --git a/src/System/Console/CmdTheLine/Manpage.hs b/src/System/Console/CmdTheLine/Manpage.hs
--- a/src/System/Console/CmdTheLine/Manpage.hs
+++ b/src/System/Console/CmdTheLine/Manpage.hs
@@ -56,7 +56,7 @@
     where
     content = try escape <|> choice replacers <|> safeChars
 
-  escape = esc <$> (anyChar <* char ',') <*> try replace <|> safeChars
+  escape = esc <$> (anyChar <* char ',') <*> (try replace <|> safeChars)
 
   safeChars = many1 $ satisfy (/= ')')
 
diff --git a/test/Arith.hs b/test/Arith.hs
new file mode 100644
--- /dev/null
+++ b/test/Arith.hs
@@ -0,0 +1,177 @@
+-- We need 'FlexibleInstances to instance 'ArgVal' for 'Maybe Exp' and
+-- '( String, Exp )'.
+{-# LANGUAGE FlexibleInstances #-}
+module Arith where
+
+import Prelude hiding ( exp )
+import System.Console.CmdTheLine hiding ( eval )
+import Control.Applicative       hiding ( (<|>) )
+
+import Control.Monad ( guard )
+import Data.Char     ( isAlpha )
+import Data.Function ( on )
+
+import Text.Parsec
+import qualified Text.PrettyPrint as PP
+
+import qualified Data.Map as M
+
+import System.IO
+
+type Parser a = Parsec String () a
+
+data Bin = Pow | Mul | Div | Add | Sub
+
+prec :: Bin -> Int
+prec b = case b of
+  { Pow -> 3 ; Mul -> 2 ; Div -> 2 ; Add -> 1 ; Sub -> 1 }
+
+assoc :: Bin -> Assoc
+assoc b = case b of
+  Pow -> R
+  _   -> L
+
+toFunc :: Bin -> (Int -> Int -> Int)
+toFunc b = case b of
+  { Pow -> (^) ; Mul -> (*) ; Div -> div ; Add -> (+) ; Sub -> (-) }
+
+data Exp = IntExp Int
+         | VarExp String
+         | BinExp Bin Exp Exp
+
+instance ArgVal Exp where
+  converter = ( parser, pretty 0 )
+    where
+    parser = fromParsec onErr exp
+    onErr str =  PP.text "invalid expression" PP.<+> PP.quotes (PP.text str)
+
+instance ArgVal (Maybe Exp) where
+  converter = just
+
+instance ArgVal ( String, Exp ) where
+  converter = pair '='
+
+data Assoc = L | R
+
+type Env = M.Map String Exp
+
+catParsers :: [Parser String] -> Parser String
+catParsers = foldl (liftA2 (++)) (return "")
+
+integer :: Parser Int
+integer = read <$> catParsers [ option "" $ string "-", many1 digit ]
+
+tok :: Parser a -> Parser a
+tok p = p <* spaces
+
+parens :: Parser a -> Parser a
+parens = between op cp
+  where
+  op = tok $ char '('
+  cp = tok $ char ')'
+
+-- Parse a terminal expression.
+term :: Parser Exp
+term = parens exp <|> int <|> var
+  where
+  int = tok $ IntExp <$> try integer -- Try so '-<not-digits>' won't fail.
+  var = tok $ VarExp <$> many1 (satisfy isAlpha)
+
+-- Parse a binary operator.
+bin :: Parser Bin
+bin = choice [ pow, mul, div, add, sub ]
+  where
+  pow = tok $ Pow <$ char '^'
+  mul = tok $ Mul <$ char '*'
+  div = tok $ Div <$ char '/'
+  add = tok $ Add <$ char '+'
+  sub = tok $ Sub <$ char '-'
+
+exp :: Parser Exp
+exp = e 0
+
+-- Precedence climbing expressions.  See
+-- <www.engr.mun.ca/~theo/Misc/exp_parsing.htm> for further information.
+e :: Int -> Parser Exp
+e p = do
+  t <- term
+  try (go t) <|> return t
+  where
+  go e1 = do
+    b <- bin
+    guard $ prec b >= p
+
+    let q = case assoc b of
+          R -> prec b
+          L -> prec b + 1
+    e2 <- e q
+
+    let expr = BinExp b e1 e2
+    try (go expr) <|> return expr
+
+-- Beta reduce by replacing variables in 'e' with values in 'env'.
+beta :: Env -> Exp -> Maybe Exp
+beta env e = case e of
+  VarExp str     -> M.lookup str env
+  int@(IntExp _) -> return int
+  BinExp b e1 e2 -> (liftA2 (BinExp b) `on` beta env) e1 e2
+
+eval :: Exp -> Int
+eval e = case e of
+  VarExp str     -> error $ "saw VarExp " ++ str ++ " while evaluating"
+  IntExp i       -> i
+  BinExp b e1 e2 -> (toFunc b `on` eval) e1 e2
+
+pretty :: Int -> Exp -> PP.Doc
+pretty p e = case e of
+  VarExp str     -> PP.text str
+  IntExp i       -> PP.int i
+  BinExp b e1 e2 -> let q = prec b
+                    in  parensOrNot q $ PP.cat [ pretty q e1, ppBin b, pretty q e2 ]
+  where
+  parensOrNot q = if q < p then PP.parens else id
+
+ppBin :: Bin -> PP.Doc
+ppBin b = case b of
+  Pow -> PP.char '^'
+  Mul -> PP.char '*'
+  Div -> PP.char '/'
+  Add -> PP.char '+'
+  Sub -> PP.char '-'
+
+arith :: Bool -> [( String, Exp )] -> Exp -> IO ()
+arith pp assoc = maybe badEnv method . beta (M.fromList assoc)
+  where
+  method = if pp then print . pretty 0 else print . eval
+  badEnv = hPutStrLn stderr "arith: bad environment"
+
+arithTerm :: Term (IO ())
+arithTerm = arith <$> pp <*> env <*> e
+  where
+  pp = value $ flag (optInfo [ "pretty", "p" ])
+     { optName = "PP"
+     , optDoc  = "If present, pretty print instead of evaluating EXP."
+     }
+
+  env = nonEmpty $ posRight 0 [] posInfo
+      { posName = "ENV"
+      , posDoc  = "One or more assignments of the form '<name>=<exp>' to be "
+               ++ "substituted in the input expression."
+      }
+
+  e = required $ pos 0 Nothing posInfo
+    { posName = "EXP"
+    , posDoc  = "An arithmetic expression to be evaluated."
+    }
+
+termInfo :: TermInfo
+termInfo = defTI
+  { termName = "arith"
+  , version  = "0.3"
+  , termDoc  = "Evaluate mathematical functions demonstrating precedence "
+           ++ "climbing and instantiating 'ArgVal' for tuples and Parsec "
+           ++ "parsers."
+  , man      = [ S "BUGS"
+              , P "Email bug reports to <fitsCarolDo@example.com>"
+              ]
+  }
diff --git a/test/CP.hs b/test/CP.hs
new file mode 100644
--- /dev/null
+++ b/test/CP.hs
@@ -0,0 +1,79 @@
+module CP where
+import System.Console.CmdTheLine
+import Control.Applicative
+
+import System.Directory ( copyFile
+                        , doesDirectoryExist
+                        )
+import System.FilePath  ( takeFileName
+                        , pathSeparator
+                        , hasTrailingPathSeparator
+                        )
+
+import System.IO
+import System.Exit ( exitFailure )
+
+sep :: String
+sep = [pathSeparator]
+
+cp :: Bool -> [String] -> String -> IO ()
+cp dry sources dest =
+  chooseTactic =<< doesDirectoryExist dest
+  where
+  chooseTactic isDir
+    | singleFile = singleCopy $ head sources
+    | not isDir  = notDirErr
+    | otherwise  = mapM_ copyToDir sources
+    where
+    singleCopy = if isDir then copyToDir else copyToFile
+
+  singleFile = length sources == 1
+
+  notDirErr = do
+    hPutStrLn stderr "cp: DEST is not a directory and SOURCES is of length >1."
+    exitFailure
+
+  copyToDir filePath = if dry
+    then putStrLn $ concat [ "cp: copying ", filePath, " to ", dest' ]
+    else copyFile filePath dest'
+    where
+    dest'           = withTrailingSep ++ takeFileName filePath
+    withTrailingSep =
+      if hasTrailingPathSeparator dest then dest else dest ++ sep
+
+  copyToFile filePath = if dry
+    then putStrLn $ concat [ "cp: copying ", filePath, " to ", dest ]
+    else copyFile filePath dest
+
+
+-- An example of using the 'rev' and 'Left' variants of 'pos', as well as
+-- validating file paths.
+term :: Term (IO ())
+term = cp <$> dry <*> filesExist sources <*> validPath dest
+  where
+  dry = value $ flag (optInfo [ "dry", "d" ])
+      { optName = "DRY"
+      , optDoc  = "Perform a dry run.  Print what would be copied, but do not "
+               ++ "copy it."
+      }
+
+  sources = nonEmpty $ revPosLeft 0 [] posInfo
+          { posName = "SOURCES"
+          , posDoc  = "Source file(s) to copy."
+          }
+
+  dest    = required $ revPos 0 Nothing posInfo
+          { posName = "DEST"
+          , posDoc  = "Destination of the copy. Must be a directory if there "
+                   ++ "is more than one $(i,SOURCE)."
+          }
+
+termInfo :: TermInfo
+termInfo = defTI
+  { termName = "cp"
+  , version  = "v1.0"
+  , termDoc  = "Copy files from SOURCES to DEST."
+  , man      = [ S "BUGS"
+               , P "Email bug reports to <portManTwo@example.com>"
+               ]
+  }
diff --git a/test/Cipher.hs b/test/Cipher.hs
new file mode 100644
--- /dev/null
+++ b/test/Cipher.hs
@@ -0,0 +1,227 @@
+module Cipher where
+import System.Console.CmdTheLine
+import Control.Applicative
+
+import Data.Char ( isUpper, isAlpha, isAlphaNum, isSpace
+                 , toLower
+                 )
+import Data.List ( intersperse )
+
+import System.IO
+import System.Exit
+
+infixr 2 <||>
+-- Split a value between predicates and 'or' the results together
+(<||>) :: (a -> Bool) -> (a -> Bool) -> (a -> Bool)
+p <||> p' = (||) <$> p <*> p'
+
+
+--
+-- Rot
+--
+
+data Cycle a = Cycle
+  { backward :: (Cycle a)
+  , at       :: a
+  , forward  :: (Cycle a)
+  }
+
+fromList :: [a] -> Cycle a
+fromList [] = error "Cycle must have at least one element"
+fromList xs = first
+  where
+  ( first, last ) = go last xs first
+
+  go :: Cycle a -> [a] -> Cycle a -> ( Cycle a, Cycle a )
+  go prev []       next = ( next, prev )
+  go prev (x : xs) next = ( this, last )
+    where
+    this        = Cycle prev x rest
+    (rest,last) = go this xs next
+
+-- Return a Cycle centered on x.
+seekTo :: Eq a => a -> Cycle a -> Cycle a
+seekTo x xs
+  | x == at xs = xs
+  | otherwise  = seekTo x $ forward xs
+ 
+-- Seek n places forwards or backwards.
+seek :: Bool -> Int -> Cycle a -> Cycle a
+seek _    0 xs = xs
+seek back n xs = seek back (n - 1) (dir xs)
+  where
+  dir = if back then backward else forward
+
+lowers, uppers :: Cycle Char
+lowers = fromList ['a'..'z']
+uppers = fromList ['A'..'Z']
+
+rot :: Bool -> Int -> Maybe String -> IO ()
+rot back n mStr = do
+  input <- case mStr of
+    Nothing  -> getContents
+    Just str -> return str
+
+  putStrLn $ map rotChar input
+  where
+  rotChar c = if isAlpha c then c' else c
+    where
+    c'    = at . seek back n $ seekTo c cycle
+    cycle = if isUpper c then uppers else lowers
+
+
+--
+-- Morse
+--
+
+switch :: ( a, b ) -> ( b, a )
+switch ( x, y ) = ( y, x )
+
+fromCode :: [( String, Char )]
+fromCode = map switch toCode
+
+toCode :: [( Char, String )]
+toCode =
+  [ ( 'a', ".-"    ), ( 'b', "-..."  ), ( 'c', "-.-."  ), ( 'd', "-.."   )
+  , ( 'e', "."     ), ( 'f', "..-."  ), ( 'g', "--."   ), ( 'h', "...."  )
+  , ( 'i', ".."    ), ( 'j', ".---"  ), ( 'k', "-.-"   ), ( 'l', ".-.."  )
+  , ( 'm', "--"    ), ( 'n', "-."    ), ( 'o', "---"   ), ( 'p', ".--."  )
+  , ( 'q', "--.-"  ), ( 'r', ".-."   ), ( 's', "..."   ), ( 't', "-"     )
+  , ( 'u', "..-"   ), ( 'v', "...-"  ), ( 'w', ".--"   ), ( 'x', "-..-"  )
+  , ( 'y', "-.--"  ), ( 'z', "--.."  ), ( '1', ".----" ), ( '2', "..---" )
+  , ( '3', "...--" ), ( '4', "....-" ), ( '5', "....." ), ( '6', "-...." )
+  , ( '7', "--..." ), ( '8', "---.." ), ( '9', "----." ), ( '0', "-----" )
+  , ( ' ', "/"     )
+  ]
+
+fromMorse, toMorse :: [String] -> Maybe String
+fromMorse    = mapM (`lookup` fromCode)
+toMorse strs = sepCat " / " <$> mapM convertLetters strs
+  where
+  convertLetters chars = sepCat " " <$> mapM (`lookup` toCode) chars
+
+  sepCat sep = concat . intersperse sep
+
+morse :: Bool -> Maybe String -> IO ()
+morse from mStr = do
+  input <- case mStr of
+    Nothing  -> getContents
+    Just str -> return str
+
+  if all pred input
+     then return ()
+     else do hPutStrLn stderr err
+             exitFailure
+
+  convert input
+  where
+  pred = if from then (== '/') <||> (== '-') <||> (== '.') <||> isSpace
+                 else isAlphaNum <||> isSpace
+
+  err = if from
+    then "cipher: morse input must be all spaces, '/'s, '-'s, and '.'s."
+    else "cipher: morse input must be alphanumeric and/or spaces"
+
+  convert str = maybe badConvert putStrLn . convert' . words $ map toLower str
+    where
+    badConvert = hPutStrLn stderr err >> exitFailure
+      where
+      err = if from then "cipher: could not convert from morse"
+                    else "cipher: could not convert to morse"
+
+    convert' = if from then fromMorse else toMorse
+
+
+--
+-- Terms
+--
+
+-- The heading under which to place common options.
+comOpts :: String
+comOpts = "COMMON OPTIONS"
+
+-- A modified default 'TermInfo' to be shared by commands.
+defTI' :: TermInfo
+defTI' = defTI
+  { man =
+      [ S comOpts
+      , P "These options are common to all commands."
+      , S "MORE HELP"
+      , P "Use '$(mname) $(i,COMMAND) --help' for help on a single command."
+      , S "BUGS"
+      , P "Email bug reports to <snideHighland@example.com>"
+      ]
+  , stdOptSec = comOpts
+  }
+
+-- 'input' is a common option. We set its 'optSec' field to 'comOpts' so
+-- that it is placed under that section instead of the default '"OPTIONS"'
+-- section, which we will reserve for command-specific options.
+input :: Term (Maybe String)
+input = value $ opt Nothing (optInfo [ "input", "i" ])
+      { optName = "INPUT"
+      , optDoc  = "For specifying input on the command line.  If present, "
+               ++ "input is not read form standard-in."
+      , optSec  = comOpts
+      }
+
+rotTerm :: ( Term (IO ()), TermInfo )
+rotTerm = ( rot <$> back <*> n <*> input, termInfo )
+  where
+  back = value $ flag (optInfo [ "back", "b" ])
+       { optName = "BACK"
+       , optDoc  = "Rotate backwards instead of forwards."
+       }
+
+  n    = value $ opt 13 (optInfo [ "n" ])
+       { optName = "N"
+       , optDoc  = "How many places to rotate by."
+       }
+
+  termInfo = defTI'
+    { termName = "rot"
+    , termDoc  = "Rotate the input characters by N."
+    , man      = [ S "DESCRIPTION"
+                 , P $ "Rotate input gathered from INPUT or standard-in N "
+                    ++ "places.  The input must be composed totally of "
+                    ++ "alphabetic characters and spaces."
+                 ] ++ man defTI'
+    }
+
+morseTerm :: ( Term (IO ()), TermInfo )
+morseTerm = ( morse <$> from <*> input, termInfo )
+  where
+  from = value $ flag (optInfo [ "from", "f" ])
+       { optName   = "FROM"
+       , optDoc    = "Convert from morse-code to the Latin alphabet. "
+                  ++ "If absent, convert from Latin alphabet to morse-code."
+       }
+
+  termInfo = defTI'
+    { termName = "morse"
+    , termDoc  = "Convert to and from morse-code."
+    , man      = [ S "DESCRIPTION"
+                 , P desc
+                 ] ++ man defTI'
+    }
+
+  desc = concat
+    [ "Converts input gathered from INPUT or standard in to and from morse "
+    , "code. 'dah' is represented by '-', 'dit' by '.'.  Each morse character "
+    , "is separated from the next by one or more ' '.  Morse words are "
+    , "separated by a '/'."
+    ]
+
+
+defaultTerm :: ( Term a, TermInfo )
+defaultTerm = ( ret $ const (helpFail Pager Nothing) <$> input
+              , termInfo
+              )
+  where
+  termInfo = defTI'
+    { termName      = "cipher"
+    , version       = "v1.0"
+    , termDoc       = doc
+    }
+
+  doc = "An implementation of the morse-code and rotational(Caesar) ciphers."
diff --git a/test/Fail.hs b/test/Fail.hs
new file mode 100644
--- /dev/null
+++ b/test/Fail.hs
@@ -0,0 +1,83 @@
+module Fail where
+import System.Console.CmdTheLine
+import Control.Applicative
+
+import Text.PrettyPrint ( fsep   -- Paragraph fill a list of 'Doc'.
+                        , text   -- Make a 'String' into a 'Doc'.
+                        , quotes -- Quote a 'Doc'.
+                        , (<+>)  -- Glue two 'Doc' together with a space.
+                        )
+
+import Data.List ( intersperse )
+
+
+cmdNames = [ "msg", "usage", "help", "success" ]
+
+failMsg, failUsage, success :: [String] -> Err String
+failMsg   strs = msgFail   . fsep $ map text strs
+failUsage strs = usageFail . fsep $ map text strs
+success   strs = return . concat $ intersperse " " strs
+
+help :: String -> Err String
+help name
+  | any (== name) cmdNames = helpFail Pager $ Just name
+  | name == ""             = helpFail Pager Nothing
+  | otherwise              =
+    usageFail $ quotes (text name) <+> text "is not the name of a command"
+
+noCmd :: Err String
+noCmd = helpFail Pager Nothing
+
+
+def' = defTI
+  { stdOptSec = "COMMON OPTIONS"
+  , man =
+      [ S "COMMON OPTIONS"
+      , P "These options are common to all commands."
+      , S "MORE HELP"
+      , P "Use '$(mname) $(i,COMMAND) --help' for help on a single command."
+      , S "BUGS"
+      , P "Email bug reports to <dogWalter@example.com>"
+      ]
+  }
+
+input :: Term [String]
+input = nonEmpty $ posAny [] posInfo
+      { posName = "INPUT"
+      , posDoc  = "Some input you would like printed to the screen on failure "
+               ++ "or success."
+      }
+
+cmds :: [( Term String, TermInfo )]
+cmds =
+  [ ( ret $ failMsg <$> input
+    , def' { termName = "msg"
+           , termDoc  = "Print a failure message."
+           }
+    )
+
+  , ( ret $ failUsage <$> input
+    , def' { termName = "usage"
+           , termDoc  = "Print a usage message."
+           }
+    )
+
+  , ( ret $ success <$> input
+    , def' { termName = "success"
+           , termDoc  = "Print a message to the screen"
+           }
+    )
+
+  , ( ret $ help <$> value (pos 0 "" posInfo { posName = "TERM" })
+    , def' { termName = "help"
+           , termDoc  = "Display help for a command."
+           }
+    )
+  ]
+
+noCmdTerm = ( ret $ pure noCmd
+            , def' { termName = "fail"
+                   , termDoc  = "A program demoing CmdTheLine's user "
+                             ++ "error functionality."
+                   }
+            )
diff --git a/test/FizzBuzz.hs b/test/FizzBuzz.hs
new file mode 100644
--- /dev/null
+++ b/test/FizzBuzz.hs
@@ -0,0 +1,68 @@
+module FizzBuzz where
+import System.Console.CmdTheLine
+import Control.Applicative
+
+import System.Exit ( exitSuccess )
+
+data Verbosity = Verbose | Normal | Silent
+
+fizzBuzz :: Verbosity -> String -> String -> Int -> IO ()
+fizzBuzz verb fizz buzz n = do
+  case verb of
+    Verbose -> putStrLn $ concat
+      [ "FizzBuzz: Printing the result of FizzBuzz over the numbers 1 to ", show n
+      , "\nFizz = ", fizz, "\nBuzz = ", buzz
+      ]
+    Silent  -> exitSuccess
+    _       -> return ()
+
+  mapM_ fizzAndBuzzOr [1..n]
+  where
+  fizzAndBuzzOr n = putStrLn output
+    where
+    output = case fizz' ++ buzz' of
+      ""  -> show n
+      str -> str
+
+    fizz' = if (n `mod` 3) == 0 then fizz else ""
+    buzz' = if (n `mod` 5) == 0 then buzz else ""
+
+
+-- A flag that can appear many times on the command line, only the last of
+-- which will be counted.
+verbosity :: Term Verbosity
+verbosity = lastOf $ vFlagAll [Normal] [ ( Verbose, verbose )
+                                       , ( Silent,  silent  )
+                                       ]
+  where
+  verbose =(optInfo [ "verbose", "v" ])
+          { optDoc  = "Give verbose output." }
+
+  silent  =(optInfo [ "quiet", "silent", "q", "s" ])
+          { optDoc  = "Provide no output." }
+
+fizz, buzz :: Term String
+fizz = value $ opt "Fizz" (optInfo [ "Fizz", "fizz", "f" ])
+     { optDoc = "A string to print in the 'Fizz' case." }
+
+buzz = value $ opt "Buzz" (optInfo [ "Buzz", "buzz", "b" ])
+     { optDoc = "A string to print in the 'Buzz' case." }
+
+times :: Term Int
+times = value $ opt 100 (optInfo [ "times", "t" ])
+      { optName = "TIMES"
+      , optDoc  = "Run $(mname) for the numbers 1 to $(argName)."
+      }
+
+term :: Term (IO ())
+term = fizzBuzz <$> verbosity <*> fizz <*> buzz <*> times
+
+termInfo :: TermInfo
+termInfo = defTI
+  { termName = "FizzBuzz"
+  , version  = "v1.0"
+  , termDoc  = "An implementation of the world renowned FizzBuzz algorithm."
+  , man      = [ S "BUGS"
+               , P "Email bug reports to <sirFrancisDrank@example.com>"
+               ]
+  }
diff --git a/test/Grep.hs b/test/Grep.hs
new file mode 100644
--- /dev/null
+++ b/test/Grep.hs
@@ -0,0 +1,28 @@
+module Grep where
+import System.Console.CmdTheLine
+import Control.Applicative
+
+import Data.List ( intersperse )
+
+import System.Cmd  ( system )
+import System.Exit ( exitWith )
+
+grep :: String -> [String] -> IO ()
+grep pattern dests = do
+  exitWith =<< system (concat . intersperse " " $ [ "grep", pattern ] ++ dests)
+
+-- An example of using the 'pos' and 'posRight' Terms.
+term = grep <$> pattern <*> files
+  where
+  pattern  = required $ pos 0 Nothing posInfo { posName = "PATTERN" }
+  files    = value    $ posRight 0 [] posInfo { posName = "FILE"    }
+
+termInfo = defTI
+  { termName = "grep"
+  , version  = "2.5"
+  , termDoc  = "Search for PATTERN in FILE(s) or standard in."
+  , man      =
+    [ S "BUGS"
+    , P "Please send bug reports to <throatWobblerMangrove@example.com>"
+    ]
+  }
diff --git a/test/Hello.hs b/test/Hello.hs
new file mode 100644
--- /dev/null
+++ b/test/Hello.hs
@@ -0,0 +1,23 @@
+module Hello where
+import System.Console.CmdTheLine
+import Control.Applicative
+
+import Control.Monad ( when )
+
+-- Define a flag argument under the names '--silent' and '-s'
+silent :: Term Bool
+silent = value . flag $ optInfo [ "silent", "s" ]
+
+-- Define the 0th positional argument, defaulting to the value '"world"' in
+-- absence.
+greeted :: Term String
+greeted = value $ pos 0 "world" posInfo { posName = "GREETED" }
+
+hello :: Bool -> String -> IO ()
+hello silent str = when (not silent) . putStrLn $ "Hello, " ++ str ++ "!"
+
+term :: Term (IO ())
+term = hello <$> silent <*> greeted
+
+termInfo :: TermInfo
+termInfo = defTI { termName = "Hello", version = "1.0" }
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -16,6 +16,7 @@
 import System.FilePath  ( (</>) )
 
 import System.Console.CmdTheLine ( unwrap, unwrapChoice, EvalExit )
+import System.Console.CmdTheLine.Manpage ( substitute, plainEsc )
 
 import Control.Applicative ( (<$>) )
 
@@ -104,6 +105,11 @@
       isRight <$> unwrapCP [ "-d", "cmdtheline.cabal", "LICENSE", "test" ]
     , testCase " w/ good args one" . assert $
       isRight <$> unwrapCP [ "-d", "cmdtheline.cabal", "foo" ]
+    ]
+
+  , testGroup "unittests"
+    [ testCase " escaping $(i,...)" . assert $ substitute plainEsc [] "$(i,foo)" == "foo"
+    , testCase " escaping $(b,...)" . assert $ substitute plainEsc [] "$(b,foo)" == "foo"
     ]
   ]
 
