diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,27 @@
+## Version 0.15.0.0 (05 Jul 2019)
+
+- Add support for GHC 8.8.1.
+
+- Add `subparserInline` modifier as additional way of
+  executing subparsers. When activated, the subparser
+  parse tree will be inserted into that of the parent
+  instead of being run independently, allowing mixing
+  of child and parent options.
+
+- Improve rendering of complex nested parse structures.
+  Previously, brackets and parenthesis did not respect
+  whether or not options had to be defined together.
+  Now the parse tree is more accurately represeted in
+  the help text.
+
+- Add `helpLongEquals` modifier, which will change how
+  long options are printed in the help text, adding an
+  equals sign, for example "--input=FILE".
+
+- Updated dependency bounds.
+
+- Clean ups and Documentation.
+
 ## Version 0.14.3.0 (03 Oct 2018)
 
 - Updated dependency bounds.
@@ -97,17 +121,17 @@
   fires when a command or subcommand is begun, and suppresses the "Missing:"
   error text.
 
-- Fix ghc 8.0 warnings
+- Fix ghc 8.0 warnings.
 
-- Fix ghc 7.10 warnings
+- Fix ghc 7.10 warnings.
 
-- Bump dependency bounds
+- Bump dependency bounds.
 
-- Add maybeReader function for convenient ReadM creation
+- Add maybeReader function for convenient ReadM creation.
 
-- Move eitherReader to Readers section (for better discoverability)
+- Move eitherReader to Readers section (for better discoverability).
 
-- Fix hsubparser metavar override
+- Fix hsubparser metavar override.
 
 - Remove ComplError, which was dead code.
 
@@ -123,9 +147,9 @@
 
 - Updated dependency bounds.
 
-- Improve subparser contexts to improve usage error texts
+- Improve subparser contexts to improve usage error texts.
 
-- Doc
+- Docs.
 
 - Fixed bugs
     * \# 164 - Invalid options and invalid arguments after parser has succeeded
@@ -145,7 +169,7 @@
 
 - Add `Show` and `Eq` instances to some types for easier debugging.
 
-- Add defaultPrefs, a default preferences value
+- Add defaultPrefs, a default preferences value.
 
 - Docs.
 
@@ -243,7 +267,7 @@
 
 ## Version 0.7.0.1 (18 Oct 2013)
 
-- Minor docs fixes
+- Minor docs fixes.
 
 ## Version 0.7.0 (17 Oct 2013)
 
@@ -271,15 +295,15 @@
     * \#44 - Can the build input restriction process == 1.1.* be relaxed?
     * \#28 - Help for subcommands
 
-## Version 0.5.2.1 (24 Dic 2012)
+## Version 0.5.2.1 (24 Dec 2012)
 
 - Minor docs fixes.
 
-## Version 0.5.2 (23 Dic 2012)
+## Version 0.5.2 (23 Dec 2012)
 
 - Fixed compatibility with GHC 7.2.
 
-## Version 0.5.1 (23 Dic 2012)
+## Version 0.5.1 (23 Dec 2012)
 
 - There is a new parser preference `noBacktrack`, that controls whether how a
   failure in a subparser is propagated. By default, an unknown option in a
@@ -295,7 +319,7 @@
     * \#29 - Document Mod
     * \#26 - Improve docs for the `Arrow` interface
 
-## Version 0.5.0 (22 Dic 2012)
+## Version 0.5.0 (22 Dec 2012)
 
 - Fewer GHC extensions required.
 
@@ -311,7 +335,7 @@
 - Fixed bugs
     * \#37 - Use (\<\>) instead of (&) in documentation
 
-## Version 0.4.3 (09 Dic 2012)
+## Version 0.4.3 (09 Dec 2012)
 
 - Updated dependency bounds.
 
@@ -402,20 +426,20 @@
 
 ## Version 0.1.1 (21 Jul 2012)
 
-- New arrow interface
+- New arrow interface.
 
 - Fixed bugs
-      * \#7 - "arguments" reads positional arguments in reverse
+    * \#7 - "arguments" reads positional arguments in reverse
 
 ## Version 0.1.0 (07 Jul 2012)
 
-- Improved error reporting internals
+- Improved error reporting internals.
 
-- Removed template-haskell dependency
+- Removed template-haskell dependency.
 
 - Fixed bugs:
-      * \#3 - No help for subparsers
-      * \#4 - Extra empty lines around command list
+    * \#3 - No help for subparsers
+    * \#4 - Extra empty lines around command list
 
 ## Version 0.0.1 (09 Jun 2012)
 
