diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,8 @@
+0.1.1
+-----
+* Added `Config.Lens` module
+* Added aligned fields to pretty printer
+
+0.1
+-----
+* Initial release
diff --git a/config-value.cabal b/config-value.cabal
--- a/config-value.cabal
+++ b/config-value.cabal
@@ -1,5 +1,5 @@
 name:                config-value
-version:             0.1
+version:             0.1.1
 synopsis:            Simple, layout-based value language similar to YAML or JSON
 license:             MIT
 license-file:        LICENSE
@@ -17,10 +17,12 @@
                      around strings.
 
 extra-source-files:    README.md
+                       CHANGELOG.md
 
 library
 
-  exposed-modules:     Config
+  exposed-modules:     Config,
+                       Config.Lens
 
   other-modules:       Config.Lexer,
                        Config.Parser,
diff --git a/dist/build/Config/Parser.hs b/dist/build/Config/Parser.hs
--- a/dist/build/Config/Parser.hs
+++ b/dist/build/Config/Parser.hs
@@ -17,9 +17,8 @@
 import qualified Data.Array as Happy_Data_Array
 import qualified GHC.Exts as Happy_GHC_Exts
 import Control.Applicative(Applicative(..))
-import Control.Monad (ap)
 
--- parser produced by Happy Version 1.19.5
+-- parser produced by Happy Version 1.19.4
 
 newtype HappyAbsSyn  = HappyAbsSyn HappyAny
 #if __GLASGOW_HASKELL__ >= 607
diff --git a/src/Config/Lens.hs b/src/Config/Lens.hs
new file mode 100644
--- /dev/null
+++ b/src/Config/Lens.hs
@@ -0,0 +1,69 @@
+{-# LANGUAGE CPP #-}
+
+-- | Optics for compatibility with the lens package
+module Config.Lens
+  ( key
+  , text
+  , number
+  , bool
+  , list
+  , sections
+  ) where
+
+import Config
+
+import Data.Text
+
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative
+import Data.Traversable
+#endif
+
+-- | Apply a function to the subsections of the given value when
+-- that value is a @Sections@ and the subsection name matches the
+-- given section name 
+key ::
+  Applicative f =>
+  Text {- ^ section name -} ->
+  (Value -> f Value) -> Value -> f Value
+key i f (Sections xs) = Sections <$> traverse (section i f) xs
+key _ _ v             = pure v
+
+-- | Apply a function to the 'Value' contained inside the given
+-- 'Value' when it is a section name matches the given name.
+section ::
+  Applicative f =>
+  Text {- ^ section name -} ->
+  (Value -> f Value) -> Section -> f Section
+section i f s@(Section j v) | i == j = Section j <$> f v
+                            | otherwise = pure s
+
+-- | Apply a function to the ['Section'] contained inside the given
+-- 'Value' when it is a @Sections@.
+sections :: Applicative f => ([Section] -> f [Section]) -> Value -> f Value
+sections f (Sections xs) = Sections <$> f xs
+sections _ v             = pure v
+
+-- | Apply a function to the 'Text' contained inside the given
+-- 'Value' when it is a @Text@.
+text :: Applicative f => (Text -> f Text) -> Value -> f Value
+text f (Text t) = Text <$> f t
+text _ v        = pure v
+
+-- | Apply a function to the 'Integer' contained inside the given
+-- 'Value' when it is a @Number@.
+number :: Applicative f => (Integer -> f Integer) -> Value -> f Value
+number f (Number b n) = Number b <$> f n
+number _ v            = pure v
+
+-- | Apply a function to the 'Bool' contained inside the given
+-- 'Value' when it is a @Bool@.
+bool :: Applicative f => (Bool -> f Bool) -> Value -> f Value
+bool f (Bool b) = Bool <$> f b
+bool _ v        = pure v
+
+-- | Apply a function to the ['Value'] contained inside the given
+-- 'Value' when it is a @List@.
+list :: Applicative f => ([Value] -> f [Value]) -> Value -> f Value
+list f (List xs) = List <$> f xs
+list _ v         = pure v
diff --git a/src/Config/Pretty.hs b/src/Config/Pretty.hs
--- a/src/Config/Pretty.hs
+++ b/src/Config/Pretty.hs
@@ -10,14 +10,14 @@
 import Config.Value
 
 -- | Pretty-print a 'Value' as shown in the example.
--- Sections will nest complex values underneat with
+-- Sections will nest complex values underneath with
 -- indentation and simple values will be rendered on
 -- the same line as their section.
 pretty :: Value -> Doc
 pretty value =
   case value of
     Sections [] -> text "{}"
-    Sections xs -> vcat (map prettySection xs)
+    Sections xs -> prettySections xs
     Number b n  -> prettyNum b n
     Text t      -> prettyText (Text.unpack t)
     Bool b      -> if b then text "yes" else text "no"
@@ -46,15 +46,31 @@
           | otherwise = (False, char '\\' <> int (fromEnum x))
 
 
-prettySection :: Section -> Doc
-prettySection s
-  | isBig val = lab $$ nest 2 (pretty val)
-  | otherwise = lab <+> pretty val
+prettySections :: [Section] -> Doc
+prettySections ss = prettySmallSections small $$ rest
+  where
+  (small,big) = break (isBig . sectionValue) ss
+  rest        = case big of
+                  []     -> empty
+                  b : bs -> prettyBigSection b $$ prettySections bs
 
+prettyBigSection :: Section -> Doc
+prettyBigSection s =
+  text (Text.unpack (sectionName s)) <> colon
+  $$ nest 2 (pretty (sectionValue s))
+
+prettySmallSections :: [Section] -> Doc
+prettySmallSections ss = vcat (map pp annotated)
   where
-  lab = text (Text.unpack (sectionName s)) <> colon
-  val = sectionValue s
+  annotate s = (Text.length (sectionName s), s)
+  annotated  = map annotate ss
+  indent     = 1 + maximum (0 : map fst annotated)
+  pp (l,s)   = prettySmallSection (indent - l) s
 
+prettySmallSection :: Int -> Section -> Doc
+prettySmallSection n s =
+  text (Text.unpack (sectionName s)) <> colon <>
+    text (replicate n ' ') <> pretty (sectionValue s)
 
 isBig :: Value -> Bool
 isBig (Sections (_:_))  = True
