diff --git a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,15 @@
 # CHANGELOG
 
+- 0.10.0.0 (2020-01-26)
+    * Switch to HsYAML library (by vijayphoenix)
+    * Expose `format` from main library (by Łukasz Gołębiewski)
+    * Support record formatting (by Łukasz Gołębiewski and Pawel Szulc)
+    * Allow setting `columns` to `null` to disable all wrapping (by Chris
+      Martin)
+    * Bump `haskell-src-exts` to 1.23
+    * New logo (by Jose Fernando García Parreño)
+    * Make language extension prefix configurable (by Flavio Corpa)
+
 - 0.9.4.4 (2019-11-03)
     * Bump `haskell-src-exts` to 1.22
 
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,5 @@
 Copyright (c) 2012, Jasper Van der Jeugt <m@jaspervdj.be>
+Copyright (c) 2016, 2018 Sean Whitton <spwhitton@spwhitton.name>
 
 All rights reserved.
 
diff --git a/README.markdown b/README.markdown
--- a/README.markdown
+++ b/README.markdown
@@ -1,10 +1,10 @@
-stylish-haskell
-===============
+## stylish-haskell
 
+<img src="./assets/Logo/SVG/RoundedLogo.svg" width="100px">
+
 [![Build Status](https://img.shields.io/circleci/project/github/jaspervdj/stylish-haskell.svg)](https://circleci.com/gh/jaspervdj/stylish-haskell)
 
-Introduction
-------------
+## Introduction
 
 A simple Haskell code prettifier. The goal is not to format all of the code in
 a file, since I find those kind of tools often "get in the way". However,
@@ -12,19 +12,18 @@
 
 This tool tries to help where necessary without getting in the way.
 
-Installation
-------------
+## Installation
 
 You can install it using `stack install stylish-haskell` or `cabal install stylish-haskell`.
 
 You can also install it using your package manager:
- * Debian 9 or later: `apt-get install stylish-haskell`
- * Ubuntu 16.10 or later: `apt-get install stylish-haskell`
- * Arch Linux: `pacman -S stylish-haskell`
 
-Features
---------
+- Debian 9 or later: `apt-get install stylish-haskell`
+- Ubuntu 16.10 or later: `apt-get install stylish-haskell`
+- Arch Linux: `pacman -S stylish-haskell`
 
+## Features
+
 - Aligns and sorts `import` statements
 - Groups and wraps `{-# LANGUAGE #-}` pragmas, can remove (some) redundant
   pragmas
@@ -39,8 +38,7 @@
 
 [issue tracker]: https://github.com/jaspervdj/stylish-haskell/issues
 
-Example
--------
+## Example
 
 Turns:
 
@@ -58,10 +56,7 @@
 import qualified Data.Map as M
 import      Data.Map    ((!), keys, Map)
 
-data Point = Point
-    { pointX, pointY :: Double
-    , pointName :: String
-    } deriving (Show)
+data Point = Point { pointX, pointY :: Double , pointName :: String} deriving (Show)
 ```
 
 into:
@@ -84,9 +79,9 @@
     , pointName      :: String
     } deriving (Show)
 ```
-Configuration
--------------
 
+## Configuration
+
 The tool is customizable to some extent. It tries to find a config file in the
 following order:
 
@@ -107,8 +102,7 @@
 well-documented default configuration to a file, this way you can get started
 quickly.
 
-VIM integration
----------------
+## VIM integration
 
 Since it works as a filter it is pretty easy to integrate this with VIM.
 
@@ -136,14 +130,13 @@
 There are also plugins that run stylish-haskell automatically when you save a
 Haskell file:
 
-* [vim-stylish-haskell]
-* [vim-stylishask]
+- [vim-stylish-haskell]
+- [vim-stylishask]
 
 [vim-stylish-haskell]: https://github.com/nbouscal/vim-stylish-haskell
 [vim-stylishask]: https://github.com/alx741/vim-stylishask
 
-Emacs integration
------------------
+## Emacs integration
 
 [haskell-mode] for Emacs supports `stylish-haskell`. For configuration,
 see [the “Using external formatters” section][haskell-mode/format] of the
@@ -152,8 +145,7 @@
 [haskell-mode]: https://github.com/haskell/haskell-mode
 [haskell-mode/format]: http://haskell.github.io/haskell-mode/manual/latest/Autoformating.html
 
-Atom integration
-----------------
+## Atom integration
 
 [ide-haskell] for Atom supports `stylish-haskell`.
 
@@ -162,15 +154,13 @@
 [ide-haskell]: https://atom.io/packages/ide-haskell
 [atom-beautify]: Https://atom.io/packages/atom-beautify
 
-Visual Studio Code integration
-------------------------------
+## Visual Studio Code integration
 
 [stylish-haskell-vscode] for VSCode supports `stylish-haskell`.
 
 [stylish-haskell-vscode]: https://github.com/vigoo/stylish-haskell-vscode
 
-Using with Continuous Integration
----------------------------------
+## Using with Continuous Integration
 
 You can quickly grab the latest binary and run `stylish-haskell` like so:
 
@@ -178,8 +168,7 @@
 
 Where the `.` can be replaced with the arguments you pass to `stylish-haskell`.
 
-Credits
--------
+## Credits
 
 Written and maintained by Jasper Van der Jeugt.
 
diff --git a/data/stylish-haskell.yaml b/data/stylish-haskell.yaml
--- a/data/stylish-haskell.yaml
+++ b/data/stylish-haskell.yaml
@@ -15,6 +15,9 @@
   #     # true.
   #     add_language_pragma: true
 
+  # Format record definitions
+  - records: {}
+
   # Align the right hand side of some elements.  This is quite conservative
   # and only applies to statements where each element occupies a single
   # line. All default to true.
@@ -203,6 +206,11 @@
       # is set to true, it will remove those redundant pragmas. Default: true.
       remove_redundant: true
 
+      # Language prefix to be used for pragma declaration, this allows you to
+      # use other options non case-sensitive like "language" or "Language".
+      # If a non correct String is provided, it will default to: LANGUAGE.
+      language_prefix: LANGUAGE
+
   # Replace tabs by spaces. This is disabled by default.
   # - tabs:
   #     # Number of spaces to use for each tab. Default: 8, as specified by the
@@ -217,8 +225,15 @@
   # simple_align but is a bit less conservative.
   # - squash: {}
 
+# A common indentation setting. Different steps take this into account.
+indent: 4
+
 # A common setting is the number of columns (parts of) code will be wrapped
-# to. Different steps take this into account. Default: 80.
+# to. Different steps take this into account.
+#
+# Set this to null to disable all line wrapping.
+#
+# Default: 80.
 columns: 80
 
 # By default, line endings are converted according to the OS. You can override
diff --git a/lib/Language/Haskell/Stylish.hs b/lib/Language/Haskell/Stylish.hs
--- a/lib/Language/Haskell/Stylish.hs
+++ b/lib/Language/Haskell/Stylish.hs
@@ -16,6 +16,8 @@
       -- * Misc
     , module Language.Haskell.Stylish.Verbose
     , version
+    , format
+    , ConfigPath(..)
     , Lines
     , Step
     ) where
@@ -40,24 +42,25 @@
 
 
 --------------------------------------------------------------------------------
-simpleAlign :: Int  -- ^ Columns
+simpleAlign :: Maybe Int  -- ^ Columns
             -> SimpleAlign.Config
             -> Step
 simpleAlign = SimpleAlign.step
 
 
 --------------------------------------------------------------------------------
-imports :: Int -- ^ columns
+imports :: Maybe Int -- ^ columns
         -> Imports.Options
         -> Step
 imports = Imports.step
 
 
 --------------------------------------------------------------------------------
-languagePragmas :: Int -- ^ columns
+languagePragmas :: Maybe Int -- ^ columns
                 -> LanguagePragmas.Style
                 -> Bool -- ^ Pad to same length in vertical mode?
                 -> Bool -- ^ remove redundant?
+                -> String -- ^ language prefix
                 -> Step
 languagePragmas = LanguagePragmas.step
 
@@ -75,6 +78,7 @@
 
 --------------------------------------------------------------------------------
 unicodeSyntax :: Bool -- ^ add language pragma?
+              -> String -- ^ language prefix
               -> Step
 unicodeSyntax = UnicodeSyntax.step
 
@@ -89,3 +93,13 @@
 runSteps :: Extensions -> Maybe FilePath -> [Step] -> Lines
          -> Either String Lines
 runSteps exts mfp steps ls = foldM (runStep exts mfp) ls steps
+
+newtype ConfigPath = ConfigPath { unConfigPath :: FilePath }
+
+-- |Formats given contents optionally using the config provided as first param.
+-- The second file path is the location from which the contents were read.
+-- If provided, it's going to be printed out in the error message.
+format :: Maybe ConfigPath -> Maybe FilePath -> String -> IO (Either String Lines)
+format maybeConfigPath maybeFilePath contents = do
+  conf <- loadConfig (makeVerbose True) (fmap unConfigPath maybeConfigPath)
+  pure $ runSteps (configLanguageExtensions conf) maybeFilePath (configSteps conf) $ lines contents
diff --git a/lib/Language/Haskell/Stylish/Align.hs b/lib/Language/Haskell/Stylish/Align.hs
--- a/lib/Language/Haskell/Stylish/Align.hs
+++ b/lib/Language/Haskell/Stylish/Align.hs
@@ -55,16 +55,21 @@
 --------------------------------------------------------------------------------
 -- | Create changes that perform the alignment.
 align
-    :: Int                    -- ^ Max columns
+    :: Maybe Int              -- ^ Max columns
     -> [Alignable H.SrcSpan]  -- ^ Alignables
     -> [Change String]        -- ^ Changes performing the alignment.
 align _ [] = []
 align maxColumns alignment
     -- Do not make any change if we would go past the maximum number of columns.
-    | longestLeft + longestRight > maxColumns = []
-    | not (fixable alignment)                 = []
-    | otherwise                               = map align' alignment
+    | exceedsColumns (longestLeft + longestRight) = []
+    | not (fixable alignment)                     = []
+    | otherwise                                   = map align' alignment
   where
+    exceedsColumns i = case maxColumns of
+        Nothing -> False  -- No number exceeds a maximum column count of
+                          -- Nothing, because there is no limit to exceed.
+        Just c -> i > c
+
     -- The longest thing in the left column.
     longestLeft = maximum $ map (H.srcSpanEndColumn . aLeft) alignment
 
diff --git a/lib/Language/Haskell/Stylish/Config.hs b/lib/Language/Haskell/Stylish/Config.hs
--- a/lib/Language/Haskell/Stylish/Config.hs
+++ b/lib/Language/Haskell/Stylish/Config.hs
@@ -16,14 +16,16 @@
 import qualified Data.Aeson                                       as A
 import qualified Data.Aeson.Types                                 as A
 import qualified Data.ByteString                                  as B
+import           Data.ByteString.Lazy                             (fromStrict)
+import           Data.Char                                        (toLower)
 import qualified Data.FileEmbed                                   as FileEmbed
 import           Data.List                                        (intercalate,
                                                                    nub)
 import           Data.Map                                         (Map)
 import qualified Data.Map                                         as M
 import           Data.Maybe                                       (fromMaybe)
-import           Data.Yaml                                        (decodeEither',
-                                                                   prettyPrintParseException)
+import           Data.YAML                                        (prettyPosWithSource)
+import           Data.YAML.Aeson                                  (decode1Strict)
 import           System.Directory
 import           System.FilePath                                  ((</>))
 import qualified System.IO                                        as IO (Newline (..),
@@ -34,6 +36,7 @@
 import qualified Language.Haskell.Stylish.Config.Cabal            as Cabal
 import           Language.Haskell.Stylish.Config.Internal
 import           Language.Haskell.Stylish.Step
+import qualified Language.Haskell.Stylish.Step.Data               as Data
 import qualified Language.Haskell.Stylish.Step.Imports            as Imports
 import qualified Language.Haskell.Stylish.Step.LanguagePragmas    as LanguagePragmas
 import qualified Language.Haskell.Stylish.Step.SimpleAlign        as SimpleAlign
@@ -51,7 +54,8 @@
 --------------------------------------------------------------------------------
 data Config = Config
     { configSteps              :: [Step]
-    , configColumns            :: Int
+    , configIndent             :: Int
+    , configColumns            :: Maybe Int
     , configLanguageExtensions :: [String]
     , configNewline            :: IO.Newline
     , configCabal              :: Bool
@@ -80,12 +84,10 @@
     current    <- getCurrentDirectory
     configPath <- getXdgDirectory XdgConfig "stylish-haskell"
     home       <- getHomeDirectory
-    mbConfig   <- search verbose $
+    search verbose $
         [d </> configFileName | d <- ancestors current] ++
         [configPath </> "config.yaml", home </> configFileName]
 
-    return mbConfig
-
 search :: Verbose -> [FilePath] -> IO (Maybe FilePath)
 search _ []             = return Nothing
 search verbose (f : fs) = do
@@ -100,9 +102,8 @@
     mbFp <- configFilePath verbose userSpecified
     verbose $ "Loading configuration at " ++ fromMaybe "<embedded>" mbFp
     bytes <- maybe (return defaultConfigBytes) B.readFile mbFp
-    case decodeEither' bytes of
-        Left err     -> error $
-            "Language.Haskell.Stylish.Config.loadConfig: " ++ prettyPrintParseException err
+    case decode1Strict bytes of
+        Left (pos, err)     -> error $ prettyPosWithSource pos (fromStrict bytes) ("Language.Haskell.Stylish.Config.loadConfig: " ++ err)
         Right config -> do
           cabalLanguageExtensions <- if configCabal config
             then map show <$> Cabal.findLanguageExtensions verbose
@@ -120,7 +121,8 @@
     -- First load the config without the actual steps
     config <- Config
         <$> pure []
-        <*> (o A..:? "columns"             A..!= 80)
+        <*> (o A..:? "indent"              A..!= 4)
+        <*> (o A..:! "columns"             A..!= Just 80)
         <*> (o A..:? "language_extensions" A..!= [])
         <*> (o A..:? "newline"             >>= parseEnum newlines IO.nativeNewline)
         <*> (o A..:? "cabal"               A..!= True)
@@ -142,6 +144,7 @@
 catalog :: Map String (Config -> A.Object -> A.Parser Step)
 catalog = M.fromList
     [ ("imports",             parseImports)
+    , ("records",             parseRecords)
     , ("language_pragmas",    parseLanguagePragmas)
     , ("simple_align",        parseSimpleAlign)
     , ("squash",              parseSquash)
@@ -181,7 +184,12 @@
   where
     withDef f k = fromMaybe (f SimpleAlign.defaultConfig) <$> (o A..:? k)
 
+--------------------------------------------------------------------------------
+parseRecords :: Config -> A.Object -> A.Parser Step
+parseRecords c _ = Data.step
+    <$> pure (configIndent c)
 
+
 --------------------------------------------------------------------------------
 parseSquash :: Config -> A.Object -> A.Parser Step
 parseSquash _ _ = return Squash.step
@@ -200,9 +208,9 @@
         -- Note that padding has to be at least 1. Default is 4.
         <*> (o A..:? "empty_list_align"
             >>= parseEnum emptyListAligns (def Imports.emptyListAlign))
-        <*> o A..:? "list_padding" A..!= (def Imports.listPadding)
-        <*> o A..:? "separate_lists" A..!= (def Imports.separateLists)
-        <*> o A..:? "space_surround" A..!= (def Imports.spaceSurround))
+        <*> o A..:? "list_padding" A..!= def Imports.listPadding
+        <*> o A..:? "separate_lists" A..!= def Imports.separateLists
+        <*> o A..:? "space_surround" A..!= def Imports.spaceSurround)
   where
     def f = f Imports.defaultOptions
 
@@ -237,8 +245,9 @@
 parseLanguagePragmas config o = LanguagePragmas.step
     <$> pure (configColumns config)
     <*> (o A..:? "style" >>= parseEnum styles LanguagePragmas.Vertical)
-    <*> o A..:? "align" A..!= True
+    <*> o A..:? "align"            A..!= True
     <*> o A..:? "remove_redundant" A..!= True
+    <*> mkLanguage o
   where
     styles =
         [ ("vertical",     LanguagePragmas.Vertical)
@@ -248,6 +257,19 @@
 
 
 --------------------------------------------------------------------------------
+-- | Utilities for validating language prefixes
+mkLanguage :: A.Object -> A.Parser String
+mkLanguage o = do
+    lang <- o A..:? "language_prefix"
+    maybe (pure "LANGUAGE") validate lang
+    where
+        validate :: String -> A.Parser String
+        validate s
+            | fmap toLower s == "language" = pure s
+            | otherwise = fail "please provide a valid language prefix"
+
+
+--------------------------------------------------------------------------------
 parseTabs :: Config -> A.Object -> A.Parser Step
 parseTabs _ o = Tabs.step
     <$> o A..:? "spaces" A..!= 8
@@ -262,3 +284,4 @@
 parseUnicodeSyntax :: Config -> A.Object -> A.Parser Step
 parseUnicodeSyntax _ o = UnicodeSyntax.step
     <$> o A..:? "add_language_pragma" A..!= True
+    <*> mkLanguage o
diff --git a/lib/Language/Haskell/Stylish/Editor.hs b/lib/Language/Haskell/Stylish/Editor.hs
--- a/lib/Language/Haskell/Stylish/Editor.hs
+++ b/lib/Language/Haskell/Stylish/Editor.hs
@@ -1,3 +1,5 @@
+{-# language LambdaCase #-}
+
 --------------------------------------------------------------------------------
 -- | This module provides you with a line-based editor. It's main feature is
 -- that you can specify multiple changes at the same time, e.g.:
@@ -19,8 +21,7 @@
 
 
 --------------------------------------------------------------------------------
-import           Data.List                      (intercalate, sortBy)
-import           Data.Ord                       (comparing)
+import           Data.List                      (intercalate, sortOn)
 
 
 --------------------------------------------------------------------------------
@@ -31,7 +32,7 @@
 -- | Changes the lines indicated by the 'Block' into the given 'Lines'
 data Change a = Change
     { changeBlock :: Block a
-    , changeLines :: ([a] -> [a])
+    , changeLines :: [a] -> [a]
     }
 
 
@@ -49,7 +50,7 @@
         intercalate ", " (map printBlock blocks)
     | otherwise          = go 1 changes1
   where
-    changes1 = sortBy (comparing (blockStart . changeBlock)) changes0
+    changes1 = sortOn (blockStart . changeBlock) changes0
     blocks   = map changeBlock changes1
 
     printBlock b = show (blockStart b) ++ "-" ++ show (blockEnd b)
@@ -87,7 +88,7 @@
 --------------------------------------------------------------------------------
 -- | Change a single line for some other lines
 changeLine :: Int -> (a -> [a]) -> Change a
-changeLine start f = change (Block start start) $ \xs -> case xs of
+changeLine start f = change (Block start start) $ \case
     []      -> []
     (x : _) -> f x
 
diff --git a/lib/Language/Haskell/Stylish/Step/Data.hs b/lib/Language/Haskell/Stylish/Step/Data.hs
new file mode 100644
--- /dev/null
+++ b/lib/Language/Haskell/Stylish/Step/Data.hs
@@ -0,0 +1,74 @@
+module Language.Haskell.Stylish.Step.Data where
+
+import           Data.List                       (find, intercalate)
+import           Data.Maybe                      (maybeToList)
+import qualified Language.Haskell.Exts           as H
+import           Language.Haskell.Exts.Comments
+import           Language.Haskell.Stylish.Block
+import           Language.Haskell.Stylish.Editor
+import           Language.Haskell.Stylish.Step
+import           Language.Haskell.Stylish.Util
+import           Prelude                         hiding (init)
+
+datas :: H.Module l -> [H.Decl l]
+datas (H.Module _ _ _ _ decls) = decls
+datas _                        = []
+
+type ChangeLine = Change String
+
+step :: Int -> Step
+step indentSize = makeStep "Data" (step' indentSize)
+
+step' :: Int -> Lines -> Module -> Lines
+step' indentSize ls (module', allComments) = applyChanges changes ls
+  where
+    datas' = datas $ fmap linesFromSrcSpan module'
+    changes = datas' >>= maybeToList . changeDecl allComments indentSize
+
+findCommentOnLine :: LineBlock -> [Comment] -> Maybe Comment
+findCommentOnLine lb = find commentOnLine
+  where
+    commentOnLine (Comment _ (H.SrcSpan _ start _ end _) _) =
+      blockStart lb == start && blockEnd lb == end
+
+findCommentBelowLine :: LineBlock -> [Comment] -> Maybe Comment
+findCommentBelowLine lb = find commentOnLine
+  where
+    commentOnLine (Comment _ (H.SrcSpan _ start _ end _) _) =
+      blockStart lb == start - 1 && blockEnd lb == end - 1
+
+commentsWithin :: LineBlock -> [Comment] -> [Comment]
+commentsWithin lb = filter within
+  where
+    within (Comment _ (H.SrcSpan _ start _ end _) _) =
+      start >= blockStart lb && end <= blockEnd lb
+
+changeDecl :: [Comment] -> Int -> H.Decl LineBlock -> Maybe ChangeLine
+changeDecl _ _ (H.DataDecl _ (H.DataType _) Nothing _ [] _) = Nothing
+changeDecl allComments indentSize (H.DataDecl block (H.DataType _) Nothing dhead decls derivings) =
+  Just $ change block (const $ concat newLines)
+  where
+    newLines = fmap constructors zipped ++ [fmap (indented . H.prettyPrint) derivings]
+    zipped = zip decls ([1..] ::[Int])
+    constructors (decl, 1) = processConstructor allComments typeConstructor indentSize decl
+    constructors (decl, _) = processConstructor allComments (indented "| ") indentSize decl
+    typeConstructor = "data " <> H.prettyPrint dhead <> " = "
+    indented = indent indentSize
+changeDecl _ _ _ = Nothing
+
+processConstructor :: [Comment] -> String -> Int -> H.QualConDecl LineBlock -> [String]
+processConstructor allComments init indentSize (H.QualConDecl _ _ _ (H.RecDecl _ dname fields)) = do
+  init <> H.prettyPrint dname : n1 ++ ns ++ [indented "}"]
+  where
+    n1 = processName "{ " ( extractField $ head fields)
+    ns = tail fields >>= (processName ", " . extractField)
+    processName prefix (fnames, _type, lineComment, commentBelowLine) =
+      [indented prefix <> intercalate ", " (fmap H.prettyPrint fnames) <> " :: " <> H.prettyPrint _type <> addLineComment lineComment] ++ addCommentBelow commentBelowLine
+    addLineComment (Just (Comment _ _ c)) = " --" <> c
+    addLineComment Nothing                = ""
+    addCommentBelow Nothing                = []
+    addCommentBelow (Just (Comment _ _ c)) = [indented "--" <> c]
+    extractField (H.FieldDecl lb names _type) =
+      (names, _type, findCommentOnLine lb allComments, findCommentBelowLine lb allComments)
+    indented = indent indentSize
+processConstructor _ init _ decl = [init <> trimLeft (H.prettyPrint decl)]
diff --git a/lib/Language/Haskell/Stylish/Step/Imports.hs b/lib/Language/Haskell/Stylish/Step/Imports.hs
--- a/lib/Language/Haskell/Stylish/Step/Imports.hs
+++ b/lib/Language/Haskell/Stylish/Step/Imports.hs
@@ -258,7 +258,7 @@
 
 --------------------------------------------------------------------------------
 prettyImport :: (Ord l, Show l) =>
-    Int -> Options -> Bool -> Bool -> Int -> H.ImportDecl l -> [String]
+    Maybe Int -> Options -> Bool -> Bool -> Int -> H.ImportDecl l -> [String]
 prettyImport columns Options{..} padQualified padName longest imp
     | (void `fmap` H.importSpecs imp) == emptyImportSpec = emptyWrap
     | otherwise = case longListAlign of
@@ -277,7 +277,7 @@
     longListWrapper shortWrap longWrap
         | listAlign == NewLine
         || length shortWrap > 1
-        || length (head shortWrap) > columns
+        || exceedsColumns (length (head shortWrap))
             = longWrap
         | otherwise = shortWrap
 
@@ -292,14 +292,14 @@
         . withLast (++ (maybeSpace ++ ")"))
 
     inlineWrapper = case listAlign of
-        NewLine        -> (paddedNoSpecBase :) . wrapRest columns listPadding'
-        WithModuleName -> wrap columns paddedBase (withModuleNameBaseLength + 4)
-        WithAlias      -> wrap columns paddedBase (inlineBaseLength + 1)
+        NewLine        -> (paddedNoSpecBase :) . wrapRestMaybe columns listPadding'
+        WithModuleName -> wrapMaybe columns paddedBase (withModuleNameBaseLength + 4)
+        WithAlias      -> wrapMaybe columns paddedBase (inlineBaseLength + 1)
         -- Add 1 extra space to ensure same padding as in original code.
         AfterAlias     -> withTail ((' ' : maybeSpace) ++)
-            . wrap columns paddedBase (afterAliasBaseLength + 1)
+            . wrapMaybe columns paddedBase (afterAliasBaseLength + 1)
 
-    inlineWithBreakWrap = paddedNoSpecBase : wrapRest columns listPadding'
+    inlineWithBreakWrap = paddedNoSpecBase : wrapRestMaybe columns listPadding'
         ( mapSpecs
         $ withInit (++ ",")
         . withHead (("(" ++ maybeSpace) ++)
@@ -307,7 +307,7 @@
 
     inlineToMultilineWrap
         | length inlineWithBreakWrap > 2
-        || any ((> columns) . length) (tail inlineWithBreakWrap)
+        || any (exceedsColumns . length) (tail inlineWithBreakWrap)
             = multilineWrap
         | otherwise = inlineWithBreakWrap
 
@@ -389,9 +389,14 @@
         True  -> " "
         False -> ""
 
+    exceedsColumns i = case columns of
+        Nothing -> False  -- No number exceeds a maximum column count of
+                          -- Nothing, because there is no limit to exceed.
+        Just c -> i > c
 
+
 --------------------------------------------------------------------------------
-prettyImportGroup :: Int -> Options -> Bool -> Int
+prettyImportGroup :: Maybe Int -> Options -> Bool -> Int
                   -> [H.ImportDecl LineBlock]
                   -> Lines
 prettyImportGroup columns align fileAlign longest imps =
@@ -415,12 +420,12 @@
 
 
 --------------------------------------------------------------------------------
-step :: Int -> Options -> Step
+step :: Maybe Int -> Options -> Step
 step columns = makeStep "Imports" . step' columns
 
 
 --------------------------------------------------------------------------------
-step' :: Int -> Options -> Lines -> Module -> Lines
+step' :: Maybe Int -> Options -> Lines -> Module -> Lines
 step' columns align ls (module', _) = applyChanges
     [ change block $ const $
         prettyImportGroup columns align fileAlign longest importGroup
diff --git a/lib/Language/Haskell/Stylish/Step/LanguagePragmas.hs b/lib/Language/Haskell/Stylish/Step/LanguagePragmas.hs
--- a/lib/Language/Haskell/Stylish/Step/LanguagePragmas.hs
+++ b/lib/Language/Haskell/Stylish/Step/LanguagePragmas.hs
@@ -2,7 +2,6 @@
 module Language.Haskell.Stylish.Step.LanguagePragmas
     ( Style (..)
     , step
-
       -- * Utilities
     , addLanguagePragma
     ) where
@@ -42,9 +41,9 @@
 
 
 --------------------------------------------------------------------------------
-verticalPragmas :: Int -> Bool -> [String] -> Lines
-verticalPragmas longest align pragmas' =
-    [ "{-# LANGUAGE " ++ pad pragma ++ " #-}"
+verticalPragmas :: String -> Int -> Bool -> [String] -> Lines
+verticalPragmas lg longest align pragmas' =
+    [ "{-# " ++ lg ++ " " ++ pad pragma ++ " #-}"
     | pragma <- pragmas'
     ]
   where
@@ -54,27 +53,23 @@
 
 
 --------------------------------------------------------------------------------
-compactPragmas :: Int -> [String] -> Lines
-compactPragmas columns pragmas' = wrap columns "{-# LANGUAGE" 13 $
+compactPragmas :: String -> Maybe Int -> [String] -> Lines
+compactPragmas lg columns pragmas' = wrapMaybe columns ("{-# " ++ lg) 13 $
     map (++ ",") (init pragmas') ++ [last pragmas' ++ " #-}"]
 
 
 --------------------------------------------------------------------------------
-compactLinePragmas :: Int -> Bool -> [String] -> Lines
-compactLinePragmas _ _ [] = []
-compactLinePragmas columns align pragmas' = map (wrapLanguage . pad) prags
+compactLinePragmas :: String -> Maybe Int -> Bool -> [String] -> Lines
+compactLinePragmas _  _ _ [] = []
+compactLinePragmas lg columns align pragmas' = map (wrapLanguage . pad) prags
   where
-    wrapLanguage ps = "{-# LANGUAGE" ++ ps ++  " #-}"
-
-    maxWidth = columns - 16
-
+    wrapLanguage ps = "{-# " ++ lg ++ ps ++  " #-}"
+    maxWidth = fmap (\c -> c - 16) columns
     longest  = maximum $ map length prags
-
     pad
       | align = padRight longest
       | otherwise = id
-
-    prags = map truncateComma $ wrap maxWidth "" 1 $
+    prags = map truncateComma $ wrapMaybe maxWidth "" 1 $
       map (++ ",") (init pragmas') ++ [last pragmas']
 
 
@@ -87,10 +82,10 @@
 
 
 --------------------------------------------------------------------------------
-prettyPragmas :: Int -> Int -> Bool -> Style -> [String] -> Lines
-prettyPragmas _    longest align Vertical    = verticalPragmas longest align
-prettyPragmas cols _       _     Compact     = compactPragmas cols
-prettyPragmas cols _       align CompactLine = compactLinePragmas cols align
+prettyPragmas :: String -> Maybe Int -> Int -> Bool -> Style -> [String] -> Lines
+prettyPragmas lp _    longest align Vertical    = verticalPragmas lp longest align
+prettyPragmas lp cols _       _     Compact     = compactPragmas lp cols
+prettyPragmas lp cols _       align CompactLine = compactLinePragmas lp cols align
 
 
 --------------------------------------------------------------------------------
@@ -110,35 +105,34 @@
         known' = xs' `S.union` known
 
 --------------------------------------------------------------------------------
-step :: Int -> Style -> Bool -> Bool -> Step
-step = (((makeStep "LanguagePragmas" .) .) .) . step'
+step :: Maybe Int -> Style -> Bool -> Bool -> String -> Step
+step = ((((makeStep "LanguagePragmas" .) .) .) .) . step'
 
 
 --------------------------------------------------------------------------------
-step' :: Int -> Style -> Bool -> Bool -> Lines -> Module -> Lines
-step' columns style align removeRedundant ls (module', _)
+step' :: Maybe Int -> Style -> Bool -> Bool -> String -> Lines -> Module -> Lines
+step' columns style align removeRedundant lngPrefix ls (module', _)
     | null pragmas' = ls
     | otherwise     = applyChanges changes ls
   where
     isRedundant'
         | removeRedundant = isRedundant module'
         | otherwise       = const False
-
     pragmas' = pragmas $ fmap linesFromSrcSpan module'
     longest  = maximum $ map length $ snd =<< pragmas'
     groups   = [(b, concat pgs) | (b, pgs) <- groupAdjacent pragmas']
     changes  =
-        [ change b (const $ prettyPragmas columns longest align style pg)
+        [ change b (const $ prettyPragmas lngPrefix columns longest align style pg)
         | (b, pg) <- filterRedundant isRedundant' groups
         ]
 
 
 --------------------------------------------------------------------------------
 -- | Add a LANGUAGE pragma to a module if it is not present already.
-addLanguagePragma :: String -> H.Module H.SrcSpanInfo -> [Change String]
-addLanguagePragma prag modu
+addLanguagePragma :: String -> String -> H.Module H.SrcSpanInfo -> [Change String]
+addLanguagePragma lg prag modu
     | prag `elem` present = []
-    | otherwise           = [insert line ["{-# LANGUAGE " ++ prag ++ " #-}"]]
+    | otherwise           = [insert line ["{-# " ++ lg ++ " " ++ prag ++ " #-}"]]
   where
     pragmas' = pragmas (fmap linesFromSrcSpan modu)
     present  = concatMap snd pragmas'
@@ -158,7 +152,7 @@
 -- | Check if the ViewPatterns language pragma is redundant.
 isRedundantViewPatterns :: H.Module H.SrcSpanInfo -> Bool
 isRedundantViewPatterns m = null
-    [() | H.PViewPat _ _ _ <- everything m :: [H.Pat H.SrcSpanInfo]]
+    [() | H.PViewPat {} <- everything m :: [H.Pat H.SrcSpanInfo]]
 
 
 --------------------------------------------------------------------------------
diff --git a/lib/Language/Haskell/Stylish/Step/SimpleAlign.hs b/lib/Language/Haskell/Stylish/Step/SimpleAlign.hs
--- a/lib/Language/Haskell/Stylish/Step/SimpleAlign.hs
+++ b/lib/Language/Haskell/Stylish/Step/SimpleAlign.hs
@@ -108,7 +108,7 @@
 
 
 --------------------------------------------------------------------------------
-step :: Int -> Config -> Step
+step :: Maybe Int -> Config -> Step
 step maxColumns config = makeStep "Cases" $ \ls (module', _) ->
     let module''               = fmap H.srcInfoSpan module'
         changes search toAlign =
diff --git a/lib/Language/Haskell/Stylish/Step/UnicodeSyntax.hs b/lib/Language/Haskell/Stylish/Step/UnicodeSyntax.hs
--- a/lib/Language/Haskell/Stylish/Step/UnicodeSyntax.hs
+++ b/lib/Language/Haskell/Stylish/Step/UnicodeSyntax.hs
@@ -39,12 +39,12 @@
 replaceAll = map changeLine'
   where
     changeLine' (r, ns) = changeLine r $ \str -> return $
-        flip applyChanges str
+        applyChanges 
             [ change (Block c ec) (const repl)
             | (c, needle) <- sort ns
             , let ec = c + length needle - 1
             , repl <- maybeToList $ M.lookup needle unicodeReplacements
-            ]
+            ] str
 
 
 --------------------------------------------------------------------------------
@@ -104,15 +104,15 @@
 
 
 --------------------------------------------------------------------------------
-step :: Bool -> Step
-step = makeStep "UnicodeSyntax" . step'
+step :: Bool -> String -> Step
+step = (makeStep "UnicodeSyntax" .) . step'
 
 
 --------------------------------------------------------------------------------
-step' :: Bool -> Lines -> Module -> Lines
-step' alp ls (module', _) = applyChanges changes ls
+step' :: Bool -> String -> Lines -> Module -> Lines
+step' alp lg ls (module', _) = applyChanges changes ls
   where
-    changes = (if alp then addLanguagePragma "UnicodeSyntax" module' else []) ++
+    changes = (if alp then addLanguagePragma lg "UnicodeSyntax" module' else []) ++
         replaceAll perLine
     perLine = sort $ groupPerLine $
         typeSigs module' ls ++
diff --git a/lib/Language/Haskell/Stylish/Util.hs b/lib/Language/Haskell/Stylish/Util.hs
--- a/lib/Language/Haskell/Stylish/Util.hs
+++ b/lib/Language/Haskell/Stylish/Util.hs
@@ -10,6 +10,8 @@
     , trimRight
     , wrap
     , wrapRest
+    , wrapMaybe
+    , wrapRestMaybe
 
     , withHead
     , withInit
@@ -99,6 +101,27 @@
 
 
 --------------------------------------------------------------------------------
+wrapMaybe :: Maybe Int -- ^ Maximum line width (maybe)
+          -> String    -- ^ Leading string
+          -> Int       -- ^ Indentation
+          -> [String]  -- ^ Strings to add/wrap
+          -> Lines     -- ^ Resulting lines
+wrapMaybe (Just maxWidth) = wrap maxWidth
+wrapMaybe Nothing         = noWrap
+
+
+--------------------------------------------------------------------------------
+noWrap :: String    -- ^ Leading string
+       -> Int       -- ^ Indentation
+       -> [String]  -- ^ Strings to add
+       -> Lines     -- ^ Resulting lines
+noWrap leading _ind = noWrap' leading
+  where
+    noWrap' ss [] = [ss]
+    noWrap' ss (str:strs) = noWrap' (ss ++ " " ++ str) strs
+
+
+--------------------------------------------------------------------------------
 wrapRest :: Int
          -> Int
          -> [String]
@@ -114,6 +137,29 @@
         | otherwise = wrapRest' ls (ss ++ " " ++ str) strs
 
     overflows ss str = (length ss + length str + 1) >= maxWidth
+
+
+--------------------------------------------------------------------------------
+wrapRestMaybe :: Maybe Int
+              -> Int
+              -> [String]
+              -> Lines
+wrapRestMaybe (Just maxWidth) = wrapRest maxWidth
+wrapRestMaybe Nothing         = noWrapRest
+
+
+--------------------------------------------------------------------------------
+noWrapRest :: Int
+           -> [String]
+           -> Lines
+noWrapRest ind = reverse . noWrapRest' [] ""
+  where
+    noWrapRest' ls ss []
+        | null ss = ls
+        | otherwise = ss:ls
+    noWrapRest' ls ss (str:strs)
+        | null ss = noWrapRest' ls (indent ind str) strs
+        | otherwise = noWrapRest' ls (ss ++ " " ++ str) strs
 
 
 --------------------------------------------------------------------------------
diff --git a/stylish-haskell.cabal b/stylish-haskell.cabal
--- a/stylish-haskell.cabal
+++ b/stylish-haskell.cabal
@@ -1,5 +1,5 @@
 Name:          stylish-haskell
-Version:       0.9.4.4
+Version:       0.10.0.0
 Synopsis:      Haskell code prettifier
 Homepage:      https://github.com/jaspervdj/stylish-haskell
 License:       BSD3
@@ -29,6 +29,7 @@
 
   Exposed-modules:
     Language.Haskell.Stylish
+    Language.Haskell.Stylish.Step.Data
     Language.Haskell.Stylish.Step.Imports
     Language.Haskell.Stylish.Step.LanguagePragmas
     Language.Haskell.Stylish.Step.SimpleAlign
@@ -59,11 +60,12 @@
     directory        >= 1.2.3  && < 1.4,
     filepath         >= 1.1    && < 1.5,
     file-embed       >= 0.0.10 && < 0.1,
-    haskell-src-exts >= 1.18   && < 1.23,
+    haskell-src-exts >= 1.18   && < 1.24,
     mtl              >= 2.0    && < 2.3,
     semigroups       >= 0.18   && < 0.20,
     syb              >= 0.3    && < 0.8,
-    yaml             >= 0.8.11 && < 0.12
+    HsYAML-aeson     >=0.2.0   && < 0.3,
+    HsYAML           >=0.2.0   && < 0.3
 
 Executable stylish-haskell
   Ghc-options:    -Wall
@@ -83,10 +85,11 @@
     directory        >= 1.2.3  && < 1.4,
     filepath         >= 1.1    && < 1.5,
     file-embed       >= 0.0.10 && < 0.1,
-    haskell-src-exts >= 1.18   && < 1.23,
+    haskell-src-exts >= 1.18   && < 1.24,
     mtl              >= 2.0    && < 2.3,
     syb              >= 0.3    && < 0.8,
-    yaml             >= 0.8.11 && < 0.12
+    HsYAML-aeson     >=0.2.0   && < 0.3,
+    HsYAML           >=0.2.0   && < 0.3
 
 Test-suite stylish-haskell-tests
   Ghc-options:    -Wall
@@ -95,6 +98,7 @@
   Type:           exitcode-stdio-1.0
 
   Other-modules:
+    Language.Haskell.Stylish
     Language.Haskell.Stylish.Align
     Language.Haskell.Stylish.Block
     Language.Haskell.Stylish.Config
@@ -107,6 +111,8 @@
     Language.Haskell.Stylish.Step
     Language.Haskell.Stylish.Step.Imports
     Language.Haskell.Stylish.Step.Imports.Tests
+    Language.Haskell.Stylish.Step.Data
+    Language.Haskell.Stylish.Step.Data.Tests
     Language.Haskell.Stylish.Step.LanguagePragmas
     Language.Haskell.Stylish.Step.LanguagePragmas.Tests
     Language.Haskell.Stylish.Step.SimpleAlign
@@ -119,9 +125,11 @@
     Language.Haskell.Stylish.Step.TrailingWhitespace.Tests
     Language.Haskell.Stylish.Step.UnicodeSyntax
     Language.Haskell.Stylish.Step.UnicodeSyntax.Tests
+    Language.Haskell.Stylish.Tests
     Language.Haskell.Stylish.Tests.Util
     Language.Haskell.Stylish.Util
     Language.Haskell.Stylish.Verbose
+    Paths_stylish_haskell
 
   Build-depends:
     HUnit                >= 1.2 && < 1.7,
@@ -137,10 +145,11 @@
     directory        >= 1.2.3  && < 1.4,
     filepath         >= 1.1    && < 1.5,
     file-embed       >= 0.0.10 && < 0.1,
-    haskell-src-exts >= 1.18   && < 1.23,
+    haskell-src-exts >= 1.18   && < 1.24,
     mtl              >= 2.0    && < 2.3,
     syb              >= 0.3    && < 0.8,
-    yaml             >= 0.8.11 && < 0.12
+    HsYAML-aeson     >=0.2.0   && < 0.3,
+    HsYAML           >=0.2.0   && < 0.3
 
 Source-repository head
   Type:     git
diff --git a/tests/Language/Haskell/Stylish/Config/Tests.hs b/tests/Language/Haskell/Stylish/Config/Tests.hs
--- a/tests/Language/Haskell/Stylish/Config/Tests.hs
+++ b/tests/Language/Haskell/Stylish/Config/Tests.hs
@@ -4,18 +4,18 @@
 
 
 --------------------------------------------------------------------------------
-import           Control.Exception               hiding (assert)
 import qualified Data.Set                        as Set
 import           System.Directory
-import           System.FilePath                 ((</>))
-import           System.IO.Error
-import           System.Random
 import           Test.Framework                  (Test, testGroup)
 import           Test.Framework.Providers.HUnit  (testCase)
 import           Test.HUnit                      (Assertion, assert)
+
+
 --------------------------------------------------------------------------------
 import           Language.Haskell.Stylish.Config
+import           Language.Haskell.Stylish.Tests.Util
 
+
 --------------------------------------------------------------------------------
 tests :: Test
 tests = testGroup "Language.Haskell.Stylish.Config"
@@ -25,38 +25,20 @@
                testExtensionsFromDotStylish
     , testCase "Extensions extracted correctly from .stylish-haskell.yaml and .cabal files"
                testExtensionsFromBoth
+    , testCase "Correctly read .stylish-haskell.yaml file with default max column number"
+               testDefaultColumns
+    , testCase "Correctly read .stylish-haskell.yaml file with specified max column number"
+               testSpecifiedColumns
+    , testCase "Correctly read .stylish-haskell.yaml file with no max column number"
+               testNoColumns
     ]
---------------------------------------------------------------------------------
 
--- | Create a temporary directory with a randomised name built from the template provided
-createTempDirectory :: String -> IO FilePath
-createTempDirectory template  = do
-  tmpRootDir <- getTemporaryDirectory
-  dirId <- randomIO :: IO Word
-  findTempName tmpRootDir dirId
-  where
-    findTempName :: FilePath -> Word -> IO FilePath
-    findTempName tmpRootDir x = do
-      let dirpath = tmpRootDir </> template ++ show x
-      r <- try $ createDirectory dirpath
-      case r of
-        Right _ -> return dirpath
-        Left  e | isAlreadyExistsError e -> findTempName tmpRootDir (x+1)
-                | otherwise              -> ioError e
 
--- | Perform an action inside a temporary directory tree and purge the tree afterwords
-withTestDirTree :: IO a -> IO a
-withTestDirTree action = bracket
-    ((,) <$> getCurrentDirectory <*> createTempDirectory "stylish_haskell")
-    (\(current, temp) ->
-        setCurrentDirectory current *>
-        removeDirectoryRecursive temp)
-    (\(_, temp) -> setCurrentDirectory temp *> action)
-
+--------------------------------------------------------------------------------
 -- | Put an example config files (.cabal/.stylish-haskell.yaml/both)
 -- into the current directory and extract extensions from it.
-createFilesAndGetExtensions :: [(FilePath, String)] -> IO Extensions
-createFilesAndGetExtensions files = withTestDirTree $ do
+createFilesAndGetConfig :: [(FilePath, String)] -> IO Config
+createFilesAndGetConfig files = withTestDirTree $ do
   mapM_ (\(k, v) -> writeFile k v) files
   -- create an empty directory and change into it
   createDirectory "src"
@@ -64,34 +46,65 @@
   -- from that directory read the config file and extract extensions
   -- to make sure the search for .cabal file works
   config <- loadConfig (const (pure ())) Nothing
-  pure $ configLanguageExtensions config
+  pure config
 
+
 --------------------------------------------------------------------------------
 testExtensionsFromDotCabal :: Assertion
 testExtensionsFromDotCabal =
-  assert $ (expected ==) . Set.fromList <$>
-    createFilesAndGetExtensions [("test.cabal", dotCabal True)]
+  assert $ (expected ==) . Set.fromList . configLanguageExtensions <$>
+    createFilesAndGetConfig [("test.cabal", dotCabal True)]
     where
       expected = Set.fromList ["ScopedTypeVariables", "DataKinds"]
 
+
 --------------------------------------------------------------------------------
 testExtensionsFromDotStylish :: Assertion
 testExtensionsFromDotStylish =
-  assert $ (expected ==) . Set.fromList <$>
-    createFilesAndGetExtensions [(".stylish-haskell.yaml", dotStylish)]
+  assert $ (expected ==) . Set.fromList . configLanguageExtensions <$>
+    createFilesAndGetConfig [(".stylish-haskell.yaml", dotStylish)]
     where
       expected = Set.fromList ["TemplateHaskell", "QuasiQuotes"]
 
+
 --------------------------------------------------------------------------------
 testExtensionsFromBoth :: Assertion
 testExtensionsFromBoth =
-  assert $ (expected ==) . Set.fromList <$>
-    createFilesAndGetExtensions [ ("test.cabal", dotCabal True)
-                                , (".stylish-haskell.yaml", dotStylish)]
+  assert $ (expected ==) . Set.fromList . configLanguageExtensions <$>
+    createFilesAndGetConfig [ ("test.cabal", dotCabal True)
+                            , (".stylish-haskell.yaml", dotStylish)]
     where
       expected = Set.fromList
         ["ScopedTypeVariables", "DataKinds", "TemplateHaskell", "QuasiQuotes"]
 
+
+--------------------------------------------------------------------------------
+testSpecifiedColumns :: Assertion
+testSpecifiedColumns =
+  assert $ (expected ==) . configColumns <$>
+    createFilesAndGetConfig [(".stylish-haskell.yaml", dotStylish)]
+    where
+      expected = Just 110
+
+
+--------------------------------------------------------------------------------
+testDefaultColumns :: Assertion
+testDefaultColumns =
+  assert $ (expected ==) . configColumns <$>
+    createFilesAndGetConfig [(".stylish-haskell.yaml", dotStylish2)]
+    where
+      expected = Just 80
+
+
+--------------------------------------------------------------------------------
+testNoColumns :: Assertion
+testNoColumns =
+  assert $ (expected ==) . configColumns <$>
+    createFilesAndGetConfig [(".stylish-haskell.yaml", dotStylish3)]
+    where
+      expected = Nothing
+
+
 -- | Example cabal file borrowed from
 --   https://www.haskell.org/cabal/users-guide/developing-packages.html
 --   with some default-extensions added
@@ -135,7 +148,48 @@
   , "      align: false"
   , "      remove_redundant: true"
   , "  - trailing_whitespace: {}"
+  , "  - records: {}"
+  , "indent: 2"
   , "columns: 110"
+  , "language_extensions:"
+  , "  - TemplateHaskell"
+  , "  - QuasiQuotes"
+  ]
+
+-- | Example .stylish-haskell.yaml
+dotStylish2 :: String
+dotStylish2 = unlines $
+  [ "steps:"
+  , "  - imports:"
+  , "      align: none"
+  , "      list_align: after_alias"
+  , "      long_list_align: inline"
+  , "      separate_lists: true"
+  , "  - language_pragmas:"
+  , "      style: vertical"
+  , "      align: false"
+  , "      remove_redundant: true"
+  , "  - trailing_whitespace: {}"
+  , "language_extensions:"
+  , "  - TemplateHaskell"
+  , "  - QuasiQuotes"
+  ]
+
+-- | Example .stylish-haskell.yaml
+dotStylish3 :: String
+dotStylish3 = unlines $
+  [ "steps:"
+  , "  - imports:"
+  , "      align: none"
+  , "      list_align: after_alias"
+  , "      long_list_align: inline"
+  , "      separate_lists: true"
+  , "  - language_pragmas:"
+  , "      style: vertical"
+  , "      align: false"
+  , "      remove_redundant: true"
+  , "  - trailing_whitespace: {}"
+  , "columns: null"
   , "language_extensions:"
   , "  - TemplateHaskell"
   , "  - QuasiQuotes"
diff --git a/tests/Language/Haskell/Stylish/Step/Data/Tests.hs b/tests/Language/Haskell/Stylish/Step/Data/Tests.hs
new file mode 100644
--- /dev/null
+++ b/tests/Language/Haskell/Stylish/Step/Data/Tests.hs
@@ -0,0 +1,391 @@
+module Language.Haskell.Stylish.Step.Data.Tests
+    ( tests
+    ) where
+
+import           Language.Haskell.Stylish.Step.Data
+import           Language.Haskell.Stylish.Tests.Util (testStep)
+import           Test.Framework                      (Test, testGroup)
+import           Test.Framework.Providers.HUnit      (testCase)
+import           Test.HUnit                          (Assertion, (@=?))
+
+tests :: Test
+tests = testGroup "Language.Haskell.Stylish.Step.Data.Tests"
+    [ testCase "case 00" case00
+    , testCase "case 01" case01
+    , testCase "case 02" case02
+    , testCase "case 03" case03
+    , testCase "case 04" case04
+    , testCase "case 05" case05
+    , testCase "case 06" case06
+    , testCase "case 07" case07
+    , testCase "case 08" case08
+    , testCase "case 09" case09
+    , testCase "case 10" case10
+    , testCase "case 11" case11
+    , testCase "case 12" case12
+    , testCase "case 13" case13
+    , testCase "case 14" case14
+    , testCase "case 15" case15
+    , testCase "case 16" case16
+    , testCase "case 17" case17
+    , testCase "case 18" case18
+    , testCase "case 19" case19
+    ]
+
+case00 :: Assertion
+case00 = expected @=? testStep (step 2) input
+  where
+    input = unlines
+      [ "module Herp where"
+      , ""
+      , "data Foo"
+      ]
+
+    expected = input
+
+case01 :: Assertion
+case01 = expected @=? testStep (step 2) input
+  where
+    input = unlines
+      [ "module Herp where"
+      , ""
+      , "data Foo = Foo { a :: Int }"
+      ]
+
+    expected = unlines
+       [ "module Herp where"
+       , ""
+       , "data Foo = Foo"
+       , "  { a :: Int"
+       , "  }"
+       ]
+
+case02 :: Assertion
+case02 = expected @=? testStep (step 2) input
+  where
+    input = unlines
+      [ "module Herp where"
+      , ""
+      , "data Foo = Foo { a :: Int, a2 :: String }"
+      ]
+    expected = unlines
+       [ "module Herp where"
+       , ""
+       , "data Foo = Foo"
+       , "  { a :: Int"
+       , "  , a2 :: String"
+       , "  }"
+       ]
+
+case03 :: Assertion
+case03 = expected @=? testStep (step 2) input
+  where
+    input = unlines
+      [ "module Herp where"
+      , ""
+      , "data Foo a = Foo { a :: a, a2 :: String }"
+      ]
+    expected = unlines
+       [ "module Herp where"
+       , ""
+       , "data Foo a = Foo"
+       , "  { a :: a"
+       , "  , a2 :: String"
+       , "  }"
+       ]
+
+case04 :: Assertion
+case04 = expected @=? testStep (step 2) input
+  where
+    input = unlines
+      [ "module Herp where"
+      , ""
+      , "data Foo a = Foo { a :: a, a2 :: String } | Bar { b :: a }"
+      ]
+    expected = unlines
+       [ "module Herp where"
+       , ""
+       , "data Foo a = Foo"
+       , "  { a :: a"
+       , "  , a2 :: String"
+       , "  }"
+       , "  | Bar"
+       , "  { b :: a"
+       , "  }"
+       ]
+
+case05 :: Assertion
+case05 = expected @=? testStep (step 2) input
+  where
+    input = unlines
+       [ "module Herp where"
+       , ""
+       , "data Foo = Foo {"
+       , "  a :: Int"
+       , "  , a2 :: String"
+       , "  }"
+       ]
+    expected = unlines
+       [ "module Herp where"
+       , ""
+       , "data Foo = Foo"
+       , "  { a :: Int"
+       , "  , a2 :: String"
+       , "  }"
+       ]
+
+case06 :: Assertion
+case06 = expected @=? testStep (step 2) input
+  where
+    input = unlines
+      [ "module Herp where"
+      , ""
+      , "data Foo = Foo Int String"
+      ]
+    expected = input
+
+case07 :: Assertion
+case07 = expected @=? testStep (step 2) input
+  where
+    input = unlines
+      [ "module Herp where"
+      , ""
+      , "data Phantom a = Phantom"
+      ]
+    expected = input
+
+case08 :: Assertion
+case08 = expected @=? testStep (step 2) input
+  where
+    input = unlines
+      [ "module Herp where"
+      , ""
+      , "data Phantom a ="
+      , "  Phantom"
+      ]
+    expected = unlines
+      [ "module Herp where"
+      , ""
+      , "data Phantom a = Phantom"
+      ]
+
+case09 :: Assertion
+case09 = expected @=? testStep (step 4) input
+  where
+    input = unlines
+      [ "module Herp where"
+      , ""
+      , "data Foo a b = Foo { a :: a, a2 :: String } | Bar { b :: a, c:: b }"
+      ]
+    expected = unlines
+       [ "module Herp where"
+       , ""
+       , "data Foo a b = Foo"
+       , "    { a :: a"
+       , "    , a2 :: String"
+       , "    }"
+       , "    | Bar"
+       , "    { b :: a"
+       , "    , c :: b"
+       , "    }"
+       ]
+
+case10 :: Assertion
+case10 = expected @=? testStep (step 2) input
+  where
+    input = unlines
+      [ "module Herp where"
+      , ""
+      , "data Foo = Foo { a :: Int } deriving (Eq, Generic) deriving (Show)"
+      ]
+
+    expected = unlines
+       [ "module Herp where"
+       , ""
+       , "data Foo = Foo"
+       , "  { a :: Int"
+       , "  }"
+       , "  deriving (Eq, Generic)"
+       , "  deriving (Show)"
+       ]
+
+case11 :: Assertion
+case11 = expected @=? testStep (step 2) input
+  where
+    input = unlines
+      [ "{-# LANGUAGE DerivingStrategies #-}"
+      , "module Herp where"
+      , ""
+      , "data Foo = Foo { a :: Int } deriving stock (Show)"
+      ]
+
+    expected = unlines
+       [ "{-# LANGUAGE DerivingStrategies #-}"
+       , "module Herp where"
+       , ""
+       , "data Foo = Foo"
+       , "  { a :: Int"
+       , "  }"
+       , "  deriving stock (Show)"
+       ]
+
+case12 :: Assertion
+case12 = expected @=? testStep (step 4) input
+  where
+    input = unlines
+      [ "module Herp where"
+      , ""
+      , "data Point = Point { pointX, pointY :: Double , pointName :: String} deriving (Show)"
+      ]
+
+    expected = unlines
+       [ "module Herp where"
+       , ""
+       , "data Point = Point"
+       , "    { pointX, pointY :: Double"
+       , "    , pointName :: String"
+       , "    }"
+       , "    deriving (Show)"
+       ]
+
+case13 :: Assertion
+case13 = expected @=? testStep (step 2) input
+  where
+    input = unlines
+      [ "module Herp where"
+      , ""
+      , "-- this is a comment"
+      , "data Foo = Foo { a :: Int }"
+      ]
+    expected = unlines
+      [ "module Herp where"
+      , ""
+      , "-- this is a comment"
+      , "data Foo = Foo"
+      , "  { a :: Int"
+      , "  }"
+      ]
+
+case14 :: Assertion
+case14 = expected @=? testStep (step 2) input
+  where
+    input = unlines
+      [ "module Herp where"
+      , ""
+      , "{- this is"
+      , "   a comment -}"
+      , "data Foo = Foo { a :: Int }"
+      ]
+    expected = unlines
+      [ "module Herp where"
+      , ""
+      , "{- this is"
+      , "   a comment -}"
+      , "data Foo = Foo"
+      , "  { a :: Int"
+      , "  }"
+      ]
+
+case15 :: Assertion
+case15 = expected @=? testStep (step 2) input
+  where
+    input = unlines
+       [ "module Herp where"
+       , ""
+       , "data Foo a = Foo"
+       , "  { a :: a, -- comment"
+       , "   a2 :: String"
+       , "  }"
+       ]
+    expected = unlines
+       [ "module Herp where"
+       , ""
+       , "data Foo a = Foo"
+       , "  { a :: a -- comment"
+       , "  , a2 :: String"
+       , "  }"
+       ]
+
+case16 :: Assertion
+case16 = expected @=? testStep (step 2) input
+  where
+    input = unlines
+      [ "module Herp where"
+      , ""
+      , "data Foo = Foo {"
+      , "   a :: Int -- ^ comment"
+      , "  }"
+      ]
+    expected = unlines
+      [ "module Herp where"
+      , ""
+      , "data Foo = Foo"
+      , "  { a :: Int -- ^ comment"
+      , "  }"
+      ]
+
+case17 :: Assertion
+case17 = expected @=? testStep (step 2) input
+  where
+    input = unlines
+       [ "module Herp where"
+       , ""
+       , "data Foo a = Foo"
+       , "  { a :: a,"
+       , "-- comment"
+       , "   a2 :: String"
+       , "  }"
+       ]
+    expected = unlines
+       [ "module Herp where"
+       , ""
+       , "data Foo a = Foo"
+       , "  { a :: a"
+       , "  -- comment"
+       , "  , a2 :: String"
+       , "  }"
+       ]
+
+case18 :: Assertion
+case18 = expected @=? testStep (step 2) input
+  where
+    input = unlines
+       [ "module Herp where"
+       , ""
+       , "data Foo a = Foo"
+       , "  { a :: a,"
+       , "-- ^ comment"
+       , "   a2 :: String"
+       , "  }"
+       ]
+    expected = unlines
+       [ "module Herp where"
+       , ""
+       , "data Foo a = Foo"
+       , "  { a :: a"
+       , "  -- ^ comment"
+       , "  , a2 :: String"
+       , "  }"
+       ]
+
+case19 :: Assertion
+case19 = expected @=? testStep (step 2) input
+  where
+    input = unlines
+       [ "module Herp where"
+       , ""
+       , "data Foo a = Foo"
+       , "  { firstName, lastName :: String,"
+       , "-- ^ names"
+       , "   age :: Int"
+       , "  }"
+       ]
+    expected = unlines
+       [ "module Herp where"
+       , ""
+       , "data Foo a = Foo"
+       , "  { firstName, lastName :: String"
+       , "  -- ^ names"
+       , "  , age :: Int"
+       , "  }"
+       ]
diff --git a/tests/Language/Haskell/Stylish/Step/Imports/Tests.hs b/tests/Language/Haskell/Stylish/Step/Imports/Tests.hs
--- a/tests/Language/Haskell/Stylish/Step/Imports/Tests.hs
+++ b/tests/Language/Haskell/Stylish/Step/Imports/Tests.hs
@@ -58,6 +58,7 @@
     , testCase "case 24" case24
     , testCase "case 25" case25
     , testCase "case 26 (issue 185)" case26
+    , testCase "case 27" case27
     ]
 
 
@@ -82,7 +83,7 @@
 
 --------------------------------------------------------------------------------
 case01 :: Assertion
-case01 = expected @=? testStep (step 80 $ fromImportAlign Global) input
+case01 = expected @=? testStep (step (Just 80) $ fromImportAlign Global) input
   where
     expected = unlines
         [ "module Herp where"
@@ -104,7 +105,7 @@
 
 --------------------------------------------------------------------------------
 case02 :: Assertion
-case02 = expected @=? testStep (step 80 $ fromImportAlign Group) input
+case02 = expected @=? testStep (step (Just 80) $ fromImportAlign Group) input
   where
     expected = unlines
         [ "module Herp where"
@@ -125,7 +126,7 @@
 
 --------------------------------------------------------------------------------
 case03 :: Assertion
-case03 = expected @=? testStep (step 80 $ fromImportAlign None) input
+case03 = expected @=? testStep (step (Just 80) $ fromImportAlign None) input
   where
     expected = unlines
         [ "module Herp where"
@@ -146,7 +147,7 @@
 
 --------------------------------------------------------------------------------
 case04 :: Assertion
-case04 = expected @=? testStep (step 80 $ fromImportAlign Global) input'
+case04 = expected @=? testStep (step (Just 80) $ fromImportAlign Global) input'
   where
     input' =
         "import Data.Aeson.Types (object, typeMismatch, FromJSON(..)," ++
@@ -161,7 +162,7 @@
 
 --------------------------------------------------------------------------------
 case05 :: Assertion
-case05 = input' @=? testStep (step 80 $ fromImportAlign Group) input'
+case05 = input' @=? testStep (step (Just 80) $ fromImportAlign Group) input'
   where
     input' = "import Distribution.PackageDescription.Configuration " ++
         "(finalizePackageDescription)\n"
@@ -169,7 +170,7 @@
 
 --------------------------------------------------------------------------------
 case06 :: Assertion
-case06 = input' @=? testStep (step 80 $ fromImportAlign File) input'
+case06 = input' @=? testStep (step (Just 80) $ fromImportAlign File) input'
   where
     input' = unlines
         [ "import Bar.Qux"
@@ -179,7 +180,7 @@
 
 --------------------------------------------------------------------------------
 case07 :: Assertion
-case07 = expected @=? testStep (step 80 $ fromImportAlign File) input'
+case07 = expected @=? testStep (step (Just 80) $ fromImportAlign File) input'
   where
     input' = unlines
         [ "import Bar.Qux"
@@ -197,7 +198,7 @@
 --------------------------------------------------------------------------------
 case08 :: Assertion
 case08 = expected
-    @=? testStep (step 80 $ Options Global WithAlias True Inline Inherit (LPConstant 4) True False) input
+    @=? testStep (step (Just 80) $ Options Global WithAlias True Inline Inherit (LPConstant 4) True False) input
   where
     expected = unlines
         [ "module Herp where"
@@ -220,7 +221,7 @@
 --------------------------------------------------------------------------------
 case08b :: Assertion
 case08b = expected
-    @=? testStep (step 80 $ Options Global WithModuleName True Inline Inherit (LPConstant 4) True False) input
+    @=? testStep (step (Just 80) $ Options Global WithModuleName True Inline Inherit (LPConstant 4) True False) input
   where
     expected = unlines
         ["module Herp where"
@@ -242,7 +243,7 @@
 --------------------------------------------------------------------------------
 case09 :: Assertion
 case09 = expected
-    @=? testStep (step 80 $ Options Global WithAlias True Multiline Inherit (LPConstant 4) True False) input
+    @=? testStep (step (Just 80) $ Options Global WithAlias True Multiline Inherit (LPConstant 4) True False) input
   where
     expected = unlines
         [ "module Herp where"
@@ -276,7 +277,7 @@
 --------------------------------------------------------------------------------
 case10 :: Assertion
 case10 = expected
-    @=? testStep (step 40 $ Options Group WithAlias True Multiline Inherit (LPConstant 4) True False) input
+    @=? testStep (step (Just 40) $ Options Group WithAlias True Multiline Inherit (LPConstant 4) True False) input
   where
     expected = unlines
         [ "module Herp where"
@@ -315,7 +316,7 @@
 --------------------------------------------------------------------------------
 case11 :: Assertion
 case11 = expected
-    @=? testStep (step 80 $ Options Group NewLine True Inline Inherit (LPConstant 4) True False) input
+    @=? testStep (step (Just 80) $ Options Group NewLine True Inline Inherit (LPConstant 4) True False) input
   where
     expected = unlines
         [ "module Herp where"
@@ -342,7 +343,7 @@
 
 case11b :: Assertion
 case11b = expected
-    @=? testStep (step 80 $ Options Group WithModuleName True Inline Inherit (LPConstant 4) True False) input
+    @=? testStep (step (Just 80) $ Options Group WithModuleName True Inline Inherit (LPConstant 4) True False) input
   where
     expected = unlines
         [ "module Herp where"
@@ -364,7 +365,7 @@
 --------------------------------------------------------------------------------
 case12 :: Assertion
 case12 = expected
-    @=? testStep (step 80 $ Options Group NewLine True Inline Inherit (LPConstant 2) True False) input'
+    @=? testStep (step (Just 80) $ Options Group NewLine True Inline Inherit (LPConstant 2) True False) input'
   where
     input' = unlines
         [ "import Data.List (map)"
@@ -379,7 +380,7 @@
 --------------------------------------------------------------------------------
 case12b :: Assertion
 case12b = expected
-    @=? testStep (step 80 $ Options Group WithModuleName True Inline Inherit (LPConstant 2) True False) input'
+    @=? testStep (step (Just 80) $ Options Group WithModuleName True Inline Inherit (LPConstant 2) True False) input'
   where
     input' = unlines
         [ "import Data.List (map)"
@@ -391,7 +392,7 @@
 --------------------------------------------------------------------------------
 case13 :: Assertion
 case13 = expected
-    @=? testStep (step 80 $ Options None WithAlias True InlineWithBreak Inherit (LPConstant 4) True False) input'
+    @=? testStep (step (Just 80) $ Options None WithAlias True InlineWithBreak Inherit (LPConstant 4) True False) input'
   where
     input' = unlines
         [ "import qualified Data.List as List (concat, foldl, foldr, head, init,"
@@ -408,7 +409,7 @@
 --------------------------------------------------------------------------------
 case13b :: Assertion
 case13b = expected
-    @=? testStep (step 80 $ Options None WithModuleName True InlineWithBreak Inherit (LPConstant 4) True False) input'
+    @=? testStep (step (Just 80) $ Options None WithModuleName True InlineWithBreak Inherit (LPConstant 4) True False) input'
   where
     input' = unlines
         [ "import qualified Data.List as List (concat, foldl, foldr, head, init,"
@@ -426,7 +427,7 @@
 case14 :: Assertion
 case14 = expected
     @=? testStep
-      (step 80 $ Options None WithAlias True InlineWithBreak Inherit (LPConstant 10) True False) expected
+      (step (Just 80) $ Options None WithAlias True InlineWithBreak Inherit (LPConstant 10) True False) expected
   where
     expected = unlines
         [ "import qualified Data.List as List (concat, map, null, reverse, tail, (++))"
@@ -436,7 +437,7 @@
 --------------------------------------------------------------------------------
 case15 :: Assertion
 case15 = expected
-    @=? testStep (step 80 $ Options None AfterAlias True Multiline Inherit (LPConstant 4) True False) input'
+    @=? testStep (step (Just 80) $ Options None AfterAlias True Multiline Inherit (LPConstant 4) True False) input'
   where
     expected = unlines
         [ "import Data.Acid (AcidState)"
@@ -462,7 +463,7 @@
 --------------------------------------------------------------------------------
 case16 :: Assertion
 case16 = expected
-    @=? testStep (step 80 $ Options None AfterAlias True Multiline Inherit (LPConstant 4) False False) input'
+    @=? testStep (step (Just 80) $ Options None AfterAlias True Multiline Inherit (LPConstant 4) False False) input'
   where
     expected = unlines
         [ "import Data.Acid (AcidState)"
@@ -486,7 +487,7 @@
 --------------------------------------------------------------------------------
 case17 :: Assertion
 case17 = expected
-    @=? testStep (step 80 $ Options None AfterAlias True Multiline Inherit (LPConstant 4) True False) input'
+    @=? testStep (step (Just 80) $ Options None AfterAlias True Multiline Inherit (LPConstant 4) True False) input'
   where
     expected = unlines
         [ "import Control.Applicative (Applicative (pure, (<*>)))"
@@ -504,7 +505,7 @@
 --------------------------------------------------------------------------------
 case18 :: Assertion
 case18 = expected @=? testStep
-    (step 40 $ Options None AfterAlias True InlineToMultiline Inherit (LPConstant 4) True False) input'
+    (step (Just 40) $ Options None AfterAlias True InlineToMultiline Inherit (LPConstant 4) True False) input'
   where
     expected = unlines
            ----------------------------------------
@@ -532,7 +533,7 @@
 --------------------------------------------------------------------------------
 case19 :: Assertion
 case19 = expected @=? testStep
-    (step 40 $ Options Global NewLine True InlineWithBreak RightAfter (LPConstant 17) True False) case19input
+    (step (Just 40) $ Options Global NewLine True InlineWithBreak RightAfter (LPConstant 17) True False) case19input
   where
     expected = unlines
            ----------------------------------------
@@ -548,7 +549,7 @@
 
 case19b :: Assertion
 case19b = expected @=? testStep
-    (step 40 $ Options File NewLine True InlineWithBreak RightAfter (LPConstant 17) True False) case19input
+    (step (Just 40) $ Options File NewLine True InlineWithBreak RightAfter (LPConstant 17) True False) case19input
   where
     expected = unlines
            ----------------------------------------
@@ -564,7 +565,7 @@
 
 case19c :: Assertion
 case19c = expected @=? testStep
-    (step 40 $ Options File NewLine True InlineWithBreak RightAfter LPModuleName True False) case19input
+    (step (Just 40) $ Options File NewLine True InlineWithBreak RightAfter LPModuleName True False) case19input
   where
     expected = unlines
            ----------------------------------------
@@ -580,7 +581,7 @@
 
 case19d :: Assertion
 case19d = expected @=? testStep
-    (step 40 $ Options Global NewLine True InlineWithBreak RightAfter LPModuleName True False) case19input
+    (step (Just 40) $ Options Global NewLine True InlineWithBreak RightAfter LPModuleName True False) case19input
   where
     expected = unlines
            ----------------------------------------
@@ -606,7 +607,7 @@
 --------------------------------------------------------------------------------
 case20 :: Assertion
 case20 = expected
-    @=? testStep (step 80 defaultOptions) input'
+    @=? testStep (step (Just 80) defaultOptions) input'
   where
     expected = unlines
         [ "import {-# SOURCE #-} Data.ByteString as BS"
@@ -625,7 +626,7 @@
 --------------------------------------------------------------------------------
 case21 :: Assertion
 case21 = expected
-    @=? testStep (step 80 defaultOptions) input'
+    @=? testStep (step (Just 80) defaultOptions) input'
   where
     expected = unlines
         [ "{-# LANGUAGE ExplicitNamespaces #-}"
@@ -656,7 +657,7 @@
 --------------------------------------------------------------------------------
 case22 :: Assertion
 case22 = expected
-    @=? testStep (step 80 defaultOptions) input'
+    @=? testStep (step (Just 80) defaultOptions) input'
   where
     expected = unlines
         [ "{-# LANGUAGE PackageImports #-}"
@@ -683,7 +684,7 @@
 --------------------------------------------------------------------------------
 case23 :: Assertion
 case23 = expected
-    @=? testStep (step 40 $ Options None AfterAlias False Inline Inherit (LPConstant 4) True True) input'
+    @=? testStep (step (Just 40) $ Options None AfterAlias False Inline Inherit (LPConstant 4) True True) input'
   where
     expected = unlines
         [ "import Data.Acid ( AcidState )"
@@ -708,7 +709,7 @@
 --------------------------------------------------------------------------------
 case23b :: Assertion
 case23b = expected
-    @=? testStep (step 40 $ Options None WithModuleName False Inline Inherit (LPConstant 4) True True) input'
+    @=? testStep (step (Just 40) $ Options None WithModuleName False Inline Inherit (LPConstant 4) True True) input'
   where
     expected = unlines
         [ "import Data.Acid ( AcidState )"
@@ -734,7 +735,7 @@
 --------------------------------------------------------------------------------
 case24 :: Assertion
 case24 = expected
-    @=? testStep (step 40 $ Options None AfterAlias False InlineWithBreak Inherit (LPConstant 4) True True) input'
+    @=? testStep (step (Just 40) $ Options None AfterAlias False InlineWithBreak Inherit (LPConstant 4) True True) input'
   where
     expected = unlines
         [ "import Data.Acid ( AcidState )"
@@ -758,7 +759,7 @@
 --------------------------------------------------------------------------------
 case25 :: Assertion
 case25 = expected
-    @=? testStep (step 80 $ Options Group AfterAlias False Multiline Inherit (LPConstant 4) False False) input'
+    @=? testStep (step (Just 80) $ Options Group AfterAlias False Multiline Inherit (LPConstant 4) False False) input'
   where
     expected = unlines
         [ "import Data.Acid (AcidState)"
@@ -783,7 +784,7 @@
 --------------------------------------------------------------------------------
 case26 :: Assertion
 case26 = expected
-    @=? testStep (step 80 options ) input'
+    @=? testStep (step (Just 80) options ) input'
   where
     options = defaultOptions { listAlign = NewLine, longListAlign = Multiline }
     input' = unlines
@@ -791,4 +792,24 @@
         ]
     expected = unlines
         [ "import           Data.List"
+        ]
+
+
+--------------------------------------------------------------------------------
+case27 :: Assertion
+case27 = expected @=? testStep (step Nothing $ fromImportAlign Global) input
+  where
+    expected = unlines
+        [ "module Herp where"
+        , ""
+        , "import           Control.Monad"
+        , "import           Data.List           as List (concat, foldl, foldr, head, init, last, length, map, null, reverse, tail, (++))"
+        , "import           Data.Map            (Map, insert, lookup, (!))"
+        , "import qualified Data.Map            as M"
+        , "import           Only.Instances      ()"
+        , ""
+        , "import           Foo                 (Bar (..))"
+        , "import           Herp.Derp.Internals hiding (foo)"
+        , ""
+        , "herp = putStrLn \"import Hello world\""
         ]
diff --git a/tests/Language/Haskell/Stylish/Step/LanguagePragmas/Tests.hs b/tests/Language/Haskell/Stylish/Step/LanguagePragmas/Tests.hs
--- a/tests/Language/Haskell/Stylish/Step/LanguagePragmas/Tests.hs
+++ b/tests/Language/Haskell/Stylish/Step/LanguagePragmas/Tests.hs
@@ -28,12 +28,16 @@
     , testCase "case 08" case08
     , testCase "case 09" case09
     , testCase "case 10" case10
+    , testCase "case 11" case11
+    , testCase "case 12" case12
     ]
 
+lANG :: String
+lANG = "LANGUAGE"
 
 --------------------------------------------------------------------------------
 case01 :: Assertion
-case01 = expected @=? testStep (step 80 Vertical True False) input
+case01 = expected @=? testStep (step (Just 80) Vertical True False lANG) input
   where
     input = unlines
         [ "{-# LANGUAGE ViewPatterns #-}"
@@ -52,7 +56,7 @@
 
 --------------------------------------------------------------------------------
 case02 :: Assertion
-case02 = expected @=? testStep (step 80 Vertical True True) input
+case02 = expected @=? testStep (step (Just 80) Vertical True True lANG) input
   where
     input = unlines
         [ "{-# LANGUAGE BangPatterns #-}"
@@ -68,7 +72,7 @@
 
 --------------------------------------------------------------------------------
 case03 :: Assertion
-case03 = expected @=? testStep (step 80 Vertical True True) input
+case03 = expected @=? testStep (step (Just 80) Vertical True True lANG) input
   where
     input = unlines
         [ "{-# LANGUAGE BangPatterns #-}"
@@ -84,7 +88,7 @@
 
 --------------------------------------------------------------------------------
 case04 :: Assertion
-case04 = expected @=? testStep (step 80 Compact True False) input
+case04 = expected @=? testStep (step (Just 80) Compact True False lANG) input
   where
     input = unlines
         [ "{-# LANGUAGE TypeOperators, StandaloneDeriving, DeriveDataTypeable,"
@@ -101,7 +105,7 @@
 
 --------------------------------------------------------------------------------
 case05 :: Assertion
-case05 = expected @=? testStep (step 80 Vertical True False) input
+case05 = expected @=? testStep (step (Just 80) Vertical True False lANG) input
   where
     input = unlines
         [ "{-# LANGUAGE CPP #-}"
@@ -122,7 +126,7 @@
 
 --------------------------------------------------------------------------------
 case06 :: Assertion
-case06 = expected @=? testStep (step 80 CompactLine True False) input
+case06 = expected @=? testStep (step (Just 80) CompactLine True False lANG) input
   where
     input = unlines
         [ "{-# LANGUAGE TypeOperators, StandaloneDeriving, DeriveDataTypeable,"
@@ -137,7 +141,7 @@
 
 --------------------------------------------------------------------------------
 case07 :: Assertion
-case07 = expected @=? testStep (step 80 Vertical False False) input
+case07 = expected @=? testStep (step (Just 80) Vertical False False lANG) input
   where
     input = unlines
         [ "{-# LANGUAGE ViewPatterns #-}"
@@ -157,7 +161,7 @@
 
 --------------------------------------------------------------------------------
 case08 :: Assertion
-case08 = expected @=? testStep (step 80 CompactLine False False) input
+case08 = expected @=? testStep (step (Just 80) CompactLine False False lANG) input
   where
     input = unlines
         [ "{-# LANGUAGE TypeOperators, StandaloneDeriving, DeriveDataTypeable,"
@@ -173,7 +177,7 @@
 
 --------------------------------------------------------------------------------
 case09 :: Assertion
-case09 = expected @=? testStep (step 80 Compact True False) input
+case09 = expected @=? testStep (step (Just 80) Compact True False lANG) input
   where
     input = unlines
         [ "{-# LANGUAGE DefaultSignatures, FlexibleInstances, LambdaCase, " ++
@@ -187,7 +191,7 @@
 
 --------------------------------------------------------------------------------
 case10 :: Assertion
-case10 = expected @=? testStep (step 80 Compact True False) input
+case10 = expected @=? testStep (step (Just 80) Compact True False lANG) input
   where
     input = unlines
         [ "{-# LANGUAGE NondecreasingIndentation, ScopedTypeVariables,"
@@ -196,4 +200,39 @@
     expected = unlines
         [ "{-# LANGUAGE NondecreasingIndentation, ScopedTypeVariables, " ++
           "TypeApplications #-}"
+        ]
+
+--------------------------------------------------------------------------------
+case11 :: Assertion
+case11 = expected @=? testStep (step (Just 80) Vertical False False "language") input
+  where
+    input = unlines
+        [ "{-# LANGUAGE ViewPatterns #-}"
+        , "{-# LANGUAGE TemplateHaskell, ViewPatterns #-}"
+        , "{-# LANGUAGE ScopedTypeVariables, NoImplicitPrelude #-}"
+        , "module Main where"
+        ]
+
+    expected = unlines
+        [ "{-# language NoImplicitPrelude #-}"
+        , "{-# language ScopedTypeVariables #-}"
+        , "{-# language TemplateHaskell #-}"
+        , "{-# language ViewPatterns #-}"
+        , "module Main where"
+        ]
+
+--------------------------------------------------------------------------------
+case12 :: Assertion
+case12 = expected @=? testStep (step Nothing Compact False False "language") input
+  where
+    input = unlines
+        [ "{-# LANGUAGE ViewPatterns, OverloadedStrings #-}"
+        , "{-# LANGUAGE TemplateHaskell, ViewPatterns #-}"
+        , "{-# LANGUAGE ScopedTypeVariables, NoImplicitPrelude #-}"
+        , "module Main where"
+        ]
+
+    expected = unlines
+        [ "{-# language NoImplicitPrelude, OverloadedStrings, ScopedTypeVariables, TemplateHaskell, ViewPatterns #-}"
+        , "module Main where"
         ]
diff --git a/tests/Language/Haskell/Stylish/Step/SimpleAlign/Tests.hs b/tests/Language/Haskell/Stylish/Step/SimpleAlign/Tests.hs
--- a/tests/Language/Haskell/Stylish/Step/SimpleAlign/Tests.hs
+++ b/tests/Language/Haskell/Stylish/Step/SimpleAlign/Tests.hs
@@ -26,12 +26,13 @@
     , testCase "case 06" case06
     , testCase "case 07" case07
     , testCase "case 08" case08
+    , testCase "case 09" case09
     ]
 
 
 --------------------------------------------------------------------------------
 case01 :: Assertion
-case01 = expected @=? testStep (step 80 defaultConfig) input
+case01 = expected @=? testStep (step (Just 80) defaultConfig) input
   where
     input = unlines
         [ "eitherToMaybe e = case e of"
@@ -48,7 +49,7 @@
 
 --------------------------------------------------------------------------------
 case02 :: Assertion
-case02 = expected @=? testStep (step 80 defaultConfig) input
+case02 = expected @=? testStep (step (Just 80) defaultConfig) input
   where
     input = unlines
         [ "eitherToMaybe (Left _) = Nothing"
@@ -63,7 +64,7 @@
 
 --------------------------------------------------------------------------------
 case03 :: Assertion
-case03 = expected @=? testStep (step 80 defaultConfig) input
+case03 = expected @=? testStep (step (Just 80) defaultConfig) input
   where
     input = unlines
         [ "heady def [] = def"
@@ -78,7 +79,7 @@
 
 --------------------------------------------------------------------------------
 case04 :: Assertion
-case04 = expected @=? testStep (step 80 defaultConfig) input
+case04 = expected @=? testStep (step (Just 80) defaultConfig) input
   where
     input = unlines
         [ "data Foo = Foo"
@@ -97,7 +98,7 @@
 
 --------------------------------------------------------------------------------
 case05 :: Assertion
-case05 = input @=? testStep (step 80 defaultConfig) input
+case05 = input @=? testStep (step (Just 80) defaultConfig) input
   where
     -- Don't attempt to align this since a field spans multiple lines
     input = unlines
@@ -113,7 +114,7 @@
 case06 :: Assertion
 case06 =
     -- 22 max columns is /just/ enough to align this stuff.
-    expected @=? testStep (step 22 defaultConfig) input
+    expected @=? testStep (step (Just 22) defaultConfig) input
   where
     input = unlines
         [ "data Foo = Foo"
@@ -134,7 +135,7 @@
 case07 :: Assertion
 case07 =
     -- 21 max columns is /just NOT/ enough to align this stuff.
-    expected @=? testStep (step 21 defaultConfig) input
+    expected @=? testStep (step (Just 21) defaultConfig) input
   where
     input = unlines
         [ "data Foo = Foo"
@@ -153,7 +154,7 @@
 
 --------------------------------------------------------------------------------
 case08 :: Assertion
-case08 = expected @=? testStep (step 80 defaultConfig) input
+case08 = expected @=? testStep (step (Just 80) defaultConfig) input
   where
     input = unlines
         [ "canDrink mbAge = case mbAge of"
@@ -165,4 +166,24 @@
         [ "canDrink mbAge = case mbAge of"
         , "    Just age | age > 18 -> True"
         , "    _                   -> False"
+        ]
+
+
+--------------------------------------------------------------------------------
+case09 :: Assertion
+case09 =
+    expected @=? testStep (step Nothing defaultConfig) input
+  where
+    input = unlines
+        [ "data Foo = Foo"
+        , "    { foo :: String"
+        , "    , barqux :: Int"
+        , "    }"
+        ]
+
+    expected = unlines
+        [ "data Foo = Foo"
+        , "    { foo    :: String"
+        , "    , barqux :: Int"
+        , "    }"
         ]
diff --git a/tests/Language/Haskell/Stylish/Step/UnicodeSyntax/Tests.hs b/tests/Language/Haskell/Stylish/Step/UnicodeSyntax/Tests.hs
--- a/tests/Language/Haskell/Stylish/Step/UnicodeSyntax/Tests.hs
+++ b/tests/Language/Haskell/Stylish/Step/UnicodeSyntax/Tests.hs
@@ -19,12 +19,13 @@
 tests :: Test
 tests = testGroup "Language.Haskell.Stylish.Step.UnicodeSyntax.Tests"
     [ testCase "case 01" case01
+    , testCase "case 02" case02
     ]
 
 
 --------------------------------------------------------------------------------
 case01 :: Assertion
-case01 = expected @=? testStep (step True) input
+case01 = expected @=? testStep (step True "LANGUAGE") input
   where
     input = unlines
         [ "sort :: Ord a => [a] -> [a]"
@@ -33,6 +34,22 @@
 
     expected = unlines
         [ "{-# LANGUAGE UnicodeSyntax #-}"
+        , "sort ∷ Ord a ⇒ [a] → [a]"
+        , "sort _ = []"
+        ]
+
+
+--------------------------------------------------------------------------------
+case02 :: Assertion
+case02 = expected @=? testStep (step True "LaNgUaGe") input
+  where
+    input = unlines
+        [ "sort :: Ord a => [a] -> [a]"
+        , "sort _ = []"
+        ]
+
+    expected = unlines
+        [ "{-# LaNgUaGe UnicodeSyntax #-}"
         , "sort ∷ Ord a ⇒ [a] → [a]"
         , "sort _ = []"
         ]
diff --git a/tests/Language/Haskell/Stylish/Tests.hs b/tests/Language/Haskell/Stylish/Tests.hs
new file mode 100644
--- /dev/null
+++ b/tests/Language/Haskell/Stylish/Tests.hs
@@ -0,0 +1,66 @@
+--------------------------------------------------------------------------------
+module Language.Haskell.Stylish.Tests
+    ( tests
+    ) where
+
+
+--------------------------------------------------------------------------------
+import           Test.Framework                      (Test, testGroup)
+import           Test.Framework.Providers.HUnit      (testCase)
+import           Test.HUnit                          (Assertion, (@?=))
+
+
+--------------------------------------------------------------------------------
+import           Language.Haskell.Stylish
+import           Language.Haskell.Stylish.Tests.Util
+
+
+--------------------------------------------------------------------------------
+tests :: Test
+tests = testGroup "Language.Haskell.Stylish.Step.Tabs.Tests"
+    [ testCase "case 01" case01
+    , testCase "case 02" case02
+    , testCase "case 03" case03
+    ]
+
+
+--------------------------------------------------------------------------------
+case01 :: Assertion
+case01 = (@?= result) =<< format Nothing Nothing input
+  where
+    input = "module Herp where\n data Foo = Bar | Baz"
+    result = Right [ "module Herp where"
+                   , "data Foo = Bar"
+                   , "    | Baz"
+                   ]
+
+
+--------------------------------------------------------------------------------
+case02 :: Assertion
+case02 = withTestDirTree $ do
+    writeFile "test-config.yaml" $ unlines
+        [ "steps:"
+        , "  - records: {}"
+        , "indent: 2"
+        ]
+
+    actual <- format (Just $ ConfigPath "test-config.yaml") Nothing input
+    actual @?= result
+  where
+    input = "module Herp where\n data Foo = Bar | Baz"
+    result = Right [ "module Herp where"
+                   , "data Foo = Bar"
+                   , "  | Baz"
+                   ]
+
+
+--------------------------------------------------------------------------------
+case03 :: Assertion
+case03 = (@?= result) =<< format Nothing (Just fileLocation) input
+  where
+    fileLocation = "directory/File.hs"
+    input = "module Herp"
+    result = Left $
+      "Language.Haskell.Stylish.Parse.parseModule: could not parse " <>
+      fileLocation <>
+      ": ParseFailed (SrcLoc \"<unknown>.hs\" 2 1) \"Parse error: EOF\""
diff --git a/tests/Language/Haskell/Stylish/Tests/Util.hs b/tests/Language/Haskell/Stylish/Tests/Util.hs
--- a/tests/Language/Haskell/Stylish/Tests/Util.hs
+++ b/tests/Language/Haskell/Stylish/Tests/Util.hs
@@ -1,9 +1,22 @@
 module Language.Haskell.Stylish.Tests.Util
     ( testStep
+    , withTestDirTree
     ) where
 
 
 --------------------------------------------------------------------------------
+import           Control.Exception              (bracket, try)
+import           System.Directory               (createDirectory,
+                                                 getCurrentDirectory,
+                                                 getTemporaryDirectory,
+                                                 removeDirectoryRecursive,
+                                                 setCurrentDirectory)
+import           System.FilePath                ((</>))
+import           System.IO.Error                (isAlreadyExistsError)
+import           System.Random                  (randomIO)
+
+
+--------------------------------------------------------------------------------
 import           Language.Haskell.Stylish.Parse
 import           Language.Haskell.Stylish.Step
 
@@ -15,3 +28,34 @@
     Right module' -> unlines $ stepFilter step ls module'
   where
     ls = lines str
+
+
+--------------------------------------------------------------------------------
+-- | Create a temporary directory with a randomised name built from the template
+-- provided
+createTempDirectory :: String -> IO FilePath
+createTempDirectory template  = do
+  tmpRootDir <- getTemporaryDirectory
+  dirId <- randomIO :: IO Word
+  findTempName tmpRootDir dirId
+  where
+    findTempName :: FilePath -> Word -> IO FilePath
+    findTempName tmpRootDir x = do
+      let dirpath = tmpRootDir </> template ++ show x
+      r <- try $ createDirectory dirpath
+      case r of
+        Right _ -> return dirpath
+        Left  e | isAlreadyExistsError e -> findTempName tmpRootDir (x+1)
+                | otherwise              -> ioError e
+
+
+--------------------------------------------------------------------------------
+-- | Perform an action inside a temporary directory tree and purge the tree
+-- afterwards
+withTestDirTree :: IO a -> IO a
+withTestDirTree action = bracket
+    ((,) <$> getCurrentDirectory <*> createTempDirectory "stylish_haskell")
+    (\(current, temp) ->
+        setCurrentDirectory current *>
+        removeDirectoryRecursive temp)
+    (\(_, temp) -> setCurrentDirectory temp *> action)
diff --git a/tests/TestSuite.hs b/tests/TestSuite.hs
--- a/tests/TestSuite.hs
+++ b/tests/TestSuite.hs
@@ -11,6 +11,7 @@
 --------------------------------------------------------------------------------
 import qualified Language.Haskell.Stylish.Config.Tests
 import qualified Language.Haskell.Stylish.Parse.Tests
+import qualified Language.Haskell.Stylish.Step.Data.Tests
 import qualified Language.Haskell.Stylish.Step.Imports.Tests
 import qualified Language.Haskell.Stylish.Step.LanguagePragmas.Tests
 import qualified Language.Haskell.Stylish.Step.SimpleAlign.Tests
@@ -18,6 +19,7 @@
 import qualified Language.Haskell.Stylish.Step.Tabs.Tests
 import qualified Language.Haskell.Stylish.Step.TrailingWhitespace.Tests
 import qualified Language.Haskell.Stylish.Step.UnicodeSyntax.Tests
+import qualified Language.Haskell.Stylish.Tests
 
 
 --------------------------------------------------------------------------------
@@ -25,6 +27,7 @@
 main = defaultMain
     [ Language.Haskell.Stylish.Parse.Tests.tests
     , Language.Haskell.Stylish.Config.Tests.tests
+    , Language.Haskell.Stylish.Step.Data.Tests.tests
     , Language.Haskell.Stylish.Step.Imports.Tests.tests
     , Language.Haskell.Stylish.Step.LanguagePragmas.Tests.tests
     , Language.Haskell.Stylish.Step.SimpleAlign.Tests.tests
@@ -32,4 +35,5 @@
     , Language.Haskell.Stylish.Step.Tabs.Tests.tests
     , Language.Haskell.Stylish.Step.TrailingWhitespace.Tests.tests
     , Language.Haskell.Stylish.Step.UnicodeSyntax.Tests.tests
+    , Language.Haskell.Stylish.Tests.tests
     ]