diff --git a/Options/Applicative.hs b/Options/Applicative.hs
deleted file mode 100644
--- a/Options/Applicative.hs
+++ /dev/null
@@ -1,235 +0,0 @@
-module Options.Applicative (
-  -- * Applicative option parsers
-  --
-  -- | This module exports all one should need for defining and using
-  -- optparse-applicative command line option parsers.
-  --
-  -- See <https://github.com/pcapriotti/optparse-applicative> for a tutorial,
-  -- and a general introduction to applicative option parsers.
-  --
-  -- See the sections below for more detail
-
-  -- * Exported modules
-  --
-  -- | The standard @Applicative@ module is re-exported here for convenience.
-  module Control.Applicative,
-
-  -- * Option Parsers
-  --
-  -- | A 'Parser' is the core type in optparse-applicative. A value of type
-  -- @Parser a@ represents a specification for a set of options, which will
-  -- yield a value of type a when the command line arguments are successfully
-  -- parsed.
-  --
-  -- There are several types of primitive 'Parser'.
-  --
-  -- * Flags: simple no-argument options. When a flag is encountered on the
-  -- command line, its value is returned.
-  --
-  -- * Options: options with an argument. An option can define a /reader/,
-  -- which converts its argument from String to the desired value, or throws a
-  -- parse error if the argument does not validate correctly.
-  --
-  -- * Arguments: positional arguments, validated in the same way as option
-  -- arguments.
-  --
-  -- * Commands. A command defines a completely independent sub-parser. When a
-  -- command is encountered, the whole command line is passed to the
-  -- corresponding parser.
-  --
-  -- See the "Parser Builders" section for how to construct and customise
-  -- these parsers.
-  Parser,
-
-  -- ** Parser builders
-  --
-  -- | This section contains utility functions and combinators to create parsers
-  -- for individual options.
-  --
-  -- Each parser builder takes an option modifier. A modifier can be created by
-  -- composing the basic modifiers provided by here using the 'Monoid' operations
-  -- 'mempty' and 'mappend', or their aliases 'idm' and '<>'.
-  --
-  -- For example:
-  --
-  -- > out = strOption
-  -- >     ( long "output"
-  -- >    <> short 'o'
-  -- >    <> metavar "FILENAME" )
-  --
-  -- creates a parser for an option called \"output\".
-  flag,
-  flag',
-  switch,
-
-  strOption,
-  option,
-
-  strArgument,
-  argument,
-
-  subparser,
-  hsubparser,
-
-  abortOption,
-  infoOption,
-  helper,
-
-  -- ** Modifiers
-  --
-  -- | 'Parser' builders take a modifier, which represents a modification of the
-  -- properties of an option, and can be composed as a monoid.
-  --
-  -- Contraints are often used to ensure that the modifiers can be sensibly applied.
-  -- For example, positional arguments can't be specified by long or short names,
-  -- so the 'HasName' constraint is used to ensure we have a flag or option.
-  Mod,
-
-  short,
-  long,
-  help,
-  helpDoc,
-  value,
-  showDefaultWith,
-  showDefault,
-  metavar,
-  noArgError,
-  hidden,
-  internal,
-  style,
-  command,
-  commandGroup,
-  completeWith,
-  action,
-  completer,
-  idm,
-  mappend,
-
-  OptionFields,
-  FlagFields,
-  ArgumentFields,
-  CommandFields,
-
-  HasName,
-  HasCompleter,
-  HasValue,
-  HasMetavar,
-  -- ** Readers
-  --
-  -- | A reader is used by the 'option' and 'argument' builders to parse
-  -- the data passed by the user on the command line into a data type.
-  --
-  -- The most common are 'str' which is used for 'String' like types,
-  -- including 'ByteString' and 'Text'; and 'auto', which uses the 'Read'
-  -- typeclass, and is good for simple types like 'Int' or 'Double'.
-  --
-  -- More complex types can use the 'eitherReader' or 'maybeReader'
-  -- functions to pattern match or use a more expressive parser like a
-  -- member of the 'Parsec' family.
-  ReadM,
-
-  auto,
-  str,
-  maybeReader,
-  eitherReader,
-  disabled,
-  readerAbort,
-  readerError,
-
-  -- * Program descriptions
-  --
-  -- ** 'ParserInfo'
-  --
-  -- | A 'ParserInfo' describes a command line program, used to generate a help
-  -- screen. Two help modes are supported: brief and full. In brief mode, only
-  -- an option and argument summary is displayed, while in full mode each
-  -- available option and command, including hidden ones, is described.
-  --
-  -- A 'ParserInfo' should be created with the 'info' function and a set of
-  -- 'InfoMod' modifiers.
-  --
-  info,
-
-  ParserInfo(..),
-
-  InfoMod,
-  fullDesc,
-  briefDesc,
-  header,
-  headerDoc,
-  footer,
-  footerDoc,
-  progDesc,
-  progDescDoc,
-  failureCode,
-  noIntersperse,
-  forwardOptions,
-
-  -- * Running parsers
-  --
-  -- | The execParser family of functions are used to run parsers
-  execParser,
-  customExecParser,
-  execParserPure,
-
-  -- ** Handling parser results manually
-  getParseResult,
-  handleParseResult,
-  parserFailure,
-  renderFailure,
-  overFailure,
-
-  -- ** 'ParserPrefs'
-  --
-  -- | A 'ParserPrefs' contains general preferences for all command-line
-  -- options, and should be built with the 'prefs' function.
-  prefs,
-
-  ParserPrefs(..),
-
-  PrefsMod,
-  multiSuffix,
-  disambiguate,
-  showHelpOnError,
-  showHelpOnEmpty,
-  noBacktrack,
-  columns,
-  defaultPrefs,
-
-  -- * Completions
-  --
-  -- | optparse-applicative supplies a rich completion system for bash,
-  -- zsh, and fish shells.
-  --
-  -- 'Completer' functions are used for option and argument to complete
-  -- their values.
-  --
-  -- Use the 'completer' builder to use these.
-  -- The 'action' and 'completeWith' builders are also provided for
-  -- convenience, to use 'bashCompleter' and 'listCompleter' as a 'Mod'.
-  Completer,
-  mkCompleter,
-  listIOCompleter,
-
-  listCompleter,
-  bashCompleter,
-
-  -- * Types
-  ParseError(..),
-  ParserHelp(..),
-  ParserFailure(..),
-  ParserResult(..),
-  CompletionResult(..)
-
-  ) where
-
--- reexport Applicative here for convenience
-import Control.Applicative
-
-import Options.Applicative.Common
-import Options.Applicative.Builder
-import Options.Applicative.Builder.Completer
-import Options.Applicative.Extra
-import Options.Applicative.Types
-
-{-# ANN module "HLint: ignore Use import/export shortcut" #-}
diff --git a/Options/Applicative/Arrows.hs b/Options/Applicative/Arrows.hs
deleted file mode 100644
--- a/Options/Applicative/Arrows.hs
+++ /dev/null
@@ -1,75 +0,0 @@
--- | This module contains an arrow interface for option parsers, which allows
--- to define and combine parsers using the arrow notation and arrow
--- combinators.
---
--- The arrow syntax is particularly useful to create parsers of nested
--- structures, or records where the order of fields is different from the order
--- in which the parsers should be applied.
---
--- For example, an 'Options.Applicative.Builder.arguments` parser often needs
--- to be applied last, and that makes it inconvenient to use it for a field
--- which is not the last one in a record.
---
--- Using the arrow syntax and the functions in this module, one can write, e.g.:
---
--- > data Options = Options
--- >   { optArgs :: [String]
--- >   , optVerbose :: Bool }
--- >
--- > opts :: Parser Options
--- > opts = runA $ proc () -> do
--- >   verbose <- asA (switch (short 'v')) -< ()
--- >   args <- asA (arguments str idm) -< ()
--- >   returnA -< Options args verbose
---
--- Parser arrows, created out of regular 'Parser' values using the 'asA'
--- function, are arrows taking @()@ as argument and returning the parsed value.
-module Options.Applicative.Arrows (
-  module Control.Arrow,
-  A(..),
-  asA,
-  runA,
-  ParserA,
-  ) where
-
-import Control.Arrow
-import Control.Category (Category(..))
-
-import Options.Applicative
-
-import Prelude hiding ((.), id)
-
--- | For any 'Applicative' functor @f@, @A f@ is the 'Arrow' instance
--- associated to @f@.
---
--- The 'A' constructor can be used to convert a value of type @f (a -> b)@ into
--- an arrow.
-newtype A f a b = A
-  { unA :: f (a -> b) }
-
--- | Convert a value of type @f a@ into an arrow taking @()@ as argument.
---
--- Applied to a value of type 'Parser', it turns it into an arrow that can be
--- used inside an arrow command, or passed to arrow combinators.
-asA :: Applicative f => f a -> A f () a
-asA x = A $ const <$> x
-
--- | Convert an arrow back to an applicative value.
---
--- This function can be used to return a result of type 'Parser' from an arrow
--- command.
-runA :: Applicative f => A f () a -> f a
-runA a = unA a <*> pure ()
-
-instance Applicative f => Category (A f) where
-  id = A $ pure id
-  -- use reverse composition, because we want effects to run from
-  -- top to bottom in the arrow syntax
-  (A f) . (A g) = A $ flip (.) <$> g <*> f
-
-instance Applicative f => Arrow (A f) where
-  arr = A . pure
-  first (A f) = A $ first <$> f
-
--- | The type of arrows associated to the applicative 'Parser' functor.
-type ParserA = A Parser
diff --git a/Options/Applicative/BashCompletion.hs b/Options/Applicative/BashCompletion.hs
deleted file mode 100644
--- a/Options/Applicative/BashCompletion.hs
+++ /dev/null
@@ -1,254 +0,0 @@
--- | You don't need to import this module to enable bash completion.
---
--- See
--- <http://github.com/pcapriotti/optparse-applicative/wiki/Bash-Completion the wiki>
--- for more information on bash completion.
-module Options.Applicative.BashCompletion
-  ( bashCompletionParser
-  ) where
-
-import Control.Applicative
-import Prelude
-import Data.Foldable ( asum )
-import Data.List ( isPrefixOf )
-import Data.Maybe ( fromMaybe, listToMaybe )
-
-import Options.Applicative.Builder
-import Options.Applicative.Common
-import Options.Applicative.Internal
-import Options.Applicative.Types
-import Options.Applicative.Help.Pretty
-import Options.Applicative.Help.Chunk
-
--- | Provide basic or rich command completions
-data Richness
-  = Standard
-  -- ^ Add no help descriptions to the completions
-  | Enriched Int Int
-  -- ^ Include tab separated description for options
-  --   and commands when available.
-  --   Takes option description length and command
-  --   description length.
-  deriving (Eq, Ord, Show)
-
-bashCompletionParser :: ParserInfo a -> ParserPrefs -> Parser CompletionResult
-bashCompletionParser pinfo pprefs = complParser
-  where
-    failure opts = CompletionResult
-      { execCompletion = \progn -> unlines <$> opts progn }
-
-    complParser = asum
-      [ failure <$>
-        (  bashCompletionQuery pinfo pprefs
-        -- To get rich completions, one just needs the first
-        -- command. To customise the lengths, use either of
-        -- the `desc-length` options.
-        -- zsh commands can go on a single line, so they might
-        -- want to be longer.
-        <$> ( flag' Enriched (long "bash-completion-enriched" `mappend` internal)
-                <*> option auto (long "bash-completion-option-desc-length" `mappend` internal `mappend` value 40)
-                <*> option auto (long "bash-completion-command-desc-length" `mappend` internal `mappend` value 40)
-          <|> pure Standard
-          )
-        <*> (many . strOption) (long "bash-completion-word"
-                                  `mappend` internal)
-        <*> option auto (long "bash-completion-index" `mappend` internal) )
-      , failure <$>
-          (bashCompletionScript <$>
-            strOption (long "bash-completion-script" `mappend` internal))
-      , failure <$>
-          (fishCompletionScript <$>
-            strOption (long "fish-completion-script" `mappend` internal))
-      , failure <$>
-          (zshCompletionScript <$>
-            strOption (long "zsh-completion-script" `mappend` internal))
-      ]
-
-bashCompletionQuery :: ParserInfo a -> ParserPrefs -> Richness -> [String] -> Int -> String -> IO [String]
-bashCompletionQuery pinfo pprefs richness ws i _ = case runCompletion compl pprefs of
-  Just (Left (SomeParser p, a))
-    -> list_options a p
-  Just (Right c)
-    -> run_completer c
-  Nothing
-    -> return []
-  where
-    compl = runParserInfo pinfo (drop 1 ws')
-
-    list_options a
-      = fmap concat
-      . sequence
-      . mapParser (opt_completions a)
-
-    --
-    -- Prior to 0.14 there was a subtle bug which would
-    -- mean that completions from positional arguments
-    -- further into the parse would be shown.
-    --
-    -- We therefore now check to see that
-    -- hinfoUnreachableArgs is off before running the
-    -- completion for position arguments.
-    --
-    -- For options and flags, ensure that the user
-    -- hasn't disabled them with `--`.
-    opt_completions argPolicy hinfo opt = case optMain opt of
-      OptReader ns _ _
-         | argPolicy /= AllPositionals
-        -> return . add_opt_help opt $ show_names ns
-         | otherwise
-        -> return []
-      FlagReader ns _
-         | argPolicy /= AllPositionals
-        -> return . add_opt_help opt $ show_names ns
-         | otherwise
-        -> return []
-      ArgReader rdr
-         | hinfoUnreachableArgs hinfo
-        -> return []
-         | otherwise
-        -> run_completer (crCompleter rdr)
-      CmdReader _ ns p
-         | hinfoUnreachableArgs hinfo
-        -> return []
-         | otherwise
-        -> return . add_cmd_help p $ filter_names ns
-
-    -- When doing enriched completions, add any help specified
-    -- to the completion variables (tab separated).
-    add_opt_help :: Functor f => Option a -> f String -> f String
-    add_opt_help opt = case richness of
-      Standard
-        -> id
-      Enriched len _
-        -> fmap (\o -> let h = unChunk $ optHelp opt
-                       in  maybe o (\h' -> o ++ "\t" ++ render_line len h') h)
-
-    -- When doing enriched completions, add the command description
-    -- to the completion variables (tab separated).
-    add_cmd_help :: Functor f => (String -> Maybe (ParserInfo a)) -> f String -> f String
-    add_cmd_help p = case richness of
-      Standard
-        -> id
-      Enriched _ len
-        -> fmap (\cmd -> let h = p cmd >>= unChunk . infoProgDesc
-                         in  maybe cmd (\h' -> cmd ++ "\t" ++ render_line len h') h)
-
-    show_names :: [OptName] -> [String]
-    show_names = filter_names . map showOption
-
-    -- We only want to show a single line in the completion results description.
-    -- If there was a line break, it would come across as a different completion
-    -- possibility.
-    render_line :: Int -> Doc -> String
-    render_line len doc = case lines (displayS (renderPretty 1 len doc) "") of
-      [] -> ""
-      [x] -> x
-      x : _ -> x ++ "..."
-
-    filter_names :: [String] -> [String]
-    filter_names = filter is_completion
-
-    run_completer :: Completer -> IO [String]
-    run_completer c = runCompleter c (fromMaybe "" (listToMaybe ws''))
-
-    (ws', ws'') = splitAt i ws
-
-    is_completion :: String -> Bool
-    is_completion =
-      case ws'' of
-        w:_ -> isPrefixOf w
-        _ -> const True
-
-bashCompletionScript :: String -> String -> IO [String]
-bashCompletionScript prog progn = return
-  [ "_" ++ progn ++ "()"
-  , "{"
-  , "    local CMDLINE"
-  , "    local IFS=$'\\n'"
-  , "    CMDLINE=(--bash-completion-index $COMP_CWORD)"
-  , ""
-  , "    for arg in ${COMP_WORDS[@]}; do"
-  , "        CMDLINE=(${CMDLINE[@]} --bash-completion-word $arg)"
-  , "    done"
-  , ""
-  , "    COMPREPLY=( $(" ++ prog ++ " \"${CMDLINE[@]}\") )"
-  , "}"
-  , ""
-  , "complete -o filenames -F _" ++ progn ++ " " ++ progn ]
-
-{-
-/Note/: Fish Shell
-
-Derived from Drezil's post in #169.
-
-@
-commandline
--c or --cut-at-cursor only print selection up until the current cursor position
--o or --tokenize tokenize the selection and print one string-type token per line
-@
-
-We tokenize so that the call to count (and hence --bash-completion-index)
-gets the right number use cut-at-curstor to not bother sending anything
-after the cursor position, which allows for completion of the middle of
-words.
-
-Tab characters separate items from descriptions.
--}
-fishCompletionScript :: String -> String -> IO [String]
-fishCompletionScript prog progn = return
-  [ " function _" ++ progn
-  , "    set -l cl (commandline --tokenize --current-process)"
-  , "    # Hack around fish issue #3934"
-  , "    set -l cn (commandline --tokenize --cut-at-cursor --current-process)"
-  , "    set -l cn (count $cn)"
-  , "    set -l tmpline --bash-completion-enriched --bash-completion-index $cn"
-  , "    for arg in $cl"
-  , "      set tmpline $tmpline --bash-completion-word $arg"
-  , "    end"
-  , "    for opt in (" ++ prog ++ " $tmpline)"
-  , "      if test -d $opt"
-  , "        echo -E \"$opt/\""
-  , "      else"
-  , "        echo -E \"$opt\""
-  , "      end"
-  , "    end"
-  , "end"
-  , ""
-  , "complete --no-files --command " ++ progn ++ " --arguments '(_"  ++ progn ++  ")'"
-  ]
-
-zshCompletionScript :: String -> String -> IO [String]
-zshCompletionScript prog progn = return
-  [ "#compdef " ++ progn
-  , ""
-  , "local request"
-  , "local completions"
-  , "local word"
-  , "local index=$((CURRENT - 1))"
-  , ""
-  , "request=(--bash-completion-enriched --bash-completion-index $index)"
-  , "for arg in ${words[@]}; do"
-  , "  request=(${request[@]} --bash-completion-word $arg)"
-  , "done"
-  , ""
-  , "IFS=$'\\n' completions=($( " ++ prog ++ " \"${request[@]}\" ))"
-  , ""
-  , "for word in $completions; do"
-  , "  local -a parts"
-  , ""
-  , "  # Split the line at a tab if there is one."
-  , "  IFS=$'\\t' parts=($( echo $word ))"
-  , ""
-  , "  if [[ -n $parts[2] ]]; then"
-  , "     if [[ $word[1] == \"-\" ]]; then"
-  , "       local desc=(\"$parts[1] ($parts[2])\")"
-  , "       compadd -d desc -- $parts[1]"
-  , "     else"
-  , "       local desc=($(print -f  \"%-019s -- %s\" $parts[1] $parts[2]))"
-  , "       compadd -l -d desc -- $parts[1]"
-  , "     fi"
-  , "  else"
-  , "    compadd -f -- $word"
-  , "  fi"
-  , "done"
-  ]
diff --git a/Options/Applicative/Builder.hs b/Options/Applicative/Builder.hs
deleted file mode 100644
--- a/Options/Applicative/Builder.hs
+++ /dev/null
@@ -1,514 +0,0 @@
-module Options.Applicative.Builder (
-  -- * Parser builders
-  --
-  -- | This module contains utility functions and combinators to create parsers
-  -- for individual options.
-  --
-  -- Each parser builder takes an option modifier. A modifier can be created by
-  -- composing the basic modifiers provided by this module using the 'Monoid'
-  -- operations 'mempty' and 'mappend', or their aliases 'idm' and '<>'.
-  --
-  -- For example:
-  --
-  -- > out = strOption
-  -- >     ( long "output"
-  -- >    <> short 'o'
-  -- >    <> metavar "FILENAME" )
-  --
-  -- creates a parser for an option called \"output\".
-  subparser,
-  strArgument,
-  argument,
-  flag,
-  flag',
-  switch,
-  abortOption,
-  infoOption,
-  strOption,
-  option,
-  nullOption,
-
-  -- * Modifiers
-  short,
-  long,
-  help,
-  helpDoc,
-  value,
-  showDefaultWith,
-  showDefault,
-  metavar,
-  noArgError,
-  ParseError(..),
-  hidden,
-  internal,
-  style,
-  command,
-  commandGroup,
-  completeWith,
-  action,
-  completer,
-  idm,
-  mappend,
-
-  -- * Readers
-  --
-  -- | A collection of basic 'Option' readers.
-  auto,
-  str,
-  maybeReader,
-  eitherReader,
-  disabled,
-  readerAbort,
-  readerError,
-
-  -- * Builder for 'ParserInfo'
-  InfoMod,
-  fullDesc,
-  briefDesc,
-  header,
-  headerDoc,
-  footer,
-  footerDoc,
-  progDesc,
-  progDescDoc,
-  failureCode,
-  noIntersperse,
-  forwardOptions,
-  info,
-
-  -- * Builder for 'ParserPrefs'
-  PrefsMod,
-  multiSuffix,
-  disambiguate,
-  showHelpOnError,
-  showHelpOnEmpty,
-  noBacktrack,
-  columns,
-  prefs,
-  defaultPrefs,
-
-  -- * Types
-  Mod,
-  ReadM,
-  OptionFields,
-  FlagFields,
-  ArgumentFields,
-  CommandFields,
-
-  HasName,
-  HasCompleter,
-  HasValue,
-  HasMetavar
-  ) where
-
-import Control.Applicative
-import Data.Semigroup hiding (option)
-import Data.String (fromString, IsString)
-
-import Options.Applicative.Builder.Completer
-import Options.Applicative.Builder.Internal
-import Options.Applicative.Common
-import Options.Applicative.Types
-import Options.Applicative.Help.Pretty
-import Options.Applicative.Help.Chunk
-
--- Readers --
-
--- | 'Option' reader based on the 'Read' type class.
-auto :: Read a => ReadM a
-auto = eitherReader $ \arg -> case reads arg of
-  [(r, "")] -> return r
-  _         -> Left $ "cannot parse value `" ++ arg ++ "'"
-
--- | String 'Option' reader.
---
---   Polymorphic over the `IsString` type class since 0.14.
-str :: IsString s => ReadM s
-str = fromString <$> readerAsk
-
--- | Convert a function producing an 'Either' into a reader.
---
--- As an example, one can create a ReadM from an attoparsec Parser
--- easily with
---
--- > import qualified Data.Attoparsec.Text as A
--- > import qualified Data.Text as T
--- > attoparsecReader :: A.Parser a -> ReadM a
--- > attoparsecReader p = eitherReader (A.parseOnly p . T.pack)
-eitherReader :: (String -> Either String a) -> ReadM a
-eitherReader f = readerAsk >>= either readerError return . f
-
--- | Convert a function producing a 'Maybe' into a reader.
-maybeReader :: (String -> Maybe a) -> ReadM a
-maybeReader f = do
-  arg  <- readerAsk
-  maybe (readerError $ "cannot parse value `" ++ arg ++ "'") return . f $ arg
-
--- | Null 'Option' reader. All arguments will fail validation.
-disabled :: ReadM a
-disabled = readerError "disabled option"
-
--- modifiers --
-
--- | Specify a short name for an option.
-short :: HasName f => Char -> Mod f a
-short = fieldMod . name . OptShort
-
--- | Specify a long name for an option.
-long :: HasName f => String -> Mod f a
-long = fieldMod . name . OptLong
-
--- | Specify a default value for an option.
---
--- /Note/: Because this modifier means the parser will never fail,
--- do not use it with combinators such as 'some' or 'many', as
--- these combinators continue until a failure occurs.
--- Careless use will thus result in a hang.
---
--- To display the default value, combine with showDefault or
--- showDefaultWith.
-value :: HasValue f => a -> Mod f a
-value x = Mod id (DefaultProp (Just x) Nothing) id
-
--- | Specify a function to show the default value for an option.
-showDefaultWith :: (a -> String) -> Mod f a
-showDefaultWith s = Mod id (DefaultProp Nothing (Just s)) id
-
--- | Show the default value for this option using its 'Show' instance.
-showDefault :: Show a => Mod f a
-showDefault = showDefaultWith show
-
--- | Specify the help text for an option.
-help :: String -> Mod f a
-help s = optionMod $ \p -> p { propHelp = paragraph s }
-
--- | Specify the help text for an option as a 'Text.PrettyPrint.ANSI.Leijen.Doc'
--- value.
-helpDoc :: Maybe Doc -> Mod f a
-helpDoc doc = optionMod $ \p -> p { propHelp = Chunk doc }
-
--- | Specify the error to display when no argument is provided to this option.
-noArgError :: ParseError -> Mod OptionFields a
-noArgError e = fieldMod $ \p -> p { optNoArgError = const e }
-
--- | Specify a metavariable for the argument.
---
--- Metavariables have no effect on the actual parser, and only serve to specify
--- the symbolic name for an argument to be displayed in the help text.
-metavar :: HasMetavar f => String -> Mod f a
-metavar var = optionMod $ \p -> p { propMetaVar = var }
-
--- | Hide this option from the brief description.
-hidden :: Mod f a
-hidden = optionMod $ \p ->
-  p { propVisibility = min Hidden (propVisibility p) }
-
--- | Apply a function to the option description in the usage text.
---
--- > import Options.Applicative.Help
--- > flag' () (short 't' <> style bold)
---
--- /NOTE/: This builder is more flexible than its name and example
--- allude. One of the motivating examples for its addition was to
--- used `const` to completely replace the usage text of an option.
-style :: ( Doc -> Doc ) -> Mod f a
-style x = optionMod $ \p ->
-  p { propDescMod = Just x }
-
--- | Add a command to a subparser option.
---
--- Suggested usage for multiple commands is to add them to a single subparser. e.g.
---
--- @
--- sample :: Parser Sample
--- sample = subparser
---        ( command "hello"
---          (info hello (progDesc "Print greeting"))
---       <> command "goodbye"
---          (info goodbye (progDesc "Say goodbye"))
---        )
--- @
-command :: String -> ParserInfo a -> Mod CommandFields a
-command cmd pinfo = fieldMod $ \p ->
-  p { cmdCommands = (cmd, pinfo) : cmdCommands p }
-
--- | Add a description to a group of commands.
---
--- Advanced feature for separating logical groups of commands on the parse line.
---
--- If using the same `metavar` for each group of commands, it may yield a more
--- attractive usage text combined with `hidden` for some groups.
-commandGroup :: String -> Mod CommandFields a
-commandGroup g = fieldMod $ \p ->
-  p { cmdGroup = Just g }
-
--- | Add a list of possible completion values.
-completeWith :: HasCompleter f => [String] -> Mod f a
-completeWith = completer . listCompleter
-
--- | Add a bash completion action. Common actions include @file@ and
--- @directory@. See
--- <http://www.gnu.org/software/bash/manual/html_node/Programmable-Completion-Builtins.html#Programmable-Completion-Builtins>
--- for a complete list.
-action :: HasCompleter f => String -> Mod f a
-action = completer . bashCompleter
-
--- | Add a completer to an argument.
---
--- A completer is a function String -> IO String which, given a partial
--- argument, returns all possible completions for that argument.
-completer :: HasCompleter f => Completer -> Mod f a
-completer f = fieldMod $ modCompleter (`mappend` f)
-
--- parsers --
-
--- | Builder for a command parser. The 'command' modifier can be used to
--- specify individual commands.
-subparser :: Mod CommandFields a -> Parser a
-subparser m = mkParser d g rdr
-  where
-    Mod _ d g = metavar "COMMAND" `mappend` m
-    (groupName, cmds, subs) = mkCommand m
-    rdr = CmdReader groupName cmds subs
-
--- | Builder for an argument parser.
-argument :: ReadM a -> Mod ArgumentFields a -> Parser a
-argument p (Mod f d g) = mkParser d g (ArgReader rdr)
-  where
-    ArgumentFields compl = f (ArgumentFields mempty)
-    rdr = CReader compl p
-
--- | Builder for a 'String' argument.
-strArgument :: IsString s => Mod ArgumentFields s -> Parser s
-strArgument = argument str
-
--- | Builder for a flag parser.
---
--- A flag that switches from a \"default value\" to an \"active value\" when
--- encountered. For a simple boolean value, use `switch` instead.
---
--- /Note/: Because this parser will never fail, it can not be used with
--- combinators such as 'some' or 'many', as these combinators continue until
--- a failure occurs. See @flag'@.
-flag :: a                         -- ^ default value
-     -> a                         -- ^ active value
-     -> Mod FlagFields a          -- ^ option modifier
-     -> Parser a
-flag defv actv m = flag' actv m <|> pure defv
-
--- | Builder for a flag parser without a default value.
---
--- Same as 'flag', but with no default value. In particular, this flag will
--- never parse successfully by itself.
---
--- It still makes sense to use it as part of a composite parser. For example
---
--- > length <$> many (flag' () (short 't'))
---
--- is a parser that counts the number of "-t" arguments on the command line,
--- alternatively
---
--- > flag' True (long "on") <|> flag' False (long "off")
---
--- will require the user to enter '--on' or '--off' on the command line.
-flag' :: a                         -- ^ active value
-      -> Mod FlagFields a          -- ^ option modifier
-      -> Parser a
-flag' actv (Mod f d g) = mkParser d g rdr
-  where
-    rdr = let fields = f (FlagFields [] actv)
-          in FlagReader (flagNames fields)
-                        (flagActive fields)
-
--- | Builder for a boolean flag.
---
--- /Note/: Because this parser will never fail, it can not be used with
--- combinators such as 'some' or 'many', as these combinators continue until
--- a failure occurs. See @flag'@.
---
--- > switch = flag False True
-switch :: Mod FlagFields Bool -> Parser Bool
-switch = flag False True
-
--- | An option that always fails.
---
--- When this option is encountered, the option parser immediately aborts with
--- the given parse error.  If you simply want to output a message, use
--- 'infoOption' instead.
-abortOption :: ParseError -> Mod OptionFields (a -> a) -> Parser (a -> a)
-abortOption err m = option (readerAbort err) . (`mappend` m) $ mconcat
-  [ noArgError err
-  , value id
-  , metavar "" ]
-
--- | An option that always fails and displays a message.
-infoOption :: String -> Mod OptionFields (a -> a) -> Parser (a -> a)
-infoOption = abortOption . InfoMsg
-
--- | Builder for an option taking a 'String' argument.
-strOption :: IsString s => Mod OptionFields s -> Parser s
-strOption = option str
-
--- | Same as 'option'.
-{-# DEPRECATED nullOption "Use 'option' instead" #-}
-nullOption :: ReadM a -> Mod OptionFields a -> Parser a
-nullOption = option
-
--- | Builder for an option using the given reader.
---
--- This is a regular option, and should always have either a @long@ or
--- @short@ name specified in the modifiers (or both).
---
--- > nameParser = option str ( long "name" <> short 'n' )
---
-option :: ReadM a -> Mod OptionFields a -> Parser a
-option r m = mkParser d g rdr
-  where
-    Mod f d g = metavar "ARG" `mappend` m
-    fields = f (OptionFields [] mempty ExpectsArgError)
-    crdr = CReader (optCompleter fields) r
-    rdr = OptReader (optNames fields) crdr (optNoArgError fields)
-
--- | Modifier for 'ParserInfo'.
-newtype InfoMod a = InfoMod
-  { applyInfoMod :: ParserInfo a -> ParserInfo a }
-
-instance Monoid (InfoMod a) where
-  mempty = InfoMod id
-  mappend = (<>)
-
-instance Semigroup (InfoMod a) where
-  m1 <> m2 = InfoMod $ applyInfoMod m2 . applyInfoMod m1
-
--- | Show a full description in the help text of this parser.
-fullDesc :: InfoMod a
-fullDesc = InfoMod $ \i -> i { infoFullDesc = True }
-
--- | Only show a brief description in the help text of this parser.
-briefDesc :: InfoMod a
-briefDesc = InfoMod $ \i -> i { infoFullDesc = False }
-
--- | Specify a header for this parser.
-header :: String -> InfoMod a
-header s = InfoMod $ \i -> i { infoHeader = paragraph s }
-
--- | Specify a header for this parser as a 'Text.PrettyPrint.ANSI.Leijen.Doc'
--- value.
-headerDoc :: Maybe Doc -> InfoMod a
-headerDoc doc = InfoMod $ \i -> i { infoHeader = Chunk doc }
-
--- | Specify a footer for this parser.
-footer :: String -> InfoMod a
-footer s = InfoMod $ \i -> i { infoFooter = paragraph s }
-
--- | Specify a footer for this parser as a 'Text.PrettyPrint.ANSI.Leijen.Doc'
--- value.
-footerDoc :: Maybe Doc -> InfoMod a
-footerDoc doc = InfoMod $ \i -> i { infoFooter = Chunk doc }
-
--- | Specify a short program description.
-progDesc :: String -> InfoMod a
-progDesc s = InfoMod $ \i -> i { infoProgDesc = paragraph s }
-
--- | Specify a short program description as a 'Text.PrettyPrint.ANSI.Leijen.Doc'
--- value.
-progDescDoc :: Maybe Doc -> InfoMod a
-progDescDoc doc = InfoMod $ \i -> i { infoProgDesc = Chunk doc }
-
--- | Specify an exit code if a parse error occurs.
-failureCode :: Int -> InfoMod a
-failureCode n = InfoMod $ \i -> i { infoFailureCode = n }
-
--- | Disable parsing of regular options after arguments. After a positional
---   argument is parsed, all remaining options and arguments will be treated
---   as a positional arguments. Not recommended in general as users often
---   expect to be able to freely intersperse regular options and flags within
---   command line options.
-noIntersperse :: InfoMod a
-noIntersperse = InfoMod $ \p -> p { infoPolicy = NoIntersperse }
-
--- | Intersperse matched options and arguments normally, but allow unmatched
---   options to be treated as positional arguments.
---   This is sometimes useful if one is wrapping a third party cli tool and
---   needs to pass options through, while also providing a handful of their
---   own options. Not recommended in general as typos by the user may not
---   yield a parse error and cause confusion.
-forwardOptions :: InfoMod a
-forwardOptions = InfoMod $ \p -> p { infoPolicy = ForwardOptions }
-
--- | Create a 'ParserInfo' given a 'Parser' and a modifier.
-info :: Parser a -> InfoMod a -> ParserInfo a
-info parser m = applyInfoMod m base
-  where
-    base = ParserInfo
-      { infoParser = parser
-      , infoFullDesc = True
-      , infoProgDesc = mempty
-      , infoHeader = mempty
-      , infoFooter = mempty
-      , infoFailureCode = 1
-      , infoPolicy = Intersperse }
-
-newtype PrefsMod = PrefsMod
-  { applyPrefsMod :: ParserPrefs -> ParserPrefs }
-
-instance Monoid PrefsMod where
-  mempty = PrefsMod id
-  mappend = (<>)
-
-instance Semigroup PrefsMod where
-  m1 <> m2 = PrefsMod $ applyPrefsMod m2 . applyPrefsMod m1
-
--- | Include a suffix to attach to the metavar when multiple values
---   can be entered.
-multiSuffix :: String -> PrefsMod
-multiSuffix s = PrefsMod $ \p -> p { prefMultiSuffix = s }
-
--- | Turn on disambiguation.
---
---   See
---   https://github.com/pcapriotti/optparse-applicative#disambiguation
-disambiguate :: PrefsMod
-disambiguate = PrefsMod $ \p -> p { prefDisambiguate = True }
-
--- | Show full help text on any error.
-showHelpOnError :: PrefsMod
-showHelpOnError = PrefsMod $ \p -> p { prefShowHelpOnError = True }
-
--- | Show the help text if the user enters only the program name or
---   subcommand.
---
---   This will suppress a "Missing:" error and show the full usage
---   instead if a user just types the name of the program.
-showHelpOnEmpty :: PrefsMod
-showHelpOnEmpty = PrefsMod $ \p -> p { prefShowHelpOnEmpty = True }
-
--- | Turn off backtracking after subcommand is parsed.
-noBacktrack :: PrefsMod
-noBacktrack = PrefsMod $ \p -> p { prefBacktrack = False }
-
--- | Set the maximum width of the generated help text.
-columns :: Int -> PrefsMod
-columns cols = PrefsMod $ \p -> p { prefColumns = cols }
-
--- | Create a `ParserPrefs` given a modifier
-prefs :: PrefsMod -> ParserPrefs
-prefs m = applyPrefsMod m base
-  where
-    base = ParserPrefs
-      { prefMultiSuffix = ""
-      , prefDisambiguate = False
-      , prefShowHelpOnError = False
-      , prefShowHelpOnEmpty = False
-      , prefBacktrack = True
-      , prefColumns = 80 }
-
--- Convenience shortcuts
-
--- | Trivial option modifier.
-idm :: Monoid m => m
-idm = mempty
-
--- | Default preferences.
-defaultPrefs :: ParserPrefs
-defaultPrefs = prefs idm
diff --git a/Options/Applicative/Builder/Completer.hs b/Options/Applicative/Builder/Completer.hs
deleted file mode 100644
--- a/Options/Applicative/Builder/Completer.hs
+++ /dev/null
@@ -1,122 +0,0 @@
-module Options.Applicative.Builder.Completer
-  ( Completer
-  , mkCompleter
-  , listIOCompleter
-  , listCompleter
-  , bashCompleter
-  ) where
-
-import Control.Applicative
-import Prelude
-import Control.Exception (IOException, try)
-import Data.List (isPrefixOf)
-import System.Process (readProcess)
-
-import Options.Applicative.Types
-
--- | Create a 'Completer' from an IO action
-listIOCompleter :: IO [String] -> Completer
-listIOCompleter ss = Completer $ \s ->
-  filter (isPrefixOf s) <$> ss
-
--- | Create a 'Completer' from a constant
--- list of strings.
-listCompleter :: [String] -> Completer
-listCompleter = listIOCompleter . pure
-
--- | Run a compgen completion action.
---
--- Common actions include @file@ and
--- @directory@. See
--- <http://www.gnu.org/software/bash/manual/html_node/Programmable-Completion-Builtins.html#Programmable-Completion-Builtins>
--- for a complete list.
-bashCompleter :: String -> Completer
-bashCompleter action = Completer $ \word -> do
-  let cmd = unwords ["compgen", "-A", action, "--", requote word]
-  result <- tryIO $ readProcess "bash" ["-c", cmd] ""
-  return . lines . either (const []) id $ result
-
-tryIO :: IO a -> IO (Either IOException a)
-tryIO = try
-
--- | Strongly quote the string we pass to compgen.
---
--- We need to do this so bash doesn't expand out any ~ or other
--- chars we want to complete on, or emit an end of line error
--- when seeking the close to the quote.
-requote :: String -> String
-requote s =
-  let
-    -- Bash doesn't appear to allow "mixed" escaping
-    -- in bash completions. So we don't have to really
-    -- worry about people swapping between strong and
-    -- weak quotes.
-    unescaped =
-      case s of
-        -- It's already strongly quoted, so we
-        -- can use it mostly as is, but we must
-        -- ensure it's closed off at the end and
-        -- there's no single quotes in the
-        -- middle which might confuse bash.
-        ('\'': rs) -> unescapeN rs
-
-        -- We're weakly quoted.
-        ('"': rs)  -> unescapeD rs
-
-        -- We're not quoted at all.
-        -- We need to unescape some characters like
-        -- spaces and quotation marks.
-        elsewise   -> unescapeU elsewise
-  in
-    strong unescaped
-
-  where
-    strong ss = '\'' : foldr go "'" ss
-      where
-        -- If there's a single quote inside the
-        -- command: exit from the strong quote and
-        -- emit it the quote escaped, then resume.
-        go '\'' t = "'\\''" ++ t
-        go h t    = h : t
-
-    -- Unescape a strongly quoted string
-    -- We have two recursive functions, as we
-    -- can enter and exit the strong escaping.
-    unescapeN = goX
-      where
-        goX ('\'' : xs) = goN xs
-        goX (x : xs) = x : goX xs
-        goX [] = []
-
-        goN ('\\' : '\'' : xs) = '\'' : goN xs
-        goN ('\'' : xs) = goX xs
-        goN (x : xs) = x : goN xs
-        goN [] = []
-
-    -- Unescape an unquoted string
-    unescapeU = goX
-      where
-        goX [] = []
-        goX ('\\' : x : xs) = x : goX xs
-        goX (x : xs) = x : goX xs
-
-    -- Unescape a weakly quoted string
-    unescapeD = goX
-      where
-        -- Reached an escape character
-        goX ('\\' : x : xs)
-          -- If it's true escapable, strip the
-          -- slashes, as we're going to strong
-          -- escape instead.
-          | x `elem` "$`\"\\\n" = x : goX xs
-          | otherwise = '\\' : x : goX xs
-        -- We've ended quoted section, so we
-        -- don't recurse on goX, it's done.
-        goX ('"' : xs)
-          = xs
-        -- Not done, but not a special character
-        -- just continue the fold.
-        goX (x : xs)
-          = x : goX xs
-        goX []
-          = []
diff --git a/Options/Applicative/Builder/Internal.hs b/Options/Applicative/Builder/Internal.hs
deleted file mode 100644
--- a/Options/Applicative/Builder/Internal.hs
+++ /dev/null
@@ -1,183 +0,0 @@
-module Options.Applicative.Builder.Internal (
-  -- * Internals
-  Mod(..),
-  HasName(..),
-  HasCompleter(..),
-  HasValue(..),
-  HasMetavar(..),
-  OptionFields(..),
-  FlagFields(..),
-  CommandFields(..),
-  ArgumentFields(..),
-  DefaultProp(..),
-
-  optionMod,
-  fieldMod,
-
-  baseProps,
-  mkCommand,
-  mkParser,
-  mkOption,
-  mkProps,
-
-  internal
-  ) where
-
-import Control.Applicative
-import Control.Monad (mplus)
-import Data.Semigroup hiding (Option)
-import Prelude
-
-import Options.Applicative.Common
-import Options.Applicative.Types
-
-data OptionFields a = OptionFields
-  { optNames :: [OptName]
-  , optCompleter :: Completer
-  , optNoArgError :: String -> ParseError }
-
-data FlagFields a = FlagFields
-  { flagNames :: [OptName]
-  , flagActive :: a }
-
-data CommandFields a = CommandFields
-  { cmdCommands :: [(String, ParserInfo a)]
-  , cmdGroup :: Maybe String }
-
-data ArgumentFields a = ArgumentFields
-  { argCompleter :: Completer }
-
-class HasName f where
-  name :: OptName -> f a -> f a
-
-instance HasName OptionFields where
-  name n fields = fields { optNames = n : optNames fields }
-
-instance HasName FlagFields where
-  name n fields = fields { flagNames = n : flagNames fields }
-
-class HasCompleter f where
-  modCompleter :: (Completer -> Completer) -> f a -> f a
-
-instance HasCompleter OptionFields where
-  modCompleter f p = p { optCompleter = f (optCompleter p) }
-
-instance HasCompleter ArgumentFields where
-  modCompleter f p = p { argCompleter = f (argCompleter p) }
-
-class HasValue f where
-  -- this is just so that it is not necessary to specify the kind of f
-  hasValueDummy :: f a -> ()
-instance HasValue OptionFields where
-  hasValueDummy _ = ()
-instance HasValue ArgumentFields where
-  hasValueDummy _ = ()
-
-class HasMetavar f where
-  hasMetavarDummy :: f a -> ()
-instance HasMetavar OptionFields where
-  hasMetavarDummy _ = ()
-instance HasMetavar ArgumentFields where
-  hasMetavarDummy _ = ()
-instance HasMetavar CommandFields where
-  hasMetavarDummy _ = ()
-
--- mod --
-
-data DefaultProp a = DefaultProp
-  (Maybe a)
-  (Maybe (a -> String))
-
-instance Monoid (DefaultProp a) where
-  mempty = DefaultProp Nothing Nothing
-  mappend = (<>)
-
-instance Semigroup (DefaultProp a) where
-  (DefaultProp d1 s1) <> (DefaultProp d2 s2) =
-    DefaultProp (d1 `mplus` d2) (s1 `mplus` s2)
-
--- | An option modifier.
---
--- Option modifiers are values that represent a modification of the properties
--- of an option.
---
--- The type parameter @a@ is the return type of the option, while @f@ is a
--- record containing its properties (e.g. 'OptionFields' for regular options,
--- 'FlagFields' for flags, etc...).
---
--- An option modifier consists of 3 elements:
---
---  - A field modifier, of the form @f a -> f a@. These are essentially
---  (compositions of) setters for some of the properties supported by @f@.
---
---  - An optional default value and function to display it.
---
---  - A property modifier, of the form @OptProperties -> OptProperties@. This
---  is just like the field modifier, but for properties applicable to any
---  option.
---
--- Modifiers are instances of 'Monoid', and can be composed as such.
---
--- One rarely needs to deal with modifiers directly, as most of the times it is
--- sufficient to pass them to builders (such as 'strOption' or 'flag') to
--- create options (see 'Options.Applicative.Builder').
-data Mod f a = Mod (f a -> f a)
-                   (DefaultProp a)
-                   (OptProperties -> OptProperties)
-
-optionMod :: (OptProperties -> OptProperties) -> Mod f a
-optionMod = Mod id mempty
-
-fieldMod :: (f a -> f a) -> Mod f a
-fieldMod f = Mod f mempty id
-
-instance Monoid (Mod f a) where
-  mempty = Mod id mempty id
-  mappend = (<>)
-
--- | @since 0.13.0.0
-instance Semigroup (Mod f a) where
-  Mod f1 d1 g1 <> Mod f2 d2 g2
-    = Mod (f2 . f1) (d2 <> d1) (g2 . g1)
-
--- | Base default properties.
-baseProps :: OptProperties
-baseProps = OptProperties
-  { propMetaVar = ""
-  , propVisibility = Visible
-  , propHelp = mempty
-  , propShowDefault = Nothing
-  , propDescMod = Nothing
-  }
-
-mkCommand :: Mod CommandFields a -> (Maybe String, [String], String -> Maybe (ParserInfo a))
-mkCommand m = (group, map fst cmds, (`lookup` cmds))
-  where
-    Mod f _ _ = m
-    CommandFields cmds group = f (CommandFields [] Nothing)
-
-mkParser :: DefaultProp a
-         -> (OptProperties -> OptProperties)
-         -> OptReader a
-         -> Parser a
-mkParser d@(DefaultProp def _) g rdr = liftOpt opt <|> maybe empty pure def
-  where
-    opt = mkOption d g rdr
-
-mkOption :: DefaultProp a
-         -> (OptProperties -> OptProperties)
-         -> OptReader a
-         -> Option a
-mkOption d g rdr = Option rdr (mkProps d g)
-
-mkProps :: DefaultProp a
-        -> (OptProperties -> OptProperties)
-        -> OptProperties
-mkProps (DefaultProp def sdef) g = props
-  where
-    props = (g baseProps)
-      { propShowDefault = sdef <*> def }
-
--- | Hide this option from the help text
-internal :: Mod f a
-internal = optionMod $ \p -> p { propVisibility = Internal }
diff --git a/Options/Applicative/Common.hs b/Options/Applicative/Common.hs
deleted file mode 100644
--- a/Options/Applicative/Common.hs
+++ /dev/null
@@ -1,311 +0,0 @@
-{-# LANGUAGE Rank2Types #-}
-module Options.Applicative.Common (
-  -- * Option parsers
-  --
-  -- | A 'Parser' is composed of a list of options. Several kinds of options
-  -- are supported:
-  --
-  --  * Flags: simple no-argument options. When a flag is encountered on the
-  --  command line, its value is returned.
-  --
-  --  * Options: options with an argument. An option can define a /reader/,
-  --  which converts its argument from String to the desired value, or throws a
-  --  parse error if the argument does not validate correctly.
-  --
-  --  * Arguments: positional arguments, validated in the same way as option
-  --  arguments.
-  --
-  --  * Commands. A command defines a completely independent sub-parser. When a
-  --  command is encountered, the whole command line is passed to the
-  --  corresponding parser.
-  --
-  Parser,
-  liftOpt,
-  showOption,
-
-  -- * Program descriptions
-  --
-  -- A 'ParserInfo' describes a command line program, used to generate a help
-  -- screen. Two help modes are supported: brief and full. In brief mode, only
-  -- an option and argument summary is displayed, while in full mode each
-  -- available option and command, including hidden ones, is described.
-  --
-  -- A basic 'ParserInfo' with default values for fields can be created using
-  -- the 'info' function.
-  --
-  -- A 'ParserPrefs' contains general preferences for all command-line
-  -- options, and can be built with the 'prefs' function.
-  ParserInfo(..),
-  ParserPrefs(..),
-
-  -- * Running parsers
-  runParserInfo,
-  runParserFully,
-  runParser,
-  evalParser,
-
-  -- * Low-level utilities
-  mapParser,
-  treeMapParser,
-  optionNames
-  ) where
-
-import Control.Applicative
-import Control.Monad (guard, mzero, msum, when, liftM)
-import Control.Monad.Trans.Class (lift)
-import Control.Monad.Trans.State (StateT(..), get, put, runStateT)
-import Data.List (isPrefixOf)
-import Data.Maybe (maybeToList, isJust, isNothing)
-import Prelude
-
-import Options.Applicative.Internal
-import Options.Applicative.Types
-
-showOption :: OptName -> String
-showOption (OptLong n) = "--" ++ n
-showOption (OptShort n) = '-' : [n]
-
-optionNames :: OptReader a -> [OptName]
-optionNames (OptReader names _ _) = names
-optionNames (FlagReader names _) = names
-optionNames _ = []
-
-isOptionPrefix :: OptName -> OptName -> Bool
-isOptionPrefix (OptShort x) (OptShort y) = x == y
-isOptionPrefix (OptLong x) (OptLong y) = x `isPrefixOf` y
-isOptionPrefix _ _ = False
-
--- | Create a parser composed of a single option.
-liftOpt :: Option a -> Parser a
-liftOpt = OptP
-
-argMatches :: MonadP m => OptReader a -> String
-           -> Maybe (StateT Args m a)
-argMatches opt arg = case opt of
-  ArgReader rdr -> Just . lift $
-    runReadM (crReader rdr) arg
-  CmdReader _ _ f ->
-    flip fmap (f arg) $ \subp -> StateT $ \args -> do
-      prefs <- getPrefs
-      let runSubparser
-            | prefBacktrack prefs = \i a ->
-                runParser (infoPolicy i) CmdStart (infoParser i) a
-            | otherwise = \i a
-            -> (,) <$> runParserInfo i a <*> pure []
-      enterContext arg subp *> runSubparser subp args <* exitContext
-  _ -> Nothing
-
-optMatches :: MonadP m => Bool -> OptReader a -> OptWord -> Maybe (StateT Args m a)
-optMatches disambiguate opt (OptWord arg1 val) = case opt of
-  OptReader names rdr no_arg_err -> do
-    guard $ has_name arg1 names
-    Just $ do
-      args <- get
-      let mb_args = uncons $ maybeToList val ++ args
-      let missing_arg = missingArgP (no_arg_err $ showOption arg1) (crCompleter rdr)
-      (arg', args') <- maybe (lift missing_arg) return mb_args
-      put args'
-      lift $ runReadM (withReadM (errorFor arg1) (crReader rdr)) arg'
-
-  FlagReader names x -> do
-    guard $ has_name arg1 names
-    -- #242 Flags/switches succeed incorrectly when given an argument.
-    -- We'll not match a long option for a flag if there's a word attached.
-    -- This was revealing an implementation detail as
-    -- `--foo=val` was being parsed as `--foo -val`, which is gibberish.
-    guard $ is_short arg1 || isNothing val
-    Just $ do
-      args <- get
-      let val' = (\s -> '-' : s) <$> val
-      put $ maybeToList val' ++ args
-      return x
-  _ -> Nothing
-  where
-    errorFor name msg = "option " ++ showOption name ++ ": " ++ msg
-
-    is_short (OptShort _) = True
-    is_short (OptLong _)  = False
-
-    has_name a
-      | disambiguate = any (isOptionPrefix a)
-      | otherwise = elem a
-
-isArg :: OptReader a -> Bool
-isArg (ArgReader _) = True
-isArg _ = False
-
-data OptWord = OptWord OptName (Maybe String)
-
-parseWord :: String -> Maybe OptWord
-parseWord ('-' : '-' : w) = Just $ let
-  (opt, arg) = case span (/= '=') w of
-    (_, "") -> (w, Nothing)
-    (w', _ : rest) -> (w', Just rest)
-  in OptWord (OptLong opt) arg
-parseWord ('-' : w) = case w of
-  [] -> Nothing
-  (a : rest) -> Just $ let
-    arg = rest <$ guard (not (null rest))
-    in OptWord (OptShort a) arg
-parseWord _ = Nothing
-
-searchParser :: Monad m
-             => (forall r . Option r -> NondetT m r)
-             -> Parser a -> NondetT m (Parser a)
-searchParser _ (NilP _) = mzero
-searchParser f (OptP opt) = liftM pure (f opt)
-searchParser f (MultP p1 p2) = foldr1 (<!>)
-  [ do p1' <- searchParser f p1
-       return (p1' <*> p2)
-  , do p2' <- searchParser f p2
-       return (p1 <*> p2') ]
-searchParser f (AltP p1 p2) = msum
-  [ searchParser f p1
-  , searchParser f p2 ]
-searchParser f (BindP p k) = msum
-  [ do p' <- searchParser f p
-       return $ BindP p' k
-  , case evalParser p of
-      Nothing -> mzero
-      Just aa -> searchParser f (k aa) ]
-
-searchOpt :: MonadP m => ParserPrefs -> OptWord -> Parser a
-          -> NondetT (StateT Args m) (Parser a)
-searchOpt pprefs w = searchParser $ \opt -> do
-  let disambiguate = prefDisambiguate pprefs
-                  && optVisibility opt > Internal
-  case optMatches disambiguate (optMain opt) w of
-    Just matcher -> lift matcher
-    Nothing -> mzero
-
-searchArg :: MonadP m => String -> Parser a
-          -> NondetT (StateT Args m) (Parser a)
-searchArg arg = searchParser $ \opt -> do
-  when (isArg (optMain opt)) cut
-  case argMatches (optMain opt) arg of
-    Just matcher -> lift matcher
-    Nothing -> mzero
-
-stepParser :: MonadP m => ParserPrefs -> ArgPolicy -> String
-           -> Parser a -> NondetT (StateT Args m) (Parser a)
-stepParser _ AllPositionals arg p =
-  searchArg arg p
-stepParser pprefs ForwardOptions arg p = case parseWord arg of
-  Just w -> searchOpt pprefs w p <|> searchArg arg p
-  Nothing -> searchArg arg p
-stepParser pprefs _ arg p = case parseWord arg of
-  Just w -> searchOpt pprefs w p
-  Nothing -> searchArg arg p
-
-
--- | Apply a 'Parser' to a command line, and return a result and leftover
--- arguments.  This function returns an error if any parsing error occurs, or
--- if any options are missing and don't have a default value.
-runParser :: MonadP m => ArgPolicy -> IsCmdStart -> Parser a -> Args -> m (a, Args)
-runParser policy _ p ("--" : argt) | policy /= AllPositionals
-                                   = runParser AllPositionals CmdCont p argt
-runParser policy isCmdStart p args = case args of
-  [] -> exitP isCmdStart policy p result
-  (arg : argt) -> do
-    prefs <- getPrefs
-    (mp', args') <- do_step prefs arg argt
-    case mp' of
-      Nothing -> hoistMaybe result <|> parseError arg p
-      Just p' -> runParser (newPolicy arg) CmdCont p' args'
-  where
-    result = (,) <$> evalParser p <*> pure args
-    do_step prefs arg argt = (`runStateT` argt)
-                           . disamb (not (prefDisambiguate prefs))
-                           $ stepParser prefs policy arg p
-
-    newPolicy a = case policy of
-      NoIntersperse -> if isJust (parseWord a) then NoIntersperse else AllPositionals
-      x             -> x
-
-parseError :: MonadP m => String -> Parser x -> m a
-parseError arg = errorP . UnexpectedError arg . SomeParser
-
-runParserInfo :: MonadP m => ParserInfo a -> Args -> m a
-runParserInfo i = runParserFully (infoPolicy i) (infoParser i)
-
-runParserFully :: MonadP m => ArgPolicy -> Parser a -> Args -> m a
-runParserFully policy p args = do
-  (r, args') <- runParser policy CmdStart p args
-  case args' of
-    []  -> return r
-    a:_ -> parseError a (pure ())
-
--- | The default value of a 'Parser'.  This function returns an error if any of
--- the options don't have a default value.
-evalParser :: Parser a -> Maybe a
-evalParser (NilP r) = r
-evalParser (OptP _) = Nothing
-evalParser (MultP p1 p2) = evalParser p1 <*> evalParser p2
-evalParser (AltP p1 p2) = evalParser p1 <|> evalParser p2
-evalParser (BindP p k) = evalParser p >>= evalParser . k
-
--- | Map a polymorphic function over all the options of a parser, and collect
--- the results in a list.
-mapParser :: (forall x. OptHelpInfo -> Option x -> b)
-          -> Parser a -> [b]
-mapParser f = flatten . treeMapParser f
-  where
-    flatten (Leaf x) = [x]
-    flatten (MultNode xs) = xs >>= flatten
-    flatten (AltNode xs) = xs >>= flatten
-
--- | Like 'mapParser', but collect the results in a tree structure.
-treeMapParser :: (forall x . OptHelpInfo -> Option x -> b)
-          -> Parser a
-          -> OptTree b
-treeMapParser g = simplify . go False False False g
-  where
-    has_default :: Parser a -> Bool
-    has_default p = isJust (evalParser p)
-
-    go :: Bool -> Bool -> Bool
-       -> (forall x . OptHelpInfo -> Option x -> b)
-       -> Parser a
-       -> OptTree b
-    go _ _ _ _ (NilP _) = MultNode []
-    go m d r f (OptP opt)
-      | optVisibility opt > Internal
-      = Leaf (f (OptHelpInfo m d r) opt)
-      | otherwise
-      = MultNode []
-    go m d r f (MultP p1 p2) = MultNode [go m d r f p1, go m d r' f p2]
-      where r' = r || hasArg p1
-    go m d r f (AltP p1 p2) = AltNode [go m d' r f p1, go m d' r f p2]
-      where d' = d || has_default p1 || has_default p2
-    go _ d r f (BindP p k) =
-      let go' = go True d r f p
-      in case evalParser p of
-        Nothing -> go'
-        Just aa -> MultNode [ go', go True d r f (k aa) ]
-
-    hasArg :: Parser a -> Bool
-    hasArg (NilP _) = False
-    hasArg (OptP p) = (isArg . optMain) p
-    hasArg (MultP p1 p2) = hasArg p1 || hasArg p2
-    hasArg (AltP p1 p2) = hasArg p1 || hasArg p2
-    hasArg (BindP p _) = hasArg p
-
-
-simplify :: OptTree a -> OptTree a
-simplify (Leaf x) = Leaf x
-simplify (MultNode xs) =
-  case concatMap (remove_mult . simplify) xs of
-    [x] -> x
-    xs' -> MultNode xs'
-  where
-    remove_mult (MultNode ts) = ts
-    remove_mult t = [t]
-simplify (AltNode xs) =
-  case concatMap (remove_alt . simplify) xs of
-    []  -> MultNode []
-    [x] -> x
-    xs' -> AltNode xs'
-  where
-    remove_alt (AltNode ts) = ts
-    remove_alt (MultNode []) = []
-    remove_alt t = [t]
diff --git a/Options/Applicative/Extra.hs b/Options/Applicative/Extra.hs
deleted file mode 100644
--- a/Options/Applicative/Extra.hs
+++ /dev/null
@@ -1,290 +0,0 @@
-{-# LANGUAGE RankNTypes #-}
-module Options.Applicative.Extra (
-  -- * Extra parser utilities
-  --
-  -- | This module contains high-level functions to run parsers.
-  helper,
-  hsubparser,
-  execParser,
-  execParserMaybe,
-  customExecParser,
-  customExecParserMaybe,
-  execParserPure,
-  getParseResult,
-  handleParseResult,
-  parserFailure,
-  renderFailure,
-  ParserFailure(..),
-  overFailure,
-  ParserResult(..),
-  ParserPrefs(..),
-  CompletionResult(..),
-  ) where
-
-import Control.Applicative
-import Data.Monoid
-import Prelude
-import System.Environment (getArgs, getProgName)
-import System.Exit (exitSuccess, exitWith, ExitCode(..))
-import System.IO (hPutStrLn, stderr)
-
-import Options.Applicative.BashCompletion
-import Options.Applicative.Builder
-import Options.Applicative.Builder.Internal
-import Options.Applicative.Common
-import Options.Applicative.Help
-
-import Options.Applicative.Internal
-import Options.Applicative.Types
-
--- | A hidden \"helper\" option which always fails.
---
--- A common usage pattern is to apply this applicatively when
--- creating a 'ParserInfo'
---
--- > opts :: ParserInfo Sample
--- > opts = info (sample <**> helper) mempty
-
-helper :: Parser (a -> a)
-helper = abortOption ShowHelpText $ mconcat
-  [ long "help"
-  , short 'h'
-  , help "Show this help text"
-  , hidden ]
-
--- | Builder for a command parser with a \"helper\" option attached.
--- Used in the same way as `subparser`, but includes a \"--help|-h\" inside
--- the subcommand.
-hsubparser :: Mod CommandFields a -> Parser a
-hsubparser m = mkParser d g rdr
-  where
-    Mod _ d g = metavar "COMMAND" `mappend` m
-    (groupName, cmds, subs) = mkCommand m
-    rdr = CmdReader groupName cmds (fmap add_helper . subs)
-    add_helper pinfo = pinfo
-      { infoParser = infoParser pinfo <**> helper }
-
--- | Run a program description.
---
--- Parse command line arguments. Display help text and exit if any parse error
--- occurs.
-execParser :: ParserInfo a -> IO a
-execParser = customExecParser defaultPrefs
-
--- | Run a program description with custom preferences.
-customExecParser :: ParserPrefs -> ParserInfo a -> IO a
-customExecParser pprefs pinfo
-  = execParserPure pprefs pinfo <$> getArgs
-  >>= handleParseResult
-
--- | Handle `ParserResult`.
-handleParseResult :: ParserResult a -> IO a
-handleParseResult (Success a) = return a
-handleParseResult (Failure failure) = do
-      progn <- getProgName
-      let (msg, exit) = renderFailure failure progn
-      case exit of
-        ExitSuccess -> putStrLn msg
-        _           -> hPutStrLn stderr msg
-      exitWith exit
-handleParseResult (CompletionInvoked compl) = do
-      progn <- getProgName
-      msg <- execCompletion compl progn
-      putStr msg
-      exitSuccess
-
--- | Extract the actual result from a `ParserResult` value.
---
--- This function returns 'Nothing' in case of errors.  Possible error messages
--- or completion actions are simply discarded.
---
--- If you want to display error messages and invoke completion actions
--- appropriately, use 'handleParseResult' instead.
-getParseResult :: ParserResult a -> Maybe a
-getParseResult (Success a) = Just a
-getParseResult _ = Nothing
-
--- | Run a program description in pure code.
---
--- This function behaves like 'execParser', but can be called from pure code.
--- Note that, in case of errors, no message is displayed, and this function
--- simply returns 'Nothing'.
---
--- If you need to keep track of error messages, use 'execParserPure' instead.
-{-# DEPRECATED execParserMaybe "Use execParserPure together with getParseResult instead" #-}
-execParserMaybe :: ParserInfo a -> [String] -> Maybe a
-execParserMaybe = customExecParserMaybe defaultPrefs
-
--- | Run a program description with custom preferences in pure code.
---
--- See 'execParserMaybe' for details.
-{-# DEPRECATED customExecParserMaybe "Use execParserPure together with getParseResult instead" #-}
-customExecParserMaybe :: ParserPrefs -> ParserInfo a -> [String] -> Maybe a
-customExecParserMaybe pprefs pinfo args = getParseResult $ execParserPure pprefs pinfo args
-
--- | The most general way to run a program description in pure code.
-execParserPure :: ParserPrefs       -- ^ Global preferences for this parser
-               -> ParserInfo a      -- ^ Description of the program to run
-               -> [String]          -- ^ Program arguments
-               -> ParserResult a
-execParserPure pprefs pinfo args =
-  case runP p pprefs of
-    (Right (Right r), _) -> Success r
-    (Right (Left c), _) -> CompletionInvoked c
-    (Left err, ctx) -> Failure $ parserFailure pprefs pinfo err ctx
-  where
-    pinfo' = pinfo
-      { infoParser = (Left <$> bashCompletionParser pinfo pprefs)
-                 <|> (Right <$> infoParser pinfo) }
-    p = runParserInfo pinfo' args
-
--- | Generate a `ParserFailure` from a `ParseError` in a given `Context`.
---
--- This function can be used, for example, to show the help text for a parser:
---
--- @handleParseResult . Failure $ parserFailure pprefs pinfo ShowHelpText mempty@
-parserFailure :: ParserPrefs -> ParserInfo a
-              -> ParseError -> [Context]
-              -> ParserFailure ParserHelp
-parserFailure pprefs pinfo msg ctx = ParserFailure $ \progn ->
-  let h = with_context ctx pinfo $ \names pinfo' -> mconcat
-            [ base_help pinfo'
-            , usage_help progn names pinfo'
-            , suggestion_help
-            , error_help ]
-  in (h, exit_code, prefColumns pprefs)
-  where
-    exit_code = case msg of
-      ErrorMsg {}        -> ExitFailure (infoFailureCode pinfo)
-      UnknownError       -> ExitFailure (infoFailureCode pinfo)
-      MissingError {}    -> ExitFailure (infoFailureCode pinfo)
-      ExpectsArgError {} -> ExitFailure (infoFailureCode pinfo)
-      UnexpectedError {} -> ExitFailure (infoFailureCode pinfo)
-      ShowHelpText       -> ExitSuccess
-      InfoMsg {}         -> ExitSuccess
-
-    with_context :: [Context]
-                 -> ParserInfo a
-                 -> (forall b . [String] -> ParserInfo b -> c)
-                 -> c
-    with_context [] i f = f [] i
-    with_context c@(Context _ i:_) _ f = f (contextNames c) i
-
-    usage_help progn names i = case msg of
-      InfoMsg _
-        -> mempty
-      _
-        -> usageHelp $ vcatChunks
-          [ pure . parserUsage pprefs (infoParser i) . unwords $ progn : names
-          , fmap (indent 2) . infoProgDesc $ i ]
-
-    error_help = errorHelp $ case msg of
-      ShowHelpText
-        -> mempty
-
-      ErrorMsg m
-        -> stringChunk m
-
-      InfoMsg  m
-        -> stringChunk m
-
-      MissingError CmdStart _
-        | prefShowHelpOnEmpty pprefs
-        -> mempty
-
-      MissingError _ (SomeParser x)
-        -> stringChunk "Missing:" <<+>> missingDesc pprefs x
-
-      ExpectsArgError x
-        -> stringChunk $ "The option `" ++ x ++ "` expects an argument."
-
-      UnexpectedError arg _
-        -> stringChunk msg'
-          where
-            --
-            -- This gives us the same error we have always
-            -- reported
-            msg' = case arg of
-              ('-':_) -> "Invalid option `" ++ arg ++ "'"
-              _       -> "Invalid argument `" ++ arg ++ "'"
-
-      UnknownError
-        -> mempty
-
-
-    suggestion_help = suggestionsHelp $ case msg of
-      UnexpectedError arg (SomeParser x)
-        --
-        -- We have an unexpected argument and the parser which
-        -- it's running over.
-        --
-        -- We can make a good help suggestion here if we do
-        -- a levenstein distance between all possible suggestions
-        -- and the supplied option or argument.
-        -> suggestions
-          where
-            --
-            -- Not using chunked here, as we don't want to
-            -- show "Did you mean" if there's nothing there
-            -- to show
-            suggestions = (.$.) <$> prose
-                                <*> (indent 4 <$> (vcatChunks . fmap stringChunk $ good ))
-
-            --
-            -- We won't worry about the 0 case, it won't be
-            -- shown anyway.
-            prose       = if length good < 2
-                            then stringChunk "Did you mean this?"
-                            else stringChunk "Did you mean one of these?"
-            --
-            -- Suggestions we will show, they're close enough
-            -- to what the user wrote
-            good        = filter isClose possibles
-
-            --
-            -- Bit of an arbitrary decision here.
-            -- Edit distances of 1 or 2 will give hints
-            isClose a   = editDistance a arg < 3
-
-            --
-            -- Similar to how bash completion works.
-            -- We map over the parser and get the names
-            -- ( no IO here though, unlike for completers )
-            possibles   = concat $ mapParser opt_completions x
-
-            --
-            -- Look at the option and give back the possible
-            -- things the user could type. If it's a command
-            -- reader also ensure that it can be immediately
-            -- reachable from where the error was given.
-            opt_completions hinfo opt = case optMain opt of
-              OptReader ns _ _ -> fmap showOption ns
-              FlagReader ns _  -> fmap showOption ns
-              ArgReader _      -> []
-              CmdReader _ ns _  | hinfoUnreachableArgs hinfo
-                               -> []
-                                | otherwise
-                               -> ns
-      _
-        -> mempty
-
-    base_help :: ParserInfo a -> ParserHelp
-    base_help i
-      | show_full_help
-      = mconcat [h, f, parserHelp pprefs (infoParser i)]
-      | otherwise
-      = mempty
-      where
-        h = headerHelp (infoHeader i)
-        f = footerHelp (infoFooter i)
-
-    show_full_help = case msg of
-      ShowHelpText             -> True
-      MissingError CmdStart  _  | prefShowHelpOnEmpty pprefs
-                               -> True
-      _                        -> prefShowHelpOnError pprefs
-
-renderFailure :: ParserFailure ParserHelp -> String -> (String, ExitCode)
-renderFailure failure progn =
-  let (h, exit, cols) = execFailure failure progn
-  in (renderHelp cols h, exit)
diff --git a/Options/Applicative/Help.hs b/Options/Applicative/Help.hs
deleted file mode 100644
--- a/Options/Applicative/Help.hs
+++ /dev/null
@@ -1,28 +0,0 @@
-module Options.Applicative.Help (
-  -- | This is an empty module which re-exports
-  --   the help text system for optparse.
-
-  -- | Pretty printer. Reexports most combinators
-  --   from Text.PrettyPrint.ANSI.Leijen
-  module Options.Applicative.Help.Pretty,
-
-  -- | A free monoid over Doc with helpers for
-  --   composing help text components.
-  module Options.Applicative.Help.Chunk,
-
-  -- | Types required by the help system.
-  module Options.Applicative.Help.Types,
-
-  -- | Core implementation of the help text
-  --   generator.
-  module Options.Applicative.Help.Core,
-
-  -- | Edit distance calculations for suggestions
-  module Options.Applicative.Help.Levenshtein
-  ) where
-
-import Options.Applicative.Help.Chunk
-import Options.Applicative.Help.Core
-import Options.Applicative.Help.Levenshtein
-import Options.Applicative.Help.Pretty
-import Options.Applicative.Help.Types
diff --git a/Options/Applicative/Help/Chunk.hs b/Options/Applicative/Help/Chunk.hs
deleted file mode 100644
--- a/Options/Applicative/Help/Chunk.hs
+++ /dev/null
@@ -1,142 +0,0 @@
-module Options.Applicative.Help.Chunk
-  ( mappendWith
-  , Chunk(..)
-  , chunked
-  , listToChunk
-  , (<<+>>)
-  , (<</>>)
-  , vcatChunks
-  , vsepChunks
-  , isEmpty
-  , stringChunk
-  , paragraph
-  , extractChunk
-  , tabulate
-  ) where
-
-import Control.Applicative
-import Control.Monad
-import Data.Maybe
-import Data.Semigroup
-import Prelude
-
-import Options.Applicative.Help.Pretty
-
-mappendWith :: Monoid a => a -> a -> a -> a
-mappendWith s x y = mconcat [x, s, y]
-
--- | The free monoid on a semigroup 'a'.
-newtype Chunk a = Chunk
-  { unChunk :: Maybe a }
-  deriving (Eq, Show)
-
-instance Functor Chunk where
-  fmap f = Chunk . fmap f . unChunk
-
-instance Applicative Chunk where
-  pure = Chunk . pure
-  Chunk f <*> Chunk x = Chunk (f <*> x)
-
-instance Alternative Chunk where
-  empty = Chunk Control.Applicative.empty
-  a <|> b = Chunk $ unChunk a <|> unChunk b
-
-instance Monad Chunk where
-  return = pure
-  m >>= f = Chunk $ unChunk m >>= unChunk . f
-
-instance Monoid a => Semigroup (Chunk a) where
-  (<>) = chunked mappend
-
-instance Monoid a => Monoid (Chunk a) where
-  mempty = Chunk Nothing
-  mappend = (<>)
-
-instance MonadPlus Chunk where
-  mzero = Chunk mzero
-  mplus m1 m2 = Chunk $ mplus (unChunk m1) (unChunk m2)
-
--- | Given a semigroup structure on 'a', return a monoid structure on 'Chunk a'.
---
--- Note that this is /not/ the same as 'liftA2'.
-chunked :: (a -> a -> a)
-        -> Chunk a -> Chunk a -> Chunk a
-chunked _ (Chunk Nothing) y = y
-chunked _ x (Chunk Nothing) = x
-chunked f (Chunk (Just x)) (Chunk (Just y)) = Chunk (Just (f x y))
-
--- | Concatenate a list into a Chunk.  'listToChunk' satisfies:
---
--- > isEmpty . listToChunk = null
--- > listToChunk = mconcat . fmap pure
-listToChunk :: Monoid a => [a] -> Chunk a
-listToChunk [] = mempty
-listToChunk xs = pure (mconcat xs)
-
--- | Part of a constrained comonad instance.
---
--- This is the counit of the adjunction between 'Chunk' and the forgetful
--- functor from monoids to semigroups.  It satisfies:
---
--- > extractChunk . pure = id
--- > extractChunk . fmap pure = id
-extractChunk :: Monoid a => Chunk a -> a
-extractChunk = fromMaybe mempty . unChunk
--- we could also define:
--- duplicate :: Monoid a => Chunk a -> Chunk (Chunk a)
--- duplicate = fmap pure
-
--- | Concatenate two 'Chunk's with a space in between.  If one is empty, this
--- just returns the other one.
---
--- Unlike '<+>' for 'Doc', this operation has a unit element, namely the empty
--- 'Chunk'.
-(<<+>>) :: Chunk Doc -> Chunk Doc -> Chunk Doc
-(<<+>>) = chunked (<+>)
-
--- | Concatenate two 'Chunk's with a softline in between.  This is exactly like
--- '<<+>>', but uses a softline instead of a space.
-(<</>>) :: Chunk Doc -> Chunk Doc -> Chunk Doc
-(<</>>) = chunked (</>)
-
--- | Concatenate 'Chunk's vertically.
-vcatChunks :: [Chunk Doc] -> Chunk Doc
-vcatChunks = foldr (chunked (.$.)) mempty
-
--- | Concatenate 'Chunk's vertically separated by empty lines.
-vsepChunks :: [Chunk Doc] -> Chunk Doc
-vsepChunks = foldr (chunked (\x y -> x .$. mempty .$. y)) mempty
-
--- | Whether a 'Chunk' is empty.  Note that something like 'pure mempty' is not
--- considered an empty chunk, even though the underlying 'Doc' is empty.
-isEmpty :: Chunk a -> Bool
-isEmpty = isNothing . unChunk
-
--- | Convert a 'String' into a 'Chunk'.  This satisfies:
---
--- > isEmpty . stringChunk = null
--- > extractChunk . stringChunk = string
-stringChunk :: String -> Chunk Doc
-stringChunk "" = mempty
-stringChunk s = pure (string s)
-
--- | Convert a paragraph into a 'Chunk'.  The resulting chunk is composed by the
--- words of the original paragraph separated by softlines, so it will be
--- automatically word-wrapped when rendering the underlying document.
---
--- This satisfies:
---
--- > isEmpty . paragraph = null . words
-paragraph :: String -> Chunk Doc
-paragraph = foldr (chunked (</>) . stringChunk) mempty
-          . words
-
-tabulate' :: Int -> [(Doc, Doc)] -> Chunk Doc
-tabulate' _ [] = mempty
-tabulate' size table = pure $ vcat
-  [ indent 2 (fillBreak size key <+> value)
-  | (key, value) <- table ]
-
--- | Display pairs of strings in a table.
-tabulate :: [(Doc, Doc)] -> Chunk Doc
-tabulate = tabulate' 24
diff --git a/Options/Applicative/Help/Core.hs b/Options/Applicative/Help/Core.hs
deleted file mode 100644
--- a/Options/Applicative/Help/Core.hs
+++ /dev/null
@@ -1,177 +0,0 @@
-module Options.Applicative.Help.Core (
-  cmdDesc,
-  briefDesc,
-  missingDesc,
-  fold_tree,
-  fullDesc,
-  ParserHelp(..),
-  errorHelp,
-  headerHelp,
-  suggestionsHelp,
-  usageHelp,
-  bodyHelp,
-  footerHelp,
-  parserHelp,
-  parserUsage,
-  ) where
-
-import Control.Applicative
-import Control.Monad (guard)
-import Data.Function (on)
-import Data.List (sort, intersperse, groupBy)
-import Data.Maybe (maybeToList, catMaybes, fromMaybe)
-import Data.Monoid
-import Prelude
-
-import Options.Applicative.Common
-import Options.Applicative.Types
-import Options.Applicative.Help.Pretty
-import Options.Applicative.Help.Chunk
-
--- | Style for rendering an option.
-data OptDescStyle = OptDescStyle
-  { descSep :: Doc
-  , descHidden :: Bool
-  , descOptional :: Bool
-  , descSurround :: Bool }
-
--- | Generate description for a single option.
-optDesc :: ParserPrefs -> OptDescStyle -> OptHelpInfo -> Option a -> Chunk Doc
-optDesc pprefs style info opt =
-  let ns = optionNames $ optMain opt
-      mv = stringChunk $ optMetaVar opt
-      descs = map (string . showOption) (sort ns)
-      desc' = listToChunk (intersperse (descSep style) descs) <<+>> mv
-      show_opt
-        | hinfoDefault info && not (descOptional style)
-        = False
-        | optVisibility opt == Hidden
-        = descHidden style
-        | otherwise
-        = optVisibility opt == Visible
-      suffix
-        | hinfoMulti info
-        = stringChunk . prefMultiSuffix $ pprefs
-        | otherwise
-        = mempty
-      render chunk
-        | not show_opt
-        = mempty
-        | isEmpty chunk || not (descSurround style)
-        = mappend chunk suffix
-        | hinfoDefault info
-        = mappend (fmap brackets chunk) suffix
-        | null (drop 1 descs)
-        = mappend chunk suffix
-        | otherwise
-        = mappend (fmap parens chunk) suffix
-  in maybe id fmap (optDescMod opt) (render desc')
-
--- | Generate descriptions for commands.
-cmdDesc :: Parser a -> [(Maybe String, Chunk Doc)]
-cmdDesc = mapParser desc
-  where
-    desc _ opt =
-      case optMain opt of
-        CmdReader gn cmds p -> (,) gn $
-          tabulate [(string cmd, align (extractChunk d))
-                   | cmd <- reverse cmds
-                   , d <- maybeToList . fmap infoProgDesc $ p cmd ]
-        _ -> mempty
-
--- | Generate a brief help text for a parser.
-briefDesc :: ParserPrefs -> Parser a -> Chunk Doc
-briefDesc = briefDesc' True
-
--- | Generate a brief help text for a parser, only including mandatory
---   options and arguments.
-missingDesc :: ParserPrefs -> Parser a -> Chunk Doc
-missingDesc = briefDesc' False
-
--- | Generate a brief help text for a parser, allowing the specification
---   of if optional arguments are show.
-briefDesc' :: Bool -> ParserPrefs -> Parser a -> Chunk Doc
-briefDesc' showOptional pprefs = fold_tree . treeMapParser (optDesc pprefs style)
-  where
-    style = OptDescStyle
-      { descSep = string "|"
-      , descHidden = False
-      , descOptional = showOptional
-      , descSurround = True }
-
-fold_tree :: OptTree (Chunk Doc) -> Chunk Doc
-fold_tree (Leaf x) = x
-fold_tree (MultNode xs) = foldr ((<</>>) . fold_tree) mempty xs
-fold_tree (AltNode xs) = alt_node
-                       . filter (not . isEmpty)
-                       . map fold_tree $ xs
-  where
-    alt_node :: [Chunk Doc] -> Chunk Doc
-    alt_node [n] = n
-    alt_node ns = fmap parens
-                . foldr (chunked (\x y -> x </> char '|' </> y)) mempty
-                $ ns
-
--- | Generate a full help text for a parser.
-fullDesc :: ParserPrefs -> Parser a -> Chunk Doc
-fullDesc pprefs = tabulate . catMaybes . mapParser doc
-  where
-    doc info opt = do
-      guard . not . isEmpty $ n
-      guard . not . isEmpty $ h
-      return (extractChunk n, align . extractChunk $ h <<+>> hdef)
-      where
-        n = optDesc pprefs style info opt
-        h = optHelp opt
-        hdef = Chunk . fmap show_def . optShowDefault $ opt
-        show_def s = parens (string "default:" <+> string s)
-    style = OptDescStyle
-      { descSep = string ","
-      , descHidden = True
-      , descOptional = True
-      , descSurround = False }
-
-errorHelp :: Chunk Doc -> ParserHelp
-errorHelp chunk = mempty { helpError = chunk }
-
-headerHelp :: Chunk Doc -> ParserHelp
-headerHelp chunk = mempty { helpHeader = chunk }
-
-suggestionsHelp :: Chunk Doc -> ParserHelp
-suggestionsHelp chunk = mempty { helpSuggestions = chunk }
-
-usageHelp :: Chunk Doc -> ParserHelp
-usageHelp chunk = mempty { helpUsage = chunk }
-
-bodyHelp :: Chunk Doc -> ParserHelp
-bodyHelp chunk = mempty { helpBody = chunk }
-
-footerHelp :: Chunk Doc -> ParserHelp
-footerHelp chunk = mempty { helpFooter = chunk }
-
--- | Generate the help text for a program.
-parserHelp :: ParserPrefs -> Parser a -> ParserHelp
-parserHelp pprefs p = bodyHelp . vsepChunks $
-  ( with_title "Available options:" (fullDesc pprefs p) )
-  : (group_title <$> cs)
-  where
-    def = "Available commands:"
-
-    cs = groupBy ((==) `on` fst) $ cmdDesc p
-
-    group_title a@((n,_):_) = with_title (fromMaybe def n) $
-      vcatChunks (snd <$> a)
-    group_title _ = mempty
-
-
-    with_title :: String -> Chunk Doc -> Chunk Doc
-    with_title title = fmap (string title .$.)
-
--- | Generate option summary.
-parserUsage :: ParserPrefs -> Parser a -> String -> Doc
-parserUsage pprefs p progn = hsep
-  [ string "Usage:"
-  , string progn
-  , align (extractChunk (briefDesc pprefs p)) ]
-
-{-# ANN footerHelp "HLint: ignore Eta reduce" #-}
diff --git a/Options/Applicative/Help/Levenshtein.hs b/Options/Applicative/Help/Levenshtein.hs
deleted file mode 100644
--- a/Options/Applicative/Help/Levenshtein.hs
+++ /dev/null
@@ -1,61 +0,0 @@
-module Options.Applicative.Help.Levenshtein (
-    editDistance
-  ) where
-
--- | Calculate the Damerau-Levenshtein edit distance
---   between two lists (strings).
---
---   This is modified from
---   https://wiki.haskell.org/Edit_distance
---   and is originally from Lloyd Allison's paper
---   "Lazy Dynamic-Programming can be Eager"
---
---   It's been changed though from Levenshtein to
---   Damerau-Levenshtein, which treats transposition
---   of adjacent characters as one change instead of
---   two.
-editDistance :: Eq a => [a] -> [a] -> Int
-editDistance a b = last $
-  case () of
-    _ | lab == 0
-     -> mainDiag
-      | lab > 0
-     -> lowers !! (lab - 1)
-      | otherwise
-     -> uppers !! (-1 - lab)
-  where
-    mainDiag = oneDiag a b (head uppers) (-1 : head lowers)
-    uppers = eachDiag a b (mainDiag : uppers) -- upper diagonals
-    lowers = eachDiag b a (mainDiag : lowers) -- lower diagonals
-    eachDiag _ [] _ = []
-    eachDiag _ _ [] = []
-    eachDiag a' (_:bs) (lastDiag:diags) =
-      oneDiag a' bs nextDiag lastDiag : eachDiag a' bs diags
-      where
-        nextDiag = head (tail diags)
-    oneDiag a' b' diagAbove diagBelow = thisdiag
-      where
-        doDiag [] _ _ _ _ = []
-        doDiag _ [] _ _ _ = []
-        -- Check for a transposition
-        -- We don't add anything to nw here, the next character
-        -- will be different however and the transposition
-        -- will have an edit distance of 1.
-        doDiag (ach:ach':as) (bch:bch':bs) nw n w
-          | ach' == bch && ach == bch'
-          = nw : (doDiag (ach' : as) (bch' : bs) nw (tail n) (tail w))
-        -- Standard case
-        doDiag (ach:as) (bch:bs) nw n w =
-          me : (doDiag as bs me (tail n) (tail w))
-          where
-            me =
-              if ach == bch
-                then nw
-                else 1 + min3 (head w) nw (head n)
-        firstelt = 1 + head diagBelow
-        thisdiag = firstelt : doDiag a' b' firstelt diagAbove (tail diagBelow)
-    lab = length a - length b
-    min3 x y z =
-      if x < y
-        then x
-        else min y z
diff --git a/Options/Applicative/Help/Pretty.hs b/Options/Applicative/Help/Pretty.hs
deleted file mode 100644
--- a/Options/Applicative/Help/Pretty.hs
+++ /dev/null
@@ -1,10 +0,0 @@
-module Options.Applicative.Help.Pretty
-  ( module Text.PrettyPrint.ANSI.Leijen
-  , (.$.)
-  ) where
-
-import Text.PrettyPrint.ANSI.Leijen hiding ((<$>), (<>), columns)
-import qualified Text.PrettyPrint.ANSI.Leijen as PP
-
-(.$.) :: Doc -> Doc -> Doc
-(.$.) = (PP.<$>)
diff --git a/Options/Applicative/Help/Types.hs b/Options/Applicative/Help/Types.hs
deleted file mode 100644
--- a/Options/Applicative/Help/Types.hs
+++ /dev/null
@@ -1,41 +0,0 @@
-module Options.Applicative.Help.Types (
-    ParserHelp (..)
-  , renderHelp
-  ) where
-
-import Data.Semigroup
-import Prelude
-
-import Options.Applicative.Help.Chunk
-import Options.Applicative.Help.Pretty
-
-data ParserHelp = ParserHelp
-  { helpError :: Chunk Doc
-  , helpSuggestions :: Chunk Doc
-  , helpHeader :: Chunk Doc
-  , helpUsage :: Chunk Doc
-  , helpBody :: Chunk Doc
-  , helpFooter :: Chunk Doc }
-
-instance Show ParserHelp where
-  showsPrec _ h = showString (renderHelp 80 h)
-
-instance Monoid ParserHelp where
-  mempty = ParserHelp mempty mempty mempty mempty mempty mempty
-  mappend = (<>)
-
-instance Semigroup ParserHelp where
-  (ParserHelp e1 s1 h1 u1 b1 f1) <> (ParserHelp e2 s2 h2 u2 b2 f2)
-    = ParserHelp (mappend e1 e2) (mappend s1 s2)
-                 (mappend h1 h2) (mappend u1 u2)
-                 (mappend b1 b2) (mappend f1 f2)
-
-helpText :: ParserHelp -> Doc
-helpText (ParserHelp e s h u b f) = extractChunk . vsepChunks $ [e, s, h, u, b, f]
-
--- | Convert a help text to 'String'.
-renderHelp :: Int -> ParserHelp -> String
-renderHelp cols
-  = (`displayS` "")
-  . renderPretty 1.0 cols
-  . helpText
diff --git a/Options/Applicative/Internal.hs b/Options/Applicative/Internal.hs
deleted file mode 100644
--- a/Options/Applicative/Internal.hs
+++ /dev/null
@@ -1,265 +0,0 @@
-module Options.Applicative.Internal
-  ( P
-  , MonadP(..)
-  , ParseError(..)
-
-  , uncons
-  , hoistMaybe
-  , hoistEither
-  , runReadM
-  , withReadM
-
-  , runP
-
-  , Completion
-  , runCompletion
-  , contextNames
-
-  , ListT
-  , takeListT
-  , runListT
-
-  , NondetT
-  , cut
-  , (<!>)
-  , disamb
-  ) where
-
-import Control.Applicative
-import Prelude
-import Control.Monad (MonadPlus(..), liftM, ap, guard)
-import Control.Monad.Trans.Class (MonadTrans, lift)
-import Control.Monad.Trans.Except
-  (runExcept, runExceptT, withExcept, ExceptT(..), throwE)
-import Control.Monad.Trans.Reader
-  (mapReaderT, runReader, runReaderT, Reader, ReaderT, ask)
-import Control.Monad.Trans.State (StateT, get, put, modify, evalStateT, runStateT)
-
-import Options.Applicative.Types
-
-class (Alternative m, MonadPlus m) => MonadP m where
-  enterContext :: String -> ParserInfo a -> m ()
-  exitContext :: m ()
-  getPrefs :: m ParserPrefs
-
-  missingArgP :: ParseError -> Completer -> m a
-  errorP :: ParseError -> m a
-  exitP :: IsCmdStart -> ArgPolicy -> Parser b -> Maybe a -> m a
-
-newtype P a = P (ExceptT ParseError (StateT [Context] (Reader ParserPrefs)) a)
-
-instance Functor P where
-  fmap f (P m) = P $ fmap f m
-
-instance Applicative P where
-  pure a = P $ pure a
-  P f <*> P a = P $ f <*> a
-
-instance Alternative P where
-  empty = P empty
-  P x <|> P y = P $ x <|> y
-
-instance Monad P where
-  return = pure
-  P x >>= k = P $ x >>= \a -> case k a of P y -> y
-
-instance MonadPlus P where
-  mzero = P mzero
-  mplus (P x) (P y) = P $ mplus x y
-
-contextNames :: [Context] -> [String]
-contextNames ns =
-  let go (Context n _) = n
-  in  reverse $ go <$> ns
-
-instance MonadP P where
-  enterContext name pinfo = P $ lift $ modify $ (:) $ Context name pinfo
-  exitContext = P $ lift $ modify $ drop 1
-  getPrefs = P . lift . lift $ ask
-
-  missingArgP e _ = errorP e
-  exitP i _ p = P . maybe (throwE . MissingError i . SomeParser $ p) return
-  errorP = P . throwE
-
-hoistMaybe :: MonadPlus m => Maybe a -> m a
-hoistMaybe = maybe mzero return
-
-hoistEither :: MonadP m => Either ParseError a -> m a
-hoistEither = either errorP return
-
-runP :: P a -> ParserPrefs -> (Either ParseError a, [Context])
-runP (P p) = runReader . flip runStateT [] . runExceptT $ p
-
-uncons :: [a] -> Maybe (a, [a])
-uncons [] = Nothing
-uncons (x : xs) = Just (x, xs)
-
-runReadM :: MonadP m => ReadM a -> String -> m a
-runReadM (ReadM r) s = hoistEither . runExcept $ runReaderT r s
-
-withReadM :: (String -> String) -> ReadM a -> ReadM a
-withReadM f = ReadM . mapReaderT (withExcept f') . unReadM
-  where
-    f' (ErrorMsg err) = ErrorMsg (f err)
-    f' e = e
-
-data ComplResult a
-  = ComplParser SomeParser ArgPolicy
-  | ComplOption Completer
-  | ComplResult a
-
-instance Functor ComplResult where
-  fmap = liftM
-
-instance Applicative ComplResult where
-  pure = ComplResult
-  (<*>) = ap
-
-instance Monad ComplResult where
-  return = pure
-  m >>= f = case m of
-    ComplResult r -> f r
-    ComplParser p a -> ComplParser p a
-    ComplOption c -> ComplOption c
-
-newtype Completion a =
-  Completion (ExceptT ParseError (ReaderT ParserPrefs ComplResult) a)
-
-instance Functor Completion where
-  fmap f (Completion m) = Completion $ fmap f m
-
-instance Applicative Completion where
-  pure a = Completion $ pure a
-  Completion f <*> Completion a = Completion $ f <*> a
-
-instance Alternative Completion where
-  empty = Completion empty
-  Completion x <|> Completion y = Completion $ x <|> y
-
-instance Monad Completion where
-  return = pure
-  Completion x >>= k = Completion $ x >>= \a -> case k a of Completion y -> y
-
-instance MonadPlus Completion where
-  mzero = Completion mzero
-  mplus (Completion x) (Completion y) = Completion $ mplus x y
-
-instance MonadP Completion where
-  enterContext _ _ = return ()
-  exitContext = return ()
-  getPrefs = Completion $ lift ask
-
-  missingArgP _ = Completion . lift . lift . ComplOption
-  exitP _ a p _ = Completion . lift . lift $ ComplParser (SomeParser p) a
-  errorP = Completion . throwE
-
-runCompletion :: Completion r -> ParserPrefs -> Maybe (Either (SomeParser, ArgPolicy) Completer)
-runCompletion (Completion c) prefs = case runReaderT (runExceptT c) prefs of
-  ComplResult _ -> Nothing
-  ComplParser p' a' -> Just $ Left (p', a')
-  ComplOption compl -> Just $ Right compl
-
--- A "ListT done right" implementation
-
-newtype ListT m a = ListT
-  { stepListT :: m (TStep a (ListT m a)) }
-
-data TStep a x
-  = TNil
-  | TCons a x
-
-bimapTStep :: (a -> b) -> (x -> y) -> TStep a x -> TStep b y
-bimapTStep _ _ TNil = TNil
-bimapTStep f g (TCons a x) = TCons (f a) (g x)
-
-hoistList :: Monad m => [a] -> ListT m a
-hoistList = foldr (\x xt -> ListT (return (TCons x xt))) mzero
-
-takeListT :: Monad m => Int -> ListT m a -> ListT m a
-takeListT 0 = const mzero
-takeListT n = ListT . liftM (bimapTStep id (takeListT (n - 1))) . stepListT
-
-runListT :: Monad m => ListT m a -> m [a]
-runListT xs = do
-  s <- stepListT xs
-  case s of
-    TNil -> return []
-    TCons x xt -> liftM (x :) (runListT xt)
-
-instance Monad m => Functor (ListT m) where
-  fmap f = ListT
-         . liftM (bimapTStep f (fmap f))
-         . stepListT
-
-instance Monad m => Applicative (ListT m) where
-  pure = hoistList . pure
-  (<*>) = ap
-
-instance Monad m => Monad (ListT m) where
-  return = pure
-  xs >>= f = ListT $ do
-    s <- stepListT xs
-    case s of
-      TNil -> return TNil
-      TCons x xt -> stepListT $ f x `mplus` (xt >>= f)
-
-instance Monad m => Alternative (ListT m) where
-  empty = mzero
-  (<|>) = mplus
-
-instance MonadTrans ListT where
-  lift = ListT . liftM (`TCons` mzero)
-
-instance Monad m => MonadPlus (ListT m) where
-  mzero = ListT (return TNil)
-  mplus xs ys = ListT $ do
-    s <- stepListT xs
-    case s of
-      TNil -> stepListT ys
-      TCons x xt -> return $ TCons x (xt `mplus` ys)
-
--- nondeterminism monad with cut operator
-
-newtype NondetT m a = NondetT
-  { runNondetT :: ListT (StateT Bool m) a }
-
-instance Monad m => Functor (NondetT m) where
-  fmap f = NondetT . fmap f . runNondetT
-
-instance Monad m => Applicative (NondetT m) where
-  pure = NondetT . pure
-  NondetT m1 <*> NondetT m2 = NondetT (m1 <*> m2)
-
-instance Monad m => Monad (NondetT m) where
-  return = pure
-  NondetT m1 >>= f = NondetT $ m1 >>= runNondetT . f
-
-instance Monad m => MonadPlus (NondetT m) where
-  mzero = NondetT mzero
-  NondetT m1 `mplus` NondetT m2 = NondetT (m1 `mplus` m2)
-
-instance Monad m => Alternative (NondetT m) where
-  empty = mzero
-  (<|>) = mplus
-
-instance MonadTrans NondetT where
-  lift = NondetT . lift . lift
-
-(<!>) :: Monad m => NondetT m a -> NondetT m a -> NondetT m a
-(<!>) m1 m2 = NondetT . mplus (runNondetT m1) $ do
-  s <- lift get
-  guard (not s)
-  runNondetT m2
-
-cut :: Monad m => NondetT m ()
-cut = NondetT $ lift (put True)
-
-disamb :: Monad m => Bool -> NondetT m a -> m (Maybe a)
-disamb allow_amb xs = do
-  xs' <- (`evalStateT` False)
-       . runListT
-       . takeListT (if allow_amb then 1 else 2)
-       . runNondetT $ xs
-  return $ case xs' of
-    [x] -> Just x
-    _   -> Nothing
diff --git a/Options/Applicative/Types.hs b/Options/Applicative/Types.hs
deleted file mode 100644
--- a/Options/Applicative/Types.hs
+++ /dev/null
@@ -1,396 +0,0 @@
-{-# LANGUAGE Rank2Types, ExistentialQuantification #-}
-module Options.Applicative.Types (
-  ParseError(..),
-  ParserInfo(..),
-  ParserPrefs(..),
-
-  Option(..),
-  OptName(..),
-  OptReader(..),
-  OptProperties(..),
-  OptVisibility(..),
-  ReadM(..),
-  readerAsk,
-  readerAbort,
-  readerError,
-  CReader(..),
-  Parser(..),
-  ParserM(..),
-  Completer(..),
-  mkCompleter,
-  CompletionResult(..),
-  ParserFailure(..),
-  ParserResult(..),
-  overFailure,
-  Args,
-  ArgPolicy(..),
-  OptHelpInfo(..),
-  OptTree(..),
-  ParserHelp(..),
-  SomeParser(..),
-  Context(..),
-  IsCmdStart(..),
-
-  fromM,
-  oneM,
-  manyM,
-  someM,
-
-  optVisibility,
-  optMetaVar,
-  optHelp,
-  optShowDefault,
-  optDescMod
-  ) where
-
-import Control.Applicative
-import Control.Monad (ap, liftM, MonadPlus, mzero, mplus)
-import Control.Monad.Trans.Except (Except, throwE)
-import Control.Monad.Trans.Class (lift)
-import Control.Monad.Trans.Reader (ReaderT, ask)
-import qualified Control.Monad.Fail as Fail
-import Data.Semigroup hiding (Option)
-import Prelude
-
-import System.Exit (ExitCode(..))
-
-import Options.Applicative.Help.Types
-import Options.Applicative.Help.Pretty
-import Options.Applicative.Help.Chunk
-
-
-data ParseError
-  = ErrorMsg String
-  | InfoMsg String
-  | ShowHelpText
-  | UnknownError
-  | MissingError IsCmdStart SomeParser
-  | ExpectsArgError String
-  | UnexpectedError String SomeParser
-
-data IsCmdStart = CmdStart | CmdCont
-  deriving Show
-
-instance Monoid ParseError where
-  mempty = UnknownError
-  mappend = (<>)
-
-instance Semigroup ParseError where
-  m <> UnknownError = m
-  _ <> m = m
-
--- | A full description for a runnable 'Parser' for a program.
-data ParserInfo a = ParserInfo
-  { infoParser :: Parser a    -- ^ the option parser for the program
-  , infoFullDesc :: Bool      -- ^ whether the help text should contain full
-                              -- documentation
-  , infoProgDesc :: Chunk Doc -- ^ brief parser description
-  , infoHeader :: Chunk Doc   -- ^ header of the full parser description
-  , infoFooter :: Chunk Doc   -- ^ footer of the full parser description
-  , infoFailureCode :: Int    -- ^ exit code for a parser failure
-  , infoPolicy :: ArgPolicy   -- ^ allow regular options and flags to occur
-                              -- after arguments (default: InterspersePolicy)
-  }
-
-instance Functor ParserInfo where
-  fmap f i = i { infoParser = fmap f (infoParser i) }
-
--- | Global preferences for a top-level 'Parser'.
-data ParserPrefs = ParserPrefs
-  { prefMultiSuffix :: String    -- ^ metavar suffix for multiple options
-  , prefDisambiguate :: Bool     -- ^ automatically disambiguate abbreviations
-                                 -- (default: False)
-  , prefShowHelpOnError :: Bool  -- ^ always show help text on parse errors
-                                 -- (default: False)
-  , prefShowHelpOnEmpty :: Bool  -- ^ show the help text for a command or subcommand
-                                 -- if it fails with no input (default: False)
-  , prefBacktrack :: Bool        -- ^ backtrack to parent parser when a
-                                 -- subcommand fails (default: True)
-  , prefColumns :: Int           -- ^ number of columns in the terminal, used to
-                                 -- format the help page (default: 80)
-  } deriving (Eq, Show)
-
-data OptName = OptShort !Char
-             | OptLong !String
-  deriving (Eq, Ord, Show)
-
--- | Visibility of an option in the help text.
-data OptVisibility
-  = Internal          -- ^ does not appear in the help text at all
-  | Hidden            -- ^ only visible in the full description
-  | Visible           -- ^ visible both in the full and brief descriptions
-  deriving (Eq, Ord, Show)
-
--- | Specification for an individual parser option.
-data OptProperties = OptProperties
-  { propVisibility :: OptVisibility       -- ^ whether this flag is shown is the brief description
-  , propHelp :: Chunk Doc                 -- ^ help text for this option
-  , propMetaVar :: String                 -- ^ metavariable for this option
-  , propShowDefault :: Maybe String       -- ^ what to show in the help text as the default
-  , propDescMod :: Maybe ( Doc -> Doc )   -- ^ a function to run over the brief description
-  }
-
-instance Show OptProperties where
-  showsPrec p (OptProperties pV pH pMV pSD _)
-    = showParen (p >= 11)
-    $ showString "OptProperties { propVisibility = " . shows pV
-    . showString ", propHelp = " . shows pH
-    . showString ", propMetaVar = " . shows pMV
-    . showString ", propShowDefault = " . shows pSD
-    . showString ", propDescMod = _ }"
-
--- | A single option of a parser.
-data Option a = Option
-  { optMain :: OptReader a               -- ^ reader for this option
-  , optProps :: OptProperties            -- ^ properties of this option
-  }
-
-data SomeParser = forall a . SomeParser (Parser a)
-
--- | Subparser context, containing the 'name' of the subparser, and its parser info.
---   Used by parserFailure to display relevant usage information when parsing inside a subparser fails.
-data Context = forall a . Context String (ParserInfo a)
-
-instance Show (Option a) where
-    show opt = "Option {optProps = " ++ show (optProps opt) ++ "}"
-
-instance Functor Option where
-  fmap f (Option m p) = Option (fmap f m) p
-
--- | A newtype over 'ReaderT String Except', used by option readers.
-newtype ReadM a = ReadM
-  { unReadM :: ReaderT String (Except ParseError) a }
-
-instance Functor ReadM where
-  fmap f (ReadM r) = ReadM (fmap f r)
-
-instance Applicative ReadM where
-  pure = ReadM . pure
-  ReadM x <*> ReadM y = ReadM $ x <*> y
-
-instance Alternative ReadM where
-  empty = mzero
-  (<|>) = mplus
-
-instance Monad ReadM where
-  return = pure
-  ReadM r >>= f = ReadM $ r >>= unReadM . f
-  fail = Fail.fail
-
-instance Fail.MonadFail ReadM where
-  fail = readerError
-
-instance MonadPlus ReadM where
-  mzero = ReadM mzero
-  mplus (ReadM x) (ReadM y) = ReadM $ mplus x y
-
--- | Return the value being read.
-readerAsk :: ReadM String
-readerAsk = ReadM ask
-
--- | Abort option reader by exiting with a 'ParseError'.
-readerAbort :: ParseError -> ReadM a
-readerAbort = ReadM . lift . throwE
-
--- | Abort option reader by exiting with an error message.
-readerError :: String -> ReadM a
-readerError = readerAbort . ErrorMsg
-
-data CReader a = CReader
-  { crCompleter :: Completer
-  , crReader :: ReadM a }
-
-instance Functor CReader where
-  fmap f (CReader c r) = CReader c (fmap f r)
-
--- | An 'OptReader' defines whether an option matches an command line argument.
-data OptReader a
-  = OptReader [OptName] (CReader a) (String -> ParseError)
-  -- ^ option reader
-  | FlagReader [OptName] !a
-  -- ^ flag reader
-  | ArgReader (CReader a)
-  -- ^ argument reader
-  | CmdReader (Maybe String) [String] (String -> Maybe (ParserInfo a))
-  -- ^ command reader
-
-instance Functor OptReader where
-  fmap f (OptReader ns cr e) = OptReader ns (fmap f cr) e
-  fmap f (FlagReader ns x) = FlagReader ns (f x)
-  fmap f (ArgReader cr) = ArgReader (fmap f cr)
-  fmap f (CmdReader n cs g) = CmdReader n cs ((fmap . fmap) f . g)
-
--- | A @Parser a@ is an option parser returning a value of type 'a'.
-data Parser a
-  = NilP (Maybe a)
-  | OptP (Option a)
-  | forall x . MultP (Parser (x -> a)) (Parser x)
-  | AltP (Parser a) (Parser a)
-  | forall x . BindP (Parser x) (x -> Parser a)
-
-instance Functor Parser where
-  fmap f (NilP x) = NilP (fmap f x)
-  fmap f (OptP opt) = OptP (fmap f opt)
-  fmap f (MultP p1 p2) = MultP (fmap (f.) p1) p2
-  fmap f (AltP p1 p2) = AltP (fmap f p1) (fmap f p2)
-  fmap f (BindP p k) = BindP p (fmap f . k)
-
-instance Applicative Parser where
-  pure = NilP . Just
-  (<*>) = MultP
-
-newtype ParserM r = ParserM
-  { runParserM :: forall x . (r -> Parser x) -> Parser x }
-
-instance Monad ParserM where
-  return = pure
-  ParserM f >>= g = ParserM $ \k -> f (\x -> runParserM (g x) k)
-
-instance Functor ParserM where
-  fmap = liftM
-
-instance Applicative ParserM where
-  pure x = ParserM $ \k -> k x
-  (<*>) = ap
-
-fromM :: ParserM a -> Parser a
-fromM (ParserM f) = f pure
-
-oneM :: Parser a -> ParserM a
-oneM p = ParserM (BindP p)
-
-manyM :: Parser a -> ParserM [a]
-manyM p = do
-  mx <- oneM (optional p)
-  case mx of
-    Nothing -> return []
-    Just x -> (x:) <$> manyM p
-
-someM :: Parser a -> ParserM [a]
-someM p = (:) <$> oneM p <*> manyM p
-
-instance Alternative Parser where
-  empty = NilP Nothing
-  (<|>) = AltP
-  many p = fromM $ manyM p
-  some p = fromM $ (:) <$> oneM p <*> manyM p
-
--- | A shell complete function.
-newtype Completer = Completer
-  { runCompleter :: String -> IO [String] }
-
--- | Smart constructor for a 'Completer'
-mkCompleter :: (String -> IO [String]) -> Completer
-mkCompleter = Completer
-
-instance Semigroup Completer where
-  (Completer c1) <> (Completer c2) =
-    Completer $ \s -> (++) <$> c1 s <*> c2 s
-
-instance Monoid Completer where
-  mempty = Completer $ \_ -> return []
-  mappend = (<>)
-
-newtype CompletionResult = CompletionResult
-  { execCompletion :: String -> IO String }
-
-instance Show CompletionResult where
-  showsPrec p _ = showParen (p > 10) $
-    showString "CompletionResult _"
-
-newtype ParserFailure h = ParserFailure
-  { execFailure :: String -> (h, ExitCode, Int) }
-
-instance Show h => Show (ParserFailure h) where
-  showsPrec p (ParserFailure f)
-    = showParen (p > 10)
-    $ showString "ParserFailure "
-    . showsPrec 11 (f "<program>")
-
-instance Functor ParserFailure where
-  fmap f (ParserFailure err) = ParserFailure $ \progn ->
-    let (h, exit, cols) = err progn in (f h, exit, cols)
-
--- | Result of 'execParserPure'.
-data ParserResult a
-  = Success a
-  | Failure (ParserFailure ParserHelp)
-  | CompletionInvoked CompletionResult
-  deriving Show
-
-instance Functor ParserResult where
-  fmap f (Success a) = Success (f a)
-  fmap _ (Failure f) = Failure f
-  fmap _ (CompletionInvoked c) = CompletionInvoked c
-
-overFailure :: (ParserHelp -> ParserHelp)
-            -> ParserResult a -> ParserResult a
-overFailure f (Failure failure) = Failure $ fmap f failure
-overFailure _ r = r
-
-instance Applicative ParserResult where
-  pure = Success
-  Success f <*> r = fmap f r
-  Failure f <*> _ = Failure f
-  CompletionInvoked c <*> _ = CompletionInvoked c
-
-instance Monad ParserResult where
-  return = pure
-  Success x >>= f = f x
-  Failure f >>= _ = Failure f
-  CompletionInvoked c >>= _ = CompletionInvoked c
-
-type Args = [String]
-
--- | Policy for how to handle options within the parse
-data ArgPolicy
-  = Intersperse
-  -- ^ The default policy, options and arguments can
-  --   be interspersed.
-  --   A `--` option can be passed to ensure all following
-  --   commands are treated as arguments.
-  | NoIntersperse
-  -- ^ Options must all come before arguments, once a
-  --   single positional argument or subcommand is parsed,
-  --   all remaining arguments are treated as positionals.
-  --   A `--` option can be passed if the first positional
-  --   one needs starts with `-`.
-  | AllPositionals
-  -- ^ No options are parsed at all, all arguments are
-  --   treated as positionals.
-  --   Is the policy used after `--` is encountered.
-  | ForwardOptions
-  -- ^ Options and arguments can be interspersed, but if
-  --   a given option is not found, it is treated as a
-  --   positional argument. This is sometimes useful if
-  --   one is passing through most options to another tool,
-  --   but are supplying just a few of their own options.
-  deriving (Eq, Ord, Show)
-
-data OptHelpInfo = OptHelpInfo
-  { hinfoMulti :: Bool    -- ^ Whether this is part of a many or some (approximately)
-  , hinfoDefault :: Bool  -- ^ Whether this option has a default value
-  , hinfoUnreachableArgs :: Bool -- ^ If the result is a positional, if it can't be
-                                 --   accessed in the current parser position ( first arg )
-  } deriving (Eq, Show)
-
-data OptTree a
-  = Leaf a
-  | MultNode [OptTree a]
-  | AltNode [OptTree a]
-  deriving Show
-
-optVisibility :: Option a -> OptVisibility
-optVisibility = propVisibility . optProps
-
-optHelp :: Option a -> Chunk Doc
-optHelp  = propHelp . optProps
-
-optMetaVar :: Option a -> String
-optMetaVar = propMetaVar . optProps
-
-optShowDefault :: Option a -> Maybe String
-optShowDefault = propShowDefault . optProps
-
-optDescMod :: Option a -> Maybe ( Doc -> Doc )
-optDescMod = propDescMod . optProps
diff --git a/optparse-applicative.cabal b/optparse-applicative.cabal
--- a/optparse-applicative.cabal
+++ b/optparse-applicative.cabal
@@ -1,5 +1,5 @@
 name:                optparse-applicative
-version:             0.14.3.0
+version:             0.15.0.0
 synopsis:            Utilities and combinators for parsing command line options
 description:
     optparse-applicative is a haskell library for parsing options
@@ -34,23 +34,41 @@
                      tests/hello.err.txt
                      tests/helponempty.err.txt
                      tests/helponemptysub.err.txt
+                     tests/long_equals.err.txt
                      tests/formatting.err.txt
                      tests/nested.err.txt
+                     tests/optional.err.txt
+                     tests/nested_optional.err.txt
                      tests/subparsers.err.txt
 
 homepage:            https://github.com/pcapriotti/optparse-applicative
 bug-reports:         https://github.com/pcapriotti/optparse-applicative/issues
+tested-with:
+  GHC==7.0.4,
+  GHC==7.2.2,
+  GHC==7.4.2,
+  GHC==7.6.3,
+  GHC==7.8.4,
+  GHC==7.10.3,
+  GHC==8.0.2,
+  GHC==8.2.2,
+  GHC==8.4.4,
+  GHC==8.6.5,
+  GHC==8.8.1
 
 source-repository head
   type:     git
   location: https://github.com/pcapriotti/optparse-applicative.git
 
 library
+  hs-source-dirs:      src
   ghc-options:         -Wall
 
   -- See https://ghc.haskell.org/trac/ghc/wiki/Migration/8.0#base-4.9.0.0
   if impl(ghc >= 8.0)
-    ghc-options:  -Wno-redundant-constraints -Wcompat -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances
+    ghc-options:  -Wno-redundant-constraints -Wcompat -Wnoncanonical-monad-instances
+    if impl(ghc < 8.8)
+      ghc-options: -Wnoncanonical-monadfail-instances
 
   exposed-modules:     Options.Applicative
                      , Options.Applicative.Arrows
@@ -73,13 +91,13 @@
                      , transformers                    >= 0.2 && < 0.6
                      , transformers-compat             >= 0.3 && < 0.7
                      , process                         >= 1.0 && < 1.7
-                     , ansi-wl-pprint                  >= 0.6.6 && < 0.7
+                     , ansi-wl-pprint                  >= 0.6.8 && < 0.7
 
   if !impl(ghc >= 8)
-    build-depends:     semigroups                      >= 0.10 && < 0.19
+    build-depends:     semigroups                      >= 0.10 && < 0.20
                      , fail                            == 4.9.*
 
-test-suite optparse-applicative-tests
+test-suite tests
   type:                exitcode-stdio-1.0
 
   main-is:             test.hs
@@ -96,9 +114,9 @@
                      , Examples.Hello
 
   build-depends:       base
-                     , bytestring                      == 0.10.*
+                     , bytestring                      >= 0.9 && < 0.11
                      , optparse-applicative
-                     , QuickCheck                      >= 2.8 && < 2.13
+                     , QuickCheck                      >= 2.8 && < 2.14
 
   if !impl(ghc >= 8)
     build-depends:     semigroups
diff --git a/src/Options/Applicative.hs b/src/Options/Applicative.hs
new file mode 100644
--- /dev/null
+++ b/src/Options/Applicative.hs
@@ -0,0 +1,235 @@
+module Options.Applicative (
+  -- * Applicative option parsers
+  --
+  -- | This module exports all one should need for defining and using
+  -- optparse-applicative command line option parsers.
+  --
+  -- See <https://github.com/pcapriotti/optparse-applicative> for a tutorial,
+  -- and a general introduction to applicative option parsers.
+  --
+  -- See the sections below for more detail
+
+  -- * Exported modules
+  --
+  -- | The standard @Applicative@ module is re-exported here for convenience.
+  module Control.Applicative,
+
+  -- * Option Parsers
+  --
+  -- | A 'Parser' is the core type in optparse-applicative. A value of type
+  -- @Parser a@ represents a specification for a set of options, which will
+  -- yield a value of type a when the command line arguments are successfully
+  -- parsed.
+  --
+  -- There are several types of primitive 'Parser'.
+  --
+  -- * Flags: simple no-argument options. When a flag is encountered on the
+  -- command line, its value is returned.
+  --
+  -- * Options: options with an argument. An option can define a /reader/,
+  -- which converts its argument from String to the desired value, or throws a
+  -- parse error if the argument does not validate correctly.
+  --
+  -- * Arguments: positional arguments, validated in the same way as option
+  -- arguments.
+  --
+  -- * Commands. A command defines a completely independent sub-parser. When a
+  -- command is encountered, the whole command line is passed to the
+  -- corresponding parser.
+  --
+  -- See the "Parser Builders" section for how to construct and customise
+  -- these parsers.
+  Parser,
+
+  -- ** Parser builders
+  --
+  -- | This section contains utility functions and combinators to create parsers
+  -- for individual options.
+  --
+  -- Each parser builder takes an option modifier. A modifier can be created by
+  -- composing the basic modifiers provided by here using the 'Monoid' operations
+  -- 'mempty' and 'mappend', or their aliases 'idm' and '<>'.
+  --
+  -- For example:
+  --
+  -- > out = strOption
+  -- >     ( long "output"
+  -- >    <> short 'o'
+  -- >    <> metavar "FILENAME" )
+  --
+  -- creates a parser for an option called \"output\".
+  flag,
+  flag',
+  switch,
+
+  strOption,
+  option,
+
+  strArgument,
+  argument,
+
+  subparser,
+  hsubparser,
+
+  abortOption,
+  infoOption,
+  helper,
+
+  -- ** Modifiers
+  --
+  -- | 'Parser' builders take a modifier, which represents a modification of the
+  -- properties of an option, and can be composed as a monoid.
+  --
+  -- Contraints are often used to ensure that the modifiers can be sensibly applied.
+  -- For example, positional arguments can't be specified by long or short names,
+  -- so the 'HasName' constraint is used to ensure we have a flag or option.
+  Mod,
+
+  short,
+  long,
+  help,
+  helpDoc,
+  value,
+  showDefaultWith,
+  showDefault,
+  metavar,
+  noArgError,
+  hidden,
+  internal,
+  style,
+  command,
+  commandGroup,
+  completeWith,
+  action,
+  completer,
+  idm,
+  mappend,
+
+  OptionFields,
+  FlagFields,
+  ArgumentFields,
+  CommandFields,
+
+  HasName,
+  HasCompleter,
+  HasValue,
+  HasMetavar,
+  -- ** Readers
+  --
+  -- | A reader is used by the 'option' and 'argument' builders to parse
+  -- the data passed by the user on the command line into a data type.
+  --
+  -- The most common are 'str' which is used for 'String' like types,
+  -- including 'ByteString' and 'Text'; and 'auto', which uses the 'Read'
+  -- typeclass, and is good for simple types like 'Int' or 'Double'.
+  --
+  -- More complex types can use the 'eitherReader' or 'maybeReader'
+  -- functions to pattern match or use a more expressive parser like a
+  -- member of the 'Parsec' family.
+  ReadM,
+
+  auto,
+  str,
+  maybeReader,
+  eitherReader,
+  disabled,
+  readerAbort,
+  readerError,
+
+  -- * Program descriptions
+  --
+  -- ** 'ParserInfo'
+  --
+  -- | A 'ParserInfo' describes a command line program, used to generate a help
+  -- screen. Two help modes are supported: brief and full. In brief mode, only
+  -- an option and argument summary is displayed, while in full mode each
+  -- available option and command, including hidden ones, is described.
+  --
+  -- A 'ParserInfo' should be created with the 'info' function and a set of
+  -- 'InfoMod' modifiers.
+  --
+  info,
+
+  ParserInfo(..),
+
+  InfoMod,
+  fullDesc,
+  briefDesc,
+  header,
+  headerDoc,
+  footer,
+  footerDoc,
+  progDesc,
+  progDescDoc,
+  failureCode,
+  noIntersperse,
+  forwardOptions,
+
+  -- * Running parsers
+  --
+  -- | The execParser family of functions are used to run parsers
+  execParser,
+  customExecParser,
+  execParserPure,
+
+  -- ** Handling parser results manually
+  getParseResult,
+  handleParseResult,
+  parserFailure,
+  renderFailure,
+  overFailure,
+
+  -- ** 'ParserPrefs'
+  --
+  -- | A 'ParserPrefs' contains general preferences for all command-line
+  -- options, and should be built with the 'prefs' function.
+  prefs,
+
+  ParserPrefs(..),
+
+  PrefsMod,
+  multiSuffix,
+  disambiguate,
+  showHelpOnError,
+  showHelpOnEmpty,
+  noBacktrack,
+  subparserInline,
+  columns,
+  helpLongEquals,
+  defaultPrefs,
+
+  -- * Completions
+  --
+  -- | optparse-applicative supplies a rich completion system for bash,
+  -- zsh, and fish shells.
+  --
+  -- 'Completer' functions are used for option and argument to complete
+  -- their values.
+  --
+  -- Use the 'completer' builder to use these.
+  -- The 'action' and 'completeWith' builders are also provided for
+  -- convenience, to use 'bashCompleter' and 'listCompleter' as a 'Mod'.
+  Completer,
+  mkCompleter,
+  listIOCompleter,
+
+  listCompleter,
+  bashCompleter,
+
+  -- * Types
+  ParseError(..),
+  ParserHelp(..),
+  ParserFailure(..),
+  ParserResult(..),
+  CompletionResult(..)
+
+  ) where
+
+-- reexport Applicative here for convenience
+import Control.Applicative
+
+import Options.Applicative.Common
+import Options.Applicative.Builder
+import Options.Applicative.Builder.Completer
+import Options.Applicative.Extra
+import Options.Applicative.Types
diff --git a/src/Options/Applicative/Arrows.hs b/src/Options/Applicative/Arrows.hs
new file mode 100644
--- /dev/null
+++ b/src/Options/Applicative/Arrows.hs
@@ -0,0 +1,75 @@
+-- | This module contains an arrow interface for option parsers, which allows
+-- to define and combine parsers using the arrow notation and arrow
+-- combinators.
+--
+-- The arrow syntax is particularly useful to create parsers of nested
+-- structures, or records where the order of fields is different from the order
+-- in which the parsers should be applied.
+--
+-- For example, an 'Options.Applicative.Builder.arguments` parser often needs
+-- to be applied last, and that makes it inconvenient to use it for a field
+-- which is not the last one in a record.
+--
+-- Using the arrow syntax and the functions in this module, one can write, e.g.:
+--
+-- > data Options = Options
+-- >   { optArgs :: [String]
+-- >   , optVerbose :: Bool }
+-- >
+-- > opts :: Parser Options
+-- > opts = runA $ proc () -> do
+-- >   verbose <- asA (switch (short 'v')) -< ()
+-- >   args <- asA (arguments str idm) -< ()
+-- >   returnA -< Options args verbose
+--
+-- Parser arrows, created out of regular 'Parser' values using the 'asA'
+-- function, are arrows taking @()@ as argument and returning the parsed value.
+module Options.Applicative.Arrows (
+  module Control.Arrow,
+  A(..),
+  asA,
+  runA,
+  ParserA,
+  ) where
+
+import Control.Arrow
+import Control.Category (Category(..))
+
+import Options.Applicative
+
+import Prelude hiding ((.), id)
+
+-- | For any 'Applicative' functor @f@, @A f@ is the 'Arrow' instance
+-- associated to @f@.
+--
+-- The 'A' constructor can be used to convert a value of type @f (a -> b)@ into
+-- an arrow.
+newtype A f a b = A
+  { unA :: f (a -> b) }
+
+-- | Convert a value of type @f a@ into an arrow taking @()@ as argument.
+--
+-- Applied to a value of type 'Parser', it turns it into an arrow that can be
+-- used inside an arrow command, or passed to arrow combinators.
+asA :: Applicative f => f a -> A f () a
+asA x = A $ const <$> x
+
+-- | Convert an arrow back to an applicative value.
+--
+-- This function can be used to return a result of type 'Parser' from an arrow
+-- command.
+runA :: Applicative f => A f () a -> f a
+runA a = unA a <*> pure ()
+
+instance Applicative f => Category (A f) where
+  id = A $ pure id
+  -- use reverse composition, because we want effects to run from
+  -- top to bottom in the arrow syntax
+  (A f) . (A g) = A $ flip (.) <$> g <*> f
+
+instance Applicative f => Arrow (A f) where
+  arr = A . pure
+  first (A f) = A $ first <$> f
+
+-- | The type of arrows associated to the applicative 'Parser' functor.
+type ParserA = A Parser
diff --git a/src/Options/Applicative/BashCompletion.hs b/src/Options/Applicative/BashCompletion.hs
new file mode 100644
--- /dev/null
+++ b/src/Options/Applicative/BashCompletion.hs
@@ -0,0 +1,256 @@
+-- | You don't need to import this module to enable bash completion.
+--
+-- See
+-- <http://github.com/pcapriotti/optparse-applicative/wiki/Bash-Completion the wiki>
+-- for more information on bash completion.
+module Options.Applicative.BashCompletion
+  ( bashCompletionParser
+  ) where
+
+import Control.Applicative
+import Prelude
+import Data.Foldable ( asum )
+import Data.List ( isPrefixOf )
+import Data.Maybe ( fromMaybe, listToMaybe )
+
+import Options.Applicative.Builder
+import Options.Applicative.Common
+import Options.Applicative.Internal
+import Options.Applicative.Types
+import Options.Applicative.Help.Pretty
+import Options.Applicative.Help.Chunk
+
+-- | Provide basic or rich command completions
+data Richness
+  = Standard
+  -- ^ Add no help descriptions to the completions
+  | Enriched Int Int
+  -- ^ Include tab separated description for options
+  --   and commands when available.
+  --   Takes option description length and command
+  --   description length.
+  deriving (Eq, Ord, Show)
+
+bashCompletionParser :: ParserInfo a -> ParserPrefs -> Parser CompletionResult
+bashCompletionParser pinfo pprefs = complParser
+  where
+    failure opts = CompletionResult
+      { execCompletion = \progn -> unlines <$> opts progn }
+
+    complParser = asum
+      [ failure <$>
+        (  bashCompletionQuery pinfo pprefs
+        -- To get rich completions, one just needs the first
+        -- command. To customise the lengths, use either of
+        -- the `desc-length` options.
+        -- zsh commands can go on a single line, so they might
+        -- want to be longer.
+        <$> ( flag' Enriched (long "bash-completion-enriched" `mappend` internal)
+                <*> option auto (long "bash-completion-option-desc-length" `mappend` internal `mappend` value 40)
+                <*> option auto (long "bash-completion-command-desc-length" `mappend` internal `mappend` value 40)
+          <|> pure Standard
+          )
+        <*> (many . strOption) (long "bash-completion-word"
+                                  `mappend` internal)
+        <*> option auto (long "bash-completion-index" `mappend` internal) )
+      , failure <$>
+          (bashCompletionScript <$>
+            strOption (long "bash-completion-script" `mappend` internal))
+      , failure <$>
+          (fishCompletionScript <$>
+            strOption (long "fish-completion-script" `mappend` internal))
+      , failure <$>
+          (zshCompletionScript <$>
+            strOption (long "zsh-completion-script" `mappend` internal))
+      ]
+
+bashCompletionQuery :: ParserInfo a -> ParserPrefs -> Richness -> [String] -> Int -> String -> IO [String]
+bashCompletionQuery pinfo pprefs richness ws i _ = case runCompletion compl pprefs of
+  Just (Left (SomeParser p, a))
+    -> list_options a p
+  Just (Right c)
+    -> run_completer c
+  Nothing
+    -> return []
+  where
+    compl = runParserInfo pinfo (drop 1 ws')
+
+    list_options a
+      = fmap concat
+      . sequence
+      . mapParser (opt_completions a)
+
+    --
+    -- Prior to 0.14 there was a subtle bug which would
+    -- mean that completions from positional arguments
+    -- further into the parse would be shown.
+    --
+    -- We therefore now check to see that
+    -- hinfoUnreachableArgs is off before running the
+    -- completion for position arguments.
+    --
+    -- For options and flags, ensure that the user
+    -- hasn't disabled them with `--`.
+    opt_completions argPolicy hinfo opt = case optMain opt of
+      OptReader ns _ _
+         | argPolicy /= AllPositionals
+        -> return . add_opt_help opt $ show_names ns
+         | otherwise
+        -> return []
+      FlagReader ns _
+         | argPolicy /= AllPositionals
+        -> return . add_opt_help opt $ show_names ns
+         | otherwise
+        -> return []
+      ArgReader rdr
+         | hinfoUnreachableArgs hinfo
+        -> return []
+         | otherwise
+        -> run_completer (crCompleter rdr)
+      CmdReader _ ns p
+         | hinfoUnreachableArgs hinfo
+        -> return []
+         | otherwise
+        -> return . add_cmd_help p $ filter_names ns
+
+    -- When doing enriched completions, add any help specified
+    -- to the completion variables (tab separated).
+    add_opt_help :: Functor f => Option a -> f String -> f String
+    add_opt_help opt = case richness of
+      Standard ->
+        id
+      Enriched len _ ->
+        fmap $ \o ->
+          let h = unChunk $ optHelp opt
+          in  maybe o (\h' -> o ++ "\t" ++ render_line len h') h
+
+    -- When doing enriched completions, add the command description
+    -- to the completion variables (tab separated).
+    add_cmd_help :: Functor f => (String -> Maybe (ParserInfo a)) -> f String -> f String
+    add_cmd_help p = case richness of
+      Standard ->
+        id
+      Enriched _ len ->
+        fmap $ \cmd ->
+          let h = p cmd >>= unChunk . infoProgDesc
+          in  maybe cmd (\h' -> cmd ++ "\t" ++ render_line len h') h
+
+    show_names :: [OptName] -> [String]
+    show_names = filter_names . map showOption
+
+    -- We only want to show a single line in the completion results description.
+    -- If there was a line break, it would come across as a different completion
+    -- possibility.
+    render_line :: Int -> Doc -> String
+    render_line len doc = case lines (displayS (renderPretty 1 len doc) "") of
+      [] -> ""
+      [x] -> x
+      x : _ -> x ++ "..."
+
+    filter_names :: [String] -> [String]
+    filter_names = filter is_completion
+
+    run_completer :: Completer -> IO [String]
+    run_completer c = runCompleter c (fromMaybe "" (listToMaybe ws''))
+
+    (ws', ws'') = splitAt i ws
+
+    is_completion :: String -> Bool
+    is_completion =
+      case ws'' of
+        w:_ -> isPrefixOf w
+        _ -> const True
+
+bashCompletionScript :: String -> String -> IO [String]
+bashCompletionScript prog progn = return
+  [ "_" ++ progn ++ "()"
+  , "{"
+  , "    local CMDLINE"
+  , "    local IFS=$'\\n'"
+  , "    CMDLINE=(--bash-completion-index $COMP_CWORD)"
+  , ""
+  , "    for arg in ${COMP_WORDS[@]}; do"
+  , "        CMDLINE=(${CMDLINE[@]} --bash-completion-word $arg)"
+  , "    done"
+  , ""
+  , "    COMPREPLY=( $(" ++ prog ++ " \"${CMDLINE[@]}\") )"
+  , "}"
+  , ""
+  , "complete -o filenames -F _" ++ progn ++ " " ++ progn ]
+
+{-
+/Note/: Fish Shell
+
+Derived from Drezil's post in #169.
+
+@
+commandline
+-c or --cut-at-cursor only print selection up until the current cursor position
+-o or --tokenize tokenize the selection and print one string-type token per line
+@
+
+We tokenize so that the call to count (and hence --bash-completion-index)
+gets the right number use cut-at-curstor to not bother sending anything
+after the cursor position, which allows for completion of the middle of
+words.
+
+Tab characters separate items from descriptions.
+-}
+fishCompletionScript :: String -> String -> IO [String]
+fishCompletionScript prog progn = return
+  [ " function _" ++ progn
+  , "    set -l cl (commandline --tokenize --current-process)"
+  , "    # Hack around fish issue #3934"
+  , "    set -l cn (commandline --tokenize --cut-at-cursor --current-process)"
+  , "    set -l cn (count $cn)"
+  , "    set -l tmpline --bash-completion-enriched --bash-completion-index $cn"
+  , "    for arg in $cl"
+  , "      set tmpline $tmpline --bash-completion-word $arg"
+  , "    end"
+  , "    for opt in (" ++ prog ++ " $tmpline)"
+  , "      if test -d $opt"
+  , "        echo -E \"$opt/\""
+  , "      else"
+  , "        echo -E \"$opt\""
+  , "      end"
+  , "    end"
+  , "end"
+  , ""
+  , "complete --no-files --command " ++ progn ++ " --arguments '(_"  ++ progn ++  ")'"
+  ]
+
+zshCompletionScript :: String -> String -> IO [String]
+zshCompletionScript prog progn = return
+  [ "#compdef " ++ progn
+  , ""
+  , "local request"
+  , "local completions"
+  , "local word"
+  , "local index=$((CURRENT - 1))"
+  , ""
+  , "request=(--bash-completion-enriched --bash-completion-index $index)"
+  , "for arg in ${words[@]}; do"
+  , "  request=(${request[@]} --bash-completion-word $arg)"
+  , "done"
+  , ""
+  , "IFS=$'\\n' completions=($( " ++ prog ++ " \"${request[@]}\" ))"
+  , ""
+  , "for word in $completions; do"
+  , "  local -a parts"
+  , ""
+  , "  # Split the line at a tab if there is one."
+  , "  IFS=$'\\t' parts=($( echo $word ))"
+  , ""
+  , "  if [[ -n $parts[2] ]]; then"
+  , "     if [[ $word[1] == \"-\" ]]; then"
+  , "       local desc=(\"$parts[1] ($parts[2])\")"
+  , "       compadd -d desc -- $parts[1]"
+  , "     else"
+  , "       local desc=($(print -f  \"%-019s -- %s\" $parts[1] $parts[2]))"
+  , "       compadd -l -d desc -- $parts[1]"
+  , "     fi"
+  , "  else"
+  , "    compadd -f -- $word"
+  , "  fi"
+  , "done"
+  ]
diff --git a/src/Options/Applicative/Builder.hs b/src/Options/Applicative/Builder.hs
new file mode 100644
--- /dev/null
+++ b/src/Options/Applicative/Builder.hs
@@ -0,0 +1,530 @@
+module Options.Applicative.Builder (
+  -- * Parser builders
+  --
+  -- | This module contains utility functions and combinators to create parsers
+  -- for individual options.
+  --
+  -- Each parser builder takes an option modifier. A modifier can be created by
+  -- composing the basic modifiers provided by this module using the 'Monoid'
+  -- operations 'mempty' and 'mappend', or their aliases 'idm' and '<>'.
+  --
+  -- For example:
+  --
+  -- > out = strOption
+  -- >     ( long "output"
+  -- >    <> short 'o'
+  -- >    <> metavar "FILENAME" )
+  --
+  -- creates a parser for an option called \"output\".
+  subparser,
+  strArgument,
+  argument,
+  flag,
+  flag',
+  switch,
+  abortOption,
+  infoOption,
+  strOption,
+  option,
+  nullOption,
+
+  -- * Modifiers
+  short,
+  long,
+  help,
+  helpDoc,
+  value,
+  showDefaultWith,
+  showDefault,
+  metavar,
+  noArgError,
+  ParseError(..),
+  hidden,
+  internal,
+  style,
+  command,
+  commandGroup,
+  completeWith,
+  action,
+  completer,
+  idm,
+  mappend,
+
+  -- * Readers
+  --
+  -- | A collection of basic 'Option' readers.
+  auto,
+  str,
+  maybeReader,
+  eitherReader,
+  disabled,
+  readerAbort,
+  readerError,
+
+  -- * Builder for 'ParserInfo'
+  InfoMod,
+  fullDesc,
+  briefDesc,
+  header,
+  headerDoc,
+  footer,
+  footerDoc,
+  progDesc,
+  progDescDoc,
+  failureCode,
+  noIntersperse,
+  forwardOptions,
+  info,
+
+  -- * Builder for 'ParserPrefs'
+  PrefsMod,
+  multiSuffix,
+  disambiguate,
+  showHelpOnError,
+  showHelpOnEmpty,
+  noBacktrack,
+  subparserInline,
+  columns,
+  helpLongEquals,
+  prefs,
+  defaultPrefs,
+
+  -- * Types
+  Mod,
+  ReadM,
+  OptionFields,
+  FlagFields,
+  ArgumentFields,
+  CommandFields,
+
+  HasName,
+  HasCompleter,
+  HasValue,
+  HasMetavar
+  ) where
+
+import Control.Applicative
+import Data.Semigroup hiding (option)
+import Data.String (fromString, IsString)
+
+import Options.Applicative.Builder.Completer
+import Options.Applicative.Builder.Internal
+import Options.Applicative.Common
+import Options.Applicative.Types
+import Options.Applicative.Help.Pretty
+import Options.Applicative.Help.Chunk
+
+-- Readers --
+
+-- | 'Option' reader based on the 'Read' type class.
+auto :: Read a => ReadM a
+auto = eitherReader $ \arg -> case reads arg of
+  [(r, "")] -> return r
+  _         -> Left $ "cannot parse value `" ++ arg ++ "'"
+
+-- | String 'Option' reader.
+--
+--   Polymorphic over the `IsString` type class since 0.14.
+str :: IsString s => ReadM s
+str = fromString <$> readerAsk
+
+-- | Convert a function producing an 'Either' into a reader.
+--
+-- As an example, one can create a ReadM from an attoparsec Parser
+-- easily with
+--
+-- > import qualified Data.Attoparsec.Text as A
+-- > import qualified Data.Text as T
+-- > attoparsecReader :: A.Parser a -> ReadM a
+-- > attoparsecReader p = eitherReader (A.parseOnly p . T.pack)
+eitherReader :: (String -> Either String a) -> ReadM a
+eitherReader f = readerAsk >>= either readerError return . f
+
+-- | Convert a function producing a 'Maybe' into a reader.
+maybeReader :: (String -> Maybe a) -> ReadM a
+maybeReader f = do
+  arg  <- readerAsk
+  maybe (readerError $ "cannot parse value `" ++ arg ++ "'") return . f $ arg
+
+-- | Null 'Option' reader. All arguments will fail validation.
+disabled :: ReadM a
+disabled = readerError "disabled option"
+
+-- modifiers --
+
+-- | Specify a short name for an option.
+short :: HasName f => Char -> Mod f a
+short = fieldMod . name . OptShort
+
+-- | Specify a long name for an option.
+long :: HasName f => String -> Mod f a
+long = fieldMod . name . OptLong
+
+-- | Specify a default value for an option.
+--
+-- /Note/: Because this modifier means the parser will never fail,
+-- do not use it with combinators such as 'some' or 'many', as
+-- these combinators continue until a failure occurs.
+-- Careless use will thus result in a hang.
+--
+-- To display the default value, combine with showDefault or
+-- showDefaultWith.
+value :: HasValue f => a -> Mod f a
+value x = Mod id (DefaultProp (Just x) Nothing) id
+
+-- | Specify a function to show the default value for an option.
+showDefaultWith :: (a -> String) -> Mod f a
+showDefaultWith s = Mod id (DefaultProp Nothing (Just s)) id
+
+-- | Show the default value for this option using its 'Show' instance.
+showDefault :: Show a => Mod f a
+showDefault = showDefaultWith show
+
+-- | Specify the help text for an option.
+help :: String -> Mod f a
+help s = optionMod $ \p -> p { propHelp = paragraph s }
+
+-- | Specify the help text for an option as a 'Text.PrettyPrint.ANSI.Leijen.Doc'
+-- value.
+helpDoc :: Maybe Doc -> Mod f a
+helpDoc doc = optionMod $ \p -> p { propHelp = Chunk doc }
+
+-- | Specify the error to display when no argument is provided to this option.
+noArgError :: ParseError -> Mod OptionFields a
+noArgError e = fieldMod $ \p -> p { optNoArgError = const e }
+
+-- | Specify a metavariable for the argument.
+--
+-- Metavariables have no effect on the actual parser, and only serve to specify
+-- the symbolic name for an argument to be displayed in the help text.
+metavar :: HasMetavar f => String -> Mod f a
+metavar var = optionMod $ \p -> p { propMetaVar = var }
+
+-- | Hide this option from the brief description.
+hidden :: Mod f a
+hidden = optionMod $ \p ->
+  p { propVisibility = min Hidden (propVisibility p) }
+
+-- | Apply a function to the option description in the usage text.
+--
+-- > import Options.Applicative.Help
+-- > flag' () (short 't' <> style bold)
+--
+-- /NOTE/: This builder is more flexible than its name and example
+-- allude. One of the motivating examples for its addition was to
+-- used `const` to completely replace the usage text of an option.
+style :: ( Doc -> Doc ) -> Mod f a
+style x = optionMod $ \p ->
+  p { propDescMod = Just x }
+
+-- | Add a command to a subparser option.
+--
+-- Suggested usage for multiple commands is to add them to a single subparser. e.g.
+--
+-- @
+-- sample :: Parser Sample
+-- sample = subparser
+--        ( command "hello"
+--          (info hello (progDesc "Print greeting"))
+--       <> command "goodbye"
+--          (info goodbye (progDesc "Say goodbye"))
+--        )
+-- @
+command :: String -> ParserInfo a -> Mod CommandFields a
+command cmd pinfo = fieldMod $ \p ->
+  p { cmdCommands = (cmd, pinfo) : cmdCommands p }
+
+-- | Add a description to a group of commands.
+--
+-- Advanced feature for separating logical groups of commands on the parse line.
+--
+-- If using the same `metavar` for each group of commands, it may yield a more
+-- attractive usage text combined with `hidden` for some groups.
+commandGroup :: String -> Mod CommandFields a
+commandGroup g = fieldMod $ \p ->
+  p { cmdGroup = Just g }
+
+-- | Add a list of possible completion values.
+completeWith :: HasCompleter f => [String] -> Mod f a
+completeWith = completer . listCompleter
+
+-- | Add a bash completion action. Common actions include @file@ and
+-- @directory@. See
+-- <http://www.gnu.org/software/bash/manual/html_node/Programmable-Completion-Builtins.html#Programmable-Completion-Builtins>
+-- for a complete list.
+action :: HasCompleter f => String -> Mod f a
+action = completer . bashCompleter
+
+-- | Add a completer to an argument.
+--
+-- A completer is a function String -> IO String which, given a partial
+-- argument, returns all possible completions for that argument.
+completer :: HasCompleter f => Completer -> Mod f a
+completer f = fieldMod $ modCompleter (`mappend` f)
+
+-- parsers --
+
+-- | Builder for a command parser. The 'command' modifier can be used to
+-- specify individual commands.
+subparser :: Mod CommandFields a -> Parser a
+subparser m = mkParser d g rdr
+  where
+    Mod _ d g = metavar "COMMAND" `mappend` m
+    (groupName, cmds, subs) = mkCommand m
+    rdr = CmdReader groupName cmds subs
+
+-- | Builder for an argument parser.
+argument :: ReadM a -> Mod ArgumentFields a -> Parser a
+argument p (Mod f d g) = mkParser d g (ArgReader rdr)
+  where
+    ArgumentFields compl = f (ArgumentFields mempty)
+    rdr = CReader compl p
+
+-- | Builder for a 'String' argument.
+strArgument :: IsString s => Mod ArgumentFields s -> Parser s
+strArgument = argument str
+
+-- | Builder for a flag parser.
+--
+-- A flag that switches from a \"default value\" to an \"active value\" when
+-- encountered. For a simple boolean value, use `switch` instead.
+--
+-- /Note/: Because this parser will never fail, it can not be used with
+-- combinators such as 'some' or 'many', as these combinators continue until
+-- a failure occurs. See @flag'@.
+flag :: a                         -- ^ default value
+     -> a                         -- ^ active value
+     -> Mod FlagFields a          -- ^ option modifier
+     -> Parser a
+flag defv actv m = flag' actv m <|> pure defv
+
+-- | Builder for a flag parser without a default value.
+--
+-- Same as 'flag', but with no default value. In particular, this flag will
+-- never parse successfully by itself.
+--
+-- It still makes sense to use it as part of a composite parser. For example
+--
+-- > length <$> many (flag' () (short 't'))
+--
+-- is a parser that counts the number of "-t" arguments on the command line,
+-- alternatively
+--
+-- > flag' True (long "on") <|> flag' False (long "off")
+--
+-- will require the user to enter '--on' or '--off' on the command line.
+flag' :: a                         -- ^ active value
+      -> Mod FlagFields a          -- ^ option modifier
+      -> Parser a
+flag' actv (Mod f d g) = mkParser d g rdr
+  where
+    rdr = let fields = f (FlagFields [] actv)
+          in FlagReader (flagNames fields)
+                        (flagActive fields)
+
+-- | Builder for a boolean flag.
+--
+-- /Note/: Because this parser will never fail, it can not be used with
+-- combinators such as 'some' or 'many', as these combinators continue until
+-- a failure occurs. See @flag'@.
+--
+-- > switch = flag False True
+switch :: Mod FlagFields Bool -> Parser Bool
+switch = flag False True
+
+-- | An option that always fails.
+--
+-- When this option is encountered, the option parser immediately aborts with
+-- the given parse error.  If you simply want to output a message, use
+-- 'infoOption' instead.
+abortOption :: ParseError -> Mod OptionFields (a -> a) -> Parser (a -> a)
+abortOption err m = option (readerAbort err) . (`mappend` m) $ mconcat
+  [ noArgError err
+  , value id
+  , metavar "" ]
+
+-- | An option that always fails and displays a message.
+infoOption :: String -> Mod OptionFields (a -> a) -> Parser (a -> a)
+infoOption = abortOption . InfoMsg
+
+-- | Builder for an option taking a 'String' argument.
+strOption :: IsString s => Mod OptionFields s -> Parser s
+strOption = option str
+
+-- | Same as 'option'.
+{-# DEPRECATED nullOption "Use 'option' instead" #-}
+nullOption :: ReadM a -> Mod OptionFields a -> Parser a
+nullOption = option
+
+-- | Builder for an option using the given reader.
+--
+-- This is a regular option, and should always have either a @long@ or
+-- @short@ name specified in the modifiers (or both).
+--
+-- > nameParser = option str ( long "name" <> short 'n' )
+--
+option :: ReadM a -> Mod OptionFields a -> Parser a
+option r m = mkParser d g rdr
+  where
+    Mod f d g = metavar "ARG" `mappend` m
+    fields = f (OptionFields [] mempty ExpectsArgError)
+    crdr = CReader (optCompleter fields) r
+    rdr = OptReader (optNames fields) crdr (optNoArgError fields)
+
+-- | Modifier for 'ParserInfo'.
+newtype InfoMod a = InfoMod
+  { applyInfoMod :: ParserInfo a -> ParserInfo a }
+
+instance Monoid (InfoMod a) where
+  mempty = InfoMod id
+  mappend = (<>)
+
+instance Semigroup (InfoMod a) where
+  m1 <> m2 = InfoMod $ applyInfoMod m2 . applyInfoMod m1
+
+-- | Show a full description in the help text of this parser.
+fullDesc :: InfoMod a
+fullDesc = InfoMod $ \i -> i { infoFullDesc = True }
+
+-- | Only show a brief description in the help text of this parser.
+briefDesc :: InfoMod a
+briefDesc = InfoMod $ \i -> i { infoFullDesc = False }
+
+-- | Specify a header for this parser.
+header :: String -> InfoMod a
+header s = InfoMod $ \i -> i { infoHeader = paragraph s }
+
+-- | Specify a header for this parser as a 'Text.PrettyPrint.ANSI.Leijen.Doc'
+-- value.
+headerDoc :: Maybe Doc -> InfoMod a
+headerDoc doc = InfoMod $ \i -> i { infoHeader = Chunk doc }
+
+-- | Specify a footer for this parser.
+footer :: String -> InfoMod a
+footer s = InfoMod $ \i -> i { infoFooter = paragraph s }
+
+-- | Specify a footer for this parser as a 'Text.PrettyPrint.ANSI.Leijen.Doc'
+-- value.
+footerDoc :: Maybe Doc -> InfoMod a
+footerDoc doc = InfoMod $ \i -> i { infoFooter = Chunk doc }
+
+-- | Specify a short program description.
+progDesc :: String -> InfoMod a
+progDesc s = InfoMod $ \i -> i { infoProgDesc = paragraph s }
+
+-- | Specify a short program description as a 'Text.PrettyPrint.ANSI.Leijen.Doc'
+-- value.
+progDescDoc :: Maybe Doc -> InfoMod a
+progDescDoc doc = InfoMod $ \i -> i { infoProgDesc = Chunk doc }
+
+-- | Specify an exit code if a parse error occurs.
+failureCode :: Int -> InfoMod a
+failureCode n = InfoMod $ \i -> i { infoFailureCode = n }
+
+-- | Disable parsing of regular options after arguments. After a positional
+--   argument is parsed, all remaining options and arguments will be treated
+--   as a positional arguments. Not recommended in general as users often
+--   expect to be able to freely intersperse regular options and flags within
+--   command line options.
+noIntersperse :: InfoMod a
+noIntersperse = InfoMod $ \p -> p { infoPolicy = NoIntersperse }
+
+-- | Intersperse matched options and arguments normally, but allow unmatched
+--   options to be treated as positional arguments.
+--   This is sometimes useful if one is wrapping a third party cli tool and
+--   needs to pass options through, while also providing a handful of their
+--   own options. Not recommended in general as typos by the user may not
+--   yield a parse error and cause confusion.
+forwardOptions :: InfoMod a
+forwardOptions = InfoMod $ \p -> p { infoPolicy = ForwardOptions }
+
+-- | Create a 'ParserInfo' given a 'Parser' and a modifier.
+info :: Parser a -> InfoMod a -> ParserInfo a
+info parser m = applyInfoMod m base
+  where
+    base = ParserInfo
+      { infoParser = parser
+      , infoFullDesc = True
+      , infoProgDesc = mempty
+      , infoHeader = mempty
+      , infoFooter = mempty
+      , infoFailureCode = 1
+      , infoPolicy = Intersperse }
+
+newtype PrefsMod = PrefsMod
+  { applyPrefsMod :: ParserPrefs -> ParserPrefs }
+
+instance Monoid PrefsMod where
+  mempty = PrefsMod id
+  mappend = (<>)
+
+instance Semigroup PrefsMod where
+  m1 <> m2 = PrefsMod $ applyPrefsMod m2 . applyPrefsMod m1
+
+-- | Include a suffix to attach to the metavar when multiple values
+--   can be entered.
+multiSuffix :: String -> PrefsMod
+multiSuffix s = PrefsMod $ \p -> p { prefMultiSuffix = s }
+
+-- | Turn on disambiguation.
+--
+--   See
+--   https://github.com/pcapriotti/optparse-applicative#disambiguation
+disambiguate :: PrefsMod
+disambiguate = PrefsMod $ \p -> p { prefDisambiguate = True }
+
+-- | Show full help text on any error.
+showHelpOnError :: PrefsMod
+showHelpOnError = PrefsMod $ \p -> p { prefShowHelpOnError = True }
+
+-- | Show the help text if the user enters only the program name or
+--   subcommand.
+--
+--   This will suppress a "Missing:" error and show the full usage
+--   instead if a user just types the name of the program.
+showHelpOnEmpty :: PrefsMod
+showHelpOnEmpty = PrefsMod $ \p -> p { prefShowHelpOnEmpty = True }
+
+-- | Turn off backtracking after subcommand is parsed.
+noBacktrack :: PrefsMod
+noBacktrack = PrefsMod $ \p -> p { prefBacktrack = NoBacktrack }
+
+-- | Allow full mixing of subcommand and parent arguments by inlining
+-- selected subparsers into the parent parser.
+--
+-- /NOTE:/ When this option is used, preferences for the subparser which
+-- effect the parser behaviour (such as noIntersperse) are ignored.
+subparserInline :: PrefsMod
+subparserInline = PrefsMod $ \p -> p { prefBacktrack = SubparserInline }
+
+-- | Set the maximum width of the generated help text.
+columns :: Int -> PrefsMod
+columns cols = PrefsMod $ \p -> p { prefColumns = cols }
+
+-- | Show equals sign, rather than space, in usage and help text for options with
+-- long names.
+helpLongEquals :: PrefsMod
+helpLongEquals = PrefsMod $ \p -> p { prefHelpLongEquals = True }
+
+-- | Create a `ParserPrefs` given a modifier
+prefs :: PrefsMod -> ParserPrefs
+prefs m = applyPrefsMod m base
+  where
+    base = ParserPrefs
+      { prefMultiSuffix = ""
+      , prefDisambiguate = False
+      , prefShowHelpOnError = False
+      , prefShowHelpOnEmpty = False
+      , prefBacktrack = Backtrack
+      , prefColumns = 80
+      , prefHelpLongEquals = False }
+
+-- Convenience shortcuts
+
+-- | Trivial option modifier.
+idm :: Monoid m => m
+idm = mempty
+
+-- | Default preferences.
+defaultPrefs :: ParserPrefs
+defaultPrefs = prefs idm
diff --git a/src/Options/Applicative/Builder/Completer.hs b/src/Options/Applicative/Builder/Completer.hs
new file mode 100644
--- /dev/null
+++ b/src/Options/Applicative/Builder/Completer.hs
@@ -0,0 +1,122 @@
+module Options.Applicative.Builder.Completer
+  ( Completer
+  , mkCompleter
+  , listIOCompleter
+  , listCompleter
+  , bashCompleter
+  ) where
+
+import Control.Applicative
+import Prelude
+import Control.Exception (IOException, try)
+import Data.List (isPrefixOf)
+import System.Process (readProcess)
+
+import Options.Applicative.Types
+
+-- | Create a 'Completer' from an IO action
+listIOCompleter :: IO [String] -> Completer
+listIOCompleter ss = Completer $ \s ->
+  filter (isPrefixOf s) <$> ss
+
+-- | Create a 'Completer' from a constant
+-- list of strings.
+listCompleter :: [String] -> Completer
+listCompleter = listIOCompleter . pure
+
+-- | Run a compgen completion action.
+--
+-- Common actions include @file@ and
+-- @directory@. See
+-- <http://www.gnu.org/software/bash/manual/html_node/Programmable-Completion-Builtins.html#Programmable-Completion-Builtins>
+-- for a complete list.
+bashCompleter :: String -> Completer
+bashCompleter action = Completer $ \word -> do
+  let cmd = unwords ["compgen", "-A", action, "--", requote word]
+  result <- tryIO $ readProcess "bash" ["-c", cmd] ""
+  return . lines . either (const []) id $ result
+
+tryIO :: IO a -> IO (Either IOException a)
+tryIO = try
+
+-- | Strongly quote the string we pass to compgen.
+--
+-- We need to do this so bash doesn't expand out any ~ or other
+-- chars we want to complete on, or emit an end of line error
+-- when seeking the close to the quote.
+requote :: String -> String
+requote s =
+  let
+    -- Bash doesn't appear to allow "mixed" escaping
+    -- in bash completions. So we don't have to really
+    -- worry about people swapping between strong and
+    -- weak quotes.
+    unescaped =
+      case s of
+        -- It's already strongly quoted, so we
+        -- can use it mostly as is, but we must
+        -- ensure it's closed off at the end and
+        -- there's no single quotes in the
+        -- middle which might confuse bash.
+        ('\'': rs) -> unescapeN rs
+
+        -- We're weakly quoted.
+        ('"': rs)  -> unescapeD rs
+
+        -- We're not quoted at all.
+        -- We need to unescape some characters like
+        -- spaces and quotation marks.
+        elsewise   -> unescapeU elsewise
+  in
+    strong unescaped
+
+  where
+    strong ss = '\'' : foldr go "'" ss
+      where
+        -- If there's a single quote inside the
+        -- command: exit from the strong quote and
+        -- emit it the quote escaped, then resume.
+        go '\'' t = "'\\''" ++ t
+        go h t    = h : t
+
+    -- Unescape a strongly quoted string
+    -- We have two recursive functions, as we
+    -- can enter and exit the strong escaping.
+    unescapeN = goX
+      where
+        goX ('\'' : xs) = goN xs
+        goX (x : xs) = x : goX xs
+        goX [] = []
+
+        goN ('\\' : '\'' : xs) = '\'' : goN xs
+        goN ('\'' : xs) = goX xs
+        goN (x : xs) = x : goN xs
+        goN [] = []
+
+    -- Unescape an unquoted string
+    unescapeU = goX
+      where
+        goX [] = []
+        goX ('\\' : x : xs) = x : goX xs
+        goX (x : xs) = x : goX xs
+
+    -- Unescape a weakly quoted string
+    unescapeD = goX
+      where
+        -- Reached an escape character
+        goX ('\\' : x : xs)
+          -- If it's true escapable, strip the
+          -- slashes, as we're going to strong
+          -- escape instead.
+          | x `elem` "$`\"\\\n" = x : goX xs
+          | otherwise = '\\' : x : goX xs
+        -- We've ended quoted section, so we
+        -- don't recurse on goX, it's done.
+        goX ('"' : xs)
+          = xs
+        -- Not done, but not a special character
+        -- just continue the fold.
+        goX (x : xs)
+          = x : goX xs
+        goX []
+          = []
diff --git a/src/Options/Applicative/Builder/Internal.hs b/src/Options/Applicative/Builder/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Options/Applicative/Builder/Internal.hs
@@ -0,0 +1,185 @@
+module Options.Applicative.Builder.Internal (
+  -- * Internals
+  Mod(..),
+  HasName(..),
+  HasCompleter(..),
+  HasValue(..),
+  HasMetavar(..),
+  OptionFields(..),
+  FlagFields(..),
+  CommandFields(..),
+  ArgumentFields(..),
+  DefaultProp(..),
+
+  optionMod,
+  fieldMod,
+
+  baseProps,
+  mkCommand,
+  mkParser,
+  mkOption,
+  mkProps,
+
+  internal
+  ) where
+
+import Control.Applicative
+import Control.Monad (mplus)
+import Data.Semigroup hiding (Option)
+import Prelude
+
+import Options.Applicative.Common
+import Options.Applicative.Types
+
+data OptionFields a = OptionFields
+  { optNames :: [OptName]
+  , optCompleter :: Completer
+  , optNoArgError :: String -> ParseError }
+
+data FlagFields a = FlagFields
+  { flagNames :: [OptName]
+  , flagActive :: a }
+
+data CommandFields a = CommandFields
+  { cmdCommands :: [(String, ParserInfo a)]
+  , cmdGroup :: Maybe String }
+
+data ArgumentFields a = ArgumentFields
+  { argCompleter :: Completer }
+
+class HasName f where
+  name :: OptName -> f a -> f a
+
+instance HasName OptionFields where
+  name n fields = fields { optNames = n : optNames fields }
+
+instance HasName FlagFields where
+  name n fields = fields { flagNames = n : flagNames fields }
+
+class HasCompleter f where
+  modCompleter :: (Completer -> Completer) -> f a -> f a
+
+instance HasCompleter OptionFields where
+  modCompleter f p = p { optCompleter = f (optCompleter p) }
+
+instance HasCompleter ArgumentFields where
+  modCompleter f p = p { argCompleter = f (argCompleter p) }
+
+class HasValue f where
+  -- this is just so that it is not necessary to specify the kind of f
+  hasValueDummy :: f a -> ()
+instance HasValue OptionFields where
+  hasValueDummy _ = ()
+instance HasValue ArgumentFields where
+  hasValueDummy _ = ()
+
+class HasMetavar f where
+  hasMetavarDummy :: f a -> ()
+instance HasMetavar OptionFields where
+  hasMetavarDummy _ = ()
+instance HasMetavar ArgumentFields where
+  hasMetavarDummy _ = ()
+instance HasMetavar CommandFields where
+  hasMetavarDummy _ = ()
+
+-- mod --
+
+data DefaultProp a = DefaultProp
+  (Maybe a)
+  (Maybe (a -> String))
+
+instance Monoid (DefaultProp a) where
+  mempty = DefaultProp Nothing Nothing
+  mappend = (<>)
+
+instance Semigroup (DefaultProp a) where
+  (DefaultProp d1 s1) <> (DefaultProp d2 s2) =
+    DefaultProp (d1 `mplus` d2) (s1 `mplus` s2)
+
+-- | An option modifier.
+--
+-- Option modifiers are values that represent a modification of the properties
+-- of an option.
+--
+-- The type parameter @a@ is the return type of the option, while @f@ is a
+-- record containing its properties (e.g. 'OptionFields' for regular options,
+-- 'FlagFields' for flags, etc...).
+--
+-- An option modifier consists of 3 elements:
+--
+--  - A field modifier, of the form @f a -> f a@. These are essentially
+--  (compositions of) setters for some of the properties supported by @f@.
+--
+--  - An optional default value and function to display it.
+--
+--  - A property modifier, of the form @OptProperties -> OptProperties@. This
+--  is just like the field modifier, but for properties applicable to any
+--  option.
+--
+-- Modifiers are instances of 'Monoid', and can be composed as such.
+--
+-- One rarely needs to deal with modifiers directly, as most of the times it is
+-- sufficient to pass them to builders (such as 'strOption' or 'flag') to
+-- create options (see 'Options.Applicative.Builder').
+data Mod f a = Mod (f a -> f a)
+                   (DefaultProp a)
+                   (OptProperties -> OptProperties)
+
+optionMod :: (OptProperties -> OptProperties) -> Mod f a
+optionMod = Mod id mempty
+
+fieldMod :: (f a -> f a) -> Mod f a
+fieldMod f = Mod f mempty id
+
+instance Monoid (Mod f a) where
+  mempty = Mod id mempty id
+  mappend = (<>)
+
+-- | @since 0.13.0.0
+instance Semigroup (Mod f a) where
+  Mod f1 d1 g1 <> Mod f2 d2 g2
+    = Mod (f2 . f1) (d2 <> d1) (g2 . g1)
+
+-- | Base default properties.
+baseProps :: OptProperties
+baseProps = OptProperties
+  { propMetaVar = ""
+  , propVisibility = Visible
+  , propHelp = mempty
+  , propShowDefault = Nothing
+  , propDescMod = Nothing
+  }
+
+mkCommand :: Mod CommandFields a -> (Maybe String, [String], String -> Maybe (ParserInfo a))
+mkCommand m = (group, map fst cmds, (`lookup` cmds))
+  where
+    Mod f _ _ = m
+    CommandFields cmds group = f (CommandFields [] Nothing)
+
+mkParser :: DefaultProp a
+         -> (OptProperties -> OptProperties)
+         -> OptReader a
+         -> Parser a
+mkParser d@(DefaultProp def _) g rdr =
+  let
+    o = liftOpt $ mkOption d g rdr
+  in
+    maybe o (\a -> o <|> pure a) def
+
+mkOption :: DefaultProp a
+         -> (OptProperties -> OptProperties)
+         -> OptReader a
+         -> Option a
+mkOption d g rdr = Option rdr (mkProps d g)
+
+mkProps :: DefaultProp a
+        -> (OptProperties -> OptProperties)
+        -> OptProperties
+mkProps (DefaultProp def sdef) g = props
+  where
+    props = (g baseProps)
+      { propShowDefault = sdef <*> def }
+
+-- | Hide this option from the help text
+internal :: Mod f a
+internal = optionMod $ \p -> p { propVisibility = Internal }
diff --git a/src/Options/Applicative/Common.hs b/src/Options/Applicative/Common.hs
new file mode 100644
--- /dev/null
+++ b/src/Options/Applicative/Common.hs
@@ -0,0 +1,314 @@
+{-# LANGUAGE Rank2Types #-}
+module Options.Applicative.Common (
+  -- * Option parsers
+  --
+  -- | A 'Parser' is composed of a list of options. Several kinds of options
+  -- are supported:
+  --
+  --  * Flags: simple no-argument options. When a flag is encountered on the
+  --  command line, its value is returned.
+  --
+  --  * Options: options with an argument. An option can define a /reader/,
+  --  which converts its argument from String to the desired value, or throws a
+  --  parse error if the argument does not validate correctly.
+  --
+  --  * Arguments: positional arguments, validated in the same way as option
+  --  arguments.
+  --
+  --  * Commands. A command defines a completely independent sub-parser. When a
+  --  command is encountered, the whole command line is passed to the
+  --  corresponding parser.
+  --
+  Parser,
+  liftOpt,
+  showOption,
+
+  -- * Program descriptions
+  --
+  -- A 'ParserInfo' describes a command line program, used to generate a help
+  -- screen. Two help modes are supported: brief and full. In brief mode, only
+  -- an option and argument summary is displayed, while in full mode each
+  -- available option and command, including hidden ones, is described.
+  --
+  -- A basic 'ParserInfo' with default values for fields can be created using
+  -- the 'info' function.
+  --
+  -- A 'ParserPrefs' contains general preferences for all command-line
+  -- options, and can be built with the 'prefs' function.
+  ParserInfo(..),
+  ParserPrefs(..),
+
+  -- * Running parsers
+  runParserInfo,
+  runParserFully,
+  runParser,
+  evalParser,
+
+  -- * Low-level utilities
+  mapParser,
+  treeMapParser,
+  optionNames
+  ) where
+
+import Control.Applicative
+import Control.Monad (guard, mzero, msum, when)
+import Control.Monad.Trans.Class (lift)
+import Control.Monad.Trans.State (StateT(..), get, put, runStateT)
+import Data.List (isPrefixOf)
+import Data.Maybe (maybeToList, isJust, isNothing)
+import Prelude
+
+import Options.Applicative.Internal
+import Options.Applicative.Types
+
+showOption :: OptName -> String
+showOption (OptLong n) = "--" ++ n
+showOption (OptShort n) = '-' : [n]
+
+optionNames :: OptReader a -> [OptName]
+optionNames (OptReader names _ _) = names
+optionNames (FlagReader names _) = names
+optionNames _ = []
+
+isOptionPrefix :: OptName -> OptName -> Bool
+isOptionPrefix (OptShort x) (OptShort y) = x == y
+isOptionPrefix (OptLong x) (OptLong y) = x `isPrefixOf` y
+isOptionPrefix _ _ = False
+
+-- | Create a parser composed of a single option.
+liftOpt :: Option a -> Parser a
+liftOpt = OptP
+
+optMatches :: MonadP m => Bool -> OptReader a -> OptWord -> Maybe (StateT Args m a)
+optMatches disambiguate opt (OptWord arg1 val) = case opt of
+  OptReader names rdr no_arg_err -> do
+    guard $ has_name arg1 names
+    Just $ do
+      args <- get
+      let mb_args = uncons $ maybeToList val ++ args
+      let missing_arg = missingArgP (no_arg_err $ showOption arg1) (crCompleter rdr)
+      (arg', args') <- maybe (lift missing_arg) return mb_args
+      put args'
+      lift $ runReadM (withReadM (errorFor arg1) (crReader rdr)) arg'
+
+  FlagReader names x -> do
+    guard $ has_name arg1 names
+    -- #242 Flags/switches succeed incorrectly when given an argument.
+    -- We'll not match a long option for a flag if there's a word attached.
+    -- This was revealing an implementation detail as
+    -- `--foo=val` was being parsed as `--foo -val`, which is gibberish.
+    guard $ isShortName arg1 || isNothing val
+    Just $ do
+      args <- get
+      let val' = ('-' :) <$> val
+      put $ maybeToList val' ++ args
+      return x
+  _ -> Nothing
+  where
+    errorFor name msg = "option " ++ showOption name ++ ": " ++ msg
+
+    has_name a
+      | disambiguate = any (isOptionPrefix a)
+      | otherwise = elem a
+
+isArg :: OptReader a -> Bool
+isArg (ArgReader _) = True
+isArg _ = False
+
+data OptWord = OptWord OptName (Maybe String)
+
+parseWord :: String -> Maybe OptWord
+parseWord ('-' : '-' : w) = Just $ let
+  (opt, arg) = case span (/= '=') w of
+    (_, "") -> (w, Nothing)
+    (w', _ : rest) -> (w', Just rest)
+  in OptWord (OptLong opt) arg
+parseWord ('-' : w) = case w of
+  [] -> Nothing
+  (a : rest) -> Just $ let
+    arg = rest <$ guard (not (null rest))
+    in OptWord (OptShort a) arg
+parseWord _ = Nothing
+
+searchParser :: Monad m
+             => (forall r . Option r -> NondetT m (Parser r))
+             -> Parser a -> NondetT m (Parser a)
+searchParser _ (NilP _) = mzero
+searchParser f (OptP opt) = f opt
+searchParser f (MultP p1 p2) = foldr1 (<!>)
+  [ do p1' <- searchParser f p1
+       return (p1' <*> p2)
+  , do p2' <- searchParser f p2
+       return (p1 <*> p2') ]
+searchParser f (AltP p1 p2) = msum
+  [ searchParser f p1
+  , searchParser f p2 ]
+searchParser f (BindP p k) = msum
+  [ do p' <- searchParser f p
+       return $ BindP p' k
+  , case evalParser p of
+      Nothing -> mzero
+      Just aa -> searchParser f (k aa) ]
+
+searchOpt :: MonadP m => ParserPrefs -> OptWord -> Parser a
+          -> NondetT (StateT Args m) (Parser a)
+searchOpt pprefs w = searchParser $ \opt -> do
+  let disambiguate = prefDisambiguate pprefs
+                  && optVisibility opt > Internal
+  case optMatches disambiguate (optMain opt) w of
+    Just matcher -> lift $ fmap pure matcher
+    Nothing -> mzero
+
+searchArg :: MonadP m => ParserPrefs -> String -> Parser a
+          -> NondetT (StateT Args m) (Parser a)
+searchArg prefs arg = searchParser $ \opt -> do
+  when (isArg (optMain opt)) cut
+  case optMain opt of
+    CmdReader _ _ f ->
+      case (f arg, prefBacktrack prefs) of
+        (Just subp, NoBacktrack) -> lift $ do
+          args <- get <* put []
+          fmap pure . lift $ enterContext arg subp *> runParserInfo subp args <* exitContext
+
+        (Just subp, Backtrack) -> fmap pure . lift . StateT $ \args ->
+          enterContext arg subp *> runParser (infoPolicy subp) CmdStart (infoParser subp) args <* exitContext
+
+        (Just subp, SubparserInline) -> lift $ do
+          lift $ enterContext arg subp
+          return $ infoParser subp
+
+        (Nothing, _)  -> mzero
+    ArgReader rdr ->
+      fmap pure . lift . lift $ runReadM (crReader rdr) arg
+    _ -> mzero
+
+stepParser :: MonadP m => ParserPrefs -> ArgPolicy -> String
+           -> Parser a -> NondetT (StateT Args m) (Parser a)
+stepParser pprefs AllPositionals arg p =
+  searchArg pprefs arg p
+stepParser pprefs ForwardOptions arg p = case parseWord arg of
+  Just w -> searchOpt pprefs w p <|> searchArg pprefs arg p
+  Nothing -> searchArg pprefs arg p
+stepParser pprefs _ arg p = case parseWord arg of
+  Just w -> searchOpt pprefs w p
+  Nothing -> searchArg pprefs arg p
+
+
+-- | Apply a 'Parser' to a command line, and return a result and leftover
+-- arguments.  This function returns an error if any parsing error occurs, or
+-- if any options are missing and don't have a default value.
+runParser :: MonadP m => ArgPolicy -> IsCmdStart -> Parser a -> Args -> m (a, Args)
+runParser policy _ p ("--" : argt) | policy /= AllPositionals
+                                   = runParser AllPositionals CmdCont p argt
+runParser policy isCmdStart p args = case args of
+  [] -> exitP isCmdStart policy p result
+  (arg : argt) -> do
+    prefs <- getPrefs
+    (mp', args') <- do_step prefs arg argt
+    case mp' of
+      Nothing -> hoistMaybe result <|> parseError arg p
+      Just p' -> runParser (newPolicy arg) CmdCont p' args'
+  where
+    result = (,) <$> evalParser p <*> pure args
+    do_step prefs arg argt = (`runStateT` argt)
+                           . disamb (not (prefDisambiguate prefs))
+                           $ stepParser prefs policy arg p
+
+    newPolicy a = case policy of
+      NoIntersperse -> if isJust (parseWord a) then NoIntersperse else AllPositionals
+      x             -> x
+
+parseError :: MonadP m => String -> Parser x -> m a
+parseError arg = errorP . UnexpectedError arg . SomeParser
+
+runParserInfo :: MonadP m => ParserInfo a -> Args -> m a
+runParserInfo i = runParserFully (infoPolicy i) (infoParser i)
+
+runParserFully :: MonadP m => ArgPolicy -> Parser a -> Args -> m a
+runParserFully policy p args = do
+  (r, args') <- runParser policy CmdStart p args
+  case args' of
+    []  -> return r
+    a:_ -> parseError a (pure ())
+
+-- | The default value of a 'Parser'.  This function returns an error if any of
+-- the options don't have a default value.
+evalParser :: Parser a -> Maybe a
+evalParser (NilP r) = r
+evalParser (OptP _) = Nothing
+evalParser (MultP p1 p2) = evalParser p1 <*> evalParser p2
+evalParser (AltP p1 p2) = evalParser p1 <|> evalParser p2
+evalParser (BindP p k) = evalParser p >>= evalParser . k
+
+-- | Map a polymorphic function over all the options of a parser, and collect
+-- the results in a list.
+mapParser :: (forall x. OptHelpInfo -> Option x -> b)
+          -> Parser a -> [b]
+mapParser f = flatten . treeMapParser f
+  where
+    flatten (Leaf x) = [x]
+    flatten (MultNode xs) = xs >>= flatten
+    flatten (AltNode _ xs) = xs >>= flatten
+
+-- | Like 'mapParser', but collect the results in a tree structure.
+treeMapParser :: (forall x . OptHelpInfo -> Option x -> b)
+          -> Parser a
+          -> OptTree b
+treeMapParser g = simplify . go False False g
+  where
+    has_default :: Parser a -> Bool
+    has_default p = isJust (evalParser p)
+
+    go :: Bool
+       -> Bool
+       -> (forall x . OptHelpInfo -> Option x -> b)
+       -> Parser a
+       -> OptTree b
+    go _ _ _ (NilP _) = MultNode []
+    go m r f (OptP opt)
+      | optVisibility opt > Internal
+      = Leaf (f (OptHelpInfo m r) opt)
+      | otherwise
+      = MultNode []
+    go m r f (MultP p1 p2) =
+      MultNode [go m r f p1, go m r' f p2]
+      where r' = r || hasArg p1
+    go m r f (AltP p1 p2) =
+      AltNode altNodeType [go m r f p1, go m r f p2]
+      where
+        -- The 'AltNode' indicates if one of the branches has a default.
+        -- This is used for rendering brackets, as well as filtering
+        -- out optional arguments when generating the "missing:" text.
+        altNodeType =
+          if has_default p1 || has_default p2
+            then MarkDefault
+            else NoDefault
+
+    go _ r f (BindP p k) =
+      let go' = go True r f p
+      in case evalParser p of
+        Nothing -> go'
+        Just aa -> MultNode [ go', go True r f (k aa) ]
+
+    hasArg :: Parser a -> Bool
+    hasArg (NilP _) = False
+    hasArg (OptP p) = (isArg . optMain) p
+    hasArg (MultP p1 p2) = hasArg p1 || hasArg p2
+    hasArg (AltP p1 p2) = hasArg p1 || hasArg p2
+    hasArg (BindP p _) = hasArg p
+
+simplify :: OptTree a -> OptTree a
+simplify (Leaf x) = Leaf x
+simplify (MultNode xs) =
+  case concatMap (remove_mult . simplify) xs of
+    [x] -> x
+    xs' -> MultNode xs'
+  where
+    remove_mult (MultNode ts) = ts
+    remove_mult t = [t]
+simplify (AltNode b xs) =
+  AltNode b (concatMap (remove_alt . simplify) xs)
+  where
+    remove_alt (AltNode _ ts) = ts
+    remove_alt (MultNode []) = []
+    remove_alt t = [t]
diff --git a/src/Options/Applicative/Extra.hs b/src/Options/Applicative/Extra.hs
new file mode 100644
--- /dev/null
+++ b/src/Options/Applicative/Extra.hs
@@ -0,0 +1,291 @@
+{-# LANGUAGE RankNTypes #-}
+module Options.Applicative.Extra (
+  -- * Extra parser utilities
+  --
+  -- | This module contains high-level functions to run parsers.
+  helper,
+  hsubparser,
+  execParser,
+  execParserMaybe,
+  customExecParser,
+  customExecParserMaybe,
+  execParserPure,
+  getParseResult,
+  handleParseResult,
+  parserFailure,
+  renderFailure,
+  ParserFailure(..),
+  overFailure,
+  ParserResult(..),
+  ParserPrefs(..),
+  CompletionResult(..),
+  ) where
+
+import Control.Applicative
+import Data.Monoid
+import Prelude
+import System.Environment (getArgs, getProgName)
+import System.Exit (exitSuccess, exitWith, ExitCode(..))
+import System.IO (hPutStrLn, stderr)
+
+import Options.Applicative.BashCompletion
+import Options.Applicative.Builder
+import Options.Applicative.Builder.Internal
+import Options.Applicative.Common
+import Options.Applicative.Help
+
+import Options.Applicative.Internal
+import Options.Applicative.Types
+
+-- | A hidden \"helper\" option which always fails.
+--
+-- A common usage pattern is to apply this applicatively when
+-- creating a 'ParserInfo'
+--
+-- > opts :: ParserInfo Sample
+-- > opts = info (sample <**> helper) mempty
+
+helper :: Parser (a -> a)
+helper = abortOption ShowHelpText $ mconcat
+  [ long "help"
+  , short 'h'
+  , help "Show this help text"
+  , hidden ]
+
+-- | Builder for a command parser with a \"helper\" option attached.
+-- Used in the same way as `subparser`, but includes a \"--help|-h\" inside
+-- the subcommand.
+hsubparser :: Mod CommandFields a -> Parser a
+hsubparser m = mkParser d g rdr
+  where
+    Mod _ d g = metavar "COMMAND" `mappend` m
+    (groupName, cmds, subs) = mkCommand m
+    rdr = CmdReader groupName cmds (fmap add_helper . subs)
+    add_helper pinfo = pinfo
+      { infoParser = infoParser pinfo <**> helper }
+
+-- | Run a program description.
+--
+-- Parse command line arguments. Display help text and exit if any parse error
+-- occurs.
+execParser :: ParserInfo a -> IO a
+execParser = customExecParser defaultPrefs
+
+-- | Run a program description with custom preferences.
+customExecParser :: ParserPrefs -> ParserInfo a -> IO a
+customExecParser pprefs pinfo
+  = execParserPure pprefs pinfo <$> getArgs
+  >>= handleParseResult
+
+-- | Handle `ParserResult`.
+handleParseResult :: ParserResult a -> IO a
+handleParseResult (Success a) = return a
+handleParseResult (Failure failure) = do
+      progn <- getProgName
+      let (msg, exit) = renderFailure failure progn
+      case exit of
+        ExitSuccess -> putStrLn msg
+        _           -> hPutStrLn stderr msg
+      exitWith exit
+handleParseResult (CompletionInvoked compl) = do
+      progn <- getProgName
+      msg <- execCompletion compl progn
+      putStr msg
+      exitSuccess
+
+-- | Extract the actual result from a `ParserResult` value.
+--
+-- This function returns 'Nothing' in case of errors.  Possible error messages
+-- or completion actions are simply discarded.
+--
+-- If you want to display error messages and invoke completion actions
+-- appropriately, use 'handleParseResult' instead.
+getParseResult :: ParserResult a -> Maybe a
+getParseResult (Success a) = Just a
+getParseResult _ = Nothing
+
+-- | Run a program description in pure code.
+--
+-- This function behaves like 'execParser', but can be called from pure code.
+-- Note that, in case of errors, no message is displayed, and this function
+-- simply returns 'Nothing'.
+--
+-- If you need to keep track of error messages, use 'execParserPure' instead.
+{-# DEPRECATED execParserMaybe "Use execParserPure together with getParseResult instead" #-}
+execParserMaybe :: ParserInfo a -> [String] -> Maybe a
+execParserMaybe = customExecParserMaybe defaultPrefs
+
+-- | Run a program description with custom preferences in pure code.
+--
+-- See 'execParserMaybe' for details.
+{-# DEPRECATED customExecParserMaybe "Use execParserPure together with getParseResult instead" #-}
+customExecParserMaybe :: ParserPrefs -> ParserInfo a -> [String] -> Maybe a
+customExecParserMaybe pprefs pinfo args = getParseResult $ execParserPure pprefs pinfo args
+
+-- | The most general way to run a program description in pure code.
+execParserPure :: ParserPrefs       -- ^ Global preferences for this parser
+               -> ParserInfo a      -- ^ Description of the program to run
+               -> [String]          -- ^ Program arguments
+               -> ParserResult a
+execParserPure pprefs pinfo args =
+  case runP p pprefs of
+    (Right (Right r), _) -> Success r
+    (Right (Left c), _) -> CompletionInvoked c
+    (Left err, ctx) -> Failure $ parserFailure pprefs pinfo err ctx
+  where
+    pinfo' = pinfo
+      { infoParser = (Left <$> bashCompletionParser pinfo pprefs)
+                 <|> (Right <$> infoParser pinfo) }
+    p = runParserInfo pinfo' args
+
+-- | Generate a `ParserFailure` from a `ParseError` in a given `Context`.
+--
+-- This function can be used, for example, to show the help text for a parser:
+--
+-- @handleParseResult . Failure $ parserFailure pprefs pinfo ShowHelpText mempty@
+parserFailure :: ParserPrefs -> ParserInfo a
+              -> ParseError -> [Context]
+              -> ParserFailure ParserHelp
+parserFailure pprefs pinfo msg ctx = ParserFailure $ \progn ->
+  let h = with_context ctx pinfo $ \names pinfo' -> mconcat
+            [ base_help pinfo'
+            , usage_help progn names pinfo'
+            , suggestion_help
+            , error_help ]
+  in (h, exit_code, prefColumns pprefs)
+  where
+    exit_code = case msg of
+      ErrorMsg {}        -> ExitFailure (infoFailureCode pinfo)
+      UnknownError       -> ExitFailure (infoFailureCode pinfo)
+      MissingError {}    -> ExitFailure (infoFailureCode pinfo)
+      ExpectsArgError {} -> ExitFailure (infoFailureCode pinfo)
+      UnexpectedError {} -> ExitFailure (infoFailureCode pinfo)
+      ShowHelpText       -> ExitSuccess
+      InfoMsg {}         -> ExitSuccess
+
+    with_context :: [Context]
+                 -> ParserInfo a
+                 -> (forall b . [String] -> ParserInfo b -> c)
+                 -> c
+    with_context [] i f = f [] i
+    with_context c@(Context _ i:_) _ f = f (contextNames c) i
+
+    usage_help progn names i = case msg of
+      InfoMsg _
+        -> mempty
+      _
+        -> usageHelp $ vcatChunks
+          [ pure . parserUsage pprefs (infoParser i) . unwords $ progn : names
+          , fmap (indent 2) . infoProgDesc $ i ]
+
+    error_help = errorHelp $ case msg of
+      ShowHelpText
+        -> mempty
+
+      ErrorMsg m
+        -> stringChunk m
+
+      InfoMsg  m
+        -> stringChunk m
+
+      MissingError CmdStart _
+        | prefShowHelpOnEmpty pprefs
+        -> mempty
+
+      MissingError _ (SomeParser x)
+        -> stringChunk "Missing:" <<+>> missingDesc pprefs x
+
+      ExpectsArgError x
+        -> stringChunk $ "The option `" ++ x ++ "` expects an argument."
+
+      UnexpectedError arg _
+        -> stringChunk msg'
+          where
+            --
+            -- This gives us the same error we have always
+            -- reported
+            msg' = case arg of
+              ('-':_) -> "Invalid option `" ++ arg ++ "'"
+              _       -> "Invalid argument `" ++ arg ++ "'"
+
+      UnknownError
+        -> mempty
+
+
+    suggestion_help = suggestionsHelp $ case msg of
+      UnexpectedError arg (SomeParser x)
+        --
+        -- We have an unexpected argument and the parser which
+        -- it's running over.
+        --
+        -- We can make a good help suggestion here if we do
+        -- a levenstein distance between all possible suggestions
+        -- and the supplied option or argument.
+        -> suggestions
+          where
+            --
+            -- Not using chunked here, as we don't want to
+            -- show "Did you mean" if there's nothing there
+            -- to show
+            suggestions = (.$.) <$> prose
+                                <*> (indent 4 <$> (vcatChunks . fmap stringChunk $ good ))
+
+            --
+            -- We won't worry about the 0 case, it won't be
+            -- shown anyway.
+            prose       = if length good < 2
+                            then stringChunk "Did you mean this?"
+                            else stringChunk "Did you mean one of these?"
+            --
+            -- Suggestions we will show, they're close enough
+            -- to what the user wrote
+            good        = filter isClose possibles
+
+            --
+            -- Bit of an arbitrary decision here.
+            -- Edit distances of 1 or 2 will give hints
+            isClose a   = editDistance a arg < 3
+
+            --
+            -- Similar to how bash completion works.
+            -- We map over the parser and get the names
+            -- ( no IO here though, unlike for completers )
+            possibles   = concat $ mapParser opt_completions x
+
+            --
+            -- Look at the option and give back the possible
+            -- things the user could type. If it's a command
+            -- reader also ensure that it can be immediately
+            -- reachable from where the error was given.
+            opt_completions hinfo opt = case optMain opt of
+              OptReader ns _ _ -> fmap showOption ns
+              FlagReader ns _  -> fmap showOption ns
+              ArgReader _      -> []
+              CmdReader _ ns _  | hinfoUnreachableArgs hinfo
+                               -> []
+                                | otherwise
+                               -> ns
+      _
+        -> mempty
+
+    base_help :: ParserInfo a -> ParserHelp
+    base_help i
+      | show_full_help
+      = mconcat [h, f, parserHelp pprefs (infoParser i)]
+      | otherwise
+      = mempty
+      where
+        h = headerHelp (infoHeader i)
+        f = footerHelp (infoFooter i)
+
+    show_full_help = case msg of
+      ShowHelpText             -> True
+      MissingError CmdStart  _  | prefShowHelpOnEmpty pprefs
+                               -> True
+      InfoMsg _                -> False
+      _                        -> prefShowHelpOnError pprefs
+
+renderFailure :: ParserFailure ParserHelp -> String -> (String, ExitCode)
+renderFailure failure progn =
+  let (h, exit, cols) = execFailure failure progn
+  in (renderHelp cols h, exit)
diff --git a/src/Options/Applicative/Help.hs b/src/Options/Applicative/Help.hs
new file mode 100644
--- /dev/null
+++ b/src/Options/Applicative/Help.hs
@@ -0,0 +1,28 @@
+module Options.Applicative.Help (
+  -- | This is an empty module which re-exports
+  --   the help text system for optparse.
+
+  -- | Pretty printer. Reexports most combinators
+  --   from Text.PrettyPrint.ANSI.Leijen
+  module Options.Applicative.Help.Pretty,
+
+  -- | A free monoid over Doc with helpers for
+  --   composing help text components.
+  module Options.Applicative.Help.Chunk,
+
+  -- | Types required by the help system.
+  module Options.Applicative.Help.Types,
+
+  -- | Core implementation of the help text
+  --   generator.
+  module Options.Applicative.Help.Core,
+
+  -- | Edit distance calculations for suggestions
+  module Options.Applicative.Help.Levenshtein
+  ) where
+
+import Options.Applicative.Help.Chunk
+import Options.Applicative.Help.Core
+import Options.Applicative.Help.Levenshtein
+import Options.Applicative.Help.Pretty
+import Options.Applicative.Help.Types
diff --git a/src/Options/Applicative/Help/Chunk.hs b/src/Options/Applicative/Help/Chunk.hs
new file mode 100644
--- /dev/null
+++ b/src/Options/Applicative/Help/Chunk.hs
@@ -0,0 +1,143 @@
+module Options.Applicative.Help.Chunk
+  ( mappendWith
+  , Chunk(..)
+  , chunked
+  , listToChunk
+  , (<<+>>)
+  , (<</>>)
+  , vcatChunks
+  , vsepChunks
+  , isEmpty
+  , stringChunk
+  , paragraph
+  , extractChunk
+  , tabulate
+  ) where
+
+import Control.Applicative
+import Control.Monad
+import Data.List.NonEmpty (NonEmpty(..))
+import Data.Maybe
+import Data.Semigroup
+import Prelude
+
+import Options.Applicative.Help.Pretty
+
+mappendWith :: Monoid a => a -> a -> a -> a
+mappendWith s x y = mconcat [x, s, y]
+
+-- | The free monoid on a semigroup 'a'.
+newtype Chunk a = Chunk
+  { unChunk :: Maybe a }
+  deriving (Eq, Show)
+
+instance Functor Chunk where
+  fmap f = Chunk . fmap f . unChunk
+
+instance Applicative Chunk where
+  pure = Chunk . pure
+  Chunk f <*> Chunk x = Chunk (f <*> x)
+
+instance Alternative Chunk where
+  empty = Chunk Control.Applicative.empty
+  a <|> b = Chunk $ unChunk a <|> unChunk b
+
+instance Monad Chunk where
+  return = pure
+  m >>= f = Chunk $ unChunk m >>= unChunk . f
+
+instance Semigroup a => Semigroup (Chunk a) where
+  (<>) = chunked (<>)
+
+instance Semigroup a => Monoid (Chunk a) where
+  mempty = Chunk Nothing
+  mappend = (<>)
+
+instance MonadPlus Chunk where
+  mzero = Chunk mzero
+  mplus m1 m2 = Chunk $ mplus (unChunk m1) (unChunk m2)
+
+-- | Given a semigroup structure on 'a', return a monoid structure on 'Chunk a'.
+--
+-- Note that this is /not/ the same as 'liftA2'.
+chunked :: (a -> a -> a)
+        -> Chunk a -> Chunk a -> Chunk a
+chunked _ (Chunk Nothing) y = y
+chunked _ x (Chunk Nothing) = x
+chunked f (Chunk (Just x)) (Chunk (Just y)) = Chunk (Just (f x y))
+
+-- | Concatenate a list into a Chunk.  'listToChunk' satisfies:
+--
+-- > isEmpty . listToChunk = null
+-- > listToChunk = mconcat . fmap pure
+listToChunk :: Semigroup a => [a] -> Chunk a
+listToChunk [] = mempty
+listToChunk (x:xs) = pure (sconcat (x :| xs))
+
+-- | Part of a constrained comonad instance.
+--
+-- This is the counit of the adjunction between 'Chunk' and the forgetful
+-- functor from monoids to semigroups.  It satisfies:
+--
+-- > extractChunk . pure = id
+-- > extractChunk . fmap pure = id
+extractChunk :: Monoid a => Chunk a -> a
+extractChunk = fromMaybe mempty . unChunk
+-- we could also define:
+-- duplicate :: Monoid a => Chunk a -> Chunk (Chunk a)
+-- duplicate = fmap pure
+
+-- | Concatenate two 'Chunk's with a space in between.  If one is empty, this
+-- just returns the other one.
+--
+-- Unlike '<+>' for 'Doc', this operation has a unit element, namely the empty
+-- 'Chunk'.
+(<<+>>) :: Chunk Doc -> Chunk Doc -> Chunk Doc
+(<<+>>) = chunked (<+>)
+
+-- | Concatenate two 'Chunk's with a softline in between.  This is exactly like
+-- '<<+>>', but uses a softline instead of a space.
+(<</>>) :: Chunk Doc -> Chunk Doc -> Chunk Doc
+(<</>>) = chunked (</>)
+
+-- | Concatenate 'Chunk's vertically.
+vcatChunks :: [Chunk Doc] -> Chunk Doc
+vcatChunks = foldr (chunked (.$.)) mempty
+
+-- | Concatenate 'Chunk's vertically separated by empty lines.
+vsepChunks :: [Chunk Doc] -> Chunk Doc
+vsepChunks = foldr (chunked (\x y -> x .$. mempty .$. y)) mempty
+
+-- | Whether a 'Chunk' is empty.  Note that something like 'pure mempty' is not
+-- considered an empty chunk, even though the underlying 'Doc' is empty.
+isEmpty :: Chunk a -> Bool
+isEmpty = isNothing . unChunk
+
+-- | Convert a 'String' into a 'Chunk'.  This satisfies:
+--
+-- > isEmpty . stringChunk = null
+-- > extractChunk . stringChunk = string
+stringChunk :: String -> Chunk Doc
+stringChunk "" = mempty
+stringChunk s = pure (string s)
+
+-- | Convert a paragraph into a 'Chunk'.  The resulting chunk is composed by the
+-- words of the original paragraph separated by softlines, so it will be
+-- automatically word-wrapped when rendering the underlying document.
+--
+-- This satisfies:
+--
+-- > isEmpty . paragraph = null . words
+paragraph :: String -> Chunk Doc
+paragraph = foldr (chunked (</>) . stringChunk) mempty
+          . words
+
+tabulate' :: Int -> [(Doc, Doc)] -> Chunk Doc
+tabulate' _ [] = mempty
+tabulate' size table = pure $ vcat
+  [ indent 2 (fillBreak size key <+> value)
+  | (key, value) <- table ]
+
+-- | Display pairs of strings in a table.
+tabulate :: [(Doc, Doc)] -> Chunk Doc
+tabulate = tabulate' 24
diff --git a/src/Options/Applicative/Help/Core.hs b/src/Options/Applicative/Help/Core.hs
new file mode 100644
--- /dev/null
+++ b/src/Options/Applicative/Help/Core.hs
@@ -0,0 +1,213 @@
+module Options.Applicative.Help.Core (
+  cmdDesc,
+  briefDesc,
+  missingDesc,
+  fullDesc,
+  ParserHelp(..),
+  errorHelp,
+  headerHelp,
+  suggestionsHelp,
+  usageHelp,
+  bodyHelp,
+  footerHelp,
+  parserHelp,
+  parserUsage,
+  ) where
+
+import Control.Applicative
+import Control.Monad (guard)
+import Data.Function (on)
+import Data.List (sort, intersperse, groupBy)
+import Data.Foldable (any)
+import Data.Maybe (maybeToList, catMaybes, fromMaybe)
+import Data.Monoid (mempty)
+import Data.Semigroup (Semigroup (..))
+import Prelude hiding (any)
+
+import Options.Applicative.Common
+import Options.Applicative.Types
+import Options.Applicative.Help.Pretty
+import Options.Applicative.Help.Chunk
+
+-- | Style for rendering an option.
+data OptDescStyle = OptDescStyle
+  { descSep :: Doc
+  , descHidden :: Bool }
+
+safelast :: [a] -> Maybe a
+safelast = foldl (const Just) Nothing
+
+-- | Generate description for a single option.
+optDesc :: ParserPrefs -> OptDescStyle -> OptHelpInfo -> Option a -> (Chunk Doc, Wrapping)
+optDesc pprefs style info opt =
+  let names
+        = sort . optionNames . optMain $ opt
+      meta
+        = stringChunk $ optMetaVar opt
+      descs
+        = map (string . showOption) names
+      descriptions
+        = listToChunk (intersperse (descSep style) descs)
+      desc
+        | prefHelpLongEquals pprefs && not (isEmpty meta) && any isLongName (safelast names)
+        = descriptions <> stringChunk "=" <> meta
+        | otherwise
+        = descriptions <<+>> meta
+      show_opt
+        | optVisibility opt == Hidden
+        = descHidden style
+        | otherwise
+        = optVisibility opt == Visible
+      suffix
+        | hinfoMulti info
+        = stringChunk . prefMultiSuffix $ pprefs
+        | otherwise
+        = mempty
+      wrapping
+        = wrapIf (length names > 1)
+      rendered
+        | not show_opt
+        = mempty
+        | otherwise
+        = desc <> suffix
+      modified
+        = maybe id fmap (optDescMod opt) rendered
+  in  (modified, wrapping)
+
+-- | Generate descriptions for commands.
+cmdDesc :: Parser a -> [(Maybe String, Chunk Doc)]
+cmdDesc = mapParser desc
+  where
+    desc _ opt =
+      case optMain opt of
+        CmdReader gn cmds p -> (,) gn $
+          tabulate [(string cmd, align (extractChunk d))
+                   | cmd <- reverse cmds
+                   , d <- maybeToList . fmap infoProgDesc $ p cmd ]
+        _ -> mempty
+
+-- | Generate a brief help text for a parser.
+briefDesc :: ParserPrefs -> Parser a -> Chunk Doc
+briefDesc = briefDesc' True
+
+-- | Generate a brief help text for a parser, only including mandatory
+--   options and arguments.
+missingDesc :: ParserPrefs -> Parser a -> Chunk Doc
+missingDesc = briefDesc' False
+
+-- | Generate a brief help text for a parser, allowing the specification
+--   of if optional arguments are show.
+briefDesc' :: Bool -> ParserPrefs -> Parser a -> Chunk Doc
+briefDesc' showOptional pprefs
+    = wrap NoDefault . foldTree . mfilterOptional . treeMapParser (optDesc pprefs style)
+  where
+    mfilterOptional
+      | showOptional
+      = id
+      | otherwise
+      = filterOptional
+
+    style = OptDescStyle
+      { descSep = string "|"
+      , descHidden = False }
+
+-- | Wrap a doc in parentheses or brackets if required.
+wrap :: AltNodeType ->  (Chunk Doc, Wrapping) -> Chunk Doc
+wrap altnode (chunk, wrapping)
+  | altnode == MarkDefault
+  = fmap brackets chunk
+  | needsWrapping wrapping
+  = fmap parens chunk
+  | otherwise
+  = chunk
+
+-- Fold a tree of option docs into a single doc with fully marked
+-- optional areas and groups.
+foldTree :: OptTree (Chunk Doc, Wrapping) -> (Chunk Doc, Wrapping)
+foldTree (Leaf x)
+  = x
+foldTree (MultNode xs)
+  = (foldr ((<</>>) . wrap NoDefault . foldTree) mempty xs, Bare)
+foldTree (AltNode b xs)
+  = (\x -> (x, Bare))
+  . wrap b
+  . alt_node
+  . filter (not . isEmpty . fst)
+  . map foldTree $ xs
+    where
+  alt_node :: [(Chunk Doc, Wrapping)] -> (Chunk Doc, Wrapping)
+  alt_node [n] = n
+  alt_node ns = (\y -> (y, Wrapped))
+              . foldr (chunked (\x y -> x </> char '|' </> y) . wrap NoDefault) mempty
+              $ ns
+
+-- | Generate a full help text for a parser.
+fullDesc :: ParserPrefs -> Parser a -> Chunk Doc
+fullDesc pprefs = tabulate . catMaybes . mapParser doc
+  where
+    doc info opt = do
+      guard . not . isEmpty $ n
+      guard . not . isEmpty $ h
+      return (extractChunk n, align . extractChunk $ h <<+>> hdef)
+      where
+        n = fst $ optDesc pprefs style info opt
+        h = optHelp opt
+        hdef = Chunk . fmap show_def . optShowDefault $ opt
+        show_def s = parens (string "default:" <+> string s)
+    style = OptDescStyle
+      { descSep = string ","
+      , descHidden = True }
+
+errorHelp :: Chunk Doc -> ParserHelp
+errorHelp chunk = mempty { helpError = chunk }
+
+headerHelp :: Chunk Doc -> ParserHelp
+headerHelp chunk = mempty { helpHeader = chunk }
+
+suggestionsHelp :: Chunk Doc -> ParserHelp
+suggestionsHelp chunk = mempty { helpSuggestions = chunk }
+
+usageHelp :: Chunk Doc -> ParserHelp
+usageHelp chunk = mempty { helpUsage = chunk }
+
+bodyHelp :: Chunk Doc -> ParserHelp
+bodyHelp chunk = mempty { helpBody = chunk }
+
+footerHelp :: Chunk Doc -> ParserHelp
+footerHelp chunk = mempty { helpFooter = chunk }
+
+-- | Generate the help text for a program.
+parserHelp :: ParserPrefs -> Parser a -> ParserHelp
+parserHelp pprefs p = bodyHelp . vsepChunks
+  $ with_title "Available options:" (fullDesc pprefs p)
+  : (group_title <$> cs)
+  where
+    def = "Available commands:"
+
+    cs = groupBy ((==) `on` fst) $ cmdDesc p
+
+    group_title a@((n,_):_) = with_title (fromMaybe def n) $
+      vcatChunks (snd <$> a)
+    group_title _ = mempty
+
+
+    with_title :: String -> Chunk Doc -> Chunk Doc
+    with_title title = fmap (string title .$.)
+
+-- | Generate option summary.
+parserUsage :: ParserPrefs -> Parser a -> String -> Doc
+parserUsage pprefs p progn = hsep
+  [ string "Usage:"
+  , string progn
+  , align (extractChunk (briefDesc pprefs p)) ]
+
+data Wrapping
+  = Bare
+  | Wrapped
+  deriving (Eq, Show)
+
+wrapIf :: Bool -> Wrapping
+wrapIf b = if b then Wrapped else Bare
+
+needsWrapping :: Wrapping -> Bool
+needsWrapping = (==) Wrapped
diff --git a/src/Options/Applicative/Help/Levenshtein.hs b/src/Options/Applicative/Help/Levenshtein.hs
new file mode 100644
--- /dev/null
+++ b/src/Options/Applicative/Help/Levenshtein.hs
@@ -0,0 +1,61 @@
+module Options.Applicative.Help.Levenshtein (
+    editDistance
+  ) where
+
+-- | Calculate the Damerau-Levenshtein edit distance
+--   between two lists (strings).
+--
+--   This is modified from
+--   https://wiki.haskell.org/Edit_distance
+--   and is originally from Lloyd Allison's paper
+--   "Lazy Dynamic-Programming can be Eager"
+--
+--   It's been changed though from Levenshtein to
+--   Damerau-Levenshtein, which treats transposition
+--   of adjacent characters as one change instead of
+--   two.
+editDistance :: Eq a => [a] -> [a] -> Int
+editDistance a b = last $
+  case () of
+    _ | lab == 0
+     -> mainDiag
+      | lab > 0
+     -> lowers !! (lab - 1)
+      | otherwise
+     -> uppers !! (-1 - lab)
+  where
+    mainDiag = oneDiag a b (head uppers) (-1 : head lowers)
+    uppers = eachDiag a b (mainDiag : uppers) -- upper diagonals
+    lowers = eachDiag b a (mainDiag : lowers) -- lower diagonals
+    eachDiag _ [] _ = []
+    eachDiag _ _ [] = []
+    eachDiag a' (_:bs) (lastDiag:diags) =
+      oneDiag a' bs nextDiag lastDiag : eachDiag a' bs diags
+      where
+        nextDiag = head (tail diags)
+    oneDiag a' b' diagAbove diagBelow = thisdiag
+      where
+        doDiag [] _ _ _ _ = []
+        doDiag _ [] _ _ _ = []
+        -- Check for a transposition
+        -- We don't add anything to nw here, the next character
+        -- will be different however and the transposition
+        -- will have an edit distance of 1.
+        doDiag (ach:ach':as) (bch:bch':bs) nw n w
+          | ach' == bch && ach == bch'
+          = nw : doDiag (ach' : as) (bch' : bs) nw (tail n) (tail w)
+        -- Standard case
+        doDiag (ach:as) (bch:bs) nw n w =
+          me : doDiag as bs me (tail n) (tail w)
+          where
+            me =
+              if ach == bch
+                then nw
+                else 1 + min3 (head w) nw (head n)
+        firstelt = 1 + head diagBelow
+        thisdiag = firstelt : doDiag a' b' firstelt diagAbove (tail diagBelow)
+    lab = length a - length b
+    min3 x y z =
+      if x < y
+        then x
+        else min y z
diff --git a/src/Options/Applicative/Help/Pretty.hs b/src/Options/Applicative/Help/Pretty.hs
new file mode 100644
--- /dev/null
+++ b/src/Options/Applicative/Help/Pretty.hs
@@ -0,0 +1,10 @@
+module Options.Applicative.Help.Pretty
+  ( module Text.PrettyPrint.ANSI.Leijen
+  , (.$.)
+  ) where
+
+import Text.PrettyPrint.ANSI.Leijen hiding ((<$>), (<>), columns)
+import qualified Text.PrettyPrint.ANSI.Leijen as PP
+
+(.$.) :: Doc -> Doc -> Doc
+(.$.) = (PP.<$>)
diff --git a/src/Options/Applicative/Help/Types.hs b/src/Options/Applicative/Help/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/Options/Applicative/Help/Types.hs
@@ -0,0 +1,41 @@
+module Options.Applicative.Help.Types (
+    ParserHelp (..)
+  , renderHelp
+  ) where
+
+import Data.Semigroup
+import Prelude
+
+import Options.Applicative.Help.Chunk
+import Options.Applicative.Help.Pretty
+
+data ParserHelp = ParserHelp
+  { helpError :: Chunk Doc
+  , helpSuggestions :: Chunk Doc
+  , helpHeader :: Chunk Doc
+  , helpUsage :: Chunk Doc
+  , helpBody :: Chunk Doc
+  , helpFooter :: Chunk Doc }
+
+instance Show ParserHelp where
+  showsPrec _ h = showString (renderHelp 80 h)
+
+instance Monoid ParserHelp where
+  mempty = ParserHelp mempty mempty mempty mempty mempty mempty
+  mappend = (<>)
+
+instance Semigroup ParserHelp where
+  (ParserHelp e1 s1 h1 u1 b1 f1) <> (ParserHelp e2 s2 h2 u2 b2 f2)
+    = ParserHelp (mappend e1 e2) (mappend s1 s2)
+                 (mappend h1 h2) (mappend u1 u2)
+                 (mappend b1 b2) (mappend f1 f2)
+
+helpText :: ParserHelp -> Doc
+helpText (ParserHelp e s h u b f) = extractChunk . vsepChunks $ [e, s, h, u, b, f]
+
+-- | Convert a help text to 'String'.
+renderHelp :: Int -> ParserHelp -> String
+renderHelp cols
+  = (`displayS` "")
+  . renderPretty 1.0 cols
+  . helpText
diff --git a/src/Options/Applicative/Internal.hs b/src/Options/Applicative/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Options/Applicative/Internal.hs
@@ -0,0 +1,265 @@
+module Options.Applicative.Internal
+  ( P
+  , MonadP(..)
+  , ParseError(..)
+
+  , uncons
+  , hoistMaybe
+  , hoistEither
+  , runReadM
+  , withReadM
+
+  , runP
+
+  , Completion
+  , runCompletion
+  , contextNames
+
+  , ListT
+  , takeListT
+  , runListT
+
+  , NondetT
+  , cut
+  , (<!>)
+  , disamb
+  ) where
+
+import Control.Applicative
+import Prelude
+import Control.Monad (MonadPlus(..), liftM, ap, guard)
+import Control.Monad.Trans.Class (MonadTrans, lift)
+import Control.Monad.Trans.Except
+  (runExcept, runExceptT, withExcept, ExceptT(..), throwE)
+import Control.Monad.Trans.Reader
+  (mapReaderT, runReader, runReaderT, Reader, ReaderT, ask)
+import Control.Monad.Trans.State (StateT, get, put, modify, evalStateT, runStateT)
+
+import Options.Applicative.Types
+
+class (Alternative m, MonadPlus m) => MonadP m where
+  enterContext :: String -> ParserInfo a -> m ()
+  exitContext :: m ()
+  getPrefs :: m ParserPrefs
+
+  missingArgP :: ParseError -> Completer -> m a
+  errorP :: ParseError -> m a
+  exitP :: IsCmdStart -> ArgPolicy -> Parser b -> Maybe a -> m a
+
+newtype P a = P (ExceptT ParseError (StateT [Context] (Reader ParserPrefs)) a)
+
+instance Functor P where
+  fmap f (P m) = P $ fmap f m
+
+instance Applicative P where
+  pure a = P $ pure a
+  P f <*> P a = P $ f <*> a
+
+instance Alternative P where
+  empty = P empty
+  P x <|> P y = P $ x <|> y
+
+instance Monad P where
+  return = pure
+  P x >>= k = P $ x >>= \a -> case k a of P y -> y
+
+instance MonadPlus P where
+  mzero = P mzero
+  mplus (P x) (P y) = P $ mplus x y
+
+contextNames :: [Context] -> [String]
+contextNames ns =
+  let go (Context n _) = n
+  in  reverse $ go <$> ns
+
+instance MonadP P where
+  enterContext name pinfo = P $ lift $ modify $ (:) $ Context name pinfo
+  exitContext = P $ lift $ modify $ drop 1
+  getPrefs = P . lift . lift $ ask
+
+  missingArgP e _ = errorP e
+  exitP i _ p = P . maybe (throwE . MissingError i . SomeParser $ p) return
+  errorP = P . throwE
+
+hoistMaybe :: MonadPlus m => Maybe a -> m a
+hoistMaybe = maybe mzero return
+
+hoistEither :: MonadP m => Either ParseError a -> m a
+hoistEither = either errorP return
+
+runP :: P a -> ParserPrefs -> (Either ParseError a, [Context])
+runP (P p) = runReader . flip runStateT [] . runExceptT $ p
+
+uncons :: [a] -> Maybe (a, [a])
+uncons [] = Nothing
+uncons (x : xs) = Just (x, xs)
+
+runReadM :: MonadP m => ReadM a -> String -> m a
+runReadM (ReadM r) s = hoistEither . runExcept $ runReaderT r s
+
+withReadM :: (String -> String) -> ReadM a -> ReadM a
+withReadM f = ReadM . mapReaderT (withExcept f') . unReadM
+  where
+    f' (ErrorMsg err) = ErrorMsg (f err)
+    f' e = e
+
+data ComplResult a
+  = ComplParser SomeParser ArgPolicy
+  | ComplOption Completer
+  | ComplResult a
+
+instance Functor ComplResult where
+  fmap = liftM
+
+instance Applicative ComplResult where
+  pure = ComplResult
+  (<*>) = ap
+
+instance Monad ComplResult where
+  return = pure
+  m >>= f = case m of
+    ComplResult r -> f r
+    ComplParser p a -> ComplParser p a
+    ComplOption c -> ComplOption c
+
+newtype Completion a =
+  Completion (ExceptT ParseError (ReaderT ParserPrefs ComplResult) a)
+
+instance Functor Completion where
+  fmap f (Completion m) = Completion $ fmap f m
+
+instance Applicative Completion where
+  pure a = Completion $ pure a
+  Completion f <*> Completion a = Completion $ f <*> a
+
+instance Alternative Completion where
+  empty = Completion empty
+  Completion x <|> Completion y = Completion $ x <|> y
+
+instance Monad Completion where
+  return = pure
+  Completion x >>= k = Completion $ x >>= \a -> case k a of Completion y -> y
+
+instance MonadPlus Completion where
+  mzero = Completion mzero
+  mplus (Completion x) (Completion y) = Completion $ mplus x y
+
+instance MonadP Completion where
+  enterContext _ _ = return ()
+  exitContext = return ()
+  getPrefs = Completion $ lift ask
+
+  missingArgP _ = Completion . lift . lift . ComplOption
+  exitP _ a p _ = Completion . lift . lift $ ComplParser (SomeParser p) a
+  errorP = Completion . throwE
+
+runCompletion :: Completion r -> ParserPrefs -> Maybe (Either (SomeParser, ArgPolicy) Completer)
+runCompletion (Completion c) prefs = case runReaderT (runExceptT c) prefs of
+  ComplResult _ -> Nothing
+  ComplParser p' a' -> Just $ Left (p', a')
+  ComplOption compl -> Just $ Right compl
+
+-- A "ListT done right" implementation
+
+newtype ListT m a = ListT
+  { stepListT :: m (TStep a (ListT m a)) }
+
+data TStep a x
+  = TNil
+  | TCons a x
+
+bimapTStep :: (a -> b) -> (x -> y) -> TStep a x -> TStep b y
+bimapTStep _ _ TNil = TNil
+bimapTStep f g (TCons a x) = TCons (f a) (g x)
+
+hoistList :: Monad m => [a] -> ListT m a
+hoistList = foldr (\x xt -> ListT (return (TCons x xt))) mzero
+
+takeListT :: Monad m => Int -> ListT m a -> ListT m a
+takeListT 0 = const mzero
+takeListT n = ListT . liftM (bimapTStep id (takeListT (n - 1))) . stepListT
+
+runListT :: Monad m => ListT m a -> m [a]
+runListT xs = do
+  s <- stepListT xs
+  case s of
+    TNil -> return []
+    TCons x xt -> liftM (x :) (runListT xt)
+
+instance Monad m => Functor (ListT m) where
+  fmap f = ListT
+         . liftM (bimapTStep f (fmap f))
+         . stepListT
+
+instance Monad m => Applicative (ListT m) where
+  pure = hoistList . pure
+  (<*>) = ap
+
+instance Monad m => Monad (ListT m) where
+  return = pure
+  xs >>= f = ListT $ do
+    s <- stepListT xs
+    case s of
+      TNil -> return TNil
+      TCons x xt -> stepListT $ f x `mplus` (xt >>= f)
+
+instance Monad m => Alternative (ListT m) where
+  empty = mzero
+  (<|>) = mplus
+
+instance MonadTrans ListT where
+  lift = ListT . liftM (`TCons` mzero)
+
+instance Monad m => MonadPlus (ListT m) where
+  mzero = ListT (return TNil)
+  mplus xs ys = ListT $ do
+    s <- stepListT xs
+    case s of
+      TNil -> stepListT ys
+      TCons x xt -> return $ TCons x (xt `mplus` ys)
+
+-- nondeterminism monad with cut operator
+
+newtype NondetT m a = NondetT
+  { runNondetT :: ListT (StateT Bool m) a }
+
+instance Monad m => Functor (NondetT m) where
+  fmap f = NondetT . fmap f . runNondetT
+
+instance Monad m => Applicative (NondetT m) where
+  pure = NondetT . pure
+  NondetT m1 <*> NondetT m2 = NondetT (m1 <*> m2)
+
+instance Monad m => Monad (NondetT m) where
+  return = pure
+  NondetT m1 >>= f = NondetT $ m1 >>= runNondetT . f
+
+instance Monad m => MonadPlus (NondetT m) where
+  mzero = NondetT mzero
+  NondetT m1 `mplus` NondetT m2 = NondetT (m1 `mplus` m2)
+
+instance Monad m => Alternative (NondetT m) where
+  empty = mzero
+  (<|>) = mplus
+
+instance MonadTrans NondetT where
+  lift = NondetT . lift . lift
+
+(<!>) :: Monad m => NondetT m a -> NondetT m a -> NondetT m a
+(<!>) m1 m2 = NondetT . mplus (runNondetT m1) $ do
+  s <- lift get
+  guard (not s)
+  runNondetT m2
+
+cut :: Monad m => NondetT m ()
+cut = NondetT $ lift (put True)
+
+disamb :: Monad m => Bool -> NondetT m a -> m (Maybe a)
+disamb allow_amb xs = do
+  xs' <- (`evalStateT` False)
+       . runListT
+       . takeListT (if allow_amb then 1 else 2)
+       . runNondetT $ xs
+  return $ case xs' of
+    [x] -> Just x
+    _   -> Nothing
diff --git a/src/Options/Applicative/Types.hs b/src/Options/Applicative/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/Options/Applicative/Types.hs
@@ -0,0 +1,436 @@
+{-# LANGUAGE CPP, Rank2Types, ExistentialQuantification #-}
+module Options.Applicative.Types (
+  ParseError(..),
+  ParserInfo(..),
+  ParserPrefs(..),
+
+  Option(..),
+  OptName(..),
+  isShortName,
+  isLongName,
+
+  OptReader(..),
+  OptProperties(..),
+  OptVisibility(..),
+  Backtracking(..),
+  ReadM(..),
+  readerAsk,
+  readerAbort,
+  readerError,
+  CReader(..),
+  Parser(..),
+  ParserM(..),
+  Completer(..),
+  mkCompleter,
+  CompletionResult(..),
+  ParserFailure(..),
+  ParserResult(..),
+  overFailure,
+  Args,
+  ArgPolicy(..),
+  OptHelpInfo(..),
+  AltNodeType(..),
+  OptTree(..),
+  ParserHelp(..),
+  SomeParser(..),
+  Context(..),
+  IsCmdStart(..),
+
+  fromM,
+  oneM,
+  manyM,
+  someM,
+
+  filterOptional,
+  optVisibility,
+  optMetaVar,
+  optHelp,
+  optShowDefault,
+  optDescMod
+  ) where
+
+import Control.Applicative
+import Control.Monad (ap, liftM, MonadPlus, mzero, mplus)
+import Control.Monad.Trans.Except (Except, throwE)
+import Control.Monad.Trans.Class (lift)
+import Control.Monad.Trans.Reader (ReaderT, ask)
+import qualified Control.Monad.Fail as Fail
+import Data.Semigroup hiding (Option)
+import Prelude
+
+import System.Exit (ExitCode(..))
+
+import Options.Applicative.Help.Types
+import Options.Applicative.Help.Pretty
+import Options.Applicative.Help.Chunk
+
+
+data ParseError
+  = ErrorMsg String
+  | InfoMsg String
+  | ShowHelpText
+  | UnknownError
+  | MissingError IsCmdStart SomeParser
+  | ExpectsArgError String
+  | UnexpectedError String SomeParser
+
+data IsCmdStart = CmdStart | CmdCont
+  deriving Show
+
+instance Monoid ParseError where
+  mempty = UnknownError
+  mappend = (<>)
+
+instance Semigroup ParseError where
+  m <> UnknownError = m
+  _ <> m = m
+
+-- | A full description for a runnable 'Parser' for a program.
+data ParserInfo a = ParserInfo
+  { infoParser :: Parser a    -- ^ the option parser for the program
+  , infoFullDesc :: Bool      -- ^ whether the help text should contain full
+                              -- documentation
+  , infoProgDesc :: Chunk Doc -- ^ brief parser description
+  , infoHeader :: Chunk Doc   -- ^ header of the full parser description
+  , infoFooter :: Chunk Doc   -- ^ footer of the full parser description
+  , infoFailureCode :: Int    -- ^ exit code for a parser failure
+  , infoPolicy :: ArgPolicy   -- ^ allow regular options and flags to occur
+                              -- after arguments (default: InterspersePolicy)
+  }
+
+instance Functor ParserInfo where
+  fmap f i = i { infoParser = fmap f (infoParser i) }
+
+data Backtracking
+  = Backtrack
+  | NoBacktrack
+  | SubparserInline
+  deriving (Eq, Show)
+
+-- | Global preferences for a top-level 'Parser'.
+data ParserPrefs = ParserPrefs
+  { prefMultiSuffix :: String     -- ^ metavar suffix for multiple options
+  , prefDisambiguate :: Bool      -- ^ automatically disambiguate abbreviations
+                                  -- (default: False)
+  , prefShowHelpOnError :: Bool   -- ^ always show help text on parse errors
+                                  -- (default: False)
+  , prefShowHelpOnEmpty :: Bool   -- ^ show the help text for a command or subcommand
+                                  -- if it fails with no input (default: False)
+  , prefBacktrack :: Backtracking -- ^ backtrack to parent parser when a
+                                  -- subcommand fails (default: Backtrack)
+  , prefColumns :: Int            -- ^ number of columns in the terminal, used to
+                                  -- format the help page (default: 80)
+  , prefHelpLongEquals :: Bool    -- ^ when displaying long names in usage and help,
+                                  -- use an '=' sign for long names, rather than a
+                                  -- single space (default: False)
+  } deriving (Eq, Show)
+
+data OptName = OptShort !Char
+             | OptLong !String
+  deriving (Eq, Ord, Show)
+
+isShortName :: OptName -> Bool
+isShortName (OptShort _) = True
+isShortName (OptLong _)  = False
+
+isLongName :: OptName -> Bool
+isLongName = not . isShortName
+
+-- | Visibility of an option in the help text.
+data OptVisibility
+  = Internal          -- ^ does not appear in the help text at all
+  | Hidden            -- ^ only visible in the full description
+  | Visible           -- ^ visible both in the full and brief descriptions
+  deriving (Eq, Ord, Show)
+
+-- | Specification for an individual parser option.
+data OptProperties = OptProperties
+  { propVisibility :: OptVisibility       -- ^ whether this flag is shown in the brief description
+  , propHelp :: Chunk Doc                 -- ^ help text for this option
+  , propMetaVar :: String                 -- ^ metavariable for this option
+  , propShowDefault :: Maybe String       -- ^ what to show in the help text as the default
+  , propDescMod :: Maybe ( Doc -> Doc )   -- ^ a function to run over the brief description
+  }
+
+instance Show OptProperties where
+  showsPrec p (OptProperties pV pH pMV pSD _)
+    = showParen (p >= 11)
+    $ showString "OptProperties { propVisibility = " . shows pV
+    . showString ", propHelp = " . shows pH
+    . showString ", propMetaVar = " . shows pMV
+    . showString ", propShowDefault = " . shows pSD
+    . showString ", propDescMod = _ }"
+
+-- | A single option of a parser.
+data Option a = Option
+  { optMain :: OptReader a               -- ^ reader for this option
+  , optProps :: OptProperties            -- ^ properties of this option
+  }
+
+data SomeParser = forall a . SomeParser (Parser a)
+
+-- | Subparser context, containing the 'name' of the subparser, and its parser info.
+--   Used by parserFailure to display relevant usage information when parsing inside a subparser fails.
+data Context = forall a . Context String (ParserInfo a)
+
+instance Show (Option a) where
+    show opt = "Option {optProps = " ++ show (optProps opt) ++ "}"
+
+instance Functor Option where
+  fmap f (Option m p) = Option (fmap f m) p
+
+-- | A newtype over 'ReaderT String Except', used by option readers.
+newtype ReadM a = ReadM
+  { unReadM :: ReaderT String (Except ParseError) a }
+
+instance Functor ReadM where
+  fmap f (ReadM r) = ReadM (fmap f r)
+
+instance Applicative ReadM where
+  pure = ReadM . pure
+  ReadM x <*> ReadM y = ReadM $ x <*> y
+
+instance Alternative ReadM where
+  empty = mzero
+  (<|>) = mplus
+
+instance Monad ReadM where
+  return = pure
+  ReadM r >>= f = ReadM $ r >>= unReadM . f
+
+#if !(MIN_VERSION_base(4,13,0))
+  fail = Fail.fail
+#endif
+
+instance Fail.MonadFail ReadM where
+  fail = readerError
+
+instance MonadPlus ReadM where
+  mzero = ReadM mzero
+  mplus (ReadM x) (ReadM y) = ReadM $ mplus x y
+
+-- | Return the value being read.
+readerAsk :: ReadM String
+readerAsk = ReadM ask
+
+-- | Abort option reader by exiting with a 'ParseError'.
+readerAbort :: ParseError -> ReadM a
+readerAbort = ReadM . lift . throwE
+
+-- | Abort option reader by exiting with an error message.
+readerError :: String -> ReadM a
+readerError = readerAbort . ErrorMsg
+
+data CReader a = CReader
+  { crCompleter :: Completer
+  , crReader :: ReadM a }
+
+instance Functor CReader where
+  fmap f (CReader c r) = CReader c (fmap f r)
+
+-- | An 'OptReader' defines whether an option matches an command line argument.
+data OptReader a
+  = OptReader [OptName] (CReader a) (String -> ParseError)
+  -- ^ option reader
+  | FlagReader [OptName] !a
+  -- ^ flag reader
+  | ArgReader (CReader a)
+  -- ^ argument reader
+  | CmdReader (Maybe String) [String] (String -> Maybe (ParserInfo a))
+  -- ^ command reader
+
+instance Functor OptReader where
+  fmap f (OptReader ns cr e) = OptReader ns (fmap f cr) e
+  fmap f (FlagReader ns x) = FlagReader ns (f x)
+  fmap f (ArgReader cr) = ArgReader (fmap f cr)
+  fmap f (CmdReader n cs g) = CmdReader n cs ((fmap . fmap) f . g)
+
+-- | A @Parser a@ is an option parser returning a value of type 'a'.
+data Parser a
+  = NilP (Maybe a)
+  | OptP (Option a)
+  | forall x . MultP (Parser (x -> a)) (Parser x)
+  | AltP (Parser a) (Parser a)
+  | forall x . BindP (Parser x) (x -> Parser a)
+
+instance Functor Parser where
+  fmap f (NilP x) = NilP (fmap f x)
+  fmap f (OptP opt) = OptP (fmap f opt)
+  fmap f (MultP p1 p2) = MultP (fmap (f.) p1) p2
+  fmap f (AltP p1 p2) = AltP (fmap f p1) (fmap f p2)
+  fmap f (BindP p k) = BindP p (fmap f . k)
+
+instance Applicative Parser where
+  pure = NilP . Just
+  (<*>) = MultP
+
+newtype ParserM r = ParserM
+  { runParserM :: forall x . (r -> Parser x) -> Parser x }
+
+instance Monad ParserM where
+  return = pure
+  ParserM f >>= g = ParserM $ \k -> f (\x -> runParserM (g x) k)
+
+instance Functor ParserM where
+  fmap = liftM
+
+instance Applicative ParserM where
+  pure x = ParserM $ \k -> k x
+  (<*>) = ap
+
+fromM :: ParserM a -> Parser a
+fromM (ParserM f) = f pure
+
+oneM :: Parser a -> ParserM a
+oneM p = ParserM (BindP p)
+
+manyM :: Parser a -> ParserM [a]
+manyM p = do
+  mx <- oneM (optional p)
+  case mx of
+    Nothing -> return []
+    Just x -> (x:) <$> manyM p
+
+someM :: Parser a -> ParserM [a]
+someM p = (:) <$> oneM p <*> manyM p
+
+instance Alternative Parser where
+  empty = NilP Nothing
+  (<|>) = AltP
+  many p = fromM $ manyM p
+  some p = fromM $ (:) <$> oneM p <*> manyM p
+
+-- | A shell complete function.
+newtype Completer = Completer
+  { runCompleter :: String -> IO [String] }
+
+-- | Smart constructor for a 'Completer'
+mkCompleter :: (String -> IO [String]) -> Completer
+mkCompleter = Completer
+
+instance Semigroup Completer where
+  (Completer c1) <> (Completer c2) =
+    Completer $ \s -> (++) <$> c1 s <*> c2 s
+
+instance Monoid Completer where
+  mempty = Completer $ \_ -> return []
+  mappend = (<>)
+
+newtype CompletionResult = CompletionResult
+  { execCompletion :: String -> IO String }
+
+instance Show CompletionResult where
+  showsPrec p _ = showParen (p > 10) $
+    showString "CompletionResult _"
+
+newtype ParserFailure h = ParserFailure
+  { execFailure :: String -> (h, ExitCode, Int) }
+
+instance Show h => Show (ParserFailure h) where
+  showsPrec p (ParserFailure f)
+    = showParen (p > 10)
+    $ showString "ParserFailure "
+    . showsPrec 11 (f "<program>")
+
+instance Functor ParserFailure where
+  fmap f (ParserFailure err) = ParserFailure $ \progn ->
+    let (h, exit, cols) = err progn in (f h, exit, cols)
+
+-- | Result of 'execParserPure'.
+data ParserResult a
+  = Success a
+  | Failure (ParserFailure ParserHelp)
+  | CompletionInvoked CompletionResult
+  deriving Show
+
+instance Functor ParserResult where
+  fmap f (Success a) = Success (f a)
+  fmap _ (Failure f) = Failure f
+  fmap _ (CompletionInvoked c) = CompletionInvoked c
+
+overFailure :: (ParserHelp -> ParserHelp)
+            -> ParserResult a -> ParserResult a
+overFailure f (Failure failure) = Failure $ fmap f failure
+overFailure _ r = r
+
+instance Applicative ParserResult where
+  pure = Success
+  Success f <*> r = fmap f r
+  Failure f <*> _ = Failure f
+  CompletionInvoked c <*> _ = CompletionInvoked c
+
+instance Monad ParserResult where
+  return = pure
+  Success x >>= f = f x
+  Failure f >>= _ = Failure f
+  CompletionInvoked c >>= _ = CompletionInvoked c
+
+type Args = [String]
+
+-- | Policy for how to handle options within the parse
+data ArgPolicy
+  = Intersperse
+  -- ^ The default policy, options and arguments can
+  --   be interspersed.
+  --   A `--` option can be passed to ensure all following
+  --   commands are treated as arguments.
+  | NoIntersperse
+  -- ^ Options must all come before arguments, once a
+  --   single positional argument or subcommand is parsed,
+  --   all remaining arguments are treated as positionals.
+  --   A `--` option can be passed if the first positional
+  --   one needs starts with `-`.
+  | AllPositionals
+  -- ^ No options are parsed at all, all arguments are
+  --   treated as positionals.
+  --   Is the policy used after `--` is encountered.
+  | ForwardOptions
+  -- ^ Options and arguments can be interspersed, but if
+  --   a given option is not found, it is treated as a
+  --   positional argument. This is sometimes useful if
+  --   one is passing through most options to another tool,
+  --   but are supplying just a few of their own options.
+  deriving (Eq, Ord, Show)
+
+data OptHelpInfo = OptHelpInfo
+  { hinfoMulti :: Bool           -- ^ Whether this is part of a many or some (approximately)
+  , hinfoUnreachableArgs :: Bool -- ^ If the result is a positional, if it can't be
+                                 --   accessed in the current parser position ( first arg )
+  } deriving (Eq, Show)
+
+-- | This type encapsulates whether an 'AltNode' of an 'OptTree' should be displayed
+-- with brackets around it.
+data AltNodeType = MarkDefault | NoDefault
+  deriving (Show, Eq)
+
+data OptTree a
+  = Leaf a
+  | MultNode [OptTree a]
+  | AltNode AltNodeType [OptTree a]
+  deriving Show
+
+filterOptional :: OptTree a -> OptTree a
+filterOptional t = case t of
+  Leaf a
+    -> Leaf a
+  MultNode xs
+    -> MultNode (map filterOptional xs)
+  AltNode MarkDefault _
+    -> AltNode MarkDefault []
+  AltNode NoDefault xs
+    -> AltNode NoDefault (map filterOptional xs)
+
+optVisibility :: Option a -> OptVisibility
+optVisibility = propVisibility . optProps
+
+optHelp :: Option a -> Chunk Doc
+optHelp  = propHelp . optProps
+
+optMetaVar :: Option a -> String
+optMetaVar = propMetaVar . optProps
+
+optShowDefault :: Option a -> Maybe String
+optShowDefault = propShowDefault . optProps
+
+optDescMod :: Option a -> Maybe ( Doc -> Doc )
+optDescMod = propDescMod . optProps
diff --git a/tests/long_equals.err.txt b/tests/long_equals.err.txt
new file mode 100644
--- /dev/null
+++ b/tests/long_equals.err.txt
@@ -0,0 +1,6 @@
+Usage: long_equals (-i|-j|--intval|--intval2=ARG)
+
+Available options:
+  -i,-j,--intval,--intval2=ARG
+                           integer value
+  -h,--help                Show this help text
diff --git a/tests/nested_optional.err.txt b/tests/nested_optional.err.txt
new file mode 100644
--- /dev/null
+++ b/tests/nested_optional.err.txt
@@ -0,0 +1,7 @@
+Usage: nested_optional (-a|--a A) [--b0 B0 [--b1 B1]]
+
+Available options:
+  -a,--a A                 value a
+  --b0 B0                  value b0
+  --b1 B1                  value b1
+  -h,--help                Show this help text
diff --git a/tests/optional.err.txt b/tests/optional.err.txt
new file mode 100644
--- /dev/null
+++ b/tests/optional.err.txt
@@ -0,0 +1,6 @@
+Usage: optional [--a A --b B]
+
+Available options:
+  --a A                    value a
+  --b B                    value b
+  -h,--help                Show this help text
diff --git a/tests/test.hs b/tests/test.hs
--- a/tests/test.hs
+++ b/tests/test.hs
@@ -13,6 +13,7 @@
 import           Control.Applicative
 import           Control.Monad
 import           Data.ByteString (ByteString)
+import qualified Data.ByteString.Char8 as BS8
 import           Data.List hiding (group)
 import           Data.Semigroup hiding (option)
 import           Data.String
@@ -146,6 +147,98 @@
       i = info (p <**> helper) idm
   in checkHelpText "alt" i ["--help"]
 
+prop_optional_help :: Property
+prop_optional_help = once $
+  let p :: Parser (Maybe (String, String))
+      p = optional ((,)
+                    <$> strOption ( long "a"
+                                    <> metavar "A"
+                                    <> help "value a" )
+                    <*> strOption ( long "b"
+                                    <> metavar "B"
+                                    <> help "value b" ) )
+      i = info (p <**> helper) idm
+  in checkHelpText "optional" i ["--help"]
+
+prop_optional_requiring_parens :: Property
+prop_optional_requiring_parens = once $
+  let p = optional $
+            (,)
+            <$> flag' () ( short 'a' <> long "a" )
+            <*> flag' () ( short 'b' <> long "b" )
+      i = info (p <**> helper) briefDesc
+      result = run i ["--help"]
+  in assertError result $ \failure ->
+    let text = head . lines . fst $ renderFailure failure "test"
+    in  "Usage: test [(-a|--a) (-b|--b)]" === text
+
+prop_optional_alt_requiring_parens :: Property
+prop_optional_alt_requiring_parens = once $
+  let p = optional $
+                flag' () ( short 'a' <> long "a" )
+            <|> flag' () ( short 'b' <> long "b" )
+      i = info (p <**> helper) briefDesc
+      result = run i ["--help"]
+  in assertError result $ \failure ->
+    let text = head . lines . fst $ renderFailure failure "test"
+    in  "Usage: test [(-a|--a) | (-b|--b)]" === text
+
+prop_nested_optional_help :: Property
+prop_nested_optional_help = once $
+  let p :: Parser (String, Maybe (String, Maybe String))
+      p = (,) <$>
+          (strOption ( short 'a'
+                       <> long "a"
+                       <> metavar "A"
+                       <> help "value a" ) ) <*>
+          (optional
+           ((,) <$>
+            (strOption ( long "b0"
+                         <> metavar "B0"
+                         <> help "value b0" ) ) <*>
+            (optional (strOption ( long "b1"
+                                   <> metavar "B1"
+                                   <> help "value b1" )))))
+      i = info (p <**> helper) idm
+  in checkHelpText "nested_optional" i ["--help"]
+
+prop_long_equals :: Property
+prop_long_equals = once $
+  let p :: Parser String
+      p = option auto (   long "intval"
+                       <> short 'j'
+                       <> long "intval2"
+                       <> short 'i'
+                       <> help "integer value")
+      i = info (p <**> helper) fullDesc
+  in checkHelpTextWith ExitSuccess (prefs helpLongEquals) "long_equals" i ["--help"]
+
+prop_long_equals_doesnt_do_shorts :: Property
+prop_long_equals_doesnt_do_shorts = once $
+  let p :: Parser String
+      p = option auto (   short 'i'
+                       <> help "integer value")
+      i = info (p <**> helper) fullDesc
+      result = execParserPure (prefs helpLongEquals) i ["--help"]
+  in assertError result $ \failure ->
+    let text = head . lines . fst $ renderFailure failure "test"
+    in  "Usage: test -i ARG" === text
+
+prop_nested_fun :: Property
+prop_nested_fun = once $
+  let p :: Parser (String, Maybe (String, Maybe String))
+      p = (,) <$>
+          (strOption (short 'a' <> long "a" <> metavar "A")) <*>
+          (optional
+           ((,) <$>
+            (strOption (short 'b' <> long "b" <> metavar "B")) <*>
+            (optional (strOption (short 'c' <> long "c" <> metavar "C")))))
+      i = info (p <**> helper) briefDesc
+      result = run i ["--help"]
+  in assertError result $ \failure ->
+    let text = head . lines . fst $ renderFailure failure "test"
+    in  "Usage: test (-a|--a A) [(-b|--b B) [-c|--c C]]" === text
+
 prop_nested_commands :: Property
 prop_nested_commands = once $
   let p3 :: Parser String
@@ -393,6 +486,16 @@
       result = execParserPure (prefs noBacktrack) i ["c", "-b"]
   in assertError result $ \_ -> property succeeded
 
+prop_subparser_inline :: Property
+prop_subparser_inline = once $
+  let p2 = switch (short 'a')
+      p1 = (,)
+        <$> subparser (command "c" (info p2 idm))
+        <*> switch (short 'b')
+      i = info (p1 <**> helper) idm
+      result = execParserPure (prefs subparserInline) i ["c", "-b", "-a" ]
+  in assertResult result ((True, True) ===)
+
 prop_error_context :: Property
 prop_error_context = once $
   let p = pk <$> option auto (long "port")
@@ -667,7 +770,7 @@
       p = argument str idm
       i = info p idm
       result = run i ["testValue"]
-  in assertResult result $ \xs -> fromString t === xs
+  in assertResult result $ \xs -> BS8.pack t === xs
 
 ---
 
@@ -732,7 +835,7 @@
 
 prop_edit_transposition :: [Char] -> [Char] -> Char -> Char -> Property
 prop_edit_transposition as bs a b = a /= b ==>
-  editDistance (as ++ [a] ++ [b] ++ bs) (as ++ [b] ++ [a] ++ bs) === 1
+  editDistance (as ++ [a,b] ++ bs) (as ++ [b,a] ++ bs) === 1
 
 ---
 
