diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown
--- a/CHANGELOG.markdown
+++ b/CHANGELOG.markdown
@@ -1,3 +1,15 @@
+0.5.2
+=====
+
+  * Added `eitherReader`. (https://github.com/supki/envparse/pull/24)
+
+0.5.1
+=====
+
+  * Added configurable maximum info block width (https://github.com/supki/envparse/pull/21).
+
+  * Added `instance (Field e a, ...) => Field e (Maybe a)` for generic environment parsing. (https://github.com/supki/envparse/pull/16)
+
 0.5
 ===
 
diff --git a/README.markdown b/README.markdown
--- a/README.markdown
+++ b/README.markdown
@@ -1,5 +1,6 @@
 envparse
 ========
+[![Build status](https://github.com/supki/envparse/actions/workflows/ci.yml/badge.svg)](https://github.com/supki/envparse/actions/workflows/ci.yml)
 
 [optparse-applicative][0], but for environment variables
 
diff --git a/envparse.cabal b/envparse.cabal
--- a/envparse.cabal
+++ b/envparse.cabal
@@ -1,5 +1,5 @@
 name:                envparse
-version:             0.5.0
+version:             0.5.2
 synopsis:            Parse environment variables
 description:
   Here's a simple example of a program that uses @envparse@'s parser:
@@ -69,7 +69,7 @@
 source-repository this
   type:     git
   location: https://github.com/supki/envparse
-  tag:      0.5.0
+  tag:      0.5.2
 
 library
   default-language:
diff --git a/src/Env.hs b/src/Env.hs
--- a/src/Env.hs
+++ b/src/Env.hs
@@ -51,6 +51,7 @@
   , Help.header
   , Help.desc
   , Help.footer
+  , Help.widthMax
   , Help.handleError
   , Help.ErrorHandler
   , Help.defaultErrorHandler
@@ -58,6 +59,7 @@
   , var
   , Var
   , Reader
+  , eitherReader
   , str
   , char
   , nonempty
diff --git a/src/Env/Generic.hs b/src/Env/Generic.hs
--- a/src/Env/Generic.hs
+++ b/src/Env/Generic.hs
@@ -241,6 +241,10 @@
 
 instance (Env.AsUnset e, Env.AsUnread e) => Field e Double
 
+-- | Optional parser.
+instance (Field e a, Env.AsUnset e, Env.AsUnread e) => Field e (Maybe a) where
+  field name help = Env.optional (field name help)
+
 -- | Uses the 'String' value verbatim.
 instance Env.AsUnset e => Field e String where
   field name help =
diff --git a/src/Env/Internal/Help.hs b/src/Env/Internal/Help.hs
--- a/src/Env/Internal/Help.hs
+++ b/src/Env/Internal/Help.hs
@@ -9,6 +9,7 @@
   , header
   , desc
   , footer
+  , widthMax
   , handleError
   ) where
 
@@ -25,35 +26,42 @@
 
 
 helpInfo :: Info e -> Parser e b -> [(String, e)] -> String
-helpInfo Info {infoHeader, infoDesc, infoFooter, infoHandleError} p errors =
+helpInfo Info {infoHeader, infoDesc, infoFooter, infoHandleError, infoWidthMax} p errors =
   List.intercalate "\n\n" $ catMaybes
     [ infoHeader
-    , fmap (List.intercalate "\n" . splitWords 50) infoDesc
-    , Just (helpDoc p)
-    , fmap (List.intercalate "\n" . splitWords 50) infoFooter
+    , fmap (List.intercalate "\n" . splitWords infoWidthMax) infoDesc
+    , Just (helpDoc infoWidthMax p)
+    , fmap (List.intercalate "\n" . splitWords infoWidthMax) infoFooter
     ] ++ helpErrors infoHandleError errors
 
 -- | A pretty-printed list of recognized environment variables suitable for usage messages
-helpDoc :: Parser e a -> String
-helpDoc p =
-  List.intercalate "\n" ("Available environment variables:\n" : helpParserDoc p)
+helpDoc :: Int -> Parser e a -> String
+helpDoc widthMax p =
+  List.intercalate "\n" ("Available environment variables:\n" : helpParserDoc widthMax p)
 
-helpParserDoc :: Parser e a -> [String]
-helpParserDoc =
-  concat . Map.elems . foldAlt (\v -> Map.singleton (varfName v) (helpVarfDoc v)) . unParser
+helpParserDoc :: Int -> Parser e a -> [String]
+helpParserDoc widthMax =
+  concat . Map.elems . foldAlt (\v -> Map.singleton (varfName v) (helpVarfDoc widthMax v)) . unParser
 
-helpVarfDoc :: VarF e a -> [String]
-helpVarfDoc VarF {varfName, varfHelp, varfHelpDef} =
+helpVarfDoc :: Int -> VarF e a -> [String]
+helpVarfDoc widthMax VarF {varfName, varfHelp, varfHelpDef} =
   case varfHelp of
-    Nothing -> [indent 2 varfName]
+    Nothing -> [indent vo varfName]
     Just h
-      | k > 15    -> indent 2 varfName : map (indent 25) (splitWords 30 t)
+      | k > nameWidthMax ->
+          indent vo varfName : map (indent ho) (splitWords (widthMax - ho) t)
       | otherwise ->
-          case zipWith indent (23 - k : repeat 25) (splitWords 30 t) of
-            (x : xs) -> (indent 2 varfName ++ x) : xs
-            []       -> [indent 2 varfName]
-     where k = length varfName
-           t = maybe h (\s -> h ++ " (default: " ++ s ++")") varfHelpDef
+          case zipWith indent (ho - vo - k : repeat ho) (splitWords (widthMax - ho) t) of
+            (x : xs) -> (indent vo varfName ++ x) : xs
+            []       -> [indent vo varfName]
+     where
+      k = length varfName
+      t = maybe h (\s -> h ++ " (default: " ++ s ++")") varfHelpDef
+ where
+  -- The longest variable name that fits the compact view.
+  nameWidthMax = ho - vo - 1 {- the space between the variable name and the help text -}
+  vo = 2  -- variable name offset
+  ho = 25 -- help text offset
 
 splitWords :: Int -> String -> [String]
 splitWords n =
@@ -87,6 +95,7 @@
   , infoDesc        :: Maybe String
   , infoFooter      :: Maybe String
   , infoHandleError :: ErrorHandler e
+  , infoWidthMax    :: Int
   }
 
 -- | Given a variable name and an error value, try to produce a useful error message
@@ -98,6 +107,7 @@
   , infoDesc = Nothing
   , infoFooter = Nothing
   , infoHandleError = defaultErrorHandler
+  , infoWidthMax = 80
   }
 
 -- | Set the help text header (it usually includes the application's name and version)
@@ -111,6 +121,12 @@
 -- | Set the help text footer (it usually includes examples)
 footer :: String -> Info e -> Info e
 footer h i = i {infoFooter=Just h}
+
+-- | Set the max info width.
+--
+-- /Note:/ It will be set to 26 columns if a smaller value is passed.
+widthMax :: Int -> Info e -> Info e
+widthMax n i = i {infoWidthMax=max 26 n}
 
 -- | An error handler
 handleError :: ErrorHandler e -> Info x -> Info e
diff --git a/src/Env/Internal/Parser.hs b/src/Env/Internal/Parser.hs
--- a/src/Env/Internal/Parser.hs
+++ b/src/Env/Internal/Parser.hs
@@ -14,6 +14,7 @@
   , Var(..)
   , defaultVar
   , Reader
+  , eitherReader
   , str
   , char
   , nonempty
@@ -124,6 +125,13 @@
 
 -- | An environment variable's value parser. Use @(<=<)@ and @(>=>)@ to combine these
 type Reader e a = String -> Either e a
+
+-- | Create a 'Reader' from a simple parser function
+eitherReader :: Error.AsUnread e => (String -> Either String a) -> Reader e a
+eitherReader f s =
+  left (Error.unread . suffix) (f s)
+ where
+  suffix x = x <> ": " <> show s
 
 -- | Parse a particular variable from the environment
 --
